Add a filesystem module
This currently contains have_file, read_file, canonical_path, get_image_size, and new functions that work with binary_path files.
This commit is contained in:
parent
bf746a0207
commit
45cb8dc428
10 changed files with 92 additions and 37 deletions
15
data/lua/core/filesystem.lua
Normal file
15
data/lua/core/filesystem.lua
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
--[========[File Handling]========]
|
||||
print("Loading filesystem module...")
|
||||
|
||||
filesystem.asset_type = {
|
||||
IMAGE = 'images',
|
||||
SOUND = 'sounds',
|
||||
MUSIC = 'music',
|
||||
MAP = 'maps',
|
||||
}
|
||||
|
||||
wesnoth.have_file = wesnoth.deprecate_api('wesnoth.have_file', 'filesystem.have_file', 1, nil, filesystem.have_file)
|
||||
wesnoth.read_file = wesnoth.deprecate_api('wesnoth.read_file', 'filesystem.read_file', 1, nil, filesystem.read_file)
|
||||
wesnoth.canonical_path = wesnoth.deprecate_api('wesnoth.canonical_path', 'filesystem.canonical_path', 1, nil, filesystem.canonical_path)
|
||||
wesnoth.get_image_size = wesnoth.deprecate_api('wesnoth.get_image_size', 'filesystem.image_size', 1, nil, filesystem.image_size)
|
|
@ -15,22 +15,22 @@ local mt = {
|
|||
local empty_pkg = setmetatable({}, mt)
|
||||
|
||||
local function resolve_package(pkg_name)
|
||||
pkg_name = wesnoth.canonical_path(pkg_name)
|
||||
pkg_name = filesystem.canonical_path(pkg_name)
|
||||
if pkg_name[#pkg_name] == '/' then
|
||||
pkg_name = pkg_name:sub(1, -2)
|
||||
end
|
||||
if wesnoth.have_file(pkg_name) then return pkg_name end
|
||||
if filesystem.have_file(pkg_name) then return pkg_name end
|
||||
if pkg_name:sub(-4) ~= ".lua" then
|
||||
local test = resolve_package(pkg_name .. ".lua")
|
||||
if test then return test end
|
||||
end
|
||||
if pkg_name:sub(1, 4) ~= "lua/" then
|
||||
if wesnoth.have_file("lua/" .. pkg_name) then
|
||||
if filesystem.have_file("lua/" .. pkg_name) then
|
||||
return "lua/" .. pkg_name
|
||||
end
|
||||
end
|
||||
if pkg_name:sub(1, 2) ~= "./" then
|
||||
if wesnoth.have_file("./" .. pkg_name) then
|
||||
if filesystem.have_file("./" .. pkg_name) then
|
||||
return "./" .. pkg_name
|
||||
end
|
||||
end
|
||||
|
@ -49,12 +49,12 @@ function wesnoth.require(pkg_name)
|
|||
end
|
||||
|
||||
-- Next, if it's a single file, load the package with dofile
|
||||
if wesnoth.have_file(loaded_name, true) then
|
||||
if filesystem.have_file(loaded_name, true) then
|
||||
local pkg = wesnoth.dofile(loaded_name)
|
||||
wesnoth.package[loaded_name] = pkg or empty_pkg
|
||||
return pkg
|
||||
else -- If it's a directory, load all the files therein
|
||||
local files = wesnoth.read_file(loaded_name)
|
||||
local files = filesystem.read_file(loaded_name)
|
||||
local pkg = {}
|
||||
for i = files.ndirs + 1, #files do
|
||||
if files[i]:sub(-4) == ".lua" then
|
||||
|
|
|
@ -1553,9 +1553,9 @@ std::string get_short_wml_path(const std::string& filename)
|
|||
return filename;
|
||||
}
|
||||
|
||||
std::string get_independent_image_path(const std::string& filename)
|
||||
std::string get_independent_binary_file_path(const std::string& type, const std::string& filename)
|
||||
{
|
||||
bfs::path full_path(get_binary_file_location("images", filename));
|
||||
bfs::path full_path(get_binary_file_location(type, filename));
|
||||
|
||||
if(full_path.empty()) {
|
||||
return full_path.generic_string();
|
||||
|
|
|
@ -435,13 +435,13 @@ std::string get_wml_location(const std::string &filename,
|
|||
std::string get_short_wml_path(const std::string &filename);
|
||||
|
||||
/**
|
||||
* Returns an image path to @a filename for binary path-independent use in saved games.
|
||||
* Returns an asset path to @a filename for binary path-independent use in saved games.
|
||||
*
|
||||
* Example:
|
||||
* units/konrad-fighter.png ->
|
||||
* images, units/konrad-fighter.png ->
|
||||
* data/campaigns/Heir_To_The_Throne/images/units/konrad-fighter.png
|
||||
*/
|
||||
std::string get_independent_image_path(const std::string &filename);
|
||||
std::string get_independent_binary_file_path(const std::string& type, const std::string &filename);
|
||||
|
||||
/**
|
||||
* Returns the appropriate invocation for a Wesnoth-related binary, assuming
|
||||
|
|
|
@ -204,7 +204,7 @@ void game_load::display_savegame_internal(const savegame::save_info& game)
|
|||
// work, we fallback on unknown-unit.png.
|
||||
std::string leader_image = leader["leader_image"].str();
|
||||
if(!::image::exists(leader_image)) {
|
||||
leader_image = filesystem::get_independent_image_path(leader_image);
|
||||
leader_image = filesystem::get_independent_binary_file_path("images", leader_image);
|
||||
|
||||
// The leader TC modifier isn't appending if the independent image path can't
|
||||
// be resolved during save_index entry creation, so we need to add it here.
|
||||
|
|
|
@ -493,11 +493,11 @@ void extract_summary_from_config(config& cfg_save, config& cfg_summary)
|
|||
|
||||
// We need a binary path-independent path to the leader image here so it can be displayed
|
||||
// for campaign-specific units even when the campaign isn't loaded yet.
|
||||
std::string leader_image_path = filesystem::get_independent_image_path(leader_image);
|
||||
std::string leader_image_path = filesystem::get_independent_binary_file_path("images", leader_image);
|
||||
|
||||
// If the image path was found, we append the leader TC modifier. If it's not (such as in
|
||||
// the case where the binary path hasn't been loaded yet, perhaps due to save_index being
|
||||
// deleted), the unaltered image path is used and will be parsed by get_independent_image_path
|
||||
// deleted), the unaltered image path is used and will be parsed by get_independent_binary_file_path
|
||||
// at runtime.
|
||||
if(!leader_image_path.empty()) {
|
||||
leader_image_path += leader_image_tc_modifier;
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "log.hpp"
|
||||
#include "scripting/lua_common.hpp" // for chat_message, luaW_pcall
|
||||
#include "scripting/push_check.hpp"
|
||||
#include "picture.hpp"
|
||||
#include "sdl/surface.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
|
@ -35,6 +37,48 @@ static lg::log_domain log_scripting_lua("scripting/lua");
|
|||
#define WRN_LUA LOG_STREAM(warn, log_scripting_lua)
|
||||
#define ERR_LUA LOG_STREAM(err, log_scripting_lua)
|
||||
|
||||
/**
|
||||
* Gets the dimension of an image.
|
||||
* - Arg 1: string.
|
||||
* - Ret 1: width.
|
||||
* - Ret 2: height.
|
||||
*/
|
||||
static int intf_get_image_size(lua_State *L)
|
||||
{
|
||||
char const *m = luaL_checkstring(L, 1);
|
||||
image::locator img(m);
|
||||
if(!img.file_exists()) return 0;
|
||||
surface s = get_image(img);
|
||||
lua_pushinteger(L, s->w);
|
||||
lua_pushinteger(L, s->h);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if an asset with the given path can be found in the binary paths.
|
||||
* - Arg 1: asset type (generally one of images, sounds, music, maps)
|
||||
* - Arg 2: relative path
|
||||
*/
|
||||
static int intf_have_asset(lua_State* L)
|
||||
{
|
||||
std::string type = luaL_checkstring(L, 1), name = luaL_checkstring(L, 2);
|
||||
lua_pushboolean(L, !filesystem::get_binary_file_location(type, name).empty());
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an asset path relative to binary paths, resolves to an absolute
|
||||
* asset path starting from data/
|
||||
* - Arg 1: asset type
|
||||
* - Arg 2: relative path
|
||||
*/
|
||||
static int intf_resolve_asset(lua_State* L)
|
||||
{
|
||||
std::string type = luaL_checkstring(L, 1), name = luaL_checkstring(L, 2);
|
||||
lua_push(L, filesystem::get_independent_binary_file_path(type, name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
namespace lua_fileops {
|
||||
static std::string get_calling_file(lua_State* L)
|
||||
{
|
||||
|
@ -275,4 +319,19 @@ int load_file(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int luaW_open(lua_State* L)
|
||||
{
|
||||
static luaL_Reg const callbacks[] {
|
||||
{ "have_file", &lua_fileops::intf_have_file },
|
||||
{ "read_file", &lua_fileops::intf_read_file },
|
||||
{ "canonical_path", &lua_fileops::intf_canonical_path },
|
||||
{ "image_size", &intf_get_image_size },
|
||||
{ "have_asset", &intf_have_asset },
|
||||
{ "resolve_asset", &intf_resolve_asset },
|
||||
};
|
||||
lua_newtable(L);
|
||||
luaL_setfuncs(L, callbacks, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // end namespace lua_fileops
|
||||
|
|
|
@ -26,5 +26,6 @@ int intf_have_file(lua_State*);
|
|||
int intf_read_file(lua_State*);
|
||||
int intf_canonical_path(lua_State*);
|
||||
int load_file(lua_State*);
|
||||
int luaW_open(lua_State *L);
|
||||
|
||||
} // end namespace lua_fileops
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
#include "scripting/push_check.hpp"
|
||||
|
||||
#include "game_version.hpp" // for do_version_check, etc
|
||||
#include "picture.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include "utils/name_generator.hpp"
|
||||
|
@ -432,22 +431,6 @@ static int intf_deprecated_message(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the dimension of an image.
|
||||
* - Arg 1: string.
|
||||
* - Ret 1: width.
|
||||
* - Ret 2: height.
|
||||
*/
|
||||
static int intf_get_image_size(lua_State *L) {
|
||||
char const *m = luaL_checkstring(L, 1);
|
||||
image::locator img(m);
|
||||
if(!img.file_exists()) return 0;
|
||||
surface s = get_image(img);
|
||||
lua_pushinteger(L, s->w);
|
||||
lua_pushinteger(L, s->h);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time stamp, exactly as [set_variable] time=stamp does.
|
||||
* - Ret 1: integer
|
||||
|
@ -507,6 +490,7 @@ lua_kernel_base::lua_kernel_base()
|
|||
{ "mathx", lua_mathx::luaW_open },
|
||||
{ "wml", lua_wml::luaW_open },
|
||||
{ "gui", lua_gui2::luaW_open },
|
||||
{ "filesystem", lua_fileops::luaW_open },
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
for (luaL_Reg const *lib = safe_libs; lib->func; ++lib)
|
||||
|
@ -546,9 +530,6 @@ lua_kernel_base::lua_kernel_base()
|
|||
|
||||
static luaL_Reg const callbacks[] {
|
||||
{ "deprecated_message", &intf_deprecated_message },
|
||||
{ "have_file", &lua_fileops::intf_have_file },
|
||||
{ "read_file", &lua_fileops::intf_read_file },
|
||||
{ "canonical_path", &lua_fileops::intf_canonical_path },
|
||||
{ "textdomain", &lua_common::intf_textdomain },
|
||||
{ "dofile", &dispatch<&lua_kernel_base::intf_dofile> },
|
||||
{ "require", &dispatch<&lua_kernel_base::intf_require> },
|
||||
|
@ -557,7 +538,6 @@ lua_kernel_base::lua_kernel_base()
|
|||
{ "eval_formula", &lua_formula_bridge::intf_eval_formula},
|
||||
{ "name_generator", &intf_name_generator },
|
||||
{ "log", &intf_log },
|
||||
{ "get_image_size", &intf_get_image_size },
|
||||
{ "ms_since_init", &intf_ms_since_init },
|
||||
{ "get_language", &intf_get_language },
|
||||
{ "version", &intf_make_version },
|
||||
|
|
|
@ -157,7 +157,7 @@ BOOST_AUTO_TEST_CASE( test_fs_binary_path )
|
|||
BOOST_CHECK_EQUAL( get_binary_file_location("sounds", "explosion.ogg"),
|
||||
gamedata + "/data/core/sounds/explosion.ogg" );
|
||||
|
||||
BOOST_CHECK_EQUAL( get_independent_image_path("wesnoth-icon.png"),
|
||||
BOOST_CHECK_EQUAL( get_independent_binary_file_path("images", "wesnoth-icon.png"),
|
||||
"data/core/images/wesnoth-icon.png" );
|
||||
|
||||
// Inexistent paths are resolved empty.
|
||||
|
@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE( test_fs_binary_path )
|
|||
BOOST_CHECK( get_binary_file_location("images", "bunnies_and_ponies_and_rainbows_oh_em_gee.psd").empty() );
|
||||
BOOST_CHECK( get_binary_file_location("music", "this_track_does_not_exist.aiff").empty() );
|
||||
BOOST_CHECK( get_binary_file_location("sounds", "rude_noises.aiff").empty() );
|
||||
BOOST_CHECK( get_independent_image_path("dopefish.txt").empty() );
|
||||
BOOST_CHECK( get_independent_binary_file_path("images", "dopefish.txt").empty() );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_fs_wml_path )
|
||||
|
|
Loading…
Add table
Reference in a new issue