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

@@ -118,6 +118,7 @@
<ClCompile Include="..\..\tools\menu_accel.win.cpp" />
<ClCompile Include="..\..\tools\porting.cpp" />
<ClCompile Include="..\..\tools\prefs.win.cpp" />
<ClCompile Include="..\..\tools\resmgr\restypes.cpp" />
<ClCompile Include="..\..\tools\soundtool.cpp" />
<ClCompile Include="..\..\tools\specials_parse.cpp" />
<ClCompile Include="..\..\tools\tarball.cpp" />

View File

@@ -333,6 +333,9 @@
<ClCompile Include="..\..\tools\porting.cpp">
<Filter>Tools\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\tools\resmgr\restypes.cpp">
<Filter>Tools\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\tools\soundtool.cpp">
<Filter>Tools\Source Files</Filter>
</ClCompile>

View File

@@ -137,6 +137,7 @@
91870F84190C90980081C150 /* scenedit.xib in Resources */ = {isa = PBXBuildFile; fileRef = 914CA49F190C4E9200B6ADD1 /* scenedit.xib */; };
919145FC18E3AB1B005CF3A4 /* boe.appleevents.mm in Sources */ = {isa = PBXBuildFile; fileRef = 919145FB18E3A32F005CF3A4 /* boe.appleevents.mm */; };
9192C12018F2745C0088A580 /* game.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9192C11E18F271920088A580 /* game.xib */; };
91960ED41BB6157A008AF8F4 /* restypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91960ED31BB613E5008AF8F4 /* restypes.cpp */; };
919CC2481B3772F300273FDA /* creatlist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91AC620A0FA2853700EEAE67 /* creatlist.cpp */; };
919CC2491B3772FB00273FDA /* creature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 914698FE1A747C4500F20F5E /* creature.cpp */; };
919CC24B1B37730300273FDA /* item.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91279D3D0F9D1D6A007B0D52 /* item.cpp */; };
@@ -657,6 +658,7 @@
9191460018E63D8E005CF3A4 /* scrollbar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scrollbar.cpp; sourceTree = "<group>"; };
9191460118E6591F005CF3A4 /* boe.menus.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = boe.menus.hpp; sourceTree = "<group>"; };
9192C11E18F271920088A580 /* game.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = game.xib; path = ../rsrc/menus/game.xib; sourceTree = "<group>"; };
91960ED31BB613E5008AF8F4 /* restypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = restypes.cpp; sourceTree = "<group>"; };
919DDBFA19006CC9003E7FED /* libboost_filesystem.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libboost_filesystem.dylib; path = /usr/local/lib/libboost_filesystem.dylib; sourceTree = "<absolute>"; };
919DDBFB19006CC9003E7FED /* libboost_system.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libboost_system.dylib; path = /usr/local/lib/libboost_system.dylib; sourceTree = "<absolute>"; };
919DDC091900750D003E7FED /* freetype.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = freetype.framework; path = ../../../../../../Library/Frameworks/freetype.framework; sourceTree = "<group>"; };
@@ -999,6 +1001,7 @@
children = (
912DFE8918E24B4C00B00D75 /* resmgr.hpp */,
912DFE8A18E24B4C00B00D75 /* restypes.hpp */,
91960ED31BB613E5008AF8F4 /* restypes.cpp */,
);
path = resmgr;
sourceTree = "<group>";
@@ -1788,6 +1791,7 @@
919CC27D1B37743700273FDA /* tarball.cpp in Sources */,
919CC27E1B37743B00273FDA /* undo.cpp in Sources */,
919CC27F1B37744000273FDA /* winutil.mac.mm in Sources */,
91960ED41BB6157A008AF8F4 /* restypes.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

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;