add basis for code rendering

This commit is contained in:
Jan 2021-02-20 02:33:40 +01:00
parent 48afb4d514
commit d4a98b7c52
17 changed files with 571 additions and 24 deletions

View File

@ -0,0 +1,126 @@
#include "CodeGenerator.h"
#include <filesystem>
#include <fstream>
#include <iostream>
#include "Domain/Computations/StructureComputations.h"
#include "Templates/AssetStructTestsTemplate.h"
#include "Templates/ZoneLoadTemplate.h"
#include "Templates/ZoneWriteTemplate.h"
namespace fs = std::filesystem;
CodeGenerator::CodeGenerator(const ZoneCodeGeneratorArguments* args)
: m_args(args)
{
SetupTemplates();
}
void CodeGenerator::SetupTemplates()
{
m_template_mapping["zoneload"] = std::make_unique<ZoneLoadTemplate>();
m_template_mapping["zonewrite"] = std::make_unique<ZoneWriteTemplate>();
m_template_mapping["assetstructtests"] = std::make_unique<AssetStructTestsTemplate>();
}
bool CodeGenerator::GenerateCodeForTemplate(RenderingContext* context, ICodeTemplate* codeTemplate) const
{
for (const auto& codeFile : codeTemplate->GetFilesToRender(context))
{
fs::path p(m_args->m_output_directory);
p.append(codeFile.m_file_name);
auto parentFolder(p);
parentFolder.remove_filename();
create_directories(parentFolder);
std::ofstream stream(p, std::fstream::out | std::fstream::binary);
if (!stream.is_open())
{
std::cout << "Failed to open file '" << p.string() << "'" << std::endl;
return false;
}
codeTemplate->RenderFile(stream, codeFile.m_tag);
stream.close();
}
return true;
}
bool CodeGenerator::GetAssetWithName(IDataRepository* repository, const std::string& name, StructureInformation*& asset)
{
auto* def = repository->GetDataDefinitionByName(name);
if (def == nullptr)
{
std::cout << "Could not find type with name '" << name << "'" << std::endl;
return false;
}
auto* defWithMembers = dynamic_cast<DefinitionWithMembers*>(def);
auto* info = defWithMembers != nullptr ? repository->GetInformationFor(defWithMembers) : nullptr;
if (info == nullptr)
{
std::cout << "Could not find type with name '" << name << "'" << std::endl;
return false;
}
if(!StructureComputations(info).IsAsset())
{
std::cout << "Type is not an asset '" << name << "'" << std::endl;
return false;
}
return true;
}
bool CodeGenerator::GenerateCode(IDataRepository* repository)
{
std::vector<StructureInformation*> assets;
for (auto* info : repository->GetAllStructureInformation())
{
StructureComputations computations(info);
if (computations.IsAsset())
assets.push_back(info);
}
for (const auto& generationTask : m_args->m_generation_tasks)
{
auto templateName = generationTask.m_template_name;
for (auto& c : templateName)
c = static_cast<char>(tolower(c));
const auto foundTemplate = m_template_mapping.find(templateName);
if (foundTemplate == m_template_mapping.end())
{
std::cout << "Unknown template '" << generationTask.m_template_name << "'." << std::endl;
return false;
}
if (generationTask.m_all_assets)
{
for (auto* asset : assets)
{
auto context = RenderingContext::BuildContext(repository, asset);
if (!GenerateCodeForTemplate(context.get(), foundTemplate->second.get()))
return false;
}
}
else
{
StructureInformation* asset;
if (!GetAssetWithName(repository, generationTask.m_asset_name, asset))
return false;
auto context = RenderingContext::BuildContext(repository, asset);
if (!GenerateCodeForTemplate(context.get(), foundTemplate->second.get()))
return false;
}
}
return true;
}

View File

@ -0,0 +1,23 @@
#pragma once
#include <unordered_map>
#include "ICodeTemplate.h"
#include "ZoneCodeGeneratorArguments.h"
class CodeGenerator
{
const ZoneCodeGeneratorArguments* m_args;
std::unordered_map<std::string, std::unique_ptr<ICodeTemplate>> m_template_mapping;
void SetupTemplates();
bool GenerateCodeForTemplate(RenderingContext* context, ICodeTemplate* codeTemplate) const;
static bool GetAssetWithName(IDataRepository* repository, const std::string& name, StructureInformation*& asset);
public:
explicit CodeGenerator(const ZoneCodeGeneratorArguments* args);
bool GenerateCode(IDataRepository* repository);
};

