class_name SystemDock extends Control ## The slide-in system dock (mock 2a): a gold handle toggles a column of screen ## buttons in/out. §2: state (owns the open toggle via ShellState). The buttons ## are the routing seam — they emit screen_requested; the screens they open land ## in later milestones, so the signal is currently a no-op for the shell. ## ## Layout is authored in SystemDock.tscn (editor-previewable). This script only ## wires the buttons' signals, drives the slide animation, and toggles state. Each ## dock button carries a `screen_id` StringName in its scene metadata; add/reorder ## buttons in the editor and the wiring follows. signal screen_requested(id: StringName) const SLIDE_SECONDS := 0.32 const HIDDEN_SHIFT := 230.0 var _screen_buttons: Dictionary = {} var _state: ShellState var _menu_open_pos: Vector2 @onready var _menu: VBoxContainer = $Menu @onready var _handle: Button = $Handle func _ready() -> void: # The buttons live in the scene; harvest each one's authored screen_id so the # routing seam follows editor edits (add/remove/reorder needs no code change). for child in _menu.get_children(): if child is Button and child.has_meta("screen_id"): var id: StringName = child.get_meta("screen_id") child.pressed.connect(func(): screen_requested.emit(id)) _screen_buttons[id] = child _handle.pressed.connect(_on_handle_pressed) # Capture the authored open position so the slide is relative to wherever the # menu is placed in the editor — moving it in the editor just works. _menu_open_pos = _menu.position func setup(state: ShellState) -> void: _state = state _apply_open(_state.dock_open) func _on_handle_pressed() -> void: if _state == null: return _apply_open(_state.toggle_dock()) func _apply_open(open: bool) -> void: _handle.text = "›" if open else "‹" var target := _menu_open_pos if open else _menu_open_pos + Vector2(HIDDEN_SHIFT, 0.0) var alpha := 1.0 if open else 0.0 if not is_inside_tree(): _menu.position = target _menu.modulate.a = alpha return var tween := create_tween().set_parallel(true) tween.tween_property(_menu, "position", target, SLIDE_SECONDS) tween.tween_property(_menu, "modulate:a", alpha, SLIDE_SECONDS)