Prefab Generator Refactor

This commit is contained in:
2023-05-16 08:56:05 -07:00
parent e6c966f3dd
commit 39fffec483
32 changed files with 707 additions and 268 deletions

View File

@@ -7,6 +7,7 @@ set(D ${CMAKE_CURRENT_LIST_DIR})
set(
DAWN_TOOL_SOURCES
${DAWN_TOOL_SOURCES}
${D}/DawnTool.cpp
${D}/File.cpp
${D}/Language.cpp

View File

@@ -0,0 +1,17 @@
# 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}/SceneItemComponentGenerator.cpp
CACHE INTERNAL
${DAWN_CACHE_TARGET}
)

View File

@@ -0,0 +1,38 @@
// 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> *initBody,
std::vector<std::string> *assetsBody,
struct SceneAsset *asset,
std::string tabs
) {
std::string assetType = "";
asset->usageName = "asset" + std::to_string(assetNumber++);
switch(asset->type) {
case SCENE_ASSET_TYPE_TEXTURE:
assetType = "TextureAsset";
assetMap[asset->fileName] = "&" + asset->usageName + "->texture";
break;
case SCENE_ASSET_TYPE_TRUETYPE_FONT:
assetType = "TrueTypeAsset";
assetMap[asset->fileName] = "&" + asset->usageName + "->font";
break;
default:
assertUnreachable();
}
line(initBody, "auto " + asset->usageName + " = man->get<" + assetType + ">(\"" + asset->fileName + "\");", "");
line(assetsBody, "assets.push_back(man->get<" + assetType + ">(\"" + asset->fileName + "\"));", "");
}

View File

@@ -0,0 +1,22 @@
// 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> *initBody,
std::vector<std::string> *assetsBody,
struct SceneAsset *asset,
std::string tabs
);
};
}

View File

@@ -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);
}

View File

@@ -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
);
};
}

View File

@@ -0,0 +1,101 @@
// 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::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,
struct SceneItem *item,
std::string tabs
) {
auto name = "itm" + std::to_string(childNumber++);
if(item->ref == "this") {
name = item->ref;
} else {
bool_t init = true;
if(item->ref.size() > 0) {
init = false;
name = item->ref;
if(item->ref != "this") {
line(publicProperties, "SceneItemComponent *" + name + " = nullptr;", "");
}
}
line(initBody, (init ? "auto " : "") + name + " = scene->createSceneItem();", "");
}
// Process extra properties
if(item->position.size() > 0) {
line(initBody, name + "->transform.setLocalPosition(" + item->position + ");", "");
}
if(item->scale.size() > 0) {
line(initBody, name + "->transform.setLocalScale(" + item->scale + ");", "");
}
// Add assets
auto itAssets = item->assets.begin();
while(itAssets != item->assets.end()) {
SceneAssetGenerator::generate(
assetMap,
assetNumber,
initBody,
assetBody,
&(*itAssets),
""
);
++itAssets;
}
// Add components for children
auto itComponents = item->components.begin();
while(itComponents != item->components.end()) {
SceneItemComponentGenerator::generate(
assetMap,
componentNumber,
includes,
name,
publicProperties,
initBody,
&(*itComponents),
""
);
++itComponents;
}
// Process sub children
auto itChildren = item->children.begin();
while(itChildren != item->children.end()) {
SceneItemGenerator::generate(
assetNumber,
componentNumber,
childNumber,
assetMap,
includes,
publicProperties,
initBody,
assetBody,
name,
&(*itChildren),
""
);
++itChildren;
}
// Set parent
if(!parentRef.empty()) {
line(initBody, name + "->transform.setParent(&"+parentRef+"->transform);", "");
}
}

View File

@@ -0,0 +1,28 @@
// 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"
namespace Dawn {
class SceneItemGenerator : public CodeGen {
public:
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,
struct SceneItem *item,
std::string tabs
);
};
}

View File

@@ -0,0 +1,18 @@
# 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}/SceneItemParser.cpp
${D}/SceneAssetParser.cpp
${D}/SceneItemComponentParser.cpp
${D}/SceneItemComponentRegistry.cpp
CACHE INTERNAL
${DAWN_CACHE_TARGET}
)

View File

@@ -0,0 +1,36 @@
// 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 { };
}
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;
}
return 0;
}

View 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 SceneAssetType {
SCENE_ASSET_TYPE_TEXTURE,
SCENE_ASSET_TYPE_TRUETYPE_FONT
};
struct SceneAsset {
SceneAssetType type;
std::string fileName;
std::string usageName;
};
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
);
};
}

View File

@@ -0,0 +1,70 @@
// 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;
}
return 0;
}

View 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;
};
}

View File