View File

@ -0,0 +1,34 @@
#pragma once
#include <ostream>
#include <string>
#include <vector>
#include "RenderingContext.h"
class CodeTemplateFile
{
public:
std::string m_file_name;
int m_tag;
CodeTemplateFile(std::string fileName, const int tag)
: m_file_name(std::move(fileName)),
m_tag(tag)
{
}
};
class ICodeTemplate
{
public:
ICodeTemplate() = default;
virtual ~ICodeTemplate() = default;
ICodeTemplate(const ICodeTemplate& other) = default;
ICodeTemplate(ICodeTemplate&& other) noexcept = default;
ICodeTemplate& operator=(const ICodeTemplate& other) = default;
ICodeTemplate& operator=(ICodeTemplate&& other) noexcept = default;
virtual std::vector<CodeTemplateFile> GetFilesToRender(RenderingContext* context) = 0;
virtual void RenderFile(std::ostream& stream, int fileTag) = 0;
};

View File

@ -0,0 +1,166 @@
#include "RenderingContext.h"
#include "Domain/Computations/MemberComputations.h"
#include "Domain/Computations/StructureComputations.h"
RenderingUsedType::RenderingUsedType(const DataDefinition* type, StructureInformation* info)
: m_members_loaded(false),
m_type(type),
m_info(info),
m_is_context_asset(false),
m_non_runtime_reference_exists(false),
m_non_embedded_reference_exists(false),
m_array_reference_exists(false),
m_pointer_array_reference_exists(false),
m_pointer_array_reference_is_reusable(false)
{
}
RenderingContext::RenderingContext(std::string game, std::vector<const FastFileBlock*> fastFileBlocks)
: m_game(std::move(game)),
m_blocks(std::move(fastFileBlocks)),
m_asset(nullptr),
m_has_actions(false),
m_default_normal_block(nullptr),
m_default_temp_block(nullptr)
{
for (const auto* block : m_blocks)
{
if (block->m_is_default)
{
if (block->m_type == FastFileBlockType::NORMAL && m_default_normal_block == nullptr)
m_default_normal_block = block;
else if (block->m_type == FastFileBlockType::TEMP && m_default_temp_block == nullptr)
m_default_temp_block = block;
}
}
}
RenderingUsedType* RenderingContext::GetBaseType(RenderingUsedType* usedType)
{
if(usedType->m_type->GetType() == DataDefinitionType::TYPEDEF)
{
const auto* typedefDefinition = dynamic_cast<const TypedefDefinition*>(usedType->m_type);
while(typedefDefinition->m_type_declaration->m_type->GetType() == DataDefinitionType::TYPEDEF)
typedefDefinition = dynamic_cast<const TypedefDefinition*>(typedefDefinition->m_type_declaration->m_type);
const auto foundUsedType = m_used_types_lookup.find(typedefDefinition);
if(foundUsedType == m_used_types_lookup.end())
{
auto usedTypePtr = std::make_unique<RenderingUsedType>(typedefDefinition->m_type_declaration->m_type, nullptr);
auto* result = usedTypePtr.get();
m_used_types_lookup.emplace(std::make_pair(usedTypePtr->m_type, std::move(usedTypePtr)));
return result;
}
return foundUsedType->second.get();
}
return nullptr;
}
void RenderingContext::AddMembersToContext(StructureInformation* info)
{
for(const auto& member : info->m_ordered_members)
{
MemberComputations computations(member.get());
if(computations.ShouldIgnore())
continue;
RenderingUsedType* usedType;
const auto existingUsedType = m_used_types_lookup.find(member->m_member->m_type_declaration->m_type);
if(existingUsedType == m_used_types_lookup.end())
{
auto usedTypePtr = std::make_unique<RenderingUsedType>(member->m_member->m_type_declaration->m_type, member->m_type);
usedType = usedTypePtr.get();
m_used_types_lookup.emplace(std::make_pair(usedTypePtr->m_type, std::move(usedTypePtr)));
}
else
{
usedType = existingUsedType->second.get();
}
auto* baseUsedType = GetBaseType(usedType);
if(!computations.IsInRuntimeBlock())
{
usedType->m_non_runtime_reference_exists = true;
if (baseUsedType != nullptr)
baseUsedType->m_non_runtime_reference_exists = true;
}
if (computations.ContainsNonEmbeddedReference())
usedType->m_non_embedded_reference_exists = true;
if (computations.ContainsArrayPointerReference() || computations.ContainsArrayReference())
usedType->m_array_reference_exists = true;
if(computations.ContainsPointerArrayReference() && !member->m_is_string)
{
usedType->m_pointer_array_reference_exists = true;
if (member->m_is_reusable)
usedType->m_pointer_array_reference_is_reusable = true;
}
if(usedType->m_info != nullptr && StructureComputations(usedType->m_info).IsAsset() && !computations.IsInRuntimeBlock() && !usedType->m_members_loaded)
{
usedType->m_members_loaded = true;
AddMembersToContext(usedType->m_info);
}
}
}
void RenderingContext::MakeAsset(StructureInformation* asset)
{
m_asset = asset;
auto assetUsedType = std::make_unique<RenderingUsedType>(asset->m_definition, asset);
assetUsedType->m_is_context_asset = true;
m_used_types_lookup.emplace(std::make_pair(asset->m_definition, std::move(assetUsedType)));
AddMembersToContext(asset);
}
void RenderingContext::CreateUsedTypeCollections()
{
for(const auto& [dataDef, usedType] : m_used_types_lookup)
{
m_used_types.push_back(usedType.get());
if (usedType->m_info != nullptr)
{
StructureComputations computations(usedType->m_info);
if(usedType->m_info->m_definition == dataDef)
m_used_structures.push_back(usedType.get());
if(computations.IsAsset() && usedType->m_info != m_asset)
m_referenced_assets.push_back(usedType.get());
if (!m_has_actions)
{
if ((!computations.IsAsset() || usedType->m_is_context_asset)
&& usedType->m_non_runtime_reference_exists
&& usedType->m_info->m_post_load_action)
{
m_has_actions = true;
}
}
}
}
}
std::unique_ptr<RenderingContext> RenderingContext::BuildContext(const IDataRepository* repository, StructureInformation* asset)
{
auto context = std::make_unique<RenderingContext>(RenderingContext(repository->GetGameName(), repository->GetAllFastFileBlocks()));
context->MakeAsset(asset);
context->CreateUsedTypeCollections();
return std::move(context);
}

