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