Updated Renderer and Logging

This commit is contained in:
OusmBlueNinja 2025-04-18 18:52:52 -05:00
parent e81041fa2b
commit 50d1189fb7
10 changed files with 403 additions and 184 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
@ -207,3 +195,21 @@ objects:
- type: ScriptComponent
scriptPath: C:\Users\spenc\OneDrive\Documents\GitHub\Create-Engine\src\assets\lua\test.lua
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

View File

@ -13,6 +13,8 @@
#include "utils/EngineConfig.h"
#include "utils/GameObjectsList.h"
#include "utils/Profiler.h"
#include "utils/utils.h"
#include <GL/glew.h>
#include <GLFW/glfw3.h>
@ -39,12 +41,20 @@
static std::shared_ptr<Object> selected = nullptr;
static bool playing = false;
static bool lastPlaying = false;
static std::vector<std::shared_ptr<Object>> 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<CameraComponent> 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<Object> 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<CameraComponent>();
}
@ -565,12 +583,12 @@ void DrawInspectorUI(std::shared_ptr<Object> 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<LightComponent>())
{
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<CameraComponent>())
{
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<Object> &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<Object> &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<Object> &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<Object>("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<Object> &obj)
ImGui::EndDragDropSource();
}
// === Drop Target ===
if (ImGui::BeginDragDropTarget())
{
if (const ImGuiPayload *payload = ImGui::AcceptDragDropPayload("OBJECT"))
{
auto dragged = *(std::shared_ptr<Object> *)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<Object> &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<const unsigned char *>(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<int>(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<std::string>();
}
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<const unsigned char *>(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<int>(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<float>();
if (data["saturation"])
cc->saturation = data["saturation"].as<float>();
if (data["gamma"])
cc->gamma = data["gamma"].as<float>();
}
}
Logger::LogInfo("[LoadScene] Loaded scene: %s", root["scene_name"].as<std::string>().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<Object>("[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<float>();
if (data["saturation"])
cc->saturation = data["saturation"].as<float>();
if (data["gamma"])
cc->gamma = data["gamma"].as<float>();
}
}
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);
}

View File

@ -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);

View File

@ -4,6 +4,42 @@
#include <cstdio>
#include <iostream>
// Logger.cpp or a logger helper header
#include <fstream>
#include <filesystem>
#include <windows.h>
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::LogMessage> 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;

View File

@ -1,13 +1,16 @@
#include "Shader.h"
#include "Logging.h"
#include "utils.h"
#include <fstream>
#include <sstream>
#include <iostream>
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;
}

View File

@ -1,6 +1,9 @@
#include "utils.h"
#include <map>
#include "stb_image.h"
#include <windows.h>
#include <filesystem>
#include <string>
static std::map<std::string, GLuint> 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
}

View File

@ -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();