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
8 changes: 8 additions & 0 deletions .github/workflows/label-sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ jobs:
LABELS="$LABELS templates"
fi

if echo "$FILES" | grep -q "^examples/"; then
LABELS="$LABELS examples"
fi

if echo "$FILES" | grep -q "^showcase/"; then
LABELS="$LABELS showcase"
fi

if echo "$FILES" | grep -qE "(README\.md|AGENTS\.md|CLAUDE\.md|ROADMAP\.md|CHANGELOG\.md|^docs/)"; then
LABELS="$LABELS documentation"
fi
Expand Down
17 changes: 15 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,25 @@ AI asset pipeline track: `decimate_to_budget.py`, `convex_hull_collider.py`, `lo
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);
their renders ship in the site gallery at `docs/gallery/`. `examples/gallery.json` is the
gallery's source of truth. When authoring a new one, copy the anatomy of
**51 of the 59 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
redesign can make visible — a datablock name, an RNA attribute's presence, a
post-exit sidecar, a topology count, export metadata — so a render would look
identical whether the API held or broke. That is a category, not a shortcut: a
subject whose render *could* be made legible must be rendered, per
`docs/new-example-prompt.md`. Smoke coverage is unaffected; every check-only
example still carries a `tests/smoke/catalog.json` row and a falsifier.
`examples/gallery.json` is the
gallery's source of truth. When authoring a new gallery example, copy the anatomy of
`examples/bmesh-gear/` (script structure, README shape, dark-studio render recipe) and
wire all of: gallery.json entry, `.cursor-plugin/plugin.json` examples array (CI-gated),
a `tests/smoke/catalog.json` row, a README gallery row, hero webp (1280×720) in
`docs/gallery/assets/` + preview webp (1200×675), then run `python scripts/build_gallery.py`.
A check-only example wires only the `.cursor-plugin/plugin.json` entry, the
`tests/smoke/catalog.json` row, and its README — it is deliberately absent from
`examples/gallery.json` and `docs/gallery/`.
Renders must conform to the gallery look spec at `docs/VISUAL-STYLE.md`.
Render paths gate framing through the shared helper `examples/gallery_framing.py` —
imported via a `__file__`-relative `sys.path` shim, the repo's only
Expand Down
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

This repository ships **16 skills, 9 rules, 3 templates, 27 snippets, 59 examples, and 26 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 (Cursor, Claude Code, any MCP-capable client) when working on Blender add-ons, geometry nodes scripts, batch pipelines, or animation tooling. There is no build step. Edit the markdown and Python files directly.
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.

| Layer | Role |
| --- | --- |
Expand All @@ -58,6 +58,7 @@ git clone https://github.com/TMHSDigital/Blender-Developer-Tools.git

- **Cursor** — point Cursor at the checkout (or symlink `rules/` into your project). The `.mdc` rules apply automatically by glob scope; skills are referenced by name in chat.
- **Claude Code** — copy `skills/` and `rules/` into your project workspace, or keep this repo as a checkout that Claude Code references directly.
- **Get Blender** — download **5.2 LTS** (primary target) or **4.5 LTS** (supported fallback) from [blender.org/download/lts](https://www.blender.org/download/lts/); current stable lives at [blender.org/download](https://www.blender.org/download/). The `blender` command below is that binary — on macOS it is inside the app bundle at `/Applications/Blender.app/Contents/MacOS/Blender`.
- **Run an example** — every example is a self-checking headless script (exit non-zero on failure, no GPU needed for the check):

```bash
Expand All @@ -72,6 +73,34 @@ blender --background --python examples/bmesh-gear/bmesh_gear.py --
| Blender 5.1 | Prior stable (weekly cron; PR via `needs-5.1` or manual dispatch) |
| Blender 4.5 LTS | Fallback supported (skills show both code paths where 4.x and 5.x APIs diverge) |

## Falsifiers

Every one of the 59 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
catches it.

```bash
# The contract holds: exit 0
blender --background --python examples/bmesh-gear/bmesh_gear.py --

# The falsifier: skip the extrude, so the topology no longer matches the
# closed form. The topology check fires and the script exits 3.
blender --background --python examples/bmesh-gear/bmesh_gear.py -- --no-extrude
```

