diff --git a/src/BoE.vsproj/Common/Common.vcxproj b/src/BoE.vsproj/Common/Common.vcxproj
index a59c5fce..69b15264 100644
--- a/src/BoE.vsproj/Common/Common.vcxproj
+++ b/src/BoE.vsproj/Common/Common.vcxproj
@@ -118,6 +118,7 @@
+
diff --git a/src/BoE.vsproj/Common/Common.vcxproj.filters b/src/BoE.vsproj/Common/Common.vcxproj.filters
index ee2bc911..f0a9e59b 100644
--- a/src/BoE.vsproj/Common/Common.vcxproj.filters
+++ b/src/BoE.vsproj/Common/Common.vcxproj.filters
@@ -333,6 +333,9 @@
Tools\Source Files
+
+ Tools\Source Files
+
Tools\Source Files
diff --git a/src/BoE.xcodeproj/project.pbxproj b/src/BoE.xcodeproj/project.pbxproj
index bf78c7d5..998a9f5e 100755
--- a/src/BoE.xcodeproj/project.pbxproj
+++ b/src/BoE.xcodeproj/project.pbxproj
@@ -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 = ""; };
9191460118E6591F005CF3A4 /* boe.menus.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = boe.menus.hpp; sourceTree = ""; };
9192C11E18F271920088A580 /* game.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = game.xib; path = ../rsrc/menus/game.xib; sourceTree = ""; };
+ 91960ED31BB613E5008AF8F4 /* restypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = restypes.cpp; sourceTree = ""; };
919DDBFA19006CC9003E7FED /* libboost_filesystem.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libboost_filesystem.dylib; path = /usr/local/lib/libboost_filesystem.dylib; sourceTree = ""; };
919DDBFB19006CC9003E7FED /* libboost_system.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libboost_system.dylib; path = /usr/local/lib/libboost_system.dylib; sourceTree = ""; };
919DDC091900750D003E7FED /* freetype.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = freetype.framework; path = ../../../../../../Library/Frameworks/freetype.framework; sourceTree = ""; };
@@ -999,6 +1001,7 @@
children = (
912DFE8918E24B4C00B00D75 /* resmgr.hpp */,
912DFE8A18E24B4C00B00D75 /* restypes.hpp */,
+ 91960ED31BB613E5008AF8F4 /* restypes.cpp */,
);
path = resmgr;
sourceTree = "";
@@ -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;
};
diff --git a/src/tools/resmgr/resmgr.hpp b/src/tools/resmgr/resmgr.hpp
index 73e20dcb..ebd4c63b 100644
--- a/src/tools/resmgr/resmgr.hpp
+++ b/src/tools/resmgr/resmgr.hpp
@@ -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 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 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 std::shared_ptr get(std::string name) {
if(resPool::resources().find(name) != resPool::resources().end()) {
if(resPool::pathFound().find(name) != resPool::pathFound().end()) {
+ resLoader load;
std::string curPath = resPool::pathFound()[name].string();
- std::string checkPath = resPool::rel2abs(name).string();
- checkPath = checkPath.substr(0,curPath.length());
+ std::string checkPath = resPool::find(name, load.file_ext).string();
if(checkPath != curPath) {
free(name);
- return get(name);
+ type* tmp = load(checkPath);
+ return resPool::resources()[name] = std::shared_ptr(tmp);
}
}
return resPool::resources()[name];
} else {
- type* tmp;
resLoader load;
- tmp = load(name);
+ type* tmp = load(resPool::find(name, load.file_ext));
return resPool::resources()[name] = std::shared_ptr(tmp);
}
}
diff --git a/src/tools/resmgr/restypes.cpp b/src/tools/resmgr/restypes.cpp
new file mode 100644
index 00000000..f984a35e
--- /dev/null
+++ b/src/tools/resmgr/restypes.cpp
@@ -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::file_ext = "png";
+ template<> const std::string resLoader::file_ext = "gif";
+ template<> const std::string resLoader::file_ext = "ttf";
+ template<> const std::string resLoader::file_ext = "txt";
+ template<> const std::string resLoader::file_ext = "wav";
+}
diff --git a/src/tools/resmgr/restypes.hpp b/src/tools/resmgr/restypes.hpp
index 8ad44349..7e413269 100644
--- a/src/tools/resmgr/restypes.hpp
+++ b/src/tools/resmgr/restypes.hpp
@@ -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::operator() (std::string fname) {
- fs::path fpath = resPool::rel2abs(fname + ".png");
+ template<> inline ImageRsrc* resLoader::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::operator() (std::string fname) {
- fs::path fpath = resPool::rel2abs(fname + ".gif");
+ template<> inline CursorRsrc* resLoader::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::operator() (std::string fname) {
- fs::path fpath = resPool::rel2abs(fname + ".ttf");
+ template<> inline FontRsrc* resLoader::operator() (fs::path fpath) {
FontRsrc* theFont = new FontRsrc;
if(theFont->loadFromFile(fpath.string())) return theFont;
- fpath = resPool::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::operator() (std::string fname) {
- fs::path fpath = resPool::rel2abs(fname + ".txt");
+ template<> inline StringRsrc* resLoader::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::operator() (std::string fname) {
- fs::path fpath = resPool::rel2abs(fname + ".wav");
+ template<> inline SoundRsrc* resLoader::operator() (fs::path fpath) {
SoundRsrc* snd = new SoundRsrc;
if(snd->loadFromFile(fpath.string())) return snd;
delete snd;