Many fixes for options, settings, and keybinds
This commit is contained in:
parent
8e52e4fa57
commit
f39b7ae72f
9 changed files with 306 additions and 137 deletions
|
@ -3,6 +3,7 @@ Contribute to DMF -- add your name here!
|
||||||
+ [Aussiemon](https://github.com/Aussiemon)
|
+ [Aussiemon](https://github.com/Aussiemon)
|
||||||
+ [Fracticality](https://github.com/fracticality)
|
+ [Fracticality](https://github.com/fracticality)
|
||||||
+ [grasmann](https://github.com/grasmann)
|
+ [grasmann](https://github.com/grasmann)
|
||||||
|
+ [philipdestroyer](https://github.com/philippedavid)
|
||||||
|
|
||||||
# VMF contributors (sorted alphabetically)
|
# VMF contributors (sorted alphabetically)
|
||||||
+ [Aussiemon](https://github.com/Aussiemon)
|
+ [Aussiemon](https://github.com/Aussiemon)
|
||||||
|
|
|
@ -22,6 +22,12 @@ return {
|
||||||
percent = {
|
percent = {
|
||||||
en = "%%",
|
en = "%%",
|
||||||
},
|
},
|
||||||
|
toggle_mod = {
|
||||||
|
en = "Toggle Mod",
|
||||||
|
},
|
||||||
|
toggle_mod_description = {
|
||||||
|
en = "Enable or disable the mod",
|
||||||
|
},
|
||||||
ui_scaling = {
|
ui_scaling = {
|
||||||
en = "UI Scaling for FHD+ Resolutions",
|
en = "UI Scaling for FHD+ Resolutions",
|
||||||
es = "Reescalado de la interfaz para resoluciones Full HD+",
|
es = "Reescalado de la interfaz para resoluciones Full HD+",
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
local dmf = get_mod("DMF")
|
local dmf = get_mod("DMF")
|
||||||
|
|
||||||
|
local InputUtils = require("scripts/managers/input/input_utils")
|
||||||
|
|
||||||
local PRIMARY_BINDABLE_KEYS = {
|
local PRIMARY_BINDABLE_KEYS = {
|
||||||
KEYBOARD = {
|
["keyboard"] = {
|
||||||
[8] = {"Backspace", "backspace"},
|
[8] = {"Backspace", "backspace"},
|
||||||
[9] = {"Tab", "tab"},
|
[9] = {"Tab", "tab"},
|
||||||
[13] = {"Enter", "enter"},
|
[13] = {"Enter", "enter"},
|
||||||
|
@ -116,7 +118,7 @@ local PRIMARY_BINDABLE_KEYS = {
|
||||||
--?[226] = {"\", "oem_102 (> <)"},
|
--?[226] = {"\", "oem_102 (> <)"},
|
||||||
[256] = {"Num Enter", "numpad enter"}
|
[256] = {"Num Enter", "numpad enter"}
|
||||||
},
|
},
|
||||||
MOUSE = {
|
["mouse"] = {
|
||||||
[0] = {"Mouse Left", "mouse left"},
|
[0] = {"Mouse Left", "mouse left"},
|
||||||
[1] = {"Mouse Right", "mouse right"},
|
[1] = {"Mouse Right", "mouse right"},
|
||||||
[2] = {"Mouse Middle", "mouse middle"},
|
[2] = {"Mouse Middle", "mouse middle"},
|
||||||
|
@ -126,8 +128,9 @@ local PRIMARY_BINDABLE_KEYS = {
|
||||||
[11] = {"Mouse Wheel Down", "mouse wheel down"},
|
[11] = {"Mouse Wheel Down", "mouse wheel down"},
|
||||||
[12] = {"Mouse Wheel Left", "mouse wheel left"},
|
[12] = {"Mouse Wheel Left", "mouse wheel left"},
|
||||||
[13] = {"Mouse Wheel Right", "mouse wheel right"}
|
[13] = {"Mouse Wheel Right", "mouse wheel right"}
|
||||||
},--[[ -- will work on this if it will be needed
|
},
|
||||||
GAMEPAD = {
|
--[[ -- will work on this if it will be needed
|
||||||
|
["gamepad"] = {
|
||||||
[0] = {"", "d_up"},
|
[0] = {"", "d_up"},
|
||||||
[1] = {"", "d_down"},
|
[1] = {"", "d_down"},
|
||||||
[2] = {"", "d_left"},
|
[2] = {"", "d_left"},
|
||||||
|
@ -149,31 +152,39 @@ local PRIMARY_BINDABLE_KEYS = {
|
||||||
|
|
||||||
local OTHER_KEYS = {
|
local OTHER_KEYS = {
|
||||||
-- modifier keys
|
-- modifier keys
|
||||||
["shift"] = {160, "Shift", "KEYBOARD", 161},
|
["left shift"] = {160, "Shift", "keyboard", 161},
|
||||||
["ctrl"] = {162, "Ctrl", "KEYBOARD", 163},
|
["right shift"] = {160, "Shift", "keyboard", 161},
|
||||||
["alt"] = {164, "Alt", "KEYBOARD", 165},
|
["shift"] = {160, "Shift", "keyboard", 161},
|
||||||
|
["left ctrl"] = {162, "Ctrl", "keyboard", 163},
|
||||||
|
["right ctrl"] = {162, "Ctrl", "keyboard", 163},
|
||||||
|
["ctrl"] = {162, "Ctrl", "keyboard", 163},
|
||||||
|
["left alt"] = {164, "Alt", "keyboard", 165},
|
||||||
|
["right alt"] = {164, "Alt", "keyboard", 165},
|
||||||
|
["alt"] = {164, "Alt", "keyboard", 165},
|
||||||
-- hack for 'dmf.build_keybind_string' function
|
-- hack for 'dmf.build_keybind_string' function
|
||||||
["no_button"] = {-1, ""}
|
["no_button"] = {-1, ""}
|
||||||
}
|
}
|
||||||
|
|
||||||
local KEYS_INFO = {}
|
local KEYS_INFO = {}
|
||||||
-- Populate KEYS_INFO:
|
|
||||||
|
-- Populate KEYS_INFO: Index, readable name, device name
|
||||||
for input_device_name, input_device_keys in pairs(PRIMARY_BINDABLE_KEYS) do
|
for input_device_name, input_device_keys in pairs(PRIMARY_BINDABLE_KEYS) do
|
||||||
for key_index, key_info in pairs(input_device_keys) do
|
for key_index, key_info in pairs(input_device_keys) do
|
||||||
KEYS_INFO[key_info[2]] = {key_index, key_info[1], input_device_name}
|
KEYS_INFO[key_info[2]] = {key_index, key_info[1], input_device_name}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for key_id, key_data in pairs(OTHER_KEYS) do
|
for key_id, key_data in pairs(OTHER_KEYS) do
|
||||||
KEYS_INFO[key_id] = key_data
|
KEYS_INFO[key_id] = key_data
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Can't use 'Device.released' because it will break keybinds if button is released when game window is not active.
|
-- Can't use 'Device.released' because it will break keybinds if button is released when game window is not active.
|
||||||
local CHECK_INPUT_FUNCTIONS = {
|
local CHECK_INPUT_FUNCTIONS = {
|
||||||
KEYBOARD = {
|
keyboard = {
|
||||||
PRESSED = function(key_id) return Keyboard.pressed(KEYS_INFO[key_id][1]) end,
|
PRESSED = function(key_id) return Keyboard.pressed(KEYS_INFO[key_id][1]) end,
|
||||||
RELEASED = function(key_id) return Keyboard.button(KEYS_INFO[key_id][1]) == 0 end
|
RELEASED = function(key_id) return Keyboard.button(KEYS_INFO[key_id][1]) == 0 end
|
||||||
},
|
},
|
||||||
MOUSE = {
|
mouse = {
|
||||||
PRESSED = function(key_id) return Mouse.pressed(KEYS_INFO[key_id][1]) end,
|
PRESSED = function(key_id) return Mouse.pressed(KEYS_INFO[key_id][1]) end,
|
||||||
RELEASED = function(key_id) return Mouse.button(KEYS_INFO[key_id][1]) == 0 end
|
RELEASED = function(key_id) return Mouse.button(KEYS_INFO[key_id][1]) == 0 end
|
||||||
}
|
}
|
||||||
|
@ -234,7 +245,7 @@ end
|
||||||
|
|
||||||
-- Checks for pressed and released keybinds, performs keybind actions.
|
-- Checks for pressed and released keybinds, performs keybind actions.
|
||||||
-- * Checks for both right and left key modifiers (ctrl, alt, shift).
|
-- * Checks for both right and left key modifiers (ctrl, alt, shift).
|
||||||
-- * If some keybind is pressed, won't check for other keybinds until this keybing is released.
|
-- * If some keybind is pressed, won't check for other keybinds until this keybind is released.
|
||||||
-- * If several mods bound the same keys, keybind action will be performed for all of them, when keybind is pressed.
|
-- * If several mods bound the same keys, keybind action will be performed for all of them, when keybind is pressed.
|
||||||
-- * Keybind is considered released, when its primary key is released.
|
-- * Keybind is considered released, when its primary key is released.
|
||||||
function dmf.check_keybinds()
|
function dmf.check_keybinds()
|
||||||
|
@ -246,10 +257,34 @@ function dmf.check_keybinds()
|
||||||
for primary_key, keybinds_data in pairs(_keybinds) do
|
for primary_key, keybinds_data in pairs(_keybinds) do
|
||||||
if keybinds_data.check_pressed(primary_key) then
|
if keybinds_data.check_pressed(primary_key) then
|
||||||
for _, keybind_data in ipairs(keybinds_data) do
|
for _, keybind_data in ipairs(keybinds_data) do
|
||||||
if (not keybind_data.ctrl and not ctrl_pressed or keybind_data.ctrl and ctrl_pressed) and
|
|
||||||
(not keybind_data.alt and not alt_pressed or keybind_data.alt and alt_pressed) and
|
local all_pressed = true
|
||||||
(not keybind_data.shift and not shift_pressed or keybind_data.shift and shift_pressed)
|
for enabler, _ in pairs(keybind_data.enablers) do
|
||||||
|
|
||||||
|
-- Check that every enabler key is pressed
|
||||||
|
if OTHER_KEYS[enabler] and
|
||||||
|
(
|
||||||
|
Keyboard.button(KEYS_INFO[enabler][1]) +
|
||||||
|
Keyboard.button(KEYS_INFO[enabler][4])
|
||||||
|
) <= 0
|
||||||
|
or not (Keyboard.button(KEYS_INFO[enabler][1]) > 0)
|
||||||
then
|
then
|
||||||
|
all_pressed = false
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check that no modifier keys are pressed that shouldn't be
|
||||||
|
if all_pressed and
|
||||||
|
(not keybind_data.ctrl and ctrl_pressed) and
|
||||||
|
(not keybind_data.alt and alt_pressed) and
|
||||||
|
(not keybind_data.shift and shift_pressed)
|
||||||
|
then
|
||||||
|
all_pressed = false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Peform the keybind action if everything validates
|
||||||
|
if all_pressed then
|
||||||
if perform_keybind_action(keybind_data, true) then
|
if perform_keybind_action(keybind_data, true) then
|
||||||
if keybind_data.trigger == "held" then
|
if keybind_data.trigger == "held" then
|
||||||
keybind_data.release_action = true
|
keybind_data.release_action = true
|
||||||
|
@ -299,9 +334,10 @@ function dmf.generate_keybinds()
|
||||||
global = raw_keybind_data.global,
|
global = raw_keybind_data.global,
|
||||||
trigger = raw_keybind_data.trigger,
|
trigger = raw_keybind_data.trigger,
|
||||||
type = raw_keybind_data.type,
|
type = raw_keybind_data.type,
|
||||||
ctrl = modifier_keys["ctrl"],
|
enablers = modifier_keys,
|
||||||
alt = modifier_keys["alt"],
|
ctrl = modifier_keys["ctrl"] or modifier_keys["left ctrl"] or modifier_keys["right ctrl"],
|
||||||
shift = modifier_keys["shift"],
|
alt = modifier_keys["alt"] or modifier_keys["left alt"] or modifier_keys["right alt"],
|
||||||
|
shift = modifier_keys["shift"] or modifier_keys["left shift"] or modifier_keys["right shift"],
|
||||||
|
|
||||||
function_name = raw_keybind_data.function_name,
|
function_name = raw_keybind_data.function_name,
|
||||||
view_name = raw_keybind_data.view_name
|
view_name = raw_keybind_data.view_name
|
||||||
|
@ -347,7 +383,7 @@ function dmf.create_keybinds_input_service()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Converts key_index to readable key_id, which is used by DMF to idenify keys.
|
-- Converts key_index to readable key_id, which is used by DMF to identify keys.
|
||||||
-- (Used for capturing keybinds)
|
-- (Used for capturing keybinds)
|
||||||
function dmf.get_key_id(device, key_index)
|
function dmf.get_key_id(device, key_index)
|
||||||
local key_info = PRIMARY_BINDABLE_KEYS[device][key_index]
|
local key_info = PRIMARY_BINDABLE_KEYS[device][key_index]
|
||||||
|
@ -372,6 +408,79 @@ function dmf.build_keybind_string(keys)
|
||||||
return table.concat(readable_key_names, " + ")
|
return table.concat(readable_key_names, " + ")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Translate key watch result to mod options keybind
|
||||||
|
-- (Used in keybind widget)
|
||||||
|
function dmf.keybind_result_to_keys(keybind_result)
|
||||||
|
local keys = {}
|
||||||
|
|
||||||
|
-- Get the local name of the main key
|
||||||
|
if keybind_result.main then
|
||||||
|
|
||||||
|
local global_name = keybind_result.main
|
||||||
|
local device_type = InputUtils.key_device_type(global_name)
|
||||||
|
local local_name = InputUtils.local_key_name(global_name, device_type)
|
||||||
|
|
||||||
|
-- Check for a missing or unbindable primary key name
|
||||||
|
if not local_name or not dmf.can_bind_as_primary_key(local_name) then
|
||||||
|
return keys
|
||||||
|
end
|
||||||
|
|
||||||
|
keys[1] = local_name
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add the enablers keys as additional keys
|
||||||
|
if keybind_result.enablers then
|
||||||
|
for _, global_name in ipairs(keybind_result.enablers) do
|
||||||
|
|
||||||
|
local device_type = InputUtils.key_device_type(global_name)
|
||||||
|
local local_name = InputUtils.local_key_name(global_name, device_type)
|
||||||
|
|
||||||
|
keys[#keys + 1] = local_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return keys
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Translate mod options keybind to key watch result
|
||||||
|
-- (Used in keybind widget)
|
||||||
|
function dmf.keys_to_keybind_result(keys)
|
||||||
|
local keybind_result = {
|
||||||
|
enablers = {},
|
||||||
|
disablers = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if not keys or #keys == 0 then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if keys[1] then
|
||||||
|
local local_name = keys[1]
|
||||||
|
local global_name = KEYS_INFO[local_name] and InputUtils.local_to_global_name(local_name, KEYS_INFO[local_name][3])
|
||||||
|
|
||||||
|
-- End early if our main key doesn't exist, and return an empty result
|
||||||
|
if not global_name then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
keybind_result.main = global_name
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add all remaining keys to the enablers list
|
||||||
|
for i = 2, #keys do
|
||||||
|
local local_name = keys[i]
|
||||||
|
local global_name = KEYS_INFO[local_name] and InputUtils.local_to_global_name(local_name, KEYS_INFO[local_name][3])
|
||||||
|
|
||||||
|
if global_name then
|
||||||
|
keybind_result.enablers[#keybind_result.enablers + 1] = global_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return keybind_result
|
||||||
|
end
|
||||||
|
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
-- ##### Script ########################################################################################################
|
-- ##### Script ########################################################################################################
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
|
|
|
@ -80,7 +80,7 @@ end
|
||||||
|
|
||||||
|
|
||||||
DMFMod.add_global_localize_strings = function (self, text_translations)
|
DMFMod.add_global_localize_strings = function (self, text_translations)
|
||||||
for text_id, translations in ipairs(text_translations) do
|
for text_id, translations in pairs(text_translations) do
|
||||||
if not _global_localization_database[text_id] then
|
if not _global_localization_database[text_id] then
|
||||||
_global_localization_database[text_id] = translations
|
_global_localization_database[text_id] = translations
|
||||||
end
|
end
|
||||||
|
|
|
@ -250,7 +250,7 @@ end
|
||||||
|
|
||||||
dmf.load_developer_mode_settings = function () --@TODO: maybe move it to somewhere else?
|
dmf.load_developer_mode_settings = function () --@TODO: maybe move it to somewhere else?
|
||||||
Managers.mod._settings.developer_mode = dmf:get("developer_mode")
|
Managers.mod._settings.developer_mode = dmf:get("developer_mode")
|
||||||
Application.set_user_setting("mod_settings", Managers.mod._settings)
|
Application.set_user_setting("mod_manager_settings", Managers.mod._settings)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
|
|
|
@ -110,7 +110,15 @@ local function remove_injected_views(on_reload)
|
||||||
if on_reload then
|
if on_reload then
|
||||||
|
|
||||||
for view_name, _ in pairs(_custom_views_data) do
|
for view_name, _ in pairs(_custom_views_data) do
|
||||||
-- Remove injected views.
|
|
||||||
|
-- Close the view if active
|
||||||
|
if Managers.ui:view_active(view_name) then
|
||||||
|
|
||||||
|
local force_close = true
|
||||||
|
Managers.ui:close_view(view_name, force_close)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Remove the injected view
|
||||||
_ingame_ui._view_list[view_name] = nil
|
_ingame_ui._view_list[view_name] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -308,11 +316,6 @@ dmf:hook_safe(ViewLoader, "init", function()
|
||||||
_custom_view_persistent_data.loader_initialized = true
|
_custom_view_persistent_data.loader_initialized = true
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Track the deletion of the view loader
|
|
||||||
dmf:hook_safe(ViewLoader, "destroy", function()
|
|
||||||
_custom_view_persistent_data.loader_initialized = false
|
|
||||||
end)
|
|
||||||
|
|
||||||
|
|
||||||
-- Track the loading of views, set the loader flag if class selection is reached
|
-- Track the loading of views, set the loader flag if class selection is reached
|
||||||
dmf:hook_safe(UIManager, "load_view", function(self, view_name)
|
dmf:hook_safe(UIManager, "load_view", function(self, view_name)
|
||||||
|
|
|
@ -675,7 +675,6 @@ DMFOptionsView._setup_category_config = function (self, config)
|
||||||
for i = 1, #config_categories do
|
for i = 1, #config_categories do
|
||||||
local category_config = config_categories[i]
|
local category_config = config_categories[i]
|
||||||
local category_display_name = category_config.display_name
|
local category_display_name = category_config.display_name
|
||||||
local category_icon = category_config.icon
|
|
||||||
local category_reset_function = category_config.reset_function
|
local category_reset_function = category_config.reset_function
|
||||||
local valid = self._validation_mapping[category_display_name].validation_result
|
local valid = self._validation_mapping[category_display_name].validation_result
|
||||||
|
|
||||||
|
@ -683,7 +682,6 @@ DMFOptionsView._setup_category_config = function (self, config)
|
||||||
local entry = {
|
local entry = {
|
||||||
widget_type = "settings_button",
|
widget_type = "settings_button",
|
||||||
display_name = category_display_name,
|
display_name = category_display_name,
|
||||||
icon = category_icon,
|
|
||||||
can_be_reset = category_config.can_be_reset,
|
can_be_reset = category_config.can_be_reset,
|
||||||
pressed_function = function (parent, widget, entry)
|
pressed_function = function (parent, widget, entry)
|
||||||
self._category_content_grid:select_widget(widget)
|
self._category_content_grid:select_widget(widget)
|
||||||
|
|
|
@ -512,20 +512,20 @@ blueprints.dropdown = {
|
||||||
local has_options_function = entry.options_function ~= nil
|
local has_options_function = entry.options_function ~= nil
|
||||||
local has_dynamic_contents = entry.has_dynamic_contents
|
local has_dynamic_contents = entry.has_dynamic_contents
|
||||||
local options = entry.options or entry.options_function and entry.options_function()
|
local options = entry.options or entry.options_function and entry.options_function()
|
||||||
local options_by_id = {}
|
|
||||||
local num_options = #options
|
local num_options = #options
|
||||||
local num_visible_options = math.min(num_options, max_visible_options)
|
local num_visible_options = math.min(num_options, max_visible_options)
|
||||||
content.num_visible_options = num_visible_options
|
content.num_visible_options = num_visible_options
|
||||||
local optional_num_decimals = entry.optional_num_decimals
|
local optional_num_decimals = entry.optional_num_decimals
|
||||||
local number_format = string.format("%%.%sf", optional_num_decimals or DEFAULT_NUM_DECIMALS)
|
local number_format = string.format("%%.%sf", optional_num_decimals or DEFAULT_NUM_DECIMALS)
|
||||||
|
|
||||||
|
local options_by_value = {}
|
||||||
for i = 1, num_options do
|
for i = 1, num_options do
|
||||||
local option = options[i]
|
local option = options[i]
|
||||||
options_by_id[option.id] = option
|
options_by_value[option.value] = option
|
||||||
end
|
end
|
||||||
|
|
||||||
content.number_format = number_format
|
content.number_format = number_format
|
||||||
content.options_by_id = options_by_id
|
content.options_by_value = options_by_value
|
||||||
content.options = options
|
content.options = options
|
||||||
|
|
||||||
content.hotspot.pressed_callback = function ()
|
content.hotspot.pressed_callback = function ()
|
||||||
|
@ -559,7 +559,7 @@ blueprints.dropdown = {
|
||||||
local offset = widget.offset
|
local offset = widget.offset
|
||||||
local style = widget.style
|
local style = widget.style
|
||||||
local options = content.options
|
local options = content.options
|
||||||
local options_by_id = content.options_by_id
|
local options_by_value = content.options_by_value
|
||||||
local num_visible_options = content.num_visible_options
|
local num_visible_options = content.num_visible_options
|
||||||
local num_options = #options
|
local num_options = #options
|
||||||
local focused = content.exclusive_focus and not is_disabled
|
local focused = content.exclusive_focus and not is_disabled
|
||||||
|
@ -587,7 +587,7 @@ blueprints.dropdown = {
|
||||||
|
|
||||||
value = entry.get_function and entry:get_function() or content.internal_value or "<not selected>"
|
value = entry.get_function and entry:get_function() or content.internal_value or "<not selected>"
|
||||||
|
|
||||||
local preview_option = options_by_id[value]
|
local preview_option = options_by_value[value]
|
||||||
local preview_option_id = preview_option and preview_option.id
|
local preview_option_id = preview_option and preview_option.id
|
||||||
local preview_value = preview_option and preview_option.display_name or Localize("loc_settings_option_unavailable")
|
local preview_value = preview_option and preview_option.display_name or Localize("loc_settings_option_unavailable")
|
||||||
|
|
||||||
|
@ -677,7 +677,7 @@ blueprints.dropdown = {
|
||||||
|
|
||||||
if not new_value and focused and not using_gamepad and option_hotspot.on_pressed then
|
if not new_value and focused and not using_gamepad and option_hotspot.on_pressed then
|
||||||
option_hotspot.on_pressed = nil
|
option_hotspot.on_pressed = nil
|
||||||
new_value = option.id
|
new_value = option.value
|
||||||
content.selected_index = i
|
content.selected_index = i
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,27 @@
|
||||||
local dmf = get_mod("DMF")
|
local dmf = get_mod("DMF")
|
||||||
|
|
||||||
local OptionsUtilities = require("scripts/utilities/ui/options")
|
local OptionsUtilities = require("scripts/utilities/ui/options")
|
||||||
local InputUtils = require("scripts/managers/input/input_utils")
|
|
||||||
|
|
||||||
local _type_template_map = {}
|
local _type_template_map = {}
|
||||||
|
|
||||||
|
local _devices = {
|
||||||
|
"keyboard",
|
||||||
|
"mouse"
|
||||||
|
}
|
||||||
|
local _cancel_keys = {
|
||||||
|
"keyboard_esc"
|
||||||
|
}
|
||||||
|
local _reserved_keys = {}
|
||||||
|
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
-- ##### Local functions ##############################################################################################
|
-- ##### Local functions ##############################################################################################
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
|
|
||||||
-- Create value slider template
|
-- #####################
|
||||||
|
-- ###### Header #######
|
||||||
|
-- #####################
|
||||||
|
|
||||||
|
-- Create header template
|
||||||
local create_header_template = function (self, params)
|
local create_header_template = function (self, params)
|
||||||
|
|
||||||
local template = {
|
local template = {
|
||||||
|
@ -24,11 +36,15 @@ end
|
||||||
_type_template_map["header"] = create_header_template
|
_type_template_map["header"] = create_header_template
|
||||||
|
|
||||||
|
|
||||||
|
-- ###########################
|
||||||
|
-- ###### Percent Slider #####
|
||||||
|
-- ###########################
|
||||||
|
|
||||||
-- Create percentage slider template
|
-- Create percentage slider template
|
||||||
local create_percent_slider_template = function (self, params)
|
local create_percent_slider_template = function (self, params)
|
||||||
|
|
||||||
params.on_value_changed_function = function(new_value)
|
params.on_value_changed_function = function(new_value)
|
||||||
get_mod(params.mod_name):set(params.setting_id, new_value)
|
get_mod(params.mod_name):set(params.setting_id, new_value, true)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
@ -53,11 +69,15 @@ end
|
||||||
_type_template_map["percent_slider"] = create_percent_slider_template
|
_type_template_map["percent_slider"] = create_percent_slider_template
|
||||||
|
|
||||||
|
|
||||||
|
-- ###########################
|
||||||
|
-- ###### Value Slider #######
|
||||||
|
-- ###########################
|
||||||
|
|
||||||
-- Create value slider template
|
-- Create value slider template
|
||||||
local create_value_slider_template = function (self, params)
|
local create_value_slider_template = function (self, params)
|
||||||
|
|
||||||
params.on_value_changed_function = function(new_value)
|
params.on_value_changed_function = function(new_value)
|
||||||
get_mod(params.mod_name):set(params.setting_id, new_value)
|
get_mod(params.mod_name):set(params.setting_id, new_value, true)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
@ -87,6 +107,10 @@ _type_template_map["value_slider"] = create_value_slider_template
|
||||||
_type_template_map["numeric"] = create_value_slider_template
|
_type_template_map["numeric"] = create_value_slider_template
|
||||||
|
|
||||||
|
|
||||||
|
-- ######################
|
||||||
|
-- ###### Checkbox ######
|
||||||
|
-- ######################
|
||||||
|
|
||||||
-- Create checkbox template
|
-- Create checkbox template
|
||||||
local create_checkbox_template = function (self, params)
|
local create_checkbox_template = function (self, params)
|
||||||
local template = {
|
local template = {
|
||||||
|
@ -99,7 +123,7 @@ local create_checkbox_template = function (self, params)
|
||||||
value_type = "boolean",
|
value_type = "boolean",
|
||||||
}
|
}
|
||||||
template.on_activated = function(new_value)
|
template.on_activated = function(new_value)
|
||||||
get_mod(params.mod_name):set(params.setting_id, new_value)
|
get_mod(params.mod_name):set(params.setting_id, new_value, true)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
@ -112,6 +136,40 @@ end
|
||||||
_type_template_map["checkbox"] = create_checkbox_template
|
_type_template_map["checkbox"] = create_checkbox_template
|
||||||
|
|
||||||
|
|
||||||
|
-- ########################
|
||||||
|
-- ###### Mod Toggle ######
|
||||||
|
-- ########################
|
||||||
|
|
||||||
|
-- Create mod toggle template
|
||||||
|
local create_mod_toggle_template = function (self, params)
|
||||||
|
local template = {
|
||||||
|
after = params.after,
|
||||||
|
category = params.category,
|
||||||
|
default_value = true,
|
||||||
|
display_name = dmf:localize("toggle_mod"),
|
||||||
|
indentation_level = 0,
|
||||||
|
tooltip_text = dmf:localize("toggle_mod_description"),
|
||||||
|
value_type = "boolean",
|
||||||
|
}
|
||||||
|
|
||||||
|
template.on_activated = function(new_value)
|
||||||
|
dmf.mod_state_changed(params.mod_name, new_value)
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
template.get_function = function()
|
||||||
|
return get_mod(params.mod_name):is_enabled()
|
||||||
|
end
|
||||||
|
|
||||||
|
return template
|
||||||
|
end
|
||||||
|
_type_template_map["mod_toggle"] = create_mod_toggle_template
|
||||||
|
|
||||||
|
|
||||||
|
-- ######################
|
||||||
|
-- ###### Dropdown ######
|
||||||
|
-- ######################
|
||||||
|
|
||||||
-- Create dropdown template
|
-- Create dropdown template
|
||||||
local create_dropdown_template = function (self, params)
|
local create_dropdown_template = function (self, params)
|
||||||
|
|
||||||
|
@ -131,7 +189,7 @@ local create_dropdown_template = function (self, params)
|
||||||
widget_type = "dropdown",
|
widget_type = "dropdown",
|
||||||
}
|
}
|
||||||
template.on_activated = function(new_value)
|
template.on_activated = function(new_value)
|
||||||
get_mod(params.mod_name):set(params.setting_id, new_value)
|
get_mod(params.mod_name):set(params.setting_id, new_value, true)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
@ -144,34 +202,30 @@ end
|
||||||
_type_template_map["dropdown"] = create_dropdown_template
|
_type_template_map["dropdown"] = create_dropdown_template
|
||||||
|
|
||||||
|
|
||||||
local set_new_keybind = function (self, keybind_widget_content)
|
-- ###########################
|
||||||
|
-- ######### Keybind #########
|
||||||
|
-- ###########################
|
||||||
|
|
||||||
|
local set_new_keybind = function (self, keybind_data)
|
||||||
|
local mod = get_mod(keybind_data.mod_name)
|
||||||
dmf.add_mod_keybind(
|
dmf.add_mod_keybind(
|
||||||
get_mod(keybind_widget_content.mod_name),
|
mod,
|
||||||
keybind_widget_content.setting_id,
|
keybind_data.setting_id,
|
||||||
{
|
{
|
||||||
global = keybind_widget_content.keybind_global,
|
global = keybind_data.keybind_global,
|
||||||
trigger = keybind_widget_content.keybind_trigger,
|
trigger = keybind_data.keybind_trigger,
|
||||||
type = keybind_widget_content.keybind_type,
|
type = keybind_data.keybind_type,
|
||||||
keys = keybind_widget_content.keys,
|
keys = keybind_data.keys,
|
||||||
function_name = keybind_widget_content.function_name,
|
function_name = keybind_data.function_name,
|
||||||
view_name = keybind_widget_content.view_name,
|
view_name = keybind_data.view_name,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
mod:set(keybind_data.setting_id, keybind_data.keys, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Create keybind template
|
-- Create keybind template
|
||||||
local create_keybind_template = function (self, params)
|
local create_keybind_template = function (self, params)
|
||||||
local reserved_keys = {}
|
|
||||||
local cancel_keys = {
|
|
||||||
"keyboard_esc"
|
|
||||||
}
|
|
||||||
local devices = {
|
|
||||||
"keyboard",
|
|
||||||
"mouse",
|
|
||||||
"xbox_controller",
|
|
||||||
"ps4_controller"
|
|
||||||
}
|
|
||||||
|
|
||||||
local template = {
|
local template = {
|
||||||
widget_type = "keybind",
|
widget_type = "keybind",
|
||||||
|
@ -181,63 +235,57 @@ local create_keybind_template = function (self, params)
|
||||||
group_name = params.category,
|
group_name = params.category,
|
||||||
category = params.category,
|
category = params.category,
|
||||||
after = params.parent_index,
|
after = params.parent_index,
|
||||||
devices = devices,
|
devices = _devices,
|
||||||
sort_order = params.sort_order,
|
sort_order = params.sort_order,
|
||||||
cancel_keys = cancel_keys,
|
cancel_keys = _cancel_keys,
|
||||||
reserved_keys = reserved_keys,
|
reserved_keys = _reserved_keys,
|
||||||
indentation_level = params.depth,
|
indentation_level = params.depth,
|
||||||
mod_name = params.mod_name,
|
mod_name = params.mod_name,
|
||||||
setting_id = params.setting_id,
|
setting_id = params.setting_id,
|
||||||
|
keys = dmf.keys_to_keybind_result(params.keys),
|
||||||
|
|
||||||
on_activated = function (new_value, old_value)
|
on_activated = function (new_value, old_value)
|
||||||
|
|
||||||
for i = 1, #cancel_keys do
|
for i = 1, #_cancel_keys do
|
||||||
local cancel_key = cancel_keys[i]
|
local cancel_key = _cancel_keys[i]
|
||||||
if cancel_key == new_value.main then
|
if cancel_key == new_value.main then
|
||||||
|
|
||||||
-- Prevent unbinding the mod options menu
|
-- Prevent unbinding the mod options menu
|
||||||
if params.setting_id ~= "open_dmf_options" then
|
if params.setting_id ~= "open_dmf_options" then
|
||||||
|
|
||||||
params.keybind_text = ""
|
-- Unbind the keybind
|
||||||
params.keys = {}
|
params.keys = {}
|
||||||
|
|
||||||
set_new_keybind(self, params)
|
set_new_keybind(self, params)
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for i = 1, #reserved_keys do
|
for i = 1, #_reserved_keys do
|
||||||
local reserved_key = reserved_keys[i]
|
local reserved_key = _reserved_keys[i]
|
||||||
if reserved_key == new_value.main then
|
if reserved_key == new_value.main then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local device_type = InputUtils.key_device_type(new_value.main)
|
-- Get the new keybind
|
||||||
local key_name = InputUtils.local_key_name(new_value.main, device_type)
|
local keys = dmf.keybind_result_to_keys(new_value)
|
||||||
|
|
||||||
params.keybind_text = key_name
|
|
||||||
params.keys = {key_name}
|
|
||||||
|
|
||||||
|
-- Bind the new key and prevent unbinding the mod options menu
|
||||||
|
if keys and #keys > 0 or params.setting_id ~= "open_dmf_options" then
|
||||||
|
params.keys = keys
|
||||||
set_new_keybind(self, params)
|
set_new_keybind(self, params)
|
||||||
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
|
|
||||||
get_function = function (template)
|
get_function = function (template)
|
||||||
|
local keys = get_mod(template.mod_name):get(template.setting_id)
|
||||||
|
local keybind_result = dmf.keys_to_keybind_result(keys)
|
||||||
|
|
||||||
local setting = get_mod(template.mod_name):get(template.setting_id)
|
return keybind_result
|
||||||
local local_name = setting and setting[1]
|
|
||||||
if not local_name then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local global_name = InputUtils.local_to_global_name(local_name, "keyboard")
|
|
||||||
return {
|
|
||||||
main = global_name,
|
|
||||||
disablers = {},
|
|
||||||
enablers = {},
|
|
||||||
}
|
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,6 +294,11 @@ end
|
||||||
_type_template_map["keybind"] = create_keybind_template
|
_type_template_map["keybind"] = create_keybind_template
|
||||||
|
|
||||||
|
|
||||||
|
-- ###########################
|
||||||
|
-- ###### Miscellaneous ######
|
||||||
|
-- ###########################
|
||||||
|
|
||||||
|
-- Get the template creation function associated with a given widget data type
|
||||||
local function widget_data_to_template(self, data)
|
local function widget_data_to_template(self, data)
|
||||||
if data and data.type and type(data.type) == "string" and _type_template_map[data.type] then
|
if data and data.type and type(data.type) == "string" and _type_template_map[data.type] then
|
||||||
return _type_template_map[data.type](self, data)
|
return _type_template_map[data.type](self, data)
|
||||||
|
@ -256,18 +309,30 @@ local function widget_data_to_template(self, data)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Add mod categories to options view
|
-- Add a mod category to the options view categories
|
||||||
local create_mod_category = function (self, categories, widget_data)
|
local function create_mod_category(self, categories, widget_data)
|
||||||
local category = {
|
local category = {
|
||||||
can_be_reset = widget_data.can_be_reset or true,
|
can_be_reset = widget_data.can_be_reset or true,
|
||||||
display_name = widget_data.readable_mod_name or widget_data.mod_name or "",
|
display_name = widget_data.readable_mod_name or widget_data.mod_name or "",
|
||||||
icon = widget_data.icon_material or "content/ui/materials/icons/system/settings/category_gameplay",
|
|
||||||
custom = true
|
custom = true
|
||||||
}
|
}
|
||||||
categories[#categories + 1] = category
|
categories[#categories + 1] = category
|
||||||
return category
|
return category
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Create an option template and handle index offsets
|
||||||
|
local function create_option_template(self, widget_data, category_name, index_offset)
|
||||||
|
local template = widget_data_to_template(self, widget_data)
|
||||||
|
if template then
|
||||||
|
template.custom = true
|
||||||
|
template.category = category_name
|
||||||
|
template.after = template.after and template.after + index_offset or nil
|
||||||
|
|
||||||
|
return template
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
-- ##### Hooks ########################################################################################################
|
-- ##### Hooks ########################################################################################################
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
|
@ -276,20 +341,48 @@ end
|
||||||
-- ##### DMF internal functions and variables #########################################################################
|
-- ##### DMF internal functions and variables #########################################################################
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
|
|
||||||
|
|
||||||
-- Add mod settings to options view
|
-- Add mod settings to options view
|
||||||
dmf.create_mod_options_settings = function (self, options_templates)
|
dmf.create_mod_options_settings = function (self, options_templates)
|
||||||
local categories = options_templates.categories
|
local categories = options_templates.categories
|
||||||
local settings = options_templates.settings
|
local settings = options_templates.settings
|
||||||
|
|
||||||
|
-- Create a category for every mod
|
||||||
for _, mod_data in ipairs(dmf.options_widgets_data) do
|
for _, mod_data in ipairs(dmf.options_widgets_data) do
|
||||||
local category = create_mod_category(self, categories, mod_data[1])
|
local category = create_mod_category(self, categories, mod_data[1])
|
||||||
|
|
||||||
for _, widget_data in ipairs(mod_data) do
|
local index_offset = 0
|
||||||
local template = widget_data_to_template(self, widget_data)
|
|
||||||
|
-- Create the category header
|
||||||
|
local template = create_option_template(self, mod_data[1], category.display_name, index_offset)
|
||||||
|
if template then
|
||||||
|
settings[#settings + 1] = template
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create a top-level toggle option if the mod is togglable
|
||||||
|
if mod_data[1].is_togglable then
|
||||||
|
local toggle_widget_data = {
|
||||||
|
mod_name = mod_data[1].mod_name,
|
||||||
|
category = category.display_name,
|
||||||
|
after = #settings,
|
||||||
|
type = "mod_toggle"
|
||||||
|
}
|
||||||
|
|
||||||
|
local toggle_template = create_option_template(self, toggle_widget_data, category.display_name, index_offset)
|
||||||
|
if toggle_template then
|
||||||
|
settings[#settings + 1] = toggle_template
|
||||||
|
index_offset = index_offset + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Populate the category with options taken from the remaining options data
|
||||||
|
for i = 2, #mod_data do
|
||||||
|
local widget_data = mod_data[i]
|
||||||
|
|
||||||
|
template = widget_data_to_template(self, widget_data)
|
||||||
if template then
|
if template then
|
||||||
template.custom = true
|
template.custom = true
|
||||||
template.category = category.display_name
|
template.category = category.display_name
|
||||||
|
template.after = template.after + index_offset
|
||||||
|
|
||||||
settings[#settings + 1] = template
|
settings[#settings + 1] = template
|
||||||
end
|
end
|
||||||
|
@ -297,47 +390,6 @@ dmf.create_mod_options_settings = function (self, options_templates)
|
||||||
end
|
end
|
||||||
|
|
||||||
return options_templates
|
return options_templates
|
||||||
|
|
||||||
--[[local settings = OptionsView._options_templates.settings
|
|
||||||
|
|
||||||
for name, this_mod in pairs(Mods) do
|
|
||||||
-- Custom settings
|
|
||||||
if type(this_mod) == "table" and this_mod.options then
|
|
||||||
|
|
||||||
local text = this_mod.text or name
|
|
||||||
Mods.Localization.add("loc_settings_menu_group_mods_"..name, text)
|
|
||||||
|
|
||||||
local options_no_after = 0
|
|
||||||
for _, option in pairs(this_mod.options) do
|
|
||||||
if not option.after then
|
|
||||||
options_no_after = options_no_after + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if options_no_after > 0 then
|
|
||||||
settings[#settings+1] = {
|
|
||||||
widget_type = "group_header",
|
|
||||||
group_name = "mods_settings",
|
|
||||||
display_name = "loc_settings_menu_group_mods_"..name,
|
|
||||||
category = "loc_settings_menu_category_mods",
|
|
||||||
custom = true,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, setting in pairs(this_mod.options) do
|
|
||||||
setting.custom = true
|
|
||||||
setting.category = setting.category or "loc_settings_menu_category_mods"
|
|
||||||
setting.indentation_level = setting.after and 1 or 0
|
|
||||||
if setting.after then
|
|
||||||
local index = self:after_index(OptionsView, setting.after)
|
|
||||||
table.insert(settings, index, setting)
|
|
||||||
else
|
|
||||||
settings[#settings+1] = setting
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end]]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue