// Copyright (c) 2023 Dominic Masters // // This software is released under the MIT License. // https://opensource.org/licenses/MIT #include "VnSceneGen.hpp" using namespace Dawn; int32_t VnSceneGen::start() { if(this->args.size() != 3) { std::cout << "Invalid number of args passed to VNScene Generator" << std::endl; return 1; } // Open input file. File file(this->args[1]); std::string buffer; if(!file.readString(&buffer)) { std::cout << "Failed to read scene " << file.filename << std::endl; return 1; } // Parse XML Xml xml = Xml::load(buffer); // First, read the header information struct HeaderInformation header; auto itXml = xml.children.begin(); while(itXml != xml.children.end()) { auto child = *itXml; if(child->node != "head") { ++itXml; continue; } auto ret = parseHeader(&header, child); if(ret != 0) return ret; break; } // Validate header if(header.sceneInfo.name.size() == 0 || header.sceneInfo.type.size() == 0) { std::cout << "VN Scene header wasn't parsed properly." << std::endl; return 1; } // Parse and load events. std::string bufferEvents; itXml = xml.children.begin(); while(itXml != xml.children.end()) { auto events = *itXml; if(events->node != "events") { ++itXml; continue; } bufferEvents += "\n start\n"; auto itChildren = events->children.begin(); while(itChildren != events->children.end()) { auto evt = *itChildren; if(evt->node != "scene-transition") { auto evtParsed = parseEvent(&header, evt); if(evtParsed.size() == 0) return 1; bufferEvents += " ->then(" + evtParsed + ")\n"; } ++itChildren; } bufferEvents += " ;\n"; ++itXml; } // Now render output to file. std::string bufferOut; 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.sceneInfo.name + " : public " + header.sceneInfo.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.sceneInfo.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.sceneInfo.name + "(DawnGame *game) : " + header.sceneInfo.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.sceneInfo.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. File fileOut(this->args[2] + ".hpp"); if(!fileOut.mkdirp()) { std::cout << "Failed to make scene output dir" << std::endl; return 1; } if(!fileOut.writeString(bufferOut)) { std::cout << "Failed to generate scene " << fileOut.filename << std::endl; return 1; } return 0; }