418 lines
25 KiB
Markdown
418 lines
25 KiB
Markdown
# Stickman Studio
|
||
|
||
A Godot 4.4 editor tool for creating and assembling stick figures. Stickman Studio lets you draw individual body-part shapes, edit vertices, assemble them into a whole stickman, and save/load your figure to a JSON file (`.stk`) for later use or animation scripting.
|
||
|
||
## Overview
|
||
|
||
The editor is organized as **11 sub-windows** in a 3-column layout:
|
||
|
||
- **Left column (5)** — Head, Left Upper Arm, Left Lower Arm, Left Upper Leg, Left Lower Leg
|
||
- **Center column (5)** — Torso, Right Upper Arm, Right Lower Arm, Right Upper Leg, Right Lower Leg
|
||
- **Right column (1)** — **Whole Stickman** preview
|
||
|
||
The editor is driven by three menus: **File** (Save / Load / Clear), **Edit** (Configure Grid... / Snap to Grid), and **View** (Reset Views).
|
||
|
||
Each body-part panel is an independent vector drawing surface with per-panel zoom **and panning (middle-mouse drag)**. A configurable background grid helps align vertices, and snap-to-grid can be enabled for both vertex dragging and whole-figure assembly. **Each panel supports multiple shapes** with Z-ordering controls (Send Back / Bring Forward) and shape-level Copy/Paste and Mirror operations. The Whole Stickman panel assembles every part into one figure — treating all shapes in a panel as a single unit — and lets you reposition, rotate, and scale each part, reorder the parts (Z-order), and mirror them.
|
||
|
||
Drawing surfaces **clip** their content to the panel bounds: shapes and parts no longer render outside a panel's borders when dragged or panned. A selected shape can be **dragged to reposition** it within its panel.
|
||
|
||
## Requirements
|
||
|
||
| Item | Version |
|
||
|---|---|
|
||
| Engine | Godot 4.4 or newer |
|
||
| Addon | Scalable Vector Shapes 2D (`addons/curved_lines_2d/`) |
|
||
|
||
> The legacy `stick.tscn` scene (a rigged walk animation using `Skeleton2D` + IK) remains in the project root for reference but is **no longer the main scene**.
|
||
|
||
## Running the project
|
||
|
||
No CLI build, test, or lint commands are used. Run the project from the Godot editor:
|
||
|
||
1. Open the project folder in **Godot 4.4**.
|
||
2. Press **F5**, or open and run `res://scenes/stickman_editor.tscn`.
|
||
|
||
The main scene is configured as `run/main_scene="res://scenes/stickman_editor.tscn"` in `project.godot`.
|
||
|
||
## Quick Start
|
||
|
||
### 1. Create a body part
|
||
|
||
1. Locate one of the 10 body-part panels (e.g. **Head**).
|
||
2. **Right-click** anywhere inside its drawing area to open the context menu.
|
||
3. Choose a starter shape:
|
||
- **Line** — a 120 px horizontal segment (2 vertices, open shape).
|
||
- **Rectangle** — a 100 × 60 px rectangle (4 vertices, closed shape).
|
||
- **Circle** — a 12-segment polygon (12 vertices, closed shape, radius 40).
|
||
|
||
The shape draws immediately and syncs to the Whole Stickman panel.
|
||
|
||
Rendering behavior:
|
||
|
||
- **Closed shapes** (`closed: true`) fill their interior with the chosen color (`draw_colored_polygon`) and draw a 2 px outline.
|
||
- **Open shapes** (`closed: false`) render as an outline-only segment with no fill.
|
||
|
||
Body-part panels expand vertically to fill their column height.
|
||
|
||
### 2. Edit vertices
|
||
|
||
Each panel supports vertex-level editing:
|
||
|
||
1. **Select a shape** — **Left-click** anywhere inside a shape to select it. The outline turns white.
|
||
2. **Create a vertex** — With a shape selected, **right-click** on its outline and choose "Create Point". A new vertex (shown as a hollow rectangle) is added at the nearest edge midpoint.
|
||
3. **Drag vertices** — **Left-click** on any vertex handle (filled circle = original, hollow rectangle = user-created) and drag to reshape. The shape conforms in real time. Release to apply. With **Snap to Grid** enabled, the dragged vertex jumps to the nearest grid intersection.
|
||
4. **Delete a vertex** — **Right-click** on a vertex handle and choose **Remove Point** (see *Deleting* below).
|
||
5. **Deselect** — Left-click outside the shape or select a different panel. Only one shape is selected at a time.
|
||
|
||
**Move a whole shape (Phase 5):**
|
||
1. **Left-click** a shape **not on a vertex handle** and drag to reposition the entire shape within the panel.
|
||
2. Release to commit. All vertices translate together; the shape's Z-order is unchanged.
|
||
3. With **Snap to Grid** enabled, the dragged shape jumps to the nearest grid intersection on release.
|
||
|
||
### 3. Zoom & Pan
|
||
|
||
Scroll the mouse wheel inside any body-part panel or the Whole Stickman preview to zoom. Pan the view with the middle-mouse button:
|
||
|
||
- **Wheel up** — zoom in by 10%
|
||
- **Wheel down** — zoom out by 10%
|
||
- **Middle-mouse drag** — pan the view in any direction
|
||
- **Range** — 30% (minimum) to 300% (maximum)
|
||
- Vertex handles remain visible at all zoom levels.
|
||
- Each panel has independent zoom and pan offset.
|
||
- Panning takes priority over vertex dragging (middle-mouse press cancels any in-progress drag).
|
||
- **Content is clipped to the panel bounds (Phase 5)** — shapes, grid, and gizmos cannot render outside a panel's drawing area, even when panned or dragged beyond its edge. This keeps each panel self-contained.
|
||
- Use **View → Reset Views** to restore all panels to 100% zoom and the origin pan offset.
|
||
|
||
### 4. Assemble a stickman
|
||
|
||
1. Create shapes for every part you want in the figure.
|
||
2. In the **Whole Stickman** panel, **drag any part** to reposition it in the figure.
|
||
- Parts get a generous hit area and show a yellow highlight while being dragged.
|
||
- A short label (`H`, `T`, `LUA`, `RUA`, `LUL`, `RLL`, …) marks each part.
|
||
- Use the mouse wheel to zoom in/out and middle-mouse to pan for precise positioning.
|
||
- With **Snap to Grid** enabled, the mouse pointer snaps to the nearest grid intersection and the part follows.
|
||
3. Optionally type a name in the **Stickman Name** field at the top.
|
||
4. **Right-click a selected part (Phase 5)** to reorder or mirror it:
|
||
- **Send Back / Bring Forward** — change the part's draw order in the preview.
|
||
- **Mirror X / Mirror Y** — flip the part around its bounding-box center.
|
||
|
||
### 5. Grid & Panning
|
||
|
||
All 10 body-part panels and the Whole Stickman preview share a global background grid (default cell size **15 px**, Phase 5; previously 5 px):
|
||
|
||
1. Click **Edit → Configure Grid...** and set the grid size.
|
||
- **SpinBox** accepts 1–100 px per cell.
|
||
- The setting is applied to every panel simultaneously and persists to `user://settings.json`.
|
||
2. Toggle **Edit → Snap to Grid** to enable snapping (Phase 5: the checkable menu item now reliably shows its ✓ checkmark when toggled):
|
||
- On **vertices** — while dragging a vertex handle, it jumps to the nearest grid intersection.
|
||
- On **assembly** — while dragging a part in the Whole Stickman preview, the pointer snaps and the part follows.
|
||
- On **shape drag** — while dragging a whole shape (Phase 5), it snaps on release.
|
||
- Existing vertices are *not* retroactively snapped; snapping only applies to new drags.
|
||
3. **Pan** — hold the **middle-mouse button** and drag anywhere in a panel to pan the view.
|
||
- Panning uses the same transform as zoom, and each panel keeps an independent offset.
|
||
- **View → Reset Views** restores 100% zoom and the origin offset on all panels.
|
||
4. Grid lines are drawn behind shapes and scale with pan/zoom, so they stay aligned to world coordinates.
|
||
|
||
### 6. Changing Colors
|
||
|
||
Colors are easy to change on any existing shape:
|
||
|
||
1. **Right-click** on a shape (either selected or with the cursor over it) and choose **Color...**.
|
||
2. A **ColorPicker** popup appears with the shape's current color pre-loaded.
|
||
3. Adjust the color — the shape updates live as a preview.
|
||
4. Click **OK** to commit the change or **Cancel** to revert to the original color.
|
||
|
||
The chosen color is stored in the shape's `color` field and is saved/loaded with the `.stk` file.
|
||
|
||
### 7. Deleting
|
||
|
||
Two levels of deletion are available:
|
||
|
||
**Delete an entire shape:**
|
||
1. **Right-click** on a shape (either selected or with the cursor over it) and choose **Delete**.
|
||
- Delete is only offered when a shape exists and the mouse is over it.
|
||
2. The shape is removed from the panel and the Whole Stickman preview.
|
||
|
||
**Remove a single vertex:**
|
||
1. **Right-click** on a vertex handle and choose **Remove Point**.
|
||
2. If 2 vertices remain, the shape becomes an open **line** (`closed = false`).
|
||
3. If 1 vertex or fewer remains, the entire shape is cleared.
|
||
|
||
### 8. Multiple Shapes & Z-Ordering
|
||
|
||
Each body-part panel can contain **more than one shape**. New shapes are created via the standard right-click context menu and are drawn on top of existing shapes. Shapes are drawn in Z-order (last in the list = frontmost).
|
||
|
||
**Z-ordering controls:**
|
||
|
||
- **Right-click** on a shape and choose **Send Back** to move it one step behind (earlier in draw order).
|
||
- **Right-click** on a shape and choose **Bring Forward** to move it one step ahead (later in draw order).
|
||
|
||
Z-order is preserved in the `.stk` save file (shapes are stored in draw order within the `shapes` array).
|
||
|
||
Only one shape within a panel can be selected at a time for vertex editing. Left-click a shape to select it; right-click also selects the shape under the mouse for context menu operations.
|
||
|
||
**Shape Copy & Paste (Phase 5):**
|
||
1. **Right-click** on a shape and choose **Copy** to place a deep copy of the shape on the editor-wide clipboard.
|
||
2. **Right-click** (on empty space or a shape) and choose **Paste** to insert the clipboard shape at the click position.
|
||
- Paste only appears while the clipboard is populated.
|
||
- The clipboard **persists after pasting** and is shared across **all 10 body-part panels** — a shape copied in one panel can be pasted into any other.
|
||
- The pasted shape becomes the newly selected (topmost) shape.
|
||
- **Copy → Clear → Paste** semantics: the clipboard survives figure clear.
|
||
|
||
**Shape Mirroring (Phase 5):**
|
||
1. **Right-click** on a selected shape and choose **Mirror X** or **Mirror Y**.
|
||
2. The shape's vertices are mirrored around the shape's bounding-box center.
|
||
3. Mirroring recomputes the `points` array in place — no extra fields are stored; the result is saved as normal vertex data.
|
||
|
||
### 9. Whole Stickman Manipulation (Selection, Rotation, Scale)
|
||
|
||
The Whole Stickman preview treats all shapes in a body-part panel as **one combined object**. Each part can be independently translated, rotated, and scaled.
|
||
|
||
**Selection:**
|
||
- **Left-click** on any part in the Whole Stickman preview to select it.
|
||
- A **white bounding box** appears around the selected part, along with manipulation gizmos.
|
||
- Click empty space to deselect.
|
||
|
||
**Translation:**
|
||
- **Left-click and drag** a selected part to reposition it. Snap-to-grid applies to the pointer position when enabled.
|
||
|
||
**Rotation:**
|
||
- When a part is selected, a **filled circle** appears centered below the bounding box.
|
||
- **Click and drag** the rotation circle to rotate the part around its center.
|
||
- Hold **Ctrl** while rotating to snap to **15-degree increments** (relative to the original 0° position).
|
||
- Rotation is **absolute**: 0° always means the original orientation the object was created with.
|
||
- The accumulated rotation value is saved in the `.stk` file.
|
||
|
||
**Scale:**
|
||
- When a part is selected, **cross/plus markers** appear at all four corners of the bounding box.
|
||
- **Click and drag** any corner cross to freely scale the part.
|
||
- Hold **Ctrl** while scaling to **lock the aspect ratio** (scale uniformly).
|
||
- Grid snapping snaps the corner position to the nearest grid intersection.
|
||
- Scale is **relative to the created size**: (1.0, 1.0) = original size.
|
||
- The scale value is saved in the `.stk` file. Scale may be **negative** for mirrored parts.
|
||
- **Part mirroring (Phase 5)** — right-click a selected part and choose **Mirror X** or **Mirror Y** to mirror it around its bounding-box center. This is implemented by negating the part's scale factor along the chosen axis (no vertex data is changed).
|
||
|
||
**Part Z-ordering (Phase 5):**
|
||
- Right-click a selected part and choose **Send Back** or **Bring Forward** to move it one step within the preview's draw order.
|
||
- Selection respects Z-order: hit-testing runs **front-to-back**, so the frontmost part under the pointer is selected.
|
||
- Part Z-order is saved in the `.stk` file as the top-level `part_order` array.
|
||
|
||
### 10. Save
|
||
|
||
1. Click **File → Save**.
|
||
2. Choose a location and name. The default extension is `.stk` (appended automatically if omitted).
|
||
3. Click **Save**. The figure is written as JSON.
|
||
|
||
### 11. Load
|
||
|
||
1. Click **File → Load**.
|
||
2. Select a `.stk` file.
|
||
3. On success, all body-part panels and the Whole Stickman preview are populated. On failure, an error dialog reports the problem (missing file, parse error, or unsupported version).
|
||
|
||
> v1.0, v1.1, and v1.2 files are automatically migrated to v1.3 on load (v1.0/v1.1 single shapes wrapped in a `shapes` array, rotation defaults to 0, scale defaults to (1,1); files without `part_order` fall back to the default part order).
|
||
|
||
### 12. Clear
|
||
|
||
1. Click **File → Clear**.
|
||
2. A confirmation dialog warns that the current stickman will be cleared.
|
||
3. Confirm to reset all panels and the preview (zoom resets to 100%, pan offset to origin).
|
||
|
||
## File format (`.stk`)
|
||
|
||
Files are UTF-8 JSON, pretty-printed with tab indentation. The format is versioned and designed to remain **backward/forward compatible** — new fields can be added without breaking older files.
|
||
|
||
```json
|
||
{
|
||
"version": "1.3",
|
||
"stickman_name": "Bob",
|
||
"part_order": [
|
||
"head",
|
||
"torso",
|
||
"left_upper_arm",
|
||
"left_lower_arm",
|
||
"right_upper_arm",
|
||
"right_lower_arm",
|
||
"left_upper_leg",
|
||
"left_lower_leg",
|
||
"right_upper_leg",
|
||
"right_lower_leg"
|
||
],
|
||
"body_parts": {
|
||
"head": {
|
||
"shapes": [
|
||
{
|
||
"shape_type": "circle",
|
||
"closed": true,
|
||
"points": [
|
||
{ "x": 120, "y": 40 },
|
||
{ "x": 124, "y": 39 }
|
||
],
|
||
"color": "#000000",
|
||
"vertex_flags": [0, 0, 1, 0]
|
||
}
|
||
],
|
||
"position": { "x": 150, "y": 40 },
|
||
"rotation": 0.0,
|
||
"scale": { "x": 1.0, "y": 1.0 }
|
||
}
|
||
},
|
||
"metadata": {
|
||
"created_at": "2026-08-05T12:00:00",
|
||
"modified_at": "2026-08-05T12:00:00"
|
||
}
|
||
}
|
||
```
|
||
|
||
### Root object
|
||
|
||
| Key | Type | Description |
|
||
|---|---|---|
|
||
| `version` | `string` | Format version. Currently `"1.3"`. Loading supports `"1.0"`–`"1.3"` (auto-migrated). |
|
||
| `stickman_name` | `string` | Optional display name for the figure. |
|
||
| `part_order` | `array[string]` | **Phase 5.** Render/Z-order of parts in the Whole Stickman preview, front-to-back semantics per array position (first = back, last = front). Absent on v1.0–v1.2 files; defaults to the internal part-key order when missing. |
|
||
| `body_parts` | `object` | Map of `body_part_name → shape` objects. Keyed by the 10 internal part names below. |
|
||
| `metadata.created_at` | `string` | Timestamp written on save. |
|
||
| `metadata.modified_at` | `string` | Timestamp written on save. |
|
||
|
||
### Part keys
|
||
|
||
`head`, `torso`, `left_upper_arm`, `left_lower_arm`, `right_upper_arm`, `right_lower_arm`, `left_upper_leg`, `left_lower_leg`, `right_upper_leg`, `right_lower_leg`
|
||
|
||
### Part object
|
||
|
||
Each body part is an object with the following keys:
|
||
|
||
| Key | Type | Description |
|
||
|---|---|---|
|
||
| `shapes` | `array` | Array of shape objects (see below). Draw order = array order (first = back, last = front). Wrapped as a single-element array when migrating v1.0/v1.1 files. |
|
||
| `position` | `object` | `{ "x": float, "y": float }` position of the part within the Whole Stickman preview. |
|
||
| `rotation` | `float` | Rotation in degrees. `0.0` = original orientation. Defaults to `0.0` for v1.0/v1.1 files. |
|
||
| `scale` | `object` | `{ "x": float, "y": float }` scale factors relative to created size. `1.0` = original size. May be **negative** (Phase 5) to represent mirroring along an axis. Defaults to `{ "x": 1.0, "y": 1.0 }` for older files. |
|
||
|
||
### Shape object
|
||
|
||
Each entry in the `shapes` array:
|
||
|
||
| Key | Type | Description |
|
||
|---|---|---|
|
||
| `shape_type` | `string` | `"line"`, `"rectangle"`, `"circle"`, or `""` (empty). Descriptive tag only — rendering uses `closed`. |
|
||
| `closed` | `bool` | Whether the polygon is closed (filled) or open (outline-only). |
|
||
| `points` | `array` | Array of `{ "x": float, "y": float }` vertex positions **local to the drawing area**. |
|
||
| `color` | `string` | Hex colour, e.g. `"#000000"`. Changeable in-app via right-click → **Color...** (Phase 3). |
|
||
| `vertex_flags` | `array[int]` | Same length as `points`. `0` = original vertex, `1` = user-created via "Create Point". Controls handle appearance. |
|
||
|
||
> On load, parts missing from the file fall back to built-in default preview positions. v1.0 files have `closed` inferred from `shape_type` and `vertex_flags` default to all zeros. v1.0/v1.1 files have their single shape wrapped in a `shapes` array and default `rotation`/`scale` applied. Files without `part_order` (v1.0–v1.2) use the default part-key order. Note that shape mirroring (Phase 5) rewrites the `points` array in place, so no new shape fields are required — the resulting vertices load identically across all supported versions.
|
||
|
||
## Settings file (`user://settings.json`)
|
||
|
||
Phase 3 introduces a global settings file stored in Godot's **user data** directory (`user://`), separate from the `.stk` figure files. It persists the grid configuration and is versioned for future extensibility:
|
||
|
||
```json
|
||
{
|
||
"version": "1.0",
|
||
"grid_size": 15,
|
||
"snap_to_grid": false
|
||
}
|
||
```
|
||
|
||
### Settings keys
|
||
|
||
| Key | Type | Default | Description |
|
||
|---|---|---|---|
|
||
| `version` | `string` | `"1.0"` | Settings file version (for future extensibility). |
|
||
| `grid_size` | `int` | `15` | Grid interval in pixels, applied equally to width and height. Default changed from `5` to `15` in Phase 5. Clamped to 1–100 on load. |
|
||
| `snap_to_grid` | `bool` | `false` | Whether snap-to-grid is active. |
|
||
|
||
Behavior:
|
||
- **Load** — read on editor startup; if the file is missing or fails to parse, defaults (`grid_size = 15`, `snap_to_grid = false`) are used silently (no error dialog).
|
||
- **Save** — written whenever the user changes the grid size or toggles Snap to Grid.
|
||
- **Scope** — global; all body-part panels and the Whole Stickman preview share the same grid size and snap setting.
|
||
- **Pan offsets are NOT persisted** — they reset on load, clear, and "Reset Views".
|
||
|
||
## Project structure
|
||
|
||
| Path | Purpose |
|
||
|---|---|
|
||
| `res://project.godot` | Engine config; sets main scene to the editor and enabled features. |
|
||
| `res://scenes/stickman_editor.tscn` | **Main scene** — editor layout, File/Edit/View menu bar, dialogs (`GridConfigDialog` + SpinBox), column containers (unique-name nodes). |
|
||
| `res://scenes/body_part_panel.tscn` | Reusable single body-part editor panel (title, drawing area, context menu, `ColorPickerPopup`); expands vertically in its column. |
|
||
| `res://scripts/stickman_editor.gd` | Editor controller — File/Edit/View menu actions, save/load/clear, JSON v1.3 serialization with multi-shape/rotation/scale and `part_order`, `settings.json` load/save, editor-wide shape clipboard (Copy/Paste across panels), broadcast of grid/snap settings to panels, Reset Views, populates panels, coordinates selection across panels. |
|
||
| `res://scripts/body_part_panel.gd` | Multi-shape creation, vertex editing, shape dragging, per-panel zoom & pan, grid drawing & snap-to-grid, ColorPicker, shape/vertex delete, Z-ordering (Send Back / Bring Forward), shape Copy/Paste, shape Mirror X/Y, drawing (fill + outline for closed shapes). |
|
||
| `res://scripts/whole_stickman_preview.gd` | Assembly preview, drag-to-reposition, part selection with white bounding box, rotation gizmo (circle below box) with Ctrl 15° snap, scale gizmo (corner crosses) with Ctrl aspect lock, part Z-ordering (Send Back / Bring Forward) via `part_order`, part Mirror X/Y (scale negation), zoom & pan, grid drawing & snap-to-grid, part hit-bounds, labels. |
|
||
| `res://addons/curved_lines_2d/` | Scalable Vector Shapes 2D addon (v2.27.7) — required dependency. |
|
||
| `res://stick.tscn` | **Legacy** rigged/animated stick figure scene (Skeleton2D + IK). Not used by the editor. |
|
||
| `res://AGENTS.md` | Guidance for AI agents working in this codebase. |
|
||
|
||
### Menu bar structure
|
||
|
||
```
|
||
File Edit View
|
||
──────────── ──────────────────── ───────────
|
||
Save Configure Grid... Reset Views
|
||
Load ─────────
|
||
──────── Snap to Grid (check)
|
||
Clear
|
||
```
|
||
|
||
- **File** — Save, Load, Clear (Phase 1).
|
||
- **Edit** — `Configure Grid...` (dialog with a 1–100 SpinBox) and the checkable `Snap to Grid` toggle (Phase 3).
|
||
- **View** — `Reset Views` (resets zoom to 100% and pan offset to origin on every panel) (Phase 3).
|
||
|
||
### Context menu (per body-part panel)
|
||
|
||
The right-click context menu is context-sensitive. Item IDs:
|
||
|
||
| ID | Label | Shown when |
|
||
|----|-------|------------|
|
||
| 0 | Line | Empty space right-click |
|
||
| 1 | Rectangle | Empty space right-click |
|
||
| 2 | Circle | Empty space right-click |
|
||
| 3 | Create Point | Shape under mouse, near outline |
|
||
| 4 | Color... | Shape under mouse |
|
||
| 5 | Delete | Shape under mouse |
|
||
| 6 | Remove Point | Right-click on a vertex handle |
|
||
| 7 | Send Back | Shape under mouse |
|
||
| 8 | Bring Forward | Shape under mouse |
|
||
| 9 | Copy | Shape under mouse (Phase 5) |
|
||
| 10 | Paste | Shape or empty space right-click; shown only when the clipboard is populated (Phase 5) |
|
||
| 11 | Mirror X | Shape under mouse (Phase 5) |
|
||
| 12 | Mirror Y | Shape under mouse (Phase 5) |
|
||
|
||
### Context menu (Whole Stickman preview)
|
||
|
||
Right-clicking a selected part opens the preview's context menu:
|
||
|
||
| ID | Label | Description |
|
||
|----|-------|-------------|
|
||
| 0 | Send Back | Move the selected part one step back in `part_order` (Phase 5) |
|
||
| 1 | Bring Forward | Move the selected part one step forward in `part_order` (Phase 5) |
|
||
| 2 | Mirror X | Mirror the selected part around its bounding-box center (scale X negated) (Phase 5) |
|
||
| 3 | Mirror Y | Mirror the selected part around its bounding-box center (scale Y negated) (Phase 5) |
|
||
|
||
### Signal flow
|
||
|
||
```
|
||
BodyPartPanel.shape_changed(data) ---(bound to part_name)---> stickman_editor
|
||
| |
|
||
| _on_body_part_shape_changed |
|
||
+--------------------------> WholeStickmanPreview |
|
||
.set_body_parts(all_data) |
|
||
^ |
|
||
WholeStickmanPreview.part_moved(name, pos) (drag handling) --+
|
||
|
||
BodyPartPanel.shape_selected() ---(bound to part_name)---> stickman_editor
|
||
|
|
||
_on_body_part_shape_selected
|
||
(deselects all other panels)
|
||
```
|
||
|
||
- `BodyPartPanel` emits `shape_changed(shapes_array)` whenever a shape is created, a vertex is dragged (on release), a color is committed via the ColorPicker (on OK), a shape is deleted, a vertex is removed via "Remove Point", or Z-order changes via "Send Back"/"Bring Forward". The signal carries the full `Array[Dictionary]` of all shapes in the panel. Note: `clear_shape()` does **not** emit the signal; the editor's Clear flow refreshes the preview directly.
|
||
- `BodyPartPanel` emits `shape_selected` when left-clicked; the editor deselects all other panels.
|
||
- `stickman_editor.gd` collects shape data from all 10 panels and forwards it to `WholeStickmanPreview.set_body_parts()`.
|
||
- `WholeStickmanPreview` emits `part_moved(part_name, new_position)` during translation drags. Rotation and scale are stored internally and polled by the editor at save time via `get_part_rotation()` / `get_part_scale()`. Part Z-order is polled the same way via `get_part_order()` and saved to the top-level `part_order` field (Phase 5).
|
||
- Shape Copy/Paste (Phase 5) is owned by the editor: `_copy_shape()` stores a deep duplicate in `_shape_clipboard`, `_broadcast_clipboard_state()` tells every panel whether Paste should be offered, and `_paste_shape()` inserts the clipboard into the target panel at the click position. The clipboard persists after pasting and is shared across all panels.
|
||
|
||
> **Phase 4:** Each body part can have multiple shapes in Z-order. The Whole Stickman preview treats all shapes in a panel as one combined object, with selection (white bounding box), rotation (circle gizmo below box), and scale (cross gizmos at corners). The `.stk` format evolved to v1.2 with a `shapes` array per part plus `rotation` and `scale` fields. Rotation snaps to 15° with Ctrl; scale locks aspect ratio with Ctrl.
|
||
|
||
> **Phase 5:** Adds drawing-surface clipping, shape dragging, an editor-wide shape clipboard (Copy/Paste across panels), shape Mirror X/Y (vertex recompute), and preview object Z-ordering (Send Back/Bring Forward) with Mirror X/Y (scale negation). The format evolved to v1.3: a new top-level `part_order` array stores preview Z-order; scale may be negative for mirrored parts; shape mirroring stores no new fields because it rewrites `points`. The default grid size changed from 5 px to 15 px, and the Snap to Grid checkmark now renders correctly when toggled. v1.0–v1.2 files remain backward compatible and are migrated on load.
|