Files
stickman/docs/archive/plans/PHASE_13_SPEECH_BUBBLES.md
T

7.5 KiB
Raw Blame History

Summary of Speech & Speech Bubble Features

The goal is to expand the existing single-bubble SpeechBubble system into a comic-book movie engine designed for young directors.

1. Data Contract & Theme Integration

  • Expanded Action Payload: Extend the speak action payload to support explicit visual parameters:
{
  "type": "speak",
  "text": "Look out for the [shake]MONSTER![/shake]",
  "duration": 2.5,
  "stop_current": false,
  "visual": {
    "bubble_style": "yell",
    "font_preset": "comic",
    "size_preset": "huge",
    "color": "#FF3333",
    "anim_mode": "typewriter"
  }
}
  • Theme Fallbacks: Route missing keys through sandbox_theme.json defaults \rightarrow Global Theme \rightarrow Godot ThemeDB.fallback_font.

2. Rich Text & Visual Styles

  • RichTextLabel Migration: Shift text rendering from raw draw_string() calls to an internal RichTextLabel child node to enable full BBCode support ([wave], [shake], bolding, inline colors).

  • Shape Presets (BubbleStyle):

  • Standard: Classic rounded rectangle + downward tail triangle.

  • Yell / Shout: Multi-pointed starburst polygon.

  • Thought: Arc/circle cluster cloud boundary + descending bubble chain dots.

  • Whisper: Semi-transparent fill with dashed border lines (draw_dashed_line()).

  • Comic SFX: Borderless, high-contrast banner box for sound effect popups ("BOOM!", "POW!").

3. Dynamic Text & Bubble Animations

  • Typewriter & Word Reveals: Animate visible_characters via Godot Tween for letter-by-letter or word-by-word reveals.
  • Elastic Entrances & Transitions: Scale bubble from 0 \rightarrow 1 using TRANS_ELASTIC on pop-in; morph bounding sizes with smooth squish-and-stretch tweens when swapping text lines back-to-back.
  • Word-Specific Shake & Wave: Support inline animated text effects wrapped in BBCode tags.

4. Advanced Layout & Stagger Stacking

  • Comic Stagger Stacking: Allow multiple speech lines to chain into vertical bubble stacks. The bottom bubble anchors to the stickman's head via the main tail, while higher bubbles stack upward connected by bridge geometry (draw_colored_polygon()).

  • Mirroring & Viewport Clamping: Keep X-scale counter-mirroring active (_sync_speech_bubble_mirror). Clamp bubble bounds inside get_viewport_rect() so bubbles flip tail anchors or offset position to remain on-screen.

5. Director UI Upgrades

  • Kid-Friendly Controls: Color swatch buttons, size toggles (Small, Medium, HUGE), font style pickers, and an emoji grid picker inside the Speak parameter dialog.

  • Text Highlight Formatting Bar: Selecting text in the dialogue input shows quick-action buttons (🫨 Shake, 🌊 Wave, 🔥 Bounce) that automatically inject BBCode tags.

  • Auto-Duration Calculator: Default duration automatically calculates based on word count (1.0\text{s base} + 0.2\text{s/word}).


Detailed Implementation Plan

Phase 1: Engine Migration & Data Foundation

Goal: Upgrade SpeechBubble to use RichTextLabel and expand data contracts without breaking existing scene functionality.

  1. Update Action Data Pipeline:
  • Update ActionRegistry and StageSceneIO to preserve the optional visual dictionary payload on speak actions.

  • Ensure StickmanRig.speak() parses both flat strings and full visual dictionaries.

  1. Refactor SpeechBubble Node Structure (scripts/stickman_speech_bubble.gd):
  • Add a child RichTextLabel node to SpeechBubble.

  • Set RichTextLabel.bbcode_enabled = true and configure autowrap.

  • Modify _draw(): Calculate background rectangle bounds dynamically using RichTextLabel.get_content_height() and text size metrics, then draw the background polygon/rect and tail under the text.

