First work on EntityFileWriter for saving levels
This commit is contained in:
@@ -1,3 +1,6 @@
|
|||||||
|
#ifndef EntityFileParser_h__
|
||||||
|
#define EntityFileParser_h__
|
||||||
|
|
||||||
#include "EntityFile.h"
|
#include "EntityFile.h"
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
|
|
||||||
@@ -21,3 +24,5 @@ private:
|
|||||||
void onStartComponentField(EntityID entity, std::string componentType, std::string fieldName, std::map<std::string, std::string> attributes);
|
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);
|
void onFieldData(EntityID entity, std::string componentType, std::string fieldName, const char* fieldData);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#ifndef EntityFilePreprocessor_h__
|
||||||
|
#define EntityFilePreprocessor_h__
|
||||||
|
|
||||||
#include <xercesc/framework/psvi/XSElementDeclaration.hpp>
|
#include <xercesc/framework/psvi/XSElementDeclaration.hpp>
|
||||||
#include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp>
|
#include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp>
|
||||||
#include <xercesc/framework/psvi/XSParticle.hpp>
|
#include <xercesc/framework/psvi/XSParticle.hpp>
|
||||||
@@ -29,3 +32,5 @@ private:
|
|||||||
void parseComponentInfo();
|
void parseComponentInfo();
|
||||||
void parseDefaults();
|
void parseDefaults();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -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
|
||||||
@@ -22,7 +22,7 @@ public:
|
|||||||
// Attach a component to an entity and fill it with default values
|
// Attach a component to an entity and fill it with default values
|
||||||
ComponentWrapper AttachComponent(EntityID entity, std::string componentType);
|
ComponentWrapper AttachComponent(EntityID entity, std::string componentType);
|
||||||
// Check if an entity has a component
|
// 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
|
// Get a component of an entity
|
||||||
ComponentWrapper GetComponent(EntityID entity, std::string componentType);
|
ComponentWrapper GetComponent(EntityID entity, std::string componentType);
|
||||||
// Delete a component off an entity
|
// Delete a component off an entity
|
||||||
|
|||||||
@@ -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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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);
|
ComponentPool* pool = m_ComponentPools.at(componentType);
|
||||||
return pool->KnowsEntity(entity);
|
return pool->KnowsEntity(entity);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "Collision/TriggerSystem.h"
|
#include "Collision/TriggerSystem.h"
|
||||||
#include "Collision/CollisionSystem.h"
|
#include "Collision/CollisionSystem.h"
|
||||||
#include "Game/HealthSystem.h"
|
#include "Game/HealthSystem.h"
|
||||||
|
#include "Core/EntityFileWriter.h"
|
||||||
|
|
||||||
Game::Game(int argc, char* argv[])
|
Game::Game(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
@@ -53,6 +54,9 @@ Game::Game(int argc, char* argv[])
|
|||||||
fpp.RegisterComponents(m_World);
|
fpp.RegisterComponents(m_World);
|
||||||
EntityFileParser fp(file);
|
EntityFileParser fp(file);
|
||||||
fp.MergeEntities(m_World);
|
fp.MergeEntities(m_World);
|
||||||
|
|
||||||
|
EntityFileWriter writer("Testasdasdasd.xml");
|
||||||
|
writer.WriteWorld(m_World);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create system pipeline
|
// Create system pipeline
|
||||||
|
|||||||
Reference in New Issue
Block a user