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
1 change: 1 addition & 0 deletions .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
"examples/gn-instance-grid",
"examples/gn-modifier-inputs",
"examples/gn-sdf-remesh",
"examples/gn-sim-fountain",
"examples/gn-socket-rename",
"examples/gn-zone-iterate",
"examples/gp-lineart-contour",
Expand Down
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ a `.cursor-plugin/plugin.json` manifest so the ecosystem drift checker
classifies it as a `cursor-plugin`. This is content the AI loads when the user
asks Blender questions or works on Blender add-ons in Cursor or Claude Code.

The content base is 16 skills, 9 rules, 3 templates, 27 snippets, 59
The content base is 16 skills, 9 rules, 3 templates, 27 snippets, 60
examples, and 26 showcase pieces (counts are CI-enforced against README.md)
and the manifest). The full inventory tables and per-item purposes live in
`CLAUDE.md`. Example anatomy and authoring rules: copy `examples/bmesh-gear/`;
Expand All @@ -36,7 +36,7 @@ Blender-Developer-Tools/
rules/<rule-name>.mdc # 9 rule files
templates/<template-name>/ # 3 starter templates
snippets/<snippet-name>.py # 27 standalone Python snippets
examples/<name>/ # 59 runnable smoke-gated examples (+ gallery.json)
examples/<name>/ # 60 runnable smoke-gated examples (+ gallery.json)
examples/gallery_framing.py # shared Layer 1 framing measurement (render path only)
showcase/<name>/ # budget-conformance props (sibling of examples/)
showcase/gallery.json # this tree's gallery index; merged into docs/gallery/
Expand Down
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ skills/<skill-name>/SKILL.md - AI workflow definitions, 16 total
rules/<rule-name>.mdc - Anti-pattern rules, 9 total
templates/<template-name>/ - Starter projects, 3 total
snippets/<snippet-name>.py - Standalone code patterns, 27 total
examples/<name>/ - Runnable smoke-gated examples, 59 total (+ gallery.json)
examples/<name>/ - Runnable smoke-gated examples, 60 total (+ gallery.json)
showcase/<name>/ - Budget-conformance props, 36 pieces (sibling of examples/; see showcase/README.md)
scripts/build_gallery.py - Regenerates docs/gallery/ from examples/gallery.json + showcase/gallery.json
scripts/site/ - Vendored landing-page build (Jinja2)
Expand Down Expand Up @@ -104,12 +104,12 @@ v0.2.0: Principled BSDF material, driver-with-custom-function via `driver_namesp

AI asset pipeline track: `decimate_to_budget.py`, `convex_hull_collider.py`, `lod_chain.py` (helper duplicated, not imported), `gltf_draco_export.py`, `export_preset_unity.py`, `export_preset_godot.py`, `export_preset_unreal.py`, `setup_bake_target_image.py`, `bake_normal_high_to_low.py`, `save_baked_image.py`.

## Examples (59)
## Examples (60)

Runnable scripts at `examples/<name>/`, each asserting a real API contract with
deterministic checks (exit non-zero on failure) and optionally rendering a still via
`--output`. All of them run headless on Blender 5.2 LTS and 4.5 LTS in `blender-smoke.yml` (5.1 on the weekly cron, the `needs-5.1` PR label, or manual dispatch);
**51 of the 59 ship a render in the site gallery** at `docs/gallery/`. The other
**52 of the 60 ship a render in the site gallery** at `docs/gallery/`. The other
eight are **check-only**: they carry no `--output` path, no gallery entry, and no
hero asset. The criterion is whether the contract is expressible in pixels. An
example is check-only when its witness is a data or state fact that no scene
Expand Down
25 changes: 21 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
</p>

<p align="center">
<strong>16 skills</strong> &nbsp;&bull;&nbsp; <strong>9 rules</strong> &nbsp;&bull;&nbsp; <strong>3 templates</strong> &nbsp;&bull;&nbsp; <strong>27 snippets</strong> &nbsp;&bull;&nbsp; <strong>59 examples</strong> &nbsp;&bull;&nbsp; <strong>36 showcase pieces</strong>
<strong>16 skills</strong> &nbsp;&bull;&nbsp; <strong>9 rules</strong> &nbsp;&bull;&nbsp; <strong>3 templates</strong> &nbsp;&bull;&nbsp; <strong>27 snippets</strong> &nbsp;&bull;&nbsp; <strong>60 examples</strong> &nbsp;&bull;&nbsp; <strong>36 showcase pieces</strong>
</p>

<p align="center">
Expand All @@ -37,7 +37,7 @@

## Overview

This repository ships **16 skills, 9 rules, 3 templates, 27 snippets, 59 examples, and 36 showcase pieces** for Blender Python development targeting Blender 5.2 LTS (current stable) with Blender 4.5 LTS fallback support. Blender 5.1 is prior stable.
This repository ships **16 skills, 9 rules, 3 templates, 27 snippets, 60 examples, and 36 showcase pieces** for Blender Python development targeting Blender 5.2 LTS (current stable) with Blender 4.5 LTS fallback support. Blender 5.1 is prior stable.

The content is consumed by AI coding agents reading these files directly from a checkout — **there is no MCP server in this repository, and none is required**. Cursor applies `rules/*.mdc` automatically wherever their scope globs match and takes skills by name in chat; Claude Code reads `skills/` and `rules/` from the project workspace, or from this repo kept as a referenced checkout. Any agent that can read files in a workspace can use it the same way. There is no build step for the content — edit the Markdown and Python files directly.

Expand Down Expand Up @@ -75,7 +75,7 @@ blender --background --python examples/bmesh-gear/bmesh_gear.py --

## Falsifiers

Every one of the 59 examples carries a **falsifier**: a flag that changes the
Every one of the 60 examples carries a **falsifier**: a flag that changes the
input so a real assertion fails. It never disables the assertion, skips the
check, or short-circuits to an error — it feeds the script something the
contract says must not pass, and the same check that guards the happy path
Expand Down Expand Up @@ -556,7 +556,7 @@ exits 0 on all three. `--assume-present` is red only on 5.2.
</details>

<details>
<summary><strong>Geometry Nodes</strong> — 6 examples</summary>
<summary><strong>Geometry Nodes</strong> — 7 examples</summary>

<table>
<tr>
Expand Down Expand Up @@ -617,6 +617,23 @@ evaluated cubes against closed forms — Repeat `8×(1+N)` with X-centers at
nodes exist. Unpaired evaluates empty; For Each's main Geometry socket is a
passthrough.

</td>
</tr>
<tr>
<td width="46%" valign="middle">
<a href="examples/gn-sim-fountain/"><img src="examples/gn-sim-fountain/preview.webp" alt="GN simulation fountain: a two-tier sandstone fountain whose twenty jets are strings of cyan droplet beads, each bead a stepped Simulation Zone position threaded on its thin closed-form ballistic arc" /></a>
</td>
<td valign="middle">

### [gn-sim-fountain](examples/gn-sim-fountain/)

A Simulation Zone integrates twenty jets under gravity with the exact
constant-g update, and every stepped frame lands on `p0 + v0 t - g t^2/2`
(worst 6.6e-7 m). Two silent traps, identical on 4.5, 5.1 and 5.2: a direct
`frame_set(N)` jump runs one step, not N; and `calculate_to_frame` returns
`PASS_THROUGH` headless and leaves interpolated frames. Only a bake gives
random access.

</td>
</tr>
<tr>
Expand Down
5 changes: 4 additions & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,17 @@ Not committed; target list for the next content version. (v0.3.0 shipped the smo
- **Flagship showcase: pirate sloop** — lofted hull from stations, deck planking, mast, boom, gaff, shrouds and ratlines to chainplates, cannon ports: hull mirror-symmetric to the keel plane, every shroud terminating on its chainplate and masthead within a band, ratlines horizontal and evenly spaced
- **Flagship showcase: full chess set on a board** — 32 lathe-turned pieces (king to pawn, two woods) on an inlaid board: every piece centred on its square's computed centre, base seated on the board, lathe profiles revolved exactly (radii match profile closed form), 64 squares alternating by (file + rank) parity
- **Flagship showcase: modular dungeon kit** — floor, wall, corner, arch, stair and pillar tiles on a 2 m grid composed into a room: every open-edge boundary vert on the grid, zero gap/overlap at every joint, stair riser × count equal to one storey height, per-tile budgets plus a composed-room budget
- **Flagship example: GN simulation-zone ballistic fountain** — a Simulation Zone integrating particles under gravity: positions at frame N match the closed-form ballistic arc (p₀ + v₀t − ½gt²) per particle, determinism across re-bakes, and the 4.x vs 5.x bake/cache API paths documented; `--no-cache-reset` falsifier
- ~~**Flagship example: GN simulation-zone ballistic fountain**~~ **SHIPPED** as `examples/gn-sim-fountain/` — 20 jets integrated by the exact constant-g update land on p₀ + v₀t − ½gt² every stepped frame; an unbaked `frame_set(N)` jump runs one step, `calculate_to_frame` is PASS_THROUGH headless, only a bake gives random access. The 4.x vs 5.x divergence the entry anticipated does not exist: zone and bake operators measured identical on 4.5.11, 5.1.2 and 5.2.1. Falsifiers `--unpair` / `--euler` / `--prebake-trap` / `--calc-to-frame` replace the proposed `--no-cache-reset`, which had no failing check to target
- **Flagship example: GN procedural building generator** — one node tree with floor count, bay count and roof type as modifier inputs driving storeys, windows (instanced), cornices and a pitched or flat roof: window instance count = floors × bays × faces closed-form, storey heights exact, three buildings from the same tree side by side
- **Flagship example: GN road along a curve** — a Bezier path swept into a road with kerbs, lane markings and lamp posts instanced at equal arc-length spacing aligned to the tangent: post count = floor(length / spacing) + 1, every post perpendicular to the curve tangent within a band
- **Flagship example: L-system tree via GN repeat zone** — branching generated by a Repeat Zone: branch/leaf counts closed-form in the iteration depth, each child branch attached to its parent's tip, total height the closed-form series sum
- **Flagship example: UDIM texture set** — `Image.tiles.new` for 1001–1004, a UV layout spanning four tiles, per-tile bake/paint writes: tile numbers map to UV offsets exactly, each tile's pixels land only in its tile, `<UDIM>` filepath round-trips through save and reload
- **Flagship example: channel-packed ORM bake** — Cycles-bake AO, roughness and metallic of a prop into R/G/B of one Non-Color image: each channel matches its independently baked single-channel reference within a stated tolerance, and sRGB tagging is the falsifier
- **Flagship example: Cryptomatte ID witness** — a multi-object scene rendered with Cryptomatte passes to multilayer EXR: decoded object IDs (MurmurHash3 of the names) cover exactly each object's coverage mask, re-read with the stdlib-only EXR reader
- **Flagship example: walk cycle with planted feet** — slotted-action walk cycle on a leg rig with IK and NLA strip blending: planted-foot world position constant during each contact phase (foot slide below a band), stride length × cycles equals root travel, 4.5 vs 5.x channelbag paths
- Simulation-zone cache interpolation witness — frames between two cached simulation frames read as a linear interpolation of the endpoints (measured: steps 1.27 at frame 4 between cached 1 and 12), not a simulated state; assert the interpolant closed form and that a bake removes it (found authoring `gn-sim-fountain`)
- Operator PASS_THROUGH trap snippet — an operator whose poll fails headless (`simulation_nodes_cache_calculate_to_frame`) logs "Invalid operator call" and returns `{'PASS_THROUGH'}` without raising; check the returned set, never assume a non-raising `bpy.ops` call ran (found authoring `gn-sim-fountain`)
- Simulation-zone substeps witness — a Repeat Zone inside the Simulation Zone splitting Delta Time into k substeps: explicit Euler error shrinks exactly by 1/k against the closed-form arc, the exact update is invariant in k
- ~~Small modular kit showcase on recognizable geometry (`modular-kit-snap` contract)~~ **SHIPPED** as `showcase/fence-kit/` — tiling post-and-rail section (AABB X is the tile width; does not re-witness the snap contract); `--skip-decimate` exits 9 on the LOD1 ratio band

- ~~Custom ID-property delete witness~~ **SHIPPED** as `examples/cross-version-property-delete/` — IDs built via `bpy.data.objects.new` (not `active_object`); `property_unset` is TypeError and leaves the key; `del` removes it on 4.5 LTS and 5.x
Expand Down
Binary file added docs/gallery/assets/gn-sim-fountain-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.
Loading
Loading