feat: Enhance Trigger Area Reliability in Sandbox Stage

- Updated `_rule_matches` to ensure `entered_area` checks both source and target instance IDs for accurate event triggering.
- Refined `_update_area_entry` to utilize `_movable_overlaps_area`, ensuring that visible stickman/prop geometry is considered for area overlap detection.
- Introduced a new regression test suite in `tests/test_phase4c_area.gd` to validate the functionality of `entered_area` rules, covering various edge cases and ensuring correct behavior for source-specific and wildcard rules.
- Documented the architectural changes and validation results in `specs/phase_4c_area.md`, detailing the scope, data contracts, and design decisions made during implementation.
- Added new agent configurations for architect, developer, and writer roles to streamline the development process and improve documentation practices.
This commit is contained in:
2026-09-11 15:43:08 -04:00
parent 31282313be
commit 04e0f1bea2
11 changed files with 489 additions and 9 deletions
+12 -3
View File
@@ -598,7 +598,7 @@ assembled in a "Whole Stickman" preview that supports translation, rotation, and
stickman-vs-prop separately).
- `scripts/trigger_area.gd` — `class_name TriggerArea`, `extends Node2D`; a **placeable sensor**
(Phase 4, **not used by the editor**). `@export size: Vector2` (default 96×96), `get_area_rect()
-> Rect2` (centered on the node's global position), and `_draw()` (translucent green fill +
-> Rect2` (centered local-space rectangle), and `_draw()` (translucent green fill +
dashed border). **No physics and no signals** — it is a pure geometric region evaluated by
`sandbox_stage.gd`'s event engine (`_update_area_entry`) for `entered_area` rules.
- `scripts/prop_utils.gd` — `class_name PropUtils`, `extends RefCounted`; static factory
@@ -715,8 +715,9 @@ assembled in a "Whole Stickman" preview that supports translation, rotation, and
`action_finished`, `speech_finished`, `entered_area`, `collided`; action types reuse the Phase
3a set: `walk_to`/`speak`/`wait`/`ragdoll`/`recover`). Rules persist across Play/Edit mode
toggles but are **not** saved to disk (Phase 5). A geometric **event engine** runs in PLAY
(`_update_area_entry` tests a movable's feet/position against each `TriggerArea.get_area_rect()`;
`_update_stickman_prop_collision` tests a stickman's feet point against prop AABBs and vice-versa),
(`_update_area_entry` tests each movable's visible world AABB against the current transformed
`TriggerArea` world AABB; `_update_stickman_prop_collision` continues to test a stickman's feet
point against prop AABBs and vice-versa),
with **edge-triggered** dicts (already-fired events) reset on mode entry. A **rule-builder UI
state machine** (`RuleStep` enum: `IDLE`, `SELECT_TRIGGER`, `TRIGGER_TARGET`, `SELECT_ACTION`,
`ACTION_TARGET`, `ACTION_POSITION`, `PARAMS`) is driven from a **"⚡ When..."** item in the Direct
@@ -733,6 +734,14 @@ assembled in a "Whole Stickman" preview that supports translation, rotation, and
confirm (`_finalize_rule`), cancel (`_cancel_rule_build`), or Direct-mode/flow exit
(`_clear_director_pending`), but **not** by `_reset_rule_builder()` (the Back-to-actions path
intentionally reuses it).
- **Phase 4c area-entry reliability:** `entered_area` matching requires both the source movable
instance ID and target area instance ID; `source == -1` remains the explicit wildcard. Area
entry uses visible world-AABB overlap for ANIMATED stickmen and unfrozen props, so an object can
trigger when a visible leg/body part enters even if its feet anchor is still outside. The
`_area_overlap` edge state is independent per area/movable instance-ID pair: it fires once on
outside→overlap, does not repeat while overlapping, and re-arms after exit. The area loop's prop
enumeration is correctly scoped. Verified by `tests/test_phase4c_area.gd` (19 assertions,
all passed) and manual editor verification of A entering an area causing B's speech bubble.
- **Phase 3b asset-library selector integration:** the **Stickman** and **Prop** palette buttons no
longer place directly — pressing them opens a modal **selector grid** (`_selector: AssetSelector`,
an instantiated `scenes/asset_selector.tscn` `PopupPanel`, added to the UI `CanvasLayer` in