Files
FFCardGame/scripts/ui/MainMenu.gd
2026-02-02 16:28:53 -05:00

178 lines
5.9 KiB
GDScript

class_name MainMenu
extends CanvasLayer
## MainMenu - Title menu using pre-designed background image (title_menu.png)
## The window is sized to match the image (67% of 1024x1536).
## The image fills the entire window; buttons overlay the pre-drawn slots.
signal play_game
signal deck_builder
signal online_game
signal open_settings
signal quit_game
# UI Components
var bg_texture: TextureRect
var buttons_container: Control
var play_button: Button
var deck_builder_button: Button
var online_button: Button
var settings_button: Button
var quit_button: Button
var version_label: Label
# Custom font
var custom_font: Font = preload("res://JimNightshade-Regular.ttf")
# Per-button pixel rects: Rect2(x, y, width, height) at 460x689 window size
# Measured from the pre-drawn button slots in title_menu.png
const BUTTON_RECTS := [
Rect2(130, 78, 200, 38), # Quick Play
Rect2(130, 163, 200, 38), # Play
Rect2(130, 229, 200, 38), # Online
Rect2(130, 295, 200, 38), # Settings
Rect2(130, 360, 200, 38), # Exit
]
const DESIGN_SIZE := Vector2(460, 689)
func _ready() -> void:
# Center the window on screen
var screen := DisplayServer.screen_get_size()
var win_size := get_tree().root.size
DisplayServer.window_set_position(Vector2i(
(screen.x - win_size.x) / 2,
(screen.y - win_size.y) / 2
))
_create_menu()
func _create_menu() -> void:
var win_size := get_tree().root.get_visible_rect().size
# Background image fills the whole window
bg_texture = TextureRect.new()
add_child(bg_texture)
bg_texture.texture = load("res://assets/ui/title_menu.png")
bg_texture.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
bg_texture.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
bg_texture.position = Vector2.ZERO
bg_texture.size = win_size
bg_texture.mouse_filter = Control.MOUSE_FILTER_IGNORE
# Container for buttons
buttons_container = Control.new()
add_child(buttons_container)
buttons_container.mouse_filter = Control.MOUSE_FILTER_IGNORE
# Create buttons overlaying the pre-drawn slots
# "Play" is now in the top golden slot (formerly Quick Play)
play_button = _create_overlay_button("Play", 0)
play_button.add_theme_color_override("font_color", Color(0.15, 0.13, 0.1))
play_button.add_theme_color_override("font_hover_color", Color(0.3, 0.25, 0.2))
play_button.add_theme_color_override("font_pressed_color", Color(0.05, 0.05, 0.05))
play_button.pressed.connect(_on_play_pressed)
# "Deck Builder" is in slot 1 (formerly Play)
deck_builder_button = _create_overlay_button("Deck Builder", 1)
deck_builder_button.pressed.connect(_on_deck_builder_pressed)
online_button = _create_overlay_button("Online", 2)
online_button.pressed.connect(_on_online_pressed)
settings_button = _create_overlay_button("Settings", 3)
settings_button.disabled = true
quit_button = _create_overlay_button("Exit", 4)
quit_button.pressed.connect(_on_quit_pressed)
# Version label
version_label = Label.new()
version_label.text = "v0.1.0"
version_label.add_theme_font_override("font", custom_font)
version_label.add_theme_font_size_override("font_size", 11)
version_label.add_theme_color_override("font_color", Color(0.6, 0.6, 0.7, 0.5))
add_child(version_label)
# Position everything
_reposition_elements()
func _create_overlay_button(text: String, slot_index: int) -> Button:
var button = Button.new()
button.text = text
button.add_theme_font_override("font", custom_font)
button.add_theme_font_size_override("font_size", 20)
button.add_theme_color_override("font_color", Color(0.85, 0.82, 0.72))
button.add_theme_color_override("font_hover_color", Color(1.0, 0.95, 0.8))
button.add_theme_color_override("font_pressed_color", Color(0.7, 0.65, 0.55))
button.add_theme_color_override("font_disabled_color", Color(0.45, 0.42, 0.38))
# Transparent background so the pre-drawn button art shows through
var transparent = StyleBoxFlat.new()
transparent.bg_color = Color(0, 0, 0, 0)
transparent.set_border_width_all(0)
transparent.set_content_margin_all(0)
button.add_theme_stylebox_override("normal", transparent)
var hover_style = StyleBoxFlat.new()
hover_style.bg_color = Color(1, 1, 1, 0.1)
hover_style.set_border_width_all(0)
hover_style.set_content_margin_all(0)
button.add_theme_stylebox_override("hover", hover_style)
var pressed_style = StyleBoxFlat.new()
pressed_style.bg_color = Color(0, 0, 0, 0.2)
pressed_style.set_border_width_all(0)
pressed_style.set_content_margin_all(0)
button.add_theme_stylebox_override("pressed", pressed_style)
var disabled_style = StyleBoxFlat.new()
disabled_style.bg_color = Color(0, 0, 0, 0.35)
disabled_style.set_border_width_all(0)
disabled_style.set_content_margin_all(0)
button.add_theme_stylebox_override("disabled", disabled_style)
button.set_meta("slot_index", slot_index)
buttons_container.add_child(button)
return button
func _reposition_elements() -> void:
var win_size := get_tree().root.get_visible_rect().size
# Image fills window
bg_texture.size = win_size
# Scale factor from design size to actual window size
var scale := Vector2(win_size.x / DESIGN_SIZE.x, win_size.y / DESIGN_SIZE.y)
var base_font := int(22.0 * scale.y)
# Position each button using its individual rect
for child in buttons_container.get_children():
if child is Button:
var slot: int = child.get_meta("slot_index", -1)
if slot < 0 or slot >= BUTTON_RECTS.size():
continue
var rect: Rect2 = BUTTON_RECTS[slot]
child.position = Vector2(rect.position.x * scale.x, rect.position.y * scale.y)
child.size = Vector2(rect.size.x * scale.x, rect.size.y * scale.y)
child.add_theme_font_override("font", custom_font)
child.add_theme_font_size_override("font_size", base_font)
# Version label bottom-right
version_label.position = Vector2(win_size.x - 80, win_size.y - 24)
version_label.size = Vector2(72, 18)
func _on_play_pressed() -> void:
play_game.emit()
func _on_deck_builder_pressed() -> void:
deck_builder.emit()
func _on_online_pressed() -> void:
online_game.emit()
func _on_quit_pressed() -> void:
quit_game.emit()
get_tree().quit()