diff --git a/assets/games/pokergame/ui/uitest.xml b/assets/games/pokergame/ui/uitest.xml
new file mode 100644
index 00000000..76b8451d
--- /dev/null
+++ b/assets/games/pokergame/ui/uitest.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ >
+
\ No newline at end of file
diff --git a/src/dawn/visualnovel/scene/SimpleVNScene.cpp b/src/dawn/visualnovel/scene/SimpleVNScene.cpp
index f89c3c97..5e3c71e6 100644
--- a/src/dawn/visualnovel/scene/SimpleVNScene.cpp
+++ b/src/dawn/visualnovel/scene/SimpleVNScene.cpp
@@ -1,58 +1,58 @@
-// Copyright (c) 2022 Dominic Masters
-//
-// This software is released under the MIT License.
-// https://opensource.org/licenses/MIT
-
-#include "SimpleVNScene.hpp"
-#include "prefabs/ui/VisualNovelTextboxPrefab.hpp"
-
-using namespace Dawn;
-
-SimpleVNScene::SimpleVNScene(DawnGame *game) : Scene(game) {
-
-}
-
-
-std::vector SimpleVNScene::getRequiredAssets() {
- auto assMan = &this->game->assetManager;
- std::vector assets;
- vectorAppend(&assets, VisualNovelTextboxPrefab::getRequiredAssets(assMan));
- return assets;
-}
-
-void SimpleVNScene::stage() {
- auto assMan = &this->game->assetManager;
-
- // Camera
- this->camera = Camera::create(this);
- this->camera->transform->lookAt(
- glm::vec3(0, 0, 2),
- glm::vec3(0, 0, 0)
- );
-
- this->background = SimpleVisualNovelBackground::create(this);
-
- // Stage VN Items
- this->vnStage();
-
- // UI
- this->canvas = UICanvas::create(this);
- this->textbox = VisualNovelTextboxPrefab::create(this->canvas);
-
- // VN Manager
- auto vnManagerItem = this->createSceneItem();
- this->vnManager = vnManagerItem->addComponent();
-
- // Audio
- auto listenerItem = this->createSceneItem();
- this->audioListener = listenerItem->addComponent();
-
- auto audioBackgroundItem = this->createSceneItem();
- vnManager->audioBackground = audioBackgroundItem->addComponent();
-
- auto audioCharacterItem = this->createSceneItem();
- vnManager->audioCharacter = audioCharacterItem->addComponent();
-
- // Fader (Drawn over the top of everything else)
- this->vnFader = VisualNovelFader::create(canvas);
+// Copyright (c) 2022 Dominic Masters
+//
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#include "SimpleVNScene.hpp"
+#include "prefabs/ui/VisualNovelTextboxPrefab.hpp"
+
+using namespace Dawn;
+
+SimpleVNScene::SimpleVNScene(DawnGame *game) : Scene(game) {
+
+}
+
+
+std::vector SimpleVNScene::getRequiredAssets() {
+ auto assMan = &this->game->assetManager;
+ std::vector assets;
+ vectorAppend(&assets, VisualNovelTextboxPrefab::getRequiredAssets(assMan));
+ return assets;
+}
+
+void SimpleVNScene::stage() {
+ auto assMan = &this->game->assetManager;
+
+ // Camera
+ this->camera = Camera::create(this);
+ this->camera->transform->lookAt(
+ glm::vec3(0, 0, 2),
+ glm::vec3(0, 0, 0)
+ );
+
+ this->background = SimpleVisualNovelBackground::create(this);
+ this->canvas = UICanvas::create(this);
+
+ // Stage VN Items
+ this->vnStage();
+
+ // UI
+ this->textbox = VisualNovelTextboxPrefab::create(this->canvas);
+
+ // VN Manager
+ auto vnManagerItem = this->createSceneItem();
+ this->vnManager = vnManagerItem->addComponent();
+
+ // Audio
+ auto listenerItem = this->createSceneItem();
+ this->audioListener = listenerItem->addComponent();
+
+ auto audioBackgroundItem = this->createSceneItem();
+ vnManager->audioBackground = audioBackgroundItem->addComponent();
+
+ auto audioCharacterItem = this->createSceneItem();
+ vnManager->audioCharacter = audioCharacterItem->addComponent();
+
+ // Fader (Drawn over the top of everything else)
+ this->vnFader = VisualNovelFader::create(canvas);
}
\ No newline at end of file
diff --git a/src/dawnpokergame/CMakeLists.txt b/src/dawnpokergame/CMakeLists.txt
index d09a4a87..dedd4ee0 100644
--- a/src/dawnpokergame/CMakeLists.txt
+++ b/src/dawnpokergame/CMakeLists.txt
@@ -39,6 +39,8 @@ tool_truetype(truetype_alice ${DIR_GAME_ASSETS}/font/Alice-Regular.ttf truetype_
tool_audio(audio_test borrowed/sample_short.wav)
+tool_ui(ui_test ${DIR_GAME_ASSETS}/ui/uitest.xml)
+
add_dependencies(${DAWN_TARGET_NAME}
language_en
@@ -50,4 +52,6 @@ add_dependencies(${DAWN_TARGET_NAME}
texture_test
audio_test
+
+ ui_test
)
\ No newline at end of file
diff --git a/src/dawnpokergame/scenes/Scene_1.hpp b/src/dawnpokergame/scenes/Scene_1.hpp
index 85ddfeb0..c067088e 100644
--- a/src/dawnpokergame/scenes/Scene_1.hpp
+++ b/src/dawnpokergame/scenes/Scene_1.hpp
@@ -1,59 +1,64 @@
-// Copyright (c) 2022 Dominic Masters
-//
-// This software is released under the MIT License.
-// https://opensource.org/licenses/MIT
-
-#pragma once
-#include "visualnovel/scene/SimpleVNScene.hpp"
-#include "scenes/Scene_2.hpp"
-#include "prefabs/characters/DeathPrefab.hpp"
-#include "visualnovel/events/characters/VisualNovelFadeCharacterEvent.hpp"
-#include "visualnovel/events/characters/VisualNovelTransformItemEvent.hpp"
-#include "visualnovel/events/timing/VisualNovelBatchEvent.hpp"
-
-namespace Dawn {
- class Scene_1 : public SimpleVNScene {
- protected:
- DeathPrefab *death;
-
- void vnStage() override {
-
- this->death = DeathPrefab::create(this);
- this->death->material->color.a = 0;
- // this->death->transform.setLocalPosition(glm::vec3(-100, 0, 0));
- }
-
- void onSceneEnded() {
- auto scene = new Scene_2(this->game);
- game->assetManager.queueSwap(
- scene->getRequiredAssets(), this->getRequiredAssets()
- );
- game->assetManager.syncLoad();
- scene->stage();
- this->game->sceneCutover(scene);
- }
-
- public:
- Scene_1(DawnGame *game) : SimpleVNScene(game) {
-
- }
-
- std::vector getRequiredAssets() override {
- auto man = &this->game->assetManager;
- std::vector assets = SimpleVNScene::getRequiredAssets();
- vectorAppend(&assets, DeathPrefab::getRequiredAssets(man));
- assets.push_back(man->get("audio_test"));
- return assets;
- }
-
- IVisualNovelEvent * getVNEvent() override {
- auto start = new VisualNovelPauseEvent(vnManager, 0.1f);
- start
- ->then(new VisualNovelTextboxEvent(vnManager, this->death->vnCharacter, this->death->emotionHappy, "scene.1.1"))
- ->then(new VisualNovelFadeCharacterEvent(vnManager, this->death->vnCharacter, true, &easeOutQuad, 1.0f))
- // ->then(new VisualNovelCallbackEvent(vnManager, this, &Scene_1::onSceneEnded))
- ;
- return start;
- }
- };
+// Copyright (c) 2022 Dominic Masters
+//
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#pragma once
+#include "visualnovel/scene/SimpleVNScene.hpp"
+#include "scenes/Scene_2.hpp"
+#include "prefabs/characters/DeathPrefab.hpp"
+#include "visualnovel/events/characters/VisualNovelFadeCharacterEvent.hpp"
+#include "visualnovel/events/characters/VisualNovelTransformItemEvent.hpp"
+#include "visualnovel/events/timing/VisualNovelBatchEvent.hpp"
+
+#include "ui_test.hpp"
+
+namespace Dawn {
+ class Scene_1 : public SimpleVNScene {
+ protected:
+ DeathPrefab *death;
+
+ void vnStage() override {
+
+ this->death = DeathPrefab::create(this);
+ this->death->material->color.a = 0;
+ // this->death->transform.setLocalPosition(glm::vec3(-100, 0, 0));
+
+ auto item = this->canvas->addElement();
+ item->setTransform(UI_COMPONENT_ALIGN_STRETCH, UI_COMPONENT_ALIGN_STRETCH, glm::vec4(0, 0, 0, 0), 0.0f);
+ }
+
+ void onSceneEnded() {
+ auto scene = new Scene_2(this->game);
+ game->assetManager.queueSwap(
+ scene->getRequiredAssets(), this->getRequiredAssets()
+ );
+ game->assetManager.syncLoad();
+ scene->stage();
+ this->game->sceneCutover(scene);
+ }
+
+ public:
+ Scene_1(DawnGame *game) : SimpleVNScene(game) {
+
+ }
+
+ std::vector getRequiredAssets() override {
+ auto man = &this->game->assetManager;
+ std::vector assets = SimpleVNScene::getRequiredAssets();
+ vectorAppend(&assets, DeathPrefab::getRequiredAssets(man));
+ assets.push_back(man->get("audio_test"));
+ return assets;
+ }
+
+ IVisualNovelEvent * getVNEvent() override {
+ auto start = new VisualNovelPauseEvent(vnManager, 0.1f);
+ start
+ ->then(new VisualNovelTextboxEvent(vnManager, this->death->vnCharacter, this->death->emotionHappy, "scene.1.1"))
+ ->then(new VisualNovelFadeCharacterEvent(vnManager, this->death->vnCharacter, true, &easeOutQuad, 1.0f))
+ // ->then(new VisualNovelCallbackEvent(vnManager, this, &Scene_1::onSceneEnded))
+ ;
+ return start;
+ }
+ };
}
\ No newline at end of file
diff --git a/src/dawntools/display/CMakeLists.txt b/src/dawntools/display/CMakeLists.txt
index ff695679..a9ff41d7 100644
--- a/src/dawntools/display/CMakeLists.txt
+++ b/src/dawntools/display/CMakeLists.txt
@@ -1,36 +1,50 @@
-# Copyright (c) 2021 Dominic Msters
-#
-# This software is released under the MIT License.
-# https://opensource.org/licenses/MIT
-
-add_subdirectory(texturegen)
-add_subdirectory(tilesetgen)
-add_subdirectory(truetypegen)
-
-# Texture Tool
-function(tool_texture target in)
- add_custom_target(${target}
- COMMAND texturegen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_ASSETS_BUILD_DIR}/${target}"
- COMMENT "Generating texture ${target} from ${in}"
- DEPENDS texturegen
- )
-endfunction()
-
-# Tileset Tool
-function(tool_tileset targetTileset targetTexture in cols rows)
- tool_texture(${targetTexture} ${in})
- add_custom_target(${targetTileset}
- COMMAND tilesetgen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_ASSETS_BUILD_DIR}/${targetTileset}" "${cols}" "${rows}"
- COMMENT "Generating tileset ${target} from ${in}"
- DEPENDS tilesetgen ${targetTexture}
- )
-endfunction()
-
-# TrueType Tool
-function(tool_truetype target in out width height fontSize)
- add_custom_target(${target}
- COMMAND truetypegen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_ASSETS_BUILD_DIR}/${out}" "${width}" "${height}" "${fontSize}"
- COMMENT "Generating truetype ${target} from ${in}"
- DEPENDS truetypegen
- )
+# Copyright (c) 2021 Dominic Msters
+#
+# This software is released under the MIT License.
+# https://opensource.org/licenses/MIT
+
+add_subdirectory(texturegen)
+add_subdirectory(tilesetgen)
+add_subdirectory(truetypegen)
+add_subdirectory(uigen)
+
+# Texture Tool
+function(tool_texture target in)
+ add_custom_target(${target}
+ COMMAND texturegen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_ASSETS_BUILD_DIR}/${target}"
+ COMMENT "Generating texture ${target} from ${in}"
+ DEPENDS texturegen
+ )
+endfunction()
+
+# Tileset Tool
+function(tool_tileset targetTileset targetTexture in cols rows)
+ tool_texture(${targetTexture} ${in})
+ add_custom_target(${targetTileset}
+ COMMAND tilesetgen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_ASSETS_BUILD_DIR}/${targetTileset}" "${cols}" "${rows}"
+ COMMENT "Generating tileset ${target} from ${in}"
+ DEPENDS tilesetgen ${targetTexture}
+ )
+endfunction()
+
+# TrueType Tool
+function(tool_truetype target in out width height fontSize)
+ add_custom_target(${target}
+ COMMAND truetypegen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_ASSETS_BUILD_DIR}/${out}" "${width}" "${height}" "${fontSize}"
+ COMMENT "Generating truetype ${target} from ${in}"
+ DEPENDS truetypegen
+ )
+endfunction()
+
+# UI Tool
+function(tool_ui target in)
+ add_custom_target(${target}
+ COMMAND uigen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_ASSETS_BUILD_DIR}/${target}"
+ COMMENT "Generating ui ${target} from ${in}"
+ DEPENDS uigen
+ )
+ target_include_directories(${DAWN_TARGET_NAME}
+ PUBLIC
+ ${DAWN_ASSETS_BUILD_DIR}
+ )
endfunction()
\ No newline at end of file
diff --git a/src/dawntools/display/uigen/CMakeLists.txt b/src/dawntools/display/uigen/CMakeLists.txt
new file mode 100644
index 00000000..9fb7a2c9
--- /dev/null
+++ b/src/dawntools/display/uigen/CMakeLists.txt
@@ -0,0 +1,23 @@
+# Copyright (c) 2021 Dominic Msters
+#
+# This software is released under the MIT License.
+# https://opensource.org/licenses/MIT
+
+# Texture Build Tool
+project(uigen VERSION 1.0)
+add_executable(uigen)
+target_sources(uigen
+ PRIVATE
+ main.cpp
+ ../../utils/file.c
+ ../../utils/xml.c
+)
+target_include_directories(uigen
+ PUBLIC
+ ${CMAKE_CURRENT_LIST_DIR}/../../
+ ${CMAKE_CURRENT_LIST_DIR}
+)
+target_link_libraries(uigen
+ PUBLIC
+ ${DAWN_BUILD_HOST_LIBS}
+)
\ No newline at end of file
diff --git a/src/dawntools/display/uigen/main.cpp b/src/dawntools/display/uigen/main.cpp
new file mode 100644
index 00000000..fd980dcb
--- /dev/null
+++ b/src/dawntools/display/uigen/main.cpp
@@ -0,0 +1,347 @@
+/**
+ * Copyright (c) 2023 Dominic Masters
+ *
+ * This software is released under the MIT License.
+ * https://opensource.org/licenses/MIT
+ */
+
+extern "C" {
+ #include "../../utils/xml.h"
+ #include "../../utils/file.h"
+ #include
+}
+#include
+#include
+
+struct UIGenerated {
+ bool align = false;
+ bool alignGrid = false;
+ std::string alignX;
+ std::string alignY;
+ std::string align0;
+ std::string align1;
+ std::string align2;
+ std::string align3;
+
+ bool isGrid = false;
+ std::string rows;
+ std::string columns;
+ std::string gutterX;
+ std::string gutterY;
+
+
+ std::string type;
+ std::string name;
+
+ std::string parent;
+
+ // Optionals
+ bool hasColor = false;
+ std::string color;
+};
+
+std::vector split(std::string s, std::string delimiter) {
+ size_t pos_start = 0, pos_end, delim_len = delimiter.length();
+ std::string token;
+ std::vector res;
+
+ while ((pos_end = s.find (delimiter, pos_start)) != std::string::npos) {
+ token = s.substr (pos_start, pos_end - pos_start);
+ pos_start = pos_end + delim_len;
+ res.push_back(token);
+ }
+
+ res.push_back (s.substr (pos_start));
+ return res;
+}
+
+std::string alignmentFromRaw(std::string strRaw) {
+ if(strRaw == "start") return "UI_COMPONENT_ALIGN_START";
+ if(strRaw == "middle") return "UI_COMPONENT_ALIGN_MIDDLE";
+ if(strRaw == "end") return "UI_COMPONENT_ALIGN_END";
+ if(strRaw == "stretch") return "UI_COMPONENT_ALIGN_STRETCH";
+ return "";
+}
+
+static bool parseChildren(
+ xml_t *currentNode,
+ std::string parent,
+ std::vector *items
+) {
+ // Confirm attributes
+ auto attrName = xmlGetAttributeByName(currentNode, "name");
+ if(attrName == -1) {
+ std::cout << "Missing name attribute." << std::endl;
+ return false;
+ }
+
+ struct UIGenerated item;
+ item.name = std::string(currentNode->attributeDatas[attrName] );
+ item.type = std::string(currentNode->node);
+ item.parent = parent;
+
+ // Standard Align
+ auto attrAlign = xmlGetAttributeByName(currentNode, "align");
+ if(attrAlign != -1) {
+ // Parse alignment
+ std::string alignRaw(currentNode->attributeDatas[attrAlign]);
+ std::vector alignmentParts = split(alignRaw, " ");
+ if(alignmentParts.size() != 6) {
+ std::cout << "Alignment is invalid" << std::endl;
+ return false;
+ }
+
+ item.align = true;
+ item.alignX = alignmentFromRaw(alignmentParts[0]);
+ item.alignY = alignmentFromRaw(alignmentParts[1]);
+ item.align0 = alignmentParts[2];
+ item.align1 = alignmentParts[3];
+ item.align2 = alignmentParts[4];
+ item.align3 = alignmentParts[5];
+
+ if(item.alignX.size() == 0) {
+ std::cout << "X Align is invalid" << std::endl;
+ return "";
+ }
+ if(item.alignY.size() == 0) {
+ std::cout << "Y Align is invalid" << std::endl;
+ return "";
+ }
+ }
+
+ // Grid Align
+ auto attrGridAlign = xmlGetAttributeByName(currentNode, "grid");
+ if(attrGridAlign != -1) {
+ // Parse alignment
+ std::string alignRaw(currentNode->attributeDatas[attrGridAlign]);
+ std::vector alignmentParts = split(alignRaw, " ");
+ if(alignmentParts.size() != 4) {
+ std::cout << "Grid alignment is invalid" << std::endl;
+ return false;
+ }
+
+ item.alignGrid = true;
+ item.alignX = alignmentFromRaw(alignmentParts[0]);
+ item.alignY = alignmentFromRaw(alignmentParts[1]);
+ item.align0 = alignmentParts[2];
+ item.align1 = alignmentParts[3];
+
+ if(item.alignX.size() == 0) {
+ std::cout << "X Align is invalid" << std::endl;
+ return "";
+ }
+ if(item.alignY.size() == 0) {
+ std::cout << "Y Align is invalid" << std::endl;
+ return "";
+ }
+ }
+
+ // Parse color
+ auto attrColor = xmlGetAttributeByName(currentNode, "color");
+ if(attrColor != -1) {
+ item.hasColor = true;
+ item.color = currentNode->attributeDatas[attrColor];
+ }
+
+
+ // Grid
+ if(item.type == "UIGrid") {
+ auto attrRows = xmlGetAttributeByName(currentNode, "rows");
+ auto attrCols = xmlGetAttributeByName(currentNode, "columns");
+ auto attrGutter = xmlGetAttributeByName(currentNode, "gutter");
+ if(attrRows == -1 || attrCols == -1) {
+ std::cout << "Grid is invalid" << std::endl;
+ return false;
+ }
+ item.isGrid = true;
+ item.rows = currentNode->attributeDatas[attrRows];
+ item.columns = currentNode->attributeDatas[attrCols];
+ if(attrGutter != -1) {
+ auto gutterParts = split(currentNode->attributeDatas[attrGutter], " ");
+ if(gutterParts.size() != 2) {
+ std::cout << "Gutter is invalid" << std::endl;
+ return false;
+ }
+ item.gutterX = gutterParts[0];
+ item.gutterY = gutterParts[1];
+ } else {
+ item.gutterX = "0";
+ item.gutterY = "0";
+ }
+ }
+
+ // Self
+ items->push_back(item);
+
+ // Children
+ for(int32_t i = 0; i < currentNode->childrenCount; i++) {
+ if(!parseChildren(currentNode->children + i, item.name, items)) return false;
+ }
+
+ return true;
+}
+
+int main(int argc, char *args[]) {
+ if(argc != 3) {
+ std::cout << "Invalid number of args for ui gen" << std::endl;
+ return 1;
+ }
+
+ char fileIn[FILENAME_MAX];
+ char fileOut[FILENAME_MAX];
+
+ sprintf(fileIn, "%s", args[1]);
+ sprintf(fileOut, "%s.hpp", args[2]);
+ fileNormalizeSlashes(args[1]);
+ fileNormalizeSlashes(args[2]);
+
+ // Open input file.
+ FILE *fin = fopen(fileIn, "rb");
+ if(fin == NULL) {
+ std::cout << "Failed to open input file " << fileIn << std::endl;
+ return 1;
+ }
+
+ // Tell file len
+ fseek(fin, 0, SEEK_END);
+ auto len = ftell(fin);
+ fseek(fin, 0, SEEK_SET);
+
+ // Read data.
+ char *buffer = (char *)malloc(sizeof(char) * (len + 1));
+ if(buffer == NULL) {
+ std::cout << "Failed to create temporary memory." << std::endl;
+ fclose(fin);
+ return 1;
+ }
+ assetReadString(fin, buffer);
+ fclose(fin);
+
+ // Parse XML
+ xml_t xml;
+ xmlLoad(&xml, buffer);
+ free(buffer);
+
+ // Begin output
+ std::string bufferOut = "";
+
+ // Imports
+ bufferOut += "#pragma once\n";
+ for(int32_t i = 0; i < xml.attributeCount; i++) {
+ std::string attrName = xml.attributeNames[i];
+
+ if(
+ attrName == "name"
+ ) continue;
+
+ bufferOut += "#include \"";
+ bufferOut += xml.attributeDatas[i];
+ bufferOut += "\"\n";
+ }
+ bufferOut += "\n";
+
+ // Now prep class itself.
+ auto attrName = xmlGetAttributeByName(&xml, "name");
+ if(attrName == -1) {
+ std::cout << "Missing " << std::endl;
+ xmlDispose(&xml);
+ return 1;
+ }
+ std::string name = xml.attributeDatas[attrName];
+
+ // Children
+ std::vector items;
+ for(int32_t j = 0; j < xml.childrenCount; j++) {
+ if(parseChildren(xml.children + j, "", &items)) continue;
+ xmlDispose(&xml);
+ return 1;
+ }
+
+ // Generate strings.
+ bufferOut += "namespace Dawn {\n";
+ bufferOut += " class " + name + " : public UIEmpty {\n";
+ bufferOut += " public:\n";
+ auto it = items.begin();
+ while(it != items.end()) {
+ auto c = *it;
+ bufferOut += " " + c.type + " " + c.name + ";\n";
+ ++it;
+ }
+ bufferOut += "\n";
+ bufferOut += " " + name + "(UICanvas *canvas) : UIEmpty(canvas),\n";
+ it = items.begin();
+ while(it != items.end()) {
+ auto c = *it;
+ bufferOut += " " + c.name + "(canvas)";
+ if(it != items.end() - 1) bufferOut += ",";
+ bufferOut += "\n";
+ ++it;
+ }
+ bufferOut += " {\n";
+
+ it = items.begin();
+ while(it != items.end()) {
+ auto c = *it;
+ bufferOut += "\n";
+
+ // Transform
+ if(c.align) {
+ bufferOut += " " + c.name + ".setTransform(\n";
+ bufferOut += " " + c.alignX + ", " + c.alignY + ",\n";
+ bufferOut += " glm::vec4(" + c.align0 + ", " + c.align1 + ", " + c.align2 + ", " + c.align3 + "),\n";
+ bufferOut += " 0.0f\n";
+ bufferOut += " );\n";
+ }
+
+ // Color
+ if(c.hasColor) {
+ bufferOut += " " + c.name + ".color = " + c.color + ";\n";
+ }
+
+ // Grid
+ if(c.isGrid) {
+ bufferOut += " " + c.name + ".setGridSize(\n";
+ bufferOut += " " + c.rows + ", " + c.columns + ",\n";
+ bufferOut += " " + c.gutterX + ", " + c.gutterY + "\n";
+ bufferOut += " );\n";
+ }
+
+ // Parent setting
+ if(c.alignGrid) {
+ bufferOut += " " + c.parent + ".addToGrid(\n";
+ bufferOut += " &" + c.name + ",\n";
+ bufferOut += " " + c.align0 + ", " + c.align1 + ",\n";
+ bufferOut += " " + c.alignX + ", " + c.alignY + "\n";
+ bufferOut += " );\n";
+ } else {
+ if(c.parent == "") {
+ bufferOut += " this->addChild(&" + c.name + ");\n";
+ } else {
+ bufferOut += " " + c.parent + ".addChild(&" + c.name + ");\n";
+ }
+ }
+ ++it;
+ }
+
+ bufferOut += " }\n";
+ bufferOut += " };\n";
+ bufferOut += "}";
+
+ // Finished with XML data, now we can write data out.
+ xmlDispose(&xml);
+
+ FILE *fout = fopen(fileOut, "wb");
+ if(fout == NULL) {
+ std::cout << "Failed to open output file." << std::endl;
+ return 1;
+ }
+
+ // Buffer out data.
+ const char *bufferOutStr = bufferOut.c_str();
+ fwrite(bufferOutStr, sizeof(char), strlen(bufferOutStr), fout);
+ fclose(fout);
+ std::cout << "Generated UI " << fileOut << std::endl;
+
+ // Cleanup
+ return 0;
+}
\ No newline at end of file
diff --git a/src/dawntools/utils/xml.h b/src/dawntools/utils/xml.h
index fab84903..1bfacd04 100644
--- a/src/dawntools/utils/xml.h
+++ b/src/dawntools/utils/xml.h
@@ -1,67 +1,67 @@
-/**
- * Copyright (c) 2021 Dominic Masters
- *
- * This software is released under the MIT License.
- * https://opensource.org/licenses/MIT
- */
-
-#pragma once
-#include "common.h"
-#include "file.h"
-
-#define XML_DOING_NOTHING 0x00
-#define XML_PARSING_TAG_NAME 0x01
-#define XML_LOOKING_FOR_ATTRIBUTE 0x02
-#define XML_PARSING_ATTRIBUTE_NAME 0x03
-#define XML_LOOKING_FOR_ATTRIBUTE_VALUE 0x04
-#define XML_PARSING_ATTRIBUTE_VALUE 0x05
-#define XML_PARSING_VALUE 0x06
-#define XML_PARSING_CHILD 0x07
-#define XML_PARSING_CLOSE 0x08
-
-#define XML_TEXT_BUFFER_MAX 256
-#define XML_CHILD_COUNT_MAX 16
-#define XML_ATTRIBUTE_MAX 16
-
-typedef struct _xml_t xml_t;
-
-typedef struct _xml_t {
- char *node;
- char *value;
-
- char *attributeNames[XML_ATTRIBUTE_MAX];
- char *attributeDatas[XML_ATTRIBUTE_MAX];
- uint8_t attributeCount;
-
- xml_t *children;
- uint8_t childrenCount;
-} xml_t;
-
-/**
- * Load an XML child from a string buffer.
- *
- * @param xml XML to load.
- * @param data Data to parse
- * @param i Character index within the data
- * @return The index in the data string this XML node ends.
- */
-int32_t xmlLoadChild(xml_t *xml, char *data, int32_t i);
-
-/**
- * Load an XML String into an XML memory.
- *
- * @param xml XML to load into.
- * @param data XML string.
- */
-void xmlLoad(xml_t *xml, char *data);
-
-/**
- * Dispose a previously loaded XML.
- *
- * @param xml XML to dispose.
- */
-void xmlDispose(xml_t *xml);
-
-int16_t xmlGetAttributeByName(xml_t *xml, char *name);
-
+/**
+ * Copyright (c) 2021 Dominic Masters
+ *
+ * This software is released under the MIT License.
+ * https://opensource.org/licenses/MIT
+ */
+
+#pragma once
+#include "common.h"
+#include "file.h"
+
+#define XML_DOING_NOTHING 0x00
+#define XML_PARSING_TAG_NAME 0x01
+#define XML_LOOKING_FOR_ATTRIBUTE 0x02
+#define XML_PARSING_ATTRIBUTE_NAME 0x03
+#define XML_LOOKING_FOR_ATTRIBUTE_VALUE 0x04
+#define XML_PARSING_ATTRIBUTE_VALUE 0x05
+#define XML_PARSING_VALUE 0x06
+#define XML_PARSING_CHILD 0x07
+#define XML_PARSING_CLOSE 0x08
+
+#define XML_TEXT_BUFFER_MAX 256
+#define XML_CHILD_COUNT_MAX 128
+#define XML_ATTRIBUTE_MAX 128
+
+typedef struct _xml_t xml_t;
+
+typedef struct _xml_t {
+ char *node;
+ char *value;
+
+ char *attributeNames[XML_ATTRIBUTE_MAX];
+ char *attributeDatas[XML_ATTRIBUTE_MAX];
+ uint8_t attributeCount;
+
+ xml_t *children;
+ uint8_t childrenCount;
+} xml_t;
+
+/**
+ * Load an XML child from a string buffer.
+ *
+ * @param xml XML to load.
+ * @param data Data to parse
+ * @param i Character index within the data
+ * @return The index in the data string this XML node ends.
+ */
+int32_t xmlLoadChild(xml_t *xml, char *data, int32_t i);
+
+/**
+ * Load an XML String into an XML memory.
+ *
+ * @param xml XML to load into.
+ * @param data XML string.
+ */
+void xmlLoad(xml_t *xml, char *data);
+
+/**
+ * Dispose a previously loaded XML.
+ *
+ * @param xml XML to dispose.
+ */
+void xmlDispose(xml_t *xml);
+
+int16_t xmlGetAttributeByName(xml_t *xml, char *name);
+
bool xmlIsWhitespace(char c);
\ No newline at end of file