farmlands/src/resources/ResourceManager.cpp

195 lines
5.1 KiB
C++

/*
* ResourceManager.cpp
*
* Created on: Nov 7, 2016
* Author: tibi
*/
#include <GameState.h>
#include <graphics/backend/SdlRenderer.h>
#include <model/GameObject.h>
#include <resources/ResourceManager.h>
#include <resources/Resources.h>
#include <storage/Parsers.h>
#include <utils/Assert.h>
#include <iostream>
#include <boost/filesystem.hpp>
#define FONTID(id,size) (id * 1000 + size)
#define FONTID_SIZE(fontid) (fontid % 1000)
#define FONTID_ID(fontid) (fontid / 1000)
using namespace farmlands::graphics::backend;
namespace farmlands {
namespace resources {
ResourceManager ResourceManager::s_instance;
ResourceManager& ResourceManager::instance()
{
return s_instance;
}
ResourceManager::ResourceManager()
: m_loadedResources(new LoadedResource[sizeof(RInfo) / sizeof(RInfo[0])])
{
for(size_t i = 0; i < sizeof(RInfo) / sizeof(RInfo[0]); i++)
m_loadedResources[i].loaded = false;
}
ResourceManager::~ResourceManager()
{
// Unload resources
for(size_t i = 0; i < sizeof(RInfo) / sizeof(RInfo[0]); i++)
{
if (m_loadedResources[i].loaded)
{
switch(RInfo[i].type)
{
case ResourceType::Texture:
SDL_DestroyTexture(m_loadedResources[i].texture.texture);
SDL_FreeSurface(m_loadedResources[i].texture.surface);
break;
default:
std::cerr << "Warning: Cannot free resource " << i << " of type " << (int)RInfo[i].type << "\n";
break;
}
}
}
delete[] m_loadedResources;
// Unload fonts
for (auto pair : m_fontCache)
{
TTF_CloseFont(pair.second);
}
}
void ResourceManager::initialize()
{
}
void ResourceManager::loadMainMenu()
{
}
void ResourceManager::loadGame()
{
GameState::current().config = storage::parse<model::Configuration>(R::Config::Default);
GameState::current().scene = storage::parse<model::Scene>(R::Scenes::Game);
GameState::current().scene->root.onCreate();
storage::parseCollection(R::Items::Tools, GameState::current().itemPrefabs);
storage::parseCollection(R::Items::Weapons, GameState::current().itemPrefabs);
storage::parseCollection(R::Plants::Plantable, GameState::current().plantsPrefabs);
storage::parseCollection(R::Plants::Seeds, GameState::current().seedsPrefabs);
// Get to "Inventory" object
model::GameObject* root = &GameState::current().scene->root;
model::GameObject* player = *root->findByName("Player");
components::basic::Inventory* inventory = player->component<components::basic::Inventory>();
model::GameObject* pickables = *root->findByName("Pickables");
// Give player all items
for (auto prefab : GameState::current().itemPrefabs)
{
float x = player->transform.x + 15 * GameState::current().random.getFloat();
float y = player->transform.y + 15 * GameState::current().random.getFloat();
model::GameObject* item = model::GameObject::instantiate(prefab, "Pickable item", pickables);
item->transform.x = x;
item->transform.y = y;
item->addComponent(new components::items::Pickable());
}
for (auto prefab : GameState::current().seedsPrefabs)
{
model::GameObject* item = model::GameObject::instantiate(prefab, "inv seed", player);
inventory->add(item);
}
}
std::string ResourceManager::getPath(ResourceId resourceId)
{
Assert(resourceId >= 0 && resourceId < sizeof(RInfo) / sizeof(RInfo[0]), "Resource id out of bounds.");
boost::filesystem::path resPath(ASSETS_DIR);
resPath.append(RInfo[resourceId].path);
return resPath.native();
}
ResourceId ResourceManager::getId(std::string resPathStr)
{
boost::filesystem::path resPath(resPathStr);
for(size_t i = 0; i < sizeof(RInfo) / sizeof(RInfo[0]); i++)
{
boost::filesystem::path iPath (RInfo[i].path);
if (resPath == iPath)
return i;
}
return (ResourceId)-1;
}
TTF_Font* ResourceManager::font(ResourceId fontId, int pointSize)
{
Assert(RInfo[fontId].type == ResourceType::Font, "Resource must be a font");
// Do not load if already loaded
auto it = m_fontCache.find(FONTID(fontId, pointSize));
if (it != m_fontCache.end())
return it->second;
// Open font
std::string fontPath = getPath(fontId);
TTF_Font* font = TTF_OpenFont(fontPath.c_str(), pointSize);
if (!font)
THROW(utils::ResourceLoadException, "Could not load font " + fontPath);
// Cache font
m_fontCache.emplace(FONTID(fontId, pointSize), font);
return font;
}
SDL_Texture* ResourceManager::texture(ResourceId textureId)
{
Assert(RInfo[textureId].type == ResourceType::Texture, "Resource must be a texture");
// See if already loaded
if (!m_loadedResources[textureId].loaded)
{
// Open file
std::string texturePath = getPath(textureId);
SDL_Surface* surface = IMG_Load(texturePath.c_str());
if (surface == NULL)
THROW(utils::ResourceLoadException, "Failed to load texture " + texturePath);
SDL_Texture* texture = SDL_CreateTextureFromSurface(SdlRenderer::instance().internalRenderer(), surface);
if (texture == NULL)
THROW(utils::ResourceLoadException, "Failed to create texture " + texturePath);
// Add to loaded resources
m_loadedResources[textureId].texture.surface = surface;
m_loadedResources[textureId].texture.texture = texture;
m_loadedResources[textureId].loaded = true;
}
return m_loadedResources[textureId].texture.texture;
}
} /* namespace storage */
} /* namespace farmlands */