/* * resmgr.h * BoE * * Created by Celtic Minstrel on 10-08-24. * */ #ifndef BOE_RESMGR_H #define BOE_RESMGR_H #include #include #include #include #include #include #include // Will handle loading, retaining, and releasing of resources. // Resources include sounds, images, fonts, and cursors. namespace ResMgr { namespace fs = boost::filesystem; using idMapFn = std::function; template struct resPool { static std::map >& resources() { static std::map > data; return data; } static std::stack& resPaths() { static std::stack data; return data; } static idMapFn& mapFn() { static idMapFn data; return data; } static std::map& pathFound() { static std::map data; return data; } static fs::path rel2abs(fs::path path) { std::stack tmpPaths = resPaths(); while(!tmpPaths.empty()) { fs::path thisPath = tmpPaths.top()/path; printf("Testing %s...\n",thisPath.c_str()); if(fs::exists(thisPath)) { pathFound()[path] = tmpPaths.top(); return thisPath; } tmpPaths.pop(); } // If we got this far, it wasn't found. // Just return the original filename unchanged; // maybe it can be resolved anyway. return path; } }; template struct resLoader { type* operator() (std::string fname); }; class xResMgrErr : public std::exception { std::string msg; public: xResMgrErr() throw() {} xResMgrErr(const std::string& str) throw() : msg(str) {} ~xResMgrErr() throw() {} virtual const char* what() const throw() { return msg.c_str(); } }; template void free(std::string name) { if(resPool::resources().find(name) != resPool::resources().end()) resPool::resources().erase(name); } template void free(int id) { std::string name = resPool::mapFn()(id); if(name != "") free(name); } template void freeAll() { resPool::resources().clear(); } template std::shared_ptr get(std::string name) { if(resPool::resources().find(name) != resPool::resources().end()) { if(resPool::pathFound().find(name) != resPool::pathFound().end()) { std::string curPath = resPool::pathFound()[name].string(); std::string checkPath = resPool::rel2abs(name).string(); checkPath = checkPath.substr(0,curPath.length()); if(checkPath != curPath) { free(name); return get(name); } } return resPool::resources()[name]; } else { type* tmp; resLoader load; tmp = load(name); return resPool::resources()[name] = std::shared_ptr(tmp); } } template std::shared_ptr get(int id) { std::string name = resPool::mapFn()(id); if(name == "") throw xResMgrErr("Invalid resource ID."); return get(name); } template void pushPath(fs::path path) { printf("Pushing path %s in %s...\n",path.c_str(),__FUNCTION__); resPool::resPaths().push(path); if(resPool::resPaths().empty()) printf("A problem occurred.\n"); } template fs::path popPath() { fs::path path = resPool::resPaths.top(); // std::map::iterator mapiter; // std::deque toDestroy; // std::deque::iterator iter; // for(mapiter = resPool::pathFound().begin(); // mapiter != resPool::pathFound().end(); // mapiter++) // if(mapiter->second == path) // toDestroy.push_back(mapiter->first); // for(iter = toDestroy.begin(); iter != toDestroy.end(); iter++) // resPool::resources().erase(*iter); resPool::resPaths.pop(); return path; } template void setIdMapFn(idMapFn f) { resPool::mapFn() = f; } template idMapFn getIdMapFn() { return resPool::mapFn(); } } #endif