Files
stickman/docs/phase9_round7_feature_spec.md
ryan ab5c79ab6a 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.
2026-08-21 12:39:31 -04:00

5.0 KiB
Raw Permalink Blame History

Phase 9 Round 7 — Feature: Draggable Torso & Head IK Targets in the Test Harness

Overview

User request (test harness):

  1. Draggable torso target — so the user can drag the whole stickman around.
  2. Draggable head target — so the user can test the LookAt IK for the head.

The rig already provides both targets:

  • IK_Targets/Torso (Marker2D at the hips) with a child RemoteTransform2D whose remote_path is ../../../Skeleton2D/Torso — moving the marker moves the hip bone, and every other bone (Head/arms/legs) and Body/* visual follows.
  • IK_Targets/Head (Marker2D at (0, 624)) — the SkeletonModification2DLookAt aim point for the Head bone (bone_index = 1, constrained, constraint_in_localspace = true).

The harness (scripts/test_harness.gd) already has generic handle dragging (IK_HANDLE_PATHS_hit_test_handle_dragging_handle_handle_mouse_motion sets global_position; _draw_ik_handles draws markers). Only the two new handles need wiring, plus torso-follow semantics.

1. Fix specification — scripts/test_harness.gd

1a. Register the new handles

Add to IK_HANDLE_PATHS:

"Head":  "IK_Targets/Head",
"Torso": "IK_Targets/Torso",

(Note: LEAF_BONE_IK_PATHS stays unchanged — the head's LookAt aim point is not a bone tip, and the Torso is not a leaf bone.)

1b. Torso drag (resolved: bones only)

The Torso handle behaves like every other handle: dragging it moves only the marker (the IK_Targets/Torso RemoteTransform2D then moves the hip bone, and the bone hierarchy follows). The other IK targets (hands/legs/head) stay put, so dragging the figure away from them stretches the limbs toward the stationary targets — per user decision.

1c. Marker colors

_draw_ik_handles currently colors hands green, everything else blue. Add distinct colors:

  • HANDLE_COLOR_HEAD := Color(1.0, 1.0, 0.0) (yellow) for "Head".
  • HANDLE_COLOR_TORSO := Color(1.0, 0.0, 1.0) (magenta) for "Torso".

1d. Head aim line (visual aid for the LookAt test)

In _draw_ik_handles, when both the head bone and the head marker exist, draw a thin semi-transparent line from the head bone origin (Skeleton2D/Torso/Head global position) to the head marker so the user can see what the head is aiming at. (Optional but helpful; use the existing overlay draw style, e.g. width 1.5/zoom, alpha ~0.5.)

2. Files modified

File Changes
scripts/test_harness.gd IK_HANDLE_PATHS + 2 entries (Head, Torso); head/torso marker colors; head aim line.
docs/phase9_round7_feature_spec.md This file.

3. Edge cases

  • Missing nodes (foreign rig): _ik_handles lookups are already null-guarded; the aim line needs a null guard for the head bone.
  • Dragging the Torso moves the markers only (the RayCast_* helpers under IK_Targets stay put — they are not handles).
  • Head LookAt constraints — the head bone rotates within its authored constraint range; dragging the head marker far away clamps the rotation (expected rig behavior).
  • Camera — does not follow the dragged figure (unchanged).

4. Test plan

  1. Parse check: ..\Godot_v4.7.1-stable_win64_console.exe . --headless --check-only --quit.
  2. Headless rig-level verification (SceneTree script, spawn break.stk):
    • Move IK_Targets/Torso by (50, 30) → await a frame → assert Skeleton2D/Torso global position moved by ≈ the delta, and every Body/* visual node's global position moved by ≈ the same delta (rigid translation via the Torso RemoteTransform2D).
    • Move IK_Targets/Head from (0, 624) to (300, 624) → await a frame → assert the Head bone global_rotation changed, and Body/Head.global_rotation changed with it (rotation push) — LookAt works.
  3. Harness code review: IK_HANDLE_PATHS has 6 entries (incl. Head, Torso); marker colors per §1c (yellow head, magenta torso); the head aim line is null-guarded and drawn in the IK overlay; the generic drag flow needs no changes (the Torso marker's RemoteTransform2D moves the hip bone on drag). (Mouse-drag flow is UI-side; the same _handle_mouse_motion math is covered by the review.)
  4. Manual F6 check: drag the magenta torso marker — whole figure moves; drag the yellow head marker — the head turns to look at it.
  5. Cleanup temp files.

5. Design decisions

# Decision Justification
D1 Torso drag = bones only (no target following) User decision: dragging the figure away from the stationary limb/head targets stretches the limbs — useful for testing IK reach.
D2 Head/torso get distinct marker colors 6 markers need visual separation; matches the existing color-coded style.
D3 Head aim line drawn in the IK overlay Makes the LookAt target relationship visible.

6. Implementation order

  1. test_harness.gd — new handles + colors + aim line + torso-follow.
  2. Headless verification + parse check.
  3. Docs (BUGS.md Round 7 note, AGENTS.md, README.md).