diff --git a/assets/games/rose/prefabs/Player.xml b/assets/games/rose/prefabs/Player.xml
new file mode 100644
index 00000000..c37a6d63
--- /dev/null
+++ b/assets/games/rose/prefabs/Player.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/games/rose/prefabs/PlayerPrefab.xml b/assets/games/rose/prefabs/PlayerPrefab.xml
deleted file mode 100644
index df48b4a0..00000000
--- a/assets/games/rose/prefabs/PlayerPrefab.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
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(