- 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.
73 lines
3.5 KiB
Markdown
73 lines
3.5 KiB
Markdown
# 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. |
|