diff --git a/project.godot b/project.godot index dc9dcd2..bdf063f 100644 --- a/project.godot +++ b/project.godot @@ -59,11 +59,6 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://addons/controller_icons/objects/TextureRect.gd" }, { -"base": "SceneTree", -"class": "CreateIcon", -"language": "GDScript", -"path": "res://Neuer Ordner/CreateIcon.gd" -}, { "base": "Actor", "class": "Enemy", "language": "GDScript", @@ -89,11 +84,6 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://src/RayCasters/RayCaster.gd" }, { -"base": "Reference", -"class": "ReplaceIcon", -"language": "GDScript", -"path": "res://Neuer Ordner/ReplaceIcon.gd" -}, { "base": "Button", "class": "SoundButton", "language": "GDScript", @@ -115,13 +105,11 @@ _global_script_class_icons={ "ControllerSprite": "", "ControllerSprite3D": "", "ControllerTextureRect": "", -"CreateIcon": "", "Enemy": "", "GlobalStateResource": "", "LevelTemplate": "", "RayCastDebugLines": "", "RayCaster": "", -"ReplaceIcon": "", "SoundButton": "", "StateMachine": "" } @@ -251,34 +239,34 @@ ui_end={ } up={ "deadzone": 0.5, -"events": [ Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"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":16777232,"physical_scancode":0,"unicode":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":87,"physical_scancode":0,"unicode":0,"echo":false,"script":null) -, 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,"physical_scancode":0,"unicode":0,"echo":false,"script":null) - ] -} -duck={ -"deadzone": 0.5, -"events": [ Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":1.0,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":83,"physical_scancode":0,"unicode":0,"echo":false,"script":null) -, 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,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null) ] } move_left={ "deadzone": 0.5, -"events": [ Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":14,"pressure":0.0,"pressed":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"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":16777231,"physical_scancode":0,"unicode":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"physical_scancode":0,"unicode":0,"echo":false,"script":null) -, 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,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null) ] } move_right={ "deadzone": 0.5, -"events": [ Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":15,"pressure":0.0,"pressed":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"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,"physical_scancode":0,"unicode":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"physical_scancode":0,"unicode":0,"echo":false,"script":null) -, 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,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":15,"pressure":0.0,"pressed":false,"script":null) + ] +} +duck={ +"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,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":83,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":1.0,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null) ] } jump={ @@ -340,7 +328,6 @@ quality/intended_usage/framebuffer_allocation.mobile=0 threads/thread_model=2 2d/options/use_software_skinning=false gles3/shaders/shader_compilation_mode=2 -gles3/shaders/shader_compilation_mode.web=2 2d/options/culling_mode=0 quality/depth/hdr=false environment/default_environment="res://default_env.tres" diff --git a/src/UserInterface/Screens/InGameMenu/ControlsMenuIngame.gd b/src/UserInterface/Screens/InGameMenu/ControlsMenuIngame.gd index f48807e..47c1bec 100644 --- a/src/UserInterface/Screens/InGameMenu/ControlsMenuIngame.gd +++ b/src/UserInterface/Screens/InGameMenu/ControlsMenuIngame.gd @@ -26,7 +26,17 @@ func rebuild(input_profile): _action_list.clear() var first = true var prev_line - for input_action in input_profile.keys(): + for order_action in $InputMapper.profile_order: + + var input_action := "" + + for action in input_profile.keys(): + if action == order_action: + input_action = action + + if input_action == "": + continue + if(input_action.ends_with("_old") || input_action.begins_with(("ui_"))): continue var line = _action_list.add_input_line(input_action, input_profile[input_action]) @@ -55,7 +65,62 @@ func _on_InputLine_change_button_pressed(action_name, line): var event = yield($"%KeySelectMenu", "key_selected") if event == null: return - if($InputMapper.change_action_key(action_name, event, old_event)): + + #Check if events are basically the same + #TODO Problem with different physical locations of the same key + if "scancode" in old_event && "scancode" in event: + if event.scancode == old_event.scancode: + return + elif event == old_event: + return + + var action_with_same_event: String = check_doubled_event(event) + + # Routine to swap buttons + # TODO put into function + if action_with_same_event != "": + # Check doubled reads from the InputMap and alternative actions are only virtual + if action_with_same_event == action_name: + action_with_same_event = "alt " + action_name + $"%SwapKeysMenu".open(action_name, action_with_same_event, old_event, event) + var swap = yield($"SwapKeysMenu", "selection_made") + if swap: + swap_buttons(action_name, action_with_same_event, old_event, event) + print("bakayaroo!") + return + + if $InputMapper.change_action_key(action_name, event, old_event): changes_made = true changes_saved = false line.update_key(event) + +func check_doubled_event(event: InputEvent) -> String: + for action in $InputMapper.get_selected_profile().keys(): + if action.begins_with("ui_") || action.ends_with("_old"): + continue + var assigned_event: InputEvent = $InputMapper.get_selected_profile()[action] + if "scancode" in assigned_event && "scancode" in event: + if event.scancode == assigned_event.scancode: + return action + else: + if event == assigned_event: + return action + return "" + +func swap_buttons(action1, action2, old_event, new_event) -> void: + var input_line1 = $"%ActionKeyList".get_input_line(action1) + var input_line2 = $"%ActionKeyList".get_input_line(action2) + if $InputMapper.change_action_key(action1, new_event, old_event): + changes_made = true + changes_saved = false + input_line1.update_key(new_event) + else: + return + + # Avoid erasing the just assigned "old" event from the input map, + # when swapping alternative button assignments in place + if action1.trim_prefix("alt ") == action2.trim_prefix("alt "): + new_event = old_event + + if $InputMapper.change_action_key(action2, old_event, new_event): + input_line2.update_key(old_event) diff --git a/src/UserInterface/Screens/InGameMenu/PauseScreen.gd b/src/UserInterface/Screens/InGameMenu/PauseScreen.gd index b750330..1e6feb1 100644 --- a/src/UserInterface/Screens/InGameMenu/PauseScreen.gd +++ b/src/UserInterface/Screens/InGameMenu/PauseScreen.gd @@ -4,65 +4,68 @@ extends Control onready var signal_manager := get_tree().root.get_child(4).get_node("%SignalManager") onready var level_state := get_tree().root.get_child(4).get_node("%LevelState") onready var current_scene := get_tree().get_current_scene() -onready var pause_overlay: = get_node("PauseOverlay") +onready var pause_overlay := get_node("PauseOverlay") onready var pause_title: Label = get_node("PauseOverlay/Title") var paused := false setget set_paused var block_ui_cancel = false + func _ready(): - #signal_manager.connect("player_died", self, "_on_GlobalState_player_died") - $ControlsMenu.visible = false - $ControlsMenu.set_process_input(false) - $AudioMenu.set_process_input(false) - signal_manager.connect("game_paused", self, "set_paused") - pass + #signal_manager.connect("player_died", self, "_on_GlobalState_player_died") + $ControlsMenu.visible = false + $ControlsMenu.set_process_input(false) + $AudioMenu.set_process_input(false) + signal_manager.connect("game_paused", self, "set_paused") + pass + func open_audio_menu(): - block_ui_cancel = true - pause_overlay.visible = false - $AudioMenu.visible = true - $AudioMenu.set_process_input(true) - $"%MasterSlider".grab_focus() + block_ui_cancel = true + pause_overlay.visible = false + $AudioMenu.visible = true + $AudioMenu.set_process_input(true) + $"%MasterSlider".grab_focus() + func close_audio_menu(): - $AudioMenu.visible = false - pause_overlay.visible = true - $AudioMenu.set_process_input(false) - $"%Continue".grab_focus() - get_tree().set_input_as_handled() + $AudioMenu.visible = false + pause_overlay.visible = true + $AudioMenu.set_process_input(false) + $"%Continue".grab_focus() + get_tree().set_input_as_handled() func _on_GlobalState_player_died() -> void: - self.paused = true - pause_title.text = "You lost" + self.paused = true + pause_title.text = "You lost" func _input(event: InputEvent) -> void: - if !event.is_action("pause"): - return - if block_ui_cancel || $"%ControlsMenu".visible: - block_ui_cancel = false - get_tree().set_input_as_handled() - return - #not oder ! schaltet einen boolean um - #Ist self hier notwendig? - - self.paused = not paused - block_ui_cancel = true + if !event.is_action("pause"): + return + if block_ui_cancel || $"%ControlsMenu".visible: + block_ui_cancel = false + get_tree().set_input_as_handled() + return + #not oder ! schaltet einen boolean um + #Ist self hier notwendig? + + self.paused = not paused + block_ui_cancel = true func set_paused(value: bool) -> void: - paused = value - get_tree().paused = value - pause_overlay.visible = value - if value == true: - $"%Continue".grab_focus() + paused = value + get_tree().paused = value + pause_overlay.visible = value + if value == true: + $"%Continue".grab_focus() func _on_Controls_button_up() -> void: - $ControlsMenu.visible = true - $ControlsMenu.set_process_input(true) - block_ui_cancel = true - pause_overlay.visible = false - $"%ProfilesMenu".grab_focus() + $ControlsMenu.visible = true + $ControlsMenu.set_process_input(true) + block_ui_cancel = true + pause_overlay.visible = false + $"%ProfilesMenu".grab_focus() diff --git a/src/UserInterface/Screens/InGameMenu/PauseScreen.tscn b/src/UserInterface/Screens/InGameMenu/PauseScreen.tscn index 2fc5ca5..4624ed0 100644 --- a/src/UserInterface/Screens/InGameMenu/PauseScreen.tscn +++ b/src/UserInterface/Screens/InGameMenu/PauseScreen.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=39 format=2] +[gd_scene load_steps=44 format=2] [ext_resource path="res://assets/meta/ui_theme.tres" type="Theme" id=1] [ext_resource path="res://assets/ui/sci-fi-godot-theme/sci-fi-theme.tres" type="Theme" id=2] @@ -19,11 +19,14 @@ [ext_resource path="res://src/UserInterface/Screens/MainMenu/ControlsMenu/ProfilesMenu.gd" type="Script" id=17] [ext_resource path="res://assets/ui/fonts/Kenney Thick.ttf" type="DynamicFontData" id=18] [ext_resource path="res://assets/ui/fonts/kenny_thick.tres" type="DynamicFont" id=19] +[ext_resource path="res://addons/controller_icons/objects/Button.gd" type="Script" id=20] [ext_resource path="res://assets/ui/Screenshot 2023-05-23 160521.png" type="Texture" id=21] [ext_resource path="res://assets/meta/montserrat_extrabold.otf" type="DynamicFontData" id=22] [ext_resource path="res://src/UserInterface/Buttons/AudibleButton.gd" type="Script" id=23] [ext_resource path="res://assets/music/Shopping For The Future (LOOP).wav" type="AudioStream" id=24] +[ext_resource path="res://src/UserInterface/Screens/MainMenu/ControlsMenu/SwapKeysMenu.gd" type="Script" id=25] [ext_resource path="res://src/UserInterface/Screens/MainMenu/AudioMenu.gd" type="Script" id=26] +[ext_resource path="res://addons/controller_icons/assets/key/arrow_down.png" type="Texture" id=27] [ext_resource path="res://src/UserInterface/Screens/MainMenu/AudioSlider.gd" type="Script" id=28] [ext_resource path="res://src/UserInterface/Buttons/MenuNavigationButton.gd" type="Script" id=29] @@ -71,6 +74,14 @@ shader_param/transparency = 0.778 size = 20 font_data = ExtResource( 22 ) +[sub_resource type="ShaderMaterial" id=18] +shader = ExtResource( 7 ) +shader_param/transparency = 0.778 + +[sub_resource type="DynamicFont" id=19] +size = 8 +font_data = ExtResource( 18 ) + [sub_resource type="DynamicFont" id=16] size = 42 font_data = ExtResource( 22 ) @@ -448,6 +459,140 @@ custom_fonts/font = ExtResource( 19 ) text = "Quit Don't Save" script = ExtResource( 23 ) +[node name="SwapKeysMenu" type="Panel" parent="ControlsMenu"] +unique_name_in_owner = true +visible = false +material = SubResource( 18 ) +anchor_right = 1.0 +anchor_bottom = 1.0 +focus_mode = 2 +input_pass_on_modal_close_click = false +script = ExtResource( 25 ) + +[node name="VBoxContainer2" type="VBoxContainer" parent="ControlsMenu/SwapKeysMenu"] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -139.0 +margin_top = -123.0 +margin_right = 139.0 +margin_bottom = 123.0 +focus_mode = 2 +custom_constants/separation = 30 + +[node name="Prompt" type="Label" parent="ControlsMenu/SwapKeysMenu/VBoxContainer2"] +margin_right = 278.0 +margin_bottom = 21.0 +grow_horizontal = 2 +mouse_filter = 0 +size_flags_horizontal = 3 +size_flags_vertical = 0 +custom_fonts/font = SubResource( 19 ) +text = "selected button already assigned +swap Button actions?" +align = 1 +valign = 1 + +[node name="HBoxContainer" type="HBoxContainer" parent="ControlsMenu/SwapKeysMenu/VBoxContainer2"] +margin_top = 51.0 +margin_right = 278.0 +margin_bottom = 174.0 +custom_constants/separation = 20 +alignment = 1 + +[node name="VBoxContainer" type="VBoxContainer" parent="ControlsMenu/SwapKeysMenu/VBoxContainer2/HBoxContainer"] +margin_left = 15.0 +margin_right = 129.0 +margin_bottom = 123.0 +size_flags_horizontal = 0 +size_flags_vertical = 0 + +[node name="Action1" type="Label" parent="ControlsMenu/SwapKeysMenu/VBoxContainer2/HBoxContainer/VBoxContainer"] +unique_name_in_owner = true +margin_right = 114.0 +margin_bottom = 9.0 +text = "Action 1" +align = 1 + +[node name="ControllerButton1" type="Button" parent="ControlsMenu/SwapKeysMenu/VBoxContainer2/HBoxContainer/VBoxContainer"] +unique_name_in_owner = true +margin_top = 13.0 +margin_right = 114.0 +margin_bottom = 123.0 +focus_mode = 0 +size_flags_horizontal = 0 +size_flags_vertical = 0 +shortcut_in_tooltip = false +button_mask = 0 +enabled_focus_mode = 0 +icon = ExtResource( 27 ) +icon_align = 1 +script = ExtResource( 20 ) +path = "duck" + +[node name="VBoxContainer2" type="VBoxContainer" parent="ControlsMenu/SwapKeysMenu/VBoxContainer2/HBoxContainer"] +margin_left = 149.0 +margin_right = 263.0 +margin_bottom = 123.0 +size_flags_horizontal = 0 +size_flags_vertical = 0 + +[node name="Action2" type="Label" parent="ControlsMenu/SwapKeysMenu/VBoxContainer2/HBoxContainer/VBoxContainer2"] +unique_name_in_owner = true +margin_right = 114.0 +margin_bottom = 9.0 +text = "Action 2" +align = 1 + +[node name="ControllerButton2" type="Button" parent="ControlsMenu/SwapKeysMenu/VBoxContainer2/HBoxContainer/VBoxContainer2"] +unique_name_in_owner = true +margin_top = 13.0 +margin_right = 114.0 +margin_bottom = 123.0 +focus_mode = 0 +size_flags_horizontal = 0 +size_flags_vertical = 0 +shortcut_in_tooltip = false +button_mask = 0 +enabled_focus_mode = 0 +icon = ExtResource( 27 ) +icon_align = 1 +script = ExtResource( 20 ) +path = "duck" + +[node name="VBoxContainer" type="VBoxContainer" parent="ControlsMenu/SwapKeysMenu/VBoxContainer2"] +margin_top = 204.0 +margin_right = 278.0 +margin_bottom = 246.0 +grow_horizontal = 2 +grow_vertical = 2 +focus_mode = 2 +mouse_filter = 0 +input_pass_on_modal_close_click = false +size_flags_horizontal = 3 +size_flags_vertical = 0 +alignment = 1 + +[node name="Yes" type="Button" parent="ControlsMenu/SwapKeysMenu/VBoxContainer2/VBoxContainer"] +unique_name_in_owner = true +margin_right = 278.0 +margin_bottom = 19.0 +focus_neighbour_top = NodePath("../No") +focus_neighbour_bottom = NodePath("../No") +text = "Yes" +script = ExtResource( 23 ) + +[node name="No" type="Button" parent="ControlsMenu/SwapKeysMenu/VBoxContainer2/VBoxContainer"] +unique_name_in_owner = true +margin_top = 23.0 +margin_right = 278.0 +margin_bottom = 42.0 +focus_neighbour_top = NodePath("../Yes") +focus_neighbour_bottom = NodePath("../Yes") +text = "NO" +script = ExtResource( 23 ) + [node name="AudioMenu" type="Control" parent="."] visible = false anchor_right = 1.0 @@ -789,6 +934,8 @@ volume_db = -10.0 [connection signal="button_up" from="ControlsMenu/ReallyQuitMenu/VBoxContainer/SaveNQuit" to="ControlsMenu/ReallyQuitMenu/VBoxContainer/SaveNQuit" method="_on_button_up"] [connection signal="button_up" from="ControlsMenu/ReallyQuitMenu/VBoxContainer/ContinueEdit" to="ControlsMenu/ReallyQuitMenu" method="close"] [connection signal="button_up" from="ControlsMenu/ReallyQuitMenu/VBoxContainer/QuitDontSave" to="ControlsMenu" method="close"] +[connection signal="pressed" from="ControlsMenu/SwapKeysMenu/VBoxContainer2/VBoxContainer/Yes" to="ControlsMenu/SwapKeysMenu" method="swap"] +[connection signal="pressed" from="ControlsMenu/SwapKeysMenu/VBoxContainer2/VBoxContainer/No" to="ControlsMenu/SwapKeysMenu" method="do_not_swap"] [connection signal="button_up" from="AudioMenu/Panel/Back" to="." method="close_audio_menu"] [connection signal="button_up" from="AudioMenu/Panel/Back" to="AudioMenu" method="save"] [connection signal="button_up" from="PauseOverlay/Panel/VBoxContainer/Continue" to="PauseOverlay/Panel/VBoxContainer/Continue" method="_on_button_up"] diff --git a/src/UserInterface/Screens/MainMenu/ControlsMenu/ActionKeyList.gd b/src/UserInterface/Screens/MainMenu/ControlsMenu/ActionKeyList.gd index c27e3f1..505196b 100644 --- a/src/UserInterface/Screens/MainMenu/ControlsMenu/ActionKeyList.gd +++ b/src/UserInterface/Screens/MainMenu/ControlsMenu/ActionKeyList.gd @@ -7,6 +7,12 @@ func clear(): for child in get_children(): child.free() +func get_input_line(action_name) -> Control: + for child in get_children(): + if child.action == action_name: + return child + return null + func add_input_line(action_name, event) -> Control: var line = InputLine.instance() add_child(line) diff --git a/src/UserInterface/Screens/MainMenu/ControlsMenu/ControlsMenu.gd b/src/UserInterface/Screens/MainMenu/ControlsMenu/ControlsMenu.gd index b149e74..210d068 100644 --- a/src/UserInterface/Screens/MainMenu/ControlsMenu/ControlsMenu.gd +++ b/src/UserInterface/Screens/MainMenu/ControlsMenu/ControlsMenu.gd @@ -6,13 +6,15 @@ onready var changes_saved := false var block_ui_cancel = false + func _ready() -> void: - $InputMapper.connect('profile_changed', self, 'rebuild') + $InputMapper.connect("profile_changed", self, "rebuild") $InputMapper.initialize_profiles() $ProfilesMenu.initialize($InputMapper) $ProfilesMenu.grab_focus() $InputMapper.change_profile($ProfilesMenu.selected) + func _input(event: InputEvent) -> void: # TODO Static quit button esc if !event.is_action("ui_cancel") || !visible: @@ -22,15 +24,23 @@ func _input(event: InputEvent) -> void: get_tree().set_input_as_handled() return $"%Back"._on_button_up() - + func rebuild(input_profile) -> void: _action_list.clear() var first = true var prev_line - for input_action in input_profile.keys(): - if(input_action.ends_with("_old") || input_action.begins_with(("ui_"))): + for order_action in $InputMapper.profile_order: + + var input_action := "" + + for action in input_profile.keys(): + if action == order_action: + input_action = action + + if input_action == "": continue + var line = _action_list.add_input_line(input_action, input_profile[input_action]) # child(2) is the actual button inside the inputline if first: @@ -45,7 +55,13 @@ func rebuild(input_profile) -> void: line.get_child(2).focus_neighbour_left = $"%Back".get_path() line.get_child(2).focus_neighbour_right = $"%Save".get_path() prev_line = line.get_child(2) - line.connect('change_button_pressed', self, '_on_InputLine_change_button_pressed', [input_action, line]) + line.connect( + "change_button_pressed", + self, + "_on_InputLine_change_button_pressed", + [input_action, line] + ) + func _on_InputLine_change_button_pressed(action_name, line): var old_event = $InputMapper.get_selected_profile()[action_name] @@ -53,7 +69,62 @@ func _on_InputLine_change_button_pressed(action_name, line): var event = yield($"%KeySelectMenu", "key_selected") if event == null: return - if($InputMapper.change_action_key(action_name, event, old_event)): + + #Check if events are basically the same + #TODO Problem with different physical locations of the same key + if "scancode" in old_event && "scancode" in event: + if event.scancode == old_event.scancode: + return + elif event == old_event: + return + + var action_with_same_event: String = check_doubled_event(event) + + # Routine to swap buttons + # TODO put into function + if action_with_same_event != "": + # Check doubled reads from the InputMap and alternative actions are only virtual + if action_with_same_event == action_name: + action_with_same_event = "alt " + action_name + $"%SwapKeysMenu".open(action_name, action_with_same_event, old_event, event) + var swap = yield($"SwapKeysMenu", "selection_made") + if swap: + swap_buttons(action_name, action_with_same_event, old_event, event) + print("bakayaroo!") + return + + if $InputMapper.change_action_key(action_name, event, old_event): changes_made = true changes_saved = false line.update_key(event) + +func check_doubled_event(event: InputEvent) -> String: + for action in $InputMapper.get_selected_profile().keys(): + if action.begins_with("ui_") || action.ends_with("_old"): + continue + var assigned_event: InputEvent = $InputMapper.get_selected_profile()[action] + if "scancode" in assigned_event && "scancode" in event: + if event.scancode == assigned_event.scancode: + return action + else: + if event == assigned_event: + return action + return "" + +func swap_buttons(action1, action2, old_event, new_event) -> void: + var input_line1 = $"%ActionKeyList".get_input_line(action1) + var input_line2 = $"%ActionKeyList".get_input_line(action2) + if $InputMapper.change_action_key(action1, new_event, old_event): + changes_made = true + changes_saved = false + input_line1.update_key(new_event) + else: + return + + # Avoid erasing the just assigned "old" event from the input map, + # when swapping alternative button assignments in place + if action1.trim_prefix("alt ") == action2.trim_prefix("alt "): + new_event = old_event + + if $InputMapper.change_action_key(action2, old_event, new_event): + input_line2.update_key(old_event) diff --git a/src/UserInterface/Screens/MainMenu/ControlsMenu/ControlsMenu.tscn b/src/UserInterface/Screens/MainMenu/ControlsMenu/ControlsMenu.tscn index 0eebad4..0004bbb 100644 --- a/src/UserInterface/Screens/MainMenu/ControlsMenu/ControlsMenu.tscn +++ b/src/UserInterface/Screens/MainMenu/ControlsMenu/ControlsMenu.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=28 format=2] +[gd_scene load_steps=31 format=2] [ext_resource path="res://src/UserInterface/Screens/MainMenu/ControlsMenu/SaveButton.gd" type="Script" id=1] [ext_resource path="res://src/UserInterface/Screens/MainMenu/ControlsMenu/SavedCheckBackButton.gd" type="Script" id=2] @@ -10,6 +10,7 @@ [ext_resource path="res://src/UserInterface/Buttons/AudibleButton.gd" type="Script" id=8] [ext_resource path="res://assets/environment/background/Spaceship-Wall-Menu.png" type="Texture" id=9] [ext_resource path="res://assets/environment/background/starry-space.png" type="Texture" id=10] +[ext_resource path="res://src/UserInterface/Screens/MainMenu/ControlsMenu/SwapKeysMenu.gd" type="Script" id=11] [ext_resource path="res://assets/ui/Screenshot 2023-05-23 160521.png" type="Texture" id=12] [ext_resource path="res://src/UserInterface/Screens/MainMenu/ControlsMenu/ProfilesMenu.gd" type="Script" id=13] [ext_resource path="res://src/UserInterface/Screens/MainMenu/ControlsMenu/ActionKeyList.gd" type="Script" id=14] @@ -21,6 +22,8 @@ [ext_resource path="res://assets/ui/sci-fi-godot-theme/sci-fi-theme.tres" type="Theme" id=20] [ext_resource path="res://assets/ui/fonts/Kenney Thick.ttf" type="DynamicFontData" id=21] [ext_resource path="res://assets/ui/fonts/kenny_thick.tres" type="DynamicFont" id=22] +[ext_resource path="res://addons/controller_icons/objects/Button.gd" type="Script" id=23] +[ext_resource path="res://addons/controller_icons/assets/key/arrow_down.png" type="Texture" id=24] [sub_resource type="DynamicFont" id=1] size = 42 @@ -255,6 +258,8 @@ follow_focus = true [node name="ActionKeyList" type="VBoxContainer" parent="Panel/KeymapViewer/ScrollContainer"] unique_name_in_owner = true +margin_right = 600.0 +margin_bottom = 189.0 size_flags_horizontal = 3 size_flags_vertical = 3 script = ExtResource( 14 ) @@ -421,6 +426,140 @@ text = "Quit Don't Save" script = ExtResource( 19 ) next_screen_path = "res://src/UserInterface/Screens/MainMenu/MainScreen.tscn" +[node name="SwapKeysMenu" type="Panel" parent="."] +unique_name_in_owner = true +visible = false +material = SubResource( 8 ) +anchor_right = 1.0 +anchor_bottom = 1.0 +focus_mode = 2 +input_pass_on_modal_close_click = false +script = ExtResource( 11 ) + +[node name="VBoxContainer2" type="VBoxContainer" parent="SwapKeysMenu"] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -139.0 +margin_top = -123.0 +margin_right = 139.0 +margin_bottom = 123.0 +focus_mode = 2 +custom_constants/separation = 30 + +[node name="Prompt" type="Label" parent="SwapKeysMenu/VBoxContainer2"] +margin_right = 278.0 +margin_bottom = 21.0 +grow_horizontal = 2 +mouse_filter = 0 +size_flags_horizontal = 3 +size_flags_vertical = 0 +custom_fonts/font = SubResource( 10 ) +text = "selected button already assigned +swap Button actions?" +align = 1 +valign = 1 + +[node name="HBoxContainer" type="HBoxContainer" parent="SwapKeysMenu/VBoxContainer2"] +margin_top = 51.0 +margin_right = 278.0 +margin_bottom = 174.0 +custom_constants/separation = 20 +alignment = 1 + +[node name="VBoxContainer" type="VBoxContainer" parent="SwapKeysMenu/VBoxContainer2/HBoxContainer"] +margin_left = 15.0 +margin_right = 129.0 +margin_bottom = 123.0 +size_flags_horizontal = 0 +size_flags_vertical = 0 + +[node name="Action1" type="Label" parent="SwapKeysMenu/VBoxContainer2/HBoxContainer/VBoxContainer"] +unique_name_in_owner = true +margin_right = 114.0 +margin_bottom = 9.0 +text = "Action 1" +align = 1 + +[node name="ControllerButton1" type="Button" parent="SwapKeysMenu/VBoxContainer2/HBoxContainer/VBoxContainer"] +unique_name_in_owner = true +margin_top = 13.0 +margin_right = 114.0 +margin_bottom = 123.0 +focus_mode = 0 +size_flags_horizontal = 0 +size_flags_vertical = 0 +shortcut_in_tooltip = false +button_mask = 0 +enabled_focus_mode = 0 +icon = ExtResource( 24 ) +icon_align = 1 +script = ExtResource( 23 ) +path = "duck" + +[node name="VBoxContainer2" type="VBoxContainer" parent="SwapKeysMenu/VBoxContainer2/HBoxContainer"] +margin_left = 149.0 +margin_right = 263.0 +margin_bottom = 123.0 +size_flags_horizontal = 0 +size_flags_vertical = 0 + +[node name="Action2" type="Label" parent="SwapKeysMenu/VBoxContainer2/HBoxContainer/VBoxContainer2"] +unique_name_in_owner = true +margin_right = 114.0 +margin_bottom = 9.0 +text = "Action 2" +align = 1 + +[node name="ControllerButton2" type="Button" parent="SwapKeysMenu/VBoxContainer2/HBoxContainer/VBoxContainer2"] +unique_name_in_owner = true +margin_top = 13.0 +margin_right = 114.0 +margin_bottom = 123.0 +focus_mode = 0 +size_flags_horizontal = 0 +size_flags_vertical = 0 +shortcut_in_tooltip = false +button_mask = 0 +enabled_focus_mode = 0 +icon = ExtResource( 24 ) +icon_align = 1 +script = ExtResource( 23 ) +path = "duck" + +[node name="VBoxContainer" type="VBoxContainer" parent="SwapKeysMenu/VBoxContainer2"] +margin_top = 204.0 +margin_right = 278.0 +margin_bottom = 246.0 +grow_horizontal = 2 +grow_vertical = 2 +focus_mode = 2 +mouse_filter = 0 +input_pass_on_modal_close_click = false +size_flags_horizontal = 3 +size_flags_vertical = 0 +alignment = 1 + +[node name="Yes" type="Button" parent="SwapKeysMenu/VBoxContainer2/VBoxContainer"] +unique_name_in_owner = true +margin_right = 278.0 +margin_bottom = 19.0 +focus_neighbour_top = NodePath("../No") +focus_neighbour_bottom = NodePath("../No") +text = "Yes" +script = ExtResource( 8 ) + +[node name="No" type="Button" parent="SwapKeysMenu/VBoxContainer2/VBoxContainer"] +unique_name_in_owner = true +margin_top = 23.0 +margin_right = 278.0 +margin_bottom = 42.0 +focus_neighbour_top = NodePath("../Yes") +focus_neighbour_bottom = NodePath("../Yes") +text = "NO" +script = ExtResource( 8 ) + [connection signal="button_up" from="Panel/Back" to="Panel/Back" method="_on_button_up"] [connection signal="button_up" from="Panel/Reset" to="Panel/Reset" method="_on_button_up"] [connection signal="button_up" from="Panel/Save" to="Panel/Save" method="_on_button_up"] @@ -429,3 +568,5 @@ next_screen_path = "res://src/UserInterface/Screens/MainMenu/MainScreen.tscn" [connection signal="button_up" from="ReallyQuitMenu/VBoxContainer/SaveNQuit" to="ReallyQuitMenu/VBoxContainer/SaveNQuit" method="_on_button_up"] [connection signal="button_up" from="ReallyQuitMenu/VBoxContainer/ContinueEdit" to="ReallyQuitMenu" method="close"] [connection signal="button_up" from="ReallyQuitMenu/VBoxContainer/QuitDontSave" to="ReallyQuitMenu/VBoxContainer/QuitDontSave" method="_on_button_up"] +[connection signal="pressed" from="SwapKeysMenu/VBoxContainer2/VBoxContainer/Yes" to="SwapKeysMenu" method="swap"] +[connection signal="pressed" from="SwapKeysMenu/VBoxContainer2/VBoxContainer/No" to="SwapKeysMenu" method="do_not_swap"] diff --git a/src/UserInterface/Screens/MainMenu/ControlsMenu/InputLine.gd b/src/UserInterface/Screens/MainMenu/ControlsMenu/InputLine.gd index f0e980a..2ebf09a 100644 --- a/src/UserInterface/Screens/MainMenu/ControlsMenu/InputLine.gd +++ b/src/UserInterface/Screens/MainMenu/ControlsMenu/InputLine.gd @@ -5,8 +5,10 @@ signal change_button_pressed export var button_size: Vector2 = Vector2(30, 30) export var interactable: bool = false +onready var action = "" func initialize(action_name, event): + action = action_name $Action.text = action_name.capitalize() $Key.add_child(create_controller_button(event)) diff --git a/src/UserInterface/Screens/MainMenu/ControlsMenu/InputMapper.gd b/src/UserInterface/Screens/MainMenu/ControlsMenu/InputMapper.gd index 283f461..82958f3 100644 --- a/src/UserInterface/Screens/MainMenu/ControlsMenu/InputMapper.gd +++ b/src/UserInterface/Screens/MainMenu/ControlsMenu/InputMapper.gd @@ -5,63 +5,89 @@ signal profile_changed(new_profile) var current_profile_id = 0 var profiles = { - 0: 'keyboard', - 1: 'controller' + 0: 'keyboard', + 1: 'controller' } +var profile_order = ["move_left", "alt move_left", "move_right", "alt move_right", "jump", "run", "duck", + "alt duck", "up", "alt up", "interact", "pause"] + var keyboard = {} var controller = {} -func change_profile(id): - current_profile_id = id - var profile = get(profiles[id]) - - for action_name in profile.keys(): - change_action_key(action_name, profile[action_name]) - emit_signal('profile_changed', profile) - return profile +func change_profile(id: int) -> Dictionary: + current_profile_id = id + var profile = get(profiles[id]) + + for action_name in profile.keys(): + change_action_key(action_name, profile[action_name]) + + emit_signal('profile_changed', profile) + return profile -func commit_to_changes(): - for profile_name in profiles.values(): - var profile = get(profile_name) - for action_name in profile.keys(): - if(action_name.ends_with("_old")): - continue - erase_old_action_event(action_name) - profile[action_name + "_old"] = profile[action_name] - InputMap.action_add_event(action_name, profile[action_name]) +func commit_to_changes() -> void: + for profile_name in profiles.values(): + var profile = get(profile_name) + for action_name in profile.keys(): + if(action_name.ends_with("_old")): + continue + erase_old_action_event(action_name) + profile[action_name + "_old"] = profile[action_name] + var a_name = action_name + # Assign the alternative event to the same action as the regular event + if(action_name.begins_with("alt")): + action_name = action_name.trim_prefix("alt ") + InputMap.action_add_event(action_name, profile[a_name]) func change_action_key(action_name, event, old_event = null) -> bool: - if(old_event != null): - if(event.as_text().match("*Joy*") != old_event.as_text().match("*Joy*")): - return false - get_selected_profile()[action_name+"_old"] = old_event - get_selected_profile()[action_name] = event - return true + if(old_event != null): + if(event.as_text().match("*Joy*") != old_event.as_text().match("*Joy*")): + return false + get_selected_profile()[action_name+"_old"] = old_event + get_selected_profile()[action_name] = event + return true -func erase_old_action_event(action_name): - if(get_selected_profile().has(action_name+"_old")): - var old_event = get_selected_profile()[action_name+"_old"] - var event = get_selected_profile()[action_name] - if(old_event != event): - InputMap.action_erase_event(action_name, old_event) +func erase_old_action_event(action_name: String) -> void: + if(get_selected_profile().has(action_name+"_old")): + var old_event = get_selected_profile()[action_name+"_old"] + var event = get_selected_profile()[action_name] + if(old_event != event): + if(action_name.begins_with("alt")): + action_name = action_name.trim_prefix("alt ") + InputMap.action_erase_event(action_name, old_event) func initialize_profiles() -> void: - var actions: Array = InputMap.get_actions() - actions.sort() - for action in actions: - var input_events = InputMap.get_action_list(action) - for event in input_events: - if event.as_text().match("*JoypadButton*"): - controller[action] = event - controller[action+"_old"] = event - elif !event.as_text().match("*Joy*"): - keyboard[action] = event - keyboard[action+"_old"] = event - change_profile(current_profile_id) + var actions: Array = InputMap.get_actions() + actions.sort() + for action in actions: + var input_events: Array = InputMap.get_action_list(action) + var controller_events: Array = [] + var keyboard_events: Array = [] + + for input_event in input_events: + if input_event.as_text().match("*Joypad*"): + controller_events.append(input_event) + if !input_event.as_text().match("*Joy*"): + keyboard_events.append(input_event) + + if controller_events.size() > 0: + controller[action] = controller_events[0] + controller[action+"_old"] = controller_events[0] + if controller_events.size() > 1: + controller["alt " + action] = controller_events[1] + controller["alt " + action +"_old"] = controller_events[1] + + if keyboard_events.size() > 0: + keyboard[action] = keyboard_events[0] + keyboard[action + "_old"] = keyboard_events[0] + if keyboard_events.size() > 1: + keyboard["alt " + action] = keyboard_events[1] + keyboard["alt " + action + "_old"] = keyboard_events[1] + + change_profile(current_profile_id) func get_selected_profile(): - return get(profiles[current_profile_id]) + return get(profiles[current_profile_id]) func _on_ProfilesMenu_item_selected(ID): - change_profile(ID) + change_profile(ID) diff --git a/src/UserInterface/Screens/MainMenu/ControlsMenu/KeySelectMenu.gd b/src/UserInterface/Screens/MainMenu/ControlsMenu/KeySelectMenu.gd index 162ee8c..9e1e04c 100644 --- a/src/UserInterface/Screens/MainMenu/ControlsMenu/KeySelectMenu.gd +++ b/src/UserInterface/Screens/MainMenu/ControlsMenu/KeySelectMenu.gd @@ -17,8 +17,8 @@ func _input(event: InputEvent) -> void: event = null accept_event() get_tree().set_input_as_handled() - emit_signal("key_selected", event) close() + emit_signal("key_selected", event) func open(): show() diff --git a/src/UserInterface/Screens/MainMenu/ControlsMenu/ReallyQuitMenu.gd b/src/UserInterface/Screens/MainMenu/ControlsMenu/ReallyQuitMenu.gd index 5e48882..9c6a6ee 100644 --- a/src/UserInterface/Screens/MainMenu/ControlsMenu/ReallyQuitMenu.gd +++ b/src/UserInterface/Screens/MainMenu/ControlsMenu/ReallyQuitMenu.gd @@ -3,22 +3,22 @@ extends Panel var prev_focus func open(): - visible = true - prev_focus = get_focus_owner() - mitigate_ui_navigation_spill_over(true) - $"%SaveNQuit".grab_focus() + visible = true + prev_focus = get_focus_owner() + mitigate_ui_navigation_spill_over(true) + $"%SaveNQuit".grab_focus() func mitigate_ui_navigation_spill_over(var value: bool): - var mode = Control.FOCUS_NONE if value else Control.FOCUS_ALL - $"%ProfilesMenu".focus_mode = mode - $"%Back".focus_mode = mode - $"%Reset".focus_mode = mode - $"%Save".focus_mode = mode - for line in $"%ActionKeyList".get_children(): - line.get_node("ChangeButton").focus_mode = mode + var mode = Control.FOCUS_NONE if value else Control.FOCUS_ALL + $"%ProfilesMenu".focus_mode = mode + $"%Back".focus_mode = mode + $"%Reset".focus_mode = mode + $"%Save".focus_mode = mode + for line in $"%ActionKeyList".get_children(): + line.get_node("ChangeButton").focus_mode = mode func close(): - visible = false - mitigate_ui_navigation_spill_over(false) - self.release_focus() - prev_focus.grab_focus() + visible = false + mitigate_ui_navigation_spill_over(false) + self.release_focus() + prev_focus.grab_focus() diff --git a/src/UserInterface/Screens/MainMenu/ControlsMenu/Reset.gd b/src/UserInterface/Screens/MainMenu/ControlsMenu/Reset.gd index c42d3c7..c5829ee 100644 --- a/src/UserInterface/Screens/MainMenu/ControlsMenu/Reset.gd +++ b/src/UserInterface/Screens/MainMenu/ControlsMenu/Reset.gd @@ -3,6 +3,6 @@ extends AudibleButton onready var mapper := $"%InputMapper" func _on_button_up() -> void: - InputMap.load_from_globals() - mapper.initialize_profiles() - SaveManager.save_default() + InputMap.load_from_globals() + mapper.initialize_profiles() + SaveManager.save_default() diff --git a/src/UserInterface/Screens/MainMenu/ControlsMenu/SaveButton.gd b/src/UserInterface/Screens/MainMenu/ControlsMenu/SaveButton.gd index 0c75d5b..06648fe 100644 --- a/src/UserInterface/Screens/MainMenu/ControlsMenu/SaveButton.gd +++ b/src/UserInterface/Screens/MainMenu/ControlsMenu/SaveButton.gd @@ -4,7 +4,7 @@ onready var mapper := $"%InputMapper" onready var controllsMenu := $"../.." func _on_button_up() -> void: - mapper.commit_to_changes() - SaveManager.save_default() - controllsMenu.changes_saved = true - controllsMenu.changes_made = false + mapper.commit_to_changes() + SaveManager.save_default() + controllsMenu.changes_saved = true + controllsMenu.changes_made = false diff --git a/src/UserInterface/Screens/MainMenu/ControlsMenu/SwapKeysMenu.gd b/src/UserInterface/Screens/MainMenu/ControlsMenu/SwapKeysMenu.gd new file mode 100644 index 0000000..fec1523 --- /dev/null +++ b/src/UserInterface/Screens/MainMenu/ControlsMenu/SwapKeysMenu.gd @@ -0,0 +1,53 @@ +extends Panel + +signal selection_made(result) + +var prev_focus + +var selected_action +var action_with_same_event +var new_event_for_selected_action +var old_event_for_selected_action + +func open(selected_action: String, action_with_same_event: String, + old_event_for_selected_action: InputEvent, new_event_for_selected_action: InputEvent) -> void: + prev_focus = get_focus_owner() + self.selected_action = selected_action + self.action_with_same_event = action_with_same_event + self.new_event_for_selected_action = new_event_for_selected_action + self.old_event_for_selected_action = old_event_for_selected_action + + $"%Action1".text = selected_action + var event_path1 = ControllerIcons._convert_event_to_path(old_event_for_selected_action) + $"%ControllerButton1".path = event_path1 + + $"%Action2".text = action_with_same_event + var event_path2 = ControllerIcons._convert_event_to_path(new_event_for_selected_action) + $"%ControllerButton2".path = event_path2 + + visible = true + mitigate_ui_navigation_spill_over(true) + $"%Yes".grab_focus() + +func mitigate_ui_navigation_spill_over(var value: bool): + var mode = Control.FOCUS_NONE if value else Control.FOCUS_ALL + var inverse_mode = Control.FOCUS_ALL if value else Control.FOCUS_NONE + $"%No".focus_mode = inverse_mode + $"%Yes".focus_mode = inverse_mode + for line in $"%ActionKeyList".get_children(): + line.get_node("ChangeButton").focus_mode = mode + +func close() -> void: + visible = false + mitigate_ui_navigation_spill_over(false) + prev_focus.set_focus_mode(Control.FOCUS_ALL) + prev_focus.grab_focus() + +func swap() -> void: + close() + emit_signal("selection_made", true) + +func do_not_swap() -> void: + close() + emit_signal("selection_made", false) +