From b800e5a68b59444dff6576e2f9ee30c610619c7f Mon Sep 17 00:00:00 2001 From: Nero Frame 13 Date: Wed, 14 Oct 2026 13:49:18 +0200 Subject: [PATCH] Small config tweaks, removed cam/light check, code cleanup --- __init__.py | 15 +++++++ checks/general/objects.py | 48 ++++++++++++-------- config.py | 94 +++++++++++++++++++++++++++++++++------ core/contexts.py | 16 ++++++- tools_ops.py | 14 +++--- ui/panel.py | 4 +- 6 files changed, 148 insertions(+), 43 deletions(-) diff --git a/__init__.py b/__init__.py index c76e7d2..07f86da 100644 --- a/__init__.py +++ b/__init__.py @@ -40,19 +40,34 @@ def _load_config_override(): # Register modules def register() -> None: + # Register tool operators tools_ops.register() + + # Load all the sanity checks into the sanity REGISTRY checks.load_all() + + # Register the UI for all panels ui.register() + + # Load the configuration for sanity checks _load_config_override() + + # Load it natively bpy.app.handlers.load_post.append(_on_load_post) # Unregister modules def unregister() -> None: + # Unregister tool operators tools_ops.unregister() + + # Destroy the post loader if _on_load_post in bpy.app.handlers.load_post: bpy.app.handlers.load_post.remove(_on_load_post) + + # Unregister all panels ui.unregister() + runner.clear() # The check registry is plain Python and is rebuilt with the modules on # re-import, so it is kept as is (enable/disable without re-import). diff --git a/checks/general/objects.py b/checks/general/objects.py index 8466e64..a9d6d02 100644 --- a/checks/general/objects.py +++ b/checks/general/objects.py @@ -35,7 +35,9 @@ class ModifiersCheck(Check): continue for name in issue.data["modifiers"]: try: - with bpy.context.temp_override(object=ob, active_object=ob, selected_objects=[ob]): + with bpy.context.temp_override( + object=ob, active_object=ob, selected_objects=[ob] + ): bpy.ops.object.modifier_apply(modifier=name) except RuntimeError as exc: failed.append(f"{ob.name} / {name}: {str(exc).strip()}") @@ -58,7 +60,10 @@ class ApplyTransformCheck(Check): problems = [] if channels.get("location") and loc.length > tolerance: problems.append("location") - if channels.get("rotation") and min(rot.angle, math.tau - rot.angle) > tolerance: + if ( + channels.get("rotation") + and min(rot.angle, math.tau - rot.angle) > tolerance + ): problems.append("rotation") if channels.get("scale") and any(abs(s - 1.0) > tolerance for s in scale): problems.append("scale") @@ -73,11 +78,16 @@ class ApplyTransformCheck(Check): if ob is None: continue if ob.data is not None and ob.data.users > 1: - failed.append(f"{ob.name}: data shared by {ob.data.users} users, apply by hand") + failed.append( + f"{ob.name}: data shared by {ob.data.users} users, apply by hand" + ) continue try: with bpy.context.temp_override( - object=ob, active_object=ob, selected_objects=[ob], selected_editable_objects=[ob] + object=ob, + active_object=ob, + selected_objects=[ob], + selected_editable_objects=[ob], ): bpy.ops.object.transform_apply( location=bool(channels.get("location")), @@ -89,20 +99,20 @@ class ApplyTransformCheck(Check): return failed -class LightCameraCheck(Check): - id = "lights_cameras" - label = "Lights & cameras" - description = "Asset files contain no lights or cameras." - category = "Objects" - contexts = contexts.ASSET - fix_description = "Delete the lights and cameras" +# class LightCameraCheck(Check): +# id = "lights_cameras" +# label = "Lights & cameras" +# description = "Asset files contain no lights or cameras." +# category = "Objects" +# contexts = contexts.ASSET +# fix_description = "Delete the lights and cameras" - def run(self, ctx): - for ob in ctx.objects(*config.FORBIDDEN_ASSET_OBJECT_TYPES): - yield Issue.for_id(f"{ob.type.capitalize()} '{ob.name}' must be removed", ob) +# def run(self, ctx): +# for ob in ctx.objects(*config.FORBIDDEN_ASSET_OBJECT_TYPES): +# yield Issue.for_id(f"{ob.type.capitalize()} '{ob.name}' must be removed", ob) - def fix(self, ctx, issues): - for issue in issues: - ob = issue.get_id() - if ob is not None: - bpy.data.objects.remove(ob, do_unlink=True) +# def fix(self, ctx, issues): +# for issue in issues: +# ob = issue.get_id() +# if ob is not None: +# bpy.data.objects.remove(ob, do_unlink=True) diff --git a/config.py b/config.py index 9fc2a82..4a1876c 100644 --- a/config.py +++ b/config.py @@ -82,16 +82,48 @@ MESH_DATA_MATCHES_OBJECT = True # Blender default names that must never survive in a published file. DEFAULT_NAMES = { - "cube", "plane", "sphere", "uvsphere", "icosphere", "cylinder", "cone", - "torus", "circle", "grid", "suzanne", "monkey", "empty", "camera", - "light", "lamp", "point", "sun", "spot", "area", "material", "collection", - "beziercurve", "beziercircle", "nurbscurve", "nurbspath", "text", - "armature", "lattice", "nodegroup", "geometrynodes", "stroke", "gpencil", - "lineart", "scene", "world", "object", "mesh", + "cube", + "plane", + "sphere", + "uvsphere", + "icosphere", + "cylinder", + "cone", + "torus", + "circle", + "grid", + "suzanne", + "monkey", + "empty", + "camera", + "light", + "lamp", + "point", + "sun", + "spot", + "area", + "material", + "collection", + "beziercurve", + "beziercircle", + "nurbscurve", + "nurbspath", + "text", + "armature", + "lattice", + "nodegroup", + "geometrynodes", + "stroke", + "gpencil", + "lineart", + "scene", + "world", + "object", + "mesh", } # --------------------------------------------------------------------------- # -# Structure (placeholder, real hierarchy to be defined) +# Structure # --------------------------------------------------------------------------- # # Collections that must exist. "{asset}" is replaced by the asset name. REQUIRED_COLLECTIONS = [] @@ -111,7 +143,10 @@ UV_NEGATIVE_TOLERANCE = 1e-6 # --------------------------------------------------------------------------- # ALLOWED_MODIFIERS = {"SUBSURF", "MULTIRES"} ALLOWED_MODIFIERS_LINEART = { - "SUBSURF", "MULTIRES", "LINEART", "GREASE_PENCIL_THICKNESS", + "SUBSURF", + "MULTIRES", + "LINEART", + "GREASE_PENCIL_THICKNESS", } # Which transform channels must be applied. @@ -135,8 +170,19 @@ CHAR_BODY_NAME = "GEO_{asset}_Body" # Name keywords that identify inner mouth / eye parts (case-insensitive). CHAR_PART_KEYWORDS = [ - "eye", "iris", "pupil", "cornea", "sclera", "lid", "lash", - "mouth", "teeth", "tooth", "tongue", "gum", "palate", + "eye", + "iris", + "pupil", + "cornea", + "sclera", + "lid", + "lash", + "mouth", + "teeth", + "tooth", + "tongue", + "gum", + "palate", ] # Vertex groups the body mesh must have. TODO: real list. @@ -152,14 +198,32 @@ SET_COLLECTION_PATTERN = r"^(?:SET|ENV|set|env)[_-]" VERSION_PATTERN = r"(? None: bpy.utils.register_class(WTDGetOidForPath) + def unregister() -> None: - bpy.utils.unregister_class(WTDGetOidForPath) \ No newline at end of file + bpy.utils.unregister_class(WTDGetOidForPath) diff --git a/ui/panel.py b/ui/panel.py index 02dc0ac..b10b6b0 100644 --- a/ui/panel.py +++ b/ui/panel.py @@ -32,7 +32,7 @@ def _wrapped_label(layout, context, text, icon="NONE", margin=0): col.label(text=line, icon=icon if index == 0 else "BLANK1") -def draw_panel(self, context): +def draw_sanity_checks_panel(self, context): layout = self.layout scene = context.scene settings = scene.wtd_sanity @@ -170,7 +170,7 @@ class _SanityPanel: bl_options = {"DEFAULT_CLOSED"} # panel starts collapsed def draw(self, context): - draw_panel(self, context) + draw_sanity_checks_panel(self, context) class _ToolsPanel: