Merge remote-tracking branch 'origin/master' into FixNetworkBugs
This commit is contained in:
+14
-280
@@ -1,291 +1,25 @@
|
||||
#include "Core/EntityFile.h"
|
||||
|
||||
EntityFile::EntityFile(boost::filesystem::path path)
|
||||
: m_FilePath(path)
|
||||
EntityFile::EntityFile(std::string path)
|
||||
{
|
||||
using namespace xercesc;
|
||||
XMLPlatformUtils::Initialize();
|
||||
m_GrammarPool = new XMLGrammarPoolImpl();
|
||||
m_SAX2XMLReader = XMLReaderFactory::createXMLReader(XMLPlatformUtils::fgMemoryManager, m_GrammarPool);
|
||||
}
|
||||
EntityXMLFile* xml = ResourceManager::Load<EntityXMLFile>(path);
|
||||
|
||||
EntityFile::~EntityFile()
|
||||
{
|
||||
delete m_SAX2XMLReader;
|
||||
delete m_GrammarPool;
|
||||
xercesc::XMLPlatformUtils::Terminate();
|
||||
}
|
||||
EntityXMLFilePreprocessor preprocessor(xml);
|
||||
preprocessor.RegisterComponents(this);
|
||||
|
||||
void EntityFile::Parse(const EntityFileHandler* handler) const
|
||||
{
|
||||
using namespace xercesc;
|
||||
EntityXMLFileParser parser(xml);
|
||||
m_RootEntity = parser.MergeEntities(this);
|
||||
|
||||
EntityFileSAXHandler saxHandler(handler, m_SAX2XMLReader);
|
||||
setReaderFeatures(m_SAX2XMLReader);
|
||||
m_SAX2XMLReader->setContentHandler(&saxHandler);
|
||||
m_SAX2XMLReader->setErrorHandler(&saxHandler);
|
||||
m_SAX2XMLReader->setDeclarationHandler(&saxHandler);
|
||||
m_SAX2XMLReader->parse(m_FilePath.string().c_str());
|
||||
}
|
||||
|
||||
void EntityFile::setReaderFeatures(xercesc::SAX2XMLReader* reader)
|
||||
{
|
||||
using namespace xercesc;
|
||||
reader->setFeature(XMLUni::fgXercesCacheGrammarFromParse, true);
|
||||
reader->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true);
|
||||
reader->setFeature(XMLUni::fgSAX2CoreValidation, true);
|
||||
reader->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
|
||||
reader->setFeature(XMLUni::fgXercesSchema, true);
|
||||
reader->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
|
||||
reader->setFeature(XMLUni::fgXercesCalculateSrcOfs, true);
|
||||
reader->setFeature(XMLUni::fgXercesIdentityConstraintChecking, true);
|
||||
}
|
||||
|
||||
unsigned int EntityFile::GetTypeStride(std::string typeName)
|
||||
{
|
||||
std::map<std::string, unsigned int> typeStrides{
|
||||
{ "bool", sizeof(bool) },
|
||||
{ "int", sizeof(int) },
|
||||
{ "float", sizeof(float) },
|
||||
{ "double", sizeof(double) },
|
||||
{ "string", sizeof(std::string) },
|
||||
{ "enum", sizeof(ComponentInfo::EnumType) },
|
||||
{ "Vector", sizeof(glm::vec3) },
|
||||
{ "Quaternion", sizeof(glm::quat) },
|
||||
{ "Color", sizeof(glm::vec4) }
|
||||
};
|
||||
|
||||
auto it = typeStrides.find(typeName);
|
||||
return (it != typeStrides.end()) ? it->second : 0;
|
||||
}
|
||||
|
||||
void EntityFile::WriteAttributeData(char* outData, const ComponentInfo::Field_t& field, const std::map<std::string, std::string>& attributes)
|
||||
{
|
||||
if (field.Type == "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), field.Stride);
|
||||
} else if (field.Type == "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), field.Stride);
|
||||
} else if (field.Type == "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), field.Stride);
|
||||
} else if (!attributes.empty()) {
|
||||
LOG_WARNING("%i attributes not handled by any type conversion!", attributes.size());
|
||||
}
|
||||
}
|
||||
|
||||
void EntityFile::WriteValueData(char* outData, const ComponentInfo::Field_t& field, const char* valueData)
|
||||
{
|
||||
// Catch and ignore casting errors so whitespace around string enums won't mess anything up
|
||||
try {
|
||||
if (field.Type == "int") {
|
||||
int value = boost::lexical_cast<int>(valueData);
|
||||
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
|
||||
} else if (field.Type == "enum") {
|
||||
ComponentInfo::EnumType value = boost::lexical_cast<ComponentInfo::EnumType>(valueData);
|
||||
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
|
||||
} else if (field.Type == "float") {
|
||||
float value = boost::lexical_cast<float>(valueData);
|
||||
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
|
||||
} else if (field.Type == "double") {
|
||||
double value = boost::lexical_cast<double>(valueData);
|
||||
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
|
||||
} else if (field.Type == "bool") {
|
||||
bool value = (valueData[0] == 't'); // Lazy bool evaluation
|
||||
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
|
||||
} else if (field.Type == "string") {
|
||||
new (outData) std::string(valueData);
|
||||
} else {
|
||||
LOG_WARNING("Unknown value data type: %s", field.Type.c_str());
|
||||
}
|
||||
} catch (const boost::bad_lexical_cast&) { }
|
||||
}
|
||||
|
||||
EntityFileSAXHandler::EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader)
|
||||
: m_Handler(handler)
|
||||
, m_Reader(reader)
|
||||
{
|
||||
// 0 is imaginary base parent
|
||||
m_EntityStack.push(0);
|
||||
m_StateStack.push(State::Unknown);
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::startElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname, const xercesc::Attributes& attrs)
|
||||
{
|
||||
std::string name = XS::ToString(_localName);
|
||||
|
||||
if (m_StateStack.top() == State::Unknown || m_StateStack.top() == State::Entity) {
|
||||
if (name == "Entity") {
|
||||
m_StateStack.push(State::Entity);
|
||||
onStartEntity(attrs);
|
||||
return;
|
||||
}
|
||||
if (name == "EntityRef") {
|
||||
onStartEntityRef(attrs);
|
||||
return;
|
||||
}
|
||||
if (m_RootEntity == EntityID_Invalid) {
|
||||
ResourceManager::Release("EntityXMLFile", path);
|
||||
throw Resource::FailedLoadingException("Failed to merge entities; root entity is invalid");
|
||||
}
|
||||
|
||||
std::string uri = XS::ToString(_uri);
|
||||
if (m_StateStack.top() == State::Entity) {
|
||||
if (uri == "components") {
|
||||
m_StateStack.push(State::Component);
|
||||
onStartComponent(name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_StateStack.top() == State::Component) {
|
||||
m_StateStack.push(State::ComponentField);
|
||||
onStartComponentField(name, attrs);
|
||||
return;
|
||||
}
|
||||
ResourceManager::Release("EntityXMLFile", path);
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::endElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname)
|
||||
EntityWrapper EntityFile::MergeInto(World* other)
|
||||
{
|
||||
std::string name = XS::ToString(_localName);
|
||||
if (m_StateStack.top() == State::Entity) {
|
||||
if (name == "Entity") {
|
||||
m_StateStack.pop();
|
||||
onEndEntity();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::string uri = XS::ToString(_uri);
|
||||
if (m_StateStack.top() == State::Component) {
|
||||
//if (uri == "components") {
|
||||
m_StateStack.pop();
|
||||
onEndComponent(name);
|
||||
return;
|
||||
//}
|
||||
}
|
||||
|
||||
if (m_StateStack.top() == State::ComponentField && name == m_CurrentField) {
|
||||
m_StateStack.pop();
|
||||
onEndComponentField(name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::characters(const XMLCh* const chars, const XMLSize_t length)
|
||||
{
|
||||
if (m_StateStack.top() == State::ComponentField) {
|
||||
char* transcoded = xercesc::XMLString::transcode(chars);
|
||||
onFieldData(transcoded);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::fatalError(const xercesc::SAXParseException& e)
|
||||
{
|
||||
std::string message = XS::ToString(e.getMessage());
|
||||
std::string systemId = XS::ToString(e.getSystemId());
|
||||
XMLFileLoc line = e.getLineNumber();
|
||||
XMLFileLoc column = e.getColumnNumber();
|
||||
LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tFatal Error: %s", systemId.c_str(), line, column, message.c_str());
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::error(const xercesc::SAXParseException& e)
|
||||
{
|
||||
std::string message = XS::ToString(e.getMessage());
|
||||
std::string systemId = XS::ToString(e.getSystemId());
|
||||
XMLFileLoc line = e.getLineNumber();
|
||||
XMLFileLoc column = e.getColumnNumber();
|
||||
LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tError: %s", systemId.c_str(), line, column, message.c_str());
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::warning(const xercesc::SAXParseException& e)
|
||||
{
|
||||
std::string message = XS::ToString(e.getMessage());
|
||||
std::string systemId = XS::ToString(e.getSystemId());
|
||||
XMLFileLoc line = e.getLineNumber();
|
||||
XMLFileLoc column = e.getColumnNumber();
|
||||
LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tWarning: %s", systemId.c_str(), line, column, message.c_str());
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::onStartEntity(const xercesc::Attributes& attrs)
|
||||
{
|
||||
EntityID parent = m_EntityStack.top();
|
||||
|
||||
if (m_Handler->m_OnStartEntityCallback) {
|
||||
std::string name;
|
||||
auto xName = attrs.getValue(XS::ToXMLCh("name"));
|
||||
if (xName != nullptr) {
|
||||
name = XS::ToString(xName);
|
||||
}
|
||||
m_Handler->m_OnStartEntityCallback(m_NextEntityID, parent, name);
|
||||
}
|
||||
|
||||
m_EntityStack.push(m_NextEntityID);
|
||||
m_NextEntityID++;
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::onEndEntity()
|
||||
{
|
||||
m_EntityStack.pop();
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::onStartEntityRef(const xercesc::Attributes& attrs)
|
||||
{
|
||||
std::string path = XS::ToString(attrs.getValue(XS::ToXMLCh("file")));
|
||||
|
||||
xercesc::SAX2XMLReader* reader = xercesc::XMLReaderFactory::createXMLReader();
|
||||
EntityFile::setReaderFeatures(reader);
|
||||
reader->setContentHandler(this);
|
||||
reader->setErrorHandler(this);
|
||||
reader->parse(path.c_str());
|
||||
delete reader;
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::onStartComponentField(const std::string& field, const xercesc::Attributes& attrs)
|
||||
{
|
||||
//LOG_DEBUG(" Field: %s", field.c_str());
|
||||
m_CurrentField = field;
|
||||
m_CurrentAttributes.clear();
|
||||
for (int i = 0; i < attrs.getLength(); i++) {
|
||||
auto name = attrs.getQName(i);
|
||||
auto value = attrs.getValue(name);
|
||||
//LOG_DEBUG(" %s = %s", (char*)XS::ToString(name), (char*)XS::ToString(value));
|
||||
m_CurrentAttributes[XS::ToString(name).operator std::string()] = XS::ToString(value).operator std::string();
|
||||
}
|
||||
|
||||
if (m_Handler->m_OnStartFieldCallback) {
|
||||
m_Handler->m_OnStartFieldCallback(m_EntityStack.top(), m_CurrentComponent, field, m_CurrentAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::onEndComponent(const std::string& name) { }
|
||||
|
||||
void EntityFileSAXHandler::onStartComponent(const std::string& name)
|
||||
{
|
||||
//LOG_DEBUG(" Component: %s", name.c_str());
|
||||
m_CurrentComponent = name;
|
||||
if (m_Handler->m_OnStartComponentCallback) {
|
||||
m_Handler->m_OnStartComponentCallback(m_EntityStack.top(), name);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::onEndComponentField(const std::string& field) { }
|
||||
|
||||
void EntityFileSAXHandler::onFieldData(char* data)
|
||||
{
|
||||
//LOG_DEBUG(" Data: %s", data);
|
||||
if (m_Handler->m_OnStartFieldDataCallback) {
|
||||
m_Handler->m_OnStartFieldDataCallback(m_EntityStack.top(), m_CurrentComponent, m_CurrentField, data);
|
||||
}
|
||||
|
||||
xercesc::XMLString::release(&data);
|
||||
}
|
||||
auto mapping = other->Merge(this);
|
||||
return EntityWrapper(other, mapping.at(m_RootEntity));
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
#include "Core/EntityXMLFile.h"
|
||||
|
||||
EntityXMLFile::EntityXMLFile(boost::filesystem::path path)
|
||||
: m_FilePath(path)
|
||||
{
|
||||
using namespace xercesc;
|
||||
XMLPlatformUtils::Initialize();
|
||||
m_GrammarPool = new XMLGrammarPoolImpl();
|
||||
m_SAX2XMLReader = XMLReaderFactory::createXMLReader(XMLPlatformUtils::fgMemoryManager, m_GrammarPool);
|
||||
}
|
||||
|
||||
EntityXMLFile::~EntityXMLFile()
|
||||
{
|
||||
delete m_SAX2XMLReader;
|
||||
delete m_GrammarPool;
|
||||
xercesc::XMLPlatformUtils::Terminate();
|
||||
}
|
||||
|
||||
void EntityXMLFile::Parse(const EntityFileHandler* handler) const
|
||||
{
|
||||
using namespace xercesc;
|
||||
|
||||
EntityFileSAXHandler saxHandler(handler, m_SAX2XMLReader);
|
||||
setReaderFeatures(m_SAX2XMLReader);
|
||||
m_SAX2XMLReader->setContentHandler(&saxHandler);
|
||||
m_SAX2XMLReader->setErrorHandler(&saxHandler);
|
||||
m_SAX2XMLReader->setDeclarationHandler(&saxHandler);
|
||||
m_SAX2XMLReader->parse(m_FilePath.string().c_str());
|
||||
}
|
||||
|
||||
void EntityXMLFile::setReaderFeatures(xercesc::SAX2XMLReader* reader)
|
||||
{
|
||||
using namespace xercesc;
|
||||
reader->setFeature(XMLUni::fgXercesCacheGrammarFromParse, true);
|
||||
reader->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true);
|
||||
reader->setFeature(XMLUni::fgSAX2CoreValidation, true);
|
||||
reader->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
|
||||
reader->setFeature(XMLUni::fgXercesSchema, true);
|
||||
reader->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
|
||||
reader->setFeature(XMLUni::fgXercesCalculateSrcOfs, true);
|
||||
reader->setFeature(XMLUni::fgXercesIdentityConstraintChecking, true);
|
||||
}
|
||||
|
||||
unsigned int EntityXMLFile::GetTypeStride(std::string typeName)
|
||||
{
|
||||
std::map<std::string, unsigned int> typeStrides{
|
||||
{ "bool", sizeof(bool) },
|
||||
{ "int", sizeof(int) },
|
||||
{ "float", sizeof(float) },
|
||||
{ "double", sizeof(double) },
|
||||
{ "string", sizeof(std::string) },
|
||||
{ "enum", sizeof(ComponentInfo::EnumType) },
|
||||
{ "Vector", sizeof(glm::vec3) },
|
||||
{ "Quaternion", sizeof(glm::quat) },
|
||||
{ "Color", sizeof(glm::vec4) }
|
||||
};
|
||||
|
||||
auto it = typeStrides.find(typeName);
|
||||
return (it != typeStrides.end()) ? it->second : 0;
|
||||
}
|
||||
|
||||
void EntityXMLFile::WriteAttributeData(char* outData, const ComponentInfo::Field_t& field, const std::map<std::string, std::string>& attributes)
|
||||
{
|
||||
if (field.Type == "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), field.Stride);
|
||||
} else if (field.Type == "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), field.Stride);
|
||||
} else if (field.Type == "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), field.Stride);
|
||||
} else if (!attributes.empty()) {
|
||||
LOG_WARNING("%i attributes not handled by any type conversion!", attributes.size());
|
||||
}
|
||||
}
|
||||
|
||||
void EntityXMLFile::WriteValueData(char* outData, const ComponentInfo::Field_t& field, const char* valueData)
|
||||
{
|
||||
// Catch and ignore casting errors so whitespace around string enums won't mess anything up
|
||||
try {
|
||||
if (field.Type == "int") {
|
||||
int value = boost::lexical_cast<int>(valueData);
|
||||
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
|
||||
} else if (field.Type == "enum") {
|
||||
ComponentInfo::EnumType value = boost::lexical_cast<ComponentInfo::EnumType>(valueData);
|
||||
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
|
||||
} else if (field.Type == "float") {
|
||||
float value = boost::lexical_cast<float>(valueData);
|
||||
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
|
||||
} else if (field.Type == "double") {
|
||||
double value = boost::lexical_cast<double>(valueData);
|
||||
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
|
||||
} else if (field.Type == "bool") {
|
||||
bool value = (valueData[0] == 't'); // Lazy bool evaluation
|
||||
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
|
||||
} else if (field.Type == "string") {
|
||||
new (outData) std::string(valueData);
|
||||
} else {
|
||||
LOG_WARNING("Unknown value data type: %s", field.Type.c_str());
|
||||
}
|
||||
} catch (const boost::bad_lexical_cast&) { }
|
||||
}
|
||||
|
||||
EntityFileSAXHandler::EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader)
|
||||
: m_Handler(handler)
|
||||
, m_Reader(reader)
|
||||
{
|
||||
// 0 is imaginary base parent
|
||||
m_EntityStack.push(0);
|
||||
m_StateStack.push(State::Unknown);
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::startElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname, const xercesc::Attributes& attrs)
|
||||
{
|
||||
std::string name = XS::ToString(_localName);
|
||||
|
||||
if (m_StateStack.top() == State::Unknown || m_StateStack.top() == State::Entity) {
|
||||
if (name == "Entity") {
|
||||
m_StateStack.push(State::Entity);
|
||||
onStartEntity(attrs);
|
||||
return;
|
||||
}
|
||||
if (name == "EntityRef") {
|
||||
onStartEntityRef(attrs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::string uri = XS::ToString(_uri);
|
||||
if (m_StateStack.top() == State::Entity) {
|
||||
if (uri == "components") {
|
||||
m_StateStack.push(State::Component);
|
||||
onStartComponent(name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_StateStack.top() == State::Component) {
|
||||
m_StateStack.push(State::ComponentField);
|
||||
onStartComponentField(name, attrs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::endElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname)
|
||||
{
|
||||
std::string name = XS::ToString(_localName);
|
||||
if (m_StateStack.top() == State::Entity) {
|
||||
if (name == "Entity") {
|
||||
m_StateStack.pop();
|
||||
onEndEntity();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::string uri = XS::ToString(_uri);
|
||||
if (m_StateStack.top() == State::Component) {
|
||||
//if (uri == "components") {
|
||||
m_StateStack.pop();
|
||||
onEndComponent(name);
|
||||
return;
|
||||
//}
|
||||
}
|
||||
|
||||
if (m_StateStack.top() == State::ComponentField && name == m_CurrentField) {
|
||||
m_StateStack.pop();
|
||||
onEndComponentField(name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::characters(const XMLCh* const chars, const XMLSize_t length)
|
||||
{
|
||||
if (m_StateStack.top() == State::ComponentField) {
|
||||
char* transcoded = xercesc::XMLString::transcode(chars);
|
||||
onFieldData(transcoded);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::fatalError(const xercesc::SAXParseException& e)
|
||||
{
|
||||
std::string message = XS::ToString(e.getMessage());
|
||||
std::string systemId = XS::ToString(e.getSystemId());
|
||||
XMLFileLoc line = e.getLineNumber();
|
||||
XMLFileLoc column = e.getColumnNumber();
|
||||
LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tFatal Error: %s", systemId.c_str(), line, column, message.c_str());
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::error(const xercesc::SAXParseException& e)
|
||||
{
|
||||
std::string message = XS::ToString(e.getMessage());
|
||||
std::string systemId = XS::ToString(e.getSystemId());
|
||||
XMLFileLoc line = e.getLineNumber();
|
||||
XMLFileLoc column = e.getColumnNumber();
|
||||
LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tError: %s", systemId.c_str(), line, column, message.c_str());
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::warning(const xercesc::SAXParseException& e)
|
||||
{
|
||||
std::string message = XS::ToString(e.getMessage());
|
||||
std::string systemId = XS::ToString(e.getSystemId());
|
||||
XMLFileLoc line = e.getLineNumber();
|
||||
XMLFileLoc column = e.getColumnNumber();
|
||||
LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tWarning: %s", systemId.c_str(), line, column, message.c_str());
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::onStartEntity(const xercesc::Attributes& attrs)
|
||||
{
|
||||
EntityID parent = m_EntityStack.top();
|
||||
|
||||
if (m_Handler->m_OnStartEntityCallback) {
|
||||
std::string name;
|
||||
auto xName = attrs.getValue(XS::ToXMLCh("name"));
|
||||
if (xName != nullptr) {
|
||||
name = XS::ToString(xName);
|
||||
}
|
||||
m_Handler->m_OnStartEntityCallback(m_NextEntityID, parent, name);
|
||||
}
|
||||
|
||||
m_EntityStack.push(m_NextEntityID);
|
||||
m_NextEntityID++;
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::onEndEntity()
|
||||
{
|
||||
m_EntityStack.pop();
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::onStartEntityRef(const xercesc::Attributes& attrs)
|
||||
{
|
||||
std::string path = XS::ToString(attrs.getValue(XS::ToXMLCh("file")));
|
||||
|
||||
xercesc::SAX2XMLReader* reader = xercesc::XMLReaderFactory::createXMLReader();
|
||||
EntityXMLFile::setReaderFeatures(reader);
|
||||
reader->setContentHandler(this);
|
||||
reader->setErrorHandler(this);
|
||||
reader->parse(path.c_str());
|
||||
delete reader;
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::onStartComponentField(const std::string& field, const xercesc::Attributes& attrs)
|
||||
{
|
||||
//LOG_DEBUG(" Field: %s", field.c_str());
|
||||
m_CurrentField = field;
|
||||
m_CurrentAttributes.clear();
|
||||
for (int i = 0; i < attrs.getLength(); i++) {
|
||||
auto name = attrs.getQName(i);
|
||||
auto value = attrs.getValue(name);
|
||||
//LOG_DEBUG(" %s = %s", (char*)XS::ToString(name), (char*)XS::ToString(value));
|
||||
m_CurrentAttributes[XS::ToString(name).operator std::string()] = XS::ToString(value).operator std::string();
|
||||
}
|
||||
|
||||
if (m_Handler->m_OnStartFieldCallback) {
|
||||
m_Handler->m_OnStartFieldCallback(m_EntityStack.top(), m_CurrentComponent, field, m_CurrentAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::onEndComponent(const std::string& name) { }
|
||||
|
||||
void EntityFileSAXHandler::onStartComponent(const std::string& name)
|
||||
{
|
||||
//LOG_DEBUG(" Component: %s", name.c_str());
|
||||
m_CurrentComponent = name;
|
||||
if (m_Handler->m_OnStartComponentCallback) {
|
||||
m_Handler->m_OnStartComponentCallback(m_EntityStack.top(), name);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::onEndComponentField(const std::string& field) { }
|
||||
|
||||
void EntityFileSAXHandler::onFieldData(char* data)
|
||||
{
|
||||
//LOG_DEBUG(" Data: %s", data);
|
||||
if (m_Handler->m_OnStartFieldDataCallback) {
|
||||
m_Handler->m_OnStartFieldDataCallback(m_EntityStack.top(), m_CurrentComponent, m_CurrentField, data);
|
||||
}
|
||||
|
||||
xercesc::XMLString::release(&data);
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
#include "Core/EntityFileParser.h"
|
||||
#include "Core/EntityXMLFileParser.h"
|
||||
|
||||
EntityFileParser::EntityFileParser(const EntityFile* entityFile)
|
||||
EntityXMLFileParser::EntityXMLFileParser(const EntityXMLFile* entityFile)
|
||||
: m_EntityFile(entityFile)
|
||||
{
|
||||
m_Handler.SetStartEntityCallback(std::bind(&EntityFileParser::onStartEntity, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
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));
|
||||
m_Handler.SetStartEntityCallback(std::bind(&EntityXMLFileParser::onStartEntity, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
m_Handler.SetStartComponentCallback(std::bind(&EntityXMLFileParser::onStartComponent, this, std::placeholders::_1, std::placeholders::_2));
|
||||
m_Handler.SetStartFieldCallback(std::bind(&EntityXMLFileParser::onStartComponentField, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||
m_Handler.SetStartFieldDataCallback(std::bind(&EntityXMLFileParser::onFieldData, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||
}
|
||||
|
||||
EntityID EntityFileParser::MergeEntities(World* world, EntityID baseParent /*= EntityID_Invalid */)
|
||||
EntityID EntityXMLFileParser::MergeEntities(World* world, EntityID baseParent /*= EntityID_Invalid */)
|
||||
{
|
||||
m_World = world;
|
||||
m_EntityIDMapper[0] = baseParent;
|
||||
@@ -17,7 +17,7 @@ EntityID EntityFileParser::MergeEntities(World* world, EntityID baseParent /*= E
|
||||
return m_FirstEntity;
|
||||
}
|
||||
|
||||
void EntityFileParser::onStartEntity(EntityID entity, EntityID parent, const std::string& name)
|
||||
void EntityXMLFileParser::onStartEntity(EntityID entity, EntityID parent, const std::string& name)
|
||||
{
|
||||
EntityID realParent = m_EntityIDMapper.at(parent);
|
||||
EntityID realEntity = m_World->CreateEntity(realParent);
|
||||
@@ -31,7 +31,7 @@ void EntityFileParser::onStartEntity(EntityID entity, EntityID parent, const std
|
||||
//LOG_DEBUG("Created entity #%i (%i) with parent %i (%i)", entity, realEntity, parent, realParent);
|
||||
}
|
||||
|
||||
void EntityFileParser::onStartComponent(EntityID entity, const std::string& component)
|
||||
void EntityXMLFileParser::onStartComponent(EntityID entity, const std::string& component)
|
||||
{
|
||||
if (m_World->GetComponentPools().count(component) != 0) {
|
||||
EntityID realEntity = m_EntityIDMapper.at(entity);
|
||||
@@ -42,7 +42,7 @@ void EntityFileParser::onStartComponent(EntityID entity, const std::string& comp
|
||||
//LOG_DEBUG("Attached component of type \"%s\" to entity #%i (%i)", component.c_str(), entity, realEntity);
|
||||
}
|
||||
|
||||
void EntityFileParser::onStartComponentField(EntityID entity, const std::string& componentType, const std::string& fieldName, const std::map<std::string, std::string>& attributes)
|
||||
void EntityXMLFileParser::onStartComponentField(EntityID entity, const std::string& componentType, const std::string& fieldName, const std::map<std::string, std::string>& attributes)
|
||||
{
|
||||
if (m_World->GetComponentPools().count(componentType) == 0) {
|
||||
return;
|
||||
@@ -63,10 +63,10 @@ void EntityFileParser::onStartComponentField(EntityID entity, const std::string&
|
||||
//}
|
||||
|
||||
char* data = component.Data + field.Offset;
|
||||
EntityFile::WriteAttributeData(data, field, attributes);
|
||||
EntityXMLFile::WriteAttributeData(data, field, attributes);
|
||||
}
|
||||
|
||||
void EntityFileParser::onFieldData(EntityID entity, const std::string& componentType, const std::string& fieldName, const char* fieldData)
|
||||
void EntityXMLFileParser::onFieldData(EntityID entity, const std::string& componentType, const std::string& fieldName, const char* fieldData)
|
||||
{
|
||||
if (m_World->GetComponentPools().count(componentType) == 0) {
|
||||
return;
|
||||
@@ -80,5 +80,5 @@ void EntityFileParser::onFieldData(EntityID entity, const std::string& component
|
||||
auto& field = fieldIt->second;
|
||||
|
||||
char* data = component.Data + field.Offset;
|
||||
EntityFile::WriteValueData(data, field, fieldData);
|
||||
EntityXMLFile::WriteValueData(data, field, fieldData);
|
||||
}
|
||||
+12
-12
@@ -1,10 +1,10 @@
|
||||
#include "Core/EntityFilePreprocessor.h"
|
||||
#include "Core/EntityXMLFilePreprocessor.h"
|
||||
|
||||
EntityFilePreprocessor::EntityFilePreprocessor(const EntityFile* entityFile)
|
||||
EntityXMLFilePreprocessor::EntityXMLFilePreprocessor(const EntityXMLFile* entityFile)
|
||||
: m_EntityFile(entityFile)
|
||||
{
|
||||
EntityFileHandler handler;
|
||||
handler.SetStartComponentCallback(std::bind(&EntityFilePreprocessor::onStartComponent, this, std::placeholders::_1, std::placeholders::_2));
|
||||
handler.SetStartComponentCallback(std::bind(&EntityXMLFilePreprocessor::onStartComponent, this, std::placeholders::_1, std::placeholders::_2));
|
||||
m_EntityFile->Parse(&handler);
|
||||
|
||||
//LOG_DEBUG("___ COMPONENT DEFINITIONS ___");
|
||||
@@ -28,20 +28,20 @@ EntityFilePreprocessor::EntityFilePreprocessor(const EntityFile* entityFile)
|
||||
parseDefaults();
|
||||
}
|
||||
|
||||
void EntityFilePreprocessor::RegisterComponents(World* world)
|
||||
void EntityXMLFilePreprocessor::RegisterComponents(World* world)
|
||||
{
|
||||
for (auto& kv : m_ComponentInfo) {
|
||||
world->RegisterComponent(kv.second);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityFilePreprocessor::onStartComponent(EntityID entity, std::string type)
|
||||
void EntityXMLFilePreprocessor::onStartComponent(EntityID entity, std::string type)
|
||||
{
|
||||
//LOG_DEBUG("Component: %s", type.c_str());
|
||||
m_ComponentCounts[type]++;
|
||||
}
|
||||
|
||||
void EntityFilePreprocessor::parseComponentInfo()
|
||||
void EntityXMLFilePreprocessor::parseComponentInfo()
|
||||
{
|
||||
using namespace xercesc;
|
||||
EntityFileXMLErrorHandler errorHandler;
|
||||
@@ -141,9 +141,9 @@ void EntityFilePreprocessor::parseComponentInfo()
|
||||
std::string baseType = XS::ToString(elementDeclaration->getTypeDefinition()->getBaseType()->getName());
|
||||
|
||||
std::string effectiveType = type;
|
||||
unsigned int stride = EntityFile::GetTypeStride(type);
|
||||
unsigned int stride = EntityXMLFile::GetTypeStride(type);
|
||||
if (stride == 0) {
|
||||
stride = EntityFile::GetTypeStride(baseType);
|
||||
stride = EntityXMLFile::GetTypeStride(baseType);
|
||||
if (stride == 0) {
|
||||
LOG_WARNING("Field \"%s\" in component \"%s\" uses unexpected field type \"%s\" with base type \"%s\". Skipping.", name.c_str(), compInfo.Name.c_str(), type.c_str(), baseType.c_str());
|
||||
continue;
|
||||
@@ -196,7 +196,7 @@ void EntityFilePreprocessor::parseComponentInfo()
|
||||
}
|
||||
}
|
||||
|
||||
void EntityFilePreprocessor::parseDefaults()
|
||||
void EntityXMLFilePreprocessor::parseDefaults()
|
||||
{
|
||||
using namespace xercesc;
|
||||
|
||||
@@ -261,7 +261,7 @@ void EntityFilePreprocessor::parseDefaults()
|
||||
auto attribItem = attributeMap->item(i);
|
||||
attributes[XS::ToString(attribItem->getNodeName())] = XS::ToString(attribItem->getNodeValue());
|
||||
}
|
||||
EntityFile::WriteAttributeData(data, field, attributes);
|
||||
EntityXMLFile::WriteAttributeData(data, field, attributes);
|
||||
}
|
||||
|
||||
auto childNode = fieldElement->getFirstChild();
|
||||
@@ -278,14 +278,14 @@ void EntityFilePreprocessor::parseDefaults()
|
||||
// Handle potential field values
|
||||
if (childNode->getNodeType() == DOMNode::TEXT_NODE) {
|
||||
char* cstrValue = XMLString::transcode(childNode->getNodeValue());
|
||||
EntityFile::WriteValueData(data, field, cstrValue);
|
||||
EntityXMLFile::WriteValueData(data, field, cstrValue);
|
||||
XMLString::release(&cstrValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string EntityFilePreprocessor::parseAnnotationXML(const XMLCh* xml)
|
||||
std::string EntityXMLFilePreprocessor::parseAnnotationXML(const XMLCh* xml)
|
||||
{
|
||||
using namespace xercesc;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#include "Core/EntityFileWriter.h"
|
||||
#include "Core/EntityXMLFileWriter.h"
|
||||
|
||||
#define X(str) XS::ToXMLCh(str)
|
||||
|
||||
void EntityFileWriter::WriteWorld(World* world)
|
||||
void EntityXMLFileWriter::WriteWorld(World* world)
|
||||
{
|
||||
WriteEntity(world, 0);
|
||||
}
|
||||
|
||||
void EntityFileWriter::WriteEntity(World* world, EntityID entity)
|
||||
void EntityXMLFileWriter::WriteEntity(World* world, EntityID entity)
|
||||
{
|
||||
using namespace xercesc;
|
||||
DOMDocument* doc = m_DOMImplementation->createDocument(nullptr, X("Entity"), nullptr);
|
||||
@@ -41,7 +41,7 @@ void EntityFileWriter::WriteEntity(World* world, EntityID entity)
|
||||
doc->release();
|
||||
}
|
||||
|
||||
void EntityFileWriter::appendEntityChildren(xercesc::DOMElement* parentElement, const World* world, EntityID entity)
|
||||
void EntityXMLFileWriter::appendEntityChildren(xercesc::DOMElement* parentElement, const World* world, EntityID entity)
|
||||
{
|
||||
using namespace xercesc;
|
||||
DOMDocument* doc = parentElement->getOwnerDocument();
|
||||
@@ -67,7 +67,7 @@ void EntityFileWriter::appendEntityChildren(xercesc::DOMElement* parentElement,
|
||||
}
|
||||
}
|
||||
|
||||
void EntityFileWriter::appentEntityComponents(xercesc::DOMElement* parentElement, const World* world, EntityID entity)
|
||||
void EntityXMLFileWriter::appentEntityComponents(xercesc::DOMElement* parentElement, const World* world, EntityID entity)
|
||||
{
|
||||
using namespace xercesc;
|
||||
DOMDocument* doc = parentElement->getOwnerDocument();
|
||||
@@ -45,7 +45,7 @@ bool World::ValidEntity(EntityID entity) const
|
||||
return m_EntityParents.find(entity) != m_EntityParents.end();
|
||||
}
|
||||
|
||||
void World::RegisterComponent(ComponentInfo& ci)
|
||||
void World::RegisterComponent(const ComponentInfo& ci)
|
||||
{
|
||||
if (m_ComponentPools.find(ci.Name) == m_ComponentPools.end()) {
|
||||
m_ComponentPools[ci.Name] = new ComponentPool(ci);
|
||||
@@ -169,6 +169,45 @@ EntityWrapper World::GetFirstEntityByName(const std::string& name)
|
||||
return EntityWrapper::Invalid;
|
||||
}
|
||||
|
||||
std::unordered_map<EntityID, EntityID> World::Merge(const World* other)
|
||||
{
|
||||
std::unordered_map<EntityID, EntityID> oldToNew;
|
||||
|
||||
// Create new entities
|
||||
for (auto& kv : other->m_EntityParents) {
|
||||
EntityID entity = kv.first;
|
||||
|
||||
EntityID newEntity = CreateEntity();
|
||||
SetName(newEntity, other->GetName(entity));
|
||||
oldToNew[entity] = newEntity;
|
||||
}
|
||||
// Fix relationships
|
||||
for (auto& kv : other->m_EntityParents) {
|
||||
EntityID entity = kv.first;
|
||||
EntityID parent = kv.second;
|
||||
if (parent != EntityID_Invalid) {
|
||||
SetParent(oldToNew.at(entity), oldToNew.at(parent));
|
||||
}
|
||||
}
|
||||
|
||||
// Transfer components
|
||||
for (auto& kv : other->m_ComponentPools) {
|
||||
auto& componentType = kv.first;
|
||||
ComponentPool* pool = kv.second;
|
||||
// Register pool if it's not present in world
|
||||
if (m_ComponentPools.count(componentType) == 0) {
|
||||
RegisterComponent(pool->ComponentInfo());
|
||||
}
|
||||
// Copy components
|
||||
for (auto component : *pool) {
|
||||
ComponentWrapper newComponent = AttachComponent(oldToNew.at(component.EntityID), componentType);
|
||||
component.Copy(newComponent);
|
||||
}
|
||||
}
|
||||
|
||||
return oldToNew;
|
||||
}
|
||||
|
||||
EntityID World::generateEntityID()
|
||||
{
|
||||
// TODO: Make EntityID generation smarter
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "Core/UniformScaleSystem.h"
|
||||
#include "Editor/EditorRenderSystem.h"
|
||||
#include "Editor/EditorWidgetSystem.h"
|
||||
#include "Core/EntityFile.h"
|
||||
|
||||
EditorSystem::EditorSystem(SystemParams params, IRenderer* renderer, RenderFrame* renderFrame)
|
||||
: System(params)
|
||||
@@ -129,7 +130,7 @@ void EditorSystem::OnEntitySelected(EntityWrapper entity)
|
||||
|
||||
void EditorSystem::OnEntitySave(EntityWrapper entity, boost::filesystem::path filePath)
|
||||
{
|
||||
EntityFileWriter writer(filePath);
|
||||
EntityXMLFileWriter writer(filePath);
|
||||
writer.WriteEntity(entity.World, entity.ID);
|
||||
}
|
||||
|
||||
@@ -260,11 +261,9 @@ EntityWrapper EditorSystem::importEntity(EntityWrapper parent, boost::filesystem
|
||||
|
||||
try {
|
||||
auto entityFile = ResourceManager::Load<EntityFile>(filePath.string());
|
||||
EntityFilePreprocessor fpp(entityFile);
|
||||
fpp.RegisterComponents(parent.World);
|
||||
EntityFileParser fp(entityFile);
|
||||
EntityID newEntity = fp.MergeEntities(parent.World, parent.ID);
|
||||
return EntityWrapper(parent.World, newEntity);
|
||||
EntityWrapper newEntity = entityFile->MergeInto(parent.World);
|
||||
parent.World->SetParent(newEntity.ID, parent.ID);
|
||||
return newEntity;
|
||||
} catch (const std::exception& e) {
|
||||
LOG_ERROR("Failed to import entity \"%s\": \"%s\"", filePath.string().c_str(), e.what());
|
||||
return EntityWrapper::Invalid;
|
||||
|
||||
@@ -70,7 +70,7 @@ void FrameBuffer::Generate()
|
||||
}
|
||||
GLERROR("3");
|
||||
|
||||
GLenum* bufferTextures = &attachments[0];
|
||||
GLenum* bufferTextures = attachments.data();
|
||||
glDrawBuffers(attachments.size(), bufferTextures);
|
||||
if (GLERROR("GLBufferAttachement error")) {
|
||||
printf(": AttachmentSize %i", attachments.size());
|
||||
|
||||
Reference in New Issue
Block a user