diff --git a/.cursor-plugin/plugin.json b/.cursor-plugin/plugin.json index 91e56bb..f7aef7c 100644 --- a/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugin.json @@ -80,6 +80,7 @@ "examples/text-version-stamp", "examples/turntable", "examples/uv-layer-grid", + "examples/vse-cut-list", "examples/wave-displace" ] } diff --git a/.github/workflows/blender-smoke.yml b/.github/workflows/blender-smoke.yml index b08011f..b202638 100644 --- a/.github/workflows/blender-smoke.yml +++ b/.github/workflows/blender-smoke.yml @@ -350,3 +350,22 @@ jobs: # non-zero on failure. xvfb-run -a "$BLENDER" --background \ --python examples/png-exr-alpha/png_exr_alpha.py -- + + - name: Shipped example - vse cut list (sequencer 4.5 vs 5.x rename) + run: | + set -euo pipefail + # Check only (no render): asserts the accessor rename (.sequences + # gone on 5.x, bridged on 4.5), the new_effect end-kwarg rename + # (frame_end on 4.5, length on 5.x — the wrong kwarg TypeErrors), + # closed-form spans on each version's canonical accessors + # (frame_final_* vs left_handle/right_handle/duration with the + # deprecation bridge), GC wiring and clamping, scene-strip span, + # and a save/reload round-trip. Exits non-zero on failure. + xvfb-run -a "$BLENDER" --background \ + --python examples/vse-cut-list/vse_cut_list.py -- + # Compositing witness on a tiny Cycles render: mosaic cells carry + # their strip colors, the cross cell is a true mid blend, and a + # consumed cross source never composites independently. + xvfb-run -a "$BLENDER" --background \ + --python examples/vse-cut-list/vse_cut_list.py -- \ + --check-pixels --engine cycles diff --git a/AGENTS.md b/AGENTS.md index 8777846..8c53974 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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 12 skills, 6 rules, 2 templates, 17 snippets, and 22 +The content base is 12 skills, 6 rules, 2 templates, 17 snippets, and 23 examples (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/`; the render look is specified @@ -35,7 +35,7 @@ Blender-Developer-Tools/ rules/.mdc # 6 rule files templates// # 2 starter templates snippets/.py # 17 standalone Python snippets - examples// # 22 runnable smoke-gated examples (+ gallery.json) + examples// # 23 runnable smoke-gated examples (+ gallery.json) scripts/build_gallery.py # generates docs/gallery/ (stdlib only) scripts/site/ # vendored landing-page build (build_site.py + template) docs/gallery/ # committed generated gallery pages + hero assets diff --git a/CLAUDE.md b/CLAUDE.md index f627257..1cc1b2f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -21,7 +21,7 @@ skills//SKILL.md - AI workflow definitions, 12 total rules/.mdc - Anti-pattern rules, 6 total templates// - Starter projects, 2 total snippets/.py - Standalone code patterns, 17 total -examples// - Runnable smoke-gated examples, 22 total (+ gallery.json) +examples// - Runnable smoke-gated examples, 23 total (+ gallery.json) scripts/build_gallery.py - Regenerates docs/gallery/ from gallery.json (stdlib only) scripts/site/ - Vendored landing-page build (Jinja2) docs/gallery/ - Committed generated gallery pages + hero renders @@ -82,11 +82,11 @@ v0.1.0: canonical object creation and deletion, depsgraph evaluated mesh, bmesh v0.2.0: Principled BSDF material, driver-with-custom-function via `driver_namespace`, application handler registration, shader node group with cross-version `interface` API, `foreach_get` bulk vertex read, version-branch skeleton, and USD export with `evaluation_mode='RENDER'`. -## Examples (22) +## Examples (23) Runnable scripts at `examples//`, each asserting a real API contract with deterministic checks (exit non-zero on failure) and optionally rendering a still via -`--output`. All twenty-two run headless on Blender 4.5 LTS and 5.1 in `blender-smoke.yml`; +`--output`. All twenty-three run headless on Blender 4.5 LTS and 5.1 in `blender-smoke.yml`; 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 `examples/bmesh-gear/` (script structure, README shape, dark-studio render recipe) and diff --git a/README.md b/README.md index 449b575..aff9516 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@

- 12 skills  •  6 rules  •  2 templates  •  17 snippets  •  22 examples + 12 skills  •  6 rules  •  2 templates  •  17 snippets  •  23 examples