This is what makes a green run mean something. An assertion that has only
ever passed witnesses nothing — it could be comparing a constant to itself.
Proving each one fails once, on demand, is the difference between a test
suite and a set of scripts that print "OK". Shipping an example requires
demonstrating the falsifier's non-zero exit and reporting the measured error.

`--api`, `--check-pixels`, and `--output` are not falsifiers; they select a
code path rather than break a contract. Full conventions, including the
per-script exit-code model, are in
[`CONTRIBUTING.md`](CONTRIBUTING.md#exit-codes).

## Showcase

Budget-conformance props. Not examples. Conventions: [`showcase/README.md`](showcase/README.md).
Expand Down
13 changes: 11 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,19 @@ Issues with the Blender Python API itself (`bpy`, `bmesh`, `bpy_extras`) belong

## Supported Versions

This is a content repository — Markdown, MDC, Python, and TOML files consumed
directly by an AI agent. There is no installed runtime, no server, and no
long-lived deployment to patch, so there are no maintenance branches and no
backports.

| Version | Supported |
|---------|-----------|
| 0.2.x | Yes |
| < 0.2.0 | No |
| Latest release (see [`VERSION`](VERSION)) | Yes |
| Any earlier release | No |

A confirmed fix lands on `main` and ships in the next release cut by
`release.yml`. Consumers pin by tag or track `main`; the remedy in both cases
is to move to the current release. Nothing older is patched in place.

## Response Timeline

Expand Down
10 changes: 5 additions & 5 deletions docs/gallery/anvil/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>anvil — Examples — Blender Developer Tools</title>
<title>anvil — Showcase — Blender Developer Tools</title>
<meta name="description" content="A procedural blacksmith anvil on a timber stump through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract." />
<link rel="canonical" href="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/anvil/" />
<link rel="icon" href="../../assets/favicon.svg" type="image/svg+xml" />
<meta name="theme-color" content="#1a1b1e" />
<meta property="og:type" content="website" />
<meta property="og:title" content="anvil — Examples — Blender Developer Tools" />
<meta property="og:title" content="anvil — Showcase — Blender Developer Tools" />
<meta property="og:description" content="A procedural blacksmith anvil on a timber stump through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract." />
<meta property="og:url" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/anvil/" />
<meta property="og:image" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/assets/anvil-hero.webp" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="anvil — Examples — Blender Developer Tools" />
<meta name="twitter:title" content="anvil — Showcase — Blender Developer Tools" />
<meta name="twitter:description" content="A procedural blacksmith anvil on a timber stump through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract." />
<meta name="twitter:image" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/assets/anvil-hero.webp" />
<style>
Expand Down Expand Up @@ -239,7 +239,7 @@
<body>
<a class="skip" href="#main">Skip to content</a>
<div class="topbar">
<a class="back" href="../"><span aria-hidden="true">&larr;</span> Examples Gallery</a>
<a class="back" href="../"><span aria-hidden="true">&larr;</span> Examples and Showcase</a>
<div class="topbar-right">
<a class="ghlink" href="https://github.com/TMHSDigital/Blender-Developer-Tools">GitHub</a>
</div>
Expand All @@ -252,7 +252,7 @@ <h1>anvil</h1>
<button class="detail-hero" id="heroZoom" type="button" aria-label="Zoom anvil render">
<img src="../assets/anvil-hero.webp" alt="anvil render" width="1280" height="720" />
</button>
<p class="zoom-hint">Rendered headless by the example itself — click to zoom.</p>
<p class="zoom-hint">Rendered headless by the showcase piece itself — click to zoom.</p>
<div class="callout"><span class="tag">witnesses</span> Recomputed: 2988 tris, two materials with 1040 wood and 822 metal faces, UVs in 0..1 with zero AABB overlap, outer AABB 0.621×0.414×0.489 m, LOD ratios in band, convex collider 134 tris, hygiene 0, 16 grounded staves, hoop bite 0.003 m, foot-on-head gap 0.003 m, non-empty glTF. --skip-decimate exits 9; --stray-vert 15; --lift-z/--short-staves 16; --float-anvil 17; --round-band 18.</div>
<div class="runline">
<pre id="runCmd">blender --background --python showcase/anvil/anvil.py --</pre>
Expand Down
2 changes: 1 addition & 1 deletion docs/gallery/armature-bend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@
<body>
<a class="skip" href="#main">Skip to content</a>
<div class="topbar">
<a class="back" href="../"><span aria-hidden="true">&larr;</span> Examples Gallery</a>
<a class="back" href="../"><span aria-hidden="true">&larr;</span> Examples and Showcase</a>
<div class="topbar-right">
<a class="ghlink" href="https://github.com/TMHSDigital/Blender-Developer-Tools">GitHub</a>
</div>
Expand Down
2 changes: 1 addition & 1 deletion docs/gallery/attribute-domain-shear/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@
<body>
<a class="skip" href="#main">Skip to content</a>
<div class="topbar">
<a class="back" href="../"><span aria-hidden="true">&larr;</span> Examples Gallery</a>
<a class="back" href="../"><span aria-hidden="true">&larr;</span> Examples and Showcase</a>
<div class="topbar-right">
<a class="ghlink" href="https://github.com/TMHSDigital/Blender-Developer-Tools">GitHub</a>
</div>
Expand Down
2 changes: 1 addition & 1 deletion docs/gallery/bake-normal-high-to-low/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@
<body>
<a class="skip" href="#main">Skip to content</a>
<div class="topbar">
<a class="back" href="../"><span aria-hidden="true">&larr;</span> Examples Gallery</a>
<a class="back" href="../"><span aria-hidden="true">&larr;</span> Examples and Showcase</a>
<div class="topbar-right">
<a class="ghlink" href="https://github.com/TMHSDigital/Blender-Developer-Tools">GitHub</a>
</div>
Expand Down
2 changes: 1 addition & 1 deletion docs/gallery/bmesh-gear/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@
<body>
<a class="skip" href="#main">Skip to content</a>
<div class="topbar">
<a class="back" href="../"><span aria-hidden="true">&larr;</span> Examples Gallery</a>
<a class="back" href="../"><span aria-hidden="true">&larr;</span> Examples and Showcase</a>
<div class="topbar-right">
<a class="ghlink" href="https://github.com/TMHSDigital/Blender-Developer-Tools">GitHub</a>
</div>
Expand Down
10 changes: 5 additions & 5 deletions docs/gallery/campfire/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>campfire — Examples — Blender Developer Tools</title>
<title>campfire — Showcase — Blender Developer Tools</title>
<meta name="description" content="A procedural campfire through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract." />
<link rel="canonical" href="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/campfire/" />
<link rel="icon" href="../../assets/favicon.svg" type="image/svg+xml" />
<meta name="theme-color" content="#1a1b1e" />
<meta property="og:type" content="website" />
<meta property="og:title" content="campfire — Examples — Blender Developer Tools" />
<meta property="og:title" content="campfire — Showcase — Blender Developer Tools" />
<meta property="og:description" content="A procedural campfire through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract." />
<meta property="og:url" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/campfire/" />
<meta property="og:image" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/assets/campfire-hero.webp" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="campfire — Examples — Blender Developer Tools" />
<meta name="twitter:title" content="campfire — Showcase — Blender Developer Tools" />
<meta name="twitter:description" content="A procedural campfire through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract." />
<meta name="twitter:image" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/assets/campfire-hero.webp" />
<style>
Expand Down Expand Up @@ -239,7 +239,7 @@
<body>
<a class="skip" href="#main">Skip to content</a>
<div class="topbar">
<a class="back" href="../"><span aria-hidden="true">&larr;</span> Examples Gallery</a>
<a class="back" href="../"><span aria-hidden="true">&larr;</span> Examples and Showcase</a>
<div class="topbar-right">
<a class="ghlink" href="https://github.com/TMHSDigital/Blender-Developer-Tools">GitHub</a>
</div>
Expand All @@ -252,7 +252,7 @@ <h1>campfire</h1>
<button class="detail-hero" id="heroZoom" type="button" aria-label="Zoom campfire render">
<img src="../assets/campfire-hero.webp" alt="campfire render" width="1280" height="720" />
</button>
<p class="zoom-hint">Rendered headless by the example itself — click to zoom.</p>
<p class="zoom-hint">Rendered headless by the showcase piece itself — click to zoom.</p>
<div class="callout"><span class="tag">witnesses</span> Recomputed: 2200 tris, three materials with 216 wood, 48 ash and 1304 stone faces, UVs in 0..1 with zero AABB overlap, outer AABB 0.807×0.808×0.404 m, LOD ratios in band, convex collider 198 tris, hygiene 0, 14 grounded bottom stones, teepee kiss 0.00001 m, course seat 0, non-empty glTF. --skip-decimate exits 9; --stray-vert 15; --lift-z/--short-stones 16; --float-logs 17; --gap-courses 18.</div>
<div class="runline">
<pre id="runCmd">blender --background --python showcase/campfire/campfire.py --</pre>
Expand Down
2 changes: 1 addition & 1 deletion docs/gallery/car-mirror-symmetry/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@
<body>
<a class="skip" href="#main">Skip to content</a>
<div class="topbar">
<a class="back" href="../"><span aria-hidden="true">&larr;</span> Examples Gallery</a>
<a class="back" href="../"><span aria-hidden="true">&larr;</span> Examples and Showcase</a>
<div class="topbar-right">
<a class="ghlink" href="https://github.com/TMHSDigital/Blender-Developer-Tools">GitHub</a>
</div>
Expand Down
10 changes: 5 additions & 5 deletions docs/gallery/cart/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>cart — Examples — Blender Developer Tools</title>
<title>cart — Showcase — Blender Developer Tools</title>
<meta name="description" content="A procedural two-wheel wooden cart through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract." />
<link rel="canonical" href="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/cart/" />
<link rel="icon" href="../../assets/favicon.svg" type="image/svg+xml" />
<meta name="theme-color" content="#1a1b1e" />
<meta property="og:type" content="website" />
<meta property="og:title" content="cart — Examples — Blender Developer Tools" />
<meta property="og:title" content="cart — Showcase — Blender Developer Tools" />
<meta property="og:description" content="A procedural two-wheel wooden cart through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract." />
<meta property="og:url" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/cart/" />
<meta property="og:image" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/assets/cart-hero.webp" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="cart — Examples — Blender Developer Tools" />
<meta name="twitter:title" content="cart — Showcase — Blender Developer Tools" />
<meta name="twitter:description" content="A procedural two-wheel wooden cart through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract." />
<meta name="twitter:image" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/assets/cart-hero.webp" />
<style>
Expand Down Expand Up @@ -239,7 +239,7 @@
<body>
<a class="skip" href="#main">Skip to content</a>
<div class="topbar">
<a class="back" href="../"><span aria-hidden="true">&larr;</span> Examples Gallery</a>
<a class="back" href="../"><span aria-hidden="true">&larr;</span> Examples and Showcase</a>
<div class="topbar-right">
<a class="ghlink" href="https://github.com/TMHSDigital/Blender-Developer-Tools">GitHub</a>
</div>
Expand All @@ -252,7 +252,7 @@ <h1>cart</h1>
<button class="detail-hero" id="heroZoom" type="button" aria-label="Zoom cart render">
<img src="../assets/cart-hero.webp" alt="cart render" width="1280" height="720" />
</button>
<p class="zoom-hint">Rendered headless by the example itself — click to zoom.</p>
<p class="zoom-hint">Rendered headless by the showcase piece itself — click to zoom.</p>
<div class="callout"><span class="tag">witnesses</span> Recomputed: 2600 tris, two materials with metal and wood face floors, UVs in 0..1 with zero AABB overlap, outer AABB 1.539×0.749×0.640 m, LOD ratios in band, convex collider 122 tris, hygiene zero (loose, non-manifold, doubles, n-gons), grounded zmin, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget; --lift-z exits 16 on the grounded budget.</div>
<div class="runline">
<pre id="runCmd">blender --background --python showcase/cart/cart.py --</pre>
Expand Down
Loading
Loading