diff --git a/include/Engine/Core/EntityFile.h b/include/Engine/Core/EntityFile.h index 7f02ed8b..4c2c7b3e 100644 --- a/include/Engine/Core/EntityFile.h +++ b/include/Engine/Core/EntityFile.h @@ -2,6 +2,7 @@ #define EntityFile_h__ #include +#include #include #include #include @@ -245,58 +246,54 @@ private: public: static std::size_t GetTypeStride(std::string typeName); -static void WriteElementData(const xercesc::DOMElement* element, std::string typeName, char* outData) -{ - using namespace xercesc; - if (typeName == "Vector") { - glm::vec3 vec; - vec.x = getFloatAttribute(element, "X"); - vec.y = getFloatAttribute(element, "Y"); - vec.z = getFloatAttribute(element, "Z"); - memcpy(outData, reinterpret_cast(&vec), GetTypeStride(typeName)); - } else if (typeName == "Color") { - glm::vec4 vec; - vec.r = getFloatAttribute(element, "R"); - vec.g = getFloatAttribute(element, "G"); - vec.b = getFloatAttribute(element, "B"); - vec.a = getFloatAttribute(element, "A"); - memcpy(outData, reinterpret_cast(&vec), GetTypeStride(typeName)); - } else if (typeName == "Quaternion") { - glm::quat q; - q.x = getFloatAttribute(element, "X"); - q.y = getFloatAttribute(element, "Y"); - q.z = getFloatAttribute(element, "Z"); - q.w = getFloatAttribute(element, "W"); - memcpy(outData, reinterpret_cast(&q), GetTypeStride(typeName)); - } else if (typeName == "float") { - XSValue::Status status; - XSValue* val = XSValue::getActualValue(element->getTextContent(), xercesc::XSValue::DataType::dt_float, status); - memcpy(outData, reinterpret_cast(&val->fData.fValue.f_float), GetTypeStride(typeName)); - } else if (typeName == "double") { - XSValue::Status status; - XSValue* val = XSValue::getActualValue(element->getTextContent(), xercesc::XSValue::DataType::dt_double, status); - memcpy(outData, reinterpret_cast(&val->fData.fValue.f_double), GetTypeStride(typeName)); - } else if (typeName == "bool") { - XSValue::Status status; - XSValue* val = XSValue::getActualValue(element->getTextContent(), xercesc::XSValue::DataType::dt_boolean, status); - memcpy(outData, reinterpret_cast(&val->fData.fValue.f_bool), GetTypeStride(typeName)); - } else { - XSValue::DataType dataType = XSValue::getDataType(XS::ToXMLCh(typeName)); - if (dataType == XSValue::DataType::dt_string) { - char* str = XMLString::transcode(element->getTextContent()); - std::string standardString(str); - new (outData) std::string(str); - XMLString::release(&str); - //memcpy(outData, reinterpret_cast(&standardString), getTypeStride(typeName)); - } else { - //XSValue::Status status; - //XSValue* val = XSValue::getActualValue(element->getTextContent(), dataType, status); - //memcpy(outData, reinterpret_cast(&val->fData.fValue), getTypeStride(typeName)); - LOG_WARNING("Unknown native data type: %s", typeName.c_str()); + static void WriteAttributeData(char* outData, const std::string fieldType, const std::map& attributes) + { + if (fieldType == "Vector") { + glm::vec3 vec; + vec.x = boost::lexical_cast(attributes.at("X")); + vec.y = boost::lexical_cast(attributes.at("Y")); + vec.z = boost::lexical_cast(attributes.at("Z")); + memcpy(outData, reinterpret_cast(&vec), EntityFile::GetTypeStride(fieldType)); + } else if (fieldType == "Color") { + glm::vec4 vec; + vec.r = boost::lexical_cast(attributes.at("R")); + vec.g = boost::lexical_cast(attributes.at("G")); + vec.b = boost::lexical_cast(attributes.at("B")); + vec.a = boost::lexical_cast(attributes.at("A")); + memcpy(outData, reinterpret_cast(&vec), EntityFile::GetTypeStride(fieldType)); + } else if (fieldType == "Quaternion") { + glm::quat q; + q.x = boost::lexical_cast(attributes.at("X")); + q.y = boost::lexical_cast(attributes.at("Y")); + q.z = boost::lexical_cast(attributes.at("Z")); + q.w = boost::lexical_cast(attributes.at("W")); + memcpy(outData, reinterpret_cast(&q), EntityFile::GetTypeStride(fieldType)); + } else if (!attributes.empty()) { + LOG_WARNING("%i attributes not handled by any type conversion!", attributes.size()); + } + } + + static void WriteValueData(char* outData, const std::string fieldType, const char* valueData) + { + if (fieldType == "int") { + int value = boost::lexical_cast(valueData); + memcpy(outData, reinterpret_cast(&value), EntityFile::GetTypeStride(fieldType)); + } else if (fieldType == "float") { + float value = boost::lexical_cast(valueData); + memcpy(outData, reinterpret_cast(&value), EntityFile::GetTypeStride(fieldType)); + } else if (fieldType == "double") { + double value = boost::lexical_cast(valueData); + memcpy(outData, reinterpret_cast(&value), EntityFile::GetTypeStride(fieldType)); + } else if (fieldType == "bool") { + bool value = (valueData[0] == 't'); // Lazy bool evaluation + memcpy(outData, reinterpret_cast(&value), EntityFile::GetTypeStride(fieldType)); + } else if (fieldType == "string") { + new (outData) std::string(valueData); + } else { + LOG_WARNING("Unknown value data type: %s", fieldType.c_str()); } } -} void Parse(const EntityFileHandler* handler); //const std::map& ComponentInfo() const { return m_ComponentInfo; } diff --git a/include/Engine/Core/EntityFileParser.h b/include/Engine/Core/EntityFileParser.h index 04e732d6..4a989719 100644 --- a/include/Engine/Core/EntityFileParser.h +++ b/include/Engine/Core/EntityFileParser.h @@ -55,29 +55,7 @@ private: } char* data = component.Data + component.Info.FieldOffsets.at(fieldName); - if (fieldType == "Vector") { - glm::vec3 vec; - vec.x = boost::lexical_cast(attributes.at("X")); - vec.y = boost::lexical_cast(attributes.at("Y")); - vec.z = boost::lexical_cast(attributes.at("Z")); - memcpy(data, reinterpret_cast(&vec), EntityFile::GetTypeStride(fieldType)); - } else if (fieldType == "Color") { - glm::vec4 vec; - vec.r = boost::lexical_cast(attributes.at("R")); - vec.g = boost::lexical_cast(attributes.at("G")); - vec.b = boost::lexical_cast(attributes.at("B")); - vec.a = boost::lexical_cast(attributes.at("A")); - memcpy(data, reinterpret_cast(&vec), EntityFile::GetTypeStride(fieldType)); - } else if (fieldType == "Quaternion") { - glm::quat q; - q.x = boost::lexical_cast(attributes.at("X")); - q.y = boost::lexical_cast(attributes.at("Y")); - q.z = boost::lexical_cast(attributes.at("Z")); - q.w = boost::lexical_cast(attributes.at("W")); - memcpy(data, reinterpret_cast(&q), EntityFile::GetTypeStride(fieldType)); - } else if (!attributes.empty()) { - LOG_WARNING("%i attributes not handled by any type conversion!", attributes.size()); - } + EntityFile::WriteAttributeData(data, fieldType, attributes); } void onFieldData(EntityID entity, std::string componentType, std::string fieldName, const char* fieldData) @@ -87,22 +65,6 @@ private: std::string fieldType = component.Info.FieldTypes.at(fieldName); char* data = component.Data + component.Info.FieldOffsets.at(fieldName); - if (fieldType == "int") { - int value = boost::lexical_cast(fieldData); - memcpy(data, reinterpret_cast(&value), EntityFile::GetTypeStride(fieldType)); - } else if (fieldType == "float") { - float value = boost::lexical_cast(fieldData); - memcpy(data, reinterpret_cast(&value), EntityFile::GetTypeStride(fieldType)); - } else if (fieldType == "double") { - double value = boost::lexical_cast(fieldData); - memcpy(data, reinterpret_cast(&value), EntityFile::GetTypeStride(fieldType)); - } else if (fieldType == "bool") { - bool value = (fieldData[0] == 't'); // Lazy bool evaluation - memcpy(data, reinterpret_cast(&value), EntityFile::GetTypeStride(fieldType)); - } else if (fieldType == "string") { - new (data) std::string(fieldData); - } else { - LOG_WARNING("Unknown data type: %s", fieldType.c_str()); - } + EntityFile::WriteValueData(data, fieldType, fieldData); } }; \ No newline at end of file diff --git a/include/Engine/Core/EntityFilePreprocessor.h b/include/Engine/Core/EntityFilePreprocessor.h index 81cd6992..e0e4cd52 100644 --- a/include/Engine/Core/EntityFilePreprocessor.h +++ b/include/Engine/Core/EntityFilePreprocessor.h @@ -174,53 +174,72 @@ private: } } -void parseDefaults() -{ - using namespace xercesc; + void parseDefaults() + { + using namespace xercesc; - for (auto& ci : m_ComponentInfo) { - // Allocate memory for default values - ci.second.Defaults = std::shared_ptr(new char[ci.second.Meta.Stride]); - memset(ci.second.Defaults.get(), 0, ci.second.Meta.Stride); + for (auto& ci : m_ComponentInfo) { + // Allocate memory for default values + ci.second.Defaults = std::shared_ptr(new char[ci.second.Meta.Stride]); + memset(ci.second.Defaults.get(), 0, ci.second.Meta.Stride); - XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager); - //parser.setErrorHandler(m_ErrorHandler); + XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager); + //parser.setErrorHandler(m_ErrorHandler); - std::string componentName = ci.first; - LOG_DEBUG("Parsing defaults for component %s", componentName.c_str()); - boost::filesystem::path defaultsFile = "Schema/Components/" + componentName + ".xml"; + std::string componentName = ci.first; + LOG_DEBUG("Parsing defaults for component %s", componentName.c_str()); + boost::filesystem::path defaultsFile = "Schema/Components/" + componentName + ".xml"; - parser.parse(defaultsFile.string().c_str()); - auto doc = parser.getDocument(); - if (doc == nullptr) { - LOG_ERROR("%s not found! Skipping.", defaultsFile.string().c_str()); - continue; - } - - // Find the node in the components namespace matching the component name - std::string tagName = "c:" + componentName; - auto rootNodes = doc->getElementsByTagName(XS::ToXMLCh(tagName)); - if (rootNodes->getLength() == 0) { - LOG_ERROR("Couldn't find defaults for component \"%s\"! Skipping.", componentName.c_str()); - continue; - } - auto componentElement = dynamic_cast(rootNodes->item(0)); - - // Fill the default value buffer with values - for (auto& field : ci.second.FieldOffsets) { - std::string fieldName = field.first; - auto fieldNodes = componentElement->getElementsByTagName(XS::ToXMLCh(fieldName)); - auto fieldNode = fieldNodes->item(0); - if (fieldNode == nullptr) { - LOG_ERROR("Defaults for component \"%s\" is missing field \"%s\"!", componentName.c_str(), fieldName.c_str()); + parser.parse(defaultsFile.string().c_str()); + auto doc = parser.getDocument(); + if (doc == nullptr) { + LOG_ERROR("%s not found! Skipping.", defaultsFile.string().c_str()); continue; } - auto fieldElement = dynamic_cast(fieldNode); - std::string fieldType = ci.second.FieldTypes.at(fieldName); - unsigned int fieldOffset = ci.second.FieldOffsets.at(fieldName); - EntityFile::WriteElementData(fieldElement, fieldType, ci.second.Defaults.get() + fieldOffset); + // Find the node in the components namespace matching the component name + std::string tagName = "c:" + componentName; + auto rootNodes = doc->getElementsByTagName(XS::ToXMLCh(tagName)); + if (rootNodes->getLength() == 0) { + LOG_ERROR("Couldn't find defaults for component \"%s\"! Skipping.", componentName.c_str()); + continue; + } + auto componentElement = dynamic_cast(rootNodes->item(0)); + + // Fill the default value buffer with values + for (auto& field : ci.second.FieldOffsets) { + std::string fieldName = field.first; + auto fieldNodes = componentElement->getElementsByTagName(XS::ToXMLCh(fieldName)); + auto fieldNode = fieldNodes->item(0); + if (fieldNode == nullptr) { + LOG_ERROR("Defaults for component \"%s\" is missing field \"%s\"!", componentName.c_str(), fieldName.c_str()); + continue; + } + auto fieldElement = dynamic_cast(fieldNode); + + std::string fieldType = ci.second.FieldTypes.at(fieldName); + unsigned int fieldOffset = ci.second.FieldOffsets.at(fieldName); + char* data = ci.second.Defaults.get() + fieldOffset; + + // Handle potential field attributes + if (fieldElement->hasAttributes()) { + std::map attributes; + auto attributeMap = fieldElement->getAttributes(); + for (int i = 0; i < attributeMap->getLength(); ++i) { + auto attribItem = attributeMap->item(i); + attributes[XS::ToString(attribItem->getNodeName())] = XS::ToString(attribItem->getNodeValue()); + } + EntityFile::WriteAttributeData(data, fieldType, attributes); + } + + // Handle potential field values + auto childNode = fieldElement->getFirstChild(); + if (childNode != nullptr && childNode->getNodeType() == DOMNode::TEXT_NODE) { + char* cstrValue = XMLString::transcode(childNode->getNodeValue()); + EntityFile::WriteValueData(data, fieldType, cstrValue); + XMLString::release(&cstrValue); + } + } } } -} }; \ No newline at end of file