Blender Plugin 1.6.0

This commit is contained in:
ProDeath21
2024-03-24 20:20:59 +01:00
parent 7512e0fdfe
commit 9c765b4ef4
19 changed files with 1054 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -0,0 +1,65 @@
bl_info = {
"name": "L1960 Tools",
"author": "Prodeath21",
"version": (1, 3, 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)
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()

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -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()

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -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()

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -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()