diff --git a/src/dawn/prefab/SceneItemPrefab.hpp b/src/dawn/prefab/SceneItemPrefab.hpp index 3b3b6c04..6fc24048 100644 --- a/src/dawn/prefab/SceneItemPrefab.hpp +++ b/src/dawn/prefab/SceneItemPrefab.hpp @@ -35,7 +35,6 @@ namespace Dawn { SceneItemPrefab(Scene *scene, sceneitemid_t id) : SceneItem(scene, id) { - } /** diff --git a/src/dawn/scene/components/physics/2d/CharacterController2D.hpp b/src/dawn/scene/components/physics/2d/CharacterController2D.hpp index 7b9e9a06..04d5bbd4 100644 --- a/src/dawn/scene/components/physics/2d/CharacterController2D.hpp +++ b/src/dawn/scene/components/physics/2d/CharacterController2D.hpp @@ -13,7 +13,7 @@ namespace Dawn { public: // @optional - glm::vec2 velocity; + glm::vec2 velocity = glm::vec2(0, 0); // @optional float_t friction = 12.0f; diff --git a/src/dawnrose/CMakeLists.txt b/src/dawnrose/CMakeLists.txt index cb218c1f..a103937e 100644 --- a/src/dawnrose/CMakeLists.txt +++ b/src/dawnrose/CMakeLists.txt @@ -19,4 +19,4 @@ add_subdirectory(scene) # Assets set(ROSE_ASSETS_DIR ${DAWN_ASSETS_DIR}/games/rose) -tool_prefab(${ROSE_ASSETS_DIR}/prefabs/PlayerPrefab.xml) \ No newline at end of file +tool_prefab(${ROSE_ASSETS_DIR}/prefabs/Player.xml) \ No newline at end of file diff --git a/src/dawnrose/prefabs/PlayerPrefab_old.hpp b/src/dawnrose/prefabs/PlayerPrefab_old.hpp deleted file mode 100644 index 088d1f71..00000000 --- a/src/dawnrose/prefabs/PlayerPrefab_old.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2023 Dominic Masters -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT - -#pragma once -#include "prefab/SceneItemPrefab.hpp" -#include "scene/components/display/MeshHost.hpp" -#include "scene/components/display/MeshRenderer.hpp" -#include "scene/components/display/material/SimpleTexturedMaterial.hpp" -#include "scene/components/physics/2d/CharacterController2D.hpp" -#include "scene/components/physics/2d/BoxCollider.hpp" -#include "scene/components/PlayerController.hpp" -#include "display/mesh/CubeMesh.hpp" -#include "display/mesh/CapsuleMesh.hpp" - -namespace Dawn { - class PlayerPrefab : public SceneItemPrefab, public StateOwner { - public: - static std::vector prefabAssets(AssetManager *man) { - return {}; - } - - PlayerController *player; - - PlayerPrefab(Scene *s, sceneitemid_t i) : SceneItemPrefab(s, i) {} - - void prefabInit(AssetManager *man) override { - auto characterController = this->addComponent(); - auto hitbox = this->addComponent(); - auto meshHost = this->addComponent(); - auto meshRenderer = this->addComponent(); - auto material = this->addComponent(); - - CapsuleMesh::create(&meshHost->mesh, 0.5f, 1.5f); - - auto nose = scene->createSceneItem(); - auto noseMeshHost = nose->addComponent(); - auto noseMeshRenderer = nose->addComponent(); - auto noseMaterial = nose->addComponent(); - noseMeshHost->mesh.createBuffers(CUBE_VERTICE_COUNT, CUBE_INDICE_COUNT); - glm::vec3 noseSize = glm::vec3(0.25f, 0.25f, 0.25f); - CubeMesh::buffer(&noseMeshHost->mesh, -(noseSize * 0.5f), noseSize, 0, 0); - noseMaterial->color = COLOR_RED; - nose->transform.setParent(&this->transform); - nose->transform.setLocalPosition(glm::vec3(0, 0, 0.5f)); - - - player = this->addComponent(); - } - }; -} \ No newline at end of file diff --git a/src/dawnrose/scenes/HelloWorldScene.hpp b/src/dawnrose/scenes/HelloWorldScene.hpp index 690a7665..c4a4383c 100644 --- a/src/dawnrose/scenes/HelloWorldScene.hpp +++ b/src/dawnrose/scenes/HelloWorldScene.hpp @@ -6,8 +6,11 @@ #pragma once #include "scene/Scene.hpp" #include "scene/components/GameCamera.hpp" -#include "prefabs/PlayerPrefab.hpp" +#include "prefabs/Player.hpp" +#include "prefabs/SpinningCube.hpp" #include "prefabs/ui/debug/FPSLabel.hpp" +#include "display/mesh/CapsuleMesh.hpp" +#include "display/mesh/CubeMesh.hpp" namespace Dawn { class HelloWorldScene : public Scene { @@ -16,16 +19,14 @@ namespace Dawn { UICanvas *canvas; void stage() override { - auto player = PlayerPrefab::create(this); + + auto player = Player::create(this); + CapsuleMesh::create(&player->meshHost->mesh, 0.5f, 1.5f); + player->meshHost->mesh.createBuffers(CUBE_VERTICE_COUNT, CUBE_INDICE_COUNT); + CubeMesh::buffer(&player->meshHost->mesh, glm::vec3(-0.5f, -0.5f, -0.5f), glm::vec3(1, 1, 1), 0, 0); canvas = UICanvas::create(this); - auto labelItem = FPSLabel::create(this); - labelItem->transform.setParent(canvas->transform); - labelItem->label->alignX = UI_COMPONENT_ALIGN_END; - labelItem->label->alignment = glm::vec4(0, 0, 0, 0); - labelItem->label->fontSize = 16; - auto wallBox = this->createSceneItem()->addComponent(); wallBox->min = glm::vec2(-4, -3); wallBox->max = glm::vec2(-3, 3); diff --git a/src/dawnshared/util/string.hpp b/src/dawnshared/util/string.hpp index 99f26ada..9894927b 100644 --- a/src/dawnshared/util/string.hpp +++ b/src/dawnshared/util/string.hpp @@ -32,4 +32,67 @@ static inline char * stringFindNext( } return NULL; +} + +/** + * Splits a string into a vector of strings, using a delimiter. + * + * @param s String to split. + * @param delim Delimiter to split by. + * @return Vector of strings. + */ +static inline std::vector stringSplit( + const std::string &s, + const std::string delim +) { + size_t posStart = 0, posEnd, delimLength = delim.length(); + std::string token; + std::vector res; + + while((posEnd = s.find(delim, posStart)) != std::string::npos) { + token = s.substr(posStart, posEnd - posStart); + posStart = posEnd + delimLength; + res.push_back (token); + } + + res.push_back(s.substr(posStart)); + return res; +} + +/** + * Trims the whitespace from the left side of a string. + * + * @param i Input string to trim. + * @return Trimmed string. + */ +static inline std::string stringLTrim(const std::string &i) { + std::string s = i; + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { + return !std::isspace(ch); + })); + return s; +} + +/** + * Trims the whitespace from the right side of a string. + * + * @param i Input string to trim. + * @return Trimmed string. + */ +static inline std::string stringRTrim(const std::string &i) { + std::string s = i; + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { + return !std::isspace(ch); + }).base(), s.end()); + return s; +} + +/** + * Trims the whitespace from both sides of a string. + * + * @param s Input string to trim. + * @return Trimmed string. + */ +static inline std::string stringTrim(const std::string &s) { + return stringLTrim(stringRTrim(s)); } \ No newline at end of file diff --git a/src/dawntools/prefabtool/CMakeLists.txt b/src/dawntools/prefabtool/CMakeLists.txt index ee025b7d..b51ece00 100644 --- a/src/dawntools/prefabtool/CMakeLists.txt +++ b/src/dawntools/prefabtool/CMakeLists.txt @@ -13,6 +13,9 @@ target_sources(prefabtool ${DAWN_SHARED_SOURCES} ${DAWN_TOOL_SOURCES} PrefabTool.cpp + PrefabParser.cpp + PrefabRegistry.cpp + PrefabComponentParser.cpp ) # Includes diff --git a/src/dawntools/prefabtool/PrefabChildParser.hpp b/src/dawntools/prefabtool/PrefabChildParser.hpp new file mode 100644 index 00000000..c346c8ba --- /dev/null +++ b/src/dawntools/prefabtool/PrefabChildParser.hpp @@ -0,0 +1,10 @@ +// 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 { +} \ No newline at end of file diff --git a/src/dawntools/prefabtool/PrefabComponentParser.cpp b/src/dawntools/prefabtool/PrefabComponentParser.cpp new file mode 100644 index 00000000..657b5108 --- /dev/null +++ b/src/dawntools/prefabtool/PrefabComponentParser.cpp @@ -0,0 +1,132 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "PrefabComponentParser.hpp" + +using namespace Dawn; + +std::vector PrefabComponentParser::getRequiredAttributes() { + return { }; +} + +std::map PrefabComponentParser::getOptionalAttributes() { + return { { "ref", "" } }; +} + +int32_t PrefabComponentParser::onParse( + Xml *node, + std::map values, + struct PrefabComponent *out, + std::string *error +) { + // Check if values contains key "ref" and has a string of size more than 0 + if(values.find("ref") != values.end() && values["ref"].size() > 0) { + out->ref = values["ref"]; + } + + // Get the ruleset. + auto ruleset = out->registry->getRuleset(node->node); + if(ruleset.name.size() == 0) { + *error = "Unknown prefab node type: " + node->node; + return 1; + } + + out->include = ruleset.include; + 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(); + while(itOptional != ruleset.optional.end()) { + // Determine the parser to use + auto name = itOptional->first; + auto type = itOptional->second; + + std::function parser = rawParser; + if(type.find("string") != std::string::npos) { + parser = stringParser; + } else if(type.find("float") != std::string::npos) { + parser = floatParser; + } else if(type.find("Color") != std::string::npos) { + parser = colorParser; + } else if(type.find("vec2") != std::string::npos) { + parser = vec2Parser; + } else if(type.find("vec3") != std::string::npos) { + parser = vec3Parser; + } else if(type.find("*") == (type.size() - 1)) { + type = type.substr(0, type.size() - 1); + parser = rawParser; + } else if(name[0] == '*') { + name = name.substr(1, name.size()); + parser = rawParser; + } else { + *error = "Unkown parser for type: " + type + "::" + name; + return 1; + } + + if(node->attributes.find(name) != node->attributes.end()) { + auto raw = node->attributes[name]; + out->values[name] = parser(raw); + if(error->size() != 0) return 1; + } + ++itOptional; + } + + return 0; +} \ No newline at end of file diff --git a/src/dawntools/prefabtool/PrefabComponentParser.hpp b/src/dawntools/prefabtool/PrefabComponentParser.hpp new file mode 100644 index 00000000..e4f06020 --- /dev/null +++ b/src/dawntools/prefabtool/PrefabComponentParser.hpp @@ -0,0 +1,30 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "PrefabRegistry.hpp" + +namespace Dawn { + struct PrefabComponent { + struct PrefabRegistry *registry; + + std::string include; + std::string type; + std::map values; + std::string ref; + }; + + class PrefabComponentParser : public XmlParser { + protected: + std::vector getRequiredAttributes() override; + std::map getOptionalAttributes() override; + int32_t onParse( + Xml *node, + std::map values, + struct PrefabComponent *out, + std::string *error + ) override; + }; +} \ No newline at end of file diff --git a/src/dawntools/prefabtool/PrefabParser.cpp b/src/dawntools/prefabtool/PrefabParser.cpp new file mode 100644 index 00000000..c659edb1 --- /dev/null +++ b/src/dawntools/prefabtool/PrefabParser.cpp @@ -0,0 +1,44 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "PrefabParser.hpp" + +using namespace Dawn; + +std::vector PrefabParser::getRequiredAttributes() { + return { "name", "type" }; +} + +std::map PrefabParser::getOptionalAttributes() { + return { }; +} + +int32_t PrefabParser::onParse( + Xml *node, + std::map values, + struct Prefab *out, + std::string *error +) { + 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; +} \ No newline at end of file diff --git a/src/dawntools/prefabtool/PrefabParser.hpp b/src/dawntools/prefabtool/PrefabParser.hpp new file mode 100644 index 00000000..e39cecc5 --- /dev/null +++ b/src/dawntools/prefabtool/PrefabParser.hpp @@ -0,0 +1,28 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "PrefabComponentParser.hpp" + +namespace Dawn { + struct Prefab { + struct PrefabRegistry *registry; + std::string name; + std::string type; + std::vector components; + }; + + class PrefabParser : public XmlParser { + protected: + std::vector getRequiredAttributes() override; + std::map getOptionalAttributes() override; + int32_t onParse( + Xml *node, + std::map values, + struct Prefab *out, + std::string *error + ) override; + }; +} \ No newline at end of file diff --git a/src/dawntools/prefabtool/PrefabRegistry.cpp b/src/dawntools/prefabtool/PrefabRegistry.cpp new file mode 100644 index 00000000..950410f1 --- /dev/null +++ b/src/dawntools/prefabtool/PrefabRegistry.cpp @@ -0,0 +1,115 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "PrefabRegistry.hpp" + +using namespace Dawn; + +struct PrefabComponentParserRuleset PrefabRegistry::getRuleset(std::string type) { + std::vector pathsToScan; + pathsToScan.push_back(this->sources); + + auto it = pathsToScan.begin(); + while(it != pathsToScan.end()) { + auto str = *it; + pathsToScan.erase(it); + + Directory dir = Directory(str); + auto children = dir.readDirectory(); + + auto itChildren = children.begin(); + while(itChildren != children.end()) { + if(itChildren->second == DIRECTORY_CHILD_TYPE_DIRECTORY) { + pathsToScan.push_back(str + "/" + itChildren->first); + ++itChildren; + continue; + } + + if(itChildren->first != type+".hpp") { + ++itChildren; + continue; + } + + // Load ruleset + std::string data; + File file(str + "/" + itChildren->first); + if(!file.readString(&data)) { + std::cout << "Failed to read ruleset file!" << std::endl; + return { .name = "" }; + } + + // Begin scanning contentsr + // std::string include = this->sources; + auto toRemove = File::normalizeSlashes(this->sources + FILE_PATH_SEP); + auto includePath = file.filename.substr(toRemove.size(), file.filename.size() - toRemove.size()); + + // Now locate the first subdir since we don't want to include the root path (e.g. dawn, dawnrose, etc) + auto firstSlash = includePath.find(FILE_PATH_SEP); + if(firstSlash != std::string::npos) { + includePath = includePath.substr(firstSlash + 1, includePath.size() - firstSlash - 1); + } + + struct PrefabComponentParserRuleset ruleset; + // Replace all file seps with slashes + size_t pos = 0; + while ((pos = includePath.find(FILE_PATH_SEP, pos)) != std::string::npos) { + includePath.replace(pos, 1, "/"); + pos += 1; + } + ruleset.include = includePath; + ruleset.name = type; + + // Find each instance of "@optional" when it's used within a comment + // e.g. // @optional or /* @optional */ in the string data. + std::regex regex("^\\s*(?:\\/\\/|\\/\\*){1}\\s*\\@optional\\s*(?:\\*\\/)?\\s*$", std::regex_constants::ECMAScript); + std::sregex_iterator it(data.begin(), data.end(), regex); + std::sregex_iterator end; + while(it != end) { + // Find the next ";" + auto endPos = data.find(";", it->position() + it->length()); + if(endPos == std::string::npos) { + std::cout << "Failed to find end of line for optional attribute!" << std::endl; + return { .name = "" }; + } + + // Go backwards see if there's an equals sign after the match but before endPos + auto equalsPos = data.rfind("=", endPos); + + // If there's an equals sign, we search backwards from there, + // otherwise we search backwards from the ; + auto varStart = it->position() + it->length() + 1; + size_t lastSearchPos = ( + (equalsPos == std::string::npos || equalsPos <= varStart) ? + endPos : + equalsPos + ); + + // Now we have our string + auto varLength = lastSearchPos - varStart; + auto variableString = data.substr(varStart, varLength); + + // Now (should) be able to extract the type; + std::regex regex2("^\\s*(?:[\\S]+<)?([\\w*:_\\s]+)(?:[\\S]+)? (\\**[\\w]+)\\s*$", std::regex_constants::ECMAScript); + std::smatch match; + if(!std::regex_search(variableString, match, regex2)) { + std::cout << "Failed to extract type and name from variable string! " << variableString << std::endl; + return { .name = "" }; + } + + // Now we have our type and name + auto type = match[1].str(); + auto name = match[2].str(); + ruleset.optional[name] = type; + ++it; + } + return ruleset; + ++itChildren; + } + + it = pathsToScan.begin(); + }; + + return { .name = "" }; +} diff --git a/src/dawntools/prefabtool/PrefabRegistry.hpp b/src/dawntools/prefabtool/PrefabRegistry.hpp new file mode 100644 index 00000000..1e606a18 --- /dev/null +++ b/src/dawntools/prefabtool/PrefabRegistry.hpp @@ -0,0 +1,32 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "util/DawnTool.hpp" +#include "util/Directory.hpp" +#include "util/XmlParser.hpp" +#include "util/CodeGen.hpp" +#include "util/string.hpp" +#include + +namespace Dawn { + struct PrefabComponentParserRuleset { + std::string name; + std::string include; + std::map optional; + }; + + struct PrefabRegistry { + std::string sources; + + /** + * Gets a prefab component ruleset for a specific scene item component type. + * + * @param type Scene Item Component Type to get ruleset for. + * @return The found ruleset, or an empty ruleset if not found. + */ + struct PrefabComponentParserRuleset getRuleset(std::string type); + }; +} \ No newline at end of file diff --git a/src/dawntools/prefabtool/PrefabTool.cpp b/src/dawntools/prefabtool/PrefabTool.cpp index 769f90af..c6ad8e8a 100644 --- a/src/dawntools/prefabtool/PrefabTool.cpp +++ b/src/dawntools/prefabtool/PrefabTool.cpp @@ -7,109 +7,6 @@ using namespace Dawn; - -struct PrefabComponentParserRuleset PrefabRegistry::getRuleset(std::string type) { - std::vector pathsToScan; - pathsToScan.push_back(this->sources); - - auto it = pathsToScan.begin(); - while(it != pathsToScan.end()) { - auto str = *it; - pathsToScan.erase(it); - - Directory dir = Directory(str); - auto children = dir.readDirectory(); - - auto itChildren = children.begin(); - while(itChildren != children.end()) { - if(itChildren->second == DIRECTORY_CHILD_TYPE_DIRECTORY) { - pathsToScan.push_back(str + "/" + itChildren->first); - } else { - if(itChildren->first == type+".hpp") { - // Load ruleset - std::string data; - File file(str + "/" + itChildren->first); - if(!file.readString(&data)) { - std::cout << "Failed to read ruleset file!" << file.filename << std::endl; - } else { - // Begin scanning contentsr - // std::string include = this->sources; - auto toRemove = File::normalizeSlashes(this->sources + FILE_PATH_SEP); - auto includePath = file.filename.substr(toRemove.size(), file.filename.size() - toRemove.size()); - - // Now locate the first subdir since we don't want to include the root path (e.g. dawn, dawnrose, etc) - auto firstSlash = includePath.find(FILE_PATH_SEP); - if(firstSlash != std::string::npos) { - includePath = includePath.substr(firstSlash + 1, includePath.size() - firstSlash - 1); - } - - struct PrefabComponentParserRuleset ruleset; - // Replace all file seps with slashes - size_t pos = 0; - while ((pos = includePath.find(FILE_PATH_SEP, pos)) != std::string::npos) { - includePath.replace(pos, 1, "/"); - pos += 1; - } - ruleset.include = includePath; - ruleset.name = type; - - // Find each instance of "@optional" when it's used within a comment - // e.g. // @optional or /* @optional */ in the string data. - std::regex regex("^(\\s)*(\\/\\/|\\/\\*\\s*)(\\@optional)(\\s*\\*\\/)?(\\s)$", std::regex_constants::ECMAScript); - std::sregex_iterator it(data.begin(), data.end(), regex); - std::sregex_iterator end; - while(it != end) { - // Find the next ";" - auto endPos = data.find(";", it->position() + it->length()); - if(endPos == std::string::npos) { - std::cout << "Failed to find end of line for optional attribute!" << std::endl; - return { .name = "" }; - } - - // Go backwards see if there's an equals sign after the match but before endPos - auto equalsPos = data.rfind("=", endPos); - - // If there's an equals sign, we search backwards from there, - // otherwise we search backwards from the ; - auto varStart = it->position() + it->length() + 1; - size_t lastSearchPos = ( - (equalsPos == std::string::npos || equalsPos <= varStart) ? - endPos : - equalsPos - ); - - // Now we have our string - auto varLength = lastSearchPos - varStart; - auto variableString = data.substr(varStart, varLength); - - // Now (should) be able to extract the type; - std::regex regex2("^\\s*(?:[\\S]+<)?([\\w*:_\\s]+)(?:[\\S]+)? (\\**[\\w]+)\\s*$", std::regex_constants::ECMAScript); - std::smatch match; - if(!std::regex_search(variableString, match, regex2)) { - std::cout << "Failed to extract type and name from variable string! " << variableString << std::endl; - return { .name = "" }; - } - - // Now we have our type and name - auto type = match[1].str(); - auto name = match[2].str(); - ruleset.optional[name] = type; - ++it; - } - return ruleset; - } - } - } - ++itChildren; - } - it = pathsToScan.begin(); - }; - - return { .name = "" }; -} - -// - std::vector PrefabTool::getRequiredFlags() { return { "input", "output", "sources" }; } @@ -173,133 +70,6 @@ int32_t PrefabTool::start() { // -std::vector PrefabParser::getRequiredAttributes() { - return { "name", "type" }; -} - -std::map PrefabParser::getOptionalAttributes() { - return { }; -} - -int32_t PrefabParser::onParse( - Xml *node, - std::map values, - struct Prefab *out, - std::string *error -) { - out->name = values["name"]; - out->type = values["type"]; - - auto itChildren = node->children.begin(); - while(itChildren != node->children.end()) { - // Parse children as components - 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; -} - -// - -std::vector PrefabComponentParser::getRequiredAttributes() { - return { }; -} - -std::map PrefabComponentParser::getOptionalAttributes() { - return { { "ref", "" } }; -} - -int32_t PrefabComponentParser::onParse( - Xml *node, - std::map values, - struct PrefabComponent *out, - std::string *error -) { - // Check if values contains key "ref" and has a string of size more than 0 - if(values.find("ref") != values.end() && values["ref"].size() > 0) { - out->ref = values["ref"]; - } - - // Get the ruleset. - auto ruleset = out->registry->getRuleset(node->node); - if(ruleset.name.size() == 0) { - *error = "Unknown prefab node type: " + node->node; - return 1; - } - - out->include = ruleset.include; - 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){ - // 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 colorParser = rawParser; - - // Iterate all the optional attributes and store within the out if present - auto itOptional = ruleset.optional.begin(); - while(itOptional != ruleset.optional.end()) { - // Determine the parser to use - auto name = itOptional->first; - auto type = itOptional->second; - - std::function parser = rawParser; - if(type.find("string") != std::string::npos) { - parser = stringParser; - } else if(type.find("float") != std::string::npos) { - parser = floatParser; - } else if(type.find("Color") != std::string::npos) { - parser = colorParser; - } else if(type.find("*") == (type.size() - 1)) { - type = type.substr(0, type.size() - 1); - parser = rawParser; - } else if(name[0] == '*') { - name = name.substr(1, name.size()); - parser = rawParser; - } else { - *error = "Unkown parser for type: " + type + "::" + name; - return 1; - } - - if(node->attributes.find(name) != node->attributes.end()) { - auto raw = node->attributes[name]; - out->values[name] = parser(raw); - } - ++itOptional; - } - - return 0; -} - -// - void PrefabGen::generate( std::vector *out, struct Prefab *info, @@ -335,7 +105,7 @@ void PrefabGen::generate( if(c.ref.size() > 0) { init = false; name = c.ref; - line(&classInfo.publicProperties, c.type + " *" + c.ref + ";", ""); + line(&classInfo.publicProperties, c.type + " *" + c.ref + " = nullptr;", ""); } // Initialize diff --git a/src/dawntools/prefabtool/PrefabTool.hpp b/src/dawntools/prefabtool/PrefabTool.hpp index 7b44b1e2..66975056 100644 --- a/src/dawntools/prefabtool/PrefabTool.hpp +++ b/src/dawntools/prefabtool/PrefabTool.hpp @@ -4,46 +4,9 @@ // https://opensource.org/licenses/MIT #pragma once -#include "util/DawnTool.hpp" -#include "util/Directory.hpp" -#include "util/XmlParser.hpp" -#include "util/CodeGen.hpp" -#include +#include "PrefabParser.hpp" namespace Dawn { - enum PrefabcComponentParserRulesetType { - STRIN - }; - - struct PrefabComponentParserRuleset { - std::string name; - std::string include; - std::map optional; - }; - - struct PrefabRegistry { - std::string sources; - - struct PrefabComponentParserRuleset getRuleset(std::string type); - }; - - struct PrefabComponent { - struct PrefabRegistry *registry; - - std::string include; - std::string type; - std::map values; - std::string ref; - }; - - struct Prefab { - struct PrefabRegistry *registry; - - std::string name; - std::string type; - std::vector components; - }; - class PrefabTool : public DawnTool { protected: std::vector getRequiredFlags() override; @@ -53,30 +16,6 @@ namespace Dawn { int32_t start(); }; - class PrefabParser : public XmlParser { - protected: - std::vector getRequiredAttributes() override; - std::map getOptionalAttributes() override; - int32_t onParse( - Xml *node, - std::map values, - struct Prefab *out, - std::string *error - ) override; - }; - - class PrefabComponentParser : public XmlParser { - protected: - std::vector getRequiredAttributes() override; - std::map getOptionalAttributes() override; - int32_t onParse( - Xml *node, - std::map values, - struct PrefabComponent *out, - std::string *error - ) override; - }; - class PrefabGen : public CodeGen { public: static void generate(