View File

@ -0,0 +1,52 @@
#pragma once
#include <string>
#include <unordered_map>
#include "Domain/Information/StructureInformation.h"
#include "Persistence/IDataRepository.h"
class RenderingUsedType
{
public:
bool m_members_loaded;
const DataDefinition* m_type;
StructureInformation* m_info;
bool m_is_context_asset;
bool m_non_runtime_reference_exists;
bool m_non_embedded_reference_exists;
bool m_array_reference_exists;
bool m_pointer_array_reference_exists;
bool m_pointer_array_reference_is_reusable;
RenderingUsedType(const DataDefinition* type, StructureInformation* info);
};
class RenderingContext
{
std::unordered_map<const DataDefinition*, std::unique_ptr<RenderingUsedType>> m_used_types_lookup;
RenderingContext(std::string game, std::vector<const FastFileBlock*> fastFileBlocks);
RenderingUsedType* GetBaseType(RenderingUsedType* usedType);
void AddMembersToContext(StructureInformation* info);
void MakeAsset(StructureInformation* asset);
void CreateUsedTypeCollections();
public:
std::string m_game;
std::vector<const FastFileBlock*> m_blocks;
StructureInformation* m_asset;
std::vector<RenderingUsedType*> m_used_types;
std::vector<RenderingUsedType*> m_used_structures;
std::vector<RenderingUsedType*> m_referenced_assets;
bool m_has_actions;
const FastFileBlock* m_default_normal_block;
const FastFileBlock* m_default_temp_block;
static std::unique_ptr<RenderingContext> BuildContext(const IDataRepository* repository, StructureInformation* asset);
};

View File

@ -0,0 +1,24 @@
#include "AssetStructTestsTemplate.h"
#include <sstream>
std::vector<CodeTemplateFile> AssetStructTestsTemplate::GetFilesToRender(RenderingContext* context)
{
std::vector<CodeTemplateFile> files;
auto assetName = context->m_asset->m_definition->m_name;
for (auto& c : assetName)
c = static_cast<char>(tolower(c));
{
std::ostringstream str;
str << assetName << '/' << assetName << "_struct_test.cpp";
files.emplace_back(str.str(), TAG_SOURCE);
}
return files;
}
void AssetStructTestsTemplate::RenderFile(std::ostream& stream, int fileTag)
{
}

