feat(deck-slice): spatial framing, self-view and edge cues #909
Closed
lytedev
wants to merge 2 commits from
deck-slice-framing into deck-slice
pull from: deck-slice-framing
merge into: lytedev:deck-slice
lytedev:main
lytedev:propose/module-directory-scanner
lytedev:propose/special-args-cleanup
lytedev:propose/limine-fallback
lytedev:propose/household-kiosk
lytedev:propose/xwayland-ei-display-from-client
lytedev:propose/steamdeck-mouse-steps-aside-for-games
lytedev:propose/assistant-watch
lytedev:propose/lpcamm-watch
lytedev:propose/agents-where-information-lives
lytedev:propose/tuwunel-1.9.2
lytedev:propose/pin-flake-registry
lytedev:propose/headscale-0-29-3
lytedev:propose/canary-freshness-per-repo
lytedev:propose/boot-guard-efivars-fix
lytedev:propose/deck-dock-panel-under-niri
lytedev:propose/admindevice-ssh-anything
lytedev:propose/kdeconnect-announce
lytedev:steamdeck-mgba
lytedev:propose/doorbell-no-internet
lytedev:propose/ha-list-tasks
lytedev:propose/ha-music-not-found
lytedev:propose/bc250-40cu-measured
lytedev:propose/multiboot-foxtrot-dragon
lytedev:propose/pitft-stmpe-drive
lytedev:propose/foxtrot-multiboot-prep
lytedev:propose/pitft-no-smartd
lytedev:propose/kexec-luks-reboot
lytedev:propose/foxtrot-multiboot
lytedev:propose/model-eval
lytedev:propose/foxtrot-vm-seats
lytedev:iamb-sender
lytedev:propose/calendar-alarms
lytedev:pinephone-niri
lytedev:push-tsntxvxynzps
lytedev:propose/spoof-reject-cleanups
lytedev:propose/finance-pipeline
lytedev:steamframe-plan
lytedev:pinephone-buildable
lytedev:deck-pose-wip
lytedev:aerc-open-html
lytedev:local-auth-unification
lytedev:iamb-dotfiles
lytedev:esphome-music-panel
lytedev:wifi-system-profile
lytedev:gauge-history
lytedev:validate-gate-fix2
lytedev:validate-slot-no-hugepages
lytedev:pinephone-reenable
lytedev:cyberdeck-research
lytedev:git-anon-ratelimit
lytedev:headscale-basedomain
lytedev:ssd-fast-tier
lytedev:hold-impermanence-flip
lytedev:gate-dummy-eval
lytedev:zen-browser
lytedev:initrd-remote-unlock
lytedev:beefcake-rpool-backup
lytedev:sec-sso-plan
lytedev:sec-mail
lytedev:flab-lid-wake
lytedev:hearth-k8s
lytedev:zulip
lytedev:router-guest-vlan
lytedev:headscale-extra-records
lytedev:beefcake-advertise-lan
lytedev:push-qrvuuqmxtznv
lytedev:voxtype-per-host-model
lytedev:cleanup
lytedev:push-kanidm-opt-in
lytedev:push-voxtype-flake-fix
lytedev:push-uvqqknxvqlvy
lytedev:push-qrqsxkmlrevert
lytedev:fix-kanidm-uid-attr-map
lytedev:nix-on-droid
lytedev:self-hosted-dns
lytedev:fix-runner-tmpfs-revert
lytedev:beefcake-email
lytedev:beefcake-immich
lytedev:firefox-nightly-devedition
lytedev:fix-bun-baseline
lytedev:flab-stuff
lytedev:printer-sftp
lytedev:dragon-vr-monado
lytedev:clever-vr-game-clamshell-mode-detection
lytedev:wireguard-mesh
lytedev:rescue-beefcake-unpushed-nix
No reviewers
Labels
No labels
bug
enhancement
question
scary
upstream
Milestone
Clear milestone
No items
No milestone
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set
Reference
lytedev/nix!909
Loading…
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