Files
stickman/plans/PHASE_3b_ASSET_GRID.md
ryan 1f91f3d2e5 Add headless regression tests for Phase 4b features
- Implement test for popup anchor behavior in rule-builder menus to ensure consistent anchor positioning during menu transitions.
- Create tests for stage logic, including mode transitions, toolbar visibility, and status bar updates.
- Add terrain drag-painting tests to verify correct block placement behavior and conflict handling.
- Introduce walk waypoint tests to check for arrival conditions and position stability after navigation.
2026-09-04 15:08:08 -04:00

18 KiB
Raw Permalink Blame History

Phase 3b: Asset Library — Stickman + Prop Selector Grids

1. Overview

Phase 3b adds a visual asset library to the Sandbox Stage Builder. Currently, placing a stickman always spawns the hard-coded test.stk figure, and props are limited to the palette buttons (Crate, Ball, Plank). This phase replaces those limitations with visual selector grids that let the user choose from all available assets.

2. Core Concept

┌─────────────────────────────────────────────────────────────────────┐
│ ASSET LIBRARY WORKFLOW                                              │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│ EDIT MODE                                                           │
│ ┌─────────────────────────────────────────────────────────────┐     │
│ │ User clicks "Stickman" palette button                       │     │
│ │ ↓                                                           │     │
│ │ Stickman Selector Grid opens (popup overlay)                │     │
│ │ ┌─────────────────────────────────────────────────────┐     │     │
│ │ │ Choose Your Stickman [×] Close                      │     │     │
│ │ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐                 │     │     │
│ │ │ │ 📷   │ │ 📷  │ │ 📷   │ │ 📷  │                 │     │     │
│ │ │ │ Bob  │ │ Sally│ │ John │ │ Joe  │                 │     │     │
│ │ │ └──────┘ └──────┘ └──────┘ └──────┘                 │     │     │
│ │ │ ┌──────┐ ┌──────┐                                   │     │     │
│ │ │ │ 📷  │ │ 📷   │                                   │     │     │
│ │ │ │ Sue  │ │ Tom  │                                   │     │     │
│ │ │ └──────┘ └──────┘                                   │     │     │
│ │ │ [Prev] Page 1/2 [Next] [Browse...] [Refresh]        │     │     │
│ │ └─────────────────────────────────────────────────────┘     │     │
│ │ ↓                                                           │     │
│ │ User clicks a cell → grid closes                            │     │
│ │ ↓                                                           │     │
│ │ Click the stage → spawns the selected stickman              │     │
│ └─────────────────────────────────────────────────────────────┘     │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

3. What's Being Replaced

Before After
"Stickman" palette button spawns test.stk "Stickman" palette button opens the selector grid
Separate "Crate", "Ball", "Plank" buttons Single "Prop" button opens the prop selector grid
No visual preview Thumbnail preview in each grid cell
No choice Choose from all available assets
Hard-coded file path Dynamic library from scanned files

4. Feature Breakdown

4.1. Stickman Selector Grid

