spaceship/ui/menus/DevMenu.gd
2026-09-03 20:05:33 +02:00

149 lines
5.2 KiB
GDScript

extends "res://ui/menus/ModalMenu.gd"
signal fleet_add_requested(vessel_type: String)
signal fleet_remove_requested(vessel_type: String)
signal unlock_skills_requested
signal unlimited_resources_requested(enabled: bool)
signal wave_requested
const ICON_BUTTON = preload("res://ui/IconButton.gd")
const VESSEL_DEFINITIONS = preload("res://vessels/VesselDefinitions.gd")
const ROW_HEIGHT: float = 86.0
const DESIGN_SIZE := Vector2(720.0, 1280.0)
@onready var content: Control = $Content
@onready var fleet_summary: Label = $Content/FleetSummary
@onready var fleet_rows: VBoxContainer = $Content/FleetRows
@onready var unlock_button: IconButton = $Content/ToolButtons/UnlockSkills
@onready var unlimited_button: IconButton = $Content/ToolButtons/UnlimitedResources
@onready var wave_button: IconButton = $Content/ToolButtons/StartWave
@onready var unlimited_label: Label = $Content/ToolLabels/UnlimitedLabel
@onready var status: Label = $Content/StatusLabel
var fleet: Node = null
var row_controls: Dictionary = {}
func _ready() -> void:
super._ready()
$Content/CloseButton.pressed.connect(close_menu)
_build_fleet_rows()
unlock_button.pressed.connect(func(): unlock_skills_requested.emit())
unlimited_button.pressed.connect(func():
unlimited_resources_requested.emit(not GameState.dev_unlimited_resources))
wave_button.pressed.connect(func(): wave_requested.emit())
_layout_content()
func _notification(what: int) -> void:
if what == NOTIFICATION_RESIZED and is_node_ready():
_layout_content()
func _layout_content() -> void:
# The project has a landscape reference viewport but is played in portrait
# too. A fixed design canvas keeps touch targets at their authored size and
# scales the complete composition uniformly into either shape.
var factor: float = minf(size.x / DESIGN_SIZE.x, size.y / DESIGN_SIZE.y)
content.scale = Vector2(factor, factor)
content.position = (size - DESIGN_SIZE * factor) * 0.5
func open_for(fleet_node: Node) -> void:
fleet = fleet_node
status.text = ""
open_menu()
refresh()
func set_status(message: String) -> void:
status.text = message
refresh()
func refresh() -> void:
if fleet == null or not is_instance_valid(fleet):
return
var total: int = fleet.ships.size()
fleet_summary.text = "CURRENT FLEET %d / %d" % [total, GameState.max_fleet_size()]
for definition in VESSEL_DEFINITIONS.fleet():
var vessel_type: String = String(definition.definition_id)
var count: int = 0
for ship in fleet.ships:
if is_instance_valid(ship) and String(ship.vessel_type) == vessel_type:
count += 1
var controls: Dictionary = row_controls.get(vessel_type, {})
if controls.is_empty():
continue
(controls.count as Label).text = str(count)
(controls.add as IconButton).enabled = total < GameState.max_fleet_size()
(controls.remove as IconButton).enabled = count > 0 and total > 1
unlock_button.highlighted = _all_skills_unlocked()
unlimited_button.highlighted = GameState.dev_unlimited_resources
unlimited_label.text = "UNLIMITED RESOURCES\n%s" \
% ("ON" if GameState.dev_unlimited_resources else "OFF")
func _all_skills_unlocked() -> bool:
for node in GameState.SKILL_TREE:
if not GameState.is_unlocked(String(node.id)):
return false
return true
func _build_fleet_rows() -> void:
for definition in VESSEL_DEFINITIONS.fleet():
var vessel_type: String = String(definition.definition_id)
var row := HBoxContainer.new()
row.custom_minimum_size = Vector2(0.0, ROW_HEIGHT)
row.add_theme_constant_override("separation", 12)
fleet_rows.add_child(row)
var vessel_icon := ICON_BUTTON.new()
vessel_icon.custom_minimum_size = Vector2(76.0, 76.0)
vessel_icon.mouse_filter = Control.MOUSE_FILTER_IGNORE
vessel_icon.icon = int(definition.icon)
vessel_icon.glow_color = definition.glow_color
row.add_child(vessel_icon)
var name_label := Label.new()
name_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
name_label.text = String(definition.display_name)
name_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
name_label.add_theme_font_size_override("font_size", 25)
row.add_child(name_label)
var remove_button := ICON_BUTTON.new()
remove_button.custom_minimum_size = Vector2(70.0, 70.0)
remove_button.icon = IconButton.Icon.MINUS
remove_button.glow_color = definition.glow_color
remove_button.pressed.connect(_request_remove.bind(vessel_type))
row.add_child(remove_button)
var count_label := Label.new()
count_label.custom_minimum_size = Vector2(48.0, 0.0)
count_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
count_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
count_label.add_theme_font_size_override("font_size", 31)
row.add_child(count_label)
var add_button := ICON_BUTTON.new()
add_button.custom_minimum_size = Vector2(70.0, 70.0)
add_button.icon = IconButton.Icon.PLUS
add_button.glow_color = definition.glow_color
add_button.pressed.connect(_request_add.bind(vessel_type))
row.add_child(add_button)
row_controls[vessel_type] = {
"count": count_label,
"add": add_button,
"remove": remove_button,
}
func _request_add(vessel_type: String) -> void:
fleet_add_requested.emit(vessel_type)
func _request_remove(vessel_type: String) -> void:
fleet_remove_requested.emit(vessel_type)