Repository navigation
fix(templates): keep every mesh, handle shared and parented imports, bake modifier stacks in order - #477
Merged
Conversation
…bake modifier stacks in order The pipeline template exported only the largest mesh with exit 0. Its unit check could never fire, and LOD budgets were printed but never checked. Shared (instanced) mesh data made transform_apply raise. A child of a rotated glTF root passed the matrix_basis identity test and was grounded along a local axis. The headless template's non-first modifier_apply reversed the stack order, contrary to its README. The pipeline now isolates mesh data, unparents keeping world placement, applies transforms and joins every part. It checks the asset's extent (exit 8) and each LOD budget (exit 9), and exits 12 when the apply or join raises. The cleanup and export-preset skills and the three preset snippets get the same isolation and unparent guards. The headless template bakes the whole stack through new_from_object. check_example_rules now scans templates/ and flags object operators reached from a loop. Smoke covers the shared-mesh parented GLB, the modifier order, and the out-of-range extent. Signed-off-by: TMHSDigital <tmhospitalitystrategies@gmail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #467
Closes #468
Closes #462
What changed
#467:
templates/ai-asset-pipeline-template/pipeline.pymax(meshes, key=tris). It gives shared mesh data one copy per object, unparents keeping the world matrix, applies rotation and scale in onetransform_apply, then joins every part withobject.joinundertemp_override. The README states this behavior.read_factory_settingsalways leaves the scene metric at scale 1.0, so the old check could never fire. A geometry check replaces it: the largest world extent must be within 0.01 m to 100 m (×scale_length), or the script exits 8.RuntimeErrorfromtransform_applyorjoinexits 12. I skipped 10 and 11 because the shared render gates use them, and the README says so.apply_selected_mesh_transforms()call insideexport_presetis removed: every part is already applied by then. This also removes the object-op-in-a-loop pattern from the export loop.#468:
templates/headless-batch-script-template/bpy.ops.object.modifier_applyper object in a loop is replaced by a stack bake.bpy.data.meshes.new_from_object(obj.evaluated_get(dg), preserve_all_data_layers=True, depsgraph=dg)bakes the whole stack in order, with one depsgraph evaluation for all objects.tests/check_example_rules.pynow scanstemplates/for the existing two rules.prefer-data-over-ops-in-loopscheck. Aforloop that reachesbpy.ops.object.*fails the check, whether the call is direct or goes through same-file functions. An# ops-loop-exempt: <why>comment on the loop exempts it.template_scripts,check_ops_in_loops), so the parallel bulk-write lint work in examples: png-exr-alpha teaches scene image_settings for Image.save(); missing falsifier and per-element writes elsewhere #474 rebases cleanly. Examples are not held to this check, because some loop per part over operators that have no data-API equivalent (uv.smart_projectinlightmap-uv-channel).#462: shared and parented imports
snippets/export_preset_{unity,godot,unreal}.pyand the prelude inskills/engine-export-presets/SKILL.mdnow do two things before the singletransform_apply: copy multi-user data per object, and unparent keeping the world matrix. The Unreal snippet is now exactly 75 lines, the documented maximum.skills/ai-mesh-cleanup/SKILL.mdgainsisolate_mesh_dataandclear_parent_keep_transform, androt_scale_is_identitynow readsmatrix_world. The skill also notes thatorigin_to_baseneeds single-user data, that a scene-units check cannot catch centimeters written as meters (measure the geometry instead), and adds common mistake fix: remove stray context-mode block from CLAUDE.md and substantiate verification claims #8.transform_apply(isolate_users=True)exists on both 4.5.11 and 5.2.1 (measured). The skill mentions it but uses the data copy instead, becauseorigin_to_basealso needs single-user data, not just the apply.examples/export-preset-axis, only a comment changed: it said "same body as the snippet", which is no longer true.Smoke, in
blender-smoke.yml(both matrix series)tests/smoke/make_pipeline_glb.pynow takes--parentedand--radius. The parented fixture is a Root empty rotated 90° on X, scaled 2x, at z=3. Under it are a Body box and two wheels that share one mesh (users == 2) and have different rotations.tests/smoke/check_pipeline_glb.pyre-imports the source andlod0.glb. Exit codes: 3 whenlod0.glbhas more than one mesh object, 4 when its world bbox differs from the source's, 5 when the origin is not on the world minimum Z, 6 when the node has rotation or scale.tests/smoke/make_input.pyalso writesstack.blend, a cube with a live SUBSURF at levels 1. Newtests/smoke/check_glb_tris.pyasserts the GLB's triangle count.stack.blendwith--apply-modifier TRIANGULATE, and the GLB must have 48 tris.check_pipeline_glb.py.Evidence
Live run (Blender 5.2.1 LTS
.scratch\blender-5.2.1-windows-x64\blender.exeand 4.5.11 LTS.scratch\blender-4.5.11-windows-x64\blender.exe; both binaries report those versions, and the two gave identical results)stack.blend+ TRIANGULATEcheck_glb_tris48 = 48, exit 0input.blend+ SUBSURF (existing CI case)check_pipeline_glbexit 0, bbox[-2.2179,-1.0,2.0,2.0,1.2,4.0]matches the source, origin z = 2.0000 = min zFalsification probes (live, both versions, scratch copies of the script with one step removed)
isolate_mesh_dataremoved, parented fixtureCannot apply to a multi user: Object "WheelL", Mesh "WheelMesh"clear_parent_keep_transformremovedcheck_pipeline_glbexit 5: origin z = 3.0000 against min z = 2.0000join_meshesreplaced by the oldmax(meshes, key=tris)check_pipeline_glbexit 4: bbox drift 3.8179 (only WheelL shipped)decimate_to_budgetremoved, sphereFixture_LOD0 has 2208 triangles, over its budget of 1024pipeline.pyfrom main, parented fixtureRuntimeError: Cannot apply to a multi userscript.pyfrom main,stack.blend+ TRIANGULATEcheck_glb_trisexit 3: 72 triangles against 48 expected (4.5.11 also printedInfo: Applied modifier was not first)check_ops_in_loopson the oldscript.pyand the oldpipeline.pyscript.py:84(add_and_apply_modifier() -> bpy.ops.object.modifier_apply) andpipeline.py:376(export_preset() -> bpy.ops.object.transform_apply); the current tree is cleanTwo things have no CI falsifier:
matrix_worldidentity check. Switching it back tomatrix_basisalone fails nothing, because the unparent step already makes the two matrices equal. Thematrix_worldread protects the skill's pattern when someone keeps the parents.Inspection only
apply_selected_mesh_transformsare the same code as the template path proven live above. I did not run them separately.Local validators
python tests/run_all.py: 28 passed. The 3 failures weretest_bump_kind,test_plugin_content_changedandtest_release_gate. They fail only under PowerShell, where bash is missing (exit 127), and pass under Git Bash.tests/check_example_rules.py: 145 scripts plus 3 templates, clean.🤖 Generated with Claude Code