1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
|
extends ConfirmationDialog
enum InputTypes { KEYBOARD, MOUSE, JOY_BUTTON, JOY_AXIS }
@export var input_type := InputTypes.KEYBOARD
var listened_input: InputEvent
@onready var root := get_parent()
@onready var input_type_l := $VBoxContainer/InputTypeLabel as Label
@onready var entered_shortcut := $VBoxContainer/EnteredShortcut as LineEdit
@onready var option_button := $VBoxContainer/OptionButton as OptionButton
@onready var modifier_buttons := $VBoxContainer/ModifierButtons as HBoxContainer
@onready var alt_button := $VBoxContainer/ModifierButtons/Alt as CheckBox
@onready var shift_button := $VBoxContainer/ModifierButtons/Shift as CheckBox
@onready var control_button := $VBoxContainer/ModifierButtons/Control as CheckBox
@onready var meta_button := $VBoxContainer/ModifierButtons/Meta as CheckBox
@onready var command_control_button := $VBoxContainer/ModifierButtons/CommandOrControl as CheckBox
@onready var already_exists := $VBoxContainer/AlreadyExistsLabel as Label
func _ready() -> void:
set_process_input(false)
if input_type == InputTypes.KEYBOARD:
entered_shortcut.visible = true
option_button.visible = false
get_ok_button().focus_neighbor_top = entered_shortcut.get_path()
get_cancel_button().focus_neighbor_top = entered_shortcut.get_path()
entered_shortcut.focus_neighbor_bottom = get_ok_button().get_path()
else:
if input_type != InputTypes.MOUSE:
modifier_buttons.visible = false
get_ok_button().focus_neighbor_top = option_button.get_path()
get_cancel_button().focus_neighbor_top = option_button.get_path()
option_button.focus_neighbor_bottom = get_ok_button().get_path()
# get_close_button().focus_mode = Control.FOCUS_NONE
func _input(event: InputEvent) -> void:
if not event is InputEventKey:
return
if event.pressed:
listened_input = event
_set_modifier_buttons_state(listened_input)
entered_shortcut.text = event.as_text()
_show_assigned_state(event)
func _show_assigned_state(event: InputEvent) -> void:
var metadata = root.currently_editing_tree_item.get_metadata(0)
var action := ""
if metadata is InputEvent: # Editing an input event
action = root.currently_editing_tree_item.get_parent().get_metadata(0)
elif metadata is StringName: # Adding a new input event to an action
action = metadata
var matching_pair: Array = _find_matching_event_in_map(action, event)
if matching_pair:
already_exists.text = tr("Already assigned to: %s") % root.get_action_name(matching_pair[0])
else:
already_exists.text = ""
func _on_ShortcutSelectorDialog_confirmed() -> void:
if listened_input == null:
return
_apply_shortcut_change(listened_input)
func _apply_shortcut_change(input_event: InputEvent) -> void:
var metadata = root.currently_editing_tree_item.get_metadata(0)
if metadata is InputEvent: # Editing an input event
var parent_metadata = root.currently_editing_tree_item.get_parent().get_metadata(0)
var changed: bool = _set_shortcut(parent_metadata, metadata, input_event)
if !changed:
return
root.currently_editing_tree_item.set_metadata(0, input_event)
root.currently_editing_tree_item.set_text(0, root.event_to_str(input_event))
elif metadata is StringName: # Adding a new input event to an action
var changed: bool = _set_shortcut(metadata, null, input_event)
if !changed:
return
root.add_event_tree_item(input_event, root.currently_editing_tree_item)
func _set_shortcut(action: StringName, old_event: InputEvent, new_event: InputEvent) -> bool:
if InputMap.action_has_event(action, new_event): # If the current action already has that event
return false
if old_event:
Keychain.action_erase_event(action, old_event)
# Loop through other actions to see if the event exists there, to re-assign it
var matching_pair := _find_matching_event_in_map(action, new_event)
if matching_pair:
var group := ""
if action in Keychain.actions:
group = Keychain.actions[action].group
var action_to_replace: StringName = matching_pair[0]
var input_to_replace: InputEvent = matching_pair[1]
Keychain.action_erase_event(action_to_replace, input_to_replace)
Keychain.selected_profile.change_action(action_to_replace)
var tree_item: TreeItem = root.tree.get_root()
var prev_tree_item: TreeItem
while tree_item != null: # Loop through Tree's TreeItems...
var metadata = tree_item.get_metadata(0)
if metadata is InputEvent:
if input_to_replace.is_match(metadata):
var map_action: StringName = tree_item.get_parent().get_metadata(0)
if map_action == action_to_replace:
tree_item.free()
break
tree_item = tree_item.get_next_in_tree()
Keychain.action_add_event(action, new_event)
Keychain.selected_profile.change_action(action)
return true
func _find_matching_event_in_map(action: StringName, event: InputEvent) -> Array:
var group := ""
if action in Keychain.actions:
group = Keychain.actions[action].group
for map_action in InputMap.get_actions():
if map_action in Keychain.ignore_actions:
continue
if Keychain.ignore_ui_actions and (map_action as String).begins_with("ui_"):
continue
for map_event in InputMap.action_get_events(map_action):
if !event.is_match(map_event):
continue
if map_action in Keychain.actions:
# If it's local, check if it's the same group, otherwise ignore
if !Keychain.actions[action].global or !Keychain.actions[map_action].global:
if Keychain.actions[map_action].group != group:
continue
return [map_action, map_event]
return []
func _on_ShortcutSelectorDialog_about_to_show() -> void:
var metadata = root.currently_editing_tree_item.get_metadata(0)
if input_type == InputTypes.KEYBOARD:
listened_input = null
already_exists.text = ""
entered_shortcut.text = ""
if metadata is InputEvent:
_set_modifier_buttons_state(metadata)
await get_tree().process_frame
entered_shortcut.grab_focus()
else:
if metadata is InputEvent: # Editing an input event
var index := 0
if metadata is InputEventMouseButton:
index = metadata.button_index - 1
_set_modifier_buttons_state(metadata)
elif metadata is InputEventJoypadButton:
index = metadata.button_index
elif metadata is InputEventJoypadMotion:
index = metadata.axis * 2
index += signi(metadata.axis_value) / 2.0 + 0.5
option_button.select(index)
_on_OptionButton_item_selected(index)
elif metadata is StringName: # Adding a new input event to an action
option_button.select(0)
_on_OptionButton_item_selected(0)
func _on_ShortcutSelectorDialog_popup_hide() -> void:
set_process_input(false)
func _on_OptionButton_item_selected(index: int) -> void:
if input_type == InputTypes.MOUSE:
listened_input = InputEventMouseButton.new()
listened_input.button_index = index + 1
listened_input.alt_pressed = alt_button.button_pressed
listened_input.shift_pressed = shift_button.button_pressed
listened_input.ctrl_pressed = control_button.button_pressed
listened_input.meta_pressed = meta_button.button_pressed
listened_input.command_or_control_autoremap = command_control_button.button_pressed
elif input_type == InputTypes.JOY_BUTTON:
listened_input = InputEventJoypadButton.new()
listened_input.button_index = index
elif input_type == InputTypes.JOY_AXIS:
listened_input = InputEventJoypadMotion.new()
listened_input.axis = index / 2
listened_input.axis_value = -1.0 if index % 2 == 0 else 1.0
_show_assigned_state(listened_input)
func _on_EnteredShortcut_focus_entered() -> void:
set_process_input(true)
func _on_EnteredShortcut_focus_exited() -> void:
set_process_input(false)
func _on_alt_toggled(button_pressed: bool) -> void:
if not is_instance_valid(listened_input):
return
listened_input.alt_pressed = button_pressed
entered_shortcut.text = listened_input.as_text()
func _set_modifier_buttons_state(event: InputEventWithModifiers) -> void:
alt_button.button_pressed = event.alt_pressed
shift_button.button_pressed = event.shift_pressed
control_button.button_pressed = event.ctrl_pressed
meta_button.button_pressed = event.meta_pressed
command_control_button.button_pressed = event.command_or_control_autoremap
func _on_shift_toggled(button_pressed: bool) -> void:
if not is_instance_valid(listened_input):
return
listened_input.shift_pressed = button_pressed
entered_shortcut.text = listened_input.as_text()
func _on_control_toggled(button_pressed: bool) -> void:
if not is_instance_valid(listened_input):
return
listened_input.ctrl_pressed = button_pressed
entered_shortcut.text = listened_input.as_text()
func _on_meta_toggled(button_pressed: bool) -> void:
if not is_instance_valid(listened_input):
return
listened_input.meta_pressed = button_pressed
entered_shortcut.text = listened_input.as_text()
func _on_command_or_control_toggled(button_pressed: bool) -> void:
control_button.button_pressed = false
meta_button.button_pressed = false
control_button.visible = not button_pressed
meta_button.visible = not button_pressed
if not is_instance_valid(listened_input):
return
listened_input.command_or_control_autoremap = button_pressed
entered_shortcut.text = listened_input.as_text()
|