Housekeeping (bug fixes)

NEW FEATURES:
- added apply shapekey to basis from Cats
  - now that pesky thing I keep going back to cats for is in Avatar Toolkit.

BUG FIXES:
- now we push armature santizers into functions where they are needed
  - this prevents the methods from mirroring changes while working, causing them to blow up when mirror mode is on
  - more changes to come for armature setting santitizers
- fixed error reporting
  - now methods when catching errors will return full error tracebacks
  - this will help make debugging and finding user issues easier.
This commit is contained in:
989onan
2025-07-10 18:44:42 -04:00
parent 89fc8bc9c8
commit 6d9f751a16
27 changed files with 663 additions and 143 deletions
+21 -16
View File
@@ -1,3 +1,4 @@
import traceback
import bpy
import numpy as np
import threading
@@ -199,9 +200,9 @@ def apply_pose_as_rest(context: Context, armature_obj: Object, meshes: List[Obje
return True, t("Operation.pose_applied")
except Exception as e:
logger.error(f"Error applying pose as rest: {str(e)}")
return False, str(e)
except Exception:
logger.error(f"Error applying pose as rest: {traceback.format_exc()}")
return False, traceback.format_exc()
def apply_armature_to_mesh(armature_obj: Object, mesh_obj: Object) -> None:
"""Apply armature deformation to mesh"""
@@ -335,8 +336,8 @@ def join_mesh_objects(context: Context, meshes: List[Object], progress: Optional
return joined_mesh
except Exception as e:
logger.error(f"Failed to join meshes: {str(e)}")
except Exception:
logger.error(f"Failed to join meshes: {traceback.format_exc()}")
return None
@@ -365,8 +366,8 @@ def fix_uv_coordinates(context: Context) -> None:
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)}")
except Exception:
logger.warning(f"UV Fix - Skipped processing for {obj.name}: {traceback.format_exc()}")
finally:
bpy.ops.object.mode_set(mode='OBJECT')
@@ -488,7 +489,6 @@ def fix_zero_length_bones(armature: Object) -> None:
"""Fix zero length bones by setting a minimum length"""
if not armature:
return
bpy.ops.object.mode_set(mode='EDIT')
for bone in armature.data.edit_bones:
if bone.length < 0.001:
@@ -631,6 +631,7 @@ def get_objects() -> bpy.types.BlendData:
def duplicate_bone(bone: EditBone) -> EditBone:
"""Create a duplicate of the given bone"""
new_bone: EditBone = bone.id_data.edit_bones.new(bone.name + "_copy")
new_bone.head = bone.head.copy()
new_bone.tail = bone.tail.copy()
@@ -642,14 +643,18 @@ def duplicate_bone(bone: EditBone) -> EditBone:
new_bone.use_deform = bone.use_deform
return new_bone
#Binary tools
#encoding FrooxEngine/C# types in binary:
class ArmatureData(Tuple[bool,bool]):
pass
def store_breaking_settings_armature(armature: bpy.types.Object) -> ArmatureData:
armature_data: bpy.types.Armature = armature.data
return (armature_data.use_mirror_x, armature.pose.use_mirror_x)
def restore_breaking_settings_armature(armature: bpy.types.Object, data: ArmatureData) -> None:
armature_data: bpy.types.Armature = armature.data
armature_data.use_mirror_x, armature.pose.use_mirror_x = data
+5 -4
View File
@@ -9,6 +9,7 @@ from typing import Optional, Callable, Dict, List, Union, Set
from ..common import clear_default_objects
from ..translations import t
from ..mmd.core.pmx.importer import PMXImporter
import traceback
# Configure logging
logging.basicConfig(level=logging.INFO)
@@ -84,8 +85,8 @@ def import_multi_files(
progress_callback(fullpath)
progress.update(file["name"])
except Exception as e:
logger.error(f"Import failed: {str(e)}", exc_info=True)
except Exception:
logger.error(f"Import failed: {traceback.format_exc()}", exc_info=True)
raise
ImportMethod = Callable[[str, List[Dict[str, str]], str], None]
@@ -230,6 +231,6 @@ def import_pmx_file(filepath: str) -> None:
try:
importer.execute(**import_settings)
logger.info(f"Successfully imported PMX file: {filepath}")
except Exception as e:
logger.error(f"Failed to import PMX file: {str(e)}", exc_info=True)
except Exception:
logger.error(f"Failed to import PMX file: {traceback.format_exc()}", exc_info=True)
raise
+11 -10
View File
@@ -11,6 +11,7 @@ from typing import Optional, List, Tuple, Callable, Any, Union
import bpy
from bpy.types import Object, ID, Camera, Context
from mathutils import Vector, Matrix, Euler
import traceback
from ..bpyutils import FnContext, Props
from ....core.logging_setup import logger
@@ -87,8 +88,8 @@ class FnCamera:
__add_driver(camera_object.data, "type", "not $is_perspective")
__add_driver(camera_object.data, "lens", "$sensor_height/tan($angle/2)/2")
logger.debug(f"Successfully added drivers to camera: {camera_object.name}")
except Exception as e:
logger.error(f"Failed to add drivers to camera {camera_object.name}: {str(e)}")
except Exception:
logger.error(f"Failed to add drivers to camera {camera_object.name}: {traceback.format_exc()}")
@staticmethod
def remove_drivers(camera_object: Object) -> None:
@@ -100,8 +101,8 @@ class FnCamera:
camera_object.data.driver_remove("ortho_scale")
camera_object.data.driver_remove("lens")
logger.debug(f"Successfully removed drivers from camera: {camera_object.name}")
except Exception as e:
logger.error(f"Failed to remove drivers from camera {camera_object.name}: {str(e)}")
except Exception:
logger.error(f"Failed to remove drivers from camera {camera_object.name}: {traceback.format_exc()}")
class MigrationFnCamera:
@@ -124,8 +125,8 @@ class MigrationFnCamera:
FnCamera.remove_drivers(camera_object)
FnCamera.add_drivers(camera_object)
updated_count += 1
except Exception as e:
logger.error(f"Failed to update MMD camera {camera_object.name}: {str(e)}")
except Exception:
logger.error(f"Failed to update MMD camera {camera_object.name}: {traceback.format_exc()}")
logger.info(f"Updated {updated_count} MMD cameras")
@@ -197,8 +198,8 @@ class MMDCamera:
logger.info(f"Successfully converted {cameraObj.name} to MMD camera")
return MMDCamera(empty)
except Exception as e:
logger.error(f"Failed to convert camera {cameraObj.name} to MMD camera: {str(e)}")
except Exception:
logger.error(f"Failed to convert camera {cameraObj.name} to MMD camera: {traceback.format_exc()}")
raise
@staticmethod
@@ -305,8 +306,8 @@ class MMDCamera:
logger.info(f"Successfully created MMD camera animation with {frame_count} frames")
return MMDCamera(mmd_cam_root)
except Exception as e:
logger.error(f"Failed to create MMD camera animation: {str(e)}")
except Exception:
logger.error(f"Failed to create MMD camera animation: {traceback.format_exc()}")
raise
def object(self) -> Object:
+3 -2
View File
@@ -16,6 +16,7 @@ from ..core.exceptions import MaterialNotFoundError
from ..core.material import FnMaterial
from ..core.shader import _NodeGroupUtils
from ....core.logging_setup import logger
import traceback
class ConvertMaterialsForCycles(Operator):
@@ -50,8 +51,8 @@ class ConvertMaterialsForCycles(Operator):
def execute(self, context: Context) -> Set[str]:
try:
context.scene.render.engine = "CYCLES"
except Exception as e:
logger.error(f"Failed to change to Cycles render engine: {str(e)}")
except Exception:
logger.error(f"Failed to change to Cycles render engine: {traceback.format_exc()}")
self.report({"ERROR"}, " * Failed to change to Cycles render engine.")
return {"CANCELLED"}
+6 -5
View File
@@ -4,6 +4,7 @@ import bpy_extras
from numpy import double
from typing import Set, Dict
import re
import traceback
from .common import get_active_armature, ProgressTracker, identify_bones
from bpy.types import Context, Operator
@@ -91,16 +92,16 @@ class AvatarToolkit_OT_ConvertResonite(Operator):
progress.step(t("Tools.convert_resonite.processing", name=bone.name))
except Exception as e:
logger.error(f"Error during Resonite conversion: {str(e)}")
self.report({'ERROR'}, str(e))
except Exception:
logger.error(f"Error during Resonite conversion: {traceback.format_exc()}")
self.report({'ERROR'}, traceback.format_exc())
return {'CANCELLED'}
finally:
try:
bpy.ops.object.mode_set(mode='OBJECT')
except Exception as e:
logger.warning(f"Error returning to object mode: {str(e)}")
except Exception:
logger.warning(f"Error returning to object mode: {traceback.format_exc()}")
if translate_bone_fails > 0:
logger.info(f"Conversion completed with {translate_bone_fails} untranslated bones")