Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -580,15 +580,16 @@ verts = 72, faces = 54, and `Set Material` carries the lime accent.
</tr>
<tr>
<td width="46%" valign="middle">
<a href="examples/gn-modifier-inputs/"><img src="examples/gn-modifier-inputs/preview.webp" alt="GN modifier inputs: three separate cubes in teal, copper, and coral scaled to 1, 2, and 3 meters by a shared Geometry Nodes tree, proving per-modifier Scale writes land on 5.2 RNA and on 4.5 dict assignment" /></a>
<a href="examples/gn-modifier-inputs/"><img src="examples/gn-modifier-inputs/preview.webp" alt="GN modifier inputs: three spiral staircases from one shared Geometry Nodes tree, 1, 2 and 3 meters tall with 7, 17 and 27 oak treads, proving per-modifier Height writes land on 5.2 RNA and on 4.5 dict assignment" /></a>
</td>
<td valign="middle">

### [gn-modifier-inputs](examples/gn-modifier-inputs/)

One Geometry Nodes tree, three modifier copies. Writes a Float Scale input through
`mod.properties.inputs` on 5.2 and `mod[identifier]` on 4.5/5.1. Asserts readback and
evaluated Z-extent equal 1 / 2 / 3. The 5.1 dict form raises TypeError on 5.2.
One Geometry Nodes spiral-staircase tree, three modifier copies. Writes a Float Height
input through `mod.properties.inputs` on 5.2 and `mod[identifier]` on 4.5/5.1; the tree
turns 1 / 2 / 3 m into 7 / 17 / 27 treads. Asserts readback and evaluated Z-extent equal
1 / 2 / 3. The 5.1 dict form raises TypeError on 5.2.

