Files
stickman/AGENTS.md
T
ryan 28e8798021 Implement Phase 6 features for Stickman Editor
- Updated BUGS.md with new issues related to selection bounding box, touchpad panning speed, and zooming behavior.
- Enhanced PROJECT.md with detailed specifications for touchpad controls, recent colors in the color picker, and a status bar for project information.
- Modified project.godot to update compatibility version to 4.7.
- Added a status bar in stickman_editor.tscn to display cursor coordinates and snap status.
- Updated body_part_panel.gd to handle recent colors and cursor detection over drawing areas.
- Enhanced stickman_editor.gd to manage cursor coordinates display and recent colors tracking.
- Improved whole_stickman_preview.gd to render selection gizmos on top of other parts.
- Created master_rig.tscn for the stickman rig structure with bones and IK targets.
- Developed master_rig_builder.gd to automate the rig building process with remote transforms and IK modifications.
2026-08-14 21:49:06 -04:00

8.2 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.
    • Phase 6 recent colors: stores _recent_colors: Array[String] (max 8, most-recent-first), loads from settings.json (recent_colors key) in _load_settings(), saves on each color selection via _save_settings(), and broadcasts to all 10 panels via _broadcast_recent_colors().
    • _on_color_selected(color, part_name): deduplicates, inserts the hex string at the front, trims to 8 entries, saves settings, then broadcasts to all panels.
    • _broadcast_recent_colors(): pushes _recent_colors to every panel via BodyPartPanel.set_recent_colors(_recent_colors).
    • Phase 6 status bar (cursor coords): _process() polls get_global_mouse_position() each frame, checks each panel via is_cursor_over_drawing(global_pos) and the preview via is_cursor_over_preview(global_pos), converts to world space via global_to_world(global_pos), and writes "X: ### Y: ###" to _status_cursor_coords.
    • Phase 6 snap status: _status_snap_status displays "SNAP: ON" / "SNAP: OFF", set in _ready() and re-synced when snap is toggled (_on_edit_menu_id_pressed).
  • 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
    • signal color_selected(color: Color) — emitted when the color is confirmed (OK button)
    • set_recent_colors(colors_hex: Array) — clears existing ColorPicker presets and populates with the given hex colors
    • is_cursor_over_drawing(global_pos: Vector2) -> bool — true if global_pos is over the drawing surface
    • global_to_world(global_pos: Vector2) -> Vector2 — maps a global position to drawing ("world") space
    • 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.
    • Phase 6 touchpad: _gui_input handles InputEventMagnifyGesture (pinch zoom) and InputEventPanGesture (2-finger drag panning), both checked before InputEventMouseButton. Pan gesture delta is multiplied by 3.0 for speed parity with mouse panning.
    • Phase 6 cursor-centered zoom: both mouse wheel and pinch zoom adjust _pan_offset so the world point under the cursor stays fixed during zoom.
    • Selection gizmos always on top: bounding box, rotation circle, and scale crosses for the selected part are drawn in a second pass after all parts, via _selected_gizmo_bounds, so they always render in front.
  • 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, %StatusBar, %CursorCoords, %SnapStatus.
      • Phase 6 status bar: StatusBar is an HBoxContainer bottom-anchored at 28 px height containing CursorCoords (left) and SnapStatus (right); MainLayout offset_bottom is -28.0 to leave room for it.
    • 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).

settings.json (Phase 6)

  • Persisted editor preferences written to settings.json via _save_settings() and loaded in _load_settings().
  • Keys: version, grid_size, snap_to_grid, recent_colors.
  • recent_colors: Array[String] — the last up-to-8 selected hex colors, most-recent-first. Populated on load and flushed on every color selection.

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.