104 lines
4.0 KiB
GDScript
104 lines
4.0 KiB
GDScript
extends Control
|
|
var connection: Node
|
|
var busy := false
|
|
var status: Label
|
|
var history: RichTextLabel
|
|
var prepare: Button
|
|
var start: Button
|
|
var reset: Button
|
|
var message: Label
|
|
var confirm: ConfirmationDialog
|
|
|
|
func _ready() -> void:
|
|
connection = preload("res://core/network/room_connection.gd").new()
|
|
add_child(connection)
|
|
connection.configure("operator")
|
|
var center := CenterContainer.new()
|
|
center.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
add_child(center)
|
|
var column := VBoxContainer.new()
|
|
column.custom_minimum_size = Vector2(1050, 0)
|
|
column.add_theme_constant_override("separation", 18)
|
|
center.add_child(column)
|
|
var title := Label.new()
|
|
title.text = "ARCADE ROOM CONTROL"
|
|
title.add_theme_font_size_override("font_size", 42)
|
|
column.add_child(title)
|
|
status = Label.new()
|
|
status.add_theme_font_size_override("font_size", 25)
|
|
column.add_child(status)
|
|
var row := HBoxContainer.new()
|
|
column.add_child(row)
|
|
prepare = add_button(row, "Prepare Pac-Man", func(): command("prepare"))
|
|
start = add_button(row, "Start Game", func(): command("start"))
|
|
reset = add_button(row, "Reset Cabinet…", func(): confirm.popup_centered())
|
|
confirm = ConfirmationDialog.new()
|
|
confirm.dialog_text = "Unload the current game and reset this cabinet's room session?"
|
|
confirm.confirmed.connect(func(): command("reset"))
|
|
add_child(confirm)
|
|
message = Label.new()
|
|
message.text = "Cabinet 01 quick controls • Open the controller URL in a browser for all cabinets"
|
|
column.add_child(message)
|
|
history = RichTextLabel.new()
|
|
history.custom_minimum_size = Vector2(1050, 380)
|
|
history.add_theme_font_size_override("normal_font_size", 20)
|
|
column.add_child(history)
|
|
var hint := Label.new()
|
|
hint.text = "Accepted GPIO output does not confirm physical coin delivery.\nClosing this window leaves the room controller running. Escape closes this app."
|
|
column.add_child(hint)
|
|
set_buttons(false, false, false)
|
|
var timer := Timer.new()
|
|
timer.wait_time = 1.0
|
|
timer.timeout.connect(refresh)
|
|
add_child(timer)
|
|
timer.start()
|
|
refresh()
|
|
|
|
func add_button(parent: Node, text: String, callback: Callable) -> Button:
|
|
var button := Button.new()
|
|
button.text = text
|
|
button.add_theme_font_size_override("font_size", 24)
|
|
button.pressed.connect(callback)
|
|
parent.add_child(button)
|
|
return button
|
|
|
|
func set_buttons(can_prepare: bool, can_start: bool, can_reset: bool) -> void:
|
|
prepare.disabled = not can_prepare
|
|
start.disabled = not can_start
|
|
reset.disabled = not can_reset
|
|
|
|
func display(state: Dictionary) -> void:
|
|
if state.has("error"):
|
|
status.text = "CONTROLLER UNAVAILABLE\n" + str(state.error)
|
|
set_buttons(false, false, false)
|
|
return
|
|
var pending := false
|
|
for item in state.commands:
|
|
if item.status == "queued": pending = true
|
|
var available: bool = state.online and not pending
|
|
set_buttons(available and state.phase in ["idle", "won", "lost", "needs_prepare"], available and state.phase == "ready", available)
|
|
status.text = "Cabinet 01: %s | %s\nGame: %s | GPIO mode: %s | Agent: %s\nReward: %s" % ["ONLINE" if state.online else "OFFLINE", str(state.phase).to_upper(), state.get("game", "pacman"), state.gpio, state.version, state.reward]
|
|
history.text = "EVENT HISTORY\n"
|
|
for item in state.history:
|
|
history.text += "%s %s\n" % [Time.get_datetime_string_from_unix_time(int(item.time)).replace("T", " ") + " UTC", item.message]
|
|
history.scroll_to_line(history.get_line_count())
|
|
|
|
func refresh() -> void:
|
|
if busy: return
|
|
busy = true
|
|
var state: Dictionary = await connection.post("/operator/state")
|
|
busy = false
|
|
display(state)
|
|
|
|
func command(action: String) -> void:
|
|
if busy: return
|
|
busy = true
|
|
set_buttons(false, false, false)
|
|
var payload := {"action": action, "cabinet": "cabinet_01"}
|
|
if action == "prepare": payload = {"action": "prepare_scenario", "scenario": "proof_of_concept"}
|
|
var state: Dictionary = await connection.post("/operator/command", payload)
|
|
busy = false
|
|
if state.has("error"): message.text = str(state.error)
|
|
else: message.text = "Command queued; waiting for cabinet acknowledgement"
|
|
display(state)
|