feat: Implement Phase 4 Trigger Events System
- Added a new event-driven system for reactive storytelling, allowing rules like "When X happens, do Y." - Introduced TriggerArea class for placeable sensors in the stage. - Enhanced StickmanRig to emit signals for actions and arrivals. - Updated StageDirectorVisuals to render rules visually with labels and badges. - Modified StageSpawner to support spawning TriggerAreas. - Improved text baseline calculations in speech bubbles and rule labels. - Added tests for text baseline fixes to ensure proper rendering. - Documented the implementation plan for Phase 4 in PHASE_4_TRIGGER_EVENTS.md. - Created a polish plan for Phase 4 in PHASE_4b_POLISH.md.
This commit is contained in:
@@ -0,0 +1,326 @@
|
||||
# Phase 4: Triggers & Event System — Implementation Plan
|
||||
|
||||
## 1. Overview
|
||||
|
||||
Phase 4 adds **reactive storytelling** to the Sandbox Stage. While Phase 3a gave directors _sequential_ control (actions in a fixed order), Phase 4 gives them _reactive_ control — **"When X happens, do Y."**
|
||||
|
||||
This unlocks:
|
||||
|
||||
- **Cross-stickman communication** (Stickman A arrives → Stickman B speaks)
|
||||
- **Environmental reactions** (Stickman reaches crate → crate explodes)
|
||||
- **Branching narratives** (Arrive at different waypoints → different reactions)
|
||||
|
||||
**Crucially:** Phase 4 **does not** replace or duplicate the Phase 3a Action Queue. Sequential actions for a single stickman (Walk → Wait → Speak → Walk) remain unchanged. Phase 4 adds **cross-object reactivity**.
|
||||
|
||||
---
|
||||
|
||||
## 2. Core Distinction
|
||||
|
||||
| Feature | Phase 3a (Already Works) | Phase 4 (New) |
|
||||
| ----------------------------------------------- | ------------------------ | -------------- |
|
||||
| Walk → Wait → Speak → Walk | ✅ Action Queue | ✅ (unchanged) |
|
||||
| Waypoint → next action | ✅ Action Runner | ✅ (unchanged) |
|
||||
| **Stickman A arrives → Stickman B speaks** | ❌ | ✅ NEW |
|
||||
| **Stickman collides with prop → prop explodes** | ❌ | ✅ NEW |
|
||||
| **Stickman enters area → all stickmen react** | ❌ | ✅ NEW |
|
||||
| **Multiple reactions per event** | ❌ | ✅ NEW |
|
||||
|
||||
---
|
||||
|
||||
## 3. The User's Mental Model
|
||||
|
||||
The director should think of events as **"When → Then"** rules that exist _alongside_ the action queues.
|
||||
|
||||
- **Action Queue:** "Stickman A walks to the crate, waits, then speaks."
|
||||
- **Event Rule:** "When Stickman A reaches the crate, Stickman B says 'Welcome!'"
|
||||
|
||||
The event rule is **not** part of Stickman A's queue. It's a separate rule that watches Stickman A and reacts independently.
|
||||
|
||||
---
|
||||
|
||||
## 4. Milestone Breakdown
|
||||
|
||||
| # | Milestone | Description |
|
||||
| --- | --------------------------- | ------------------------------------------------------- |
|
||||
| 4.1 | **Event Data Model** | Define rule structure and storage. |
|
||||
| 4.2 | **Trigger System** | Detect and emit events from stickmen, props, and areas. |
|
||||
| 4.3 | **Event Rule UI** | Visual rule builder (When → Then workflow). |
|
||||
| 4.4 | **Trigger Areas** | Placeable `Area2D` sensors. |
|
||||
| 4.5 | **Prop Interaction Events** | Prop collisions emit events. |
|
||||
| 4.6 | **Chain Reactions** | Multiple actions per rule, executed in sequence. |
|
||||
| 4.7 | **Integration & Polish** | Full end-to-end testing, bug fixes, UI polish. |
|
||||
|
||||
---
|
||||
|
||||
## 5. Milestone 4.3: Event Rule UI
|
||||
|
||||
### 5.1. The "When..." Option
|
||||
|
||||
```
|
||||
The existing action popup is extended with a new section:
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 🚶 Walk To │
|
||||
│ 💬 Speak │
|
||||
│ ⏳ Wait │
|
||||
│ 💥 Ragdoll │
|
||||
│ 🔄 Recover │
|
||||
│ ───────────────────────────────────────── │
|
||||
│ ⚡ When... (opens trigger sub-menu) │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Design note:** The "When..." option is visually separated (line divider) to signal it creates a _rule_, not a direct action.
|
||||
|
||||
### 5.2. Trigger Sub-Menu
|
||||
|
||||
```
|
||||
When "When..." is clicked, the popup expands/replaces with trigger types:
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 📍 Arrives at a waypoint │
|
||||
│ ✅ Completes any action │
|
||||
│ 💬 Finishes speaking │
|
||||
│ 🎯 Enters trigger area │
|
||||
│ 💥 Collides with something │
|
||||
│ ⬅ Back to actions │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Each trigger type corresponds to a signal emitted by stickmen or the stage.
|
||||
|
||||
### 5.3. The Rule Building Flow (6 Stages)
|
||||
|
||||
```
|
||||
┌──────────────┐
|
||||
│ STAGE 1 │ → User clicks stickman → popup opens
|
||||
│ IDLE │
|
||||
└──────┬───────┘
|
||||
│ Click "When..."
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ STAGE 2 │ → User selects trigger type
|
||||
│ SELECT_TRIGGER│
|
||||
└──────┬───────┘
|
||||
│ (If trigger needs a target: waypoint, area, prop)
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ STAGE 3 │ → User clicks the specific target
|
||||
│ TARGET_ENTRY │ (e.g., a waypoint dot on the stage)
|
||||
└──────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ STAGE 4 │ → User selects the action (Speak, Walk, etc.)
|
||||
│ SELECT_ACTION│
|
||||
└──────┬───────┘
|
||||
│ (If action needs a target: a stickman or prop)
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ STAGE 5 │ → User clicks the target stickman/prop
|
||||
│ TARGET_ENTRY2│
|
||||
└──────┬───────┘
|
||||
│ (If action needs params: text, duration, etc.)
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ STAGE 6 │ → User fills in params
|
||||
│ PARAMS │
|
||||
└──────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ STAGE 7 │ → Rule is stored. Visuals update.
|
||||
│ DONE │
|
||||
└──────────────┘
|
||||
|
||||
```
|
||||
|
||||
**Escape** at any stage cancels rule creation and returns to IDLE.
|
||||
|
||||
---
|
||||
|
||||
## 6. Complete UI Walkthrough: "A Reaches Waypoint → B Speaks"
|
||||
|
||||
### Step 0: Prerequisites (Edit Mode)
|
||||
|
||||
- Stickman A and Stickman B are placed on the stage.
|
||||
- Stickman A already has a **"Walk To"** action queued (with a visible waypoint marker on the stage), OR the user is about to create one.
|
||||
|
||||
### Step 1: Create Stickman A's Walk (If Not Done)
|
||||
|
||||
| # | User Action | System Response |
|
||||
| --- | -------------------------------------------------- | ------------------------------------------------------------------------ |
|
||||
| 1 | Click the **"Direct"** tool button in the palette. | Cursor changes to crosshair. |
|
||||
| 2 | Click **Stickman A** on the stage. | Action popup appears. |
|
||||
| 3 | Click **"🚶 Walk To"** in the popup. | Popup closes. Stage enters target placement mode. |
|
||||
| 4 | Click a spot on the stage. | Blue waypoint dot appears. `walk_to` action added to Stickman A's queue. |
|
||||
|
||||
### Step 2: Create the Reactive Event Rule
|
||||
|
||||
| # | User Action | System Response |
|
||||
| --- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
||||
| 5 | Click the **"Direct"** tool again (if it was deselected). | Cursor changes to crosshair. |
|
||||
| 6 | Click **Stickman A** on the stage. | Action popup appears with new "When..." option. |
|
||||
| 7 | Click **"⚡ When..."** | Trigger sub-menu opens. |
|
||||
| 8 | Click **"📍 Arrives at a waypoint"** | Popup closes. Cursor changes to target selector. Status bar: _"Click the waypoint you want to trigger on."_ |
|
||||
| 9 | Click **the blue waypoint dot** on the stage. | Waypoint glows green briefly. Popup reappears with trigger confirmed. |
|
||||
| 10 | Click **"💬 Speak"** | Popup closes. Cursor changes to target selector. Status bar: _"Click the stickman who will speak."_ |
|
||||
| 11 | Click **Stickman B** on the stage. | Stickman B glows yellow. Text dialog appears. |
|
||||
| 12 | Type **"Hello there!"** and click **[OK]** | Dialog closes. Toast: _"Rule created!"_ |
|
||||
|
||||
### Step 3: Visual Feedback (Edit Mode)
|
||||
|
||||
| Element | Appearance | Description |
|
||||
| ---------------- | ------------------------------------------- | --------------------------------------- |
|
||||
| **Dashed line** | White dashed line | Connects waypoint to Stickman B. |
|
||||
| **Label** | _"When arrives → Speak 'Hello there!'"_ | Centered on the line. |
|
||||
| **Color coding** | Green waypoint + orange badge on Stickman B | Shows trigger source and action target. |
|
||||
| **Rule badge** | ⚡ icon on the label | Hover shows full rule details. |
|
||||
| **Delete icon** | ✕ on the label | Click to remove rule. |
|
||||
|
||||
### Step 4: Test in Play Mode
|
||||
|
||||
| # | User Action | System Response |
|
||||
| --- | ------------------------------------- | ----------------------------------------------------------- |
|
||||
| 13 | Click **"Play"** button. | All queues start executing. |
|
||||
| 14 | Stickman A walks to waypoint. | Normal Phase 3a behavior. |
|
||||
| 15 | When Stickman A arrives, event fires. | Stickman B says **"Hello there!"** (speech bubble appears). |
|
||||
|
||||
---
|
||||
|
||||
## 7. Visual Feedback (Edit Mode Only)
|
||||
|
||||
### 7.1. Rule Visualization Elements
|
||||
|
||||
| Element | Color/Style | Position |
|
||||
| ------------------- | ----------------------------- | ---------------------- |
|
||||
| **Trigger badge** | Green, small, "⚡" | Near source object. |
|
||||
| **Action badge** | Orange, small, "→" | Near target object. |
|
||||
| **Connection line** | Dashed white, alpha 0.6 | From source to target. |
|
||||
| **Label** | White text on dark background | Centered on line. |
|
||||
| **Waypoint glow** | Green (if trigger source) | On the waypoint dot. |
|
||||
|
||||
### 7.2. Rule Interaction
|
||||
|
||||
| Action | Behavior |
|
||||
| --------------------- | ----------------------------------------- |
|
||||
| **Click rule label** | Opens edit popup for that rule. |
|
||||
| **Click delete icon** | Removes the rule (confirmation optional). |
|
||||
| **Hover rule label** | Shows tooltip with full rule details. |
|
||||
|
||||
### 7.3. What the User Sees on the Stage
|
||||
|
||||
```
|
||||
Stickman A Stickman B
|
||||
┌──────┐ ┌──────┐
|
||||
│ 🔵 │ │ 🔵 │
|
||||
│ (A) │ │ (B) │
|
||||
└──┬───┘ └──┬───┘
|
||||
│ │
|
||||
│ ════════════╗ │
|
||||
│ (When arrives) │ │
|
||||
│ ════════════╝ │
|
||||
│ ── ── ── ── ── ── ── ── →│
|
||||
│ (Then Speak "Got it!") │
|
||||
│ │
|
||||
┌──┴──────────────────────────────────┐│
|
||||
│ 📍 Waypoint 3 ││
|
||||
└──────────────────────────────────────┘
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Event Data Model
|
||||
|
||||
### 8.1. Rule Structure
|
||||
|
||||
Rules are stored in the stage's event registry and have three parts:
|
||||
|
||||
**Trigger** — The "When" part.
|
||||
|
||||
| Trigger Type | Source | Target | Description |
|
||||
| --------------------- | ------------- | ------------ | ------------------------------------ |
|
||||
| `arrived_at_waypoint` | Stickman | Waypoint | Stickman completes a walk. |
|
||||
| `action_finished` | Stickman | Action type | Stickman finishes any action. |
|
||||
| `speech_finished` | Stickman | (none) | Stickman finishes speaking. |
|
||||
| `entered_area` | Stickman/Prop | Trigger Area | Object enters a trigger area. |
|
||||
| `collided` | Stickman/Prop | Object | Object collides with another object. |
|
||||
|
||||
**Action** — The "Then" part.
|
||||
|
||||
| Action Type | Target | Params |
|
||||
| -------------- | -------- | ----------------------------------- |
|
||||
| `walk_to` | Stickman | `target` (Vector2) |
|
||||
| `speak` | Stickman | `text` (String), `duration` (float) |
|
||||
| `wait` | Stickman | `duration` (float) |
|
||||
| `ragdoll` | Stickman | (none) |
|
||||
| `recover` | Stickman | (none) |
|
||||
| `explode_prop` | Prop | (none) — future |
|
||||
| `spawn_prop` | Stage | `type` (String) — future |
|
||||
|
||||
### 8.2. Rule Storage
|
||||
|
||||
Rules are stored in `SandboxStage._event_rules` and persist across mode toggles (Play ↔ Edit). They are **not** saved to disk in Phase 4 (deferred to Phase 5).
|
||||
|
||||
### 8.3. Rule Evaluation
|
||||
|
||||
Rules are evaluated **in order** when an event occurs. If a rule's trigger matches the event, its actions are executed.
|
||||
|
||||
---
|
||||
|
||||
## 9. What's NOT in Phase 4
|
||||
|
||||
| Feature | Why Excluded |
|
||||
| ----------------------------------------------------------- | -------------------------------------------------- |
|
||||
| "When Stickman A arrives → Stickman A speaks" | This is just a sequential queue action (Phase 3a). |
|
||||
| "When Stickman A finishes walking → Stickman A walks again" | Same as above. |
|
||||
| Conditions (AND/OR logic) | Too complex for Phase 4; deferred to future. |
|
||||
| Variables / counters | Deferred to future. |
|
||||
| Save/Load rules to disk | Phase 5. |
|
||||
| Edit/Delete actions | Phase 3c. |
|
||||
| Stickman/Prop selector grids | Phase 3b. |
|
||||
|
||||
---
|
||||
|
||||
## 10. Acceptance Criteria
|
||||
|
||||
### 10.1. Cross-Stickman Events
|
||||
|
||||
- [ ] **"When..." option appears** in the action popup.
|
||||
- [ ] **Trigger sub-menu opens** when "When..." is clicked.
|
||||
- [ ] **Waypoint trigger works:** A arrives → B speaks.
|
||||
- [ ] **Action completion trigger works:** A finishes speaking → B walks.
|
||||
- [ ] **Speech completion trigger works:** A finishes speaking → B speaks.
|
||||
- [ ] **Multiple actions per rule work:** Trigger → B speaks AND C walks.
|
||||
|
||||
### 10.2. Cross-Object Events
|
||||
|
||||
- [ ] **Area trigger works:** A enters area → B speaks.
|
||||
- [ ] **Prop collision trigger works:** A hits crate → crate explodes.
|
||||
- [ ] **Prop reaction works:** Trigger → prop explodes (disappears + particles).
|
||||
|
||||
### 10.3. UI & Visuals
|
||||
|
||||
- [ ] **Rule label shows summary:** "When arrives → Speak" text appears.
|
||||
- [ ] **Delete icon works:** Click ✕ → rule removed.
|
||||
- [ ] **Clicking rule label opens edit popup:** Click label → popup re-opens.
|
||||
- [ ] **Rules persist across mode toggles:** Create rule → Play → Edit → rule still there.
|
||||
- [ ] **Rules are cleaned up** when source/target objects are deleted.
|
||||
|
||||
### 10.4. Backward Compatibility
|
||||
|
||||
- [ ] **Sequential actions still work:** Walk → Wait → Speak → Walk works.
|
||||
- [ ] **Existing queues unchanged:** Any Phase 3a scene loads and runs.
|
||||
|
||||
---
|
||||
|
||||
## 11. File Changes Summary
|
||||
|
||||
| File | Changes |
|
||||
| ----------------------------------- | ------------------------------------------------------------- |
|
||||
| `scripts/sandbox_stage.gd` | Add `_event_rules`, event evaluation, rule UI state machine. |
|
||||
| `scripts/stickman_rig.gd` | Emit `arrived`, `action_finished`, `speech_finished` signals. |
|
||||
| `scripts/stage_director_visuals.gd` | Draw rule lines, labels, and badges. |
|
||||
| `scripts/trigger_area.gd` | NEW: Placeable `Area2D` sensor. |
|
||||
| `scripts/prop_block.gd` | Emit `collided` signal. |
|
||||
|
||||
---
|
||||
Reference in New Issue
Block a user