Blender add-on: exportGltf action #7

Merged
libby merged 3 commits from libby/blender-export-gltf into main 2026-11-10 18:01:28 +00:00
Member

Gap cut from the Noka MKI harness (G1): Brokkr had no glTF export action. Commit 3791667.

What changed: new exportGltf action (filepath .glb or .gltf, optional extras, yUp, applyModifiers, selection). It mirrors renderStill path safety under the Render Output Directory preference: no overwrite, no links, no escape. Advertises asset.export.gltf. Docs updated.

Stacking: this branch sits on libby/blender-gn-recreation (PR #5, still open), so the diff against main also shows #5. The change itself is the commit(s) named above; review them with git diff libby/blender-gn-recreation..HEAD. Merge #5 first.

Verified

  • Unit (fake bpy): 115 tests, OK, 10 skipped (same skips as the other branches; need cultmesh_py).
  • Live, headless Blender 5.2.2 LTS, ad hoc script (not committed): exportGltf a.glb accepted and wrote a 1968-byte GLB; the custom property tag=hello appears as node extras in the GLB JSON; a second export to the same name, a ../ path, a selection naming a missing object, and yUp="no" were all refused with the expected message.

Not verified

  • No committed live test for exportGltf (this branch adds unit tests only); the live run above is mine and not in the repo.
  • .gltf (separate .bin) path, yUp=false, applyModifiers=false and a multi-object selection were exercised by unit tests only, not live.
  • Material colour is on a separate branch; the exported GLB here carries the default 0.8 grey, as expected.
  • No Windows or Starfire run.

🤖 Generated with Claude Code

Steward pass, 2026-11-10: replayed as one commit on main (it was stacked on #5), then merged with main after #6. Soul pass (separate agent): ~45 path probes through the real resolver found no escape from the render output directory; 22 hand mutants, survivors equivalent or covered by a second layer. Fixed from it: the selection is no longer read or written when none is given, and only view-layer objects are touched (an off-layer selection name is refused by name), because real Blender raises in select_set for them; docs now say texture sidecars of a .gltf and the check-to-write swap are not checked. 143 unit tests and 20 daemon tests pass locally (the old count in this body is superseded). Not run: tests/live scripts and the real exporter (Blender not installed), so the view-layer behaviour is reasoned from the Blender API, not observed. Brokkr has no CI.

Gap cut from the Noka MKI harness (G1): Brokkr had no glTF export action. Commit 3791667. What changed: new exportGltf action (filepath .glb or .gltf, optional extras, yUp, applyModifiers, selection). It mirrors renderStill path safety under the Render Output Directory preference: no overwrite, no links, no escape. Advertises asset.export.gltf. Docs updated. Stacking: this branch sits on libby/blender-gn-recreation (PR #5, still open), so the diff against main also shows #5. The change itself is the commit(s) named above; review them with `git diff libby/blender-gn-recreation..HEAD`. Merge #5 first. Verified - Unit (fake bpy): 115 tests, OK, 10 skipped (same skips as the other branches; need cultmesh_py). - Live, headless Blender 5.2.2 LTS, ad hoc script (not committed): exportGltf a.glb accepted and wrote a 1968-byte GLB; the custom property tag=hello appears as node extras in the GLB JSON; a second export to the same name, a ../ path, a selection naming a missing object, and yUp="no" were all refused with the expected message. Not verified - No committed live test for exportGltf (this branch adds unit tests only); the live run above is mine and not in the repo. - .gltf (separate .bin) path, yUp=false, applyModifiers=false and a multi-object selection were exercised by unit tests only, not live. - Material colour is on a separate branch; the exported GLB here carries the default 0.8 grey, as expected. - No Windows or Starfire run. 🤖 Generated with [Claude Code](https://claude.com/claude-code) **Steward pass, 2026-11-10:** replayed as one commit on main (it was stacked on #5), then merged with main after #6. Soul pass (separate agent): ~45 path probes through the real resolver found no escape from the render output directory; 22 hand mutants, survivors equivalent or covered by a second layer. Fixed from it: the selection is no longer read or written when none is given, and only view-layer objects are touched (an off-layer selection name is refused by name), because real Blender raises in select_set for them; docs now say texture sidecars of a .gltf and the check-to-write swap are not checked. 143 unit tests and 20 daemon tests pass locally (the old count in this body is superseded). Not run: tests/live scripts and the real exporter (Blender not installed), so the view-layer behaviour is reasoned from the Blender API, not observed. Brokkr has no CI.
Builds a ring array, boundary_step and a seeded scatter natively and through
BrokkrBlenderTarget actions on Blender 5.2.3; records the gaps.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
createNodeGroup, addNode, linkSockets, addModifier, setModifierInput (node_actions.py);
setObjectCustomProperty refuses a name that is a Geometry Nodes modifier input instead of
accepting with no effect; object snapshots carry the evaluated counts, bounds and locations.
Live proof on Blender 5.2.3: ring, boundary_step and seeded scatter rebuilt by actions only
match the native trees (66 checks).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A refused linkSockets puts back the link it displaced; snapshot positions keep local and world
bounds apart, scan instances once per capture, skip positions above 1M vertices and flag
non-finite values; Int values capped at 4096; id/key patterns use fullmatch; addModifier names
the object type it cannot take; setObjectCustomProperty refuses only a modifier input identifier.
Live: 108 checks pass on Blender 5.2.3.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Cycles and self links are refused before Blender is asked; the snapshot's instance scan stops at
100k depsgraph items and says instancesComplete=false (2000x2000 instanced grid: 22 s -> 1.4 s);
the daemon advertisement lists the scene-action and node-graph capabilities. Live: 156 checks pass
on Blender 5.2.3.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
bpy hands out a fresh wrapper per access, so id() keys made reaches() stop early and accept cycles
on chains of six or more nodes; keyed by as_pointer() with one adjacency map per call. Objects the
stopped instance scan never reached report instanceCount null. removeModifier validates its name.
Live: 158 checks pass on Blender 5.2.3.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A refused link restores the displaced link's is_muted; removeModifier no longer applies the
creation-name pattern to a lookup, so hand-made Unicode modifier names are removable; the
pattern message lists the space it allows. Live: 166 checks pass on Blender 5.2.3.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Mirrors renderStill path safety: no overwrite, no links, no escape. Advertises asset.export.gltf.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
libby force-pushed libby/blender-export-gltf from 379166799c to b3afd70cf9 2026-11-10 17:55:38 +00:00 Compare
select_set raises in Blender for an object with no base in the view layer, so a scene
with off-layer objects could fail the export or mask its result. A selection naming an
off-layer object is refused by name; no selection means the selection is never read or
written. Docs state the unchecked texture sidecars and the TOCTOU residue.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
libby merged commit 730ceb9e0e into main 2026-11-10 18:01:28 +00:00
libby referenced this pull request from a commit 2026-11-10 18:01:29 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
GameCult/Brokkr!7
No description provided.