Feature Description
Source Scans res://stickmen/ for .stk files
Thumbnails Renders each stickman to a texture (cached to user://thumbnails/)
Display Grid cells: thumbnail + stickman_name (or filename if no name)
Pagination 12 items per page (3 rows × 4 columns) with Prev/Next buttons
Selection Click a cell → selected stickman is cached as the default
Browse "Browse..." button opens a FileDialog to select a .stk from anywhere
Refresh "Refresh" button rescans the stickmen/ folder
Empty state "No stickmen found! Create one in the editor first."

4.2. Prop Selector Grid

Feature Description
Source Built-in prop templates (Crate, Ball, Plank, Triangle)
Thumbnails Renders each prop with its material/color
Display Grid cells: thumbnail + prop name + material badge
Pagination 12 items per page with Prev/Next buttons
Selection Click a cell → selected prop is cached as the default
Future Custom props (.prp files) will appear here

4.3. Single Palette Buttons

Before After
"Stickman" (hard-coded) "Stickman" (opens grid)
"Crate" (hard-coded) Removed
"Ball" (hard-coded) Removed
"Plank" (hard-coded) Removed
(None) "Prop" (opens prop grid)

5. Visual Design

5.1. Grid Cell Layout

┌─────────────────────────────────────┐
│ ┌─────────────────────────────┐     │
│ │                             │     │
│ │ [THUMBNAIL]                 │     │ ← 150×150 px preview
│ │                             │     │
│ └─────────────────────────────┘     │
│                                     │
│ ┌─────────────────────────────┐     │
│ │ Bob                         │     │ ← Name (bold, centered)
│ │ 🪵 Wood                      │     │ ← Material badge (props only)
│ └─────────────────────────────┘     │
└─────────────────────────────────────┘

Cell size: ~160×220 px (thumbnail 150×150, name area 60px)

5.2. Grid Popup Layout

┌─────────────────────────────────────────────────────────────────────────┐
│ Choose Your Stickman [×] Close                                          │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐                                     │
│ │ 📷  │  │ 📷  │ │ 📷   │ │ 📷  │                                     │
│ │ Bob  │ │Sally │ │ John │ │ Joe  │                                     │
│ └──────┘ └──────┘ └──────┘ └──────┘                                     │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐                                     │
│ │ 📷  │  │ 📷  │ │ 📷  │  │ 📷  │                                     │
│ │ Sue  │ │ Tom  │ │Alex  │ │Jess  │                                     │
│ └──────┘ └──────┘ └──────┘ └──────┘                                     │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐                                     │
│ │ 📷  │ │ 📷   │ │ 📷   │ │ 📷  │                                     │
│ │Sam   │ │Ella  │ │Max   │ │Mia   │                                     │
│ └──────┘ └──────┘ └──────┘ └──────┘                                     │
│                                                                         │
│ [← Prev] Page 1/3 [Next →] [Browse...] [Refresh]                        │
│                                                                         │
│ Selected: Bob                                                           │
└─────────────────────────────────────────────────────────────────────────┘

5.3. Visual States

State Appearance
Default cell Light background, subtle border
Hover Border highlight, slight scale (1.05)
Selected Blue/cyan border, checkmark overlay
Loading thumbnail Spinner or placeholder icon
Empty cell "No preview available" placeholder

6. Data Flow

6.1. Stickman Library Indexer

# stickman_library.gd (NEW)
class_name StickmanLibrary
extends RefCounted

# Scans res://stickmen/*.stk
# Returns Array[Dictionary] with:
#   {
#       "path": "res://stickmen/bob.stk",
#       "name": "Bob",
#       "thumbnail": Texture2D,
#       "data": Dictionary  # parsed .stk data (optional)
#   }

6.2. Prop Library Registry

# prop_library.gd (NEW)
class_name PropLibrary
extends RefCounted

# Built-in prop templates:
#   - Crate (Wood)
#   - Ball (Rubber)
#   - Plank (Metal)
#   - Triangle (Cardboard)

# Returns Array[Dictionary] with:
#   {
#       "id": "crate",
#       "name": "Crate",
#       "factory": Callable (returns shape payload),
#       "material_preset": PropBlock.MaterialPreset.WOOD,
#       "thumbnail": Texture2D
#   }

6.3. Thumbnail Generation

Stickman Thumbnails:

  • Parse the .stk file to get body_parts and part_order.
  • Create a temporary SubViewport (200×200 px).
  • Render the stickman using a simplified version of WholeStickmanPreview logic.
  • Capture the viewport as a Texture2D.
  • Cache to user://thumbnails/stickmen/.png.

Prop Thumbnails:

  • Instantiate a temporary PropBlock in a SubViewport.
  • Apply the material preset and geometry.
  • Capture the viewport as a Texture2D.
  • Cache to user://thumbnails/props/.png.

Caching Strategy:

  • Thumbnails are generated once per file and cached to disk.
  • On subsequent runs, load the cached thumbnail if it exists and the source file hasn't been modified.
  • If the source file is modified, regenerate the thumbnail.

7. UI Integration

7.1. Palette Button Changes

Button Behavior

  • "Stickman" Opens the Stickman Selector Grid
  • "Prop" Opens the Prop Selector Grid

7.2. Selected Asset Persistence

  • The last selected stickman is stored in StageSpawner.selected_stickman_path.
  • The last selected prop is stored in StageSpawner.selected_prop_id.
  • These persist across mode toggles and scene reloads (in memory only — no disk save in Phase 3b).

7.3. Placement Flow

User clicks "Stickman" palette button
    ↓
Stickman Selector Grid opens
    ↓
User clicks a stickman cell
    ↓
Grid closes → selected stickman is cached
    ↓
Stage enters placement mode (ghost appears)
    ↓
User clicks the stage → spawns the selected stickman

8. File Structure

File Purpose
res://scripts/stickman_library.gd Scans .stk files, manages thumbnails
res://scripts/prop_library.gd Registry of prop templates
res://scripts/asset_selector.gd Grid UI controller (shared between stickmen and props)
res://scenes/asset_selector.tscn Grid popup scene
res://scripts/thumbnails/stickman_thumbnail.gd Renders stickman to texture
res://scripts/thumbnails/prop_thumbnail.gd Renders prop to texture
res://user://thumbnails/ Cached thumbnails (generated at runtime)

9. Acceptance Criteria

9.1. Stickman Selector Grid

  • Clicking "Stickman" palette button opens the grid.
  • Grid displays all .stk files in res://stickmen/.
  • Each cell shows a thumbnail preview of the stickman.
  • Each cell shows the stickman's stickman_name (or filename if no name).
  • Clicking a cell selects that stickman and closes the grid.
  • The selected stickman persists for future placements.
  • Pagination works when more than 12 stickmen exist.
  • "Browse..." button opens a FileDialog to select any .stk.
  • "Refresh" button rescans the stickmen/ folder.
  • If no .stk files exist, shows "No stickmen found! Create one in the editor first."
  • If only one .stk exists, the grid is skipped and the stickman is selected directly.
  • Thumbnails are cached to user://thumbnails/ and reused.
  • Modified .stk files regenerate their thumbnails.

9.2. Prop Selector Grid

  • Clicking "Prop" palette button opens the grid.
  • Grid displays all built-in prop templates.
  • Each cell shows a thumbnail preview of the prop.
  • Each cell shows the prop name and material badge.
  • Clicking a cell selects that prop and closes the grid.
  • The selected prop persists for future placements.
  • Pagination works when more than 12 props exist.
  • Thumbnails are cached to user://thumbnails/props/.

9.3. Palette Integration

  • The old "Crate", "Ball", and "Plank" buttons are removed.
  • A single "Prop" button replaces them.
  • The "Stickman" button now opens the grid (instead of spawning test.stk).

9.4. Performance

  • Scanning 50+ .stk files does not stall the UI.
  • Thumbnail generation is non-blocking (or uses a loading state).
  • Grid opens and paginates smoothly.

10. Implementation Order

Step Task Dependencies
1 Create stickman_library.gd (file scanner + entry model) None
2 Create stickman_thumbnail.gd (renders stickman to texture) Step 1
3 Create asset_selector.gd / asset_selector.tscn (grid UI) Steps 1-2
4 Integrate selector with "Stickman" palette button Step 3
5 Create prop_library.gd (built-in prop registry) None
6 Create prop_thumbnail.gd (renders prop to texture) Step 5
7 Integrate selector with "Prop" palette button Steps 5-6
8 Remove old "Crate", "Ball", "Plank" buttons Step 7
9 Implement thumbnail caching Steps 2, 6

11. Edge Cases

Edge Case Handling
No .stk files exist Show "No stickmen found! Create one in the editor first."
Only one .stk exists Skip the grid, select it directly
Thumbnail generation fails Show placeholder icon + regenerate on next run
File is corrupted/invalid Skip the file, log a warning
Stickman has no name Use the filename (without .stk)
Many files (50+) Pagination keeps the UI responsive
Grid size changes Rebuild the grid layout on resize
Selected file is deleted Reselect the first available file (or show empty state)

12. Summary

Before After
Hard-coded test.stk Visual grid of all .stk files
Separate Crate/Ball/Plank buttons Single "Prop" button with visual grid
No preview Thumbnail preview in every cell
No choice Choose from all available assets
No caching Thumbnails cached to user://

This is the final piece connecting the Stickman Editor to the Sandbox Stage. Users can now create stickmen in the editor, save them as .stk, and pick them from the grid when placing actors on the stage.