From 6fb9fbbd2f292190c016517135f7995d8305589b Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Sat, 4 Feb 2023 23:44:55 -0800 Subject: [PATCH] Begin VN scene parser --- src/dawnpokergame/CMakeLists.txt | 4 + src/dawnpokergame/scenes/Scene_1.hpp | 6 - src/dawntools/utils/xml.c | 12 +- src/dawntools/utils/xml.h | 1 + src/dawntools/visualnovel/CMakeLists.txt | 15 +- .../visualnovel/vnscenegen/CMakeLists.txt | 1 + src/dawntools/visualnovel/vnscenegen/main.cpp | 188 ++++++++++++++++++ 7 files changed, 219 insertions(+), 8 deletions(-) diff --git a/src/dawnpokergame/CMakeLists.txt b/src/dawnpokergame/CMakeLists.txt index 2fd520ef..f48fd997 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_vnscene(vnscene_1 ${DIR_GAME_ASSETS}/vn/Scene_1.xml) + add_dependencies(${DAWN_TARGET_NAME} locale_poker @@ -50,4 +52,6 @@ add_dependencies(${DAWN_TARGET_NAME} texture_test audio_test + + vnscene_1 ) \ No newline at end of file diff --git a/src/dawnpokergame/scenes/Scene_1.hpp b/src/dawnpokergame/scenes/Scene_1.hpp index c067088e..2c2e7d34 100644 --- a/src/dawnpokergame/scenes/Scene_1.hpp +++ b/src/dawnpokergame/scenes/Scene_1.hpp @@ -11,8 +11,6 @@ #include "visualnovel/events/characters/VisualNovelTransformItemEvent.hpp" #include "visualnovel/events/timing/VisualNovelBatchEvent.hpp" -#include "ui_test.hpp" - namespace Dawn { class Scene_1 : public SimpleVNScene { protected: @@ -22,10 +20,6 @@ namespace Dawn { 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() { diff --git a/src/dawntools/utils/xml.c b/src/dawntools/utils/xml.c index caeea259..6ab327f9 100644 --- a/src/dawntools/utils/xml.c +++ b/src/dawntools/utils/xml.c @@ -27,7 +27,10 @@ int32_t xmlLoadChild(xml_t *xml, char *data, int32_t i) { // Look for either an opening tag (<) or a word for a value. if(c == '>') continue; if(c == '<') { - if(insideTag) { + if(data[i] == '!' && data[i+1] == '-') { + doing = XML_PARSING_COMMENT; + i += 2; + } else if(insideTag) { i = xmlLoadChild(xml->children + xml->childrenCount++, data, i-1); doing = XML_PARSING_CHILD; } else { @@ -161,6 +164,13 @@ int32_t xmlLoadChild(xml_t *xml, char *data, int32_t i) { free(buffer); return i; + case XML_PARSING_COMMENT: + if(c != '-') continue; + if(data[i] != '-') continue; + if(data[i+1] != '>') continue; + i+= 2; + doing = XML_DOING_NOTHING; + default: break; } diff --git a/src/dawntools/utils/xml.h b/src/dawntools/utils/xml.h index 6e045b36..b05cb307 100644 --- a/src/dawntools/utils/xml.h +++ b/src/dawntools/utils/xml.h @@ -18,6 +18,7 @@ #define XML_PARSING_VALUE 0x06 #define XML_PARSING_CHILD 0x07 #define XML_PARSING_CLOSE 0x08 +#define XML_PARSING_COMMENT 0x09 #define XML_TEXT_BUFFER_MAX 2048 #define XML_CHILD_COUNT_MAX 128 diff --git a/src/dawntools/visualnovel/CMakeLists.txt b/src/dawntools/visualnovel/CMakeLists.txt index 9466b558..bbf2d387 100644 --- a/src/dawntools/visualnovel/CMakeLists.txt +++ b/src/dawntools/visualnovel/CMakeLists.txt @@ -3,4 +3,17 @@ # This software is released under the MIT License. # https://opensource.org/licenses/MIT -add_subdirectory(vnscenegen) \ No newline at end of file +add_subdirectory(vnscenegen) + +# UI Tool +function(tool_vnscene target in) + add_custom_target(${target} + COMMAND vnscenegen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_GENERATED_DIR}/scenes/${target}" + COMMENT "Generating VN Scene ${target} from ${in}" + DEPENDS vnscenegen + ) + target_include_directories(${DAWN_TARGET_NAME} + PUBLIC + ${DAWN_GENERATED_DIR}/scenes + ) +endfunction() \ No newline at end of file diff --git a/src/dawntools/visualnovel/vnscenegen/CMakeLists.txt b/src/dawntools/visualnovel/vnscenegen/CMakeLists.txt index 3daf5c33..945f6059 100644 --- a/src/dawntools/visualnovel/vnscenegen/CMakeLists.txt +++ b/src/dawntools/visualnovel/vnscenegen/CMakeLists.txt @@ -10,6 +10,7 @@ target_sources(vnscenegen PRIVATE main.cpp ../../utils/file.c + ../../utils/xml.c ) target_include_directories(vnscenegen PUBLIC diff --git a/src/dawntools/visualnovel/vnscenegen/main.cpp b/src/dawntools/visualnovel/vnscenegen/main.cpp index 5b4376ae..f0724fbe 100644 --- a/src/dawntools/visualnovel/vnscenegen/main.cpp +++ b/src/dawntools/visualnovel/vnscenegen/main.cpp @@ -5,11 +5,199 @@ extern "C" { #include "../../utils/file.h" + #include "../../utils/xml.h" #include } #include #include +struct CharacterInformation { + std::string clazz; + std::string name; +}; + +struct Asset { + std::string type; + std::string name; +}; + +struct HeaderInformation { + std::string type; + std::string name; + std::vector includes; + std::vector characters; + std::vector assets; +}; + +int32_t parseInclude(struct HeaderInformation *info, xml_t *node) { + auto attrPath = xmlGetAttributeByName(node, "path"); + if(attrPath == -1) { + std::cout << "Missing include path in VN Header Defintions." << std::endl; + return 1; + } + + info->includes.push_back(node->attributeDatas[attrPath]); + return 0; +} + +int32_t parseCharacter(struct HeaderInformation *info, xml_t *node) { + auto attrClass = xmlGetAttributeByName(node, "class"); + if(attrClass == -1) { + std::cout << "Character definition is missing class" << std::endl; + return 1; + } + + auto attrName = xmlGetAttributeByName(node, "name"); + if(attrName == -1) { + std::cout << "Character definition is missing name" << std::endl; + } + + struct CharacterInformation character; + character.clazz = std::string(node->attributeDatas[attrClass]); + character.name = std::string(node->attributeDatas[attrName]); + info->characters.push_back(character); + return 0; +} + +int32_t parseScene(struct HeaderInformation *info, xml_t *node) { + auto attrName = xmlGetAttributeByName(node, "name"); + if(attrName == -1) { + std::cout << "VN Scene definition is missing name attribute" << std::endl; + return 1; + } + info->name = std::string(node->attributeDatas[attrName]); + + auto attrType = xmlGetAttributeByName(node, "type"); + if(attrType == -1) { + info->type = "SimpleVNScene"; + } else { + info->type = std::string(node->attributeDatas[attrType]); + } + return 0; +} + +int32_t parseAsset(struct HeaderInformation *info, xml_t *node) { + auto attrType = xmlGetAttributeByName(node, "type"); + if(attrType == -1) { + std::cout << "VN Scene Asset missing type attribute" << std::endl; + return 1; + } + auto attrName = xmlGetAttributeByName(node, "name"); + if(attrName == -1) { + std::cout << "VN Scene Asset missing name attribute" << std::endl; + return 1; + } + + struct Asset ass; + ass.type = std::string(node->attributeDatas[attrType]); + ass.name = std::string(node->attributeDatas[attrName]); + info->assets.push_back(ass); + return 0; +} + +int32_t parseHeader(struct HeaderInformation *info, xml_t *node) { + for(int32_t i = 0; i < node->childrenCount; i++) { + auto c = node->children + i; + auto n = std::string(c->node); + int32_t ret = 0; + + std::cout << n << std::endl; + + if(n == "include") { + ret = parseInclude(info, c); + } else if(n == "character") { + ret = parseCharacter(info, c); + } else if(n == "scene") { + ret = parseScene(info, c); + } else if (n == "asset") { + ret = parseAsset(info, c); + } else { + std::cout << "Parsing VN Scene header, unknown node " << n << std::endl; + } + if(ret != 0) return ret; + } + return 0; +} + int main(int32_t argc, char *args[]) { + if(argc != 3) { + std::cout << "Invalid number of args passed to VNScene Generator" << std::endl; + return 1; + } + + // Open input file. + char fileIn[FILENAME_MAX]; + fileNormalizeSlashes(args[1]); + sprintf(fileIn, "%s", args[1]); + FILE *fin = fopen(fileIn, "rb"); + if(fin == NULL) { + std::cout << "Failed to open input file " << fileIn << std::endl; + return 1; + } + + // Tell file len + auto len = assetReadString(fin, NULL); + + // 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); + + // First, read the header information + struct HeaderInformation header; + for(int32_t i = 0; i < xml.childrenCount; i++) { + auto child = xml.children + i; + if(std::string(child->node) != "head") continue; + auto ret = parseHeader(&header, child); + if(ret != 0) { + xmlDispose(&xml); + return ret; + } + break; + } + // Validate header + if(header.name.size() == 0 || header.type.size() == 0) { + std::cout << "VN Scene header wasn't parsed properly." << std::endl; + return 1; + } + + std::string bufferOut; + bufferOut += "#pragma once\n"; + auto itInclude = header.includes.begin(); + while(itInclude != header.includes.end()) { + bufferOut += "#include \"" + (*itInclude) + "\"\n"; + ++itInclude; + } + + // Finished with XML data, now we can write data out. + xmlDispose(&xml); + + char fileOut[FILENAME_MAX]; + fileNormalizeSlashes(args[2]); + sprintf(fileOut, "%s.hpp", args[2]); + fileMkdirp(fileOut); + 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 Scene " << fileOut << std::endl; + + return 0; } \ No newline at end of file