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

6.6 KiB
Raw Blame History

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.gdextends 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.gdclass_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.gdclass_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.