Moved C++ tools out
This commit is contained in:
19
archive/dawntools/util/CMakeLists.txt
Normal file
19
archive/dawntools/util/CMakeLists.txt
Normal file
@ -0,0 +1,19 @@
|
||||
# Copyright (c) 2023 Dominic Msters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
set(D ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
set(
|
||||
DAWN_TOOL_SOURCES
|
||||
${DAWN_TOOL_SOURCES}
|
||||
${D}/DawnTool.cpp
|
||||
${D}/File.cpp
|
||||
${D}/Language.cpp
|
||||
${D}/CodeGen.cpp
|
||||
${D}/Directory.cpp
|
||||
|
||||
CACHE INTERNAL
|
||||
${DAWN_CACHE_TARGET}
|
||||
)
|
100
archive/dawntools/util/CodeGen.cpp
Normal file
100
archive/dawntools/util/CodeGen.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "CodeGen.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
void CodeGen::line(
|
||||
std::vector<std::string> *out,
|
||||
std::string contents,
|
||||
std::string tabs
|
||||
) {
|
||||
out->push_back(tabs + contents);
|
||||
}
|
||||
|
||||
void CodeGen::lines(
|
||||
std::vector<std::string> *out,
|
||||
std::vector<std::string> lines,
|
||||
std::string tabs
|
||||
) {
|
||||
auto itLine = lines.begin();
|
||||
while(itLine != lines.end()) {
|
||||
line(out, *itLine, tabs);
|
||||
++itLine;
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGen::classGen(
|
||||
std::vector<std::string> *out,
|
||||
struct ClassGenInfo info
|
||||
) {
|
||||
std::vector<std::string> buffer;
|
||||
|
||||
line(out, "#pragma once", "");
|
||||
line(out, "", "");
|
||||
|
||||
// Includes
|
||||
if(info.includes.size() > 0) {
|
||||
// iterate over info.includes
|
||||
std::vector<std::string> included;
|
||||
auto itInclude = info.includes.begin();
|
||||
while(itInclude != info.includes.end()) {
|
||||
// skip if already included
|
||||
if(std::find(included.begin(), included.end(), *itInclude) != included.end()) {
|
||||
++itInclude;
|
||||
continue;
|
||||
}
|
||||
if(itInclude->find("#include") == std::string::npos) {
|
||||
line(out, "#include \"" + *itInclude + "\"", "");
|
||||
} else {
|
||||
line(out, *itInclude, "");
|
||||
}
|
||||
|
||||
included.push_back(*itInclude);
|
||||
++itInclude;
|
||||
}
|
||||
line(out, "", "");
|
||||
}
|
||||
|
||||
line(out, "namespace Dawn {", "");
|
||||
auto itTemplates = info.classTemplates.begin();
|
||||
while(itTemplates != info.classTemplates.end()) {
|
||||
line(out, "template<" + itTemplates->second + " " + itTemplates->first + ">", " ");
|
||||
++itTemplates;
|
||||
}
|
||||
line(out, "class " + info.clazz + (info.extend.size() == 0 ? "{" : " : public " + info.extend + " {" ), " ");
|
||||
if(info.protectedCode.size() > 0) {
|
||||
line(out, "protected:", " ");
|
||||
lines(out, info.protectedProperties, " ");
|
||||
line(out, "", " ");
|
||||
lines(out, info.protectedCode, " ");
|
||||
}
|
||||
|
||||
if(info.publicCode.size() > 0 || info.constructorArgs.size() > 0 || info.constructorCode.size() > 0) {
|
||||
line(out, "public:", " ");
|
||||
lines(out, info.publicProperties, " ");
|
||||
line(out, "", " ");
|
||||
line(out, info.clazz + "(" + info.constructorArgs + ")" + (info.extend.size() > 0 ? " : " + info.extend + "(" + info.extendArgs + ")" : "") + " {", " ");
|
||||
lines(out, info.constructorCode, " ");
|
||||
line(out, "}", " ");
|
||||
if(info.publicCode.size() > 0) {
|
||||
line(out, "", " ");
|
||||
lines(out, info.publicCode, " ");
|
||||
}
|
||||
}
|
||||
line(out, "};", " ");
|
||||
line(out, "}", "");
|
||||
}
|
||||
|
||||
|
||||
void CodeGen::methodGen(
|
||||
std::vector<std::string> *out,
|
||||
struct MethodGenInfo info
|
||||
) {
|
||||
line(out, (info.isStatic ? "static " : "") + info.type + " " + info.name + "(" + info.args + ") " + ( info.isOverride ? "override " : "" ) + "{", "");
|
||||
lines(out, info.body, " ");
|
||||
line(out, "}", "");
|
||||
}
|
87
archive/dawntools/util/CodeGen.hpp
Normal file
87
archive/dawntools/util/CodeGen.hpp
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "dawnsharedlibs.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct ClassGenInfo {
|
||||
std::vector<std::string> includes;
|
||||
std::string clazz = "Unknown";
|
||||
std::string extend = "";
|
||||
std::string constructorArgs = "";
|
||||
std::string extendArgs = "";
|
||||
|
||||
std::map<std::string, std::string> classTemplates;
|
||||
|
||||
std::vector<std::string> constructorCode;
|
||||
|
||||
std::vector<std::string> protectedCode;
|
||||
std::vector<std::string> protectedProperties;
|
||||
|
||||
std::vector<std::string> publicCode;
|
||||
std::vector<std::string> publicProperties;
|
||||
};
|
||||
|
||||
struct MethodGenInfo {
|
||||
std::string name;
|
||||
std::string type = "void";
|
||||
std::vector<std::string> body;
|
||||
std::string args = "";
|
||||
bool_t isStatic = false;
|
||||
bool_t isOverride = false;
|
||||
};
|
||||
|
||||
class CodeGen {
|
||||
protected:
|
||||
/**
|
||||
* Append a line of code to the output buffer.
|
||||
*
|
||||
* @param out Output buffer to append to.
|
||||
* @param contents Line of code to append to the buffer.
|
||||
* @param tabs Prepended string of spaces/tabs.
|
||||
*/
|
||||
static void line(
|
||||
std::vector<std::string> *out,
|
||||
std::string contents,
|
||||
std::string tabs
|
||||
);
|
||||
|
||||
/**
|
||||
* Append an array of lines to the output buffer.
|
||||
*
|
||||
* @param out Output buffer to append to.
|
||||
* @param lines List of lines of code to append to the buffer.
|
||||
* @param tabs Prepended string of tabs/spaces to prepend to EACH line.
|
||||
*/
|
||||
static void lines(
|
||||
std::vector<std::string> *out,
|
||||
std::vector<std::string> lines,
|
||||
std::string tabs
|
||||
);
|
||||
|
||||
/**
|
||||
* Generate code of a class
|
||||
*
|
||||
* @param out Output buffer to write the class to.
|
||||
* @param info Information about how the class should be generated.
|
||||
*/
|
||||
static void classGen(
|
||||
std::vector<std::string> *out,
|
||||
struct ClassGenInfo info
|
||||
);
|
||||
|
||||
/**
|
||||
* Generate code of a method/function.
|
||||
*
|
||||
* @param out Output buffer to write the method to.
|
||||
* @param info Information about how the method should be generated.
|
||||
*/
|
||||
static void methodGen(
|
||||
std::vector<std::string> *out,
|
||||
struct MethodGenInfo info
|
||||
);
|
||||
};
|
||||
}
|
81
archive/dawntools/util/DawnTool.cpp
Normal file
81
archive/dawntools/util/DawnTool.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "DawnTool.hpp"
|
||||
#include "util/memory.hpp"
|
||||
|
||||
#if !defined(DAWN_TOOL_INSTANCE)
|
||||
#error Dawn Tool Instance, e.g. LanguageTool has not been defined
|
||||
#endif
|
||||
|
||||
#if !defined(DAWN_TOOL_HEADER)
|
||||
#error Dawn Tool Include, e.g. LanguageTool.hpp has not been defined
|
||||
#endif
|
||||
|
||||
#include DAWN_TOOL_HEADER
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
std::vector<std::string> DawnTool::getRequiredFlags() {
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> DawnTool::getOptionalFlags() {
|
||||
return std::map<std::string, std::string>();
|
||||
}
|
||||
|
||||
int32_t DawnTool::exec(const int32_t argc, const char *argv[]) {
|
||||
// Set up flags
|
||||
flags = this->getOptionalFlags();
|
||||
|
||||
// Parse args
|
||||
for(int32_t i = 0; i < argc; i++) {
|
||||
std::string a(argv[i]);
|
||||
this->args.push_back(a);
|
||||
|
||||
// First arg is the path, we ignore it.
|
||||
if(i == 0) continue;
|
||||
|
||||
// Is this a flag-like arg, as in has "--[name]=[value]"
|
||||
if(a.size() < 5) continue;
|
||||
if(a[0] != '-' || a[1] != '-') continue;
|
||||
|
||||
// Remove --
|
||||
auto flag = a.erase(0, 2);
|
||||
|
||||
// Ensure = is present
|
||||
auto equalPos = flag.find('=');
|
||||
if(equalPos == std::string::npos) continue;
|
||||
|
||||
// Get prefix and val and store
|
||||
auto prefix = flag.substr(0, equalPos);
|
||||
auto val = flag.substr(equalPos + 1);
|
||||
if(val.size() == 0) continue;
|
||||
flags[prefix] = val;
|
||||
}
|
||||
|
||||
// Now validate flags
|
||||
auto required = this->getRequiredFlags();
|
||||
auto itReq = required.begin();
|
||||
while(itReq != required.end()) {
|
||||
auto match = flags.find(*itReq);
|
||||
if(match == flags.end()) {
|
||||
std::cout << "Missing required flag \"" + *itReq + "\"!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
++itReq;
|
||||
}
|
||||
|
||||
return this->start();
|
||||
}
|
||||
|
||||
int main(const int32_t argc, const char *argv[]) {
|
||||
memoryInit();
|
||||
DAWN_TOOL_INSTANCE *self = new DAWN_TOOL_INSTANCE();
|
||||
int32_t ret = self->exec(argc, argv);
|
||||
delete self;
|
||||
if(ret == 0) memoryDispose();
|
||||
return ret;
|
||||
}
|
57
archive/dawntools/util/DawnTool.hpp
Normal file
57
archive/dawntools/util/DawnTool.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "dawnsharedlibs.hpp"
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
namespace Dawn {
|
||||
class DawnTool {
|
||||
protected:
|
||||
std::vector<std::string> args;
|
||||
std::map<std::string, std::string> flags;
|
||||
|
||||
/**
|
||||
* Get the required flags for this tool. These flags will be checked in
|
||||
* the passed args to the CLI.
|
||||
*
|
||||
* @return Array of required flags.
|
||||
*/
|
||||
virtual std::vector<std::string> getRequiredFlags();
|
||||
|
||||
/**
|
||||
* Get the optional flags for this tool. Mapped by key value pair where
|
||||
* the value is some default value you want for your tool.
|
||||
*
|
||||
* @return Array of optional flags.
|
||||
*/
|
||||
virtual std::map<std::string, std::string> getOptionalFlags();
|
||||
|
||||
public:
|
||||
int32_t *test;
|
||||
|
||||
/**
|
||||
* Execute the Dawn Tool from the CLI, functionally identically to main()
|
||||
*
|
||||
* @param argc Count of arguments in the array.
|
||||
* @param argv Array of arguments.
|
||||
* @return int32_t
|
||||
*/
|
||||
int32_t exec(const int32_t argc, const char *argv[]);
|
||||
|
||||
/**
|
||||
* Overridable start method after the tool has been set up.
|
||||
*
|
||||
* @return 0 for success, otherwise for failure.
|
||||
*/
|
||||
virtual int32_t start() = 0;
|
||||
};
|
||||
}
|
||||
|
||||
int main(const int32_t argc, const char *argv[]);
|
58
archive/dawntools/util/Directory.cpp
Normal file
58
archive/dawntools/util/Directory.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "Directory.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
Directory::Directory(std::string dirname) {
|
||||
this->filename = File::normalizeSlashes(dirname);
|
||||
}
|
||||
|
||||
bool_t Directory::open() {
|
||||
if(!this->exists()) return false;
|
||||
if (handle != std::filesystem::end(handle)) return true;
|
||||
handle = std::filesystem::directory_iterator(filename);
|
||||
return handle != std::filesystem::end(handle);
|
||||
}
|
||||
|
||||
bool_t Directory::isOpen() {
|
||||
return handle != std::filesystem::end(handle);
|
||||
}
|
||||
|
||||
void Directory::close() {
|
||||
if(this->isOpen()) {
|
||||
handle = std::filesystem::directory_iterator();
|
||||
}
|
||||
}
|
||||
|
||||
bool_t Directory::exists() {
|
||||
return std::filesystem::exists(filename);
|
||||
}
|
||||
|
||||
void Directory::mkdirp() {
|
||||
File::mkdirp(this->filename);
|
||||
}
|
||||
|
||||
std::map<std::string, enum DirectoryChildType> Directory::readDirectory() {
|
||||
this->close();
|
||||
if(!this->open()) return {};
|
||||
|
||||
std::map<std::string, enum DirectoryChildType> children;
|
||||
for(const auto& entry : handle) {
|
||||
if (entry.is_directory()) {
|
||||
children[entry.path().filename().string()] = DIRECTORY_CHILD_TYPE_DIRECTORY;
|
||||
} else if (entry.is_regular_file()) {
|
||||
children[entry.path().filename().string()] = DIRECTORY_CHILD_TYPE_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
this->close();
|
||||
return children;
|
||||
}
|
||||
|
||||
Directory::~Directory() {
|
||||
this->close();
|
||||
}
|
60
archive/dawntools/util/Directory.hpp
Normal file
60
archive/dawntools/util/Directory.hpp
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/File.hpp"
|
||||
#include <filesystem>
|
||||
|
||||
namespace Dawn {
|
||||
enum DirectoryChildType {
|
||||
DIRECTORY_CHILD_TYPE_FILE,
|
||||
DIRECTORY_CHILD_TYPE_DIRECTORY
|
||||
};
|
||||
|
||||
class Directory {
|
||||
public:
|
||||
std::string filename;
|
||||
std::filesystem::directory_iterator handle;
|
||||
|
||||
Directory(std::string dir);
|
||||
|
||||
/**
|
||||
* Opens a connection to the directory.
|
||||
* @return True if success, otherwise for failure.
|
||||
*/
|
||||
bool_t open();
|
||||
|
||||
/**
|
||||
* Returns if the directory is open.
|
||||
* @return True if open, otherwise false.
|
||||
*/
|
||||
bool_t isOpen();
|
||||
|
||||
/**
|
||||
* Closes the directory.
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Returns if the directory exists.
|
||||
* @return True if exists, otherwise false.
|
||||
*/
|
||||
bool_t exists();
|
||||
|
||||
/**
|
||||
* Creates the directory and all parent directories.
|
||||
*/
|
||||
void mkdirp();
|
||||
|
||||
/**
|
||||
* Reads the directory and returns a list of files.
|
||||
*
|
||||
* @return List of filenames/directories within this directory.
|
||||
*/
|
||||
std::map<std::string, enum DirectoryChildType> readDirectory();
|
||||
|
||||
~Directory();
|
||||
};
|
||||
}
|
264
archive/dawntools/util/File.cpp
Normal file
264
archive/dawntools/util/File.cpp
Normal file
@ -0,0 +1,264 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "File.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
std::string File::normalizeSlashes(std::string str) {
|
||||
size_t i = 0;
|
||||
while(i < str.size()) {
|
||||
auto c = str[i];
|
||||
if(c == '\\' || c == '/') str[i] = FILE_PATH_SEP;
|
||||
++i;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
void File::mkdirp(std::string path) {
|
||||
std::string buffer;
|
||||
char c;
|
||||
size_t i = 0;
|
||||
bool_t inFile;
|
||||
bool_t hasMore;
|
||||
|
||||
inFile = false;
|
||||
hasMore = false;
|
||||
while(c = path[i]) {
|
||||
if((c == '\\' || c == '/') && i > 0) {
|
||||
fileMkdir(buffer.c_str(), 0755);
|
||||
inFile = false;
|
||||
hasMore = false;
|
||||
buffer += FILE_PATH_SEP;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(c == '.') inFile = true;
|
||||
hasMore = true;
|
||||
buffer += c;
|
||||
i++;
|
||||
}
|
||||
|
||||
if(!inFile && hasMore) {
|
||||
fileMkdir(buffer.c_str(), 0755);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
File::File(std::string filename) {
|
||||
this->filename = File::normalizeSlashes(filename);
|
||||
}
|
||||
|
||||
bool_t File::open(enum FileMode mode) {
|
||||
assertNull(this->file, "File is already open");
|
||||
|
||||
this->mode = mode;
|
||||
this->file = fopen(
|
||||
this->filename.c_str(),
|
||||
mode == FILE_MODE_READ ? "rb" : "wb"
|
||||
);
|
||||
|
||||
if(this->file == NULL) return false;
|
||||
|
||||
if(mode == FILE_MODE_READ) {
|
||||
fseek(this->file, 0, SEEK_END);
|
||||
this->length = ftell(this->file);
|
||||
fseek(this->file, 0, SEEK_SET);
|
||||
|
||||
if(this->length <= 0) {
|
||||
this->close();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
this->length = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool_t File::isOpen() {
|
||||
return this->file != nullptr;
|
||||
}
|
||||
|
||||
bool_t File::exists() {
|
||||
if(this->file != nullptr) return true;
|
||||
FILE *f = fopen(this->filename.c_str(), "rb");
|
||||
if(f == NULL || f == nullptr) return false;
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
|
||||
void File::close() {
|
||||
assertNotNull(this->file, "File::close: File is not open");
|
||||
fclose(this->file);
|
||||
this->file = nullptr;
|
||||
}
|
||||
|
||||
bool_t File::mkdirp() {
|
||||
File::mkdirp(this->filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool_t File::readString(std::string *out) {
|
||||
assertNotNull(out, "File::readString: Out cannot be null");
|
||||
|
||||
if(!this->isOpen()) {
|
||||
if(!this->open(FILE_MODE_READ)) return false;
|
||||
}
|
||||
assertTrue(this->mode == FILE_MODE_READ, "File::readString: File must be open in read mode");
|
||||
out->clear();
|
||||
|
||||
size_t i = 0;
|
||||
char buffer[FILE_BUFFER_SIZE + 1];// +1 for null term
|
||||
while(i != this->length) {
|
||||
size_t amt = mathMin<size_t>(FILE_BUFFER_SIZE, (this->length - i));
|
||||
auto amtRead = fread(buffer, sizeof(char), amt, this->file);
|
||||
if(amtRead != amt) return false;
|
||||
i += amtRead;
|
||||
buffer[amtRead] = '\0';
|
||||
out->append(buffer);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t File::readAhead(char *buffer, size_t max, char needle) {
|
||||
assertNotNull(buffer, "File::readAhead: Buffer cannot be null");
|
||||
assertTrue(max > 0, "File::readAhead: Max must be greater than 0");
|
||||
|
||||
if(!this->isOpen()) {
|
||||
if(!this->open(FILE_MODE_READ)) return 0;
|
||||
}
|
||||
assertTrue(this->mode == FILE_MODE_READ, "File::readAhead: File must be open in read mode");
|
||||
|
||||
// Buffer
|
||||
size_t pos = ftell(this->file);
|
||||
size_t amountLeftToRead = mathMin<size_t>(max, this->length - pos);
|
||||
char temporary[FILE_BUFFER_SIZE];
|
||||
size_t n = 0;
|
||||
|
||||
while(amountLeftToRead > 0) {
|
||||
size_t toRead = mathMin<size_t>(amountLeftToRead, FILE_BUFFER_SIZE);
|
||||
amountLeftToRead -= toRead;
|
||||
// Read bytes
|
||||
size_t read = fread(temporary, sizeof(char), toRead, this->file);
|
||||
|
||||
// Read error?
|
||||
if(toRead != read) return 0;
|
||||
|
||||
// Did we read the needle?
|
||||
size_t i = 0;
|
||||
while(i < read) {
|
||||
char c = temporary[i++];
|
||||
if(c == needle) {
|
||||
return n;
|
||||
} else {
|
||||
buffer[n++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Needle was not found.
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t File::readToBuffer(char **buffer) {
|
||||
if(!this->isOpen()) {
|
||||
if(!this->open(FILE_MODE_READ)) return 0;
|
||||
}
|
||||
assertTrue(this->mode == FILE_MODE_READ, "File::readToBuffer: File must be open in read mode");
|
||||
|
||||
if((*buffer) == nullptr) *buffer = (char*)malloc(this->length);
|
||||
fseek(this->file, 0, SEEK_SET);
|
||||
auto l = fread((*buffer), sizeof(char), this->length, this->file);
|
||||
return l;
|
||||
}
|
||||
|
||||
size_t File::readRaw(char *buffer, size_t max) {
|
||||
assertNotNull(buffer, "File::readRaw: Buffer cannot be null");
|
||||
assertTrue(max > 0, "File::readRaw: Max must be greater than 0");
|
||||
if(!this->isOpen()) {
|
||||
if(!this->open(FILE_MODE_READ)) return 0;
|
||||
}
|
||||
assertTrue(this->mode == FILE_MODE_READ, "File::readRaw: File must be open in read mode");
|
||||
return fread(buffer, sizeof(char), max, this->file);
|
||||
}
|
||||
|
||||
bool_t File::writeString(std::string in) {
|
||||
if(!this->isOpen() && !this->open(FILE_MODE_WRITE)) return false;
|
||||
assertTrue(this->mode == FILE_MODE_WRITE, "File::writeString: File must be open in write mode");
|
||||
return this->writeRaw((char *)in.c_str(), in.size()) && this->length == in.size();
|
||||
}
|
||||
|
||||
bool_t File::writeRaw(char *data, size_t len) {
|
||||
if(!this->isOpen() && !this->open(FILE_MODE_WRITE)) return false;
|
||||
assertTrue(this->mode == FILE_MODE_WRITE, "File::writeRaw: File must be open in write mode");
|
||||
assertTrue(len > 0, "File::writeRaw: Length must be greater than 0");
|
||||
this->length = fwrite(data, sizeof(char_t), len, this->file);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool_t File::copyRaw(File *otherFile, size_t length) {
|
||||
assertTrue(length > 0, "File::copyRaw: Length must be greater than 0");
|
||||
assertTrue(otherFile->isOpen(), "File::copyRaw: Other file must be open");
|
||||
|
||||
char buffer[FILE_BUFFER_SIZE];
|
||||
size_t amountLeftToRead = length;
|
||||
size_t read = 0;
|
||||
while(amountLeftToRead > 0) {
|
||||
auto iRead = otherFile->readRaw(buffer, mathMin<size_t>(FILE_BUFFER_SIZE, amountLeftToRead));
|
||||
if(iRead == 0) return false;
|
||||
this->writeRaw(buffer, iRead);
|
||||
amountLeftToRead -= iRead;
|
||||
read += iRead;
|
||||
}
|
||||
|
||||
assertTrue(read == length, "File::copyRaw: Read length does not match expected length");
|
||||
return true;
|
||||
}
|
||||
|
||||
void File::setPosition(size_t n) {
|
||||
fseek(this->file, 0, SEEK_SET);
|
||||
fseek(this->file, n, SEEK_CUR);
|
||||
}
|
||||
|
||||
std::string File::getFileName(bool_t withExt) {
|
||||
// Remove all but last slash
|
||||
std::string basename;
|
||||
size_t lastSlash = this->filename.find_last_of('/');
|
||||
if(lastSlash == std::string::npos) {
|
||||
basename = this->filename;
|
||||
} else {
|
||||
basename = this->filename.substr(lastSlash + 1);
|
||||
}
|
||||
|
||||
// Do we need to remove ext?
|
||||
if(withExt) return basename;
|
||||
size_t lastDot = basename.find_last_of('.');
|
||||
if(lastDot == std::string::npos) return basename;
|
||||
return basename.substr(0, lastDot);
|
||||
}
|
||||
|
||||
std::string File::getExtension() {
|
||||
// Remove all but last slash
|
||||
std::string basename;
|
||||
size_t lastSlash = this->filename.find_last_of('/');
|
||||
if(lastSlash == std::string::npos) {
|
||||
basename = this->filename;
|
||||
} else {
|
||||
basename = this->filename.substr(lastSlash + 1);
|
||||
}
|
||||
|
||||
size_t lastDot = basename.find_last_of('.');
|
||||
if(lastDot == std::string::npos) return "";
|
||||
return basename.substr(lastDot + 1);
|
||||
}
|
||||
|
||||
|
||||
File::~File() {
|
||||
if(this->file != nullptr) this->close();
|
||||
}
|
183
archive/dawntools/util/File.hpp
Normal file
183
archive/dawntools/util/File.hpp
Normal file
@ -0,0 +1,183 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "assert/assert.hpp"
|
||||
#include "util/mathutils.hpp"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <direct.h>
|
||||
#include <windows.h>
|
||||
#define getcwd _getcwd
|
||||
#define FILE_PATH_SEP '\\'
|
||||
#define fileMkdir(path, perms) _mkdir(path)
|
||||
#elif defined(__GNUC__)
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#define FILE_PATH_SEP '/'
|
||||
#define fileMkdir(path, perms) mkdir(path, perms)
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#define FILE_BUFFER_SIZE 512
|
||||
|
||||
namespace Dawn {
|
||||
enum FileMode {
|
||||
FILE_MODE_READ,
|
||||
FILE_MODE_WRITE
|
||||
};
|
||||
|
||||
class File {
|
||||
private:
|
||||
enum FileMode mode;
|
||||
|
||||
public:
|
||||
static std::string normalizeSlashes(std::string str);
|
||||
static void mkdirp(std::string path);
|
||||
|
||||
std::string filename;
|
||||
size_t length;
|
||||
FILE *file = nullptr;
|
||||
|
||||
/**
|
||||
* Constructs a new File interface class.
|
||||
*
|
||||
* @param filename Filename that you want to interface with.
|
||||
*/
|
||||
File(std::string filename);
|
||||
|
||||
/**
|
||||
* Opens a connection to the file.
|
||||
*
|
||||
* @param mode File mode to use for this interface.
|
||||
* @return True if success, otherwise for failure.
|
||||
*/
|
||||
bool_t open(enum FileMode mode);
|
||||
|
||||
/**
|
||||
* Returns whether or not the file connection is currently opened.
|
||||
*
|
||||
* @return True if the connection is open, otherwise if it's not.
|
||||
*/
|
||||
bool_t isOpen();
|
||||
|
||||
/**
|
||||
* Returns whether or not the file exists. Will open the connection if it
|
||||
* does exist.
|
||||
*
|
||||
* @return True if exists, otherwsie if it doesn't.
|
||||
*/
|
||||
bool_t exists();
|
||||
|
||||
/**
|
||||
* Closes the currently open interface to the file. Done automatically
|
||||
* when this object is disposed.
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Makes all directories above this file's filename.
|
||||
*
|
||||
* @return True if successful, otherwise false.
|
||||
*/
|
||||
bool_t mkdirp();
|
||||
|
||||
/**
|
||||
* Reads the entire contents of a file to the given output string buffer.
|
||||
* This is a bit dangerous since the length of the file isn't checked
|
||||
* against the memory to be consumed.
|
||||
*
|
||||
* @param out Pointer to a string where the output data will be stored.
|
||||
* @return True if the read was successful, otherwise false.
|
||||
*/
|
||||
bool_t readString(std::string *out);
|
||||
|
||||
/**
|
||||
* Reads ahead from the current position to a specific needle (character).
|
||||
*
|
||||
* @param buffer Buffer to output read chars to.
|
||||
* @param max Max length of the buffer / amount of chars to read ahead.
|
||||
* @param needle The character (needle) to look for.
|
||||
* @return Amount of chars read, or <= 0 on error.
|
||||
*/
|
||||
size_t readAhead(
|
||||
char *buffer,
|
||||
size_t max,
|
||||
char needle
|
||||
);
|
||||
|
||||
/**
|
||||
* Reads the contents of this file into a given buffer. If buffer is null
|
||||
* then the buffer will be allocated and returned.
|
||||
*
|
||||
* @param buffer Pointer to buffer to read to.
|
||||
* @return The size of the read data.
|
||||
*/
|
||||
size_t readToBuffer(char **buffer);
|
||||
|
||||
/**
|
||||
* Reads the contents of this file into a given buffer.
|
||||
*
|
||||
* @param buffer Pointer to buffer to read to.
|
||||
* @param max Max length of the buffer.
|
||||
* @return Amount of bytes read.
|
||||
*/
|
||||
size_t readRaw(char *buffer, size_t max);
|
||||
|
||||
/**
|
||||
* Writes the entire contents of a string to a file.
|
||||
*
|
||||
* @param in String to write to this file.
|
||||
* @return True if written successfully, otherwise false.
|
||||
*/
|
||||
bool_t writeString(std::string in);
|
||||
|
||||
/**
|
||||
* Write raw bytes to the file.
|
||||
*
|
||||
* @param data Data to write.
|
||||
* @param size Size of the data to write.
|
||||
* @return True if written successfully, otherwise false.
|
||||
*/
|
||||
bool_t writeRaw(char *data, size_t size);
|
||||
|
||||
/**
|
||||
* Write raw bytes to the file from another file.
|
||||
*
|
||||
* @param otherFile Other file to read from.
|
||||
* @param length Length of the data to read.
|
||||
* @return True if written successfully, otherwise false.
|
||||
*/
|
||||
bool_t copyRaw(File *otherFile, size_t length);
|
||||
|
||||
/**
|
||||
* Set the position of the cursor of the file reader.
|
||||
*
|
||||
* @param pos Position to set.
|
||||
*/
|
||||
void setPosition(size_t pos);
|
||||
|
||||
/**
|
||||
* Get the file name of this file, optionally with the extension.
|
||||
*
|
||||
* @param withExtension If true, the extension will be included.
|
||||
* @return The file name.
|
||||
*/
|
||||
std::string getFileName(bool_t withExtension = true);
|
||||
|
||||
/**
|
||||
* Returns the extension of this file.
|
||||
*
|
||||
* @return The extension of this file.
|
||||
*/
|
||||
std::string getExtension();
|
||||
|
||||
/**
|
||||
* Destruct the File manager.
|
||||
*/
|
||||
~File();
|
||||
};
|
||||
}
|
55
archive/dawntools/util/Image.cpp
Normal file
55
archive/dawntools/util/Image.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2021 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "Image.hpp"
|
||||
|
||||
#ifndef STB_IMAGE_IMPLEMENTATION
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
#endif
|
||||
|
||||
#ifndef STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#include <stb_image_resize.h>
|
||||
#endif
|
||||
|
||||
#ifndef STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include <stb_image_write.h>
|
||||
#endif
|
||||
|
||||
void imageCopy(
|
||||
uint8_t *source, int32_t sourceWidth, int32_t sourceHeight,
|
||||
uint8_t *dest, int32_t destWidth, int32_t destHeight,
|
||||
int32_t cropX, int32_t cropY, int32_t cropWidth, int32_t cropHeight,
|
||||
int32_t pasteX, int32_t pasteY,
|
||||
int32_t channels
|
||||
) {
|
||||
int32_t x, y, c;
|
||||
int32_t absX, absY;
|
||||
int32_t sourceIndex, targetIndex;
|
||||
|
||||
if(cropX == -1) cropX = 0;
|
||||
if(cropY == -1) cropY = 0;
|
||||
if(cropWidth == -1) cropWidth = sourceWidth;
|
||||
if(cropHeight == -1) cropHeight = sourceHeight;
|
||||
if(pasteX == -1) pasteX = 0;
|
||||
if(pasteY == -1) pasteY = 0;
|
||||
|
||||
for(x = cropX; x < cropX + cropWidth; x++) {
|
||||
for(y = cropY; y < cropY + cropHeight; y++) {
|
||||
absX = x - cropX + pasteX;
|
||||
absY = y - cropY + pasteY;
|
||||
if(absX >= destWidth || absY >= destHeight || absX < 0 || absY < 0)continue;
|
||||
targetIndex = absY * destWidth + absX;
|
||||
sourceIndex = y * sourceWidth + x;
|
||||
for(c = 0; c < channels; c++) {
|
||||
dest[(targetIndex*channels) + c] = source[(sourceIndex*channels) + c];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
38
archive/dawntools/util/Image.hpp
Normal file
38
archive/dawntools/util/Image.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2021 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "File.hpp"
|
||||
|
||||
#include <stb_image.h>
|
||||
#include <stb_image_resize.h>
|
||||
#include <stb_image_write.h>
|
||||
|
||||
/**
|
||||
* Unused currently.
|
||||
*
|
||||
* @param source
|
||||
* @param sourceWidth
|
||||
* @param sourceHeight
|
||||
* @param dest
|
||||
* @param destWidth
|
||||
* @param destHeight
|
||||
* @param cropX
|
||||
* @param cropY
|
||||
* @param cropWidth
|
||||
* @param cropHeight
|
||||
* @param pasteX
|
||||
* @param pasteY
|
||||
* @param channels
|
||||
*/
|
||||
void imageCopy(
|
||||
uint8_t *source, int32_t sourceWidth, int32_t sourceHeight,
|
||||
uint8_t *dest, int32_t destWidth, int32_t destHeight,
|
||||
int32_t cropX, int32_t cropY, int32_t cropWidth, int32_t cropHeight,
|
||||
int32_t pasteX, int32_t pasteY,
|
||||
int32_t channels
|
||||
);
|
36
archive/dawntools/util/Language.cpp
Normal file
36
archive/dawntools/util/Language.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "Language.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
int32_t languageSaveStrings(
|
||||
std::string languagesDir,
|
||||
std::vector<struct LanguageString> strings
|
||||
) {
|
||||
if(languagesDir.size() <= 0) {
|
||||
std::cout << "Languages dir is not defined" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
File file(languagesDir);
|
||||
if(!file.mkdirp()) {
|
||||
std::cout << "Failed to create languages string output dir " << file.filename << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Now convert to xml
|
||||
std::string buffer;
|
||||
auto it = strings.begin();
|
||||
while(it != strings.end()) {
|
||||
auto s = *it;
|
||||
buffer += s.lang + "|" + s.key + "|" + s.text + "|";
|
||||
++it;
|
||||
}
|
||||
file.writeString(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
26
archive/dawntools/util/Language.hpp
Normal file
26
archive/dawntools/util/Language.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/Xml.hpp"
|
||||
#include "util/File.hpp"
|
||||
|
||||
struct LanguageString {
|
||||
std::string key;
|
||||
std::string lang;
|
||||
std::string text;
|
||||
};
|
||||
|
||||
/**
|
||||
* Shorthand method to save a list of languages to a file.
|
||||
*
|
||||
* @param languagesDir Directory where the language(s) are to be stored.
|
||||
* @param strings List of strings to store.
|
||||
* @return 0 for success, otherwise for failure.
|
||||
*/
|
||||
static int32_t languageSaveStrings(
|
||||
std::string languagesDir,
|
||||
std::vector<struct LanguageString> strings
|
||||
);
|
113
archive/dawntools/util/XmlParser.hpp
Normal file
113
archive/dawntools/util/XmlParser.hpp
Normal file
@ -0,0 +1,113 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/Xml.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
template<typename T>
|
||||
class XmlParser {
|
||||
protected:
|
||||
/**
|
||||
* Get the required attributes for this Xml Node to have.
|
||||
*
|
||||
* @return Vector of strings of required attribute keys.
|
||||
*/
|
||||
virtual std::vector<std::string> getRequiredAttributes() = 0;
|
||||
|
||||
/**
|
||||
* Return optional attributes with defaults for this node to have.
|
||||
*
|
||||
* @return Key-Value Pair of optional attributes and defaults.
|
||||
*/
|
||||
virtual std::map<std::string, std::string> getOptionalAttributes() = 0;
|
||||
|
||||
/**
|
||||
* Callback to be invoked upon successful parse of this node.
|
||||
*
|
||||
* @param node Node that was parsed.
|
||||
* @param values KVP of values from the required and optional attrs.
|
||||
* @param output Templated output of the parse from this method.
|
||||
* @param error Pointer to a string to write-out any errors.
|
||||
* @return Non 0 for error, 0 for success.
|
||||
*/
|
||||
virtual int32_t onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
T *output,
|
||||
std::string *error
|
||||
) = 0;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Common parse method to parse a duration from a value string.
|
||||
*
|
||||
* @param duration Duration string to parse.
|
||||
* @return The parsed duration.
|
||||
*/
|
||||
static std::string parseDuration(std::string duration) {
|
||||
std::string dur = duration;
|
||||
if(dur.find('.') == std::string::npos) dur += ".0";
|
||||
return dur + "f";
|
||||
}
|
||||
|
||||
/**
|
||||
* Common parse method to parse an easing from a value string.
|
||||
*
|
||||
* @param e Easing string to parse.
|
||||
* @return The parsed ease.
|
||||
*/
|
||||
static std::string parseEase(std::string e) {
|
||||
if(e == "out-quad") return "&easeOutQuad";
|
||||
if(e == "linear") return "&easeLinear";
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles parsing of an Xml node.
|
||||
*
|
||||
* @param xml Xml node to parse.
|
||||
* @param output Output struct to put the output data.
|
||||
* @param error Pointer to the string for errors to be stored.
|
||||
* @return 0 for success, otherwise for error.
|
||||
*/
|
||||
int32_t parse(Xml *xml, T *output, std::string *error) {
|
||||
std::map<std::string, std::string> values;
|
||||
|
||||
// First get the required attributes
|
||||
auto required = this->getRequiredAttributes();
|
||||
auto itRequired = required.begin();
|
||||
while(itRequired != required.end()) {
|
||||
auto s = *itRequired;
|
||||
auto attr = xml->attributes.find(s);
|
||||
if(attr == xml->attributes.end()) {
|
||||
std::cout << "Missing required attribute \"" << s << "\" on node \"" << xml->node << "\"" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
values[s] = attr->second;
|
||||
++itRequired;
|
||||
}
|
||||
|
||||
// Now get the optional attributes
|
||||
auto optional = this->getOptionalAttributes();
|
||||
auto itOptional = optional.begin();
|
||||
while(itOptional != optional.end()) {
|
||||
auto key = itOptional->first;
|
||||
auto defaultValue = itOptional->second;
|
||||
|
||||
auto attr = xml->attributes.find(key);
|
||||
if(attr == xml->attributes.end()) {
|
||||
values[key] = defaultValue;
|
||||
} else {
|
||||
values[key] = attr->second;
|
||||
}
|
||||
++itOptional;
|
||||
}
|
||||
|
||||
// Now send to parser
|
||||
return this->onParse(xml, values, output, error);
|
||||
}
|
||||
};
|
||||
}
|
19
archive/dawntools/util/generator/CMakeLists.txt
Normal file
19
archive/dawntools/util/generator/CMakeLists.txt
Normal file
@ -0,0 +1,19 @@
|
||||
# Copyright (c) 2023 Dominic Msters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
set(D ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
set(
|
||||
DAWN_TOOL_SOURCES
|
||||
${DAWN_TOOL_SOURCES}
|
||||
${D}/SceneItemGenerator.cpp
|
||||
${D}/SceneAssetGenerator.cpp
|
||||
${D}/SceneCodeGenerator.cpp
|
||||
${D}/SceneGenerator.cpp
|
||||
${D}/SceneItemComponentGenerator.cpp
|
||||
|
||||
CACHE INTERNAL
|
||||
${DAWN_CACHE_TARGET}
|
||||
)
|
53
archive/dawntools/util/generator/SceneAssetGenerator.cpp
Normal file
53
archive/dawntools/util/generator/SceneAssetGenerator.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "SceneAssetGenerator.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
void SceneAssetGenerator::generate(
|
||||
std::map<std::string, std::string> &assetMap,
|
||||
int32_t &assetNumber,
|
||||
std::vector<std::string> *publicProperties,
|
||||
std::vector<std::string> *initBody,
|
||||
std::vector<std::string> *assetsBody,
|
||||
struct SceneAsset *asset,
|
||||
std::string tabs
|
||||
) {
|
||||
std::string assetType = "";
|
||||
|
||||
bool_t componentInit = true;
|
||||
if(asset->ref.empty()) {
|
||||
asset->usageName = "asset" + std::to_string(assetNumber++);
|
||||
} else {
|
||||
asset->usageName = asset->ref;
|
||||
}
|
||||
|
||||
switch(asset->type) {
|
||||
case SCENE_ASSET_TYPE_TEXTURE:
|
||||
assetType = "TextureAsset";
|
||||
assetMap[asset->fileName] = "&" + asset->usageName + "->texture";
|
||||
assetMap[asset->usageName] = "&" + asset->usageName + "->texture";
|
||||
break;
|
||||
|
||||
case SCENE_ASSET_TYPE_TRUETYPE_FONT:
|
||||
assetType = "TrueTypeAsset";
|
||||
assetMap[asset->fileName] = asset->usageName;
|
||||
assetMap[asset->usageName] = asset->usageName;
|
||||
break;
|
||||
|
||||
default:
|
||||
assertUnreachable("SceneAssetGenerator::generate: Unknown asset type");
|
||||
}
|
||||
|
||||
if(!asset->ref.empty()) {
|
||||
line(publicProperties, assetType + " *" + asset->usageName + " = nullptr;", "");
|
||||
line(initBody, asset->usageName + " = man->get<" + assetType + ">(\"" + asset->fileName + "\");", "");
|
||||
} else {
|
||||
line(initBody, "auto " + asset->usageName + " = man->get<" + assetType + ">(\"" + asset->fileName + "\");", "");
|
||||
}
|
||||
|
||||
line(assetsBody, "assets.push_back(man->get<" + assetType + ">(\"" + asset->fileName + "\"));", "");
|
||||
}
|
23
archive/dawntools/util/generator/SceneAssetGenerator.hpp
Normal file
23
archive/dawntools/util/generator/SceneAssetGenerator.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/parser/SceneAssetParser.hpp"
|
||||
#include "util/CodeGen.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
class SceneAssetGenerator : public CodeGen {
|
||||
public:
|
||||
static void generate(
|
||||
std::map<std::string, std::string> &assetMap,
|
||||
int32_t &assetNumber,
|
||||
std::vector<std::string> *publicProperties,
|
||||
std::vector<std::string> *initBody,
|
||||
std::vector<std::string> *assetsBody,
|
||||
struct SceneAsset *asset,
|
||||
std::string tabs
|
||||
);
|
||||
};
|
||||
}
|
33
archive/dawntools/util/generator/SceneCodeGenerator.cpp
Normal file
33
archive/dawntools/util/generator/SceneCodeGenerator.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "SceneCodeGenerator.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
void SceneCodeGenerator::generate(
|
||||
std::vector<std::string> *publicProperties,
|
||||
std::vector<std::string> *initBody,
|
||||
std::vector<std::string> *includes,
|
||||
struct SceneCode *code,
|
||||
std::string tabs
|
||||
) {
|
||||
switch(code->codeType) {
|
||||
case SCENE_CODE_TYPE_PROPERTIES:
|
||||
line(publicProperties, code->code, "");
|
||||
break;
|
||||
|
||||
case SCENE_CODE_TYPE_INIT:
|
||||
line(initBody, code->code, "");
|
||||
break;
|
||||
|
||||
case SCENE_CODE_TYPE_INCLUDE:
|
||||
line(includes, code->code, "");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
21
archive/dawntools/util/generator/SceneCodeGenerator.hpp
Normal file
21
archive/dawntools/util/generator/SceneCodeGenerator.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/parser/SceneCodeParser.hpp"
|
||||
#include "util/CodeGen.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
class SceneCodeGenerator : public CodeGen {
|
||||
public:
|
||||
static void generate(
|
||||
std::vector<std::string> *publicProperties,
|
||||
std::vector<std::string> *initBody,
|
||||
std::vector<std::string> *includes,
|
||||
struct SceneCode *code,
|
||||
std::string tabs
|
||||
);
|
||||
};
|
||||
}
|
103
archive/dawntools/util/generator/SceneGenerator.cpp
Normal file
103
archive/dawntools/util/generator/SceneGenerator.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "SceneGenerator.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
void SceneGenerator::generate(
|
||||
struct Scene *scene,
|
||||
struct ClassGenInfo &classInfo,
|
||||
struct MethodGenInfo &methodAssets,
|
||||
struct MethodGenInfo &methodInit
|
||||
) {
|
||||
assertNotNull(scene, "SceneGenerator::generate: Scene cannot be null");
|
||||
|
||||
std::map<std::string, std::string> assetMap;
|
||||
int32_t assetNumber = 0;
|
||||
std::string baseClassName = "Scene";
|
||||
|
||||
classInfo.clazz = scene->name;
|
||||
classInfo.constructorArgs = "DawnGame *game";
|
||||
classInfo.extendArgs = "game";
|
||||
|
||||
// Determine extends
|
||||
if(scene->extend.empty()) {
|
||||
classInfo.includes.push_back("scene/Scene.hpp");
|
||||
} else {
|
||||
classInfo.includes.push_back(scene->extend + ".hpp");
|
||||
|
||||
// Get last slash of scene->extend
|
||||
auto lastSlash = scene->extend.find_last_of('/');
|
||||
baseClassName = scene->extend;
|
||||
if(lastSlash != std::string::npos) {
|
||||
baseClassName = scene->extend.substr(lastSlash + 1);
|
||||
}
|
||||
}
|
||||
classInfo.extend = baseClassName;
|
||||
|
||||
methodAssets.name = "getRequiredAssets";
|
||||
methodAssets.isOverride = true;
|
||||
methodAssets.type = "std::vector<Asset*>";
|
||||
line(&methodAssets.body, "auto man = &this->game->assetManager;", "");
|
||||
|
||||
methodInit.name = "stage";
|
||||
methodInit.isOverride = true;
|
||||
|
||||
if(scene->extend.empty()) {
|
||||
line(&methodAssets.body, "std::vector<Asset*> assets;", "");
|
||||
} else {
|
||||
line(&methodAssets.body, "std::vector<Asset*> assets = " + baseClassName + "::getRequiredAssets();", "");
|
||||
line(&methodInit.body, baseClassName + "::stage();", "");
|
||||
}
|
||||
|
||||
// Scene assets
|
||||
line(&methodInit.body, "auto man = &this->game->assetManager;", "");
|
||||
|
||||
auto itAssets = scene->assets.begin();
|
||||
while(itAssets != scene->assets.end()) {
|
||||
SceneAssetGenerator::generate(
|
||||
assetMap,
|
||||
assetNumber,
|
||||
&classInfo.publicProperties,
|
||||
&methodInit.body,
|
||||
&methodAssets.body,
|
||||
&(*itAssets),
|
||||
""
|
||||
);
|
||||
++itAssets;
|
||||
}
|
||||
|
||||
// Generate
|
||||
int32_t childNumber = 0;
|
||||
int32_t componentNumber = 0;
|
||||
std::vector<struct SceneItemComponent> componentsUnused;
|
||||
|
||||
auto itDeps = scene->dependencies.begin();
|
||||
while(itDeps != scene->dependencies.end()) {
|
||||
auto dep = *itDeps;
|
||||
SceneItemGenerator::generateDependency(
|
||||
assetNumber,
|
||||
componentNumber,
|
||||
childNumber,
|
||||
assetMap,
|
||||
classInfo.includes,
|
||||
&classInfo.publicProperties,
|
||||
&methodInit.body,
|
||||
&methodAssets.body,
|
||||
"",
|
||||
"this",
|
||||
componentsUnused,
|
||||
scene->items,
|
||||
scene->code,
|
||||
dep
|
||||
);
|
||||
++itDeps;
|
||||
}
|
||||
|
||||
|
||||
// Seal methods
|
||||
line(&methodAssets.body, "return assets;", "");
|
||||
}
|
21
archive/dawntools/util/generator/SceneGenerator.hpp
Normal file
21
archive/dawntools/util/generator/SceneGenerator.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/parser/SceneParser.hpp"
|
||||
#include "SceneItemGenerator.hpp"
|
||||
#include "util/CodeGen.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
class SceneGenerator : public CodeGen {
|
||||
public:
|
||||
static void generate(
|
||||
struct Scene *scene,
|
||||
struct ClassGenInfo &classInfo,
|
||||
struct MethodGenInfo &methodAssets,
|
||||
struct MethodGenInfo &methodInit
|
||||
);
|
||||
};
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "SceneItemComponentGenerator.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
void SceneItemComponentGenerator::generate(
|
||||
std::map<std::string, std::string> &assetMap,
|
||||
int32_t &componentNumber,
|
||||
std::vector<std::string> &includes,
|
||||
std::string itemRef,
|
||||
std::vector<std::string> *publicProperties,
|
||||
std::vector<std::string> *initBody,
|
||||
struct SceneItemComponent *component,
|
||||
std::string tabs
|
||||
) {
|
||||
auto componentName = "cmp" + std::to_string(componentNumber++);
|
||||
bool_t componentInit = true;
|
||||
if(component->ref.size() > 0) {
|
||||
componentInit = false;
|
||||
componentName = component->ref;
|
||||
line(publicProperties, component->type + " *" + component->ref + " = nullptr;", "");
|
||||
}
|
||||
|
||||
// Initialize
|
||||
line(initBody, (componentInit ? "auto " : "") + componentName + " = " + itemRef + "->addComponent<" + component->type + ">();", "");
|
||||
|
||||
// Now set each property
|
||||
auto itValues = component->values.begin();
|
||||
while(itValues != component->values.end()) {
|
||||
auto value = itValues->second;
|
||||
if(assetMap.find(value) != assetMap.end()) {
|
||||
value = assetMap[value];
|
||||
}
|
||||
line(initBody, componentName + "->" + itValues->first + " = " + value + ";", "");
|
||||
++itValues;
|
||||
}
|
||||
|
||||
includes.push_back(component->include);
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/parser/SceneItemComponentParser.hpp"
|
||||
#include "util/CodeGen.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
class SceneItemComponentGenerator : public CodeGen {
|
||||
public:
|
||||
static void generate(
|
||||
std::map<std::string, std::string> &assetMap,
|
||||
int32_t &componentNumber,
|
||||
std::vector<std::string> &includes,
|
||||
std::string itemRef,
|
||||
std::vector<std::string> *publicProperties,
|
||||
std::vector<std::string> *initBody,
|
||||
struct SceneItemComponent *component,
|
||||
std::string tabs
|
||||
);
|
||||
};
|
||||
}
|
213
archive/dawntools/util/generator/SceneItemGenerator.cpp
Normal file
213
archive/dawntools/util/generator/SceneItemGenerator.cpp
Normal file
@ -0,0 +1,213 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "SceneItemGenerator.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
void SceneItemGenerator::generateDependency(
|
||||
int32_t &assetNumber,
|
||||
int32_t &componentNumber,
|
||||
int32_t &childNumber,
|
||||
std::map<std::string, std::string> &assetMap,
|
||||
std::vector<std::string> &includes,
|
||||
std::vector<std::string> *publicProperties,
|
||||
std::vector<std::string> *initBody,
|
||||
std::vector<std::string> *assetBody,
|
||||
std::string name,
|
||||
std::string sceneRef,
|
||||
std::vector<struct SceneItemComponent> &components,
|
||||
std::vector<struct SceneItem> &children,
|
||||
std::vector<struct SceneCode> &code,
|
||||
struct SceneItemDependency dep
|
||||
) {
|
||||
switch(dep.type) {
|
||||
case SCENE_ITEM_DEPENDENCY_TYPE_CODE: {
|
||||
auto i = &code[dep.position];
|
||||
SceneCodeGenerator::generate(
|
||||
publicProperties,
|
||||
initBody,
|
||||
&includes,
|
||||
i,
|
||||
""
|
||||
);
|
||||
line(initBody, "", "");
|
||||
break;
|
||||
}
|
||||
|
||||
case SCENE_ITEM_DEPENDENCY_TYPE_COMPONENT: {
|
||||
auto i = &components[dep.position];
|
||||
SceneItemComponentGenerator::generate(
|
||||
assetMap,
|
||||
componentNumber,
|
||||
includes,
|
||||
name,
|
||||
publicProperties,
|
||||
initBody,
|
||||
i,
|
||||
""
|
||||
);
|
||||
line(initBody, "", "");
|
||||
break;
|
||||
}
|
||||
|
||||
case SCENE_ITEM_DEPENDENCY_TYPE_ITEM: {
|
||||
auto i = &children[dep.position];
|
||||
SceneItemGenerator::generate(
|
||||
assetNumber,
|
||||
componentNumber,
|
||||
childNumber,
|
||||
assetMap,
|
||||
includes,
|
||||
publicProperties,
|
||||
initBody,
|
||||
assetBody,
|
||||
name,
|
||||
sceneRef,
|
||||
i,
|
||||
""
|
||||
);
|
||||
line(initBody, "", "");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assertUnreachable("SceneItemGenerator::generateDependency: Unknown dependency type");
|
||||
}
|
||||
}
|
||||
|
||||
void SceneItemGenerator::generate(
|
||||
int32_t &assetNumber,
|
||||
int32_t &componentNumber,
|
||||
int32_t &childNumber,
|
||||
std::map<std::string, std::string> &assetMap,
|
||||
std::vector<std::string> &includes,
|
||||
std::vector<std::string> *publicProperties,
|
||||
std::vector<std::string> *initBody,
|
||||
std::vector<std::string> *assetBody,
|
||||
std::string parentRef,
|
||||
std::string sceneRef,
|
||||
struct SceneItem *item,
|
||||
std::string tabs
|
||||
) {
|
||||
assertNotNull(publicProperties, "SceneItemGenerator::generate: publicProperties cannot be null");
|
||||
assertNotNull(initBody, "SceneItemGenerator::generate: initBody cannot be null");
|
||||
assertNotNull(assetBody, "SceneItemGenerator::generate: assetBody cannot be null");
|
||||
assertNotNull(item, "SceneItemGenerator::generate: item cannot be null");
|
||||
|
||||
// Determine interface
|
||||
std::string name = "itm" + std::to_string(childNumber++);
|
||||
std::string itemType = "SceneItem";
|
||||
|
||||
if(item->ref == "this") {
|
||||
name = item->ref;
|
||||
} else {
|
||||
// Determine name
|
||||
if(!item->ref.empty()) name = item->ref;
|
||||
|
||||
// Initialize, either prefab or created.
|
||||
if(!item->prefab.empty()) {
|
||||
// Determine prefab name, type and include
|
||||
std::string prefabName = item->prefab;
|
||||
if(prefabName.find("/") != std::string::npos) {
|
||||
prefabName = prefabName.substr(prefabName.find_last_of("/") + 1);
|
||||
}
|
||||
itemType = prefabName;
|
||||
|
||||
// Create prefab
|
||||
includes.push_back(item->prefab + ".hpp");
|
||||
line(initBody, (item->ref.empty() ? "auto " : "") + name + " = " + prefabName + "::create(" + sceneRef + ");", "");
|
||||
line(assetBody, "vectorAppend(&assets, " + prefabName + "::getRequiredAssets(man));", "");
|
||||
} else {
|
||||
// Not a prefab, init empty child.
|
||||
line(initBody, (item->ref.empty() ? "auto " : "") + name + " = " + sceneRef + "->createSceneItem();", "");
|
||||
}
|
||||
|
||||
// Property/Ref defintion
|
||||
if(!item->ref.empty() && item->ref != "this") {
|
||||
line(publicProperties, itemType + " *" + name + " = nullptr;", "");
|
||||
}
|
||||
}
|
||||
|
||||
// Process extra properties
|
||||
if(item->position.size() > 0) {
|
||||
line(initBody, name + "->transform.setLocalPosition(" + item->position + ");", "");
|
||||
}
|
||||
|
||||
if(item->alignment.size() > 0) {
|
||||
line(initBody, name + "->uiItem->alignment = " + item->alignment + ";", "");
|
||||
}
|
||||
|
||||
if(item->alignX.size() > 0) {
|
||||
line(initBody, name + "->uiItem->alignX = " + item->alignX + ";", "");
|
||||
}
|
||||
|
||||
if(item->alignY.size() > 0) {
|
||||
line(initBody, name + "->uiItem->alignY = " + item->alignY + ";", "");
|
||||
}
|
||||
|
||||
if(item->menuX.size() > 0) {
|
||||
line(initBody, name + "->menuItem->menuX = " + item->menuX + ";", "");
|
||||
}
|
||||
|
||||
if(item->menuY.size() > 0) {
|
||||
line(initBody, name + "->menuItem->menuY = " + item->menuY + ";", "");
|
||||
}
|
||||
|
||||
if(item->scale.size() > 0) {
|
||||
line(initBody, name + "->transform.setLocalScale(" + item->scale + ");", "");
|
||||
}
|
||||
|
||||
if(item->lookAtPosition.size() > 0) {
|
||||
line(initBody, name + "->transform.lookAt(" + item->lookAtPosition + ", " + item->lookAtTarget + ");", "");
|
||||
}
|
||||
|
||||
if(!item->label.empty()) {
|
||||
line(initBody, name + "->label->text = " + item->label + ";", "");
|
||||
}
|
||||
|
||||
// Add assets
|
||||
auto itAssets = item->assets.begin();
|
||||
while(itAssets != item->assets.end()) {
|
||||
SceneAssetGenerator::generate(
|
||||
assetMap,
|
||||
assetNumber,
|
||||
publicProperties,
|
||||
initBody,
|
||||
assetBody,
|
||||
&(*itAssets),
|
||||
""
|
||||
);
|
||||
++itAssets;
|
||||
}
|
||||
|
||||
// Add the dependencies
|
||||
auto itDeps = item->dependencies.begin();
|
||||
while(itDeps != item->dependencies.end()) {
|
||||
auto dep = *itDeps;
|
||||
SceneItemGenerator::generateDependency(
|
||||
assetNumber,
|
||||
componentNumber,
|
||||
childNumber,
|
||||
assetMap,
|
||||
includes,
|
||||
publicProperties,
|
||||
initBody,
|
||||
assetBody,
|
||||
name,
|
||||
sceneRef,
|
||||
item->components,
|
||||
item->children,
|
||||
item->code,
|
||||
dep
|
||||
);
|
||||
++itDeps;
|
||||
}
|
||||
|
||||
// Set parent
|
||||
if(!parentRef.empty()) {
|
||||
line(initBody, name + "->transform.setParent(&"+parentRef+"->transform);", "");
|
||||
}
|
||||
}
|
47
archive/dawntools/util/generator/SceneItemGenerator.hpp
Normal file
47
archive/dawntools/util/generator/SceneItemGenerator.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "SceneItemComponentGenerator.hpp"
|
||||
#include "SceneAssetGenerator.hpp"
|
||||
#include "util/parser/SceneItemParser.hpp"
|
||||
#include "util/generator/SceneCodeGenerator.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
class SceneItemGenerator : public CodeGen {
|
||||
public:
|
||||
static void generateDependency(
|
||||
int32_t &assetNumber,
|
||||
int32_t &componentNumber,
|
||||
int32_t &childNumber,
|
||||
std::map<std::string, std::string> &assetMap,
|
||||
std::vector<std::string> &includes,
|
||||
std::vector<std::string> *publicProperties,
|
||||
std::vector<std::string> *initBody,
|
||||
std::vector<std::string> *assetBody,
|
||||
std::string name,
|
||||
std::string sceneRef,
|
||||
std::vector<struct SceneItemComponent> &components,
|
||||
std::vector<struct SceneItem> &children,
|
||||
std::vector<struct SceneCode> &code,
|
||||
struct SceneItemDependency dep
|
||||
);
|
||||
|
||||
static void generate(
|
||||
int32_t &assetNumber,
|
||||
int32_t &componentNumber,
|
||||
int32_t &childNumber,
|
||||
std::map<std::string, std::string> &assetMap,
|
||||
std::vector<std::string> &includes,
|
||||
std::vector<std::string> *publicProperties,
|
||||
std::vector<std::string> *initBody,
|
||||
std::vector<std::string> *assetBody,
|
||||
std::string parentRef,
|
||||
std::string sceneRef,
|
||||
struct SceneItem *item,
|
||||
std::string tabs
|
||||
);
|
||||
};
|
||||
}
|
20
archive/dawntools/util/parser/CMakeLists.txt
Normal file
20
archive/dawntools/util/parser/CMakeLists.txt
Normal file
@ -0,0 +1,20 @@
|
||||
# Copyright (c) 2023 Dominic Msters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
set(D ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
set(
|
||||
DAWN_TOOL_SOURCES
|
||||
${DAWN_TOOL_SOURCES}
|
||||
${D}/SceneParser.cpp
|
||||
${D}/SceneItemParser.cpp
|
||||
${D}/SceneAssetParser.cpp
|
||||
${D}/SceneCodeParser.cpp
|
||||
${D}/SceneItemComponentParser.cpp
|
||||
${D}/SceneItemComponentRegistry.cpp
|
||||
|
||||
CACHE INTERNAL
|
||||
${DAWN_CACHE_TARGET}
|
||||
)
|
40
archive/dawntools/util/parser/SceneAssetParser.cpp
Normal file
40
archive/dawntools/util/parser/SceneAssetParser.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "SceneAssetParser.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
std::vector<std::string> SceneAssetParser::getRequiredAttributes() {
|
||||
return { "type", "name" };
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> SceneAssetParser::getOptionalAttributes() {
|
||||
return {
|
||||
{ "ref", "" }
|
||||
};
|
||||
}
|
||||
|
||||
int32_t SceneAssetParser::onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct SceneAsset *out,
|
||||
std::string *error
|
||||
) {
|
||||
out->fileName = values["name"];
|
||||
|
||||
if(values["type"] == "texture") {
|
||||
out->type = SCENE_ASSET_TYPE_TEXTURE;
|
||||
} else if(values["type"] == "truetype") {
|
||||
out->type = SCENE_ASSET_TYPE_TRUETYPE_FONT;
|
||||
} else {
|
||||
*error = "Unknown asset type '" + values["type"] + "'";
|
||||
return 1;
|
||||
}
|
||||
|
||||
out->ref = values["ref"];
|
||||
|
||||
return 0;
|
||||
}
|
34
archive/dawntools/util/parser/SceneAssetParser.hpp
Normal file
34
archive/dawntools/util/parser/SceneAssetParser.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/XmlParser.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
enum SceneAssetType {
|
||||
SCENE_ASSET_TYPE_TEXTURE,
|
||||
SCENE_ASSET_TYPE_TRUETYPE_FONT
|
||||
};
|
||||
|
||||
struct SceneAsset {
|
||||
SceneAssetType type;
|
||||
std::string fileName;
|
||||
std::string usageName;
|
||||
std::string ref;
|
||||
};
|
||||
|
||||
class SceneAssetParser : public XmlParser<SceneAsset> {
|
||||
public:
|
||||
virtual std::vector<std::string> getRequiredAttributes();
|
||||
virtual std::map<std::string, std::string> getOptionalAttributes();
|
||||
|
||||
virtual int32_t onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct SceneAsset *out,
|
||||
std::string *error
|
||||
);
|
||||
};
|
||||
}
|
41
archive/dawntools/util/parser/SceneCodeParser.cpp
Normal file
41
archive/dawntools/util/parser/SceneCodeParser.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "SceneCodeParser.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
std::vector<std::string> SceneCodeParser::getRequiredAttributes() {
|
||||
return { "type" };
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> SceneCodeParser::getOptionalAttributes() {
|
||||
return {};
|
||||
}
|
||||
|
||||
int32_t SceneCodeParser::onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct SceneCode *out,
|
||||
std::string *error
|
||||
) {
|
||||
// Get the type
|
||||
std::string type = values["type"];
|
||||
if(type == "properties") {
|
||||
out->codeType = SCENE_CODE_TYPE_PROPERTIES;
|
||||
} else if(type == "init") {
|
||||
out->codeType = SCENE_CODE_TYPE_INIT;
|
||||
} else if(type == "include") {
|
||||
out->codeType = SCENE_CODE_TYPE_INCLUDE;
|
||||
} else {
|
||||
*error = "Invalid type '" + type + "' for SceneCode.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get the code
|
||||
out->code = node->textContent;
|
||||
|
||||
return 0;
|
||||
}
|
33
archive/dawntools/util/parser/SceneCodeParser.hpp
Normal file
33
archive/dawntools/util/parser/SceneCodeParser.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/XmlParser.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
enum SceneCodeType {
|
||||
SCENE_CODE_TYPE_PROPERTIES,
|
||||
SCENE_CODE_TYPE_INIT,
|
||||
SCENE_CODE_TYPE_INCLUDE
|
||||
};
|
||||
|
||||
struct SceneCode {
|
||||
enum SceneCodeType codeType;
|
||||
std::string code;
|
||||
};
|
||||
|
||||
class SceneCodeParser : public XmlParser<struct SceneCode> {
|
||||
public:
|
||||
virtual std::vector<std::string> getRequiredAttributes();
|
||||
virtual std::map<std::string, std::string> getOptionalAttributes();
|
||||
|
||||
virtual int32_t onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct SceneCode *out,
|
||||
std::string *error
|
||||
);
|
||||
};
|
||||
}
|
80
archive/dawntools/util/parser/SceneItemComponentParser.cpp
Normal file
80
archive/dawntools/util/parser/SceneItemComponentParser.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "SceneItemComponentParser.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
std::vector<std::string> SceneItemComponentParser::getRequiredAttributes() {
|
||||
return { };
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> SceneItemComponentParser::getOptionalAttributes() {
|
||||
return { { "ref", "" } };
|
||||
}
|
||||
|
||||
int32_t SceneItemComponentParser::onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct SceneItemComponent *out,
|
||||
std::string *error
|
||||
) {
|
||||
// Check if values contains key "ref" and has a string of size more than 0
|
||||
if(values.find("ref") != values.end() && values["ref"].size() > 0) {
|
||||
out->ref = values["ref"];
|
||||
}
|
||||
|
||||
// Get the ruleset.
|
||||
auto ruleset = out->registry->getRuleset(node->node);
|
||||
if(ruleset.name.size() == 0) {
|
||||
*error = "Unknown prefab node type: " + node->node;
|
||||
return 1;
|
||||
}
|
||||
|
||||
out->include = ruleset.include;
|
||||
out->type = node->node;
|
||||
|
||||
// Define parser types here.
|
||||
|
||||
// Iterate all the optional attributes and store within the out if present
|
||||
auto itOptional = ruleset.optional.begin();
|
||||
while(itOptional != ruleset.optional.end()) {
|
||||
// Determine the parser to use
|
||||
auto name = itOptional->first;
|
||||
auto type = itOptional->second;
|
||||
|
||||
std::function<std::string(std::string, std::string*)> parser = rawParser;
|
||||
try {
|
||||
parser = parserFromTypeName(type);
|
||||
} catch(std::string err) {
|
||||
if(name[0] == '*') {
|
||||
name = name.substr(1, name.size());
|
||||
parser = rawParser;
|
||||
} else {
|
||||
*error = "Unknown parser for type: " + type + "::" + name;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(node->attributes.find(name) != node->attributes.end()) {
|
||||
auto raw = node->attributes[name];
|
||||
out->values[name] = parser(raw, error);
|
||||
if(error->size() != 0) return 1;
|
||||
}
|
||||
++itOptional;
|
||||
}
|
||||
|
||||
auto itInnerXml = ruleset.innerXml.begin();
|
||||
while(itInnerXml != ruleset.innerXml.end()) {
|
||||
auto name = itInnerXml->first;
|
||||
auto type = itInnerXml->second;
|
||||
|
||||
out->values[name] = stringParser(node->innerXml, error);
|
||||
if(error->size() != 0) return 1;
|
||||
++itInnerXml;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
30
archive/dawntools/util/parser/SceneItemComponentParser.hpp
Normal file
30
archive/dawntools/util/parser/SceneItemComponentParser.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/parser/SceneItemComponentRegistry.hpp"
|
||||
#include "util/parser/TypeParsers.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct SceneItemComponent {
|
||||
struct SceneItemComponentRegistry *registry;
|
||||
std::string include;
|
||||
std::string type;
|
||||
std::map<std::string, std::string> values;
|
||||
std::string ref;
|
||||
};
|
||||
|
||||
class SceneItemComponentParser : public XmlParser<struct SceneItemComponent> {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredAttributes() override;
|
||||
std::map<std::string, std::string> getOptionalAttributes() override;
|
||||
int32_t onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct SceneItemComponent *out,
|
||||
std::string *error
|
||||
) override;
|
||||
};
|
||||
}
|
203
archive/dawntools/util/parser/SceneItemComponentRegistry.cpp
Normal file
203
archive/dawntools/util/parser/SceneItemComponentRegistry.cpp
Normal file
@ -0,0 +1,203 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "SceneItemComponentRegistry.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
struct SceneItemComponentRuleset SceneItemComponentRegistry::parseFile(
|
||||
File *file,
|
||||
std::string clazz
|
||||
) {
|
||||
assertNotNull(file, "SceneItemCOmponentRegistry::parseFile: File is null");
|
||||
|
||||
std::string data;
|
||||
if(!file->readString(&data)) {
|
||||
std::cout << "Failed to read ruleset file!" << std::endl;
|
||||
return { .name = "" };
|
||||
}
|
||||
|
||||
// Begin scanning contentsr
|
||||
// std::string include = this->sources;
|
||||
auto toRemove = File::normalizeSlashes(this->sources + FILE_PATH_SEP);
|
||||
auto includePath = file->filename.substr(toRemove.size(), file->filename.size() - toRemove.size());
|
||||
|
||||
// Now locate the first subdir since we don't want to include the root path (e.g. dawn, dawnrose, etc)
|
||||
auto firstSlash = includePath.find(FILE_PATH_SEP);
|
||||
if(firstSlash != std::string::npos) {
|
||||
includePath = includePath.substr(firstSlash + 1, includePath.size() - firstSlash - 1);
|
||||
}
|
||||
|
||||
struct SceneItemComponentRuleset ruleset;
|
||||
// Replace all file seps with slashes
|
||||
size_t pos = 0;
|
||||
while ((pos = includePath.find(FILE_PATH_SEP, pos)) != std::string::npos) {
|
||||
includePath.replace(pos, 1, "/");
|
||||
pos += 1;
|
||||
}
|
||||
ruleset.include = includePath;
|
||||
ruleset.name = clazz;
|
||||
|
||||
std::regex_constants::syntax_option_type regexFlags;
|
||||
#if defined(__GNUC__)
|
||||
regexFlags = std::regex_constants::ECMAScript | std::regex_constants::multiline;
|
||||
#else
|
||||
regexFlags = std::regex_constants::ECMAScript;
|
||||
#endif
|
||||
|
||||
// First, let's look for what class(es) this class extends
|
||||
std::regex regexClassName("class\\s+\\w+\\s+:\\s+", regexFlags);
|
||||
std::smatch match;
|
||||
if(std::regex_search(data, match, regexClassName)) {
|
||||
// Now find the next "{"
|
||||
auto matchStart = match.position() + match.length();
|
||||
auto openBracePos = data.find("{", matchStart);
|
||||
if(openBracePos == std::string::npos) {
|
||||
std::cout << "Failed to find open brace for class!" << std::endl;
|
||||
return { .name = "" };
|
||||
}
|
||||
|
||||
// Match each of the class names
|
||||
std::regex regexClass("(public\\s+(\\w+))[,\\s{]+", regexFlags);
|
||||
std::sregex_iterator itClass(data.begin() + matchStart, data.begin() + openBracePos, regexClass);
|
||||
std::sregex_iterator endClass;
|
||||
while(itClass != endClass) {
|
||||
// Get the class name
|
||||
auto className = itClass->str(2);
|
||||
itClass++;
|
||||
|
||||
// We don't parse interface classes
|
||||
if(className[0] == 'I') continue;
|
||||
ruleset.extends.push_back(className);
|
||||
}
|
||||
}
|
||||
|
||||
// Find each instance of "@optional" when it's used within a comment
|
||||
// e.g. // @optional or /* @optional */ in the string data.1
|
||||
std::regex regex("^\\s*(?:\\/\\/|\\/\\*){1}\\s*\\@(optional|innerXml)\\s*(?:\\*\\/)?\\s*$", regexFlags);
|
||||
std::sregex_iterator it(data.begin(), data.end(), regex);
|
||||
std::sregex_iterator end;
|
||||
while(it != end) {
|
||||
// Extract the kind of parameter this is
|
||||
std::smatch match;
|
||||
if(!std::regex_search(data, match, regex)) {
|
||||
std::cout << "Failed to determine parameter type!" << std::endl;
|
||||
return { .name = "" };
|
||||
}
|
||||
|
||||
std::string paramType = match[1].str();
|
||||
|
||||
// Find the next ";"
|
||||
auto endPos = data.find(";", it->position() + it->length());
|
||||
if(endPos == std::string::npos) {
|
||||
std::cout << "Failed to find end of line for attribute!" << std::endl;
|
||||
return { .name = "" };
|
||||
}
|
||||
|
||||
// Go backwards see if there's an equals sign after the match but before endPos
|
||||
auto equalsPos = data.rfind("=", endPos);
|
||||
|
||||
// If there's an equals sign, we search backwards from there,
|
||||
// otherwise we search backwards from the ;
|
||||
auto varStart = it->position() + it->length() + 1;
|
||||
size_t lastSearchPos = (
|
||||
(equalsPos == std::string::npos || equalsPos <= varStart) ?
|
||||
endPos :
|
||||
equalsPos
|
||||
);
|
||||
|
||||
// Now we have our string
|
||||
auto varLength = lastSearchPos - varStart;
|
||||
auto variableString = data.substr(varStart, varLength);
|
||||
|
||||
// Now (should) be able to extract the type;
|
||||
std::regex regex2("^\\s*(?:[\\S]+<)?([\\w*:_\\s]+)(?:[\\S]+)? (\\**[\\w]+)\\s*$", regexFlags);
|
||||
std::smatch match2;
|
||||
if(!std::regex_search(variableString, match2, regex2)) {
|
||||
std::cout << "Failed to extract type and name from variable string! " << variableString << std::endl;
|
||||
return { .name = "" };
|
||||
}
|
||||
|
||||
// Now we have our type and name
|
||||
auto type = match2[1].str();
|
||||
auto name = match2[2].str();
|
||||
|
||||
// Now store depending on the type
|
||||
if(paramType == "optional") {
|
||||
ruleset.selfOptional[name] = type;
|
||||
} else if(paramType == "innerXml") {
|
||||
ruleset.innerXml[name] = type;
|
||||
} else {
|
||||
assertUnreachable("SceneItemComponentRegistry::parseFile: Unknown parameter type");
|
||||
}
|
||||
++it;
|
||||
}
|
||||
return ruleset;
|
||||
}
|
||||
|
||||
struct SceneItemComponentRuleset SceneItemComponentRegistry::getRuleset(std::string type) {
|
||||
if(this->rulesets.find(type) != this->rulesets.end()) {
|
||||
return this->rulesets[type];
|
||||
}
|
||||
|
||||
std::vector<std::string> pathsToScan;
|
||||
pathsToScan.push_back(this->sources);
|
||||
|
||||
auto it = pathsToScan.begin();
|
||||
while(it != pathsToScan.end()) {
|
||||
auto str = *it;
|
||||
pathsToScan.erase(it);
|
||||
|
||||
Directory dir = Directory(str);
|
||||
auto children = dir.readDirectory();
|
||||
|
||||
auto itChildren = children.begin();
|
||||
while(itChildren != children.end()) {
|
||||
if(itChildren->second == DIRECTORY_CHILD_TYPE_DIRECTORY) {
|
||||
pathsToScan.push_back(str + "/" + itChildren->first);
|
||||
++itChildren;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(itChildren->first != type+".hpp") {
|
||||
++itChildren;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Load ruleset
|
||||
File file(str + "/" + itChildren->first);
|
||||
auto parsed = SceneItemComponentRegistry::parseFile(&file, type);
|
||||
if(parsed.name == "") {
|
||||
std::cout << "Parsing error occured on " << type << std::endl;
|
||||
return parsed;
|
||||
}
|
||||
|
||||
// Update optionals
|
||||
parsed.optional.insert(parsed.selfOptional.begin(), parsed.selfOptional.end());
|
||||
|
||||
// Recursively parse children
|
||||
auto itExtends = parsed.extends.begin();
|
||||
while(itExtends != parsed.extends.end()) {
|
||||
auto ruleset = this->getRuleset(*itExtends);
|
||||
if(ruleset.name == "") {
|
||||
++itExtends;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Merge ruleset
|
||||
parsed.optional.insert(ruleset.optional.begin(), ruleset.optional.end());
|
||||
++itExtends;
|
||||
}
|
||||
|
||||
this->rulesets[type] = parsed;
|
||||
return parsed;
|
||||
}
|
||||
|
||||
it = pathsToScan.begin();
|
||||
};
|
||||
|
||||
return { .name = "" };
|
||||
}
|
41
archive/dawntools/util/parser/SceneItemComponentRegistry.hpp
Normal file
41
archive/dawntools/util/parser/SceneItemComponentRegistry.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/DawnTool.hpp"
|
||||
#include "util/Directory.hpp"
|
||||
#include "util/XmlParser.hpp"
|
||||
#include "util/CodeGen.hpp"
|
||||
#include "util/string.hpp"
|
||||
#include <regex>
|
||||
|
||||
namespace Dawn {
|
||||
struct SceneItemComponentRuleset {
|
||||
std::string name;
|
||||
std::string include;
|
||||
std::map<std::string, std::string> selfOptional;
|
||||
std::map<std::string, std::string> innerXml;
|
||||
std::map<std::string, std::string> optional;
|
||||
std::vector<std::string> extends;
|
||||
};
|
||||
|
||||
struct SceneItemComponentRegistry {
|
||||
std::string sources;
|
||||
std::map<std::string, struct SceneItemComponentRuleset> rulesets;
|
||||
|
||||
struct SceneItemComponentRuleset parseFile(
|
||||
File *file,
|
||||
std::string clazz
|
||||
);
|
||||
|
||||
/**
|
||||
* Gets a prefab component ruleset for a specific scene item component type.
|
||||
*
|
||||
* @param type Scene Item Component Type to get ruleset for.
|
||||
* @return The found ruleset, or an empty ruleset if not found.
|
||||
*/
|
||||
struct SceneItemComponentRuleset getRuleset(std::string type);
|
||||
};
|
||||
}
|
152
archive/dawntools/util/parser/SceneItemParser.cpp
Normal file
152
archive/dawntools/util/parser/SceneItemParser.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "SceneItemParser.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
std::vector<std::string> SceneItemParser::getRequiredAttributes() {
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> SceneItemParser::getOptionalAttributes() {
|
||||
return {
|
||||
{ "ref", "" },
|
||||
{ "position", "" },
|
||||
{ "lookAt", "" },
|
||||
{ "scale", "" },
|
||||
{ "prefab", "" },
|
||||
{ "alignment", "" },
|
||||
{ "alignX", "" },
|
||||
{ "aignY", "" },
|
||||
{ "menuX", "" },
|
||||
{ "menuY", "" },
|
||||
{ "label", "" }
|
||||
};
|
||||
}
|
||||
|
||||
int32_t SceneItemParser::onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct SceneItem *out,
|
||||
std::string *error
|
||||
) {
|
||||
out->ref = values["ref"];
|
||||
|
||||
if(values["position"].size() > 0) {
|
||||
out->position = vec3Parser(values["position"], error);
|
||||
if(error->size() > 0) return 1;
|
||||
}
|
||||
|
||||
if(values["alignment"].size() > 0) {
|
||||
out->alignment = vec4Parser(values["alignment"], error);
|
||||
if(error->size() > 0) return 1;
|
||||
}
|
||||
|
||||
if(values["alignX"].size() > 0) {
|
||||
out->alignX = uiComponentAlignParser(values["alignX"], error);
|
||||
if(error->size() > 0) return 1;
|
||||
}
|
||||
|
||||
if(values["alignY"].size() > 0) {
|
||||
out->alignY = uiComponentAlignParser(values["alignY"], error);
|
||||
if(error->size() > 0) return 1;
|
||||
}
|
||||
|
||||
if(values["menuX"].size() > 0) {
|
||||
out->menuX = intParser(values["menuX"], error);
|
||||
if(error->size() > 0) return 1;
|
||||
}
|
||||
|
||||
if(values["menuY"].size() > 0) {
|
||||
out->menuY = intParser(values["menuY"], error);
|
||||
if(error->size() > 0) return 1;
|
||||
}
|
||||
|
||||
if(values["scale"].size() > 0) {
|
||||
out->scale = vec3Parser(values["scale"], error);
|
||||
if(error->size() > 0) return 1;
|
||||
}
|
||||
|
||||
if(values["label"].size() > 0) {
|
||||
out->label = stringParser(values["label"], error);
|
||||
if(error->size() > 0) return 1;
|
||||
}
|
||||
|
||||
if(values["lookAt"].size() > 0) {
|
||||
auto lookAtSplit = stringSplit(values["lookAt"], ",");
|
||||
if(lookAtSplit.size() != 6) {
|
||||
*error = "Invalid lookAt value: " + values["lookAt"];
|
||||
return 1;
|
||||
}
|
||||
|
||||
out->lookAtPosition = vec3Parser(lookAtSplit[0] + "," + lookAtSplit[1] + "," + lookAtSplit[2], error);
|
||||
if(error->size() > 0) return 1;
|
||||
out->lookAtTarget = vec3Parser(lookAtSplit[3] + "," + lookAtSplit[4] + "," + lookAtSplit[5], error);
|
||||
if(error->size() > 0) return 1;
|
||||
}
|
||||
|
||||
out->prefab = values["prefab"];
|
||||
|
||||
struct SceneItemDependency dep;
|
||||
|
||||
auto itChildren = node->childNodes.begin();
|
||||
while(itChildren != node->childNodes.end()) {
|
||||
if(itChildren->nodeType != XML_NODE_TYPE_ELEMENT) {
|
||||
++itChildren;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parse child nodes, they may be components or not
|
||||
auto c = itChildren->child;
|
||||
|
||||
if(c->node == "child" || c->node == "item") {
|
||||
struct SceneItem child;
|
||||
child.registry = out->registry;
|
||||
auto ret = (SceneItemParser()).parse(c, &child, error);
|
||||
if(ret != 0) return ret;
|
||||
out->children.push_back(child);
|
||||
|
||||
// Add a dependency. This solves the reference order problem.
|
||||
struct SceneItemDependency dep;
|
||||
dep.type = SCENE_ITEM_DEPENDENCY_TYPE_ITEM;
|
||||
dep.position = out->children.size() - 1;
|
||||
out->dependencies.push_back(dep);
|
||||
|
||||
} else if(c->node == "asset") {
|
||||
struct SceneAsset asset;
|
||||
auto ret = (SceneAssetParser()).parse(c, &asset, error);
|
||||
if(ret != 0) return ret;
|
||||
out->assets.push_back(asset);
|
||||
|
||||
} else if(c->node == "code") {
|
||||
struct SceneCode code;
|
||||
auto ret = (SceneCodeParser()).parse(c, &code, error);
|
||||
if(ret != 0) return ret;
|
||||
out->code.push_back(code);
|
||||
|
||||
// Add Dep
|
||||
dep.type = SCENE_ITEM_DEPENDENCY_TYPE_CODE;
|
||||
dep.position = out->code.size() - 1;
|
||||
out->dependencies.push_back(dep);
|
||||
|
||||
} else {
|
||||
struct SceneItemComponent component;
|
||||
component.registry = out->registry;
|
||||
auto ret = (SceneItemComponentParser()).parse(c, &component, error);
|
||||
if(ret != 0) return ret;
|
||||
out->components.push_back(component);
|
||||
|
||||
// Add dep
|
||||
struct SceneItemDependency dep;
|
||||
dep.type = SCENE_ITEM_DEPENDENCY_TYPE_COMPONENT;
|
||||
dep.position = out->components.size() - 1;
|
||||
out->dependencies.push_back(dep);
|
||||
}
|
||||
++itChildren;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
55
archive/dawntools/util/parser/SceneItemParser.hpp
Normal file
55
archive/dawntools/util/parser/SceneItemParser.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/parser/SceneItemComponentParser.hpp"
|
||||
#include "util/parser/SceneAssetParser.hpp"
|
||||
#include "util/parser/SceneCodeParser.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
enum SceneItemDependencyType {
|
||||
SCENE_ITEM_DEPENDENCY_TYPE_ITEM,
|
||||
SCENE_ITEM_DEPENDENCY_TYPE_COMPONENT,
|
||||
SCENE_ITEM_DEPENDENCY_TYPE_CODE,
|
||||
};
|
||||
|
||||
struct SceneItemDependency {
|
||||
enum SceneItemDependencyType type;
|
||||
size_t position;
|
||||
};
|
||||
|
||||
struct SceneItem {
|
||||
struct SceneItemComponentRegistry *registry;
|
||||
std::string ref;
|
||||
std::string position;
|
||||
std::string alignment;
|
||||
std::string alignX;
|
||||
std::string alignY;
|
||||
std::string lookAtPosition;
|
||||
std::string lookAtTarget;
|
||||
std::string scale;
|
||||
std::string prefab;
|
||||
std::string menuX;
|
||||
std::string menuY;
|
||||
std::string label;
|
||||
std::vector<struct SceneItemComponent> components;
|
||||
std::vector<struct SceneItem> children;
|
||||
std::vector<struct SceneAsset> assets;
|
||||
std::vector<struct SceneCode> code;
|
||||
std::vector<struct SceneItemDependency> dependencies;
|
||||
};
|
||||
|
||||
class SceneItemParser : public XmlParser<struct SceneItem> {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredAttributes() override;
|
||||
std::map<std::string, std::string> getOptionalAttributes() override;
|
||||
int32_t onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct SceneItem *out,
|
||||
std::string *error
|
||||
) override;
|
||||
};
|
||||
}
|
78
archive/dawntools/util/parser/SceneParser.cpp
Normal file
78
archive/dawntools/util/parser/SceneParser.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "SceneParser.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
std::vector<std::string> SceneParser::getRequiredAttributes() {
|
||||
return { "name" };
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> SceneParser::getOptionalAttributes() {
|
||||
return {
|
||||
{ "extend", "" }
|
||||
};
|
||||
}
|
||||
|
||||
int32_t SceneParser::onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct Scene *out,
|
||||
std::string *error
|
||||
) {
|
||||
int32_t ret;
|
||||
|
||||
//Create the scene item
|
||||
out->name = values["name"];
|
||||
out->extend = values["extend"];
|
||||
|
||||
struct SceneItemDependency dep;
|
||||
|
||||
//Parse the children
|
||||
auto itChildren = node->childNodes.begin();
|
||||
while(itChildren != node->childNodes.end()) {
|
||||
if(itChildren->nodeType != XML_NODE_TYPE_ELEMENT) {
|
||||
++itChildren;
|
||||
continue;
|
||||
}
|
||||
|
||||
Xml *child = itChildren->child;
|
||||
|
||||
if(child->node == "asset") {
|
||||
struct SceneAsset asset;
|
||||
auto ret = (SceneAssetParser()).parse(child, &asset, error);
|
||||
if(ret != 0) return ret;
|
||||
out->assets.push_back(asset);
|
||||
|
||||
} else if(child->node == "item") {
|
||||
struct SceneItem item;
|
||||
item.registry = out->registry;
|
||||
ret = (SceneItemParser()).parse(child, &item, error);
|
||||
if(ret != 0) return 1;
|
||||
out->items.push_back(item);
|
||||
|
||||
//Add the dependency
|
||||
dep.type = SCENE_ITEM_DEPENDENCY_TYPE_ITEM;
|
||||
dep.position = out->items.size() - 1;
|
||||
out->dependencies.push_back(dep);
|
||||
|
||||
} else if(child->node == "code") {
|
||||
struct SceneCode code;
|
||||
ret = (SceneCodeParser()).parse(child, &code, error);
|
||||
if(ret != 0) return ret;
|
||||
out->code.push_back(code);
|
||||
|
||||
//Add the dependency
|
||||
dep.type = SCENE_ITEM_DEPENDENCY_TYPE_CODE;
|
||||
dep.position = out->code.size() - 1;
|
||||
out->dependencies.push_back(dep);
|
||||
}
|
||||
|
||||
++itChildren;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
32
archive/dawntools/util/parser/SceneParser.hpp
Normal file
32
archive/dawntools/util/parser/SceneParser.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/parser/SceneItemParser.hpp"
|
||||
#include "util/parser/SceneCodeParser.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct Scene {
|
||||
std::string name;
|
||||
std::string extend;
|
||||
std::vector<struct SceneItem> items;
|
||||
std::vector<struct SceneCode> code;
|
||||
std::vector<struct SceneAsset> assets;
|
||||
struct SceneItemComponentRegistry *registry;
|
||||
std::vector<struct SceneItemDependency> dependencies;
|
||||
};
|
||||
|
||||
class SceneParser : public XmlParser<struct Scene> {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredAttributes() override;
|
||||
std::map<std::string, std::string> getOptionalAttributes() override;
|
||||
int32_t onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct Scene *out,
|
||||
std::string *error
|
||||
) override;
|
||||
};
|
||||
}
|
36
archive/dawntools/util/string.hpp
Normal file
36
archive/dawntools/util/string.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2023 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dawnsharedlibs.hpp"
|
||||
|
||||
/**
|
||||
* Remove all instances of a character from a C-Styled string.
|
||||
*
|
||||
* @param string String to remove characters from.
|
||||
* @param remove Character to remove.
|
||||
*/
|
||||
static inline void stringRemoveAll(char *string, char remove) {
|
||||
size_t len = strlen(string);
|
||||
size_t i, j;
|
||||
|
||||
i = 0;
|
||||
while(i < len) {
|
||||
char c = string[i];
|
||||
if(c != remove) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
j = i + 1;
|
||||
while(j < len) {
|
||||
string[j-1] = string[j];
|
||||
j++;
|
||||
}
|
||||
len--;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user