diff --git a/src/dawn/visualnovel/scene/SimpleVNScene.cpp b/src/dawn/visualnovel/scene/SimpleVNScene.cpp index 5e3c71e6..99f35f6c 100644 --- a/src/dawn/visualnovel/scene/SimpleVNScene.cpp +++ b/src/dawn/visualnovel/scene/SimpleVNScene.cpp @@ -12,6 +12,9 @@ SimpleVNScene::SimpleVNScene(DawnGame *game) : Scene(game) { } +void SimpleVNScene::vnStage() { + +} std::vector SimpleVNScene::getRequiredAssets() { auto assMan = &this->game->assetManager; diff --git a/src/dawn/visualnovel/scene/SimpleVNScene.hpp b/src/dawn/visualnovel/scene/SimpleVNScene.hpp index ae070f8b..1469f0c8 100644 --- a/src/dawn/visualnovel/scene/SimpleVNScene.hpp +++ b/src/dawn/visualnovel/scene/SimpleVNScene.hpp @@ -1,55 +1,55 @@ -// Copyright (c) 2022 Dominic Masters -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT - -#pragma once -#include "scene/Scene.hpp" -#include "game/DawnGame.hpp" -#include "util/array.hpp" -#include "scene/components/Components.hpp" -#include "scene/components/audio/AudioListener.hpp" -#include "visualnovel/VisualNovelManager.hpp" -#include "visualnovel/events/VisualNovelTextboxEvent.hpp" -#include "visualnovel/events/timing/VisualNovelPauseEvent.hpp" -#include "visualnovel/events/VisualNovelFadeEvent.hpp" -#include "visualnovel/events/VisualNovelCallbackEvent.hpp" -#include "visualnovel/events/VisualNovelChangeSimpleBackgroundEvent.hpp" - -namespace Dawn { - class SimpleVNScene : public Scene { - protected: - Camera *camera = nullptr; - UICanvas *canvas = nullptr; - VisualNovelTextbox *textbox = nullptr; - SimpleVisualNovelBackground *background = nullptr; - VisualNovelFader *vnFader = nullptr; - VisualNovelManager *vnManager = nullptr; - AudioListener *audioListener = nullptr; - - /** - * Internal method to stage the VN scene. - */ - virtual void vnStage() = 0; - - public: - /** - * Constructs a new Simple VN Scene. Custom class that implements the most - * common VN Things. - * - * @param game - */ - SimpleVNScene(DawnGame *game); - - std::vector getRequiredAssets() override; - void stage() override; - - /** - * Returns the first VN event for the scene. Called by the VN Manager for - * simple scenes. - * - * @return First VN event to be queued. - */ - virtual IVisualNovelEvent * getVNEvent() = 0; - }; +// Copyright (c) 2022 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "scene/Scene.hpp" +#include "game/DawnGame.hpp" +#include "util/array.hpp" +#include "scene/components/Components.hpp" +#include "scene/components/audio/AudioListener.hpp" +#include "visualnovel/VisualNovelManager.hpp" +#include "visualnovel/events/VisualNovelTextboxEvent.hpp" +#include "visualnovel/events/timing/VisualNovelPauseEvent.hpp" +#include "visualnovel/events/VisualNovelFadeEvent.hpp" +#include "visualnovel/events/VisualNovelCallbackEvent.hpp" +#include "visualnovel/events/VisualNovelChangeSimpleBackgroundEvent.hpp" + +namespace Dawn { + class SimpleVNScene : public Scene { + protected: + Camera *camera = nullptr; + UICanvas *canvas = nullptr; + VisualNovelTextbox *textbox = nullptr; + SimpleVisualNovelBackground *background = nullptr; + VisualNovelFader *vnFader = nullptr; + VisualNovelManager *vnManager = nullptr; + AudioListener *audioListener = nullptr; + + /** + * Internal method to stage the VN scene. + */ + virtual void vnStage(); + + public: + /** + * Constructs a new Simple VN Scene. Custom class that implements the most + * common VN Things. + * + * @param game + */ + SimpleVNScene(DawnGame *game); + + std::vector getRequiredAssets() override; + void stage() override; + + /** + * Returns the first VN event for the scene. Called by the VN Manager for + * simple scenes. + * + * @return First VN event to be queued. + */ + virtual IVisualNovelEvent * getVNEvent() = 0; + }; } \ No newline at end of file diff --git a/src/dawnpokergame/game/DawnGame.cpp b/src/dawnpokergame/game/DawnGame.cpp index 74ce541e..39f57f40 100644 --- a/src/dawnpokergame/game/DawnGame.cpp +++ b/src/dawnpokergame/game/DawnGame.cpp @@ -4,7 +4,7 @@ // https://opensource.org/licenses/MIT #include "DawnGame.hpp" -#include "scenes/Scene_1.hpp" +#include "scenes/vnscene_1.hpp" using namespace Dawn; @@ -24,7 +24,7 @@ int32_t DawnGame::init() { this->renderManager.init(); this->audioManager.init(); - this->scene = new Scene_1(this); + this->scene = new vnscene_1(this); return DAWN_GAME_INIT_RESULT_SUCCESS; } diff --git a/src/dawntools/locale/languagegen/main.cpp b/src/dawntools/locale/languagegen/main.cpp index a2b57854..2669bf5c 100644 --- a/src/dawntools/locale/languagegen/main.cpp +++ b/src/dawntools/locale/languagegen/main.cpp @@ -175,7 +175,7 @@ int main(int argc, char *argv[]) { } std::string filenameOut(argv[2]); - filenameOut += "/nlanguage_" + it->first + ".language"; + filenameOut += "/language_" + it->first + ".language"; char *filenameOutC = (char *)malloc(sizeof(char) * (filenameOut.size() + 1)); if(filenameOutC == NULL) { diff --git a/src/dawntools/utils/xml.c b/src/dawntools/utils/xml.c index 6ab327f9..6031551d 100644 --- a/src/dawntools/utils/xml.c +++ b/src/dawntools/utils/xml.c @@ -11,6 +11,7 @@ int32_t xmlLoadChild(xml_t *xml, char *data, int32_t i) { char c; int32_t level = 0; uint8_t doing = XML_DOING_NOTHING; + uint8_t doingBeforeComment; bool insideTag = false; char* buffer = malloc(sizeof(char) * XML_TEXT_BUFFER_MAX); int32_t bufferLength = 0; @@ -27,9 +28,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(data[i] == '!' && data[i+1] == '-') { + if(data[i] == '!' && data[i+1] == '-' && data[i+2] == '-') { + doingBeforeComment = doing; doing = XML_PARSING_COMMENT; - i += 2; + i += 3; } else if(insideTag) { i = xmlLoadChild(xml->children + xml->childrenCount++, data, i-1); doing = XML_PARSING_CHILD; @@ -145,6 +147,13 @@ int32_t xmlLoadChild(xml_t *xml, char *data, int32_t i) { continue; } + if(data[i] == '!' && data[i+1] == '-' && data[i+2] == '-') { + doingBeforeComment = doing; + doing = XML_PARSING_COMMENT; + i += 3; + continue; + } + // Likely another child. i = xmlLoadChild(xml->children + xml->childrenCount++, data, i-1); } @@ -168,8 +177,9 @@ int32_t xmlLoadChild(xml_t *xml, char *data, int32_t i) { if(c != '-') continue; if(data[i] != '-') continue; if(data[i+1] != '>') continue; - i+= 2; - doing = XML_DOING_NOTHING; + i += 2; + doing = doingBeforeComment; + break; default: break; diff --git a/src/dawntools/visualnovel/CMakeLists.txt b/src/dawntools/visualnovel/CMakeLists.txt index bbf2d387..16ad8d1a 100644 --- a/src/dawntools/visualnovel/CMakeLists.txt +++ b/src/dawntools/visualnovel/CMakeLists.txt @@ -14,6 +14,6 @@ function(tool_vnscene target in) ) target_include_directories(${DAWN_TARGET_NAME} PUBLIC - ${DAWN_GENERATED_DIR}/scenes + ${DAWN_GENERATED_DIR} ) endfunction() \ No newline at end of file diff --git a/src/dawntools/visualnovel/vnscenegen/main.cpp b/src/dawntools/visualnovel/vnscenegen/main.cpp index f0724fbe..26435b24 100644 --- a/src/dawntools/visualnovel/vnscenegen/main.cpp +++ b/src/dawntools/visualnovel/vnscenegen/main.cpp @@ -119,6 +119,101 @@ int32_t parseHeader(struct HeaderInformation *info, xml_t *node) { return 0; } +std::string parseEase(std::string e) { + if(e == "out-quad") return "easeOutQuad"; + std::cout << "Invalid ease defined" << std::endl; + return ""; +} + +std::string parseEvent(xml_t *evt, struct HeaderInformation *header) { + std::string buffer; + std::string node(evt->node); + + if(node == "pause") { + header->includes.push_back("visualnovel/events/timing/VisualNovelPauseEvent.hpp"); + + auto attrDuration = xmlGetAttributeByName(evt, "duration"); + if(attrDuration == -1) { + std::cout << "Pause event is missing duration argument." << std::endl; + return ""; + } + auto dur = std::string(evt->attributeDatas[attrDuration]); + if(dur.find('.') == std::string::npos) dur += ".0"; + buffer += "new VisualNovelPauseEvent(vnManager, " + dur + "f)"; + + + } else if(node == "text") { + header->includes.push_back("visualnovel/events/VisualNovelTextboxEvent.hpp"); + + auto attrChar = xmlGetAttributeByName(evt, "character"); + if(attrChar == -1) { + std::cout << "Text event missing character attribute." << std::endl; + return ""; + } + + auto attrEmotion = xmlGetAttributeByName(evt, "emotion"); + if(attrEmotion == -1) { + std::cout << "Text event missing emotion attribute." << std::endl; + return ""; + } + + auto attrString = xmlGetAttributeByName(evt, "string"); + if(attrString == -1) { + std::cout << "Text event missing string attribute." << std::endl; + return ""; + } + + std::string charName(evt->attributeDatas[attrChar]); + std::string emo(evt->attributeDatas[attrEmotion]); + emo[0] = toupper(emo[0]); + + buffer += "new VisualNovelTextboxEvent(vnManager, "; + buffer += "this->" + charName + "->vnCharacter, "; + buffer += "this->" + charName + "->emotion" + emo + ", "; + buffer += "\"" + std::string(evt->attributeDatas[attrString]) + "\"" ; + buffer += ")"; + + + } else if(node == "character-fade") { + header->includes.push_back("visualnovel/events/characters/VisualNovelFadeCharacterEvent.hpp"); + auto attrChar = xmlGetAttributeByName(evt, "character"); + auto attrDuration = xmlGetAttributeByName(evt, "duration"); + auto attrEase = xmlGetAttributeByName(evt, "ease"); + auto attrFade = xmlGetAttributeByName(evt, "fade"); + + if(attrChar == -1) { + std::cout << "Character fade event missing character attribute." << std::endl; + return ""; + } + + std::string character = std::string(evt->attributeDatas[attrChar]); + std::string easeIn = "true"; + std::string ease = "easeLinear"; + std::string duration = "1.0"; + + if(attrFade != -1) easeIn = std::string(evt->attributeDatas[attrFade]) == "in" ? "true" : "false"; + + if(attrDuration != -1) duration = std::string(evt->attributeDatas[attrDuration]); + if(duration.find('.') == std::string::npos) duration += ".0"; + + if(attrEase != -1) { + ease = parseEase(std::string(evt->attributeDatas[attrEase])); + if(ease.size() == 0) return ""; + } + + buffer += "new VisualNovelFadeCharacterEvent(vnManager, "; + buffer += "this->" + character + "->vnCharacter, "; + buffer += easeIn + ", "; + buffer += "&" + ease + ", "; + buffer += duration + "f"; + buffer += ")"; + } else if(node == "scene-transition") { + buffer += " "; + } + + return buffer; +} + int main(int32_t argc, char *args[]) { if(argc != 3) { std::cout << "Invalid number of args passed to VNScene Generator" << std::endl; @@ -172,13 +267,80 @@ int main(int32_t argc, char *args[]) { return 1; } + // Parse and load events. + std::string bufferEvents; + for(int32_t i = 0; i < xml.childrenCount; i++) { + auto events = xml.children + i; + if(std::string(events->node) != "events") continue; + bufferEvents += "\n start\n"; + for(int32_t j = 0; j < events->childrenCount; j++) { + auto evt = events->children + j; + if(std::string(evt->node) == "scene-transition") continue; + auto evtParsed = parseEvent(evt, &header); + if(evtParsed.size() == 0) return 1; + bufferEvents += " ->then(" + evtParsed + ")\n"; + } + bufferEvents += " ;\n"; + } + + // Now render output to file. std::string bufferOut; - bufferOut += "#pragma once\n"; + bufferOut += "#pragma once\n\n"; auto itInclude = header.includes.begin(); while(itInclude != header.includes.end()) { bufferOut += "#include \"" + (*itInclude) + "\"\n"; ++itInclude; } + bufferOut += "\nnamespace Dawn{\n"; + bufferOut += " class " + header.name + " : public " + header.type + " {\n"; + bufferOut += " protected:\n"; + + // Characters (As properties) + auto itCharacters = header.characters.begin(); + while(itCharacters != header.characters.end()) { + auto c = *itCharacters; + bufferOut += " " + c.clazz + " *" + c.name + ";\n"; + ++itCharacters; + } + bufferOut += "\n void vnStage() override {\n"; + bufferOut += " " + header.type + "::vnStage();\n"; + + // Initialize the characters + itCharacters = header.characters.begin(); + while(itCharacters != header.characters.end()) { + auto c = *itCharacters; + bufferOut += " this->" + c.name + " = " + c.clazz + "::create(this);\n"; + ++itCharacters; + } + + bufferOut += " }\n"; + + bufferOut += "\n public:\n"; + bufferOut += " " + header.name + "(DawnGame *game) : " + header.type + "(game) {\n"; + bufferOut += " }\n"; + + // Assets + bufferOut += "\n std::vector getRequiredAssets() override{\n"; + bufferOut += " auto man = &this->game->assetManager;\n"; + bufferOut += " std::vector assets = " + header.type + "::getRequiredAssets();\n"; + itCharacters = header.characters.begin(); + while(itCharacters != header.characters.end()) { + auto c = *itCharacters; + bufferOut += " vectorAppend(&assets, " + c.clazz + "::getRequiredAssets(man));\n"; + ++itCharacters; + } + bufferOut += " return assets;\n"; + bufferOut += " }\n"; + + // VN Events + bufferOut += "\n IVisualNovelEvent * getVNEvent() override {\n"; + bufferOut += " auto start = new VisualNovelPauseEvent(vnManager, 0.01f);\n"; + bufferOut += bufferEvents; + bufferOut += "\n return start;\n"; + bufferOut += " }\n"; + + bufferOut += " };\n"; + bufferOut += "}"; // Finished with XML data, now we can write data out. xmlDispose(&xml);