Skip to content

Commit ce98928

Browse files
committed
fix: reframe vse-cut-list bay into the band and gate the Bay scene
The corrected survey (render_pre capture) measured this hero for the first time: the monitor top was cropped and the desk bled the bottom edge (fill 1.000y, touch B+T) — the #107 survey had read bpy.context.scene, which is the cut-list scene, not the Bay the still renders from. BayCam pulls back from (2.0,-5.2,1.72) to (3.05,-7.9,2.0) with aim z 1.28 -> 1.20, landing fill 0.506x/0.850y with margins L0.247 R0.247 B0.067 T0.083. This was the most-broken of the seven (frame-filling before), so the composition change is correspondingly larger; the bezel, stand, desk, and on-screen cut list are all fully in frame now. The gate runs on the Bay scene (the helper's scene-targeted matte from the previous commit), falsified at lens 66 (fill 1.000 FAIL, exit 10) and restored. check and --check-pixels both exit 0 on 5.1.2 and 4.5.11 with identical pixel witnesses. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com>
1 parent ff20848 commit ce98928

6 files changed

Lines changed: 71 additions & 10 deletions

File tree

-2.59 KB
Loading
-6.61 KB
Loading

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

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ <h2>Run</h2>
204204
# Also render the still (EEVEE on a GPU host; --engine cycles on GPU-less):
205205
blender --background --python vse_cut_list.py -- --output vse.png</code></pre>
206206
<p>It exits non-zero on failure and prints every measured value and tolerance on success, so CI logs carry the numbers. The <code>blender-smoke</code> workflow runs the check and the pixel witness on Blender 4.5 LTS and 5.1.</p>
207+
<p>The <code>--output</code> render path additionally measures framing against the Layer 1 band via <code>examples/gallery_framing.py</code> (exit 10 on violation) before writing the still.</p>
207208
</section>
208209
<section class="detail-section src">
209210
<h2>Source</h2>
@@ -259,6 +260,11 @@ <h2>Source</h2>
259260
<span class="k">import</span> bpy, sys, os, math, argparse, tempfile, warnings, shutil
260261
<span class="k">import</span> mathutils
261262

263+
<span class="c"># Shared Layer 1 framing measurement (render path only) — see gallery_framing.py</span>
264+
sys.path.insert(<span class="n">0</span>, os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir))
265+
sys.dont_write_bytecode = <span class="k">True</span> <span class="c"># keep examples/__pycache__ out of the repo tree</span>
266+
<span class="k">import</span> gallery_framing
267+
262268
IS_5X = bpy.app.version &gt;= (<span class="n">5</span>, <span class="n">0</span>, <span class="n">0</span>)
263269

