Cleaned up code

This commit is contained in:
2016-01-07 14:43:54 +01:00
parent 3e7f27e1fe
commit 23e78c4947
10 changed files with 352 additions and 939 deletions
+4 -64
View File
@@ -275,79 +275,19 @@ private:
public:
static std::size_t GetTypeStride(std::string typeName);
static void WriteAttributeData(char* outData, const std::string fieldType, const std::map<std::string, std::string>& attributes)
{
if (fieldType == "Vector") {
glm::vec3 vec;
vec.x = boost::lexical_cast<float>(attributes.at("X"));
vec.y = boost::lexical_cast<float>(attributes.at("Y"));
vec.z = boost::lexical_cast<float>(attributes.at("Z"));
memcpy(outData, reinterpret_cast<char*>(&vec), EntityFile::GetTypeStride(fieldType));
} else if (fieldType == "Color") {
glm::vec4 vec;
vec.r = boost::lexical_cast<float>(attributes.at("R"));
vec.g = boost::lexical_cast<float>(attributes.at("G"));
vec.b = boost::lexical_cast<float>(attributes.at("B"));
vec.a = boost::lexical_cast<float>(attributes.at("A"));
memcpy(outData, reinterpret_cast<char*>(&vec), EntityFile::GetTypeStride(fieldType));
} else if (fieldType == "Quaternion") {
glm::quat q;
q.x = boost::lexical_cast<float>(attributes.at("X"));
q.y = boost::lexical_cast<float>(attributes.at("Y"));
q.z = boost::lexical_cast<float>(attributes.at("Z"));
q.w = boost::lexical_cast<float>(attributes.at("W"));
memcpy(outData, reinterpret_cast<char*>(&q), EntityFile::GetTypeStride(fieldType));
} else if (!attributes.empty()) {
LOG_WARNING("%i attributes not handled by any type conversion!", attributes.size());
}
}
static void WriteValueData(char* outData, const std::string fieldType, const char* valueData)
{
if (fieldType == "int") {
int value = boost::lexical_cast<int>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), EntityFile::GetTypeStride(fieldType));
} else if (fieldType == "float") {
float value = boost::lexical_cast<float>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), EntityFile::GetTypeStride(fieldType));
} else if (fieldType == "double") {
double value = boost::lexical_cast<double>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), EntityFile::GetTypeStride(fieldType));
} else if (fieldType == "bool") {
bool value = (valueData[0] == 't'); // Lazy bool evaluation
memcpy(outData, reinterpret_cast<char*>(&value), EntityFile::GetTypeStride(fieldType));
} else if (fieldType == "string") {
new (outData) std::string(valueData);
} else {
LOG_WARNING("Unknown value data type: %s", fieldType.c_str());
}
}
void Parse(const EntityFileHandler* handler);
//const std::map<std::string, ::ComponentInfo>& ComponentInfo() const { return m_ComponentInfo; }
//const std::vector<std::string>& EntityReferences() const { return m_EntityReferences; }
static void WriteAttributeData(char* outData, const std::string fieldType, const std::map<std::string, std::string>& attributes);
static void WriteValueData(char* outData, const std::string fieldType, const char* valueData);
xercesc::XMLGrammarPool* GrammarPool() const { return m_GrammarPool; }
void Parse(const EntityFileHandler* handler) const;
private:
boost::filesystem::path m_FilePath;
xercesc::XMLGrammarPool* m_GrammarPool;
xercesc::SAX2XMLReader* m_SAX2XMLReader;
//std::map<std::string, ::ComponentInfo> m_ComponentInfo;
//std::vector<std::string> m_EntityReferences;
static float getFloatAttribute(const xercesc::DOMElement* element, const char* attribute)
{
using namespace xercesc;
XSValue::Status status;
XSValue* val = XSValue::getActualValue(element->getAttribute(XS::ToXMLCh(attribute)), xercesc::XSValue::DataType::dt_double, status);
if (val == nullptr) {
LOG_ERROR("Element \"%s\" doesn't have an \"%s\" attribute!", ((std::string)XS::ToString(element->getTagName())).c_str(), attribute);
return 0.f;
} else {
return static_cast<float>(val->fData.fValue.f_double);
}
}
};
#endif
+9 -56
View File
@@ -4,67 +4,20 @@
class EntityFileParser
{
public:
EntityFileParser(EntityFile* entityFile)
: m_EntityFile(entityFile)
{
m_Handler.SetStartEntityCallback(std::bind(&EntityFileParser::onStartEntity, this, std::placeholders::_1, std::placeholders::_2));
m_Handler.SetStartComponentCallback(std::bind(&EntityFileParser::onStartComponent, this, std::placeholders::_1, std::placeholders::_2));
m_Handler.SetStartFieldCallback(std::bind(&EntityFileParser::onStartComponentField, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
m_Handler.SetStartFieldDataCallback(std::bind(&EntityFileParser::onFieldData, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
}
EntityFileParser(const EntityFile* entityFile);
void MergeEntities(World* world)
{
m_World = world;
m_EntityIDMapper[0] = 0;
m_EntityFile->Parse(&m_Handler);
}
void MergeEntities(World* world);
private:
EntityFile* m_EntityFile;
const EntityFile* m_EntityFile;
EntityFileHandler m_Handler;
World* m_World = nullptr;
// Maps EntityIDs local to the file to real IDs in the world
// Maps EntityIDs local to the file to real IDs in the world after they've been
// created in order to resolve parent-child relationships.
std::map<EntityID, EntityID> m_EntityIDMapper;
void onStartEntity(EntityID entity, EntityID parent)
{
EntityID realParent = m_EntityIDMapper.at(parent);
EntityID realEntity = m_World->CreateEntity(realParent);
m_EntityIDMapper[entity] = realEntity;
LOG_DEBUG("Created entity #%i (%i) with parent %i (%i)", entity, realEntity, parent, realParent);
}
void onStartComponent(EntityID entity, std::string component)
{
EntityID realEntity = m_EntityIDMapper.at(entity);
m_World->AttachComponent(entity, component);
LOG_DEBUG("Attached component of type \"%s\" to entity #%i (%i)", component.c_str(), entity, realEntity);
}
void onStartComponentField(EntityID entity, std::string componentType, std::string fieldName, std::map<std::string, std::string> attributes)
{
EntityID realEntity = m_EntityIDMapper.at(entity);
ComponentWrapper component = m_World->GetComponent(realEntity, componentType);
std::string fieldType = component.Info.FieldTypes.at(fieldName);
LOG_DEBUG("Field \"%s\" type \"%s\"", fieldName.c_str(), fieldType.c_str());
LOG_DEBUG("Attributes:");
for (auto& kv : attributes) {
LOG_DEBUG("\t%s = %s", kv.first.c_str(), kv.second.c_str());
}
char* data = component.Data + component.Info.FieldOffsets.at(fieldName);
EntityFile::WriteAttributeData(data, fieldType, attributes);
}
void onFieldData(EntityID entity, std::string componentType, std::string fieldName, const char* fieldData)
{
EntityID realEntity = m_EntityIDMapper.at(entity);
ComponentWrapper component = m_World->GetComponent(realEntity, componentType);
std::string fieldType = component.Info.FieldTypes.at(fieldName);
char* data = component.Data + component.Info.FieldOffsets.at(fieldName);
EntityFile::WriteValueData(data, fieldType, fieldData);
}
void onStartEntity(EntityID entity, EntityID parent);
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);
};
+6 -223
View File
@@ -16,233 +16,16 @@
class EntityFilePreprocessor
{
public:
EntityFilePreprocessor(std::string path)
: m_FilePath(path)
{
m_EntityFile = ResourceManager::Load<EntityFile>(path);
EntityFileHandler handler;
handler.SetStartComponentCallback(std::bind(&EntityFilePreprocessor::onStartComponent, this, std::placeholders::_1, std::placeholders::_2));
m_EntityFile->Parse(&handler);
EntityFilePreprocessor(const EntityFile* entityFile);
LOG_DEBUG("___ COMPONENT DEFINITIONS ___");
for (auto& kv : m_ComponentCounts) {
LOG_DEBUG("%s: %i", kv.first.c_str(), kv.second);
}
parseComponentInfo();
for (auto& kv : m_ComponentInfo) {
auto& info = kv.second;
LOG_DEBUG("Component: %s (%s)", info.Name.c_str(), info.Meta.Annotation.c_str());
LOG_DEBUG("Stride: %i", info.Meta.Stride);
LOG_DEBUG("Allocation: %i", info.Meta.Allocation);
for (auto& kv : info.FieldTypes) {
LOG_DEBUG("\t%i\t%s %s", info.FieldOffsets[kv.first], kv.second.c_str(), kv.first.c_str());
}
}
parseDefaults();
}
void RegisterComponents(World* world)
{
for (auto& kv : m_ComponentInfo) {
world->RegisterComponent(kv.second);
}
}
void RegisterComponents(World* world);
private:
std::string m_FilePath;
EntityFile* m_EntityFile;
const EntityFile* m_EntityFile;
std::map<std::string, unsigned int> m_ComponentCounts;
std::map<std::string, ComponentInfo> m_ComponentInfo;
void onStartComponent(EntityID entity, std::string type)
{
//LOG_DEBUG("Component: %s", type.c_str());
m_ComponentCounts[type]++;
}
void parseComponentInfo()
{
using namespace xercesc;
EntityFileXMLErrorHandler errorHandler;
auto grammarPool = m_EntityFile->GrammarPool();
bool whateverTheFuckThisIs;
auto xsModel = grammarPool->getXSModel(whateverTheFuckThisIs);
// Find component xsd element declarations
std::cout << "Enumerating components..." << std::endl;
// <xs:element name="ComponentName">
auto topLevelElements = xsModel->getComponents(XSConstants::ELEMENT_DECLARATION);
for (unsigned int i = 0; i < topLevelElements->getLength(); ++i) {
auto element = static_cast<XSElementDeclaration*>(topLevelElements->item(i));
std::string nameSpace = XS::ToString(element->getNamespace());
if (nameSpace != "components") {
continue;
}
ComponentInfo compInfo;
// Name
compInfo.Name = XS::ToString(element->getName());
// Known allocation
compInfo.Meta.Allocation = m_ComponentCounts[compInfo.Name];
// Annotation
auto componentAnnotation = element->getAnnotation();
if (componentAnnotation != nullptr) {
// Parse annotation XML
char* annotationString = XMLString::transcode(componentAnnotation->getAnnotationString());
MemBufInputSource annotationInput(reinterpret_cast<const XMLByte*>(annotationString), strlen(annotationString), "MemBuf: Annotation String");
XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager, grammarPool);
parser.setErrorHandler(&errorHandler);
parser.parse(annotationInput);
XMLString::release(&annotationString);
auto doc = parser.getDocument();
// TODO: Add allocation estimations from external file on map-to-map basis
// Add allocation estimation(s)
//auto allocationTags = doc->getElementsByTagName(XSTR("meta:allocation"));
//for (int i = 0; i < allocationTags->getLength(); ++i) {
// auto allocation = dynamic_cast<DOMElement*>(allocationTags->item(i));
// auto child = allocation->getFirstChild();
// if (child == nullptr) {
// continue;
// }
// XSValue::Status status;
// XSValue* val = XSValue::getActualValue(child->getNodeValue(), XSValue::dt_integer, status);
// compInfo.Meta.Allocation += val->fData.fValue.f_int;
//}
// Save documentation string
auto documentationTags = doc->getElementsByTagName(XS::ToXMLCh("xs:documentation"));
if (documentationTags->getLength() != 0) {
auto child = documentationTags->item(0)->getFirstChild();
if (child != nullptr) {
compInfo.Meta.Annotation = XS::ToString(child->getNodeValue());
}
}
} else {
LOG_WARNING("Component is missing an annotation!");
}
// <xs:complexType>
auto typeDefinition = element->getTypeDefinition();
if (typeDefinition->getTypeCategory() != XSTypeDefinition::COMPLEX_TYPE) {
LOG_ERROR("Type definition wasn't COMPLEX_TYPE! Skipping.");
continue;
}
auto complexTypeDefinition = dynamic_cast<XSComplexTypeDefinition*>(typeDefinition);
// <xs:all>
auto modelGroupParticle = complexTypeDefinition->getParticle();
if (modelGroupParticle->getTermType() != XSParticle::TERM_MODELGROUP) {
LOG_ERROR("Model group particle wasn't TERM_MODELGROUP! Skipping.");
continue;
}
auto modelGroup = modelGroupParticle->getModelGroupTerm();
// <xs:element...
// <xs:attribute...
unsigned int fieldOffset = 0;
auto particles = modelGroup->getParticles();
for (unsigned int i = 0; i < particles->size(); ++i) {
auto particle = particles->elementAt(i);
if (particle->getTermType() != XSParticle::TERM_ELEMENT) {
LOG_ERROR("Particle wasn't TERM_ELEMENT! Skipping.");
continue;
}
auto elementDeclaration = particle->getElementTerm();
std::string name = XS::ToString(elementDeclaration->getName());
std::string type = XS::ToString(elementDeclaration->getTypeDefinition()->getName());
size_t stride = EntityFile::GetTypeStride(type);
if (stride == 0) {
std::cout << "Warning: Field \"" << name << "\" in component \"" << compInfo.Name << "\" uses unexpected field type \"" << type << "\". Skipping." << std::endl;
continue;
}
compInfo.FieldTypes[name] = type;
compInfo.FieldOffsets[name] = fieldOffset;
fieldOffset += stride;
}
compInfo.Meta.Stride = fieldOffset;
m_ComponentInfo[compInfo.Name] = compInfo;
}
}
void parseDefaults()
{
using namespace xercesc;
EntityFileXMLErrorHandler errorHandler;
for (auto& ci : m_ComponentInfo) {
// Allocate memory for default values
ci.second.Defaults = std::shared_ptr<char>(new char[ci.second.Meta.Stride]);
memset(ci.second.Defaults.get(), 0, ci.second.Meta.Stride);
XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager);
parser.setErrorHandler(&errorHandler);
std::string componentName = ci.first;
LOG_DEBUG("Parsing defaults for component %s", componentName.c_str());
boost::filesystem::path defaultsFile = "Schema/Components/" + componentName + ".xml";
parser.parse(defaultsFile.string().c_str());
auto doc = parser.getDocument();
if (doc == nullptr) {
LOG_ERROR("%s not found! Skipping.", defaultsFile.string().c_str());
continue;
}
// Find the node in the components namespace matching the component name
std::string tagName = "c:" + componentName;
auto rootNodes = doc->getElementsByTagName(XS::ToXMLCh(tagName));
if (rootNodes->getLength() == 0) {
LOG_ERROR("Couldn't find defaults for component \"%s\"! Skipping.", componentName.c_str());
continue;
}
auto componentElement = dynamic_cast<DOMElement*>(rootNodes->item(0));
// Fill the default value buffer with values
for (auto& field : ci.second.FieldOffsets) {
std::string fieldName = field.first;
auto fieldNodes = componentElement->getElementsByTagName(XS::ToXMLCh(fieldName));
auto fieldNode = fieldNodes->item(0);
if (fieldNode == nullptr) {
LOG_ERROR("Defaults for component \"%s\" is missing field \"%s\"!", componentName.c_str(), fieldName.c_str());
continue;
}
auto fieldElement = dynamic_cast<DOMElement*>(fieldNode);
std::string fieldType = ci.second.FieldTypes.at(fieldName);
unsigned int fieldOffset = ci.second.FieldOffsets.at(fieldName);
char* data = ci.second.Defaults.get() + fieldOffset;
// Handle potential field attributes
if (fieldElement->hasAttributes()) {
std::map<std::string, std::string> attributes;
auto attributeMap = fieldElement->getAttributes();
for (int i = 0; i < attributeMap->getLength(); ++i) {
auto attribItem = attributeMap->item(i);
attributes[XS::ToString(attribItem->getNodeName())] = XS::ToString(attribItem->getNodeValue());
}
EntityFile::WriteAttributeData(data, fieldType, attributes);
}
// Handle potential field values
auto childNode = fieldElement->getFirstChild();
if (childNode != nullptr && childNode->getNodeType() == DOMNode::TEXT_NODE) {
char* cstrValue = XMLString::transcode(childNode->getNodeValue());
EntityFile::WriteValueData(data, fieldType, cstrValue);
XMLString::release(&cstrValue);
}
}
}
}
void onStartComponent(EntityID entity, std::string type);
void parseComponentInfo();
void parseDefaults();
};
-141
View File
@@ -1,141 +0,0 @@
#ifndef EntityXMLFile_h__
#define EntityXMLFile_h__
#include <sstream>
#include "../Common.h"
#include "../GLM.h"
#include <xercesc/dom/DOM.hpp>
#include <xercesc/dom/DOMLSInput.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/framework/Wrapper4InputSource.hpp>
#include <xercesc/framework/LocalFileInputSource.hpp>
#include <xercesc/framework/LocalFileFormatTarget.hpp>
#include <xercesc/framework/MemBufFormatTarget.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLFloat.hpp>
#include <xercesc/framework/XMLGrammarPoolImpl.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/framework/psvi/XSElementDeclaration.hpp>
#include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp>
#include <xercesc/framework/psvi/XSParticle.hpp>
#include <xercesc/framework/psvi/XSModelGroup.hpp>
#include <xercesc/framework/psvi/XSAnnotation.hpp>
#include <xercesc/framework/psvi/XSValue.hpp>
#include <xercesc/framework/XMLValidator.hpp>
#include "ResourceManager.h"
#include "Entity.h"
#include "ComponentInfo.h"
class World;
class EntityPreprocessorXMLErrorHandler : public xercesc::DOMErrorHandler
{
public:
bool handleError(const xercesc::DOMError &e) override
{
char* message = xercesc::XMLString::transcode(e.getMessage());
std::cerr << "Preprocessor DOMError: " << message << std::endl;
xercesc::XMLString::release(&message);
return false;
}
};
class EntityParserXMLErrorHandler : public xercesc::ErrorHandler
{
public:
void warning(const xercesc::SAXParseException& e) override
{
reportParseException("Warning", e);
}
void error(const xercesc::SAXParseException& e) override
{
reportParseException("Error", e);
}
void fatalError(const xercesc::SAXParseException& e) override
{
reportParseException("FATAL ERROR", e);
}
void resetErrors() override { }
private:
void reportParseException(std::string type, const xercesc::SAXParseException& e)
{
char* message = xercesc::XMLString::transcode(e.getMessage());
char* systemID = xercesc::XMLString::transcode(e.getSystemId());
std::cerr << systemID << ":" << e.getLineNumber() << ":" << e.getColumnNumber() << std::endl;
std::cerr << type << ": " << message << std::endl;
xercesc::XMLString::release(&systemID);
xercesc::XMLString::release(&message);
}
};
class XSTR
{
public:
XSTR(const XMLCh* const xmlString)
{
m_AsChar = xercesc::XMLString::transcode(xmlString);
}
XSTR(const char* normalString)
{
m_AsXMLCh = xercesc::XMLString::transcode(normalString);
}
~XSTR()
{
if (m_AsChar != nullptr) {
xercesc::XMLString::release(&m_AsChar);
}
if (m_AsXMLCh != nullptr) {
xercesc::XMLString::release(&m_AsXMLCh);
}
}
operator const char*() const { return m_AsChar; }
operator const XMLCh*() const { return m_AsXMLCh; }
private:
char* m_AsChar = nullptr;
XMLCh* m_AsXMLCh = nullptr;
};
class EntityXMLFile : public Resource
{
friend class ResourceManager;
private:
EntityXMLFile(std::string path);
public:
~EntityXMLFile();
void PopulateWorld(World* world);
private:
static unsigned int InstanceCount;
std::string m_EntityFile;
xercesc::XMLGrammarPool* m_GrammarPool = nullptr;
EntityParserXMLErrorHandler* m_ErrorHandler = nullptr;
xercesc::XercesDOMParser* m_DOMParser = nullptr;
xercesc::DOMDocument* m_DOMDocument = nullptr;
std::map<std::string, ComponentInfo> m_ComponentInfo;
// Preprocesses the entity file to insert include-by-copy child entities
// TODO: Make this work in memory instead of saving to file
void preprocess(std::string inPath, std::string outPath);
void parseComponentInfo();
void parseDefaults();
void predictComponentAllocation();
void parseEntityGraph(World* world, xercesc::DOMElement* parent, EntityID parentEntity);
std::size_t getTypeStride(std::string typeName);
float getFloatAttribute(const xercesc::DOMElement* element, const char* attribute) const;
void writeData(const xercesc::DOMElement* element, std::string typeName, char* outData);
};
#endif