From 6a29c5bdee04df4c7830c7a62da1f63d0bd9b3e8 Mon Sep 17 00:00:00 2001 From: OusmBlueNinja <89956790+OusmBlueNinja@users.noreply.github.com> Date: Sun, 11 May 2025 13:33:07 -0500 Subject: [PATCH] Added Project Manager mostly, just need to make a Asset Metadata save file so you can reload assets --- .idea/material_theme_project_new.xml | 4 +- imgui.ini | 127 +++--- src/assets/icons/folder-outline.png | Bin 0 -> 3670 bytes src/assets/icons/movie-open-outline.png | Bin 0 -> 6424 bytes src/src/Engine.cpp | 24 +- src/src/core/functions/ProjectManager.cpp | 465 +++++++++++++++++++-- src/src/core/functions/ProjectManager.h | 64 ++- src/src/core/functions/SceneSerializer.cpp | 23 +- src/src/core/utils/AssetManager.cpp | 20 + src/src/core/utils/AssetManager.h | 4 + src/src/core/utils/Logging.cpp | 2 +- 11 files changed, 614 insertions(+), 119 deletions(-) create mode 100644 src/assets/icons/folder-outline.png create mode 100644 src/assets/icons/movie-open-outline.png diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml index 79c85c6..5ce3305 100644 --- a/.idea/material_theme_project_new.xml +++ b/.idea/material_theme_project_new.xml @@ -3,7 +3,9 @@ diff --git a/imgui.ini b/imgui.ini index 82f4e72..eff096c 100644 --- a/imgui.ini +++ b/imgui.ini @@ -14,74 +14,74 @@ Size=1920,1158 Collapsed=0 [Window][Inspector] -Pos=1553,19 -Size=367,537 +Pos=1529,19 +Size=391,636 Collapsed=0 DockId=0x0000001B,0 [Window][Scene Tree] Pos=0,19 -Size=341,444 +Size=340,763 Collapsed=0 DockId=0x0000000F,0 [Window][Viewport] -Pos=343,19 -Size=1208,659 +Pos=342,19 +Size=1185,488 Collapsed=0 -DockId=0x00000017,0 +DockId=0x00000011,0 [Window][##MainMenuBar] -Size=1920,19 +Size=1280,19 Collapsed=0 [Window][Performance Info] -Pos=1628,680 -Size=292,268 +Pos=1587,794 +Size=333,220 Collapsed=0 -DockId=0x00000019,0 +DockId=0x00000015,0 [Window][Console] -Pos=343,680 -Size=1207,497 +Pos=342,509 +Size=1185,273 Collapsed=0 -DockId=0x00000013,0 +DockId=0x00000012,0 [Window][Tilemap Editor] Pos=265,19 Size=1263,674 Collapsed=0 -DockId=0x00000017,1 +DockId=0x00000011,1 [Window][Profiler] Pos=343,955 Size=1232,222 Collapsed=0 -DockId=0x00000011,0 +DockId=0x00000008,0 [Window][Profiler Timeline] Pos=265,69 Size=623,651 Collapsed=0 -DockId=0x00000015,1 +DockId=0x00000008,1 [Window][Profiler (Unity Style)] Pos=265,430 Size=623,290 Collapsed=0 -DockId=0x00000015,1 +DockId=0x00000008,1 [Window][Profiler Timeline View] Pos=265,526 Size=1263,651 Collapsed=0 -DockId=0x00000015,1 +DockId=0x00000008,1 [Window][Color Correction] -Pos=1628,950 -Size=292,227 +Pos=1587,1016 +Size=333,161 Collapsed=0 -DockId=0x0000001A,0 +DockId=0x00000016,0 [Window][Asset Browser] Pos=0,658 @@ -113,10 +113,10 @@ Collapsed=0 DockId=0x0000000E,0 [Window][Audio Output] -Pos=1552,680 -Size=74,497 +Pos=1529,794 +Size=56,383 Collapsed=0 -DockId=0x00000014,0 +DockId=0x00000019,0 [Window][Master Bus] Pos=1003,570 @@ -128,7 +128,7 @@ DockId=0x0000000D,0 Pos=0,465 Size=341,712 Collapsed=0 -DockId=0x00000010,0 +DockId=0x00000003,0 [Window][Import Preview] Pos=584,22 @@ -136,10 +136,10 @@ Size=550,695 Collapsed=0 [Window][Lua Globals] -Pos=1553,558 -Size=367,120 +Pos=1529,657 +Size=391,135 Collapsed=0 -DockId=0x0000001C,0 +DockId=0x00000013,0 [Window][Import Assets] Pos=626,263 @@ -151,6 +151,17 @@ Pos=298,22 Size=600,209 Collapsed=0 +[Window][File Explorer] +Pos=0,784 +Size=1527,393 +Collapsed=0 +DockId=0x0000001E,0 + +[Window][ConfirmClearScene] +Pos=808,551 +Size=304,75 +Collapsed=0 + [Table][0x96376740,2] RefScale=13 Column 0 Weight=1.0000 @@ -186,33 +197,35 @@ Column 1 Width=86 Column 2 Weight=1.0000 [Docking][Data] -DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1920,1158 Split=X - DockNode ID=0x00000005 Parent=0x11111111 SizeRef=989,1158 Split=X - DockNode ID=0x00000001 Parent=0x00000005 SizeRef=341,701 Split=Y Selected=0x12EF0F59 - DockNode ID=0x00000003 Parent=0x00000001 SizeRef=342,637 Split=Y Selected=0x12EF0F59 - DockNode ID=0x0000000F Parent=0x00000003 SizeRef=341,444 HiddenTabBar=1 Selected=0x12EF0F59 - DockNode ID=0x00000010 Parent=0x00000003 SizeRef=341,712 HiddenTabBar=1 Selected=0x30401527 - DockNode ID=0x00000004 Parent=0x00000001 SizeRef=342,519 HiddenTabBar=1 Selected=0x36AF052B - DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1577,701 Split=Y Selected=0xC450F867 - DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,659 Split=X Selected=0xC450F867 - DockNode ID=0x00000017 Parent=0x00000007 SizeRef=1208,860 CentralNode=1 HiddenTabBar=1 Selected=0xC450F867 - DockNode ID=0x00000018 Parent=0x00000007 SizeRef=367,860 Split=Y Selected=0x36DC96AB - DockNode ID=0x0000001B Parent=0x00000018 SizeRef=367,537 HiddenTabBar=1 Selected=0x36DC96AB - DockNode ID=0x0000001C Parent=0x00000018 SizeRef=367,120 HiddenTabBar=1 Selected=0x8CFF897F - DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,497 Split=X Selected=0xEA83D666 - DockNode ID=0x00000015 Parent=0x00000008 SizeRef=1283,172 Split=X Selected=0xEA83D666 - DockNode ID=0x00000011 Parent=0x00000015 SizeRef=1206,168 HiddenTabBar=1 Selected=0x9B5D3198 - DockNode ID=0x00000012 Parent=0x00000015 SizeRef=75,168 Split=X Selected=0x56009A08 - DockNode ID=0x00000013 Parent=0x00000012 SizeRef=1207,497 Selected=0xEA83D666 - DockNode ID=0x00000014 Parent=0x00000012 SizeRef=74,497 HiddenTabBar=1 Selected=0x56009A08 - DockNode ID=0x00000016 Parent=0x00000008 SizeRef=292,172 Split=Y Selected=0x3FC1A724 - DockNode ID=0x00000019 Parent=0x00000016 SizeRef=314,268 HiddenTabBar=1 Selected=0x3FC1A724 - DockNode ID=0x0000001A Parent=0x00000016 SizeRef=314,227 HiddenTabBar=1 Selected=0xA873C17F - DockNode ID=0x00000006 Parent=0x11111111 SizeRef=289,1158 Split=Y Selected=0x36DC96AB - DockNode ID=0x00000009 Parent=0x00000006 SizeRef=449,488 Split=Y Selected=0x36DC96AB - DockNode ID=0x0000000B Parent=0x00000009 SizeRef=449,556 Split=Y Selected=0x36DC96AB - DockNode ID=0x0000000D Parent=0x0000000B SizeRef=449,860 Selected=0x36DC96AB - DockNode ID=0x0000000E Parent=0x0000000B SizeRef=449,296 HiddenTabBar=1 Selected=0x9D7E7171 - DockNode ID=0x0000000C Parent=0x00000009 SizeRef=449,143 HiddenTabBar=1 Selected=0xB6C74292 - DockNode ID=0x0000000A Parent=0x00000006 SizeRef=449,211 HiddenTabBar=1 Selected=0xD83E5DD3 +DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1920,1158 Split=X + DockNode ID=0x00000005 Parent=0x11111111 SizeRef=989,1158 Split=X + DockNode ID=0x00000001 Parent=0x00000005 SizeRef=341,701 Split=Y Selected=0x12EF0F59 + DockNode ID=0x00000003 Parent=0x00000001 SizeRef=342,637 HiddenTabBar=1 Selected=0x12EF0F59 + DockNode ID=0x00000004 Parent=0x00000001 SizeRef=342,519 HiddenTabBar=1 Selected=0x36AF052B + DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1577,701 Split=Y Selected=0xC450F867 + DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,684 Split=X Selected=0xC450F867 + DockNode ID=0x00000017 Parent=0x00000007 SizeRef=1184,860 Split=Y Selected=0xC450F867 + DockNode ID=0x0000001D Parent=0x00000017 SizeRef=1208,763 Split=X Selected=0xC450F867 + DockNode ID=0x0000000F Parent=0x0000001D SizeRef=340,399 HiddenTabBar=1 Selected=0x12EF0F59 + DockNode ID=0x00000010 Parent=0x0000001D SizeRef=1185,399 Split=Y Selected=0xC450F867 + DockNode ID=0x00000011 Parent=0x00000010 SizeRef=1185,488 CentralNode=1 HiddenTabBar=1 Selected=0xC450F867 + DockNode ID=0x00000012 Parent=0x00000010 SizeRef=1185,273 HiddenTabBar=1 Selected=0xEA83D666 + DockNode ID=0x0000001E Parent=0x00000017 SizeRef=1208,393 HiddenTabBar=1 Selected=0x9C2B5678 + DockNode ID=0x00000018 Parent=0x00000007 SizeRef=391,860 Split=Y Selected=0x36DC96AB + DockNode ID=0x0000001B Parent=0x00000018 SizeRef=367,636 HiddenTabBar=1 Selected=0x36DC96AB + DockNode ID=0x0000001C Parent=0x00000018 SizeRef=367,520 Split=Y Selected=0x8CFF897F + DockNode ID=0x00000013 Parent=0x0000001C SizeRef=367,135 HiddenTabBar=1 Selected=0x8CFF897F + DockNode ID=0x00000014 Parent=0x0000001C SizeRef=367,383 Split=X Selected=0x56009A08 + DockNode ID=0x00000019 Parent=0x00000014 SizeRef=56,70 HiddenTabBar=1 Selected=0x56009A08 + DockNode ID=0x0000001A Parent=0x00000014 SizeRef=333,70 Split=Y Selected=0x3FC1A724 + DockNode ID=0x00000015 Parent=0x0000001A SizeRef=181,220 HiddenTabBar=1 Selected=0x3FC1A724 + DockNode ID=0x00000016 Parent=0x0000001A SizeRef=181,161 HiddenTabBar=1 Selected=0xA873C17F + DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,472 HiddenTabBar=1 Selected=0xEA83D666 + DockNode ID=0x00000006 Parent=0x11111111 SizeRef=289,1158 Split=Y Selected=0x36DC96AB + DockNode ID=0x00000009 Parent=0x00000006 SizeRef=449,488 Split=Y Selected=0x36DC96AB + DockNode ID=0x0000000B Parent=0x00000009 SizeRef=449,556 Split=Y Selected=0x36DC96AB + DockNode ID=0x0000000D Parent=0x0000000B SizeRef=449,860 Selected=0x36DC96AB + DockNode ID=0x0000000E Parent=0x0000000B SizeRef=449,296 HiddenTabBar=1 Selected=0x9D7E7171 + DockNode ID=0x0000000C Parent=0x00000009 SizeRef=449,143 HiddenTabBar=1 Selected=0xB6C74292 + DockNode ID=0x0000000A Parent=0x00000006 SizeRef=449,211 HiddenTabBar=1 Selected=0xD83E5DD3 diff --git a/src/assets/icons/folder-outline.png b/src/assets/icons/folder-outline.png new file mode 100644 index 0000000000000000000000000000000000000000..e0fc9ec8fe84e2152990bed45f7401c3ea1ba23d GIT binary patch literal 3670 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 AjQ{`u literal 0 HcmV?d00001 diff --git a/src/src/Engine.cpp b/src/src/Engine.cpp index 9de8f04..f74cd83 100644 --- a/src/src/Engine.cpp +++ b/src/src/Engine.cpp @@ -550,7 +550,10 @@ void Engine::Init() ProjectManager::Init(); Logger::LogVerbose("Init Script Core"); ScriptCore::Init(); - Logger::LogVerbose("Resverving Objects"); + + Logger::LogVerbose("Init Files Core"); + FileExplorer::Init(); + Logger::LogVerbose("Reserving Objects"); // These values were AI Generated. @@ -570,7 +573,7 @@ void Engine::Init() - ProjectManager::LoadProject("C:/Users/spenc/OneDrive/Desktop", "TestProject"); + //ProjectManager::LoadProject("C:/Users/spenc/OneDrive/Desktop", "TestProject"); } core::types::Vec2 ScreenToWorld(const core::types::Vec2 &screenPos, const core::types::Vec2 &viewportSize, const core::types::Vec2 &cameraPos, float zoom) @@ -757,7 +760,16 @@ void Engine::Run() ImGui::Separator(); ImGui::Spacing(); - + if (ImGui::MenuItem("Load Project")) + { + std::string file = OpenFileDialog(FileDialogType::Project); + Logger::LogInfo("Loading Project."); + if (!file.empty()) + { + ProjectManager::LoadProject(file); + } + selected = nullptr; + } if (ImGui::MenuItem("Create New Project")) { OpenNewProjectMenu = true; @@ -766,6 +778,8 @@ void Engine::Run() + + ImGui::Separator(); ImGui::Spacing(); @@ -915,6 +929,10 @@ void Engine::Run() ShowAssetBrowser(); DrawAudioPlayingList(); DrawImGuiWindow(); + FileExplorer::Update(); + FileExplorer::Show(nullptr); + FileExplorer::ProcessLoadQueue(); + diff --git a/src/src/core/functions/ProjectManager.cpp b/src/src/core/functions/ProjectManager.cpp index b85ae23..fbcd35f 100644 --- a/src/src/core/functions/ProjectManager.cpp +++ b/src/src/core/functions/ProjectManager.cpp @@ -1,10 +1,11 @@ -// ProjectManager.cpp - #include "ProjectManager.h" #include "../../core/utils/EngineConfig.h" #include "../../core/utils/Logging.h" #include "../../Engine.h" #include "../../core/utils/FileDialog.h" +#include "../../core/utils/utils.h" +#include "../../core/utils/AssetManager.h" + #include "SceneSerializer.h" #include @@ -16,6 +17,351 @@ #include + + + + + +bool FileExplorer::s_initialized = false; +std::string FileExplorer::SelectedPath; +fs::path FileExplorer::s_root; +fs::path FileExplorer::s_currentDir; +std::unordered_set FileExplorer::s_knownFiles; +const char* FileExplorer::ICONS_PATH = "./src/assets/icons/"; +unsigned int FileExplorer::s_folderIcon = 0; + +std::string FileExplorer::fileSearchQuery = ""; +bool FileExplorer::sortAscending = true; +int FileExplorer::sortMode = 0; +bool FileExplorer::showScenes = true; +bool FileExplorer::showImages = true; +bool FileExplorer::showAudio = true; +bool FileExplorer::showScripts = true; +bool FileExplorer::showOther = true; + +std::vector FileExplorer::s_loadQueue; +size_t FileExplorer::s_loadIndex = 0; +bool FileExplorer::s_loadingInit = false; + + +bool FileExplorer::Init() +{ + if (s_initialized) + return false; + + if (!ProjectManager::HasProject()) + return false; + + // Resolve and verify root… + s_root = fs::path(ProjectManager::ResolveResPath("res://")); + s_currentDir = s_root; + if (!fs::exists(s_root) || !fs::is_directory(s_root)) { + Logger::LogError("FileExplorer: invalid root path '%s'", s_root.string().c_str()); + return false; + } + + s_folderIcon = EngineLoadTextureIfNeeded(std::string(ICONS_PATH) + "folder-outline.png"); + + std::error_code ec; + fs::recursive_directory_iterator it(s_root, fs::directory_options::skip_permission_denied, ec); + fs::recursive_directory_iterator end; + for (; it != end; it.increment(ec)) { + if (ec) { + Logger::LogWarning("FileExplorer: skipping '%s': %s", + it->path().string().c_str(), + ec.message().c_str()); + ec.clear(); + continue; + } + if (it->is_regular_file()) + s_loadQueue.push_back(it->path()); + } + + s_initialized = true; + return true; +} + + + +void FileExplorer::Show(bool* p_open) +{ + if (!s_initialized) return; + if (!ImGui::Begin("File Explorer", p_open, + ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_HorizontalScrollbar)) + { + ImGui::End(); + return; + } + + // --- Left pane: folder tree --- + ImGui::BeginChild("##FolderPane", ImVec2(250, 0), true); + ImGui::TextUnformatted("res://"); + ImGui::Separator(); + DrawFolderTree(s_root); + ImGui::EndChild(); + + ImGui::SameLine(); + + // --- Right pane: content + toolbar --- + ImGui::BeginChild("##ContentPane", ImVec2(0, 0), false); + + // Filters / Search + if (ImGui::Button("Filters / Sort")) ImGui::OpenPopup("FileFilterPopup"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(200); + char buf[256]; + strncpy(buf, fileSearchQuery.c_str(), sizeof(buf)); + buf[sizeof(buf)-1] = '\0'; + if (ImGui::InputTextWithHint("##Search", "Search...", buf, sizeof(buf))) + fileSearchQuery = buf; + + if (ImGui::BeginPopup("FileFilterPopup")) { + ImGui::Text("Sort By:"); + if (ImGui::Selectable("Name", sortMode == 0)) sortMode = 0; + if (ImGui::Selectable("Type", sortMode == 1)) sortMode = 1; + ImGui::Checkbox("Ascending", &sortAscending); + ImGui::Separator(); + ImGui::Text("Type:"); + ImGui::Checkbox("Scenes", &showScenes); + ImGui::Checkbox("Images", &showImages); + ImGui::Checkbox("Audio", &showAudio); + ImGui::Checkbox("Scripts", &showScripts); + ImGui::Checkbox("Other", &showOther); + ImGui::EndPopup(); + } + + ImGui::Separator(); + + // “Up” button + if (s_currentDir != s_root) { + if (ImGui::Button("Up")) s_currentDir = s_currentDir.parent_path(); + ImGui::SameLine(); + } + + // Current path display + fs::path rel = fs::relative(s_currentDir, s_root); + std::string displayPath = "res://" + + (rel.empty() ? std::string() : rel.generic_string() + "/"); + ImGui::TextUnformatted(displayPath.c_str()); + ImGui::Separator(); + + // Gather & filter + std::vector entries; + for (auto &e : fs::directory_iterator(s_currentDir)) { + if (!e.is_directory()) { + AssetType t = AssetManager::AssetTypeFromPath(e.path().string()); + switch (t) { + case AssetType::Scene: if (!showScenes) continue; break; + case AssetType::Image: if (!showImages) continue; break; + case AssetType::Audio: if (!showAudio) continue; break; + case AssetType::Script: if (!showScripts) continue; break; + default: if (!showOther) continue; break; + } + } + if (!fileSearchQuery.empty() && + e.path().filename().string().find(fileSearchQuery) == std::string::npos) + continue; + entries.push_back(e); + } + + // Sort + std::sort(entries.begin(), entries.end(), [&](auto &a, auto &b) { + if (sortMode == 1) { + bool da = a.is_directory(), db = b.is_directory(); + if (da != db) return sortAscending ? da > db : da < db; + return sortAscending + ? a.path().extension() < b.path().extension() + : a.path().extension() > b.path().extension(); + } + return sortAscending + ? a.path().filename() < b.path().filename() + : a.path().filename() > b.path().filename(); + }); + + // Icon grid setup + constexpr float iconSize = 64.0f, padding = 8.0f; + float avail = ImGui::GetContentRegionAvail().x; + int cols = std::max(1, int(avail / (iconSize + padding))); + ImGui::Columns(cols, nullptr, false); + + // Draw each entry + for (auto &e : entries) { + fs::path p = e.path(); + std::string pathStr = p.string(); + AssetType type = AssetManager::AssetTypeFromPath(pathStr); + + ImGui::PushID(pathStr.c_str()); + + // --- IMAGE THUMBNAIL w/ InvisibleButton for clicks --- + if (type == AssetType::Image) { + if (auto* asset = AssetManager::GetAssetByPath(pathStr)) + if (asset->type == AssetType::Image) { + auto* img = dynamic_cast(asset); + if (img) { + if (ImGui::ImageButton("##Image", (ImTextureID)(intptr_t)img->textureID, ImVec2(iconSize, iconSize))) + { + s_currentDir = p; + } + } + } + } + else if (e.is_directory()) { + if (ImGui::ImageButton("##item", + (ImTextureID)(intptr_t)s_folderIcon, + ImVec2(iconSize, iconSize))) + { + s_currentDir = p; + } + } + else { + std::string label; + switch (type) { + case AssetType::Prefab: label = "Prefab"; break; + case AssetType::Scene: label = "Scene"; break; + case AssetType::Audio: label = "Audio"; break; + case AssetType::Script: label = "Script"; break; + case AssetType::Video: label = "Video"; break; + case AssetType::Font: label = "Font"; break; + case AssetType::Shader: label = "Shader"; break; + default: + label = p.extension().string(); + if (!label.empty() && label.front()=='.') + label.erase(0,1); + break; + } + if (ImGui::Button(label.c_str(), + ImVec2(iconSize, iconSize))) + { + SelectedPath = pathStr; + } + } + + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID)) { + if (auto* asset = AssetManager::GetAssetByPath(pathStr)) { + if (type == AssetType::Image) + ImGui::SetDragDropPayload(ASSET_TEXTURE, + &asset->uaid, + sizeof(asset->uaid)); + else if (type == AssetType::Prefab) + ImGui::SetDragDropPayload(ASSET_PREFAB, + &asset->uaid, + sizeof(asset->uaid)); + ImGui::TextUnformatted(p.filename().string().c_str()); + } + ImGui::EndDragDropSource(); + } + + if (ImGui::BeginPopupContextItem()) { + if (e.is_directory() && ImGui::MenuItem("Open")) + s_currentDir = p; + if (!e.is_directory() && ImGui::MenuItem("Open File")) + SelectedPath = pathStr; + if (ImGui::MenuItem("Copy Path")) + ImGui::SetClipboardText(pathStr.c_str()); + ImGui::EndPopup(); + } + + ImGui::TextWrapped("%s", p.filename().string().c_str()); + ImGui::NextColumn(); + ImGui::PopID(); + } + + ImGui::Columns(1); + ImGui::EndChild(); + ImGui::End(); +} + + + + +void FileExplorer::Update() +{ + if (!s_initialized) + { + Init(); + return; + } + + std::error_code ec; + std::unordered_set currentFiles; + for (auto it = fs::recursive_directory_iterator(s_root, + fs::directory_options::skip_permission_denied, ec), + end = fs::recursive_directory_iterator{}; + it != end; it.increment(ec)) + { + if (ec) { + Logger::LogWarning("FileExplorer: skipping '%s': %s", + it->path().string().c_str(), + ec.message().c_str()); + ec.clear(); + continue; + } + if (!it->is_regular_file()) continue; + + auto pathStr = it->path().string(); + currentFiles.insert(pathStr); + + if (!s_knownFiles.count(pathStr)) { + s_knownFiles.insert(pathStr); + s_loadQueue.push_back(it->path()); + Logger::LogVerbose("FileExplorer: added '%s'", pathStr.c_str()); + } + } + + // detect deletions + for (auto it = s_knownFiles.begin(); it != s_knownFiles.end(); ) + { + if (!currentFiles.count(*it)) { + Logger::LogVerbose("FileExplorer: removed '%s'", it->c_str()); + AssetManager::GetAssetByPath(*it); + it = s_knownFiles.erase(it); + } + else ++it; + } +} + +bool FileExplorer::LoadingDone() +{ + return s_initialized && s_loadIndex >= s_loadQueue.size(); +} + +void FileExplorer::DrawFolderTree(const fs::path &path) +{ + for (auto &e : fs::directory_iterator(path)) { + if (!e.is_directory()) continue; + auto &d = e.path(); + ImGui::PushID(d.string().c_str()); + ImGui::Image((ImTextureID)(intptr_t)s_folderIcon, ImVec2(16,16)); ImGui::SameLine(); + bool open = ImGui::TreeNodeEx(d.string().c_str(), ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_SpanAvailWidth, "%s", d.filename().string().c_str()); + if (ImGui::IsItemClicked()) s_currentDir = d; + if (open) { DrawFolderTree(d); ImGui::TreePop(); } + ImGui::PopID(); + } +} + +void FileExplorer::ProcessLoadQueue() +{ + while (!s_loadQueue.empty()) { + fs::path p = s_loadQueue.back(); + s_loadQueue.pop_back(); + + // Load the asset and get the type,... Long way... + AssetManager::LoadAssetAsync(p.string(), AssetManager::AssetTypeFromExtension(AssetManager::GetFileExtension(p.string()))); + + Logger::LogVerbose("FileExplorer: imported '%s'", p.string().c_str()); + } +} + + +std::string FileExplorer::IconFileForPath(const fs::path &path) +{ + auto ext = path.extension().string(); + if (ext == ".cene") return "movie-open-outline.png"; + return "error.png"; +} + + + namespace fs = std::filesystem; std::string ProjectManager::s_currentProjectPath; @@ -102,7 +448,7 @@ bool CreateDirectories(const fs::path &baseDir) "Scenes", "Images", "Sounds", - "Fomts", + "Fonts", "Shaders", "Scripts", "Videos", @@ -129,25 +475,49 @@ bool CreateDirectories(const fs::path &baseDir) return allOk; } +bool ProjectManager::HasProject() { + if (s_currentProjectPath.empty() || s_currentProjectName.empty()) + { + return false; + + } + return true; +} + + + std::string ProjectManager::ResolveResPath(const std::string &resPath) { constexpr const char *prefix = "res://"; + // if it’s not a “res://” path, just return it if (resPath.rfind(prefix, 0) != 0) return resPath; - if (s_currentProjectPath.empty() || s_currentProjectName.empty()) + if (s_currentProjectPath.empty()) { - Logger::LogError("Cannot resolve res path: 'project not loaded!'"); + Logger::LogError("Cannot resolve res path: project not loaded!"); return resPath; } - fs::path baseDir = fs::path(s_currentProjectPath) / s_currentProjectName; - std::string relativePart = resPath.substr(strlen(prefix)); - fs::path fullPath = baseDir / relativePart; + // start from whatever s_currentProjectPath holds + fs::path baseDir{s_currentProjectPath}; - return fullPath.lexically_normal().string(); + // only append the project name if it isn't already the last path component + if (!s_currentProjectName.empty() && + baseDir.filename().string() != s_currentProjectName) + { + baseDir /= s_currentProjectName; + } + + // drop the "res://" prefix + std::string relativePart = resPath.substr(strlen(prefix)); + // build & normalize + fs::path fullPath = (baseDir / relativePart).lexically_normal(); + + return fullPath.string(); } + bool ProjectManager::Init() { s_currentProjectPath.clear(); @@ -157,63 +527,60 @@ bool ProjectManager::Init() return true; } -bool ProjectManager::LoadProject(const std::string &projectPath, - const std::string &projectName) +bool ProjectManager::LoadProject(const std::string &projectFilePath) { - fs::path baseDir = fs::path(projectPath) / projectName; - fs::path projFile = baseDir / (projectName + ".cproj"); - - if (!fs::exists(projFile)) - { - Logger::LogInfo("Project '%s' not found at '%s' creating new one.", - projectName.c_str(), projectPath.c_str()); - return SaveProject(projectPath, projectName); + fs::path projFile{ projectFilePath }; + if (projFile.extension() != ".cproj" || !fs::exists(projFile)) { + Logger::LogError("Project file not found or invalid: '%s'", + projectFilePath.c_str()); + return false; } + fs::path baseDir = projFile.parent_path(); + std::string projectName = projFile.stem().string(); + YAML::Node config; - try - { + try { config = YAML::LoadFile(projFile.string()); } - catch (const YAML::Exception &e) - { + catch (const YAML::Exception &e) { Logger::LogError("Failed to parse project file '%s': %s", projFile.string().c_str(), e.what()); return false; } - std::string savedName = config["Name"].as(projectName); - std::string createdDate = config["CreatedDate"].as("unknown"); - std::string s_defaultScene = config["s_defaultScene"].as("s_defaultScene"); + // Read settings + std::string savedName = config["Name"].as(projectName); + std::string defaultScene = config["s_defaultScene"].as(""); - Logger::LogInfo("Loading Project: '%s", savedName.c_str()); + Logger::LogInfo("Loading Project: '%s' from '%s'", + savedName.c_str(), projFile.string().c_str()); - s_currentProjectPath = projectPath; + s_currentProjectPath = baseDir.string(); s_currentProjectName = savedName; - std::string resScenePath = config["s_defaultScene"].as(""); + if (!defaultScene.empty()) { + s_defaultScene = ResolveResPath(defaultScene); + Logger::LogDebug("Loading Default Scene: %s", s_defaultScene.c_str()); - if (!resScenePath.empty()) - { - s_defaultScene = ResolveResPath(resScenePath); - Logger::LogDebug("Loading Scene: %s", s_defaultScene.c_str()); - - if (!std::filesystem::exists(s_defaultScene)) - { - Logger::LogError("Scene file does not exist: %s", s_defaultScene.c_str()); + if (!fs::exists(s_defaultScene)) { + Logger::LogError("Default scene does not exist: %s", s_defaultScene.c_str()); return false; } SceneLoader::LoadScene(s_defaultScene); } - Logger::LogInfo("Loaded project '%s'", savedName.c_str()); + Logger::LogInfo("Successfully loaded project '%s'", savedName.c_str()); CreateDirectories(baseDir); + SceneLoader::LoadScene(s_defaultScene); + return true; } + bool ProjectManager::CreateProject(const std::string &projectPath, const std::string &projectName) { @@ -228,14 +595,11 @@ bool ProjectManager::CreateProject(const std::string &projectPath, return false; } - // Set current project path before scene creation s_currentProjectPath = baseDir.string(); s_currentProjectName = projectName; - // Create initial scene - fs::path scenePath = baseDir / "Assets" / "Scenes" / "main.cene"; + fs::path scenePath = baseDir / "Assets" / "Scenes" / projectName / ".cene"; - SceneLoader::SaveScene(scenePath.string()); s_defaultScene = scenePath.string(); @@ -275,6 +639,9 @@ bool ProjectManager::CreateProject(const std::string &projectPath, CreateDirectories(baseDir); + SceneLoader::SaveScene(scenePath.string()); + + SceneLoader::LoadScene(scenePath.string()); return true; @@ -351,8 +718,16 @@ const std::string &ProjectManager::GetCurrentProjectName() const std::string &ProjectManager::GetCurrentAssetsPath() { static std::string assetsPath; - fs::path p = fs::path(s_currentProjectPath) / s_currentProjectName / "Assets"; - assetsPath = p.string(); - return assetsPath; + fs::path baseDir{s_currentProjectPath}; + if (!s_currentProjectName.empty() && + baseDir.filename().string() != s_currentProjectName) + { + baseDir /= s_currentProjectName; + } + + fs::path assetDir = (baseDir / "Assets").lexically_normal(); + assetsPath = assetDir.string(); + return assetsPath; } + diff --git a/src/src/core/functions/ProjectManager.h b/src/src/core/functions/ProjectManager.h index 2d7eae1..eb48a3b 100644 --- a/src/src/core/functions/ProjectManager.h +++ b/src/src/core/functions/ProjectManager.h @@ -2,6 +2,65 @@ #include #include +#include +#include + + + + +namespace fs = std::filesystem; + +class FileExplorer +{ +public: + // Shows the explorer window (call every frame) + static void Show(bool* p_open = nullptr); + static bool Init(); + + static void Update(); + static void ProcessLoadQueue(); + + + + static bool LoadingDone(); + + static const std::vector& GetLoadQueue() { return s_loadQueue; } + + + static std::string SelectedPath; + +private: + static bool s_initialized; + + // File browsing state + static fs::path s_root; + static fs::path s_currentDir; + + static std::unordered_set s_knownFiles; // <-- new + + + // Icons + static const char* ICONS_PATH; + static unsigned int s_folderIcon; + + // Filters & view state (unchanged)... + static std::string fileSearchQuery; + static bool sortAscending; + static int sortMode; + static bool showScenes, showImages, showAudio, showScripts, showOther; + + // Asset loading queue + static std::vector s_loadQueue; + static size_t s_loadIndex; + static bool s_loadingInit; + + static std::string IconFileForPath(const fs::path &path); + static void DrawFolderTree(const fs::path &path); + + // Initializes file queue by scanning res:// recursively + static void InitLoading(); +}; + class ProjectManager { @@ -10,8 +69,7 @@ public: /// Load an existing project at projectPath/projectName. /// Reads the .cproj, sets current path/name, and ensures folders. - static bool LoadProject(const std::string& projectPath, - const std::string& projectName); + static bool LoadProject(const std::string& projectFilePath); /// Save (or create) a project at projectPath/projectName. /// Writes the .cproj YAML, sets current path/name, and ensures folders. @@ -25,6 +83,8 @@ public: static void ShowCreateProjectPopup(); + static bool HasProject(); + static const std::string& GetCurrentProjectPath(); static const std::string& GetCurrentProjectName(); diff --git a/src/src/core/functions/SceneSerializer.cpp b/src/src/core/functions/SceneSerializer.cpp index ff38775..d055a90 100644 --- a/src/src/core/functions/SceneSerializer.cpp +++ b/src/src/core/functions/SceneSerializer.cpp @@ -43,6 +43,7 @@ void SceneLoader::SaveScene(const std::string &path) YAML::Emitter out; YAML::Emitter sceneData; + // Serialize object list only sceneData << YAML::BeginSeq; for (const auto &obj : objects) @@ -57,6 +58,8 @@ void SceneLoader::SaveScene(const std::string &path) for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) hashHex << std::hex << std::setw(2) << std::setfill('0') << static_cast(hash[i]); + + out << YAML::BeginMap; out << YAML::Key << "engine_version" << YAML::Value << g_engineConfig.version; out << YAML::Key << "scene_name" << YAML::Value << std::filesystem::path(path).stem().string(); @@ -75,7 +78,7 @@ void SceneLoader::SaveScene(const std::string &path) out << YAML::Key << "threshold" << YAML::Value << Renderer::GetColorCorrection()->threshold; out << YAML::EndMap; - AssetManager::Save(out); + //AssetManager::Save(out); out << YAML::EndMap; @@ -150,15 +153,15 @@ void SceneLoader::LoadScene(const std::string &path) Logger::LogWarning("Scene hash does not match! File may be corrupted or tampered."); } - if (root["Assets"]) - { - currentStep = "Loading Assets"; - currentDetail = "Parsing asset data..."; - loadingUI.Update(currentStep, currentDetail, 0.05f); - - Logger::LogDebug("Loading Assets"); - AssetManager::Load(root["Assets"]); - } + //if (root["Assets"]) + //{ + // currentStep = "Loading Assets"; + // currentDetail = "Parsing asset data..."; + // loadingUI.Update(currentStep, currentDetail, 0.05f); + // + // Logger::LogDebug("Loading Assets"); + // AssetManager::Load(root["Assets"]); + //} Logger::LogDebug("Reseting Scene."); currentStep = "Clearing Previous Scene"; diff --git a/src/src/core/utils/AssetManager.cpp b/src/src/core/utils/AssetManager.cpp index 31bde10..9301409 100644 --- a/src/src/core/utils/AssetManager.cpp +++ b/src/src/core/utils/AssetManager.cpp @@ -4,6 +4,7 @@ #include #include "../audio/AudioEngine.h" #include "LoadingWindow.h" +#include #define STB_IMAGE_IMPLEMENTATION #include #include "../../Entitys/Object.h" @@ -11,12 +12,25 @@ #include #include FT_FREETYPE_H +namespace fs = std::filesystem; + + std::unordered_map> AssetManager::s_Assets; std::unordered_map AssetManager::s_PathToUAID; uint64_t AssetManager::s_NextUAID = 1; +std::string AssetManager::GetFileExtension(const std::string& filepath) +{ + std::string ext = fs::path(filepath).extension().string(); // ".PNG" + if (!ext.empty() && ext.front() == '.') + ext.erase(0, 1); // "PNG" + std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); + return ext; // "png" +} + + AssetType AssetManager::AssetTypeFromExtension(std::string ext) { @@ -75,6 +89,12 @@ AssetType AssetManager::AssetTypeFromExtension(std::string ext) +AssetType AssetManager::AssetTypeFromPath(const std::string& filepath) +{ + return AssetTypeFromExtension(GetFileExtension(filepath)); +} + + const char *MiniaudioResultToString(ma_result result) { diff --git a/src/src/core/utils/AssetManager.h b/src/src/core/utils/AssetManager.h index 6030066..7d79760 100644 --- a/src/src/core/utils/AssetManager.h +++ b/src/src/core/utils/AssetManager.h @@ -157,8 +157,12 @@ public: static uint64_t GenerateUAID(); + + static std::string GetFileExtension(const std::string& filepath); static AssetType AssetTypeFromExtension(std::string ext); + static AssetType AssetTypeFromPath(const std::string& filepath); + private: static std::unordered_map> s_Assets; static std::unordered_map s_PathToUAID; diff --git a/src/src/core/utils/Logging.cpp b/src/src/core/utils/Logging.cpp index 05f6dcf..1a7fef0 100644 --- a/src/src/core/utils/Logging.cpp +++ b/src/src/core/utils/Logging.cpp @@ -56,7 +56,7 @@ bool Logger::s_ShowWarning = true; bool Logger::s_ShowError = true; bool Logger::s_ShowDebug = false; bool Logger::s_ShowVerbose = false; -bool Logger::s_PrintToTerminal = false; +bool Logger::s_PrintToTerminal = true; const char *Logger::ToString(Level level) {