Compare commits
2 Commits
fba1465991
...
e81041fa2b
Author | SHA1 | Date | |
---|---|---|---|
|
e81041fa2b | ||
|
e409bed53f |
62
imgui.ini
62
imgui.ini
@ -15,19 +15,19 @@ Collapsed=0
|
|||||||
|
|
||||||
[Window][Inspector]
|
[Window][Inspector]
|
||||||
Pos=890,19
|
Pos=890,19
|
||||||
Size=390,505
|
Size=390,292
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000005,0
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
[Window][Scene Tree]
|
[Window][Scene Tree]
|
||||||
Pos=0,19
|
Pos=0,19
|
||||||
Size=263,701
|
Size=376,366
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000001,0
|
DockId=0x00000009,0
|
||||||
|
|
||||||
[Window][Viewport]
|
[Window][Viewport]
|
||||||
Pos=265,19
|
Pos=378,19
|
||||||
Size=623,329
|
Size=510,218
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000007,0
|
DockId=0x00000007,0
|
||||||
|
|
||||||
@ -42,10 +42,10 @@ Collapsed=0
|
|||||||
DockId=0x00000006,0
|
DockId=0x00000006,0
|
||||||
|
|
||||||
[Window][Console]
|
[Window][Console]
|
||||||
Pos=265,350
|
Pos=0,387
|
||||||
Size=623,370
|
Size=376,333
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000008,0
|
DockId=0x0000000A,0
|
||||||
|
|
||||||
[Window][Tilemap Editor]
|
[Window][Tilemap Editor]
|
||||||
Pos=265,19
|
Pos=265,19
|
||||||
@ -53,14 +53,48 @@ Size=1263,674
|
|||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000007,1
|
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]
|
[Docking][Data]
|
||||||
DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1280,701 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=0x00000003 Parent=0x11111111 SizeRef=888,1158 Split=X
|
||||||
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=263,701 HiddenTabBar=1 Selected=0x12EF0F59
|
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=376,701 Split=Y Selected=0x12EF0F59
|
||||||
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=623,701 Split=Y Selected=0xC450F867
|
DockNode ID=0x00000009 Parent=0x00000001 SizeRef=376,605 HiddenTabBar=1 Selected=0x12EF0F59
|
||||||
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,329 CentralNode=1 Selected=0xC450F867
|
DockNode ID=0x0000000A Parent=0x00000001 SizeRef=376,551 HiddenTabBar=1 Selected=0xEA83D666
|
||||||
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,370 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=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
|
DockNode ID=0x00000006 Parent=0x00000004 SizeRef=407,321 HiddenTabBar=1 Selected=0x3FC1A724
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ cxx: g++
|
|||||||
cxxflags:
|
cxxflags:
|
||||||
- -std=c++20
|
- -std=c++20
|
||||||
- -Wall
|
- -Wall
|
||||||
|
- -g
|
||||||
|
|
||||||
# Auto-detect libraries and headers
|
# Auto-detect libraries and headers
|
||||||
auto_libs:
|
auto_libs:
|
||||||
|
@ -1 +1,10 @@
|
|||||||
[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
|
[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
|
engine_version: 0.1.0
|
||||||
scene_name: lighting_test_2
|
scene_name: lighting_test_2
|
||||||
scene_hash: a0ae96d593e1990a6f3944184fd6595738629af0dcb2d4cdd83011a91aaa738c
|
scene_hash: 8f8260f09292105727f7f8afe890565a9feeaa92a1ca6d7fa55790a5019c67d7
|
||||||
format_version: 1
|
format_version: 1
|
||||||
objects:
|
objects:
|
||||||
- name: Tiles
|
- name: Tiles
|
||||||
uid: f5e01f7892874a67b662633650b41dbd
|
uid: f5e01f7892874a67b662633650b41dbd
|
||||||
id: 3
|
id: 3
|
||||||
position: [0, 0]
|
position: [0, 0]
|
||||||
|
rotation: 0
|
||||||
layer: 0
|
layer: 0
|
||||||
visable: true
|
visable: true
|
||||||
components: []
|
components: []
|
||||||
@ -15,6 +16,7 @@ objects:
|
|||||||
uid: 7dc3bbf8affb4844ae3801f03857b904
|
uid: 7dc3bbf8affb4844ae3801f03857b904
|
||||||
id: 4
|
id: 4
|
||||||
position: [0, 0]
|
position: [0, 0]
|
||||||
|
rotation: 0
|
||||||
layer: 0
|
layer: 0
|
||||||
visable: true
|
visable: true
|
||||||
components:
|
components:
|
||||||
@ -27,6 +29,7 @@ objects:
|
|||||||
uid: 13d8988343354e3c8a1f51c03ed40cda
|
uid: 13d8988343354e3c8a1f51c03ed40cda
|
||||||
id: 5
|
id: 5
|
||||||
position: [1024, 0]
|
position: [1024, 0]
|
||||||
|
rotation: 0
|
||||||
layer: 0
|
layer: 0
|
||||||
visable: true
|
visable: true
|
||||||
components:
|
components:
|
||||||
@ -39,6 +42,7 @@ objects:
|
|||||||
uid: cff28abe7e3b455ab9b756acc84cd2d7
|
uid: cff28abe7e3b455ab9b756acc84cd2d7
|
||||||
id: 6
|
id: 6
|
||||||
position: [0, 1024]
|
position: [0, 1024]
|
||||||
|
rotation: 0
|
||||||
layer: 0
|
layer: 0
|
||||||
visable: true
|
visable: true
|
||||||
components:
|
components:
|
||||||
@ -51,6 +55,7 @@ objects:
|
|||||||
uid: 98967eb30e5b429b992766d8062b7c17
|
uid: 98967eb30e5b429b992766d8062b7c17
|
||||||
id: 7
|
id: 7
|
||||||
position: [1024, 1024]
|
position: [1024, 1024]
|
||||||
|
rotation: 0
|
||||||
layer: 0
|
layer: 0
|
||||||
visable: true
|
visable: true
|
||||||
components:
|
components:
|
||||||
@ -62,7 +67,8 @@ objects:
|
|||||||
- name: Logo
|
- name: Logo
|
||||||
uid: c4ce6f16dfb347b0ae0ac67f5881b243
|
uid: c4ce6f16dfb347b0ae0ac67f5881b243
|
||||||
id: 8
|
id: 8
|
||||||
position: [2048, 0]
|
position: [2104, 56]
|
||||||
|
rotation: 0
|
||||||
layer: 0
|
layer: 0
|
||||||
visable: true
|
visable: true
|
||||||
components:
|
components:
|
||||||
@ -74,7 +80,8 @@ objects:
|
|||||||
- name: Carbooon Fobar
|
- name: Carbooon Fobar
|
||||||
uid: 5ea269572751401da6d86519d3513b7d
|
uid: 5ea269572751401da6d86519d3513b7d
|
||||||
id: 9
|
id: 9
|
||||||
position: [2559.30005, 1562]
|
position: [2048, 3070]
|
||||||
|
rotation: 0
|
||||||
layer: 1
|
layer: 1
|
||||||
visable: true
|
visable: true
|
||||||
components:
|
components:
|
||||||
@ -86,7 +93,8 @@ objects:
|
|||||||
- name: Mud
|
- name: Mud
|
||||||
uid: a36b71937ba349bd8e6414f75be9ee16
|
uid: a36b71937ba349bd8e6414f75be9ee16
|
||||||
id: 10
|
id: 10
|
||||||
position: [0, 2561.80005]
|
position: [0, 3070]
|
||||||
|
rotation: 0
|
||||||
layer: 0
|
layer: 0
|
||||||
visable: true
|
visable: true
|
||||||
components:
|
components:
|
||||||
@ -99,6 +107,7 @@ objects:
|
|||||||
uid: 051b338a725a4076ad53ad8fa00c5f4e
|
uid: 051b338a725a4076ad53ad8fa00c5f4e
|
||||||
id: 12
|
id: 12
|
||||||
position: [-556, 951]
|
position: [-556, 951]
|
||||||
|
rotation: 0
|
||||||
layer: 0
|
layer: 0
|
||||||
visable: true
|
visable: true
|
||||||
components: []
|
components: []
|
||||||
@ -107,6 +116,7 @@ objects:
|
|||||||
uid: 6afde2dd47aa4557b6afb1a607c99dc8
|
uid: 6afde2dd47aa4557b6afb1a607c99dc8
|
||||||
id: 13
|
id: 13
|
||||||
position: [512, 1024]
|
position: [512, 1024]
|
||||||
|
rotation: 0
|
||||||
layer: 2
|
layer: 2
|
||||||
visable: true
|
visable: true
|
||||||
components:
|
components:
|
||||||
@ -128,6 +138,7 @@ objects:
|
|||||||
uid: 0f950d76d24b4dc18f54cab2c3aaaf9a
|
uid: 0f950d76d24b4dc18f54cab2c3aaaf9a
|
||||||
id: 14
|
id: 14
|
||||||
position: [1024, 512]
|
position: [1024, 512]
|
||||||
|
rotation: 0
|
||||||
layer: 2
|
layer: 2
|
||||||
visable: true
|
visable: true
|
||||||
components:
|
components:
|
||||||
@ -149,6 +160,7 @@ objects:
|
|||||||
uid: 09f722f51c7c4b0f98de3a0a16d127c4
|
uid: 09f722f51c7c4b0f98de3a0a16d127c4
|
||||||
id: 15
|
id: 15
|
||||||
position: [250, 250]
|
position: [250, 250]
|
||||||
|
rotation: 0
|
||||||
layer: 2
|
layer: 2
|
||||||
visable: true
|
visable: true
|
||||||
components:
|
components:
|
||||||
@ -170,6 +182,7 @@ objects:
|
|||||||
uid: d4fb425522d84a8cbbd7d1415bcd93df
|
uid: d4fb425522d84a8cbbd7d1415bcd93df
|
||||||
id: 16
|
id: 16
|
||||||
position: [500, 500]
|
position: [500, 500]
|
||||||
|
rotation: 0
|
||||||
layer: 0
|
layer: 0
|
||||||
visable: true
|
visable: true
|
||||||
components:
|
components:
|
||||||
@ -187,6 +200,7 @@ objects:
|
|||||||
uid: 895c655f3dda4aec9f2a354c1276c53e
|
uid: 895c655f3dda4aec9f2a354c1276c53e
|
||||||
id: 14
|
id: 14
|
||||||
position: [0, 0]
|
position: [0, 0]
|
||||||
|
rotation: 0
|
||||||
layer: 0
|
layer: 0
|
||||||
visable: true
|
visable: true
|
||||||
components:
|
components:
|
||||||
|
@ -6,6 +6,11 @@ out vec4 FragColor;
|
|||||||
|
|
||||||
uniform sampler2D uTex;
|
uniform sampler2D uTex;
|
||||||
uniform sampler2D uNormalMap;
|
uniform sampler2D uNormalMap;
|
||||||
|
uniform float uRotation;
|
||||||
|
|
||||||
|
uniform float uBrightness;
|
||||||
|
uniform float uSaturation;
|
||||||
|
uniform float uGamma;
|
||||||
|
|
||||||
#define MAX_LIGHTS 512
|
#define MAX_LIGHTS 512
|
||||||
|
|
||||||
@ -17,16 +22,22 @@ uniform float uLightRadius[MAX_LIGHTS];
|
|||||||
|
|
||||||
void main()
|
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)
|
if (texColor.a < 0.1)
|
||||||
discard;
|
discard;
|
||||||
|
|
||||||
// unpack normal map and convert from [0,1] to [-1,1]
|
vec3 n = texture(uNormalMap, rotatedUV).rgb * 2.0 - 1.0;
|
||||||
vec3 n = texture(uNormalMap, vUV).rgb * 2.0 - 1.0;
|
|
||||||
// invert the green channel for OpenGL
|
|
||||||
n.y = -n.y;
|
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);
|
vec3 finalLight = vec3(0.0);
|
||||||
|
|
||||||
for (int i = 0; i < uLightCount; ++i)
|
for (int i = 0; i < uLightCount; ++i)
|
||||||
@ -37,9 +48,8 @@ void main()
|
|||||||
if (dist < uLightRadius[i])
|
if (dist < uLightRadius[i])
|
||||||
{
|
{
|
||||||
vec2 lightDir2D = normalize(lightVec);
|
vec2 lightDir2D = normalize(lightVec);
|
||||||
vec3 lightDir = normalize(vec3(lightDir2D, 1.0)); // pseudo-3D
|
vec3 lightDir = normalize(vec3(lightDir2D, 1.0));
|
||||||
|
float attenuation = smoothstep(uLightRadius[i], 0.0, dist);
|
||||||
float attenuation = 1.0 - dist / uLightRadius[i];
|
|
||||||
float diff = max(dot(normal, lightDir), 0.0);
|
float diff = max(dot(normal, lightDir), 0.0);
|
||||||
vec3 light = uLightColor[i] * diff * attenuation * uLightIntensity[i];
|
vec3 light = uLightColor[i] * diff * attenuation * uLightIntensity[i];
|
||||||
finalLight += light;
|
finalLight += light;
|
||||||
@ -47,5 +57,15 @@ void main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
vec3 result = texColor.rgb * finalLight;
|
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);
|
FragColor = vec4(result, texColor.a);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#version 430 core
|
#version 330 core
|
||||||
|
|
||||||
layout (location = 0) in vec2 aPos;
|
layout (location = 0) in vec2 aPos;
|
||||||
layout (location = 1) in vec2 aUV;
|
layout (location = 1) in vec2 aUV;
|
||||||
@ -9,17 +9,22 @@ out vec2 vFragScreenPos;
|
|||||||
uniform vec2 uPos;
|
uniform vec2 uPos;
|
||||||
uniform vec2 uSize;
|
uniform vec2 uSize;
|
||||||
uniform vec2 uScreen;
|
uniform vec2 uScreen;
|
||||||
|
uniform float uRotation;//r
|
||||||
|
|
||||||
void main()
|
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;
|
vUV = aUV;
|
||||||
|
vFragScreenPos = finalPos;
|
||||||
|
|
||||||
vec2 worldPos = uPos + aPos * uSize;
|
vec2 ndc = finalPos / uScreen * 2.0 - 1.0;
|
||||||
|
gl_Position = vec4(ndc.x, -ndc.y, 0.0, 1.0); // Y-flip
|
||||||
vFragScreenPos = worldPos;
|
|
||||||
|
|
||||||
vec2 ndc = (worldPos / uScreen) * 2.0 - 1.0;
|
|
||||||
ndc.y *= -1.0;
|
|
||||||
|
|
||||||
gl_Position = vec4(ndc, 0.0, 1.0);
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
#version 430 core
|
#version 330 core
|
||||||
in vec2 vUV;
|
in vec2 vUV;
|
||||||
out vec4 FragColor;
|
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)
|
if (color.a < 0.01)
|
||||||
discard;
|
discard;
|
||||||
|
|
||||||
|
@ -1,13 +1,28 @@
|
|||||||
#version 430 core
|
#version 330 core
|
||||||
layout (location = 0) in vec2 aPos;
|
layout (location = 0) in vec2 aPos;
|
||||||
layout (location = 1) in vec2 aUV;
|
layout (location = 1) in vec2 aUV;
|
||||||
|
|
||||||
out vec2 vUV;
|
out vec2 vUV;
|
||||||
|
out vec2 vFragScreenPos;
|
||||||
|
|
||||||
uniform vec2 uPos;
|
uniform vec2 uPos;
|
||||||
uniform vec2 uSize;
|
uniform vec2 uSize;
|
||||||
uniform vec2 uScreen;
|
uniform vec2 uScreen;
|
||||||
void main() {
|
uniform float uRotation; // radians
|
||||||
vec2 worldPos = aPos * uSize + uPos;
|
|
||||||
|
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;
|
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
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ public:
|
|||||||
|
|
||||||
virtual std::string GetName() const = 0;
|
virtual std::string GetName() const = 0;
|
||||||
|
|
||||||
|
|
||||||
virtual void Save(YAML::Emitter& out) const = 0;
|
virtual void Save(YAML::Emitter& out) const = 0;
|
||||||
virtual void Load(const YAML::Node& node) = 0;
|
virtual void Load(const YAML::Node& node) = 0;
|
||||||
|
|
||||||
|
@ -10,74 +10,110 @@
|
|||||||
#include "../Components/TextComponent.h"
|
#include "../Components/TextComponent.h"
|
||||||
#include "../Components/TilemapComponent.h"
|
#include "../Components/TilemapComponent.h"
|
||||||
|
|
||||||
|
#include "../utils/Profiler.h"
|
||||||
|
|
||||||
#include <lua.hpp>
|
#include <lua.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
static bool luaDebugEnabled = false;
|
static bool luaDebugEnabled = false;
|
||||||
|
static bool old_state = false;
|
||||||
|
|
||||||
struct LuaObjectWrapper {
|
struct LuaObjectWrapper
|
||||||
|
{
|
||||||
Object *obj;
|
Object *obj;
|
||||||
};
|
};
|
||||||
#define LUA_OBJECT_MT "LuaObjectMeta"
|
#define LUA_OBJECT_MT "LuaObjectMeta"
|
||||||
|
|
||||||
struct LuaVector2 {
|
struct LuaVector2
|
||||||
|
{
|
||||||
float x, y;
|
float x, y;
|
||||||
};
|
};
|
||||||
#define LUA_VECTOR2_MT "LuaVector2Meta"
|
#define LUA_VECTOR2_MT "LuaVector2Meta"
|
||||||
|
|
||||||
ScriptComponent::ScriptComponent(Object *owner) : Component(owner), L(nullptr) {}
|
ScriptComponent::ScriptComponent(Object *owner) : Component(owner), L(nullptr) {}
|
||||||
ScriptComponent::~ScriptComponent() { if (L) lua_close(L); }
|
ScriptComponent::~ScriptComponent()
|
||||||
|
{
|
||||||
|
if (L)
|
||||||
|
lua_close(L);
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptComponent::SetScriptPath(const std::string& path) {
|
void ScriptComponent::SetScriptPath(const std::string &path)
|
||||||
|
{
|
||||||
scriptPath = path;
|
scriptPath = path;
|
||||||
ReloadScript();
|
ReloadScript();
|
||||||
}
|
}
|
||||||
const std::string &ScriptComponent::GetScriptPath() const { return scriptPath; }
|
const std::string &ScriptComponent::GetScriptPath() const { return scriptPath; }
|
||||||
|
|
||||||
// Logging bindings
|
// Logging bindings
|
||||||
static int Lua_LogInfo(lua_State* L) {
|
static int Lua_LogInfo(lua_State *L)
|
||||||
|
{
|
||||||
Logger::LogInfo("[Lua] %s", lua_tostring(L, 1));
|
Logger::LogInfo("[Lua] %s", lua_tostring(L, 1));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static int Lua_LogError(lua_State* L) {
|
static int Lua_LogError(lua_State *L)
|
||||||
|
{
|
||||||
Logger::LogError("[Lua] %s", lua_tostring(L, 1));
|
Logger::LogError("[Lua] %s", lua_tostring(L, 1));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static int Lua_LogDebug(lua_State* L) {
|
static int Lua_LogDebug(lua_State *L)
|
||||||
|
{
|
||||||
Logger::LogDebug("[Lua] %s", lua_tostring(L, 1));
|
Logger::LogDebug("[Lua] %s", lua_tostring(L, 1));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static int Lua_DebugLua(lua_State* L) {
|
static int Lua_DebugLua(lua_State *L)
|
||||||
|
{
|
||||||
luaDebugEnabled = lua_toboolean(L, 1);
|
luaDebugEnabled = lua_toboolean(L, 1);
|
||||||
Logger::LogInfo("[Lua] DebugLua = %s", luaDebugEnabled ? "true" : "false");
|
if (old_state != luaDebugEnabled)
|
||||||
|
{
|
||||||
|
Logger::LogInfo("[Lua] DebugLua(%s)", luaDebugEnabled ? "true" : "false");
|
||||||
|
}
|
||||||
|
old_state = luaDebugEnabled;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Component resolver
|
// Component resolver
|
||||||
static Component* GetComponentByName(Object* obj, const std::string& type) {
|
static Component *GetComponentByName(Object *obj, const std::string &type)
|
||||||
if (type == "SpriteComponent") return obj->GetComponent<SpriteComponent>().get();
|
{
|
||||||
if (type == "CameraComponent") return obj->GetComponent<CameraComponent>().get();
|
PROFILE_SCOPE("LUA_GetComponentByName");
|
||||||
if (type == "LightComponent") return obj->GetComponent<LightComponent>().get();
|
|
||||||
if (type == "TilemapComponent") return obj->GetComponent<TilemapComponent>().get();
|
if (type == "SpriteComponent")
|
||||||
if (type == "TextComponent") return obj->GetComponent<TextComponent>().get();
|
return obj->GetComponent<SpriteComponent>().get();
|
||||||
if (type == "ScriptComponent") return obj->GetComponent<ScriptComponent>().get();
|
if (type == "CameraComponent")
|
||||||
|
return obj->GetComponent<CameraComponent>().get();
|
||||||
|
if (type == "LightComponent")
|
||||||
|
return obj->GetComponent<LightComponent>().get();
|
||||||
|
if (type == "TilemapComponent")
|
||||||
|
return obj->GetComponent<TilemapComponent>().get();
|
||||||
|
if (type == "TextComponent")
|
||||||
|
return obj->GetComponent<TextComponent>().get();
|
||||||
|
if (type == "ScriptComponent")
|
||||||
|
return obj->GetComponent<ScriptComponent>().get();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Object:GetComponent("Type")
|
// Object:GetComponent("Type")
|
||||||
static int Lua_Object_GetComponent(lua_State* L) {
|
static int Lua_Object_GetComponent(lua_State *L)
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE("Lua_Object_GetComponent");
|
||||||
|
|
||||||
auto *wrapper = (LuaObjectWrapper *)luaL_checkudata(L, 1, LUA_OBJECT_MT);
|
auto *wrapper = (LuaObjectWrapper *)luaL_checkudata(L, 1, LUA_OBJECT_MT);
|
||||||
const char *type = luaL_checkstring(L, 2);
|
const char *type = luaL_checkstring(L, 2);
|
||||||
|
|
||||||
Component *comp = GetComponentByName(wrapper->obj, type);
|
Component *comp = GetComponentByName(wrapper->obj, type);
|
||||||
if (comp) lua_pushlightuserdata(L, comp);
|
if (comp)
|
||||||
else lua_pushnil(L);
|
lua_pushlightuserdata(L, comp);
|
||||||
|
else
|
||||||
|
lua_pushnil(L);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Object:GetPosition()
|
// Object:GetPosition()
|
||||||
static int Lua_Object_GetPosition(lua_State* L) {
|
static int Lua_Object_GetPosition(lua_State *L)
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE("Lua_Object_GetPosition");
|
||||||
|
|
||||||
auto *wrapper = (LuaObjectWrapper *)luaL_checkudata(L, 1, LUA_OBJECT_MT);
|
auto *wrapper = (LuaObjectWrapper *)luaL_checkudata(L, 1, LUA_OBJECT_MT);
|
||||||
glm::vec2 pos = wrapper->obj->GetLocalPosition();
|
glm::vec2 pos = wrapper->obj->GetLocalPosition();
|
||||||
|
|
||||||
@ -90,7 +126,10 @@ static int Lua_Object_GetPosition(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Object:SetPosition(Vector2)
|
// Object:SetPosition(Vector2)
|
||||||
static int Lua_Object_SetPosition(lua_State* L) {
|
static int Lua_Object_SetPosition(lua_State *L)
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE("Lua_Object_SetPosition");
|
||||||
|
|
||||||
auto *wrapper = (LuaObjectWrapper *)luaL_checkudata(L, 1, LUA_OBJECT_MT);
|
auto *wrapper = (LuaObjectWrapper *)luaL_checkudata(L, 1, LUA_OBJECT_MT);
|
||||||
auto *vec = (LuaVector2 *)luaL_checkudata(L, 2, LUA_VECTOR2_MT);
|
auto *vec = (LuaVector2 *)luaL_checkudata(L, 2, LUA_VECTOR2_MT);
|
||||||
wrapper->obj->SetLocalPosition({vec->x, vec->y});
|
wrapper->obj->SetLocalPosition({vec->x, vec->y});
|
||||||
@ -98,19 +137,26 @@ static int Lua_Object_SetPosition(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// __index for Object
|
// __index for Object
|
||||||
static int Lua_Object_Index(lua_State* L) {
|
static int Lua_Object_Index(lua_State *L)
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE("Lua_Object_Index");
|
||||||
|
|
||||||
const char *key = luaL_checkstring(L, 2);
|
const char *key = luaL_checkstring(L, 2);
|
||||||
lua_getfield(L, lua_upvalueindex(1), key);
|
lua_getfield(L, lua_upvalueindex(1), key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterObjectType(lua_State* L) {
|
void RegisterObjectType(lua_State *L)
|
||||||
|
{
|
||||||
luaL_newmetatable(L, LUA_OBJECT_MT);
|
luaL_newmetatable(L, LUA_OBJECT_MT);
|
||||||
|
|
||||||
lua_newtable(L); // method table
|
lua_newtable(L); // method table
|
||||||
lua_pushcfunction(L, Lua_Object_GetComponent); lua_setfield(L, -2, "GetComponent");
|
lua_pushcfunction(L, Lua_Object_GetComponent);
|
||||||
lua_pushcfunction(L, Lua_Object_GetPosition); lua_setfield(L, -2, "GetPosition");
|
lua_setfield(L, -2, "GetComponent");
|
||||||
lua_pushcfunction(L, Lua_Object_SetPosition); lua_setfield(L, -2, "SetPosition");
|
lua_pushcfunction(L, Lua_Object_GetPosition);
|
||||||
|
lua_setfield(L, -2, "GetPosition");
|
||||||
|
lua_pushcfunction(L, Lua_Object_SetPosition);
|
||||||
|
lua_setfield(L, -2, "SetPosition");
|
||||||
|
|
||||||
lua_pushcclosure(L, Lua_Object_Index, 1);
|
lua_pushcclosure(L, Lua_Object_Index, 1);
|
||||||
lua_setfield(L, -2, "__index");
|
lua_setfield(L, -2, "__index");
|
||||||
@ -118,7 +164,8 @@ void RegisterObjectType(lua_State* L) {
|
|||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PushObject(lua_State* L, Object* obj) {
|
static void PushObject(lua_State *L, Object *obj)
|
||||||
|
{
|
||||||
auto *wrapper = (LuaObjectWrapper *)lua_newuserdata(L, sizeof(LuaObjectWrapper));
|
auto *wrapper = (LuaObjectWrapper *)lua_newuserdata(L, sizeof(LuaObjectWrapper));
|
||||||
wrapper->obj = obj;
|
wrapper->obj = obj;
|
||||||
luaL_getmetatable(L, LUA_OBJECT_MT);
|
luaL_getmetatable(L, LUA_OBJECT_MT);
|
||||||
@ -126,11 +173,16 @@ static void PushObject(lua_State* L, Object* obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Engine.GetObjectByTag(name)
|
// Engine.GetObjectByTag(name)
|
||||||
static int Lua_GetObjectByTag(lua_State* L) {
|
static int Lua_GetObjectByTag(lua_State *L)
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE("Lua_GetObjectByTag");
|
||||||
|
|
||||||
const char *name = luaL_checkstring(L, 1);
|
const char *name = luaL_checkstring(L, 1);
|
||||||
for (const auto& obj : objects) {
|
for (const auto &obj : objects)
|
||||||
|
{
|
||||||
auto found = FindByTagRecursive(obj, name);
|
auto found = FindByTagRecursive(obj, name);
|
||||||
if (found) {
|
if (found)
|
||||||
|
{
|
||||||
PushObject(L, found.get());
|
PushObject(L, found.get());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -140,57 +192,86 @@ static int Lua_GetObjectByTag(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Vector2(x, y)
|
// Vector2(x, y)
|
||||||
static int Lua_Vector2_New(lua_State* L) {
|
static int Lua_Vector2_New(lua_State *L)
|
||||||
LuaVector2* vec = (LuaVector2*)lua_newuserdata(L, sizeof(LuaVector2));
|
{
|
||||||
vec->x = (float)luaL_optnumber(L, 1, 0);
|
PROFILE_SCOPE("Lua_Vector2_New");
|
||||||
vec->y = (float)luaL_optnumber(L, 2, 0);
|
|
||||||
luaL_getmetatable(L, LUA_VECTOR2_MT);
|
LuaVector2 *vec = static_cast<LuaVector2 *>(lua_newuserdata(L, sizeof(LuaVector2)));
|
||||||
lua_setmetatable(L, -2);
|
|
||||||
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Lua_Vector2_Index(lua_State* L) {
|
static int Lua_Vector2_Index(lua_State *L)
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE("Lua_Vector2_Index");
|
||||||
|
|
||||||
auto *vec = (LuaVector2 *)luaL_checkudata(L, 1, LUA_VECTOR2_MT);
|
auto *vec = (LuaVector2 *)luaL_checkudata(L, 1, LUA_VECTOR2_MT);
|
||||||
const char *key = luaL_checkstring(L, 2);
|
const char *key = luaL_checkstring(L, 2);
|
||||||
if (strcmp(key, "x") == 0) lua_pushnumber(L, vec->x);
|
if (strcmp(key, "x") == 0)
|
||||||
else if (strcmp(key, "y") == 0) lua_pushnumber(L, vec->y);
|
lua_pushnumber(L, vec->x);
|
||||||
else lua_pushnil(L);
|
else if (strcmp(key, "y") == 0)
|
||||||
|
lua_pushnumber(L, vec->y);
|
||||||
|
else
|
||||||
|
lua_pushnil(L);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
static int Lua_Vector2_NewIndex(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);
|
auto *vec = (LuaVector2 *)luaL_checkudata(L, 1, LUA_VECTOR2_MT);
|
||||||
const char *key = luaL_checkstring(L, 2);
|
const char *key = luaL_checkstring(L, 2);
|
||||||
float value = (float)luaL_checknumber(L, 3);
|
float value = (float)luaL_checknumber(L, 3);
|
||||||
if (strcmp(key, "x") == 0) vec->x = value;
|
if (strcmp(key, "x") == 0)
|
||||||
else if (strcmp(key, "y") == 0) vec->y = value;
|
vec->x = value;
|
||||||
|
else if (strcmp(key, "y") == 0)
|
||||||
|
vec->y = value;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterVector2Type(lua_State* L) {
|
void RegisterVector2Type(lua_State *L)
|
||||||
|
{
|
||||||
|
|
||||||
luaL_newmetatable(L, LUA_VECTOR2_MT);
|
luaL_newmetatable(L, LUA_VECTOR2_MT);
|
||||||
lua_pushcfunction(L, Lua_Vector2_Index); lua_setfield(L, -2, "__index");
|
lua_pushcfunction(L, Lua_Vector2_Index);
|
||||||
lua_pushcfunction(L, Lua_Vector2_NewIndex); lua_setfield(L, -2, "__newindex");
|
lua_setfield(L, -2, "__index");
|
||||||
|
lua_pushcfunction(L, Lua_Vector2_NewIndex);
|
||||||
|
lua_setfield(L, -2, "__newindex");
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
lua_pushcfunction(L, Lua_Vector2_New);
|
lua_pushcfunction(L, Lua_Vector2_New);
|
||||||
lua_setglobal(L, "Vector2");
|
lua_setglobal(L, "Vector2");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptComponent::RegisterEngineBindings() {
|
void ScriptComponent::RegisterEngineBindings()
|
||||||
|
{
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
|
|
||||||
lua_pushcfunction(L, Lua_LogInfo); lua_setfield(L, -2, "LogInfo");
|
lua_pushcfunction(L, Lua_LogInfo);
|
||||||
lua_pushcfunction(L, Lua_LogError); lua_setfield(L, -2, "LogError");
|
lua_setfield(L, -2, "LogInfo");
|
||||||
lua_pushcfunction(L, Lua_LogDebug); lua_setfield(L, -2, "LogDebug");
|
lua_pushcfunction(L, Lua_LogError);
|
||||||
lua_pushcfunction(L, Lua_GetObjectByTag); lua_setfield(L, -2, "GetObjectByTag");
|
lua_setfield(L, -2, "LogError");
|
||||||
lua_pushcfunction(L, Lua_DebugLua); lua_setfield(L, -2, "DebugLua");
|
lua_pushcfunction(L, Lua_LogDebug);
|
||||||
|
lua_setfield(L, -2, "LogDebug");
|
||||||
|
lua_pushcfunction(L, Lua_GetObjectByTag);
|
||||||
|
lua_setfield(L, -2, "GetObjectByTag");
|
||||||
|
lua_pushcfunction(L, Lua_DebugLua);
|
||||||
|
lua_setfield(L, -2, "DebugLua");
|
||||||
|
|
||||||
lua_setglobal(L, "Engine");
|
lua_setglobal(L, "Engine");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptComponent::ReloadScript() {
|
void ScriptComponent::ReloadScript()
|
||||||
if (scriptPath.empty()) return;
|
{
|
||||||
|
if (scriptPath.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
if (L) lua_close(L);
|
if (L)
|
||||||
|
lua_close(L);
|
||||||
L = luaL_newstate();
|
L = luaL_newstate();
|
||||||
luaL_openlibs(L);
|
luaL_openlibs(L);
|
||||||
|
|
||||||
@ -198,54 +279,79 @@ void ScriptComponent::ReloadScript() {
|
|||||||
RegisterVector2Type(L);
|
RegisterVector2Type(L);
|
||||||
RegisterEngineBindings();
|
RegisterEngineBindings();
|
||||||
|
|
||||||
if (luaL_dofile(L, scriptPath.c_str())) {
|
Logger::LogVerbose("[Lua] Loading Script from file.");
|
||||||
|
|
||||||
|
if (luaL_dofile(L, scriptPath.c_str()))
|
||||||
|
{
|
||||||
Logger::LogError("[Lua] %s", lua_tostring(L, -1));
|
Logger::LogError("[Lua] %s", lua_tostring(L, -1));
|
||||||
RecoverableError("Failed to load Lua script: " + scriptPath, Create::Exceptions::ComponentLoad).Handle();
|
RecoverableError("Failed to load Lua script: " + scriptPath, Create::Exceptions::ComponentLoad).Handle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (luaDebugEnabled)
|
||||||
|
{
|
||||||
|
Logger::LogVerbose("[Lua][call] OnInit()");
|
||||||
|
}
|
||||||
lua_getglobal(L, "OnInit");
|
lua_getglobal(L, "OnInit");
|
||||||
if (lua_isfunction(L, -1)) {
|
if (lua_isfunction(L, -1))
|
||||||
if (lua_pcall(L, 0, 0, 0) != LUA_OK) {
|
{
|
||||||
|
if (lua_pcall(L, 0, 0, 0) != LUA_OK)
|
||||||
|
{
|
||||||
Logger::LogError("[Lua] %s", lua_tostring(L, -1));
|
Logger::LogError("[Lua] %s", lua_tostring(L, -1));
|
||||||
RecoverableError("OnInit failed: " + scriptPath, Create::Exceptions::ComponentLoad).Handle();
|
RecoverableError("OnInit failed: " + scriptPath, Create::Exceptions::ComponentLoad).Handle();
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptComponent::OnUpdate(float dt) {
|
void ScriptComponent::OnUpdate(float dt)
|
||||||
if (!L) return;
|
{
|
||||||
|
PROFILE_SCOPE("ScriptComponent::OnUpdate");
|
||||||
|
|
||||||
|
if (!L)
|
||||||
|
return;
|
||||||
lua_getglobal(L, "OnUpdate");
|
lua_getglobal(L, "OnUpdate");
|
||||||
if (lua_isfunction(L, -1)) {
|
if (lua_isfunction(L, -1))
|
||||||
|
{
|
||||||
lua_pushnumber(L, dt);
|
lua_pushnumber(L, dt);
|
||||||
if (lua_pcall(L, 1, 0, 0) != LUA_OK) {
|
if (lua_pcall(L, 1, 0, 0) != LUA_OK)
|
||||||
|
{
|
||||||
Logger::LogError("[Lua] %s", lua_tostring(L, -1));
|
Logger::LogError("[Lua] %s", lua_tostring(L, -1));
|
||||||
RecoverableError("OnUpdate failed in: " + scriptPath, Create::Exceptions::ComponentLoad).Handle();
|
RecoverableError("OnUpdate failed in: " + scriptPath, Create::Exceptions::ComponentLoad).Handle();
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptComponent::Save(YAML::Emitter& out) const {
|
void ScriptComponent::Save(YAML::Emitter &out) const
|
||||||
|
{
|
||||||
out << YAML::BeginMap;
|
out << YAML::BeginMap;
|
||||||
out << YAML::Key << "type" << YAML::Value << "ScriptComponent";
|
out << YAML::Key << "type" << YAML::Value << "ScriptComponent";
|
||||||
out << YAML::Key << "scriptPath" << YAML::Value << scriptPath;
|
out << YAML::Key << "scriptPath" << YAML::Value << scriptPath;
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptComponent::Load(const YAML::Node& node) {
|
void ScriptComponent::Load(const YAML::Node &node)
|
||||||
try {
|
{
|
||||||
if (!node["scriptPath"]) {
|
try
|
||||||
|
{
|
||||||
|
if (!node["scriptPath"])
|
||||||
|
{
|
||||||
RecoverableError("Missing 'scriptPath' in ScriptComponent", Create::Exceptions::MissingField).Handle();
|
RecoverableError("Missing 'scriptPath' in ScriptComponent", Create::Exceptions::MissingField).Handle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptPath = node["scriptPath"].as<std::string>();
|
scriptPath = node["scriptPath"].as<std::string>();
|
||||||
ReloadScript();
|
ReloadScript();
|
||||||
} catch (const YAML::Exception& e) {
|
}
|
||||||
|
catch (const YAML::Exception &e)
|
||||||
|
{
|
||||||
RecoverableError("YAML error in ScriptComponent::Load: " + std::string(e.what()), Create::Exceptions::ComponentLoad).Handle();
|
RecoverableError("YAML error in ScriptComponent::Load: " + std::string(e.what()), Create::Exceptions::ComponentLoad).Handle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include "../utils/utils.h"
|
#include "../utils/utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct ImageCacheEntry {
|
struct ImageCacheEntry {
|
||||||
unsigned int textureID;
|
unsigned int textureID;
|
||||||
glm::vec2 size;
|
glm::vec2 size;
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "utils/EngineConfig.h"
|
#include "utils/EngineConfig.h"
|
||||||
#include "utils/GameObjectsList.h"
|
#include "utils/GameObjectsList.h"
|
||||||
|
#include "utils/Profiler.h"
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
@ -24,6 +25,10 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <format>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -40,14 +45,15 @@ static glm::vec2 cameraPos = {0, 0};
|
|||||||
static float cameraZoom = 1.0f;
|
static float cameraZoom = 1.0f;
|
||||||
static ImVec2 lastMousePos = {};
|
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;
|
GLFWwindow *window = nullptr;
|
||||||
|
|
||||||
Engine::Engine()
|
Engine::Engine()
|
||||||
{
|
{
|
||||||
|
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,46 +62,251 @@ Engine::~Engine()
|
|||||||
Shutdown();
|
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)
|
void Engine::ShowDebugOverlay(float deltaTime)
|
||||||
{
|
{
|
||||||
|
// === Performance Window ===
|
||||||
static std::vector<float> fpsHistory;
|
static std::vector<float> fpsHistory;
|
||||||
static const int maxHistory = 100;
|
static const int maxFpsHistory = 100;
|
||||||
static float timer = 0;
|
static float fpsTimer = 0.0f;
|
||||||
float fps = 1.0f / deltaTime;
|
float fps = 1.0f / deltaTime;
|
||||||
g_fps = fps;
|
g_fps = fps;
|
||||||
if (fpsHistory.size() >= maxHistory)
|
if (fpsHistory.size() >= maxFpsHistory)
|
||||||
fpsHistory.erase(fpsHistory.begin());
|
fpsHistory.erase(fpsHistory.begin());
|
||||||
if (timer >= 0.05)
|
if (fpsTimer >= 0.05f)
|
||||||
{
|
{
|
||||||
timer = 0;
|
fpsTimer = 0;
|
||||||
fpsHistory.push_back(fps);
|
fpsHistory.push_back(fps);
|
||||||
}
|
}
|
||||||
timer += deltaTime;
|
fpsTimer += deltaTime;
|
||||||
|
|
||||||
ImGui::Begin("Performance Info", nullptr,
|
ImGui::Begin("Performance Info", nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize);
|
||||||
ImGuiWindowFlags_NoDecoration);
|
|
||||||
|
|
||||||
ImGui::TextColored(ImVec4(0.3f, 1.0f, 0.3f, 1.0f), "Performance");
|
ImGui::TextColored(ImVec4(0.3f, 1.0f, 0.3f, 1.0f), "Performance");
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::Text("FPS: %.1f", fps);
|
ImGui::Text("FPS: %.1f", fps);
|
||||||
ImGui::Text("Delta Time: %.4f s", deltaTime);
|
ImGui::Text("Delta Time: %.4f s", deltaTime);
|
||||||
ImGui::Text("Frame Time: %.2f ms", deltaTime * 1000.0f);
|
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::Spacing();
|
||||||
ImGui::TextColored(ImVec4(0.4f, 0.7f, 1.0f, 1.0f), "Renderer");
|
ImGui::TextColored(ImVec4(0.4f, 0.7f, 1.0f, 1.0f), "Renderer");
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::Text("Draw Calls: %d", Renderer::GetDrawCallCount());
|
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("Scene Lights: %d / %d", Renderer::GetLightsCount(), g_engineConfig.gl_maxLight);
|
||||||
|
|
||||||
ImGui::Text("Reserved Draws: %d", m_Reserved_draws);
|
ImGui::Text("Reserved Draws: %d", m_Reserved_draws);
|
||||||
|
|
||||||
ImGui::Text("Camera Zoom: %.2f", cameraZoom);
|
ImGui::Text("Camera Zoom: %.2f", cameraZoom);
|
||||||
ImGui::Text("Camera Pos: (%.1f, %.1f)", cameraPos.x, cameraPos.y);
|
ImGui::Text("Camera Pos: (%.1f, %.1f)", cameraPos.x, cameraPos.y);
|
||||||
|
|
||||||
ImGui::End();
|
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()
|
void Engine::Init()
|
||||||
{
|
{
|
||||||
glfwInit();
|
glfwInit();
|
||||||
@ -108,6 +319,8 @@ void Engine::Init()
|
|||||||
glfwSwapInterval(0); // No VSync
|
glfwSwapInterval(0); // No VSync
|
||||||
glewInit();
|
glewInit();
|
||||||
|
|
||||||
|
g_engineConfig.LoadFromFile();
|
||||||
|
|
||||||
IMGUI_CHECKVERSION();
|
IMGUI_CHECKVERSION();
|
||||||
ImGui::CreateContext();
|
ImGui::CreateContext();
|
||||||
ImGuiIO &io = ImGui::GetIO();
|
ImGuiIO &io = ImGui::GetIO();
|
||||||
@ -123,10 +336,16 @@ void Engine::Init()
|
|||||||
|
|
||||||
objects.push_back(obj);
|
objects.push_back(obj);
|
||||||
selected = obj;
|
selected = obj;
|
||||||
|
Logger::LogVerbose("Resverving Objects");
|
||||||
|
|
||||||
|
m_toDraw.reserve(1024);
|
||||||
|
m_scriptUpdates.reserve(256);
|
||||||
|
m_collectStack.reserve(1024);
|
||||||
Logger::LogInfo("Initialized Engine");
|
Logger::LogInfo("Initialized Engine");
|
||||||
}
|
}
|
||||||
void DrawInspectorUI(std::shared_ptr<Object> selected)
|
void DrawInspectorUI(std::shared_ptr<Object> selected)
|
||||||
{
|
{
|
||||||
|
PROFILE_ENGINE_SCOPE("Engine::DrawInspectorUI");
|
||||||
ImGui::Begin("Inspector");
|
ImGui::Begin("Inspector");
|
||||||
|
|
||||||
if (!selected)
|
if (!selected)
|
||||||
@ -167,6 +386,10 @@ void DrawInspectorUI(std::shared_ptr<Object> selected)
|
|||||||
if (ImGui::DragFloat2("Position", &pos.x, 0.1f))
|
if (ImGui::DragFloat2("Position", &pos.x, 0.1f))
|
||||||
selected->SetLocalPosition(pos);
|
selected->SetLocalPosition(pos);
|
||||||
|
|
||||||
|
float rotation = selected->GetLocalRotation();
|
||||||
|
if (ImGui::DragFloat("Rotation", &rotation, 1.0f))
|
||||||
|
selected->SetLocalRotation(rotation);
|
||||||
|
|
||||||
int layer = selected->layer;
|
int layer = selected->layer;
|
||||||
if (ImGui::InputInt("Layer", &layer))
|
if (ImGui::InputInt("Layer", &layer))
|
||||||
selected->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()
|
void Engine::Run()
|
||||||
{
|
{
|
||||||
while (!glfwWindowShouldClose(window))
|
while (!glfwWindowShouldClose(window))
|
||||||
{
|
{
|
||||||
|
if (g_engineConfig.settings.profile_editor)
|
||||||
|
{
|
||||||
|
profiler.BeginFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
profiler.BeginEngineSection("glfwPollEvents");
|
||||||
|
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
profiler.EndEngineSection();
|
||||||
|
|
||||||
|
profiler.BeginEngineSection("NewFrame");
|
||||||
|
|
||||||
|
profiler.BeginEngineSection("ImGui_ImplOpenGL3_NewFrame");
|
||||||
|
|
||||||
ImGui_ImplOpenGL3_NewFrame();
|
ImGui_ImplOpenGL3_NewFrame();
|
||||||
|
|
||||||
|
profiler.EndEngineSection();
|
||||||
|
|
||||||
|
profiler.BeginEngineSection("ImGui_ImplGlfw_NewFrame");
|
||||||
|
|
||||||
ImGui_ImplGlfw_NewFrame();
|
ImGui_ImplGlfw_NewFrame();
|
||||||
|
|
||||||
|
profiler.EndEngineSection();
|
||||||
|
|
||||||
|
profiler.BeginEngineSection("ImGui::NewFrame");
|
||||||
|
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
|
|
||||||
|
profiler.EndEngineSection();
|
||||||
|
|
||||||
|
profiler.BeginEngineSection("ImGui::DockSpaceOverViewport");
|
||||||
|
|
||||||
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport()->ID);
|
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport()->ID);
|
||||||
|
|
||||||
|
profiler.EndEngineSection();
|
||||||
|
|
||||||
|
profiler.BeginEngineSection("glfwGetTime");
|
||||||
|
|
||||||
float currentTime = glfwGetTime();
|
float currentTime = glfwGetTime();
|
||||||
static float lastTime = currentTime;
|
static float lastTime = currentTime;
|
||||||
float deltaTime = currentTime - lastTime;
|
float deltaTime = currentTime - lastTime;
|
||||||
lastTime = currentTime;
|
lastTime = currentTime;
|
||||||
|
profiler.EndEngineSection();
|
||||||
|
|
||||||
|
profiler.EndEngineSection();
|
||||||
|
|
||||||
|
profiler.BeginEngineSection("Engine::ShowDebugOverlay");
|
||||||
|
|
||||||
ShowDebugOverlay(deltaTime);
|
ShowDebugOverlay(deltaTime);
|
||||||
|
profiler.EndEngineSection();
|
||||||
|
|
||||||
|
profiler.BeginEngineSection("Logger::Draw");
|
||||||
|
|
||||||
Logger::Draw();
|
Logger::Draw();
|
||||||
|
profiler.EndEngineSection();
|
||||||
|
|
||||||
|
profiler.BeginEngineSection("BeginMainMenuBar");
|
||||||
|
|
||||||
if (ImGui::BeginMainMenuBar())
|
if (ImGui::BeginMainMenuBar())
|
||||||
{
|
{
|
||||||
@ -369,12 +677,12 @@ void Engine::Run()
|
|||||||
if (!playing)
|
if (!playing)
|
||||||
{
|
{
|
||||||
Logger::LogVerbose("[RestoreScene] Saving original scene");
|
Logger::LogVerbose("[RestoreScene] Saving original scene");
|
||||||
SaveScene(tempScenePath);
|
SaveState();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Logger::LogVerbose("[RestoreScene] Reloading original scene");
|
Logger::LogVerbose("[RestoreScene] Reloading original scene");
|
||||||
LoadScene(tempScenePath);
|
LoadState();
|
||||||
}
|
}
|
||||||
selected = nullptr;
|
selected = nullptr;
|
||||||
playing = !playing;
|
playing = !playing;
|
||||||
@ -402,9 +710,24 @@ void Engine::Run()
|
|||||||
|
|
||||||
if (ImGui::BeginMenu("Options"))
|
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("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();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
@ -426,6 +749,14 @@ void Engine::Run()
|
|||||||
|
|
||||||
ImGui::EndMainMenuBar();
|
ImGui::EndMainMenuBar();
|
||||||
}
|
}
|
||||||
|
profiler.EndEngineSection();
|
||||||
|
|
||||||
|
if (g_engineConfig.settings.show_color_correction_window)
|
||||||
|
ShowColorCorrectionWindow();
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
PROFILE_ENGINE_SCOPE("Engine::DrawSceneTree");
|
||||||
|
|
||||||
ImGui::Begin("Scene Tree");
|
ImGui::Begin("Scene Tree");
|
||||||
|
|
||||||
@ -463,6 +794,7 @@ void Engine::Run()
|
|||||||
DrawObjectNode(obj);
|
DrawObjectNode(obj);
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
DrawInspectorUI(selected);
|
DrawInspectorUI(selected);
|
||||||
|
|
||||||
@ -506,95 +838,92 @@ void Engine::Run()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resize
|
||||||
|
profiler.BeginEngineSection("Renderer::Resize");
|
||||||
Renderer::Resize((int)size.x, (int)size.y);
|
Renderer::Resize((int)size.x, (int)size.y);
|
||||||
|
profiler.EndEngineSection();
|
||||||
|
|
||||||
|
// Begin
|
||||||
|
profiler.BeginEngineSection("Renderer::Begin");
|
||||||
Renderer::Begin();
|
Renderer::Begin();
|
||||||
|
profiler.EndEngineSection();
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Object>> toDraw;
|
// Reserve (no profiling)
|
||||||
std::vector<ScriptComponent *> scriptUpdates;
|
m_toDraw.reserve(m_Reserved_draws);
|
||||||
|
|
||||||
toDraw.reserve(m_Reserved_draws);
|
|
||||||
m_Reserved_draws = 0; // Reset
|
|
||||||
|
|
||||||
Renderer::DrawEditorGrid(cameraPos, cameraZoom);
|
|
||||||
|
|
||||||
// clear arrays each frame…
|
|
||||||
toDraw.clear();
|
|
||||||
scriptUpdates.clear();
|
|
||||||
m_Reserved_draws = 0;
|
m_Reserved_draws = 0;
|
||||||
|
|
||||||
// recursive collector now skips invisible objects (and their children)
|
// Draw Editor Grid
|
||||||
std::function<void(const std::shared_ptr<Object> &)> collect =
|
profiler.BeginEngineSection("Draw Editor Grid");
|
||||||
[&](const std::shared_ptr<Object> &obj)
|
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
|
std::sort(m_toDraw.begin(), m_toDraw.end(),
|
||||||
if (!obj->GetVisable())
|
[](auto const &a, auto const &b)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
if (a->layer != b->layer)
|
if (a->layer != b->layer)
|
||||||
return 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
|
if (!g_engineConfig.settings.profile_editor)
|
||||||
for (auto *script : scriptUpdates)
|
profiler.BeginFrame();
|
||||||
|
|
||||||
|
m_OnUpdateCalls = 0;
|
||||||
|
|
||||||
|
profiler.BeginSection("Script Updates");
|
||||||
|
for (auto *script : m_scriptUpdates)
|
||||||
|
{
|
||||||
|
profiler.BeginSection("Script: " + script->GetOwner()->GetName());
|
||||||
script->OnUpdate(deltaTime);
|
script->OnUpdate(deltaTime);
|
||||||
|
m_OnUpdateCalls++;
|
||||||
|
profiler.EndSection();
|
||||||
|
}
|
||||||
|
profiler.EndSection();
|
||||||
|
|
||||||
// Draw all sprites
|
profiler.BeginSection("Render");
|
||||||
for (const auto &obj : toDraw)
|
for (auto *obj : m_toDraw)
|
||||||
{
|
{
|
||||||
if (auto sprite = obj->GetComponent<SpriteComponent>())
|
if (auto spritePtr = obj->GetComponent<SpriteComponent>())
|
||||||
{
|
{
|
||||||
glm::vec2 worldPos = obj->GetWorldPosition();
|
profiler.BeginSection("Draw Sprite: " + obj->GetName());
|
||||||
Renderer::DrawSprite(sprite.get(), worldPos, cameraZoom, cameraPos);
|
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();
|
Renderer::End();
|
||||||
|
profiler.EndEngineSection();
|
||||||
|
|
||||||
|
// Display render target texture
|
||||||
GLuint texID = Renderer::GetRenderTexture();
|
GLuint texID = Renderer::GetRenderTexture();
|
||||||
ImGui::Image((ImTextureID)(uintptr_t)texID, size, ImVec2(0, 1), ImVec2(1, 0));
|
ImGui::Image((ImTextureID)(uintptr_t)texID, size, ImVec2(0, 1), ImVec2(1, 0));
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
if (ImGui::BeginPopup("RenameObject"))
|
if (ImGui::BeginPopup("RenameObject"))
|
||||||
@ -627,7 +956,13 @@ void Engine::Run()
|
|||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_engineConfig.settings.profile_editor)
|
||||||
|
{
|
||||||
|
profiler.EndFrame(); // Finish frame
|
||||||
|
}
|
||||||
// ImGui render
|
// ImGui render
|
||||||
|
ShowProfilerTimeline();
|
||||||
|
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
int w, h;
|
int w, h;
|
||||||
glfwGetFramebufferSize(window, &w, &h);
|
glfwGetFramebufferSize(window, &w, &h);
|
||||||
@ -656,6 +991,8 @@ void Engine::Run()
|
|||||||
|
|
||||||
void Engine::DrawObjectNode(const std::shared_ptr<Object> &obj)
|
void Engine::DrawObjectNode(const std::shared_ptr<Object> &obj)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
PROFILE_ENGINE_SCOPE("Engine::DrawObjectNode");
|
||||||
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow |
|
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow |
|
||||||
ImGuiTreeNodeFlags_SpanAvailWidth |
|
ImGuiTreeNodeFlags_SpanAvailWidth |
|
||||||
(obj == selected ? ImGuiTreeNodeFlags_Selected : 0);
|
(obj == selected ? ImGuiTreeNodeFlags_Selected : 0);
|
||||||
@ -813,8 +1150,53 @@ void Engine::LoadScene(const std::string &path)
|
|||||||
Logger::LogInfo("[LoadScene] Loaded scene: %s", root["scene_name"].as<std::string>().c_str());
|
Logger::LogInfo("[LoadScene] Loaded scene: %s", root["scene_name"].as<std::string>().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Engine::LoadState()
|
||||||
|
{
|
||||||
|
if (savedStateYAML.empty())
|
||||||
|
{
|
||||||
|
Logger::LogWarning("[LoadState] No scene state in memory.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
YAML::Node objectArray;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
objectArray = YAML::Load(savedStateYAML);
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
Logger::LogError("[LoadState] Failed to parse saved scene: %s", e.what());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
objects.clear();
|
||||||
|
for (const auto &node : objectArray)
|
||||||
|
{
|
||||||
|
auto obj = std::make_shared<Object>("[DefaultObject]");
|
||||||
|
obj->Load(node);
|
||||||
|
objects.push_back(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
void Engine::Shutdown()
|
||||||
{
|
{
|
||||||
|
g_engineConfig.SaveToFile();
|
||||||
|
|
||||||
ImGui_ImplOpenGL3_Shutdown();
|
ImGui_ImplOpenGL3_Shutdown();
|
||||||
ImGui_ImplGlfw_Shutdown();
|
ImGui_ImplGlfw_Shutdown();
|
||||||
ImGui::DestroyContext();
|
ImGui::DestroyContext();
|
||||||
@ -822,4 +1204,5 @@ void Engine::Shutdown()
|
|||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
|
|
||||||
std::filesystem::remove(tempScenePath);
|
std::filesystem::remove(tempScenePath);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,30 +1,40 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector> // ← for std::vector<>
|
||||||
|
#include <glm/vec2.hpp> // ← for glm::vec2
|
||||||
|
|
||||||
|
|
||||||
class Object;
|
class Object;
|
||||||
|
class ScriptComponent;
|
||||||
|
|
||||||
class Engine {
|
class Engine
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
Engine();
|
Engine();
|
||||||
~Engine();
|
~Engine();
|
||||||
void Run();
|
void Run();
|
||||||
std::shared_ptr<Object> GetObjectByTag(const std::string &tag);
|
std::shared_ptr<Object> GetObjectByTag(const std::string &tag);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Init();
|
void Init();
|
||||||
void Shutdown();
|
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 SaveScene(const std::string &path);
|
||||||
void LoadScene(const std::string &path);
|
void LoadScene(const std::string &path);
|
||||||
void ShowDebugOverlay(float deltaTime);
|
void ShowDebugOverlay(float deltaTime);
|
||||||
|
|
||||||
|
void collectObjects(bool playing, const glm::vec2& camPos, float camZoom);
|
||||||
|
|
||||||
|
void SaveState();
|
||||||
|
void LoadState();
|
||||||
|
|
||||||
int m_Reserved_draws;
|
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>
|
#include <algorithm>
|
||||||
|
|
||||||
Object::Object(const std::string &name)
|
Object::Object(const std::string &name)
|
||||||
: name(name), localPosition(0.0f, 0.0f), uid() {}
|
: name(name), localPosition(0.0f, 0.0f), localRotationDeg(0.0f), uid(), visable(true) {}
|
||||||
|
|
||||||
Object::~Object() {}
|
Object::~Object() {}
|
||||||
|
|
||||||
@ -45,6 +45,41 @@ glm::vec2 Object::GetLocalPosition() const
|
|||||||
return localPosition;
|
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
|
bool Object::GetVisable() const
|
||||||
{
|
{
|
||||||
return visable;
|
return visable;
|
||||||
@ -55,19 +90,6 @@ void Object::SetVisable(bool state)
|
|||||||
visable = 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; }
|
const std::string &Object::GetName() const { return name; }
|
||||||
void Object::SetName(const std::string &n) { name = n; }
|
void Object::SetName(const std::string &n) { name = n; }
|
||||||
std::vector<std::shared_ptr<Object>> &Object::GetChildren() { return children; }
|
std::vector<std::shared_ptr<Object>> &Object::GetChildren() { return children; }
|
||||||
@ -77,16 +99,15 @@ void Object::Save(YAML::Emitter &out) const
|
|||||||
{
|
{
|
||||||
Logger::LogVerbose("[LoadScene] Saving Object: [%s, %d]", name.c_str(), uid.id);
|
Logger::LogVerbose("[LoadScene] Saving Object: [%s, %d]", name.c_str(), uid.id);
|
||||||
|
|
||||||
|
|
||||||
out << YAML::BeginMap;
|
out << YAML::BeginMap;
|
||||||
out << YAML::Key << "name" << YAML::Value << name;
|
out << YAML::Key << "name" << YAML::Value << name;
|
||||||
out << YAML::Key << "uid" << YAML::Value << uid.uuid;
|
out << YAML::Key << "uid" << YAML::Value << uid.uuid;
|
||||||
out << YAML::Key << "id" << YAML::Value << uid.id;
|
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 << "layer" << YAML::Value << layer;
|
||||||
out << YAML::Key << "visable" << YAML::Value << visable;
|
out << YAML::Key << "visable" << YAML::Value << visable;
|
||||||
|
|
||||||
|
|
||||||
out << YAML::Key << "components" << YAML::Value << YAML::BeginSeq;
|
out << YAML::Key << "components" << YAML::Value << YAML::BeginSeq;
|
||||||
for (const auto &comp : components)
|
for (const auto &comp : components)
|
||||||
{
|
{
|
||||||
@ -106,71 +127,36 @@ void Object::Save(YAML::Emitter &out) const
|
|||||||
void Object::Load(const YAML::Node &node)
|
void Object::Load(const YAML::Node &node)
|
||||||
{
|
{
|
||||||
name = node["name"].as<std::string>();
|
name = node["name"].as<std::string>();
|
||||||
|
uid.uuid = node["uid"] ? node["uid"].as<std::string>() : GenerateUUID();
|
||||||
if (node["uid"])
|
uid.id = node["id"] ? node["id"].as<int>() : 0;
|
||||||
uid.uuid = node["uid"].as<std::string>();
|
|
||||||
else
|
|
||||||
uid.uuid = GenerateUUID();
|
|
||||||
|
|
||||||
if (node["id"])
|
|
||||||
uid.id = node["id"].as<int>();
|
|
||||||
|
|
||||||
auto pos = node["position"];
|
auto pos = node["position"];
|
||||||
if (pos && pos.IsSequence() && pos.size() == 2)
|
if (pos && pos.IsSequence() && pos.size() == 2)
|
||||||
{
|
localPosition = {pos[0].as<float>(), pos[1].as<float>()};
|
||||||
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>();
|
|
||||||
|
|
||||||
|
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);
|
Logger::LogVerbose("[LoadScene] Loading Object: [%s, %d]", name.c_str(), uid.id);
|
||||||
|
|
||||||
|
components.clear();
|
||||||
if (node["components"])
|
if (node["components"])
|
||||||
{
|
{
|
||||||
for (const auto &compNode : node["components"])
|
for (const auto &compNode : node["components"])
|
||||||
{
|
{
|
||||||
std::string type = compNode["type"].as<std::string>();
|
std::string type = compNode["type"].as<std::string>();
|
||||||
Logger::LogVerbose("[LoadScene] Createing Component: %s", type.c_str());
|
|
||||||
|
|
||||||
if (type == "SpriteComponent")
|
if (type == "SpriteComponent") AddComponent<SpriteComponent>()->Load(compNode);
|
||||||
{
|
else if (type == "CameraComponent") AddComponent<CameraComponent>()->Load(compNode);
|
||||||
auto comp = AddComponent<SpriteComponent>();
|
else if (type == "LightComponent") AddComponent<LightComponent>()->Load(compNode);
|
||||||
comp->Load(compNode);
|
else if (type == "TilemapComponent") AddComponent<TilemapComponent>()->Load(compNode);
|
||||||
}
|
else if (type == "TextComponent") AddComponent<TextComponent>()->Load(compNode);
|
||||||
else if (type == "CameraComponent")
|
else if (type == "ScriptComponent") AddComponent<ScriptComponent>()->Load(compNode);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
children.clear();
|
||||||
if (node["children"])
|
if (node["children"])
|
||||||
{
|
{
|
||||||
for (const auto &childNode : node["children"])
|
for (const auto &childNode : node["children"])
|
||||||
|
@ -3,7 +3,10 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtx/rotate_vector.hpp>
|
||||||
|
|
||||||
#include <yaml-cpp/yaml.h>
|
#include <yaml-cpp/yaml.h>
|
||||||
#include "../utils/UID.h"
|
#include "../utils/UID.h"
|
||||||
|
|
||||||
@ -22,6 +25,10 @@ public:
|
|||||||
void SetLocalPosition(glm::vec2 pos);
|
void SetLocalPosition(glm::vec2 pos);
|
||||||
glm::vec2 GetWorldPosition() const;
|
glm::vec2 GetWorldPosition() const;
|
||||||
|
|
||||||
|
float GetLocalRotation() const;
|
||||||
|
void SetLocalRotation(float deg);
|
||||||
|
float GetWorldRotation() const;
|
||||||
|
|
||||||
void SetParent(Object *parent);
|
void SetParent(Object *parent);
|
||||||
Object *GetParent() const;
|
Object *GetParent() const;
|
||||||
void AddChild(std::shared_ptr<Object> child);
|
void AddChild(std::shared_ptr<Object> child);
|
||||||
@ -31,7 +38,6 @@ public:
|
|||||||
bool GetVisable() const;
|
bool GetVisable() const;
|
||||||
void SetVisable(bool state);
|
void SetVisable(bool state);
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::shared_ptr<T> GetComponent() const;
|
std::shared_ptr<T> GetComponent() const;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -46,9 +52,10 @@ public:
|
|||||||
int layer = 0;
|
int layer = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool visable;
|
bool visable = true;
|
||||||
std::string name;
|
std::string name;
|
||||||
glm::vec2 localPosition;
|
glm::vec2 localPosition{0.0f};
|
||||||
|
float localRotationDeg = 0.0f; // Rotation in degrees
|
||||||
Object *parent = nullptr;
|
Object *parent = nullptr;
|
||||||
std::vector<std::shared_ptr<Object>> children;
|
std::vector<std::shared_ptr<Object>> children;
|
||||||
std::vector<std::shared_ptr<Component>> components;
|
std::vector<std::shared_ptr<Component>> components;
|
||||||
@ -58,10 +65,8 @@ template <typename T>
|
|||||||
std::shared_ptr<T> Object::GetComponent() const
|
std::shared_ptr<T> Object::GetComponent() const
|
||||||
{
|
{
|
||||||
for (const auto &comp : components)
|
for (const auto &comp : components)
|
||||||
{
|
|
||||||
if (auto casted = std::dynamic_pointer_cast<T>(comp))
|
if (auto casted = std::dynamic_pointer_cast<T>(comp))
|
||||||
return casted;
|
return casted;
|
||||||
}
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +77,7 @@ std::shared_ptr<T> Object::AddComponent()
|
|||||||
if (existing)
|
if (existing)
|
||||||
return existing;
|
return existing;
|
||||||
|
|
||||||
std::shared_ptr<T> component = std::make_shared<T>(this);
|
auto component = std::make_shared<T>(this);
|
||||||
components.push_back(component);
|
components.push_back(component);
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include "utils/Logging.h"
|
#include "utils/Logging.h"
|
||||||
#include "utils/EngineConfig.h"
|
#include "utils/EngineConfig.h"
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
|
#include "utils/Profiler.h"
|
||||||
|
#include "Entitys/Object.h"
|
||||||
|
|
||||||
#include "stb_image.h"
|
#include "stb_image.h"
|
||||||
|
|
||||||
@ -25,6 +27,8 @@ int Renderer::width = 1280;
|
|||||||
int Renderer::height = 720;
|
int Renderer::height = 720;
|
||||||
int Renderer::s_DrawCalls = 0;
|
int Renderer::s_DrawCalls = 0;
|
||||||
int Renderer::s_LightsCount = 0;
|
int Renderer::s_LightsCount = 0;
|
||||||
|
std::unique_ptr<ColorCorrection> Renderer::s_ColorCorrection = nullptr;
|
||||||
|
|
||||||
|
|
||||||
std::vector<Light> Renderer::s_Lights;
|
std::vector<Light> Renderer::s_Lights;
|
||||||
|
|
||||||
@ -83,6 +87,9 @@ void Renderer::Init()
|
|||||||
// Load unlit shader
|
// Load unlit shader
|
||||||
unlitShader.LoadFromFile("src/assets/shaders/unlit.vert", "src/assets/shaders/unlit.frag");
|
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)
|
// Create a 1x1 flat normal map (RGB: 128,128,255)
|
||||||
unsigned char flatNormal[3] = {128, 128, 255};
|
unsigned char flatNormal[3] = {128, 128, 255};
|
||||||
glGenTextures(1, &defaultNormalMap);
|
glGenTextures(1, &defaultNormalMap);
|
||||||
@ -96,6 +103,7 @@ void Renderer::Init()
|
|||||||
|
|
||||||
void Renderer::Resize(int w, int h)
|
void Renderer::Resize(int w, int h)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (w == width && h == height)
|
if (w == width && h == height)
|
||||||
return;
|
return;
|
||||||
width = w;
|
width = w;
|
||||||
@ -111,15 +119,27 @@ void Renderer::Resize(int w, int h)
|
|||||||
|
|
||||||
void Renderer::Begin()
|
void Renderer::Begin()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
{
|
||||||
|
PROFILE_ENGINE_SCOPE("glBindFramebuffer");
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||||
|
}
|
||||||
|
{
|
||||||
glViewport(0, 0, width, height);
|
glViewport(0, 0, width, height);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
|
||||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
|
||||||
s_DrawCalls = 0;
|
s_DrawCalls = 0;
|
||||||
ClearLights();
|
ClearLights();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::End()
|
void Renderer::End()
|
||||||
{
|
{
|
||||||
@ -128,12 +148,16 @@ void Renderer::End()
|
|||||||
|
|
||||||
void Renderer::ClearLights()
|
void Renderer::ClearLights()
|
||||||
{
|
{
|
||||||
|
PROFILE_ENGINE_SCOPE("Renderer::ClearLights");
|
||||||
|
|
||||||
s_Lights.clear();
|
s_Lights.clear();
|
||||||
s_LightsCount = 0;
|
s_LightsCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::AddLight(const glm::vec2 &screenPos, const glm::vec3 &color, float intensity, float radius)
|
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)
|
if (s_Lights.size() >= g_engineConfig.gl_maxLight)
|
||||||
return;
|
return;
|
||||||
s_Lights.push_back({screenPos, color, intensity, radius});
|
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)
|
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())
|
if (!tilemap || tilemap->GetAtlasPath().empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -209,26 +235,32 @@ void Renderer::DrawSprite(SpriteComponent *sprite, const glm::vec2 &pos, float z
|
|||||||
|
|
||||||
Shader *shader = &unlitShader;
|
Shader *shader = &unlitShader;
|
||||||
bool useLighting = false;
|
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;
|
shader = &spriteShader;
|
||||||
useLighting = true;
|
useLighting = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
shader->Use();
|
shader->Use();
|
||||||
|
|
||||||
glm::vec2 size = sprite->GetSize();
|
glm::vec2 size = sprite->GetSize();
|
||||||
glm::vec2 screenPos = (pos - CameraPos) * zoom + glm::vec2(width, height) * 0.5f - (size * zoom * 0.5f);
|
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("uPos", screenPos);
|
||||||
shader->SetVec2("uSize", size * zoom);
|
shader->SetVec2("uSize", size * zoom);
|
||||||
shader->SetVec2("uScreen", glm::vec2(width, height));
|
shader->SetVec2("uScreen", glm::vec2(width, height));
|
||||||
|
shader->SetFloat("uRotation", glm::radians(rotationDeg));
|
||||||
shader->SetInt("uTex", 0);
|
shader->SetInt("uTex", 0);
|
||||||
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, sprite->GetTextureID());
|
glBindTexture(GL_TEXTURE_2D, sprite->GetTextureID());
|
||||||
|
|
||||||
if (useLighting)
|
if (useLighting)
|
||||||
{
|
{
|
||||||
|
s_ColorCorrection->Upload(*shader);
|
||||||
|
|
||||||
shader->SetInt("uLightCount", static_cast<int>(s_Lights.size()));
|
shader->SetInt("uLightCount", static_cast<int>(s_Lights.size()));
|
||||||
for (size_t i = 0; i < s_Lights.size(); ++i)
|
for (size_t i = 0; i < s_Lights.size(); ++i)
|
||||||
{
|
{
|
||||||
@ -370,3 +402,11 @@ glm::ivec2 Renderer::GetSize()
|
|||||||
{
|
{
|
||||||
return {width, height};
|
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/TilemapComponent.h"
|
||||||
#include "Components/SpriteComponent.h"
|
#include "Components/SpriteComponent.h"
|
||||||
#include "utils/EngineConfig.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::vec2 screenPos;
|
||||||
glm::vec3 color;
|
glm::vec3 color;
|
||||||
float intensity;
|
float intensity;
|
||||||
float radius;
|
float radius;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Renderer {
|
class Renderer
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
static void Init();
|
static void Init();
|
||||||
static void Resize(int w, int h);
|
static void Resize(int w, int h);
|
||||||
@ -29,40 +48,19 @@ public:
|
|||||||
|
|
||||||
static void DrawEditorGrid(const glm::vec2 &cameraPos, float zoom);
|
static void DrawEditorGrid(const glm::vec2 &cameraPos, float zoom);
|
||||||
|
|
||||||
// —— New gizmo functions ——
|
static void DrawGizmoLine(const glm::vec2 &worldStart, const glm::vec2 &worldEnd, const glm::vec3 &color, const glm::vec2 &cameraPos, float zoom);
|
||||||
// Draws a colored line between two world‑space points.
|
static void DrawGizmoRect(const glm::vec2 &worldPos, const glm::vec2 &size, const glm::vec3 &color, const glm::vec2 &cameraPos, float zoom);
|
||||||
static void DrawGizmoLine(
|
static void DrawGizmoCircle(const glm::vec2 &worldCenter, float radius, int segments, const glm::vec3 &color, const glm::vec2 &cameraPos, float zoom);
|
||||||
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 GLuint GetRenderTexture();
|
static GLuint GetRenderTexture();
|
||||||
static glm::ivec2 GetSize();
|
static glm::ivec2 GetSize();
|
||||||
static int GetDrawCallCount();
|
static int GetDrawCallCount();
|
||||||
static int GetLightsCount();
|
static int GetLightsCount();
|
||||||
|
|
||||||
|
static void SetColorCorrection(std::unique_ptr<ColorCorrection> correction);
|
||||||
|
|
||||||
|
static ColorCorrection *GetColorCorrection();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::vector<Light> s_Lights;
|
static std::vector<Light> s_Lights;
|
||||||
static GLuint fbo, textureColorBuffer, rbo;
|
static GLuint fbo, textureColorBuffer, rbo;
|
||||||
@ -74,4 +72,6 @@ private:
|
|||||||
static GLuint shader, quadVAO, quadVBO;
|
static GLuint shader, quadVAO, quadVBO;
|
||||||
static void InitQuad();
|
static void InitQuad();
|
||||||
static GLuint LoadShader(const char *vertexSrc, const char *fragmentSrc);
|
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 "EngineConfig.h"
|
||||||
|
#include <yaml-cpp/yaml.h>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <shlobj.h> // SHGetFolderPathA
|
||||||
|
|
||||||
|
#include "Logging.h"
|
||||||
|
|
||||||
EngineConfig g_engineConfig{
|
EngineConfig g_engineConfig{
|
||||||
.lighting_enabled = true,
|
|
||||||
.version = "0.1.0",
|
.version = "0.1.0",
|
||||||
.gl_version = "430",
|
.gl_version = "430",
|
||||||
.gl_maxLight = 512,
|
.gl_maxLight = 512,
|
||||||
.settings{
|
.settings = {
|
||||||
.draw_gizmos = true,
|
.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 {
|
struct UserSettings {
|
||||||
bool draw_gizmos;
|
bool draw_gizmos;
|
||||||
|
bool profile_editor;
|
||||||
|
bool profile_enabled;
|
||||||
|
bool show_color_correction_window;
|
||||||
|
bool lighting_enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EngineConfig {
|
struct EngineConfig {
|
||||||
bool lighting_enabled;
|
|
||||||
std::string version;
|
std::string version;
|
||||||
std::string gl_version;
|
std::string gl_version;
|
||||||
int gl_maxLight;
|
int gl_maxLight;
|
||||||
|
|
||||||
UserSettings settings;
|
UserSettings settings;
|
||||||
|
|
||||||
|
void SaveToFile();
|
||||||
|
void LoadFromFile();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern EngineConfig g_engineConfig;
|
extern EngineConfig g_engineConfig;
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#include "../utils/Logging.h"
|
#include "../utils/Logging.h"
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Object>> objects;
|
std::vector<std::shared_ptr<Object>> objects;
|
||||||
|
std::string savedStateYAML;
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<Object> FindByTagRecursive(const std::shared_ptr<Object>& obj, const std::string& tag) {
|
std::shared_ptr<Object> FindByTagRecursive(const std::shared_ptr<Object>& obj, const std::string& tag) {
|
||||||
if (obj->GetName() == tag)
|
if (obj->GetName() == tag)
|
||||||
|
@ -5,4 +5,6 @@
|
|||||||
#include "../Entitys/Object.h"
|
#include "../Entitys/Object.h"
|
||||||
|
|
||||||
extern std::vector<std::shared_ptr<Object>> objects;
|
extern std::vector<std::shared_ptr<Object>> objects;
|
||||||
|
extern std::string savedStateYAML;
|
||||||
|
|
||||||
std::shared_ptr<Object> FindByTagRecursive(const std::shared_ptr<Object>& obj, const std::string& tag);
|
std::shared_ptr<Object> FindByTagRecursive(const std::shared_ptr<Object>& obj, const std::string& tag);
|
||||||
|
@ -67,7 +67,7 @@ void Logger::LogVA(Level level, const char *fmt, va_list args)
|
|||||||
|
|
||||||
std::cout << GetAnsiColor(level)
|
std::cout << GetAnsiColor(level)
|
||||||
<< "[Logger][" << ToString(level) << "] "
|
<< "[Logger][" << ToString(level) << "] "
|
||||||
<< buffer << "\033[0m" << std::endl;
|
<< buffer << "\033[0m" << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::LogInfo(const char *fmt, ...)
|
void Logger::LogInfo(const char *fmt, ...)
|
||||||
|
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