From 9849c9edb9713cb1b3a5b27631f9ce06aae125ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Sat, 23 Sep 2017 20:35:54 +0200 Subject: [PATCH] Input mapping: Add code to load/save config --- gui/input_mapping/controls.gd | 67 +++++- gui/input_mapping/controls.scn | Bin 954 -> 0 bytes gui/input_mapping/controls.tscn | 348 ++++++++++++++++++++++++++++++ gui/input_mapping/icon.png.import | 1 + gui/input_mapping/project.godot | 19 +- 5 files changed, 419 insertions(+), 16 deletions(-) delete mode 100644 gui/input_mapping/controls.scn create mode 100644 gui/input_mapping/controls.tscn diff --git a/gui/input_mapping/controls.gd b/gui/input_mapping/controls.gd index d1ba10d7..3eb5b6f9 100644 --- a/gui/input_mapping/controls.gd +++ b/gui/input_mapping/controls.gd @@ -1,4 +1,3 @@ - extends Control # Note for the reader: @@ -12,45 +11,91 @@ extends Control # action and the node, e.g.: # button.connect("pressed", self, "wait_for_input", [ button, action ]) +# Constants +const INPUT_ACTIONS = [ "move_up", "move_down", "move_left", "move_right", "jump" ] +const CONFIG_FILE = "user://input.cfg" + # Member variables -var player_actions = [ "move_up", "move_down", "move_left", "move_right", "jump" ] var action # To register the action the UI is currently handling var button # Button node corresponding to the above action +# 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) + + +# Input management + func wait_for_input(action_bind): action = action_bind # See note at the beginning of the script button = get_node("bindings").get_node(action).get_node("Button") - get_node("contextual_help").text="Press a key to assign to the '" + action + "' action." + get_node("contextual_help").text = "Press a key to assign to the '" + action + "' action." set_process_input(true) func _input(event): # Handle the first pressed key - if (event is InputEventKey): + 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 - get_node("contextual_help").text="Click a key binding to reassign it, or press the Cancel action." - if (not event.is_action("ui_cancel")): + get_node("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 - button.text=OS.get_scancode_string(event.scancode) + 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 _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 - var input_event - for action in player_actions: + for action in INPUT_ACTIONS: # We assume that the key binding that we want is the first one (0), if there are several - input_event = InputMap.get_action_list(action)[0] + var input_event = InputMap.get_action_list(action)[0] # See note at the beginning of the script var button = get_node("bindings").get_node(action).get_node("Button") - button.text=OS.get_scancode_string(input_event.scancode) + button.text = OS.get_scancode_string(input_event.scancode) button.connect("pressed", self, "wait_for_input", [action]) diff --git a/gui/input_mapping/controls.scn b/gui/input_mapping/controls.scn deleted file mode 100644 index d2a80d390a0295897e11bf241e6e053e3f995777..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 954 zcmV;r14aB&Q$s@n000005C8y#4FCY50{{RhwJ-f(gbc+T04An-KR~I506bVATEr9p zNm_u}QvkAR#xTn7r|>;3R@46NKTXNon}bL}N$1N|ffh0=T7m)q6azsJTup@)w#eNB zUI1bMW&q8jiFc`bQsb*+GyV7cT?+C)_9&j zt2bv`$+#Jtuqv#v$V|mOC<$%MTioZl6W^rx>#0yxt3g-^Kwj5YT>BG{eSVL*rW@qiaT<5B9s)A$ZyI$^^8wT z-7I~K>^>nM0_>wRpab&Z!SUd9aCB@oHX0j_4FQ;p02mh@jYS2;XQD!Lk@0vSIv)+D zQxO62;BZcceOh$9*y&On9Z+CFu}n@x3o=SXos+y!97BtX1%bpRq=4iND*VC*1}!3y zU%STOy4XZ)O96o5sBy_c0|Eme01*HHzyg3FA{G*0^*EOiWDJNw1mVO(5rG-77*67= z0uDCk_%PhT;>{1Y7rSYE|GZd z?x_@7*w4;fws?WfG^D@iV|$5RKV{BzJV*2!(WVgN^;{ zqY?BiT+M&Z9M?hj%|HhP(x?z%H1lX`O_&9~Y=&MBm?p+ cniePYic>=mL|$GDAA#6v(U}aC0a8;#L+4DsPXGV_ diff --git a/gui/input_mapping/controls.tscn b/gui/input_mapping/controls.tscn new file mode 100644 index 00000000..41bbe764 --- /dev/null +++ b/gui/input_mapping/controls.tscn @@ -0,0 +1,348 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://controls.gd" type="Script" id=1] + +[node name="controls_ui" type="Control"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_right = 40.0 +margin_bottom = 40.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 0 +size_flags_horizontal = 2 +size_flags_vertical = 2 +script = ExtResource( 1 ) +__meta__ = { +"__editor_plugin_screen__": "2D" +} + +[node name="contextual_help" type="Label" parent="."] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 100.0 +margin_top = 50.0 +margin_right = 465.0 +margin_bottom = 89.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 2 +size_flags_horizontal = 2 +size_flags_vertical = 0 +text = "Click on a key binding to reassign it, or press the Cancel action." +percent_visible = 1.0 +lines_skipped = 0 +max_lines_visible = -1 + +[node name="bindings" type="Control" parent="."] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 50.0 +margin_top = 50.0 +margin_right = 90.0 +margin_bottom = 90.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 0 +size_flags_horizontal = 2 +size_flags_vertical = 2 + +[node name="move_up" type="Control" parent="bindings"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 50.0 +margin_top = 50.0 +margin_right = 90.0 +margin_bottom = 90.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 0 +size_flags_horizontal = 2 +size_flags_vertical = 2 + +[node name="Label" type="Label" parent="bindings/move_up"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 5.0 +margin_top = 8.0 +margin_right = 45.0 +margin_bottom = 21.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 2 +size_flags_horizontal = 2 +size_flags_vertical = 0 +text = "Up" +percent_visible = 1.0 +lines_skipped = 0 +max_lines_visible = -1 + +[node name="Button" type="Button" parent="bindings/move_up"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 84.0 +margin_top = -1.0 +margin_right = 144.0 +margin_bottom = 29.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 0 +size_flags_horizontal = 2 +size_flags_vertical = 2 +toggle_mode = false +enabled_focus_mode = 2 +shortcut = null +group = null +flat = false + +[node name="move_down" type="Control" parent="bindings"] + +editor/display_folded = true +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 50.0 +margin_top = 100.0 +margin_right = 90.0 +margin_bottom = 140.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 0 +size_flags_horizontal = 2 +size_flags_vertical = 2 + +[node name="Label" type="Label" parent="bindings/move_down"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 5.0 +margin_top = 8.0 +margin_right = 45.0 +margin_bottom = 21.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 2 +size_flags_horizontal = 2 +size_flags_vertical = 0 +text = "Down" +percent_visible = 1.0 +lines_skipped = 0 +max_lines_visible = -1 + +[node name="Button" type="Button" parent="bindings/move_down"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 84.0 +margin_top = -1.0 +margin_right = 144.0 +margin_bottom = 29.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 0 +size_flags_horizontal = 2 +size_flags_vertical = 2 +toggle_mode = false +enabled_focus_mode = 2 +shortcut = null +group = null +flat = false + +[node name="move_left" type="Control" parent="bindings"] + +editor/display_folded = true +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 50.0 +margin_top = 150.0 +margin_right = 90.0 +margin_bottom = 190.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 0 +size_flags_horizontal = 2 +size_flags_vertical = 2 + +[node name="Label" type="Label" parent="bindings/move_left"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 5.0 +margin_top = 8.0 +margin_right = 45.0 +margin_bottom = 21.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 2 +size_flags_horizontal = 2 +size_flags_vertical = 0 +text = "Left" +percent_visible = 1.0 +lines_skipped = 0 +max_lines_visible = -1 + +[node name="Button" type="Button" parent="bindings/move_left"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 84.0 +margin_top = -1.0 +margin_right = 144.0 +margin_bottom = 29.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 0 +size_flags_horizontal = 2 +size_flags_vertical = 2 +toggle_mode = false +enabled_focus_mode = 2 +shortcut = null +group = null +flat = false + +[node name="move_right" type="Control" parent="bindings"] + +editor/display_folded = true +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 50.0 +margin_top = 200.0 +margin_right = 90.0 +margin_bottom = 240.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 0 +size_flags_horizontal = 2 +size_flags_vertical = 2 + +[node name="Label" type="Label" parent="bindings/move_right"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 5.0 +margin_top = 8.0 +margin_right = 45.0 +margin_bottom = 21.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 2 +size_flags_horizontal = 2 +size_flags_vertical = 0 +text = "Right" +percent_visible = 1.0 +lines_skipped = 0 +max_lines_visible = -1 + +[node name="Button" type="Button" parent="bindings/move_right"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 84.0 +margin_top = -1.0 +margin_right = 144.0 +margin_bottom = 29.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 0 +size_flags_horizontal = 2 +size_flags_vertical = 2 +toggle_mode = false +enabled_focus_mode = 2 +shortcut = null +group = null +flat = false + +[node name="jump" type="Control" parent="bindings"] + +editor/display_folded = true +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 50.0 +margin_top = 250.0 +margin_right = 90.0 +margin_bottom = 290.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 0 +size_flags_horizontal = 2 +size_flags_vertical = 2 + +[node name="Label" type="Label" parent="bindings/jump"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 5.0 +margin_top = 8.0 +margin_right = 45.0 +margin_bottom = 21.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 2 +size_flags_horizontal = 2 +size_flags_vertical = 0 +text = "Jump" +percent_visible = 1.0 +lines_skipped = 0 +max_lines_visible = -1 + +[node name="Button" type="Button" parent="bindings/jump"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 84.0 +margin_top = -1.0 +margin_right = 144.0 +margin_bottom = 29.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 0 +size_flags_horizontal = 2 +size_flags_vertical = 2 +toggle_mode = false +enabled_focus_mode = 2 +shortcut = null +group = null +flat = false + + diff --git a/gui/input_mapping/icon.png.import b/gui/input_mapping/icon.png.import index 627820bd..42e94a35 100644 --- a/gui/input_mapping/icon.png.import +++ b/gui/input_mapping/icon.png.import @@ -21,3 +21,4 @@ process/HDR_as_SRGB=false stream=false size_limit=0 detect_3d=true +svg/scale=1.0 diff --git a/gui/input_mapping/project.godot b/gui/input_mapping/project.godot index 0ab591c3..601c23c7 100644 --- a/gui/input_mapping/project.godot +++ b/gui/input_mapping/project.godot @@ -1,18 +1,27 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + config_version=3 [application] config/name="Input Mapping GUI" -run/main_scene="res://controls.scn" +run/main_scene="res://controls.tscn" config/icon="res://icon.png" -icon="res://icon.png" -main_scene="res://controls.scn" -name="Input Mapping GUI" [display] -window/size/height=480 window/size/width=640 +window/size/height=480 + +[gdnative] + +singletons=[ ] [input]