From 9c765b4ef428e9695e2469226ba4bef6fa49416f Mon Sep 17 00:00:00 2001 From: ProDeath21 <> Date: Sun, 24 Mar 2024 20:20:59 +0100 Subject: [PATCH] Blender Plugin 1.6.0 --- Blender/_Release/L1960_Tools_1_3_0.zip | Bin 0 -> 3261 bytes Blender/_Release/L1960_Tools_1_4_0.zip | Bin 0 -> 3722 bytes Blender/_Release/L1960_Tools_1_5_0.zip | Bin 0 -> 4199 bytes Blender/_Release/L1960_Tools_1_6_0.zip | Bin 0 -> 4413 bytes .../L1960_Tools_1_3_0/CubeProjection.py | 94 ++++++++++++++++ .../_Source/L1960_Tools_1_3_0/FixMaterials.py | 65 +++++++++++ Blender/_Source/L1960_Tools_1_3_0/__init__.py | 65 +++++++++++ .../L1960_Tools_1_4_0/CubeProjection.py | 94 ++++++++++++++++ .../_Source/L1960_Tools_1_4_0/FixMaterials.py | 65 +++++++++++ .../_Source/L1960_Tools_1_4_0/PrepareLods.py | 13 +++ Blender/_Source/L1960_Tools_1_4_0/__init__.py | 74 +++++++++++++ .../L1960_Tools_1_5_0/CubeProjection.py | 94 ++++++++++++++++ .../_Source/L1960_Tools_1_5_0/FixMaterials.py | 65 +++++++++++ .../_Source/L1960_Tools_1_5_0/PrepareLods.py | 40 +++++++ Blender/_Source/L1960_Tools_1_5_0/__init__.py | 82 ++++++++++++++ .../L1960_Tools_1_6_0/CubeProjection.py | 94 ++++++++++++++++ .../_Source/L1960_Tools_1_6_0/FixMaterials.py | 65 +++++++++++ .../_Source/L1960_Tools_1_6_0/PrepareLods.py | 40 +++++++ Blender/_Source/L1960_Tools_1_6_0/__init__.py | 104 ++++++++++++++++++ 19 files changed, 1054 insertions(+) create mode 100644 Blender/_Release/L1960_Tools_1_3_0.zip create mode 100644 Blender/_Release/L1960_Tools_1_4_0.zip create mode 100644 Blender/_Release/L1960_Tools_1_5_0.zip create mode 100644 Blender/_Release/L1960_Tools_1_6_0.zip create mode 100644 Blender/_Source/L1960_Tools_1_3_0/CubeProjection.py create mode 100644 Blender/_Source/L1960_Tools_1_3_0/FixMaterials.py create mode 100644 Blender/_Source/L1960_Tools_1_3_0/__init__.py create mode 100644 Blender/_Source/L1960_Tools_1_4_0/CubeProjection.py create mode 100644 Blender/_Source/L1960_Tools_1_4_0/FixMaterials.py create mode 100644 Blender/_Source/L1960_Tools_1_4_0/PrepareLods.py create mode 100644 Blender/_Source/L1960_Tools_1_4_0/__init__.py create mode 100644 Blender/_Source/L1960_Tools_1_5_0/CubeProjection.py create mode 100644 Blender/_Source/L1960_Tools_1_5_0/FixMaterials.py create mode 100644 Blender/_Source/L1960_Tools_1_5_0/PrepareLods.py create mode 100644 Blender/_Source/L1960_Tools_1_5_0/__init__.py create mode 100644 Blender/_Source/L1960_Tools_1_6_0/CubeProjection.py create mode 100644 Blender/_Source/L1960_Tools_1_6_0/FixMaterials.py create mode 100644 Blender/_Source/L1960_Tools_1_6_0/PrepareLods.py create mode 100644 Blender/_Source/L1960_Tools_1_6_0/__init__.py diff --git a/Blender/_Release/L1960_Tools_1_3_0.zip b/Blender/_Release/L1960_Tools_1_3_0.zip new file mode 100644 index 0000000000000000000000000000000000000000..ef3e6b0517ad63753c59c03b91da2d860b1f6d6f GIT binary patch literal 3261 zcmZ{n2{e@JAIHZM#;ztrwuvE2q-F@&vSdw`$;dLcFbosQo)B5bIt_(EcE*xjgpe$a zvS*7#_LeEhGXB%O|IT&qJ@VvBXgiHwN^o5#8rX8-=;KY6OAb*%-Yz0*CkM zaoB7FXBFm|tv)@x^;5pVPjpT;2(%GLTR)o>v+WM4jM6t83?dkk6^=hn?j_TgzGzaZ z{87xe;m~!m80Bo-;1(o}ov%>acTEtIUQ*qEIEm(l%IcO@WXG!q` z*D($AgNq$GZdP918?wSz_ja$a_6vuPjE2J6ZNi0^=Da)&`H{MrKz7y8$o7xRVIrkC z(aGmE);%unSg`_PK#P2$#?Wnc!RwgB^`}_6ClKN$f1(CG=hXDapnhS|L0)tlDwT4- z<6Ewp#!zj~n^%^*57NaB1fFTNPtP({^h{spLoz;_^8yB3us64#Bg9I^;#+2Tp9M})o>4e3a%V!y)zJqxK zcARj$tvWfCt~^5abn5`!w)DeP;#KbR|cdh|=Zo?$p~|52+J$ihcJ zadT)fIZ|J{`IgmLy^_r|#;hz!z;v#Zn*^7D16ca~=k1Y3$N2!Q2t zR~68HMW=du{^$*gBCHg|wYp`@4jD*X#$bHYAK|qGQetv0s@fA=oyj@NXUp`~CRHrn zerQ5SDY^KKs4KR3Lrbpxq(IUtWQk^O zv57g8t@yhsBKzA;Ggn>^c3K%T`|eezD(Bog9Z#3#(S;zn+pdb87SX?q14S-IJ&meb zM=lJvx2pO%)>@zU;BHuKkgrYy+UOi3ngAnAwFB__k~hSJ{LlGe?L5d|E$LtGH{n8h zThsBGAx`Doi(G1jDkE$z29qZ6K3x|{Crf2$kAZo{x9Hm4fo~L!zpC1EYE_FZmKRQ? z1pwYN0swq}uWCAO{zmq`&faeJ9zN8XmSxfJIVH#0!v9%KdLqJE%RUt*{#X?hJ-nU7 zdwIwV$y8fsYI!+deTYccd0;C)7EwP@Sj-+SSX0CCs@xx;=Zv&yWoPWvh&>@u&RqW@ z--+S4i*~I;$Q+ z{p&~96koIB!LJOjMPi+1XU`uwNpeR#Fcl5QF`0cvj$HhjtU~S>{74Wt=&PGZ<9>$a z8&fS3I)9OF!sRR|=Q_|96! zUg?NtFR%$em;Zft9ah=5!3Z%gqVmA>g zF^NZ{v&PW8QKvu4MHd5vykJZ&^lN^BUda$_4w{yJZ@0*@CttQy|I{{5CllW^QleB; zT83JJKP<&ym(7kWS+EWWbU0m9s4gsV z2XhCSf?{n__|7?ZbYXl7V8nJaOdYJ|K&sC=S7c=Wnyz3@A3T7olQO|E6hL>=OTS+@ zv(}i`Kr6`;rY?xH)i7>|R^pG*73&IAb>V}BWEdBwGFFkV@dRb2p@#~F6S^@3-h9h} zHQbz5VfTBf+heJKcnWupZ@o z!eWstU|bAo*j(xG4igkn+U&1C<<4+h=i!)1*-5ecIT^>t#e2LKDapLA1l2fSxrX|H z3sY6)dTLNuSp4!9?xwVVQC5}boc%r4kY|yrKet!2&vWOrT0v;g$(oy`(F!+TRtWHF z)L5l6Pi2-{H9^9q#!ehXCM?Mz82hY}fj!C~uL{4hZct5Kgr9-pwD)7#UYM{CH1K%V z6?!3`t+Gwd)4m?HM*g^O@ud5^XFbo|d51p54`q&bk0l+%C)5zeMUlkj_L_G*==J$f z+=1g@;(Ir9hwmR+9lrEnIiiBfa`y(dLJ^~|MJp@X~8w!37J&d zZyg8MFFl}sAEy1gs~x5tP#yds+CO^SVHSVS3G6S{Z=Ge2lE(jo_3yHCnAJz^sfSpH oiqK(B=mED{HZ|^V9nAFpg8PGWgyGk3rl(#68tN(J*XacCKf(2>o&W#< literal 0 HcmV?d00001 diff --git a/Blender/_Release/L1960_Tools_1_4_0.zip b/Blender/_Release/L1960_Tools_1_4_0.zip new file mode 100644 index 0000000000000000000000000000000000000000..63be180c1433f2aa9b680da7574671f655fc7f34 GIT binary patch literal 3722 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 Sidebar > 1960Life category", + "description": "Set´s up the Projection-Modifier automatically and add´s in the Emptys if not allready created.", + "category": "Object", +} + +# ---------------------------------------------- +# Import modules +# ---------------------------------------------- +if "bpy" in locals(): + import imp + imp.reload(CubeProjection) + imp.reload(FixMaterials) + print("L1960 Tools: Reloaded multifiles") +else: + import bpy + from . import CubeProjection + from . import FixMaterials + +from . CubeProjection import MESH_OT_add_auto_cube_projection, MESH_OT_add_modifier_to_mesh +from . FixMaterials import MESH_OT_fix_material_names + +class L1960_PT_AutoAddProjection(bpy.types.Panel): + pass + #where to add the panel + bl_space_type = "VIEW_3D" + bl_region_type = "UI" + + #add labels + bl_label = "1960-Life Tools" + bl_category = "1960-Life" + + def draw(self, context): + """define the layout of the panel""" + self.layout.label(text="UV-Projection") + row = self.layout.row() + row.operator("mesh.add_auto_cube_projection", text="Set up Projectors") + row = self.layout.row() + row.operator("mesh.add_modifier_to_mesh", text="Add Modifier to Mesh") + self.layout.separator() + self.layout.label(text="Materials") + row = self.layout.row() + row.operator("mesh.fix_material_names", text="Fix Material Name´s") + #self.layout.separator() + #self.layout.label(text="LOD´s") + #row = self.layout.row() + #row.operator("mesh.prepareLods_decimate", text="Create LOD´s with decimate") + +#register the panel with blender +modules = [L1960_PT_AutoAddProjection, MESH_OT_add_auto_cube_projection, MESH_OT_add_modifier_to_mesh, MESH_OT_fix_material_names] + +def register(): + for mod in modules: + bpy.utils.register_class(mod) + +def unregister(): + for mod in modules: + bpy.utils.unregister_class(mod) + +if __name__== "__main__": + register() \ No newline at end of file diff --git a/Blender/_Source/L1960_Tools_1_4_0/CubeProjection.py b/Blender/_Source/L1960_Tools_1_4_0/CubeProjection.py new file mode 100644 index 0000000..c586c48 --- /dev/null +++ b/Blender/_Source/L1960_Tools_1_4_0/CubeProjection.py @@ -0,0 +1,94 @@ +import bpy +from math import pi + +L1960_Arr_PlainData = [ + ["Proj_Empty_01", (0, 0, 2), (0, 0, 0)], + ["Proj_Empty_02", (2, 0, 0), ((pi * 90 / 180), 0, (pi * 90 / 180))], + ["Proj_Empty_03", (0, 2, 0), ((pi * 90 / 180), 0, (pi * 180 / 180))], + ["Proj_Empty_04", (0, 0, -2), ((pi * 180 / 180), 0, 0)], + ["Proj_Empty_05", (-2, 0, 0), ((pi * 90 / 180), 0, (pi * -90 / 180))], + ["Proj_Empty_06", (0, -2, 0), ((pi * 90 / 180), 0, 0)] +] + +class MESH_OT_add_auto_cube_projection(bpy.types.Operator): + """Check Empty´s for projecting, if not existing create new one´s""" + + bl_idname = "mesh.add_auto_cube_projection" + bl_label = "Add Plain_Axes to scene" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + + scene = bpy.context.scene + oldSelection = bpy.context.selected_objects + oldActive = bpy.context.active_object + + for EmptyData in L1960_Arr_PlainData: + + EmptyName = EmptyData[0] + EmptyLocation = EmptyData[1] + EmptyRotation = EmptyData[2] + + if not scene.objects.get(EmptyName): + bpy.ops.object.empty_add(type='PLAIN_AXES', align='WORLD', location=EmptyLocation, scale=(1, 1, 1), rotation=EmptyRotation) + empty = bpy.context.active_object + empty.name = EmptyName + empty.hide_select = True + empty.hide_set(True) + + #Change back to old selection and select old active + for obj in oldSelection: + obj.select_set(True) + bpy.context.view_layer.objects.active = oldActive + + self.report({'INFO'}, 'Added/Fixed Emptys for Projection to Scene') + return {"FINISHED"} + +class MESH_OT_add_modifier_to_mesh(bpy.types.Operator): + """Add Modifier to selected Mesh´s and prepare UV-Maps""" + + bl_idname = "mesh.add_modifier_to_mesh" + bl_label = "Add Modifier to selected Mesh" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + + newModifierName = "CubeTexModifier" + Arr_obj = bpy.context.selected_objects + if len(Arr_obj) < 1: + self.report({'WARNING'}, 'Select a mesh to add the UVProject-Modifier') + return {"CANCELLED"} + + empty_objs = [emp_obj for emp_obj in bpy.context.scene.objects if emp_obj.name.startswith("Proj_Empty")] + if len(empty_objs) < 6: + self.report({'WARNING'}, 'Create/Recreate projectors, they need to be set up first!') + return {"CANCELLED"}; + + for obj in Arr_obj: + + if obj.data.uv_layers.get("UVMap"): + obj.data.uv_layers['UVMap'].name = 'UVMap0' + + if not obj.data.uv_layers.get("UVMap0"): + obj.data.uv_layers.new(name = 'UVMap0') + + if not obj.data.uv_layers.get("UVMap1"): + obj.data.uv_layers.new(name = 'UVMap1') + + + if obj.type == "MESH" and newModifierName not in obj.modifiers: + obj.modifiers.new(type='UV_PROJECT', name=newModifierName) + mod = obj.modifiers[newModifierName] + mod.uv_layer = "UVMap1" + mod.projector_count = 6 + + i = 0 + for p in mod.projectors: + p.object = bpy.data.objects[L1960_Arr_PlainData[i][0]] + i = i+1 + else: + self.report({'INFO'}, 'UVProject-Modifier allready set') + return {"FINISHED"} + + self.report({'INFO'}, 'Added UVProject-Modifier to mesh') + return {"FINISHED"} \ No newline at end of file diff --git a/Blender/_Source/L1960_Tools_1_4_0/FixMaterials.py b/Blender/_Source/L1960_Tools_1_4_0/FixMaterials.py new file mode 100644 index 0000000..83e9dbd --- /dev/null +++ b/Blender/_Source/L1960_Tools_1_4_0/FixMaterials.py @@ -0,0 +1,65 @@ +import bpy + +def replace_material(bad_mat, good_mat): + bad_mat.user_remap(good_mat) + bpy.data.materials.remove(bad_mat) + + +def get_duplicate_materials(og_material): + + common_name = og_material.name + + if common_name[-3:].isnumeric(): + common_name = common_name[:-4] + + duplicate_materials = [] + + for material in bpy.data.materials: + if material is not og_material: + name = material.name + if name[-3:].isnumeric() and name[-4] == ".": + name = name[:-4] + + if name == common_name: + duplicate_materials.append(material) + + text = "{} duplicate materials found" + print(text.format(len(duplicate_materials))) + + return duplicate_materials + + +def remove_all_duplicate_materials(): + i = 0 + while i < len(bpy.data.materials): + + og_material = bpy.data.materials[i] + + print("og material: " + og_material.name) + + # get duplicate materials + duplicate_materials = get_duplicate_materials(og_material) + + # replace all duplicates + for duplicate_material in duplicate_materials: + replace_material(duplicate_material, og_material) + + # adjust name to no trailing numbers + if og_material.name[-3:].isnumeric() and og_material.name[-4] == ".": + og_material.name = og_material.name[:-4] + + i = i+1 + +class MESH_OT_fix_material_names(bpy.types.Operator): + """Fixes the material naming, if duplicated are present e.g. Material.001, Material.002 ...""" + + bl_idname = "mesh.fix_material_names" + bl_label = "Fixes the material naming, if duplicated are present" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + + remove_all_duplicate_materials() + + self.report({'INFO'}, 'All duplicated Materials merged/fixed') + return {"FINISHED"} \ No newline at end of file diff --git a/Blender/_Source/L1960_Tools_1_4_0/PrepareLods.py b/Blender/_Source/L1960_Tools_1_4_0/PrepareLods.py new file mode 100644 index 0000000..79453db --- /dev/null +++ b/Blender/_Source/L1960_Tools_1_4_0/PrepareLods.py @@ -0,0 +1,13 @@ +import bpy + +class MESH_OT_prepare_lods_decimate(bpy.types.Operator): + """Copy current Mesh and apply decimate Modifier""" + + bl_idname = "mesh.prepare_lods_decimate" + bl_label = "Copy current Mesh and apply decimate Modifier" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + + self.report({'INFO'}, 'Currently not in use') + return {"FINISHED"} \ No newline at end of file diff --git a/Blender/_Source/L1960_Tools_1_4_0/__init__.py b/Blender/_Source/L1960_Tools_1_4_0/__init__.py new file mode 100644 index 0000000..1ca1d5c --- /dev/null +++ b/Blender/_Source/L1960_Tools_1_4_0/__init__.py @@ -0,0 +1,74 @@ +bl_info = { + "name": "L1960 Tools", + "author": "Prodeath21", + "version": (1, 4, 0), + "blender": (2, 80, 0), + "location": "3D Viewport > Sidebar > 1960Life category", + "description": "Set´s up the Projection-Modifier automatically and add´s in the Emptys if not allready created.", + "category": "Object", +} + +# ---------------------------------------------- +# Import modules +# ---------------------------------------------- +if "bpy" in locals(): + import imp + imp.reload(CubeProjection) + imp.reload(FixMaterials) + imp.reload(PrepareLods) + print("L1960 Tools: Reloaded multifiles") +else: + from . import CubeProjection + from . import FixMaterials + from . import PrepareLods + +import bpy + +from . CubeProjection import MESH_OT_add_auto_cube_projection, MESH_OT_add_modifier_to_mesh +from . FixMaterials import MESH_OT_fix_material_names +from . PrepareLods import MESH_OT_prepare_lods_decimate + +class L1960_PT_tools(bpy.types.Panel): + pass + #where to add the panel + bl_space_type = "VIEW_3D" + bl_region_type = "UI" + + #add labels + bl_label = "1960-Life Tools" + bl_category = "1960-Life" + + def draw(self, context): + """define the layout of the panel""" + self.layout.label(text="UV-Projection") + row = self.layout.row() + row.operator("mesh.add_auto_cube_projection", text="Set up Projectors") + row = self.layout.row() + row.operator("mesh.add_modifier_to_mesh", text="Add Modifier to Mesh") + self.layout.separator() + self.layout.label(text="Materials") + row = self.layout.row() + row.operator("mesh.fix_material_names", text="Fix Material Name´s") + self.layout.separator() + self.layout.label(text="LOD´s") + row = self.layout.row() + row.operator("mesh.prepare_lods_decimate", text="Create LOD´s with decimate") + +#register the panel with blender +modules = [ L1960_PT_tools, + MESH_OT_add_auto_cube_projection, + MESH_OT_add_modifier_to_mesh, + MESH_OT_fix_material_names, + MESH_OT_prepare_lods_decimate +] + +def register(): + for mod in modules: + bpy.utils.register_class(mod) + +def unregister(): + for mod in modules: + bpy.utils.unregister_class(mod) + +if __name__== "__main__": + register() \ No newline at end of file diff --git a/Blender/_Source/L1960_Tools_1_5_0/CubeProjection.py b/Blender/_Source/L1960_Tools_1_5_0/CubeProjection.py new file mode 100644 index 0000000..c586c48 --- /dev/null +++ b/Blender/_Source/L1960_Tools_1_5_0/CubeProjection.py @@ -0,0 +1,94 @@ +import bpy +from math import pi + +L1960_Arr_PlainData = [ + ["Proj_Empty_01", (0, 0, 2), (0, 0, 0)], + ["Proj_Empty_02", (2, 0, 0), ((pi * 90 / 180), 0, (pi * 90 / 180))], + ["Proj_Empty_03", (0, 2, 0), ((pi * 90 / 180), 0, (pi * 180 / 180))], + ["Proj_Empty_04", (0, 0, -2), ((pi * 180 / 180), 0, 0)], + ["Proj_Empty_05", (-2, 0, 0), ((pi * 90 / 180), 0, (pi * -90 / 180))], + ["Proj_Empty_06", (0, -2, 0), ((pi * 90 / 180), 0, 0)] +] + +class MESH_OT_add_auto_cube_projection(bpy.types.Operator): + """Check Empty´s for projecting, if not existing create new one´s""" + + bl_idname = "mesh.add_auto_cube_projection" + bl_label = "Add Plain_Axes to scene" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + + scene = bpy.context.scene + oldSelection = bpy.context.selected_objects + oldActive = bpy.context.active_object + + for EmptyData in L1960_Arr_PlainData: + + EmptyName = EmptyData[0] + EmptyLocation = EmptyData[1] + EmptyRotation = EmptyData[2] + + if not scene.objects.get(EmptyName): + bpy.ops.object.empty_add(type='PLAIN_AXES', align='WORLD', location=EmptyLocation, scale=(1, 1, 1), rotation=EmptyRotation) + empty = bpy.context.active_object + empty.name = EmptyName + empty.hide_select = True + empty.hide_set(True) + + #Change back to old selection and select old active + for obj in oldSelection: + obj.select_set(True) + bpy.context.view_layer.objects.active = oldActive + + self.report({'INFO'}, 'Added/Fixed Emptys for Projection to Scene') + return {"FINISHED"} + +class MESH_OT_add_modifier_to_mesh(bpy.types.Operator): + """Add Modifier to selected Mesh´s and prepare UV-Maps""" + + bl_idname = "mesh.add_modifier_to_mesh" + bl_label = "Add Modifier to selected Mesh" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + + newModifierName = "CubeTexModifier" + Arr_obj = bpy.context.selected_objects + if len(Arr_obj) < 1: + self.report({'WARNING'}, 'Select a mesh to add the UVProject-Modifier') + return {"CANCELLED"} + + empty_objs = [emp_obj for emp_obj in bpy.context.scene.objects if emp_obj.name.startswith("Proj_Empty")] + if len(empty_objs) < 6: + self.report({'WARNING'}, 'Create/Recreate projectors, they need to be set up first!') + return {"CANCELLED"}; + + for obj in Arr_obj: + + if obj.data.uv_layers.get("UVMap"): + obj.data.uv_layers['UVMap'].name = 'UVMap0' + + if not obj.data.uv_layers.get("UVMap0"): + obj.data.uv_layers.new(name = 'UVMap0') + + if not obj.data.uv_layers.get("UVMap1"): + obj.data.uv_layers.new(name = 'UVMap1') + + + if obj.type == "MESH" and newModifierName not in obj.modifiers: + obj.modifiers.new(type='UV_PROJECT', name=newModifierName) + mod = obj.modifiers[newModifierName] + mod.uv_layer = "UVMap1" + mod.projector_count = 6 + + i = 0 + for p in mod.projectors: + p.object = bpy.data.objects[L1960_Arr_PlainData[i][0]] + i = i+1 + else: + self.report({'INFO'}, 'UVProject-Modifier allready set') + return {"FINISHED"} + + self.report({'INFO'}, 'Added UVProject-Modifier to mesh') + return {"FINISHED"} \ No newline at end of file diff --git a/Blender/_Source/L1960_Tools_1_5_0/FixMaterials.py b/Blender/_Source/L1960_Tools_1_5_0/FixMaterials.py new file mode 100644 index 0000000..b398704 --- /dev/null +++ b/Blender/_Source/L1960_Tools_1_5_0/FixMaterials.py @@ -0,0 +1,65 @@ +import bpy + +def replace_material(bad_mat, good_mat): + bad_mat.user_remap(good_mat) + bpy.data.materials.remove(bad_mat) + + +def get_duplicate_materials(og_material): + + common_name = og_material.name + + if common_name[-3:].isnumeric(): + common_name = common_name[:-4] + + duplicate_materials = [] + + for material in bpy.data.materials: + if material is not og_material: + name = material.name + if name[-3:].isnumeric() and name[-4] == ".": + name = name[:-4] + + if name == common_name: + duplicate_materials.append(material) + + text = "{} duplicate materials found" + print(text.format(len(duplicate_materials))) + + return duplicate_materials + + +def remove_all_duplicate_materials(): + i = 0 + while i < len(bpy.data.materials): + + og_material = bpy.data.materials[i] + + print("og material: " + og_material.name) + + # get duplicate materials + duplicate_materials = get_duplicate_materials(og_material) + + # replace all duplicates + for duplicate_material in duplicate_materials: + replace_material(duplicate_material, og_material) + + # adjust name to no trailing numbers + if og_material.name[-3:].isnumeric() and og_material.name[-4] == ".": + og_material.name = og_material.name[:-4] + + i = i+1 + +class MESH_OT_fix_material_names(bpy.types.Operator): + """Fixes the material naming, if duplicated are present e.g. Material.001, Material.002 ...""" + + bl_idname = "mesh.fix_material_names" + bl_label = "Fixes the material naming, if duplicated are present" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + + remove_all_duplicate_materials() + + self.report({'INFO'}, 'All duplicated Materials fixed') + return {"FINISHED"} \ No newline at end of file diff --git a/Blender/_Source/L1960_Tools_1_5_0/PrepareLods.py b/Blender/_Source/L1960_Tools_1_5_0/PrepareLods.py new file mode 100644 index 0000000..ef61f03 --- /dev/null +++ b/Blender/_Source/L1960_Tools_1_5_0/PrepareLods.py @@ -0,0 +1,40 @@ +import bpy + +class MESH_OT_prepare_lods_decimate(bpy.types.Operator): + """Copy current Mesh and apply decimate Modifier""" + + bl_idname = "mesh.prepare_lods_decimate" + bl_label = "Copy current Mesh and apply decimate Modifier" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + + #Selected Mesh + obj = bpy.context.active_object + + if obj not in bpy.context.selected_objects or obj.type != "MESH": + self.report({'WARNING'}, 'Select a Mesh to continue') + return {"CANCELLED"} + + if not obj.name[:-1].endswith('LOD'): + obj.name = obj.name + '_LOD0' + + LODnumber = context.scene.lod_slider #Get from Slider + startLODcount = int(obj.name[-1]) + endLODcount = startLODcount + LODnumber + + for i in range (startLODcount + 1, endLODcount): + new_obj = obj.copy() + new_obj.data = obj.data.copy() + new_obj.name = obj.name[:-1] + str(i) + bpy.context.collection.objects.link(new_obj) + + for t in range (startLODcount, i): + newModifierName = 'LOD_Decimate_' + str(t) + new_obj.modifiers.new(type='DECIMATE', name=newModifierName) + mod = new_obj.modifiers[newModifierName] + mod.ratio = 0.49 + mod.use_collapse_triangulate = True + + self.report({'INFO'}, 'LOD´s created') + return {"FINISHED"} \ No newline at end of file diff --git a/Blender/_Source/L1960_Tools_1_5_0/__init__.py b/Blender/_Source/L1960_Tools_1_5_0/__init__.py new file mode 100644 index 0000000..7003c34 --- /dev/null +++ b/Blender/_Source/L1960_Tools_1_5_0/__init__.py @@ -0,0 +1,82 @@ +bl_info = { + "name": "L1960 Tools", + "author": "Prodeath21", + "version": (1, 5, 0), + "blender": (2, 80, 0), + "location": "3D Viewport > Sidebar > 1960Life category", + "description": "Set´s up the Projection-Modifier automatically and add´s in the Emptys if not allready created.", + "category": "Object", +} + +# ---------------------------------------------- +# Import modules +# ---------------------------------------------- +if "bpy" in locals(): + import imp + imp.reload(CubeProjection) + imp.reload(FixMaterials) + imp.reload(PrepareLods) + print("L1960 Tools: Reloaded multifiles") +else: + from . import CubeProjection + from . import FixMaterials + from . import PrepareLods + +import bpy + +from . CubeProjection import MESH_OT_add_auto_cube_projection, MESH_OT_add_modifier_to_mesh +from . FixMaterials import MESH_OT_fix_material_names +from . PrepareLods import MESH_OT_prepare_lods_decimate + +class L1960_PT_tools(bpy.types.Panel): + pass + #where to add the panel + bl_space_type = "VIEW_3D" + bl_region_type = "UI" + + #add labels + bl_label = "1960-Life Tools" + bl_category = "1960-Life" + + def draw(self, context): + """define the layout of the panel""" + box = self.layout.box() + box.label(text="UV-Projection") + row = box.row() + row.operator("mesh.add_auto_cube_projection", text="Set up Projectors") + row = box.row() + row.operator("mesh.add_modifier_to_mesh", text="Add Modifier to Mesh") + self.layout.separator() + box = self.layout.box() + box.label(text="Materials") + row = box.row() + row.operator("mesh.fix_material_names", text="Fix Material Name´s") + self.layout.separator() + box = self.layout.box() + box.label(text="LOD´s") + row = box.row() + row.operator("mesh.prepare_lods_decimate", text="Create LOD´s") + box.prop(context.scene, "lod_slider", text="") + +#register the panel with blender +modules = [ L1960_PT_tools, + MESH_OT_add_auto_cube_projection, + MESH_OT_add_modifier_to_mesh, + MESH_OT_fix_material_names, + MESH_OT_prepare_lods_decimate +] + +def register(): + for mod in modules: + bpy.utils.register_class(mod) + + bpy.types.Scene.lod_slider = bpy.props.IntProperty(name="LOD Number", default=3, min=0, max=10) + +def unregister(): + for mod in modules: + bpy.utils.unregister_class(mod) + + del bpy.types.Scene.lod_slider + +if __name__== "__main__": + register() \ No newline at end of file diff --git a/Blender/_Source/L1960_Tools_1_6_0/CubeProjection.py b/Blender/_Source/L1960_Tools_1_6_0/CubeProjection.py new file mode 100644 index 0000000..c586c48 --- /dev/null +++ b/Blender/_Source/L1960_Tools_1_6_0/CubeProjection.py @@ -0,0 +1,94 @@ +import bpy +from math import pi + +L1960_Arr_PlainData = [ + ["Proj_Empty_01", (0, 0, 2), (0, 0, 0)], + ["Proj_Empty_02", (2, 0, 0), ((pi * 90 / 180), 0, (pi * 90 / 180))], + ["Proj_Empty_03", (0, 2, 0), ((pi * 90 / 180), 0, (pi * 180 / 180))], + ["Proj_Empty_04", (0, 0, -2), ((pi * 180 / 180), 0, 0)], + ["Proj_Empty_05", (-2, 0, 0), ((pi * 90 / 180), 0, (pi * -90 / 180))], + ["Proj_Empty_06", (0, -2, 0), ((pi * 90 / 180), 0, 0)] +] + +class MESH_OT_add_auto_cube_projection(bpy.types.Operator): + """Check Empty´s for projecting, if not existing create new one´s""" + + bl_idname = "mesh.add_auto_cube_projection" + bl_label = "Add Plain_Axes to scene" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + + scene = bpy.context.scene + oldSelection = bpy.context.selected_objects + oldActive = bpy.context.active_object + + for EmptyData in L1960_Arr_PlainData: + + EmptyName = EmptyData[0] + EmptyLocation = EmptyData[1] + EmptyRotation = EmptyData[2] + + if not scene.objects.get(EmptyName): + bpy.ops.object.empty_add(type='PLAIN_AXES', align='WORLD', location=EmptyLocation, scale=(1, 1, 1), rotation=EmptyRotation) + empty = bpy.context.active_object + empty.name = EmptyName + empty.hide_select = True + empty.hide_set(True) + + #Change back to old selection and select old active + for obj in oldSelection: + obj.select_set(True) + bpy.context.view_layer.objects.active = oldActive + + self.report({'INFO'}, 'Added/Fixed Emptys for Projection to Scene') + return {"FINISHED"} + +class MESH_OT_add_modifier_to_mesh(bpy.types.Operator): + """Add Modifier to selected Mesh´s and prepare UV-Maps""" + + bl_idname = "mesh.add_modifier_to_mesh" + bl_label = "Add Modifier to selected Mesh" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + + newModifierName = "CubeTexModifier" + Arr_obj = bpy.context.selected_objects + if len(Arr_obj) < 1: + self.report({'WARNING'}, 'Select a mesh to add the UVProject-Modifier') + return {"CANCELLED"} + + empty_objs = [emp_obj for emp_obj in bpy.context.scene.objects if emp_obj.name.startswith("Proj_Empty")] + if len(empty_objs) < 6: + self.report({'WARNING'}, 'Create/Recreate projectors, they need to be set up first!') + return {"CANCELLED"}; + + for obj in Arr_obj: + + if obj.data.uv_layers.get("UVMap"): + obj.data.uv_layers['UVMap'].name = 'UVMap0' + + if not obj.data.uv_layers.get("UVMap0"): + obj.data.uv_layers.new(name = 'UVMap0') + + if not obj.data.uv_layers.get("UVMap1"): + obj.data.uv_layers.new(name = 'UVMap1') + + + if obj.type == "MESH" and newModifierName not in obj.modifiers: + obj.modifiers.new(type='UV_PROJECT', name=newModifierName) + mod = obj.modifiers[newModifierName] + mod.uv_layer = "UVMap1" + mod.projector_count = 6 + + i = 0 + for p in mod.projectors: + p.object = bpy.data.objects[L1960_Arr_PlainData[i][0]] + i = i+1 + else: + self.report({'INFO'}, 'UVProject-Modifier allready set') + return {"FINISHED"} + + self.report({'INFO'}, 'Added UVProject-Modifier to mesh') + return {"FINISHED"} \ No newline at end of file diff --git a/Blender/_Source/L1960_Tools_1_6_0/FixMaterials.py b/Blender/_Source/L1960_Tools_1_6_0/FixMaterials.py new file mode 100644 index 0000000..b398704 --- /dev/null +++ b/Blender/_Source/L1960_Tools_1_6_0/FixMaterials.py @@ -0,0 +1,65 @@ +import bpy + +def replace_material(bad_mat, good_mat): + bad_mat.user_remap(good_mat) + bpy.data.materials.remove(bad_mat) + + +def get_duplicate_materials(og_material): + + common_name = og_material.name + + if common_name[-3:].isnumeric(): + common_name = common_name[:-4] + + duplicate_materials = [] + + for material in bpy.data.materials: + if material is not og_material: + name = material.name + if name[-3:].isnumeric() and name[-4] == ".": + name = name[:-4] + + if name == common_name: + duplicate_materials.append(material) + + text = "{} duplicate materials found" + print(text.format(len(duplicate_materials))) + + return duplicate_materials + + +def remove_all_duplicate_materials(): + i = 0 + while i < len(bpy.data.materials): + + og_material = bpy.data.materials[i] + + print("og material: " + og_material.name) + + # get duplicate materials + duplicate_materials = get_duplicate_materials(og_material) + + # replace all duplicates + for duplicate_material in duplicate_materials: + replace_material(duplicate_material, og_material) + + # adjust name to no trailing numbers + if og_material.name[-3:].isnumeric() and og_material.name[-4] == ".": + og_material.name = og_material.name[:-4] + + i = i+1 + +class MESH_OT_fix_material_names(bpy.types.Operator): + """Fixes the material naming, if duplicated are present e.g. Material.001, Material.002 ...""" + + bl_idname = "mesh.fix_material_names" + bl_label = "Fixes the material naming, if duplicated are present" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + + remove_all_duplicate_materials() + + self.report({'INFO'}, 'All duplicated Materials fixed') + return {"FINISHED"} \ No newline at end of file diff --git a/Blender/_Source/L1960_Tools_1_6_0/PrepareLods.py b/Blender/_Source/L1960_Tools_1_6_0/PrepareLods.py new file mode 100644 index 0000000..ef61f03 --- /dev/null +++ b/Blender/_Source/L1960_Tools_1_6_0/PrepareLods.py @@ -0,0 +1,40 @@ +import bpy + +class MESH_OT_prepare_lods_decimate(bpy.types.Operator): + """Copy current Mesh and apply decimate Modifier""" + + bl_idname = "mesh.prepare_lods_decimate" + bl_label = "Copy current Mesh and apply decimate Modifier" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + + #Selected Mesh + obj = bpy.context.active_object + + if obj not in bpy.context.selected_objects or obj.type != "MESH": + self.report({'WARNING'}, 'Select a Mesh to continue') + return {"CANCELLED"} + + if not obj.name[:-1].endswith('LOD'): + obj.name = obj.name + '_LOD0' + + LODnumber = context.scene.lod_slider #Get from Slider + startLODcount = int(obj.name[-1]) + endLODcount = startLODcount + LODnumber + + for i in range (startLODcount + 1, endLODcount): + new_obj = obj.copy() + new_obj.data = obj.data.copy() + new_obj.name = obj.name[:-1] + str(i) + bpy.context.collection.objects.link(new_obj) + + for t in range (startLODcount, i): + newModifierName = 'LOD_Decimate_' + str(t) + new_obj.modifiers.new(type='DECIMATE', name=newModifierName) + mod = new_obj.modifiers[newModifierName] + mod.ratio = 0.49 + mod.use_collapse_triangulate = True + + self.report({'INFO'}, 'LOD´s created') + return {"FINISHED"} \ No newline at end of file diff --git a/Blender/_Source/L1960_Tools_1_6_0/__init__.py b/Blender/_Source/L1960_Tools_1_6_0/__init__.py new file mode 100644 index 0000000..a5eea70 --- /dev/null +++ b/Blender/_Source/L1960_Tools_1_6_0/__init__.py @@ -0,0 +1,104 @@ +bl_info = { + "name": "L1960 Tools", + "author": "Prodeath21", + "version": (1, 6, 0), + "blender": (2, 80, 0), + "location": "3D Viewport > Sidebar > 1960Life category", + "description": "Set´s up the Projection-Modifier automatically and add´s in the Emptys if not allready created.", + "category": "Object", +} + +# ---------------------------------------------- +# Import modules +# ---------------------------------------------- +if "bpy" in locals(): + import imp + imp.reload(CubeProjection) + imp.reload(FixMaterials) + imp.reload(PrepareLods) + print("L1960 Tools: Reloaded multifiles") +else: + from . import CubeProjection + from . import FixMaterials + from . import PrepareLods + +import bpy + +from . CubeProjection import MESH_OT_add_auto_cube_projection, MESH_OT_add_modifier_to_mesh +from . FixMaterials import MESH_OT_fix_material_names +from . PrepareLods import MESH_OT_prepare_lods_decimate + +class L1960_PT_tools(bpy.types.Panel): + pass + #where to add the panel + bl_space_type = "VIEW_3D" + bl_region_type = "UI" + + #add labels + bl_label = "1960-Life Tools" + bl_category = "1960-Life" + + def draw(self, context): + """define the layout of the panel""" + box = self.layout.box() + # UV-Project helper + box.label(text="UV-Projection") + row = box.row() + row.operator("mesh.add_auto_cube_projection", text="Set up Projectors") + row = box.row() + row.operator("mesh.add_modifier_to_mesh", text="Add Modifier to Mesh") + self.layout.separator() + box = self.layout.box() + # Materials helper + box.label(text="Materials") + row = box.row() + row.operator("mesh.fix_material_names", text="Fix Material Name´s") + self.layout.separator() + box = self.layout.box() + # Generate LODs + box.label(text="LOD´s") + row = box.row() + row.operator("mesh.prepare_lods_decimate", text="Create LOD´s") + box.prop(context.scene, "lod_slider", text="LOD Number") + ############################### + # Enfusion Blender Tools Linked + box = self.layout.box() + box.label(text="EBT Linked") + row = box.row() + row.operator("view3d.ebt_sort", text="Sort Objects") + # colliders setup is allowed in both OBJECT and EDIT mode + row = box.row() + row.operator("view3d.ebt_colliders_setup", text=" Colliders Setup") + row = box.row() + # Light Setup + row.operator("view3d.ebt_setup_light", text=" Light Setup") + row = box.row() + col = row.column(align=True) + # Update Materials + col.operator("scene.ebt_update_enf_materials",) + row = box.row() + col = row.column(align=True) + + +#register the panel with blender +modules = [ L1960_PT_tools, + MESH_OT_add_auto_cube_projection, + MESH_OT_add_modifier_to_mesh, + MESH_OT_fix_material_names, + MESH_OT_prepare_lods_decimate +] + +def register(): + for mod in modules: + bpy.utils.register_class(mod) + + bpy.types.Scene.lod_slider = bpy.props.IntProperty(name="LOD Number", default=3, min=0, max=10) + +def unregister(): + for mod in modules: + bpy.utils.unregister_class(mod) + + del bpy.types.Scene.lod_slider + +if __name__== "__main__": + register() \ No newline at end of file