Optimzation Panel Re-Added

- Major Improvements all round, Join Meshes improved, Combined Materials, Remove Doubles Improvements.
This commit is contained in:
Yusarina
2024-12-05 01:13:10 +00:00
parent 9961223548
commit 9cc5a41a98
15 changed files with 755 additions and 9 deletions
View File
+83 -4
View File
@@ -146,12 +146,12 @@ def validate_symmetry(bones: Dict[str, bpy.types.Bone], base: str, left: str, ri
right_exists = any(pattern in bones for pattern in right_patterns)
return left_exists and right_exists
def auto_select_single_armature(context: bpy.types.Context) -> None:
"""Automatically select armature if only one exists in scene"""
armatures = get_armature_list(context)
if len(armatures) == 1:
if len(armatures) == 1 and armatures[0][0] != 'NONE':
toolkit = context.scene.avatar_toolkit
set_active_armature(context, armatures[0])
def clear_default_objects() -> None:
@@ -305,4 +305,83 @@ def apply_armature_to_mesh_with_shapekeys(armature_obj: Object, mesh_obj: Object
sk.mute = mute
mesh_obj.active_shape_key_index = old_active_index
mesh_obj.show_only_shape_key = old_show_only
mesh_obj.show_only_shape_key = old_show_only
def validate_meshes(meshes: List[Object]) -> Tuple[bool, str]:
"""Validates a list of mesh objects to ensure they are suitable for joining operations"""
if not meshes:
return False, t("Optimization.no_meshes")
if not all(mesh.data for mesh in meshes):
return False, t("Optimization.invalid_mesh_data")
if not all(mesh.type == 'MESH' for mesh in meshes):
return False, t("Optimization.non_mesh_objects")
return True, ""
def join_mesh_objects(context: Context, meshes: List[Object], progress: Optional[ProgressTracker] = None) -> Tuple[bool, str]:
"""Combines multiple mesh objects into a single mesh with proper cleanup and UV fixing"""
try:
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='DESELECT')
for mesh in meshes:
mesh.select_set(True)
if context.selected_objects:
context.view_layer.objects.active = context.selected_objects[0]
if progress:
progress.step(t("Optimization.joining_meshes"))
bpy.ops.object.join()
if progress:
progress.step(t("Optimization.applying_transforms"))
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
if progress:
progress.step(t("Optimization.fixing_uvs"))
fix_uv_coordinates(context)
return True, t("Optimization.meshes_joined")
return False, t("Optimization.no_mesh_selected")
except Exception as e:
logger.error(f"Failed to join meshes: {str(e)}")
return False, str(e)
def fix_uv_coordinates(context: Context) -> None:
"""Normalizes and fixes UV coordinates for the active mesh object"""
obj: Object = context.object
current_mode: str = context.mode
current_active: Object = context.view_layer.objects.active
current_selected: List[Object] = context.selected_objects.copy()
try:
bpy.ops.object.mode_set(mode='OBJECT')
obj.select_set(True)
context.view_layer.objects.active = obj
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
with context.temp_override(active_object=obj):
bpy.ops.uv.select_all(action='SELECT')
bpy.ops.uv.average_islands_scale()
logger.debug(f"UV Fix - Successfully processed {obj.name}")
except Exception as e:
logger.warning(f"UV Fix - Skipped processing for {obj.name}: {str(e)}")
finally:
bpy.ops.object.mode_set(mode='OBJECT')
for sel_obj in current_selected:
sel_obj.select_set(True)
context.view_layer.objects.active = current_active
def clear_unused_data_blocks(self) -> int:
"""Removes all unused data blocks from the current Blender file"""
initial_count: int = sum(len(getattr(bpy.data, attr)) for attr in dir(bpy.data) if isinstance(getattr(bpy.data, attr), bpy.types.bpy_prop_collection))
bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True)
final_count: int = sum(len(getattr(bpy.data, attr)) for attr in dir(bpy.data) if isinstance(getattr(bpy.data, attr), bpy.types.bpy_prop_collection))
return initial_count - final_count
View File
View File
+16 -3
View File
@@ -14,7 +14,7 @@ from .logging_setup import logger
from .translations import t, get_languages_list, update_language
from .addon_preferences import get_preference, save_preference
from .updater import get_version_list
from .common import get_armature_list
from .common import get_armature_list, get_active_armature, get_all_meshes
def update_validation_mode(self, context):
logger.info(f"Updating validation mode to: {self.validation_mode}")
@@ -38,7 +38,7 @@ class AvatarToolkitSceneProperties(PropertyGroup):
active_armature: EnumProperty(
items=get_armature_list,
name=t("QuickAccess.select_armature"),
description=t("QuickAccess.select_armature")
description=t("QuickAccess.select_armature"),
)
language: EnumProperty(
@@ -72,6 +72,20 @@ class AvatarToolkitSceneProperties(PropertyGroup):
default=False
)
remove_doubles_merge_distance: FloatProperty(
name=t("Optimization.merge_distance"),
description=t("Optimization.merge_distance_desc"),
default=0.0001,
min=0.00001,
max=0.1
)
remove_doubles_advanced: BoolProperty(
name=t("Optimization.remove_doubles_advanced"),
description=t("Optimization.remove_doubles_advanced_desc"),
default=False
)
def register() -> None:
"""Register the Avatar Toolkit property group"""
logger.info("Registering Avatar Toolkit properties")
@@ -83,4 +97,3 @@ def unregister() -> None:
logger.info("Unregistering Avatar Toolkit properties")
del bpy.types.Scene.avatar_toolkit
logger.debug("Properties unregistered successfully")
+1 -1
View File
@@ -76,7 +76,7 @@ class AvatarToolkit_PT_UpdaterPanel(bpy.types.Panel):
bl_region_type = 'UI'
bl_category = CATEGORY_NAME
bl_parent_id = AvatarToolKit_PT_AvatarToolkitPanel.bl_idname
bl_order = 1
bl_order = 3
def draw(self, context: bpy.types.Context) -> None:
layout = self.layout