feat(deck-slice): spatial framing, self-view and edge cues #909
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "deck-slice-framing"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Addresses Daniel's feedback after the live test: "I need a sense of space, and I think the window versus camera's viewport makes the ratios feel confusing? and showing the skeleton at least a tad might help provide that."
Stacked on #908 (which is on #907, which is on #906). Base is
deck-slice.Priority note: the letterbox/viewport-ratio fix (part 1 below) is the approved, prioritised piece. The self-view and edge cues (parts 2 and 3) were small — a few hundred lines of pure drawing code with no coupling to the mapping — so they landed alongside rather than being deferred. Nothing was held up to include them. If you want part 1 mergeable on its own anyway, say so and I will split them; I have not rewritten the pushed commits to do that unasked.
1. Letterbox the camera aspect (the prioritised fix)
Pose coordinates are normalised against the camera frame. Mapping 0..1 onto a viewport of a different aspect scales x and y by different factors, so identical physical hand movement covered different screen distance horizontally vs vertically — exactly the "ratios feel confusing" symptom.
The camera aspect is now letterboxed inside the viewport, and every pose→screen mapping goes through that rect. The aspect is derived from the
w/hcarried on each pose message rather than hardcoded, since the daemon negotiates the capture format at runtime and does not always get what it asked for. A mid-stream resolution change recomputes the rect, as does a window resize.The rect is made visible: everything outside it is dimmed and it carries a faint border, so "where the camera can see me" is a place rather than an inference. Targets spawn inside it, so nothing is thrown where a hand cannot reach.
Consequence worth flagging: the cut-speed threshold is now in play-rect widths per second, not pixels. A fixed pixel threshold silently demanded a faster physical swing on a larger window. The number changed meaning, so it may want retuning once someone plays it.
2. Self-view
Each player's skeleton drawn faintly behind the gameplay — low alpha, thin bones, deliberately subordinate to the targets. Blades say where your hands are but nothing about where you are; a player who has drifted sideways or stood too close otherwise cannot tell. Toggle with
--no-self-viewor theSkey, with a hint in the corner since there is no menu.3. Edge cues
When a hand leaves the frame or drops below the confidence threshold, the edge it was last seen near glows. A hand merely approaching an edge glows it weakly, as a warning. Without this, "my hand left the frame", "the model lost my hand" and "the game has hung" all look identical — a blade that stopped moving. Naming the direction is what turns the loss into something the player can act on.
Mirroring — already correct, verified by hand
MIRROR_Xwas alreadytrueand the behaviour was right: raise your right hand and the blade on your right moves. Daniel confirmed this directly by playing it. Unchanged in this PR, but now pinned by a test so it cannot regress silently.Tests
The mapping arithmetic is extracted into
framing.gdas pure static functions, covered bytests/framing_test.gd, which the nix build runs — 13 checks including the uniform-scaling property this change exists to establish:Sandbox-safe by construction — no camera, socket, network or clock. I verified Godot propagates the script exit code by deliberately failing a check (exit 1) rather than assuming it, so this can actually fail a build.
The letterbox is now verified at runtime, not just in unit tests
A gap I found while firming this up: every end-to-end run so far used a 16:9 viewport, where letterboxing is a no-op — so the runtime path was effectively untested even though the arithmetic was covered.
The resolved play rect is now logged on every change (startup, resize, camera renegotiation), which both closes that gap and makes future "the ratios feel wrong" reports diagnosable. A headless run turns out to use a square 1280x1280 viewport, which exercises it properly:
Inset 280px top and bottom, as it should be, with spawning-inside-the-rect and slicing working against it.
Also fixed in passing
The scene gained an
Entitiesnode so runtime targets and blades draw between the self-view and the HUD. They were previously appended after the HUD and drew over the score.Untested
/dev/video0was held by the daemon you left running for Daniel (PID 3335421), so I did not touch it; this round was validated against the synthetic pose stream.f182a46dd359851455b559851455b523ab92880fSuperseded by #915, which consolidates the whole markerless-pose-input program into a single WIP branch against
main. Every commit from this PR is preserved there — nothing was squashed, so the root-cause writeups in the commit messages are intact. Closing here; review happens on #915.Pull request closed