Files
code_of_conquest_dnd/client/scripts/ui/shell/system_dock.gd
Phillip Tarrant 4698732285 refactor(shell): author shell scenes as editor-previewable node trees
Move the three shell scenes (SystemDock, NarrationBook, MainWindowShell)
from build-everything-in-_ready() to authored .tscn node trees with the
theme + type-variations set in the editor, so the layout previews and can
be arranged in the Godot editor. Scripts keep only on-load work: @onready
node refs, DM-loop wiring, the dock slide, and binding seed ShellState into
the fixed authored turn-order tokens + consumable slots.

Fixes the dock offset + over-long buttons (now fixed-width DockButtons in a
right-anchored menu). Headless probe: root 1920x1080, world/book split
1180/740, dock at the world's right edge — no collapse. Suite 138/138.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 09:38:22 -05:00

62 lines
2.2 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)