Files
stickman/AGENTS.md
T
2026-08-08 00:00:50 -04:00

100 lines
6.6 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.
# AGENTS.md — stickman (Godot 4.4)
## Project type
- **Godot 4.4** 2D/GUI project (Forward Plus renderer)
- No CLI build/test/lint commands; open in the Godot editor to run
- **Main scene:** `res://scenes/stickman_editor.tscn` (set as `run/main_scene` in `project.godot`)
## Project overview
Stickman Studio is an editor tool for drawing and assembling stick figures. It is a
`Control`-based GUI (not physics/animation) in its current phase. Body-part vector shapes
are authored per-panel (each panel supports **multiple shapes** with Z-ordering) and
assembled in a "Whole Stickman" preview that supports translation, rotation, and scale.
## Required addon
- **Scalable Vector Shapes 2D** (v2.27.7) at `addons/curved_lines_2d/`
- Declared dependency for the project. The current editor UI does not instantiate it directly,
but keep it present — it is required for the legacy `stick.tscn` rig.
## Architecture
- `scripts/stickman_editor.gd``extends Control`; the main controller. Owns the menu bar,
save/load/clear flow, JSON (de)serialization, and populates the 10 body-part panels.
Writes `FILE_VERSION "1.2"`; auto-migrates `"1.0"`/`"1.1"` files on load. Coordinates cross-panel
selection so only one shape is selected at a time (`shape_selected` → deselect others).
Collects per-part `{shapes[], position, rotation, scale}` for save/load.
- `scripts/body_part_panel.gd``class_name BodyPartPanel`, `extends PanelContainer`.
Reusable per-part editor. Public API:
- `set_shape_data(data: Variant)` — import shape data (Array or single Dictionary; used on Load/Clear)
- `get_shape_data() -> Array[Dictionary]` — export array of `{shape_type, points, color, closed, vertex_flags}`
- `clear_shape()` — reset panel, clears all shapes (does **not** emit `shape_changed`)
- `select()` — mark the panel's topmost shape as selected (white outline highlight)
- `deselect()` — clear selection and cancel any in-progress vertex drag
- `signal shape_changed(shapes: Array)` — emitted when any shape is created, modified, deleted, or reordered
- `signal shape_selected()` — emitted on left-click; the editor deselects all other panels
- **Phase 2 vertex editing:** left-click on a shape selects it; drag a vertex handle to
reshape in real time; with a shape selected, right-click near an outline edge offers
"Create Point" (inserts a vertex flagged `1` at the edge midpoint). Original vertices
are filled circles; user-created vertices are hollow rectangles.
- **Phase 4 multi-shape:** panels store a `shapes[]` array. Right-click context menu
includes "Send Back" (id 7) and "Bring Forward" (id 8) for Z-ordering. "Delete" (id 5)
removes the specific shape under the mouse. `_selected_shape_idx` tracks which shape
is active for vertex editing.
- **Per-panel zoom:** mouse wheel multiplies `_zoom` by 1.10, clamped to `[0.3, 3.0]`;
drawing and input hit-testing both run in world space via `draw_set_transform`.
- **Drawing approach:** closedness is read from the `closed` flag (Phase 2), not
`shape_type`. Closed shapes are filled via `draw_colored_polygon(pts, color)` before a
2 px outline is drawn with `_draw_polyline(..., closed=true)`. Open shapes render
outline-only (`closed=false`). Shapes draw in array order (z-order).
- `scripts/whole_stickman_preview.gd``class_name WholeStickmanPreview`,
`extends PanelContainer`. Assembles all parts and handles drag-to-reposition, rotation, scale.
- `set_body_parts(parts_data)`, `set_all_part_positions(pos)`, `get_part_position(name)`
- `get_part_rotation(name) -> float`, `set_part_rotation(name, degrees)`
- `get_part_scale(name) -> Vector2`, `set_part_scale(name, scale)`
- `_selected_part` (String) — part with white bounding box selected
- `_interaction` (enum: NONE, TRANSLATE, ROTATE, SCALE) — current gizmo interaction
- Rotation gizmo: filled circle centered below bounding box; Ctrl = 15° snap
- Scale gizmo: crosses at 4 corners; Ctrl = aspect ratio lock
- `signal part_moved(part_name, new_position)`
- Per-panel zoom via mouse wheel (×1.10, clamped to `[0.3, 3.0]`); drag hit-tests and
rendering run in world space.
- Scenes:
- `scenes/stickman_editor.tscn` — main editor layout; unique-name nodes (`%Prefix`) used
for typed `@onready` access: `%MenuBar`, `%StickmanNameEdit`, `%LeftColumn`,
`%CenterColumn`, `%WholeStickmanPreview`, `%SaveDialog`, `%LoadDialog`,
`%ClearConfirmDialog`, `%ErrorDialog`.
- `scenes/body_part_panel.tscn` — instantiated 10× at runtime (5 per column). Each panel
sets `size_flags_vertical = SIZE_EXPAND_FILL` so the panels expand to fill the column
height in their parent VBoxContainer.
### Body-part data model
- 10 internal part keys (ordered): `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`.
- Shape dictionary: `{ "shape_type": String, "points": Array[{x,y}], "color": "#hex",
"closed": bool, "vertex_flags": Array[int] }`.
- `shape_type` values: `"line"`, `"rectangle"`, `"circle"`, `""` (empty).
Descriptive tag in Phase 2 — rendering uses `closed`.
- `closed`: `true` = filled + closed outline, `false` = open outline-only.
- `vertex_flags`: same length as `points`; `0` = original vertex (filled circle),
`1` = user-created via "Create Point" (hollow rectangle).
- **Phase 4:** A panel stores a `shapes[]` array of shape dictionaries. Z-order = array
position (first = back, last = front). Per-part data includes `{shapes[], position,
rotation, scale}`.
- The JSON `.stk` format is defined in `README.md` (versioned `"1.2"`, extensible;
`"1.0"`/`"1.1"` files auto-migrate on load).
### Legacy scene (do not delete)
- `stick.tscn` — the original rigged/animated figure using `Skeleton2D` + IK targets +
`RemoteTransform2D` + `Line2D` limbs, plus an embedded `@tool` script drawing the head
circle. Animations: "walk", "walk_to", "RESET". **Not** the current main scene; kept for
future animation/rigging phases.
## Editor conventions
- `.godot/` is gitignored; never edit it manually.
- Scene files (`*.tscn`) and `.import` files are text-based; use Godot's editor for complex changes.
- UID references (Godot 4 native) exist in scenes; do not change them by hand.
- Use standard Godot `Control` nodes where applicable.
- Use `class_name` for globally referenced scripts (`BodyPartPanel`, `WholeStickmanPreview`).
- Prefer `%UniqueName` access over exported node paths in `stickman_editor.gd` / `body_part_panel.gd`.
- Keep the `.stk` JSON format backward compatible — never change the meaning of an existing key.