Add Phase 3a Core Director Functionality

- Introduced `PHASE_3a_CORE_DIRECTOR.md` detailing the core functionality for directors, including navigation, action queue, UI, waypoint visualization, and action execution.
- Implemented `StageDirectorVisuals` for drawing stickman action queues in edit mode, including waypoints and action badges.
- Created `SpeechBubble` class for displaying speech bubbles above stickmen, with customizable text and styling.
This commit is contained in:
2026-08-30 00:29:30 -04:00
parent badff571f0
commit bf11a5fab5
14 changed files with 2030 additions and 23 deletions
+9
View File
@@ -114,3 +114,12 @@ When applying .stk v1.4 data to master*rig.tscn, shapes are severely distorted:G
## Stickman editor (Phase 9 Round 7)
> ADDED — 2026 Round 7: implemented per docs/phase9_round7_feature_spec.md; the test harness now exposes **six** draggable IK handles. `IK_HANDLE_PATHS` gains `"Head"` (`IK_Targets/Head`, the `SkeletonModification2DLookAt` aim point) and `"Torso"` (`IK_Targets/Torso`, whose child `RemoteTransform2D` moves the hip bone). Dragging the **Torso** handle moves **bones only** — the marker's `RemoteTransform2D` translates the hip bone and the whole skeleton + `Body/*` visuals follow rigidly, while the limb/head targets stay put (dragging the figure away from them stretches the limbs toward the stationary targets, per user decision). Dragging the **Head** handle drives the Head bone's LookAt rotation (clamped at the authored ~55° constraint); `Body/Head` follows. `_handle_color()` colors the head marker yellow (`HANDLE_COLOR_HEAD`) and the torso marker magenta (`HANDLE_COLOR_TORSO`); hands stay green, feet blue. The IK overlay additionally draws a null-guarded semi-transparent yellow aim line from the Head bone origin to the head marker (visual aid for the LookAt test). Verified with a 17-assertion headless test (Torso moved by (60, 40) → `Skeleton2D/Torso` and `Body/*` translate by exactly (60, 40); Head marker moved → Head bone + `Body/Head` rotate).
## Sandbox Stage — Director Tool (Phase 3a)
> FIXED — 2026-08-29: `walk_to` no longer stops after a few pixels. `_update_walking` now defers all nav reads until `NavigationServer2D.map_get_iteration_id(...) != 0` (map-sync guard), forces the path query via `get_next_path_position()` before any empty-path/finished check, and consumes the empty-path grace (`_walk_path_grace = 2`) only after map sync. Off-by-default diagnostics added: `DEBUG_WALK` + `_walk_dbg()` in `stickman_rig.gd`, `DEBUG_STAGE` + `_stage_dbg()` in `sandbox_stage.gd`. Verified with a 44-assertion headless regression suite. **Follow-up (2026-08-29):** the initial "warn + finish in place" unreachable-target policy was itself reported as "stickman stands still with a waypoint" and was replaced by **hybrid nav/direct steering** — on-mesh targets follow the nav path (`_walk_mode = "nav"`), off-mesh/unreachable targets switch to straight-line direct steering toward the clicked waypoint (`_walk_mode = "direct"`, root target = waypoint + `FOOT_OFFSET`). No `push_warning` on off-mesh (a supported case, logged only via `_walk_dbg`); `_walk_path_grace` removed (map-sync guard + forced path query replace it); the debug trace now includes `mode=nav|direct`.
1. **`walk_to` stops after a few pixels.** A stickman directed to walk stops ~5 px into the move and then either sits still or is treated as finished, instead of walking to the target.
- **Symptom:** in Play, the stickman advances one `move_toward` step then stops; the walk never reaches its target.
- **Root cause:** `_update_walking` checked `is_navigation_finished()` before the map had synchronized. An unsynced `NavigationAgent2D` (map iteration id `0`) reports an empty, already-finished path, so the walk was ended after a single step. Additionally, `get_current_navigation_path()` alone never triggers a path computation — only `get_next_path_position()` forces the agent's internal `_update_navigation()` to re-query the map for a fresh target, so the empty-path guard would misjudge an off-mesh target as "unreachable" immediately.
- **Fix:** (1) defer all nav reads until `map_get_iteration_id(...) != 0`; (2) call `get_next_path_position()` **before** the empty-path / finished checks so the path is actually computed; (3) make walking **hybrid** — an on-mesh target follows the nav path (`_walk_mode = "nav"`), while an off-mesh/unreachable target (path empty **or** `is_target_reachable()` false) switches to **direct straight-line steering** toward the clicked waypoint (`_walk_mode = "direct"`, root target = waypoint + `FOOT_OFFSET`), so the stickman always reaches the waypoint the user clicked; (4) **no** `push_warning` for an off-mesh waypoint (a supported case — logged only via `_walk_dbg`); the original "warn + finish in place" policy was itself reported as "stickman stands still with a waypoint" and was superseded by this DIRECT branch; (5) `_finish_walk(reason: String)` internal param for the debug trace. The `_walk_path_grace` counter is **removed** — the map-sync guard + forced path query replace it.