class_name EditorToolbar extends HBoxContainer ## Tool-mode switcher for the in-game editor (docs/architecture/editor.md ## ยง7.2 `Toolbar`). Pure UI: it only emits signals: `InGameEditor` decides ## what to do with them (calling into `EditorCore`/`ToolRegistry`). signal tool_selected(tool_id: String) signal undo_pressed signal redo_pressed const TOOL_LABELS := { "select": "Select", "brush": "Brush", "object_place": "Place", "erase": "Erase", } var _tool_buttons: Dictionary = {} var _undo_button: Button var _redo_button: Button func _init() -> void: name = "EditorToolbar" func _ready() -> void: for tool_id in TOOL_LABELS: var btn := Button.new() btn.text = TOOL_LABELS[tool_id] btn.toggle_mode = true btn.pressed.connect(_on_tool_button_pressed.bind(tool_id)) add_child(btn) _tool_buttons[tool_id] = btn add_child(VSeparator.new()) _undo_button = Button.new() _undo_button.text = "Undo" _undo_button.pressed.connect(func(): undo_pressed.emit()) add_child(_undo_button) _redo_button = Button.new() _redo_button.text = "Redo" _redo_button.pressed.connect(func(): redo_pressed.emit()) add_child(_redo_button) func _on_tool_button_pressed(tool_id: String) -> void: set_active_tool(tool_id) tool_selected.emit(tool_id) ## Reflect the active tool in the button states without re-emitting the signal. func set_active_tool(tool_id: String) -> void: for id in _tool_buttons: _tool_buttons[id].button_pressed = (id == tool_id) ## Reflect whether undo/redo currently have anything to do. func set_history_state(can_undo: bool, can_redo: bool) -> void: if _undo_button: _undo_button.disabled = not can_undo if _redo_button: _redo_button.disabled = not can_redo