</td>
</tr>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/gallery/assets/gn-modifier-inputs-hero.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
423 changes: 310 additions & 113 deletions docs/gallery/gn-modifier-inputs/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/gallery/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -453,12 +453,12 @@ <h2><a href="gn-instance-grid/">gn-instance-grid</a></h2>
</article>
<article class="card" data-tags="geometry-nodes modifiers">
<a class="card-media" href="gn-modifier-inputs/" tabindex="-1" aria-hidden="true">
<img src="assets/gn-modifier-inputs-hero.webp" alt="Three separate cubes stepping up in size from left to right: a small teal cube, an orange block and a large red block." loading="lazy" decoding="async" />
<img src="assets/gn-modifier-inputs-hero.webp" alt="Three spiral staircases of one design, with oak treads, teal posts and brass rails, rising left to right from seven steps to seventeen to twenty-seven." loading="lazy" decoding="async" />
</a>
<div class="card-body">
<h2><a href="gn-modifier-inputs/">gn-modifier-inputs</a></h2>
<p class="teaches">Per-modifier Geometry Nodes Float inputs on a shared tree — 4.5/5.1 write mod[identifier], 5.2 writes mod.properties.inputs.Socket_1.value.</p>
<p class="witnesses"><span class="tag">witnesses</span> The 5.1 dict form raises TypeError on 5.2 rather than silently no-opping; RNA properties are AttributeError on 4.5. Readback and evaluated Z-extent match written scales 1/2/3.</p>
<p class="witnesses"><span class="tag">witnesses</span> The 5.1 dict form raises TypeError on 5.2 rather than silently no-opping; RNA properties are AttributeError on 4.5. Readback and evaluated Z-extent match written heights 1/2/3, which the shared tree turns into 7/17/27 treads.</p>
<a class="card-link" href="gn-modifier-inputs/">View example<span class="sr-only"> gn-modifier-inputs</span> <span aria-hidden="true">&rarr;</span></a>
</div>
</article>
Expand Down
4 changes: 2 additions & 2 deletions examples/gallery.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@
"name": "gn-modifier-inputs",
"dir": "examples/gn-modifier-inputs",
"teaches": "Per-modifier Geometry Nodes Float inputs on a shared tree — 4.5/5.1 write mod[identifier], 5.2 writes mod.properties.inputs.Socket_1.value.",
"alt": "Three separate cubes stepping up in size from left to right: a small teal cube, an orange block and a large red block.",
"witnessesFix": "The 5.1 dict form raises TypeError on 5.2 rather than silently no-opping; RNA properties are AttributeError on 4.5. Readback and evaluated Z-extent match written scales 1/2/3.",
"alt": "Three spiral staircases of one design, with oak treads, teal posts and brass rails, rising left to right from seven steps to seventeen to twenty-seven.",
"witnessesFix": "The 5.1 dict form raises TypeError on 5.2 rather than silently no-opping; RNA properties are AttributeError on 4.5. Readback and evaluated Z-extent match written heights 1/2/3, which the shared tree turns into 7/17/27 treads.",
"hero": "docs/gallery/assets/gn-modifier-inputs-hero.webp",
"preview": "examples/gn-modifier-inputs/preview.webp",
"tags": [
Expand Down
50 changes: 33 additions & 17 deletions examples/gn-modifier-inputs/README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
# GN Modifier Inputs

A runnable example that attaches one Geometry Nodes tree to three cubes and
writes a per-modifier Float **Scale** input through the version-appropriate
API. The tree scales a 1 m cube by that value and lifts it onto the floor.
Evaluated Z-extent must match the written scale (1 / 2 / 3). That is the
closed form: if the write did not land, the three cubes collapse to the
socket default and the extents are no longer distinct.
A runnable example that attaches one Geometry Nodes tree to three carrier
objects and writes a per-modifier Float **Height** input through the
version-appropriate API. The tree is a parametric spiral staircase: from
Height it derives the step count (`round((Height - 0.3) / 0.1)`), instances
the carrier mesh — one bevelled oak tread with its brass baluster — up a
helix at 22.5° per step, and adds a teal newel post and a brass helical
handrail. Written heights 1 / 2 / 3 m give 7 / 17 / 27 treads, so the
three staircases read left to right as one design at three settings of one
input.

The closed form: the newel post runs from the floor at z=0 to exactly
z=Height and every other part stays inside that span, so the evaluated
Z-extent must equal the written height. If a write did not land, that
staircase falls back to the socket default (1 m, 7 treads) and the extents
are no longer distinct — in the render, the tall staircases collapse to
copies of the short one.

**What it witnesses:** Blender 5.2 removed ID-property assignment on
`NodesModifier`. `mod["Socket_1"] = 2.0` raises `TypeError` rather than
silently no-opping. 4.5 LTS and 5.1 still require that dict form;
`mod.properties` does not exist there (`AttributeError`). 5.2+ writes
`mod.properties.inputs.Socket_1.value`. After the write, the depsgraph
must be updated or `evaluated_get` still sees the previous scale.
must be updated or `evaluated_get` still sees the previous height.

Follows [`geometry-nodes-python`](../../skills/geometry-nodes-python/SKILL.md).

Staging: the carriers now stand 0.5 m apart (`XS`). The old spacing
overlapped the 2 m and 3 m cubes by 0.2 m. The check reads only each
cube's evaluated Z extent and zmin, never X, so this is layout only. The
camera looks from the front, so small to large reads left to right, and a
duller finish keeps the tops from blowing out.
Staging: the default dark studio. The three staircases stand on 1.62 m
centres (`XS`); the check reads only each object's evaluated Z extent and
zmin, never X, so the layout is free. All three share one tree and one set
of materials — the only thing that differs between them is the modifier
input. The key carries a 36° spread so its pool stays on the stairs, and
the rim sits high behind them so it does not wash the foreground floor.

## Run

Expand All @@ -29,7 +40,8 @@ duller finish keeps the tops from blowing out.
blender --background --python gn_modifier_inputs.py --

# Portable falsifier: write 1.0 to every modifier. Must exit non-zero.
blender --background --python gn_modifier_inputs.py -- --same-scale
# (--same-scale is kept as an alias for the pre-staircase flag name.)
blender --background --python gn_modifier_inputs.py -- --same-height

# Force one side of the split (must fail on the other series, not all three):
blender --background --python gn_modifier_inputs.py -- --api dict
Expand All @@ -50,25 +62,29 @@ against it. `10` is the shared framing helper.
| 0 | Success |
| 1 | Uncaught exception (FATAL wrapper) |
| 2 | argparse / usage |
| 3 | Scale input identifier missing on the tree interface |
| 3 | Height input identifier missing on the tree interface |
| 4 | Modifiers do not share one node_group |
| 5 | Version-path write raised (`--api dict` on 5.2, `--api rna` on 4.5) |
| 6 | Version-path read raised |
| 7 | Readback ≠ intended scale (`--same-scale` lands here) |
| 8 | Evaluated Z-extent ≠ intended scale |
| 7 | Readback ≠ intended height (`--same-height` lands here) |
| 8 | Evaluated Z-extent ≠ intended height |
| 9 | Evaluated mesh not sitting on z=0 |
| 10 | Gallery framing violation |
| 11 | Evaluated extents not distinct |
| 12 | `--output` produced no file |

The `blender-smoke` workflow runs the check on Blender 5.2 LTS and 4.5 LTS
(5.1 on the weekly cron, the `needs-5.1` PR label, or manual dispatch).
Smoke does not pass `--output`, `--same-scale`, or `--api dict`/`rna`.
Smoke does not pass `--output`, `--same-height`, or `--api dict`/`rna`.

## Falsification

| Probe | Binary | Result |
| --- | --- | --- |
| `--api dict` | 5.2.1 LTS | exit 5, `TypeError: id properties not supported for this type` |
| `--api rna` | 4.5.11 LTS | exit 5, `AttributeError: 'NodesModifier' object has no attribute 'properties'` |
| `--api dict` | 5.1.2 | exit 0 (5.1 still takes the dict form) |
| `--api rna` | 5.1.2 | exit 5, `AttributeError: 'NodesModifier' object has no attribute 'properties'` |
| `--same-height` | 5.2.1, 5.1.2, 4.5.11 | exit 7, `readback 1.0 != written 2.0 on SpiralStair.H2` |
| `RAIL_H = -0.5` (treads climb past the post) | 5.2.1, 4.5.11 | exit 8, `evaluated Z-extent 1.934334 != height 1.0` |
| `--api auto` | 5.2.1, 5.1.2, 4.5.11 | exit 0, extents 1.000 / 2.000 / 3.000 |
Loading
Loading