View File

@ -0,0 +1,11 @@
#pragma once
#include "Generating/ICodeTemplate.h"
class AssetStructTestsTemplate final : public ICodeTemplate
{
static constexpr int TAG_SOURCE = 1;
public:
std::vector<CodeTemplateFile> GetFilesToRender(RenderingContext* context) override;
void RenderFile(std::ostream& stream, int fileTag) override;
};

View File

@ -0,0 +1,42 @@
#include "ZoneLoadTemplate.h"
#include <sstream>
std::vector<CodeTemplateFile> ZoneLoadTemplate::GetFilesToRender(RenderingContext* context)
{
std::vector<CodeTemplateFile> files;
auto assetName = context->m_asset->m_definition->m_name;
for (auto& c : assetName)
c = static_cast<char>(tolower(c));
{
std::ostringstream str;
str << assetName << '/' << assetName << "_load_db.h";
files.emplace_back(str.str(), TAG_HEADER);
}
{
std::ostringstream str;
str << assetName << '/' << assetName << "_load_db.cpp";
files.emplace_back(str.str(), TAG_SOURCE);
}
return files;
}
void ZoneLoadTemplate::RenderFile(std::ostream& stream, const int fileTag)
{
if (fileTag == TAG_HEADER)
{
stream << "Header";
}
else if (fileTag == TAG_SOURCE)
{
stream << "Source";
}
else
{
stream << "Unknown";
}
}

View File

@ -0,0 +1,12 @@
#pragma once
#include "Generating/ICodeTemplate.h"
class ZoneLoadTemplate final : public ICodeTemplate
{
static constexpr int TAG_HEADER = 1;
static constexpr int TAG_SOURCE = 2;
public:
std::vector<CodeTemplateFile> GetFilesToRender(RenderingContext* context) override;
void RenderFile(std::ostream& stream, int fileTag) override;
};

View File

@ -0,0 +1,30 @@
#include "ZoneWriteTemplate.h"
#include <sstream>
std::vector<CodeTemplateFile> ZoneWriteTemplate::GetFilesToRender(RenderingContext* context)
{
std::vector<CodeTemplateFile> files;
auto assetName = context->m_asset->m_definition->m_name;
for (auto& c : assetName)
c = static_cast<char>(tolower(c));
{
std::ostringstream str;
str << assetName << '/' << assetName << "_write_db.h";
files.emplace_back(str.str(), TAG_HEADER);
}
{
std::ostringstream str;
str << assetName << '/' << assetName << "_write_db.cpp";
files.emplace_back(str.str(), TAG_SOURCE);
}
return files;
}
void ZoneWriteTemplate::RenderFile(std::ostream& stream, const int fileTag)
{
}

View File

@ -0,0 +1,12 @@
#pragma once
#include "Generating/ICodeTemplate.h"
class ZoneWriteTemplate final : public ICodeTemplate
{
static constexpr int TAG_HEADER = 1;
static constexpr int TAG_SOURCE = 2;
public:
std::vector<CodeTemplateFile> GetFilesToRender(RenderingContext* context) override;
void RenderFile(std::ostream& stream, int fileTag) override;
};

View File

@ -38,10 +38,10 @@ public:
_NODISCARD virtual const std::vector<UnionDefinition*>& GetAllUnions() const = 0; _NODISCARD virtual const std::vector<UnionDefinition*>& GetAllUnions() const = 0;
_NODISCARD virtual const std::vector<TypedefDefinition*>& GetAllTypedefs() const = 0; _NODISCARD virtual const std::vector<TypedefDefinition*>& GetAllTypedefs() const = 0;
_NODISCARD virtual const std::vector<StructureInformation*>& GetAllStructureInformation() const = 0; _NODISCARD virtual const std::vector<StructureInformation*>& GetAllStructureInformation() const = 0;
_NODISCARD virtual const std::vector<FastFileBlock*>& GetAllFastFileBlocks() const = 0; _NODISCARD virtual const std::vector<const FastFileBlock*>& GetAllFastFileBlocks() const = 0;
_NODISCARD virtual DataDefinition* GetDataDefinitionByName(const std::string& name) const = 0; _NODISCARD virtual DataDefinition* GetDataDefinitionByName(const std::string& name) const = 0;
_NODISCARD virtual StructureInformation* GetInformationFor(const DefinitionWithMembers* definitionWithMembers) const = 0; _NODISCARD virtual StructureInformation* GetInformationFor(const DefinitionWithMembers* definitionWithMembers) const = 0;
_NODISCARD virtual EnumMember* GetEnumMemberByName(const std::string& name) const = 0; _NODISCARD virtual EnumMember* GetEnumMemberByName(const std::string& name) const = 0;
_NODISCARD virtual FastFileBlock* GetFastFileBlockByName(const std::string& name) const = 0; _NODISCARD virtual const FastFileBlock* GetFastFileBlockByName(const std::string& name) const = 0;
}; };

