Added stride information to ComponentInfo, refactored FieldOffsets and FieldTypes into new struct Field_t Fields while I was at it.

This commit is contained in:
2016-01-08 11:47:58 +01:00
parent 81024b4a1d
commit 24b9e951c2
8 changed files with 83 additions and 75 deletions
+8 -2
View File
@@ -12,9 +12,15 @@ struct ComponentInfo
unsigned int Stride = 0; unsigned int Stride = 0;
}; };
struct Field_t
{
std::string Type;
unsigned int Offset;
unsigned int Stride;
};
std::string Name; std::string Name;
std::unordered_map<std::string, std::string> FieldTypes; std::unordered_map<std::string, Field_t> Fields;
std::unordered_map<std::string, unsigned int> FieldOffsets;
Meta_t Meta; Meta_t Meta;
std::shared_ptr<char> Defaults = nullptr; std::shared_ptr<char> Defaults = nullptr;
}; };
+4 -3
View File
@@ -21,7 +21,7 @@ struct ComponentWrapper
template <typename T> template <typename T>
T& Property(std::string name) T& Property(std::string name)
{ {
unsigned int offset = Info.FieldOffsets.at(name); unsigned int offset = Info.Fields.at(name).Offset;
return *reinterpret_cast<T*>(&Data[offset]); return *reinterpret_cast<T*>(&Data[offset]);
} }
@@ -78,8 +78,9 @@ public:
void AddProperty(std::string fieldName, T defaultValue) void AddProperty(std::string fieldName, T defaultValue)
{ {
m_DefaultValues.push_back(defaultValue); m_DefaultValues.push_back(defaultValue);
m_ComponentInfo.FieldTypes[fieldName] = typeid(T).name(); m_ComponentInfo.Fields[fieldName].Name = typeid(T).name();
m_ComponentInfo.FieldOffsets[fieldName] = m_ComponentInfo.Meta.Stride; m_ComponentInfo.Fields[fieldName].Offset = m_ComponentInfo.Meta.Stride;
m_ComponentInfo.Fields[fieldName].Stride = sizeof(T);
m_ComponentInfo.Meta.Stride += sizeof(T); m_ComponentInfo.Meta.Stride += sizeof(T);
} }
+2 -2
View File
@@ -275,8 +275,8 @@ private:
public: public:
static std::size_t GetTypeStride(std::string typeName); static std::size_t GetTypeStride(std::string typeName);
static void WriteAttributeData(char* outData, const std::string fieldType, const std::map<std::string, std::string>& attributes); static void WriteAttributeData(char* outData, const ComponentInfo::Field_t& field, const std::map<std::string, std::string>& attributes);
static void WriteValueData(char* outData, const std::string fieldType, const char* valueData); static void WriteValueData(char* outData, const ComponentInfo::Field_t& field, const char* valueData);
xercesc::XMLGrammarPool* GrammarPool() const { return m_GrammarPool; } xercesc::XMLGrammarPool* GrammarPool() const { return m_GrammarPool; }
+18 -18
View File
@@ -46,50 +46,50 @@ std::size_t EntityFile::GetTypeStride(std::string typeName)
return (it != typeStrides.end()) ? it->second : 0; return (it != typeStrides.end()) ? it->second : 0;
} }
void EntityFile::WriteAttributeData(char* outData, const std::string fieldType, const std::map<std::string, std::string>& attributes) void EntityFile::WriteAttributeData(char* outData, const ComponentInfo::Field_t& field, const std::map<std::string, std::string>& attributes)
{ {
if (fieldType == "Vector") { if (field.Type == "Vector") {
glm::vec3 vec; glm::vec3 vec;
vec.x = boost::lexical_cast<float>(attributes.at("X")); vec.x = boost::lexical_cast<float>(attributes.at("X"));
vec.y = boost::lexical_cast<float>(attributes.at("Y")); vec.y = boost::lexical_cast<float>(attributes.at("Y"));
vec.z = boost::lexical_cast<float>(attributes.at("Z")); vec.z = boost::lexical_cast<float>(attributes.at("Z"));
memcpy(outData, reinterpret_cast<char*>(&vec), EntityFile::GetTypeStride(fieldType)); memcpy(outData, reinterpret_cast<char*>(&vec), field.Stride);
} else if (fieldType == "Color") { } else if (field.Type == "Color") {
glm::vec4 vec; glm::vec4 vec;
vec.r = boost::lexical_cast<float>(attributes.at("R")); vec.r = boost::lexical_cast<float>(attributes.at("R"));
vec.g = boost::lexical_cast<float>(attributes.at("G")); vec.g = boost::lexical_cast<float>(attributes.at("G"));
vec.b = boost::lexical_cast<float>(attributes.at("B")); vec.b = boost::lexical_cast<float>(attributes.at("B"));
vec.a = boost::lexical_cast<float>(attributes.at("A")); vec.a = boost::lexical_cast<float>(attributes.at("A"));
memcpy(outData, reinterpret_cast<char*>(&vec), EntityFile::GetTypeStride(fieldType)); memcpy(outData, reinterpret_cast<char*>(&vec), field.Stride);
} else if (fieldType == "Quaternion") { } else if (field.Type == "Quaternion") {
glm::quat q; glm::quat q;
q.x = boost::lexical_cast<float>(attributes.at("X")); q.x = boost::lexical_cast<float>(attributes.at("X"));
q.y = boost::lexical_cast<float>(attributes.at("Y")); q.y = boost::lexical_cast<float>(attributes.at("Y"));
q.z = boost::lexical_cast<float>(attributes.at("Z")); q.z = boost::lexical_cast<float>(attributes.at("Z"));
q.w = boost::lexical_cast<float>(attributes.at("W")); q.w = boost::lexical_cast<float>(attributes.at("W"));
memcpy(outData, reinterpret_cast<char*>(&q), EntityFile::GetTypeStride(fieldType)); memcpy(outData, reinterpret_cast<char*>(&q), field.Stride);
} else if (!attributes.empty()) { } else if (!attributes.empty()) {
LOG_WARNING("%i attributes not handled by any type conversion!", attributes.size()); LOG_WARNING("%i attributes not handled by any type conversion!", attributes.size());
} }
} }
void EntityFile::WriteValueData(char* outData, const std::string fieldType, const char* valueData) void EntityFile::WriteValueData(char* outData, const ComponentInfo::Field_t& field, const char* valueData)
{ {
if (fieldType == "int") { if (field.Type == "int") {
int value = boost::lexical_cast<int>(valueData); int value = boost::lexical_cast<int>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), EntityFile::GetTypeStride(fieldType)); memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (fieldType == "float") { } else if (field.Type == "float") {
float value = boost::lexical_cast<float>(valueData); float value = boost::lexical_cast<float>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), EntityFile::GetTypeStride(fieldType)); memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (fieldType == "double") { } else if (field.Type == "double") {
double value = boost::lexical_cast<double>(valueData); double value = boost::lexical_cast<double>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), EntityFile::GetTypeStride(fieldType)); memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (fieldType == "bool") { } else if (field.Type == "bool") {
bool value = (valueData[0] == 't'); // Lazy bool evaluation bool value = (valueData[0] == 't'); // Lazy bool evaluation
memcpy(outData, reinterpret_cast<char*>(&value), EntityFile::GetTypeStride(fieldType)); memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (fieldType == "string") { } else if (field.Type == "string") {
new (outData) std::string(valueData); new (outData) std::string(valueData);
} else { } else {
LOG_WARNING("Unknown value data type: %s", fieldType.c_str()); LOG_WARNING("Unknown value data type: %s", field.Type.c_str());
} }
} }
+7 -7
View File
@@ -35,24 +35,24 @@ void EntityFileParser::onStartComponentField(EntityID entity, std::string compon
{ {
EntityID realEntity = m_EntityIDMapper.at(entity); EntityID realEntity = m_EntityIDMapper.at(entity);
ComponentWrapper component = m_World->GetComponent(realEntity, componentType); ComponentWrapper component = m_World->GetComponent(realEntity, componentType);
std::string fieldType = component.Info.FieldTypes.at(fieldName); auto& field = component.Info.Fields.at(fieldName);
LOG_DEBUG("Field \"%s\" type \"%s\"", fieldName.c_str(), fieldType.c_str()); LOG_DEBUG("Field \"%s\" type \"%s\"", fieldName.c_str(), field.Type.c_str());
LOG_DEBUG("Attributes:"); LOG_DEBUG("Attributes:");
for (auto& kv : attributes) { for (auto& kv : attributes) {
LOG_DEBUG("\t%s = %s", kv.first.c_str(), kv.second.c_str()); LOG_DEBUG("\t%s = %s", kv.first.c_str(), kv.second.c_str());
} }
char* data = component.Data + component.Info.FieldOffsets.at(fieldName); char* data = component.Data + field.Offset;
EntityFile::WriteAttributeData(data, fieldType, attributes); EntityFile::WriteAttributeData(data, field, attributes);
} }
void EntityFileParser::onFieldData(EntityID entity, std::string componentType, std::string fieldName, const char* fieldData) void EntityFileParser::onFieldData(EntityID entity, std::string componentType, std::string fieldName, const char* fieldData)
{ {
EntityID realEntity = m_EntityIDMapper.at(entity); EntityID realEntity = m_EntityIDMapper.at(entity);
ComponentWrapper component = m_World->GetComponent(realEntity, componentType); ComponentWrapper component = m_World->GetComponent(realEntity, componentType);
std::string fieldType = component.Info.FieldTypes.at(fieldName); auto& field = component.Info.Fields.at(fieldName);
char* data = component.Data + component.Info.FieldOffsets.at(fieldName); char* data = component.Data + field.Offset;
EntityFile::WriteValueData(data, fieldType, fieldData); EntityFile::WriteValueData(data, field, fieldData);
} }
+13 -11
View File
@@ -19,8 +19,9 @@ EntityFilePreprocessor::EntityFilePreprocessor(const EntityFile* entityFile)
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.Meta.Stride);
LOG_DEBUG("Allocation: %i", info.Meta.Allocation); LOG_DEBUG("Allocation: %i", info.Meta.Allocation);
for (auto& kv : info.FieldTypes) { for (auto& kv : info.Fields) {
LOG_DEBUG("\t%i\t%s %s", info.FieldOffsets[kv.first], kv.second.c_str(), kv.first.c_str()); auto& field = kv.second;
LOG_DEBUG("\t%i\t%s %s", field.Offset, field.Type, kv.first.c_str());
} }
} }
@@ -142,8 +143,10 @@ void EntityFilePreprocessor::parseComponentInfo()
continue; continue;
} }
compInfo.FieldTypes[name] = type; compInfo.Fields[name].Type = type;
compInfo.FieldOffsets[name] = fieldOffset; compInfo.Fields[name].Offset = fieldOffset;
compInfo.Fields[name].Stride = stride;
fieldOffset += stride; fieldOffset += stride;
} }
@@ -187,8 +190,9 @@ void EntityFilePreprocessor::parseDefaults()
auto componentElement = dynamic_cast<DOMElement*>(rootNodes->item(0)); auto componentElement = dynamic_cast<DOMElement*>(rootNodes->item(0));
// Fill the default value buffer with values // Fill the default value buffer with values
for (auto& field : ci.second.FieldOffsets) { for (auto& kv : ci.second.Fields) {
std::string fieldName = field.first; std::string fieldName = kv.first;
auto& field = kv.second;
auto fieldNodes = componentElement->getElementsByTagName(XS::ToXMLCh(fieldName)); auto fieldNodes = componentElement->getElementsByTagName(XS::ToXMLCh(fieldName));
auto fieldNode = fieldNodes->item(0); auto fieldNode = fieldNodes->item(0);
if (fieldNode == nullptr) { if (fieldNode == nullptr) {
@@ -197,9 +201,7 @@ void EntityFilePreprocessor::parseDefaults()
} }
auto fieldElement = dynamic_cast<DOMElement*>(fieldNode); auto fieldElement = dynamic_cast<DOMElement*>(fieldNode);
std::string fieldType = ci.second.FieldTypes.at(fieldName); char* data = ci.second.Defaults.get() + field.Offset;
unsigned int fieldOffset = ci.second.FieldOffsets.at(fieldName);
char* data = ci.second.Defaults.get() + fieldOffset;
// Handle potential field attributes // Handle potential field attributes
if (fieldElement->hasAttributes()) { if (fieldElement->hasAttributes()) {
@@ -209,14 +211,14 @@ void EntityFilePreprocessor::parseDefaults()
auto attribItem = attributeMap->item(i); auto attribItem = attributeMap->item(i);
attributes[XS::ToString(attribItem->getNodeName())] = XS::ToString(attribItem->getNodeValue()); attributes[XS::ToString(attribItem->getNodeName())] = XS::ToString(attribItem->getNodeValue());
} }
EntityFile::WriteAttributeData(data, fieldType, attributes); EntityFile::WriteAttributeData(data, field, attributes);
} }
// Handle potential field values // Handle potential field values
auto childNode = fieldElement->getFirstChild(); auto childNode = fieldElement->getFirstChild();
if (childNode != nullptr && childNode->getNodeType() == DOMNode::TEXT_NODE) { if (childNode != nullptr && childNode->getNodeType() == DOMNode::TEXT_NODE) {
char* cstrValue = XMLString::transcode(childNode->getNodeValue()); char* cstrValue = XMLString::transcode(childNode->getNodeValue());
EntityFile::WriteValueData(data, fieldType, cstrValue); EntityFile::WriteValueData(data, field, cstrValue);
XMLString::release(&cstrValue); XMLString::release(&cstrValue);
} }
} }
+11 -12
View File
@@ -64,54 +64,53 @@ void EntityFileWriter::appentEntityComponents(xercesc::DOMElement* parentElement
DOMElement* componentElement = doc->createElement(X(qualifiedComponentName)); DOMElement* componentElement = doc->createElement(X(qualifiedComponentName));
parentElement->appendChild(componentElement); parentElement->appendChild(componentElement);
ComponentWrapper c = kv.second->GetByEntity(entity); ComponentWrapper c = kv.second->GetByEntity(entity);
for (auto& kv : c.Info.FieldTypes) { for (auto& kv : c.Info.Fields) {
std::string fieldName = kv.first; std::string fieldName = kv.first;
std::string fieldType = kv.second; auto& field = kv.second;
std::size_t fieldOffset = c.Info.FieldOffsets.at(fieldName);
// Ignore fields that are equal to the default // Ignore fields that are equal to the default
// HACK: This is probably sloooooow, but it's okay. // HACK: This is probably sloooooow, but it's okay.
if (memcmp(c.Data + fieldOffset, c.Info.Defaults.get() + fieldOffset, EntityFile::GetTypeStride(fieldType)) == 0) { if (memcmp(c.Data + field.Offset, c.Info.Defaults.get() + field.Offset, field.Stride) == 0) {
continue; continue;
} }
DOMElement* fieldElement = doc->createElement(X(fieldName)); DOMElement* fieldElement = doc->createElement(X(fieldName));
componentElement->appendChild(fieldElement); componentElement->appendChild(fieldElement);
if (fieldType == "Vector") { if (field.Type == "Vector") {
const glm::vec3& vec = c[fieldName]; const glm::vec3& vec = c[fieldName];
fieldElement->setAttribute(X("X"), X(boost::lexical_cast<std::string>(vec.x))); fieldElement->setAttribute(X("X"), X(boost::lexical_cast<std::string>(vec.x)));
fieldElement->setAttribute(X("Y"), X(boost::lexical_cast<std::string>(vec.y))); fieldElement->setAttribute(X("Y"), X(boost::lexical_cast<std::string>(vec.y)));
fieldElement->setAttribute(X("Z"), X(boost::lexical_cast<std::string>(vec.z))); fieldElement->setAttribute(X("Z"), X(boost::lexical_cast<std::string>(vec.z)));
} else if (fieldType == "Color") { } else if (field.Type == "Color") {
const glm::vec4& vec = c[fieldName]; const glm::vec4& vec = c[fieldName];
fieldElement->setAttribute(X("R"), X(boost::lexical_cast<std::string>(vec.r))); fieldElement->setAttribute(X("R"), X(boost::lexical_cast<std::string>(vec.r)));
fieldElement->setAttribute(X("G"), X(boost::lexical_cast<std::string>(vec.g))); fieldElement->setAttribute(X("G"), X(boost::lexical_cast<std::string>(vec.g)));
fieldElement->setAttribute(X("B"), X(boost::lexical_cast<std::string>(vec.b))); fieldElement->setAttribute(X("B"), X(boost::lexical_cast<std::string>(vec.b)));
fieldElement->setAttribute(X("A"), X(boost::lexical_cast<std::string>(vec.a))); fieldElement->setAttribute(X("A"), X(boost::lexical_cast<std::string>(vec.a)));
} else if (fieldType == "Quaternion") { } else if (field.Type == "Quaternion") {
const glm::quat& q = c[fieldName]; const glm::quat& q = c[fieldName];
fieldElement->setAttribute(X("X"), X(boost::lexical_cast<std::string>(q.x))); fieldElement->setAttribute(X("X"), X(boost::lexical_cast<std::string>(q.x)));
fieldElement->setAttribute(X("Y"), X(boost::lexical_cast<std::string>(q.y))); fieldElement->setAttribute(X("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 (fieldType == "int") { } else if (field.Type == "int") {
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 (fieldType == "float") { } else if (field.Type == "float") {
const float& value = c[fieldName]; const float& 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 (fieldType == "double") { } else if (field.Type == "double") {
const double& value = c[fieldName]; const double& 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 (fieldType == "bool") { } else if (field.Type == "bool") {
const bool& value = c[fieldName]; const bool& value = c[fieldName];
if (value) { if (value) {
fieldElement->appendChild(doc->createTextNode(X("true"))); fieldElement->appendChild(doc->createTextNode(X("true")));
} else { } else {
fieldElement->appendChild(doc->createTextNode(X("false"))); fieldElement->appendChild(doc->createTextNode(X("false")));
} }
} else if (fieldType == "string") { } else if (field.Type == "string") {
const std::string& value = c[fieldName]; const std::string& value = c[fieldName];
fieldElement->appendChild(doc->createTextNode(X(value))); fieldElement->appendChild(doc->createTextNode(X(value)));
} }
+20 -20
View File
@@ -432,16 +432,16 @@ void EditorSystem::drawUI(World* world, double dt)
} }
auto& component = world->GetComponent(m_Selection, componentType); auto& component = world->GetComponent(m_Selection, componentType);
for (auto& pair : ci.FieldTypes) { for (auto& kv : ci.Fields) {
const std::string& field = pair.first; const std::string& fieldName = kv.first;
const std::string& type = pair.second; auto& field = kv.second;
ImGui::PushID(field.c_str()); ImGui::PushID(fieldName.c_str());
if (type == "Vector") { if (field.Type == "Vector") {
auto& val = component.Property<glm::vec3>(field); auto& val = component.Property<glm::vec3>(fieldName);
if (field == "Scale") { if (fieldName == "Scale") {
ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits<float>::max()); ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits<float>::max());
} else if (field == "Orientation") { } else if (fieldName == "Orientation") {
glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi<float>())); glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi<float>()));
if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi<float>())) { if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi<float>())) {
val = tempVal; val = tempVal;
@@ -449,16 +449,16 @@ void EditorSystem::drawUI(World* world, double dt)
} else { } else {
ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max()); ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max());
} }
} else if (type == "Color") { } else if (field.Type == "Color") {
auto& val = component.Property<glm::vec4>(field); auto& val = component.Property<glm::vec4>(fieldName);
ImGui::ColorEdit4("", glm::value_ptr(val), true); ImGui::ColorEdit4("", glm::value_ptr(val), true);
} else if (type == "string") { } else if (field.Type == "string") {
std::string& val = component.Property<std::string>(field); std::string& val = component.Property<std::string>(fieldName);
char tempString[1024]; char tempString[1024];
memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString))); memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString)));
if (ImGui::InputText("", tempString, sizeof(tempString))) { if (ImGui::InputText("", tempString, sizeof(tempString))) {
val = std::string(tempString); val = std::string(tempString);
LOG_DEBUG("%s::%s changed!", componentType.c_str(), field.c_str()); LOG_DEBUG("%s::%s changed!", componentType.c_str(), fieldName.c_str());
} }
// DROP STUFF // DROP STUFF
if (ImGui::IsItemHovered() && !m_LastDroppedFile.empty()) { if (ImGui::IsItemHovered() && !m_LastDroppedFile.empty()) {
@@ -466,21 +466,21 @@ void EditorSystem::drawUI(World* world, double dt)
m_LastDroppedFile = ""; m_LastDroppedFile = "";
} }
} else if (type == "double") { } else if (field.Type == "double") {
float tempVal = static_cast<float>(component.Property<double>(field)); float tempVal = static_cast<float>(component.Property<double>(fieldName));
if (ImGui::InputFloat("", &tempVal, 0.01f, 1.f)) { if (ImGui::InputFloat("", &tempVal, 0.01f, 1.f)) {
component.SetProperty(field, static_cast<double>(tempVal)); component.SetProperty(fieldName, static_cast<double>(tempVal));
} }
} else if (type == "bool") { } else if (field.Type == "bool") {
auto& val = component.Property<bool>(field); auto& val = component.Property<bool>(fieldName);
ImGui::Checkbox("", &val); ImGui::Checkbox("", &val);
} else { } else {
ImGui::TextDisabled(type.c_str()); ImGui::TextDisabled(field.Type.c_str());
} }
ImGui::PopID(); ImGui::PopID();
ImGui::SameLine(); ImGui::SameLine();
ImGui::Text(field.c_str()); ImGui::Text(fieldName.c_str());
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("field annotation goes here"); ImGui::SetTooltip("field annotation goes here");
} }