From 50d1189fb7f0e8d263286979de447c34657fe575 Mon Sep 17 00:00:00 2001 From: OusmBlueNinja <89956790+OusmBlueNinja@users.noreply.github.com> Date: Fri, 18 Apr 2025 18:52:52 -0500 Subject: [PATCH] Updated Renderer and Logging --- imgui.ini | 70 +++--- remake/build.log | 11 +- src/assets/lua/test.lua | 6 +- src/assets/scenes/lighting_test_2.cene | 46 ++-- src/src/Engine.cpp | 314 +++++++++++++++++-------- src/src/Renderer.cpp | 29 ++- src/src/utils/Logging.cpp | 59 ++++- src/src/utils/Shader.cpp | 28 ++- src/src/utils/utils.cpp | 22 ++ src/src/utils/utils.h | 2 + 10 files changed, 403 insertions(+), 184 deletions(-) diff --git a/imgui.ini b/imgui.ini index bc880ac..d13de6b 100644 --- a/imgui.ini +++ b/imgui.ini @@ -10,24 +10,24 @@ Collapsed=1 [Window][WindowOverViewport_11111111] Pos=0,19 -Size=1280,701 +Size=1920,1158 Collapsed=0 [Window][Inspector] -Pos=890,19 -Size=390,292 +Pos=0,358 +Size=385,819 Collapsed=0 -DockId=0x0000000B,0 +DockId=0x0000000A,0 [Window][Scene Tree] Pos=0,19 -Size=376,366 +Size=385,337 Collapsed=0 DockId=0x00000009,0 [Window][Viewport] -Pos=378,19 -Size=510,218 +Pos=387,19 +Size=1533,675 Collapsed=0 DockId=0x00000007,0 @@ -36,16 +36,16 @@ Size=1280,19 Collapsed=0 [Window][Performance Info] -Pos=890,526 -Size=390,194 +Pos=1672,696 +Size=248,300 Collapsed=0 -DockId=0x00000006,0 +DockId=0x00000003,0 [Window][Console] -Pos=0,387 -Size=376,333 +Pos=387,939 +Size=1283,238 Collapsed=0 -DockId=0x0000000A,0 +DockId=0x0000000C,0 [Window][Tilemap Editor] Pos=265,19 @@ -54,47 +54,47 @@ Collapsed=0 DockId=0x00000007,1 [Window][Profiler] -Pos=378,239 -Size=510,481 +Pos=387,696 +Size=1283,241 Collapsed=0 -DockId=0x00000008,0 +DockId=0x0000000B,0 [Window][Profiler Timeline] Pos=265,69 Size=623,651 Collapsed=0 -DockId=0x00000008,1 +DockId=0x0000000B,1 [Window][Profiler (Unity Style)] Pos=265,430 Size=623,290 Collapsed=0 -DockId=0x00000008,1 +DockId=0x0000000B,1 [Window][Profiler Timeline View] Pos=265,526 Size=1263,651 Collapsed=0 -DockId=0x00000008,1 +DockId=0x0000000B,1 [Window][Color Correction] -Pos=890,313 -Size=390,211 +Pos=1672,998 +Size=248,179 Collapsed=0 -DockId=0x0000000C,0 +DockId=0x00000004,0 [Docking][Data] -DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1280,701 Split=X - DockNode ID=0x00000003 Parent=0x11111111 SizeRef=888,1158 Split=X - DockNode ID=0x00000001 Parent=0x00000003 SizeRef=376,701 Split=Y Selected=0x12EF0F59 - DockNode ID=0x00000009 Parent=0x00000001 SizeRef=376,605 HiddenTabBar=1 Selected=0x12EF0F59 - DockNode ID=0x0000000A Parent=0x00000001 SizeRef=376,551 HiddenTabBar=1 Selected=0xEA83D666 - DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1150,701 Split=Y Selected=0xC450F867 - DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,675 CentralNode=1 Selected=0xC450F867 - DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,481 Selected=0x9B5D3198 - DockNode ID=0x00000004 Parent=0x11111111 SizeRef=390,1158 Split=Y Selected=0x36DC96AB - DockNode ID=0x00000005 Parent=0x00000004 SizeRef=407,835 Split=Y Selected=0x36DC96AB - DockNode ID=0x0000000B Parent=0x00000005 SizeRef=390,483 Selected=0x36DC96AB - DockNode ID=0x0000000C Parent=0x00000005 SizeRef=390,350 Selected=0xA873C17F - DockNode ID=0x00000006 Parent=0x00000004 SizeRef=407,321 HiddenTabBar=1 Selected=0x3FC1A724 +DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1920,1158 Split=X + DockNode ID=0x00000001 Parent=0x11111111 SizeRef=385,701 Split=Y Selected=0x12EF0F59 + DockNode ID=0x00000009 Parent=0x00000001 SizeRef=385,337 HiddenTabBar=1 Selected=0x12EF0F59 + DockNode ID=0x0000000A Parent=0x00000001 SizeRef=385,819 HiddenTabBar=1 Selected=0x36DC96AB + DockNode ID=0x00000002 Parent=0x11111111 SizeRef=1533,701 Split=Y Selected=0xC450F867 + DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,675 CentralNode=1 HiddenTabBar=1 Selected=0xC450F867 + DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,481 Split=X Selected=0x9B5D3198 + DockNode ID=0x00000005 Parent=0x00000008 SizeRef=1283,481 Split=Y Selected=0x9B5D3198 + DockNode ID=0x0000000B Parent=0x00000005 SizeRef=1336,241 Selected=0x9B5D3198 + DockNode ID=0x0000000C Parent=0x00000005 SizeRef=1336,238 Selected=0xEA83D666 + DockNode ID=0x00000006 Parent=0x00000008 SizeRef=248,481 Split=Y Selected=0x3FC1A724 + DockNode ID=0x00000003 Parent=0x00000006 SizeRef=226,300 Selected=0x3FC1A724 + DockNode ID=0x00000004 Parent=0x00000006 SizeRef=226,179 HiddenTabBar=1 Selected=0xA873C17F diff --git a/remake/build.log b/remake/build.log index 63a2f52..5740fea 100644 --- a/remake/build.log +++ b/remake/build.log @@ -1,10 +1 @@ -[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\Engine.cpp -o src\build\Engine.o -[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\main.cpp -o src\build\main.o -[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\Renderer.cpp -o src\build\Renderer.o -[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\Components\CameraComponent.cpp -o src\build\Components\CameraComponent.o -[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\Components\LightComponent.cpp -o src\build\Components\LightComponent.o -[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\Components\ScriptComponent.cpp -o src\build\Components\ScriptComponent.o -[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\Components\SpriteComponent.cpp -o src\build\Components\SpriteComponent.o -[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\Components\TextComonent.cpp -o src\build\Components\TextComonent.o -[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\Components\TilemapComponent.cpp -o src\build\Components\TilemapComponent.o -[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\Entitys\Object.cpp -o src\build\Entitys\Object.o +[LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\CameraComponent.o src\build\Components\LightComponent.o src\build\Components\ScriptComponent.o src\build\Components\SpriteComponent.o src\build\Components\TextComonent.o src\build\Components\TilemapComponent.o src\build\Entitys\Object.o src\build\utils\EngineConfig.o src\build\utils\ExceptionHandler.o src\build\utils\FileDialog.o src\build\utils\GameObjectsList.o src\build\utils\Logging.o src\build\utils\Profiler.o src\build\utils\Shader.o src\build\utils\UID.o src\build\utils\utils.o src\build\imgui\imgui.o src\build\imgui\imgui_demo.o src\build\imgui\imgui_draw.o src\build\imgui\imgui_impl_glfw.o src\build\imgui\imgui_impl_opengl3.o src\build\imgui\imgui_tables.o src\build\imgui\imgui_widgets.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 -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto diff --git a/src/assets/lua/test.lua b/src/assets/lua/test.lua index cbc25e6..5617eb0 100644 --- a/src/assets/lua/test.lua +++ b/src/assets/lua/test.lua @@ -8,12 +8,14 @@ local center = Vector2(1024, 1024) -- pivot point local angles = {} + + function OnInit() for i, tag in ipairs(ObjectTags) do local obj = Engine.GetObjectByTag(tag) if obj then Objects[i] = obj - angles[i] = (i - 1) * (2 * math.pi / #ObjectTags) -- spread them evenly + angles[i] = (i - 1) * (2 * math.pi / #ObjectTags) else Engine.LogError("Object '" .. tag .. "' not found!") end @@ -24,11 +26,9 @@ function OnUpdate(dt) for i, obj in ipairs(Objects) do if obj then angles[i] = angles[i] + OrbitSpeed * dt - local angle = angles[i] local x = center.x + math.cos(angle) * OrbitRadius local y = center.y + math.sin(angle) * OrbitRadius - obj:SetPosition(Vector2(x, y)) end end diff --git a/src/assets/scenes/lighting_test_2.cene b/src/assets/scenes/lighting_test_2.cene index b408763..2ce155f 100644 --- a/src/assets/scenes/lighting_test_2.cene +++ b/src/assets/scenes/lighting_test_2.cene @@ -1,6 +1,6 @@ engine_version: 0.1.0 scene_name: lighting_test_2 -scene_hash: 8f8260f09292105727f7f8afe890565a9feeaa92a1ca6d7fa55790a5019c67d7 +scene_hash: 59f49b4319d714200de64e90f576e787dcc9aa5d0dfc217d78e87f8332be626f format_version: 1 objects: - name: Tiles @@ -90,7 +90,7 @@ objects: normalMap: C:\Users\spenc\OneDrive\Pictures\textures\carbon-fiber-smooth-bl\carbon-fiber-smooth-bl\carbon-fiber_smooth_normal-ogl.png renderType: Lit children: [] - - name: Mud + - name: Carbooon Fobar 2 uid: a36b71937ba349bd8e6414f75be9ee16 id: 10 position: [0, 3070] @@ -99,8 +99,8 @@ objects: visable: true components: - type: SpriteComponent - texture: C:\Users\spenc\OneDrive\Pictures\textures\mud-bl\mud-bl\mud_albedo.png - normalMap: C:\Users\spenc\OneDrive\Pictures\textures\mud-bl\mud-bl\mud_normal-ogl.png + texture: C:\Users\spenc\OneDrive\Pictures\textures\carbon-fiber-smooth-bl\carbon-fiber-smooth-bl\carbon-fiber_smooth_albedo.png + normalMap: C:\Users\spenc\OneDrive\Pictures\textures\carbon-fiber-smooth-bl\carbon-fiber-smooth-bl\carbon-fiber_smooth_normal-ogl.png renderType: Lit children: [] - name: Lights @@ -115,7 +115,7 @@ objects: - name: Red uid: 6afde2dd47aa4557b6afb1a607c99dc8 id: 13 - position: [512, 1024] + position: [1113.06287, 1516.00391] rotation: 0 layer: 2 visable: true @@ -129,15 +129,11 @@ objects: radius: 1000 falloff: 0.100000001 type: 0 - - type: SpriteComponent - texture: C:\Users\spenc\OneDrive\Documents\GitHub\Create-Engine\src\assets\icons\lightbulb-on-10.png - normalMap: "" - renderType: Unlit children: [] - name: Green uid: 0f950d76d24b4dc18f54cab2c3aaaf9a id: 14 - position: [1024, 512] + position: [553.380676, 855.128784] rotation: 0 layer: 2 visable: true @@ -151,15 +147,11 @@ objects: radius: 1000 falloff: 1 type: 0 - - type: SpriteComponent - texture: C:\Users\spenc\OneDrive\Documents\GitHub\Create-Engine\src\assets\icons\lightbulb-on-10.png - normalMap: "" - renderType: Unlit children: [] - name: Blue uid: 09f722f51c7c4b0f98de3a0a16d127c4 id: 15 - position: [250, 250] + position: [1405.5564, 700.86731] rotation: 0 layer: 2 visable: true @@ -173,10 +165,6 @@ objects: radius: 1000 falloff: 1 type: 0 - - type: SpriteComponent - texture: C:\Users\spenc\OneDrive\Documents\GitHub\Create-Engine\src\assets\icons\lightbulb-on-10.png - normalMap: "" - renderType: Unlit children: [] - name: Ambient light uid: d4fb425522d84a8cbbd7d1415bcd93df @@ -206,4 +194,22 @@ objects: components: - type: ScriptComponent scriptPath: C:\Users\spenc\OneDrive\Documents\GitHub\Create-Engine\src\assets\lua\test.lua - children: [] \ No newline at end of file + children: [] + - name: Camera + uid: 7d10561480d54060882f1c986023a58b + id: 106 + position: [512, 2000] + rotation: 0 + layer: 3 + visable: true + components: + - type: CameraComponent + fov: 45 + aspect: 1.76999998 + zoom: 1 + primary: true + children: [] +color_correction: + brightness: 2 + saturation: 2 + gamma: 0.610000014 \ No newline at end of file diff --git a/src/src/Engine.cpp b/src/src/Engine.cpp index bfb159e..70c76db 100644 --- a/src/src/Engine.cpp +++ b/src/src/Engine.cpp @@ -13,6 +13,8 @@ #include "utils/EngineConfig.h" #include "utils/GameObjectsList.h" #include "utils/Profiler.h" +#include "utils/utils.h" + #include #include @@ -39,12 +41,20 @@ static std::shared_ptr selected = nullptr; static bool playing = false; +static bool lastPlaying = false; + static std::vector> pendingDeletion; static glm::vec2 cameraPos = {0, 0}; static float cameraZoom = 1.0f; static ImVec2 lastMousePos = {}; +static glm::vec2 editorCameraSavedPos = {0.0f, 0.0f}; +static float editorCameraSavedZoom = 1.0f; +static bool editorCameraWasSaved = false; + +static std::shared_ptr m_activeCamera; + float g_fps = 0.0f; static const std::string tempScenePath = "__tmp_scene.yaml"; @@ -282,17 +292,16 @@ void ShowColorCorrectionWindow() { PROFILE_ENGINE_SCOPE("Engine::ShowColorCorrectionWindow"); - ColorCorrection* cc = Renderer::GetColorCorrection(); + ColorCorrection *cc = Renderer::GetColorCorrection(); if (!cc) return; ImGui::Begin("Color Correction"); - bool changed = false; changed |= ImGui::SliderFloat("Brightness", &cc->brightness, 0.0f, 2.0f, "%.2f"); changed |= ImGui::SliderFloat("Saturation", &cc->saturation, 0.0f, 2.0f, "%.2f"); - changed |= ImGui::SliderFloat("Gamma", &cc->gamma, 0.1f, 4.0f, "%.2f"); + changed |= ImGui::SliderFloat("Gamma", &cc->gamma, 0.1f, 4.0f, "%.2f"); ImGui::Spacing(); @@ -305,10 +314,15 @@ void ShowColorCorrectionWindow() ImGui::End(); } - - void Engine::Init() { + + if (DeleteLatestLogFile()) { + Logger::LogVerbose("Log file deleted"); + } else { + Logger::LogVerbose("Failed to delete log file"); + } + glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); @@ -492,6 +506,10 @@ void DrawInspectorUI(std::shared_ptr selected) if (ImGui::DragFloat("Zoom", &zoom, 0.1f, 0.1f, 10.0f)) cam->SetZoom(zoom); + bool isPrimary = cam->IsPrimary(); + if (ImGui::Checkbox("Primary", &isPrimary)) + cam->SetPrimary(isPrimary); + if (ImGui::Button("Remove CameraComponent")) selected->RemoveComponent(); } @@ -565,12 +583,12 @@ void DrawInspectorUI(std::shared_ptr selected) } } -// Add this method to Engine: void Engine::collectObjects(bool playing, const glm::vec2 &camPos, float camZoom) { m_toDraw.clear(); m_scriptUpdates.clear(); m_collectStack.clear(); + m_activeCamera = nullptr; for (auto &root : objects) if (!root->GetParent()) @@ -583,17 +601,25 @@ void Engine::collectObjects(bool playing, const glm::vec2 &camPos, float camZoom if (!obj->GetVisable()) continue; + m_toDraw.push_back(obj.get()); + // Handle light components if (auto light = obj->GetComponent()) { - glm::vec2 world = obj->GetWorldPosition(); glm::vec2 screen = (world - camPos) * camZoom + glm::vec2(Renderer::GetSize()) * 0.5f; - Renderer::AddLight(screen, - light->GetColor(), - light->GetIntensity(), - light->GetRadius() * camZoom); + Renderer::AddLight(screen, light->GetColor(), light->GetIntensity(), light->GetRadius() * camZoom); + } + + // Handle primary camera + if (!m_activeCamera) + { + if (auto camera = obj->GetComponent()) + { + if (camera->IsPrimary()) + m_activeCamera = camera; + } } if (playing) @@ -602,6 +628,7 @@ void Engine::collectObjects(bool playing, const glm::vec2 &camPos, float camZoom m_scriptUpdates.push_back(script.get()); } + // Add children to stack for (auto &child : obj->GetChildren()) m_collectStack.push_back(child); } @@ -754,7 +781,6 @@ void Engine::Run() if (g_engineConfig.settings.show_color_correction_window) ShowColorCorrectionWindow(); - { PROFILE_ENGINE_SCOPE("Engine::DrawSceneTree"); @@ -802,39 +828,69 @@ void Engine::Run() ImGui::Begin("Viewport", nullptr, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); ImVec2 size = ImGui::GetContentRegionAvail(); + // Save/restore editor camera position/zoom on play toggle + static bool lastPlaying = false; + + if (playing && !lastPlaying) + { + // Entering play mode – save editor camera + editorCameraSavedPos = cameraPos; + editorCameraSavedZoom = cameraZoom; + editorCameraWasSaved = true; + } + else if (!playing && lastPlaying) + { + // Exiting play mode – restore editor camera + if (editorCameraWasSaved) + { + cameraPos = editorCameraSavedPos; + cameraZoom = editorCameraSavedZoom; + editorCameraWasSaved = false; + } + } + + lastPlaying = playing; + + // Use active camera when playing + if (playing && m_activeCamera) + { + cameraPos = m_activeCamera->GetOwner()->GetWorldPosition(); + cameraZoom = m_activeCamera->GetZoom(); + } + + // Use editor camera logic when not playing if (!playing && ImGui::IsWindowHovered()) { + // Pan if (ImGui::IsMouseDragging(ImGuiMouseButton_Right)) { - ImVec2 mouseDelta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right); + ImVec2 delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right); ImGui::ResetMouseDragDelta(ImGuiMouseButton_Right); - cameraPos -= glm::vec2(mouseDelta.x, mouseDelta.y) / cameraZoom; + cameraPos -= glm::vec2(delta.x, delta.y) / cameraZoom; } + // Zoom float wheel = ImGui::GetIO().MouseWheel; if (wheel != 0.0f) { float zoomFactor = (wheel > 0) ? 1.1f : 1.0f / 1.1f; - // Get mouse position in screen space ImVec2 mousePos = ImGui::GetMousePos(); ImVec2 windowPos = ImGui::GetWindowPos(); - ImVec2 contentRegionMin = ImGui::GetWindowContentRegionMin(); - glm::vec2 relativeMouse = glm::vec2(mousePos.x - windowPos.x - contentRegionMin.x, - mousePos.y - windowPos.y - contentRegionMin.y); + ImVec2 contentMin = ImGui::GetWindowContentRegionMin(); - // Convert to world position before zoom - glm::vec2 beforeZoom = (relativeMouse - glm::vec2(size.x / 2, size.y / 2)) / cameraZoom + cameraPos; + glm::vec2 relativeMouse = glm::vec2( + mousePos.x - windowPos.x - contentMin.x, + mousePos.y - windowPos.y - contentMin.y); + + glm::vec2 before = (relativeMouse - glm::vec2(size.x / 2, size.y / 2)) / cameraZoom + cameraPos; - // Apply zoom cameraZoom *= zoomFactor; cameraZoom = std::clamp(cameraZoom, 0.1f, 10.0f); - // Convert to world position after zoom - glm::vec2 afterZoom = (relativeMouse - glm::vec2(size.x / 2, size.y / 2)) / cameraZoom + cameraPos; + glm::vec2 after = (relativeMouse - glm::vec2(size.x / 2, size.y / 2)) / cameraZoom + cameraPos; - // Offset camera so zoom is centered at mouse - cameraPos += beforeZoom - afterZoom; + cameraPos += before - after; } } @@ -848,20 +904,21 @@ void Engine::Run() Renderer::Begin(); profiler.EndEngineSection(); - // Reserve (no profiling) + profiler.BeginEngineSection("Reserve"); m_toDraw.reserve(m_Reserved_draws); m_Reserved_draws = 0; + m_toDraw.clear(); + m_scriptUpdates.clear(); + profiler.EndEngineSection(); + + + + - // Draw Editor Grid profiler.BeginEngineSection("Draw Editor Grid"); Renderer::DrawEditorGrid(cameraPos, cameraZoom); profiler.EndEngineSection(); - // Clear temporary arrays - m_toDraw.clear(); - m_scriptUpdates.clear(); - m_Reserved_draws = 0; - // Collect Objects profiler.BeginEngineSection("Collect Objects"); collectObjects(playing, cameraPos, cameraZoom); @@ -973,6 +1030,7 @@ void Engine::Run() for (auto &obj : pendingDeletion) { + Logger::LogVerbose("Deleting Object From Que: '%s', [%d, %s]", obj->GetName().c_str(), obj->uid.id, obj->uid.uuid.c_str()); if (obj->GetParent()) { obj->GetParent()->RemoveChild(obj.get()); @@ -991,8 +1049,8 @@ void Engine::Run() void Engine::DrawObjectNode(const std::shared_ptr &obj) { - PROFILE_ENGINE_SCOPE("Engine::DrawObjectNode"); + ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_SpanAvailWidth | (obj == selected ? ImGuiTreeNodeFlags_Selected : 0); @@ -1002,8 +1060,7 @@ void Engine::DrawObjectNode(const std::shared_ptr &obj) if (ImGui::IsItemClicked()) selected = obj; - // Global or class-level list - + // === Context Menu === if (ImGui::BeginPopupContextItem()) { if (ImGui::MenuItem("Rename")) @@ -1014,21 +1071,18 @@ void Engine::DrawObjectNode(const std::shared_ptr &obj) if (ImGui::MenuItem("Delete")) { pendingDeletion.push_back(obj); - ImGui::EndPopup(); - return; // Still return so you don't draw the item } if (ImGui::MenuItem("Create Child")) { auto child = std::make_shared("NewObject"); obj->AddChild(child); selected = child; - child->SetName("NewObject"); ImGui::OpenPopup("RenameObject"); } ImGui::EndPopup(); } - // === Drag and Drop === + // === Drag Source === if (ImGui::BeginDragDropSource()) { ImGui::SetDragDropPayload("OBJECT", &obj, sizeof(obj)); @@ -1036,15 +1090,40 @@ void Engine::DrawObjectNode(const std::shared_ptr &obj) ImGui::EndDragDropSource(); } + // === Drop Target === if (ImGui::BeginDragDropTarget()) { if (const ImGuiPayload *payload = ImGui::AcceptDragDropPayload("OBJECT")) { auto dragged = *(std::shared_ptr *)payload->Data; - if (dragged != obj) + + if (dragged != obj && dragged) + { + Object *oldParent = dragged->GetParent(); + + if (oldParent) + { + oldParent->RemoveChild(dragged.get()); + + for (const auto &candidate : objects) + { + if (candidate.get() == oldParent) + { + pendingDeletion.push_back(candidate); + break; + } + } + } + else + { + objects.erase(std::remove(objects.begin(), objects.end(), dragged), objects.end()); + } + obj->AddChild(dragged); + } } - ImGui::EndDragDropTarget(); + ImGui::EndDragDropTarget(); + } // === Children === @@ -1056,39 +1135,6 @@ void Engine::DrawObjectNode(const std::shared_ptr &obj) } } -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; - - // Hash the serialized object data - 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]); - - // Build final full YAML output - 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); - out << YAML::EndMap; - - std::ofstream file(path); - file << out.c_str(); -} - bool VerifySceneHash(const YAML::Node &root) { if (!root["scene_hash"] || !root["objects"]) @@ -1108,6 +1154,47 @@ bool VerifySceneHash(const YAML::Node &root) 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]); + + // Build final full YAML output + 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::EndMap; + + out << YAML::EndMap; + + std::ofstream file(path); + file << out.c_str(); +} + void Engine::LoadScene(const std::string &path) { Logger::LogDebug("[LoadScene] Reading Scene File."); @@ -1134,10 +1221,9 @@ void Engine::LoadScene(const std::string &path) } Logger::LogDebug("[LoadScene] Reseting Scene."); - objects.clear(); - Logger::LogDebug("[LoadScene] Recreting Objects"); + Logger::LogDebug("[LoadScene] Recreating Objects"); const auto &objectArray = root["objects"]; for (const auto &node : objectArray) @@ -1147,9 +1233,48 @@ void Engine::LoadScene(const std::string &path) objects.push_back(obj); } + if (root["color_correction"]) + { + Logger::LogVerbose("[LoadScene] Loading Color Correction Attributes"); + + 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(); + } + } + Logger::LogInfo("[LoadScene] Loaded scene: %s", root["scene_name"].as().c_str()); } +void Engine::SaveState() +{ + YAML::Emitter out; + out << YAML::BeginMap; + out << YAML::Key << "objects" << YAML::BeginSeq; + for (const auto &obj : objects) + obj->Save(out); + out << YAML::EndSeq; + + Logger::LogVerbose("[SaveState] Saving Color Correction State"); + + 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::EndMap; + + out << YAML::EndMap; + + savedStateYAML = out.c_str(); + Logger::LogVerbose("[SaveState] Scene serialized (%zu bytes)", savedStateYAML.size()); +} void Engine::LoadState() { if (savedStateYAML.empty()) @@ -1158,10 +1283,10 @@ void Engine::LoadState() return; } - YAML::Node objectArray; + YAML::Node root; try { - objectArray = YAML::Load(savedStateYAML); + root = YAML::Load(savedStateYAML); } catch (const std::exception &e) { @@ -1170,6 +1295,8 @@ void Engine::LoadState() } objects.clear(); + + const auto &objectArray = root["objects"]; for (const auto &node : objectArray) { auto obj = std::make_shared("[DefaultObject]"); @@ -1177,22 +1304,26 @@ void Engine::LoadState() objects.push_back(obj); } + if (root["color_correction"]) + { + Logger::LogVerbose("[LoadState] Loading Color Correction State"); + + 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(); + } + } + Logger::LogVerbose("[LoadState] Scene restored"); } -void Engine::SaveState() -{ - YAML::Emitter sceneData; - - sceneData << YAML::BeginSeq; - for (const auto &obj : objects) - obj->Save(sceneData); - sceneData << YAML::EndSeq; - - savedStateYAML = sceneData.c_str(); - Logger::LogVerbose("[SaveState] Scene serialized (%zu bytes)", savedStateYAML.size()); -} - void Engine::Shutdown() { g_engineConfig.SaveToFile(); @@ -1204,5 +1335,4 @@ void Engine::Shutdown() glfwTerminate(); std::filesystem::remove(tempScenePath); - } diff --git a/src/src/Renderer.cpp b/src/src/Renderer.cpp index c2f257e..2ef8230 100644 --- a/src/src/Renderer.cpp +++ b/src/src/Renderer.cpp @@ -76,13 +76,15 @@ void Renderer::Init() glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - std::cerr << "Framebuffer is not complete!" << std::endl; + Logger::LogError("[Renderer::Init] FBO incomplete"); + glBindFramebuffer(GL_FRAMEBUFFER, 0); InitQuad(); // Load lit shader + spriteShader.LoadFromFile("src/assets/shaders/sprite.vert", "src/assets/shaders/sprite.frag"); // Load unlit shader unlitShader.LoadFromFile("src/assets/shaders/unlit.vert", "src/assets/shaders/unlit.frag"); @@ -119,28 +121,25 @@ void Renderer::Resize(int w, int h) void Renderer::Begin() { - { PROFILE_ENGINE_SCOPE("glBindFramebuffer"); glBindFramebuffer(GL_FRAMEBUFFER, fbo); - } - { - glViewport(0, 0, width, height); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - { - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); } - { - s_DrawCalls = 0; - ClearLights(); - } + glViewport(0, 0, width, height); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + s_DrawCalls = 0; + ClearLights(); } + + void Renderer::End() { glBindFramebuffer(GL_FRAMEBUFFER, 0); diff --git a/src/src/utils/Logging.cpp b/src/src/utils/Logging.cpp index fffb0ab..801d59e 100644 --- a/src/src/utils/Logging.cpp +++ b/src/src/utils/Logging.cpp @@ -4,6 +4,42 @@ #include #include + +// Logger.cpp or a logger helper header +#include +#include +#include + +class ScopedLogFileWriter { +public: + ScopedLogFileWriter() { + // Resolve user folder + char userPath[MAX_PATH]; + DWORD len = GetEnvironmentVariableA("USERPROFILE", userPath, MAX_PATH); + if (len == 0 || len >= MAX_PATH) + return; + + std::filesystem::path logPath = std::filesystem::path(userPath) / ".CreateEngine"; + std::filesystem::create_directories(logPath); + logPath /= ".latest.log"; + + stream.open(logPath, std::ios::out | std::ios::app); // append mode + } + + ~ScopedLogFileWriter() { + if (stream.is_open()) + stream.close(); + } + + std::ofstream& Get() { return stream; } + +private: + std::ofstream stream; +}; + + + + std::vector Logger::s_Messages; bool Logger::s_AutoScroll = true; bool Logger::s_ShowInfo = true; @@ -59,17 +95,30 @@ void Logger::Log(Level level, const char *fmt, ...) va_end(args); } -void Logger::LogVA(Level level, const char *fmt, va_list args) + + + +void Logger::LogVA(Level level, const char* fmt, va_list args) { char buffer[1024]; vsnprintf(buffer, sizeof(buffer), fmt, args); - s_Messages.push_back({buffer, level}); + s_Messages.push_back({ buffer, level }); - std::cout << GetAnsiColor(level) - << "[Logger][" << ToString(level) << "] " - << buffer << "\033[0m" << "\n"; + const char* levelStr = ToString(level); + const char* ansiColor = GetAnsiColor(level); + + std::string formatted = std::string("[Logger][") + levelStr + "] " + buffer; + + std::cout << ansiColor << formatted << "\033[0m\n"; + + ScopedLogFileWriter logFile; + auto& out = logFile.Get(); + if (out.is_open()) + out << formatted << "\n"; } + + void Logger::LogInfo(const char *fmt, ...) { va_list args; diff --git a/src/src/utils/Shader.cpp b/src/src/utils/Shader.cpp index d835701..ec8815f 100644 --- a/src/src/utils/Shader.cpp +++ b/src/src/utils/Shader.cpp @@ -1,13 +1,16 @@ #include "Shader.h" +#include "Logging.h" +#include "utils.h" + #include #include -#include Shader::Shader() {} Shader::~Shader() { Clear(); } void Shader::Clear() { if (id != 0) { + Logger::LogVerbose("[Shader] Deleting program ID: %u", id); glDeleteProgram(id); id = 0; } @@ -18,10 +21,20 @@ std::string Shader::ReadFile(const std::string& path) { std::ifstream stream(path); std::stringstream buffer; buffer << stream.rdbuf(); + + std::string filename = GetFilenameFromPath(path); + Logger::LogVerbose("[Shader] ReadFile: %s", filename.c_str()); + Logger::LogVerbose("[Shader] Size (%zu bytes)", buffer.str().size()); + return buffer.str(); } + + GLuint Shader::Compile(GLenum type, const std::string& source) { + Logger::LogVerbose("[Shader] Compiling %s shader...", + type == GL_VERTEX_SHADER ? "Vertex" : "Fragment"); + GLuint shader = glCreateShader(type); const char* src = source.c_str(); glShaderSource(shader, 1, &src, nullptr); @@ -32,13 +45,19 @@ GLuint Shader::Compile(GLenum type, const std::string& source) { if (!success) { char info[512]; glGetShaderInfoLog(shader, 512, nullptr, info); - std::cerr << "[Shader Compile Error]:\n" << info << std::endl; + Logger::LogError("[Shader] Type %s:\n%s", + type == GL_VERTEX_SHADER ? "Vertex" : "Fragment", info); + } else { + Logger::LogVerbose("[Shader] Compiled %s shader successfully.", + type == GL_VERTEX_SHADER ? "Vertex" : "Fragment"); } return shader; } + bool Shader::LoadFromFile(const std::string& vertexPath, const std::string& fragmentPath) { + Logger::LogVerbose("[Shader] Loading from file: %s + %s", vertexPath.c_str(), fragmentPath.c_str()); return LoadFromSource(ReadFile(vertexPath), ReadFile(fragmentPath)); } @@ -61,10 +80,11 @@ bool Shader::LoadFromSource(const std::string& vertexSrc, const std::string& fra if (!success) { char info[512]; glGetProgramInfoLog(id, 512, nullptr, info); - std::cerr << "[Shader Link Error]:\n" << info << std::endl; + Logger::LogError("[Shader]]:\n%s", info); return false; } + Logger::LogVerbose("[Shader] Linked shader program successfully (ID: %u)", id); return true; } @@ -80,7 +100,7 @@ GLint Shader::GetUniformLocation(const std::string& name) { if (uniformCache.contains(name)) return uniformCache[name]; GLint loc = glGetUniformLocation(id, name.c_str()); if (loc == -1) - std::cerr << "[Shader] Warning: Uniform not found: " << name << "\n"; + Logger::LogWarning("[Shader] Uniform not found: %s", name.c_str()); uniformCache[name] = loc; return loc; } diff --git a/src/src/utils/utils.cpp b/src/src/utils/utils.cpp index 9f73240..6cca049 100644 --- a/src/src/utils/utils.cpp +++ b/src/src/utils/utils.cpp @@ -1,6 +1,9 @@ #include "utils.h" #include #include "stb_image.h" +#include +#include +#include static std::map textureCache; @@ -39,3 +42,22 @@ std::string GetFilenameFromPath(const std::string& path) } + + +bool DeleteLatestLogFile() { + // Get %USERPROFILE% + char userPath[MAX_PATH]; + DWORD len = GetEnvironmentVariableA("USERPROFILE", userPath, MAX_PATH); + if (len == 0 || len >= MAX_PATH) + return false; + + std::filesystem::path logPath = std::filesystem::path(userPath) / ".CreateEngine" / ".latest.log"; + + if (std::filesystem::exists(logPath)) { + std::error_code ec; + std::filesystem::remove(logPath, ec); + return !ec; // true = success + } + + return false; // File didn't exist +} \ No newline at end of file diff --git a/src/src/utils/utils.h b/src/src/utils/utils.h index e9e3320..c0b75d0 100644 --- a/src/src/utils/utils.h +++ b/src/src/utils/utils.h @@ -8,3 +8,5 @@ std::string GetFilenameFromPath(const std::string& path); // Loads a texture (with caching). Returns OpenGL texture ID GLuint LoadTextureIfNeeded(const std::string& path); + +bool DeleteLatestLogFile();