mtmenu/views/settings.lua
2026-02-10 21:46:25 -05:00

271 lines
No EOL
10 KiB
Lua

dofile(core.get_builtin_path().."common/settings/settingtypes.lua")
-- Some categories, like Accessibility and Theme, do not appear
-- in the builtin settingtypes.txt, so they are added to the state table here.
local function inject_settings(state)
-- Theme
table.insert(state.categories, 1, "Theme")
state.settings.Theme = {
{
comment = "The background color of containers.",
context = "client",
default = "#fff",
name = "theme.container_bg_color",
readable_name = "Container background color",
requires = {},
type = "string",
value = imfs.state("#fff")
}
}
-- Accessibility
table.insert(state.categories, 2, "Accessibility")
state.settings.Accessibility = {
{
comment = "Smooths rotation of camera, also called look or mouse smoothing. 0 to disable.",
context = "client",
default = "0.0",
max = 0.99,
min = 0,
name = "camera_smoothing",
readable_name = "Camera smoothing",
requires = {},
type = "float",
value = imfs.state("0.0")
}
}
end
local function search_settings(state, search)
if state.search == "" then
return state.settings, state.categories
end
local out = {}
for category, settings in pairs(state.settings) do
for i = 1, #settings do
if settings[i].name:find(search, 1, true) then
if not out[category] then
out[category] = {settings[i]}
else
table.insert(out[category], settings[i])
end
end
end
end
local categories = {}
for i = 1, #state.categories do
local category = state.categories[i]
if category.name then
for j = 1, #state.categories do
if out[category[j]] then
if not categories[category.name] then
table.insert(categories, {name = category.name})
end
table.insert(categories[#categories], category[j])
break
end
end
else
if out[category] then
table.insert(categories, category)
break
end
end
end
return out, categories
end
return function(state)
imfs.begin(size.x, size.y)
:padding(0, 0)
:bgcolor(theme.styles.bg_color, true)
if not state.settings then
state.settings = {}
state.categories = {}
local category
local settings = settingtypes.parse_config_file(false, false)
for _, x in ipairs(settings) do
if x.type == "category" then
if x.level == 0 then
state.categories[#state.categories + 1] = {name = x.name}
elseif x.level == 1 then
local group = state.categories[#state.categories]
group[#group + 1] = x.name
state.settings[x.name] = {}
category = x.name
end
else
local s = state.settings[category]
x.value = imfs.state()
if x.type == "string" or x.type == "float" or x.type == "int" or x.type == "enum" then
x.value._val = minetest.settings:get(x.name) or x.default
elseif x.type == "bool" then
x.value._val = minetest.settings:get_bool(x.name, x.default)
end
s[#s +1] = x
end
end
inject_settings(state)
state.settings_shown._val = state.settings
state.categories_shown._val = state.categories
end
imfs.box(0, 0, "100%", 1, theme.styles.container.bg_color)
imfs.row(0.2, 0.125, "100% - 0.4", 0.75)
:gap(0.1)
theme.field(0, 0, "1x", "100%", state.search)
:onchange(function(value)
state.search = value
end)
:onenter(function()
local settings, categories = search_settings(state, state.search)
if categories[1] then
local first = categories[1].name and categories[1][1] or categories[1]
state.category(first)
end
state.categories_shown(categories)
state.settings_shown(settings)
end)
imfs.button(0, 0, 0.75, 0.75)
:image(theme.icon("search"))
:style({
bgimg = theme.get_background_image("button"),
bgimg_middle = theme.styles.button.border_width,
})
:tooltip("Search settings")
:onclick(function()
local settings, categories = search_settings(state, state.search)
if categories[1] then
local first = categories[1].name and categories[1][1] or categories[1]
state.category(first)
end
state.categories_shown(categories)
state.settings_shown(settings)
end)
imfs.button(0, 0, 0.75, 0.75)
:image(theme.icon("cancel"))
:style({
bgimg = theme.get_background_image("button"),
bgimg_middle = theme.styles.button.border_width,
})
:tooltip("Clear search")
:onclick(function()
state.search = ""
state.settings_shown(state.settings)
state.categories_shown(state.categories)
end)
imfs.button(0, 0, 2, "100%", "Back")
:onclick(function()
show_meta_menu()
end)
imfs.row_end()
imfs.box(0, 1, "20%", "100% - 1", theme.styles.container.bg_color)
imfs.box(0, 0.95, "100%", 0.1, theme.styles.container.border_color)
imfs.scroll_container(0.2, 1.05, "20% - 0.45", "100% - 1.05")
local categories = state.categories_shown()
if categories then
local y = 0.1
for i = 1, #categories do
local group = categories[i]
if not group then break end
-- Top-level categories.
if type(group) == "string" then
imfs.button(0, y, "100%", 0.5, group)
:onclick(function()
if state.category() ~= group then
state.category(group)
end
end)
y = y + 0.55
-- Grouped categories.
else
imfs.arealabel(0, y + 0.125, "100%", 0.375, group.name)
y = y + 0.425
local h = 0
for j = 1, #group do
local category = group[j]
imfs.box(0.12, y + 0.245, 0.25, 0.01, theme.styles.text_color)
imfs.button(0.25, y, "100% - 0.25", 0.5, category)
:onclick(function()
if state.category() ~= category then
state.category(category)
end
end)
h = h + 0.55
y = y + 0.55
end
imfs.box(0.12, y - h, 0.01, h - 0.3, theme.styles.text_color)
end
end
end
imfs.scroll_container_end()
imfs.box("20% - 0.05", 1, 0.1, "100% - 1", theme.styles.container.border_color)
imfs.scroll_container("20% + 0.25", 1.05, "80% - 0.45", "100% - 1.05")
imfs.column(0, 0, "100%", 1000)
:gap(0.1)
local settings = state.settings_shown()[state.category()]
if settings then
for i = 1, #settings do
local setting = settings[i]
if not setting then break end
if setting.type == "bool" then
local active = minetest.settings:get_bool(setting.name, setting.default)
theme.checkbox(0, 0, setting.readable_name, setting.value, setting.comment)
elseif setting.type == "float" or setting.type == "int" then
imfs.arealabel(0, 0, "100%", 0.325, setting.readable_name)
imfs.row(0, 0, "100%", 0.75)
:gap(0.1)
theme.number_field(0, 0, "1x", 0.75, setting.value)
:tooltip(setting.comment)
imfs.button(0, 0, 2, 0.75, "Set")
imfs.row_end()
elseif setting.type == "string" then
imfs.arealabel(0, 0, "100%", 0.325, setting.readable_name)
imfs.row(0, 0, "100%", 0.75)
:gap(0.1)
theme.field(0, 0, "1x", 0.75, setting.value)
:tooltip(setting.comment)
if setting.value._val ~= setting.default then
imfs.button(0, 0, 0.75, 0.75)
:image(theme.icon("refresh"))
:style({
bgimg = theme.get_background_image("button"),
bgimg_middle = theme.styles.button.border_width,
})
:tooltip("Reset to default")
end
imfs.button(0, 0, 2, 0.75, "Set")
imfs.row_end()
elseif setting.type == "enum" then
imfs.scope(setting.name)
imfs.arealabel(0, 0, "100%", 0.325, setting.readable_name)
imfs.row(0, 0, "100%", "fit")
:gap(0.1)
theme.dropdown(0, 0, "1x", 0.75, setting.values, setting.value)
:tooltip(setting.comment)
imfs.button(0, 0, 2, 0.75, "Set")
imfs.row_end()
imfs.scope_end()
else
print(dump(setting))
end
end
end
imfs.column_end()
imfs.scroll_container_end()
return imfs.end_()
end