From d4f6bf31c29d29b4ffc9f3bd84ad8edb21c4b731 Mon Sep 17 00:00:00 2001 From: luk3yx Date: Sat, 25 Jun 2022 21:05:54 +1200 Subject: [PATCH] Fix some main menu bugs and improve UI (#63) Co-authored-by: Maksim --- builtin/fstk/buttonbar.lua | 14 +++--- builtin/fstk/dialog.lua | 1 + builtin/fstk/tabview.lua | 40 ++++++++++++------ builtin/mainmenu/common.lua | 4 ++ builtin/mainmenu/dlg_contentstore.lua | 5 +++ builtin/mainmenu/dlg_create_world.lua | 10 ++++- builtin/mainmenu/dlg_delete_content.lua | 10 +++++ builtin/mainmenu/init.lua | 1 + builtin/mainmenu/tab_content.lua | 7 +-- builtin/mainmenu/tab_credits.lua | 16 ++++--- builtin/mainmenu/tab_local.lua | 27 ++++++++---- builtin/mainmenu/tab_local_default.lua | 2 +- builtin/mainmenu/tab_online.lua | 2 +- textures/base/pack/authors_menu.png | Bin 349 -> 279 bytes textures/base/pack/authors_menu_hover.png | Bin 0 -> 277 bytes textures/base/pack/authors_menu_pressed.png | Bin 354 -> 0 bytes textures/base/pack/authors_menu_selected.png | Bin 0 -> 280 bytes textures/base/pack/logo.png | Bin 0 -> 2410 bytes textures/base/pack/select_btn.png | Bin 647 -> 525 bytes textures/base/pack/settings_menu.png | Bin 328 -> 279 bytes textures/base/pack/settings_menu_hover.png | Bin 0 -> 279 bytes textures/base/pack/settings_menu_pressed.png | Bin 337 -> 0 bytes textures/base/pack/settings_menu_selected.png | Bin 0 -> 279 bytes textures/base/pack/side_menu.png | Bin 0 -> 193 bytes textures/base/pack/side_menu_divider.png | Bin 0 -> 570 bytes textures/base/pack/side_menu_left.png | Bin 0 -> 5681 bytes .../base/pack/switch_local_default_hover.png | Bin 2661 -> 2657 bytes textures/base/pack/switch_local_hover.png | Bin 1118 -> 1121 bytes 28 files changed, 97 insertions(+), 42 deletions(-) create mode 100644 textures/base/pack/authors_menu_hover.png delete mode 100644 textures/base/pack/authors_menu_pressed.png create mode 100644 textures/base/pack/authors_menu_selected.png create mode 100644 textures/base/pack/logo.png create mode 100644 textures/base/pack/settings_menu_hover.png delete mode 100644 textures/base/pack/settings_menu_pressed.png create mode 100644 textures/base/pack/settings_menu_selected.png create mode 100644 textures/base/pack/side_menu.png create mode 100644 textures/base/pack/side_menu_divider.png create mode 100644 textures/base/pack/side_menu_left.png diff --git a/builtin/fstk/buttonbar.lua b/builtin/fstk/buttonbar.lua index ef8f577a4..25b9a668c 100644 --- a/builtin/fstk/buttonbar.lua +++ b/builtin/fstk/buttonbar.lua @@ -24,8 +24,8 @@ local function buttonbar_formspec(self) return "" end - local formspec = string.format("box[%f,%f;%f,%f;%s]", - self.pos.x,self.pos.y ,self.size.x,self.size.y,self.bgcolor) + local formspec = string.format("background9[%f,%f;%f,%f;%sside_menu_left.png;false;30]", + self.pos.x, self.pos.y - 0.1, self.size.x + 0.025, self.size.y + 0.35, defaulttexturedir) for i=self.startbutton,#self.buttons,1 do local btn_name = self.buttons[i].name @@ -36,7 +36,7 @@ local function buttonbar_formspec(self) (i - self.startbutton) * self.btn_size + --button offset self.btn_initial_offset else - btn_pos.x = self.pos.x + (self.btn_size * 0.1) + btn_pos.x = self.pos.x + (self.btn_size * 0.05) end if self.orientation == "vertical" then @@ -99,10 +99,10 @@ local function buttonbar_formspec(self) else btn_size.x = self.btn_size btn_size.y = self.btn_size * 0.5 - btn_dec_pos.x = self.pos.x + (self.btn_size * 0.1) + btn_dec_pos.x = self.pos.x + (self.btn_size * 0.05) btn_dec_pos.y = self.pos.y + (self.btn_size * 0.05) - btn_inc_pos.x = self.pos.x + (self.btn_size * 0.1) - btn_inc_pos.y = self.size.y - (self.btn_size * 0.75) + btn_inc_pos.x = self.pos.x + (self.btn_size * 0.05) + btn_inc_pos.y = self.pos.y + self.size.y - (self.btn_size * 0.45) end if self.orientation == "horizontal" then @@ -141,7 +141,7 @@ end local function buttonbar_buttonhandler(self, fields) if fields["btnbar_inc_" .. self.name] ~= nil and - self.startbutton < #self.buttons - 5 then + self.startbutton < #self.buttons - 4 then self.startbutton = self.startbutton + 1 return true diff --git a/builtin/fstk/dialog.lua b/builtin/fstk/dialog.lua index f70cc2b6a..feee1d46f 100644 --- a/builtin/fstk/dialog.lua +++ b/builtin/fstk/dialog.lua @@ -85,6 +85,7 @@ function messagebox(name, message) return dialog_create(name, function() return ([[ + set_focus[ok;true] textarea[1,1;10,4;;;%s] button[5,4.5;2,0.8;ok;%s] ]]):format(message, fgettext("OK")) diff --git a/builtin/fstk/tabview.lua b/builtin/fstk/tabview.lua index b0d634c63..d4fcd708b 100644 --- a/builtin/fstk/tabview.lua +++ b/builtin/fstk/tabview.lua @@ -26,6 +26,8 @@ -- element.getFormspec() returns formspec of tabview -- -------------------------------------------------------------------------------- +local defaulttexturedir = core.formspec_escape(defaulttexturedir) + -------------------------------------------------------------------------------- local function add_tab(self,tab) assert(tab.size == nil or (type(tab.size) == table and @@ -49,6 +51,7 @@ local function add_tab(self,tab) -- Hidden tabs have a negative index local i if tab.hidden then + newtab.tabdata.hidden = true i = -1 while self.tablist[i] do i = i - 1 @@ -67,6 +70,21 @@ local function add_tab(self,tab) end -------------------------------------------------------------------------------- +local function make_side_pane_tab(y, tab_name, tooltip, selected) + local formspec = "style[" .. tab_name .. "_tab;bgimg=" .. + defaulttexturedir .. tab_name + if selected then + formspec = formspec .. "_menu_selected.png]" + else + formspec = formspec .. "_menu.png;bgimg_hovered=" .. + defaulttexturedir .. tab_name .. "_menu_hover.png]" + end + + return formspec .. + "image_button[12.1," .. y .. ";1,1.5;;" .. tab_name .. "_tab;;true;false]" .. + "tooltip[" .. tab_name .. "_tab;" .. tooltip .. "]" +end + local function get_formspec(self) local formspec = "" @@ -76,7 +94,6 @@ local function get_formspec(self) if self.parent == nil then local tsize = self.tablist[self.last_tab_index].tabsize or {width=self.width, height=self.height} - local defaulttexturedir = core.formspec_escape(defaulttexturedir) formspec = formspec .. string.format("size[%f,%f,%s]",tsize.width + 2,tsize.height + 1, dump(self.fixed_size)) .. @@ -85,19 +102,15 @@ local function get_formspec(self) "background9[-0.2,-1.26;" .. tsize.width + 0.4 .. "," .. tsize.height + 1.75 .. ";" .. defaulttexturedir .. "bg_common.png;false;40]" .. - "style[settings_tab;content_offset=0]" .. - "image_button[12.02,1.3;1,1.55;" .. - defaulttexturedir .. "settings_menu.png;settings_tab;;true;false;" .. - defaulttexturedir .. "settings_menu_pressed.png]" .. - "style[authors_tab;content_offset=0]" .. - "image_button[12.02,2.7;1,1.55;" .. - defaulttexturedir .. "authors_menu.png;authors_tab;;true;false;" .. - defaulttexturedir .. "authors_menu_pressed.png]" + + "background9[12.13,1.05;0.9,2.6;" .. defaulttexturedir .. "side_menu.png;false;30]" .. + make_side_pane_tab(0.9, "settings", fgettext("Settings"), name == "settings") .. + "image[12.15,2.26;0.9,0.06;" .. defaulttexturedir .. "side_menu_divider.png]" .. + make_side_pane_tab(2.3, "authors", fgettext("Credits"), name == "credits") end -- formspec = formspec .. self:tab_header() - formspec = formspec .. self:button_header() - formspec = formspec .. + formspec = formspec .. self:button_header() .. self.tablist[self.last_tab_index].get_formspec( self, name, @@ -269,17 +282,18 @@ end -------------------------------------------------------------------------------- local function handle_tab_buttons(self,fields) --save tab selection to config file - if fields[self.name] then + --[[if fields[self.name] then local index = tonumber(fields[self.name]) switch_to_tab(self, index) return true - end + end]] local name_prefix = self.name .. "_" local name_prefix_len = #name_prefix for field in pairs(fields) do if field:sub(1, name_prefix_len) == name_prefix then local index = tonumber(field:sub(name_prefix_len + 1)) + if self.last_tab_index == index then return false end switch_to_tab(self, index) return true end diff --git a/builtin/mainmenu/common.lua b/builtin/mainmenu/common.lua index 99357e59c..cadf169f3 100644 --- a/builtin/mainmenu/common.lua +++ b/builtin/mainmenu/common.lua @@ -59,6 +59,10 @@ end -------------------------------------------------------------------------------- function render_serverlist_row(spec, is_favorite) + if not spec then + spec = {} + end + -- Get information from non_mobile_servers. if is_favorite and not spec.proto_min and spec.address and spec.port and serverlistmgr.non_mobile_servers then diff --git a/builtin/mainmenu/dlg_contentstore.lua b/builtin/mainmenu/dlg_contentstore.lua index f7f728d43..dfaa96add 100644 --- a/builtin/mainmenu/dlg_contentstore.lua +++ b/builtin/mainmenu/dlg_contentstore.lua @@ -1004,6 +1004,11 @@ function create_store_dlg(type) search_string = "" cur_page = 1 + -- ToDo: delete me when MultiCraft ContentDB is ready + if type and type ~= "game" then + type = "game" + end + if type then -- table.indexof does not work on tables that contain `nil` for i, v in pairs(filter_types_type) do diff --git a/builtin/mainmenu/dlg_create_world.lua b/builtin/mainmenu/dlg_create_world.lua index f7c0945b9..11c30b8c4 100644 --- a/builtin/mainmenu/dlg_create_world.lua +++ b/builtin/mainmenu/dlg_create_world.lua @@ -388,6 +388,12 @@ local function create_world_buttonhandler(this, fields) gameindex = gameindex + 1 end + if not pkgmgr.games[gameindex] then + gamedata.errormessage = fgettext("No game selected") + this:delete() + return true + end + -- For unnamed worlds use the generated name 'World ', -- where the number increments: it is set to 1 larger than the largest -- generated name number found. @@ -457,7 +463,9 @@ local function create_world_buttonhandler(this, fields) if gameindex >= pkgmgr.default_game_idx then gameindex = gameindex + 1 end - core.settings:set("menu_last_game", pkgmgr.games[gameindex].id) + local game = pkgmgr.games[gameindex] + if not game then return end + core.settings:set("menu_last_game", game.id) return true end diff --git a/builtin/mainmenu/dlg_delete_content.lua b/builtin/mainmenu/dlg_delete_content.lua index f583b25ce..402441d36 100644 --- a/builtin/mainmenu/dlg_delete_content.lua +++ b/builtin/mainmenu/dlg_delete_content.lua @@ -70,6 +70,16 @@ end function create_delete_content_dlg(content) assert(content.name) + if content.type == "game" then + for _, world in ipairs(menudata.worldlist:get_raw_list()) do + if world.gameid == content.id then + return messagebox("dlg_delete_content", + fgettext("You cannot delete this game!") .. "\n" .. + fgettext("You have worlds that use it.")) + end + end + end + local retval = dialog_create("dlg_delete_content", delete_content_formspec, delete_content_buttonhandler, diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua index 6be81c243..fea2b506e 100644 --- a/builtin/mainmenu/init.lua +++ b/builtin/mainmenu/init.lua @@ -109,6 +109,7 @@ function menudata.init_tabs() for i = 1, #pkgmgr.games do if pkgmgr.games[i].id == "default" then tv_main:add(tabs.local_default_game) + tabs.local_game.hidden = true break end end diff --git a/builtin/mainmenu/tab_content.lua b/builtin/mainmenu/tab_content.lua index e96358321..745a6fdb2 100644 --- a/builtin/mainmenu/tab_content.lua +++ b/builtin/mainmenu/tab_content.lua @@ -66,7 +66,9 @@ local function get_formspec(tabview, name, tabdata) "table[0,0.25;5.1,4.3;pkglist;" .. pkgmgr.render_packagelist(packages) .. ";" .. tabdata.selected_pkg .. "]" .. - "button[0,4.85;5.25,0.5;btn_contentdb;".. fgettext("Browse online content") .. "]" + "style[btn_contentdb;padding=-5;bgimg=" .. defaulttexturedir .. + "select_btn.png;bgimg_middle=10]" .. + "image_button[-0.11,4.8;5.5,0.92;;btn_contentdb;" .. fgettext("Browse online content") .. ";true;false]" local selected_pkg @@ -144,8 +146,7 @@ local function get_formspec(tabview, name, tabdata) retval = retval .. "textarea[5.85,2.2;6.35,2.9;;" .. fgettext("Information:") .. ";" .. desc .. "]" - if core.may_modify_path(selected_pkg.path) and not - (selected_pkg.type == "game" and selected_pkg.name == "default") then + if core.may_modify_path(selected_pkg.path) then retval = retval .. "button[5.5,4.65;3.25,1;btn_mod_mgr_delete_mod;" .. fgettext("Uninstall Package") .. "]" diff --git a/builtin/mainmenu/tab_credits.lua b/builtin/mainmenu/tab_credits.lua index 54db52ce6..41fd821f8 100644 --- a/builtin/mainmenu/tab_credits.lua +++ b/builtin/mainmenu/tab_credits.lua @@ -118,17 +118,19 @@ return { caption = "", -- fgettext("Credits"), cbf_formspec = function(tabview, name, tabdata) local version = core.get_version() - local fs = "label[0.05,-0.2;" .. + local logofile = defaulttexturedir .. "logo.png" + local fs = "image[-0.1,-0.3;2,2;" .. logofile .. "]" .. + "label[1.4,-0.25;" .. "MultiCraft Open Source, ver. " .. version.string .. "\n" .. "Copyright (C) 2014-2022 MultiCraft Development Team\n" .. "License: GNU LGPLv3.0+ and CC BY-SA 4.0\n" .. "Created and Powered by Minetest Engine, ver. 5.4.1]" .. - "style[homepage;padding=-10;bgimg=" .. defaulttexturedir .. - "select_btn.png;bgimg_middle=20]" .. + "style[homepage;padding=-5;bgimg=" .. defaulttexturedir .. + "select_btn.png;bgimg_middle=10]" .. "image_button[9.5,-0.25;2.5,0.9;;homepage;Home Page;true;false]" .. - "style[privacy;padding=-10;bgimg=" .. defaulttexturedir .. - "select_btn.png;bgimg_middle=20]" .. + "style[privacy;padding=-5;bgimg=" .. defaulttexturedir .. + "select_btn.png;bgimg_middle=10]" .. "image_button[9.5,0.6;2.5,0.9;;privacy;Privacy Policy;true;false]" .. "background9[0.1,1.5;11.85,4.15;" .. defaulttexturedir .. @@ -136,9 +138,9 @@ return { "tablecolumns[color;text]" .. "tableoptions[background=#0000;highlight=#00000000;border=false]" .. "table[0.1,1.5;11.65,4;list_credits;" .. - "#FFFF00," .. fgettext("MultiCraft Developers") .. ",," .. + "#FFFF00," .. fgettext("Core Developers") .. " (MultiCraft)" .. ",," .. buildCreditList(multicraft_developers) .. ",,," .. - "#FFFF00," .. fgettext("Minetest Developers") .. ",," .. + "#FFFF00," .. fgettext("Core Developers") .. " (Minetest Engine)" .. ",," .. buildCreditList(core_developers) .. ",,," .. "#FFFF00," .. fgettext("Active Contributors") .. ",," .. buildCreditList(active_contributors) .. ",,," .. diff --git a/builtin/mainmenu/tab_local.lua b/builtin/mainmenu/tab_local.lua index c6e1002c6..9d60e7c41 100644 --- a/builtin/mainmenu/tab_local.lua +++ b/builtin/mainmenu/tab_local.lua @@ -71,7 +71,7 @@ local function singleplayer_refresh_gamebar() local btnbar = buttonbar_create("game_button_bar", game_buttonbar_button_handler, - {x=-0.35, y=-0.32}, "vertical", {x=1, y=7.14}) + {x=-0.15, y=0.18}, "vertical", {x=1, y=6.14}) for i=1, #pkgmgr.games do if pkgmgr.games[i].id ~= "default" then @@ -103,7 +103,7 @@ local function singleplayer_refresh_gamebar() btnbar:add_button("game_open_cdb", "", "", fgettext("Install games from ContentDB"), true) end -local function get_formspec() +local function get_formspec(_, _, tab_data) local index = filterlist.get_current_index(menudata.worldlist, tonumber(core.settings:get("mainmenu_last_selected_world"))) @@ -141,16 +141,19 @@ local function get_formspec() "background9[0,0;6.5,4.8;" .. defaulttexturedir .. "worldlist_bg.png" .. ";false;40]" .. "tableoptions[background=#0000;border=false]" .. - "table[0,0;6.28,4.64;sp_worlds;" .. menu_render_worldlist() .. ";" .. index .. "]" .. + "table[0,0;6.28,4.64;sp_worlds;" .. menu_render_worldlist() .. ";" .. index .. "]" + if tab_data.hidden then + retval = retval .. "style[switch_local_default;fgimg=" .. defaulttexturedir .. "switch_local_default.png;fgimg_hovered=" .. defaulttexturedir .. "switch_local_default_hover.png]" .. "image_button[10.6,-0.1;1.5,1.5;;switch_local_default;;true;false]" + end if PLATFORM ~= "Android" and PLATFORM ~= "iOS" then retval = retval .. - "style[world_configure;padding=-10;bgimg=" .. defaulttexturedir .. - "select_btn.png;bgimg_middle=20]" .. + "style[world_configure;padding=-5;bgimg=" .. defaulttexturedir .. + "select_btn.png;bgimg_middle=10]" .. "image_button[9.3,4.84;2.7,0.92;;world_configure;" .. fgettext("Select Mods") .. ";true;false]" end @@ -239,7 +242,7 @@ local function main_button_handler(this, fields, name) local world = menudata.worldlist:get_raw_element(gamedata.selected_world) if world then local game = pkgmgr.find_by_gameid(world.gameid) - core.settings:set("menu_last_game", game.id) + core.settings:set("menu_last_game", (game and game.id or "")) end if core.settings:get_bool("enable_server") then @@ -321,7 +324,14 @@ local function main_button_handler(this, fields, name) end if fields["game_open_cdb"] then - this:set_tab("content") + if #pkgmgr.games > 1 or (pkgmgr.games[1] and pkgmgr.games[1].id ~= "default") then + this:set_tab("content") + else + local dlg = create_store_dlg() + dlg:set_parent(this) + this:hide() + dlg:show() + end return true end @@ -347,7 +357,7 @@ local function on_change(type, old_tab, new_tab) local game = current_game() - if game then + if game and game.id ~= "default" then menudata.worldlist:set_filtercriteria(game.id) mm_texture.update("singleplayer",game) end @@ -371,7 +381,6 @@ end return { name = "local", caption = fgettext("Singleplayer"), - hidden = true, cbf_formspec = get_formspec, cbf_button_handler = main_button_handler, on_change = on_change diff --git a/builtin/mainmenu/tab_local_default.lua b/builtin/mainmenu/tab_local_default.lua index 4fdd11be9..95266cedd 100644 --- a/builtin/mainmenu/tab_local_default.lua +++ b/builtin/mainmenu/tab_local_default.lua @@ -118,7 +118,7 @@ local function get_formspec(this) defaulttexturedir .. "gift_btn_pressed.png]" end - if PLATFORM ~= "Android" and PLATFORM ~= "iOS" then + if PLATFORM ~= "iOS" then retval = retval .. "style[switch_local;fgimg=" .. defaulttexturedir .. "switch_local.png;fgimg_hovered=" .. defaulttexturedir .. "switch_local_hover.png]" .. diff --git a/builtin/mainmenu/tab_online.lua b/builtin/mainmenu/tab_online.lua index 9ff746396..2d7837dde 100644 --- a/builtin/mainmenu/tab_online.lua +++ b/builtin/mainmenu/tab_online.lua @@ -371,7 +371,7 @@ local function main_button_handler(tabview, fields, name, tabdata) gamedata.playername = fields.te_name gamedata.password = fields.te_pwd gamedata.address = fields.te_address - gamedata.port = tonumber(fields.te_port) + gamedata.port = tonumber(fields.te_port) or 30000 gamedata.selected_world = 0 local fav_idx = core.get_table_index("favorites") local fav = serverlist[fav_idx] diff --git a/textures/base/pack/authors_menu.png b/textures/base/pack/authors_menu.png index b4035c2e5f955a773418a585022f7c593e6feaa6..b5ca2c5a3c6b58a0dacd1f3b3264743d18700140 100644 GIT binary patch delta 251 zcmVIGG=Hk%@ADPJj0004W zQchC0JO%SCK`O_IyT+{0GT`^YqaqL6C?hECoOn)2uA=ePOcT0sEd90X9XC znjmZu!It3YR?#cyvbaibstA%&lLSj+LHtLj(;K;ri%_yy>DmAQ002ovPDHLkV1j+@ BadZFx delta 322 zcmV-I0log00^I_TB!47OOjJbx005S%<2-iD6%ifw^XTT{(O!wY($2d7|Nm2EoW9HP zb)MQ17`ave0004WQchCASQ5y4+GQS?Ie3(EndJPjBBq@z{(nX(L<3>evH%#R5DgH* zr&_ckGsl3m0szD$h$!*1L@m9*5?NysjLd?FQ3~`(A?91o7nJ%#$sqRMhuj*>f@-OI zKx% za%q+z5aNlD0Jvfi$eJ&UumvBm?}?FMQ}nDEB8mvML}Pb~UQDsYl`ORciPkK^ZV z`}X<8vqu->I`>{Wx9k7^|G}wq_MQG%I`3B4V$L~0rHmy(e!&b5&u*jvIWIk3978JN z-d+miJZvD+`Y>un>zM-!_}p~PIO!g7(gC6vZqco&?Qa4&mZ~@Q9sIZa&|f(|)yuo$ z%8EXhc>I{_C)OX;d9-yUQ-h0mYK)&o@(L}BX6Iclt4g~C z?35mF=XSbL*u_z4ZSo@NPp!h6H)4$b9sC|*cTTQd^SaieARSFNdCBzCH3RY=x zSbRO*6l|KvE66P&&cN=P_4KblS2n}y2Ma!=MW>|2iJq9?&afzfrTGwJ3HSFbwh2e> yD#o0S72FY*eq^=Ez3aD+Sh1|PestxZEu+!Wprdk=qB($`X7F_Nb6Mw<&;$T8ua9s5 diff --git a/textures/base/pack/authors_menu_selected.png b/textures/base/pack/authors_menu_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..ba88124537ae80f0748e018e623f0f64ec2d63e1 GIT binary patch literal 280 zcmeAS@N?(olHy`uVBq!ia0vp^jzFBi!VDxgXfizoQW60^A+G|o1Xu&37O+MwXx;Ka zETi$;W)1u4>-YA|VR233o2EMNh*ZobzkU@prZXxEER!ZgELiznTFkTBCAwFTpZCrp518#_Pb{_?#T&e}0crNCR{tM|ppjvG7Pcuy4g$R%`YTH}v? bzvb#Xd%6Q2)N~yOx}3q&)z4*}Q$iB}oUD1i literal 0 HcmV?d00001 diff --git a/textures/base/pack/logo.png b/textures/base/pack/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..5e139b2c366ea64d33c054c6190b9ebc73e8684e GIT binary patch literal 2410 zcmV-w36=JVP)FBC3X=dauYhV87PGmA!rdOd=eZ`4k?ZlE}j-Suo)g#4k?QiER+=|dJ!y_ z6(emCG^Q6dsuw7O5;39|GNTtLPz@+w4kkzpC`}9~NDC=h4kbIoD_;&GSq~#< z5UF7{8A1#xeG(Wp3oC{bE_o6yZ4enb3ow%vp++EZFc%j+41P5kAyW-0YY;7P5iNca zcr+L)jT0)56y2Rck31W`Vk&|+8zgEGCT0&Wj1+V-7o32vMVCPyj8HZqVGk^J5qmQjt4|`lVJM7nA0RXeRx1&aPan5~HIhIbub6(ua4*}QMXOOHfkPXlZz`isBF=v^$F``sU?(b) z6rgu6q;M*?d@s&^Gp|=DaXc4|M;^w7G@nHv-JL#tK^k~E7lAt(yM8gwk~`nBYnehG zwst^^Rw2NMHPDhe+oD8QDwjeY zvv4e_P$RBVC8kg#(4j}3RUwvNB(jG|)SW@dn?$Z{DxO>z00001bW%=J06^y0 zW&i*N7)eAyRCodG(#4+KFboFpTAv$5mIst{ouOrBW+-#t|9LvuUcJRjNvD}4`u{|a z{>L8>?ibS?Irl5+@E(tUmT<0MloEpCX9(w1G(|ft(cO)%+s9T2<-5rI5mxV*HwmIKz;H%6OV z!@9mdJJRGyQL89dQiFn7l!`XDcjh;C_j176{`$e*-f(l)dq4)!;A`%)_8Fi=?ST|4 zheyjhi^nIYIpFO4Vzhg?y*<3zNQo+C@;XzP_CzTWm{lj^mFxMfgPYsC9Psqn^A~5U zr(5gu(<ftB&$0V! z_-po40sFrY8_j^Krv3piNIEcthH+PUWVGSOSZz3^j(hwThqL+}UtR6jU_EMj^cTPQwKnMB6F4L`2{$Y?OmJ}i3gUJ5yEI? zW>pY=e5_k5tg|jphzV3X<9^r11_-C?8omqNn-hy@D?3d(u)V!p#t1FrENpoFsVUeP zu_xU$!}~2e?pgpF1fl=??(|~s-rmsA5b?nB@;=50;{&b#`ym8X!5FIs|2e((qoe3? z5el$h*ex%X_wdj(@xaN@>CpD}^w1F2wC@5GK~)CWQtOnLJ34MUJHNXGyW;)B;{m$Xp4zVmUhR$`4&dom>31oE z;)ze)^Y6Txx?Al`)NXQ4wM|~zxVCNEwrkwF%@gBVQ76V4^Ba4G#0QGg8+8CCu$+b! z&o8`TK6&B9iK|b({OGlZuiv-HTc&wRxQvCvn%;Y|bwUYxOaMPIX_edpM__n!Rt z#cN;Oe{eJ9-sMy;ns$YSSmZ0(_#Om7V4>!{+iFv#fXGrCa+M3pvH_7zoHaT+XQ>C+by$g95pN={MwDarIW)V*c~-PgPdY c-N*m&AIw}0D`|lR*8l(j07*qoM6N<$f=hoWLjV8( literal 0 HcmV?d00001 diff --git a/textures/base/pack/select_btn.png b/textures/base/pack/select_btn.png index d984c58ff4bed481cba9ac08cb1e9fd9455cf570..eb7a8e9980b177826a04018391e9d9d5cbe3e798 100644 GIT binary patch literal 525 zcmV+o0`mQdP)hOU80004WQchCInFP zIc{?7RQ({NhJYo^y&leM7^t9c1e`iWX~7boK}NkHU<5i4_$!!K1e9>H&IwA2fc0*a zGv;^~BS1l7F91qVL?ZyRDL!y50CH>ipfv^nlC~cYcinciP2JqhR{u{DUdp)sc{Ep7 zwb$pin)+3(T^MgvbK;9kg+`jP)FCg#Lmu&qMb6CA>(5h3RVoP+p8((=gLi}Q=nkF1 P00000NkvXXu0mjfQ=`>^ delta 639 zcmV-_0)YLE1cwDIiBL{Q4GJ0x0000DNk~Le0001h0001h1Oos705K4J_y7O^8&FJC zMF0Q*kuMd0Co@;TOlW=p0004WQchCM%C3{16c(-08`h`i_xvw0=nM;!3H389p)XutN{HMsFZwQ z9H3YLG*=s0SOADJ0F4hwoo|6^@Bvi)9*}$hF6%+^fr$56$kYaa0W|mkMoX*Q07lgY z5I&%P$TZ4XJ^)Tb0UuCg84V>C0G0LU>H|YsZQTc;E+Y&0faupicgP1u)-5amQ026B zACS{j8$7^&khA~@XQR0S$SG&W2Z(N`srtZRY_@AQfN^R;_yD{Ix{wW6Y3!5@n77a@ z0CJjY1q;9!S!jh1gw@gpACLiD#R9;TQ%vK31L2ml4@??ORpSG28QVPA0Gzgtd_ZBn zjAH?qbZTJ%z}W6zDfvK<&K3tBn0Q~#xdJd{l=BK;y&Bg75IAjpeBi&sOQI7U#s^To z0;*sK2)e4jPhmCM0f?&a^KjOP72ps^Rh@s|CA+$=&g!nZ1ApP{dq~Wq`GAJ(ysoNB zv+6^1pOYt$pLyp8u8`OR&HxR;h>$cwFz^Is2nC2Un|tvhAS5Y9hs1` Z@DCcQ>PAdleewVR002ovPDHLkV1i9;2JlvXHwU4^82i>%iF69^-8o7a#go6 zv1pHITe&ztBo|*K7WyQgXA&X*BC+@+?kN-v0mP!(Ee%jC&UBCh7!rvgfPy4qhyboq zX9Cg_Hyn#2_75;55JNBnq)0$8YE?lJ@o7eMr2+$KNF-=P1tM8;&yTzwu{Q$Zu7WH? zm$VTOodeklZv}c8B!3%FOjJbx004EK+B|m46%ic+A$_^Z>o#S|ag)(*g~-C#B*Opz z00DGTPE!Ct=GbNc007%bL_t(|0b)P}qd-td*_dJ#f#vFUsjBoqw0>$ON?oTyqJM6#Goi?|qZ!DNaNNQX z>f}UpG7ya*I(a5k1OXWc#Xp&fA_xzKAqAR%JQV4$02&KO3J^uk1w?>^jD-M^DGvq2 zhRBYgfM5UtnTRp~X(2GOG9g1j2n!!YQo; zM76Dmm4E;i0wxlGjer1Fg1)1-3W*LpfG8CJdRd~PbIRUC00000NkvXXu0mjfc3^Y2 diff --git a/textures/base/pack/settings_menu_hover.png b/textures/base/pack/settings_menu_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..0f07e1a5ea6cefe9792516e92cf213df41f45176 GIT binary patch literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^jzFBi!VDxgXfizoQbGYfA+A7L#jfwr#diUf7n>Je zkLbGe%21*mD9Tt8(T zba?}G&P`yF5b9KHXi`b)U|1KF&U8uGT&7$38^3{yfU^Pf5)TK1tWZaxkC|>IOPQE6 zJybGWSd}7+&iC(;+i1@8XkC+z%k(XR0&|&fa^$1~CkEAV_1#~`xr>mdKI;Vst0P}ZWZvX%Q literal 0 HcmV?d00001 diff --git a/textures/base/pack/settings_menu_pressed.png b/textures/base/pack/settings_menu_pressed.png deleted file mode 100644 index c625b504e86a8c9d15903b6764cb58762a1acfb5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 337 zcmeAS@N?(olHy`uVBq!ia0vp^jzFBi!VDxgXfizoQgQ)4A+A8WblxqSveTl1vSpKw zF)P;YJoVZv^;F^Hi+QalW~O?Z097!S1o;IsI6S+N2IM^Sba4!+U`%pgUF;CxadSqJ zsFI)8F$ag4T;k%Y3>%9Q7!5^Q9Cu95R^0kWH;4Q7q4;m9cbv^+DtDhqI8a^|^NQnF zjFYL$%jIrKE0e=JLe6ef7nxa>z;#ooFWBOdo0*HEZXm~^N$F1A3JSancTCt8!SZmK z0ZW1Kgyl-IVh*{Co()Wk`WhH^{9;;gV#;i$BGB5XoSVQTA=IhZ(4>;o!LTkUo#~RWxlFh6H+};Z0cQi|B_0k2S)qY%zuM}LqS}?L5E|5(De7R Y*JY=P9!Xm;3+Q|XPgg&ebxsLQ0COE*`~Uy| literal 0 HcmV?d00001 diff --git a/textures/base/pack/side_menu.png b/textures/base/pack/side_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..903f9ee44721336e149207523d8191b7b4182c3d GIT binary patch literal 193 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-u0YzR?6jz$Z0WpPdiM`^ z1Nn?4L4Lsu4$p3+0XfN@E{-7;x87da$jhL};~Y3`$;pzHd*fflOvso}^oO?iV5w9AJazMpR*Nm m?>xDOEly%A_P)EX>4Tx04R}tkv&MmKpe$iQ?*4Z4i*t{h)|s@h>AFB6^c-y)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfbaGO3krMxx6k5c1aNLh~_a1le0HI!Hs@X9PsG4P@ z;xRFkT@?eb=t4h&h+tS^raqTUCg3@~?&0I>U6f~epZjz4C^?e>K9P8q>4rtTK|H-_ z>74h8!>lMN#OK6g23?T&k?XR{Z=4Gb3p_Jyq*L?6VPdh+#&R38qM;H`5l0kNqkJLb zvch?bvs$jQ<~{ifLpg0_nd>x%5XT~xkc0>sRg_SMg($5WDJD|1AM@}JI{qZNWO9|j z$gzM5R7j2={11M2Yvv~>+@w$p=zOv5j}aiS3p8rB{e5iPjT6BC3|wg~f29u0e3D*k zX^|tKcN@64ZfWu!aJd5vJn51lIg+2Ikk13}XY@^3pzjvwUUPeE?&I_UNK;pd8{ps& z7%foty2rbN?Y;ebrrF;Qb&hhVy+#=200006VoOIv0RI600RN!9r;`8x010qNS#tmY zE+YT{E+YYWr9XB6000McNliru<^~oBCJNi*lwJS;02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{000t6L_t&t*JH?QJ@KDOLsgmq02I*!C2Vog#Q*>R07*qo IM6N<$f>sLYL;wH) literal 0 HcmV?d00001 diff --git a/textures/base/pack/side_menu_left.png b/textures/base/pack/side_menu_left.png new file mode 100644 index 0000000000000000000000000000000000000000..d84644a69561d4b832f36b2b3255be5849cc24af GIT binary patch literal 5681 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 literal 0 HcmV?d00001 diff --git a/textures/base/pack/switch_local_default_hover.png b/textures/base/pack/switch_local_default_hover.png index 0a6abed74483e4068cd97a64703a1ed6a8f1db6f..dca808e3a8e443c74ab22ff121dbe6e2900af5c6 100644 GIT binary patch delta 1880 zcmV-e2dDVu6yX$*H3L|R(vdYbv2MEpf5{QRHUIzs0d!JMQvg8b*k%9#2Mp#DEJSKTr(jTpOb&cI7U4??VVO&I@5vN(S`IZY~!g z=Q16*NL9BFFz5;gq0`idR~nQuItJ3Dvz%@g0|SMDIqr#meACsUn@$i0@SDHhf7F;+ zhG8~PvNWlib8ZiL=E`iDlJr9*a^t|Vm{{(oZ?h^(a zhVlwg1*&yn(X|MWnaB}wnTjv~{x13-`|-S_P6-=?sFsQ$lKAc0PyIL}|D_NL;NJom z)Cn6X5CQ`>{T30%uHSYkjJ{9>f6BhAD;01A7V)^me+bM<0U{-0 z&;nW;hQ^w>NJ&%y_qaU@TpZv+WDEduh%5}Cb&?Q^OD%$&D1|C897VmUyL8;%i)bSt znNB6kIvsLh&M%hEiClOLjEs)eY9b{0MrsYf8AE80z!**FK7fD&B!4_Er%(YVCPzl5 zd_O-%w~=HmibcbTk_=EWe**x50vsNhoGyeaFf%hdJw7+rXoy(LAXb53Ls%%~214lO z!70oyj4UoK$K7%Ye*i11YwH^u!<%DDA#$b-ss`0b>Vyau@(bcmjcrYBPb}^17D5Hs z+dr6IUOqe;KAyD}QXx>%@{J@cuAg5l86BBAIXyeSxV(A}xHdOef49@SXETd#7COts zWRP-NGZ+R4OmsJYzqx*P_%QkT;mdQt*Kgl{{Jgqdo|zs$8J$Wynou?J$wwS0fYIa8 zUu@9>Vk=P?1>ikA+ji_^P(?LjdQsS1qd3{{t zKZ&j~MG{puSx9@hxy8Y^*0tRSw8IWmEOd4SzuA1&{CpRge`8ds+)rh0w_acA$<^dy zq?2$kpu4A+hG+TPK;JRYKR|sOblQf7Ic&tMNRr5864k%T6pU1lI@z%Z)jM80(N}*j zFgXPwg46voH2v+3zhY>XP?MJAs9Tjer=DMEcCqi?J*G<*yC>jMS>GA(=LWF6JS89q zr_eYRe7xc?e}`5O>H0q5!w{_wGR|% zF=HfW&QNKUTU+++#Bt^wO$igiI%>aK;5x9=zT3XM+}GZYMDZ(4F`y;ftjwQH)8=k% zH}9Q9-i>#{4LH%he7?Znn?MId`)IjOXy1hgG*vPQe;nb2S7FoZw~pAXYb`69Ab{iP zCpa(Ai-kkR^I#FtoY2;d^bN;`{y6WYt z=>HbTRkg@Q{O(g86d(lRd{AuYae;jDI6J$p{@#tMa}AA6Hi-bLmF#lcrvW~YZ@5&d zX4bhXe^5m^#Vz%h?^ac{wuv(iuw!%AAGUomK;Zkn0V zJ{^#XQL)BSgwEPp3_`dPi(Tldwp%SVcYO*_LmV(51DArVl?Y+j9gE%Sik4b(ZpZdn zsQ_Yuifb}Gy}BnKh*{y&>oMpOo&{2K+ou72e`J8UAL4*^G@~J+>o6cZ&uvv3yV~`c zfa`|Ahmd*=6PA)+DoG9w{T9x6c3duwX8^Q*P6hxWh!cP&L#(x=fyOqwiOxjhdLcx< z$pF~xJj@Up^kv-k8jvlfd8Dyz^q1hatNnP~_Njoo4*)`D;8M+mNWcL3U1Q@DlU6uv ze*r|6TDsf;|0V$LLJ61wO(`>ygsGaE{OO^Y*}3^hI4mFx7F?bga5oZwuMs7K){9Ha zw9>Wu?0P$hv)*B$mCG{&PKbznhOkumw6?ynfiGLfHn-Xh3eOV>x$Dz_--n(KSuN9c z^Ukh$xz{+lm1mfRC$bXzWMKbaD-?k#juwN0CFao}*0AJ5C z113gnWUQc?=hhmnW>68yd*HhQDC(_NyA5E3Su_*@74eKK_Mk>2HQ?I<@H@}UX)59n zkx0l}h}JSICWFCXqR9Wkdmsp+Os!RoV?<^mrnZPNBFxSuzF%e})PW$1e?a|*z-$a4 zQYwlL(78BPr%9QLs003S2Nd~uz=uc`069h$2Cz0wiN&YUgo3DqIxyL64yR7kSItGN z3P^4<$@6}ne3*-iWecJZ-UCz9GmVA_NwJaE0&va{D-x($LjM6o93h3XNi~HUFgHIn zwGf8IF{;Mo9EwBb)JP6!f0zLP!2nK9%`cWh9avggUYuQ7X}3k3V-RORuq`ZW(jr7~P+X93Vdh}raBk!1xD;x@ z$?4hR=H~guqLgT$jb_-?e;m%8PGBD}yYBt-%a{De7}!Yv5!yd#HF}$|xR`f13WUitEs(rDR7Mbjnvq*c8xtM%AB5r)zu3Pjd|w*B9LH1Q?t<0>cEK- z%wp7J=%-a$k^s2Jq7I@sX}LC*LeT}-LOpTf9cJ8?#^~4C#RDMQ6^Ky zHC;xA-CmQKXi3D#G$NIy`uYbL5b93@gMMIWn0`Kz<{lm6vGFX!2aQgrF}<((gpuZn zG|pQ{5BM77!KQNoMFjwY??XQr=K0;6>d~KsnRI?E$}q+LGXMV5p3dFBf0-%&+b4s6 zm4hMR?FnFVe^M1804ns+d6%bB9rETLsIIXQ?Bl%!`2%~Bl& z?Z)JvU#y7>i|s3c7TLKp8+~ z%gW@SysxN|EXsWi{Ri8HBmdc~Yb7~iAdKUo8J|FB3dhgn)Zs#QHC;W9*1aah(+Yi{ zJ&=9Oe_&>2W@bpQw>lY8s`~%Z{)UGam&`r|B5I zqn6L*N#9ch5RarCN8#LgcdiY@oZ`u50%uGle?T#pz64yL0L&Mm11Qfi1|n+0B@;z* zRW;UH`zoLr7;50@d|<*ps`Xj2m#?TGeI!qFv$Fzl?lc7egt$WhjsmfBmM+aM$tBv? zecBsi+MxoF>wJ~L2dvqS^bU{(b9`-f>AF!tud96Sl)eb)J^=8{zDbLd;I=kC}ojpg<0 zzh{ArAcSiz9QpD3=iLuCejRUB&Fu{t;G+Ts;`i@A6Mygi`~RRiSK#|v=VhS5U<`vn zI*eb+_Wn;;5C*nw>6Q}|`HS`dxbp#g5fCm^z8lZi`}3Gx4*aiaCm?c-LQ4GRN;>`s zGzw=c<~DvaBTz0K WJLV9`^qhPE00002ZzPonc}4yCLrG?z_qG%+~ZwYq)`#;@{=?Sc=l6x9g6i<}6N^V`F2s zZf>~V|B$8TJy(}*nb={F)vJexzp=4Re#WrB?mAU{Tztz!YJZ~6h#{=3tlZPn=$9eN zoSb^1+oQGXEqKQFdYp{_0004WQchCJM9?Wj>wFrn)=7^~ntegR(5IZb@9;Etkug zY-$L1k|-C8A%6rpV3|$RKTLqfl?a#9rS_%n?XCRLPz;9;j{;oHmX>43i7ZQ!I`JUD zN`RU6$X{Ogt-mjdL}r2qrT~y*$g#9%IN&M4&pLp;x-p%;D9{%WNYnvlmSg<~0Kn?N zv@G|Q`fsC6YkI-B7|Tx&PxAoW0oWU%yB>7_RIdO)$$y#vX8CB;1(1yi@XZ)-SC%&_ z-1r>8b@zfX0sk}&7?k@P5b_PV0@pnkC;+JmtObx*2p~T1z6G2h2iVhW0WbhCC(t=T zW>2#ND1qF7?g{oZ4OkCKo(}>szS%?Ub2{48PX5#+1GqB>>_j*L1YB+a zV%-6Vj{@x3)&ZQ2FZ_gVAf}t02vl(ej2cxK&3r}U4-)- zwttoN0AX$b7gg04P$>{^V|<5GA#{KkH+BW|75-j8%khLRfEydavk2&)wMS?|7YGDU zA#Vu2KZG90j{p!12q5eZ_a9RBLC^yr=DvV9s&+f;HJ1Dc06}Jg0CCjnk)!Veu(&}4 z5SqQT=#K&N8T|AE!QY5$V@+Vt{5#PA6@Q}kyx{v5Kq1Cdh_dz~1JJhs6~bUkfxx7` z1`ulB0n$wvLeNF*Z3cwlCT#-e0}6VD2de71zN(7Y>#MUL%xeGzBO>-T0-Cco;GBRF zFt$;9s4XWjC$Lyku!UGqTZol5?LRK&_W%})bw{9LD{a;ra1MdS=~<2b{Ne(@>P2cX zRKf3b$ytv-whe!^2W&o{U&!v!%L%u`-y0&_>j4l}x4+z@3^{rVe;sP>@AZG7kpm6i S6aahx0000n(W329{m+SSCJJ%hqR+eR+=lcgCvh!}YTT>8#Xjh4RyPcDO19s^$`9TD{ zXC!3H9q)7Q=_&tG5a#pycLMh7T{B1HM4GNvA#qPYM!*_-o_~CQ;A@PisuiVz0!sm& z5C|?A2nYOLB~%Y+K3$nUQB~Mi5QGQ;odw^A4*-BdV43H4I@Pbqu@he~t)}$H%WGbM zGl08*K+lsNfYmPmpr|&0n)zhX2QZroz^@qq=RAL9;kBLvcT*$0@wT!DcT^fd$EQ08(z z2#f*fBMv$}0Ov~#$Rk>9@HO)gknUh7gBn`5Qst6OuNNBmm?Qk)b6gCm2V6`(KEJBSnKQa6C5ukenkx z1;l$5h5<@|$hk%^Auy%quSNl6?4|F)&3}0UOC&es1hR0Q(w%Jpi7|*n5xt zcLBZv`7}*ENctHn2-w>(0DBCb?Bg1cM<4;w_s9+d`Tz((9P0(ts*bL-V}QG4_yWqO zGXPw~0O2ElfED zyiwqvM*vV{I0#n&PWLGyAVr?%*MV>jpy0g-Cy(SMbke;DG#>#VI6)MMe7#oynLz+WEy6(P?2W;G44@O`+zTOp5e3OwfHDLU ztAGf;TP@W44j@8=Snz2#uK@2m01MVEL=a#W)&eZ=dq8ru76Rw74^x2V$D|Fsl_KyJ zHBc0PFJVRDWzU~3`*ITkA}Hap4-)`$*$2QI0|5bJ;k#ko%mvs8usuKsv&aNllxwp8 zd%O7ru-zV1=qMW0-o63eAgFOIU1R@tdkY}jZ|4xS>q`{w@!z)jx4K80&E}T+#GX!g xn1A0O;gb)5kUe~}cM5atS@>}`+RxYj0q58f@kdgygS`L%002ovPDHLkV1hp}_6Yz0