69 lines
2.0 KiB
GDScript
69 lines
2.0 KiB
GDScript
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.
|
||
|
||
signal screen_requested(id: StringName)
|
||
|
||
const SCREENS := [
|
||
[&"inventory", "Inventory", "I"],
|
||
[&"character", "Character", "C"],
|
||
[&"quest_log", "Quest Log", "J"],
|
||
[&"spellbook", "Spellbook", "K"],
|
||
[&"world_map", "World Map", "M"],
|
||
[&"party", "Party", "P"],
|
||
]
|
||
const SLIDE_SECONDS := 0.32
|
||
const HIDDEN_SHIFT := 230.0
|
||
|
||
var _screen_buttons: Dictionary = {}
|
||
var _state: ShellState
|
||
var _menu: VBoxContainer
|
||
var _handle: Button
|
||
|
||
|
||
func _ready() -> void:
|
||
_menu = VBoxContainer.new()
|
||
_menu.add_theme_constant_override("separation", 10)
|
||
add_child(_menu)
|
||
for entry in SCREENS:
|
||
var id: StringName = entry[0]
|
||
var button := Button.new()
|
||
button.text = "%s %s" % [entry[2], entry[1]]
|
||
button.theme_type_variation = ThemeKeys.DARK_PANEL
|
||
button.pressed.connect(func(): screen_requested.emit(id))
|
||
_menu.add_child(button)
|
||
_screen_buttons[id] = button
|
||
|
||
_handle = Button.new()
|
||
_handle.text = "›"
|
||
_handle.theme_type_variation = ThemeKeys.TAB_ACTIVE
|
||
_handle.pressed.connect(_on_handle_pressed)
|
||
add_child(_handle)
|
||
|
||
|
||
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 := Vector2.ZERO if open else 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)
|