Fix resource manager not properly accounting for overrides

This commit is contained in:
2015-09-25 20:14:55 -04:00
parent f66c1cb36f
commit 67cf73e593
6 changed files with 47 additions and 24 deletions

View File

@@ -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);
}
}

View 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";
}

View File

@@ -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;