Added enum support to entity file format, see "Team" component for an example. Use ComponentInfo::Enum to convert enum string keys to its corresponding integer representation at runtime.

This commit is contained in:
2016-01-16 22:48:08 +01:00
parent f65ac65e30
commit 9ec32464bc
17 changed files with 383 additions and 222 deletions
+4 -2
View File
@@ -9,7 +9,8 @@ struct ComponentInfo
{
std::string Annotation;
unsigned int Allocation = 0;
unsigned int Stride = 0;
std::map<std::string, std::string> FieldAnnotations;
std::map<std::string, std::map<std::string, int>> FieldEnumDefinitions;
};
struct Field_t
@@ -23,8 +24,9 @@ struct ComponentInfo
std::string Name;
std::unordered_map<std::string, Field_t> Fields;
std::vector<std::string> FieldsInOrder;
Meta_t Meta;
unsigned int Stride = 0;
std::shared_ptr<char> Defaults = nullptr;
std::shared_ptr<Meta_t> Meta = nullptr;
};
template<>
+1 -1
View File
@@ -43,7 +43,7 @@ public:
ComponentPool(const ::ComponentInfo& ci)
: m_ComponentInfo(ci)
, m_Pool(ci.Meta.Allocation, sizeof(EntityID) + ci.Meta.Stride)
, m_Pool(ci.Meta->Allocation, sizeof(EntityID) + ci.Stride)
{ }
ComponentPool(const ComponentPool& other) = delete;
ComponentPool(const ComponentPool&& other) = delete;
+14 -5
View File
@@ -6,6 +6,7 @@
#include "ComponentInfo.h"
#include "Util/Any.h"
// TODO: Change all instances "Property" to "Field" to remain consistent with ComponentInfo
struct ComponentWrapper
{
ComponentWrapper(const ComponentInfo& componentInfo, char* data)
@@ -18,6 +19,11 @@ struct ComponentWrapper
const ::EntityID EntityID;
char* Data;
int Enum(const char* fieldName, const char* enumKey)
{
return Info.Meta->FieldEnumDefinitions.at(fieldName).at(enumKey);
}
template <typename T>
T& Property(std::string name)
{
@@ -33,7 +39,7 @@ struct ComponentWrapper
// Specialization for string literals
template <std::size_t N>
void SetProperty(std::string name, const char(&value)[N]) { Property<std::string>(name) = std::string(value); }
struct SubscriptProxy
{
friend struct ComponentWrapper;
@@ -47,6 +53,9 @@ struct ComponentWrapper
std::string m_PropertyName;
public:
// Return the integer value of an enum type key for this field
int Enum(const char* enumKey) { return m_Component->Enum(m_PropertyName.c_str(), enumKey); }
template <typename T>
operator T&() { return m_Component->Property<T>(m_PropertyName); }
@@ -71,7 +80,7 @@ public:
ComponentWrapperFactory(std::string componentTypeName, std::size_t allocation = 0)
{
m_ComponentInfo.Name = componentTypeName;
m_ComponentInfo.Meta.Allocation = allocation;
m_ComponentInfo.Meta->Allocation = allocation;
}
template <typename T>
@@ -79,14 +88,14 @@ public:
{
m_DefaultValues.push_back(defaultValue);
m_ComponentInfo.Fields[fieldName].Name = typeid(T).name();
m_ComponentInfo.Fields[fieldName].Offset = m_ComponentInfo.Meta.Stride;
m_ComponentInfo.Fields[fieldName].Offset = m_ComponentInfo.Stride;
m_ComponentInfo.Fields[fieldName].Stride = sizeof(T);
m_ComponentInfo.Meta.Stride += sizeof(T);
m_ComponentInfo.Stride += sizeof(T);
}
ComponentInfo& Finalize()
{
m_ComponentInfo.Defaults = std::shared_ptr<char>(new char[m_ComponentInfo.Meta.Stride]);
m_ComponentInfo.Defaults = std::shared_ptr<char>(new char[m_ComponentInfo.Stride]);
std::size_t offset = 0;
for (auto& val : m_DefaultValues) {
memcpy(m_ComponentInfo.Defaults.get() + offset, val.Data.get(), val.Size);
+8 -8
View File
@@ -285,7 +285,7 @@ private:
XSValue::Status status;
XSValue* val = XSValue::getActualValue(child->getNodeValue(), XSValue::dt_integer, status);
compInfo.Meta.Allocation += val->fData.fValue.f_int;
compInfo.Meta->Allocation += val->fData.fValue.f_int;
}
// Save documentation string
@@ -293,11 +293,11 @@ private:
if (documentationTags->getLength() != 0) {
auto child = documentationTags->item(0)->getFirstChild();
if (child != nullptr) {
compInfo.Meta.Annotation = XSTR(child->getNodeValue());
compInfo.Meta->Annotation = XSTR(child->getNodeValue());
}
}
// TODO: Parse annotation string XML
// compInfo.Meta.Allocation = ...
// compInfo.Meta->Allocation = ...
} else {
std::cout << "Warning: Component is missing an annotation!" << std::endl;
}
@@ -344,7 +344,7 @@ private:
fieldOffset += getTypeStride(type);
}
compInfo.Meta.Stride = fieldOffset;
compInfo.Stride = fieldOffset;
m_ComponentInfo[compInfo.Name] = compInfo;
}
}
@@ -367,14 +367,14 @@ private:
std::string componentName = XSTR(component->getLocalName());
auto& compInfo = m_ComponentInfo.at(componentName);
compInfo.Meta.Allocation += 1;
compInfo.Meta->Allocation += 1;
}
std::cout << "COMPONENT INFO" << std::endl;
for (auto& pair : m_ComponentInfo) {
ComponentInfo& ci = pair.second;
std::cout << "Component: " << ci.Name << " (" << ci.Meta.Annotation << ")" << std::endl;
std::cout << " Allocation: " << ci.Meta.Allocation << std::endl;
std::cout << "Component: " << ci.Name << " (" << ci.Meta->Annotation << ")" << std::endl;
std::cout << " Allocation: " << ci.Meta->Allocation << std::endl;
std::cout << " Fields:" << std::endl;
// Calculate component size
@@ -393,7 +393,7 @@ private:
cs.ComponentName = ci.Name;
cs.Stride = stride;
cs.Info = ci;
cs.Data = new char[stride*ci.Meta.Allocation];
cs.Data = new char[stride*ci.Meta->Allocation];
m_ComponentStore[cs.ComponentName] = cs;
}
}
+18 -147
View File
@@ -73,88 +73,15 @@ public:
ComponentField
};
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);
}
EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader);
void startElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname, const xercesc::Attributes& attrs) override
{
std::string name = XS::ToString(_localName);
void startElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname, const xercesc::Attributes& attrs) override;
void characters(const XMLCh* const chars, const XMLSize_t length) override;
void endElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname) override;
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 characters(const XMLCh* const chars, const XMLSize_t length) override
{
if (m_StateStack.top() == State::ComponentField) {
char* transcoded = xercesc::XMLString::transcode(chars);
onFieldData(transcoded);
}
}
void endElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname) override
{
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) {
m_StateStack.pop();
onEndComponentField(name);
return;
}
}
void fatalError(const xercesc::SAXParseException& e)
{
XS::ToString s(e.getMessage());
LOG_ERROR("SAXParseException: %s", ((std::string)s).c_str());
//throw e;
}
void warning(const xercesc::SAXParseException& e);
void error(const xercesc::SAXParseException& e);
void fatalError(const xercesc::SAXParseException& e);
private:
const EntityFileHandler* m_Handler;
@@ -168,73 +95,14 @@ private:
std::string m_CurrentField;
std::map<std::string, std::string> m_CurrentAttributes;
void 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 onEndEntity()
{
m_EntityStack.pop();
}
void onStartEntityRef(const xercesc::Attributes& attrs)
{
std::string path = XS::ToString(attrs.getValue(XS::ToXMLCh("file")));
xercesc::SAX2XMLReader* parser = xercesc::XMLReaderFactory::createXMLReader();
parser->setContentHandler(this);
parser->setErrorHandler(this);
parser->parse(path.c_str());
delete parser;
}
void 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 onEndComponent(const std::string& name) { }
void 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 onEndComponentField(const std::string& field) { }
void 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);
}
void onStartEntity(const xercesc::Attributes& attrs);
void onEndEntity();
void onStartEntityRef(const xercesc::Attributes& attrs);
void onStartComponent(const std::string& name);
void onEndComponent(const std::string& name);
void onStartComponentField(const std::string& field, const xercesc::Attributes& attrs);
void onEndComponentField(const std::string& field);
void onFieldData(char* data);
};
class EntityFileXMLErrorHandler : public xercesc::ErrorHandler
@@ -269,6 +137,7 @@ private:
class EntityFile : public Resource
{
friend class ResourceManager;
friend class EntityFileSAXHandler;
private:
EntityFile(boost::filesystem::path path);
~EntityFile();
@@ -288,6 +157,8 @@ private:
xercesc::SAX2XMLReader* m_SAX2XMLReader;
//std::map<std::string, ::ComponentInfo> m_ComponentInfo;
//std::vector<std::string> m_EntityReferences;
static void setReaderFeatures(xercesc::SAX2XMLReader* reader);
};
#endif
@@ -5,6 +5,7 @@
#include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp>
#include <xercesc/framework/psvi/XSParticle.hpp>
#include <xercesc/framework/psvi/XSModelGroup.hpp>
#include <xercesc/framework/psvi/XSModelGroupDefinition.hpp>
#include <xercesc/framework/psvi/XSAnnotation.hpp>
#include <xercesc/framework/psvi/XSValue.hpp>
#include <xercesc/framework/MemBufFormatTarget.hpp>
@@ -31,6 +32,7 @@ private:
void onStartComponent(EntityID entity, std::string type);
void parseComponentInfo();
void parseDefaults();
std::string parseAnnotationXML(const XMLCh* xml);
};
#endif
+1
View File
@@ -18,4 +18,5 @@
<xs:include schemaLocation="Components/Spawner.xsd"/>
<xs:include schemaLocation="Components/SpawnPoint.xsd"/>
<xs:include schemaLocation="Components/PlayerSpawn.xsd"/>
<xs:include schemaLocation="Components/Team.xsd"/>
</xs:schema>
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Team xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Team.xsd">
<Team><Spectator/></Team>
</Team>
+28
View File
@@ -0,0 +1,28 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:complexType name="TeamEnum" mixed="true">
<xs:complexContent>
<xs:extension base="t:enum">
<xs:choice>
<xs:element name="Spectator" type="xs:integer" fixed="1" minOccurs="0"/>
<xs:element name="Red" type="xs:integer" fixed="2" minOccurs="0"/>
<xs:element name="Blue" type="xs:integer" fixed="3" minOccurs="0"/>
</xs:choice>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="Team">
<xs:annotation>
<xs:documentation>Represents entity team affiliation</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="Team" type="TeamEnum" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
+3
View File
@@ -4,6 +4,9 @@
<xs:include schemaLocation="Types/Quaternion.xsd"/>
<xs:include schemaLocation="Types/Vector.xsd"/>
<xs:include schemaLocation="Types/Color.xsd"/>
<xs:complexType name="enum" mixed="true">
<xs:choice></xs:choice>
</xs:complexType>
<xs:simpleType name="bool">
<xs:restriction base="xs:boolean"></xs:restriction>
</xs:simpleType>
+1
View File
@@ -27,6 +27,7 @@
<xs:element ref="c:Spawner" minOccurs="0"/>
<xs:element ref="c:SpawnPoint" minOccurs="0"/>
<xs:element ref="c:PlayerSpawn" minOccurs="0"/>
<xs:element ref="c:Team" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
+182 -5
View File
@@ -21,16 +21,24 @@ void EntityFile::Parse(const EntityFileHandler* handler) const
using namespace xercesc;
EntityFileSAXHandler saxHandler(handler, nullptr);
m_SAX2XMLReader->setFeature(XMLUni::fgXercesCacheGrammarFromParse, true);
m_SAX2XMLReader->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true);
m_SAX2XMLReader->setFeature(XMLUni::fgXercesSchema, true);
m_SAX2XMLReader->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
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);
}
std::size_t EntityFile::GetTypeStride(std::string typeName)
{
std::map<std::string, size_t> typeStrides{
@@ -39,6 +47,7 @@ std::size_t EntityFile::GetTypeStride(std::string typeName)
{ "float", sizeof(float) },
{ "double", sizeof(double) },
{ "string", sizeof(std::string) },
{ "enum", sizeof(int) },
{ "Vector", sizeof(glm::vec3) },
{ "Quaternion", sizeof(glm::quat) },
{ "Color", sizeof(glm::vec4) }
@@ -77,7 +86,7 @@ void EntityFile::WriteAttributeData(char* outData, const ComponentInfo::Field_t&
void EntityFile::WriteValueData(char* outData, const ComponentInfo::Field_t& field, const char* valueData)
{
if (field.Type == "int") {
if (field.Type == "int" || field.Type == "enum") {
int value = boost::lexical_cast<int>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "float") {
@@ -95,3 +104,171 @@ void EntityFile::WriteValueData(char* outData, const ComponentInfo::Field_t& fie
LOG_WARNING("Unknown value data type: %s", field.Type.c_str());
}
}
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) {
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)
{
XS::ToString s(e.getMessage());
LOG_ERROR("SAXParseException: %s", ((std::string)s).c_str());
//throw e;
}
void EntityFileSAXHandler::error(const xercesc::SAXParseException& e)
{
XS::ToString s(e.getMessage());
LOG_ERROR("SAXParseException: %s", ((std::string)s).c_str());
}
void EntityFileSAXHandler::warning(const xercesc::SAXParseException& e)
{
XS::ToString s(e.getMessage());
LOG_ERROR("SAXParseException: %s", ((std::string)s).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);
}
+91 -48
View File
@@ -16,12 +16,12 @@ EntityFilePreprocessor::EntityFilePreprocessor(const EntityFile* entityFile)
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);
LOG_DEBUG("Component: %s (%s)", info.Name.c_str(), info.Meta->Annotation.c_str());
LOG_DEBUG("Stride: %i", info.Stride);
LOG_DEBUG("Allocation: %i", info.Meta->Allocation);
for (auto& kv : info.Fields) {
auto& field = kv.second;
LOG_DEBUG("\t%i\t%s %s", field.Offset, field.Type, kv.first.c_str());
LOG_DEBUG("\t%i\t%s %s", field.Offset, field.Type.c_str(), kv.first.c_str());
}
}
@@ -62,46 +62,16 @@ void EntityFilePreprocessor::parseComponentInfo()
}
ComponentInfo compInfo;
compInfo.Meta = std::make_shared<ComponentInfo::Meta_t>();
// Name
compInfo.Name = XS::ToString(element->getName());
// Known allocation
compInfo.Meta.Allocation = m_ComponentCounts[compInfo.Name];
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());
}
}
compInfo.Meta->Annotation = parseAnnotationXML(componentAnnotation->getAnnotationString());
} else {
LOG_WARNING("Component \"%s\" is missing an annotation!", compInfo.Name.c_str());
}
@@ -140,24 +110,58 @@ void EntityFilePreprocessor::parseComponentInfo()
std::string name = XS::ToString(elementDeclaration->getName());
std::string type = XS::ToString(elementDeclaration->getTypeDefinition()->getName());
std::string typeNamespace = XS::ToString(elementDeclaration->getTypeDefinition()->getNamespace());
std::string baseType = XS::ToString(elementDeclaration->getTypeDefinition()->getBaseType()->getName());
std::string effectiveType = type;
size_t stride = EntityFile::GetTypeStride(type);
if (stride == 0) {
LOG_WARNING("Field \"%s\" in component \"%s\" uses unexpected field type \"%s\". Skipping.", name.c_str(), compInfo.Name.c_str(), type.c_str());
continue;
stride = EntityFile::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;
}
effectiveType = baseType;
}
// Annotation
auto fieldAnnotation = elementDeclaration->getAnnotation();
if (fieldAnnotation != nullptr) {
compInfo.Meta->FieldAnnotations[name] = parseAnnotationXML(fieldAnnotation->getAnnotationString());
} else {
LOG_WARNING("Component field \"%s.%s\" is missing an annotation!", compInfo.Name.c_str(), name.c_str());
}
if (effectiveType == "enum") {
// Parse potential enum type definition for field type
if (compInfo.Meta->FieldEnumDefinitions.count(name) == 0) {
auto enumTypeDefinition = xsModel->getTypeDefinition(XS::ToXMLCh(type), XS::ToXMLCh("components"));
auto xsComplexType = dynamic_cast<XSComplexTypeDefinition*>(enumTypeDefinition);
auto xsComplexContent = xsComplexType->getParticle();
auto xsExtension = xsComplexContent->getModelGroupTerm();
auto xsExtensionParticles = xsExtension->getParticles();
auto xsChoice = xsExtensionParticles->elementAt(0)->getModelGroupTerm();
auto xsChoiceParticles = xsChoice->getParticles();
for (int i = 0; i < xsChoiceParticles->size(); ++i) {
auto enumElement = xsChoiceParticles->elementAt(i)->getElementTerm();
std::string enumName = XS::ToString(enumElement->getName());
std::string enumValue = XS::ToString(enumElement->getConstraintValue());
compInfo.Meta->FieldEnumDefinitions[name][enumName] = boost::lexical_cast<int>(enumValue);
LOG_DEBUG("ENUM %s = %s", enumName.c_str(), enumValue.c_str());
}
}
}
auto& field = compInfo.Fields[name];
field.Name = name;
field.Type = type;
field.Type = effectiveType;
field.Offset = fieldOffset;
field.Stride = stride;
compInfo.FieldsInOrder.push_back(name);
fieldOffset += stride;
}
compInfo.Meta.Stride = fieldOffset;
compInfo.Stride = fieldOffset;
m_ComponentInfo[compInfo.Name] = compInfo;
}
}
@@ -170,8 +174,10 @@ void EntityFilePreprocessor::parseDefaults()
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);
ci.second.Defaults = std::shared_ptr<char>(new char[ci.second.Stride]);
memset(ci.second.Defaults.get(), 0, ci.second.Stride);
std::string componentName = ci.first;
XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager);
parser.setDoSchema(true);
@@ -179,8 +185,11 @@ void EntityFilePreprocessor::parseDefaults()
parser.setErrorHandler(&errorHandler);
parser.setValidationScheme(XercesDOMParser::Val_Always);
parser.setValidationSchemaFullChecking(true);
//parser.setDoNamespaces(true);
//boost::filesystem::path schemaLocation = "Schema/Components/" + componentName + ".xsd";
//std::string namespaceSchema = schemaLocation.string();
//parser.setExternalNoNamespaceSchemaLocation("Teamasdasdasdasd.xsd");
std::string componentName = ci.first;
LOG_DEBUG("Parsing defaults for component %s", componentName.c_str());
boost::filesystem::path defaultsFile = "Schema/Components/" + componentName + ".xml";
@@ -192,7 +201,7 @@ void EntityFilePreprocessor::parseDefaults()
}
// Find the node in the components namespace matching the component name
std::string tagName = "c:" + componentName;
std::string tagName = 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());
@@ -225,9 +234,19 @@ void EntityFilePreprocessor::parseDefaults()
EntityFile::WriteAttributeData(data, field, attributes);
}
// Handle potential field values
auto childNode = fieldElement->getFirstChild();
if (childNode != nullptr && childNode->getNodeType() == DOMNode::TEXT_NODE) {
if (childNode == nullptr) {
continue;
}
// An enum will either have an element node with a text node inside,
// or contain a text node directly.
if (childNode->getNodeType() == DOMNode::ELEMENT_NODE) {
childNode = childNode->getFirstChild();
}
// Handle potential field values
if (childNode->getNodeType() == DOMNode::TEXT_NODE) {
char* cstrValue = XMLString::transcode(childNode->getNodeValue());
EntityFile::WriteValueData(data, field, cstrValue);
XMLString::release(&cstrValue);
@@ -236,3 +255,27 @@ void EntityFilePreprocessor::parseDefaults()
}
}
std::string EntityFilePreprocessor::parseAnnotationXML(const XMLCh* xml)
{
using namespace xercesc;
// Parse annotation XML
char* annotationString = XMLString::transcode(xml);
MemBufInputSource annotationInput(reinterpret_cast<const XMLByte*>(annotationString), strlen(annotationString), "MemBuf: Annotation String");
XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager);
//parser.setErrorHandler(&errorHandler);
parser.parse(annotationInput);
XMLString::release(&annotationString);
auto doc = parser.getDocument();
// Save documentation string
auto documentationTags = doc->getElementsByTagName(XS::ToXMLCh("xs:documentation"));
if (documentationTags->getLength() != 0) {
auto child = documentationTags->item(0)->getFirstChild();
if (child != nullptr) {
return XS::ToString(child->getNodeValue());
}
}
return std::string();
}
+1 -1
View File
@@ -114,7 +114,7 @@ void EntityFileWriter::appentEntityComponents(xercesc::DOMElement* parentElement
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 (field.Type == "int") {
} else if (field.Type == "int" || field.Type == "enum") {
const int& value = c[fieldName];
fieldElement->appendChild(doc->createTextNode(X(boost::lexical_cast<std::string>(value))));
} else if (field.Type == "float") {
+1 -1
View File
@@ -75,7 +75,7 @@ ComponentWrapper World::AttachComponent(EntityID entity, const std::string& comp
// Allocate space for the component
ComponentWrapper c = pool->Allocate(entity);
// Write default values
memcpy(c.Data, ci.Defaults.get(), ci.Meta.Stride);
memcpy(c.Data, ci.Defaults.get(), ci.Stride);
return c;
}
+22 -2
View File
@@ -484,8 +484,8 @@ void EditorSystem::drawUI(World* world, double dt)
}
if (ImGui::CollapsingHeader(componentType.c_str())) {
if (!ci.Meta.Annotation.empty()) {
ImGui::Text(ci.Meta.Annotation.c_str());
if (!ci.Meta->Annotation.empty()) {
ImGui::Text(ci.Meta->Annotation.c_str());
}
auto& component = world->GetComponent(m_Selection, componentType);
@@ -529,6 +529,26 @@ void EditorSystem::drawUI(World* world, double dt)
if (ImGui::InputFloat("", &tempVal, 0.01f, 1.f)) {
component.SetProperty(fieldName, static_cast<double>(tempVal));
}
} else if (field.Type == "int") {
int val = component.Property<int>(fieldName);
ImGui::InputInt("", &val);
} else if (field.Type == "enum") {
int currentValue = component.Property<int>(fieldName);
int item = -1;
std::stringstream enumKeys;
std::vector<int> enumValues;
int i = 0;
for (auto& kv : ci.Meta->FieldEnumDefinitions.at(fieldName)) {
enumKeys << kv.first << " (" << kv.second << ")" << '\0';
enumValues.push_back(kv.second);
if (currentValue == kv.second) {
item = i;
}
i++;
}
if (ImGui::Combo("", &item, enumKeys.str().c_str())) {
component.SetProperty(fieldName, enumValues.at(item));
}
} else if (field.Type == "bool") {
auto& val = component.Property<bool>(fieldName);
ImGui::Checkbox("", &val);
+2 -2
View File
@@ -10,8 +10,8 @@ BOOST_AUTO_TEST_CASE(ComponentPoolTest)
//ci.Name = "Test";
//ci.FieldTypes["Field"] = "int";
//ci.FieldOffsets["Field"] = 0;
//ci.Meta.Allocation = 3;
//ci.Meta.Stride = sizeof(EntityID) + sizeof(int);
//ci.Meta->Allocation = 3;
//ci.Stride = sizeof(EntityID) + sizeof(int);
//std::vector<ComponentWrapper> wrappers;
//ComponentPool pool(ci);