264270
<span class="c"># Closed-form cut list, end-exclusive [start, end) spans on the timeline.</span>
@@ -724,10 +730,12 @@ <h2>Source</h2>
724730
cam_data = bpy.data.cameras.new(<span class="s">&quot;BayCam&quot;</span>)
725731
cam_data.lens = <span class="n">52.0</span>
726732
cam = bpy.data.objects.new(<span class="s">&quot;BayCam&quot;</span>, cam_data)
727-
cam.location = (<span class="n">2.0</span>, -<span class="n">5.2</span>, <span class="n">1.72</span>)
733+
<span class="c"># Pulled back from (2.0, -5.2, 1.72) so the bezel top and desk base</span>
734+
<span class="c"># clear the frame edges (framing gate on the Bay scene).</span>
735+
cam.location = (<span class="n">3.05</span>, -<span class="n">7.9</span>, <span class="n">2.0</span>)
728736
sc.collection.objects.link(cam)
729737
target = bpy.data.objects.new(<span class="s">&quot;BayAim&quot;</span>, <span class="k">None</span>)
730-
target.location = (<span class="n">0.0</span>, <span class="n">0.0</span>, <span class="n">1.28</span>)
738+
target.location = (<span class="n">0.0</span>, <span class="n">0.0</span>, <span class="n">1.20</span>)
731739
sc.collection.objects.link(target)
732740
con = cam.constraints.new(<span class="s">&quot;TRACK_TO&quot;</span>)
733741
con.target = target
@@ -749,8 +757,27 @@ <h2>Source</h2>
749757
sc.render.filepath = path
750758
<span class="c"># Standard keeps both the stage saturated and the on-screen frame true</span>
751759
sc.view_settings.view_transform = <span class="s">&quot;Standard&quot;</span>
760+
<span class="c"># Layer 1 framing gate (silhouette matte) on the BAY scene — exit 10 on</span>
761+
<span class="c"># violation, before the beauty render. Renderables here are the desk,</span>
762+
<span class="c"># stand, and monitor assembly; floor/wall are the stage.</span>
763+
stage = [o <span class="k">for</span> o <span class="k">in</span> sc.objects <span class="k">if</span> any(k <span class="k">in</span> o.name.lower() <span class="k">for</span> k <span class="k">in</span> (<span class="s">&quot;floor&quot;</span>, <span class="s">&quot;wall&quot;</span>))]
764+
hero = [
765+
o <span class="k">for</span> o <span class="k">in</span> sc.objects
766+
<span class="k">if</span> o.type <span class="k">in</span> gallery_framing._RENDER_TYPES <span class="k">and</span> <span class="k">not</span> o.hide_render <span class="k">and</span> o <span class="k">not</span> <span class="k">in</span> stage
767+
]
768+
fcode = gallery_framing.check_framing(
769+
sc, cam,
770+
hero=hero,
771+
elements=hero,
772+
stage=stage,
773+
)
774+
<span class="k">if</span> fcode:
775+
<span class="k">return</span> fcode
752776
bpy.ops.render.render(write_still=<span class="k">True</span>, scene=sc.name)
753-
<span class="k">return</span> os.path.exists(path) <span class="k">and</span> os.path.getsize(path) &gt; <span class="n">0</span>
777+
<span class="k">if</span> <span class="k">not</span> (os.path.exists(path) <span class="k">and</span> os.path.getsize(path) &gt; <span class="n">0</span>):
778+
print(<span class="s">&quot;ERROR: render produced no file&quot;</span>, file=sys.stderr)
779+
<span class="k">return</span> <span class="n">11</span>
780+
<span class="k">return</span> <span class="n">0</span>
754781

755782

756783
<span class="k">def</span> render_still(path, engine):
@@ -763,7 +790,7 @@ <h2>Source</h2>
763790
<span class="k">try</span>:
764791
frame_path = os.path.join(tmp, <span class="s">&quot;program.png&quot;</span>)
765792
<span class="k">if</span> <span class="k">not</span> render_frame(sc, frame_path, engine, RENDER_W, RENDER_H):
766-
<span class="k">return</span> <span class="k">False</span>
793+
<span class="k">return</span> <span class="n">11</span>
767794
bay = bpy.data.scenes.new(<span class="s">&quot;Bay&quot;</span>)
768795
build_stage(bay) <span class="c"># the house dark studio, lights included</span>
769796
build_bay(bay, frame_path)
@@ -860,8 +887,11 @@ <h2>Source</h2>
860887
<span class="k">if</span> args.output:
861888
<span class="c"># The round-trip reloaded a .blend; start clean for the still.</span>
862889
bpy.ops.wm.read_factory_settings(use_empty=<span class="k">True</span>)
863-
<span class="k">if</span> <span class="k">not</span> render_still(os.path.abspath(args.output), args.engine):
890+
rcode = render_still(os.path.abspath(args.output), args.engine)
891+
<span class="k">if</span> rcode == <span class="n">11</span>:
864892
<span class="k">return</span> fail(<span class="s">f&quot;</span><span class="s">render produced no file at </span>{args.output}<span class="s">&quot;</span>, <span class="n">11</span>)
893+
<span class="k">if</span> rcode:
894+
<span class="k">return</span> rcode
865895
print(<span class="s">f&quot;</span><span class="s">wrote </span>{args.output}<span class="s">&quot;</span>)
866896
<span class="k">return</span> <span class="n">0</span>
867897

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,5 @@ blender --background --python vse_cut_list.py -- --output vse.png
116116
It exits non-zero on failure and prints every measured value and tolerance on
117117
success, so CI logs carry the numbers. The `blender-smoke` workflow runs the
118118
check and the pixel witness on Blender 4.5 LTS and 5.1.
119+
120+
The `--output` render path additionally measures framing against the Layer 1 band via `examples/gallery_framing.py` (exit 10 on violation) before writing the still.

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

