Files
stickman/specs/speech_style_toolbar_refinements.md
T
ryan 6666173c4f Implement speech style toolbar live-edit refinements and whole speech show controls
- Added a new specification for the speech style toolbar live-edit, detailing immediate style application, scoped effect demonstration, and hover feedback.
- Introduced refinements to the speech style toolbar, including improved chooser sizing, exclusive stage editing during speech composition, and removal of redundant controls.
- Documented new stage controls for managing how the whole speech shows, including options for bubble arrangement, word appearance, and bubble motion.
- Created a new log file for speech padding syntax to track engine versioning.
2026-10-03 14:49:22 -04:00

89 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Speech style toolbar refinements
Status: **Approved; implementation complete, editor verification pending** (2026-09-28). This follow-up refines `specs/speech_style_toolbar.md` based on editor review. It supersedes that spec's toolbar bubble/target status, Whole bubble and Replay controls, chooser sizing, and stage input-routing details. Speech data, provisional style commits, token selection, and Save speech semantics remain as previously specified.
## 1. Goals
- Keep the selected bubble and character visible while choosing a style.
- Make the active style category and chooser heading easy to read.
- Let the chooser use only the space its content needs, while remaining scrollable on small viewports.
- Treat speech composition as an exclusive stage-editing task: bubble interactions remain available, but other scene objects cannot be selected or changed until the composer is saved or canceled.
- Use a blank-stage click to return to whole-bubble styling without a separate button or target-status label.
- Present replay as a preview of the whole speech sequence.
## 2. Recommended architecture
Keep the code-built `SpeechStyleToolbar` under the stage's existing `UI` CanvasLayer. It remains a transient view, and `SpeechComposer` remains the authority for draft text, style targets, provisional edits, replay, and Save speech. `SandboxStage` remains the single owner of pointer routing and toolbar placement.
Do not introduce a second popup implementation or change the speech payload. The current toolbar already owns one reusable chooser and the composer already owns full-sequence replay. This change refines those controls and makes stage input exclusive while the composer is open.
## 3. Toolbar and chooser appearance
### 3.1 Main toolbar
- Add a light-blue ribbon heading **Speech Style** above or integrated with the category row, using the same visual treatment as the inspector's section ribbons.
- Keep **Frame**, **Letters**, and **Effects** as the primary category buttons. Use readable text (about 20–22 px) and large hit targets (at least 56 px high).
- While a chooser is open, its category button is visibly selected with a high-contrast fill and bright outline. Only one category can be active at a time. Clear the active state when the chooser closes.
- Remove the **Bubble N of N · “word”** status, the **Whole bubble** button, and **Replay** from this toolbar. Do not replace them with any target-status text.
- The selected bubble's stage outline and the selected token's stage highlight remain the selection feedback. With no token highlight, Letters applies to the whole bubble.
### 3.2 Chooser sizing, heading, and footer
- Keep one chooser surface open at a time and position it beside the selected bubble when space permits. Otherwise place it above or below the bubble, keeping the bubble frame visible and staying within the usable stage bounds.
- Size the chooser to its content. In particular, the **Frame** chooser should end shortly after its five frame cards and footer; it must not stretch down to the stage or screen bottom and leave a large empty area.
- Give the chooser's category-specific heading (for example, **Choose a frame**) a light ribbon treatment matching the inspector's section headings.
- Do not give the `ScrollContainer` a minimum height based on all remaining stage space. Compute the natural chooser height, then cap it to the available viewport height. Scroll only when the chooser's content exceeds that cap; the chooser heading and footer stay visible while content scrolls.
- Make **Cancel** and **Done** at least 60 px high, center them horizontally in the footer, and leave a clear gap between them. Preserve their existing behavior: Cancel discards provisional style changes; Done applies them to the composer draft.
- Preserve the current larger frame cards, sample previews, selected-choice borders, font/size previews, and color swatches. This refinement does not change choice values or token-style semantics.
## 4. Whole-bubble targeting by stage click
- Remove the toolbar's explicit **Whole bubble** control. A primary click/tap anywhere within the usable stage that hits no speech bubble clears the current token target and returns Letters to whole-bubble scope.
- Keep the currently selected bubble selected and outlined when this happens. Clear its token highlight. If no token was selected, the click does not change the selected bubble.
- A click on another speech bubble selects that bubble and clears the old token target, as it does now. A click on rendered text continues to select the tapped word or punctuation token. Overlapping speech bubbles continue to use the existing temporary bubble picker.
- Apply the outside-click behavior to the stage area only. Clicks on the composer, toolbar, chooser, or token picker continue to belong to those controls and must not clear the target.
- Resolve a blank-stage click on release, after checking the existing drag threshold. A drag or camera-navigation gesture must not be mistaken for a target-clearing click.
## 5. Exclusive stage editing while speech is open
While `SpeechComposer.visible` is true, speech composition owns edits on the usable stage. The stage input gate must run before normal scene selection, gizmo, prop/terrain placement, director, and context-menu handling.
- **Allowed speech edits:** select a speech bubble, select one of its text tokens, move a speech bubble using the existing bubble drag gesture, use the overlapping-bubble picker, and use the existing explicit speech-placement mode to place the speech group or selected speech bubble.
- **Outside-bubble stage click:** clear the word target, keep the selected speech bubble, and consume the event. This applies even when the pointer is visually over a character or prop; do not select, move, edit, place, or open a context menu for that other object.
- **Other stage interactions:** block them until Save speech or Cancel closes the composer. This includes character/prop selection and dragging, terrain editing, generic placement, and director/rule actions.
- **View navigation:** retain camera-only navigation (middle-button pan, wheel zoom, pinch zoom, and trackpad pan). These gestures must not select or edit scene objects or clear a token target as if they were clicks.
- **Composer exit:** Save speech commits through the existing queue/rule path and restores normal stage input. Cancel discards the composer draft through the existing cancellation path and restores normal stage input.
- **Chooser dismissal:** a click outside the chooser still cancels its provisional visual preview, except tapping Save speech completes the chooser as Done before the normal save flow. If the same click lands on the stage, then apply the stage bubble/outside-bubble routing above.
The gate must be limited to the usable stage rectangle and must not block input to the composer or overlay controls. Speech bubble dragging and speech placement remain available because they edit the current speech draft, not unrelated scene objects.
## 6. Full-sequence preview
- Remove the toolbar's Replay button, `replay_requested` signal, and replay hit-test exception.
- Use the existing composer replay control as the single replay entry point. Rename it **Preview speech** and place it beside **Save speech** in the composer footer/action area, with responsive wrapping at narrow widths.
- Keep the existing `SpeechComposer.replay_preview_once()` behavior: play the complete speech sequence once, including configured bubble transitions, effects, and the one-second blank hold. Do not add a per-bubble replay behavior or alter saved duration/sequence data.
## 7. Implementation ownership and order
1. **`scripts/speech_style_toolbar.gd`** — build the Speech Style ribbon, category active states, category chooser ribbon, content-sized/max-capped chooser layout, centered large footer buttons; remove target status, Whole bubble button, and Replay UI/signal.
2. **`scripts/speech_composer.gd`** — rename and relocate the existing full-sequence replay control next to Save speech; retain its signal and replay implementation.
3. **`scripts/sandbox_stage.gd`** — add speech-composer stage input gating and blank-stage click resolution. Preserve bubble/token hit routing, overlap picking, bubble drag, explicit speech placement, and view-only camera navigation; prevent all normal non-speech object interactions until composer close.
4. **`sandbox_theme.json` / theme accessors as needed** — add or reuse local theme values for ribbon colors, category selection, heading sizes, and button sizing. Do not change the global theme or serialize UI state.
No new `.scene` fields, speech payload fields, or action IDs are introduced.
## 8. Acceptance checks
- The Frame chooser ends after its cards and footer without a screen-height blank area. Letters and Effects also size to content; only overflowing content scrolls, with heading and footer kept visible.
- The main toolbar and chooser headings have distinct, readable light ribbons. Frame/Letters/Effects clearly show which chooser is open. Text does not show a bubble count or token/whole-bubble status.
- Cancel and Done are large, horizontally centered, and visibly separated. Cancel/Done preserve provisional-preview semantics.
- Selecting a word and then clicking empty stage, the character, or a prop clears the word highlight and returns to whole-bubble scope while retaining the bubble outline. The character/prop does not become selected or move.
- Clicking another speech bubble selects it and clears the token target; clicking its text selects a token; overlapping clicks keep the bubble picker. When a drag starts inside overlapping frames, move the smallest bubble under the pointer; if frames are the same size, move the topmost one.
- During speech composition, generic stage object selection/editing, placement, and context actions do not run. Save speech and Cancel both restore ordinary stage interaction. Speech-placement mode and camera-only pan/zoom remain available.
- Exactly one **Preview speech** control remains in the composer beside Save speech. It previews the full sequence once and preserves the one-second blank hold.
- Existing save/load payloads, draft recovery, and queue/rule commit behavior are unchanged.
## 9. Risks and boundaries
The main risk is input routing order: RichTextLabel metadata clicks and the stage's deferred bubble click resolver must still select tokens before the exclusive stage gate consumes the release. The gate must distinguish click from drag and camera navigation, and must explicitly exempt speech placement. Chooser height must be measured from its content before applying the viewport cap so a scrolling child does not force the panel to fill the stage. These behaviors should be verified in the Godot editor at normal and narrow window sizes before the refinement is considered complete.