Many fixes for options, settings, and keybinds

This commit is contained in:
Aussiemon 2023-01-07 12:27:05 -07:00
parent 8e52e4fa57
commit f39b7ae72f
9 changed files with 306 additions and 137 deletions

View file

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

View file

@ -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+",

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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