View File

@ -17,7 +17,7 @@ InMemoryRepository::~InMemoryRepository()
delete typedefDefinition; delete typedefDefinition;
for (auto* structureInformation : m_structures_information) for (auto* structureInformation : m_structures_information)
delete structureInformation; delete structureInformation;
for (auto* fastFileBlock : m_fast_file_blocks) for (const auto* fastFileBlock : m_fast_file_blocks)
delete fastFileBlock; delete fastFileBlock;
} }
@ -111,7 +111,7 @@ const std::vector<StructureInformation*>& InMemoryRepository::GetAllStructureInf
return m_structures_information; return m_structures_information;
} }
const std::vector<FastFileBlock*>& InMemoryRepository::GetAllFastFileBlocks() const const std::vector<const FastFileBlock*>& InMemoryRepository::GetAllFastFileBlocks() const
{ {
return m_fast_file_blocks; return m_fast_file_blocks;
} }
@ -146,7 +146,7 @@ EnumMember* InMemoryRepository::GetEnumMemberByName(const std::string& name) con
return nullptr; return nullptr;
} }
FastFileBlock* InMemoryRepository::GetFastFileBlockByName(const std::string& name) const const FastFileBlock* InMemoryRepository::GetFastFileBlockByName(const std::string& name) const
{ {
const auto foundEntry = m_fast_file_blocks_by_name.find(name); const auto foundEntry = m_fast_file_blocks_by_name.find(name);

View File

@ -11,10 +11,10 @@ class InMemoryRepository final : public IDataRepository
std::vector<UnionDefinition*> m_unions; std::vector<UnionDefinition*> m_unions;
std::vector<TypedefDefinition*> m_typedefs; std::vector<TypedefDefinition*> m_typedefs;
std::vector<StructureInformation*> m_structures_information; std::vector<StructureInformation*> m_structures_information;
std::vector<FastFileBlock*> m_fast_file_blocks; std::vector<const FastFileBlock*> m_fast_file_blocks;
std::map<std::string, DataDefinition*> m_data_definitions_by_name; std::map<std::string, DataDefinition*> m_data_definitions_by_name;
std::map<std::string, EnumMember*> m_enum_members_by_name; std::map<std::string, EnumMember*> m_enum_members_by_name;
std::map<std::string, FastFileBlock*> m_fast_file_blocks_by_name; std::map<std::string, const FastFileBlock*> m_fast_file_blocks_by_name;
std::map<const DefinitionWithMembers*, StructureInformation*> m_structure_information_by_definition; std::map<const DefinitionWithMembers*, StructureInformation*> m_structure_information_by_definition;
std::string m_game_name; std::string m_game_name;
Architecture m_architecture; Architecture m_architecture;
@ -44,10 +44,10 @@ public:
_NODISCARD const std::vector<UnionDefinition*>& GetAllUnions() const override; _NODISCARD const std::vector<UnionDefinition*>& GetAllUnions() const override;
_NODISCARD const std::vector<TypedefDefinition*>& GetAllTypedefs() const override; _NODISCARD const std::vector<TypedefDefinition*>& GetAllTypedefs() const override;
_NODISCARD const std::vector<StructureInformation*>& GetAllStructureInformation() const override; _NODISCARD const std::vector<StructureInformation*>& GetAllStructureInformation() const override;
_NODISCARD const std::vector<FastFileBlock*>& GetAllFastFileBlocks() const override; _NODISCARD const std::vector<const FastFileBlock*>& GetAllFastFileBlocks() const override;
_NODISCARD DataDefinition* GetDataDefinitionByName(const std::string& name) const override; _NODISCARD DataDefinition* GetDataDefinitionByName(const std::string& name) const override;
_NODISCARD StructureInformation* GetInformationFor(const DefinitionWithMembers* definitionWithMembers) const override; _NODISCARD StructureInformation* GetInformationFor(const DefinitionWithMembers* definitionWithMembers) const override;
_NODISCARD EnumMember* GetEnumMemberByName(const std::string& name) const override; _NODISCARD EnumMember* GetEnumMemberByName(const std::string& name) const override;
_NODISCARD FastFileBlock* GetFastFileBlockByName(const std::string& name) const override; _NODISCARD const FastFileBlock* GetFastFileBlockByName(const std::string& name) const override;
}; };

