From 87c1ac3710060b5ed1ecd8fbe6319bfe4543dac3 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Wed, 29 Mar 2023 18:44:28 -0700 Subject: [PATCH] Cleaned prefab parser a lot --- .../material/SimpleTexturedMaterial.hpp | 2 + src/dawntools/prefabtool/CMakeLists.txt | 2 + src/dawntools/prefabtool/Parsers.hpp | 71 ++++++++++ .../prefabtool/PrefabChildParser.cpp | 61 +++++++++ .../prefabtool/PrefabChildParser.hpp | 24 +++- .../prefabtool/PrefabComponentParser.cpp | 56 +------- .../prefabtool/PrefabComponentParser.hpp | 2 +- src/dawntools/prefabtool/PrefabGen.cpp | 125 ++++++++++++++++++ src/dawntools/prefabtool/PrefabGen.hpp | 18 +++ src/dawntools/prefabtool/PrefabParser.cpp | 20 +-- src/dawntools/prefabtool/PrefabParser.hpp | 3 +- src/dawntools/prefabtool/PrefabRegistry.cpp | 1 + src/dawntools/prefabtool/PrefabTool.cpp | 67 +--------- src/dawntools/prefabtool/PrefabTool.hpp | 11 +- 14 files changed, 311 insertions(+), 152 deletions(-) create mode 100644 src/dawntools/prefabtool/Parsers.hpp create mode 100644 src/dawntools/prefabtool/PrefabChildParser.cpp create mode 100644 src/dawntools/prefabtool/PrefabGen.cpp create mode 100644 src/dawntools/prefabtool/PrefabGen.hpp diff --git a/src/dawnopengl/scene/components/display/material/SimpleTexturedMaterial.hpp b/src/dawnopengl/scene/components/display/material/SimpleTexturedMaterial.hpp index cc6f2264..ec29eb36 100644 --- a/src/dawnopengl/scene/components/display/material/SimpleTexturedMaterial.hpp +++ b/src/dawnopengl/scene/components/display/material/SimpleTexturedMaterial.hpp @@ -9,7 +9,9 @@ namespace Dawn { class SimpleTexturedMaterial : public Material { public: + // @optional Texture *texture = nullptr; + // @optional struct Color color = COLOR_WHITE; /** diff --git a/src/dawntools/prefabtool/CMakeLists.txt b/src/dawntools/prefabtool/CMakeLists.txt index b51ece00..cfa6ebc6 100644 --- a/src/dawntools/prefabtool/CMakeLists.txt +++ b/src/dawntools/prefabtool/CMakeLists.txt @@ -13,6 +13,8 @@ target_sources(prefabtool ${DAWN_SHARED_SOURCES} ${DAWN_TOOL_SOURCES} PrefabTool.cpp + PrefabGen.cpp + PrefabChildParser.cpp PrefabParser.cpp PrefabRegistry.cpp PrefabComponentParser.cpp diff --git a/src/dawntools/prefabtool/Parsers.hpp b/src/dawntools/prefabtool/Parsers.hpp new file mode 100644 index 00000000..3fcf7f56 --- /dev/null +++ b/src/dawntools/prefabtool/Parsers.hpp @@ -0,0 +1,71 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "util/string.hpp" + +namespace Dawn { + static inline std::string rawParser(std::string v, std::string *error) { + return v; + }; + + static inline std::string stringParser(std::string v, std::string *error) { + return "\"" + v + "\""; + }; + + static inline std::string floatParser(std::string v, std::string *error) { + v = stringTrim(v); + + // Make sure number contains decimal + if(v.find(".") == std::string::npos) { + v += ".0"; + } + // Make sure number contains a number before the decimal + if(v.find(".") == 0) { + v = "0" + v; + } + // Make sure ends with f + if(v.find("f") == std::string::npos) { + v += "f"; + } + return v; + }; + + static inline std::string vec2Parser(std::string v, std::string *error) { + // Split string by comma into two strings that we pass into float + auto split = stringSplit(v, ","); + if(split.size() != 2) { + *error = "Invalid vec2 value: " + v; + return std::string(""); + } + return std::string( + "glm::vec2(" + + floatParser(split[0], error) + ", " + + floatParser(split[1], error) + + ")" + ); + }; + + + static inline std::string vec3Parser(std::string v, std::string *error) { + // Split string by comma into two strings that we pass into float + auto split = stringSplit(v, ","); + if(split.size() != 3) { + *error = "Invalid vec3 value: " + v; + return std::string(""); + } + return std::string( + "glm::vec3(" + + floatParser(split[0], error) + ", " + + floatParser(split[1], error) + ", " + + floatParser(split[2], error) + + ")" + ); + }; + + static inline std::string colorParser(std::string v, std::string *error) { + return rawParser(v, error); + } +} \ No newline at end of file diff --git a/src/dawntools/prefabtool/PrefabChildParser.cpp b/src/dawntools/prefabtool/PrefabChildParser.cpp new file mode 100644 index 00000000..0dc5ecb6 --- /dev/null +++ b/src/dawntools/prefabtool/PrefabChildParser.cpp @@ -0,0 +1,61 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "PrefabChildParser.hpp" + +using namespace Dawn; + +std::vector PrefabChildParser::getRequiredAttributes() { + return std::vector(); +} + +std::map PrefabChildParser::getOptionalAttributes() { + return { + { "ref", "" }, + { "position", "" }, + { "scale", "" } + }; +} + +int32_t PrefabChildParser::onParse( + Xml *node, + std::map values, + struct PrefabChild *out, + std::string *error +) { + out->ref = values["ref"]; + + if(values["position"].size() > 0) { + out->position = vec3Parser(values["position"], error); + if(error->size() > 0) return 1; + } + + if(values["scale"].size() > 0) { + out->scale = vec3Parser(values["scale"], error); + if(error->size() > 0) return 1; + } + + auto itChildren = node->children.begin(); + while(itChildren != node->children.end()) { + // Parse child nodes, they may be components or not + auto c = *itChildren; + if(c->node == "child") { + struct PrefabChild child; + child.registry = out->registry; + auto ret = (PrefabChildParser()).parse(c, &child, error); + if(ret != 0) return ret; + out->children.push_back(child); + } else { + struct PrefabComponent component; + component.registry = out->registry; + auto ret = (PrefabComponentParser()).parse(c, &component, error); + if(ret != 0) return ret; + out->components.push_back(component); + } + ++itChildren; + } + + return 0; +} diff --git a/src/dawntools/prefabtool/PrefabChildParser.hpp b/src/dawntools/prefabtool/PrefabChildParser.hpp index c346c8ba..e9309f78 100644 --- a/src/dawntools/prefabtool/PrefabChildParser.hpp +++ b/src/dawntools/prefabtool/PrefabChildParser.hpp @@ -4,7 +4,27 @@ // https://opensource.org/licenses/MIT #pragma once -#include "PrefabParser.hpp" +#include "PrefabComponentParser.hpp" namespace Dawn { -} \ No newline at end of file + struct PrefabChild { + struct PrefabRegistry *registry; + std::string ref; + std::string position; + std::string scale; + std::vector components; + std::vector children; + }; + + class PrefabChildParser : public XmlParser { + protected: + std::vector getRequiredAttributes() override; + std::map getOptionalAttributes() override; + int32_t onParse( + Xml *node, + std::map values, + struct PrefabChild *out, + std::string *error + ) override; + }; +} diff --git a/src/dawntools/prefabtool/PrefabComponentParser.cpp b/src/dawntools/prefabtool/PrefabComponentParser.cpp index 657b5108..e84e316e 100644 --- a/src/dawntools/prefabtool/PrefabComponentParser.cpp +++ b/src/dawntools/prefabtool/PrefabComponentParser.cpp @@ -38,58 +38,6 @@ int32_t PrefabComponentParser::onParse( out->type = node->node; // Define parser types here. - auto rawParser = [&](std::string v){ - return v; - }; - - auto stringParser = [&](std::string v){ - return "\"" + v + "\""; - }; - - auto floatParser = [&](std::string v){ - v = stringTrim(v); - - // Make sure number contains decimal - if(v.find(".") == std::string::npos) { - v += ".0"; - } - // Make sure number contains a number before the decimal - if(v.find(".") == 0) { - v = "0" + v; - } - // Make sure ends with f - if(v.find("f") == std::string::npos) { - v += "f"; - } - return v; - }; - - auto vec2Parser = [&](std::string v) { - // Split string by comma into two strings that we pass into float - auto split = stringSplit(v, ","); - if(split.size() != 2) { - *error = "Invalid vec2 value: " + v; - return std::string(""); - } - return std::string( - "glm::vec2(" + floatParser(split[0]) + ", " + floatParser(split[1]) + ")" - ); - }; - - - auto vec3Parser = [&](std::string v) { - // Split string by comma into two strings that we pass into float - auto split = stringSplit(v, ","); - if(split.size() != 3) { - *error = "Invalid vec3 value: " + v; - return std::string(""); - } - return std::string( - "glm::vec3(" + floatParser(split[0]) + ", " + floatParser(split[1]) + ", " + floatParser(split[2]) + ")" - ); - }; - - auto colorParser = rawParser; // Iterate all the optional attributes and store within the out if present auto itOptional = ruleset.optional.begin(); @@ -98,7 +46,7 @@ int32_t PrefabComponentParser::onParse( auto name = itOptional->first; auto type = itOptional->second; - std::function parser = rawParser; + std::function parser = rawParser; if(type.find("string") != std::string::npos) { parser = stringParser; } else if(type.find("float") != std::string::npos) { @@ -122,7 +70,7 @@ int32_t PrefabComponentParser::onParse( if(node->attributes.find(name) != node->attributes.end()) { auto raw = node->attributes[name]; - out->values[name] = parser(raw); + out->values[name] = parser(raw, error); if(error->size() != 0) return 1; } ++itOptional; diff --git a/src/dawntools/prefabtool/PrefabComponentParser.hpp b/src/dawntools/prefabtool/PrefabComponentParser.hpp index e4f06020..7c209ba4 100644 --- a/src/dawntools/prefabtool/PrefabComponentParser.hpp +++ b/src/dawntools/prefabtool/PrefabComponentParser.hpp @@ -5,11 +5,11 @@ #pragma once #include "PrefabRegistry.hpp" +#include "Parsers.hpp" namespace Dawn { struct PrefabComponent { struct PrefabRegistry *registry; - std::string include; std::string type; std::map values; diff --git a/src/dawntools/prefabtool/PrefabGen.cpp b/src/dawntools/prefabtool/PrefabGen.cpp new file mode 100644 index 00000000..5a79f7d3 --- /dev/null +++ b/src/dawntools/prefabtool/PrefabGen.cpp @@ -0,0 +1,125 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "PrefabGen.hpp" + +using namespace Dawn; + +void PrefabGen::generate( + std::vector *out, + struct Prefab *info, + std::string tabs +) { + struct ClassGenInfo classInfo; + classInfo.clazz = info->name; + classInfo.extend = "SceneItemPrefab<" + info->name + ">"; + classInfo.constructorArgs = "Scene *scene, sceneitemid_t id"; + classInfo.extendArgs = "scene, id"; + + struct MethodGenInfo methodAssets; + methodAssets.name = "prefabAssets"; + methodAssets.isStatic = true; + methodAssets.type = "std::vector"; + methodAssets.args = "AssetManager *man"; + line(&methodAssets.body, "std::vector assets;", ""); + + struct MethodGenInfo methodInit; + methodInit.name = "prefabInit"; + methodInit.isOverride = true; + methodInit.args = "AssetManager *man"; + + classInfo.includes.push_back("prefab/SceneItemPrefab.hpp"); + + // Process root and all of its children + int32_t childNumber = 0; + int32_t componentNumber = 0; + + auto processComponent = [&](struct PrefabComponent c, std::string item) { + auto componentName = "cmp" + std::to_string(componentNumber++); + bool_t componentInit = true; + if(c.ref.size() > 0) { + componentInit = false; + componentName = c.ref; + line(&classInfo.publicProperties, c.type + " *" + c.ref + " = nullptr;", ""); + } + + // Initialize + line(&methodInit.body, (componentInit ? "auto " : "") + componentName + " = " + item + "->addComponent<" + c.type + ">();", ""); + + // Now set each property + auto itValues = c.values.begin(); + while(itValues != c.values.end()) { + line(&methodInit.body, componentName + "->" + itValues->first + " = " + itValues->second + ";", ""); + ++itValues; + } + + classInfo.includes.push_back(c.include); + }; + + std::function processChild; + processChild = [&](struct PrefabChild &child, std::string parent) { + auto name = "itm" + std::to_string(childNumber++); + bool_t init = true; + if(child.ref.size() > 0) { + init = false; + name = child.ref; + line(&classInfo.publicProperties, "SceneItemComponent *" + name + " = nullptr;", ""); + } + line(&methodInit.body, (init ? "auto " : "") + name + " = scene->createSceneItem();", ""); + + // Process extra properties + if(child.position.size() > 0) { + line(&methodInit.body, name + "->transform.setLocalPosition(" + child.position + ");", ""); + } + + if(child.scale.size() > 0) { + line(&methodInit.body, name + "->transform.setLocalScale(" + child.scale + ");", ""); + } + + // Add components for children + auto itComponents = child.components.begin(); + while(itComponents != child.components.end()) { + auto c = *itComponents; + processComponent(c, name); + ++itComponents; + } + + // Process sub children + auto itChildren = child.children.begin(); + while(itChildren != child.children.end()) { + processChild(*itChildren, name); + ++itChildren; + } + + // Set parent + line(&methodInit.body, name + "->transform.setParent(&"+parent+"->transform);", ""); + }; + + // Process each child + auto itChildren = info->root.children.begin(); + while(itChildren != info->root.children.end()) { + processChild(*itChildren, "this"); + line(&methodInit.body, "", ""); + ++itChildren; + } + + // Process self components + auto itComponents = info->root.components.begin(); + while(itComponents != info->root.components.end()) { + auto c = *itComponents; + processComponent(c, "this"); + ++itComponents; + } + + // Seal methods + line(&methodAssets.body, "return assets;", ""); + + // Add in methods + CodeGen::methodGen(&classInfo.publicCode, methodAssets); + line(&classInfo.publicCode, "", ""); + CodeGen::methodGen(&classInfo.publicCode, methodInit); + + CodeGen::classGen(out, classInfo); +} \ No newline at end of file diff --git a/src/dawntools/prefabtool/PrefabGen.hpp b/src/dawntools/prefabtool/PrefabGen.hpp new file mode 100644 index 00000000..43ecbed3 --- /dev/null +++ b/src/dawntools/prefabtool/PrefabGen.hpp @@ -0,0 +1,18 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "PrefabParser.hpp" + +namespace Dawn { + class PrefabGen : public CodeGen { + public: + static void generate( + std::vector *out, + struct Prefab *prefab, + std::string tabs + ); + }; +} \ No newline at end of file diff --git a/src/dawntools/prefabtool/PrefabParser.cpp b/src/dawntools/prefabtool/PrefabParser.cpp index c659edb1..159d7f1c 100644 --- a/src/dawntools/prefabtool/PrefabParser.cpp +++ b/src/dawntools/prefabtool/PrefabParser.cpp @@ -23,22 +23,6 @@ int32_t PrefabParser::onParse( ) { out->name = values["name"]; out->type = values["type"]; - - auto itChildren = node->children.begin(); - while(itChildren != node->children.end()) { - // Parse child nodes, they may be components or not - auto c = *itChildren; - if(c->node == "child") { - std::cout << "Child detected" << std::endl; - } else { - struct PrefabComponent component; - component.registry = out->registry; - auto ret = (PrefabComponentParser()).parse(*itChildren, &component, error); - if(ret != 0) return ret; - out->components.push_back(component); - } - ++itChildren; - } - - return 0; + out->root.registry = out->registry; + return (PrefabChildParser()).parse(node, &out->root, error); } \ No newline at end of file diff --git a/src/dawntools/prefabtool/PrefabParser.hpp b/src/dawntools/prefabtool/PrefabParser.hpp index e39cecc5..89053e87 100644 --- a/src/dawntools/prefabtool/PrefabParser.hpp +++ b/src/dawntools/prefabtool/PrefabParser.hpp @@ -5,13 +5,14 @@ #pragma once #include "PrefabComponentParser.hpp" +#include "PrefabChildParser.hpp" namespace Dawn { struct Prefab { struct PrefabRegistry *registry; + struct PrefabChild root; std::string name; std::string type; - std::vector components; }; class PrefabParser : public XmlParser { diff --git a/src/dawntools/prefabtool/PrefabRegistry.cpp b/src/dawntools/prefabtool/PrefabRegistry.cpp index 950410f1..bfd189bf 100644 --- a/src/dawntools/prefabtool/PrefabRegistry.cpp +++ b/src/dawntools/prefabtool/PrefabRegistry.cpp @@ -32,6 +32,7 @@ struct PrefabComponentParserRuleset PrefabRegistry::getRuleset(std::string type) continue; } + // Load ruleset std::string data; File file(str + "/" + itChildren->first); diff --git a/src/dawntools/prefabtool/PrefabTool.cpp b/src/dawntools/prefabtool/PrefabTool.cpp index c6ad8e8a..cd64f6b9 100644 --- a/src/dawntools/prefabtool/PrefabTool.cpp +++ b/src/dawntools/prefabtool/PrefabTool.cpp @@ -41,6 +41,7 @@ int32_t PrefabTool::start() { return result; } + // Generate output std::vector outputData; PrefabGen::generate(&outputData, &prefab, ""); @@ -66,70 +67,4 @@ int32_t PrefabTool::start() { } return 0; -} - -// - -void PrefabGen::generate( - std::vector *out, - struct Prefab *info, - std::string tabs -) { - struct ClassGenInfo classInfo; - classInfo.clazz = info->name; - classInfo.extend = "SceneItemPrefab<" + info->name + ">"; - classInfo.constructorArgs = "Scene *scene, sceneitemid_t id"; - classInfo.extendArgs = "scene, id"; - - struct MethodGenInfo methodAssets; - methodAssets.name = "prefabAssets"; - methodAssets.isStatic = true; - methodAssets.type = "std::vector"; - methodAssets.args = "AssetManager *man"; - line(&methodAssets.body, "std::vector assets;", ""); - - struct MethodGenInfo methodInit; - methodInit.name = "prefabInit"; - methodInit.isOverride = true; - methodInit.args = "AssetManager *man"; - - classInfo.includes.push_back("prefab/SceneItemPrefab.hpp"); - - // Includes - int32_t componentNumber = 0; - auto itChildren = info->components.begin(); - while(itChildren != info->components.end()) { - auto c = *itChildren; - std::string name = "c" + std::to_string(componentNumber++); - bool_t init = true; - if(c.ref.size() > 0) { - init = false; - name = c.ref; - line(&classInfo.publicProperties, c.type + " *" + c.ref + " = nullptr;", ""); - } - - // Initialize - line(&methodInit.body, (init ? "auto " : "") + name + " = this->addComponent<" + c.type + ">();", ""); - - // Now set each property - auto itValues = c.values.begin(); - while(itValues != c.values.end()) { - line(&methodInit.body, name + "->" + itValues->first + " = " + itValues->second + ";", ""); - ++itValues; - } - line(&methodInit.body, "", ""); - - classInfo.includes.push_back(c.include); - ++itChildren; - } - - // Seal methods - line(&methodAssets.body, "return assets;", ""); - - // Add in methods - CodeGen::methodGen(&classInfo.publicCode, methodAssets); - line(&classInfo.publicCode, "", ""); - CodeGen::methodGen(&classInfo.publicCode, methodInit); - - CodeGen::classGen(out, classInfo); } \ No newline at end of file diff --git a/src/dawntools/prefabtool/PrefabTool.hpp b/src/dawntools/prefabtool/PrefabTool.hpp index 66975056..4ff53d31 100644 --- a/src/dawntools/prefabtool/PrefabTool.hpp +++ b/src/dawntools/prefabtool/PrefabTool.hpp @@ -4,7 +4,7 @@ // https://opensource.org/licenses/MIT #pragma once -#include "PrefabParser.hpp" +#include "PrefabGen.hpp" namespace Dawn { class PrefabTool : public DawnTool { @@ -15,13 +15,4 @@ namespace Dawn { public: int32_t start(); }; - - class PrefabGen : public CodeGen { - public: - static void generate( - std::vector *out, - struct Prefab *prefab, - std::string tabs - ); - }; } \ No newline at end of file