From e7bf00516be9bdf9af4b06962783a8d2d0db5b53 Mon Sep 17 00:00:00 2001 From: OusmBlueNinja <89956790+OusmBlueNinja@users.noreply.github.com> Date: Sat, 10 May 2025 15:07:03 -0500 Subject: [PATCH] Added AutoLoad Projects --- imgui.ini | 36 ++-- remake/build.log | 5 +- src/src/Engine.cpp | 219 +------------------ src/src/Engine.h | 3 +- src/src/core/audio/AudioEngine.cpp | 22 +- src/src/core/functions/ProjectManager.cpp | 64 +++++- src/src/core/functions/ProjectManager.h | 5 + src/src/core/functions/SceneSerializer.cpp | 234 +++++++++++++++++++++ src/src/core/functions/SceneSerializer.h | 11 + src/src/editor/windows/AssetBrowser.cpp | 2 + 10 files changed, 347 insertions(+), 254 deletions(-) create mode 100644 src/src/core/functions/SceneSerializer.cpp create mode 100644 src/src/core/functions/SceneSerializer.h diff --git a/imgui.ini b/imgui.ini index 92b3ede..94954b8 100644 --- a/imgui.ini +++ b/imgui.ini @@ -10,24 +10,24 @@ Collapsed=1 [Window][WindowOverViewport_11111111] Pos=0,19 -Size=1920,1158 +Size=1280,701 Collapsed=0 [Window][Inspector] -Pos=1553,19 -Size=367,537 +Pos=913,19 +Size=367,163 Collapsed=0 DockId=0x0000001B,0 [Window][Scene Tree] Pos=0,19 -Size=341,444 +Size=341,268 Collapsed=0 DockId=0x0000000F,0 [Window][Viewport] Pos=343,19 -Size=1208,659 +Size=568,202 Collapsed=0 DockId=0x00000017,0 @@ -36,14 +36,14 @@ Size=1280,19 Collapsed=0 [Window][Performance Info] -Pos=1628,680 -Size=292,268 +Pos=1107,223 +Size=173,268 Collapsed=0 DockId=0x00000019,0 [Window][Console] -Pos=343,680 -Size=1206,497 +Pos=343,223 +Size=716,497 Collapsed=0 DockId=0x00000013,0 @@ -78,8 +78,8 @@ Collapsed=0 DockId=0x00000015,1 [Window][Color Correction] -Pos=1628,950 -Size=292,227 +Pos=1107,493 +Size=173,227 Collapsed=0 DockId=0x0000001A,0 @@ -113,8 +113,8 @@ Collapsed=0 DockId=0x0000000E,0 [Window][Audio Output] -Pos=1551,680 -Size=75,497 +Pos=1061,223 +Size=44,497 Collapsed=0 DockId=0x00000012,0 @@ -125,8 +125,8 @@ Collapsed=0 DockId=0x0000000D,0 [Window][Resources] -Pos=0,465 -Size=341,712 +Pos=0,289 +Size=341,431 Collapsed=0 DockId=0x00000010,0 @@ -136,8 +136,8 @@ Size=550,695 Collapsed=0 [Window][Lua Globals] -Pos=1553,558 -Size=367,120 +Pos=913,184 +Size=367,37 Collapsed=0 DockId=0x0000001C,0 @@ -181,7 +181,7 @@ Column 1 Width=86 Column 2 Weight=1.0000 [Docking][Data] -DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1920,1158 Split=X +DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1280,701 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 diff --git a/remake/build.log b/remake/build.log index 88fd368..ae69871 100644 --- a/remake/build.log +++ b/remake/build.log @@ -1,2 +1,3 @@ -[COMPILE] g++ -std=c++20 -Wall -g -DGLM_ENABLE_EXPERIMENTAL -O2 -static -static-libstdc++ -static-libgcc -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -Isrc/vendor/xxhash -Isrc/vendor/miniaudio -Isrc/vendor/imguizmo -IC:/msys64/mingw64/include -IC:\msys64\mingw64\lib\libyaml-cpp.a -Isrc\vendor\imgui -MMD -MP -c src\src\core\functions\ProjectManager.cpp -o src\build\core\functions\ProjectManager.o -[LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\AnimationComponent.o src\build\Components\AudioPlayerComponent.o src\build\Components\CameraComponent.o src\build\Components\LightComponent.o src\build\Components\ParticleComponent.o src\build\Components\PathFollowerComponent.o src\build\Components\PhysicsComponent.o src\build\Components\ScriptComponent.o src\build\Components\SpriteComponent.o src\build\Components\TextComonent.o src\build\Components\TilemapComponent.o src\build\core\audio\AudioEngine.o src\build\core\functions\Prefab.o src\build\core\functions\ProjectManager.o src\build\core\functions\ScenePacker.o src\build\core\scripts\LuaGlobalBridge.o src\build\core\scripts\ScriptCore.o src\build\core\utils\AssetManager.o src\build\core\utils\EngineConfig.o src\build\core\utils\ExceptionHandler.o src\build\core\utils\FileDialog.o src\build\core\utils\input.o src\build\core\utils\LoadingWindow.o src\build\core\utils\Logging.o src\build\core\utils\Popup.o src\build\core\utils\Profiler.o src\build\core\utils\Texture.o src\build\core\utils\utils.o src\build\editor\utils\Themes.o src\build\editor\windows\AssetBrowser.o src\build\editor\windows\AudioInfo.o src\build\editor\windows\Inspector.o src\build\editor\windows\LuaGlobals.o src\build\editor\windows\SceneTree.o src\build\Entitys\Object.o src\build\utils\GameObjectsList.o src\build\utils\Shader.o src\build\utils\UID.o src\build\lapi.o src\build\lauxlib.o src\build\lbaselib.o src\build\lcode.o src\build\lcorolib.o src\build\lctype.o src\build\ldblib.o src\build\ldebug.o src\build\ldo.o src\build\ldump.o src\build\lfunc.o src\build\lgc.o src\build\linit.o src\build\liolib.o src\build\llex.o src\build\lmathlib.o src\build\lmem.o src\build\loadlib.o src\build\lobject.o src\build\lopcodes.o src\build\loslib.o src\build\lparser.o src\build\lstate.o src\build\lstring.o src\build\lstrlib.o src\build\ltable.o src\build\ltablib.o src\build\ltm.o src\build\lua.o src\build\luac.o src\build\lundump.o src\build\lutf8lib.o src\build\lvm.o src\build\lzio.o src\build\imgui.o src\build\imgui_demo.o src\build\imgui_draw.o src\build\imgui_impl_glfw.o src\build\imgui_impl_opengl3.o src\build\imgui_tables.o src\build\imgui_widgets.o src\build\aabb.o src\build\arena_allocator.o src\build\array.o src\build\bitset.o src\build\body.o src\build\broad_phase.o src\build\constraint_graph.o src\build\contact.o src\build\contact_solver.o src\build\core.o src\build\distance.o src\build\distance_joint.o src\build\dynamic_tree.o src\build\geometry.o src\build\hull.o src\build\id_pool.o src\build\island.o src\build\joint.o src\build\manifold.o src\build\math_functions.o src\build\motor_joint.o src\build\mouse_joint.o src\build\mover.o src\build\prismatic_joint.o src\build\revolute_joint.o src\build\sensor.o src\build\shape.o src\build\solver.o src\build\solver_set.o src\build\table.o src\build\timer.o src\build\types.o src\build\weld_joint.o src\build\wheel_joint.o src\build\world.o src\build\xxhash.o src\build\miniaudio.o src\build\ImGuizmo.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto -ldbghelp -lz -lfreetype +[COMPILE] g++ -std=c++20 -Wall -g -DGLM_ENABLE_EXPERIMENTAL -O2 -static -static-libstdc++ -static-libgcc -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -Isrc/vendor/xxhash -Isrc/vendor/miniaudio -Isrc/vendor/imguizmo -IC:/msys64/mingw64/include -IC:\msys64\mingw64\lib\libyaml-cpp.a -Isrc\vendor\imgui -MMD -MP -c src\src\core\audio\AudioEngine.cpp -o src\build\core\audio\AudioEngine.o +[LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\AnimationComponent.o src\build\Components\AudioPlayerComponent.o src\build\Components\CameraComponent.o src\build\Components\LightComponent.o src\build\Components\ParticleComponent.o src\build\Components\PathFollowerComponent.o src\build\Components\PhysicsComponent.o src\build\Components\ScriptComponent.o src\build\Components\SpriteComponent.o src\build\Components\TextComonent.o src\build\Components\TilemapComponent.o src\build\core\audio\AudioEngine.o src\build\core\functions\Prefab.o src\build\core\functions\ProjectManager.o src\build\core\functions\ScenePacker.o src\build\core\functions\SceneSerializer.o src\build\core\scripts\LuaGlobalBridge.o src\build\core\scripts\ScriptCore.o src\build\core\utils\AssetManager.o src\build\core\utils\EngineConfig.o src\build\core\utils\ExceptionHandler.o src\build\core\utils\FileDialog.o src\build\core\utils\input.o src\build\core\utils\LoadingWindow.o src\build\core\utils\Logging.o src\build\core\utils\Popup.o src\build\core\utils\Profiler.o src\build\core\utils\Texture.o src\build\core\utils\utils.o src\build\editor\utils\Themes.o src\build\editor\windows\AssetBrowser.o src\build\editor\windows\AudioInfo.o src\build\editor\windows\Inspector.o src\build\editor\windows\LuaGlobals.o src\build\editor\windows\SceneTree.o src\build\Entitys\Object.o src\build\utils\GameObjectsList.o src\build\utils\Shader.o src\build\utils\UID.o src\build\lapi.o src\build\lauxlib.o src\build\lbaselib.o src\build\lcode.o src\build\lcorolib.o src\build\lctype.o src\build\ldblib.o src\build\ldebug.o src\build\ldo.o src\build\ldump.o src\build\lfunc.o src\build\lgc.o src\build\linit.o src\build\liolib.o src\build\llex.o src\build\lmathlib.o src\build\lmem.o src\build\loadlib.o src\build\lobject.o src\build\lopcodes.o src\build\loslib.o src\build\lparser.o src\build\lstate.o src\build\lstring.o src\build\lstrlib.o src\build\ltable.o src\build\ltablib.o src\build\ltm.o src\build\lua.o src\build\luac.o src\build\lundump.o src\build\lutf8lib.o src\build\lvm.o src\build\lzio.o src\build\imgui.o src\build\imgui_demo.o src\build\imgui_draw.o src\build\imgui_impl_glfw.o src\build\imgui_impl_opengl3.o src\build\imgui_tables.o src\build\imgui_widgets.o src\build\aabb.o src\build\arena_allocator.o src\build\array.o src\build\bitset.o src\build\body.o src\build\broad_phase.o src\build\constraint_graph.o src\build\contact.o src\build\contact_solver.o src\build\core.o src\build\distance.o src\build\distance_joint.o src\build\dynamic_tree.o src\build\geometry.o src\build\hull.o src\build\id_pool.o src\build\island.o src\build\joint.o src\build\manifold.o src\build\math_functions.o src\build\motor_joint.o src\build\mouse_joint.o src\build\mover.o src\build\prismatic_joint.o src\build\revolute_joint.o src\build\sensor.o src\build\shape.o src\build\solver.o src\build\solver_set.o src\build\table.o src\build\timer.o src\build\types.o src\build\weld_joint.o src\build\wheel_joint.o src\build\world.o src\build\xxhash.o src\build\miniaudio.o src\build\ImGuizmo.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto -ldbghelp -lz -lfreetype +[ERROR] Interrupted by user. diff --git a/src/src/Engine.cpp b/src/src/Engine.cpp index 473ddd9..6d88530 100644 --- a/src/src/Engine.cpp +++ b/src/src/Engine.cpp @@ -20,8 +20,11 @@ #include "core/utils/EngineConfig.h" + #include "core/functions/Prefab.h" #include "core/functions/ProjectManager.h" +#include "core/functions/SceneSerializer.h" + #include "utils/GameObjectsList.h" #include "core/utils/Profiler.h" @@ -727,7 +730,7 @@ void Engine::Run() { std::string file = CreateFileDialog(FileDialogType::Scenes); if (!file.empty()) - SaveScene(file); + SceneLoader::SaveScene(file); selected = nullptr; } if (ImGui::MenuItem("Load Scene")) @@ -735,7 +738,7 @@ void Engine::Run() std::string file = OpenFileDialog(FileDialogType::Scenes); Logger::LogInfo("Loading Scene."); if (!file.empty()) - LoadScene(file); + SceneLoader::LoadScene(file); selected = nullptr; } ImGui::Separator(); @@ -1587,219 +1590,7 @@ void Engine::Run() } } -bool VerifySceneHash(const YAML::Node &root) -{ - if (!root["scene_hash"] || !root["objects"]) - return false; - YAML::Emitter sceneOnly; - sceneOnly << root["objects"]; - - std::string sceneString = sceneOnly.c_str(); - unsigned char hash[SHA256_DIGEST_LENGTH]; - SHA256(reinterpret_cast(sceneString.c_str()), sceneString.size(), hash); - - std::ostringstream hashHex; - for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) - hashHex << std::hex << std::setw(2) << std::setfill('0') << static_cast(hash[i]); - - return hashHex.str() == root["scene_hash"].as(); -} - -void Engine::SaveScene(const std::string &path) -{ - YAML::Emitter out; - YAML::Emitter sceneData; - - // Serialize object list only - sceneData << YAML::BeginSeq; - for (const auto &obj : objects) - obj->Save(sceneData); - sceneData << YAML::EndSeq; - - std::string objectData = sceneData.c_str(); - unsigned char hash[SHA256_DIGEST_LENGTH]; - SHA256(reinterpret_cast(objectData.c_str()), objectData.size(), hash); - - std::ostringstream hashHex; - 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(); - out << YAML::Key << "scene_hash" << YAML::Value << hashHex.str(); - out << YAML::Key << "format_version" << YAML::Value << 1; - out << YAML::Key << "objects" << YAML::Value << YAML::Load(objectData); - - Logger::LogVerbose("[SaveScene] Saving Color Correction Attributes"); - - out << YAML::Key << "color_correction" << YAML::BeginMap; - out << YAML::Key << "brightness" << YAML::Value << Renderer::GetColorCorrection()->brightness; - out << YAML::Key << "saturation" << YAML::Value << Renderer::GetColorCorrection()->saturation; - out << YAML::Key << "gamma" << YAML::Value << Renderer::GetColorCorrection()->gamma; - out << YAML::Key << "bloom" << YAML::Value << Renderer::GetColorCorrection()->bloom; - out << YAML::Key << "intensity" << YAML::Value << Renderer::GetColorCorrection()->intensity; - out << YAML::Key << "threshold" << YAML::Value << Renderer::GetColorCorrection()->threshold; - out << YAML::EndMap; - - AssetManager::Save(out); - - out << YAML::EndMap; - - std::ofstream file(path); - file << out.c_str(); - - Logger::LogOk("Scene Saved"); -} - -void Engine::LoadScene(const std::string &path) -{ - - bool legacyLoad = false; - Logger::LogDebug("Reading Scene File."); - YAML::Node root = YAML::LoadFile(path); - - LoadingWindow loadingUI; - loadingUI.Create("Loading Scene"); - - std::string currentStep = "Verifying Scene"; - std::string currentDetail = ""; - loadingUI.Update(currentStep, currentDetail, 0.0f); - - if (!root["engine_version"] || !root["format_version"] || !root["scene_name"]) - { - Logger::LogError("Missing required metadata!"); - loadingUI.Destroy(); - return; - } - - std::string loadedVersion = root["engine_version"].as(); - std::string expectedVersion = g_engineConfig.version; - - if (loadedVersion != expectedVersion) - { - Logger::LogWarning("Version mismatch! Expected %s, got %s", - expectedVersion.c_str(), loadedVersion.c_str()); - - if (!g_engineConfig.settings.ignore_invalid_versions_popups) - { - loadingUI.Destroy(); // Close visual loading before blocking popup - - int result = Popup::Show("Version Mismatch", - "Scene was created with engine version: " + loadedVersion + - "\nExpected: " + expectedVersion + - "\n\nLoad anyway?", - {Popup::Option("Yes", 1), - Popup::Option("Yes (Don't Ask Again)", 2), - Popup::Option("No", 0)}); - - if (result == 0) - { - Logger::LogInfo("User cancelled scene load."); - return; - } - if (result == 2) - { - g_engineConfig.settings.ignore_invalid_versions_popups = true; - } - - loadingUI.Create("Loading Scene (Legacy Recovery)"); - loadingUI.Update("Attempting Recovery", "Loading scene with fallback...", 0.02f); - } - else - { - Logger::LogInfo("Version mismatch ignored due to user setting."); - } - } - - if (!VerifySceneHash(root)) - { - 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"]); - } - - Logger::LogDebug("Reseting Scene."); - currentStep = "Clearing Previous Scene"; - currentDetail = "Removing existing objects"; - loadingUI.Update(currentStep, currentDetail, 0.1f); - - objects.clear(); - Object::usedIDs.clear(); - - Logger::LogDebug("Recreating Objects"); - currentStep = "Creating Scene Objects"; - - const auto &objectArray = root["objects"]; - int objectIndex = 0; - int totalObjects = static_cast(objectArray.size()); - - for (const auto &node : objectArray) - { - std::string objName = node["name"] ? node["name"].as() : ("Unnamed_" + std::to_string(objectIndex)); - currentDetail = "Loading: " + objName; - float progress = 0.1f + (0.75f * (objectIndex / static_cast(std::max(1, totalObjects)))); - loadingUI.Update(currentStep, currentDetail, progress); - - try - { - auto obj = std::make_shared(objName); - obj->Load(node); - objects.push_back(obj); - } - catch (const std::exception &e) - { - Logger::LogWarning("Failed to load object '%s': %s", objName.c_str(), e.what()); - } - - objectIndex++; - } - - // Color correction settings - if (root["color_correction"]) - { - Logger::LogVerbose("Loading Color Correction Attributes"); - currentStep = "Color Correction"; - currentDetail = "Applying settings..."; - loadingUI.Update(currentStep, currentDetail, 0.9f); - - ColorCorrection *cc = Renderer::GetColorCorrection(); - const auto &data = root["color_correction"]; - if (cc) - { - if (data["brightness"]) - cc->brightness = data["brightness"].as(); - if (data["saturation"]) - cc->saturation = data["saturation"].as(); - if (data["gamma"]) - cc->gamma = data["gamma"].as(); - if (data["bloom"]) - cc->bloom = data["bloom"].as(); - if (data["intensity"]) - cc->intensity = data["intensity"].as(); - if (data["threshold"]) - cc->threshold = data["threshold"].as(); - } - } - - // Finalize - currentStep = "Done"; - currentDetail = "Finalizing load..."; - loadingUI.Update(currentStep, currentDetail, 1.0f); - - Logger::LogOk("Scene Loaded: %s", root["scene_name"].as().c_str()); - - loadingUI.Destroy(); -} void Engine::SaveState() { diff --git a/src/src/Engine.h b/src/src/Engine.h index 9745f16..b36485a 100644 --- a/src/src/Engine.h +++ b/src/src/Engine.h @@ -26,8 +26,7 @@ public: void Stop() {running = false;} - void SaveScene(const std::string &path); - void LoadScene(const std::string &path); + private: diff --git a/src/src/core/audio/AudioEngine.cpp b/src/src/core/audio/AudioEngine.cpp index 7255e71..1ffa531 100644 --- a/src/src/core/audio/AudioEngine.cpp +++ b/src/src/core/audio/AudioEngine.cpp @@ -63,7 +63,6 @@ void AudioEngine::Shutdown() void AudioEngine::Play(uint64_t uaid, bool loop) { - Cleanup(uaid); const AssetInfo *asset = AssetManager::GetAssetByID(uaid); if (!asset || !asset->loaded || asset->type != AssetType::Audio) @@ -72,6 +71,8 @@ void AudioEngine::Play(uint64_t uaid, bool loop) return; } + Cleanup(uaid); + ma_sound *sound = new ma_sound; if (ma_sound_init_from_file( &s_Engine, @@ -104,6 +105,8 @@ void AudioEngine::Play(uint64_t uaid, bool loop) info.sound = sound; s_PlayingInfoMap[uaid] = info; + + } void AudioEngine::Stop(uint64_t uaid) @@ -137,9 +140,10 @@ void AudioEngine::CleanupSound(uint64_t uaid) s_SoundMap.erase(itSound); } else - { - Logger::LogError("[AudioEngine] Invalid Asset ID"); - } +{ + Logger::LogVerbose("[AudioEngine] No sound found for ID %llu", uaid); +} + } void AudioEngine::Update() @@ -203,9 +207,10 @@ void AudioEngine::Cleanup(uint64_t uaid) s_SoundMap.erase(it); } else - { - Logger::LogError("[AudioEngine] Invalid Asset ID"); - } +{ + Logger::LogVerbose("[AudioEngine] No sound found for ID %llu", uaid); +} + s_PlayingInfoMap.erase(uaid); } @@ -240,7 +245,10 @@ void AudioEngine::EngineProcessCallback( } } + + const std::vector &AudioEngine::GetMasterVU() { + return s_MasterVU; } diff --git a/src/src/core/functions/ProjectManager.cpp b/src/src/core/functions/ProjectManager.cpp index e52acd9..bc609ff 100644 --- a/src/src/core/functions/ProjectManager.cpp +++ b/src/src/core/functions/ProjectManager.cpp @@ -4,6 +4,9 @@ #include "../../core/utils/EngineConfig.h" #include "../../core/utils/Logging.h" #include "../../Engine.h" +#include "SceneSerializer.h" + + #include #include #include @@ -51,6 +54,27 @@ bool CreateDirectories(const fs::path& baseDir) return allOk; } +std::string ProjectManager::ResolveResPath(const std::string& resPath) +{ + constexpr const char* prefix = "res://"; + if (resPath.rfind(prefix, 0) != 0) + return resPath; + + if (s_currentProjectPath.empty() || s_currentProjectName.empty()) + { + 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; + + return fullPath.lexically_normal().string(); +} + + + bool ProjectManager::Init() @@ -89,25 +113,40 @@ bool ProjectManager::LoadProject(const std::string& projectPath, std::string createdDate = config["CreatedDate"].as("unknown"); std::string s_defaultScene = config["s_defaultScene"].as("s_defaultScene"); - if (!s_defaultScene.empty()) + + s_currentProjectPath = projectPath; + s_currentProjectName = savedName; + + + + + + + + std::string resScenePath = config["s_defaultScene"].as(""); + + if (!resScenePath.empty()) { - Logger::LogInfo("Loading Default Scene '%s'", s_defaultScene.c_str()); - Logger::LogWarning("TODO: Migrate Scene loading to scene Manager or ProjectManager class instead of engine class, then actualy load the scene here"); - - } - else - { - Logger::LogWarning("Invalid Deafult Scene"); + s_defaultScene = ResolveResPath(resScenePath); + Logger::LogInfo("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()); + return false; + } + + SceneLoader::LoadScene(s_defaultScene); } + Logger::LogInfo("Loaded project '%s' at '%s' (created %s)", savedName.c_str(), projectPath.c_str(), createdDate.c_str()); - s_currentProjectPath = projectPath; - s_currentProjectName = savedName; + CreateDirectories(baseDir); @@ -132,7 +171,10 @@ bool ProjectManager::SaveProject(const std::string& projectPath, out << YAML::BeginMap; out << YAML::Key << "Name" << YAML::Value << projectName; out << YAML::Key << "EngineVersion" << YAML::Value << g_engineConfig.version; - out << YAML::Key << "s_defaultScene" << YAML::Value << s_defaultScene; + fs::path relPath = fs::relative(s_defaultScene, + fs::path(s_currentProjectPath) / s_currentProjectName); +out << YAML::Key << "s_defaultScene" << YAML::Value << ("res://" + relPath.generic_string()); + auto now = std::chrono::system_clock::now(); diff --git a/src/src/core/functions/ProjectManager.h b/src/src/core/functions/ProjectManager.h index 5180116..e975f64 100644 --- a/src/src/core/functions/ProjectManager.h +++ b/src/src/core/functions/ProjectManager.h @@ -3,6 +3,7 @@ #include #include +#include class ProjectManager { @@ -23,6 +24,10 @@ public: static const std::string& GetCurrentProjectName(); static const std::string& GetCurrentAssetsPath(); + static std::string ResolveResPath(const std::string& resPath); + + + private: static std::string s_currentProjectPath; static std::string s_currentProjectName; diff --git a/src/src/core/functions/SceneSerializer.cpp b/src/src/core/functions/SceneSerializer.cpp new file mode 100644 index 0000000..ff38775 --- /dev/null +++ b/src/src/core/functions/SceneSerializer.cpp @@ -0,0 +1,234 @@ +#include "SceneSerializer.h" +#include +#include "../../Entitys/Object.h" +#include "../../Renderer.h" +#include "../../utils/GameObjectsList.h" +#include "../../core/utils/LoadingWindow.h" +#include "../../core/utils/Popup.h" + + + + +#include +#include +#include +#include +#include +#include +#include +#include + + +bool VerifySceneHash(const YAML::Node &root) +{ + if (!root["scene_hash"] || !root["objects"]) + return false; + + YAML::Emitter sceneOnly; + sceneOnly << root["objects"]; + + std::string sceneString = sceneOnly.c_str(); + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256(reinterpret_cast(sceneString.c_str()), sceneString.size(), hash); + + std::ostringstream hashHex; + for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) + hashHex << std::hex << std::setw(2) << std::setfill('0') << static_cast(hash[i]); + + return hashHex.str() == root["scene_hash"].as(); +} + +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) + obj->Save(sceneData); + sceneData << YAML::EndSeq; + + std::string objectData = sceneData.c_str(); + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256(reinterpret_cast(objectData.c_str()), objectData.size(), hash); + + std::ostringstream hashHex; + 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(); + out << YAML::Key << "scene_hash" << YAML::Value << hashHex.str(); + out << YAML::Key << "format_version" << YAML::Value << 1; + out << YAML::Key << "objects" << YAML::Value << YAML::Load(objectData); + + Logger::LogVerbose("[SaveScene] Saving Color Correction Attributes"); + + out << YAML::Key << "color_correction" << YAML::BeginMap; + out << YAML::Key << "brightness" << YAML::Value << Renderer::GetColorCorrection()->brightness; + out << YAML::Key << "saturation" << YAML::Value << Renderer::GetColorCorrection()->saturation; + out << YAML::Key << "gamma" << YAML::Value << Renderer::GetColorCorrection()->gamma; + out << YAML::Key << "bloom" << YAML::Value << Renderer::GetColorCorrection()->bloom; + out << YAML::Key << "intensity" << YAML::Value << Renderer::GetColorCorrection()->intensity; + out << YAML::Key << "threshold" << YAML::Value << Renderer::GetColorCorrection()->threshold; + out << YAML::EndMap; + + AssetManager::Save(out); + + out << YAML::EndMap; + + std::ofstream file(path); + file << out.c_str(); + + Logger::LogOk("Scene Saved"); +} + +void SceneLoader::LoadScene(const std::string &path) +{ + + bool legacyLoad = false; + Logger::LogDebug("Reading Scene File."); + YAML::Node root = YAML::LoadFile(path); + + LoadingWindow loadingUI; + loadingUI.Create("Loading Scene"); + + std::string currentStep = "Verifying Scene"; + std::string currentDetail = ""; + loadingUI.Update(currentStep, currentDetail, 0.0f); + + if (!root["engine_version"] || !root["format_version"] || !root["scene_name"]) + { + Logger::LogError("Missing required metadata!"); + loadingUI.Destroy(); + return; + } + + std::string loadedVersion = root["engine_version"].as(); + std::string expectedVersion = g_engineConfig.version; + + if (loadedVersion != expectedVersion) + { + Logger::LogWarning("Version mismatch! Expected %s, got %s", + expectedVersion.c_str(), loadedVersion.c_str()); + + if (!g_engineConfig.settings.ignore_invalid_versions_popups) + { + loadingUI.Destroy(); // Close visual loading before blocking popup + + int result = Popup::Show("Version Mismatch", + "Scene was created with engine version: " + loadedVersion + + "\nExpected: " + expectedVersion + + "\n\nLoad anyway?", + {Popup::Option("Yes", 1), + Popup::Option("Yes (Don't Ask Again)", 2), + Popup::Option("No", 0)}); + + if (result == 0) + { + Logger::LogInfo("User cancelled scene load."); + return; + } + if (result == 2) + { + g_engineConfig.settings.ignore_invalid_versions_popups = true; + } + + loadingUI.Create("Loading Scene (Legacy Recovery)"); + loadingUI.Update("Attempting Recovery", "Loading scene with fallback...", 0.02f); + } + else + { + Logger::LogInfo("Version mismatch ignored due to user setting."); + } + } + + if (!VerifySceneHash(root)) + { + 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"]); + } + + Logger::LogDebug("Reseting Scene."); + currentStep = "Clearing Previous Scene"; + currentDetail = "Removing existing objects"; + loadingUI.Update(currentStep, currentDetail, 0.1f); + + objects.clear(); + Object::usedIDs.clear(); + + Logger::LogDebug("Recreating Objects"); + currentStep = "Creating Scene Objects"; + + const auto &objectArray = root["objects"]; + int objectIndex = 0; + int totalObjects = static_cast(objectArray.size()); + + for (const auto &node : objectArray) + { + std::string objName = node["name"] ? node["name"].as() : ("Unnamed_" + std::to_string(objectIndex)); + currentDetail = "Loading: " + objName; + float progress = 0.1f + (0.75f * (objectIndex / static_cast(std::max(1, totalObjects)))); + loadingUI.Update(currentStep, currentDetail, progress); + + try + { + auto obj = std::make_shared(objName); + obj->Load(node); + objects.push_back(obj); + } + catch (const std::exception &e) + { + Logger::LogWarning("Failed to load object '%s': %s", objName.c_str(), e.what()); + } + + objectIndex++; + } + + // Color correction settings + if (root["color_correction"]) + { + Logger::LogVerbose("Loading Color Correction Attributes"); + currentStep = "Color Correction"; + currentDetail = "Applying settings..."; + loadingUI.Update(currentStep, currentDetail, 0.9f); + + ColorCorrection *cc = Renderer::GetColorCorrection(); + const auto &data = root["color_correction"]; + if (cc) + { + if (data["brightness"]) + cc->brightness = data["brightness"].as(); + if (data["saturation"]) + cc->saturation = data["saturation"].as(); + if (data["gamma"]) + cc->gamma = data["gamma"].as(); + if (data["bloom"]) + cc->bloom = data["bloom"].as(); + if (data["intensity"]) + cc->intensity = data["intensity"].as(); + if (data["threshold"]) + cc->threshold = data["threshold"].as(); + } + } + + // Finalize + currentStep = "Done"; + currentDetail = "Finalizing load..."; + loadingUI.Update(currentStep, currentDetail, 1.0f); + + Logger::LogOk("Scene Loaded: %s", root["scene_name"].as().c_str()); + + loadingUI.Destroy(); +} \ No newline at end of file diff --git a/src/src/core/functions/SceneSerializer.h b/src/src/core/functions/SceneSerializer.h new file mode 100644 index 0000000..b7b5ce2 --- /dev/null +++ b/src/src/core/functions/SceneSerializer.h @@ -0,0 +1,11 @@ +#pragma once +#include + + +class SceneLoader +{ +public: + static void SaveScene(const std::string &path); + static void LoadScene(const std::string &path); +}; + diff --git a/src/src/editor/windows/AssetBrowser.cpp b/src/src/editor/windows/AssetBrowser.cpp index f57229d..9496a33 100644 --- a/src/src/editor/windows/AssetBrowser.cpp +++ b/src/src/editor/windows/AssetBrowser.cpp @@ -308,6 +308,8 @@ void ShowAssetBrowser() ImGui::EndChild(); ImGui::End(); + + if (ImGui::BeginPopupModal("Import Assets", nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize)) { ImGui::TextWrapped("Confirm Imports");