View File

@ -6,6 +6,7 @@
#include <iostream> #include <iostream>
#include "ZoneCodeGeneratorArguments.h" #include "ZoneCodeGeneratorArguments.h"
#include "Generating/CodeGenerator.h"
#include "Parsing/Commands/CommandsFileReader.h" #include "Parsing/Commands/CommandsFileReader.h"
#include "Parsing/Header/HeaderFileReader.h" #include "Parsing/Header/HeaderFileReader.h"
#include "Persistence/IDataRepository.h" #include "Persistence/IDataRepository.h"
@ -49,15 +50,10 @@ class ZoneCodeGenerator::Impl
prettyPrinter.PrintAll(); prettyPrinter.PrintAll();
} }
bool GenerateCode() _NODISCARD bool GenerateCode() const
{ {
for(const auto& generationTask : m_args.m_generation_tasks) CodeGenerator codeGenerator(&m_args);
{ return codeGenerator.GenerateCode(m_repository.get());
// TODO: Implement
std::cout << "Generating code for asset \"" << generationTask.m_asset_name << "\" and preset \"" << generationTask.m_preset_name << "\" ..." << std::endl;
}
return true;
} }
public: public:

View File

@ -85,11 +85,20 @@ const CommandLineOption* const COMMAND_LINE_OPTIONS[]
}; };
ZoneCodeGeneratorArguments::GenerationTask::GenerationTask() ZoneCodeGeneratorArguments::GenerationTask::GenerationTask()
= default; : m_all_assets(false)
{
}
ZoneCodeGeneratorArguments::GenerationTask::GenerationTask(std::string assetName, std::string presetName) ZoneCodeGeneratorArguments::GenerationTask::GenerationTask(std::string templateName)
: m_asset_name(std::move(assetName)), : m_all_assets(true),
m_preset_name(std::move(presetName)) m_template_name(std::move(templateName))
{
}
ZoneCodeGeneratorArguments::GenerationTask::GenerationTask(std::string assetName, std::string templateName)
: m_all_assets(false),
m_asset_name(std::move(assetName)),
m_template_name(std::move(templateName))
{ {
} }
@ -169,7 +178,15 @@ bool ZoneCodeGeneratorArguments::Parse(const int argc, const char** argv)
m_task_flags |= FLAG_TASK_GENERATE; m_task_flags |= FLAG_TASK_GENERATE;
const auto generateParameterValues = m_argument_parser.GetParametersForOption(OPTION_GENERATE); const auto generateParameterValues = m_argument_parser.GetParametersForOption(OPTION_GENERATE);
for (auto i = 0u; i < generateParameterValues.size(); i += 2) for (auto i = 0u; i < generateParameterValues.size(); i += 2)
m_generation_tasks.emplace_back(generateParameterValues[i], generateParameterValues[i + 1]); {
const auto& assetName = generateParameterValues[i];
const auto& templateName = generateParameterValues[i + 1];
if (assetName == "*")
m_generation_tasks.emplace_back(templateName);
else
m_generation_tasks.emplace_back(assetName, templateName);
}
} }
if (m_task_flags == 0) if (m_task_flags == 0)

View File

@ -21,11 +21,13 @@ public:
class GenerationTask class GenerationTask
{ {
public: public:
bool m_all_assets;
std::string m_asset_name; std::string m_asset_name;
std::string m_preset_name; std::string m_template_name;
GenerationTask(); GenerationTask();
GenerationTask(std::string assetName, std::string presetName); explicit GenerationTask(std::string templateName);
GenerationTask(std::string assetName, std::string templateName);
}; };
bool m_verbose; bool m_verbose;