Files
farmlands/src/storage/Parsers.cpp

495 lines
15 KiB
C++

/*
* Parsers.cpp
*
* Created on: Dec 2, 2016
* Author: tibi
*/
#include <storage/Parsers.h>
#include <resources/Resources.h>
using namespace farmlands::resources;
namespace farmlands {
namespace storage {
/****** Components ******/
void parseBackgroundCells(resources::ResourceId cellsResource, components::Background* back, size_t layer)
{
Assert(RInfo[cellsResource].type == ResourceType::BackgroundLayer, "Resource must be a level layer.");
char buffer[1024 * 10];
// Open file
std::string pathIn = ResourceManager::instance().getPath(cellsResource);
std::ifstream in(pathIn);
if (!in)
THROW(utils::ResourceLoadException, "Could not load level layer " + pathIn);
// Read CSV file line by line
for (size_t row = 0; row < back->rowCount(); row++)
{
in.getline(buffer, sizeof(buffer));
if (in.eof())
THROW(utils::ResourceLoadException, "Unexpected end of file " + pathIn);
// Separated by comma (or maybe semicolon)
char* nextNum = strtok(buffer, ",;");
for (size_t col = 0; col < back->columnCount() && nextNum != NULL; col++)
{
components::Cell cell = (components::Cell) strtol(nextNum, NULL, 10);
back->setCell(layer, row, col, cell);
nextNum = strtok(NULL, ",;");
}
}
in.close();
}
template <>
components::Background* parse<components::Background> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "Background")
root = root.front().second;
// This object can be declared in another file
std::string src = root.get<std::string>("<xmlattr>.src", "");
if (!src.empty())
{
ResourceId id = ResourceManager::instance().getId(src);
return parse<components::Background>(id);
}
// Read sizes
uint32_t layers = root.count("Layer");
uint32_t rows = root.get<uint32_t>("<xmlattr>.rows");
uint32_t cols = root.get<uint32_t>("<xmlattr>.columns");
// Create components::Background object
components::Background* back = new components::Background(layers, rows, cols);
// Read layers
size_t layerNum = 0;
for (auto layer : root)
{
if (layer.first == "Layer")
{
// Read cells
std::string cellsPath = layer.second.get<std::string>("<xmlattr>.cells");
resources::ResourceId cellsId = resources::ResourceManager::instance().getId(cellsPath);
parseBackgroundCells(cellsId, back, layerNum);
// Read texture name
std::string texPath = layer.second.get<std::string>("<xmlattr>.texture");
resources::ResourceId tex = resources::ResourceManager::instance().getId(texPath);
back->setTexture(layerNum, tex);
++layerNum;
}
}
return back;
}
template <>
components::basic::Camera* parse<components::basic::Camera> (boost::property_tree::ptree& root)
{
if (root.front().first == "Camera")
root = root.front().second;
components::basic::Camera* camera = new components::basic::Camera();
camera->scale = root.get<float>("<xmlattr>.scale", 1.0f);
camera->mainCamera = root.get<bool>("<xmlattr>.mainCamera", false);
return camera;
}
template <>
components::basic::Frame* parse<components::basic::Frame> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "Frame")
root = root.front().second;
components::basic::Frame* frame = new components::basic::Frame();
// Obtine tile set id
std::string tileSetPath = root.get<std::string>("<xmlattr>.tileSet");
frame->tileSetId = resources::ResourceManager::instance().getId(tileSetPath);
// Set properties
frame->tileSetCell = root.get<int>("<xmlattr>.cell");
frame->width = root.get<uint32_t>("<xmlattr>.w", 1u);
frame->height = root.get<uint32_t>("<xmlattr>.h", 1u);
frame->duration = root.get<float>("<xmlattr>.duration");
return frame;
}
template <>
components::basic::Sprite* parse<components::basic::Sprite> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "Sprite")
root = root.front().second;
// This object can be declared in another file
std::string src = root.get<std::string>("<xmlattr>.src", "");
if (!src.empty())
{
ResourceId id = ResourceManager::instance().getId(src);
return parse<components::basic::Sprite>(id);
}
// Parse components::basic::Sprite
components::basic::Sprite* sprite = new components::basic::Sprite();
sprite->anchorX = root.get<float>("<xmlattr>.anchorX");
sprite->anchorY = root.get<float>("<xmlattr>.anchorY");
sprite->animationVelocity = root.get<float>("<xmlattr>.animationVelocity", 1.0f);
for (auto child : root)
{
if (child.first == "State")
{
components::basic::SpriteState* state = parse<components::basic::SpriteState>(child.second);
sprite->addState(*state);
delete state;
}
}
return sprite;
}
template <>
components::basic::SpriteState* parse<components::basic::SpriteState> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "SpriteState")
root = root.front().second;
components::basic::SpriteState* spriteState = new components::basic::SpriteState();
spriteState->name = root.get<std::string>("<xmlattr>.name");
for (auto child : root)
{
if (child.first == "Frame")
{
components::basic::Frame* frame = parse<components::basic::Frame>(child.second);
spriteState->frames.push_back(*frame);
delete frame;
}
}
return spriteState;
}
template <>
components::basic::Transform* parse<components::basic::Transform> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "Transform")
root = root.front().second;
components::basic::Transform* transform = new components::basic::Transform();
transform->x = root.get<float>("<xmlattr>.x", 0.0f);
transform->y = root.get<float>("<xmlattr>.y", 0.0f);
transform->w = root.get<float>("<xmlattr>.w", 0.0f);
transform->h = root.get<float>("<xmlattr>.h", 0.0f);
return transform;
}
template <>
components::DebugController* parse<components::DebugController> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "DebugController")
root = root.front().second;
components::DebugController* controller = new components::DebugController();
return controller;
}
template <>
components::items::Axe* parse<components::items::Axe> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "Axe")
root = root.front().second;
// Parse
return new components::items::Axe();
}
template <>
components::items::Giftable* parse<components::items::Giftable> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "Giftable")
root = root.front().second;
// Parse
return new components::items::Giftable();
}
template <>
components::items::Hoe* parse<components::items::Hoe> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "Hoe")
root = root.front().second;
// Parse
return new components::items::Hoe();
}
template <>
components::items::Item* parse<components::items::Item> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "Item")
root = root.front().second;
// Parse
components::items::Item* item = new components::items::Item();
item->name = root.get<std::string>("<xmlattr>.name");
item->description = root.get<std::string>("<xmlattr>.description");
item->level = root.get<uint8_t>("<xmlattr>.level");
return item;
}
template <>
components::items::Pickaxe* parse<components::items::Pickaxe> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "Pickaxe")
root = root.front().second;
// Parse
return new components::items::Pickaxe();
}
template <>
components::items::Scythe* parse<components::items::Scythe> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "Pickaxe")
root = root.front().second;
// Parse
return new components::items::Scythe();
}
template <>
components::items::WateringCan* parse<components::items::WateringCan> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "WateringCan")
root = root.front().second;
// Parse
components::items::WateringCan* can = new components::items::WateringCan();
can->capacity = root.get<float>("<xmlattr>.capacity");
can->amountLeft = root.get<float>("<xmlattr>.amountLeft");
return can;
}
template <>
components::items::Weapon* parse<components::items::Weapon> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "Weapon")
root = root.front().second;
// Parse
components::items::Weapon* weapon = new components::items::Weapon();
weapon->damage = root.get<float>("<xmlattr>.damage");
weapon->critProbability = root.get<float>("<xmlattr>.critProbability");
weapon->critDamage = root.get<float>("<xmlattr>.critDamage");
weapon->attackDuration = root.get<float>("<xmlattr>.attackDuration");
return weapon;
}
template <>
components::player::PlayerInventory* parse<components::player::PlayerInventory> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "PlayerInventory")
root = root.front().second;
components::player::PlayerInventory* controller = new components::player::PlayerInventory();
controller->capacity = root.get<uint32_t>("<xmlattr>.capacity");
controller->currentItemIndex = root.get<int>("<xmlattr>.currentItemIndex", -1);
return controller;
}
template <>
components::player::PlayerMovement* parse<components::player::PlayerMovement> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "PlayerMovement")
root = root.front().second;
components::player::PlayerMovement* controller = new components::player::PlayerMovement();
controller->facingDirection = (model::Direction)root.get<int>("<xmlattr>.facingDirection", model::Direction::South);
return controller;
}
/****** Graphics ******/
template <>
graphics::BackgroundRenderer* parse<graphics::BackgroundRenderer> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "BackgroundRenderer")
root = root.front().second;
graphics::BackgroundRenderer* renderer = new graphics::BackgroundRenderer();
return renderer;
}
template <>
graphics::SpriteRenderer* parse<graphics::SpriteRenderer> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "SpriteRenderer")
root = root.front().second;
graphics::SpriteRenderer* renderer = new graphics::SpriteRenderer();
return renderer;
}
/****** Model ******/
template <>
model::GameObject* parse<model::GameObject> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "GameObject")
root = root.front().second;
model::GameObject* gameObj = new model::GameObject();
gameObj->name = root.get<std::string>("<xmlattr>.name");
gameObj->visible = root.get<bool>("<xmlattr>.visible", true);
gameObj->setEnabled(root.get<bool>("<xmlattr>.enabled", true));
for (auto child : root)
{
// Game object
if (child.first == "GameObject")
gameObj->addChild(parse<model::GameObject>(child.second));
// Components::basic
else if (child.first == "Camera")
gameObj->addComponent(parse<components::basic::Camera>(child.second));
else if (child.first == "Sprite")
gameObj->addComponent(parse<components::basic::Sprite>(child.second));
else if (child.first == "Transform")
gameObj->addComponent(parse<components::basic::Transform>(child.second));
// Components::items
else if (child.first == "Axe")
gameObj->addComponent(parse<components::items::Axe>(child.second));
else if (child.first == "Giftable")
gameObj->addComponent(parse<components::items::Giftable>(child.second));
else if (child.first == "Hoe")
gameObj->addComponent(parse<components::items::Hoe>(child.second));
else if (child.first == "Item")
gameObj->addComponent(parse<components::items::Item>(child.second));
else if (child.first == "Pickaxe")
gameObj->addComponent(parse<components::items::Pickaxe>(child.second));
else if (child.first == "Scythe")
gameObj->addComponent(parse<components::items::Scythe>(child.second));
else if (child.first == "WateringCan")
gameObj->addComponent(parse<components::items::WateringCan>(child.second));
else if (child.first == "Weapon")
gameObj->addComponent(parse<components::items::Weapon>(child.second));
// Components::player
else if (child.first == "PlayerInventory")
gameObj->addComponent(parse<components::player::PlayerInventory>(child.second));
else if (child.first == "PlayerMovement")
gameObj->addComponent(parse<components::player::PlayerMovement>(child.second));
// Components
else if (child.first == "Background")
gameObj->addComponent(parse<components::Background>(child.second));
else if (child.first == "DebugController")
gameObj->addComponent(parse<components::DebugController>(child.second));
// Graphics
else if (child.first == "BackgroundRenderer")
gameObj->addComponent(parse<graphics::BackgroundRenderer>(child.second));
else if (child.first == "SpriteRenderer")
gameObj->addComponent(parse<graphics::SpriteRenderer>(child.second));
// !!! Add additional types here !!!
}
return gameObj;
}
template <>
model::Configuration* parse<model::Configuration> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "Configuration")
root = root.front().second;
model::Configuration* config = new model::Configuration();
config->animationFps = root.get<float>("animationFps");
return config;
}
template <>
model::Scene* parse<model::Scene> (boost::property_tree::ptree& root)
{
// Ensure we are on the model::Scene node (property tree seems to add root of its own)
if (root.front().first == "Scene")
root = root.front().second;
model::Scene* scene = new model::Scene();
scene->cellWidth = root.get<uint32_t>("<xmlattr>.cellWidth");
scene->cellHeight = root.get<uint32_t>("<xmlattr>.cellHeight");
for (auto child : root)
{
if (child.first == "GameObject")
{
model::GameObject* obj = parse<model::GameObject>(child.second);
scene->root.addChild(obj);
}
}
return scene;
}
}
}