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:
@@ -9,7 +9,8 @@ struct ComponentInfo
|
|||||||
{
|
{
|
||||||
std::string Annotation;
|
std::string Annotation;
|
||||||
unsigned int Allocation = 0;
|
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
|
struct Field_t
|
||||||
@@ -23,8 +24,9 @@ struct ComponentInfo
|
|||||||
std::string Name;
|
std::string Name;
|
||||||
std::unordered_map<std::string, Field_t> Fields;
|
std::unordered_map<std::string, Field_t> Fields;
|
||||||
std::vector<std::string> FieldsInOrder;
|
std::vector<std::string> FieldsInOrder;
|
||||||
Meta_t Meta;
|
unsigned int Stride = 0;
|
||||||
std::shared_ptr<char> Defaults = nullptr;
|
std::shared_ptr<char> Defaults = nullptr;
|
||||||
|
std::shared_ptr<Meta_t> Meta = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public:
|
|||||||
|
|
||||||
ComponentPool(const ::ComponentInfo& ci)
|
ComponentPool(const ::ComponentInfo& ci)
|
||||||
: m_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;
|
||||||
ComponentPool(const ComponentPool&& other) = delete;
|
ComponentPool(const ComponentPool&& other) = delete;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "ComponentInfo.h"
|
#include "ComponentInfo.h"
|
||||||
#include "Util/Any.h"
|
#include "Util/Any.h"
|
||||||
|
|
||||||
|
// TODO: Change all instances "Property" to "Field" to remain consistent with ComponentInfo
|
||||||
struct ComponentWrapper
|
struct ComponentWrapper
|
||||||
{
|
{
|
||||||
ComponentWrapper(const ComponentInfo& componentInfo, char* data)
|
ComponentWrapper(const ComponentInfo& componentInfo, char* data)
|
||||||
@@ -18,6 +19,11 @@ struct ComponentWrapper
|
|||||||
const ::EntityID EntityID;
|
const ::EntityID EntityID;
|
||||||
char* Data;
|
char* Data;
|
||||||
|
|
||||||
|
int Enum(const char* fieldName, const char* enumKey)
|
||||||
|
{
|
||||||
|
return Info.Meta->FieldEnumDefinitions.at(fieldName).at(enumKey);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T& Property(std::string name)
|
T& Property(std::string name)
|
||||||
{
|
{
|
||||||
@@ -33,7 +39,7 @@ struct ComponentWrapper
|
|||||||
// Specialization for string literals
|
// Specialization for string literals
|
||||||
template <std::size_t N>
|
template <std::size_t N>
|
||||||
void SetProperty(std::string name, const char(&value)[N]) { Property<std::string>(name) = std::string(value); }
|
void SetProperty(std::string name, const char(&value)[N]) { Property<std::string>(name) = std::string(value); }
|
||||||
|
|
||||||
struct SubscriptProxy
|
struct SubscriptProxy
|
||||||
{
|
{
|
||||||
friend struct ComponentWrapper;
|
friend struct ComponentWrapper;
|
||||||
@@ -47,6 +53,9 @@ struct ComponentWrapper
|
|||||||
std::string m_PropertyName;
|
std::string m_PropertyName;
|
||||||
|
|
||||||
public:
|
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>
|
template <typename T>
|
||||||
operator T&() { return m_Component->Property<T>(m_PropertyName); }
|
operator T&() { return m_Component->Property<T>(m_PropertyName); }
|
||||||
|
|
||||||
@@ -71,7 +80,7 @@ public:
|
|||||||
ComponentWrapperFactory(std::string componentTypeName, std::size_t allocation = 0)
|
ComponentWrapperFactory(std::string componentTypeName, std::size_t allocation = 0)
|
||||||
{
|
{
|
||||||
m_ComponentInfo.Name = componentTypeName;
|
m_ComponentInfo.Name = componentTypeName;
|
||||||
m_ComponentInfo.Meta.Allocation = allocation;
|
m_ComponentInfo.Meta->Allocation = allocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -79,14 +88,14 @@ public:
|
|||||||
{
|
{
|
||||||
m_DefaultValues.push_back(defaultValue);
|
m_DefaultValues.push_back(defaultValue);
|
||||||
m_ComponentInfo.Fields[fieldName].Name = typeid(T).name();
|
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.Fields[fieldName].Stride = sizeof(T);
|
||||||
m_ComponentInfo.Meta.Stride += sizeof(T);
|
m_ComponentInfo.Stride += sizeof(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
ComponentInfo& Finalize()
|
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;
|
std::size_t offset = 0;
|
||||||
for (auto& val : m_DefaultValues) {
|
for (auto& val : m_DefaultValues) {
|
||||||
memcpy(m_ComponentInfo.Defaults.get() + offset, val.Data.get(), val.Size);
|
memcpy(m_ComponentInfo.Defaults.get() + offset, val.Data.get(), val.Size);
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ private:
|
|||||||
|
|
||||||
XSValue::Status status;
|
XSValue::Status status;
|
||||||
XSValue* val = XSValue::getActualValue(child->getNodeValue(), XSValue::dt_integer, 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
|
// Save documentation string
|
||||||
@@ -293,11 +293,11 @@ private:
|
|||||||
if (documentationTags->getLength() != 0) {
|
if (documentationTags->getLength() != 0) {
|
||||||
auto child = documentationTags->item(0)->getFirstChild();
|
auto child = documentationTags->item(0)->getFirstChild();
|
||||||
if (child != nullptr) {
|
if (child != nullptr) {
|
||||||
compInfo.Meta.Annotation = XSTR(child->getNodeValue());
|
compInfo.Meta->Annotation = XSTR(child->getNodeValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: Parse annotation string XML
|
// TODO: Parse annotation string XML
|
||||||
// compInfo.Meta.Allocation = ...
|
// compInfo.Meta->Allocation = ...
|
||||||
} else {
|
} else {
|
||||||
std::cout << "Warning: Component is missing an annotation!" << std::endl;
|
std::cout << "Warning: Component is missing an annotation!" << std::endl;
|
||||||
}
|
}
|
||||||
@@ -344,7 +344,7 @@ private:
|
|||||||
fieldOffset += getTypeStride(type);
|
fieldOffset += getTypeStride(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
compInfo.Meta.Stride = fieldOffset;
|
compInfo.Stride = fieldOffset;
|
||||||
m_ComponentInfo[compInfo.Name] = compInfo;
|
m_ComponentInfo[compInfo.Name] = compInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -367,14 +367,14 @@ private:
|
|||||||
|
|
||||||
std::string componentName = XSTR(component->getLocalName());
|
std::string componentName = XSTR(component->getLocalName());
|
||||||
auto& compInfo = m_ComponentInfo.at(componentName);
|
auto& compInfo = m_ComponentInfo.at(componentName);
|
||||||
compInfo.Meta.Allocation += 1;
|
compInfo.Meta->Allocation += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "COMPONENT INFO" << std::endl;
|
std::cout << "COMPONENT INFO" << std::endl;
|
||||||
for (auto& pair : m_ComponentInfo) {
|
for (auto& pair : m_ComponentInfo) {
|
||||||
ComponentInfo& ci = pair.second;
|
ComponentInfo& ci = pair.second;
|
||||||
std::cout << "Component: " << ci.Name << " (" << ci.Meta.Annotation << ")" << std::endl;
|
std::cout << "Component: " << ci.Name << " (" << ci.Meta->Annotation << ")" << std::endl;
|
||||||
std::cout << " Allocation: " << ci.Meta.Allocation << std::endl;
|
std::cout << " Allocation: " << ci.Meta->Allocation << std::endl;
|
||||||
std::cout << " Fields:" << std::endl;
|
std::cout << " Fields:" << std::endl;
|
||||||
|
|
||||||
// Calculate component size
|
// Calculate component size
|
||||||
@@ -393,7 +393,7 @@ private:
|
|||||||
cs.ComponentName = ci.Name;
|
cs.ComponentName = ci.Name;
|
||||||
cs.Stride = stride;
|
cs.Stride = stride;
|
||||||
cs.Info = ci;
|
cs.Info = ci;
|
||||||
cs.Data = new char[stride*ci.Meta.Allocation];
|
cs.Data = new char[stride*ci.Meta->Allocation];
|
||||||
m_ComponentStore[cs.ComponentName] = cs;
|
m_ComponentStore[cs.ComponentName] = cs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,88 +73,15 @@ public:
|
|||||||
ComponentField
|
ComponentField
|
||||||
};
|
};
|
||||||
|
|
||||||
EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader)
|
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 startElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname, const xercesc::Attributes& attrs) override
|
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;
|
||||||
std::string name = XS::ToString(_localName);
|
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) {
|
void warning(const xercesc::SAXParseException& e);
|
||||||
if (name == "Entity") {
|
void error(const xercesc::SAXParseException& e);
|
||||||
m_StateStack.push(State::Entity);
|
void fatalError(const xercesc::SAXParseException& e);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const EntityFileHandler* m_Handler;
|
const EntityFileHandler* m_Handler;
|
||||||
@@ -168,73 +95,14 @@ private:
|
|||||||
std::string m_CurrentField;
|
std::string m_CurrentField;
|
||||||
std::map<std::string, std::string> m_CurrentAttributes;
|
std::map<std::string, std::string> m_CurrentAttributes;
|
||||||
|
|
||||||
void onStartEntity(const xercesc::Attributes& attrs)
|
void onStartEntity(const xercesc::Attributes& attrs);
|
||||||
{
|
void onEndEntity();
|
||||||
EntityID parent = m_EntityStack.top();
|
void onStartEntityRef(const xercesc::Attributes& attrs);
|
||||||
|
void onStartComponent(const std::string& name);
|
||||||
if (m_Handler->m_OnStartEntityCallback) {
|
void onEndComponent(const std::string& name);
|
||||||
std::string name;
|
void onStartComponentField(const std::string& field, const xercesc::Attributes& attrs);
|
||||||
auto xName = attrs.getValue(XS::ToXMLCh("name"));
|
void onEndComponentField(const std::string& field);
|
||||||
if (xName != nullptr) {
|
void onFieldData(char* data);
|
||||||
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);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class EntityFileXMLErrorHandler : public xercesc::ErrorHandler
|
class EntityFileXMLErrorHandler : public xercesc::ErrorHandler
|
||||||
@@ -269,6 +137,7 @@ private:
|
|||||||
class EntityFile : public Resource
|
class EntityFile : public Resource
|
||||||
{
|
{
|
||||||
friend class ResourceManager;
|
friend class ResourceManager;
|
||||||
|
friend class EntityFileSAXHandler;
|
||||||
private:
|
private:
|
||||||
EntityFile(boost::filesystem::path path);
|
EntityFile(boost::filesystem::path path);
|
||||||
~EntityFile();
|
~EntityFile();
|
||||||
@@ -288,6 +157,8 @@ private:
|
|||||||
xercesc::SAX2XMLReader* m_SAX2XMLReader;
|
xercesc::SAX2XMLReader* m_SAX2XMLReader;
|
||||||
//std::map<std::string, ::ComponentInfo> m_ComponentInfo;
|
//std::map<std::string, ::ComponentInfo> m_ComponentInfo;
|
||||||
//std::vector<std::string> m_EntityReferences;
|
//std::vector<std::string> m_EntityReferences;
|
||||||
|
|
||||||
|
static void setReaderFeatures(xercesc::SAX2XMLReader* reader);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp>
|
#include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp>
|
||||||
#include <xercesc/framework/psvi/XSParticle.hpp>
|
#include <xercesc/framework/psvi/XSParticle.hpp>
|
||||||
#include <xercesc/framework/psvi/XSModelGroup.hpp>
|
#include <xercesc/framework/psvi/XSModelGroup.hpp>
|
||||||
|
#include <xercesc/framework/psvi/XSModelGroupDefinition.hpp>
|
||||||
#include <xercesc/framework/psvi/XSAnnotation.hpp>
|
#include <xercesc/framework/psvi/XSAnnotation.hpp>
|
||||||
#include <xercesc/framework/psvi/XSValue.hpp>
|
#include <xercesc/framework/psvi/XSValue.hpp>
|
||||||
#include <xercesc/framework/MemBufFormatTarget.hpp>
|
#include <xercesc/framework/MemBufFormatTarget.hpp>
|
||||||
@@ -31,6 +32,7 @@ private:
|
|||||||
void onStartComponent(EntityID entity, std::string type);
|
void onStartComponent(EntityID entity, std::string type);
|
||||||
void parseComponentInfo();
|
void parseComponentInfo();
|
||||||
void parseDefaults();
|
void parseDefaults();
|
||||||
|
std::string parseAnnotationXML(const XMLCh* xml);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -18,4 +18,5 @@
|
|||||||
<xs:include schemaLocation="Components/Spawner.xsd"/>
|
<xs:include schemaLocation="Components/Spawner.xsd"/>
|
||||||
<xs:include schemaLocation="Components/SpawnPoint.xsd"/>
|
<xs:include schemaLocation="Components/SpawnPoint.xsd"/>
|
||||||
<xs:include schemaLocation="Components/PlayerSpawn.xsd"/>
|
<xs:include schemaLocation="Components/PlayerSpawn.xsd"/>
|
||||||
|
<xs:include schemaLocation="Components/Team.xsd"/>
|
||||||
</xs:schema>
|
</xs:schema>
|
||||||
Executable
+4
@@ -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>
|
||||||
Executable
+28
@@ -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>
|
||||||
@@ -4,6 +4,9 @@
|
|||||||
<xs:include schemaLocation="Types/Quaternion.xsd"/>
|
<xs:include schemaLocation="Types/Quaternion.xsd"/>
|
||||||
<xs:include schemaLocation="Types/Vector.xsd"/>
|
<xs:include schemaLocation="Types/Vector.xsd"/>
|
||||||
<xs:include schemaLocation="Types/Color.xsd"/>
|
<xs:include schemaLocation="Types/Color.xsd"/>
|
||||||
|
<xs:complexType name="enum" mixed="true">
|
||||||
|
<xs:choice></xs:choice>
|
||||||
|
</xs:complexType>
|
||||||
<xs:simpleType name="bool">
|
<xs:simpleType name="bool">
|
||||||
<xs:restriction base="xs:boolean"></xs:restriction>
|
<xs:restriction base="xs:boolean"></xs:restriction>
|
||||||
</xs:simpleType>
|
</xs:simpleType>
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
<xs:element ref="c:Spawner" minOccurs="0"/>
|
<xs:element ref="c:Spawner" minOccurs="0"/>
|
||||||
<xs:element ref="c:SpawnPoint" minOccurs="0"/>
|
<xs:element ref="c:SpawnPoint" minOccurs="0"/>
|
||||||
<xs:element ref="c:PlayerSpawn" minOccurs="0"/>
|
<xs:element ref="c:PlayerSpawn" minOccurs="0"/>
|
||||||
|
<xs:element ref="c:Team" minOccurs="0"/>
|
||||||
</xs:all>
|
</xs:all>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
|
|||||||
@@ -21,16 +21,24 @@ void EntityFile::Parse(const EntityFileHandler* handler) const
|
|||||||
using namespace xercesc;
|
using namespace xercesc;
|
||||||
|
|
||||||
EntityFileSAXHandler saxHandler(handler, nullptr);
|
EntityFileSAXHandler saxHandler(handler, nullptr);
|
||||||
m_SAX2XMLReader->setFeature(XMLUni::fgXercesCacheGrammarFromParse, true);
|
setReaderFeatures(m_SAX2XMLReader);
|
||||||
m_SAX2XMLReader->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true);
|
|
||||||
m_SAX2XMLReader->setFeature(XMLUni::fgXercesSchema, true);
|
|
||||||
m_SAX2XMLReader->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
|
|
||||||
m_SAX2XMLReader->setContentHandler(&saxHandler);
|
m_SAX2XMLReader->setContentHandler(&saxHandler);
|
||||||
m_SAX2XMLReader->setErrorHandler(&saxHandler);
|
m_SAX2XMLReader->setErrorHandler(&saxHandler);
|
||||||
m_SAX2XMLReader->setDeclarationHandler(&saxHandler);
|
m_SAX2XMLReader->setDeclarationHandler(&saxHandler);
|
||||||
m_SAX2XMLReader->parse(m_FilePath.string().c_str());
|
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::size_t EntityFile::GetTypeStride(std::string typeName)
|
||||||
{
|
{
|
||||||
std::map<std::string, size_t> typeStrides{
|
std::map<std::string, size_t> typeStrides{
|
||||||
@@ -39,6 +47,7 @@ std::size_t EntityFile::GetTypeStride(std::string typeName)
|
|||||||
{ "float", sizeof(float) },
|
{ "float", sizeof(float) },
|
||||||
{ "double", sizeof(double) },
|
{ "double", sizeof(double) },
|
||||||
{ "string", sizeof(std::string) },
|
{ "string", sizeof(std::string) },
|
||||||
|
{ "enum", sizeof(int) },
|
||||||
{ "Vector", sizeof(glm::vec3) },
|
{ "Vector", sizeof(glm::vec3) },
|
||||||
{ "Quaternion", sizeof(glm::quat) },
|
{ "Quaternion", sizeof(glm::quat) },
|
||||||
{ "Color", sizeof(glm::vec4) }
|
{ "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)
|
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);
|
int value = boost::lexical_cast<int>(valueData);
|
||||||
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
|
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
|
||||||
} else if (field.Type == "float") {
|
} 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());
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ EntityFilePreprocessor::EntityFilePreprocessor(const EntityFile* entityFile)
|
|||||||
|
|
||||||
for (auto& kv : m_ComponentInfo) {
|
for (auto& kv : m_ComponentInfo) {
|
||||||
auto& info = kv.second;
|
auto& info = kv.second;
|
||||||
LOG_DEBUG("Component: %s (%s)", info.Name.c_str(), info.Meta.Annotation.c_str());
|
LOG_DEBUG("Component: %s (%s)", info.Name.c_str(), info.Meta->Annotation.c_str());
|
||||||
LOG_DEBUG("Stride: %i", info.Meta.Stride);
|
LOG_DEBUG("Stride: %i", info.Stride);
|
||||||
LOG_DEBUG("Allocation: %i", info.Meta.Allocation);
|
LOG_DEBUG("Allocation: %i", info.Meta->Allocation);
|
||||||
for (auto& kv : info.Fields) {
|
for (auto& kv : info.Fields) {
|
||||||
auto& field = kv.second;
|
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;
|
ComponentInfo compInfo;
|
||||||
|
compInfo.Meta = std::make_shared<ComponentInfo::Meta_t>();
|
||||||
|
|
||||||
// Name
|
// Name
|
||||||
compInfo.Name = XS::ToString(element->getName());
|
compInfo.Name = XS::ToString(element->getName());
|
||||||
// Known allocation
|
// Known allocation
|
||||||
compInfo.Meta.Allocation = m_ComponentCounts[compInfo.Name];
|
compInfo.Meta->Allocation = m_ComponentCounts[compInfo.Name];
|
||||||
// Annotation
|
// Annotation
|
||||||
auto componentAnnotation = element->getAnnotation();
|
auto componentAnnotation = element->getAnnotation();
|
||||||
if (componentAnnotation != nullptr) {
|
if (componentAnnotation != nullptr) {
|
||||||
// Parse annotation XML
|
compInfo.Meta->Annotation = parseAnnotationXML(componentAnnotation->getAnnotationString());
|
||||||
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 {
|
} else {
|
||||||
LOG_WARNING("Component \"%s\" is missing an annotation!", compInfo.Name.c_str());
|
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 name = XS::ToString(elementDeclaration->getName());
|
||||||
std::string type = XS::ToString(elementDeclaration->getTypeDefinition()->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);
|
size_t stride = EntityFile::GetTypeStride(type);
|
||||||
if (stride == 0) {
|
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());
|
stride = EntityFile::GetTypeStride(baseType);
|
||||||
continue;
|
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];
|
auto& field = compInfo.Fields[name];
|
||||||
field.Name = name;
|
field.Name = name;
|
||||||
field.Type = type;
|
field.Type = effectiveType;
|
||||||
field.Offset = fieldOffset;
|
field.Offset = fieldOffset;
|
||||||
field.Stride = stride;
|
field.Stride = stride;
|
||||||
compInfo.FieldsInOrder.push_back(name);
|
compInfo.FieldsInOrder.push_back(name);
|
||||||
|
|
||||||
fieldOffset += stride;
|
fieldOffset += stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
compInfo.Meta.Stride = fieldOffset;
|
compInfo.Stride = fieldOffset;
|
||||||
m_ComponentInfo[compInfo.Name] = compInfo;
|
m_ComponentInfo[compInfo.Name] = compInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,8 +174,10 @@ void EntityFilePreprocessor::parseDefaults()
|
|||||||
|
|
||||||
for (auto& ci : m_ComponentInfo) {
|
for (auto& ci : m_ComponentInfo) {
|
||||||
// Allocate memory for default values
|
// Allocate memory for default values
|
||||||
ci.second.Defaults = std::shared_ptr<char>(new char[ci.second.Meta.Stride]);
|
ci.second.Defaults = std::shared_ptr<char>(new char[ci.second.Stride]);
|
||||||
memset(ci.second.Defaults.get(), 0, ci.second.Meta.Stride);
|
memset(ci.second.Defaults.get(), 0, ci.second.Stride);
|
||||||
|
|
||||||
|
std::string componentName = ci.first;
|
||||||
|
|
||||||
XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager);
|
XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager);
|
||||||
parser.setDoSchema(true);
|
parser.setDoSchema(true);
|
||||||
@@ -179,8 +185,11 @@ void EntityFilePreprocessor::parseDefaults()
|
|||||||
parser.setErrorHandler(&errorHandler);
|
parser.setErrorHandler(&errorHandler);
|
||||||
parser.setValidationScheme(XercesDOMParser::Val_Always);
|
parser.setValidationScheme(XercesDOMParser::Val_Always);
|
||||||
parser.setValidationSchemaFullChecking(true);
|
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());
|
LOG_DEBUG("Parsing defaults for component %s", componentName.c_str());
|
||||||
boost::filesystem::path defaultsFile = "Schema/Components/" + componentName + ".xml";
|
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
|
// 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));
|
auto rootNodes = doc->getElementsByTagName(XS::ToXMLCh(tagName));
|
||||||
if (rootNodes->getLength() == 0) {
|
if (rootNodes->getLength() == 0) {
|
||||||
LOG_ERROR("Couldn't find defaults for component \"%s\"! Skipping.", componentName.c_str());
|
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);
|
EntityFile::WriteAttributeData(data, field, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle potential field values
|
|
||||||
auto childNode = fieldElement->getFirstChild();
|
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());
|
char* cstrValue = XMLString::transcode(childNode->getNodeValue());
|
||||||
EntityFile::WriteValueData(data, field, cstrValue);
|
EntityFile::WriteValueData(data, field, cstrValue);
|
||||||
XMLString::release(&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();
|
||||||
|
}
|
||||||
|
|||||||
@@ -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("Y"), X(boost::lexical_cast<std::string>(q.y)));
|
||||||
fieldElement->setAttribute(X("Z"), X(boost::lexical_cast<std::string>(q.z)));
|
fieldElement->setAttribute(X("Z"), X(boost::lexical_cast<std::string>(q.z)));
|
||||||
fieldElement->setAttribute(X("W"), X(boost::lexical_cast<std::string>(q.w)));
|
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];
|
const int& value = c[fieldName];
|
||||||
fieldElement->appendChild(doc->createTextNode(X(boost::lexical_cast<std::string>(value))));
|
fieldElement->appendChild(doc->createTextNode(X(boost::lexical_cast<std::string>(value))));
|
||||||
} else if (field.Type == "float") {
|
} else if (field.Type == "float") {
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ ComponentWrapper World::AttachComponent(EntityID entity, const std::string& comp
|
|||||||
// Allocate space for the component
|
// Allocate space for the component
|
||||||
ComponentWrapper c = pool->Allocate(entity);
|
ComponentWrapper c = pool->Allocate(entity);
|
||||||
// Write default values
|
// Write default values
|
||||||
memcpy(c.Data, ci.Defaults.get(), ci.Meta.Stride);
|
memcpy(c.Data, ci.Defaults.get(), ci.Stride);
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -484,8 +484,8 @@ void EditorSystem::drawUI(World* world, double dt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader(componentType.c_str())) {
|
if (ImGui::CollapsingHeader(componentType.c_str())) {
|
||||||
if (!ci.Meta.Annotation.empty()) {
|
if (!ci.Meta->Annotation.empty()) {
|
||||||
ImGui::Text(ci.Meta.Annotation.c_str());
|
ImGui::Text(ci.Meta->Annotation.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& component = world->GetComponent(m_Selection, componentType);
|
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)) {
|
if (ImGui::InputFloat("", &tempVal, 0.01f, 1.f)) {
|
||||||
component.SetProperty(fieldName, static_cast<double>(tempVal));
|
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") {
|
} else if (field.Type == "bool") {
|
||||||
auto& val = component.Property<bool>(fieldName);
|
auto& val = component.Property<bool>(fieldName);
|
||||||
ImGui::Checkbox("", &val);
|
ImGui::Checkbox("", &val);
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ BOOST_AUTO_TEST_CASE(ComponentPoolTest)
|
|||||||
//ci.Name = "Test";
|
//ci.Name = "Test";
|
||||||
//ci.FieldTypes["Field"] = "int";
|
//ci.FieldTypes["Field"] = "int";
|
||||||
//ci.FieldOffsets["Field"] = 0;
|
//ci.FieldOffsets["Field"] = 0;
|
||||||
//ci.Meta.Allocation = 3;
|
//ci.Meta->Allocation = 3;
|
||||||
//ci.Meta.Stride = sizeof(EntityID) + sizeof(int);
|
//ci.Stride = sizeof(EntityID) + sizeof(int);
|
||||||
|
|
||||||
//std::vector<ComponentWrapper> wrappers;
|
//std::vector<ComponentWrapper> wrappers;
|
||||||
//ComponentPool pool(ci);
|
//ComponentPool pool(ci);
|
||||||
|
|||||||
Reference in New Issue
Block a user