Files
modbison/scripts/pause_menu.gd
T

189 lines
6.0 KiB
GDScript

class_name PauseMenu
extends Control
## In-game Pause & System Menu overlay.
##
## Provides resume, settings, controls guide, and safe exit confirmation.
signal resume_requested
signal edit_world_requested
signal friends_requested
signal chat_requested
signal controls_requested
signal leave_world_confirmed
var can_edit: bool = false
var world_title: String = "World"
var _confirm_box: VBoxContainer
var _main_menu_vbox: VBoxContainer
var _fs_button: Button
func _init(p_can_edit: bool = false, p_world_title: String = "World") -> void:
name = "PauseMenu"
can_edit = p_can_edit
world_title = p_world_title
set_anchors_preset(Control.PRESET_FULL_RECT)
func _ready() -> void:
mouse_filter = Control.MOUSE_FILTER_STOP
# Dark semi-transparent background
var bg := ColorRect.new()
bg.color = Color(0.05, 0.07, 0.10, 0.85)
bg.set_anchors_preset(Control.PRESET_FULL_RECT)
add_child(bg)
var center := CenterContainer.new()
center.set_anchors_preset(Control.PRESET_FULL_RECT)
add_child(center)
var panel := PanelContainer.new()
panel.custom_minimum_size = Vector2(400, 0)
var style := StyleBoxFlat.new()
style.bg_color = Color(0.12, 0.14, 0.18, 0.98)
style.border_color = Color(0.35, 0.45, 0.65, 1.0)
style.set_border_width_all(2)
style.set_corner_radius_all(10)
style.content_margin_left = 28
style.content_margin_right = 28
style.content_margin_top = 24
style.content_margin_bottom = 24
panel.add_theme_stylebox_override("panel", style)
center.add_child(panel)
var root_vbox := VBoxContainer.new()
root_vbox.add_theme_constant_override("separation", 16)
panel.add_child(root_vbox)
# Title & World info
var header_vbox := VBoxContainer.new()
header_vbox.add_theme_constant_override("separation", 4)
root_vbox.add_child(header_vbox)
var title := Label.new()
title.text = "PAUSED"
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
title.add_theme_font_size_override("font_size", 28)
title.add_theme_color_override("font_color", Color(1.0, 1.0, 1.0))
header_vbox.add_child(title)
var subtitle := Label.new()
subtitle.text = world_title
subtitle.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
subtitle.add_theme_font_size_override("font_size", 14)
subtitle.add_theme_color_override("font_color", Color(0.65, 0.75, 0.9))
header_vbox.add_child(subtitle)
# Main action buttons
_main_menu_vbox = VBoxContainer.new()
_main_menu_vbox.add_theme_constant_override("separation", 10)
root_vbox.add_child(_main_menu_vbox)
var resume_btn := _make_menu_btn("▶ Resume Game (ESC)", _on_resume_pressed, Color(0.4, 0.9, 0.5))
_main_menu_vbox.add_child(resume_btn)
if can_edit:
var edit_btn := _make_menu_btn("🛠️ Creator Studio / Edit World (F2)", func(): edit_world_requested.emit())
_main_menu_vbox.add_child(edit_btn)
var friends_btn := _make_menu_btn("👥 Friends & Social (F1)", func(): friends_requested.emit())
_main_menu_vbox.add_child(friends_btn)
var chat_btn := _make_menu_btn("💬 Chat (T / Enter)", func(): chat_requested.emit())
_main_menu_vbox.add_child(chat_btn)
var controls_btn := _make_menu_btn("⌨️ Controls & Keybindings", func(): controls_requested.emit())
_main_menu_vbox.add_child(controls_btn)
_fs_button = _make_menu_btn("⛶ Toggle Fullscreen (F11)", _on_toggle_fs)
_update_fs_label()
_main_menu_vbox.add_child(_fs_button)
var leave_btn := _make_menu_btn("🚪 Leave World", _on_prompt_leave, Color(1.0, 0.45, 0.45))
_main_menu_vbox.add_child(leave_btn)
# Confirmation Box (hidden initially)
_confirm_box = VBoxContainer.new()
_confirm_box.visible = false
_confirm_box.add_theme_constant_override("separation", 14)
root_vbox.add_child(_confirm_box)
var confirm_msg := Label.new()
confirm_msg.text = "Are you sure you want to leave this world?\nAny unsaved changes will be lost."
confirm_msg.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
confirm_msg.autowrap_mode = TextServer.AUTOWRAP_WORD
confirm_msg.add_theme_font_size_override("font_size", 14)
confirm_msg.add_theme_color_override("font_color", Color(1.0, 0.85, 0.85))
_confirm_box.add_child(confirm_msg)
var confirm_btns := HBoxContainer.new()
confirm_btns.alignment = BoxContainer.ALIGNMENT_CENTER
confirm_btns.add_theme_constant_override("separation", 16)
_confirm_box.add_child(confirm_btns)
var cancel_leave_btn := Button.new()
cancel_leave_btn.text = "Stay in World"
cancel_leave_btn.custom_minimum_size = Vector2(130, 36)
cancel_leave_btn.pressed.connect(_on_cancel_leave)
confirm_btns.add_child(cancel_leave_btn)
var confirm_leave_btn := Button.new()
confirm_leave_btn.text = "Confirm Leave"
confirm_leave_btn.custom_minimum_size = Vector2(130, 36)
confirm_leave_btn.add_theme_color_override("font_color", Color(1.0, 0.4, 0.4))
confirm_leave_btn.pressed.connect(func(): leave_world_confirmed.emit())
confirm_btns.add_child(confirm_leave_btn)
func _make_menu_btn(label: String, callback: Callable, color: Color = Color.WHITE) -> Button:
var btn := Button.new()
btn.text = label
btn.custom_minimum_size = Vector2(0, 38)
if color != Color.WHITE:
btn.add_theme_color_override("font_color", color)
btn.pressed.connect(callback)
return btn
func _on_resume_pressed() -> void:
resume_requested.emit()
func _on_toggle_fs() -> void:
Session.toggle_fullscreen()
_update_fs_label()
func _update_fs_label() -> void:
if _fs_button == null:
return
if DisplayServer.get_name() == "headless":
_fs_button.text = "⛶ Toggle Fullscreen (F11)"
return
var m := DisplayServer.window_get_mode()
if m == DisplayServer.WINDOW_MODE_FULLSCREEN or m == DisplayServer.WINDOW_MODE_EXCLUSIVE_FULLSCREEN:
_fs_button.text = "🗗 Windowed Mode (F11)"
else:
_fs_button.text = "⛶ Fullscreen Mode (F11)"
func _on_prompt_leave() -> void:
_main_menu_vbox.visible = false
_confirm_box.visible = true
func _on_cancel_leave() -> void:
_confirm_box.visible = false
_main_menu_vbox.visible = true
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("ui_cancel"):
get_viewport().set_input_as_handled()
if _confirm_box.visible:
_on_cancel_leave()
else:
_on_resume_pressed()