First work on EntityFileWriter for saving levels

This commit is contained in:
2016-01-08 11:21:10 +01:00
parent 23e78c4947
commit 81024b4a1d
7 changed files with 177 additions and 4 deletions
+6 -1
View File
@@ -1,3 +1,6 @@
#ifndef EntityFileParser_h__
#define EntityFileParser_h__
#include "EntityFile.h"
#include "World.h"
@@ -20,4 +23,6 @@ private:
void onStartComponent(EntityID entity, std::string component);
void onStartComponentField(EntityID entity, std::string componentType, std::string fieldName, std::map<std::string, std::string> attributes);
void onFieldData(EntityID entity, std::string componentType, std::string fieldName, const char* fieldData);
};
};
#endif
+6 -1
View File
@@ -1,3 +1,6 @@
#ifndef EntityFilePreprocessor_h__
#define EntityFilePreprocessor_h__
#include <xercesc/framework/psvi/XSElementDeclaration.hpp>
#include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp>
#include <xercesc/framework/psvi/XSParticle.hpp>
@@ -28,4 +31,6 @@ private:
void onStartComponent(EntityID entity, std::string type);
void parseComponentInfo();
void parseDefaults();
};
};
#endif
+38
View File
@@ -0,0 +1,38 @@
#ifndef EntityFileWriter_h__
#define EntityFileWriter_h__
#include <boost/filesystem.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/framework/StdOutFormatTarget.hpp>
#include "Util/XercesString.h"
#include "EntityFile.h"
#include "World.h"
class EntityFileWriter
{
public:
EntityFileWriter(boost::filesystem::path file)
: m_FilePath(file)
{
using namespace xercesc;
m_DOMImplementation = DOMImplementationRegistry::getDOMImplementation(XS::ToXMLCh("LS"));
m_DOMLSSerializer = static_cast<DOMImplementationLS*>(m_DOMImplementation)->createLSSerializer();
m_DOMLSSerializer->getDomConfig()->setParameter(XMLUni::fgDOMWRTDiscardDefaultContent, true);
m_DOMLSSerializer->getDomConfig()->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true);
}
void WriteWorld(World* world);
private:
boost::filesystem::path m_FilePath;
xercesc::DOMImplementation* m_DOMImplementation;
xercesc::DOMLSSerializer* m_DOMLSSerializer;
void appendEntityChildren(xercesc::DOMElement* parentElement, const World* world, EntityID entity);
void appentEntityComponents(xercesc::DOMElement* parentElemetn, const World* world, EntityID entity);
};
#endif
+1 -1
View File
@@ -22,7 +22,7 @@ public:
// Attach a component to an entity and fill it with default values
ComponentWrapper AttachComponent(EntityID entity, std::string componentType);
// Check if an entity has a component
bool HasComponent(EntityID entity, std::string componentType);
bool HasComponent(EntityID entity, std::string componentType) const;
// Get a component of an entity
ComponentWrapper GetComponent(EntityID entity, std::string componentType);
// Delete a component off an entity
+121
View File
@@ -0,0 +1,121 @@
#include "Core/EntityFileWriter.h"
#define X(str) XS::ToXMLCh(str)
void EntityFileWriter::WriteWorld(World* world)
{
using namespace xercesc;
DOMDocument* doc = m_DOMImplementation->createDocument(nullptr, X("Entity"), nullptr);
DOMElement* root = doc->getDocumentElement();
root->setAttribute(X("xmlns:xsi"), X("http://www.w3.org/2001/XMLSchema-instance"));
root->setAttribute(X("xsi:noNamespaceSchemaLocation"), X("../Types/Entity.xsd"));
root->setAttribute(X("xmlns:c"), X("components"));
DOMElement* componentsElement = doc->createElement(X("Components"));
root->appendChild(componentsElement);
appentEntityComponents(componentsElement, world, 0);
DOMElement* childrenElement = doc->createElement(X("Children"));
root->appendChild(childrenElement);
appendEntityChildren(childrenElement, world, 0);
XMLFormatTarget* target = new StdOutFormatTarget();
DOMLSOutput* output = static_cast<DOMImplementationLS*>(m_DOMImplementation)->createLSOutput();
output->setByteStream(target);
m_DOMLSSerializer->write(doc, output);
}
void EntityFileWriter::appendEntityChildren(xercesc::DOMElement* parentElement, const World* world, EntityID entity)
{
using namespace xercesc;
DOMDocument* doc = parentElement->getOwnerDocument();
auto childrenRange = world->GetEntityChildren().equal_range(entity);
for (auto it = childrenRange.first; it != childrenRange.second; ++it) {
EntityID childEntity = it->second;
DOMElement* entityElement = doc->createElement(X("Entity"));
parentElement->appendChild(entityElement);
DOMElement* componentsElement = doc->createElement(X("Components"));
entityElement->appendChild(componentsElement);
appentEntityComponents(componentsElement, world, childEntity);
DOMElement* childrenElement = doc->createElement(X("Children"));
entityElement->appendChild(childrenElement);
appendEntityChildren(childrenElement, world, childEntity);
}
}
void EntityFileWriter::appentEntityComponents(xercesc::DOMElement* parentElement, const World* world, EntityID entity)
{
using namespace xercesc;
DOMDocument* doc = parentElement->getOwnerDocument();
auto& componentPools = world->GetComponentPools();
// Step through all component pools to get an entity's components
// HACK: This is sloooow.
for (auto& kv : componentPools) {
const std::string& componentName = kv.first;
if (!world->HasComponent(entity, componentName)) {
continue;
}
std::string qualifiedComponentName = "c:" + componentName;
DOMElement* componentElement = doc->createElement(X(qualifiedComponentName));
parentElement->appendChild(componentElement);
ComponentWrapper c = kv.second->GetByEntity(entity);
for (auto& kv : c.Info.FieldTypes) {
std::string fieldName = kv.first;
std::string fieldType = kv.second;
std::size_t fieldOffset = c.Info.FieldOffsets.at(fieldName);
// Ignore fields that are equal to the default
// HACK: This is probably sloooooow, but it's okay.
if (memcmp(c.Data + fieldOffset, c.Info.Defaults.get() + fieldOffset, EntityFile::GetTypeStride(fieldType)) == 0) {
continue;
}
DOMElement* fieldElement = doc->createElement(X(fieldName));
componentElement->appendChild(fieldElement);
if (fieldType == "Vector") {
const glm::vec3& vec = c[fieldName];
fieldElement->setAttribute(X("X"), X(boost::lexical_cast<std::string>(vec.x)));
fieldElement->setAttribute(X("Y"), X(boost::lexical_cast<std::string>(vec.y)));
fieldElement->setAttribute(X("Z"), X(boost::lexical_cast<std::string>(vec.z)));
} else if (fieldType == "Color") {
const glm::vec4& vec = c[fieldName];
fieldElement->setAttribute(X("R"), X(boost::lexical_cast<std::string>(vec.r)));
fieldElement->setAttribute(X("G"), X(boost::lexical_cast<std::string>(vec.g)));
fieldElement->setAttribute(X("B"), X(boost::lexical_cast<std::string>(vec.b)));
fieldElement->setAttribute(X("A"), X(boost::lexical_cast<std::string>(vec.a)));
} else if (fieldType == "Quaternion") {
const glm::quat& q = c[fieldName];
fieldElement->setAttribute(X("X"), X(boost::lexical_cast<std::string>(q.x)));
fieldElement->setAttribute(X("Y"), X(boost::lexical_cast<std::string>(q.y)));
fieldElement->setAttribute(X("Z"), X(boost::lexical_cast<std::string>(q.z)));
fieldElement->setAttribute(X("W"), X(boost::lexical_cast<std::string>(q.w)));
} else if (fieldType == "int") {
const int& value = c[fieldName];
fieldElement->appendChild(doc->createTextNode(X(boost::lexical_cast<std::string>(value))));
} else if (fieldType == "float") {
const float& value = c[fieldName];
fieldElement->appendChild(doc->createTextNode(X(boost::lexical_cast<std::string>(value))));
} else if (fieldType == "double") {
const double& value = c[fieldName];
fieldElement->appendChild(doc->createTextNode(X(boost::lexical_cast<std::string>(value))));
} else if (fieldType == "bool") {
const bool& value = c[fieldName];
if (value) {
fieldElement->appendChild(doc->createTextNode(X("true")));
} else {
fieldElement->appendChild(doc->createTextNode(X("false")));
}
} else if (fieldType == "string") {
const std::string& value = c[fieldName];
fieldElement->appendChild(doc->createTextNode(X(value)));
}
}
}
}
+1 -1
View File
@@ -68,7 +68,7 @@ ComponentWrapper World::AttachComponent(EntityID entity, std::string componentTy
}
bool World::HasComponent(EntityID entity, std::string componentType)
bool World::HasComponent(EntityID entity, std::string componentType) const
{
ComponentPool* pool = m_ComponentPools.at(componentType);
return pool->KnowsEntity(entity);
+4
View File
@@ -2,6 +2,7 @@
#include "Collision/TriggerSystem.h"
#include "Collision/CollisionSystem.h"
#include "Game/HealthSystem.h"
#include "Core/EntityFileWriter.h"
Game::Game(int argc, char* argv[])
{
@@ -53,6 +54,9 @@ Game::Game(int argc, char* argv[])
fpp.RegisterComponents(m_World);
EntityFileParser fp(file);
fp.MergeEntities(m_World);
EntityFileWriter writer("Testasdasdasd.xml");
writer.WriteWorld(m_World);
}
// Create system pipeline