/ gui.lua
gui.lua
1 local gui = flow.widgets 2 local _ps = player_settings 3 local S = minetest.get_translator("player_settings") 4 5 _ps.gui = flow.make_gui(function(player,ctx) 6 ctx.name = player:get_player_name() 7 if not ctx.showinfo then ctx.showinfo = {} end 8 if not ctx.navbarData then 9 local settings_by_category = {} 10 for k,v in pairs(_ps.registered_settings) do 11 if v.allow_show(ctx.name) then 12 if not settings_by_category[v.category] then 13 settings_by_category[v.category] = {} 14 end 15 settings_by_category[v.category][k] = v 16 end 17 end 18 local categories_by_metacat = {} 19 for k,v in pairs(settings_by_category) do 20 if not (_ps.registered_categories[k] and _ps.registered_categories[k].allow_show(ctx.name)) then 21 settings_by_category[k] = nil 22 end 23 if not categories_by_metacat[_ps.registered_categories[k].metacategory] then 24 categories_by_metacat[_ps.registered_categories[k].metacategory] = {} 25 end 26 categories_by_metacat[_ps.registered_categories[k].metacategory][k] = v 27 end 28 for k,v in pairs(categories_by_metacat) do 29 if not (_ps.registered_metacategories[k] and _ps.registered_metacategories[k].allow_show(ctx.name)) then 30 categories_by_metacat[k] = nil 31 end 32 end 33 ctx.navbarData = categories_by_metacat 34 end 35 local navbar = {} 36 for k,v in pairs(ctx.navbarData) do 37 table.insert(navbar,gui.Label{ label = _ps.registered_metacategories[k].title }) 38 for k2,v2 in pairs(v) do 39 table.insert(navbar,gui.Button { 40 label = _ps.registered_categories[k2].title, 41 w = 1, expand = true, 42 ---@diagnostic disable-next-line: redefined-local, unused-local 43 on_event = function(player,ctx) 44 if ctx.current_category == k2 then return end 45 ctx.current_metacat = k 46 ctx.current_category = k2 47 return true 48 end, 49 }) 50 end 51 end 52 navbar.w = 4; navbar.h = 10; 53 navbar.name = "shbox" 54 55 local settings_screen 56 if not ctx.current_category then 57 settings_screen = gui.Label { 58 w = 10, h = 10, 59 label = S("Select a category on the left."), 60 expand = true, align_h = "centre", align_w = "centre", 61 } 62 else 63 local list_settings = ctx.navbarData[ctx.current_metacat][ctx.current_category] 64 local svbox = {} 65 for k,v in pairs(list_settings) do 66 local desc = S("@1 (@2)",v.description,_ps.util.types[v.type] or v.type) 67 if v.type == "enum" then 68 desc = S("@1 (Multiple-choice of @2)", 69 v.description, 70 _ps.util.types[v.enum_type] or v.enum_type) 71 end 72 73 local display_type = v.display_type 74 if display_type == "enum" and v.type ~= "enum" or 75 display_type == "bool" and v.type ~= "bool" then 76 display_type = nil 77 end 78 79 -- TODO: Add support to scrollbar for numbers (waiting for flow mod support) 80 if not display_type then 81 if v.type == "bool" then 82 display_type = "bool" 83 elseif v.type == "enum" then 84 display_type = "enum" 85 else 86 display_type = "string" 87 end 88 end 89 90 91 local s_status, selected = _ps.get_setting(ctx.name,k) 92 if not s_status then 93 ctx.errmsg = {k, S("Failed to get setting of @1: @2", 94 k, _ps.util.errmsgs[selected] or selected 95 )} 96 elseif display_type == "bool" then 97 table.insert(svbox, gui.HBox { 98 gui.Checkbox { 99 w = 5,h=1, 100 name = "settings_" .. k, 101 label = desc, 102 selected = selected, 103 on_event = function(player,ctx) 104 ctx.errmsg = nil 105 local form = ctx.form 106 if type(form["settings_" .. k]) == "boolean" then 107 local status, errmsg =_ps.set_setting(ctx.name,k,form["settings_" .. k]) 108 if not status then 109 ctx.errmsg = {k,errmsg} 110 form["settings_" .. k] = _ps.get_setting(ctx.name,k) 111 end 112 return true 113 end 114 end, 115 expand = true, align_h = "left", 116 }, 117 gui.ImageButton { 118 w = 1, h = 1, 119 texture_name = "settings_reset.png", 120 name = "settingsReset_" .. k, 121 ---@diagnostic disable-next-line: redefined-local, unused-local 122 on_event = function(player,ctx) 123 ctx.errmsg = nil 124 local form = ctx.form 125 _ps.set_default(ctx.name,k) 126 form["settings_" .. k] = v.default 127 return true 128 end, 129 drawborder = false, 130 }, 131 gui.ImageButton { 132 w = 1, h = 1, 133 texture_name = "settings_info.png", 134 name = "settingsInfo_" .. k, 135 ---@diagnostic disable-next-line: redefined-local, unused-local 136 on_event = function(player,ctx) 137 ctx.showinfo[k] = not ctx.showinfo[k] 138 return true 139 end, 140 drawborder = false, 141 } 142 }) 143 elseif display_type == "enum" then 144 table.insert(svbox, gui.Label { 145 label = desc 146 }) 147 table.insert(svbox, gui.HBox { 148 gui.Dropdown { 149 w = 3,h=1, 150 name = "settings_" .. k, 151 items = v.enum_choices, 152 selected_idx = _ps.util.idx_in_table(v.enum_choices,selected), 153 }, 154 gui.Button { 155 w = 2, h = 1, 156 name = "settingsSubmit_" .. k, 157 label = S("Set"), 158 ---@diagnostic disable-next-line: redefined-local, unused-local 159 on_event = function(player,ctx) 160 ctx.errmsg = nil 161 local form = ctx.form 162 print(form["settings_" .. k]) 163 local status, errmsg =_ps.set_setting(ctx.name,k,form["settings_" .. k]) 164 if not status then 165 ctx.errmsg = {k,errmsg} 166 form["settings_" .. k] = _ps.get_setting(ctx.name,k) 167 end 168 return true 169 end, 170 expand = true, align_h = "left", 171 }, 172 gui.ImageButton { 173 w = 1, h = 1, 174 texture_name = "settings_reset.png", 175 name = "settingsReset_" .. k, 176 ---@diagnostic disable-next-line: redefined-local, unused-local 177 on_event = function(player,ctx) 178 ctx.errmsg = nil 179 local form = ctx.form 180 _ps.set_default(ctx.name,k) 181 form["settings_" .. k] = v.default 182 return true 183 end, 184 drawborder = false, 185 }, 186 gui.ImageButton { 187 w = 1, h = 1, 188 texture_name = "settings_info.png", 189 name = "settingsInfo_" .. k, 190 ---@diagnostic disable-next-line: redefined-local, unused-local 191 on_event = function(player,ctx) 192 ctx.showinfo[k] = not ctx.showinfo[k] 193 return true 194 end, 195 drawborder = false, 196 } 197 }) 198 elseif display_type == "string" then -- String-like 199 table.insert(svbox, gui.Label { 200 label = desc 201 }) 202 table.insert(svbox, gui.HBox { 203 gui.Field { 204 w = 3,h=1, 205 name = "settings_" .. k, 206 default = selected, 207 }, 208 gui.Button { 209 w = 2,h=1, 210 name = "settingsSubmit_" .. k, 211 label = S("Set"), 212 ---@diagnostic disable-next-line: redefined-local, unused-local 213 on_event = function(player,ctx) 214 ctx.errmsg = nil 215 local form = ctx.form 216 local status, errmsg =_ps.set_setting(ctx.name,k,form["settings_" .. k]) 217 if not status then 218 ctx.errmsg = {k,errmsg} 219 form["settings_" .. k] = _ps.get_setting(ctx.name,k) 220 end 221 return true 222 end, 223 expand = true, align_h = "left", 224 }, 225 gui.ImageButton { 226 w = 1, h = 1, 227 texture_name = "settings_reset.png", 228 name = "settingsReset_" .. k, 229 ---@diagnostic disable-next-line: redefined-local, unused-local 230 on_event = function(player,ctx) 231 ctx.errmsg = nil 232 local form = ctx.form 233 _ps.set_default(ctx.name,k) 234 form["settings_" .. k] = v.default 235 return true 236 end, 237 drawborder = false, 238 }, 239 gui.ImageButton { 240 w = 1, h = 1, 241 texture_name = "settings_info.png", 242 name = "settingsInfo_" .. k, 243 ---@diagnostic disable-next-line: redefined-local, unused-local 244 on_event = function(player,ctx) 245 ctx.showinfo[k] = not ctx.showinfo[k] 246 return true 247 end, 248 drawborder = false, 249 } 250 }) 251 else 252 error("[player_settings] Attempt to display setting with unknown display type " .. display_type) 253 end 254 if ctx.errmsg and ctx.errmsg[1] == k then 255 local user_errmsg = _ps.util.errmsgs[ctx.errmsg[2]] or ctx.errmsg[2] 256 table.insert(svbox, gui.Label { 257 label = minetest.colorize("#FF0000", S("Error: @1", user_errmsg)), 258 -- label = ctx.errmsg[2], 259 }) 260 end 261 if ctx.showinfo[k] and v.long_description then 262 table.insert(svbox, gui.Label { 263 label = minetest.get_color_escape_sequence("#00FF00") .. v.long_description, 264 }) 265 end 266 end 267 svbox.w = 10; svbox.h = 10; 268 svbox.name = "svbox" 269 settings_screen = gui.ScrollableVBox(svbox) 270 end 271 local content_body = gui.HBox { 272 gui.ScrollableVBox(navbar), 273 settings_screen 274 } 275 local content_with_header = gui.VBox { 276 gui.HBox { 277 gui.Label { label = S("Settings"), expand = true, align_h = "left" }, 278 gui.ButtonExit { w = 0.7, h = 0.7, label = "x" } 279 }, 280 gui.Box{w = 1, h = 0.05, color = "grey", padding = 0}, 281 content_body 282 } 283 return ctx.inside_sway and content_body or content_with_header 284 end) 285 286 minetest.register_chatcommand("settings", { 287 description = S("Open settings menu"), 288 func = function(name,param) 289 _ps.gui:show(minetest.get_player_by_name(name)) 290 end 291 }) 292 293 if minetest.get_modpath("sway") then 294 sway.register_page("player_settings:settings", { 295 title = S("Settings"), 296 get = function (_self, player, ctx) 297 if not ctx.player_settings then 298 ctx.player_settings = { inside_sway = true } 299 end 300 return sway.Form { 301 _ps.gui:embed { 302 player = player, 303 name = "player_settings" 304 } 305 } 306 end 307 }) 308 end