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)
{