Skip to content

Commit 0c818a9

Browse files
TMHSDigitalclaude
andauthored
fix(examples): seat the vse-cut-list monitor and stand its caption up (#245)
Render path only; the Bay scene is staging. The monitor neck butted its top face onto the bezel's bottom on one plane with half its depth behind, and the PROGRAM caption lay flat on the desk 6 mm up, unreadable from the camera. The neck now rises 0.10 m into the bezel, the base sits 5 mm into the desk, and the caption stands on the desk's front face. Sequencer frame, checks and exit codes unchanged on all three binaries. Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent d46732d commit 0c818a9

8 files changed

Lines changed: 52 additions & 17 deletions

File tree

304 Bytes
Loading
152 Bytes
Loading

‎docs/gallery/index.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ <h2><a href="uv-layer-grid/">uv-layer-grid</a></h2>
596596
</article>
597597
<article class="card" data-tags="sequencer rendering">
598598
<a class="card-media" href="vse-cut-list/" tabindex="-1" aria-hidden="true">
599-
<img src="assets/vse-cut-list-hero.webp" alt="A monitor on a plinth showing a sequencer frame of four colour blocks with a cut-list caption strip." loading="lazy" decoding="async" />
599+
<img src="assets/vse-cut-list-hero.webp" alt="A monitor on a desk labelled PROGRAM, showing a sequencer frame of four colour blocks with a cut-list caption strip." loading="lazy" decoding="async" />
600600
</a>
601601
<div class="card-body">
602602
<h2><a href="vse-cut-list/">vse-cut-list</a></h2>

‎docs/gallery/vse-cut-list/index.html‎

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616
<meta property="og:image" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/assets/vse-cut-list-hero.webp" />
1717
<meta property="og:image:width" content="1280" />
1818
<meta property="og:image:height" content="720" />
19-
<meta property="og:image:alt" content="A monitor on a plinth showing a sequencer frame of four colour blocks with a cut-list caption strip." />
19+
<meta property="og:image:alt" content="A monitor on a desk labelled PROGRAM, showing a sequencer frame of four colour blocks with a cut-list caption strip." />
2020
<meta property="og:site_name" content="Blender Developer Tools" />
2121
<meta name="twitter:card" content="summary_large_image" />
2222
<meta name="twitter:title" content="vse-cut-list — Examples — Blender Developer Tools" />
2323
<meta name="twitter:description" content="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." />
2424
<meta name="twitter:image" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/assets/vse-cut-list-hero.webp" />
25-
<meta name="twitter:image:alt" content="A monitor on a plinth showing a sequencer frame of four colour blocks with a cut-list caption strip." />
25+
<meta name="twitter:image:alt" content="A monitor on a desk labelled PROGRAM, showing a sequencer frame of four colour blocks with a cut-list caption strip." />
2626
<style>
2727
/* fonts are deployed by the landing build (docs/fonts/) */
2828
@font-face { font-family: 'Barlow Condensed'; font-weight: 600; font-display: swap;
@@ -268,8 +268,8 @@ <h1>vse-cut-list</h1>
268268
<p>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.</p>
269269
</header>
270270
<main id="main">
271-
<button class="detail-hero" id="heroZoom" type="button" aria-label="View full size: A monitor on a plinth showing a sequencer frame of four colour blocks with a cut-list caption strip.">
272-
<img src="../assets/vse-cut-list-hero.webp" alt="A monitor on a plinth showing a sequencer frame of four colour blocks with a cut-list caption strip." width="1280" height="720" />
271+
<button class="detail-hero" id="heroZoom" type="button" aria-label="View full size: A monitor on a desk labelled PROGRAM, showing a sequencer frame of four colour blocks with a cut-list caption strip.">
272+
<img src="../assets/vse-cut-list-hero.webp" alt="A monitor on a desk labelled PROGRAM, showing a sequencer frame of four colour blocks with a cut-list caption strip." width="1280" height="720" />
273273
</button>
274274
<p class="zoom-hint">Rendered headless by the example itself — click to zoom.</p>
275275
<div class="callout"><span class="tag">witnesses</span> Each side hard-fails the other&#x27;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.</div>
@@ -287,6 +287,7 @@ <h1>vse-cut-list</h1>
287287
<ul><li>A GAMMA_CROSS asked to outlast its inputs&#x27; overlap is <strong>silently clamped</strong> to the overlap — request length 9 over a (25, 33) overlap, get (25, 33).</li><li>A scene strip pointing at its <strong>own</strong> scene is a feedback loop and renders transparent (alpha 0) — the &quot;stage&quot; is silently absent. Source a separate scene.</li><li>Effect strips <strong>consume</strong> their inputs: input strips never composite on their own channel, and the effect&#x27;s transform applies on top of the inputs&#x27; transforms. Consumption requires the effect on a channel <strong>above</strong> its inputs; below, they keep painting independently.</li><li>An empty <code>bpy_prop_collection</code> is falsy — <code>se.strips or se.sequences</code> silently falls through to the legacy accessor on an empty timeline. Always branch on <code>hasattr</code>.</li></ul>
288288
<p><strong>Version divergence:</strong> the whole example is the divergence — gated on the <code>bpy.app.version</code> tuple (<code>&gt;= (5, 0, 0)</code>), never on <code>version_string</code> (<code>&quot;4.5.11 LTS&quot;</code> is not bare semver). Each side asserts its own canonical contract plus the other side&#x27;s removal/bridge state. Measured values are identical on 4.5.11 and 5.1.2, including the pixel witness. <strong>5.2 LTS COLOR strips bake readonly <code>width</code>/<code>height</code> from the scene render resolution at <code>new_effect</code> time</strong> (4.5/5.1 have no intrinsic size — scale is a fraction of the output frame). The pixel check sets 96×54 <em>before</em> building the cut list; creating at factory 1920×1080 then rendering 96×54 makes 0.36-scaled cells larger than the output, C covers the frame, and TL samples amber <code>(0.949, 0.62, 0.102)</code> instead of crimson.</p>
289289
<p><strong>Render:</strong> the program wall <em>is</em> the sequencer output at frame 29 (mid cross) — crimson A, teal B, amber long-runner C, and the 50/50 cross blend, over the Stage scene strip showing the dark studio. An off-by-one in end-exclusive span math drops its cell to the dark stage; the caption strip carries the closed form. The hero presents that authentic frame on a reference monitor in a dark-studio editing bay — the pixels on the screen are the genuine sequencer output (evidence); only the bay around them is staged (presentation). Rendered locally with EEVEE (GPU host); the checks and <code>--check-pixels</code> need no GPU (Cycles CPU).</p>
290+
<p>In the bay, each part bites the one it rests on. The monitor&#x27;s neck rises 0.10 m into the bezel, the stand base sits 5 mm into the desk, and the &quot;PROGRAM&quot; caption stands on the desk&#x27;s front face. The neck used to butt its top face onto the bezel&#x27;s bottom on one plane, with half its depth hanging out behind, and the caption lay flat on the desk top 6 mm up, where the camera read it as a smear. None of this touches the sequencer frame or any check.</p>
290291
<h2>Framing measurement</h2>
291292
<p>The gallery still renders from the dedicated <code>Bay</code> scene (camera <code>BayCam</code>), not <code>bpy.context.scene</code> — a framing measurement with <code>examples/gallery_framing.py</code> must be handed that (scene, camera) pair explicitly.</p>
292293
<h2>Run</h2>
@@ -790,10 +791,20 @@ <h2>Source</h2>
790791
deskmat = pbr(<span class="s">&quot;DeskTop&quot;</span>, (<span class="n">0.05</span>, <span class="n">0.05</span>, <span class="n">0.06</span>), <span class="n">0.0</span>, <span class="n">0.80</span>)
791792

792793
<span class="c"># desk slab, stand, and the monitor bezel (screen face toward -Y)</span>
793-
box(<span class="s">&quot;Desk&quot;</span>, (<span class="n">2.80</span>, <span class="n">1.10</span>, <span class="n">0.72</span>), (<span class="n">0.0</span>, <span class="n">0.0</span>, <span class="n">0.36</span>), deskmat)
794-
box(<span class="s">&quot;StandBase&quot;</span>, (<span class="n">0.70</span>, <span class="n">0.50</span>, <span class="n">0.06</span>), (<span class="n">0.0</span>, <span class="n">0.05</span>, <span class="n">0.75</span>), gunmetal)
795-
box(<span class="s">&quot;Stand&quot;</span>, (<span class="n">0.18</span>, <span class="n">0.12</span>, <span class="n">0.50</span>), (<span class="n">0.0</span>, <span class="n">0.05</span>, <span class="n">0.99</span>), gunmetal)
796-
box(<span class="s">&quot;Bezel&quot;</span>, (<span class="n">2.06</span>, <span class="n">0.09</span>, <span class="n">1.30</span>), (<span class="n">0.0</span>, <span class="n">0.0</span>, <span class="n">1.89</span>), gunmetal)
794+
<span class="c"># Each part bites the one it rests on. The neck used to butt its top face</span>
795+
<span class="c"># onto the bezel&#x27;s bottom face (one plane, no joint) with half its depth</span>
796+
<span class="c"># hanging out behind, and the base sat exactly on the desk top.</span>
797+
desk_top, base_h, base_bite = <span class="n">0.72</span>, <span class="n">0.06</span>, <span class="n">0.005</span>
798+
bezel_z, bezel_h, bezel_d = <span class="n">1.89</span>, <span class="n">1.30</span>, <span class="n">0.09</span>
799+
neck_bite, neck_d = <span class="n">0.10</span>, <span class="n">0.07</span>
800+
base_z0 = desk_top - base_bite
801+
neck_z0 = base_z0 + base_h - base_bite
802+
neck_z1 = bezel_z - bezel_h / <span class="n">2</span> + neck_bite
803+
box(<span class="s">&quot;Desk&quot;</span>, (<span class="n">2.80</span>, <span class="n">1.10</span>, desk_top), (<span class="n">0.0</span>, <span class="n">0.0</span>, desk_top / <span class="n">2</span>), deskmat)
804+
box(<span class="s">&quot;StandBase&quot;</span>, (<span class="n">0.70</span>, <span class="n">0.50</span>, base_h), (<span class="n">0.0</span>, <span class="n">0.05</span>, base_z0 + base_h / <span class="n">2</span>), gunmetal)
805+
box(<span class="s">&quot;Stand&quot;</span>, (<span class="n">0.18</span>, neck_d, neck_z1 - neck_z0),
806+
(<span class="n">0.0</span>, bezel_d / <span class="n">2</span> - neck_d / <span class="n">2</span> + <span class="n">0.02</span>, <span class="n">0.5</span> * (neck_z0 + neck_z1)), gunmetal)
807+
box(<span class="s">&quot;Bezel&quot;</span>, (<span class="n">2.06</span>, bezel_d, bezel_h), (<span class="n">0.0</span>, <span class="n">0.0</span>, bezel_z), gunmetal)
797808

798809
<span class="c"># the screen: one unlit quad sampling the authentic frame end to end —</span>
799810
<span class="c"># emission only, so the VSE pixels read exactly as the sequencer wrote them</span>
@@ -836,7 +847,10 @@ <h2>Source</h2>
836847
cu.size = <span class="n">0.10</span>
837848
cu.extrude = <span class="n">0.004</span>
838849
cob = bpy.data.objects.new(<span class="s">&quot;BayCaption&quot;</span>, cu)
839-
cob.location = (<span class="n">0.0</span>, -<span class="n">0.40</span>, <span class="n">0.73</span>)
850+
<span class="c"># upright on the desk&#x27;s front face, set 1 mm into it: laid flat on the</span>
851+
<span class="c"># top it floated 6 mm up and read as a smear at the camera&#x27;s grazing angle</span>
852+
cob.location = (<span class="n">0.0</span>, -<span class="n">0.55</span> - cu.extrude + <span class="n">0.001</span>, desk_top - <span class="n">0.16</span>)
853+
cob.rotation_euler = (math.radians(<span class="n">90.0</span>), <span class="n">0.0</span>, <span class="n">0.0</span>)
840854
cob.data.materials.append(cmat)
841855
sc.collection.objects.link(cob)
842856

@@ -1054,7 +1068,7 @@ <h2>Source</h2>
10541068
</main>
10551069
<dialog class="lightbox" id="lightbox" aria-label="Full-size render">
10561070
<button class="lightbox-close" type="button" autofocus>Close</button>
1057-
<img src="../assets/vse-cut-list-hero.webp" alt="A monitor on a plinth showing a sequencer frame of four colour blocks with a cut-list caption strip." />
1071+
<img src="../assets/vse-cut-list-hero.webp" alt="A monitor on a desk labelled PROGRAM, showing a sequencer frame of four colour blocks with a cut-list caption strip." />
10581072
</dialog>
10591073
<footer>
10601074
<div class="statusbar">

‎examples/gallery.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@
316316
"name": "vse-cut-list",
317317
"dir": "examples/vse-cut-list",
318318
"teaches": "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.",
319-
"alt": "A monitor on a plinth showing a sequencer frame of four colour blocks with a cut-list caption strip.",
319+
"alt": "A monitor on a desk labelled PROGRAM, showing a sequencer frame of four colour blocks with a cut-list caption strip.",
320320
"witnessesFix": "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.",
321321
"hero": "docs/gallery/assets/vse-cut-list-hero.webp",
322322
"preview": "examples/vse-cut-list/preview.webp",

‎examples/vse-cut-list/README.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,14 @@ are the genuine sequencer output (evidence); only the bay around them is
9999
staged (presentation). Rendered locally with EEVEE (GPU host); the checks
100100
and `--check-pixels` need no GPU (Cycles CPU).
101101

102+
In the bay, each part bites the one it rests on. The monitor's neck rises
103+
0.10 m into the bezel, the stand base sits 5 mm into the desk, and the
104+
"PROGRAM" caption stands on the desk's front face. The neck used to butt its
105+
top face onto the bezel's bottom on one plane, with half its depth hanging
106+
out behind, and the caption lay flat on the desk top 6 mm up, where the
107+
camera read it as a smear. None of this touches the sequencer frame or any
108+
check.
109+
102110
## Framing measurement
103111

104112
The gallery still renders from the dedicated `Bay` scene (camera `BayCam`),

‎examples/vse-cut-list/preview.webp‎

320 Bytes
Loading

‎examples/vse-cut-list/vse_cut_list.py‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -475,10 +475,20 @@ def pbr(name, base, metallic, roughness):
475475
deskmat = pbr("DeskTop", (0.05, 0.05, 0.06), 0.0, 0.80)
476476

477477
# desk slab, stand, and the monitor bezel (screen face toward -Y)
478-
box("Desk", (2.80, 1.10, 0.72), (0.0, 0.0, 0.36), deskmat)
479-
box("StandBase", (0.70, 0.50, 0.06), (0.0, 0.05, 0.75), gunmetal)
480-
box("Stand", (0.18, 0.12, 0.50), (0.0, 0.05, 0.99), gunmetal)
481-
box("Bezel", (2.06, 0.09, 1.30), (0.0, 0.0, 1.89), gunmetal)
478+
# Each part bites the one it rests on. The neck used to butt its top face
479+
# onto the bezel's bottom face (one plane, no joint) with half its depth
480+
# hanging out behind, and the base sat exactly on the desk top.
481+
desk_top, base_h, base_bite = 0.72, 0.06, 0.005
482+
bezel_z, bezel_h, bezel_d = 1.89, 1.30, 0.09
483+
neck_bite, neck_d = 0.10, 0.07
484+
base_z0 = desk_top - base_bite
485+
neck_z0 = base_z0 + base_h - base_bite
486+
neck_z1 = bezel_z - bezel_h / 2 + neck_bite
487+
box("Desk", (2.80, 1.10, desk_top), (0.0, 0.0, desk_top / 2), deskmat)
488+
box("StandBase", (0.70, 0.50, base_h), (0.0, 0.05, base_z0 + base_h / 2), gunmetal)
489+
box("Stand", (0.18, neck_d, neck_z1 - neck_z0),
490+
(0.0, bezel_d / 2 - neck_d / 2 + 0.02, 0.5 * (neck_z0 + neck_z1)), gunmetal)
491+
box("Bezel", (2.06, bezel_d, bezel_h), (0.0, 0.0, bezel_z), gunmetal)
482492

483493
# the screen: one unlit quad sampling the authentic frame end to end —
484494
# emission only, so the VSE pixels read exactly as the sequencer wrote them
@@ -521,7 +531,10 @@ def pbr(name, base, metallic, roughness):
521531
cu.size = 0.10
522532
cu.extrude = 0.004
523533
cob = bpy.data.objects.new("BayCaption", cu)
524-
cob.location = (0.0, -0.40, 0.73)
534+
# upright on the desk's front face, set 1 mm into it: laid flat on the
535+
# top it floated 6 mm up and read as a smear at the camera's grazing angle
536+
cob.location = (0.0, -0.55 - cu.extrude + 0.001, desk_top - 0.16)
537+
cob.rotation_euler = (math.radians(90.0), 0.0, 0.0)
525538
cob.data.materials.append(cmat)
526539
sc.collection.objects.link(cob)
527540

0 commit comments

Comments
 (0)