diff --git a/assets/games/rose/prefabs/Player.xml b/assets/games/rose/prefabs/Player.xml
index c37a6d63..40218b32 100644
--- a/assets/games/rose/prefabs/Player.xml
+++ b/assets/games/rose/prefabs/Player.xml
@@ -6,7 +6,7 @@
<BoxCollider min="-1, -1" max="1, 1" />
<PlayerController ref="player" />
- <child ref="nose">
+ <child position="0, 0, 2" scale="0.1, 0.1, 0.1">
<MeshRenderer />
<MeshHost ref="noseMeshHost" />
<SimpleTexturedMaterial color="COLOR_RED" />
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<std::string> PrefabChildParser::getRequiredAttributes() {
+ return std::vector<std::string>();
+}
+
+std::map<std::string, std::string> PrefabChildParser::getOptionalAttributes() {
+ return {
+ { "ref", "" },
+ { "position", "" },
+ { "scale", "" }
+ };
+}
+
+int32_t PrefabChildParser::onParse(
+ Xml *node,
+ std::map<std::string, std::string> 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<struct PrefabComponent> components;
+ std::vector<struct PrefabChild> children;
+ };
+
+ class PrefabChildParser : public XmlParser<struct PrefabChild> {
+ protected:
+ std::vector<std::string> getRequiredAttributes() override;
+ std::map<std::string, std::string> getOptionalAttributes() override;
+ int32_t onParse(
+ Xml *node,
+ std::map<std::string, std::string> 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<std::string(std::string)> parser = rawParser;
+ std::function<std::string(std::string, std::string*)> 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<std::string, std::string> 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<std::string> *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<Asset*>";
+ methodAssets.args = "AssetManager *man";
+ line(&methodAssets.body, "std::vector<Asset*> 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<void(struct PrefabChild &, std::string)> 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<std::string> *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<struct PrefabComponent> components;
};
class PrefabParser : public XmlParser<struct Prefab> {
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<std::string> outputData;
PrefabGen::generate(&outputData, &prefab, "");
@@ -66,70 +67,4 @@ int32_t PrefabTool::start() {
}
return 0;
-}
-
-//
-
-void PrefabGen::generate(
- std::vector<std::string> *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<Asset*>";
- methodAssets.args = "AssetManager *man";
- line(&methodAssets.body, "std::vector<Asset*> 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<std::string> *out,
- struct Prefab *prefab,
- std::string tabs
- );
- };
}
\ No newline at end of file