Adde Profiling and user Setting saving
This commit is contained in:
parent
e409bed53f
commit
e81041fa2b
72
imgui.ini
72
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=1530,19
|
||||
Size=390,835
|
||||
Pos=890,19
|
||||
Size=390,292
|
||||
Collapsed=0
|
||||
DockId=0x00000005,0
|
||||
DockId=0x0000000B,0
|
||||
|
||||
[Window][Scene Tree]
|
||||
Pos=0,19
|
||||
Size=263,1158
|
||||
Size=376,366
|
||||
Collapsed=0
|
||||
DockId=0x00000001,0
|
||||
DockId=0x00000009,0
|
||||
|
||||
[Window][Viewport]
|
||||
Pos=265,19
|
||||
Size=1263,786
|
||||
Pos=378,19
|
||||
Size=510,218
|
||||
Collapsed=0
|
||||
DockId=0x00000007,0
|
||||
|
||||
@ -36,16 +36,16 @@ Size=1280,19
|
||||
Collapsed=0
|
||||
|
||||
[Window][Performance Info]
|
||||
Pos=1530,856
|
||||
Size=390,321
|
||||
Pos=890,526
|
||||
Size=390,194
|
||||
Collapsed=0
|
||||
DockId=0x00000006,0
|
||||
|
||||
[Window][Console]
|
||||
Pos=265,807
|
||||
Size=1263,370
|
||||
Pos=0,387
|
||||
Size=376,333
|
||||
Collapsed=0
|
||||
DockId=0x00000008,0
|
||||
DockId=0x0000000A,0
|
||||
|
||||
[Window][Tilemap Editor]
|
||||
Pos=265,19
|
||||
@ -53,14 +53,48 @@ Size=1263,674
|
||||
Collapsed=0
|
||||
DockId=0x00000007,1
|
||||
|
||||
[Window][Profiler]
|
||||
Pos=378,239
|
||||
Size=510,481
|
||||
Collapsed=0
|
||||
DockId=0x00000008,0
|
||||
|
||||
[Window][Profiler Timeline]
|
||||
Pos=265,69
|
||||
Size=623,651
|
||||
Collapsed=0
|
||||
DockId=0x00000008,1
|
||||
|
||||
[Window][Profiler (Unity Style)]
|
||||
Pos=265,430
|
||||
Size=623,290
|
||||
Collapsed=0
|
||||
DockId=0x00000008,1
|
||||
|
||||
[Window][Profiler Timeline View]
|
||||
Pos=265,526
|
||||
Size=1263,651
|
||||
Collapsed=0
|
||||
DockId=0x00000008,1
|
||||
|
||||
[Window][Color Correction]
|
||||
Pos=890,313
|
||||
Size=390,211
|
||||
Collapsed=0
|
||||
DockId=0x0000000C,0
|
||||
|
||||
[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=0x00000003 Parent=0x11111111 SizeRef=888,1158 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=263,701 HiddenTabBar=1 Selected=0x12EF0F59
|
||||
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=623,701 Split=Y Selected=0xC450F867
|
||||
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,329 CentralNode=1 Selected=0xC450F867
|
||||
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,370 Selected=0xEA83D666
|
||||
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 HiddenTabBar=1 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
|
||||
|
||||
|
@ -39,6 +39,7 @@ cxx: g++
|
||||
cxxflags:
|
||||
- -std=c++20
|
||||
- -Wall
|
||||
- -g
|
||||
|
||||
# Auto-detect libraries and headers
|
||||
auto_libs:
|
||||
|
@ -1,3 +1,10 @@
|
||||
[COMPILE] g++ -std=c++20 -Wall -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -IC:/msys64/mingw64/include -IC:\msys64\mingw64\lib\libyaml-cpp.a -Isrc\vendor\imgui -MMD -MP -c src\src\Components\ScriptComponent.cpp -o src\build\Components\ScriptComponent.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\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
|
||||
[RUN] Executed app.exe successfully.
|
||||
[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
|
||||
|
16
src/assets/lua/slow.lua
Normal file
16
src/assets/lua/slow.lua
Normal file
@ -0,0 +1,16 @@
|
||||
Engine.DebugLua(true)
|
||||
|
||||
local function sleep (a)
|
||||
local sec = tonumber(os.clock() + a);
|
||||
while (os.clock() < sec) do
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function OnInit()
|
||||
|
||||
end
|
||||
|
||||
function OnUpdate(dt)
|
||||
sleep(0.001)
|
||||
end
|
@ -1,12 +1,13 @@
|
||||
engine_version: 0.1.0
|
||||
scene_name: lighting_test_2
|
||||
scene_hash: a0ae96d593e1990a6f3944184fd6595738629af0dcb2d4cdd83011a91aaa738c
|
||||
scene_hash: 8f8260f09292105727f7f8afe890565a9feeaa92a1ca6d7fa55790a5019c67d7
|
||||
format_version: 1
|
||||
objects:
|
||||
- name: Tiles
|
||||
uid: f5e01f7892874a67b662633650b41dbd
|
||||
id: 3
|
||||
position: [0, 0]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components: []
|
||||
@ -15,6 +16,7 @@ objects:
|
||||
uid: 7dc3bbf8affb4844ae3801f03857b904
|
||||
id: 4
|
||||
position: [0, 0]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components:
|
||||
@ -27,6 +29,7 @@ objects:
|
||||
uid: 13d8988343354e3c8a1f51c03ed40cda
|
||||
id: 5
|
||||
position: [1024, 0]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components:
|
||||
@ -39,6 +42,7 @@ objects:
|
||||
uid: cff28abe7e3b455ab9b756acc84cd2d7
|
||||
id: 6
|
||||
position: [0, 1024]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components:
|
||||
@ -51,6 +55,7 @@ objects:
|
||||
uid: 98967eb30e5b429b992766d8062b7c17
|
||||
id: 7
|
||||
position: [1024, 1024]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components:
|
||||
@ -62,7 +67,8 @@ objects:
|
||||
- name: Logo
|
||||
uid: c4ce6f16dfb347b0ae0ac67f5881b243
|
||||
id: 8
|
||||
position: [2048, 0]
|
||||
position: [2104, 56]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components:
|
||||
@ -74,7 +80,8 @@ objects:
|
||||
- name: Carbooon Fobar
|
||||
uid: 5ea269572751401da6d86519d3513b7d
|
||||
id: 9
|
||||
position: [2559.30005, 1562]
|
||||
position: [2048, 3070]
|
||||
rotation: 0
|
||||
layer: 1
|
||||
visable: true
|
||||
components:
|
||||
@ -86,7 +93,8 @@ objects:
|
||||
- name: Mud
|
||||
uid: a36b71937ba349bd8e6414f75be9ee16
|
||||
id: 10
|
||||
position: [0, 2561.80005]
|
||||
position: [0, 3070]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components:
|
||||
@ -99,6 +107,7 @@ objects:
|
||||
uid: 051b338a725a4076ad53ad8fa00c5f4e
|
||||
id: 12
|
||||
position: [-556, 951]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components: []
|
||||
@ -107,6 +116,7 @@ objects:
|
||||
uid: 6afde2dd47aa4557b6afb1a607c99dc8
|
||||
id: 13
|
||||
position: [512, 1024]
|
||||
rotation: 0
|
||||
layer: 2
|
||||
visable: true
|
||||
components:
|
||||
@ -128,6 +138,7 @@ objects:
|
||||
uid: 0f950d76d24b4dc18f54cab2c3aaaf9a
|
||||
id: 14
|
||||
position: [1024, 512]
|
||||
rotation: 0
|
||||
layer: 2
|
||||
visable: true
|
||||
components:
|
||||
@ -149,6 +160,7 @@ objects:
|
||||
uid: 09f722f51c7c4b0f98de3a0a16d127c4
|
||||
id: 15
|
||||
position: [250, 250]
|
||||
rotation: 0
|
||||
layer: 2
|
||||
visable: true
|
||||
components:
|
||||
@ -170,6 +182,7 @@ objects:
|
||||
uid: d4fb425522d84a8cbbd7d1415bcd93df
|
||||
id: 16
|
||||
position: [500, 500]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components:
|
||||
@ -187,6 +200,7 @@ objects:
|
||||
uid: 895c655f3dda4aec9f2a354c1276c53e
|
||||
id: 14
|
||||
position: [0, 0]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components:
|
||||
|
@ -6,6 +6,11 @@ out vec4 FragColor;
|
||||
|
||||
uniform sampler2D uTex;
|
||||
uniform sampler2D uNormalMap;
|
||||
uniform float uRotation;
|
||||
|
||||
uniform float uBrightness;
|
||||
uniform float uSaturation;
|
||||
uniform float uGamma;
|
||||
|
||||
#define MAX_LIGHTS 512
|
||||
|
||||
@ -17,16 +22,22 @@ uniform float uLightRadius[MAX_LIGHTS];
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 texColor = texture(uTex, vUV);
|
||||
// Rotate UV 90° clockwise
|
||||
vec2 rotatedUV = vec2(vUV.y, 1.0 - vUV.x);
|
||||
|
||||
vec4 texColor = texture(uTex, rotatedUV);
|
||||
if (texColor.a < 0.1)
|
||||
discard;
|
||||
|
||||
// unpack normal map and convert from [0,1] to [-1,1]
|
||||
vec3 n = texture(uNormalMap, vUV).rgb * 2.0 - 1.0;
|
||||
// invert the green channel for OpenGL
|
||||
vec3 n = texture(uNormalMap, rotatedUV).rgb * 2.0 - 1.0;
|
||||
n.y = -n.y;
|
||||
vec3 normal = normalize(n);
|
||||
|
||||
float c = cos(uRotation);
|
||||
float s = sin(uRotation);
|
||||
mat2 rot = mat2(c, -s, s, c);
|
||||
n.xy = rot * n.xy;
|
||||
|
||||
vec3 normal = normalize(n);
|
||||
vec3 finalLight = vec3(0.0);
|
||||
|
||||
for (int i = 0; i < uLightCount; ++i)
|
||||
@ -37,9 +48,8 @@ void main()
|
||||
if (dist < uLightRadius[i])
|
||||
{
|
||||
vec2 lightDir2D = normalize(lightVec);
|
||||
vec3 lightDir = normalize(vec3(lightDir2D, 1.0)); // pseudo-3D
|
||||
|
||||
float attenuation = 1.0 - dist / uLightRadius[i];
|
||||
vec3 lightDir = normalize(vec3(lightDir2D, 1.0));
|
||||
float attenuation = smoothstep(uLightRadius[i], 0.0, dist);
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
vec3 light = uLightColor[i] * diff * attenuation * uLightIntensity[i];
|
||||
finalLight += light;
|
||||
@ -47,5 +57,15 @@ void main()
|
||||
}
|
||||
|
||||
vec3 result = texColor.rgb * finalLight;
|
||||
|
||||
result *= uBrightness;
|
||||
|
||||
float gray = dot(result, vec3(0.299, 0.587, 0.114));
|
||||
result = mix(vec3(gray), result, uSaturation);
|
||||
|
||||
result = pow(result, vec3(1.0 / uGamma));
|
||||
|
||||
result = clamp(result, 0.0, 1.0);
|
||||
|
||||
FragColor = vec4(result, texColor.a);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
#version 430 core
|
||||
#version 330 core
|
||||
|
||||
layout (location = 0) in vec2 aPos;
|
||||
layout (location = 1) in vec2 aUV;
|
||||
@ -9,17 +9,22 @@ out vec2 vFragScreenPos;
|
||||
uniform vec2 uPos;
|
||||
uniform vec2 uSize;
|
||||
uniform vec2 uScreen;
|
||||
uniform float uRotation;//r
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 centered = aPos - vec2(0.5);
|
||||
|
||||
float s = cos(uRotation);
|
||||
float c = sin(uRotation);
|
||||
mat2 rot = mat2(c, -s, s, c);
|
||||
vec2 rotated = rot * (centered * uSize);
|
||||
|
||||
vec2 finalPos = uPos + rotated;
|
||||
|
||||
vUV = aUV;
|
||||
vFragScreenPos = finalPos;
|
||||
|
||||
vec2 worldPos = uPos + aPos * uSize;
|
||||
|
||||
vFragScreenPos = worldPos;
|
||||
|
||||
vec2 ndc = (worldPos / uScreen) * 2.0 - 1.0;
|
||||
ndc.y *= -1.0;
|
||||
|
||||
gl_Position = vec4(ndc, 0.0, 1.0);
|
||||
vec2 ndc = finalPos / uScreen * 2.0 - 1.0;
|
||||
gl_Position = vec4(ndc.x, -ndc.y, 0.0, 1.0); // Y-flip
|
||||
}
|
||||
|
@ -1,10 +1,15 @@
|
||||
#version 430 core
|
||||
#version 330 core
|
||||
in vec2 vUV;
|
||||
out vec4 FragColor;
|
||||
uniform sampler2D uTex;
|
||||
void main() {
|
||||
vec4 color = texture(uTex, vUV);
|
||||
|
||||
uniform sampler2D uTex;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
vec2 rotatedUV = vec2(vUV.y, 1.0 - vUV.x);
|
||||
|
||||
vec4 color = texture(uTex, rotatedUV);
|
||||
if (color.a < 0.01)
|
||||
discard;
|
||||
|
||||
|
@ -1,13 +1,28 @@
|
||||
#version 430 core
|
||||
#version 330 core
|
||||
layout (location = 0) in vec2 aPos;
|
||||
layout (location = 1) in vec2 aUV;
|
||||
|
||||
out vec2 vUV;
|
||||
out vec2 vFragScreenPos;
|
||||
|
||||
uniform vec2 uPos;
|
||||
uniform vec2 uSize;
|
||||
uniform vec2 uScreen;
|
||||
void main() {
|
||||
vec2 worldPos = aPos * uSize + uPos;
|
||||
uniform float uRotation; // radians
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 centered = aPos - vec2(0.5);
|
||||
float s = cos(uRotation);
|
||||
float c = sin(uRotation);
|
||||
mat2 rot = mat2(c, -s, s, c);
|
||||
vec2 rotated = rot * (centered * uSize);
|
||||
|
||||
vec2 finalPos = uPos + rotated;
|
||||
|
||||
vFragScreenPos = finalPos;
|
||||
vUV = aUV;
|
||||
vec2 ndc = (worldPos / uScreen) * 2.0 - 1.0;
|
||||
gl_Position = vec4(ndc.x, -ndc.y, 0.0, 1.0);
|
||||
|
||||
vec2 ndc = finalPos / uScreen * 2.0 - 1.0;
|
||||
gl_Position = vec4(ndc.x, -ndc.y, 0.0, 1.0); // Y flip for OpenGL
|
||||
}
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include "../Components/TextComponent.h"
|
||||
#include "../Components/TilemapComponent.h"
|
||||
|
||||
#include "../utils/Profiler.h"
|
||||
|
||||
#include <lua.hpp>
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
@ -74,6 +76,8 @@ static int Lua_DebugLua(lua_State *L)
|
||||
// Component resolver
|
||||
static Component *GetComponentByName(Object *obj, const std::string &type)
|
||||
{
|
||||
PROFILE_SCOPE("LUA_GetComponentByName");
|
||||
|
||||
if (type == "SpriteComponent")
|
||||
return obj->GetComponent<SpriteComponent>().get();
|
||||
if (type == "CameraComponent")
|
||||
@ -92,6 +96,8 @@ static Component *GetComponentByName(Object *obj, const std::string &type)
|
||||
// Object:GetComponent("Type")
|
||||
static int Lua_Object_GetComponent(lua_State *L)
|
||||
{
|
||||
PROFILE_SCOPE("Lua_Object_GetComponent");
|
||||
|
||||
auto *wrapper = (LuaObjectWrapper *)luaL_checkudata(L, 1, LUA_OBJECT_MT);
|
||||
const char *type = luaL_checkstring(L, 2);
|
||||
|
||||
@ -106,6 +112,8 @@ static int Lua_Object_GetComponent(lua_State *L)
|
||||
// Object:GetPosition()
|
||||
static int Lua_Object_GetPosition(lua_State *L)
|
||||
{
|
||||
PROFILE_SCOPE("Lua_Object_GetPosition");
|
||||
|
||||
auto *wrapper = (LuaObjectWrapper *)luaL_checkudata(L, 1, LUA_OBJECT_MT);
|
||||
glm::vec2 pos = wrapper->obj->GetLocalPosition();
|
||||
|
||||
@ -120,6 +128,8 @@ static int Lua_Object_GetPosition(lua_State *L)
|
||||
// Object:SetPosition(Vector2)
|
||||
static int Lua_Object_SetPosition(lua_State *L)
|
||||
{
|
||||
PROFILE_SCOPE("Lua_Object_SetPosition");
|
||||
|
||||
auto *wrapper = (LuaObjectWrapper *)luaL_checkudata(L, 1, LUA_OBJECT_MT);
|
||||
auto *vec = (LuaVector2 *)luaL_checkudata(L, 2, LUA_VECTOR2_MT);
|
||||
wrapper->obj->SetLocalPosition({vec->x, vec->y});
|
||||
@ -129,6 +139,8 @@ static int Lua_Object_SetPosition(lua_State *L)
|
||||
// __index for Object
|
||||
static int Lua_Object_Index(lua_State *L)
|
||||
{
|
||||
PROFILE_SCOPE("Lua_Object_Index");
|
||||
|
||||
const char *key = luaL_checkstring(L, 2);
|
||||
lua_getfield(L, lua_upvalueindex(1), key);
|
||||
return 1;
|
||||
@ -163,6 +175,8 @@ static void PushObject(lua_State *L, Object *obj)
|
||||
// Engine.GetObjectByTag(name)
|
||||
static int Lua_GetObjectByTag(lua_State *L)
|
||||
{
|
||||
PROFILE_SCOPE("Lua_GetObjectByTag");
|
||||
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
for (const auto &obj : objects)
|
||||
{
|
||||
@ -180,16 +194,22 @@ static int Lua_GetObjectByTag(lua_State *L)
|
||||
// Vector2(x, y)
|
||||
static int Lua_Vector2_New(lua_State *L)
|
||||
{
|
||||
LuaVector2 *vec = (LuaVector2 *)lua_newuserdata(L, sizeof(LuaVector2));
|
||||
vec->x = (float)luaL_optnumber(L, 1, 0);
|
||||
vec->y = (float)luaL_optnumber(L, 2, 0);
|
||||
luaL_getmetatable(L, LUA_VECTOR2_MT);
|
||||
lua_setmetatable(L, -2);
|
||||
PROFILE_SCOPE("Lua_Vector2_New");
|
||||
|
||||
LuaVector2 *vec = static_cast<LuaVector2 *>(lua_newuserdata(L, sizeof(LuaVector2)));
|
||||
|
||||
int nargs = lua_gettop(L);
|
||||
vec->x = nargs >= 1 ? (float)lua_tonumber(L, 1) : 0.0f;
|
||||
vec->y = nargs >= 2 ? (float)lua_tonumber(L, 2) : 0.0f;
|
||||
|
||||
luaL_setmetatable(L, LUA_VECTOR2_MT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int Lua_Vector2_Index(lua_State *L)
|
||||
{
|
||||
PROFILE_SCOPE("Lua_Vector2_Index");
|
||||
|
||||
auto *vec = (LuaVector2 *)luaL_checkudata(L, 1, LUA_VECTOR2_MT);
|
||||
const char *key = luaL_checkstring(L, 2);
|
||||
if (strcmp(key, "x") == 0)
|
||||
@ -202,6 +222,8 @@ static int Lua_Vector2_Index(lua_State *L)
|
||||
}
|
||||
static int Lua_Vector2_NewIndex(lua_State *L)
|
||||
{
|
||||
PROFILE_SCOPE("Lua_Vector2_NewIndex");
|
||||
|
||||
auto *vec = (LuaVector2 *)luaL_checkudata(L, 1, LUA_VECTOR2_MT);
|
||||
const char *key = luaL_checkstring(L, 2);
|
||||
float value = (float)luaL_checknumber(L, 3);
|
||||
@ -214,6 +236,7 @@ static int Lua_Vector2_NewIndex(lua_State *L)
|
||||
|
||||
void RegisterVector2Type(lua_State *L)
|
||||
{
|
||||
|
||||
luaL_newmetatable(L, LUA_VECTOR2_MT);
|
||||
lua_pushcfunction(L, Lua_Vector2_Index);
|
||||
lua_setfield(L, -2, "__index");
|
||||
@ -286,6 +309,8 @@ void ScriptComponent::ReloadScript()
|
||||
|
||||
void ScriptComponent::OnUpdate(float dt)
|
||||
{
|
||||
PROFILE_SCOPE("ScriptComponent::OnUpdate");
|
||||
|
||||
if (!L)
|
||||
return;
|
||||
lua_getglobal(L, "OnUpdate");
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include "../utils/utils.h"
|
||||
|
||||
|
||||
|
||||
|
||||
struct ImageCacheEntry {
|
||||
unsigned int textureID;
|
||||
glm::vec2 size;
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "utils/EngineConfig.h"
|
||||
#include "utils/GameObjectsList.h"
|
||||
#include "utils/Profiler.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
@ -24,6 +25,10 @@
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <algorithm>
|
||||
#include <format>
|
||||
#include <memory>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
@ -40,14 +45,15 @@ static glm::vec2 cameraPos = {0, 0};
|
||||
static float cameraZoom = 1.0f;
|
||||
static ImVec2 lastMousePos = {};
|
||||
|
||||
static const std::string tempScenePath = "__tmp_scene.yaml";
|
||||
float g_fps = 0.0f;
|
||||
|
||||
static float g_fps = 0.0f;
|
||||
static const std::string tempScenePath = "__tmp_scene.yaml";
|
||||
|
||||
GLFWwindow *window = nullptr;
|
||||
|
||||
Engine::Engine()
|
||||
{
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
@ -56,46 +62,251 @@ Engine::~Engine()
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void DrawProfilerTimelineBars(const ProfileNode &node,
|
||||
int depth,
|
||||
float baseOffsetX,
|
||||
float frameDuration,
|
||||
ImVec2 origin)
|
||||
{
|
||||
constexpr float rowHeight = 24.0f;
|
||||
constexpr float textPadding = 5.0f;
|
||||
|
||||
// compute bar rect
|
||||
float startRel = node.visualStartMs / frameDuration;
|
||||
float durRel = node.visualDurationMs / frameDuration;
|
||||
float x = origin.x + startRel * baseOffsetX;
|
||||
float width = std::fmax(1.0f, durRel * baseOffsetX);
|
||||
float y = origin.y + depth * rowHeight;
|
||||
|
||||
ImVec2 barMin(x, y);
|
||||
ImVec2 barMax(x + width, y + rowHeight - 4.0f);
|
||||
|
||||
// draw the bar
|
||||
size_t hash = std::hash<std::string>{}(node.name);
|
||||
ImU32 color = ImColor::HSV((hash % 1000) / 1000.0f, 0.6f, 0.85f);
|
||||
ImDrawList *draw = ImGui::GetWindowDrawList();
|
||||
draw->AddRectFilled(barMin, barMax, color, 3.0f);
|
||||
draw->AddRect(barMin, barMax, IM_COL32_BLACK, 3.0f);
|
||||
|
||||
// how much room we have for text
|
||||
float availW = width - textPadding * 2;
|
||||
const char *textToDraw = nullptr;
|
||||
|
||||
// 1) try the short "XX.XX ms"
|
||||
char timeBuf[16];
|
||||
int tn = std::snprintf(timeBuf, sizeof(timeBuf), "%.2f ms", node.visualDurationMs);
|
||||
if (tn > 0)
|
||||
{
|
||||
ImVec2 sz = ImGui::CalcTextSize(timeBuf);
|
||||
if (sz.x <= availW)
|
||||
{
|
||||
textToDraw = timeBuf;
|
||||
}
|
||||
}
|
||||
|
||||
// 2) only if the short fits, see if full fits
|
||||
if (textToDraw == timeBuf)
|
||||
{
|
||||
char fullBuf[64];
|
||||
int fn = std::snprintf(fullBuf, sizeof(fullBuf),
|
||||
"%s (%.2f ms)",
|
||||
node.name.c_str(),
|
||||
node.visualDurationMs);
|
||||
if (fn > 0)
|
||||
{
|
||||
ImVec2 fsz = ImGui::CalcTextSize(fullBuf);
|
||||
if (fsz.x <= availW)
|
||||
{
|
||||
textToDraw = fullBuf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3) draw if we decided on something
|
||||
if (textToDraw)
|
||||
{
|
||||
draw->AddText(
|
||||
ImVec2(barMin.x + textPadding,
|
||||
barMin.y),
|
||||
IM_COL32_WHITE,
|
||||
textToDraw);
|
||||
}
|
||||
|
||||
// tooltip
|
||||
ImVec2 mouse = ImGui::GetMousePos();
|
||||
if (mouse.x >= barMin.x && mouse.x <= barMax.x &&
|
||||
mouse.y >= barMin.y && mouse.y <= barMax.y)
|
||||
{
|
||||
ImGui::SetTooltip(
|
||||
"%s\nCurrent: %.3f ms\nSmoothed: %.3f ms",
|
||||
node.name.c_str(),
|
||||
node.durationMs,
|
||||
node.visualDurationMs);
|
||||
}
|
||||
|
||||
// recurse
|
||||
for (auto &child : node.children)
|
||||
DrawProfilerTimelineBars(child,
|
||||
depth + 1,
|
||||
baseOffsetX,
|
||||
frameDuration,
|
||||
origin);
|
||||
}
|
||||
|
||||
static ProfileNode GetAveragedFrameCopy(const ProfileNode &src)
|
||||
{
|
||||
ProfileNode averaged = src;
|
||||
averaged.visualStartMs = src.startMs;
|
||||
averaged.visualDurationMs = src.durationMs;
|
||||
|
||||
averaged.children.clear();
|
||||
for (const auto &child : src.children)
|
||||
averaged.children.push_back(GetAveragedFrameCopy(child));
|
||||
|
||||
return averaged;
|
||||
}
|
||||
|
||||
void ShowProfilerTimeline()
|
||||
{
|
||||
|
||||
static ProfileNode cachedAveragedFrame;
|
||||
static double lastUpdateTime = 0.0;
|
||||
static double updateInterval = 0.25;
|
||||
static bool freezeView = false;
|
||||
|
||||
const double now = ImGui::GetTime();
|
||||
const ProfileNode *latest = profiler.GetLatestFrame();
|
||||
|
||||
ImGui::Begin("Profiler", nullptr, ImGuiWindowFlags_NoScrollbar);
|
||||
|
||||
// --- Controls ---
|
||||
if (g_engineConfig.settings.profile_enabled)
|
||||
{
|
||||
|
||||
ImGui::Checkbox("Freeze View", &freezeView);
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(100);
|
||||
float interval = static_cast<float>(updateInterval);
|
||||
if (ImGui::DragFloat("Update Interval", &interval, 0.05f, 0.05f, 5.0f))
|
||||
updateInterval = interval;
|
||||
|
||||
updateInterval = std::clamp(updateInterval, 0.05, 5.0);
|
||||
|
||||
if (!freezeView && latest && (now - lastUpdateTime) >= updateInterval)
|
||||
{
|
||||
cachedAveragedFrame = GetAveragedFrameCopy(*latest);
|
||||
lastUpdateTime = now;
|
||||
}
|
||||
|
||||
if (cachedAveragedFrame.durationMs <= 0.0f)
|
||||
{
|
||||
ImGui::Text("Waiting for profiler data...");
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
const float rowHeight = 24.0f;
|
||||
const float timelineHeight = 400.0f;
|
||||
float frameDuration = cachedAveragedFrame.visualDurationMs;
|
||||
float timelineWidth = ImGui::GetContentRegionAvail().x * 0.95f;
|
||||
|
||||
ImGui::BeginChild("TimelineScroll", ImVec2(0, timelineHeight));
|
||||
ImVec2 origin = ImGui::GetCursorScreenPos();
|
||||
|
||||
DrawProfilerTimelineBars(cachedAveragedFrame, 0, timelineWidth, frameDuration, origin);
|
||||
|
||||
ImGui::Dummy(ImVec2(timelineWidth, 32 * rowHeight));
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::Text("Frame Duration (Avg): %.2f ms | View Update Rate: %.2fs", frameDuration, updateInterval);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("Profiling Disabled.");
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void Engine::ShowDebugOverlay(float deltaTime)
|
||||
{
|
||||
// === Performance Window ===
|
||||
static std::vector<float> fpsHistory;
|
||||
static const int maxHistory = 100;
|
||||
static float timer = 0;
|
||||
static const int maxFpsHistory = 100;
|
||||
static float fpsTimer = 0.0f;
|
||||
float fps = 1.0f / deltaTime;
|
||||
g_fps = fps;
|
||||
if (fpsHistory.size() >= maxHistory)
|
||||
if (fpsHistory.size() >= maxFpsHistory)
|
||||
fpsHistory.erase(fpsHistory.begin());
|
||||
if (timer >= 0.05)
|
||||
if (fpsTimer >= 0.05f)
|
||||
{
|
||||
timer = 0;
|
||||
fpsTimer = 0;
|
||||
fpsHistory.push_back(fps);
|
||||
}
|
||||
timer += deltaTime;
|
||||
fpsTimer += deltaTime;
|
||||
|
||||
ImGui::Begin("Performance Info", nullptr,
|
||||
ImGuiWindowFlags_NoDecoration);
|
||||
ImGui::Begin("Performance Info", nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize);
|
||||
|
||||
ImGui::TextColored(ImVec4(0.3f, 1.0f, 0.3f, 1.0f), "Performance");
|
||||
ImGui::Separator();
|
||||
ImGui::Text("FPS: %.1f", fps);
|
||||
ImGui::Text("Delta Time: %.4f s", deltaTime);
|
||||
ImGui::Text("Frame Time: %.2f ms", deltaTime * 1000.0f);
|
||||
ImGui::PlotLines("##FPS", fpsHistory.data(), fpsHistory.size(), 0, "FPS History", 0.0f, 144.0f, ImVec2(-1, 50));
|
||||
|
||||
if (!fpsHistory.empty())
|
||||
{
|
||||
float maxFps = *std::max_element(fpsHistory.begin(), fpsHistory.end());
|
||||
maxFps = std::max(maxFps * 1.1f, 60.0f);
|
||||
|
||||
ImGui::PlotLines("##FPS", fpsHistory.data(), fpsHistory.size(), 0, "FPS History",
|
||||
0.0f, maxFps, ImVec2(-1, 50));
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("FPS data unavailable");
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::TextColored(ImVec4(0.4f, 0.7f, 1.0f, 1.0f), "Renderer");
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Draw Calls: %d", Renderer::GetDrawCallCount());
|
||||
ImGui::Text("Lua OnUpdate Calls: %d", m_OnUpdateCalls);
|
||||
ImGui::Text("Scene Lights: %d / %d", Renderer::GetLightsCount(), g_engineConfig.gl_maxLight);
|
||||
|
||||
ImGui::Text("Reserved Draws: %d", m_Reserved_draws);
|
||||
|
||||
ImGui::Text("Camera Zoom: %.2f", cameraZoom);
|
||||
ImGui::Text("Camera Pos: (%.1f, %.1f)", cameraPos.x, cameraPos.y);
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void ShowColorCorrectionWindow()
|
||||
{
|
||||
PROFILE_ENGINE_SCOPE("Engine::ShowColorCorrectionWindow");
|
||||
|
||||
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");
|
||||
|
||||
ImGui::Spacing();
|
||||
|
||||
if (ImGui::Button("Reset to Default"))
|
||||
{
|
||||
*cc = ColorCorrection();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Engine::Init()
|
||||
{
|
||||
glfwInit();
|
||||
@ -108,6 +319,8 @@ void Engine::Init()
|
||||
glfwSwapInterval(0); // No VSync
|
||||
glewInit();
|
||||
|
||||
g_engineConfig.LoadFromFile();
|
||||
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
@ -123,10 +336,16 @@ void Engine::Init()
|
||||
|
||||
objects.push_back(obj);
|
||||
selected = obj;
|
||||
Logger::LogVerbose("Resverving Objects");
|
||||
|
||||
m_toDraw.reserve(1024);
|
||||
m_scriptUpdates.reserve(256);
|
||||
m_collectStack.reserve(1024);
|
||||
Logger::LogInfo("Initialized Engine");
|
||||
}
|
||||
void DrawInspectorUI(std::shared_ptr<Object> selected)
|
||||
{
|
||||
PROFILE_ENGINE_SCOPE("Engine::DrawInspectorUI");
|
||||
ImGui::Begin("Inspector");
|
||||
|
||||
if (!selected)
|
||||
@ -167,6 +386,10 @@ void DrawInspectorUI(std::shared_ptr<Object> selected)
|
||||
if (ImGui::DragFloat2("Position", &pos.x, 0.1f))
|
||||
selected->SetLocalPosition(pos);
|
||||
|
||||
float rotation = selected->GetLocalRotation();
|
||||
if (ImGui::DragFloat("Rotation", &rotation, 1.0f))
|
||||
selected->SetLocalRotation(rotation);
|
||||
|
||||
int layer = selected->layer;
|
||||
if (ImGui::InputInt("Layer", &layer))
|
||||
selected->layer = layer;
|
||||
@ -342,24 +565,109 @@ 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();
|
||||
|
||||
for (auto &root : objects)
|
||||
if (!root->GetParent())
|
||||
m_collectStack.push_back(root);
|
||||
|
||||
while (!m_collectStack.empty())
|
||||
{
|
||||
auto obj = m_collectStack.back();
|
||||
m_collectStack.pop_back();
|
||||
|
||||
if (!obj->GetVisable())
|
||||
continue;
|
||||
m_toDraw.push_back(obj.get());
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (playing)
|
||||
{
|
||||
if (auto script = obj->GetComponent<ScriptComponent>())
|
||||
m_scriptUpdates.push_back(script.get());
|
||||
}
|
||||
|
||||
for (auto &child : obj->GetChildren())
|
||||
m_collectStack.push_back(child);
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::Run()
|
||||
{
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
if (g_engineConfig.settings.profile_editor)
|
||||
{
|
||||
profiler.BeginFrame();
|
||||
}
|
||||
|
||||
profiler.BeginEngineSection("glfwPollEvents");
|
||||
|
||||
glfwPollEvents();
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.BeginEngineSection("NewFrame");
|
||||
|
||||
profiler.BeginEngineSection("ImGui_ImplOpenGL3_NewFrame");
|
||||
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.BeginEngineSection("ImGui_ImplGlfw_NewFrame");
|
||||
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.BeginEngineSection("ImGui::NewFrame");
|
||||
|
||||
ImGui::NewFrame();
|
||||
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.BeginEngineSection("ImGui::DockSpaceOverViewport");
|
||||
|
||||
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport()->ID);
|
||||
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.BeginEngineSection("glfwGetTime");
|
||||
|
||||
float currentTime = glfwGetTime();
|
||||
static float lastTime = currentTime;
|
||||
float deltaTime = currentTime - lastTime;
|
||||
lastTime = currentTime;
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.BeginEngineSection("Engine::ShowDebugOverlay");
|
||||
|
||||
ShowDebugOverlay(deltaTime);
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.BeginEngineSection("Logger::Draw");
|
||||
|
||||
Logger::Draw();
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.BeginEngineSection("BeginMainMenuBar");
|
||||
|
||||
if (ImGui::BeginMainMenuBar())
|
||||
{
|
||||
@ -402,9 +710,24 @@ void Engine::Run()
|
||||
|
||||
if (ImGui::BeginMenu("Options"))
|
||||
{
|
||||
// simple checkbox never closes the menu when you click it
|
||||
ImGui::Checkbox("Enable Lighting", &g_engineConfig.lighting_enabled);
|
||||
|
||||
if (ImGui::BeginMenu("Settings"))
|
||||
{
|
||||
ImGui::Checkbox("Enable Lighting", &g_engineConfig.settings.lighting_enabled);
|
||||
ImGui::Checkbox("Enable Gizmos", &g_engineConfig.settings.draw_gizmos);
|
||||
ImGui::Checkbox("Profiling", &g_engineConfig.settings.profile_enabled);
|
||||
if (g_engineConfig.settings.profile_enabled)
|
||||
{
|
||||
ImGui::Checkbox("Profile Engine", &g_engineConfig.settings.profile_editor);
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Windows"))
|
||||
{
|
||||
ImGui::Checkbox("Color Correction", &g_engineConfig.settings.show_color_correction_window);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@ -426,6 +749,14 @@ void Engine::Run()
|
||||
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
profiler.EndEngineSection();
|
||||
|
||||
if (g_engineConfig.settings.show_color_correction_window)
|
||||
ShowColorCorrectionWindow();
|
||||
|
||||
|
||||
{
|
||||
PROFILE_ENGINE_SCOPE("Engine::DrawSceneTree");
|
||||
|
||||
ImGui::Begin("Scene Tree");
|
||||
|
||||
@ -463,6 +794,7 @@ void Engine::Run()
|
||||
DrawObjectNode(obj);
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
DrawInspectorUI(selected);
|
||||
|
||||
@ -506,95 +838,92 @@ void Engine::Run()
|
||||
}
|
||||
}
|
||||
|
||||
// Resize
|
||||
profiler.BeginEngineSection("Renderer::Resize");
|
||||
Renderer::Resize((int)size.x, (int)size.y);
|
||||
profiler.EndEngineSection();
|
||||
|
||||
// Begin
|
||||
profiler.BeginEngineSection("Renderer::Begin");
|
||||
Renderer::Begin();
|
||||
profiler.EndEngineSection();
|
||||
|
||||
std::vector<std::shared_ptr<Object>> toDraw;
|
||||
std::vector<ScriptComponent *> scriptUpdates;
|
||||
|
||||
toDraw.reserve(m_Reserved_draws);
|
||||
m_Reserved_draws = 0; // Reset
|
||||
|
||||
Renderer::DrawEditorGrid(cameraPos, cameraZoom);
|
||||
|
||||
// clear arrays each frame…
|
||||
toDraw.clear();
|
||||
scriptUpdates.clear();
|
||||
// Reserve (no profiling)
|
||||
m_toDraw.reserve(m_Reserved_draws);
|
||||
m_Reserved_draws = 0;
|
||||
|
||||
// recursive collector now skips invisible objects (and their children)
|
||||
std::function<void(const std::shared_ptr<Object> &)> collect =
|
||||
[&](const std::shared_ptr<Object> &obj)
|
||||
// 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);
|
||||
profiler.EndEngineSection();
|
||||
|
||||
// Sort Objects
|
||||
profiler.BeginEngineSection("Sort Objects");
|
||||
if (m_toDraw.size() > 1)
|
||||
{
|
||||
// if this object isn’t visible, skip it and its children
|
||||
if (!obj->GetVisable())
|
||||
return;
|
||||
|
||||
// still visible → collect for drawing
|
||||
toDraw.push_back(obj);
|
||||
m_Reserved_draws += 1;
|
||||
|
||||
// Collect lights
|
||||
if (auto light = obj->GetComponent<LightComponent>())
|
||||
{
|
||||
glm::vec2 world = obj->GetWorldPosition();
|
||||
glm::vec2 screen = (world - cameraPos) * cameraZoom + glm::vec2(Renderer::GetSize().x * 0.5f,
|
||||
Renderer::GetSize().y * 0.5f);
|
||||
Renderer::AddLight(screen,
|
||||
light->GetColor(),
|
||||
light->GetIntensity(),
|
||||
light->GetRadius() * cameraZoom);
|
||||
|
||||
Renderer::DrawGizmoCircle(
|
||||
world,
|
||||
light->GetRadius(),
|
||||
64, // segments
|
||||
light->GetColor(), // circle color
|
||||
cameraPos,
|
||||
cameraZoom);
|
||||
}
|
||||
|
||||
// Collect scripts
|
||||
if (playing)
|
||||
{
|
||||
if (auto script = obj->GetComponent<ScriptComponent>())
|
||||
scriptUpdates.push_back(script.get());
|
||||
}
|
||||
|
||||
// recurse into children
|
||||
for (const auto &child : obj->GetChildren())
|
||||
collect(child);
|
||||
};
|
||||
|
||||
// Traverse only root objects
|
||||
for (const auto &obj : objects)
|
||||
if (!obj->GetParent())
|
||||
collect(obj);
|
||||
|
||||
// Sort drawables by layer then Y
|
||||
std::sort(toDraw.begin(), toDraw.end(), [](auto const &a, auto const &b)
|
||||
std::sort(m_toDraw.begin(), m_toDraw.end(),
|
||||
[](auto const &a, auto const &b)
|
||||
{
|
||||
if (a->layer != b->layer)
|
||||
return a->layer < b->layer;
|
||||
return a->GetWorldPosition().y < b->GetWorldPosition().y; });
|
||||
return a->GetWorldPosition().y < b->GetWorldPosition().y;
|
||||
});
|
||||
}
|
||||
profiler.EndEngineSection();
|
||||
|
||||
// Run script updates
|
||||
for (auto *script : scriptUpdates)
|
||||
if (!g_engineConfig.settings.profile_editor)
|
||||
profiler.BeginFrame();
|
||||
|
||||
m_OnUpdateCalls = 0;
|
||||
|
||||
profiler.BeginSection("Script Updates");
|
||||
for (auto *script : m_scriptUpdates)
|
||||
{
|
||||
profiler.BeginSection("Script: " + script->GetOwner()->GetName());
|
||||
script->OnUpdate(deltaTime);
|
||||
m_OnUpdateCalls++;
|
||||
profiler.EndSection();
|
||||
}
|
||||
profiler.EndSection();
|
||||
|
||||
// Draw all sprites
|
||||
for (const auto &obj : toDraw)
|
||||
profiler.BeginSection("Render");
|
||||
for (auto *obj : m_toDraw)
|
||||
{
|
||||
if (auto sprite = obj->GetComponent<SpriteComponent>())
|
||||
if (auto spritePtr = obj->GetComponent<SpriteComponent>())
|
||||
{
|
||||
glm::vec2 worldPos = obj->GetWorldPosition();
|
||||
Renderer::DrawSprite(sprite.get(), worldPos, cameraZoom, cameraPos);
|
||||
profiler.BeginSection("Draw Sprite: " + obj->GetName());
|
||||
Renderer::DrawSprite(spritePtr.get(),
|
||||
obj->GetWorldPosition(),
|
||||
cameraZoom,
|
||||
cameraPos);
|
||||
profiler.EndSection();
|
||||
}
|
||||
}
|
||||
profiler.EndSection();
|
||||
|
||||
// Finish frame profiling
|
||||
if (!g_engineConfig.settings.profile_editor)
|
||||
profiler.EndFrame();
|
||||
|
||||
// End renderer
|
||||
profiler.BeginEngineSection("Renderer::End");
|
||||
Renderer::End();
|
||||
profiler.EndEngineSection();
|
||||
|
||||
// Display render target texture
|
||||
GLuint texID = Renderer::GetRenderTexture();
|
||||
ImGui::Image((ImTextureID)(uintptr_t)texID, size, ImVec2(0, 1), ImVec2(1, 0));
|
||||
|
||||
ImGui::End();
|
||||
|
||||
if (ImGui::BeginPopup("RenameObject"))
|
||||
@ -627,7 +956,13 @@ void Engine::Run()
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (g_engineConfig.settings.profile_editor)
|
||||
{
|
||||
profiler.EndFrame(); // Finish frame
|
||||
}
|
||||
// ImGui render
|
||||
ShowProfilerTimeline();
|
||||
|
||||
ImGui::Render();
|
||||
int w, h;
|
||||
glfwGetFramebufferSize(window, &w, &h);
|
||||
@ -656,6 +991,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);
|
||||
@ -813,7 +1150,6 @@ void Engine::LoadScene(const std::string &path)
|
||||
Logger::LogInfo("[LoadScene] Loaded scene: %s", root["scene_name"].as<std::string>().c_str());
|
||||
}
|
||||
|
||||
|
||||
void Engine::LoadState()
|
||||
{
|
||||
if (savedStateYAML.empty())
|
||||
@ -857,12 +1193,10 @@ void Engine::SaveState()
|
||||
Logger::LogVerbose("[SaveState] Scene serialized (%zu bytes)", savedStateYAML.size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Engine::Shutdown()
|
||||
{
|
||||
g_engineConfig.SaveToFile();
|
||||
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
@ -870,4 +1204,5 @@ void Engine::Shutdown()
|
||||
glfwTerminate();
|
||||
|
||||
std::filesystem::remove(tempScenePath);
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector> // ← for std::vector<>
|
||||
#include <glm/vec2.hpp> // ← for glm::vec2
|
||||
|
||||
class Object;
|
||||
class ScriptComponent;
|
||||
|
||||
class Engine
|
||||
{
|
||||
@ -16,13 +20,21 @@ public:
|
||||
private:
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void DrawObjectNode(const std::shared_ptr<Object> &obj); // make sure this matches Engine.cpp
|
||||
void DrawObjectNode(const std::shared_ptr<Object> &obj);
|
||||
void SaveScene(const std::string &path);
|
||||
void LoadScene(const std::string &path);
|
||||
void ShowDebugOverlay(float deltaTime);
|
||||
|
||||
void collectObjects(bool playing, const glm::vec2& camPos, float camZoom);
|
||||
|
||||
void SaveState();
|
||||
void LoadState();
|
||||
|
||||
int m_Reserved_draws;
|
||||
|
||||
std::vector<Object *> m_toDraw;
|
||||
std::vector<ScriptComponent *> m_scriptUpdates;
|
||||
int m_OnUpdateCalls;
|
||||
|
||||
std::vector<std::shared_ptr<Object>> m_collectStack;
|
||||
};
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
Object::Object(const std::string &name)
|
||||
: name(name), localPosition(0.0f, 0.0f), uid(), visable(true) {}
|
||||
: name(name), localPosition(0.0f, 0.0f), localRotationDeg(0.0f), uid(), visable(true) {}
|
||||
|
||||
Object::~Object() {}
|
||||
|
||||
@ -45,6 +45,41 @@ glm::vec2 Object::GetLocalPosition() const
|
||||
return localPosition;
|
||||
}
|
||||
|
||||
void Object::SetLocalPosition(glm::vec2 pos)
|
||||
{
|
||||
localPosition = pos;
|
||||
}
|
||||
|
||||
|
||||
glm::vec2 Object::GetWorldPosition() const
|
||||
{
|
||||
if (parent)
|
||||
{
|
||||
float parentRotation = glm::radians(parent->GetWorldRotation());
|
||||
glm::vec2 rotated = glm::rotate(localPosition, parentRotation);
|
||||
return parent->GetWorldPosition() + rotated;
|
||||
}
|
||||
return localPosition;
|
||||
}
|
||||
|
||||
|
||||
float Object::GetLocalRotation() const
|
||||
{
|
||||
return localRotationDeg;
|
||||
}
|
||||
|
||||
void Object::SetLocalRotation(float deg)
|
||||
{
|
||||
localRotationDeg = deg;
|
||||
}
|
||||
|
||||
float Object::GetWorldRotation() const
|
||||
{
|
||||
if (parent)
|
||||
return parent->GetWorldRotation() + localRotationDeg;
|
||||
return localRotationDeg;
|
||||
}
|
||||
|
||||
bool Object::GetVisable() const
|
||||
{
|
||||
return visable;
|
||||
@ -55,21 +90,6 @@ void Object::SetVisable(bool state)
|
||||
visable = state;
|
||||
}
|
||||
|
||||
|
||||
void Object::SetLocalPosition(glm::vec2 pos)
|
||||
{
|
||||
localPosition = pos;
|
||||
}
|
||||
|
||||
glm::vec2 Object::GetWorldPosition() const
|
||||
{
|
||||
if (parent)
|
||||
return parent->GetWorldPosition() + localPosition;
|
||||
return localPosition;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const std::string &Object::GetName() const { return name; }
|
||||
void Object::SetName(const std::string &n) { name = n; }
|
||||
std::vector<std::shared_ptr<Object>> &Object::GetChildren() { return children; }
|
||||
@ -79,16 +99,15 @@ void Object::Save(YAML::Emitter &out) const
|
||||
{
|
||||
Logger::LogVerbose("[LoadScene] Saving Object: [%s, %d]", name.c_str(), uid.id);
|
||||
|
||||
|
||||
out << YAML::BeginMap;
|
||||
out << YAML::Key << "name" << YAML::Value << name;
|
||||
out << YAML::Key << "uid" << YAML::Value << uid.uuid;
|
||||
out << YAML::Key << "id" << YAML::Value << uid.id;
|
||||
out << YAML::Key << "position" << YAML::Value << YAML::Flow << YAML::BeginSeq << localPosition.x << localPosition.y << YAML::EndSeq;
|
||||
out << YAML::Key << "position" << YAML::Flow << YAML::BeginSeq << localPosition.x << localPosition.y << YAML::EndSeq;
|
||||
out << YAML::Key << "rotation" << YAML::Value << localRotationDeg;
|
||||
out << YAML::Key << "layer" << YAML::Value << layer;
|
||||
out << YAML::Key << "visable" << YAML::Value << visable;
|
||||
|
||||
|
||||
out << YAML::Key << "components" << YAML::Value << YAML::BeginSeq;
|
||||
for (const auto &comp : components)
|
||||
{
|
||||
@ -108,71 +127,36 @@ void Object::Save(YAML::Emitter &out) const
|
||||
void Object::Load(const YAML::Node &node)
|
||||
{
|
||||
name = node["name"].as<std::string>();
|
||||
|
||||
if (node["uid"])
|
||||
uid.uuid = node["uid"].as<std::string>();
|
||||
else
|
||||
uid.uuid = GenerateUUID();
|
||||
|
||||
if (node["id"])
|
||||
uid.id = node["id"].as<int>();
|
||||
uid.uuid = node["uid"] ? node["uid"].as<std::string>() : GenerateUUID();
|
||||
uid.id = node["id"] ? node["id"].as<int>() : 0;
|
||||
|
||||
auto pos = node["position"];
|
||||
if (pos && pos.IsSequence() && pos.size() == 2)
|
||||
{
|
||||
localPosition.x = pos[0].as<float>();
|
||||
localPosition.y = pos[1].as<float>();
|
||||
}
|
||||
|
||||
if (node["layer"])
|
||||
layer = node["layer"].as<int>();
|
||||
|
||||
if (node["visable"])
|
||||
visable = node["visable"].as<bool>();
|
||||
localPosition = {pos[0].as<float>(), pos[1].as<float>()};
|
||||
|
||||
localRotationDeg = node["rotation"] ? node["rotation"].as<float>() : 0.0f;
|
||||
layer = node["layer"] ? node["layer"].as<int>() : 0;
|
||||
visable = node["visable"] ? node["visable"].as<bool>() : true;
|
||||
|
||||
Logger::LogVerbose("[LoadScene] Loading Object: [%s, %d]", name.c_str(), uid.id);
|
||||
|
||||
components.clear();
|
||||
if (node["components"])
|
||||
{
|
||||
for (const auto &compNode : node["components"])
|
||||
{
|
||||
std::string type = compNode["type"].as<std::string>();
|
||||
Logger::LogVerbose("[LoadScene] Createing Component: %s", type.c_str());
|
||||
|
||||
if (type == "SpriteComponent")
|
||||
{
|
||||
auto comp = AddComponent<SpriteComponent>();
|
||||
comp->Load(compNode);
|
||||
}
|
||||
else if (type == "CameraComponent")
|
||||
{
|
||||
auto comp = AddComponent<CameraComponent>();
|
||||
comp->Load(compNode);
|
||||
}
|
||||
else if (type == "LightComponent")
|
||||
{
|
||||
auto comp = AddComponent<LightComponent>();
|
||||
comp->Load(compNode);
|
||||
}
|
||||
else if (type == "TilemapComponent")
|
||||
{
|
||||
auto comp = AddComponent<TilemapComponent>();
|
||||
comp->Load(compNode);
|
||||
}
|
||||
else if (type == "TextComponent")
|
||||
{
|
||||
auto comp = AddComponent<TextComponent>();
|
||||
comp->Load(compNode);
|
||||
}
|
||||
else if (type == "ScriptComponent")
|
||||
{
|
||||
auto comp = AddComponent<ScriptComponent>();
|
||||
comp->Load(compNode);
|
||||
}
|
||||
if (type == "SpriteComponent") AddComponent<SpriteComponent>()->Load(compNode);
|
||||
else if (type == "CameraComponent") AddComponent<CameraComponent>()->Load(compNode);
|
||||
else if (type == "LightComponent") AddComponent<LightComponent>()->Load(compNode);
|
||||
else if (type == "TilemapComponent") AddComponent<TilemapComponent>()->Load(compNode);
|
||||
else if (type == "TextComponent") AddComponent<TextComponent>()->Load(compNode);
|
||||
else if (type == "ScriptComponent") AddComponent<ScriptComponent>()->Load(compNode);
|
||||
}
|
||||
}
|
||||
|
||||
children.clear();
|
||||
if (node["children"])
|
||||
{
|
||||
for (const auto &childNode : node["children"])
|
||||
|
@ -3,7 +3,10 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/rotate_vector.hpp>
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
#include "../utils/UID.h"
|
||||
|
||||
@ -22,6 +25,10 @@ public:
|
||||
void SetLocalPosition(glm::vec2 pos);
|
||||
glm::vec2 GetWorldPosition() const;
|
||||
|
||||
float GetLocalRotation() const;
|
||||
void SetLocalRotation(float deg);
|
||||
float GetWorldRotation() const;
|
||||
|
||||
void SetParent(Object *parent);
|
||||
Object *GetParent() const;
|
||||
void AddChild(std::shared_ptr<Object> child);
|
||||
@ -31,9 +38,6 @@ public:
|
||||
bool GetVisable() const;
|
||||
void SetVisable(bool state);
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
std::shared_ptr<T> GetComponent() const;
|
||||
template <typename T>
|
||||
@ -48,9 +52,10 @@ public:
|
||||
int layer = 0;
|
||||
|
||||
private:
|
||||
bool visable;
|
||||
bool visable = true;
|
||||
std::string name;
|
||||
glm::vec2 localPosition;
|
||||
glm::vec2 localPosition{0.0f};
|
||||
float localRotationDeg = 0.0f; // Rotation in degrees
|
||||
Object *parent = nullptr;
|
||||
std::vector<std::shared_ptr<Object>> children;
|
||||
std::vector<std::shared_ptr<Component>> components;
|
||||
@ -60,10 +65,8 @@ template <typename T>
|
||||
std::shared_ptr<T> Object::GetComponent() const
|
||||
{
|
||||
for (const auto &comp : components)
|
||||
{
|
||||
if (auto casted = std::dynamic_pointer_cast<T>(comp))
|
||||
return casted;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -74,7 +77,7 @@ std::shared_ptr<T> Object::AddComponent()
|
||||
if (existing)
|
||||
return existing;
|
||||
|
||||
std::shared_ptr<T> component = std::make_shared<T>(this);
|
||||
auto component = std::make_shared<T>(this);
|
||||
components.push_back(component);
|
||||
return component;
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include "utils/Logging.h"
|
||||
#include "utils/EngineConfig.h"
|
||||
#include "utils/utils.h"
|
||||
#include "utils/Profiler.h"
|
||||
#include "Entitys/Object.h"
|
||||
|
||||
#include "stb_image.h"
|
||||
|
||||
@ -25,6 +27,8 @@ int Renderer::width = 1280;
|
||||
int Renderer::height = 720;
|
||||
int Renderer::s_DrawCalls = 0;
|
||||
int Renderer::s_LightsCount = 0;
|
||||
std::unique_ptr<ColorCorrection> Renderer::s_ColorCorrection = nullptr;
|
||||
|
||||
|
||||
std::vector<Light> Renderer::s_Lights;
|
||||
|
||||
@ -83,6 +87,9 @@ void Renderer::Init()
|
||||
// Load unlit shader
|
||||
unlitShader.LoadFromFile("src/assets/shaders/unlit.vert", "src/assets/shaders/unlit.frag");
|
||||
|
||||
SetColorCorrection(std::make_unique<ColorCorrection>());
|
||||
|
||||
|
||||
// Create a 1x1 flat normal map (RGB: 128,128,255)
|
||||
unsigned char flatNormal[3] = {128, 128, 255};
|
||||
glGenTextures(1, &defaultNormalMap);
|
||||
@ -96,6 +103,7 @@ void Renderer::Init()
|
||||
|
||||
void Renderer::Resize(int w, int h)
|
||||
{
|
||||
|
||||
if (w == width && h == height)
|
||||
return;
|
||||
width = w;
|
||||
@ -111,15 +119,27 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::End()
|
||||
{
|
||||
@ -128,12 +148,16 @@ void Renderer::End()
|
||||
|
||||
void Renderer::ClearLights()
|
||||
{
|
||||
PROFILE_ENGINE_SCOPE("Renderer::ClearLights");
|
||||
|
||||
s_Lights.clear();
|
||||
s_LightsCount = 0;
|
||||
}
|
||||
|
||||
void Renderer::AddLight(const glm::vec2 &screenPos, const glm::vec3 &color, float intensity, float radius)
|
||||
{
|
||||
PROFILE_ENGINE_SCOPE("Engine::AddLight");
|
||||
|
||||
if (s_Lights.size() >= g_engineConfig.gl_maxLight)
|
||||
return;
|
||||
s_Lights.push_back({screenPos, color, intensity, radius});
|
||||
@ -142,6 +166,8 @@ void Renderer::AddLight(const glm::vec2 &screenPos, const glm::vec3 &color, floa
|
||||
|
||||
void Renderer::DrawTilemap(TilemapComponent *tilemap, const glm::vec2 &worldPos, float zoom, const glm::vec2 &cameraPos)
|
||||
{
|
||||
PROFILE_ENGINE_SCOPE("Renderer::DrawTilemap");
|
||||
|
||||
if (!tilemap || tilemap->GetAtlasPath().empty())
|
||||
return;
|
||||
|
||||
@ -209,26 +235,32 @@ void Renderer::DrawSprite(SpriteComponent *sprite, const glm::vec2 &pos, float z
|
||||
|
||||
Shader *shader = &unlitShader;
|
||||
bool useLighting = false;
|
||||
if (g_engineConfig.lighting_enabled && sprite->GetRenderType() == SpriteComponent::RenderType::Lit)
|
||||
if (g_engineConfig.settings.lighting_enabled && sprite->GetRenderType() == SpriteComponent::RenderType::Lit)
|
||||
{
|
||||
shader = &spriteShader;
|
||||
useLighting = true;
|
||||
}
|
||||
|
||||
shader->Use();
|
||||
|
||||
glm::vec2 size = sprite->GetSize();
|
||||
glm::vec2 screenPos = (pos - CameraPos) * zoom + glm::vec2(width, height) * 0.5f - (size * zoom * 0.5f);
|
||||
float rotationDeg = sprite->GetOwner()->GetWorldRotation();
|
||||
|
||||
shader->SetVec2("uPos", screenPos);
|
||||
shader->SetVec2("uSize", size * zoom);
|
||||
shader->SetVec2("uScreen", glm::vec2(width, height));
|
||||
shader->SetFloat("uRotation", glm::radians(rotationDeg));
|
||||
shader->SetInt("uTex", 0);
|
||||
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, sprite->GetTextureID());
|
||||
|
||||
if (useLighting)
|
||||
{
|
||||
s_ColorCorrection->Upload(*shader);
|
||||
|
||||
shader->SetInt("uLightCount", static_cast<int>(s_Lights.size()));
|
||||
for (size_t i = 0; i < s_Lights.size(); ++i)
|
||||
{
|
||||
@ -370,3 +402,11 @@ glm::ivec2 Renderer::GetSize()
|
||||
{
|
||||
return {width, height};
|
||||
}
|
||||
void Renderer::SetColorCorrection(std::unique_ptr<ColorCorrection> correction)
|
||||
{
|
||||
s_ColorCorrection = std::move(correction);
|
||||
}
|
||||
ColorCorrection *Renderer::GetColorCorrection()
|
||||
{
|
||||
return s_ColorCorrection.get();
|
||||
}
|
@ -6,15 +6,34 @@
|
||||
#include "Components/TilemapComponent.h"
|
||||
#include "Components/SpriteComponent.h"
|
||||
#include "utils/EngineConfig.h"
|
||||
#include "utils/Shader.h"
|
||||
#include "utils/Profiler.h"
|
||||
|
||||
struct Light {
|
||||
|
||||
struct ColorCorrection {
|
||||
float brightness = 1.0f;
|
||||
float saturation = 1.0f;
|
||||
float gamma = 1.0f;
|
||||
|
||||
|
||||
void Upload(Shader& shader) const {
|
||||
shader.SetFloat("uBrightness", brightness);
|
||||
shader.SetFloat("uSaturation", saturation);
|
||||
shader.SetFloat("uGamma", gamma);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Light
|
||||
{
|
||||
glm::vec2 screenPos;
|
||||
glm::vec3 color;
|
||||
float intensity;
|
||||
float radius;
|
||||
};
|
||||
|
||||
class Renderer {
|
||||
class Renderer
|
||||
{
|
||||
public:
|
||||
static void Init();
|
||||
static void Resize(int w, int h);
|
||||
@ -29,40 +48,19 @@ public:
|
||||
|
||||
static void DrawEditorGrid(const glm::vec2 &cameraPos, float zoom);
|
||||
|
||||
// —— New gizmo functions ——
|
||||
// Draws a colored line between two world‑space points.
|
||||
static void DrawGizmoLine(
|
||||
const glm::vec2& worldStart,
|
||||
const glm::vec2& worldEnd,
|
||||
const glm::vec3& color,
|
||||
const glm::vec2& cameraPos,
|
||||
float zoom
|
||||
);
|
||||
|
||||
// Draws a colored axis‑aligned rectangle in world space.
|
||||
static void DrawGizmoRect(
|
||||
const glm::vec2& worldPos,
|
||||
const glm::vec2& size,
|
||||
const glm::vec3& color,
|
||||
const glm::vec2& cameraPos,
|
||||
float zoom
|
||||
);
|
||||
|
||||
// Draws a colored circle (approximated by segments) in world space.
|
||||
static void DrawGizmoCircle(
|
||||
const glm::vec2& worldCenter,
|
||||
float radius,
|
||||
int segments,
|
||||
const glm::vec3& color,
|
||||
const glm::vec2& cameraPos,
|
||||
float zoom
|
||||
);
|
||||
static void DrawGizmoLine(const glm::vec2 &worldStart, const glm::vec2 &worldEnd, const glm::vec3 &color, const glm::vec2 &cameraPos, float zoom);
|
||||
static void DrawGizmoRect(const glm::vec2 &worldPos, const glm::vec2 &size, const glm::vec3 &color, const glm::vec2 &cameraPos, float zoom);
|
||||
static void DrawGizmoCircle(const glm::vec2 &worldCenter, float radius, int segments, const glm::vec3 &color, const glm::vec2 &cameraPos, float zoom);
|
||||
|
||||
static GLuint GetRenderTexture();
|
||||
static glm::ivec2 GetSize();
|
||||
static int GetDrawCallCount();
|
||||
static int GetLightsCount();
|
||||
|
||||
static void SetColorCorrection(std::unique_ptr<ColorCorrection> correction);
|
||||
|
||||
static ColorCorrection *GetColorCorrection();
|
||||
|
||||
private:
|
||||
static std::vector<Light> s_Lights;
|
||||
static GLuint fbo, textureColorBuffer, rbo;
|
||||
@ -74,4 +72,6 @@ private:
|
||||
static GLuint shader, quadVAO, quadVBO;
|
||||
static void InitQuad();
|
||||
static GLuint LoadShader(const char *vertexSrc, const char *fragmentSrc);
|
||||
|
||||
static std::unique_ptr<ColorCorrection> s_ColorCorrection;
|
||||
};
|
||||
|
@ -1,14 +1,71 @@
|
||||
// EngineConfig.cpp
|
||||
#include "EngineConfig.h"
|
||||
#include <yaml-cpp/yaml.h>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <Windows.h>
|
||||
#include <shlobj.h> // SHGetFolderPathA
|
||||
|
||||
#include "Logging.h"
|
||||
|
||||
EngineConfig g_engineConfig{
|
||||
.lighting_enabled = true,
|
||||
.version = "0.1.0",
|
||||
.gl_version = "430",
|
||||
.gl_maxLight = 512,
|
||||
.settings{
|
||||
.settings = {
|
||||
.draw_gizmos = true,
|
||||
},
|
||||
|
||||
.profile_editor = false,
|
||||
.profile_enabled = true,
|
||||
.show_color_correction_window = false,
|
||||
.lighting_enabled = true
|
||||
}
|
||||
};
|
||||
|
||||
static std::filesystem::path GetUserSettingsPath() {
|
||||
char userPath[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_PROFILE, NULL, 0, userPath))) {
|
||||
std::filesystem::path path = std::filesystem::path(userPath) / ".CreateEngine" / ".user_settings.yaml";
|
||||
std::filesystem::create_directories(path.parent_path());
|
||||
Logger::LogVerbose("Settings Path: %s", path.string().c_str());
|
||||
|
||||
return path;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void EngineConfig::SaveToFile() {
|
||||
Logger::LogVerbose("Saving User Settings");
|
||||
|
||||
YAML::Emitter out;
|
||||
out << YAML::BeginMap;
|
||||
|
||||
out << YAML::Key << "draw_gizmos" << YAML::Value << settings.draw_gizmos;
|
||||
out << YAML::Key << "profile_editor" << YAML::Value << settings.profile_editor;
|
||||
out << YAML::Key << "profile_enabled" << YAML::Value << settings.profile_enabled;
|
||||
out << YAML::Key << "show_color_correction_window" << YAML::Value << settings.show_color_correction_window;
|
||||
out << YAML::Key << "lighting_enabled" << YAML::Value << settings.lighting_enabled;
|
||||
|
||||
out << YAML::EndMap;
|
||||
|
||||
std::ofstream fout(GetUserSettingsPath());
|
||||
fout << out.c_str();
|
||||
}
|
||||
|
||||
void EngineConfig::LoadFromFile() {
|
||||
Logger::LogVerbose("Loading User Settings");
|
||||
|
||||
auto path = GetUserSettingsPath();
|
||||
if (!std::filesystem::exists(path)) return;
|
||||
|
||||
YAML::Node root = YAML::LoadFile(path.string());
|
||||
|
||||
if (root["draw_gizmos"])
|
||||
settings.draw_gizmos = root["draw_gizmos"].as<bool>();
|
||||
if (root["profile_editor"])
|
||||
settings.profile_editor = root["profile_editor"].as<bool>();
|
||||
if (root["profile_enabled"])
|
||||
settings.profile_enabled = root["profile_enabled"].as<bool>();
|
||||
if (root["show_color_correction_window"])
|
||||
settings.show_color_correction_window = root["show_color_correction_window"].as<bool>();
|
||||
if (root["lighting_enabled"])
|
||||
settings.lighting_enabled = root["lighting_enabled"].as<bool>();
|
||||
}
|
||||
|
@ -3,15 +3,21 @@
|
||||
|
||||
struct UserSettings {
|
||||
bool draw_gizmos;
|
||||
bool profile_editor;
|
||||
bool profile_enabled;
|
||||
bool show_color_correction_window;
|
||||
bool lighting_enabled;
|
||||
};
|
||||
|
||||
struct EngineConfig {
|
||||
bool lighting_enabled;
|
||||
std::string version;
|
||||
std::string gl_version;
|
||||
int gl_maxLight;
|
||||
|
||||
UserSettings settings;
|
||||
|
||||
void SaveToFile();
|
||||
void LoadFromFile();
|
||||
};
|
||||
|
||||
extern EngineConfig g_engineConfig;
|
||||
|
107
src/src/utils/Profiler.cpp
Normal file
107
src/src/utils/Profiler.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
#include "Profiler.h"
|
||||
#include <cmath>
|
||||
|
||||
extern float g_fps;
|
||||
extern EngineConfig g_engineConfig;
|
||||
|
||||
inline double Lerp(double a, double b, double t) {
|
||||
return a + (b - a) * t;
|
||||
}
|
||||
|
||||
static void SmoothVisualDurations(ProfileNode& node, double blendFactor) {
|
||||
node.visualStartMs = Lerp(node.visualStartMs, node.startMs, blendFactor);
|
||||
node.visualDurationMs = Lerp(node.visualDurationMs, node.durationMs, blendFactor);
|
||||
for (auto& child : node.children)
|
||||
SmoothVisualDurations(child, blendFactor);
|
||||
}
|
||||
|
||||
void HierarchicalProfiler::BeginFrame() {
|
||||
if (!g_engineConfig.settings.profile_enabled)
|
||||
return;
|
||||
|
||||
root.startMs = 0.0;
|
||||
root.durationMs = 0.0;
|
||||
root.visualStartMs = 0.0;
|
||||
root.visualDurationMs = 0.0;
|
||||
root.children.clear();
|
||||
|
||||
currentStack.clear();
|
||||
sectionStartTimes.clear();
|
||||
|
||||
currentStack.reserve(ProfilesLastFrame);
|
||||
sectionStartTimes.reserve(ProfilesLastFrame);
|
||||
|
||||
startTime = Clock::now();
|
||||
currentStack.push_back(&root);
|
||||
|
||||
ProfilesLastFrame = 0;
|
||||
}
|
||||
|
||||
void HierarchicalProfiler::BeginSection(const std::string& name) {
|
||||
if (!g_engineConfig.settings.profile_enabled)
|
||||
return;
|
||||
|
||||
auto now = Clock::now();
|
||||
double timeSinceStart = std::chrono::duration<double, std::milli>(now - startTime).count();
|
||||
|
||||
ProfileNode& parent = *currentStack.back();
|
||||
parent.children.emplace_back(name, timeSinceStart);
|
||||
currentStack.push_back(&parent.children.back());
|
||||
|
||||
sectionStartTimes.push_back(now);
|
||||
ProfilesLastFrame++;
|
||||
}
|
||||
|
||||
void HierarchicalProfiler::EndSection() {
|
||||
if (!g_engineConfig.settings.profile_enabled)
|
||||
return;
|
||||
|
||||
if (currentStack.size() <= 1 || sectionStartTimes.empty())
|
||||
return;
|
||||
|
||||
auto now = Clock::now();
|
||||
ProfileNode& node = *currentStack.back();
|
||||
double duration = std::chrono::duration<double, std::milli>(now - sectionStartTimes.back()).count();
|
||||
|
||||
node.durationMs = duration;
|
||||
|
||||
currentStack.pop_back();
|
||||
sectionStartTimes.pop_back();
|
||||
}
|
||||
|
||||
void HierarchicalProfiler::BeginEngineSection(const std::string& name) {
|
||||
if (g_engineConfig.settings.profile_enabled && g_engineConfig.settings.profile_editor)
|
||||
BeginSection(name);
|
||||
}
|
||||
|
||||
void HierarchicalProfiler::EndEngineSection() {
|
||||
if (g_engineConfig.settings.profile_enabled && g_engineConfig.settings.profile_editor)
|
||||
EndSection();
|
||||
}
|
||||
|
||||
void HierarchicalProfiler::EndFrame() {
|
||||
if (!g_engineConfig.settings.profile_enabled)
|
||||
return;
|
||||
|
||||
root.durationMs = std::chrono::duration<double, std::milli>(Clock::now() - startTime).count();
|
||||
|
||||
if (frameHistory.empty())
|
||||
root.visualDurationMs = root.durationMs;
|
||||
|
||||
double blendFactor = 1.0 - std::pow(0.01, 1.0 / g_fps);
|
||||
SmoothVisualDurations(root, blendFactor);
|
||||
|
||||
frameHistory.push_back(root);
|
||||
if (frameHistory.size() > maxFrames)
|
||||
frameHistory.erase(frameHistory.begin());
|
||||
}
|
||||
|
||||
const std::vector<ProfileNode>& HierarchicalProfiler::GetFrames() const {
|
||||
return frameHistory;
|
||||
}
|
||||
|
||||
const ProfileNode* HierarchicalProfiler::GetLatestFrame() const {
|
||||
return frameHistory.empty() ? nullptr : &frameHistory.back();
|
||||
}
|
||||
|
||||
HierarchicalProfiler profiler;
|
94
src/src/utils/Profiler.h
Normal file
94
src/src/utils/Profiler.h
Normal file
@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
#include "EngineConfig.h"
|
||||
|
||||
struct ProfileNode
|
||||
{
|
||||
std::string name;
|
||||
double startMs = 0.0;
|
||||
double durationMs = 0.0;
|
||||
double visualStartMs = 0.0;
|
||||
double visualDurationMs = 0.0;
|
||||
std::vector<ProfileNode> children;
|
||||
|
||||
|
||||
|
||||
ProfileNode() = default;
|
||||
|
||||
|
||||
ProfileNode(const std::string &n, double start)
|
||||
: name(n), startMs(start)
|
||||
{
|
||||
children.reserve(8);
|
||||
}
|
||||
};
|
||||
|
||||
class HierarchicalProfiler
|
||||
{
|
||||
public:
|
||||
void BeginFrame();
|
||||
void EndFrame();
|
||||
|
||||
void BeginSection(const std::string &name);
|
||||
void EndSection();
|
||||
|
||||
void BeginEngineSection(const std::string &name);
|
||||
void EndEngineSection();
|
||||
|
||||
const std::vector<ProfileNode> &GetFrames() const;
|
||||
const ProfileNode *GetLatestFrame() const;
|
||||
|
||||
private:
|
||||
using Clock = std::chrono::high_resolution_clock;
|
||||
Clock::time_point startTime;
|
||||
std::vector<Clock::time_point> sectionStartTimes;
|
||||
std::vector<ProfileNode *> currentStack;
|
||||
ProfileNode root{"Frame", 0.0};
|
||||
|
||||
std::vector<ProfileNode> frameHistory;
|
||||
static constexpr size_t maxFrames = 30;
|
||||
|
||||
size_t ProfilesLastFrame = 128;
|
||||
};
|
||||
|
||||
extern HierarchicalProfiler profiler;
|
||||
|
||||
// RAII Scoped Profiling (Zero-overhead when disabled)
|
||||
struct ScopedProfile
|
||||
{
|
||||
ScopedProfile(const std::string &name)
|
||||
{
|
||||
if (g_engineConfig.settings.profile_enabled)
|
||||
profiler.BeginSection(name);
|
||||
}
|
||||
~ScopedProfile()
|
||||
{
|
||||
if (g_engineConfig.settings.profile_enabled)
|
||||
profiler.EndSection();
|
||||
}
|
||||
};
|
||||
|
||||
struct ScopedEngineProfile
|
||||
{
|
||||
ScopedEngineProfile(const std::string &name)
|
||||
{
|
||||
if (g_engineConfig.settings.profile_enabled && g_engineConfig.settings.profile_editor)
|
||||
profiler.BeginSection(name);
|
||||
}
|
||||
~ScopedEngineProfile()
|
||||
{
|
||||
if (g_engineConfig.settings.profile_enabled && g_engineConfig.settings.profile_editor)
|
||||
profiler.EndSection();
|
||||
}
|
||||
};
|
||||
|
||||
#define CONCAT_IMPL(a, b) a##b
|
||||
#define CONCAT(a, b) CONCAT_IMPL(a, b)
|
||||
|
||||
#define PROFILE_SCOPE(label) \
|
||||
ScopedProfile CONCAT(_scopedProfile_, __LINE__)(label)
|
||||
|
||||
#define PROFILE_ENGINE_SCOPE(label) \
|
||||
ScopedEngineProfile CONCAT(_scopedEngineProfile_, __LINE__)(label)
|
Loading…
Reference in New Issue
Block a user