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.
This commit is contained in:
2026-08-14 21:49:06 -04:00
parent b97bc145e4
commit 28e8798021
11 changed files with 647 additions and 42 deletions
+60
View File
@@ -73,6 +73,8 @@ const MAX_GRID_SIZE := 100
@onready var _error_dialog: AcceptDialog = %ErrorDialog
@onready var _grid_config_dialog: ConfirmationDialog = %GridConfigDialog
@onready var _grid_size_spin_box: SpinBox = %GridSizeSpinBox
@onready var _status_cursor_coords: Label = %CursorCoords
@onready var _status_snap_status: Label = %SnapStatus
# ---------------------------------------------------------------------------
# Grid / snap state
@@ -84,6 +86,9 @@ var _snap_enabled: bool = false
# Phase 5: shape clipboard
var _shape_clipboard: Dictionary = {}
# Phase 6: recent colors
var _recent_colors: Array[String] = []
var _edit_menu: PopupMenu
# ---------------------------------------------------------------------------
@@ -98,11 +103,31 @@ func _ready() -> void:
_whole_preview.set_body_parts(_collect_all_shape_data())
_load_settings()
_update_snap_status_label()
_broadcast_settings()
_broadcast_recent_colors()
if not _grid_config_dialog.confirmed.is_connected(_on_grid_config_confirmed):
_grid_config_dialog.confirmed.connect(_on_grid_config_confirmed)
func _process(_delta: float) -> void:
var mouse_pos := get_global_mouse_position()
for part_name: String in BODY_PART_NAMES:
var panel: BodyPartPanel = _body_part_panels.get(part_name) as BodyPartPanel
if panel and panel.is_cursor_over_drawing(mouse_pos):
var world_pos := panel.global_to_world(mouse_pos)
_status_cursor_coords.text = "X: %d Y: %d" % [int(world_pos.x), int(world_pos.y)]
return
if _whole_preview.is_cursor_over_preview(mouse_pos):
var world_pos := _whole_preview.global_to_world(mouse_pos)
_status_cursor_coords.text = "X: %d Y: %d" % [int(world_pos.x), int(world_pos.y)]
return
_status_cursor_coords.text = ""
# ---------------------------------------------------------------------------
# Menu & Dialog setup
# ---------------------------------------------------------------------------
@@ -162,6 +187,7 @@ func _populate_body_part_panels() -> void:
panel.shape_selected.connect(_on_body_part_shape_selected.bind(part_name))
panel.shape_copy_requested.connect(_on_shape_copy_requested.bind(part_name))
panel.shape_paste_requested.connect(_on_shape_paste_requested.bind(part_name))
panel.color_selected.connect(_on_color_selected.bind(part_name))
_body_part_panels[part_name] = panel
left_col.add_child(panel)
@@ -173,6 +199,7 @@ func _populate_body_part_panels() -> void:
panel.shape_selected.connect(_on_body_part_shape_selected.bind(part_name))
panel.shape_copy_requested.connect(_on_shape_copy_requested.bind(part_name))
panel.shape_paste_requested.connect(_on_shape_paste_requested.bind(part_name))
panel.color_selected.connect(_on_color_selected.bind(part_name))
_body_part_panels[part_name] = panel
center_col.add_child(panel)
@@ -201,6 +228,7 @@ func _on_edit_menu_id_pressed(id: int) -> void:
_edit_menu.set_item_text(1, _snap_menu_label())
_save_settings()
_broadcast_settings()
_update_snap_status_label()
func _on_edit_menu_about_to_popup() -> void:
@@ -448,6 +476,12 @@ func _broadcast_clipboard_state() -> void:
(panel as BodyPartPanel).set_has_clipboard(not _shape_clipboard.is_empty())
func _broadcast_recent_colors() -> void:
for panel in _body_part_panels.values():
if panel is BodyPartPanel:
(panel as BodyPartPanel).set_recent_colors(_recent_colors)
func _paste_shape_into_panel(part_name: String, world_pos: Vector2) -> void:
if _shape_clipboard.is_empty():
return
@@ -459,6 +493,18 @@ func _paste_shape_into_panel(part_name: String, world_pos: Vector2) -> void:
func _on_shape_paste_requested(world_pos: Vector2, part_name: String) -> void:
_paste_shape_into_panel(part_name, world_pos)
func _on_color_selected(color: Color, _part_name: String) -> void:
var hex_str := color.to_html()
var idx := _recent_colors.find(hex_str)
if idx >= 0:
_recent_colors.remove_at(idx)
_recent_colors.insert(0, hex_str)
while _recent_colors.size() > 8:
_recent_colors.pop_back()
_save_settings()
_broadcast_recent_colors()
# ---------------------------------------------------------------------------
# Phase 3: Settings persistence
# ---------------------------------------------------------------------------
@@ -483,6 +529,15 @@ func _load_settings() -> void:
_snap_enabled = bool(d.get("snap_to_grid", false))
_grid_size = clampi(_grid_size, MIN_GRID_SIZE, MAX_GRID_SIZE)
var raw_colors: Variant = d.get("recent_colors", [])
if raw_colors is Array:
var arr: Array = raw_colors as Array
for c in arr:
if c is String:
_recent_colors.append(c as String)
while _recent_colors.size() > 8:
_recent_colors.pop_back()
if _edit_menu:
_edit_menu.set_item_text(1, _snap_menu_label())
@@ -492,6 +547,7 @@ func _save_settings() -> void:
"version": SETTINGS_VERSION,
"grid_size": _grid_size,
"snap_to_grid": _snap_enabled,
"recent_colors": _recent_colors,
}
var file := FileAccess.open(SETTINGS_PATH, FileAccess.WRITE)
if file:
@@ -511,3 +567,7 @@ func _broadcast_settings() -> void:
func _snap_menu_label() -> String:
return "[√] Snap to Grid" if _snap_enabled else "Snap to Grid"
func _update_snap_status_label() -> void:
_status_snap_status.text = "SNAP: ON" if _snap_enabled else "SNAP: OFF"