-2.07 KB
Loading

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

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@
4646
import bpy, sys, os, math, argparse, tempfile, warnings, shutil
4747
import mathutils
4848

49+
# Shared Layer 1 framing measurement (render path only) — see gallery_framing.py
50+
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir))
51+
sys.dont_write_bytecode = True # keep examples/__pycache__ out of the repo tree
52+
import gallery_framing
53+
4954
IS_5X = bpy.app.version >= (5, 0, 0)
5055

5156
# Closed-form cut list, end-exclusive [start, end) spans on the timeline.
@@ -511,10 +516,12 @@ def render_bay(sc, path, engine, w, h):
511516
cam_data = bpy.data.cameras.new("BayCam")
512517
cam_data.lens = 52.0
513518
cam = bpy.data.objects.new("BayCam", cam_data)
514-
cam.location = (2.0, -5.2, 1.72)
519+
# Pulled back from (2.0, -5.2, 1.72) so the bezel top and desk base
520+
# clear the frame edges (framing gate on the Bay scene).
521+
cam.location = (3.05, -7.9, 2.0)
515522
sc.collection.objects.link(cam)
516523
target = bpy.data.objects.new("BayAim", None)
517-
target.location = (0.0, 0.0, 1.28)
524+
target.location = (0.0, 0.0, 1.20)
518525
sc.collection.objects.link(target)
519526
con = cam.constraints.new("TRACK_TO")
520527
con.target = target
@@ -536,8 +543,27 @@ def render_bay(sc, path, engine, w, h):
536543
sc.render.filepath = path
537544
# Standard keeps both the stage saturated and the on-screen frame true
538545
sc.view_settings.view_transform = "Standard"
546+
# Layer 1 framing gate (silhouette matte) on the BAY scene — exit 10 on
547+
# violation, before the beauty render. Renderables here are the desk,
548+
# stand, and monitor assembly; floor/wall are the stage.
549+
stage = [o for o in sc.objects if any(k in o.name.lower() for k in ("floor", "wall"))]
550+
hero = [
551+
o for o in sc.objects
552+
if o.type in gallery_framing._RENDER_TYPES and not o.hide_render and o not in stage
553+
]
554+
fcode = gallery_framing.check_framing(
555+
sc, cam,
556+
hero=hero,
557+
elements=hero,
558+
stage=stage,
559+
)
560+
if fcode:
561+
return fcode
539562
bpy.ops.render.render(write_still=True, scene=sc.name)
540-
return os.path.exists(path) and os.path.getsize(path) > 0
563+
if not (os.path.exists(path) and os.path.getsize(path) > 0):
564+
print("ERROR: render produced no file", file=sys.stderr)
565+
return 11
566+
return 0
541567

542568

543569
def render_still(path, engine):
@@ -550,7 +576,7 @@ def render_still(path, engine):
550576
try:
551577
frame_path = os.path.join(tmp, "program.png")
552578
if not render_frame(sc, frame_path, engine, RENDER_W, RENDER_H):
553-
return False
579+
return 11
554580
bay = bpy.data.scenes.new("Bay")
555581
build_stage(bay) # the house dark studio, lights included
556582
build_bay(bay, frame_path)
@@ -647,8 +673,11 @@ def main():
647673
if args.output:
648674
# The round-trip reloaded a .blend; start clean for the still.
649675
bpy.ops.wm.read_factory_settings(use_empty=True)
650-
if not render_still(os.path.abspath(args.output), args.engine):
676+
rcode = render_still(os.path.abspath(args.output), args.engine)
677+
if rcode == 11:
651678
return fail(f"render produced no file at {args.output}", 11)
679+
if rcode:
680+
return rcode
652681
print(f"wrote {args.output}")
653682
return 0
654683

0 commit comments

Comments
 (0)