From b780bb5a2cd80785f3d2730c17baa8037b9cc89f Mon Sep 17 00:00:00 2001 From: Rob Kelly Date: Sun, 8 Dec 2024 20:55:24 -0700 Subject: [PATCH] Settings control menu allows rebinding controls --- assets/text/text.csv | 2 + project.godot | 50 ++++++------ src/ui/main_theme.tres | 5 ++ .../control_binding/control_binding.gd | 76 ++++++++++++++++++- .../control_binding/control_binding.tscn | 20 +---- src/util/prompt_map.gd | 8 +- 6 files changed, 115 insertions(+), 46 deletions(-) diff --git a/assets/text/text.csv b/assets/text/text.csv index 455bc02..2f9a7c2 100644 --- a/assets/text/text.csv +++ b/assets/text/text.csv @@ -1,4 +1,6 @@ keys,en +UI_UNSET,unset +UI_LISTEN,listening... ACTION_camera_forward,"Forward (free camera)" ACTION_camera_back,"Backward (free camera)" ACTION_camera_left,"Left (free camera)" diff --git a/project.godot b/project.godot index ccf16b9..36ba6ec 100644 --- a/project.godot +++ b/project.godot @@ -163,6 +163,31 @@ select_putter={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":53,"key_label":0,"unicode":53,"location":0,"echo":false,"script":null) ] } +club_next={ +"deadzone": 0.5, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(105, 13),"global_position":Vector2(114, 59),"factor":1.0,"button_index":8,"canceled":false,"pressed":true,"double_click":false,"script":null) +] +} +club_previous={ +"deadzone": 0.5, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(277, 2),"global_position":Vector2(286, 48),"factor":1.0,"button_index":9,"canceled":false,"pressed":true,"double_click":false,"script":null) +] +} +ball_next={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194306,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} +ball_previous={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194306,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} +pause={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} debug_1={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194332,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) @@ -183,30 +208,9 @@ debug_4={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194335,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) ] } -pause={ +debug_5={ "deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) -] -} -ball_next={ -"deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194306,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) -] -} -ball_previous={ -"deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194306,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) -] -} -club_next={ -"deadzone": 0.5, -"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(105, 13),"global_position":Vector2(114, 59),"factor":1.0,"button_index":8,"canceled":false,"pressed":true,"double_click":false,"script":null) -] -} -club_previous={ -"deadzone": 0.5, -"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(277, 2),"global_position":Vector2(286, 48),"factor":1.0,"button_index":9,"canceled":false,"pressed":true,"double_click":false,"script":null) -] +"events": [] } [internationalization] diff --git a/src/ui/main_theme.tres b/src/ui/main_theme.tres index 10b3413..9c18625 100644 --- a/src/ui/main_theme.tres +++ b/src/ui/main_theme.tres @@ -80,6 +80,11 @@ HeaderMedium/font_sizes/font_size = 24 HeaderSmall/font_sizes/font_size = 20 HeaderXLarge/base_type = &"Label" HeaderXLarge/font_sizes/font_size = 36 +InputBindButton/base_type = &"UIButton" +InputBindButton/colors/font_color = Color(1, 1, 0.870588, 1) +InputBindButton/constants/outline_size = 8 +InputBindButton/font_sizes/font_size = 32 +InputBindButton/fonts/font = ExtResource("2_8kux8") InputPrompt/base_type = &"Label" InputPrompt/colors/font_color = Color(1, 1, 0.870588, 1) InputPrompt/constants/outline_size = 8 diff --git a/src/ui/menus/settings_menu/control_binding/control_binding.gd b/src/ui/menus/settings_menu/control_binding/control_binding.gd index d9e7b6b..53e60a5 100644 --- a/src/ui/menus/settings_menu/control_binding/control_binding.gd +++ b/src/ui/menus/settings_menu/control_binding/control_binding.gd @@ -2,12 +2,21 @@ class_name ControlBinding extends CheckerContainer ## Input for rebinding an action. const ACTION_KEY_FMT := "ACTION_{0}" +const LISTENING_TEXT := "UI_LISTEN" const SCENE := preload("res://src/ui/menus/settings_menu/control_binding/control_binding.tscn") +const MOTION_THRESHOLD := 0.5 + @export var key: StringName +var listening: bool = false: + set(value): + if button: + button.disabled = value + listening = value + @onready var action: Label = %Action -@onready var binding: Label = %Binding +@onready var button: Button = %Button func _ready() -> void: @@ -21,10 +30,73 @@ func _ready() -> void: action.text = loc_action if loc_action else key # Set the binding label + _set_label_from_binding() + + +func _set_label_from_binding() -> void: var actions := InputMap.action_get_events(key) if actions: var primary := actions[0] - binding.text = PromptMap.from_event(primary) + button.text = PromptMap.from_event(primary) + if button.text == PromptMap.UNKNOWN_INPUT_SYMBOL: + print_debug("No mapping for input event: ", primary) + # Special case: Can't rebind things bound to ESC + if primary is InputEventKey and (primary as InputEventKey).physical_keycode == KEY_ESCAPE: + button.disabled = true + + +func _input(event: InputEvent) -> void: + if not listening: + return + + if event is InputEventKey: + var key_event: InputEventKey = event + if ( + key_event.physical_keycode in [KEY_CTRL, KEY_ALT, KEY_SHIFT, KEY_META] + and key_event.pressed + ): + # Ignore modifier key until release + return + if key_event.physical_keycode == KEY_ESCAPE: + get_viewport().set_input_as_handled() + cancel_rebinding() + return + + if event is InputEventJoypadMotion: + var motion_event: InputEventJoypadMotion = event + if abs(motion_event.axis_value) < MOTION_THRESHOLD: + # Ignore axis motion unless it's over our threshold + return + + if ( + event is InputEventKey + or event is InputEventMouseButton + or event is InputEventJoypadButton + or event is InputEventJoypadMotion + ): + get_viewport().set_input_as_handled() + rebind(event) + + +func start_listening() -> void: + button.text = LISTENING_TEXT + listening = true + + +func cancel_rebinding() -> void: + _set_label_from_binding() + listening = false + + +func rebind(event: InputEvent) -> void: + # Clear previous binding + InputMap.action_erase_events(key) + # Add new binding + InputMap.action_add_event(key, event) + # Update label + _set_label_from_binding() + + listening = false static func create(_key: StringName) -> ControlBinding: diff --git a/src/ui/menus/settings_menu/control_binding/control_binding.tscn b/src/ui/menus/settings_menu/control_binding/control_binding.tscn index f7f1ab0..2cb8744 100644 --- a/src/ui/menus/settings_menu/control_binding/control_binding.tscn +++ b/src/ui/menus/settings_menu/control_binding/control_binding.tscn @@ -28,21 +28,7 @@ text = "Action" unique_name_in_owner = true custom_minimum_size = Vector2(300, 42) layout_mode = 2 +theme_type_variation = &"InputBindButton" +text = "UI_UNSET" -[node name="Binding" type="Label" parent="MarginContainer/HBoxContainer/Button"] -unique_name_in_owner = true -layout_mode = 1 -anchors_preset = 8 -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -offset_left = -13.0 -offset_top = -19.5 -offset_right = 13.0 -offset_bottom = 19.5 -grow_horizontal = 2 -grow_vertical = 2 -theme_type_variation = &"InputPrompt" -text = "unset" -horizontal_alignment = 1 +[connection signal="pressed" from="MarginContainer/HBoxContainer/Button" to="." method="start_listening"] diff --git a/src/util/prompt_map.gd b/src/util/prompt_map.gd index 1781657..d5f6d97 100644 --- a/src/util/prompt_map.gd +++ b/src/util/prompt_map.gd @@ -96,10 +96,10 @@ const MOUSE := { MOUSE_BUTTON_LEFT: PromptFont.MOUSE_1, MOUSE_BUTTON_RIGHT: PromptFont.MOUSE_2, MOUSE_BUTTON_MIDDLE: PromptFont.MOUSE_3, - MOUSE_BUTTON_XBUTTON1: PromptFont.MOUSE_4, - MOUSE_BUTTON_XBUTTON2: PromptFont.MOUSE_5, - # PromptFont.MOUSE_6, - # PromptFont.MOUSE_7, + MOUSE_BUTTON_WHEEL_LEFT: PromptFont.MOUSE_4, + MOUSE_BUTTON_WHEEL_RIGHT: PromptFont.MOUSE_5, + MOUSE_BUTTON_XBUTTON1: PromptFont.MOUSE_6, + MOUSE_BUTTON_XBUTTON2: PromptFont.MOUSE_7, # PromptFont.MOUSE_8, MOUSE_BUTTON_WHEEL_UP: PromptFont.MOUSE_SCROLL_UP, MOUSE_BUTTON_WHEEL_DOWN: PromptFont.MOUSE_SCROLL_DOWN