mirror of
https://github.com/luanti-org/luanti.git
synced 2025-08-01 17:38:41 +00:00
Settings GUI: Add setting dependencies (#13704)
This commit is contained in:
parent
752ce1a1b2
commit
d16d1a1341
4 changed files with 274 additions and 56 deletions
|
@ -49,6 +49,9 @@ end
|
|||
|
||||
local change_keys = {
|
||||
query_text = "Change keys",
|
||||
requires = {
|
||||
keyboard_mouse = true,
|
||||
},
|
||||
get_formspec = function(self, avail_w)
|
||||
local btn_w = math.min(avail_w, 3)
|
||||
return ("button[0,0;%f,0.8;btn_change_keys;%s]"):format(btn_w, fgettext("Change keys")), 0.8
|
||||
|
@ -173,7 +176,7 @@ end
|
|||
|
||||
local function filter_page_content(page, query_keywords)
|
||||
if #query_keywords == 0 then
|
||||
return page.content
|
||||
return page.content, 0
|
||||
end
|
||||
|
||||
local retval = {}
|
||||
|
@ -209,12 +212,6 @@ local function update_filtered_pages(query)
|
|||
filtered_pages = {}
|
||||
filtered_page_by_id = {}
|
||||
|
||||
if query == "" or query == nil then
|
||||
filtered_pages = all_pages
|
||||
filtered_page_by_id = page_by_id
|
||||
return filtered_pages[1].id
|
||||
end
|
||||
|
||||
local query_keywords = {}
|
||||
for word in query:lower():gmatch("%S+") do
|
||||
table.insert(query_keywords, word)
|
||||
|
@ -225,7 +222,7 @@ local function update_filtered_pages(query)
|
|||
|
||||
for _, page in ipairs(all_pages) do
|
||||
local content, page_weight = filter_page_content(page, query_keywords)
|
||||
if #content > 0 then
|
||||
if page_has_contents(content) then
|
||||
local new_page = table.copy(page)
|
||||
new_page.content = content
|
||||
|
||||
|
@ -243,28 +240,113 @@ local function update_filtered_pages(query)
|
|||
end
|
||||
|
||||
|
||||
local function build_page_components(page)
|
||||
local retval = {}
|
||||
local j = 1
|
||||
for i, content in ipairs(page.content) do
|
||||
if content == false then
|
||||
-- false is used to disable components conditionally (ie: Android specific)
|
||||
j = j - 1
|
||||
elseif type(content) == "string" then
|
||||
local setting = get_setting_info(content)
|
||||
assert(setting, "Unknown setting: " .. content)
|
||||
local function check_requirements(name, requires)
|
||||
if requires == nil then
|
||||
return true
|
||||
end
|
||||
|
||||
local video_driver = core.get_active_driver()
|
||||
local shaders_support = video_driver == "opengl" or video_driver == "ogles2"
|
||||
local special = {
|
||||
android = PLATFORM == "Android",
|
||||
desktop = PLATFORM ~= "Android",
|
||||
touchscreen_gui = TOUCHSCREEN_GUI,
|
||||
keyboard_mouse = not TOUCHSCREEN_GUI,
|
||||
shaders_support = shaders_support,
|
||||
shaders = core.settings:get_bool("enable_shaders") and shaders_support,
|
||||
opengl = video_driver == "opengl",
|
||||
gles = video_driver:sub(1, 5) == "ogles",
|
||||
}
|
||||
|
||||
for req_key, req_value in pairs(requires) do
|
||||
if special[req_key] == nil then
|
||||
local required_setting = get_setting_info(req_key)
|
||||
if required_setting == nil then
|
||||
core.log("warning", "Unknown setting " .. req_key .. " required by " .. name)
|
||||
end
|
||||
local actual_value = core.settings:get_bool(req_key,
|
||||
required_setting and core.is_yes(required_setting.default))
|
||||
if actual_value ~= req_value then
|
||||
return false
|
||||
end
|
||||
elseif special[req_key] ~= req_value then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
function page_has_contents(content)
|
||||
for _, item in ipairs(content) do
|
||||
if item == false or item.heading then --luacheck: ignore
|
||||
-- skip
|
||||
elseif type(item) == "string" then
|
||||
local setting = get_setting_info(item)
|
||||
assert(setting, "Unknown setting: " .. item)
|
||||
if check_requirements(setting.name, setting.requires) then
|
||||
return true
|
||||
end
|
||||
elseif item.get_formspec then
|
||||
if check_requirements(item.id, item.requires) then
|
||||
return true
|
||||
end
|
||||
else
|
||||
error("Unknown content in page: " .. dump(item))
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
local function build_page_components(page)
|
||||
-- Filter settings based on requirements
|
||||
local content = {}
|
||||
local last_heading
|
||||
for _, item in ipairs(page.content) do
|
||||
if item == false then --luacheck: ignore
|
||||
-- skip
|
||||
elseif item.heading then
|
||||
last_heading = item
|
||||
else
|
||||
local name, requires
|
||||
if type(item) == "string" then
|
||||
local setting = get_setting_info(item)
|
||||
assert(setting, "Unknown setting: " .. item)
|
||||
name = setting.name
|
||||
requires = setting.requires
|
||||
elseif item.get_formspec then
|
||||
name = item.id
|
||||
requires = item.requires
|
||||
else
|
||||
error("Unknown content in page: " .. dump(item))
|
||||
end
|
||||
|
||||
if check_requirements(name, requires) then
|
||||
if last_heading then
|
||||
content[#content + 1] = last_heading
|
||||
last_heading = nil
|
||||
end
|
||||
content[#content + 1] = item
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Create components
|
||||
local retval = {}
|
||||
for i, item in ipairs(content) do
|
||||
if type(item) == "string" then
|
||||
local setting = get_setting_info(item)
|
||||
local component_func = component_funcs[setting.type]
|
||||
assert(component_func, "Unknown setting type: " .. setting.type)
|
||||
retval[j] = component_func(setting)
|
||||
elseif content.get_formspec then
|
||||
retval[j] = content
|
||||
elseif content.heading then
|
||||
retval[j] = component_funcs.heading(content.heading)
|
||||
else
|
||||
error("Unknown content in page: " .. dump(content))
|
||||
retval[i] = component_func(setting)
|
||||
elseif item.get_formspec then
|
||||
retval[i] = item
|
||||
elseif item.heading then
|
||||
retval[i] = component_funcs.heading(item.heading)
|
||||
end
|
||||
j = j + 1
|
||||
end
|
||||
return retval
|
||||
end
|
||||
|
@ -343,7 +425,8 @@ local function get_formspec(dialogdata)
|
|||
local last_section = nil
|
||||
for _, other_page in ipairs(filtered_pages) do
|
||||
if other_page.section ~= last_section then
|
||||
fs[#fs + 1] = ("label[0.1,%f;%s]"):format(y + 0.41, core.colorize("#ff0", fgettext(other_page.section)))
|
||||
fs[#fs + 1] = ("label[0.1,%f;%s]"):format(
|
||||
y + 0.41, core.colorize("#ff0", fgettext(other_page.section)))
|
||||
last_section = other_page.section
|
||||
y = y + 0.82
|
||||
end
|
||||
|
@ -487,10 +570,15 @@ local function buttonhandler(this, fields)
|
|||
|
||||
for i, comp in ipairs(dialogdata.components) do
|
||||
if comp.on_submit and comp:on_submit(fields, this) then
|
||||
-- Clear components so they regenerate
|
||||
dialogdata.components = nil
|
||||
return true
|
||||
end
|
||||
if comp.setting and fields["reset_" .. i] then
|
||||
core.settings:remove(comp.setting.name)
|
||||
|
||||
-- Clear components so they regenerate
|
||||
dialogdata.components = nil
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
|
|
@ -51,20 +51,16 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
line = line:gsub("\r", "")
|
||||
|
||||
-- comment
|
||||
local comment = line:match("^#" .. CHAR_CLASSES.SPACE .. "*(.*)$")
|
||||
if comment then
|
||||
if settings.current_comment == "" then
|
||||
settings.current_comment = comment
|
||||
else
|
||||
settings.current_comment = settings.current_comment .. "\n" .. comment
|
||||
end
|
||||
local comment_match = line:match("^#" .. CHAR_CLASSES.SPACE .. "*(.*)$")
|
||||
if comment_match then
|
||||
settings.current_comment[#settings.current_comment + 1] = comment_match
|
||||
return
|
||||
end
|
||||
|
||||
-- clear current_comment so only comments directly above a setting are bound to it
|
||||
-- but keep a local reference to it for variables in the current line
|
||||
local current_comment = settings.current_comment
|
||||
settings.current_comment = ""
|
||||
settings.current_comment = {}
|
||||
|
||||
-- empty lines
|
||||
if line:match("^" .. CHAR_CLASSES.SPACE .. "*$") then
|
||||
|
@ -103,11 +99,32 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
return "Tried to add \"secure.\" setting"
|
||||
end
|
||||
|
||||
local requires = {}
|
||||
local last_line = #current_comment > 0 and current_comment[#current_comment]:trim()
|
||||
if last_line and last_line:lower():sub(1, 9) == "requires:" then
|
||||
local parts = last_line:sub(10):split(",")
|
||||
current_comment[#current_comment] = nil
|
||||
|
||||
for _, part in ipairs(parts) do
|
||||
part = part:trim()
|
||||
|
||||
local value = true
|
||||
if part:sub(1, 1) == "!" then
|
||||
value = false
|
||||
part = part:sub(2):trim()
|
||||
end
|
||||
|
||||
requires[part] = value
|
||||
end
|
||||
end
|
||||
|
||||
if readable_name == "" then
|
||||
readable_name = nil
|
||||
end
|
||||
local remaining_line = line:sub(first_part:len() + 1)
|
||||
|
||||
local comment = table.concat(current_comment, "\n"):trim()
|
||||
|
||||
if setting_type == "int" then
|
||||
local default, min, max = remaining_line:match("^"
|
||||
-- first int is required, the last 2 are optional
|
||||
|
@ -129,7 +146,8 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
default = default,
|
||||
min = min,
|
||||
max = max,
|
||||
comment = current_comment,
|
||||
requires = requires,
|
||||
comment = comment,
|
||||
})
|
||||
return
|
||||
end
|
||||
|
@ -151,7 +169,8 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
readable_name = readable_name,
|
||||
type = setting_type,
|
||||
default = default,
|
||||
comment = current_comment,
|
||||
requires = requires,
|
||||
comment = comment,
|
||||
})
|
||||
return
|
||||
end
|
||||
|
@ -203,7 +222,8 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
flags = values[10]
|
||||
},
|
||||
values = values,
|
||||
comment = current_comment,
|
||||
requires = requires,
|
||||
comment = comment,
|
||||
noise_params = true,
|
||||
flags = flags_to_table("defaults,eased,absvalue")
|
||||
})
|
||||
|
@ -220,7 +240,8 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
readable_name = readable_name,
|
||||
type = "bool",
|
||||
default = remaining_line,
|
||||
comment = current_comment,
|
||||
requires = requires,
|
||||
comment = comment,
|
||||
})
|
||||
return
|
||||
end
|
||||
|
@ -246,7 +267,8 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
default = default,
|
||||
min = min,
|
||||
max = max,
|
||||
comment = current_comment,
|
||||
requires = requires,
|
||||
comment = comment,
|
||||
})
|
||||
return
|
||||
end
|
||||
|
@ -268,7 +290,8 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
type = "enum",
|
||||
default = default,
|
||||
values = values:split(",", true),
|
||||
comment = current_comment,
|
||||
requires = requires,
|
||||
comment = comment,
|
||||
})
|
||||
return
|
||||
end
|
||||
|
@ -285,7 +308,8 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
readable_name = readable_name,
|
||||
type = setting_type,
|
||||
default = default,
|
||||
comment = current_comment,
|
||||
requires = requires,
|
||||
comment = comment,
|
||||
})
|
||||
return
|
||||
end
|
||||
|
@ -314,7 +338,8 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
type = "flags",
|
||||
default = default,
|
||||
possible = flags_to_table(possible),
|
||||
comment = current_comment,
|
||||
requires = requires,
|
||||
comment = comment,
|
||||
})
|
||||
return
|
||||
end
|
||||
|
@ -324,7 +349,7 @@ end
|
|||
|
||||
local function parse_single_file(file, filepath, read_all, result, base_level, allow_secure)
|
||||
-- store this helper variable in the table so it's easier to pass to parse_setting_line()
|
||||
result.current_comment = ""
|
||||
result.current_comment = {}
|
||||
|
||||
local line = file:read("*line")
|
||||
while line do
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue