// Copyright (c) 2023 Dominic Masters // // This software is released under the MIT License. // https://opensource.org/licenses/MIT 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; }