diff --git a/core/src/cubos/core/data/binary_deserializer.cpp b/core/src/cubos/core/data/binary_deserializer.cpp index 8687e20c2..83931e676 100644 --- a/core/src/cubos/core/data/binary_deserializer.cpp +++ b/core/src/cubos/core/data/binary_deserializer.cpp @@ -103,7 +103,7 @@ std::size_t BinaryDeserializer::beginArray() { uint64_t size; this->readU64(size); - return size; + return (std::size_t)size; } void BinaryDeserializer::endArray() @@ -115,7 +115,7 @@ std::size_t BinaryDeserializer::beginDictionary() { uint64_t size; this->readU64(size); - return size; + return (std::size_t)size; } void BinaryDeserializer::endDictionary() diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index c8555ff92..a4962d1c1 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -20,6 +20,7 @@ set(CUBOS_ENGINE_SOURCE "src/cubos/engine/file_settings/plugin.cpp" "src/cubos/engine/imgui/plugin.cpp" + "src/cubos/engine/tools/asset_explorer/plugin.cpp" "src/cubos/engine/tools/settings_inspector/plugin.cpp" "src/cubos/engine/tools/entity_selector/plugin.cpp" "src/cubos/engine/tools/world_inspector/plugin.cpp" @@ -66,6 +67,7 @@ set(CUBOS_ENGINE_INCLUDE "include/cubos/engine/file_settings/plugin.hpp" "include/cubos/engine/imgui/plugin.hpp" + "include/cubos/engine/tools/asset_explorer/plugin.hpp" "include/cubos/engine/tools/settings_inspector/plugin.hpp" "include/cubos/engine/tools/entity_selector/plugin.hpp" "include/cubos/engine/tools/world_inspector/plugin.hpp" diff --git a/engine/include/cubos/engine/assets/assets.hpp b/engine/include/cubos/engine/assets/assets.hpp index 809590443..9e9c205d7 100644 --- a/engine/include/cubos/engine/assets/assets.hpp +++ b/engine/include/cubos/engine/assets/assets.hpp @@ -172,6 +172,10 @@ namespace cubos::engine [](void* data) { delete static_cast(data); }); } + /// Gets all assets that have been registered + /// @returns a vector with all registered assets. + std::vector listAll() const; + private: /// Represents a known asset - may or may not be loaded. struct Entry diff --git a/engine/include/cubos/engine/tools/asset_explorer/plugin.hpp b/engine/include/cubos/engine/tools/asset_explorer/plugin.hpp new file mode 100644 index 000000000..b390dbda3 --- /dev/null +++ b/engine/include/cubos/engine/tools/asset_explorer/plugin.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include + +namespace cubos::engine::tools +{ + /// @brief Event sent when an asset is selected. + struct AssetSelectedEvent { + AnyAsset asset; + }; + + /// Plugin that allows exploring and selecting assets through a ImGui window. + /// + /// @details This plugin adds one system, which adds a ImGui window with the assets folder. + /// + /// Dependencies: + /// - `imguiPlugin` + /// - `assetsPlugin` + /// + /// Events: + /// - `AssetSelectedEvent`: sent when an asset is selected in the explorer. + /// + /// @param cubos CUBOS. main class + void assetExplorerPlugin(Cubos& cubos); +} // namespace cubos::engine::tools \ No newline at end of file diff --git a/engine/src/cubos/engine/assets/assets.cpp b/engine/src/cubos/engine/assets/assets.cpp index 7d04ed705..b1b050420 100644 --- a/engine/src/cubos/engine/assets/assets.cpp +++ b/engine/src/cubos/engine/assets/assets.cpp @@ -591,3 +591,11 @@ void Assets::loader() } } } + +std::vector Assets::listAll() const { + std::vector out; + for (auto const& [entry,_] : mEntries) { + out.emplace_back(entry); + } + return out; +} \ No newline at end of file diff --git a/engine/src/cubos/engine/tools/asset_explorer/plugin.cpp b/engine/src/cubos/engine/tools/asset_explorer/plugin.cpp new file mode 100644 index 000000000..ecc73c56c --- /dev/null +++ b/engine/src/cubos/engine/tools/asset_explorer/plugin.cpp @@ -0,0 +1,140 @@ +#include + +#include + +#include +#include +#include + +using cubos::core::ecs::Read; +using cubos::core::ecs::EventWriter; + +using namespace cubos::engine; + +static bool assetsCompare(AnyAsset const& a, AnyAsset const& b, Assets const& assets) +{ + std::string aPath = assets.readMeta(a)->get("path").value(); + std::string bPath = assets.readMeta(b)->get("path").value(); + + auto aCount = std::count(aPath.begin(), aPath.end(), '/'); + auto bCount = std::count(bPath.begin(), bPath.end(), '/'); + + std::string aDir = aPath; + std::string bDir = bPath; + + aDir.erase(aDir.rfind("/")); + bDir.erase(bDir.rfind("/")); + + if (aCount != bCount) + { + if (aDir.find(bDir + "/") != std::string::npos) + { + return true; + } + else if (bDir.find(aDir + "/") != std::string::npos) + { + return false; + } + } + + return aPath.compare(bPath) > 0; +} + +static void showAsset(Assets const& assets, AnyAsset const& asset, EventWriter events) +{ + std::string path = assets.readMeta(asset)->get("path").value(); + ImGui::PushID(path.c_str()); + ImGui::BulletText("%s", path.erase(0, path.rfind("/") + 1).c_str()); + ImGui::SameLine(); + if (ImGui::Button("Select")) + { + events.push(tools::AssetSelectedEvent{asset}); + } + ImGui::PopID(); +} + +static std::vector::iterator showFolder(Assets const& assets, std::string const& folder, + std::vector::iterator iter, std::vector::iterator end, + EventWriter events) +{ + std::string displayName = folder; + displayName.erase(0, displayName.rfind("/")); + + ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4)ImColor(149, 252, 75)); + if (ImGui::TreeNode(displayName.c_str())) + { + ImGui::PopStyleColor(1); + while (iter != end) + { + AnyAsset asset = *iter; + std::string assetPath = assets.readMeta(asset)->get("path").value(); + if (assetPath.find(folder + "/") == std::string::npos) + { + break; + } + + std::string dirless = assetPath; + dirless.erase(0, folder.length() + 1); + auto pos = dirless.find('/'); + if (pos != std::string::npos) + { + std::string subfolder = folder + "/" + dirless.substr(0, pos); + iter = showFolder(assets, subfolder, iter, end, events); + } + else + { + showAsset(assets, *iter, events); + iter++; + } + } + ImGui::TreePop(); + } + else + { + ImGui::PopStyleColor(1); + while (iter != end) + { + if (assets.readMeta(*iter)->get("path").value().find(folder + "/") == std::string::npos) + { + break; + } + iter++; + } + } + return iter; +} + +static void showAssets(Read assets, Read settings, + EventWriter events) +{ + ImGui::Begin("Asset Explorer"); + + std::string folder = settings->getString("assets.io.path", ""); + + folder.erase(0, folder.rfind("/")); + + std::vector assetsVector; + for (auto const& a : assets->listAll()) + { + if (assets->readMeta(a)->get("path").has_value()) + { + assetsVector.push_back(a); + } + } + std::sort(assetsVector.begin(), assetsVector.end(), + [assets](AnyAsset const& a, AnyAsset const& b) { return assetsCompare(a, b, *assets); }); + + showFolder((*assets), folder, assetsVector.begin(), assetsVector.end(), events); + + ImGui::End(); +} + +void cubos::engine::tools::assetExplorerPlugin(Cubos& cubos) +{ + cubos.addEvent(); + + cubos.addPlugin(imguiPlugin); + cubos.addPlugin(assetsPlugin); + + cubos.system(showAssets).tagged("cubos.imgui"); +} \ No newline at end of file diff --git a/tools/tesserato/CMakeLists.txt b/tools/tesserato/CMakeLists.txt index d1303c427..812ccdd71 100644 --- a/tools/tesserato/CMakeLists.txt +++ b/tools/tesserato/CMakeLists.txt @@ -8,3 +8,5 @@ set(TESSERATO_SOURCE add_executable(tesserato ${TESSERATO_SOURCE}) target_link_libraries(tesserato PUBLIC cubos-core cubos-engine) cubos_common_target_options(tesserato) + +target_compile_definitions(tesserato PUBLIC TESSERATO_ASSETS_FOLDER="${CMAKE_CURRENT_SOURCE_DIR}/assets") diff --git a/tools/tesserato/assets/example_asset.txt b/tools/tesserato/assets/example_asset.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tools/tesserato/assets/example_asset.txt.meta b/tools/tesserato/assets/example_asset.txt.meta new file mode 100644 index 000000000..c7afcf5e7 --- /dev/null +++ b/tools/tesserato/assets/example_asset.txt.meta @@ -0,0 +1,3 @@ +{ + "id": "059c16e7-a439-44c7-9bdc-6e069dba0c75" +} \ No newline at end of file diff --git a/tools/tesserato/assets/subfolder/example_asset_2.txt b/tools/tesserato/assets/subfolder/example_asset_2.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tools/tesserato/assets/subfolder/example_asset_2.txt.meta b/tools/tesserato/assets/subfolder/example_asset_2.txt.meta new file mode 100644 index 000000000..67bf6b2c7 --- /dev/null +++ b/tools/tesserato/assets/subfolder/example_asset_2.txt.meta @@ -0,0 +1,3 @@ +{ + "id": "059c16e7-a449-44c7-9bdc-6e069dba0c75" +} \ No newline at end of file diff --git a/tools/tesserato/assets/subfolder/subsubFolder/example_asset_3.txt b/tools/tesserato/assets/subfolder/subsubFolder/example_asset_3.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tools/tesserato/assets/subfolder/subsubFolder/example_asset_3.txt.meta b/tools/tesserato/assets/subfolder/subsubFolder/example_asset_3.txt.meta new file mode 100644 index 000000000..f26df0b12 --- /dev/null +++ b/tools/tesserato/assets/subfolder/subsubFolder/example_asset_3.txt.meta @@ -0,0 +1,3 @@ +{ + "id": "059c16e7-a449-44c7-0bdc-6e069dba0c75" +} \ No newline at end of file diff --git a/tools/tesserato/src/main.cpp b/tools/tesserato/src/main.cpp index fe2043fa3..cd0fcd4e9 100644 --- a/tools/tesserato/src/main.cpp +++ b/tools/tesserato/src/main.cpp @@ -1,19 +1,41 @@ #include #include +#include + +#include +#include + +#include using namespace cubos::engine; +using cubos::core::ecs::Write; +using cubos::core::ecs::Commands; -static void show() +static void mockCamera(Write camera, Commands cmds) { + camera->entities[0] = cmds.create() + .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F}) + .add(LocalToWorld{}) + .add(Position{{5.0F, 5.0F, -10.0F}}) + .add(Rotation{glm::quatLookAt(glm::vec3{0.0F, 0.0F, 1.0F}, glm::vec3{0.0F, 1.0F, 0.0F})}) + .entity(); + +} + +static void mockSettings(Write settings) { - ImGui::Begin("Editor"); - ImGui::End(); + settings->setString("assets.io.path", TESSERATO_ASSETS_FOLDER); } int main(int argc, char** argv) { Cubos cubos(argc, argv); cubos.addPlugin(imguiPlugin); - cubos.system(show).tagged("cubos.imgui"); + cubos.addPlugin(rendererPlugin); + cubos.addPlugin(tools::assetExplorerPlugin); + + cubos.startupSystem(mockCamera).tagged("setup"); + cubos.startupSystem(mockSettings).tagged("setup"); + cubos.run(); }