Phase 2: Animated Reveals & Line Transitions

Goal: Implement typewriter effects, word reveals, and smooth line-swapping transitions.

  1. Typewriter & Word Reveal Engine:
  • Add _play_typewriter(text: String, duration: float, mode: String) to SpeechBubble.
  • Use a Godot Tween targeting RichTextLabel.visible_characters from 0 to total character length over the target duration.
  • Implement word-by-word step incrementing by parsing space/punctuation indices in the input string.
  1. Line Swap & Elastic Transitions:
  • Update show_text(): If a bubble is already visible when a new speak command arrives:

  • Scale container down (1.0 \rightarrow 0.8) via EASE_IN tween.

  • Swap payload and recalculate bounds.

  • Scale container back out (0.8 \rightarrow 1.0) using TRANS_ELASTIC / EASE_OUT.

  • Add squish-and-stretch size morphing when text length changes between consecutive lines.

Phase 3: Polygon Shape Styles & Comic Geometry

Goal: Generate dynamic background shapes for distinct bubble styles.

  1. Shape Draw Functions:
  • _draw_standard_bubble(rect): Existing rounded rect + downward tail triangle.

  • _draw_yell_bubble(rect): Generate an outer jagged polygon by iterating around rect perimeter and alternating vertex radii with random/sine noise offsets.

  • _draw_thought_bubble(rect): Draw overlapping circles along the bounding box edges using draw_circle(), followed by 2–3 smaller descending circles pointing to origin.

  • _draw_whisper_bubble(rect): Draw semi-transparent background fill; outline using draw_dashed_line() around the perimeter.

  1. Viewport Boundary Protection:
  • Calculate global screen position of bubble rect in _process().
  • If top or side edges exit get_viewport_rect(), offset the bubble box downward/inward and flip tail geometry anchor accordingly.

Phase 4: Staggered Multi-Bubble Stacking

Goal: Support chained comic bubbles stacking upward from a single character.

  1. Stack Container Logic:
  • Extend SpeechBubble to manage an array of child BubbleItem records.
  • When a multi-line or stacked speech payload is received, instantiate child bubble slots.
  1. Stack Geometry & Bridge Rendering:
  • Anchor the bottom-most bubble to SPEECH_BUBBLE_OFFSET.

  • Position preceding bubbles vertically above it with vertical spacing gaps.

  • In _draw(), calculate bridge vertices between Bubble N bottom-center and Bubble N+1 top-center, drawing connecting polygons using draw_colored_polygon().

  • Restrict the downward head tail exclusively to the bottom bubble in the stack.

Phase 5: Director UI & Formatting Controls

Goal: Expose all visual styling tools to kids in the editor UI.

  1. Integrate Theme Controls into Speak Parameter Dialog:
  • Add ColorSwatchGrid popover hooked into theme colors.

  • Add SizeToggle segmented control (Small, Medium, HUGE) mapping to font scale metrics.

  • Add StylePicker icon buttons (Standard, Yell, Thought, Whisper).

  • Embed EmojiPicker grid widget.

  1. Implement Selection Highlight Formatting Bar:
  • Attach a floating mini-toolbar above the dialogue LineEdit / TextEdit field in the Speak dialog.
  • Detect text selection (get_selected_text()). When text is highlighted, show mini-buttons:
  • 🫨 Shake \rightarrow wraps selection in [shake rate=20.0 level=10.0]...[/shake]
  • 🌊 Wave \rightarrow wraps selection in [wave amp=50.0 freq=5.0]...[/wave]
  • 🔥 Bounce \rightarrow wraps selection in [bounce]...[/bounce]
  1. Auto-Duration & Stagger Helpers:
  • Add auto-duration calculation checkbox/toggle in dialog.
  • Add "+ Add Stacked Bubble" button in the speech dialog to split longer dialogue into chained stack items easily.