From a180e1b56025c6b7d81d2e587ad90531d29de44c Mon Sep 17 00:00:00 2001 From: rtk0c Date: Sat, 5 Jun 2021 19:44:54 -0700 Subject: Initial work on asset system (does not compile) --- core/CMakeLists.txt | 1 + core/src/Model/Assets.cpp | 126 +++++++++++++++++++++++++++ core/src/Model/Assets.hpp | 104 ++++++++++++++++++++++ core/src/Model/Project.cpp | 139 ------------------------------ core/src/Model/Project.hpp | 17 +--- core/src/Model/Template/Template.hpp | 22 +++-- core/src/Model/Template/Template_Main.cpp | 66 +++++++++++++- core/src/Model/Template/fwd.hpp | 2 +- core/src/Model/Workflow/Workflow.hpp | 25 ++++-- core/src/Model/Workflow/Workflow_Main.cpp | 56 ++++++++++-- core/src/Model/Workflow/fwd.hpp | 2 +- core/src/Model/fwd.hpp | 6 ++ core/src/UI/UI_Templates.cpp | 44 +++------- 13 files changed, 396 insertions(+), 214 deletions(-) create mode 100644 core/src/Model/Assets.cpp create mode 100644 core/src/Model/Assets.hpp diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 8483981..64a31d7 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -33,6 +33,7 @@ set(ENTRYPOINT_MODULE_SOURCES ) add_source_group(MODEL_MODULE_SOURCES + src/Model/Assets.cpp src/Model/Database.cpp src/Model/Filter.cpp src/Model/GlobalStates.cpp diff --git a/core/src/Model/Assets.cpp b/core/src/Model/Assets.cpp new file mode 100644 index 0000000..e4eee54 --- /dev/null +++ b/core/src/Model/Assets.cpp @@ -0,0 +1,126 @@ +#include "Assets.hpp" + +#include +#include +#include + +namespace fs = std::filesystem; + +Asset::Asset() +{ +} + +std::unique_ptr AssetCategory::CreateEmptyUnique(const SavedAsset& diskForm) const +{ + return std::unique_ptr(CreateEmpty(diskForm)); +} + +std::unique_ptr AssetCategory::LoadUnique(const SavedAsset& diskForm) const +{ + return std::unique_ptr(Load(diskForm)); +} + +void AssetCategory::DiscoverFilesByExtension(const std::function& callback, const std::filesystem::path& containerDir, std::string_view extension) +{ + for (auto entry : fs::directory_iterator(containerDir)) { + if (!entry.is_regular_file()) continue; + + // If the caller provided an extension to match against, and it doesn't equal to current file extension, skip + if (!extension.empty() && + entry.path().extension() != extension) + { + continue; + } + + callback(SavedAsset{ + .Path = entry.path(), + .Name = entry.path().stem().string(), + }); + } +} + +void AssetCategory::DiscoverFilesByHeader(const std::function& callback, const std::filesystem::__cxx11::path& containerDir, const std::function& validater) +{ + // TODO +} + +AssetList::AssetList(const AssetCategory& loader) + : mLoader{ &loader } +{ +} + +void AssetList::Reload() +{ + mLoader->DiscoverFiles([this](SavedAsset asset) -> void { + Create(std::move(asset)); + }); +} + +const SavedAsset* AssetList::FindByName(std::string_view name) const +{ + auto iter = mAssets.find(name); + if (iter != mAssets.end()) { + return &iter.value(); + } else { + return nullptr; + } +} + +const SavedAsset& AssetList::Create(SavedAsset asset) +{ + auto [iter, DISCARD] = mAssets.insert(asset.Name, SavedAsset{}); + auto& savedAsset = iter.value(); + + mLoader->CreateEmpty(asset); + savedAsset = std::move(asset); + + return savedAsset; +} + +std::unique_ptr AssetList::CreateAndLoad(SavedAsset assetIn) +{ + auto& savedAsset = Create(std::move(assetIn)); + auto asset = std::unique_ptr(mLoader->CreateEmpty(savedAsset)); + return asset; +} + +std::unique_ptr AssetList::LoadFromDisk(std::string_view name) const +{ + if (auto savedAsset = FindByName(name)) { + auto asset = mLoader->LoadUnique(*savedAsset); + return asset; + } +} + +bool AssetList::Rename(std::string_view oldName, std::string_view newName) +{ +} + +bool AssetList::Remove(std::string_view name) +{ +} + +int AssetList::GetCacheSizeLimit() const +{ + return mCacheSizeLimit; +} + +void AssetList::SetCacheSizeLimit(int limit) +{ + mCacheSizeLimit = limit; +} + +void AssetList::DrawBigIcons(DrawState& state) +{ + // TODO +} + +void AssetList::DrawDetails(DrawState& state) +{ + mLoader->SetupDetailsTable("AssetDetailsTable"); + for (auto& asset : mAssets) { + mLoader->DrawDetailsTableRow(asset); + ImGui::TableNextRow(); + } + ImGui::EndTable(); +} diff --git a/core/src/Model/Assets.hpp b/core/src/Model/Assets.hpp new file mode 100644 index 0000000..bc5219d --- /dev/null +++ b/core/src/Model/Assets.hpp @@ -0,0 +1,104 @@ +#pragma once + +#include +#include +#include +#include +#include + +/// A structure representing a ready-to-be-loaded asset, locating on the disk. +struct SavedAsset +{ + std::filesystem::path Path; + std::string Name; + /// `Path`'s string form, encoded in UTF-8. + std::string PathString = Path.string(); +}; + +class Asset +{ +public: + Asset(); + virtual ~Asset() = default; +}; + +class AssetCategory +{ +public: + virtual ~AssetCategory() = default; + + virtual void DiscoverFiles(const std::function& callback) const = 0; + + virtual Asset* CreateEmpty(const SavedAsset& diskForm) const = 0; + std::unique_ptr CreateEmptyUnique(const SavedAsset& diskForm) const; + virtual Asset* Load(const SavedAsset& diskForm) const = 0; + std::unique_ptr LoadUnique(const SavedAsset& diskForm) const; + + /// This should call ImGui::BeginTable() along with other accessories such as setting up the header row. + virtual void SetupDetailsTable(const char* tableId) const = 0; + virtual void DrawBigIcon(const SavedAsset& asset) const = 0; + virtual void DrawDetailsTableRow(const SavedAsset& asset) const = 0; + +protected: + /* Helper loader functions */ + + static void DiscoverFilesByExtension(const std::function& callback, const std::filesystem::path& containerDir, std::string_view extension); + static void DiscoverFilesByHeader(const std::function& callback, const std::filesystem::path& containerDir, const std::function& validater); +}; + +class AssetList +{ +private: + const AssetCategory* mLoader; + tsl::array_map mAssets; + tsl::array_map> mCache; + int mCacheSizeLimit = 0; + +public: + AssetList(const AssetCategory& loader); + + // TODO support file watches + void Reload(); + + const SavedAsset* FindByName(std::string_view name) const; + const SavedAsset& Create(SavedAsset asset); + std::unique_ptr CreateAndLoad(SavedAsset asset); + std::unique_ptr LoadFromDisk(std::string_view name) const; + bool Rename(std::string_view oldName, std::string_view newName); + bool Remove(std::string_view name); + + int GetCacheSizeLimit() const; + void SetCacheSizeLimit(int limit); + + struct DrawState + { + const SavedAsset* SelectedAsset = nullptr; + }; + void DrawBigIcons(DrawState& state); + void DrawDetails(DrawState& state); +}; + +template +class TypedAssetList : public AssetList +{ +public: + using Asset = TAsset; + using AssetType = typename TAsset::CategoryType; + +public: + // Import constructor + using AssetList::AssetList; + + Asset* FindByName(std::string_view name) const + { + return static_cast(AssetList::FindByName(name)); + } + std::unique_ptr Create(std::string_view name) + { + return std::unique_ptr(static_cast(AssetList::Create(name).release())); + } + std::unique_ptr LoadFromDisk(std::string_view name) const + { + return std::unique_ptr(static_cast(AssetList::LoadFromDisk(name))); + } +}; diff --git a/core/src/Model/Project.cpp b/core/src/Model/Project.cpp index 3cb3cb4..9f41d3a 100644 --- a/core/src/Model/Project.cpp +++ b/core/src/Model/Project.cpp @@ -62,23 +62,6 @@ Project::Project(fs::path rootPath) ReadItemList(Products, itemsDir / "products.json"); ReadItemList(Factories, itemsDir / "factories.json"); ReadItemList(Customers, itemsDir / "customers.json"); - - auto workflowsDir = mRootPath / "workflows"; - fs::create_directories(workflowsDir); - - for (auto& entry : fs::directory_iterator(workflowsDir)) { - if (!entry.is_regular_file()) continue; - auto& path = entry.path(); - if (path.extension() != ".cplt-workflow") continue; - - auto name = path.stem().string(); - auto [it, DISCARD] = mWorkflows.insert(name, WorkflowInfo{}); - auto& info = it.value(); - - info.Name = std::move(name); - info.PathStringCache = path.string(); - info.Path = path; - } } Project::Project(fs::path rootPath, std::string name) @@ -139,128 +122,6 @@ void Project::SetName(std::string name) mName = std::move(name); } -const tsl::array_map& Project::GetWorkflows() const -{ - return mWorkflows; -} - -std::unique_ptr Project::LoadWorkflow(std::string_view name) -{ - auto iter = mWorkflows.find(name); - if (iter == mWorkflows.end()) { - return iter.value().LoadFromDisk(); - } else { - return nullptr; - } -} - -std::unique_ptr Project::CreateWorkflow(std::string_view name) -{ - if (mWorkflows.find(name) != mWorkflows.end()) { - // Workflow with name already exists - return nullptr; - } - - auto workflow = std::make_unique(); - auto [it, DISCARD] = mWorkflows.insert( - name, - WorkflowInfo{ - .Path = GetWorkflowPath(name), - .Name = std::string(name), - }); - - return workflow; -} - -bool Project::RemoveWorkflow(std::string_view name) -{ - auto iter = mWorkflows.find(name); - if (iter == mWorkflows.end()) { - return false; - } - auto& info = iter.value(); - - fs::remove(info.Path); - mWorkflows.erase(iter); - - return true; -} - -bool Project::RenameWorkflow(std::string_view oldName, std::string_view newName) -{ - auto iter = mWorkflows.find(oldName); - if (iter == mWorkflows.end()) return false; - - auto info = std::move(iter.value()); - - auto& oldPath = info.Path; - auto newPath = GetWorkflowPath(newName); - fs::rename(oldPath, newPath); - info.Path = std::move(newPath); - - mWorkflows.insert(newName, std::move(info)); - mWorkflows.erase(iter); - - return true; -} - -const tsl::array_map& Project::GetTemplates() const -{ - return mTemplates; -} - -std::unique_ptr