class_name ControlsModal extends Control ## Controls & Keybindings Guide Modal. ## ## Displays keyboard and mouse bindings clearly in-game and from the main menu. signal closed const CONTROLS_DATA = [ {"key": "W A S D", "action": "Move character"}, {"key": "Space", "action": "Jump"}, {"key": "Mouse", "action": "Look / Rotate camera"}, {"key": "E", "action": "Interact with objects & chests"}, {"key": "T / Enter", "action": "Open In-World Chat"}, {"key": "Tab / F1", "action": "Friends & Social Panel"}, {"key": "M", "action": "Toggle Sound (Mute / Unmute)"}, {"key": "F2", "action": "Creator Studio / World Editor"}, {"key": "F11 / Alt+Enter", "action": "Toggle Fullscreen"}, {"key": "ESC", "action": "Pause Menu / Go Back / Close Modal"}, ] func _init() -> void: name = "ControlsModal" set_anchors_preset(Control.PRESET_FULL_RECT) func _ready() -> void: mouse_filter = Control.MOUSE_FILTER_STOP var bg := ColorRect.new() bg.color = Color(0.04, 0.05, 0.08, 0.88) 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(520, 0) var style := StyleBoxFlat.new() style.bg_color = Color(0.12, 0.14, 0.19, 0.98) style.border_color = Color(0.4, 0.55, 0.8, 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 = 22 style.content_margin_bottom = 22 panel.add_theme_stylebox_override("panel", style) center.add_child(panel) var vbox := VBoxContainer.new() vbox.add_theme_constant_override("separation", 16) panel.add_child(vbox) var title := Label.new() title.text = "Keyboard & Mouse Controls" title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER title.add_theme_font_size_override("font_size", 22) title.add_theme_color_override("font_color", Color(1.0, 1.0, 1.0)) vbox.add_child(title) var grid := GridContainer.new() grid.columns = 2 grid.add_theme_constant_override("h_separation", 24) grid.add_theme_constant_override("v_separation", 10) vbox.add_child(grid) for item in CONTROLS_DATA: var key_lbl := Label.new() key_lbl.text = item["key"] key_lbl.add_theme_font_size_override("font_size", 14) key_lbl.add_theme_color_override("font_color", Color(0.95, 0.8, 0.3)) key_lbl.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN grid.add_child(key_lbl) var action_lbl := Label.new() action_lbl.text = item["action"] action_lbl.add_theme_font_size_override("font_size", 14) action_lbl.add_theme_color_override("font_color", Color(0.85, 0.9, 0.95)) action_lbl.size_flags_horizontal = Control.SIZE_EXPAND_FILL grid.add_child(action_lbl) var close_btn := Button.new() close_btn.text = "Close (ESC)" close_btn.custom_minimum_size = Vector2(140, 36) close_btn.size_flags_horizontal = Control.SIZE_SHRINK_CENTER close_btn.pressed.connect(_on_close_pressed) vbox.add_child(close_btn) func _on_close_pressed() -> void: closed.emit() queue_free() func _unhandled_input(event: InputEvent) -> void: if event.is_action_pressed("ui_cancel"): get_viewport().set_input_as_handled() _on_close_pressed()