@@ -0,0 +1,186 @@
// 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);
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\\s*(?:\\*\\/)?\\s*$", regexFlags);
std::sregex_iterator it(data.begin(), data.end(), regex);
std::sregex_iterator end;
while(it != end) {
// 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 optional 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 match;
if(!std::regex_search(variableString, match, 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 = match[1].str();
auto name = match[2].str();
ruleset.selfOptional[name] = 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 = "" };
}

View File

@@ -0,0 +1,40 @@
// 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> 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);
};
}

View File

@@ -0,0 +1,69 @@
// 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", "" },
{ "scale", "" }
};
}
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["scale"].size() > 0) {
out->scale = vec3Parser(values["scale"], error);
if(error->size() > 0) return 1;
}
auto itChildren = node->children.begin();
while(itChildren != node->children.end()) {
// Parse child nodes, they may be components or not
auto c = *itChildren;
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);
} 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 {
struct SceneItemComponent component;
component.registry = out->registry;
auto ret = (SceneItemComponentParser()).parse(c, &component, error);
if(ret != 0) return ret;
out->components.push_back(component);
}
++itChildren;
}
return 0;
}

View 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/SceneItemComponentParser.hpp"
#include "util/parser/SceneAssetParser.hpp"
namespace Dawn {
struct SceneItem {
struct SceneItemComponentRegistry *registry;
std::string ref;
std::string position;
std::string scale;
std::vector<struct SceneItemComponent> components;
std::vector<struct SceneItem> children;
std::vector<struct SceneAsset> assets;
};
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;
};
}

View File

@@ -0,0 +1,135 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "util/string.hpp"
namespace Dawn {
static inline std::string rawParser(std::string v, std::string *error) {
return v;
};
static inline std::string stringParser(std::string v, std::string *error) {
return "\"" + v + "\"";
};
static inline std::string floatParser(std::string v, std::string *error) {
v = stringTrim(v);
// Make sure number contains decimal
if(v.find(".") == std::string::npos) {
v += ".0";
}
// Make sure number contains a number before the decimal
if(v.find(".") == 0) {
v = "0" + v;
}
// Make sure ends with f
if(v.find("f") == std::string::npos) {
v += "f";
}
return v;
};
static inline std::string intParser(std::string v, std::string *error) {
v = stringTrim(v);
return v;
}
static inline std::string boolParser(std::string v, std::string *error) {
v = stringTrim(v);
if(v == "true") return "true";
if(v == "false") return "false";
*error = "Invalid bool value: " + v;
return std::string("");
}
static inline std::string vec2Parser(std::string v, std::string *error) {
// Split string by comma into two strings that we pass into float
auto split = stringSplit(v, ",");
if(split.size() != 2) {
*error = "Invalid vec2 value: " + v;
return std::string("");
}
return std::string(
"glm::vec2(" +
floatParser(split[0], error) + ", " +
floatParser(split[1], error) +
")"
);
};
static inline std::string vec3Parser(std::string v, std::string *error) {
// Split string by comma into two strings that we pass into float
auto split = stringSplit(v, ",");
if(split.size() != 3) {
*error = "Invalid vec3 value: " + v;
return std::string("");
}
return std::string(
"glm::vec3(" +
floatParser(split[0], error) + ", " +
floatParser(split[1], error) + ", " +
floatParser(split[2], error) +
")"
);
};
static inline std::string vec4Parser(std::string v, std::string *error) {
// Split string by comma into two strings that we pass into float
auto split = stringSplit(v, ",");
if(split.size() != 4) {
*error = "Invalid vec4 value: " + v;
return std::string("");
}
return std::string(
"glm::vec4(" +
floatParser(split[0], error) + ", " +
floatParser(split[1], error) + ", " +
floatParser(split[2], error) + ", " +
floatParser(split[3], error) +
")"
);
};
static inline std::string colorParser(std::string v, std::string *error) {
return rawParser(v, error);
}
static inline std::function<std::string(std::string, std::string*)> parserFromTypeName(std::string type) {
std::function<std::string(std::string, std::string*)> parser = rawParser;
if(type.find("string") != std::string::npos) {
parser = stringParser;
} else if(type.find("float") != std::string::npos) {
parser = floatParser;
} else if(type.find("Color") != std::string::npos) {
parser = colorParser;
} else if(type.find("vec2") != std::string::npos) {
parser = vec2Parser;
} else if(type.find("vec3") != std::string::npos) {
parser = vec3Parser;
} else if(type.find("vec4") != std::string::npos) {
parser = vec4Parser;
} else if(type == "int32_t" || type == "int") {
parser = intParser;
} else if(type == "bool_t") {
parser = boolParser;
} else if(type == "flag_t") {
parser = rawParser;
} else if(type.starts_with("enum")) {
parser = rawParser;
} else if(type.find("*") == (type.size() - 1)) {
type = type.substr(0, type.size() - 1);
parser = rawParser;
} else {
throw std::string("Invalid parser type");
}
return parser;
}
}