feat: Implement draggable torso and head IK targets in the test harness

- Added draggable handles for the torso and head to the test harness.
- Updated `IK_HANDLE_PATHS` to include new entries for "Head" and "Torso".
- Implemented distinct colors for the torso (magenta) and head (yellow) markers.
- Added a visual aid (aim line) to indicate the head's LookAt target direction.
- Ensured that dragging the torso moves only the torso marker, allowing for limb stretching towards stationary targets.
This commit is contained in:
2026-08-21 12:39:31 -04:00
parent 6b273c049c
commit ab5c79ab6a
14 changed files with 1459 additions and 174 deletions
+72
View File
@@ -0,0 +1,72 @@
# Phase 9 Round 4 — Bugfix: Head Position vs. the Editor's Silhouette Guide
## Overview
User report: the head is **too high** in the harness. Reference: the editor's silhouette guide
head is a circle; the bottom of the mounted head shape must line up with the bottom of that
circle relative to the torso bone, so the head **overlaps the torso** some.
### Guide geometry (source of truth, `scripts/whole_stickman_preview.gd`)
| Constant | Value |
|---|---|
| `GUIDE_JOINTS["Neck"]` (`:61`) | `(0, 391.5)` — the Head bone origin |
| `GUIDE_JOINTS["Head"]` (`:62`) | `(0, 463.5)` — the head circle **center** |
| `GUIDE_HEAD_RADIUS` (`:49`) | `100.0` |
→ The guide's head circle bottom = `463.5 + 100 = 363.5`**28 px below the neck**,
overlapping the torso's top region (torso spans `0 → 391.5`) by 28 px.
### Current behavior (wrong)
Round 3 zeroes the Head driver's local position, so `Body/Head` sits on the Head bone origin
(the neck, `y = 391.5`); the mounted chin is the local origin → the chin lands at the neck
and the head floats above the torso with no overlap.
### Required behavior
The mounted head's bottom (chin) must land at `y = 363.5` — i.e. the mounted head geometry
gets a `+28 px` local Y offset so the chin sits 28 px below the neck joint, matching the
guide circle's bottom and overlapping the torso.
## Fix specification — `scripts/stk_rig_adapter.gd`
1. Add `const HEAD_CHIN_DROP := 28.0` with a doc comment deriving the value
(guide head circle bottom `363.5` neck `391.5` = 28; the guide circle has radius 100
centered at the Head joint `(0, 463.5)`).
2. In the head branch of the mount (where `θ = 0`, `s = 1`), after transforming the points,
translate them by `Vector2(0.0, HEAD_CHIN_DROP)` — the chin (local origin) ends up 28 px
below the node origin (the neck).
3. The flip anchor rule from Round 3 is unchanged (a flipped head still attaches at its cap
top; the drop applies identically).
4. Nothing else changes (no driver/overlay/serialization changes).
Note: the offset is applied **after** the part scale/rotation composition (it is a rig-space
fixture position, not part geometry), so a 180°-rotated head drops by the same 28 px.
## Files modified
| File | Changes |
|---|---|
| `scripts/stk_rig_adapter.gd` | `HEAD_CHIN_DROP` const + head-points translation. |
| `docs/phase9_round4_bugfix_spec.md` | This file. |
## Test plan
1. Parse check: `..\Godot_v4.7.1-stable_win64_console.exe . --headless --check-only --quit`.
2. Headless smoke test (spawn `break.stk`, stack enabled, 2 frames):
- `Body/Head` world position ≈ `(0, 391.5)` (node still at the neck).
- Mounted head chin point ≈ local `(0, +28)`; world chin ≈ `(0, 363.5)`.
- Head top ≈ world `(0, 363.5 219)``(0, 582)`; the head now overlaps the torso's
top region (torso top at 391.5) by ≈ 28 px.
- Regression: the head's other Round 3 properties (scale ≈160 face, one node per shape,
IK following, flip behavior) unchanged.
3. Manual harness check (F6): head bottom aligned with the guide circle's bottom; head
overlaps the torso.
## Design decisions
| # | Decision | Justification |
|---|---|---|
| D1 | Fixed `+28 px` rig-space offset (not relative to the head's drawn size) | The guide circle is a fixed rig fixture; the requirement is to align to its bottom. |
| D2 | Offset applied to the mounted points (not the driver) | The Head driver's zeroing stays (rotation about the neck with the LookAt); a driver offset would swing with the bone rotation. |