From a76d9471f41dac2926cfe5054fb6254404a7d4c2 Mon Sep 17 00:00:00 2001 From: Henrique Campos Date: Wed, 12 Feb 2020 19:42:12 -0300 Subject: [PATCH] Add a simplified version of input remapping --- gui/input_mapping/ActionRemapButton.gd | 35 +++++ gui/input_mapping/ActionRemapButton.tscn | 12 ++ gui/input_mapping/InputRemapMenu.tscn | 173 +++++++++++++++++++++++ gui/input_mapping/controls.gd | 102 ------------- gui/input_mapping/controls.tscn | 153 -------------------- gui/input_mapping/project.godot | 28 ++-- 6 files changed, 234 insertions(+), 269 deletions(-) create mode 100644 gui/input_mapping/ActionRemapButton.gd create mode 100644 gui/input_mapping/ActionRemapButton.tscn create mode 100644 gui/input_mapping/InputRemapMenu.tscn delete mode 100644 gui/input_mapping/controls.gd delete mode 100644 gui/input_mapping/controls.tscn diff --git a/gui/input_mapping/ActionRemapButton.gd b/gui/input_mapping/ActionRemapButton.gd new file mode 100644 index 00000000..94b6491d --- /dev/null +++ b/gui/input_mapping/ActionRemapButton.gd @@ -0,0 +1,35 @@ +extends Button + +export(String) var action = "ui_up" + +func _ready(): + assert(InputMap.has_action(action)) + set_process_unhandled_key_input(false) + display_current_key() + + +func _toggled(button_pressed): + set_process_unhandled_key_input(button_pressed) + if button_pressed: + text = "... Key" + release_focus() + else: + display_current_key() + + +func _unhandled_key_input(event): + # Note that you can use the _input callback instead, especially if + # you want to work with gamepads. + remap_action_to(event) + pressed = false + + +func remap_action_to(event): + InputMap.action_erase_events(action) + InputMap.action_add_event(action, event) + text = "%s Key" % event.as_text() + + +func display_current_key(): + var current_key = InputMap.get_action_list(action)[0].as_text() + text = "%s Key" % current_key diff --git a/gui/input_mapping/ActionRemapButton.tscn b/gui/input_mapping/ActionRemapButton.tscn new file mode 100644 index 00000000..79604c18 --- /dev/null +++ b/gui/input_mapping/ActionRemapButton.tscn @@ -0,0 +1,12 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://ActionRemapButton.gd" type="Script" id=1] + +[node name="ActionRemapButton" type="Button"] +margin_right = 90.0 +margin_bottom = 30.0 +toggle_mode = true +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} diff --git a/gui/input_mapping/InputRemapMenu.tscn b/gui/input_mapping/InputRemapMenu.tscn new file mode 100644 index 00000000..8a4462ab --- /dev/null +++ b/gui/input_mapping/InputRemapMenu.tscn @@ -0,0 +1,173 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://ActionRemapButton.tscn" type="PackedScene" id=1] + +[sub_resource type="ButtonGroup" id=1] + +[node name="InputRemapMenu" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 + +[node name="Instructions" type="Label" parent="."] +anchor_right = 1.0 +margin_top = 24.0 +margin_bottom = 55.0 +text = "Click on a button to reassign its action key." +align = 1 +autowrap = true +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="RemapButtonGroup" type="Button" parent="."] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -160.0 +margin_top = -144.0 +margin_right = 160.0 +margin_bottom = 144.0 +disabled = true +group = SubResource( 1 ) +flat = true +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="ActionsList" type="VBoxContainer" parent="RemapButtonGroup"] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -160.0 +margin_top = -140.0 +margin_right = 160.0 +margin_bottom = 140.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="ActionRemapRow" type="HBoxContainer" parent="RemapButtonGroup/ActionsList"] +margin_right = 320.0 +margin_bottom = 52.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="ActionName" type="Label" parent="RemapButtonGroup/ActionsList/ActionRemapRow"] +margin_right = 158.0 +margin_bottom = 52.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +text = "Move Left" +align = 1 +valign = 1 + +[node name="RemapButton" parent="RemapButtonGroup/ActionsList/ActionRemapRow" instance=ExtResource( 1 )] +margin_left = 162.0 +margin_right = 320.0 +margin_bottom = 52.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +group = SubResource( 1 ) +action = "move_left" + +[node name="ActionRemapRow2" type="HBoxContainer" parent="RemapButtonGroup/ActionsList"] +margin_top = 56.0 +margin_right = 320.0 +margin_bottom = 108.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="ActionName" type="Label" parent="RemapButtonGroup/ActionsList/ActionRemapRow2"] +margin_right = 158.0 +margin_bottom = 52.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +text = "Move Right" +align = 1 +valign = 1 + +[node name="RemapButton" parent="RemapButtonGroup/ActionsList/ActionRemapRow2" instance=ExtResource( 1 )] +margin_left = 162.0 +margin_right = 320.0 +margin_bottom = 52.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +group = SubResource( 1 ) +action = "move_right" + +[node name="ActionRemapRow3" type="HBoxContainer" parent="RemapButtonGroup/ActionsList"] +margin_top = 112.0 +margin_right = 320.0 +margin_bottom = 164.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="ActionName" type="Label" parent="RemapButtonGroup/ActionsList/ActionRemapRow3"] +margin_right = 158.0 +margin_bottom = 52.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +text = "Look Up" +align = 1 +valign = 1 + +[node name="RemapButton" parent="RemapButtonGroup/ActionsList/ActionRemapRow3" instance=ExtResource( 1 )] +margin_left = 162.0 +margin_right = 320.0 +margin_bottom = 52.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +group = SubResource( 1 ) +action = "look_up" + +[node name="ActionRemapRow4" type="HBoxContainer" parent="RemapButtonGroup/ActionsList"] +margin_top = 168.0 +margin_right = 320.0 +margin_bottom = 220.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="ActionName" type="Label" parent="RemapButtonGroup/ActionsList/ActionRemapRow4"] +margin_right = 158.0 +margin_bottom = 52.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +text = "Crouch" +align = 1 +valign = 1 + +[node name="RemapButton" parent="RemapButtonGroup/ActionsList/ActionRemapRow4" instance=ExtResource( 1 )] +margin_left = 162.0 +margin_right = 320.0 +margin_bottom = 52.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +group = SubResource( 1 ) +action = "crouch" + +[node name="ActionRemapRow5" type="HBoxContainer" parent="RemapButtonGroup/ActionsList"] +margin_top = 224.0 +margin_right = 320.0 +margin_bottom = 280.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="ActionName" type="Label" parent="RemapButtonGroup/ActionsList/ActionRemapRow5"] +margin_right = 158.0 +margin_bottom = 56.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +text = "Dash" +align = 1 +valign = 1 + +[node name="RemapButton" parent="RemapButtonGroup/ActionsList/ActionRemapRow5" instance=ExtResource( 1 )] +margin_left = 162.0 +margin_right = 320.0 +margin_bottom = 56.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +group = SubResource( 1 ) +action = "dash" diff --git a/gui/input_mapping/controls.gd b/gui/input_mapping/controls.gd deleted file mode 100644 index dc5c3431..00000000 --- a/gui/input_mapping/controls.gd +++ /dev/null @@ -1,102 +0,0 @@ -extends Control - -# Note for the reader: -# -# This demo conveniently uses the same names for actions and for the container nodes -# that hold each remapping button. This allow to get back to the button based simply -# on the name of the corresponding action, but it might not be so simple in your project. -# -# A better approach for large-scale input remapping might be to do the connections between -# buttons and wait_for_input through the code, passing as arguments both the name of the -# action and the node, e.g.: -# button.connect("pressed", self, "wait_for_input", [ button, action ]) - -const INPUT_ACTIONS = [ "move_up", "move_down", "move_left", "move_right", "jump" ] -const CONFIG_FILE = "user://input.cfg" - -var action # To register the action the UI is currently handling -var button # Button node corresponding to the above action - -onready var bindings = $Bindings -onready var contextual_help = $ContextualHelp - -func _ready(): - # Load config if existing, if not it will be generated with default values - load_config() - # Initialise each button with the default key binding from InputMap - for action in INPUT_ACTIONS: - # We assume that the key binding that we want is the first one (0), if there are several - var input_event = InputMap.get_action_list(action)[0] - # See note at the beginning of the script - var button = bindings.get_node(action).get_node("Button") - button.text = OS.get_scancode_string(input_event.scancode) - button.connect("pressed", self, "wait_for_input", [action]) - - # Do not start processing input until a button is pressed - set_process_input(false) - - -# Input management -func _input(event): - # Handle the first pressed key - if event is InputEventKey: - # Register the event as handled and stop polling - get_tree().set_input_as_handled() - set_process_input(false) - # Reinitialise the contextual help label - contextual_help.text = "Click a key binding to reassign it, or press the Cancel action." - if not event.is_action("ui_cancel"): - # Display the string corresponding to the pressed key - var scancode = OS.get_scancode_string(event.scancode) - button.text = scancode - # Start by removing previously key binding(s) - for old_event in InputMap.get_action_list(action): - InputMap.action_erase_event(action, old_event) - # Add the new key binding - InputMap.action_add_event(action, event) - save_to_config("input", action, scancode) - - -func wait_for_input(action_bind): - action = action_bind - # See note at the beginning of the script - button = bindings.get_node(action).get_node("Button") - contextual_help.text = "Press a key to assign to the '" + action + "' action." - set_process_input(true) - - -# Load/save input mapping to a config file -# Changes done while testing the demo will be persistent, saved to CONFIG_FILE -func load_config(): - var config = ConfigFile.new() - var err = config.load(CONFIG_FILE) - if err: # Assuming that file is missing, generate default config - for action_name in INPUT_ACTIONS: - var action_list = InputMap.get_action_list(action_name) - # There could be multiple actions in the list, but we save the first one by default - var scancode = OS.get_scancode_string(action_list[0].scancode) - config.set_value("input", action_name, scancode) - config.save(CONFIG_FILE) - else: # ConfigFile was properly loaded, initialize InputMap - for action_name in config.get_section_keys("input"): - # Get the key scancode corresponding to the saved human-readable string - var scancode = OS.find_scancode_from_string(config.get_value("input", action_name)) - # Create a new event object based on the saved scancode - var event = InputEventKey.new() - event.scancode = scancode - # Replace old action (key) events by the new one - for old_event in InputMap.get_action_list(action_name): - if old_event is InputEventKey: - InputMap.action_erase_event(action_name, old_event) - InputMap.action_add_event(action_name, event) - - -func save_to_config(section, key, value): - # Helper function to redefine a parameter in the settings file. - var config = ConfigFile.new() - var err = config.load(CONFIG_FILE) - if err: - print("Error code when loading config file: ", err) - else: - config.set_value(section, key, value) - config.save(CONFIG_FILE) diff --git a/gui/input_mapping/controls.tscn b/gui/input_mapping/controls.tscn deleted file mode 100644 index 21b9d802..00000000 --- a/gui/input_mapping/controls.tscn +++ /dev/null @@ -1,153 +0,0 @@ -[gd_scene load_steps=2 format=2] - -[ext_resource path="res://controls.gd" type="Script" id=1] - -[node name="Controls" type="Control"] -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -margin_left = -320.0 -margin_top = -240.0 -margin_right = 320.0 -margin_bottom = 240.0 -size_flags_horizontal = 2 -size_flags_vertical = 2 -script = ExtResource( 1 ) -__meta__ = { -"__editor_plugin_screen__": "2D", -"_edit_use_anchors_": false -} - -[node name="ContextualHelp" type="Label" parent="."] -margin_left = 130.0 -margin_top = 100.0 -margin_right = 533.0 -margin_bottom = 139.0 -size_flags_horizontal = 2 -size_flags_vertical = 0 -text = "Click on a key binding to reassign it, or press the Cancel action." -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="Bindings" type="VBoxContainer" parent="."] -margin_left = 150.0 -margin_top = 150.0 -margin_right = 350.0 -margin_bottom = 450.0 -size_flags_horizontal = 2 -size_flags_vertical = 2 - -[node name="move_up" type="Control" parent="Bindings"] -size_flags_horizontal = 2 -size_flags_vertical = 2 - -[node name="Label" type="Label" parent="Bindings/move_up"] -margin_left = 5.0 -margin_top = 8.0 -margin_right = 45.0 -margin_bottom = 21.0 -size_flags_horizontal = 2 -size_flags_vertical = 0 -text = "Up" - -[node name="Button" type="Button" parent="Bindings/move_up"] -margin_left = 84.0 -margin_top = -1.0 -margin_right = 144.0 -margin_bottom = 29.0 -size_flags_horizontal = 2 -size_flags_vertical = 2 - -[node name="move_down" type="Control" parent="Bindings"] -margin_top = 60.0 -margin_bottom = 60.0 -size_flags_horizontal = 2 -size_flags_vertical = 2 - -[node name="Label" type="Label" parent="Bindings/move_down"] -margin_left = 5.0 -margin_top = 8.0 -margin_right = 45.0 -margin_bottom = 21.0 -size_flags_horizontal = 2 -size_flags_vertical = 0 -text = "Down" - -[node name="Button" type="Button" parent="Bindings/move_down"] -margin_left = 84.0 -margin_top = -1.0 -margin_right = 144.0 -margin_bottom = 29.0 -size_flags_horizontal = 2 -size_flags_vertical = 2 - -[node name="move_left" type="Control" parent="Bindings"] -margin_top = 120.0 -margin_bottom = 120.0 -size_flags_horizontal = 2 -size_flags_vertical = 2 - -[node name="Label" type="Label" parent="Bindings/move_left"] -margin_left = 5.0 -margin_top = 8.0 -margin_right = 45.0 -margin_bottom = 21.0 -size_flags_horizontal = 2 -size_flags_vertical = 0 -text = "Left" - -[node name="Button" type="Button" parent="Bindings/move_left"] -margin_left = 84.0 -margin_top = -1.0 -margin_right = 144.0 -margin_bottom = 29.0 -size_flags_horizontal = 2 -size_flags_vertical = 2 - -[node name="move_right" type="Control" parent="Bindings"] -margin_top = 180.0 -margin_bottom = 180.0 -size_flags_horizontal = 2 -size_flags_vertical = 2 - -[node name="Label" type="Label" parent="Bindings/move_right"] -margin_left = 5.0 -margin_top = 8.0 -margin_right = 45.0 -margin_bottom = 21.0 -size_flags_horizontal = 2 -size_flags_vertical = 0 -text = "Right" - -[node name="Button" type="Button" parent="Bindings/move_right"] -margin_left = 84.0 -margin_top = -1.0 -margin_right = 144.0 -margin_bottom = 29.0 -size_flags_horizontal = 2 -size_flags_vertical = 2 - -[node name="jump" type="Control" parent="Bindings"] -margin_top = 240.0 -margin_bottom = 240.0 -size_flags_horizontal = 2 -size_flags_vertical = 2 - -[node name="Label" type="Label" parent="Bindings/jump"] -margin_left = 5.0 -margin_top = 8.0 -margin_right = 45.0 -margin_bottom = 21.0 -size_flags_horizontal = 2 -size_flags_vertical = 0 -text = "Jump" - -[node name="Button" type="Button" parent="Bindings/jump"] -margin_left = 84.0 -margin_top = -1.0 -margin_right = 144.0 -margin_bottom = 29.0 -size_flags_horizontal = 2 -size_flags_vertical = 2 diff --git a/gui/input_mapping/project.godot b/gui/input_mapping/project.godot index 80709800..2473c6d7 100644 --- a/gui/input_mapping/project.godot +++ b/gui/input_mapping/project.godot @@ -16,7 +16,7 @@ _global_script_class_icons={ [application] config/name="Input Mapping GUI" -run/main_scene="res://controls.tscn" +run/main_scene="res://InputRemapMenu.tscn" config/icon="res://icon.png" [display] @@ -32,14 +32,9 @@ singletons=[ ] [input] -jump={ +move_right={ "deadzone": 0.5, -"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"unicode":0,"echo":false,"script":null) - ] -} -move_down={ -"deadzone": 0.5, -"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777234,"unicode":0,"echo":false,"script":null) +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"unicode":0,"echo":false,"script":null) ] } move_left={ @@ -47,13 +42,18 @@ move_left={ "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777231,"unicode":0,"echo":false,"script":null) ] } -move_right={ -"deadzone": 0.5, -"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"unicode":0,"echo":false,"script":null) - ] -} -move_up={ +look_up={ "deadzone": 0.5, "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777232,"unicode":0,"echo":false,"script":null) ] } +crouch={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777234,"unicode":0,"echo":false,"script":null) + ] +} +dash={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777237,"unicode":0,"echo":false,"script":null) + ] +}