Input mapping: Add code to load/save config

This commit is contained in:
Rémi Verschelde
2017-09-23 20:35:54 +02:00
parent f6d8ed6136
commit 9849c9edb9
5 changed files with 419 additions and 16 deletions

View File

@@ -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])

Binary file not shown.

View File

@@ -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

View File

@@ -21,3 +21,4 @@ process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View File

@@ -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]