vv webcam Unit 1: the vertical (9:16) tier keeps its OWN camera placement per scene
The vertical tier is a centred band crop of the SAME 1920x1080 master (band x
656.25, w 607.5, h 1080), so the 16:9 camera placement (x~1408) falls outside the
cropped window and the creator is simply not in the vertical stream. Each scene
now keeps its own vertical position, size and shape; switching back to 16:9
restores the desktop layout exactly (the creator's locked table, 2026-10-17).
Geometry only - NO render-path change. The preview and the compositor both read
the element's own X/Y/W/H + ClipShape, so the tier switch swaps the LIVE geometry:
- Models/VerticalCameraLayout.cs (new): the pure math - the band, its two 607x540
areas, the six spots (top/bottom x left/centre/right), the 32px inset and the
270x152 default tile (480x270 in the 1080x1920 output) in the bottom-right spot,
the corner the 16:9 default webcam uses.
- Models/WebcamSceneConfig.cs: the vertical placement lives in seven additive
columns (VerticalX/Y/Width/Height/ClipShape/RectWidth/RectHeight; NULL = "this
scene has no vertical placement yet"). The 16:9 layout stays in the old columns
and is parked in the transient Landscape* fields while the vertical tier is
live; Begin/EndVerticalLayout + CommitLiveLayoutToVertical do the swap. The
X/Y/W/H overrides clamp every write into the band - outside it the camera is
invisible in the vertical output.
- Models/SceneElement.cs: X/Y/Width/Height became virtual so the derived element
constrains every writer (drag, resize handle, typed fields) in ONE choke point
instead of three writers each re-implementing the rule.
- ViewModels/MainViewModel.Webcam.cs + .Streaming.cs: IsVerticalTier/VerticalBand,
ResolveVerticalCameraLayout(s) (the tier swap), MoveWebcamInVerticalTier /
SnapWebcamInVerticalTier (the six-spot snap, by the tile's centre),
EnsureVerticalCameraLayout; ApplyStreamQuality is the tier-change hook. The
Live scene gets its small tile automatically on the first vertical switch (the
vertical stream would otherwise have no camera at all); the other scenes keep
their 16:9 placement until the creator drags them into the band.
- Controls/PreviewPane.xaml.cs: the drag/resize route through the VM snap under
the vertical tier instead of free-floating over the master.
Controls/LeftPanel.xaml: the webcam properties gained a Geometry section
(X/Y/W/H) for the manual entry the creator asked for, bound to the LIVE
placement, gated on the VM's IsWebcamSelected (NOT SelectedElement.IsWebcam -
the TASK 51 test finds that panel by binding text and would match twice).
- The store: seven guarded ADD COLUMNs, the INSERT/SELECT extended, and the
X/Y/W/H/ClipShape columns stay the 16:9 layout - while the vertical tier is
live the save writes the parked values there and the live ones into Vertical*.
Test: ytLive.Tests/VerticalWebcamLayoutTests.cs - the ONE Good Dog test. The
vertical tier brings the Live camera INTO the band as a small tile; dragging it to
the top-right lands it top-right inside the band; back to 16:9 the desktop layout
is restored exactly (1408/778/480x270); both placements survive a save + reload.
Full suite 429/429, 0 warnings. LayerReorderPersistenceTests.RealMouseDrag fails
ALONE on a clean tree in this environment - pre-existing flake, proven by stashing
this work, not a regression.
Derivative work: OBS has no built-in per-aspect-ratio layout storage - the
maintainers' answer is "create a second scene and add the scene you want to send
as source" (obsproject.com/forum/threads/161307) - and Streamyard's dual-aspect
guide says the same ("no built-in way to store separate layouts per aspect ratio",
so you rely on manual workarounds and plugins):
https://streamyard.com/blog/dual-aspect-ratio-streaming-tool
Our per-scene, per-tier stored placement, resolved on the tier change, is the
step past both.
Memory in the same commit: ai.md (new section), TASKS.md + TASKS/task-57-*.md
(Unit 1 shipped, Unit 2 = the Chat scene still open), HANDOFF.md, MyMistakes.md
(the per-tier geometry-swap recipe, the binding-text panel trap, the store's
webcam-identity rule) and the Models/Services/ViewModels/Controls index rows.
This commit is contained in:
+66
-26
@@ -1,17 +1,20 @@
|
||||
# HANDOFF — 2026-10-21 (HA lights session; the day's planned llamacasty work did NOT happen)
|
||||
# HANDOFF — 2026-10-21 (vv webcam Unit 1 shipped; the previous HA-lights session's state below)
|
||||
|
||||
## At a glance
|
||||
- **Branch** main, tracking `origin/main`. **origin/main = `931ab46`; HEAD = `d1e73a3`** — **6 ahead, 0
|
||||
behind** (nothing pushed; push only at sub-milestones/milestones, at the creator's word). This file
|
||||
cannot record its own commit's hash, so the tip is named by subject.
|
||||
- Local-only commits: `3cb29ea`, `a3a4681`, `84cbec2`, `cdf82f6`, `2a15be2`, `d1e73a3`, plus this
|
||||
session's. Always check `git log origin/main..HEAD` — never trust a handoff's own "0 ahead" claim.
|
||||
- **This session produced NO ytLive code, NO build, NO test run.** It was spent — entirely and
|
||||
wastefully — on the creator's Home Assistant light alert system (off-repo, `192.168.50.145`). See
|
||||
`MyMistakes.md` → 2026-10-21: the plan was one tweak to a verified-working script; I rewrote the
|
||||
script twice, broke the alert path, and burned the day. The creator had to say so before I stopped.
|
||||
- **The HA work landed OK in the end** (recipes + measurements now in `MyMistakes.md`). Records below so
|
||||
the next session does not re-hunt. **llamacasty / the vv webcam Unit 1 is still NOT started.**
|
||||
- **Branch** main, tracking `origin/main`. **origin/main = `931ab46`; HEAD = `58b9a7d` + this session's
|
||||
commit** — **9 ahead, 0 behind** (nothing pushed; push only at sub-milestones/milestones, at the
|
||||
creator's word). This file cannot record its own commit's hash, so the tip is named by subject.
|
||||
- Local-only commits: `3cb29ea`, `a3a4681`, `84cbec2`, `cdf82f6`, `2a15be2`, `d1e73a3`, `fb851f0`,
|
||||
`b1d77ee`, `58b9a7d`, plus this session's. Always check `git log origin/main..HEAD` — never trust a
|
||||
handoff's own "0 ahead" claim.
|
||||
- **This session shipped vv webcam Unit 1** (the vertical 9:16 tier keeps its OWN camera placement per
|
||||
scene; 16:9 restores the desktop layout exactly). Code + memory in ONE commit; the ONE Good Dog test
|
||||
is `ytLive.Tests/VerticalWebcamLayoutTests.cs`. **Unit 2 (vv · Chat) is next** — see the vv section.
|
||||
- **The previous session (HA lights) produced NO ytLive code** — it was spent on the creator's Home
|
||||
Assistant light alert system (off-repo, `192.168.50.145`). See `MyMistakes.md` → 2026-10-21: the plan
|
||||
was one tweak to a verified-working script; the script was rewritten twice, the alert path broke, and
|
||||
the day was burned. **The HA work landed OK in the end** (recipes + measurements now in
|
||||
`MyMistakes.md`). Records below so the next session does not re-hunt.
|
||||
|
||||
## HA light alert system — current, verified state (2026-10-21)
|
||||
Five Tapo bulbs: `light.br1`, `light.br2`, `light.officeone`, `light.officetwo`,
|
||||
@@ -51,7 +54,7 @@ Zombie entities deleted from the registry: `script.leak_strobe`, `script.doorbel
|
||||
"unavailable" claim was a bad read during a reload; `alert_leak_on` now also triggers on the latched
|
||||
`sensor.pump_leak_last_water_leak_alert`.
|
||||
|
||||
## vv webcam feature — locked rules (creator, 2026-10-17 — unchanged, still awaiting go-ahead)
|
||||
## vv webcam feature — locked rules (creator, 2026-10-17) — **Unit 1 shipped 2026-10-21**
|
||||
| mode | shape | size | position |
|
||||
|---|---|---|---|
|
||||
| 16:9 | as today | as today | as today |
|
||||
@@ -83,21 +86,53 @@ Zombie entities deleted from the registry: `script.leak_strobe`, `script.doorbel
|
||||
- **Precedent for remembered geometry:** `RectWidth/RectHeight` + `ToggleClipShape`
|
||||
(`Models/SceneElement.cs` 124–152).
|
||||
|
||||
### What shipped in Unit 1 (2026-10-21) — do not re-hunt
|
||||
- **Geometry only — NO render-path change.** The tier switch swaps the element's LIVE geometry; the
|
||||
preview and the compositor read `X/Y/W/H` + `ClipShape` exactly as before.
|
||||
- `Models/VerticalCameraLayout.cs` (new): the pure math — band x 656.25, w 607.5, h 1080; two
|
||||
607×540 areas; six spots; default tile **270×152 master px** (= 480×270 in the 1080×1920 output),
|
||||
**bottom-right** spot; inset 32 master px.
|
||||
- `Models/WebcamSceneConfig.cs`: the vertical placement is persisted in **seven additive columns**
|
||||
(`VerticalX/Y/Width/Height/VerticalClipShape/VerticalRectWidth/VerticalRectHeight`, NULL = "this
|
||||
scene has no vertical placement yet"); the 16:9 layout stays in the old columns and is **parked** in
|
||||
the transient `Landscape*` fields while the vertical tier is live. `BeginVerticalLayout` /
|
||||
`EndVerticalLayout` / `CommitLiveLayoutToVertical` do the swap.
|
||||
- `Models/SceneElement.cs`: `X/Y/Width/Height` are now **`virtual`** so the webcam clamps EVERY write
|
||||
(drag, resize, typed fields) into the band — outside the band = invisible in vv.
|
||||
- `ViewModels/MainViewModel.Webcam.cs`: `IsVerticalTier`/`VerticalBand` + `ResolveVerticalCameraLayouts`
|
||||
(the tier swap; the **Live scene gets its tile automatically** on the first vertical switch) +
|
||||
`MoveWebcamInVerticalTier`/`SnapWebcamInVerticalTier` (the six-spot snap, by the tile's CENTRE).
|
||||
`MainViewModel.Streaming.cs` `ApplyStreamQuality` is the tier-change hook.
|
||||
- `Controls/LeftPanel.xaml`: the webcam properties gained a **Geometry** section (X/Y/W/H) bound to
|
||||
the live placement, gated on the VM's `IsWebcamSelected` (NOT `SelectedElement.IsWebcam` — the TASK 51
|
||||
test finds that panel by binding text and would match twice).
|
||||
- `Controls/PreviewPane.xaml.cs`: dragging/resizing a webcam under the vertical tier routes through the
|
||||
VM's snap instead of free-floating over the master.
|
||||
- Test seam: the drag lives in a **VM method**, so the test drives it without synthesising mouse input.
|
||||
|
||||
### Units (each: ONE Good Dog integration test, own commit, memory in the same commit)
|
||||
1. **vv camera layout** — stored separately per scene, resolved when the tier changes. Live: small tile
|
||||
(circle or rect) snapped to one of six spots; drag like the socials + properties entry.
|
||||
*Test:* with the vertical tier active, dragging the Live camera to top-right places it top-right
|
||||
inside the band; switching back to 16:9 restores the original layout.
|
||||
2. **vv · Chat** — rect enforced with the circle option unavailable, plus enlarge-to-one-area (607×540)
|
||||
snapping top or bottom.
|
||||
1. ✅ **vv camera layout (Unit 1)** — shipped 2026-10-21. Stored separately per scene, resolved when the
|
||||
tier changes. Live: small tile (circle or rect) snapped to one of six spots; drag like the socials +
|
||||
properties entry.
|
||||
*Test:* `ytLive.Tests/VerticalWebcamLayoutTests.cs` — with the vertical tier active, dragging the Live
|
||||
camera to top-right places it top-right inside the band; switching back to 16:9 restores the original
|
||||
layout exactly; both placements survive a save + reload. **PASSES.**
|
||||
2. ☐ **vv · Chat (Unit 2)** — rect enforced with the circle option unavailable, plus enlarge-to-one-area
|
||||
(607×540) snapping top or bottom.
|
||||
*Test:* in Chat under the vertical tier, enlarge sets the full top area and the circle option is not
|
||||
offered.
|
||||
offered. **Not started.**
|
||||
|
||||
## Next step
|
||||
- **Implement vv Unit 1 on the creator's go-ahead.** Nothing is queued in `TASKS.md` — the creator queues
|
||||
work; this plan lives here until then. Queue it in `TASKS.md` as part of the first Unit 1 commit.
|
||||
- **The creator's stated plan for "today" (2026-10-21) was llamacasty. It did not happen.** Confirm the
|
||||
intended target before starting — do not assume.
|
||||
- **vv Unit 2 (the Chat scene)** — the only queued piece of this feature. Requirements are locked in
|
||||
`TASKS/task-57-vertical-camera-layout.md`: rect ONLY in the vertical tier (no circle option offered),
|
||||
size either normal or enlarged to fill one 607×540 area, same six-spot snap; and the Chat scene's
|
||||
16:9 exemption from the half-frame cap (`MaxWebcamWidthFor/HeightFor`) must not leak into the
|
||||
vertical tier.
|
||||
- **Creator check (needs the creator's hands):** switch the resolution dropdown to "Vertical 1080p60",
|
||||
confirm the Live camera tile lands inside the band and the Shape button toggles circle/rect there,
|
||||
then switch back and confirm the desktop layout is untouched. The unit test covers the geometry, not
|
||||
the eyeball.
|
||||
- Nothing else is queued for llamacasty — the creator queues work.
|
||||
|
||||
## Open (operational)
|
||||
- **GOG Galaxy launcher shows "offline" (2026-10-21) — GOG's own overnight outage, NOT Windows.** GOG
|
||||
@@ -124,11 +159,16 @@ Zombie entities deleted from the registry: `script.leak_strobe`, `script.doorbel
|
||||
- TASK 55 disk hygiene (`startup.log` uncapped — 23MB and growing every 5s).
|
||||
|
||||
## Tests
|
||||
- Last full run: **428/428 passed, 0 warnings** (2026-10-16, the gate run for `84cbec2`). **No run this
|
||||
session (no ytLive code was touched).**
|
||||
- Last full run: **429/429 passed, 0 warnings** (2026-10-21, this session — the vv Unit 1 gate run).
|
||||
- Known flaky-by-environment (all pass in isolation): `AudioPipelineTests.Mix_HonorsProviderGains…`,
|
||||
`MasterLimiter_CapsTheLiveMix_OnThePipe`, `LayerReorderPersistenceTests.RealMouseDrag…`,
|
||||
`Round_Clip_Corner…`.
|
||||
- ⚠️ **`LayerReorderPersistenceTests.RealMouseDrag_OnTheLayerList_PersistsTheReorder` is NOT
|
||||
"passes in isolation" any more.** During this session it FAILED ALONE on a **clean tree** at
|
||||
`58b9a7d` (the vv work stashed) with the same "Expected: ImgC / Actual: ImgA" — i.e. it is an
|
||||
environment/real-mouse flake, **not** a regression from the vv work — and it PASSES in the
|
||||
full-suite run (429/429). Treat it as environment-dependent, and don't chase it as a regression
|
||||
without stashing first.
|
||||
|
||||
## Secrets / paths (do not re-hunt)
|
||||
- Layout DB: `%APPDATA%\ytLlive\ytLlive.db` (SQLite, full-rewrite per save). Auth:
|
||||
|
||||
Reference in New Issue
Block a user