mirror of
https://github.com/luanti-org/luanti.git
synced 2026-10-11 22:09:57 +00:00
Add client-side support for multiple ordered texture packs + Separate tabs for content (#17552)
This commit is contained in:
@@ -61,13 +61,17 @@ end
|
||||
|
||||
local function load_texture_packs(txtpath, retval)
|
||||
local list = core.get_dir_list(txtpath, true)
|
||||
local current_texture_path = core.settings:get("texture_path")
|
||||
local enabled_packs = pkgmgr.get_enabled_texture_packs()
|
||||
|
||||
for _, item in ipairs(list) do
|
||||
if item ~= "base" then
|
||||
local path = txtpath .. DIR_DELIM .. item .. DIR_DELIM
|
||||
local conf = Settings(path .. "texture_pack.conf")
|
||||
local enabled = path == current_texture_path
|
||||
local order = table.indexof(enabled_packs, path)
|
||||
if order == -1 then
|
||||
order = nil
|
||||
end
|
||||
local enabled = order ~= nil
|
||||
|
||||
local title = conf:get("title") or item
|
||||
|
||||
@@ -75,13 +79,14 @@ local function load_texture_packs(txtpath, retval)
|
||||
retval[#retval + 1] = {
|
||||
name = conf:get("name") or item,
|
||||
title = title,
|
||||
list_name = enabled and fgettext("$1 (Enabled)", item) or nil,
|
||||
list_title = enabled and fgettext("$1 (Enabled)", title) or nil,
|
||||
list_name = enabled and ("(" .. order .. ") " .. item) or nil,
|
||||
list_title = enabled and ("(" .. order .. ") " .. title) or nil,
|
||||
author = conf:get("author"),
|
||||
release = tonumber(conf:get("release")) or 0,
|
||||
type = "txp",
|
||||
path = path,
|
||||
enabled = enabled,
|
||||
order = order,
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -116,6 +121,48 @@ function pkgmgr.get_mods(path, virtual_path, listing)
|
||||
pkgmgr.update_translations(mods)
|
||||
end
|
||||
|
||||
-- Must match PATH_DELIM in filesys.h
|
||||
local PATH_DELIM = PLATFORM == "Windows" and ";" or ":"
|
||||
|
||||
--- Returns the ordered list of enabled texture pack paths, highest priority first.
|
||||
function pkgmgr.get_enabled_texture_packs()
|
||||
return (core.settings:get("texture_path") or ""):split(PATH_DELIM)
|
||||
end
|
||||
|
||||
function pkgmgr.set_enabled_texture_packs(list)
|
||||
core.settings:set("texture_path", table.concat(list, PATH_DELIM))
|
||||
end
|
||||
|
||||
--- Newly enabled packs are appended at the end, lowest priority.
|
||||
function pkgmgr.set_texture_pack_enabled(path, enabled)
|
||||
local list = pkgmgr.get_enabled_texture_packs()
|
||||
|
||||
local index = table.indexof(list, path)
|
||||
if index ~= -1 then
|
||||
table.remove(list, index)
|
||||
end
|
||||
|
||||
if enabled then
|
||||
list[#list + 1] = path
|
||||
end
|
||||
|
||||
pkgmgr.set_enabled_texture_packs(list)
|
||||
end
|
||||
|
||||
--- Moves an enabled texture pack by `delta` places in the priority list.
|
||||
function pkgmgr.move_texture_pack(path, delta)
|
||||
local list = pkgmgr.get_enabled_texture_packs()
|
||||
|
||||
local index = table.indexof(list, path)
|
||||
if index == -1 then
|
||||
return
|
||||
end
|
||||
|
||||
local new_index = math.max(1, math.min(#list, index + delta))
|
||||
table.insert(list, new_index, table.remove(list, index))
|
||||
pkgmgr.set_enabled_texture_packs(list)
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
function pkgmgr.reload_texture_packs()
|
||||
local txtpath = core.get_texturepath()
|
||||
@@ -307,7 +354,14 @@ function pkgmgr.render_packagelist(render_list, use_technical_names, with_icon)
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif v.enabled or v.type == "txp" then
|
||||
elseif v.type == "txp" then
|
||||
if v.enabled then
|
||||
icon = 1
|
||||
color = mt_color_green
|
||||
else
|
||||
color = mt_color_grey
|
||||
end
|
||||
elseif v.enabled then
|
||||
icon = 1
|
||||
color = mt_color_green
|
||||
end
|
||||
|
||||
@@ -11,7 +11,8 @@ local COLORS = {
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
function mm_game_theme.init()
|
||||
mm_game_theme.texturepack = core.settings:get("texture_path")
|
||||
-- TODO: scan texture packs in order to get game theme images
|
||||
mm_game_theme.texturepack = pkgmgr.get_enabled_texture_packs()[1]
|
||||
|
||||
mm_game_theme.gameid = nil
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ local function get_content_icons(packages_with_updates)
|
||||
end
|
||||
|
||||
|
||||
local SUBTAB_KEYS = { "games", "mods", "txps" }
|
||||
|
||||
local packages_raw, packages
|
||||
|
||||
local function update_packages()
|
||||
@@ -32,8 +34,25 @@ local function update_packages()
|
||||
element.name == uid
|
||||
end
|
||||
|
||||
packages = filterlist.create(get_data, pkgmgr.compare_package,
|
||||
is_equal, nil, {})
|
||||
local category_types = { game = "games", txp = "txps", mod = "mods", modpack = "mods" }
|
||||
local function filter_by_category(element, category)
|
||||
return category_types[element.type] == category
|
||||
end
|
||||
|
||||
packages = filterlist.create(get_data, pkgmgr.compare_package, is_equal, filter_by_category, {})
|
||||
end
|
||||
|
||||
-- Enabled packs first ordered by priority, then disabled packs alphabetically
|
||||
local function sort_resources_list(list)
|
||||
table.sort(list, function(a, b)
|
||||
if a.enabled ~= b.enabled then
|
||||
return a.enabled
|
||||
end
|
||||
if a.enabled then
|
||||
return a.order < b.order
|
||||
end
|
||||
return a.title:lower() < b.title:lower()
|
||||
end)
|
||||
end
|
||||
|
||||
local function on_change(type)
|
||||
@@ -48,8 +67,23 @@ local function get_formspec(tabview, name, tabdata)
|
||||
update_packages()
|
||||
end
|
||||
|
||||
if not tabdata.selected_pkg then
|
||||
tabdata.selected_pkg = 1
|
||||
tabdata.selected_pkg = tabdata.selected_pkg or 1
|
||||
tabdata.subtab = tabdata.subtab or 1
|
||||
|
||||
local subtab_key = SUBTAB_KEYS[tabdata.subtab]
|
||||
packages:set_filtercriteria(subtab_key)
|
||||
if subtab_key == "txps" then
|
||||
sort_resources_list(packages:get_list())
|
||||
end
|
||||
|
||||
if tabdata.selected_path then
|
||||
for i, pkg in ipairs(packages:get_list()) do
|
||||
if pkg.path == tabdata.selected_path then
|
||||
tabdata.selected_pkg = i
|
||||
break
|
||||
end
|
||||
end
|
||||
tabdata.selected_path = nil
|
||||
end
|
||||
|
||||
local use_technical_names = core.settings:get_bool("show_technical_names")
|
||||
@@ -66,19 +100,29 @@ local function get_formspec(tabview, name, tabdata)
|
||||
end
|
||||
|
||||
local retval = {
|
||||
"label[0.4,0.4;", fgettext("Installed Packages:"), "]",
|
||||
string.format("tabheader[0.4,0.9;6.3,0.6;content_subtab;%s,%s,%s;%i;true;false]",
|
||||
fgettext("Games"), fgettext("Mods"), fgettext("Texture packs"), tabdata.subtab),
|
||||
"tablecolumns[color;tree;image,align=inline,width=1.5",
|
||||
",tooltip=", fgettext("Update available?"),
|
||||
",0=", core.formspec_escape(defaulttexturedir .. "blank.png"),
|
||||
",4=", core.formspec_escape(defaulttexturedir .. "cdb_update_cropped.png"),
|
||||
";text]",
|
||||
"table[0.4,0.8;6.3,4.8;pkglist;",
|
||||
"table[0.4,1.0;6.3,4.6;pkglist;",
|
||||
pkgmgr.render_packagelist(packages, use_technical_names, update_icons),
|
||||
";", tabdata.selected_pkg, "]",
|
||||
|
||||
"button[0.4,5.8;6.3,0.9;btn_contentdb;", contentdb_label, "]"
|
||||
}
|
||||
|
||||
if subtab_key == "txps" then
|
||||
local priority_tooltip = fgettext("Enabled texture packs are applied in priority order.") ..
|
||||
"\n" .. fgettext("If two packs provide the same texture, the one listed first wins.")
|
||||
table.insert_all(retval, {
|
||||
"image[6.2,0.4;0.5,0.5;", core.formspec_escape(defaulttexturedir .. "settings_info.png"), "]",
|
||||
"tooltip[6.2,0.4;0.5,0.5;", priority_tooltip, "]",
|
||||
})
|
||||
end
|
||||
|
||||
local selected_pkg
|
||||
if filterlist.size(packages) >= tabdata.selected_pkg then
|
||||
selected_pkg = packages:get_list()[tabdata.selected_pkg]
|
||||
@@ -157,13 +201,27 @@ local function get_formspec(tabview, name, tabdata)
|
||||
|
||||
if selected_pkg.enabled then
|
||||
table.insert_all(retval, {
|
||||
"button[7.1,4.7;8,0.9;btn_mod_mgr_disable_txp;",
|
||||
"button[7.1,4.7;4,0.9;btn_mod_mgr_disable_txp;",
|
||||
fgettext("Disable Texture Pack"), "]"
|
||||
})
|
||||
|
||||
local enabled_count = #pkgmgr.get_enabled_texture_packs()
|
||||
if selected_pkg.order > 1 then
|
||||
table.insert_all(retval, {
|
||||
"button[11.1,4.7;2,0.9;btn_mod_mgr_txp_move_up;",
|
||||
fgettext("Move Up"), "]"
|
||||
})
|
||||
end
|
||||
if selected_pkg.order < enabled_count then
|
||||
table.insert_all(retval, {
|
||||
"button[13.1,4.7;2,0.9;btn_mod_mgr_txp_move_down;",
|
||||
fgettext("Move Down"), "]"
|
||||
})
|
||||
end
|
||||
else
|
||||
table.insert_all(retval, {
|
||||
"button[7.1,4.7;8,0.9;btn_mod_mgr_use_txp;",
|
||||
fgettext("Use Texture Pack"), "]"
|
||||
fgettext("Enable Texture Pack"), "]"
|
||||
})
|
||||
end
|
||||
end
|
||||
@@ -193,13 +251,10 @@ local function get_formspec(tabview, name, tabdata)
|
||||
return table.concat(retval)
|
||||
end
|
||||
|
||||
local function handle_doubleclick(pkg)
|
||||
local function handle_doubleclick(pkg, tabdata)
|
||||
if pkg.type == "txp" then
|
||||
if core.settings:get("texture_path") == pkg.path then
|
||||
core.settings:set("texture_path", "")
|
||||
else
|
||||
core.settings:set("texture_path", pkg.path)
|
||||
end
|
||||
pkgmgr.set_texture_pack_enabled(pkg.path, not pkg.enabled)
|
||||
tabdata.selected_path = pkg.path
|
||||
packages = nil
|
||||
pkgmgr.reload_texture_packs()
|
||||
|
||||
@@ -210,11 +265,17 @@ end
|
||||
|
||||
local function handle_buttons(tabview, fields, tabname, tabdata)
|
||||
|
||||
if fields.content_subtab then
|
||||
tabdata.subtab = tonumber(fields.content_subtab)
|
||||
tabdata.selected_pkg = 1
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.pkglist then
|
||||
local event = core.explode_table_event(fields.pkglist)
|
||||
tabdata.selected_pkg = event.row
|
||||
if event.type == "DCL" then
|
||||
handle_doubleclick(packages:get_list()[tabdata.selected_pkg])
|
||||
handle_doubleclick(packages:get_list()[tabdata.selected_pkg], tabdata)
|
||||
end
|
||||
return true
|
||||
end
|
||||
@@ -259,12 +320,9 @@ local function handle_buttons(tabview, fields, tabname, tabdata)
|
||||
end
|
||||
|
||||
if fields.btn_mod_mgr_use_txp or fields.btn_mod_mgr_disable_txp then
|
||||
local txp_path = ""
|
||||
if fields.btn_mod_mgr_use_txp then
|
||||
txp_path = packages:get_list()[tabdata.selected_pkg].path
|
||||
end
|
||||
|
||||
core.settings:set("texture_path", txp_path)
|
||||
local pkg = packages:get_list()[tabdata.selected_pkg]
|
||||
pkgmgr.set_texture_pack_enabled(pkg.path, fields.btn_mod_mgr_use_txp ~= nil)
|
||||
tabdata.selected_path = pkg.path
|
||||
packages = nil
|
||||
pkgmgr.reload_texture_packs()
|
||||
|
||||
@@ -273,6 +331,16 @@ local function handle_buttons(tabview, fields, tabname, tabdata)
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.btn_mod_mgr_txp_move_up or fields.btn_mod_mgr_txp_move_down then
|
||||
local pkg = packages:get_list()[tabdata.selected_pkg]
|
||||
local delta = fields.btn_mod_mgr_txp_move_up and -1 or 1
|
||||
pkgmgr.move_texture_pack(pkg.path, delta)
|
||||
tabdata.selected_path = pkg.path
|
||||
packages = nil
|
||||
pkgmgr.reload_texture_packs()
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
@@ -2503,8 +2503,11 @@ serverlist_file (Serverlist file) [client] string favoriteservers.json
|
||||
|
||||
[*Hide: Temporary Settings] [common]
|
||||
|
||||
# Path to texture directory. All textures are first searched from here.
|
||||
texture_path (Texture path) path
|
||||
# Ordered list of texture pack paths, separated by ";" on Windows
|
||||
# and ":" on other platforms.
|
||||
# Earlier entries take priority: if multiple packs provide the same
|
||||
# texture, the first one wins.
|
||||
texture_path (Texture path) string
|
||||
|
||||
# Enables minimap.
|
||||
enable_minimap (Minimap) bool true
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "client/particles.h"
|
||||
#include "client/renderingengine.h"
|
||||
#include "client/sound.h"
|
||||
#include "client/texturepaths.h"
|
||||
#include "client/texturesource.h"
|
||||
#include "camera.h"
|
||||
#include "filesys.h"
|
||||
@@ -1915,7 +1914,8 @@ void Client::afterContentReceived()
|
||||
m_rendering_engine->draw_load_screen(wstrgettext("Initializing nodes..."),
|
||||
guienv, m_tsrc, 0, 70);
|
||||
m_nodedef->updateAliases(m_itemdef);
|
||||
for (const auto &path : getTextureDirs()) {
|
||||
// Apply texture overrides from texturepack/override.txt
|
||||
for (const std::string &path : getTexturePathsReversed()) {
|
||||
TextureOverrideSource override_source(path + DIR_DELIM + "override.txt");
|
||||
m_nodedef->applyTextureOverrides(override_source.getNodeTileOverrides());
|
||||
m_itemdef->applyTextureOverrides(override_source.getItemTextureOverrides());
|
||||
|
||||
@@ -99,7 +99,8 @@ std::vector<std::string> getTextureDirs()
|
||||
{
|
||||
std::vector<std::string> ret = g_texturedirs_cache.get();
|
||||
if (ret.empty()) {
|
||||
ret = fs::GetRecursiveDirs(g_settings->get("texture_path"));
|
||||
for (const std::string &pack_path : str_split(g_settings->get("texture_path"), PATH_DELIM[0]))
|
||||
fs::GetRecursiveDirs(ret, pack_path);
|
||||
g_texturedirs_cache.set(ret);
|
||||
}
|
||||
return ret;
|
||||
|
||||
+1
-2
@@ -538,8 +538,7 @@ void Server::init()
|
||||
m_nodedef->updateAliases(m_itemdef);
|
||||
|
||||
// Apply texture overrides from texturepack/override.txt
|
||||
std::vector<std::string> paths;
|
||||
fs::GetRecursiveDirs(paths, g_settings->get("texture_path"));
|
||||
std::vector<std::string> paths = getTexturePathsReversed();
|
||||
fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
|
||||
for (const std::string &path : paths) {
|
||||
TextureOverrideSource override_source(path + DIR_DELIM + "override.txt");
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "log.h"
|
||||
#include "filesys.h"
|
||||
#include "settings.h"
|
||||
#include "util/string.h"
|
||||
#include <map>
|
||||
|
||||
@@ -133,3 +134,13 @@ std::vector<TextureOverride> TextureOverrideSource::getNodeTileOverrides() const
|
||||
|
||||
return found_overrides;
|
||||
}
|
||||
|
||||
std::vector<std::string> getTexturePathsReversed()
|
||||
{
|
||||
std::vector<std::string> paths;
|
||||
// reversed: applyTextureOverrides() so highest priority gets applied last, aka overrides others
|
||||
std::vector<std::string> pack_paths = str_split(g_settings->get("texture_path"), PATH_DELIM[0]);
|
||||
for (auto it = pack_paths.rbegin(); it != pack_paths.rend(); ++it)
|
||||
fs::GetRecursiveDirs(paths, *it);
|
||||
return paths;
|
||||
}
|
||||
|
||||
@@ -74,3 +74,6 @@ public:
|
||||
private:
|
||||
std::vector<TextureOverride> m_overrides;
|
||||
};
|
||||
|
||||
//! Texture pack dirs from the texture_path setting, lowest priority pack first
|
||||
std::vector<std::string> getTexturePathsReversed();
|
||||
|
||||
Reference in New Issue
Block a user