Blender Plugin 1.8.0

NEW:
- auto gen. Emptys at mesh origin
- fix naming convention from point to underscore
- auto gen. Collections for Unreal export
FIX:
- "Fix Material Names" completely redone (pls test)
This commit is contained in:
ProDeath21
2024-05-13 23:25:03 +02:00
parent 1529bda410
commit 5e62f1d81d
7 changed files with 513 additions and 0 deletions

View File

@@ -0,0 +1,169 @@
import bpy
import re
### FIX MATERIALS ###
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 duplicated materials
self.merge_duplicated_materials()
#Merge material slots for every mesh in the scene
#for obj in bpy.context.scene.objects:
#if obj.type == "MESH":
#self.merge_material_slots(obj)
self.report({'INFO'}, 'All duplicated Materials fixed')
return {"FINISHED"}
def merge_duplicated_materials(self):
for material in bpy.data.materials:
if material.name[-3].isnumeric():
opti_matName = material.name[:-4]
if bpy.data.materials.get(opti_matName): #check if og_mat exists
material.user_remap(bpy.data.materials.get(opti_matName))
print("Removed Material: " + material.name)
bpy.data.materials.remove(material)
else:
material.name = opti_matName
def merge_material_slots(self, obj):
duplicated_material_list = []
#create list with indexes of material slots with the same name
for og_slot in obj.material_slots:
for slot in obj.material_slots:
if slot.name == og_slot.name:
if slot.slot_index == og_slot.slot_index:
continue
if og_slot.slot_index in duplicated_material_list:
continue
duplicated_material_list.append(int(slot.slot_index))
#delete all material slots within list
for slot_index in sorted(duplicated_material_list, reverse=True):
obj.data.materials.pop(index = slot_index)
### GROUP OBJECTS TO COLLECTIONS ###
class MESH_OT_group_objects_in_collections(bpy.types.Operator):
"""Groups objects by name into seperate collections, usefull for Unreal Decogon import"""
bl_idname = "mesh.group_objects_in_collections"
bl_label = "Groups objects by name into seperate collections, usefull for Unreal Decogon import"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
# Erstellen einer leeren Dictionary zur Speicherung der Collections nach Basisnamen
collection_dict = {}
# Durchlaufen aller Objekte in der Szene
for obj in bpy.context.scene.objects:
# Überprüfen, ob das Objekt ein leeres Elternobjekt ist
if obj.type == 'EMPTY':
# Anwenden der Regex auf den Objektnamen
match = re.match(r'^(.*?)_(.*?)_(\d+)([a-zA-Z]+)$', obj.name)
if match:
prefix = match.group(1)
name = match.group(2)
number = match.group(3)
letter = match.group(4)
# Extrahieren des Basisnamens für die Collection
base_name = f"L1960_{name}"
# Hinzufügen des Objekts zur entsprechenden Liste in der Dictionary
if base_name not in collection_dict:
collection_dict[base_name] = {}
if number not in collection_dict[base_name]:
collection_dict[base_name][number] = {}
if letter not in collection_dict[base_name][number]:
collection_dict[base_name][number][letter] = {'empty': obj, 'children': []}
# Durchlaufen der Dictionary und Erstellen der Collections
for base_name, number_dict in collection_dict.items():
# Erstellen einer neuen Collection für den Basisnamen
base_collection = bpy.data.collections.new(base_name)
bpy.context.scene.collection.children.link(base_collection)
# Durchlaufen der sortierten Liste der Objekte und Verschieben in die Collections
for number, letter_dict in number_dict.items():
# Erstellen einer Collection für die Nummer und Verschieben des leeren Elternobjekts dorthin
number_collection = bpy.data.collections.new(f"{base_name}_{number}")
base_collection.children.link(number_collection)
# Durchlaufen der Buchstaben und Erstellen der Buchstaben-Collection unter der Nummer
for letter, obj_data in letter_dict.items():
empty = obj_data['empty']
children = empty.children
letter_collection = bpy.data.collections.new(f"{base_name}_{number}{letter}")
number_collection.children.link(letter_collection)
# Verschieben des leeren Elternobjekts in die entsprechende Collection
letter_collection.objects.link(empty)
# Verschieben der Kinder des leeren Elternobjekts in die entsprechende Collection
for child in children:
letter_collection.objects.link(child)
# Entfernen des leeren Elternobjekts und seiner Kinder aus der Szene
bpy.context.collection.objects.unlink(empty)
for child in children:
bpy.context.collection.objects.unlink(child)
self.report({'INFO'}, 'All objects sorted')
return {"FINISHED"}
### FIX NAMING CONVENTIONS ###
class MESH_OT_fix_naming_conventions(bpy.types.Operator):
"""Changes . to _ to solve naming issues with workbench"""
bl_idname = "mesh.fix_naming_convention"
bl_label = "Changes . to _ to solve naming issues with workbench"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
for obj in bpy.data.objects:
obj.name = obj.name.replace(".","_")
self.report({'INFO'}, 'Fixed Naming')
return {"FINISHED"}
class MESH_OT_generate_empty_for_mesh(bpy.types.Operator):
"""Generates a Empty with the objects name at it´s position"""
bl_idname = "mesh.generate_empty_for_mesh"
bl_label = "Generates a Empty with the objects name at it´s position"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
scene = bpy.context.scene
Selection = bpy.context.selected_objects
FilteredSelection = [obj for obj in Selection if obj.type != 'EMPTY']
ActiveObj = bpy.context.active_object
for obj in FilteredSelection:
oldEmpty = scene.objects.get("Socket_" + obj.name)
if oldEmpty:
oldEmpty.location = obj.location
oldEmpty.rotation_euler = obj.rotation_euler
else:
obj.select_set(True)
bpy.ops.object.empty_add(type='PLAIN_AXES', align='WORLD', location=obj.location, scale=(1, 1, 1), rotation=obj.rotation_euler)
empty = bpy.context.active_object
empty.name = "Socket_" + obj.name
#Change back to selection and select old active
bpy.ops.object.select_all(action='DESELECT')
self.report({'INFO'}, 'Generated Emptys for selectes Meshes in Scene')
return {"FINISHED"}