1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
#include <vector>
#include "Texture.h"
#include "Model.h"
#ifndef _RESM_H_
#define _RESM_H_
/******************************************************
Copyright Antoine Henry 2013-2014
Resource Manager.h
Desc: This header contains the ResourceManager class. Go to Management(.h/.cpp)
if you'd like the global object that's delcared there.
INFO ON "class ResourceManager": This resource manager is relatively simple.
The Resource class template declared in Resource.h is put into a vector (used as dynamic array) of
shared_ptrs, and they're loaded upon request. When used correctly, the ResourceManager
polls the shared_ptrs every 5 minutes. If the shared_ptr is not referenced (.unique() == true),
the resource is unloaded.
NOTES TO USE CLASS CORRECTLY: If you'd like to use this class correctly,
.reset() the shared_ptr when you're done with it so the ResourceManager object
knows the pointer isn't being used when it's polled, and can be unloaded from memory
without any problems. If you decide not to, the program will keep that resource in memory
until the program is shutdown.
Unload() and UnloadAll() should NEVER be used by a non-management class.
This can lead to a laggy program. Let the ResourceManager do all the work for you,
that's why it's here in the first place, to manage your resources.
******************************************************/
class CF::Management::ResourceManager
{
public:
////////////////////////////////////////////////////////////////////////////////////////////
// * void CF::Management::ResourceManager::Resource Manager()
//
// Desc: The class constructor, just initializes required variables.
////////////////////////////////////////////////////////////////////////////////////////////
ResourceManager()
{
// Initialize some variables to avoid errors.
numResources = 0;
prevTime = 0;
currentTime = 0;
}
////////////////////////////////////////////////////////////////////////////////////////////
// * void CF::Management::ResourceManager::LoadResource()
// Desc: Loads requested resource. (If it can find it on the HD, that is.)
////////////////////////////////////////////////////////////////////////////////////////////
template<class sParam, class tParam>
int LoadResource(std::string &location, ResourceType type, sParam secondParam, tParam thirdParam)
{
bool resLoaded = isLoaded(location, type);
if(resLoaded) {return -1;} // Tells the resource was already loaded.
if(type == R_TEXTURE)
{
// Load the texture
Video::Texture* texture = new Video::Texture(location.c_str());
if(texture == nullptr) {return 1;} // If the texture failed to load...
// Load the texture into a resource template, then to a shared_ptr object.
std::shared_ptr<Resource<Video::Texture*>> tmpRes(new Resource<Video::Texture*>(texture, location.c_str()));
// Add the shared_ptr to the texture database.
textures.push_back(tmpRes);
}
else if(type == R_MESH)
{
switch(secondParam)
{
case FILE_OBJ:
try {Mesh* mesh = new Mesh;}
catch(std::bad_alloc& ba)
{
std::cerr << "Failure to allocate memory: " << ba.what() << '\n';
}
// Load the file into memory
mesh->LoadOBJ(location.c_str());
break;
case FILE_OBJ_TEXTURED:
try {Mesh* mesh = new Mesh;}
catch(std::bad_alloc& ba)
{
std::cerr << "Failure to allocate memory: " << ba.what() << '\n';
}
mesh->LoadOBJT(location.c_str(), (CF::Video::Texture*)thirdParam);
break;
}
}
// Now since a resource was loaded, we can safely add 1 to the numResources variable...
numResources++;
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////
// * void CF::Management::ResourceManager::PollResources()
//
// Desc: Polls the resource database every X minutes for unused resources. If it finds
// any, we immediately unload it from memory, as it's no longer being used.
////////////////////////////////////////////////////////////////////////////////////////////
void PollResources()
{
// Every 5 minutes we check if a resource is referenced. If not, we unload it
if((currentTime - prevTime) > 300000) // There are 300,000 miliseconds in 5 minutes
{
prevTime = currentTime; // Reset
for(unsigned int r = 0; r < textures.size(); r++)
{
if(textures[r].unique()) // If the texture isn't referenced any more...
{
// Unload the resource
UnloadResource(textures[r]->getID(), R_TEXTURE);
}
}
for(unsigned int r = 0; r < meshes.size(); r++)
{
if(meshes[r].unique())
{
// Unload the resource
UnloadResource(meshes[r]->getID(), R_MESH);
}
}
for(unsigned int r = 0; r < models.size(); r++)
{
if(models[r].unique())
{
// Unload the resource
UnloadResource(models[r]->getID(), R_MODEL);
}
}
}
currentTime = SDL_GetTicks(); // Update...
}
////////////////////////////////////////////////////////////////////////////////////////////
// * void CF::Management::ResourceManager::UnloadResource()
//
// Desc: Unloads the requested resource.
////////////////////////////////////////////////////////////////////////////////////////////
int UnloadResource(std::string &location, ResourceType type)
{
bool resLoaded = isLoaded(location, type);
if(!resLoaded) {return -1;} // Tells the resource isn't loaded.
switch(type)
{
case R_TEXTURE:
long i = -1; // The index of the resource with the requested location
for(unsigned int r = 0; r < textures.size(); r++)
{
if(location == textures[r]->getID())
{
i = r; // Set the index
}
}
if(i == -1) {return -1;} // There was no match
std::cout << textures[i]->getID() << " Unloaded.\n";
//delete textures[i]->getResource(); // Free the resource.
textures[i].reset(); // Free the resource's container
textures.erase(textures.begin() + i); // Remove the resource from the vector.
break;
}
return 0;
}
|