@@ -285,6 +285,21 @@ A depsgraph-evaluated export — builds a cube with `SUBSURF`, measures the eval `evaluated_get().to_mesh()` / `to_mesh_clear()`, and asserts `wm.obj_export` ships the modifier-applied geometry (exported vertex count == evaluated > base). + + + + +VSE cut list: a two-by-two program wall in a dark studio — crimson, teal, and amber color strips plus the mid cross-blend cell, composited by the sequencer over a scene strip, with the span caption below + + + +### [vse-cut-list](examples/vse-cut-list/) + +The sequencer API rename from 4.5 LTS to 5.x — `strips` (never `.sequences`), `new_effect` +ending in `length=` vs `frame_end=`, and `left_handle`/`right_handle`/`duration` replacing +the deprecated `frame_final_*`. Asserts closed-form spans, GC wiring and clamping, the +consumed-input compositing contract, and a save/reload round-trip. + diff --git a/ROADMAP.md b/ROADMAP.md index eb9a28b..9225bd0 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -97,12 +97,14 @@ Not committed; target list for the next content version. (v0.3.0 shipped the smo - Refresh the `slotted-actions-animation` skill against any 5.2 changes - Bump `blender_version_min` in the templates if 5.2 APIs are used - Additional snippets for asset library scripting, EXR baking, multi-file extensions -- Gallery coverage follow-ups from the GPv3 review: light-linking, VSE sequences-to-strips witness (`grease-pencil-rosette`, `armature-bend`, `text-version-stamp`, and `image-pixels-testcard` shipped first) +- Gallery coverage follow-ups from the GPv3 review: light-linking (`grease-pencil-rosette`, `armature-bend`, `text-version-stamp`, `image-pixels-testcard`, and `vse-cut-list` shipped first) - ~~UV-layer authoring witness~~ **SHIPPED** as `examples/uv-layer-grid/` — `create_grid(..., calc_uvs=True)` silent no-op without a pre-existing UV layer; closed-form UV fill + explicit assignment fallback; dual-panel render (flat texel (0,0) vs neon checker) - ~~Image save-format witness~~ **SHIPPED** as `examples/png-exr-alpha/` — float→PNG is RGBA16 and false-unpremultiplies as if associated-alpha (closed-form err 0.98 at RGB 0.02 / a=1/255); OpenEXR preserves float RGBA; byte→PNG is straight RGBA8; `EXR color_mode='RGB'` drops alpha - Attribute domain witness: writing a POINT-domain color attribute and reading it as if it were CORNER (or vice versa) silently shears colors across shared verts — companion to `color-attribute-wheel` - Light-linking collection witness: object light linking / receiver collections so a key illuminates only the hero (common AI miss when staging multi-light studios) -- VSE sequences-to-strips witness: building a short cut list from `sequences.new_effect` / movie strips and asserting frame ranges survive reload +- ~~VSE sequences-to-strips witness~~ **SHIPPED** as `examples/vse-cut-list/` — `.sequences` removed on 5.x (4.5 bridges to `.strips`), `new_effect` end kwarg `frame_end=` (4.5) vs `length=` (5.x), `frame_final_*` deprecated in favor of `left_handle`/`right_handle`/`duration`, TRANSFORM effect type removed, GAMMA_CROSS clamps to the source overlap, effect strips consume inputs only when stacked above them, same-scene scene strips render transparent; save/reload round-trip + tiny-render pixel witness +- GAMMA_CROSS blend-curve witness: the cross blend is not the naive linear mix (mid-cross measured (0.341, 0.349, 0.463) from crimson (0.85, 0.10, 0.22) and teal (0.06, 0.75, 0.80)) — derive and assert the gamma-space closed form per frame; follow-up to `vse-cut-list` +- Falsy `bpy_prop_collection` trap snippet: an empty collection is falsy, so `editor.strips or editor.sequences` silently falls through to the legacy accessor on an empty timeline — always branch on `hasattr`; likely generalizes across the API (found authoring `vse-cut-list`) ## Future (uncommitted) diff --git a/docs/gallery/assets/vse-cut-list-hero.webp b/docs/gallery/assets/vse-cut-list-hero.webp new file mode 100644 index 0000000..d0a70f1 Binary files /dev/null and b/docs/gallery/assets/vse-cut-list-hero.webp differ diff --git a/docs/gallery/contact-sheets/vse-cut-list-contact-sheet.webp b/docs/gallery/contact-sheets/vse-cut-list-contact-sheet.webp new file mode 100644 index 0000000..fb9a836 Binary files /dev/null and b/docs/gallery/contact-sheets/vse-cut-list-contact-sheet.webp differ diff --git a/docs/gallery/index.html b/docs/gallery/index.html index 3ab4fdc..43efeb4 100644 --- a/docs/gallery/index.html +++ b/docs/gallery/index.html @@ -198,6 +198,7 @@

Examples Gallery

+ @@ -446,6 +447,17 @@

uv-layer-grid

View example +
+ + vse-cut-list — The sequencer API rename from 4.5 LTS to 5.x — strips (never .sequences), new_effect ending in length= vs frame_end=, and left_handle/right_handle/duration… + +
+

vse-cut-list

+

The sequencer API rename from 4.5 LTS to 5.x — strips (never .sequences), new_effect ending in length= vs frame_end=, and left_handle/right_handle/duration replacing the deprecated frame_final_*. A deterministic cut list — color programs, a clamped GAMMA_CROSS, a scene strip, a text strip — asserted before and after save/reload.

+

witnesses Each side hard-fails the other's spelling: TypeError on the wrong end kwarg, AttributeError on .sequences. The cross clamps to the source overlap, effect strips consume their inputs only when stacked above them, and a same-scene scene strip renders transparent.

+ View example +
+