189 lines
6.0 KiB
GDScript
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()
|