Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 105 additions & 23 deletions game/addons/keychain/Keychain.gd
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
extends Node

const PROFILES_PATH := "user://shortcut_profiles"
signal profile_switched(profile: ShortcutProfile)
signal action_changed(action_name: String)

signal reload_keychain()
const PROFILES_PATH := "user://shortcut_profiles"
const DEFAULT_PROFILE := preload("profiles/default.tres")

## [Array] of [ShortcutProfile]s.
var profiles: Array[ShortcutProfile] = [preload("profiles/default.tres")]
var selected_profile := profiles[0] ## The currently selected [ShortcutProfile].
var profiles: Array[ShortcutProfile] = []
var selected_profile: ShortcutProfile ## The currently selected [ShortcutProfile].
var profile_index := 0 ## The index of the currently selected [ShortcutProfile].
## [Dictionary] of [String] and [InputAction].
## Syntax: "action_name": InputAction.new("Action Display Name", "Group", true)
## Note that "action_name" must already exist in the Project's Input Map.
var actions := {}
## [Dictionary] of [String] and [InputGroup].
var actions: Dictionary[StringName, InputAction] = {}
## Syntax: "Group Name": InputGroup.new("Parent Group Name")
var groups := {}
var groups: Dictionary[StringName, InputGroup] = {}
var ignore_actions: Array[StringName] = [] ## [Array] of [StringName] input map actions to ignore.
## If [code]true[/code], ignore Godot's default "ui_" input map actions.
var ignore_ui_actions := true
Expand All @@ -37,12 +37,77 @@ class InputAction:
var group := ""
var global := true

func _init(_display_name := "", _group := "", _global := true):
func _init(_display_name := "", _group := "", _global := true) -> void:
display_name = _display_name
group = _group
global = _global


class MouseMovementInputAction:
extends InputAction

var action_name := &""
## The default direction of the mouse, towards where the value increments.
## This should be set only once during an instance's initialization.
var default_mouse_dir := Vector2.RIGHT
## The default sensitivity of the mouse for the value to change.
## This should be set only once during an instance's initialization.
var default_sensitivity := 0.1

var mouse_dir := default_mouse_dir
var sensitivity := default_sensitivity:
set(value):
if is_zero_approx(value):
sensitivity = 0.001
else:
sensitivity = value

var motion_accum := 0.0

func _init(
_display_name := "",
_group := "",
_global := true,
_action_name := &"",
_default_mouse_dir := Vector2.RIGHT,
_default_sensitivity := 0.1
) -> void:
super(_display_name, _group, _global)
action_name = _action_name
default_mouse_dir = _default_mouse_dir
default_sensitivity = _default_sensitivity

func get_action_distance(event: InputEvent, exact_match := false) -> float:
if event is InputEventMouseMotion and Input.is_action_pressed(action_name, exact_match):
var relative := (event as InputEventMouseMotion).relative
var delta := relative.dot(mouse_dir.normalized()) * sensitivity
return delta
return 0.0

func get_action_distance_int(event: InputEvent, exact_match := false) -> int:
if event is InputEventMouseMotion and Input.is_action_pressed(action_name, exact_match):
var relative := (event as InputEventMouseMotion).relative
var delta := relative.dot(mouse_dir.normalized()) * sensitivity
motion_accum += delta

var step := int(motion_accum)
motion_accum -= step

return step
return 0

func restore_to_default() -> void:
mouse_dir = default_mouse_dir
sensitivity = default_sensitivity

func serialize() -> Dictionary:
return {"mouse_dir": mouse_dir, "sensitivity": sensitivity}

func deserialize(dict: Dictionary) -> void:
mouse_dir = dict.get("mouse_dir", mouse_dir)
sensitivity = dict.get("sensitivity", sensitivity)


class InputGroup:
var parent_group := ""
var folded := true
Expand All @@ -57,6 +122,7 @@ func _init() -> void:
for locale in TranslationServer.get_loaded_locales():
load_translation(locale)


func _ready() -> void:
if !config_file:
config_file = ConfigFile.new()
Expand All @@ -73,38 +139,54 @@ func _ready() -> void:
if file_name.get_extension() == "tres":
var file := load(PROFILES_PATH.path_join(file_name))
if file is ShortcutProfile:
file.fill_bindings()
profiles.append(file)
file_name = profile_dir.get_next()

# If there are no profiles besides the default, create one custom
if profiles.size() == 1:
if profiles.size() == 0:
var profile := ShortcutProfile.new()
profile.name = "Custom"
profile.resource_path = PROFILES_PATH.path_join("custom.tres")
var saved := profile.save()
if saved:
profiles.append(profile)

initialize_profiles()

func initialize_profiles() -> void:
for profile in profiles:
profile.fill_bindings()

profile_index = config_file.get_value("shortcuts", "shortcuts_profile", 0)
change_profile(profile_index)
Keychain.reload_keychain.emit()


func change_profile(index: int) -> void:
if index >= profiles.size():
index = profiles.size() - 1
profile_index = index
selected_profile = profiles[index]
for action in selected_profile.bindings:
if not InputMap.has_action(action): continue
action_erase_events(action)
for event in selected_profile.bindings[action]:
action_add_event(action, event)
for action_name in selected_profile.bindings:
if not InputMap.has_action(action_name):
continue
action_erase_events(action_name)
for event in selected_profile.bindings[action_name]:
action_add_event(action_name, event)
if actions.has(action_name):
var input_action := actions[action_name]
if input_action is MouseMovementInputAction:
if selected_profile.mouse_movement_options.has(action_name):
var mm_options := selected_profile.mouse_movement_options[action_name]
input_action.deserialize(mm_options)
else:
input_action.restore_to_default()
profile_switched.emit(selected_profile)


func change_action(action_name: String) -> void:
selected_profile.change_action(action_name)
action_changed.emit(action_name)


func change_mouse_movement_action_settings(action: MouseMovementInputAction) -> void:
var action_name := action.action_name
selected_profile.mouse_movement_options[action_name] = action.serialize()
selected_profile.save()
action_changed.emit(action_name)


func action_add_event(action: StringName, event: InputEvent) -> void:
Expand Down
2 changes: 1 addition & 1 deletion game/addons/keychain/Keychain.gd.uid
Original file line number Diff line number Diff line change
@@ -1 +1 @@
uid://ba4bw6vqtoail
uid://dgiia2xg7fsud
Loading
Loading