diff --git a/builtin/mainmenu/common.lua b/builtin/mainmenu/common.lua index a5b06d793..a0725212d 100644 --- a/builtin/mainmenu/common.lua +++ b/builtin/mainmenu/common.lua @@ -19,6 +19,9 @@ -------------------------------------------------------------------------------- menudata = {} +local fmt = string.format +local esc = core.formspec_escape + -------------------------------------------------------------------------------- -- Local cached values -------------------------------------------------------------------------------- @@ -157,13 +160,21 @@ os.tmpname = function() end -------------------------------------------------------------------------------- -function menu_render_worldlist() - local retval = {} +local button_path = defaulttexturedir_esc .. "gui" .. DIR_DELIM_esc +local worldlist_scrbar_pos = 0 +function menu_render_worldlist(selected_index) + local fs = {"formspec_version[4]"} + + local outer_w, outer_h = 6.93, 5.65 + fs[#fs + 1] = fmt("background9[0.52,0.21;%s,%s;%sworldlist_bg_new.png;false;32]", + outer_w + 1.2, outer_h + 0.2, button_path) + fs[#fs + 1] = fmt("scroll_container[0.62,0.31;%s,%s;scrbar;vertical]", outer_w, outer_h) local creative = core.settings:get_bool("creative_mode", false) local damage = core.settings:get_bool("enable_damage", true) - for _, world in ipairs(menudata.worldlist:get_list()) do + local list = menudata.worldlist:get_list() + for i, world in ipairs(list) do if world.creative_mode == nil or world.enable_damage == nil then -- There's a built-in menu_worldmt function that can read from -- world.mt but it would read from the file once for each setting @@ -173,22 +184,76 @@ function menu_render_worldlist() world.enable_damage = world_conf:get_bool("enable_damage", damage) end - retval[#retval + 1] = world.creative_mode and "5" or "4" - retval[#retval + 1] = core.formspec_escape(world.name) + local y = (i - 1) * 0.8 + fs[#fs + 1] = fmt("image[0,%s;%s,0.7;%sgui/row_bg%s.png;16]", + y, outer_w, defaulttexturedir_esc, i == selected_index and "_selected" or "" + ) + fs[#fs + 1] = fmt("image[0.2,%s;0.4,0.4;%sserver_flags_%s.png]", + y + 0.15, defaulttexturedir_esc, world.creative_mode and "creative" or "damage") + + -- Use a scroll_container to clip the label + fs[#fs + 1] = fmt("scroll_container[0.8,%s;%s,0.7;;vertical]", y, outer_w - 1) + fs[#fs + 1] = fmt("label[0,0.35;%s]", esc(world.name)) + fs[#fs + 1] = "scroll_container_end[]" + + fs[#fs + 1] = fmt("image_button[0,%s;%s,0.7;;worldlist_%d;;false;false]", y, outer_w, i) end - return table.concat(retval, ",") + fs[#fs + 1] = "scroll_container_end[]" + + local inner_h = math.max(#list * 0.8 - 0.1, outer_h) + local scrollbar_max = (inner_h - outer_h) * 10 + + -- Make sure the selected world is visible + local min_pos = math.ceil(((selected_index - 1) * 0.8 - outer_h + 0.7) * 10) + local max_pos = math.floor((selected_index - 1) * 0.8 * 10) + worldlist_scrbar_pos = math.min(math.max(worldlist_scrbar_pos, min_pos), max_pos) + + fs[#fs + 1] = fmt("scrollbaroptions[max=%d;thumbsize=%s]", math.ceil(scrollbar_max), + (outer_h / inner_h) * scrollbar_max) + fs[#fs + 1] = fmt("scrollbar[%s,0.31;0.8,5.65;vertical;scrbar;%s;" .. + "%sscrollbar_bg.png,%sscrollbar_slider_middle.png,%sscrollbar_up.png," .. + "%sscrollbar_down.png,%sscrollbar_slider_top.png,%sscrollbar_slider_bottom.png]", + outer_w + 0.82, worldlist_scrbar_pos, button_path, button_path, + button_path, button_path, button_path, button_path) + + return table.concat(fs) end -------------------------------------------------------------------------------- function menu_handle_key_up_down(fields, textlist, settingname) - local oldidx, newidx = core.get_textlist_index(textlist), 1 + if fields.scrbar then + worldlist_scrbar_pos = core.explode_scrollbar_event(fields.scrbar).value + end + + for field in pairs(fields) do + if field:sub(1, 10) == "worldlist_" then + local idx = menudata.worldlist:get_raw_index(tonumber(field:sub(11))) + if idx then + core.settings:set(settingname, idx) + + local world = menudata.worldlist:get_raw_element(idx) + if world and world.creative_mode ~= nil and + world.enable_damage ~= nil then + core.settings:set_bool("creative_mode", world.creative_mode) + core.settings:set_bool("enable_damage", world.enable_damage) + end + + return true + end + end + end + if fields.key_up or fields.key_down then + local oldidx = menudata.worldlist:get_current_index(tonumber(core.settings:get(settingname))) + local newidx if fields.key_up and oldidx and oldidx > 1 then newidx = oldidx - 1 elseif fields.key_down and oldidx and oldidx < menudata.worldlist:size() then newidx = oldidx + 1 + else + return false end core.settings:set(settingname, menudata.worldlist:get_raw_index(newidx)) return true diff --git a/builtin/mainmenu/tab_local.lua b/builtin/mainmenu/tab_local.lua index 821a21b4e..f3f1c58fe 100644 --- a/builtin/mainmenu/tab_local.lua +++ b/builtin/mainmenu/tab_local.lua @@ -52,7 +52,7 @@ local function singleplayer_refresh_gamebar() --[[local index = filterlist.get_current_index(menudata.worldlist, tonumber(core.settings:get("mainmenu_last_selected_world"))) if not index or index < 1 then - local selected = core.get_table_index("sp_worlds") + local selected = get_index() if selected ~= nil and selected < #menudata.worldlist:get_list() then index = selected else @@ -100,13 +100,19 @@ local function singleplayer_refresh_gamebar() btnbar:add_button("game_open_cdb", "", "", fgettext("Install games from ContentDB"), true) end -local function get_formspec(_, _, tab_data) +local function get_index() local index = filterlist.get_current_index(menudata.worldlist, tonumber(core.settings:get("mainmenu_last_selected_world"))) -- Default index if index == 0 then index = 1 end + return index +end + +local function get_formspec(_, _, tab_data) + local index = get_index() + local space = small_screen and ("\n"):rep(3) or ("\n"):rep(5) local retval = "style[world_delete,world_create,world_configure;font_size=*" .. @@ -144,11 +150,9 @@ local function get_formspec(_, _, tab_data) (core.settings:get_bool("creative_mode") and "checkbox_checked" or "checkbox") .. ".png]" .. "image_button[7.31,3.09;4.2,0.83;;cb_creative_mode;" .. c_label .. ";true;false]" .. - "background9[0,0;6.5,4.8;" .. defaulttexturedir_esc .. "worldlist_bg.png;false;40]" .. - "tableoptions[background=#0000;border=false]" .. - "tablecolumns[" .. image_column(fgettext("Creative mode")) .. ";text]" .. - scrollbar_style("sp_worlds") .. - "table[0,0;6.28,4.64;sp_worlds;" .. menu_render_worldlist() .. ";" .. index .. "]" + "real_coordinates[true]" .. + menu_render_worldlist(index) .. + "real_coordinates[false]" if tab_data.hidden then retval = retval .. @@ -182,30 +186,6 @@ end local function main_button_handler(this, fields, name, tab_data) assert(name == "local") - local world_doubleclick = false - - if fields["sp_worlds"] ~= nil then - local event = core.explode_table_event(fields["sp_worlds"]) - local selected = core.get_table_index("sp_worlds") - - if event.type == "DCL" then - world_doubleclick = true - end - - if event.type == "CHG" and selected ~= nil then - local world = menudata.worldlist:get_list()[selected] - if world and world.creative_mode ~= nil and - world.enable_damage ~= nil then - core.settings:set_bool("creative_mode", world.creative_mode) - core.settings:set_bool("enable_damage", world.enable_damage) - end - - core.settings:set("mainmenu_last_selected_world", - menudata.worldlist:get_raw_index(selected)) - return true - end - end - if menu_handle_key_up_down(fields,"sp_worlds","mainmenu_last_selected_world") then return true end @@ -215,7 +195,7 @@ local function main_button_handler(this, fields, name, tab_data) core.settings:set_bool("creative_mode", not creative_mode) core.settings:set_bool("enable_damage", creative_mode) - local selected = core.get_table_index("sp_worlds") + local selected = get_index() local world = menudata.worldlist:get_list()[selected] if world then -- Update the cached values @@ -246,8 +226,8 @@ local function main_button_handler(this, fields, name, tab_data) return true end - if fields["play"] ~= nil or world_doubleclick or fields["key_enter"] then - local selected = core.get_table_index("sp_worlds") + if fields["play"] ~= nil or fields["key_enter"] then + local selected = get_index() gamedata.selected_world = menudata.worldlist:get_raw_index(selected) core.settings:set("maintab_LAST", "local") core.settings:set("mainmenu_last_selected_world", gamedata.selected_world) @@ -321,7 +301,7 @@ local function main_button_handler(this, fields, name, tab_data) end if fields["world_delete"] ~= nil then - local selected = core.get_table_index("sp_worlds") + local selected = get_index() if selected ~= nil and selected <= menudata.worldlist:size() then local world = menudata.worldlist:get_list()[selected] @@ -342,7 +322,7 @@ local function main_button_handler(this, fields, name, tab_data) end if fields["world_configure"] ~= nil then - local selected = core.get_table_index("sp_worlds") + local selected = get_index() if selected ~= nil then local configdialog = create_configure_world_dlg( diff --git a/builtin/mainmenu/tab_local_default.lua b/builtin/mainmenu/tab_local_default.lua index 257f37b0a..b33e20893 100644 --- a/builtin/mainmenu/tab_local_default.lua +++ b/builtin/mainmenu/tab_local_default.lua @@ -25,6 +25,29 @@ local default_worlds = { {name = "World 5 Flat", mg_name = "flat", seed = "2"} } +local function menu_render_worldlist() + local retval = {} + + local creative = core.settings:get_bool("creative_mode", false) + local damage = core.settings:get_bool("enable_damage", true) + + for _, world in ipairs(menudata.worldlist:get_list()) do + if world.creative_mode == nil or world.enable_damage == nil then + -- There's a built-in menu_worldmt function that can read from + -- world.mt but it would read from the file once for each setting + -- read + local world_conf = Settings(world.path .. DIR_DELIM .. "world.mt") + world.creative_mode = world_conf:get_bool("creative_mode", creative) + world.enable_damage = world_conf:get_bool("enable_damage", damage) + end + + retval[#retval + 1] = world.creative_mode and "5" or "4" + retval[#retval + 1] = core.formspec_escape(world.name) + end + + return table.concat(retval, ",") +end + local function create_default_worlds() if #menudata.worldlist:get_list() > 0 then return end diff --git a/textures/base/pack/gui/row_bg.png b/textures/base/pack/gui/row_bg.png new file mode 100644 index 000000000..0e2965b42 Binary files /dev/null and b/textures/base/pack/gui/row_bg.png differ diff --git a/textures/base/pack/gui/row_bg_selected.png b/textures/base/pack/gui/row_bg_selected.png new file mode 100644 index 000000000..912e201cf Binary files /dev/null and b/textures/base/pack/gui/row_bg_selected.png differ diff --git a/textures/base/pack/gui/worldlist_bg_new.png b/textures/base/pack/gui/worldlist_bg_new.png new file mode 100644 index 000000000..dbd5d4e86 Binary files /dev/null and b/textures/base/pack/gui/worldlist_bg_new.png differ diff --git a/textures/base/pack/server_flags_pvp.png b/textures/base/pack/server_flags_pvp.png old mode 100644 new mode 100755 index b3be380cd..e8bd131bb Binary files a/textures/base/pack/server_flags_pvp.png and b/textures/base/pack/server_flags_pvp.png differ diff --git a/textures/base/pack/server_ping_3.png b/textures/base/pack/server_ping_3.png index b3ff45e35..f9b7e5874 100644 Binary files a/textures/base/pack/server_ping_3.png and b/textures/base/pack/server_ping_3.png differ diff --git a/textures/base/pack/server_ping_4.png b/textures/base/pack/server_ping_4.png index 348ac1fa9..634b8a8e7 100644 Binary files a/textures/base/pack/server_ping_4.png and b/textures/base/pack/server_ping_4.png differ