Fix resource manager not properly accounting for overrides
This commit is contained in:
@@ -23,7 +23,9 @@
|
||||
/// Resources include sounds, images, fonts, and cursors.
|
||||
///
|
||||
/// To implement a new resource type, all you have to do is specialize
|
||||
/// @a ResMgr::resLoader::operator() for the desired resource type.
|
||||
/// @a ResMgr::resLoader::operator() and declare @a ResMgr::resLoader::file_ext
|
||||
/// for the desired resource type. The operator() receives the
|
||||
/// full file path with the extension already applied.
|
||||
namespace ResMgr {
|
||||
namespace fs = boost::filesystem;
|
||||
/// The signature of an ID map function.
|
||||
@@ -56,12 +58,13 @@ namespace ResMgr {
|
||||
/// Convert a relative path to an absolute path by checking the current search path stack.
|
||||
/// @param path The path to resolve.
|
||||
/// @return The resolved absolute path, or the relative path unchanged if resolution failed.
|
||||
static fs::path rel2abs(fs::path path) {
|
||||
static fs::path find(std::string name, std::string ext) {
|
||||
fs::path path = name + "." + ext;
|
||||
std::stack<fs::path> tmpPaths = resPaths();
|
||||
while(!tmpPaths.empty()) {
|
||||
fs::path thisPath = tmpPaths.top()/path;
|
||||
if(fs::exists(thisPath)) {
|
||||
pathFound()[path] = tmpPaths.top();
|
||||
pathFound()[name] = thisPath;
|
||||
return thisPath;
|
||||
}
|
||||
tmpPaths.pop();
|
||||
@@ -78,10 +81,12 @@ namespace ResMgr {
|
||||
/// @tparam type The type of resource.
|
||||
template<typename type> struct resLoader {
|
||||
/// Load a resource of this type from the given file.
|
||||
/// @param fname The path to the resource; this will be an absolute path unless resolution failed.
|
||||
/// @param fpath The path to the resource; this will be an absolute path unless resolution failed.
|
||||
/// @return A pointer to the loaded resource. The resource manager takes responsibility for freeing it,
|
||||
/// so it must be a pointer allocated with `new` rather than `new[]`.
|
||||
type* operator() (std::string fname);
|
||||
type* operator() (fs::path path);
|
||||
/// The standard file extension for this resource type;
|
||||
static const std::string file_ext;
|
||||
};
|
||||
|
||||
/// Thrown if an error occurs while loading a resource.
|
||||
@@ -131,19 +136,19 @@ namespace ResMgr {
|
||||
template<typename type> std::shared_ptr<type> get(std::string name) {
|
||||
if(resPool<type>::resources().find(name) != resPool<type>::resources().end()) {
|
||||
if(resPool<type>::pathFound().find(name) != resPool<type>::pathFound().end()) {
|
||||
resLoader<type> load;
|
||||
std::string curPath = resPool<type>::pathFound()[name].string();
|
||||
std::string checkPath = resPool<type>::rel2abs(name).string();
|
||||
checkPath = checkPath.substr(0,curPath.length());
|
||||
std::string checkPath = resPool<type>::find(name, load.file_ext).string();
|
||||
if(checkPath != curPath) {
|
||||
free<type>(name);
|
||||
return get<type>(name);
|
||||
type* tmp = load(checkPath);
|
||||
return resPool<type>::resources()[name] = std::shared_ptr<type>(tmp);
|
||||
}
|
||||
}
|
||||
return resPool<type>::resources()[name];
|
||||
} else {
|
||||
type* tmp;
|
||||
resLoader<type> load;
|
||||
tmp = load(name);
|
||||
type* tmp = load(resPool<type>::find(name, load.file_ext));
|
||||
return resPool<type>::resources()[name] = std::shared_ptr<type>(tmp);
|
||||
}
|
||||
}
|
||||
|
17
src/tools/resmgr/restypes.cpp
Normal file
17
src/tools/resmgr/restypes.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// restypes.cpp
|
||||
// BoE
|
||||
//
|
||||
// Created by Celtic Minstrel on 15-09-25.
|
||||
//
|
||||
//
|
||||
|
||||
#include "restypes.hpp"
|
||||
|
||||
namespace ResMgr {
|
||||
template<> const std::string resLoader<ImageRsrc>::file_ext = "png";
|
||||
template<> const std::string resLoader<CursorRsrc>::file_ext = "gif";
|
||||
template<> const std::string resLoader<FontRsrc>::file_ext = "ttf";
|
||||
template<> const std::string resLoader<StringRsrc>::file_ext = "txt";
|
||||
template<> const std::string resLoader<SoundRsrc>::file_ext = "wav";
|
||||
}
|
@@ -33,8 +33,7 @@ extern std::ostream& std_fmterr(std::ostream& out);
|
||||
|
||||
namespace ResMgr {
|
||||
/// Load an image from a PNG file.
|
||||
template<> inline ImageRsrc* resLoader<ImageRsrc>::operator() (std::string fname) {
|
||||
fs::path fpath = resPool<ImageRsrc>::rel2abs(fname + ".png");
|
||||
template<> inline ImageRsrc* resLoader<ImageRsrc>::operator() (fs::path fpath) {
|
||||
ImageRsrc* img = new ImageRsrc();
|
||||
if(img->loadFromFile(fpath.string())) return img;
|
||||
delete img;
|
||||
@@ -44,10 +43,9 @@ namespace ResMgr {
|
||||
/// Load a cursor from a GIF file.
|
||||
/// The cursor's hotspot location is stored in a GIF comment, with the following syntax (case-sensitive):
|
||||
/// "Hotspot(x,y)"
|
||||
template<> inline CursorRsrc* resLoader<CursorRsrc>::operator() (std::string fname) {
|
||||
fs::path fpath = resPool<CursorRsrc>::rel2abs(fname + ".gif");
|
||||
template<> inline CursorRsrc* resLoader<CursorRsrc>::operator() (fs::path fpath) {
|
||||
if(!fs::exists(fpath))
|
||||
throw xResMgrErr("Failed to load GIF cursor: " + fname);
|
||||
throw xResMgrErr("Failed to load GIF cursor: " + fpath.string());
|
||||
int x = 0, y = 0, f_sz;
|
||||
std::ifstream fin(fpath.c_str(), std::ios::binary);
|
||||
fin.seekg(0, std::ios::end);
|
||||
@@ -83,19 +81,16 @@ namespace ResMgr {
|
||||
}
|
||||
}
|
||||
if(!found_hotspot)
|
||||
std::cerr << "Cursor hotspot missing: " << fname << std::endl;
|
||||
std::cerr << "Cursor hotspot missing: " << fpath.string() << std::endl;
|
||||
// TODO: Handle errors?
|
||||
CursorRsrc* cur = new Cursor(fpath.string(),x,y);
|
||||
return cur;
|
||||
}
|
||||
|
||||
/// Load a font from a TTF file.
|
||||
template<> inline FontRsrc* resLoader<FontRsrc>::operator() (std::string fname) {
|
||||
fs::path fpath = resPool<FontRsrc>::rel2abs(fname + ".ttf");
|
||||
template<> inline FontRsrc* resLoader<FontRsrc>::operator() (fs::path fpath) {
|
||||
FontRsrc* theFont = new FontRsrc;
|
||||
if(theFont->loadFromFile(fpath.string())) return theFont;
|
||||
fpath = resPool<FontRsrc>::rel2abs(fname + ".otf");
|
||||
if(theFont->loadFromFile(fpath.string())) return theFont;
|
||||
delete theFont;
|
||||
throw xResMgrErr("Failed to find font: " + fpath.string());
|
||||
}
|
||||
@@ -103,8 +98,7 @@ namespace ResMgr {
|
||||
/// Load a list of strings from a TXT file.
|
||||
/// Each line in the file becomes one string in the resulting list.
|
||||
/// (Empty lines are included too.)
|
||||
template<> inline StringRsrc* resLoader<StringRsrc>::operator() (std::string fname) {
|
||||
fs::path fpath = resPool<StringRsrc>::rel2abs(fname + ".txt");
|
||||
template<> inline StringRsrc* resLoader<StringRsrc>::operator() (fs::path fpath) {
|
||||
std::ifstream fin(fpath.c_str());
|
||||
if(fin.fail()) {
|
||||
std::cerr << std_fmterr << ": Error opening file";
|
||||
@@ -120,8 +114,7 @@ namespace ResMgr {
|
||||
}
|
||||
|
||||
/// Load a sound from a WAV file.
|
||||
template<> inline SoundRsrc* resLoader<SoundRsrc>::operator() (std::string fname) {
|
||||
fs::path fpath = resPool<SoundRsrc>::rel2abs(fname + ".wav");
|
||||
template<> inline SoundRsrc* resLoader<SoundRsrc>::operator() (fs::path fpath) {
|
||||
SoundRsrc* snd = new SoundRsrc;
|
||||
if(snd->loadFromFile(fpath.string())) return snd;
|
||||
delete snd;
|
||||
|
Reference in New Issue
Block a user