SP3-16 Slight rework to SHColour for compatibility #159
|
@ -0,0 +1,5 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*.{c,cpp,h,hpp}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
|
@ -1,3 +1,3 @@
|
||||||
Name: Cube.003
|
Name: Cube.003
|
||||||
ID: 110152941
|
ID: 71245919
|
||||||
Type: 6
|
Type: 4
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
Name: Cube.012
|
Name: Cube.012
|
||||||
ID: 107348815
|
ID: 80365422
|
||||||
Type: 6
|
Type: 4
|
||||||
|
|
|
@ -4,13 +4,13 @@ Size=1920,20
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][SHEditorMenuBar]
|
[Window][SHEditorMenuBar]
|
||||||
Pos=0,24
|
Pos=0,48
|
||||||
Size=1920,1036
|
Size=1920,1012
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Hierarchy Panel]
|
[Window][Hierarchy Panel]
|
||||||
Pos=0,120
|
Pos=0,197
|
||||||
Size=225,940
|
Size=308,863
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000004,0
|
DockId=0x00000004,0
|
||||||
|
|
||||||
|
@ -20,29 +20,96 @@ Size=400,400
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Inspector]
|
[Window][Inspector]
|
||||||
Pos=1686,24
|
Pos=1528,48
|
||||||
Size=234,1036
|
Size=392,1012
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,0
|
DockId=0x00000006,0
|
||||||
|
|
||||||
[Window][Profiler]
|
[Window][Profiler]
|
||||||
Pos=0,24
|
Pos=0,48
|
||||||
Size=225,94
|
Size=308,147
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000003,0
|
DockId=0x00000003,0
|
||||||
|
|
||||||
[Window][Viewport]
|
[Window][Viewport]
|
||||||
Pos=227,24
|
Pos=227,48
|
||||||
Size=1457,1036
|
Size=1457,1012
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000002,0
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
|
[Window][ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌð‡Žoû]
|
||||||
|
Pos=60,60
|
||||||
|
Size=32,64
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ]
|
||||||
|
Pos=60,60
|
||||||
|
Size=999,581
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][ð‡–oû]
|
||||||
|
Pos=60,60
|
||||||
|
Size=32,64
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][ÌÌÌÌ]
|
||||||
|
Pos=60,60
|
||||||
|
Size=553,422
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][]
|
||||||
|
Pos=60,60
|
||||||
|
Size=770,394
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][ Viewport]
|
||||||
|
Pos=227,48
|
||||||
|
Size=1457,1012
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
|
[Window][ Viewport]
|
||||||
|
Pos=227,48
|
||||||
|
Size=1457,1012
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
|
[Window][î<>‹ Viewport]
|
||||||
|
Pos=310,48
|
||||||
|
Size=1216,715
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
|
[Window][V]
|
||||||
|
Pos=310,722
|
||||||
|
Size=1501,338
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000008,0
|
||||||
|
|
||||||
|
[Window][p›£€Ê]
|
||||||
|
Pos=310,750
|
||||||
|
Size=1501,310
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000A,0
|
||||||
|
|
||||||
|
[Window][ Asset Browser]
|
||||||
|
Pos=310,765
|
||||||
|
Size=1216,295
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000C,0
|
||||||
|
|
||||||
[Docking][Data]
|
[Docking][Data]
|
||||||
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,55 Size=1920,1036 Split=X
|
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X
|
||||||
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1684,1036 Split=X
|
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1526,1036 Split=X
|
||||||
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=225,1036 Split=Y Selected=0x1E6EB881
|
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=308,1036 Split=Y Selected=0x1E6EB881
|
||||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
|
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,147 Selected=0x1E6EB881
|
||||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE
|
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,863 Selected=0xE096E5AE
|
||||||
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1293,1036 CentralNode=1 Selected=0x13926F0B
|
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1216,1036 Split=Y Selected=0xB41284E7
|
||||||
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=234,1036 Selected=0xE7039252
|
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=1501,672 Split=Y Selected=0xB41284E7
|
||||||
|
DockNode ID=0x00000009 Parent=0x00000007 SizeRef=1501,700 Split=Y Selected=0xB41284E7
|
||||||
|
DockNode ID=0x0000000B Parent=0x00000009 SizeRef=1501,715 CentralNode=1 Selected=0xB41284E7
|
||||||
|
DockNode ID=0x0000000C Parent=0x00000009 SizeRef=1501,295 Selected=0xB128252A
|
||||||
|
DockNode ID=0x0000000A Parent=0x00000007 SizeRef=1501,310 Selected=0xD446F7B6
|
||||||
|
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1501,338 Selected=0xD9F31532
|
||||||
|
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=392,1036 Selected=0xE7039252
|
||||||
|
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
[Window][MainStatusBar]
|
|
||||||
Pos=0,1060
|
|
||||||
Size=1920,20
|
|
||||||
Collapsed=0
|
|
||||||
|
|
||||||
[Window][SHEditorMenuBar]
|
|
||||||
Pos=0,48
|
|
||||||
Size=1920,1012
|
|
||||||
Collapsed=0
|
|
||||||
|
|
||||||
[Window][Hierarchy Panel]
|
|
||||||
Pos=0,142
|
|
||||||
Size=387,918
|
|
||||||
Collapsed=0
|
|
||||||
DockId=0x00000004,0
|
|
||||||
|
|
||||||
[Window][Debug##Default]
|
|
||||||
Pos=60,60
|
|
||||||
Size=400,400
|
|
||||||
Collapsed=0
|
|
||||||
|
|
||||||
[Window][Inspector]
|
|
||||||
Pos=1649,48
|
|
||||||
Size=271,1012
|
|
||||||
Collapsed=0
|
|
||||||
DockId=0x00000006,0
|
|
||||||
|
|
||||||
[Window][Profiler]
|
|
||||||
Pos=0,48
|
|
||||||
Size=387,92
|
|
||||||
Collapsed=0
|
|
||||||
DockId=0x00000003,0
|
|
||||||
|
|
||||||
[Window][Viewport]
|
|
||||||
Pos=648,48
|
|
||||||
Size=2519,1319
|
|
||||||
Collapsed=0
|
|
||||||
DockId=0x00000002,0
|
|
||||||
|
|
||||||
[Window][ Viewport]
|
|
||||||
Pos=389,48
|
|
||||||
Size=1258,1012
|
|
||||||
Collapsed=0
|
|
||||||
DockId=0x00000002,0
|
|
||||||
|
|
||||||
[Docking][Data]
|
|
||||||
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X
|
|
||||||
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X
|
|
||||||
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=387,1036 Split=Y Selected=0x1E6EB881
|
|
||||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
|
|
||||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE
|
|
||||||
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1258,1036 CentralNode=1 Selected=0xB41284E7
|
|
||||||
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252
|
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
||||||
|
Name: RaccoonBag_Color_Ver4
|
||||||
|
ID: 58303057
|
||||||
|
Type: 3
|
|
@ -1,3 +1,3 @@
|
||||||
Name: RaccoonPreTexturedVer1_Base9
|
Name: RaccoonPreTexturedVer1_Base9
|
||||||
ID: 91918845
|
ID: 64651793
|
||||||
Type: 4
|
Type: 3
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
||||||
|
Name: Kirsch_CS
|
||||||
|
ID: 19931255
|
||||||
|
Type: 2
|
|
@ -0,0 +1,67 @@
|
||||||
|
//#version 450
|
||||||
|
//
|
||||||
|
//layout(local_size_x = 16, local_size_y = 16) in;
|
||||||
|
//layout(set = 4, binding = 0, rgba8) uniform image2D targetImage;
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//void main()
|
||||||
|
//{
|
||||||
|
// ivec2 imageSize = imageSize (targetImage);
|
||||||
|
//
|
||||||
|
// if (gl_GlobalInvocationID.x >= imageSize.x && gl_GlobalInvocationID.y >= imageSize.y)
|
||||||
|
// return;
|
||||||
|
//
|
||||||
|
// // load the image
|
||||||
|
// vec4 color = imageLoad (targetImage, ivec2 (gl_GlobalInvocationID));
|
||||||
|
//
|
||||||
|
// // get the average
|
||||||
|
// float average = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
|
||||||
|
//
|
||||||
|
// // store result into result image
|
||||||
|
// imageStore(targetImage, ivec2(gl_GlobalInvocationID), vec4(average, average, average, 1.0f));
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
/* Start Header *****************************************************************/
|
||||||
|
|
||||||
|
/*! \file (e.g. kirsch.comp)
|
||||||
|
|
||||||
|
\author William Zheng, william.zheng, 60001906. Brandon Mak, brandon.hao 390003920.
|
||||||
|
|
||||||
|
\par william.zheng\@digipen.edu. brandon.hao\@digipen.edu.
|
||||||
|
|
||||||
|
\date Sept 20, 2022
|
||||||
|
|
||||||
|
\brief Copyright (C) 20xx DigiPen Institute of Technology.
|
||||||
|
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited. */
|
||||||
|
|
||||||
|
/* End Header *******************************************************************/
|
||||||
|
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
|
||||||
|
layout(local_size_x = 16, local_size_y = 16) in;
|
||||||
|
layout(set = 4, binding = 0, rgba8) uniform image2D inputImage;
|
||||||
|
layout(set = 4, binding = 1, rgba8) uniform image2D targetImage;
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// convenient variables
|
||||||
|
ivec2 globalThread = ivec2(gl_GlobalInvocationID);
|
||||||
|
|
||||||
|
vec3 color = imageLoad (inputImage, globalThread).rgb;
|
||||||
|
|
||||||
|
// store result into result image
|
||||||
|
imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(color, 1.0f));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
||||||
|
Name: PureCopy_CS
|
||||||
|
ID: 29659779
|
||||||
|
Type: 2
|
|
@ -23,6 +23,7 @@ layout(location = 2) flat in struct
|
||||||
{
|
{
|
||||||
int materialIndex;
|
int materialIndex;
|
||||||
uint eid;
|
uint eid;
|
||||||
|
uint lightLayerIndex;
|
||||||
} In2;
|
} In2;
|
||||||
|
|
||||||
//layout (set = 0, binding = )
|
//layout (set = 0, binding = )
|
||||||
|
@ -35,6 +36,7 @@ layout (set = 3, binding = 0) buffer MaterialProperties // For materials
|
||||||
|
|
||||||
layout(location = 0) out vec4 outColor;
|
layout(location = 0) out vec4 outColor;
|
||||||
layout(location = 1) out uint outEntityID;
|
layout(location = 1) out uint outEntityID;
|
||||||
|
layout(location = 2) out uint lightLayerIndices;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
@ -42,5 +44,6 @@ void main()
|
||||||
MatProp.data[In2.materialIndex].color / MatProp.data[In2.materialIndex].alpha;
|
MatProp.data[In2.materialIndex].color / MatProp.data[In2.materialIndex].alpha;
|
||||||
|
|
||||||
outEntityID = In2.eid;
|
outEntityID = In2.eid;
|
||||||
|
lightLayerIndices = In2.lightLayerIndex;
|
||||||
//outColor = vec4 (1.0f);
|
//outColor = vec4 (1.0f);
|
||||||
}
|
}
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
||||||
|
Name: TestCube_FS
|
||||||
|
ID: 18415057
|
||||||
|
Type: 2
|
|
@ -3,12 +3,13 @@
|
||||||
|
|
||||||
//#include "ShaderDescriptorDefinitions.glsl"
|
//#include "ShaderDescriptorDefinitions.glsl"
|
||||||
|
|
||||||
|
|
||||||
layout(location = 0) in vec3 aVertexPos;
|
layout(location = 0) in vec3 aVertexPos;
|
||||||
layout(location = 1) in vec2 aUV;
|
layout(location = 1) in vec2 aUV;
|
||||||
layout(location = 2) in vec3 aNormal;
|
layout(location = 2) in vec3 aNormal;
|
||||||
layout(location = 3) in vec3 aTangent;
|
layout(location = 3) in vec3 aTangent;
|
||||||
layout(location = 4) in mat4 worldTransform;
|
layout(location = 4) in mat4 worldTransform;
|
||||||
layout(location = 8) in uint eid;
|
layout(location = 8) in uvec2 integerData;
|
||||||
|
|
||||||
|
|
||||||
layout(location = 0) out struct
|
layout(location = 0) out struct
|
||||||
|
@ -23,6 +24,7 @@ layout(location = 2) out struct
|
||||||
{
|
{
|
||||||
int materialIndex;
|
int materialIndex;
|
||||||
uint eid;
|
uint eid;
|
||||||
|
uint lightLayerIndex;
|
||||||
|
|
||||||
} Out2;
|
} Out2;
|
||||||
|
|
||||||
|
@ -36,7 +38,8 @@ void main()
|
||||||
{
|
{
|
||||||
Out.uv = aUV;
|
Out.uv = aUV;
|
||||||
Out2.materialIndex = gl_InstanceIndex;
|
Out2.materialIndex = gl_InstanceIndex;
|
||||||
Out2.eid = eid;
|
Out2.eid = integerData[0];
|
||||||
|
Out2.lightLayerIndex = integerData[1];
|
||||||
gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f);
|
gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f);
|
||||||
Out.vertColor = vec4 (aVertexPos, 1.0f);
|
Out.vertColor = vec4 (aVertexPos, 1.0f);
|
||||||
}
|
}
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
||||||
|
Name: TestCube_VS
|
||||||
|
ID: 29315909
|
||||||
|
Type: 2
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
||||||
|
Name: TD_Checker_Base_Color
|
||||||
|
ID: 51995224
|
||||||
|
Type: 3
|
|
@ -56,8 +56,8 @@ namespace Sandbox
|
||||||
_In_ INT nCmdShow
|
_In_ INT nCmdShow
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Set working directory
|
// Set working directory
|
||||||
SHFileUtilities::SetWorkDirToExecDir();
|
SHFileUtilities::SetWorkDirToExecDir();
|
||||||
|
|
||||||
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
|
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
|
||||||
|
|
||||||
|
@ -110,14 +110,7 @@ namespace Sandbox
|
||||||
SHComponentManager::CreateComponentSparseSet<SHRenderable>();
|
SHComponentManager::CreateComponentSparseSet<SHRenderable>();
|
||||||
SHComponentManager::CreateComponentSparseSet<SHCameraComponent>();
|
SHComponentManager::CreateComponentSparseSet<SHCameraComponent>();
|
||||||
|
|
||||||
//TODO: REMOVE AFTER PRESENTATION
|
SHAssetManager::Load();
|
||||||
//SHAssetManager::LoadDataTemp("../../Assets/racoon.gltf");
|
|
||||||
//SHAssetManager::LoadDataTemp("../../Assets/Cube.012.shmesh");
|
|
||||||
//SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds");
|
|
||||||
//SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds");
|
|
||||||
//SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.shtex");
|
|
||||||
//TODO: REMOVE AFTER PRESENTATION
|
|
||||||
|
|
||||||
|
|
||||||
auto id = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
|
auto id = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
|
||||||
auto id2 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
|
auto id2 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
|
||||||
|
@ -133,8 +126,6 @@ namespace Sandbox
|
||||||
SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
|
SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
|
||||||
|
|
||||||
SHFrameRateController::UpdateFRC();
|
SHFrameRateController::UpdateFRC();
|
||||||
|
|
||||||
SHAssetManager::Load();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SBApplication::Update(void)
|
void SBApplication::Update(void)
|
||||||
|
@ -152,16 +143,16 @@ namespace Sandbox
|
||||||
SHSceneManager::SceneUpdate(0.016f);
|
SHSceneManager::SceneUpdate(0.016f);
|
||||||
#endif
|
#endif
|
||||||
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
|
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
|
||||||
//editor->PollPicking();
|
editor->PollPicking();
|
||||||
}
|
}
|
||||||
// Finish all graphics jobs first
|
// Finish all graphics jobs first
|
||||||
graphicsSystem->AwaitGraphicsExecution();
|
graphicsSystem->AwaitGraphicsExecution();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SBApplication::Exit(void)
|
void SBApplication::Exit(void)
|
||||||
{
|
{
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
SDL_DestroyWindow(sdlWindow);
|
SDL_DestroyWindow(sdlWindow);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
#include "Physics/Components/SHRigidBodyComponent.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Components/SHColliderComponent.h"
|
||||||
|
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||||
|
|
||||||
#include "Assets/SHAssetManager.h"
|
#include "Assets/SHAssetManager.h"
|
||||||
#include "Camera/SHCameraComponent.h"
|
#include "Camera/SHCameraComponent.h"
|
||||||
|
@ -52,7 +53,8 @@ namespace Sandbox
|
||||||
if (asset.name == "Cube.012")
|
if (asset.name == "Cube.012")
|
||||||
handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id));
|
handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id));
|
||||||
break;
|
break;
|
||||||
case AssetType::IMAGE:
|
case AssetType::TEXTURE:
|
||||||
|
if (asset.name == "RaccoonPreTexturedVer1_Base9")
|
||||||
texHandles.emplace_back(SHResourceManager::LoadOrGet<SHTexture>(asset.id));
|
texHandles.emplace_back(SHResourceManager::LoadOrGet<SHTexture>(asset.id));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -82,7 +84,7 @@ namespace Sandbox
|
||||||
auto& collider = *SHComponentManager::GetComponent_s<SHColliderComponent>(entity);
|
auto& collider = *SHComponentManager::GetComponent_s<SHColliderComponent>(entity);
|
||||||
|
|
||||||
//renderable.Mesh = handles.front();
|
//renderable.Mesh = handles.front();
|
||||||
renderable.Mesh = CUBE_MESH;
|
renderable.SetMesh(CUBE_MESH);
|
||||||
renderable.SetMaterial(customMat);
|
renderable.SetMaterial(customMat);
|
||||||
|
|
||||||
if (y == 50)
|
if (y == 50)
|
||||||
|
@ -94,11 +96,7 @@ namespace Sandbox
|
||||||
transform.SetWorldRotation(SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f));
|
transform.SetWorldRotation(SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f));
|
||||||
transform.SetWorldScale(TEST_OBJ_SCALE);
|
transform.SetWorldScale(TEST_OBJ_SCALE);
|
||||||
|
|
||||||
//if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN)
|
collider.AddBoundingBox(SHVec3::One, SHVec3::Zero);
|
||||||
collider.AddBoundingBox(SHVec3::One * 0.5f, SHVec3::Zero);
|
|
||||||
//else
|
|
||||||
// collider.AddBoundingSphere(0.5f, SHVec3::Zero);
|
|
||||||
|
|
||||||
stressTestObjects.emplace_back(entity);
|
stressTestObjects.emplace_back(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +104,7 @@ namespace Sandbox
|
||||||
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonSpin);
|
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonSpin);
|
||||||
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonSpin);
|
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonSpin);
|
||||||
|
|
||||||
renderable.Mesh = handles.front();
|
renderable.SetMesh(handles.front());
|
||||||
renderable.SetMaterial(customMat);
|
renderable.SetMaterial(customMat);
|
||||||
renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||||
renderable.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
|
renderable.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
|
||||||
|
@ -121,9 +119,8 @@ namespace Sandbox
|
||||||
auto& floorRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(floor);
|
auto& floorRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(floor);
|
||||||
auto& floorCollider = *SHComponentManager::GetComponent_s<SHColliderComponent>(floor);
|
auto& floorCollider = *SHComponentManager::GetComponent_s<SHColliderComponent>(floor);
|
||||||
|
|
||||||
floorRenderable.Mesh = CUBE_MESH;
|
floorRenderable.SetMesh(CUBE_MESH);
|
||||||
floorRenderable.SetMaterial(customMat);
|
floorRenderable.SetMaterial(graphicsSystem->GetDefaultMaterialInstance());
|
||||||
floorRenderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
|
||||||
|
|
||||||
floorTransform.SetWorldScale({ 7.5f, 0.5f, 7.5 });
|
floorTransform.SetWorldScale({ 7.5f, 0.5f, 7.5 });
|
||||||
floorTransform.SetWorldPosition({ 0.0f, -3.0f, -5.0f });
|
floorTransform.SetWorldPosition({ 0.0f, -3.0f, -5.0f });
|
||||||
|
@ -147,7 +144,7 @@ namespace Sandbox
|
||||||
auto& renderableShowcase = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonShowcase);
|
auto& renderableShowcase = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonShowcase);
|
||||||
auto& transformShowcase = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonShowcase);
|
auto& transformShowcase = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonShowcase);
|
||||||
|
|
||||||
renderableShowcase.Mesh = handles.front();
|
renderableShowcase.SetMesh(handles.front());
|
||||||
renderableShowcase.SetMaterial(customMat);
|
renderableShowcase.SetMaterial(customMat);
|
||||||
renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||||
renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
|
renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
|
||||||
|
@ -158,6 +155,7 @@ namespace Sandbox
|
||||||
scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase");
|
scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase");
|
||||||
|
|
||||||
SHComponentManager::AddComponent<SHCameraComponent>(0);
|
SHComponentManager::AddComponent<SHCameraComponent>(0);
|
||||||
|
SHComponentManager::AddComponent<SHLightComponent>(0);
|
||||||
SHComponentManager::RemoveComponent <SHRigidBodyComponent>(0);
|
SHComponentManager::RemoveComponent <SHRigidBodyComponent>(0);
|
||||||
SHComponentManager::RemoveComponent <SHColliderComponent>(0);
|
SHComponentManager::RemoveComponent <SHColliderComponent>(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
project "SHADE_CSharp"
|
||||||
|
architecture "x64"
|
||||||
|
kind "SharedLib"
|
||||||
|
language "C#"
|
||||||
|
clr "NetCore"
|
||||||
|
dotnetframework "net5.0"
|
||||||
|
namespace ("SHADE")
|
||||||
|
targetdir (outputdir)
|
||||||
|
objdir (interdir)
|
||||||
|
systemversion "latest"
|
||||||
|
|
||||||
|
files
|
||||||
|
{
|
||||||
|
"%{prj.location}/src/**.cs",
|
||||||
|
"%{prj.location}/src/**.tt"
|
||||||
|
}
|
||||||
|
|
||||||
|
flags
|
||||||
|
{
|
||||||
|
"MultiProcessorCompile"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependson
|
||||||
|
{
|
||||||
|
"SHADE_Engine"
|
||||||
|
}
|
||||||
|
|
||||||
|
warnings 'Extra'
|
||||||
|
|
||||||
|
filter "configurations:Debug"
|
||||||
|
symbols "On"
|
||||||
|
defines {"_DEBUG"}
|
||||||
|
|
||||||
|
filter "configurations:Release"
|
||||||
|
optimize "On"
|
||||||
|
defines{"_RELEASE"}
|
||||||
|
|
||||||
|
filter "configurations:Publish"
|
||||||
|
optimize "On"
|
||||||
|
defines{"_RELEASE"}
|
||||||
|
|
||||||
|
require "vstudio"
|
||||||
|
|
||||||
|
function platformsElement(cfg)
|
||||||
|
_p(2,'<Platforms>x64</Platforms>')
|
||||||
|
end
|
||||||
|
|
||||||
|
premake.override(premake.vstudio.cs2005.elements, "projectProperties", function (oldfn, cfg)
|
||||||
|
return table.join(oldfn(cfg), {
|
||||||
|
platformsElement,
|
||||||
|
})
|
||||||
|
end)
|
|
@ -0,0 +1,852 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file CallbackAction.cs
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 23, 2022
|
||||||
|
\brief Contains the definition of CallbackAction and related classes.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for a CallbackAction that all variants inherit from.
|
||||||
|
/// </summary>
|
||||||
|
public interface ICallbackAction
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not this CallbackAction is runtime assigned. If it is, then the
|
||||||
|
/// TargetMethodName and TargetObject properties are invalid.
|
||||||
|
/// </summary>
|
||||||
|
bool IsRuntimeAction { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the method that this CallbackAction is using.
|
||||||
|
/// </summary>
|
||||||
|
string TargetMethodName { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Object which the specified target method is called on.
|
||||||
|
/// </summary>
|
||||||
|
Object TargetObject { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a function call that can be serialised and put togetheer with scripts.
|
||||||
|
/// This variant accepts functions with 1 parameter.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackAction<T1> : ICallbackAction
|
||||||
|
{
|
||||||
|
#region Properties ------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public Object TargetObject { get; private set; }
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string TargetMethodName => targetMethod == null ? "" : targetMethod.Name;
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool IsRuntimeAction => targetAction != null;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private MethodInfo targetMethod;
|
||||||
|
private Action<T1> targetAction;
|
||||||
|
private Object[] parameters;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors ------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs an empty Callback action.
|
||||||
|
/// </summary>
|
||||||
|
public CallbackAction() {}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a CallbackAction that represents a call to the specified method on the
|
||||||
|
/// specified target.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
/// <exception cref="ArgumentException">
|
||||||
|
/// Thrown if a method that is not compatible with the target is specified. The method's
|
||||||
|
/// source type must match the target's type.
|
||||||
|
/// </exception>
|
||||||
|
public CallbackAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
// Error Checks
|
||||||
|
if (method.DeclaringType != target.GetType())
|
||||||
|
throw new ArgumentException("[CallbackAction] Attempted register an action using an incompatible target object and method.");
|
||||||
|
|
||||||
|
// No errors, assign
|
||||||
|
TargetObject = target;
|
||||||
|
targetMethod = method;
|
||||||
|
|
||||||
|
// Create storage for parameters for calling
|
||||||
|
parameters = new Object[1];
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a Callback action based on an action.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
public CallbackAction(Action<T1> action)
|
||||||
|
{
|
||||||
|
targetAction = action;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the CallbackAction's stored method/action with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1)
|
||||||
|
{
|
||||||
|
if (targetAction != null)
|
||||||
|
{
|
||||||
|
targetAction.Invoke(t1);
|
||||||
|
}
|
||||||
|
else if (TargetObject != null && targetMethod != null)
|
||||||
|
{
|
||||||
|
parameters[0] = t1;
|
||||||
|
_ = targetMethod.Invoke(TargetObject, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a function call that can be serialised and put togetheer with scripts.
|
||||||
|
/// This variant accepts functions with 2 parameters.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackAction<T1, T2> : ICallbackAction
|
||||||
|
{
|
||||||
|
#region Properties ------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public Object TargetObject { get; private set; }
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string TargetMethodName => targetMethod == null ? "" : targetMethod.Name;
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool IsRuntimeAction => targetAction != null;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private MethodInfo targetMethod;
|
||||||
|
private Action<T1, T2> targetAction;
|
||||||
|
private Object[] parameters;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors ------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs an empty Callback action.
|
||||||
|
/// </summary>
|
||||||
|
public CallbackAction() {}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a CallbackAction that represents a call to the specified method on the
|
||||||
|
/// specified target.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
/// <exception cref="ArgumentException">
|
||||||
|
/// Thrown if a method that is not compatible with the target is specified. The method's
|
||||||
|
/// source type must match the target's type.
|
||||||
|
/// </exception>
|
||||||
|
public CallbackAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
// Error Checks
|
||||||
|
if (method.DeclaringType != target.GetType())
|
||||||
|
throw new ArgumentException("[CallbackAction] Attempted register an action using an incompatible target object and method.");
|
||||||
|
|
||||||
|
// No errors, assign
|
||||||
|
TargetObject = target;
|
||||||
|
targetMethod = method;
|
||||||
|
|
||||||
|
// Create storage for parameters for calling
|
||||||
|
parameters = new Object[1];
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a Callback action based on an action.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
public CallbackAction(Action<T1, T2> action)
|
||||||
|
{
|
||||||
|
targetAction = action;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the CallbackAction's stored method/action with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2)
|
||||||
|
{
|
||||||
|
if (targetAction != null)
|
||||||
|
{
|
||||||
|
targetAction.Invoke(t1, t2);
|
||||||
|
}
|
||||||
|
else if (TargetObject != null && targetMethod != null)
|
||||||
|
{
|
||||||
|
parameters[0] = t1;
|
||||||
|
parameters[1] = t2;
|
||||||
|
_ = targetMethod.Invoke(TargetObject, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a function call that can be serialised and put togetheer with scripts.
|
||||||
|
/// This variant accepts functions with 3 parameters.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackAction<T1, T2, T3> : ICallbackAction
|
||||||
|
{
|
||||||
|
#region Properties ------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public Object TargetObject { get; private set; }
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string TargetMethodName => targetMethod == null ? "" : targetMethod.Name;
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool IsRuntimeAction => targetAction != null;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private MethodInfo targetMethod;
|
||||||
|
private Action<T1, T2, T3> targetAction;
|
||||||
|
private Object[] parameters;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors ------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs an empty Callback action.
|
||||||
|
/// </summary>
|
||||||
|
public CallbackAction() {}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a CallbackAction that represents a call to the specified method on the
|
||||||
|
/// specified target.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
/// <exception cref="ArgumentException">
|
||||||
|
/// Thrown if a method that is not compatible with the target is specified. The method's
|
||||||
|
/// source type must match the target's type.
|
||||||
|
/// </exception>
|
||||||
|
public CallbackAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
// Error Checks
|
||||||
|
if (method.DeclaringType != target.GetType())
|
||||||
|
throw new ArgumentException("[CallbackAction] Attempted register an action using an incompatible target object and method.");
|
||||||
|
|
||||||
|
// No errors, assign
|
||||||
|
TargetObject = target;
|
||||||
|
targetMethod = method;
|
||||||
|
|
||||||
|
// Create storage for parameters for calling
|
||||||
|
parameters = new Object[1];
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a Callback action based on an action.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
public CallbackAction(Action<T1, T2, T3> action)
|
||||||
|
{
|
||||||
|
targetAction = action;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the CallbackAction's stored method/action with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2, T3 t3)
|
||||||
|
{
|
||||||
|
if (targetAction != null)
|
||||||
|
{
|
||||||
|
targetAction.Invoke(t1, t2, t3);
|
||||||
|
}
|
||||||
|
else if (TargetObject != null && targetMethod != null)
|
||||||
|
{
|
||||||
|
parameters[0] = t1;
|
||||||
|
parameters[1] = t2;
|
||||||
|
parameters[2] = t3;
|
||||||
|
_ = targetMethod.Invoke(TargetObject, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a function call that can be serialised and put togetheer with scripts.
|
||||||
|
/// This variant accepts functions with 4 parameters.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackAction<T1, T2, T3, T4> : ICallbackAction
|
||||||
|
{
|
||||||
|
#region Properties ------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public Object TargetObject { get; private set; }
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string TargetMethodName => targetMethod == null ? "" : targetMethod.Name;
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool IsRuntimeAction => targetAction != null;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private MethodInfo targetMethod;
|
||||||
|
private Action<T1, T2, T3, T4> targetAction;
|
||||||
|
private Object[] parameters;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors ------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs an empty Callback action.
|
||||||
|
/// </summary>
|
||||||
|
public CallbackAction() {}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a CallbackAction that represents a call to the specified method on the
|
||||||
|
/// specified target.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
/// <exception cref="ArgumentException">
|
||||||
|
/// Thrown if a method that is not compatible with the target is specified. The method's
|
||||||
|
/// source type must match the target's type.
|
||||||
|
/// </exception>
|
||||||
|
public CallbackAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
// Error Checks
|
||||||
|
if (method.DeclaringType != target.GetType())
|
||||||
|
throw new ArgumentException("[CallbackAction] Attempted register an action using an incompatible target object and method.");
|
||||||
|
|
||||||
|
// No errors, assign
|
||||||
|
TargetObject = target;
|
||||||
|
targetMethod = method;
|
||||||
|
|
||||||
|
// Create storage for parameters for calling
|
||||||
|
parameters = new Object[1];
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a Callback action based on an action.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
public CallbackAction(Action<T1, T2, T3, T4> action)
|
||||||
|
{
|
||||||
|
targetAction = action;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the CallbackAction's stored method/action with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2, T3 t3, T4 t4)
|
||||||
|
{
|
||||||
|
if (targetAction != null)
|
||||||
|
{
|
||||||
|
targetAction.Invoke(t1, t2, t3, t4);
|
||||||
|
}
|
||||||
|
else if (TargetObject != null && targetMethod != null)
|
||||||
|
{
|
||||||
|
parameters[0] = t1;
|
||||||
|
parameters[1] = t2;
|
||||||
|
parameters[2] = t3;
|
||||||
|
parameters[3] = t4;
|
||||||
|
_ = targetMethod.Invoke(TargetObject, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a function call that can be serialised and put togetheer with scripts.
|
||||||
|
/// This variant accepts functions with 5 parameters.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackAction<T1, T2, T3, T4, T5> : ICallbackAction
|
||||||
|
{
|
||||||
|
#region Properties ------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public Object TargetObject { get; private set; }
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string TargetMethodName => targetMethod == null ? "" : targetMethod.Name;
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool IsRuntimeAction => targetAction != null;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private MethodInfo targetMethod;
|
||||||
|
private Action<T1, T2, T3, T4, T5> targetAction;
|
||||||
|
private Object[] parameters;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors ------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs an empty Callback action.
|
||||||
|
/// </summary>
|
||||||
|
public CallbackAction() {}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a CallbackAction that represents a call to the specified method on the
|
||||||
|
/// specified target.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
/// <exception cref="ArgumentException">
|
||||||
|
/// Thrown if a method that is not compatible with the target is specified. The method's
|
||||||
|
/// source type must match the target's type.
|
||||||
|
/// </exception>
|
||||||
|
public CallbackAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
// Error Checks
|
||||||
|
if (method.DeclaringType != target.GetType())
|
||||||
|
throw new ArgumentException("[CallbackAction] Attempted register an action using an incompatible target object and method.");
|
||||||
|
|
||||||
|
// No errors, assign
|
||||||
|
TargetObject = target;
|
||||||
|
targetMethod = method;
|
||||||
|
|
||||||
|
// Create storage for parameters for calling
|
||||||
|
parameters = new Object[1];
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a Callback action based on an action.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
public CallbackAction(Action<T1, T2, T3, T4, T5> action)
|
||||||
|
{
|
||||||
|
targetAction = action;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the CallbackAction's stored method/action with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
|
||||||
|
{
|
||||||
|
if (targetAction != null)
|
||||||
|
{
|
||||||
|
targetAction.Invoke(t1, t2, t3, t4, t5);
|
||||||
|
}
|
||||||
|
else if (TargetObject != null && targetMethod != null)
|
||||||
|
{
|
||||||
|
parameters[0] = t1;
|
||||||
|
parameters[1] = t2;
|
||||||
|
parameters[2] = t3;
|
||||||
|
parameters[3] = t4;
|
||||||
|
parameters[4] = t5;
|
||||||
|
_ = targetMethod.Invoke(TargetObject, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a function call that can be serialised and put togetheer with scripts.
|
||||||
|
/// This variant accepts functions with 6 parameters.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackAction<T1, T2, T3, T4, T5, T6> : ICallbackAction
|
||||||
|
{
|
||||||
|
#region Properties ------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public Object TargetObject { get; private set; }
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string TargetMethodName => targetMethod == null ? "" : targetMethod.Name;
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool IsRuntimeAction => targetAction != null;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private MethodInfo targetMethod;
|
||||||
|
private Action<T1, T2, T3, T4, T5, T6> targetAction;
|
||||||
|
private Object[] parameters;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors ------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs an empty Callback action.
|
||||||
|
/// </summary>
|
||||||
|
public CallbackAction() {}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a CallbackAction that represents a call to the specified method on the
|
||||||
|
/// specified target.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
/// <exception cref="ArgumentException">
|
||||||
|
/// Thrown if a method that is not compatible with the target is specified. The method's
|
||||||
|
/// source type must match the target's type.
|
||||||
|
/// </exception>
|
||||||
|
public CallbackAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
// Error Checks
|
||||||
|
if (method.DeclaringType != target.GetType())
|
||||||
|
throw new ArgumentException("[CallbackAction] Attempted register an action using an incompatible target object and method.");
|
||||||
|
|
||||||
|
// No errors, assign
|
||||||
|
TargetObject = target;
|
||||||
|
targetMethod = method;
|
||||||
|
|
||||||
|
// Create storage for parameters for calling
|
||||||
|
parameters = new Object[1];
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a Callback action based on an action.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
public CallbackAction(Action<T1, T2, T3, T4, T5, T6> action)
|
||||||
|
{
|
||||||
|
targetAction = action;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the CallbackAction's stored method/action with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
|
||||||
|
{
|
||||||
|
if (targetAction != null)
|
||||||
|
{
|
||||||
|
targetAction.Invoke(t1, t2, t3, t4, t5, t6);
|
||||||
|
}
|
||||||
|
else if (TargetObject != null && targetMethod != null)
|
||||||
|
{
|
||||||
|
parameters[0] = t1;
|
||||||
|
parameters[1] = t2;
|
||||||
|
parameters[2] = t3;
|
||||||
|
parameters[3] = t4;
|
||||||
|
parameters[4] = t5;
|
||||||
|
parameters[5] = t6;
|
||||||
|
_ = targetMethod.Invoke(TargetObject, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a function call that can be serialised and put togetheer with scripts.
|
||||||
|
/// This variant accepts functions with 7 parameters.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackAction<T1, T2, T3, T4, T5, T6, T7> : ICallbackAction
|
||||||
|
{
|
||||||
|
#region Properties ------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public Object TargetObject { get; private set; }
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string TargetMethodName => targetMethod == null ? "" : targetMethod.Name;
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool IsRuntimeAction => targetAction != null;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private MethodInfo targetMethod;
|
||||||
|
private Action<T1, T2, T3, T4, T5, T6, T7> targetAction;
|
||||||
|
private Object[] parameters;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors ------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs an empty Callback action.
|
||||||
|
/// </summary>
|
||||||
|
public CallbackAction() {}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a CallbackAction that represents a call to the specified method on the
|
||||||
|
/// specified target.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
/// <exception cref="ArgumentException">
|
||||||
|
/// Thrown if a method that is not compatible with the target is specified. The method's
|
||||||
|
/// source type must match the target's type.
|
||||||
|
/// </exception>
|
||||||
|
public CallbackAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
// Error Checks
|
||||||
|
if (method.DeclaringType != target.GetType())
|
||||||
|
throw new ArgumentException("[CallbackAction] Attempted register an action using an incompatible target object and method.");
|
||||||
|
|
||||||
|
// No errors, assign
|
||||||
|
TargetObject = target;
|
||||||
|
targetMethod = method;
|
||||||
|
|
||||||
|
// Create storage for parameters for calling
|
||||||
|
parameters = new Object[1];
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a Callback action based on an action.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
public CallbackAction(Action<T1, T2, T3, T4, T5, T6, T7> action)
|
||||||
|
{
|
||||||
|
targetAction = action;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the CallbackAction's stored method/action with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
|
||||||
|
{
|
||||||
|
if (targetAction != null)
|
||||||
|
{
|
||||||
|
targetAction.Invoke(t1, t2, t3, t4, t5, t6, t7);
|
||||||
|
}
|
||||||
|
else if (TargetObject != null && targetMethod != null)
|
||||||
|
{
|
||||||
|
parameters[0] = t1;
|
||||||
|
parameters[1] = t2;
|
||||||
|
parameters[2] = t3;
|
||||||
|
parameters[3] = t4;
|
||||||
|
parameters[4] = t5;
|
||||||
|
parameters[5] = t6;
|
||||||
|
parameters[6] = t7;
|
||||||
|
_ = targetMethod.Invoke(TargetObject, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a function call that can be serialised and put togetheer with scripts.
|
||||||
|
/// This variant accepts functions with 8 parameters.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8> : ICallbackAction
|
||||||
|
{
|
||||||
|
#region Properties ------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public Object TargetObject { get; private set; }
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string TargetMethodName => targetMethod == null ? "" : targetMethod.Name;
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool IsRuntimeAction => targetAction != null;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private MethodInfo targetMethod;
|
||||||
|
private Action<T1, T2, T3, T4, T5, T6, T7, T8> targetAction;
|
||||||
|
private Object[] parameters;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors ------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs an empty Callback action.
|
||||||
|
/// </summary>
|
||||||
|
public CallbackAction() {}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a CallbackAction that represents a call to the specified method on the
|
||||||
|
/// specified target.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
/// <exception cref="ArgumentException">
|
||||||
|
/// Thrown if a method that is not compatible with the target is specified. The method's
|
||||||
|
/// source type must match the target's type.
|
||||||
|
/// </exception>
|
||||||
|
public CallbackAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
// Error Checks
|
||||||
|
if (method.DeclaringType != target.GetType())
|
||||||
|
throw new ArgumentException("[CallbackAction] Attempted register an action using an incompatible target object and method.");
|
||||||
|
|
||||||
|
// No errors, assign
|
||||||
|
TargetObject = target;
|
||||||
|
targetMethod = method;
|
||||||
|
|
||||||
|
// Create storage for parameters for calling
|
||||||
|
parameters = new Object[1];
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a Callback action based on an action.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
public CallbackAction(Action<T1, T2, T3, T4, T5, T6, T7, T8> action)
|
||||||
|
{
|
||||||
|
targetAction = action;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the CallbackAction's stored method/action with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
|
||||||
|
{
|
||||||
|
if (targetAction != null)
|
||||||
|
{
|
||||||
|
targetAction.Invoke(t1, t2, t3, t4, t5, t6, t7, t8);
|
||||||
|
}
|
||||||
|
else if (TargetObject != null && targetMethod != null)
|
||||||
|
{
|
||||||
|
parameters[0] = t1;
|
||||||
|
parameters[1] = t2;
|
||||||
|
parameters[2] = t3;
|
||||||
|
parameters[3] = t4;
|
||||||
|
parameters[4] = t5;
|
||||||
|
parameters[5] = t6;
|
||||||
|
parameters[6] = t7;
|
||||||
|
parameters[7] = t8;
|
||||||
|
_ = targetMethod.Invoke(TargetObject, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a function call that can be serialised and put togetheer with scripts.
|
||||||
|
/// This variant accepts functions with 9 parameters.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9> : ICallbackAction
|
||||||
|
{
|
||||||
|
#region Properties ------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public Object TargetObject { get; private set; }
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string TargetMethodName => targetMethod == null ? "" : targetMethod.Name;
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool IsRuntimeAction => targetAction != null;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private MethodInfo targetMethod;
|
||||||
|
private Action<T1, T2, T3, T4, T5, T6, T7, T8, T9> targetAction;
|
||||||
|
private Object[] parameters;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors ------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs an empty Callback action.
|
||||||
|
/// </summary>
|
||||||
|
public CallbackAction() {}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a CallbackAction that represents a call to the specified method on the
|
||||||
|
/// specified target.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
/// <exception cref="ArgumentException">
|
||||||
|
/// Thrown if a method that is not compatible with the target is specified. The method's
|
||||||
|
/// source type must match the target's type.
|
||||||
|
/// </exception>
|
||||||
|
public CallbackAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
// Error Checks
|
||||||
|
if (method.DeclaringType != target.GetType())
|
||||||
|
throw new ArgumentException("[CallbackAction] Attempted register an action using an incompatible target object and method.");
|
||||||
|
|
||||||
|
// No errors, assign
|
||||||
|
TargetObject = target;
|
||||||
|
targetMethod = method;
|
||||||
|
|
||||||
|
// Create storage for parameters for calling
|
||||||
|
parameters = new Object[1];
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a Callback action based on an action.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
public CallbackAction(Action<T1, T2, T3, T4, T5, T6, T7, T8, T9> action)
|
||||||
|
{
|
||||||
|
targetAction = action;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the CallbackAction's stored method/action with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9)
|
||||||
|
{
|
||||||
|
if (targetAction != null)
|
||||||
|
{
|
||||||
|
targetAction.Invoke(t1, t2, t3, t4, t5, t6, t7, t8, t9);
|
||||||
|
}
|
||||||
|
else if (TargetObject != null && targetMethod != null)
|
||||||
|
{
|
||||||
|
parameters[0] = t1;
|
||||||
|
parameters[1] = t2;
|
||||||
|
parameters[2] = t3;
|
||||||
|
parameters[3] = t4;
|
||||||
|
parameters[4] = t5;
|
||||||
|
parameters[5] = t6;
|
||||||
|
parameters[6] = t7;
|
||||||
|
parameters[7] = t8;
|
||||||
|
parameters[8] = t9;
|
||||||
|
_ = targetMethod.Invoke(TargetObject, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a function call that can be serialised and put togetheer with scripts.
|
||||||
|
/// This variant accepts functions with 10 parameters.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : ICallbackAction
|
||||||
|
{
|
||||||
|
#region Properties ------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public Object TargetObject { get; private set; }
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string TargetMethodName => targetMethod == null ? "" : targetMethod.Name;
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool IsRuntimeAction => targetAction != null;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private MethodInfo targetMethod;
|
||||||
|
private Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> targetAction;
|
||||||
|
private Object[] parameters;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors ------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs an empty Callback action.
|
||||||
|
/// </summary>
|
||||||
|
public CallbackAction() {}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a CallbackAction that represents a call to the specified method on the
|
||||||
|
/// specified target.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
/// <exception cref="ArgumentException">
|
||||||
|
/// Thrown if a method that is not compatible with the target is specified. The method's
|
||||||
|
/// source type must match the target's type.
|
||||||
|
/// </exception>
|
||||||
|
public CallbackAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
// Error Checks
|
||||||
|
if (method.DeclaringType != target.GetType())
|
||||||
|
throw new ArgumentException("[CallbackAction] Attempted register an action using an incompatible target object and method.");
|
||||||
|
|
||||||
|
// No errors, assign
|
||||||
|
TargetObject = target;
|
||||||
|
targetMethod = method;
|
||||||
|
|
||||||
|
// Create storage for parameters for calling
|
||||||
|
parameters = new Object[1];
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a Callback action based on an action.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
public CallbackAction(Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> action)
|
||||||
|
{
|
||||||
|
targetAction = action;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the CallbackAction's stored method/action with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10)
|
||||||
|
{
|
||||||
|
if (targetAction != null)
|
||||||
|
{
|
||||||
|
targetAction.Invoke(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10);
|
||||||
|
}
|
||||||
|
else if (TargetObject != null && targetMethod != null)
|
||||||
|
{
|
||||||
|
parameters[0] = t1;
|
||||||
|
parameters[1] = t2;
|
||||||
|
parameters[2] = t3;
|
||||||
|
parameters[3] = t4;
|
||||||
|
parameters[4] = t5;
|
||||||
|
parameters[5] = t6;
|
||||||
|
parameters[6] = t7;
|
||||||
|
parameters[7] = t8;
|
||||||
|
parameters[8] = t9;
|
||||||
|
parameters[9] = t10;
|
||||||
|
_ = targetMethod.Invoke(TargetObject, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,132 @@
|
||||||
|
<#
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file CallbackAction.tt
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 23, 2022
|
||||||
|
\brief Contains the T4 template for the definition of CallbackAction and
|
||||||
|
related classes.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/#>
|
||||||
|
<#@ template hostspecific="false" language="C#" #>
|
||||||
|
<#@ output extension=".cs" #>
|
||||||
|
<# var max = 10; #>
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file CallbackAction.cs
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 23, 2022
|
||||||
|
\brief Contains the definition of CallbackAction and related classes.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for a CallbackAction that all variants inherit from.
|
||||||
|
/// </summary>
|
||||||
|
public interface ICallbackAction
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not this CallbackAction is runtime assigned. If it is, then the
|
||||||
|
/// TargetMethodName and TargetObject properties are invalid.
|
||||||
|
/// </summary>
|
||||||
|
bool IsRuntimeAction { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the method that this CallbackAction is using.
|
||||||
|
/// </summary>
|
||||||
|
string TargetMethodName { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Object which the specified target method is called on.
|
||||||
|
/// </summary>
|
||||||
|
Object TargetObject { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
<# for (int i = 1; i <= max; ++i) { #>
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a function call that can be serialised and put togetheer with scripts.
|
||||||
|
/// This variant accepts functions with <#=i#> parameter<# if (i > 1) {#>s<#} #>.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> : ICallbackAction
|
||||||
|
{
|
||||||
|
#region Properties ------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public Object TargetObject { get; private set; }
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string TargetMethodName => targetMethod == null ? "" : targetMethod.Name;
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool IsRuntimeAction => targetAction != null;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private MethodInfo targetMethod;
|
||||||
|
private Action<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> targetAction;
|
||||||
|
private Object[] parameters;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors ------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs an empty Callback action.
|
||||||
|
/// </summary>
|
||||||
|
public CallbackAction() {}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a CallbackAction that represents a call to the specified method on the
|
||||||
|
/// specified target.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
/// <exception cref="ArgumentException">
|
||||||
|
/// Thrown if a method that is not compatible with the target is specified. The method's
|
||||||
|
/// source type must match the target's type.
|
||||||
|
/// </exception>
|
||||||
|
public CallbackAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
// Error Checks
|
||||||
|
if (method.DeclaringType != target.GetType())
|
||||||
|
throw new ArgumentException("[CallbackAction] Attempted register an action using an incompatible target object and method.");
|
||||||
|
|
||||||
|
// No errors, assign
|
||||||
|
TargetObject = target;
|
||||||
|
targetMethod = method;
|
||||||
|
|
||||||
|
// Create storage for parameters for calling
|
||||||
|
parameters = new Object[1];
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a Callback action based on an action.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
public CallbackAction(Action<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> action)
|
||||||
|
{
|
||||||
|
targetAction = action;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the CallbackAction's stored method/action with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#> t<#=t#><# if (t != i) { #>, <# } #><# } #>)
|
||||||
|
{
|
||||||
|
if (targetAction != null)
|
||||||
|
{
|
||||||
|
targetAction.Invoke(<# for (int t = 1; t < i + 1; ++t) { #>t<#=t#><# if (t != i) { #>, <# } #><# } #>);
|
||||||
|
}
|
||||||
|
else if (TargetObject != null && targetMethod != null)
|
||||||
|
{
|
||||||
|
<# for (int t = 0; t < i; ++t) {#>parameters[<#=t#>] = t<#=t+1#>;
|
||||||
|
<# } #>_ = targetMethod.Invoke(TargetObject, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
<# } #>
|
||||||
|
}
|
|
@ -0,0 +1,908 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file CallbackEvent.cs
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 23, 2022
|
||||||
|
\brief Contains the definition of CallbackEvent and related classes.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Reflection.Metadata.Ecma335;
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for a CallbackEvent that all variants inherit from.
|
||||||
|
/// </summary>
|
||||||
|
public interface ICallbackEvent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Registers an empty ICallbackAction.
|
||||||
|
/// </summary>
|
||||||
|
void RegisterAction();
|
||||||
|
/// <summary>
|
||||||
|
/// Registers an ICallbackAction with the event such that it will be called in
|
||||||
|
/// future
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">ICallbackAction to register with.</param>
|
||||||
|
void RegisterAction(ICallbackAction action);
|
||||||
|
/// <summary>
|
||||||
|
/// Deregisters an ICallbackAction that was previously added. This should
|
||||||
|
/// only emit a warning if an action that was not previous added was
|
||||||
|
/// provided.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">ICallbackAction to remove.</param>
|
||||||
|
void DeregisterAction(ICallbackAction action);
|
||||||
|
/// <summary>
|
||||||
|
/// Iterable set of ICallbackActions that were registered to this event.
|
||||||
|
/// </summary>
|
||||||
|
IEnumerable<ICallbackAction> Actions { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A container of CallbackActions that is correlated to a specific scenario as
|
||||||
|
/// specified by the user of this class.
|
||||||
|
/// This variant accepts CallbackEvents with 1 generic parameter.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackEvent<T1> : ICallbackEvent
|
||||||
|
{
|
||||||
|
#region Properties --------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IEnumerable<ICallbackAction> Actions => actions;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private List<ICallbackAction> actions = new List<ICallbackAction>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction()
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1>());
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
// Check if valid action
|
||||||
|
if (action.GetType() != typeof(CallbackAction<T1>))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to register an invalid CallbackAction type. Ignoring.", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a CallbackAction into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">CallbackAction to add.</param>
|
||||||
|
public void RegisterAction(CallbackAction<T1> action)
|
||||||
|
{
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">System.Action to add as a CallbackAction.</param>
|
||||||
|
public void RegisterAction(Action<T1> action)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1>(action));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
public void RegisterAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1>(target, method));
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void DeregisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
if (!actions.Remove(action))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to deregister invalid action. Ignored.", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes all stored CallbackActions with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1)
|
||||||
|
{
|
||||||
|
foreach (CallbackAction<T1> action in actions)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action.Invoke(t1);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogException(e, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// A container of CallbackActions that is correlated to a specific scenario as
|
||||||
|
/// specified by the user of this class.
|
||||||
|
/// This variant accepts CallbackEvents with 1 generic parameter.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackEvent<T1, T2> : ICallbackEvent
|
||||||
|
{
|
||||||
|
#region Properties --------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IEnumerable<ICallbackAction> Actions => actions;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private List<ICallbackAction> actions = new List<ICallbackAction>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction()
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2>());
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
// Check if valid action
|
||||||
|
if (action.GetType() != typeof(CallbackAction<T1, T2>))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to register an invalid CallbackAction type. Ignoring.", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a CallbackAction into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">CallbackAction to add.</param>
|
||||||
|
public void RegisterAction(CallbackAction<T1, T2> action)
|
||||||
|
{
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">System.Action to add as a CallbackAction.</param>
|
||||||
|
public void RegisterAction(Action<T1, T2> action)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2>(action));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
public void RegisterAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2>(target, method));
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void DeregisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
if (!actions.Remove(action))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to deregister invalid action. Ignored.", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes all stored CallbackActions with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2)
|
||||||
|
{
|
||||||
|
foreach (CallbackAction<T1, T2> action in actions)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action.Invoke(t1, t2);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogException(e, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// A container of CallbackActions that is correlated to a specific scenario as
|
||||||
|
/// specified by the user of this class.
|
||||||
|
/// This variant accepts CallbackEvents with 1 generic parameter.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackEvent<T1, T2, T3> : ICallbackEvent
|
||||||
|
{
|
||||||
|
#region Properties --------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IEnumerable<ICallbackAction> Actions => actions;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private List<ICallbackAction> actions = new List<ICallbackAction>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction()
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3>());
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
// Check if valid action
|
||||||
|
if (action.GetType() != typeof(CallbackAction<T1, T2, T3>))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to register an invalid CallbackAction type. Ignoring.", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a CallbackAction into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">CallbackAction to add.</param>
|
||||||
|
public void RegisterAction(CallbackAction<T1, T2, T3> action)
|
||||||
|
{
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">System.Action to add as a CallbackAction.</param>
|
||||||
|
public void RegisterAction(Action<T1, T2, T3> action)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3>(action));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
public void RegisterAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3>(target, method));
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void DeregisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
if (!actions.Remove(action))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to deregister invalid action. Ignored.", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes all stored CallbackActions with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2, T3 t3)
|
||||||
|
{
|
||||||
|
foreach (CallbackAction<T1, T2, T3> action in actions)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action.Invoke(t1, t2, t3);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogException(e, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// A container of CallbackActions that is correlated to a specific scenario as
|
||||||
|
/// specified by the user of this class.
|
||||||
|
/// This variant accepts CallbackEvents with 1 generic parameter.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackEvent<T1, T2, T3, T4> : ICallbackEvent
|
||||||
|
{
|
||||||
|
#region Properties --------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IEnumerable<ICallbackAction> Actions => actions;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private List<ICallbackAction> actions = new List<ICallbackAction>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction()
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4>());
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
// Check if valid action
|
||||||
|
if (action.GetType() != typeof(CallbackAction<T1, T2, T3, T4>))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to register an invalid CallbackAction type. Ignoring.", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a CallbackAction into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">CallbackAction to add.</param>
|
||||||
|
public void RegisterAction(CallbackAction<T1, T2, T3, T4> action)
|
||||||
|
{
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">System.Action to add as a CallbackAction.</param>
|
||||||
|
public void RegisterAction(Action<T1, T2, T3, T4> action)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4>(action));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
public void RegisterAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4>(target, method));
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void DeregisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
if (!actions.Remove(action))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to deregister invalid action. Ignored.", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes all stored CallbackActions with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2, T3 t3, T4 t4)
|
||||||
|
{
|
||||||
|
foreach (CallbackAction<T1, T2, T3, T4> action in actions)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action.Invoke(t1, t2, t3, t4);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogException(e, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// A container of CallbackActions that is correlated to a specific scenario as
|
||||||
|
/// specified by the user of this class.
|
||||||
|
/// This variant accepts CallbackEvents with 1 generic parameter.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackEvent<T1, T2, T3, T4, T5> : ICallbackEvent
|
||||||
|
{
|
||||||
|
#region Properties --------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IEnumerable<ICallbackAction> Actions => actions;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private List<ICallbackAction> actions = new List<ICallbackAction>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction()
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5>());
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
// Check if valid action
|
||||||
|
if (action.GetType() != typeof(CallbackAction<T1, T2, T3, T4, T5>))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to register an invalid CallbackAction type. Ignoring.", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a CallbackAction into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">CallbackAction to add.</param>
|
||||||
|
public void RegisterAction(CallbackAction<T1, T2, T3, T4, T5> action)
|
||||||
|
{
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">System.Action to add as a CallbackAction.</param>
|
||||||
|
public void RegisterAction(Action<T1, T2, T3, T4, T5> action)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5>(action));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
public void RegisterAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5>(target, method));
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void DeregisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
if (!actions.Remove(action))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to deregister invalid action. Ignored.", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes all stored CallbackActions with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
|
||||||
|
{
|
||||||
|
foreach (CallbackAction<T1, T2, T3, T4, T5> action in actions)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action.Invoke(t1, t2, t3, t4, t5);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogException(e, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// A container of CallbackActions that is correlated to a specific scenario as
|
||||||
|
/// specified by the user of this class.
|
||||||
|
/// This variant accepts CallbackEvents with 1 generic parameter.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackEvent<T1, T2, T3, T4, T5, T6> : ICallbackEvent
|
||||||
|
{
|
||||||
|
#region Properties --------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IEnumerable<ICallbackAction> Actions => actions;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private List<ICallbackAction> actions = new List<ICallbackAction>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction()
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6>());
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
// Check if valid action
|
||||||
|
if (action.GetType() != typeof(CallbackAction<T1, T2, T3, T4, T5, T6>))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to register an invalid CallbackAction type. Ignoring.", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a CallbackAction into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">CallbackAction to add.</param>
|
||||||
|
public void RegisterAction(CallbackAction<T1, T2, T3, T4, T5, T6> action)
|
||||||
|
{
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">System.Action to add as a CallbackAction.</param>
|
||||||
|
public void RegisterAction(Action<T1, T2, T3, T4, T5, T6> action)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6>(action));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
public void RegisterAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6>(target, method));
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void DeregisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
if (!actions.Remove(action))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to deregister invalid action. Ignored.", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes all stored CallbackActions with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
|
||||||
|
{
|
||||||
|
foreach (CallbackAction<T1, T2, T3, T4, T5, T6> action in actions)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action.Invoke(t1, t2, t3, t4, t5, t6);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogException(e, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// A container of CallbackActions that is correlated to a specific scenario as
|
||||||
|
/// specified by the user of this class.
|
||||||
|
/// This variant accepts CallbackEvents with 1 generic parameter.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackEvent<T1, T2, T3, T4, T5, T6, T7> : ICallbackEvent
|
||||||
|
{
|
||||||
|
#region Properties --------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IEnumerable<ICallbackAction> Actions => actions;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private List<ICallbackAction> actions = new List<ICallbackAction>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction()
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7>());
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
// Check if valid action
|
||||||
|
if (action.GetType() != typeof(CallbackAction<T1, T2, T3, T4, T5, T6, T7>))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to register an invalid CallbackAction type. Ignoring.", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a CallbackAction into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">CallbackAction to add.</param>
|
||||||
|
public void RegisterAction(CallbackAction<T1, T2, T3, T4, T5, T6, T7> action)
|
||||||
|
{
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">System.Action to add as a CallbackAction.</param>
|
||||||
|
public void RegisterAction(Action<T1, T2, T3, T4, T5, T6, T7> action)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7>(action));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
public void RegisterAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7>(target, method));
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void DeregisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
if (!actions.Remove(action))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to deregister invalid action. Ignored.", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes all stored CallbackActions with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
|
||||||
|
{
|
||||||
|
foreach (CallbackAction<T1, T2, T3, T4, T5, T6, T7> action in actions)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action.Invoke(t1, t2, t3, t4, t5, t6, t7);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogException(e, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// A container of CallbackActions that is correlated to a specific scenario as
|
||||||
|
/// specified by the user of this class.
|
||||||
|
/// This variant accepts CallbackEvents with 1 generic parameter.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackEvent<T1, T2, T3, T4, T5, T6, T7, T8> : ICallbackEvent
|
||||||
|
{
|
||||||
|
#region Properties --------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IEnumerable<ICallbackAction> Actions => actions;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private List<ICallbackAction> actions = new List<ICallbackAction>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction()
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8>());
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
// Check if valid action
|
||||||
|
if (action.GetType() != typeof(CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8>))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to register an invalid CallbackAction type. Ignoring.", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a CallbackAction into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">CallbackAction to add.</param>
|
||||||
|
public void RegisterAction(CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8> action)
|
||||||
|
{
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">System.Action to add as a CallbackAction.</param>
|
||||||
|
public void RegisterAction(Action<T1, T2, T3, T4, T5, T6, T7, T8> action)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8>(action));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
public void RegisterAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8>(target, method));
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void DeregisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
if (!actions.Remove(action))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to deregister invalid action. Ignored.", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes all stored CallbackActions with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
|
||||||
|
{
|
||||||
|
foreach (CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8> action in actions)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action.Invoke(t1, t2, t3, t4, t5, t6, t7, t8);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogException(e, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// A container of CallbackActions that is correlated to a specific scenario as
|
||||||
|
/// specified by the user of this class.
|
||||||
|
/// This variant accepts CallbackEvents with 1 generic parameter.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackEvent<T1, T2, T3, T4, T5, T6, T7, T8, T9> : ICallbackEvent
|
||||||
|
{
|
||||||
|
#region Properties --------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IEnumerable<ICallbackAction> Actions => actions;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private List<ICallbackAction> actions = new List<ICallbackAction>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction()
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9>());
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
// Check if valid action
|
||||||
|
if (action.GetType() != typeof(CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9>))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to register an invalid CallbackAction type. Ignoring.", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a CallbackAction into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">CallbackAction to add.</param>
|
||||||
|
public void RegisterAction(CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9> action)
|
||||||
|
{
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">System.Action to add as a CallbackAction.</param>
|
||||||
|
public void RegisterAction(Action<T1, T2, T3, T4, T5, T6, T7, T8, T9> action)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9>(action));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
public void RegisterAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9>(target, method));
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void DeregisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
if (!actions.Remove(action))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to deregister invalid action. Ignored.", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes all stored CallbackActions with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9)
|
||||||
|
{
|
||||||
|
foreach (CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9> action in actions)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action.Invoke(t1, t2, t3, t4, t5, t6, t7, t8, t9);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogException(e, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// A container of CallbackActions that is correlated to a specific scenario as
|
||||||
|
/// specified by the user of this class.
|
||||||
|
/// This variant accepts CallbackEvents with 1 generic parameter.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackEvent<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : ICallbackEvent
|
||||||
|
{
|
||||||
|
#region Properties --------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IEnumerable<ICallbackAction> Actions => actions;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private List<ICallbackAction> actions = new List<ICallbackAction>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction()
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>());
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
// Check if valid action
|
||||||
|
if (action.GetType() != typeof(CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to register an invalid CallbackAction type. Ignoring.", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a CallbackAction into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">CallbackAction to add.</param>
|
||||||
|
public void RegisterAction(CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> action)
|
||||||
|
{
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">System.Action to add as a CallbackAction.</param>
|
||||||
|
public void RegisterAction(Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> action)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(action));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
public void RegisterAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(target, method));
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void DeregisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
if (!actions.Remove(action))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to deregister invalid action. Ignored.", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes all stored CallbackActions with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10)
|
||||||
|
{
|
||||||
|
foreach (CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> action in actions)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action.Invoke(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogException(e, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,152 @@
|
||||||
|
<#
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file CallbackEvent.tt
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 23, 2022
|
||||||
|
\brief Contains the T4 template for the definition of CallbackEvent and
|
||||||
|
related classes.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/#>
|
||||||
|
<#@ template hostspecific="false" language="C#" #>
|
||||||
|
<#@ output extension=".cs" #>
|
||||||
|
<# var max = 10; #>
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file CallbackEvent.cs
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 23, 2022
|
||||||
|
\brief Contains the definition of CallbackEvent and related classes.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Reflection.Metadata.Ecma335;
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for a CallbackEvent that all variants inherit from.
|
||||||
|
/// </summary>
|
||||||
|
public interface ICallbackEvent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Registers an empty ICallbackAction.
|
||||||
|
/// </summary>
|
||||||
|
void RegisterAction();
|
||||||
|
/// <summary>
|
||||||
|
/// Registers an ICallbackAction with the event such that it will be called in
|
||||||
|
/// future
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">ICallbackAction to register with.</param>
|
||||||
|
void RegisterAction(ICallbackAction action);
|
||||||
|
/// <summary>
|
||||||
|
/// Deregisters an ICallbackAction that was previously added. This should
|
||||||
|
/// only emit a warning if an action that was not previous added was
|
||||||
|
/// provided.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">ICallbackAction to remove.</param>
|
||||||
|
void DeregisterAction(ICallbackAction action);
|
||||||
|
/// <summary>
|
||||||
|
/// Iterable set of ICallbackActions that were registered to this event.
|
||||||
|
/// </summary>
|
||||||
|
IEnumerable<ICallbackAction> Actions { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
<# for (int i = 1; i <= max; ++i) { #>
|
||||||
|
/// <summary>
|
||||||
|
/// A container of CallbackActions that is correlated to a specific scenario as
|
||||||
|
/// specified by the user of this class.
|
||||||
|
/// This variant accepts CallbackEvents with 1 generic parameter.
|
||||||
|
/// </summary>
|
||||||
|
public class CallbackEvent<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> : ICallbackEvent
|
||||||
|
{
|
||||||
|
#region Properties --------------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IEnumerable<ICallbackAction> Actions => actions;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields ------------------------------------------------------------------
|
||||||
|
private List<ICallbackAction> actions = new List<ICallbackAction>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Usage Functions ---------------------------------------------------------
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction()
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>>());
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RegisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
// Check if valid action
|
||||||
|
if (action.GetType() != typeof(CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>>))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to register an invalid CallbackAction type. Ignoring.", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a CallbackAction into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">CallbackAction to add.</param>
|
||||||
|
public void RegisterAction(CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> action)
|
||||||
|
{
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">System.Action to add as a CallbackAction.</param>
|
||||||
|
public void RegisterAction(Action<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> action)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>>(action));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a CallbackACtion into the event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">Object to call the method on.</param>
|
||||||
|
/// <param name="method">Method to call.</param>
|
||||||
|
public void RegisterAction(Object target, MethodInfo method)
|
||||||
|
{
|
||||||
|
actions.Add(new CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>>(target, method));
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void DeregisterAction(ICallbackAction action)
|
||||||
|
{
|
||||||
|
if (!actions.Remove(action))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attempted to deregister invalid action. Ignored.", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes all stored CallbackActions with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
public void Invoke(<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#> t<#=t#><# if (t != i) { #>, <# } #><# } #>)
|
||||||
|
{
|
||||||
|
foreach (CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> action in actions)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action.Invoke(<# for (int t = 1; t < i + 1; ++t) { #>t<#=t#><# if (t != i) { #>, <# } #><# } #>);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogException(e, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
<# } #>
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
internal static class Debug
|
||||||
|
{
|
||||||
|
[DllImport("SHADE_Engine.dll", EntryPoint = "SHLog_Info")]
|
||||||
|
public static extern void LogInfo([MarshalAs(UnmanagedType.LPStr)] string str);
|
||||||
|
[DllImport("SHADE_Engine.dll", EntryPoint = "SHLog_Warning")]
|
||||||
|
public static extern void LogWarning([MarshalAs(UnmanagedType.LPStr)] string str);
|
||||||
|
[DllImport("SHADE_Engine.dll", EntryPoint = "SHLog_Error")]
|
||||||
|
public static extern void LogError([MarshalAs(UnmanagedType.LPStr)] string str);
|
||||||
|
[DllImport("SHADE_Engine.dll", EntryPoint = "SHLog_Critical")]
|
||||||
|
public static extern void LogCritical([MarshalAs(UnmanagedType.LPStr)] string str);
|
||||||
|
public static void LogInfo(string msg, Object thrower)
|
||||||
|
{
|
||||||
|
LogInfo($"[{thrower.GetType().Name}] {msg}");
|
||||||
|
}
|
||||||
|
public static void LogWarning(string msg, Object thrower)
|
||||||
|
{
|
||||||
|
LogWarning($"[{thrower.GetType().Name}] {msg}");
|
||||||
|
}
|
||||||
|
public static void LogError(string msg, Object thrower)
|
||||||
|
{
|
||||||
|
LogError($"[{thrower.GetType().Name}] {msg}");
|
||||||
|
}
|
||||||
|
public static void LogCritical(string msg, Object thrower)
|
||||||
|
{
|
||||||
|
LogCritical($"[{thrower.GetType().Name}] {msg}");
|
||||||
|
}
|
||||||
|
public static void LogException(Exception exception, Object thrower)
|
||||||
|
{
|
||||||
|
LogError($"[{ thrower.GetType().Name }] Unhandled exception: { exception.ToString() }");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHShaderAsset.cpp
|
||||||
|
* \author Brandon Mak
|
||||||
|
* \date 24 October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHShaderAsset.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
SHShaderAsset::SHShaderAsset() noexcept
|
||||||
|
: spirvBinary{},
|
||||||
|
shaderType{SH_SHADER_TYPE::VERTEX},
|
||||||
|
name{}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SHShaderAsset::SHShaderAsset(SHShaderAsset const& rhs) noexcept
|
||||||
|
: spirvBinary{rhs.spirvBinary},
|
||||||
|
shaderType{ rhs.shaderType },
|
||||||
|
name{rhs.name}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SHShaderAsset::SHShaderAsset(SHShaderAsset&& rhs) noexcept
|
||||||
|
: spirvBinary{ std::move(rhs.spirvBinary) },
|
||||||
|
shaderType{ std::move(rhs.shaderType) },
|
||||||
|
name{ std::move(rhs.name) }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SHShaderAsset& SHShaderAsset::operator=(SHShaderAsset&& rhs) noexcept
|
||||||
|
{
|
||||||
|
if (this == &rhs)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
spirvBinary = std::move(rhs.spirvBinary);
|
||||||
|
shaderType = std::move(rhs.shaderType);
|
||||||
|
name = std::move(rhs.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
SHShaderAsset& SHShaderAsset::operator=(SHShaderAsset const& rhs) noexcept
|
||||||
|
{
|
||||||
|
if (this == &rhs)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
spirvBinary = rhs.spirvBinary;
|
||||||
|
shaderType = rhs.shaderType;
|
||||||
|
name = rhs.name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHShaderAsset.h
|
||||||
|
* \author Brandon Mak
|
||||||
|
* \date 24 October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SHAssetData.h"
|
||||||
|
#include "SH_API.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
enum class SH_SHADER_TYPE : uint8_t
|
||||||
|
{
|
||||||
|
VERTEX,
|
||||||
|
FRAGMENT,
|
||||||
|
COMPUTE,
|
||||||
|
INAVLID_TYPE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SH_API SHShaderAsset : SHAssetData
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* MEMBER VARIABLES */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
//! container storing the spirv binary
|
||||||
|
std::vector<uint32_t> spirvBinary;
|
||||||
|
|
||||||
|
//! For the compilation of the shader. Vulkan backend will use it too
|
||||||
|
SH_SHADER_TYPE shaderType;
|
||||||
|
|
||||||
|
//! Name of the shader file (without parent path)
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
SHShaderAsset() noexcept;
|
||||||
|
SHShaderAsset(SHShaderAsset const& rhs) noexcept;
|
||||||
|
SHShaderAsset(SHShaderAsset&& rhs) noexcept;
|
||||||
|
SHShaderAsset& operator= (SHShaderAsset&& rhs) noexcept;
|
||||||
|
SHShaderAsset& operator= (SHShaderAsset const& rhs) noexcept;
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,24 +1,30 @@
|
||||||
/*************************************************************************//**
|
/*************************************************************************//**
|
||||||
* \file SHAssimpLibrary.cpp
|
* \file SHMeshCompiler.cpp
|
||||||
* \author Loh Xiao Qi
|
* \author Loh Xiao Qi
|
||||||
* \date October 2022
|
* \date 30 September 2022
|
||||||
* \brief
|
* \brief Library to write data in SHMeshAsset into binary file for faster
|
||||||
|
* loading in the future
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
* disclosure of this file or its contents without the prior written consent
|
* disclosure of this file or its contents without the prior written consent
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#include "SHpch.h"
|
#include "SHpch.h"
|
||||||
#include "SHAssimpLibrary.h"
|
#include "SHMeshCompiler.h"
|
||||||
|
#include "Graphics/MiddleEnd/Meshes/SHMeshData.h"
|
||||||
#include <assimp/postprocess.h>
|
#include <assimp/postprocess.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
Assimp::Importer SHAssimpLibrary::aiImporter;
|
|
||||||
|
|
||||||
void SHAssimpLibrary::ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept
|
Assimp::Importer SHMeshCompiler::aiImporter;
|
||||||
{
|
|
||||||
for (size_t i {0}; i < node.mNumMeshes; ++i)
|
void SHMeshCompiler::ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept
|
||||||
|
{
|
||||||
|
for (size_t i{ 0 }; i < node.mNumMeshes; ++i)
|
||||||
{
|
{
|
||||||
aiMesh* mesh = scene.mMeshes[node.mMeshes[i]];
|
aiMesh* mesh = scene.mMeshes[node.mMeshes[i]];
|
||||||
meshes.push_back(ProcessMesh(*mesh));
|
meshes.push_back(ProcessMesh(*mesh));
|
||||||
|
@ -28,16 +34,16 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
ProcessNode(*node.mChildren[i], scene, meshes);
|
ProcessNode(*node.mChildren[i], scene, meshes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssimpLibrary::ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept
|
void SHMeshCompiler::ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept
|
||||||
{
|
{
|
||||||
if (scene.HasAnimations())
|
if (scene.HasAnimations())
|
||||||
{
|
{
|
||||||
std::vector<SHAnimationAsset> anims(scene.mNumAnimations);
|
std::vector<SHAnimationAsset> anims(scene.mNumAnimations);
|
||||||
for (auto i{0}; i < scene.mNumAnimations; ++i)
|
for (auto i{ 0 }; i < scene.mNumAnimations; ++i)
|
||||||
{
|
{
|
||||||
auto const& anim {*scene.mAnimations[i]};
|
auto const& anim{ *scene.mAnimations[i] };
|
||||||
|
|
||||||
anims[i].name = anim.mName.C_Str();
|
anims[i].name = anim.mName.C_Str();
|
||||||
|
|
||||||
|
@ -47,17 +53,17 @@ namespace SHADE
|
||||||
std::copy_n(anim.mChannels, anim.mNumChannels, anims[i].nodeChannels.data());
|
std::copy_n(anim.mChannels, anim.mNumChannels, anims[i].nodeChannels.data());
|
||||||
std::copy_n(anim.mMeshChannels, anim.mNumMeshChannels, anims[i].meshChannels.data());
|
std::copy_n(anim.mMeshChannels, anim.mNumMeshChannels, anims[i].meshChannels.data());
|
||||||
std::copy_n(anim.mMorphMeshChannels, anim.mNumMorphMeshChannels, anims[i].morphMeshChannels.data());
|
std::copy_n(anim.mMorphMeshChannels, anim.mNumMorphMeshChannels, anims[i].morphMeshChannels.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMeshAsset* SHAssimpLibrary::ProcessMesh(aiMesh const& mesh) noexcept
|
SHMeshAsset* SHMeshCompiler::ProcessMesh(aiMesh const& mesh) noexcept
|
||||||
{
|
{
|
||||||
SHMeshAsset* result = new SHMeshAsset();
|
SHMeshAsset* result = new SHMeshAsset();
|
||||||
result->compiled = false;
|
result->compiled = false;
|
||||||
result->changed = false;
|
result->changed = false;
|
||||||
|
|
||||||
for (size_t i{0}; i < mesh.mNumVertices; ++i)
|
for (size_t i{ 0 }; i < mesh.mNumVertices; ++i)
|
||||||
{
|
{
|
||||||
// Vertex position
|
// Vertex position
|
||||||
SHVec3 vertex;
|
SHVec3 vertex;
|
||||||
|
@ -67,7 +73,7 @@ namespace SHADE
|
||||||
result->vertexPosition.push_back(vertex);
|
result->vertexPosition.push_back(vertex);
|
||||||
|
|
||||||
// Tex coords
|
// Tex coords
|
||||||
SHVec2 texCoord{0.f, 0.f};
|
SHVec2 texCoord{ 0.f, 0.f };
|
||||||
if (mesh.mTextureCoords[0])
|
if (mesh.mTextureCoords[0])
|
||||||
{
|
{
|
||||||
texCoord.x = mesh.mTextureCoords[0][i].x;
|
texCoord.x = mesh.mTextureCoords[0][i].x;
|
||||||
|
@ -76,7 +82,7 @@ namespace SHADE
|
||||||
result->texCoords.push_back(texCoord);
|
result->texCoords.push_back(texCoord);
|
||||||
|
|
||||||
// Normals
|
// Normals
|
||||||
SHVec3 normal{0.f, 0.f, 0.f};
|
SHVec3 normal{ 0.f, 0.f, 0.f };
|
||||||
if (mesh.mNormals)
|
if (mesh.mNormals)
|
||||||
{
|
{
|
||||||
normal.x = mesh.mNormals[i].x;
|
normal.x = mesh.mNormals[i].x;
|
||||||
|
@ -86,7 +92,7 @@ namespace SHADE
|
||||||
result->vertexNormal.push_back(normal);
|
result->vertexNormal.push_back(normal);
|
||||||
|
|
||||||
// Tangent
|
// Tangent
|
||||||
SHVec3 tangent{0.f, 0.f, 0.f};
|
SHVec3 tangent{ 0.f, 0.f, 0.f };
|
||||||
if (mesh.mTangents)
|
if (mesh.mTangents)
|
||||||
{
|
{
|
||||||
tangent.x = mesh.mTangents[i].x;
|
tangent.x = mesh.mTangents[i].x;
|
||||||
|
@ -96,10 +102,10 @@ namespace SHADE
|
||||||
result->vertexTangent.push_back(tangent);
|
result->vertexTangent.push_back(tangent);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i {0}; i < mesh.mNumFaces; ++i)
|
for (size_t i{ 0 }; i < mesh.mNumFaces; ++i)
|
||||||
{
|
{
|
||||||
aiFace face = mesh.mFaces[i];
|
aiFace face = mesh.mFaces[i];
|
||||||
for (size_t j{0}; j < face.mNumIndices; ++j)
|
for (size_t j{ 0 }; j < face.mNumIndices; ++j)
|
||||||
{
|
{
|
||||||
result->indices.push_back(face.mIndices[j]);
|
result->indices.push_back(face.mIndices[j]);
|
||||||
}
|
}
|
||||||
|
@ -110,10 +116,10 @@ namespace SHADE
|
||||||
result->header.name = mesh.mName.C_Str();
|
result->header.name = mesh.mName.C_Str();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssimpLibrary::LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept
|
void SHMeshCompiler::LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept
|
||||||
{
|
{
|
||||||
const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
|
const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
|
||||||
aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
|
aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
|
||||||
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
|
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
|
||||||
|
@ -132,10 +138,64 @@ namespace SHADE
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtractAnimations(*scene, anims);
|
//ExtractAnimations(*scene, anims);
|
||||||
|
|
||||||
ProcessNode(*scene->mRootNode, *scene, meshes);
|
ProcessNode(*scene->mRootNode, *scene, meshes);
|
||||||
|
|
||||||
aiImporter.FreeScene();
|
aiImporter.FreeScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<AssetPath> SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept
|
||||||
|
{
|
||||||
|
std::string newPath{ path.parent_path().string() + '/' };
|
||||||
|
newPath += asset.header.name + MESH_EXTENSION.data();
|
||||||
|
|
||||||
|
std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc };
|
||||||
|
if (!file.is_open())
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Unable to open file for writing mesh file: {}", path.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&(asset.header.vertexCount)),
|
||||||
|
sizeof(uint32_t)
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<const char*>(&(asset.header.indexCount)),
|
||||||
|
sizeof(uint32_t)
|
||||||
|
);
|
||||||
|
|
||||||
|
auto const vertexVec3Byte{ sizeof(SHVec3) * asset.header.vertexCount };
|
||||||
|
auto const vertexVec2Byte{ sizeof(SHVec2) * asset.header.vertexCount };
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.vertexPosition.data()),
|
||||||
|
vertexVec3Byte
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.vertexTangent.data()),
|
||||||
|
vertexVec3Byte
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.vertexNormal.data()),
|
||||||
|
vertexVec3Byte
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.texCoords.data()),
|
||||||
|
vertexVec2Byte
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.indices.data()),
|
||||||
|
sizeof(uint32_t) * asset.header.indexCount
|
||||||
|
);
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
return newPath;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHMeshCompiler.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 30 September 2022
|
||||||
|
* \brief Library to write data in SHMeshAsset into binary file for faster
|
||||||
|
* loading in the future
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <assimp/Importer.hpp>
|
||||||
|
#include <assimp/scene.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Assets/Asset Types/SHAnimationAsset.h"
|
||||||
|
#include "Assets/Asset Types/SHMeshAsset.h"
|
||||||
|
#include "Assets/SHAssetMacros.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHMeshCompiler
|
||||||
|
{
|
||||||
|
|
||||||
|
using MeshVectorRef = std::vector<SHMeshAsset*>&;
|
||||||
|
using AnimVectorRef = std::vector<SHAnimationAsset*>&;
|
||||||
|
|
||||||
|
static Assimp::Importer aiImporter;
|
||||||
|
static void ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept;
|
||||||
|
static void ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept;
|
||||||
|
static SHMeshAsset* ProcessMesh(aiMesh const& mesh) noexcept;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept;
|
||||||
|
static std::optional<AssetPath> CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,162 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHShaderSourceCompiler.cpp
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 23 10 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHShaderSourceCompiler.h"
|
||||||
|
#include "shaderc/shaderc.hpp"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
std::string SHShaderSourceCompiler::CompileShaderSourceToBinary(AssetPath path, SHShaderAsset const& data) noexcept
|
||||||
|
{
|
||||||
|
std::string newPath{ path.string() };
|
||||||
|
newPath = newPath.substr(0, newPath.find_last_of('.'));
|
||||||
|
newPath += SHADER_BUILT_IN_EXTENSION.data();
|
||||||
|
|
||||||
|
std::ofstream file{ newPath, std::ios::binary | std::ios::out | std::ios::trunc };
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(& data.shaderType), sizeof(uint8_t)
|
||||||
|
);
|
||||||
|
|
||||||
|
size_t const byteCount = sizeof(uint32_t) * data.spirvBinary.size();
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&byteCount), sizeof(size_t)
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(data.spirvBinary.data()), byteCount
|
||||||
|
);
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
return newPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHShaderAsset const* SHShaderSourceCompiler::CompileShaderSourceToMemory(std::string const& data, std::string const& name, SH_SHADER_TYPE type) noexcept
|
||||||
|
{
|
||||||
|
// shaderc compiler
|
||||||
|
shaderc::Compiler compiler;
|
||||||
|
shaderc::CompileOptions options;
|
||||||
|
|
||||||
|
options.AddMacroDefinition("MY_DEFINE", "1");
|
||||||
|
|
||||||
|
//TODO: Check if we need optimisation levels when compiling into spirv
|
||||||
|
// Set optimization levels
|
||||||
|
//if (opLevel != shaderc_optimization_level_zero)
|
||||||
|
// options.SetOptimizationLevel(opLevel);
|
||||||
|
|
||||||
|
// Attempt to get the shaderc equivalent shader stage
|
||||||
|
shaderc_shader_kind shaderKind;
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case SH_SHADER_TYPE::VERTEX:
|
||||||
|
shaderKind = shaderc_shader_kind::shaderc_glsl_vertex_shader;
|
||||||
|
break;
|
||||||
|
case SH_SHADER_TYPE::FRAGMENT:
|
||||||
|
shaderKind = shaderc_shader_kind::shaderc_glsl_fragment_shader;
|
||||||
|
break;
|
||||||
|
case SH_SHADER_TYPE::COMPUTE:
|
||||||
|
shaderKind = shaderc_shader_kind::shaderc_glsl_compute_shader;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
shaderKind = shaderc_shader_kind::shaderc_glsl_vertex_shader;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile the shader and get the result
|
||||||
|
shaderc::SpvCompilationResult compileResult = compiler.CompileGlslToSpv(data, shaderKind, name.c_str(), options);
|
||||||
|
|
||||||
|
if (compileResult.GetCompilationStatus() != shaderc_compilation_status_success)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Shaderc failed to compile GLSL shader to binary | " + compileResult.GetErrorMessage());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = new SHShaderAsset();
|
||||||
|
result->spirvBinary.resize(compileResult.end() - compileResult.begin());
|
||||||
|
|
||||||
|
std::ranges::copy(compileResult.begin(), compileResult.end(), result->spirvBinary.data());
|
||||||
|
|
||||||
|
result->name = name;
|
||||||
|
result->shaderType = type;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SH_SHADER_TYPE SHShaderSourceCompiler::GetShaderTypeFromFilename(std::string name) noexcept
|
||||||
|
{
|
||||||
|
for (auto i { 0}; i < SHADER_TYPE_MAX_COUNT; ++i)
|
||||||
|
{
|
||||||
|
if (name.find(SHADER_IDENTIFIERS[i].data()) != std::string::npos)
|
||||||
|
{
|
||||||
|
return static_cast<SH_SHADER_TYPE>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SH_SHADER_TYPE::INAVLID_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<AssetPath> SHShaderSourceCompiler::LoadAndCompileShader(AssetPath path) noexcept
|
||||||
|
{
|
||||||
|
auto type = GetShaderTypeFromFilename(path.filename().string());
|
||||||
|
|
||||||
|
if (type == SH_SHADER_TYPE::INAVLID_TYPE)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Invalid filename for shaders, follow suffix in SHAssetMacros.h: {}", path.string());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
path.make_preferred();
|
||||||
|
|
||||||
|
std::ifstream file{ path.string(), std::ios::in };
|
||||||
|
|
||||||
|
if (file.is_open())
|
||||||
|
{
|
||||||
|
std::stringstream stream;
|
||||||
|
|
||||||
|
stream << file.rdbuf();
|
||||||
|
|
||||||
|
std::string const content = stream.str();
|
||||||
|
|
||||||
|
auto data = CompileShaderSourceToMemory(content, path.filename().string(), type);
|
||||||
|
|
||||||
|
if (data == nullptr)
|
||||||
|
{
|
||||||
|
return{};
|
||||||
|
}
|
||||||
|
|
||||||
|
return CompileShaderSourceToBinary(path, *data);
|
||||||
|
}
|
||||||
|
|
||||||
|
SHLOG_ERROR("Unable to open shader file: {}", path.string());
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<AssetPath> SHShaderSourceCompiler::CompileShaderFromString
|
||||||
|
(std::string const& string, AssetPath path, SH_SHADER_TYPE type) noexcept
|
||||||
|
{
|
||||||
|
auto const data = CompileShaderSourceToMemory(string, path.filename().string(), type);
|
||||||
|
|
||||||
|
if (data == nullptr)
|
||||||
|
{
|
||||||
|
return{};
|
||||||
|
}
|
||||||
|
|
||||||
|
return CompileShaderSourceToBinary(path, *data);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHShaderSourceCompiler.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 23 10 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Assets/SHAssetMacros.h"
|
||||||
|
#include "Assets/Asset Types/SHShaderAsset.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHShaderSourceCompiler
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static std::string CompileShaderSourceToBinary(AssetPath path, SHShaderAsset const& data) noexcept;
|
||||||
|
static SHShaderAsset const* CompileShaderSourceToMemory(std::string const& data, std::string const& name, SH_SHADER_TYPE type) noexcept;
|
||||||
|
|
||||||
|
static SH_SHADER_TYPE GetShaderTypeFromFilename(std::string name) noexcept;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static std::optional<AssetPath> LoadAndCompileShader(AssetPath path) noexcept;
|
||||||
|
static std::optional<AssetPath> CompileShaderFromString
|
||||||
|
(std::string const& string, AssetPath path, SH_SHADER_TYPE type) noexcept;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,171 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHTextureCompiler.cpp
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 30 September 2022
|
||||||
|
* \brief Library to write data in SHTextureAsset into binary file for
|
||||||
|
* faster loading in the future
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHTextureCompiler.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
|
||||||
|
std::string SHTextureCompiler::TinyDDSResultToString(tinyddsloader::Result value)
|
||||||
|
{
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case tinyddsloader::Result::ErrorFileOpen:
|
||||||
|
return "File open err";
|
||||||
|
case tinyddsloader::Result::ErrorRead:
|
||||||
|
return "File read err";
|
||||||
|
case tinyddsloader::Result::ErrorMagicWord:
|
||||||
|
return "File header magic word err";
|
||||||
|
case tinyddsloader::Result::ErrorSize:
|
||||||
|
return "File size err";
|
||||||
|
case tinyddsloader::Result::ErrorVerify:
|
||||||
|
return "Pixel format err";
|
||||||
|
case tinyddsloader::Result::ErrorNotSupported:
|
||||||
|
return "Unsupported format";
|
||||||
|
case tinyddsloader::Result::ErrorInvalidData:
|
||||||
|
return "Invalid data";
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::Format SHTextureCompiler::ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm:
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm_SRGB:
|
||||||
|
return isLinear ? vk::Format::eBc1RgbaUnormBlock : vk::Format::eBc1RgbaSrgbBlock;
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm:
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm_SRGB:
|
||||||
|
return isLinear ? vk::Format::eBc2UnormBlock : vk::Format::eBc2SrgbBlock;
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm:
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm_SRGB:
|
||||||
|
return isLinear ? vk::Format::eBc3UnormBlock : vk::Format::eBc3SrgbBlock;
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::BC5_UNorm:
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::BC5_SNorm:
|
||||||
|
return isLinear ? vk::Format::eBc5UnormBlock : vk::Format::eBc5SnormBlock;
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm:
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm_SRGB:
|
||||||
|
return isLinear ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR8G8B8A8Srgb;
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_SNorm:
|
||||||
|
return vk::Format::eR8G8B8A8Snorm;
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm:
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm_SRGB:
|
||||||
|
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8A8Srgb;
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm:
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm_SRGB:
|
||||||
|
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8Srgb;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("Unsupported DDS format.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHTextureCompiler::LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept
|
||||||
|
{
|
||||||
|
tinyddsloader::Result loadResult = tinyddsloader::Result::Success;
|
||||||
|
tinyddsloader::DDSFile file;
|
||||||
|
loadResult = file.Load(path.string().c_str());
|
||||||
|
if (loadResult != tinyddsloader::Result::Success)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Unable to load Texture file: {} at {}", TinyDDSResultToString(loadResult), path.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t totalBytes{ 0 };
|
||||||
|
|
||||||
|
std::vector<uint32_t> mipOff(file.GetMipCount());
|
||||||
|
|
||||||
|
for (size_t i{ 0 }; i < file.GetMipCount(); ++i)
|
||||||
|
{
|
||||||
|
mipOff[i] = static_cast<uint32_t>(totalBytes);
|
||||||
|
totalBytes += file.GetImageData(static_cast<uint32_t>(i), 0)->m_memSlicePitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHTexture::PixelChannel* pixel = new SHTexture::PixelChannel[totalBytes];
|
||||||
|
std::memcpy(pixel, file.GetImageData()->m_mem, totalBytes);
|
||||||
|
//pixel = std::move(reinterpret_cast<SHTexture::PixelChannel const*>(file.GetDDSData()));
|
||||||
|
|
||||||
|
asset.name = path.stem().string();
|
||||||
|
asset.compiled = false;
|
||||||
|
asset.numBytes = static_cast<uint32_t>(totalBytes);
|
||||||
|
asset.width = file.GetWidth();
|
||||||
|
asset.height = file.GetHeight();
|
||||||
|
asset.format = ddsLoaderToVkFormat(file.GetFormat(), true);
|
||||||
|
asset.mipOffsets = std::move(mipOff);
|
||||||
|
asset.pixelData = std::move(pixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SHTextureCompiler::WriteToFile(SHTextureAsset const& asset, AssetPath path) noexcept
|
||||||
|
{
|
||||||
|
std::string newPath{ path.string() };
|
||||||
|
newPath = newPath.substr(0, newPath.find_last_of('.'));
|
||||||
|
newPath += TEXTURE_EXTENSION;
|
||||||
|
|
||||||
|
std::ofstream file{ newPath, std::ios::out | std::ios::binary };
|
||||||
|
if (!file.is_open())
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Unable to open file for writing texture file: {}", path.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto intBytes{ sizeof(uint32_t) };
|
||||||
|
|
||||||
|
uint32_t const mipOffsetCount{ static_cast<uint32_t>(asset.mipOffsets.size()) };
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&asset.numBytes),
|
||||||
|
intBytes
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&asset.width),
|
||||||
|
intBytes
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&asset.height),
|
||||||
|
intBytes
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&asset.format),
|
||||||
|
sizeof(SHTexture::TextureFormat)
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&mipOffsetCount),
|
||||||
|
intBytes
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.mipOffsets.data()),
|
||||||
|
intBytes * asset.mipOffsets.size()
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.pixelData),
|
||||||
|
asset.numBytes
|
||||||
|
);
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
return newPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<AssetPath> SHTextureCompiler::CompileTextureAsset(AssetPath path)
|
||||||
|
{
|
||||||
|
auto data = new SHTextureAsset();
|
||||||
|
LoadTinyDDS(path, *data);
|
||||||
|
return WriteToFile(*data, path);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHTextureCompiler.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 30 September 2022
|
||||||
|
* \brief Library to write data in SHTextureAsset into binary file for
|
||||||
|
* faster loading in the future
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
#define TINYDDSLOADER_IMPLEMENTATION
|
||||||
|
|
||||||
|
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||||
|
#include "Assets/SHAssetMacros.h"
|
||||||
|
#include "tinyddsloader.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHTextureCompiler
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static std::string TinyDDSResultToString(tinyddsloader::Result value);
|
||||||
|
static vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
|
||||||
|
static void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept;
|
||||||
|
|
||||||
|
static std::string WriteToFile(SHTextureAsset const& asset, AssetPath path) noexcept;
|
||||||
|
public:
|
||||||
|
static std::optional<AssetPath> CompileTextureAsset(AssetPath path);
|
||||||
|
};
|
||||||
|
}
|
|
@ -10,6 +10,7 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Assets/SHAssetMacros.h"
|
||||||
#include "Assets/Asset Types/SHAssetData.h"
|
#include "Assets/Asset Types/SHAssetData.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
|
@ -10,13 +10,13 @@
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../SHAssetMacros.h"
|
#include "Assets/SHAssetMacros.h"
|
||||||
#include "../Asset Types/SHMeshAsset.h"
|
#include "Assets/Asset Types/SHMeshAsset.h"
|
||||||
#include "SHAssetLoader.h"
|
#include "SHAssetLoader.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
struct SHMeshLoader : public SHAssetLoader
|
struct SHMeshLoader : SHAssetLoader
|
||||||
{
|
{
|
||||||
void LoadSHMesh(AssetPath path, SHMeshAsset& meshes) noexcept;
|
void LoadSHMesh(AssetPath path, SHMeshAsset& meshes) noexcept;
|
||||||
SHAssetData* Load(AssetPath path) override;
|
SHAssetData* Load(AssetPath path) override;
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHShaderSourceLoader.cpp
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 23 10 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHShaderSourceLoader.h"
|
||||||
|
#include "Assets/Asset Types/SHShaderAsset.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
SHAssetData* SHShaderSourceLoader::Load(AssetPath path)
|
||||||
|
{
|
||||||
|
auto result = new SHShaderAsset();
|
||||||
|
|
||||||
|
result->name = path.stem().stem().string();
|
||||||
|
|
||||||
|
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
|
||||||
|
if (!file.is_open())
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Unable to open compiled shader file: {}", path.string());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t byteCount = 0;
|
||||||
|
|
||||||
|
file.read(reinterpret_cast<char*>(&result->shaderType), sizeof(uint8_t));
|
||||||
|
file.read(reinterpret_cast<char*>(&byteCount), sizeof(size_t));
|
||||||
|
|
||||||
|
result->spirvBinary.resize(byteCount / sizeof(uint32_t));
|
||||||
|
|
||||||
|
file.read(reinterpret_cast<char*>(result->spirvBinary.data()), byteCount);
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*************************************************************************//**
|
/*************************************************************************//**
|
||||||
* \file SHAnimationAsset.h
|
* \file SHShaderSourceLoader.h
|
||||||
* \author Loh Xiao Qi
|
* \author Loh Xiao Qi
|
||||||
* \date October 2022
|
* \date 23 10 2022
|
||||||
* \brief
|
* \brief
|
||||||
*
|
*
|
||||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
@ -10,21 +10,13 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include "Assets/Libraries/Loaders/SHAssetLoader.h"
|
||||||
#include <assimp/anim.h>
|
#include "Assets/SHAssetMacros.h"
|
||||||
#include "SH_API.power h"
|
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
struct SH_API SHAnimationAsset
|
struct SHShaderSourceLoader : SHAssetLoader
|
||||||
{
|
{
|
||||||
std::string name;
|
SHAssetData* Load(AssetPath path) override;
|
||||||
|
|
||||||
std::vector<aiNodeAnim*> nodeChannels;
|
|
||||||
std::vector<aiMeshAnim*> meshChannels;
|
|
||||||
std::vector<aiMeshMorphAnim*> morphMeshChannels;
|
|
||||||
|
|
||||||
double duration;
|
|
||||||
double ticksPerSecond;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHTextureLoader.cpp
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 30 September 2022
|
||||||
|
* \brief Library to load dds textures and custom binary format
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHTextureLoader.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
|
||||||
|
void SHTextureLoader::LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept
|
||||||
|
{
|
||||||
|
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
|
||||||
|
if (!file.is_open())
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Error opening SHTexture file: {}", path.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const intBytes{ sizeof(uint32_t) };
|
||||||
|
uint32_t mipCount;
|
||||||
|
|
||||||
|
file.read(reinterpret_cast<char*>(&asset.numBytes), intBytes);
|
||||||
|
file.read(reinterpret_cast<char*>(&asset.width), intBytes);
|
||||||
|
file.read(reinterpret_cast<char*>(&asset.height), intBytes);
|
||||||
|
file.read(reinterpret_cast<char*>(&asset.format), sizeof(SHTexture::TextureFormat));
|
||||||
|
|
||||||
|
file.read(reinterpret_cast<char*>(&mipCount), intBytes);
|
||||||
|
std::vector<uint32_t> mips(mipCount);
|
||||||
|
file.read(reinterpret_cast<char*>(mips.data()), intBytes * mipCount);
|
||||||
|
|
||||||
|
auto pixel = new SHTexture::PixelChannel[asset.numBytes];
|
||||||
|
file.read(reinterpret_cast<char*>(pixel), asset.numBytes);
|
||||||
|
|
||||||
|
asset.mipOffsets = std::move(mips);
|
||||||
|
asset.pixelData = std::move(pixel);
|
||||||
|
|
||||||
|
asset.compiled = true;
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
SHAssetData* SHTextureLoader::Load(AssetPath path)
|
||||||
|
{
|
||||||
|
auto result = new SHTextureAsset();
|
||||||
|
|
||||||
|
LoadSHTexture(path, *result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,8 @@
|
||||||
/*************************************************************************//**
|
/*************************************************************************//**
|
||||||
* \file SHTextureCompiler.h
|
* \file SHTextureLoader.h
|
||||||
* \author Loh Xiao Qi
|
* \author Loh Xiao Qi
|
||||||
* \date 30 September 2022
|
* \date 30 September 2022
|
||||||
* \brief Library to write data in SHTextureAsset into binary file for
|
* \brief Library to load dds textures and custom binary format
|
||||||
* faster loading in the future
|
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
@ -12,13 +11,15 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Assets/Asset Types/SHTextureAsset.h"
|
|
||||||
#include "Assets/SHAssetMacros.h"
|
#include "Assets/SHAssetMacros.h"
|
||||||
|
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||||
|
#include "SHAssetLoader.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
struct SHTextureCompiler
|
class SHTextureLoader : public SHAssetLoader
|
||||||
{
|
{
|
||||||
static std::string CompileTextureBinary(SHTextureAsset const& asset, AssetPath path);
|
void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
|
||||||
|
SHAssetData* Load(AssetPath path) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -1,36 +0,0 @@
|
||||||
/*************************************************************************//**
|
|
||||||
* \file SHAssimpLibrary.h
|
|
||||||
* \author Loh Xiao Qi
|
|
||||||
* \date October 2022
|
|
||||||
* \brief
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
|
||||||
* disclosure of this file or its contents without the prior written consent
|
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include <assimp/Importer.hpp>
|
|
||||||
#include <assimp/scene.h>
|
|
||||||
#include <vector>
|
|
||||||
#include "../SHAssetMacros.h"
|
|
||||||
#include "../Asset Types/SHMeshAsset.h"
|
|
||||||
#include "../Asset Types/SHAnimationAsset.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
class SHAssimpLibrary
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
using MeshVectorRef = std::vector<SHMeshAsset*>&;
|
|
||||||
using AnimVectorRef = std::vector<SHAnimationAsset*>&;
|
|
||||||
|
|
||||||
static Assimp::Importer aiImporter;
|
|
||||||
static void ProcessNode(aiNode const& node, aiScene const& scene,MeshVectorRef meshes) noexcept;
|
|
||||||
static void ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept;
|
|
||||||
static SHMeshAsset* ProcessMesh(aiMesh const& mesh) noexcept;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static void LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*************************************************************************//**
|
|
||||||
* \file SHMeshCompiler.cpp
|
|
||||||
* \author Loh Xiao Qi
|
|
||||||
* \date 30 September 2022
|
|
||||||
* \brief Library to write data in SHMeshAsset into binary file for faster
|
|
||||||
* loading in the future
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
|
||||||
* disclosure of this file or its contents without the prior written consent
|
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
|
||||||
*****************************************************************************/
|
|
||||||
#include "SHpch.h"
|
|
||||||
#include "SHMeshCompiler.h"
|
|
||||||
#include "Graphics/MiddleEnd/Meshes/SHMeshData.h"
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
std::string SHADE::SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept
|
|
||||||
{
|
|
||||||
std::string newPath{ path.string() };
|
|
||||||
newPath = newPath.substr(0, newPath.find_last_of('/') + 1);
|
|
||||||
newPath += asset.header.name + MESH_EXTENSION.data();
|
|
||||||
|
|
||||||
std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc };
|
|
||||||
if (!file.is_open())
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Unable to open file for writing mesh file: {}", path.string());
|
|
||||||
}
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&(asset.header.vertexCount)),
|
|
||||||
sizeof(uint32_t)
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<const char*>(&(asset.header.indexCount)),
|
|
||||||
sizeof(uint32_t)
|
|
||||||
);
|
|
||||||
|
|
||||||
auto const vertexVec3Byte {sizeof(SHVec3) * asset.header.vertexCount};
|
|
||||||
auto const vertexVec2Byte {sizeof(SHVec2) * asset.header.vertexCount};
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.vertexPosition.data()),
|
|
||||||
vertexVec3Byte
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.vertexTangent.data()),
|
|
||||||
vertexVec3Byte
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.vertexNormal.data()),
|
|
||||||
vertexVec3Byte
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.texCoords.data()),
|
|
||||||
vertexVec2Byte
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.indices.data()),
|
|
||||||
sizeof(uint32_t) * asset.header.indexCount
|
|
||||||
);
|
|
||||||
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
return newPath;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*************************************************************************//**
|
|
||||||
* \file SHMeshCompiler.h
|
|
||||||
* \author Loh Xiao Qi
|
|
||||||
* \date 30 September 2022
|
|
||||||
* \brief Library to write data in SHMeshAsset into binary file for faster
|
|
||||||
* loading in the future
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
|
||||||
* disclosure of this file or its contents without the prior written consent
|
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
|
||||||
*****************************************************************************/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../Asset Types/SHMeshAsset.h"
|
|
||||||
#include "../SHAssetMacros.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
class SHMeshCompiler
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
public:
|
|
||||||
static std::string CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
/*************************************************************************//**
|
|
||||||
* \file SHTextureCompiler.cpp
|
|
||||||
* \author Loh Xiao Qi
|
|
||||||
* \date 30 September 2022
|
|
||||||
* \brief Library to write data in SHTextureAsset into binary file for
|
|
||||||
* faster loading in the future
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
|
||||||
* disclosure of this file or its contents without the prior written consent
|
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
|
||||||
*****************************************************************************/
|
|
||||||
#include "SHpch.h"
|
|
||||||
#include "SHTextureCompiler.h"
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
std::string SHTextureCompiler::CompileTextureBinary(SHTextureAsset const& asset, AssetPath path)
|
|
||||||
{
|
|
||||||
std::string newPath{ path.string() };
|
|
||||||
newPath = newPath.substr(0, newPath.find_last_of('.'));
|
|
||||||
newPath += TEXTURE_EXTENSION;
|
|
||||||
|
|
||||||
std::ofstream file{ newPath, std::ios::out | std::ios::binary };
|
|
||||||
if (!file.is_open())
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Unable to open file for writing texture file: {}", path.string());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto const intBytes{sizeof(uint32_t)};
|
|
||||||
|
|
||||||
uint32_t mipOffsetCount{ static_cast<uint32_t>(asset.mipOffsets.size()) };
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&asset.numBytes),
|
|
||||||
intBytes
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&asset.width),
|
|
||||||
intBytes
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&asset.height),
|
|
||||||
intBytes
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&asset.format),
|
|
||||||
sizeof(SHTexture::TextureFormat)
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&mipOffsetCount),
|
|
||||||
intBytes
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.mipOffsets.data()),
|
|
||||||
intBytes * asset.mipOffsets.size()
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.pixelData),
|
|
||||||
asset.numBytes
|
|
||||||
);
|
|
||||||
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
return newPath;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,156 +0,0 @@
|
||||||
/*************************************************************************//**
|
|
||||||
* \file SHTextureLoader.cpp
|
|
||||||
* \author Loh Xiao Qi
|
|
||||||
* \date 30 September 2022
|
|
||||||
* \brief Library to load dds textures and custom binary format
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
|
||||||
* disclosure of this file or its contents without the prior written consent
|
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
|
||||||
*****************************************************************************/
|
|
||||||
#include "SHpch.h"
|
|
||||||
#include "SHTextureLoader.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
std::string SHTextureLoader::TinyDDSResultToString(tinyddsloader::Result value)
|
|
||||||
{
|
|
||||||
switch (value)
|
|
||||||
{
|
|
||||||
case tinyddsloader::Result::ErrorFileOpen:
|
|
||||||
return "File open err";
|
|
||||||
case tinyddsloader::Result::ErrorRead:
|
|
||||||
return "File read err";
|
|
||||||
case tinyddsloader::Result::ErrorMagicWord:
|
|
||||||
return "File header magic word err";
|
|
||||||
case tinyddsloader::Result::ErrorSize:
|
|
||||||
return "File size err";
|
|
||||||
case tinyddsloader::Result::ErrorVerify:
|
|
||||||
return "Pixel format err";
|
|
||||||
case tinyddsloader::Result::ErrorNotSupported:
|
|
||||||
return "Unsupported format";
|
|
||||||
case tinyddsloader::Result::ErrorInvalidData:
|
|
||||||
return "Invalid data";
|
|
||||||
default:
|
|
||||||
return "Unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vk::Format SHTextureLoader::ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear)
|
|
||||||
{
|
|
||||||
switch (format)
|
|
||||||
{
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm:
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm_SRGB:
|
|
||||||
return isLinear ? vk::Format::eBc1RgbaUnormBlock : vk::Format::eBc1RgbaSrgbBlock;
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm:
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm_SRGB:
|
|
||||||
return isLinear ? vk::Format::eBc2UnormBlock : vk::Format::eBc2SrgbBlock;
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm:
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm_SRGB:
|
|
||||||
return isLinear ? vk::Format::eBc3UnormBlock : vk::Format::eBc3SrgbBlock;
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::BC5_UNorm:
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::BC5_SNorm:
|
|
||||||
return isLinear ? vk::Format::eBc5UnormBlock : vk::Format::eBc5SnormBlock;
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm:
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm_SRGB:
|
|
||||||
return isLinear ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR8G8B8A8Srgb;
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_SNorm:
|
|
||||||
return vk::Format::eR8G8B8A8Snorm;
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm:
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm_SRGB:
|
|
||||||
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8A8Srgb;
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm:
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm_SRGB:
|
|
||||||
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8Srgb;
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Unsupported DDS format.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHTextureLoader::LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept
|
|
||||||
{
|
|
||||||
tinyddsloader::Result loadResult = tinyddsloader::Result::Success;
|
|
||||||
tinyddsloader::DDSFile file;
|
|
||||||
loadResult = file.Load(path.string().c_str());
|
|
||||||
if (loadResult != tinyddsloader::Result::Success)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Unable to load Texture file: {} at {}", TinyDDSResultToString(loadResult), path.string());
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t totalBytes{ 0 };
|
|
||||||
|
|
||||||
std::vector<uint32_t> mipOff(file.GetMipCount());
|
|
||||||
|
|
||||||
for (size_t i{0}; i < file.GetMipCount(); ++i)
|
|
||||||
{
|
|
||||||
mipOff[i] = static_cast<uint32_t>(totalBytes);
|
|
||||||
totalBytes += file.GetImageData(static_cast<uint32_t>(i), 0)->m_memSlicePitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHTexture::PixelChannel* pixel = new SHTexture::PixelChannel[totalBytes];
|
|
||||||
std::memcpy(pixel, file.GetImageData()->m_mem, totalBytes);
|
|
||||||
//pixel = std::move(reinterpret_cast<SHTexture::PixelChannel const*>(file.GetDDSData()));
|
|
||||||
|
|
||||||
asset.name = path.stem().string();
|
|
||||||
asset.compiled = false;
|
|
||||||
asset.numBytes = static_cast<uint32_t>(totalBytes);
|
|
||||||
asset.width = file.GetWidth();
|
|
||||||
asset.height = file.GetHeight();
|
|
||||||
asset.format = ddsLoaderToVkFormat(file.GetFormat(), true);
|
|
||||||
asset.mipOffsets = std::move(mipOff);
|
|
||||||
asset.pixelData = std::move(pixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHTextureLoader::LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept
|
|
||||||
{
|
|
||||||
std::ifstream file{path.string(), std::ios::in | std::ios::binary};
|
|
||||||
if (!file.is_open())
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Error opening SHTexture file: {}", path.string());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto const intBytes{ sizeof(uint32_t) };
|
|
||||||
uint32_t mipCount;
|
|
||||||
|
|
||||||
file.read(reinterpret_cast<char*>(&asset.numBytes), intBytes);
|
|
||||||
file.read(reinterpret_cast<char*>(&asset.width), intBytes);
|
|
||||||
file.read(reinterpret_cast<char*>(&asset.height), intBytes);
|
|
||||||
file.read(reinterpret_cast<char*>(&asset.format), sizeof(SHTexture::TextureFormat));
|
|
||||||
|
|
||||||
file.read(reinterpret_cast<char*>(&mipCount), intBytes);
|
|
||||||
std::vector<uint32_t> mips(mipCount);
|
|
||||||
file.read(reinterpret_cast<char*>(mips.data()), intBytes * mipCount);
|
|
||||||
|
|
||||||
auto pixel = new SHTexture::PixelChannel[asset.numBytes];
|
|
||||||
file.read(reinterpret_cast<char*>(pixel), asset.numBytes);
|
|
||||||
|
|
||||||
asset.mipOffsets = std::move(mips);
|
|
||||||
asset.pixelData = std::move( pixel );
|
|
||||||
|
|
||||||
asset.compiled = true;
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
SHAssetData* SHTextureLoader::Load(AssetPath path)
|
|
||||||
{
|
|
||||||
auto result = new SHTextureAsset();
|
|
||||||
|
|
||||||
LoadImageAsset(path, *result);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHTextureLoader::LoadImageAsset(AssetPath path, SHTextureAsset& asset)
|
|
||||||
{
|
|
||||||
if (path.extension().string() == DDS_EXTENSION)
|
|
||||||
{
|
|
||||||
LoadTinyDDS(path, asset);
|
|
||||||
}
|
|
||||||
else if (path.extension().string() == TEXTURE_EXTENSION)
|
|
||||||
{
|
|
||||||
LoadSHTexture(path, asset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
/*************************************************************************//**
|
|
||||||
* \file SHTextureLoader.h
|
|
||||||
* \author Loh Xiao Qi
|
|
||||||
* \date 30 September 2022
|
|
||||||
* \brief Library to load dds textures and custom binary format
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
|
||||||
* disclosure of this file or its contents without the prior written consent
|
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
|
||||||
*****************************************************************************/
|
|
||||||
#pragma once
|
|
||||||
#define TINYDDSLOADER_IMPLEMENTATION
|
|
||||||
|
|
||||||
#include "../SHAssetMacros.h"
|
|
||||||
#include "../Asset Types/SHTextureAsset.h"
|
|
||||||
#include "tinyddsloader.h"
|
|
||||||
#include "SHAssetLoader.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
class SHTextureLoader : public SHAssetLoader
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
std::string TinyDDSResultToString(tinyddsloader::Result value);
|
|
||||||
vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
|
|
||||||
|
|
||||||
void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept;
|
|
||||||
public:
|
|
||||||
void LoadImageAsset(AssetPath paths, SHTextureAsset& image);
|
|
||||||
void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
|
|
||||||
SHAssetData* Load(AssetPath path) override;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -42,20 +42,14 @@ constexpr std::string_view ASSET_META_VER { "1.0" };
|
||||||
// Asset type enum
|
// Asset type enum
|
||||||
enum class AssetType : AssetTypeMeta
|
enum class AssetType : AssetTypeMeta
|
||||||
{
|
{
|
||||||
INVALID = 0,
|
INVALID,
|
||||||
AUDIO = 1,
|
|
||||||
SHADER,
|
SHADER,
|
||||||
MATERIAL,
|
SHADER_BUILT_IN,
|
||||||
IMAGE,
|
TEXTURE,
|
||||||
TEXTURE,
|
MESH,
|
||||||
MESH,
|
|
||||||
SCRIPT,
|
|
||||||
SCENE,
|
|
||||||
PREFAB,
|
|
||||||
AUDIO_WAV,
|
|
||||||
DDS,
|
|
||||||
MAX_COUNT
|
MAX_COUNT
|
||||||
};
|
};
|
||||||
|
constexpr size_t TYPE_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) };
|
||||||
|
|
||||||
//Directory
|
//Directory
|
||||||
#ifdef _PUBLISH
|
#ifdef _PUBLISH
|
||||||
|
@ -67,37 +61,55 @@ constexpr std::string_view ASSET_ROOT {"../../Assets"};
|
||||||
|
|
||||||
// ASSET EXTENSIONS
|
// ASSET EXTENSIONS
|
||||||
constexpr std::string_view META_EXTENSION {".shmeta"};
|
constexpr std::string_view META_EXTENSION {".shmeta"};
|
||||||
constexpr std::string_view IMAGE_EXTENSION {".png"};
|
|
||||||
constexpr std::string_view AUDIO_EXTENSION {".ogg"};
|
constexpr std::string_view AUDIO_EXTENSION {".ogg"};
|
||||||
constexpr std::string_view AUDIO_WAV_EXTENSION {".wav"};
|
constexpr std::string_view AUDIO_WAV_EXTENSION {".wav"};
|
||||||
constexpr std::string_view SHADER_EXTENSION {".glsl"};
|
constexpr std::string_view SHADER_EXTENSION{ ".shshader" };
|
||||||
|
constexpr std::string_view SHADER_BUILT_IN_EXTENSION{".shshaderb"};
|
||||||
constexpr std::string_view SCRIPT_EXTENSION {".cs"};
|
constexpr std::string_view SCRIPT_EXTENSION {".cs"};
|
||||||
constexpr std::string_view SCENE_EXTENSION {".SHADE"};
|
constexpr std::string_view SCENE_EXTENSION {".shade"};
|
||||||
constexpr std::string_view PREFAB_EXTENSION {".SHPrefab"};
|
constexpr std::string_view PREFAB_EXTENSION {".shprefab"};
|
||||||
constexpr std::string_view MATERIAL_EXTENSION {".SHMat"};
|
constexpr std::string_view MATERIAL_EXTENSION {".shmat"};
|
||||||
constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
|
constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
|
||||||
constexpr std::string_view DDS_EXTENSION {".dds"};
|
|
||||||
constexpr std::string_view FBX_EXTENSION {".fbx"};
|
|
||||||
constexpr std::string_view GLTF_EXTENSION {".gltf"};
|
|
||||||
constexpr std::string_view MESH_EXTENSION {".shmesh"};
|
constexpr std::string_view MESH_EXTENSION {".shmesh"};
|
||||||
|
|
||||||
constexpr std::string_view EXTENSIONS[] = {
|
constexpr std::string_view EXTENSIONS[] = {
|
||||||
AUDIO_EXTENSION,
|
AUDIO_EXTENSION,
|
||||||
SHADER_EXTENSION,
|
SHADER_EXTENSION,
|
||||||
|
SHADER_BUILT_IN_EXTENSION,
|
||||||
MATERIAL_EXTENSION,
|
MATERIAL_EXTENSION,
|
||||||
IMAGE_EXTENSION,
|
|
||||||
TEXTURE_EXTENSION,
|
TEXTURE_EXTENSION,
|
||||||
DDS_EXTENSION,
|
|
||||||
MESH_EXTENSION,
|
MESH_EXTENSION,
|
||||||
SCRIPT_EXTENSION,
|
SCRIPT_EXTENSION,
|
||||||
SCENE_EXTENSION,
|
SCENE_EXTENSION,
|
||||||
PREFAB_EXTENSION,
|
PREFAB_EXTENSION,
|
||||||
AUDIO_WAV_EXTENSION,
|
AUDIO_WAV_EXTENSION,
|
||||||
|
};
|
||||||
|
|
||||||
|
// EXTERNAL EXTENSIONS
|
||||||
|
constexpr std::string_view GLSL_EXTENSION{ ".glsl" };
|
||||||
|
constexpr std::string_view DDS_EXTENSION{ ".dds" };
|
||||||
|
constexpr std::string_view FBX_EXTENSION{ ".fbx" };
|
||||||
|
constexpr std::string_view GLTF_EXTENSION{ ".gltf" };
|
||||||
|
|
||||||
|
constexpr std::string_view EXTERNALS[] = {
|
||||||
|
GLSL_EXTENSION,
|
||||||
|
DDS_EXTENSION,
|
||||||
FBX_EXTENSION,
|
FBX_EXTENSION,
|
||||||
GLTF_EXTENSION
|
GLTF_EXTENSION
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr size_t TYPE_COUNT {static_cast<size_t>(AssetType::MAX_COUNT) };
|
// SHADER IDENTIFIERS
|
||||||
|
constexpr std::string_view VERTEX_SHADER{ "_VS" };
|
||||||
|
constexpr std::string_view FRAGMENT_SHADER{ "_FS" };
|
||||||
|
constexpr std::string_view COMPUTER_SHADER{ "_CS" };
|
||||||
|
|
||||||
|
constexpr std::string_view SHADER_IDENTIFIERS[] = {
|
||||||
|
VERTEX_SHADER,
|
||||||
|
FRAGMENT_SHADER,
|
||||||
|
COMPUTER_SHADER
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr size_t SHADER_TYPE_MAX_COUNT{ 3 };
|
||||||
|
|
||||||
// Error flags
|
// Error flags
|
||||||
constexpr std::string_view FILE_NOT_FOUND_ERR {"FILE NOT FOUND"};
|
constexpr std::string_view FILE_NOT_FOUND_ERR {"FILE NOT FOUND"};
|
||||||
|
|
|
@ -14,12 +14,13 @@
|
||||||
#include "SHAssetMetaHandler.h"
|
#include "SHAssetMetaHandler.h"
|
||||||
#include "Filesystem/SHFileSystem.h"
|
#include "Filesystem/SHFileSystem.h"
|
||||||
|
|
||||||
#include "Libraries/SHAssimpLibrary.h"
|
#include "Libraries/Loaders/SHMeshLoader.h"
|
||||||
#include "Libraries/SHMeshLoader.h"
|
#include "Libraries/Loaders/SHTextureLoader.h"
|
||||||
#include "Libraries/SHTextureLoader.h"
|
#include "Libraries/Loaders/SHShaderSourceLoader.h"
|
||||||
|
|
||||||
#include "Libraries/SHMeshCompiler.h"
|
#include "Libraries/Compilers/SHMeshCompiler.h"
|
||||||
#include "Libraries/SHTextureCompiler.h"
|
#include "Libraries/Compilers/SHTextureCompiler.h"
|
||||||
|
#include "Libraries/Compilers/SHShaderSourceCompiler.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -44,7 +45,13 @@ namespace SHADE
|
||||||
|
|
||||||
result |= unique;
|
result |= unique;
|
||||||
|
|
||||||
while (result == 0)
|
while (result == 0 ||
|
||||||
|
std::ranges::any_of(
|
||||||
|
assetCollection.begin(),
|
||||||
|
assetCollection.end(),
|
||||||
|
[result](SHAsset const& asset) { return asset.id == result; }
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
result = GenerateAssetID(type);
|
result = GenerateAssetID(type);
|
||||||
}
|
}
|
||||||
|
@ -64,7 +71,20 @@ namespace SHADE
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept
|
void SHAssetManager::Exit() noexcept
|
||||||
|
{
|
||||||
|
for (auto const& loader : loaders)
|
||||||
|
{
|
||||||
|
delete loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto const& data : assetData)
|
||||||
|
{
|
||||||
|
delete data.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept
|
||||||
{
|
{
|
||||||
if (!IsRecognised(path.extension().string().c_str()))
|
if (!IsRecognised(path.extension().string().c_str()))
|
||||||
{
|
{
|
||||||
|
@ -91,17 +111,10 @@ namespace SHADE
|
||||||
|
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case AssetType::SCENE:
|
case AssetType::SHADER:
|
||||||
folder = "scenes/";
|
case AssetType::SHADER_BUILT_IN:
|
||||||
break;
|
folder = "Shaders/";
|
||||||
|
break;
|
||||||
case AssetType::PREFAB:
|
|
||||||
folder = "prefabs/";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AssetType::MATERIAL:
|
|
||||||
folder = "materials/";
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
folder = "/";
|
folder = "/";
|
||||||
|
@ -206,7 +219,56 @@ namespace SHADE
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHAssetManager::IsRecognised(char const* ext) noexcept
|
std::vector<SHAssetData const*> SHAssetManager::GetAllDataOfType(AssetType type) noexcept
|
||||||
|
{
|
||||||
|
auto const toRetrieve = GetAllRecordOfType(type);
|
||||||
|
std::vector<SHAssetData const*> result;
|
||||||
|
result.reserve(toRetrieve.size());
|
||||||
|
for (auto const& get : toRetrieve)
|
||||||
|
{
|
||||||
|
result.push_back(LoadData(get));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<SHAsset> SHAssetManager::GetAllRecordOfType(AssetType type) noexcept
|
||||||
|
{
|
||||||
|
std::vector<SHAsset> result;
|
||||||
|
for (auto const& asset : assetCollection)
|
||||||
|
{
|
||||||
|
if (asset.type == type)
|
||||||
|
{
|
||||||
|
result.push_back(asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetID SHAssetManager::CompileAsset(AssetPath path) noexcept
|
||||||
|
{
|
||||||
|
SHAsset newAsset
|
||||||
|
{
|
||||||
|
.name = path.stem().string(),
|
||||||
|
.location = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
auto const ext{ path.extension().string() };
|
||||||
|
if (ext == GLSL_EXTENSION.data())
|
||||||
|
{
|
||||||
|
newAsset.path = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
|
||||||
|
newAsset.id = GenerateAssetID(AssetType::SHADER_BUILT_IN);
|
||||||
|
newAsset.type = AssetType::SHADER_BUILT_IN;
|
||||||
|
}
|
||||||
|
|
||||||
|
assetCollection.push_back(newAsset);
|
||||||
|
SHAssetMetaHandler::WriteMetaData(newAsset);
|
||||||
|
|
||||||
|
return newAsset.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHAssetManager::IsRecognised(char const* ext) noexcept
|
||||||
{
|
{
|
||||||
for (auto const& e : EXTENSIONS)
|
for (auto const& e : EXTENSIONS)
|
||||||
{
|
{
|
||||||
|
@ -227,23 +289,82 @@ namespace SHADE
|
||||||
result.type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string());
|
result.type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string());
|
||||||
result.id = GenerateAssetID(result.type);
|
result.id = GenerateAssetID(result.type);
|
||||||
result.path = path;
|
result.path = path;
|
||||||
|
result.location = 0;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetManager::InitLoaders() noexcept
|
void SHAssetManager::CompileAll() noexcept
|
||||||
|
{
|
||||||
|
std::vector<AssetPath> paths;
|
||||||
|
|
||||||
|
for (auto const& dir : std::filesystem::recursive_directory_iterator{ ASSET_ROOT })
|
||||||
|
{
|
||||||
|
if (dir.is_regular_file())
|
||||||
|
{
|
||||||
|
for (auto const& ext : EXTERNALS)
|
||||||
|
{
|
||||||
|
if (dir.path().extension().string() == ext.data())
|
||||||
|
{
|
||||||
|
paths.push_back(dir.path());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto const& path : paths)
|
||||||
|
{
|
||||||
|
SHAsset newAsset
|
||||||
|
{
|
||||||
|
.name = path.stem().string(),
|
||||||
|
.location = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
auto const ext{ path.extension().string() };
|
||||||
|
if (ext == GLSL_EXTENSION.data())
|
||||||
|
{
|
||||||
|
newAsset.path = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
|
||||||
|
newAsset.id = GenerateAssetID(AssetType::SHADER_BUILT_IN);
|
||||||
|
newAsset.type = AssetType::SHADER_BUILT_IN;
|
||||||
|
}
|
||||||
|
else if (ext == DDS_EXTENSION.data())
|
||||||
|
{
|
||||||
|
newAsset.path = SHTextureCompiler::CompileTextureAsset(path).value();
|
||||||
|
newAsset.id = GenerateAssetID(AssetType::TEXTURE);
|
||||||
|
newAsset.type = AssetType::TEXTURE;
|
||||||
|
}
|
||||||
|
else if (ext == GLTF_EXTENSION.data() || ext == FBX_EXTENSION.data())
|
||||||
|
{
|
||||||
|
std::vector<SHMeshAsset*> meshes;
|
||||||
|
std::vector<SHAnimationAsset*> anims;
|
||||||
|
SHMeshCompiler::LoadFromFile(path, meshes, anims);
|
||||||
|
|
||||||
|
for (auto const& mesh : meshes)
|
||||||
|
{
|
||||||
|
SHAsset meshAsset{
|
||||||
|
.name = mesh->header.name,
|
||||||
|
.location = 0
|
||||||
|
};
|
||||||
|
meshAsset.path = SHMeshCompiler::CompileMeshBinary(*mesh, path).value();
|
||||||
|
meshAsset.id = GenerateAssetID(AssetType::MESH);
|
||||||
|
meshAsset.type = AssetType::MESH;
|
||||||
|
assetCollection.push_back(meshAsset);
|
||||||
|
SHAssetMetaHandler::WriteMetaData(meshAsset);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
assetCollection.push_back(newAsset);
|
||||||
|
SHAssetMetaHandler::WriteMetaData(newAsset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetManager::InitLoaders() noexcept
|
||||||
{
|
{
|
||||||
loaders[static_cast<size_t>(AssetType::AUDIO)] = nullptr;
|
loaders[static_cast<size_t>(AssetType::SHADER)] = dynamic_cast<SHAssetLoader*>(new SHShaderSourceLoader());
|
||||||
loaders[static_cast<size_t>(AssetType::SHADER)] = nullptr;
|
loaders[static_cast<size_t>(AssetType::SHADER_BUILT_IN)] = loaders[static_cast<size_t>(AssetType::SHADER)];
|
||||||
loaders[static_cast<size_t>(AssetType::MATERIAL)] = nullptr;
|
loaders[static_cast<size_t>(AssetType::TEXTURE)] = dynamic_cast<SHAssetLoader*>(new SHTextureLoader());
|
||||||
loaders[static_cast<size_t>(AssetType::IMAGE)] = dynamic_cast<SHAssetLoader*>(new SHTextureLoader());
|
loaders[static_cast<size_t>(AssetType::MESH)] = dynamic_cast<SHAssetLoader*>(new SHMeshLoader());
|
||||||
loaders[static_cast<size_t>(AssetType::TEXTURE)] = nullptr;
|
|
||||||
loaders[static_cast<size_t>(AssetType::MESH)] = dynamic_cast<SHAssetLoader*>(new SHMeshLoader());
|
|
||||||
loaders[static_cast<size_t>(AssetType::SCRIPT)] = nullptr;
|
|
||||||
loaders[static_cast<size_t>(AssetType::SCENE)] = nullptr;
|
|
||||||
loaders[static_cast<size_t>(AssetType::PREFAB)] = nullptr;
|
|
||||||
loaders[static_cast<size_t>(AssetType::AUDIO_WAV)] = nullptr;
|
|
||||||
loaders[static_cast<size_t>(AssetType::DDS)] = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -251,6 +372,7 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void SHAssetManager::Load() noexcept
|
void SHAssetManager::Load() noexcept
|
||||||
{
|
{
|
||||||
|
//CompileAll();
|
||||||
InitLoaders();
|
InitLoaders();
|
||||||
BuildAssetCollection();
|
BuildAssetCollection();
|
||||||
//LoadAllData();
|
//LoadAllData();
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include "tinyddsloader.h"
|
#include "tinyddsloader.h"
|
||||||
#include "SHAsset.h"
|
#include "SHAsset.h"
|
||||||
#include "Asset Types/SHAssetData.h"
|
#include "Asset Types/SHAssetData.h"
|
||||||
#include "Libraries/SHAssetLoader.h"
|
#include "Assets/Libraries/Loaders/SHAssetLoader.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
|
@ -37,6 +37,8 @@ namespace SHADE
|
||||||
static void Unload() noexcept;
|
static void Unload() noexcept;
|
||||||
static void Unload(AssetID assetId) noexcept;
|
static void Unload(AssetID assetId) noexcept;
|
||||||
|
|
||||||
|
static void Exit() noexcept;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Load all resources that are in the folder
|
* \brief Load all resources that are in the folder
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
@ -77,21 +79,24 @@ namespace SHADE
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T const* const> GetData(AssetID id) noexcept;
|
static std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T const* const> GetData(AssetID id) noexcept;
|
||||||
|
|
||||||
|
static std::vector<SHAssetData const*> GetAllDataOfType(AssetType type) noexcept;
|
||||||
|
static std::vector<SHAsset> GetAllRecordOfType(AssetType type) noexcept;
|
||||||
|
|
||||||
|
static AssetID CompileAsset(AssetPath path) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/****************************************************************************
|
|
||||||
* \brief Load resource data into memory
|
static void InitLoaders() noexcept;
|
||||||
****************************************************************************/
|
|
||||||
static void LoadAllData() noexcept;
|
static void LoadAllData() noexcept;
|
||||||
|
|
||||||
static SHAssetData* LoadData(SHAsset const& asset) noexcept;
|
static SHAssetData* LoadData(SHAsset const& asset) noexcept;
|
||||||
|
|
||||||
inline static void BuildAssetCollection() noexcept;
|
inline static void BuildAssetCollection() noexcept;
|
||||||
|
|
||||||
static bool IsRecognised(char const*) noexcept;
|
static bool IsRecognised(char const*) noexcept;
|
||||||
|
|
||||||
static SHAsset CreateAssetFromPath(AssetPath path) noexcept;
|
static SHAsset CreateAssetFromPath(AssetPath path) noexcept;
|
||||||
|
|
||||||
static void InitLoaders() noexcept;
|
static void CompileAll() noexcept;
|
||||||
|
|
||||||
static FMOD::System* audioSystem;
|
static FMOD::System* audioSystem;
|
||||||
static std::unordered_map<AssetID,SHSound>* audioSoundList;
|
static std::unordered_map<AssetID,SHSound>* audioSoundList;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "SHCameraSystem.h"
|
#include "SHCameraSystem.h"
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
|
#include "Math/SHMath.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -28,7 +29,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
||||||
SHVec3 rotation = transform->GetWorldRotation();
|
SHVec3 rotation = transform->GetWorldRotation();
|
||||||
transform->SetWorldRotation(SHVec3{rotation.x,yaw, rotation.z});
|
transform->SetWorldRotation(SHVec3{rotation.x,SHMath::DegreesToRadians(yaw), rotation.z});
|
||||||
}
|
}
|
||||||
dirtyView = true;
|
dirtyView = true;
|
||||||
}
|
}
|
||||||
|
@ -40,7 +41,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
||||||
SHVec3 rotation = transform->GetWorldRotation();
|
SHVec3 rotation = transform->GetWorldRotation();
|
||||||
transform->SetWorldRotation(SHVec3{ pitch,rotation.y, rotation.z });
|
transform->SetWorldRotation(SHVec3{ SHMath::DegreesToRadians(pitch),rotation.y, rotation.z });
|
||||||
}
|
}
|
||||||
dirtyView = true;
|
dirtyView = true;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +53,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
||||||
SHVec3 rotation = transform->GetWorldRotation();
|
SHVec3 rotation = transform->GetWorldRotation();
|
||||||
transform->SetWorldRotation(SHVec3{ rotation.x,rotation.y, roll});
|
transform->SetWorldRotation(SHVec3{ rotation.x,rotation.y, SHMath::DegreesToRadians(roll)});
|
||||||
}
|
}
|
||||||
dirtyView = true;
|
dirtyView = true;
|
||||||
}
|
}
|
||||||
|
@ -102,7 +103,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
dirtyView = true;
|
dirtyView = true;
|
||||||
}
|
}
|
||||||
void SHCameraComponent::SetPosition(SHVec3& pos) noexcept
|
void SHCameraComponent::SetPosition(SHVec3 pos) noexcept
|
||||||
{
|
{
|
||||||
this->position = pos;
|
this->position = pos;
|
||||||
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
|
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
|
||||||
|
@ -145,6 +146,17 @@ namespace SHADE
|
||||||
dirtyProj = true;
|
dirtyProj = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHCameraComponent::SetIsPerspective(bool persp) noexcept
|
||||||
|
{
|
||||||
|
this->perspProj = persp;
|
||||||
|
dirtyProj = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHVec3 SHCameraComponent::GetPosition() const noexcept
|
||||||
|
{
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
float SHCameraComponent::GetYaw() const noexcept
|
float SHCameraComponent::GetYaw() const noexcept
|
||||||
{
|
{
|
||||||
return yaw;
|
return yaw;
|
||||||
|
@ -158,6 +170,27 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
return roll;
|
return roll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float SHCameraComponent::GetWidth() const noexcept
|
||||||
|
{
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
float SHCameraComponent::GetHeight() const noexcept
|
||||||
|
{
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
float SHCameraComponent::GetNear() const noexcept
|
||||||
|
{
|
||||||
|
return zNear;
|
||||||
|
}
|
||||||
|
|
||||||
|
float SHCameraComponent::GetFar() const noexcept
|
||||||
|
{
|
||||||
|
return zFar;
|
||||||
|
}
|
||||||
|
|
||||||
float SHCameraComponent::GetAspectRatio() const noexcept
|
float SHCameraComponent::GetAspectRatio() const noexcept
|
||||||
{
|
{
|
||||||
return width/height;
|
return width/height;
|
||||||
|
@ -168,6 +201,11 @@ namespace SHADE
|
||||||
return fov;
|
return fov;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SHCameraComponent::GetIsPerspective() const noexcept
|
||||||
|
{
|
||||||
|
return perspProj;
|
||||||
|
}
|
||||||
|
|
||||||
const SHMatrix& SHCameraComponent::GetViewMatrix() const noexcept
|
const SHMatrix& SHCameraComponent::GetViewMatrix() const noexcept
|
||||||
{
|
{
|
||||||
return viewMatrix;
|
return viewMatrix;
|
||||||
|
@ -178,12 +216,32 @@ namespace SHADE
|
||||||
return projMatrix;
|
return projMatrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCameraComponent::SetMainCamera(size_t directorCameraIndex) noexcept
|
//void SHCameraComponent::SetMainCamera(size_t directorCameraIndex) noexcept
|
||||||
{
|
//{
|
||||||
auto system = SHSystemManager::GetSystem<SHCameraSystem>();
|
// auto system = SHSystemManager::GetSystem<SHCameraSystem>();
|
||||||
system->GetDirector(directorCameraIndex)->SetMainCamera(*this);
|
// system->GetDirector(directorCameraIndex)->SetMainCamera(*this);
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}//namespace SHADE
|
||||||
|
|
||||||
|
|
||||||
|
RTTR_REGISTRATION
|
||||||
|
{
|
||||||
|
using namespace SHADE;
|
||||||
|
using namespace rttr;
|
||||||
|
|
||||||
|
registration::class_<SHCameraComponent>("Camera Component")
|
||||||
|
.property("Position", &SHCameraComponent::GetPosition, select_overload<void(SHVec3)>(&SHCameraComponent::SetPosition))
|
||||||
|
.property("Pitch", &SHCameraComponent::GetPitch, &SHCameraComponent::SetPitch)
|
||||||
|
.property("Yaw", &SHCameraComponent::GetYaw, &SHCameraComponent::SetYaw)
|
||||||
|
.property("Roll", &SHCameraComponent::GetRoll, &SHCameraComponent::SetRoll)
|
||||||
|
.property("Width", &SHCameraComponent::GetWidth, &SHCameraComponent::SetWidth)
|
||||||
|
.property("Height", &SHCameraComponent::GetHeight, &SHCameraComponent::SetHeight)
|
||||||
|
.property("Near", &SHCameraComponent::GetNear, &SHCameraComponent::SetNear)
|
||||||
|
.property("Far", &SHCameraComponent::GetFar, &SHCameraComponent::SetFar)
|
||||||
|
.property("Perspective", &SHCameraComponent::GetIsPerspective, &SHCameraComponent::SetIsPerspective);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <rttr/registration>
|
||||||
|
|
||||||
#include "ECS_Base/Components/SHComponent.h"
|
#include "ECS_Base/Components/SHComponent.h"
|
||||||
#include "Math/Vector/SHVec3.h"
|
#include "Math/Vector/SHVec3.h"
|
||||||
#include "Math/SHMatrix.h"
|
#include "Math/SHMatrix.h"
|
||||||
|
@ -50,37 +52,44 @@ namespace SHADE
|
||||||
void SetPositionY(float y) noexcept;
|
void SetPositionY(float y) noexcept;
|
||||||
void SetPositionZ(float z) noexcept;
|
void SetPositionZ(float z) noexcept;
|
||||||
void SetPosition(float x, float y, float z) noexcept;
|
void SetPosition(float x, float y, float z) noexcept;
|
||||||
void SetPosition(SHVec3& pos) noexcept;
|
void SetPosition(SHVec3 pos) noexcept;
|
||||||
|
|
||||||
void SetWidth(float width) noexcept;
|
void SetWidth(float width) noexcept;
|
||||||
void SetHeight(float height) noexcept;
|
void SetHeight(float height) noexcept;
|
||||||
void SetNear(float znear) noexcept;
|
void SetNear(float znear) noexcept;
|
||||||
void SetFar(float zfar) noexcept;
|
void SetFar(float zfar) noexcept;
|
||||||
void SetFOV(float fov) noexcept;
|
void SetFOV(float fov) noexcept;
|
||||||
|
void SetIsPerspective(bool persp) noexcept;
|
||||||
|
|
||||||
|
|
||||||
|
SHVec3 GetPosition() const noexcept;
|
||||||
float GetYaw() const noexcept;
|
float GetYaw() const noexcept;
|
||||||
float GetPitch() const noexcept;
|
float GetPitch() const noexcept;
|
||||||
float GetRoll() const noexcept;
|
float GetRoll() const noexcept;
|
||||||
|
|
||||||
|
float GetWidth() const noexcept;
|
||||||
|
float GetHeight() const noexcept;
|
||||||
|
float GetNear() const noexcept;
|
||||||
|
float GetFar() const noexcept;
|
||||||
|
|
||||||
float GetAspectRatio() const noexcept;
|
float GetAspectRatio() const noexcept;
|
||||||
float GetFOV() const noexcept;
|
float GetFOV() const noexcept;
|
||||||
|
bool GetIsPerspective() const noexcept;
|
||||||
|
|
||||||
const SHMatrix& GetViewMatrix() const noexcept;
|
const SHMatrix& GetViewMatrix() const noexcept;
|
||||||
const SHMatrix& GetProjMatrix() const noexcept;
|
const SHMatrix& GetProjMatrix() const noexcept;
|
||||||
|
|
||||||
void SetMainCamera(size_t cameraDirectorIndex = 0) noexcept;
|
//void SetMainCamera(size_t cameraDirectorIndex = 0) noexcept;
|
||||||
|
|
||||||
|
|
||||||
float movementSpeed;
|
float movementSpeed;
|
||||||
SHVec3 turnSpeed;
|
SHVec3 turnSpeed;
|
||||||
|
RTTR_ENABLE()
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,7 @@ namespace SHADE
|
||||||
SHVec3 view, right, UP;
|
SHVec3 view, right, UP;
|
||||||
|
|
||||||
|
|
||||||
//ClampCameraRotation(camera);
|
ClampCameraRotation(camera);
|
||||||
|
|
||||||
GetCameraAxis(camera, view, right, UP);
|
GetCameraAxis(camera, view, right, UP);
|
||||||
|
|
||||||
|
@ -221,8 +221,8 @@ namespace SHADE
|
||||||
SHVec3 up = { 0.0f,1.0f,0.0f };
|
SHVec3 up = { 0.0f,1.0f,0.0f };
|
||||||
|
|
||||||
|
|
||||||
|
target = SHVec3::RotateX(target, SHMath::DegreesToRadians(camera.pitch));
|
||||||
target = SHVec3::RotateY(target, SHMath::DegreesToRadians(camera.yaw));
|
target = SHVec3::RotateY(target, SHMath::DegreesToRadians(camera.yaw));
|
||||||
target =SHVec3::RotateX(target, SHMath::DegreesToRadians(camera.pitch));
|
|
||||||
target += camera.position;
|
target += camera.position;
|
||||||
////SHVec3::RotateZ(target, SHMath::DegreesToRadians(camera.roll));
|
////SHVec3::RotateZ(target, SHMath::DegreesToRadians(camera.roll));
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHAssetBrowser.h"
|
||||||
|
|
||||||
|
#include "Editor/IconsMaterialDesign.h"
|
||||||
|
#include "Editor/SHImGuiHelpers.hpp"
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include "Assets/SHAssetManager.h"
|
||||||
|
#include "Editor/DragDrop/SHDragDrop.hpp"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
SHAssetBrowser::SHAssetBrowser()
|
||||||
|
:SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::Init()
|
||||||
|
{
|
||||||
|
SHEditorWindow::Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::Update()
|
||||||
|
{
|
||||||
|
SHEditorWindow::Update();
|
||||||
|
if(Begin())
|
||||||
|
{
|
||||||
|
DrawMenuBar();
|
||||||
|
auto const& assets = SHAssetManager::GetAllAssets();
|
||||||
|
if(ImGui::BeginTable("AssetBrowserTable", 3))
|
||||||
|
{
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TableHeader("Asset ID");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TableHeader("Name");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TableHeader("Type");
|
||||||
|
for(SHAsset const& asset : assets)
|
||||||
|
{
|
||||||
|
DrawAsset(asset);
|
||||||
|
}
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::DrawMenuBar()
|
||||||
|
{
|
||||||
|
if(ImGui::BeginMenuBar())
|
||||||
|
{
|
||||||
|
|
||||||
|
ImGui::EndMenuBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::DrawAsset(SHAsset const& asset)
|
||||||
|
{
|
||||||
|
ImGui::PushID(asset.id);
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Selectable(std::format("{}", asset.id).data(), false, ImGuiSelectableFlags_SpanAllColumns);
|
||||||
|
if(SHDragDrop::BeginSource())
|
||||||
|
{
|
||||||
|
auto id = asset.id;
|
||||||
|
ImGui::Text("Moving Asset: %zu", id);
|
||||||
|
SHDragDrop::SetPayload<AssetID>(DRAG_RESOURCE, &id);
|
||||||
|
SHDragDrop::EndSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%s", asset.name.c_str());
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%s", "Type");
|
||||||
|
|
||||||
|
ImGui::EndGroup();
|
||||||
|
ImGui::PopID();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Assets/SHAsset.h"
|
||||||
|
#include "Editor/EditorWindow/SHEditorWindow.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHAssetBrowser final : public SHEditorWindow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SHAssetBrowser();
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
void Update();
|
||||||
|
|
||||||
|
void Refresh();
|
||||||
|
private:
|
||||||
|
void DrawMenuBar();
|
||||||
|
void DrawAsset(SHAsset const& asset);
|
||||||
|
|
||||||
|
float idColumnWidth, nameColumnWidth, typeColumnWidth;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -93,8 +93,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
if (ImGui::BeginMenuBar())
|
if (ImGui::BeginMenuBar())
|
||||||
{
|
{
|
||||||
|
ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x * 0.75f);
|
||||||
ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x - 35.0f);
|
|
||||||
if(ImGui::SmallButton(ICON_MD_DESELECT))
|
if(ImGui::SmallButton(ICON_MD_DESELECT))
|
||||||
{
|
{
|
||||||
auto editor = SHSystemManager::GetSystem<SHEditor>();
|
auto editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
|
|
@ -39,6 +39,10 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHComponentManager::RemoveComponent<T>(component->GetEID());
|
SHComponentManager::RemoveComponent<T>(component->GetEID());
|
||||||
}
|
}
|
||||||
|
if (ImGui::Selectable(std::format("{} Reset {}", ICON_MD_RESTART_ALT, componentName.data()).data()))
|
||||||
|
{
|
||||||
|
*component = T();
|
||||||
|
}
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +52,7 @@ namespace SHADE
|
||||||
if (!component)
|
if (!component)
|
||||||
return;
|
return;
|
||||||
const auto componentType = rttr::type::get(*component);
|
const auto componentType = rttr::type::get(*component);
|
||||||
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; });
|
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::CollapsingHeader(componentType.get_name().data()))
|
if (ImGui::CollapsingHeader(componentType.get_name().data()))
|
||||||
{
|
{
|
||||||
|
@ -89,7 +93,7 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin && metaMax)
|
if (metaMin && metaMax)
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value<int>(), metaMin.template get_value<int>(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); });
|
SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value<int>(), metaMax.template get_value<int>(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -115,7 +119,7 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value<uint16_t>(), metaMin.template get_value<uint16_t>(), [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, "%zu");
|
SHEditorWidgets::SliderScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value<uint16_t>(), metaMax.template get_value<uint16_t>(), [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, "%zu");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -128,7 +132,7 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value<uint32_t>(), metaMin.template get_value<uint32_t>(), [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, "%zu");
|
SHEditorWidgets::SliderScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value<uint32_t>(), metaMax.template get_value<uint32_t>(), [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, "%zu");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -141,7 +145,7 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value<uint64_t>(), metaMin.template get_value<uint64_t>(), [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, "%zu");
|
SHEditorWidgets::SliderScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value<uint64_t>(), metaMax.template get_value<uint64_t>(), [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, "%zu");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -152,13 +156,18 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
auto metaMin = property.get_metadata(META::min);
|
auto metaMin = property.get_metadata(META::min);
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
|
float min{}, max{};
|
||||||
|
if(metaMin.is_valid())
|
||||||
|
min = std::max(metaMin.template get_value<float>(), -FLT_MAX * 0.5f);
|
||||||
|
if(metaMax.is_valid())
|
||||||
|
max = std::min(metaMax.template get_value<float>(), FLT_MAX * 0.5f);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderFloat(property.get_name().data(), metaMin.template get_value<float>(), metaMin.template get_value<float>(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); });
|
SHEditorWidgets::SliderFloat(property.get_name().data(), min, max, [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragFloat(property.get_name().data(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); });
|
SHEditorWidgets::DragFloat(property.get_name().data(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }, "Test");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == rttr::type::get<double>())
|
else if (type == rttr::type::get<double>())
|
||||||
|
@ -167,7 +176,7 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderScalar<double>(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value<double>(), metaMin.template get_value<double>(), [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); });
|
SHEditorWidgets::SliderScalar<double>(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value<double>(), metaMax.template get_value<double>(), [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -198,6 +207,10 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
if (!component)
|
if (!component)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Get transform component for extrapolating relative sizes
|
||||||
|
auto* transformComponent = SHComponentManager::GetComponent<SHTransformComponent>(component->GetEID());
|
||||||
|
|
||||||
const auto componentType = rttr::type::get(*component);
|
const auto componentType = rttr::type::get(*component);
|
||||||
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; });
|
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; });
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
@ -212,28 +225,41 @@ namespace SHADE
|
||||||
for (int i{}; i < size; ++i)
|
for (int i{}; i < size; ++i)
|
||||||
{
|
{
|
||||||
ImGui::PushID(i);
|
ImGui::PushID(i);
|
||||||
SHCollider& collider = component->GetCollider(i);
|
SHCollider* collider = &component->GetCollider(i);
|
||||||
auto cursorPos = ImGui::GetCursorPos();
|
auto cursorPos = ImGui::GetCursorPos();
|
||||||
|
|
||||||
if (collider.GetType() == SHCollider::Type::BOX)
|
if (collider->GetType() == SHCollider::Type::BOX)
|
||||||
{
|
{
|
||||||
SHEditorWidgets::BeginPanel( std::format("{} Box Collider #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
SHEditorWidgets::BeginPanel( std::format("{} Box Collider #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
||||||
auto box = reinterpret_cast<SHBoundingBox*>(collider.GetShape());
|
auto box = reinterpret_cast<SHBoundingBox*>(collider->GetShape());
|
||||||
SHEditorWidgets::DragVec3("Half Extents", { "X", "Y", "Z" }, [box] {return box->GetHalfExtents(); }, [box](SHVec3 const& vec) {box->SetHalfExtents(vec);});
|
SHEditorWidgets::DragVec3
|
||||||
|
(
|
||||||
|
"Half Extents", { "X", "Y", "Z" },
|
||||||
|
[box, transformComponent] { return (transformComponent->GetWorldScale() * 2.0f) * box->GetHalfExtents(); },
|
||||||
|
[collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); });
|
||||||
}
|
}
|
||||||
else if (collider.GetType() == SHCollider::Type::SPHERE)
|
else if (collider->GetType() == SHCollider::Type::SPHERE)
|
||||||
{
|
{
|
||||||
SHEditorWidgets::BeginPanel(std::format("{} Sphere Collider #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
SHEditorWidgets::BeginPanel(std::format("{} Sphere Collider #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
||||||
auto sphere = reinterpret_cast<SHBoundingSphere*>(collider.GetShape());
|
auto sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape());
|
||||||
SHEditorWidgets::DragFloat("Radius", [sphere] {return sphere->GetRadius(); }, [sphere](float const& value) {sphere->SetRadius(value);});
|
SHEditorWidgets::DragFloat
|
||||||
|
(
|
||||||
|
"Radius",
|
||||||
|
[sphere, transformComponent]
|
||||||
|
{
|
||||||
|
const SHVec3& TF_WORLD_SCALE = transformComponent->GetWorldScale();
|
||||||
|
const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z });
|
||||||
|
return sphere->GetRadius() / MAX_SCALE;
|
||||||
|
},
|
||||||
|
[collider](float const& value) { collider->SetBoundingSphere(value);});
|
||||||
}
|
}
|
||||||
else if (collider.GetType() == SHCollider::Type::CAPSULE)
|
else if (collider->GetType() == SHCollider::Type::CAPSULE)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
SHEditorWidgets::BeginPanel("Offset", { ImGui::GetContentRegionAvail().x, 30.0f });
|
SHEditorWidgets::BeginPanel("Offset", { ImGui::GetContentRegionAvail().x, 30.0f });
|
||||||
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [&collider] {return collider.GetPositionOffset(); }, [&collider](SHVec3 const& vec) {collider.SetPositionOffset(vec); });
|
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [&collider] {return collider->GetPositionOffset(); }, [&collider](SHVec3 const& vec) {collider->SetPositionOffset(vec); });
|
||||||
SHEditorWidgets::EndPanel();
|
SHEditorWidgets::EndPanel();
|
||||||
}
|
}
|
||||||
if(ImGui::Button(std::format("{} Remove Collider #{}", ICON_MD_REMOVE, i).data()))
|
if(ImGui::Button(std::format("{} Remove Collider #{}", ICON_MD_REMOVE, i).data()))
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "AudioSystem/SHAudioSystem.h"
|
#include "AudioSystem/SHAudioSystem.h"
|
||||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
#include "Physics/Components/SHRigidBodyComponent.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Components/SHColliderComponent.h"
|
||||||
|
#include "Camera/SHCameraComponent.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -35,6 +36,23 @@ namespace SHADE
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ComponentType, typename EnforcedComponent, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true, std::enable_if_t<std::is_base_of_v<SHComponent, EnforcedComponent>, bool> = true>
|
||||||
|
bool DrawAddComponentWithEnforcedComponentButton(EntityID const& eid)
|
||||||
|
{
|
||||||
|
bool selected = false;
|
||||||
|
if (!SHComponentManager::HasComponent<ComponentType>(eid))
|
||||||
|
{
|
||||||
|
if(selected = ImGui::Selectable(std::format("Add {}", rttr::type::get<ComponentType>().get_name().data()).data()); selected)
|
||||||
|
{
|
||||||
|
if(SHComponentManager::GetComponent_s<EnforcedComponent>(eid) == nullptr)
|
||||||
|
SHComponentManager::AddComponent<EnforcedComponent>(eid);
|
||||||
|
|
||||||
|
SHComponentManager::AddComponent<ComponentType>(eid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
SHEditorInspector::SHEditorInspector()
|
SHEditorInspector::SHEditorInspector()
|
||||||
:SHEditorWindow("Inspector", ImGuiWindowFlags_MenuBar)
|
:SHEditorWindow("Inspector", ImGuiWindowFlags_MenuBar)
|
||||||
{
|
{
|
||||||
|
@ -82,23 +100,27 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
DrawComponent(rigidbodyComponent);
|
DrawComponent(rigidbodyComponent);
|
||||||
}
|
}
|
||||||
|
if (auto cameraComponent = SHComponentManager::GetComponent_s<SHCameraComponent>(eid))
|
||||||
|
{
|
||||||
|
DrawComponent(cameraComponent);
|
||||||
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
// Render Scripts
|
// Render Scripts
|
||||||
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||||
scriptEngine->RenderScriptsInInspector(eid);
|
scriptEngine->RenderScriptsInInspector(eid);
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data()))
|
if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data()))
|
||||||
{
|
{
|
||||||
DrawAddComponentButton<SHTransformComponent>(eid);
|
DrawAddComponentButton<SHTransformComponent>(eid);
|
||||||
DrawAddComponentButton<SHRenderable>(eid);
|
DrawAddComponentButton<SHCameraComponent>(eid);
|
||||||
DrawAddComponentButton<SHColliderComponent>(eid);
|
|
||||||
if(DrawAddComponentButton<SHRigidBodyComponent>(eid))
|
// Components that require Transforms
|
||||||
{
|
|
||||||
if(SHComponentManager::GetComponent_s<SHTransformComponent>(eid) == nullptr)
|
DrawAddComponentWithEnforcedComponentButton<SHRenderable, SHTransformComponent>(eid);
|
||||||
{
|
DrawAddComponentWithEnforcedComponentButton<SHRigidBodyComponent, SHTransformComponent>(eid);
|
||||||
SHComponentManager::AddComponent<SHTransformComponent>(eid);
|
DrawAddComponentWithEnforcedComponentButton<SHColliderComponent, SHTransformComponent>(eid);
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,4 +3,5 @@
|
||||||
#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel
|
#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel
|
||||||
#include "Inspector/SHEditorInspector.h" //Inspector
|
#include "Inspector/SHEditorInspector.h" //Inspector
|
||||||
#include "Profiling/SHEditorProfiler.h" //Profiler
|
#include "Profiling/SHEditorProfiler.h" //Profiler
|
||||||
#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport
|
#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport
|
||||||
|
#include "AssetBrowser/SHAssetBrowser.h" //Asset Browser
|
|
@ -24,12 +24,13 @@ namespace SHADE
|
||||||
void SHEditorViewport::Init()
|
void SHEditorViewport::Init()
|
||||||
{
|
{
|
||||||
SHEditorWindow::Init();
|
SHEditorWindow::Init();
|
||||||
|
transformGizmo.Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHEditorViewport::Update()
|
void SHEditorViewport::Update()
|
||||||
{
|
{
|
||||||
SHEditorWindow::Update();
|
SHEditorWindow::Update();
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f,0.0f));
|
||||||
if(Begin())
|
if(Begin())
|
||||||
{
|
{
|
||||||
ImGuizmo::SetDrawlist();
|
ImGuizmo::SetDrawlist();
|
||||||
|
@ -55,7 +56,7 @@ namespace SHADE
|
||||||
ImGuizmo::SetRect(beginCursorPos.x , beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y);
|
ImGuizmo::SetRect(beginCursorPos.x , beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y);
|
||||||
transformGizmo.Draw();
|
transformGizmo.Draw();
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
ImGui::PopStyleVar();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHEditorViewport::Exit()
|
void SHEditorViewport::Exit()
|
||||||
|
|
|
@ -13,6 +13,12 @@
|
||||||
#include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h"
|
#include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h"
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
void SHTransformGizmo::Init()
|
||||||
|
{
|
||||||
|
auto& style = ImGuizmo::GetStyle();
|
||||||
|
style.RotationLineThickness = 2.5f;
|
||||||
|
}
|
||||||
|
|
||||||
void SHTransformGizmo::Draw()
|
void SHTransformGizmo::Draw()
|
||||||
{
|
{
|
||||||
bool justChangedTfm = false;
|
bool justChangedTfm = false;
|
||||||
|
@ -26,9 +32,12 @@ namespace SHADE
|
||||||
|
|
||||||
SHMatrix view = SHMatrix::Transpose(editorCamera->GetViewMatrix());
|
SHMatrix view = SHMatrix::Transpose(editorCamera->GetViewMatrix());
|
||||||
SHMatrix proj = SHMatrix::Transpose(editorCamera->GetProjMatrix());
|
SHMatrix proj = SHMatrix::Transpose(editorCamera->GetProjMatrix());
|
||||||
|
|
||||||
|
//Invert projection y-axis
|
||||||
proj(1, 1) *= -1;
|
proj(1, 1) *= -1;
|
||||||
|
|
||||||
static SHMatrix gridMat = SHMatrix::Translate(0, -0.5f, 0.f) * SHMatrix::Identity;
|
static SHMatrix gridMat = SHMatrix::Translate(0, -0.5f, 0.f) * SHMatrix::Identity;
|
||||||
//ImGuizmo::DrawGrid(&view._11, &proj._11, &gridMat._11, 100.f);
|
|
||||||
if (selectedEntityTransformComponent == nullptr)
|
if (selectedEntityTransformComponent == nullptr)
|
||||||
{
|
{
|
||||||
SHEditor* editor = SHSystemManager::GetSystem<SHEditor>();
|
SHEditor* editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
@ -55,31 +64,37 @@ namespace SHADE
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SHMatrix mat = selectedEntityTransformComponent->GetTRS();
|
SHMatrix mat = selectedEntityTransformComponent->GetTRS();
|
||||||
isManipulating = ImGuizmo::Manipulate(&view._11, &proj._11, static_cast<ImGuizmo::OPERATION>(operation), ImGuizmo::MODE::WORLD, &mat._11);
|
useSnap = ImGui::IsKeyDown(ImGuiKey_LeftCtrl);
|
||||||
if (!justChangedTfm)
|
if(useSnap)
|
||||||
{
|
{
|
||||||
if (ImGui::IsItemClicked())
|
switch (operation)
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHMatrix>>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = std::move(selectedEntityTransformComponent)](SHMatrix const& mtx)
|
{
|
||||||
{
|
case Operation::TRANSLATE: snap = &translationSnap.x; break;
|
||||||
if (!tfm)
|
case Operation::ROTATE: snap = &rotationSnap; break;
|
||||||
return;
|
case Operation::SCALE: snap = &scaleSnap; break;
|
||||||
SHVec3 translate{}, rotate{}, scale{};
|
default: snap = &translationSnap.x;
|
||||||
mtx.Decompose(translate, rotate, scale);
|
}
|
||||||
tfm->SetWorldPosition(translate);
|
|
||||||
tfm->SetWorldRotation(rotate);
|
|
||||||
tfm->SetWorldScale(scale);
|
|
||||||
})));
|
|
||||||
else if (ImGui::IsItemHovered(ImGuiMouseButton_Left) && ImGui::IsMouseDown(ImGuiMouseButton_Left) && isManipulating)
|
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHMatrix>>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = std::move(selectedEntityTransformComponent)](SHMatrix const& mtx)
|
|
||||||
{
|
|
||||||
if (!tfm)
|
|
||||||
return;
|
|
||||||
SHVec3 translate{}, rotate{}, scale{};
|
|
||||||
mtx.Decompose(translate, rotate, scale);
|
|
||||||
tfm->SetWorldPosition(translate);
|
|
||||||
tfm->SetWorldRotation(rotate);
|
|
||||||
tfm->SetWorldScale(scale);
|
|
||||||
})), true);
|
|
||||||
}
|
}
|
||||||
|
ImGuizmo::Manipulate(&view._11, &proj._11, static_cast<ImGuizmo::OPERATION>(operation), ImGuizmo::MODE::WORLD, &mat._11, nullptr, useSnap ? snap : nullptr);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (!justChangedTfm && ImGuizmo::IsUsing())
|
||||||
|
{
|
||||||
|
|
||||||
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHMatrix>>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = (selectedEntityTransformComponent)](SHMatrix const& mtx)
|
||||||
|
{
|
||||||
|
if (!tfm)
|
||||||
|
return;
|
||||||
|
SHVec3 translate{}, rotate{}, scale{};
|
||||||
|
mtx.Decompose(translate, rotate, scale);
|
||||||
|
tfm->SetWorldPosition(translate);
|
||||||
|
tfm->SetWorldRotation(rotate);
|
||||||
|
tfm->SetWorldScale(scale);
|
||||||
|
})), startRecording);
|
||||||
|
if(!startRecording)
|
||||||
|
startRecording = true;
|
||||||
|
}
|
||||||
|
isManipulating = ImGuizmo::IsUsing() || startRecording;
|
||||||
|
if(startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
|
startRecording = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,11 +37,17 @@ namespace SHADE
|
||||||
UNIVERSAL = TRANSLATE | ROTATE | SCALEU
|
UNIVERSAL = TRANSLATE | ROTATE | SCALEU
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void Init();
|
||||||
void Draw();
|
void Draw();
|
||||||
bool isManipulating = false;
|
bool isManipulating = false;
|
||||||
|
bool useSnap = false;
|
||||||
Mode mode = Mode::WORLD;
|
Mode mode = Mode::WORLD;
|
||||||
Operation operation = Operation::TRANSLATE;
|
Operation operation = Operation::TRANSLATE;
|
||||||
private:
|
private:
|
||||||
|
float scaleSnap = 0.25f;
|
||||||
|
float rotationSnap = 1.0f;
|
||||||
|
SHVec3 translationSnap = SHVec3(0.25f, 0.25f, 0.25f);
|
||||||
|
float* snap = nullptr;
|
||||||
SHTransformComponent* selectedEntityTransformComponent{nullptr};
|
SHTransformComponent* selectedEntityTransformComponent{nullptr};
|
||||||
SHCameraComponent* editorCamera{nullptr};
|
SHCameraComponent* editorCamera{nullptr};
|
||||||
};
|
};
|
||||||
|
|
|
@ -92,6 +92,7 @@ namespace SHADE
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
|
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
|
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>();
|
SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>();
|
||||||
|
SHEditorWindowManager::CreateEditorWindow<SHAssetBrowser>();
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
|
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
|
||||||
|
|
||||||
io = &ImGui::GetIO();
|
io = &ImGui::GetIO();
|
||||||
|
@ -134,7 +135,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PollPicking();
|
//PollPicking();
|
||||||
|
|
||||||
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
|
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
|
||||||
{
|
{
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
bool SHEditorUI::CollapsingHeader(const std::string& title)
|
bool SHEditorUI::CollapsingHeader(const std::string& title)
|
||||||
{
|
{
|
||||||
return ImGui::CollapsingHeader(title.c_str());
|
return ImGui::CollapsingHeader(title.c_str(), ImGuiTreeNodeFlags_DefaultOpen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHEditorUI::SameLine()
|
void SHEditorUI::SameLine()
|
||||||
|
|
|
@ -40,7 +40,6 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
|
|
||||||
auto cursorPos = ImGui::GetCursorScreenPos();
|
|
||||||
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
|
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
||||||
|
@ -158,7 +157,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
static bool DragN(const std::string& fieldLabel, std::vector<std::string>const& componentLabels,
|
static bool DragN(const std::string& label, std::vector<std::string>const& componentLabels,
|
||||||
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(),
|
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(),
|
||||||
ImGuiSliderFlags flags = 0, bool* isHovered = nullptr)
|
ImGuiSliderFlags flags = 0, bool* isHovered = nullptr)
|
||||||
{
|
{
|
||||||
|
@ -169,13 +168,13 @@ namespace SHADE
|
||||||
const ImGuiContext& g = *GImGui;
|
const ImGuiContext& g = *GImGui;
|
||||||
bool valueChanged = false;
|
bool valueChanged = false;
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
ImGui::PushID(fieldLabel.c_str());
|
ImGui::PushID(label.c_str());
|
||||||
PushMultiItemsWidthsAndLabels(componentLabels, 0.0f);
|
PushMultiItemsWidthsAndLabels(componentLabels, 0.0f);
|
||||||
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
|
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
|
||||||
ImGui::SetColumnWidth(-1, 80.0f);
|
ImGui::SetColumnWidth(-1, 80.0f);
|
||||||
ImGui::Text(fieldLabel.c_str());
|
ImGui::Text(label.c_str());
|
||||||
if (isHovered)
|
if (isHovered)
|
||||||
*isHovered = ImGui::IsItemHovered();
|
*isHovered = ImGui::IsItemHovered();
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
for (std::size_t i = 0; i < N; ++i)
|
for (std::size_t i = 0; i < N; ++i)
|
||||||
{
|
{
|
||||||
|
@ -203,75 +202,91 @@ namespace SHADE
|
||||||
return valueChanged;
|
return valueChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragVec2(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec2(void)> get,
|
static bool DragVec2(const std::string& label, std::vector<std::string>const& componentLabels, std::function<SHVec2(void)> get,
|
||||||
std::function<void(SHVec2)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
std::function<void(SHVec2)> set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f,
|
||||||
ImGuiSliderFlags flags = 0)
|
ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
SHVec2 values = get();
|
SHVec2 values = get();
|
||||||
bool changed = false;
|
bool const changed = DragN<float, 2>(label, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags);
|
||||||
if (DragN<float, 2>(fieldLabel, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags))
|
static bool startRecording = false;
|
||||||
{
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), true);
|
}
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
|
startRecording = false;
|
||||||
|
if(!tooltip.empty())
|
||||||
|
{
|
||||||
|
if(ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragVec3(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec3(void)> get,
|
static bool DragVec3(const std::string& label, std::vector<std::string>const& componentLabels, std::function<SHVec3(void)> get,
|
||||||
std::function<void(SHVec3)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
std::function<void(SHVec3)> set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f,
|
||||||
ImGuiSliderFlags flags = 0)
|
ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
SHVec3 values = get();
|
SHVec3 values = get();
|
||||||
bool changed = false;
|
bool const changed = DragN<float, 3>(label, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags);
|
||||||
if (DragN<float, 3>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags))
|
|
||||||
{
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
static bool startRecording = false;
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
SHVec3 old = get();
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(old, values, set)), startRecording);
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
if (!startRecording)
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), true);
|
startRecording = true;
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
}
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
if(!tooltip.empty())
|
||||||
|
{
|
||||||
|
if(ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragVec4(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec4(void)> get,
|
static bool DragVec4(const std::string& label, std::vector<std::string>const& componentLabels, std::function<SHVec4(void)> get,
|
||||||
std::function<void(SHVec4)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
std::function<void(SHVec4)> set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f,
|
||||||
ImGuiSliderFlags flags = 0)
|
ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
SHVec4 values = get();
|
SHVec4 values = get();
|
||||||
bool changed = false;
|
bool const changed = DragN<float, 4>(label, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags);
|
||||||
if (DragN<float, 4>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags))
|
static bool startRecording = false;
|
||||||
{
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), true);
|
}
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
if(!tooltip.empty())
|
||||||
|
{
|
||||||
|
if(ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,173 +294,325 @@ namespace SHADE
|
||||||
//|| Widget Extensions ||
|
//|| Widget Extensions ||
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
|
|
||||||
static bool CheckBox(std::string const& label, std::function<bool(void)> get, std::function<void(bool const&)> set)
|
static void TextLabel(std::string_view const& text, bool sameLine = true)
|
||||||
|
{
|
||||||
|
const ImVec2 textSize = ImGui::CalcTextSize(text.data(), NULL, true);
|
||||||
|
if(textSize.x > 0.0f)
|
||||||
|
{
|
||||||
|
ImGui::Text(text.data());
|
||||||
|
ImGui::SameLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CheckBox(std::string_view const& label, std::function<bool(void)> get, std::function<void(bool const&)> set, std::string_view const& tooltip = {})
|
||||||
{
|
{
|
||||||
bool value = get();
|
bool value = get();
|
||||||
if (ImGui::Checkbox(label.c_str(), &value))
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
if (ImGui::Checkbox("##", &value))
|
||||||
{
|
{
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if(!tooltip.empty())
|
||||||
|
{
|
||||||
|
if(ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static bool RadioButton(std::vector<std::string> const& listLabels, std::vector<T> const& listTypes, std::function<T(void)> get, std::function<void(T const&)> set)
|
static bool RadioButton(std::vector<std::string> const& label, std::vector<T> const& listTypes, std::function<T(void)> get, std::function<void(T const&)> set ,std::string_view const& tooltip = {})
|
||||||
{
|
{
|
||||||
T type = get();
|
T type = get();
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
for (size_t i = 0; i < listTypes.size(); i++)
|
for (size_t i = 0; i < listTypes.size(); i++)
|
||||||
{
|
{
|
||||||
if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i]))
|
if (ImGui::RadioButton(label[i].c_str(), type == listTypes[i]))
|
||||||
{
|
{
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), listTypes[i], set)), false);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), listTypes[i], set)), false);
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
}
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool InputText(const std::string& label, const std::function<std::string(void)> get,
|
static bool InputText(const std::string& label, const std::function<std::string(void)> get,
|
||||||
const std::function<void(std::string)> set, ImGuiInputTextFlags flag = 0,
|
const std::function<void(std::string)> set, std::string_view const& tooltip = {},
|
||||||
ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0)
|
ImGuiInputTextFlags flag = 0, ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0)
|
||||||
{
|
{
|
||||||
std::string text = get();
|
std::string text = get();
|
||||||
if (ImGui::InputText(label.c_str(), &text, flag, callback, userData))
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
if (ImGui::InputText("##", &text, flag, callback, userData))
|
||||||
{
|
{
|
||||||
if (ImGui::IsItemDeactivatedAfterEdit())
|
if (ImGui::IsItemDeactivatedAfterEdit())
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<std::string>>(get(), text, set)), false);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<std::string>>(get(), text, set)), false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
ImGui::PopID();
|
||||||
}
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
template <typename T>
|
|
||||||
static bool DragScalar(const std::string& fieldLabel, ImGuiDataType data_type, std::function<T(void)> get, std::function<void(T const&)> set,
|
|
||||||
float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
|
||||||
{
|
|
||||||
T value = get();
|
|
||||||
std::cout << value << " \n";
|
|
||||||
//bool hasChange = ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags);
|
|
||||||
|
|
||||||
if (ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags))
|
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
if (ImGui::IsItemHovered())
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
|
{
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
ImGui::BeginTooltip();
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true);
|
ImGui::Text(tooltip.data());
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
ImGui::EndTooltip();
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragFloat(const std::string& fieldLabel, std::function<float(void)> get, std::function<void(float const&)> set,
|
template <typename T>
|
||||||
|
static bool DragScalar(const std::string& label, ImGuiDataType data_type, std::function<T(void)> get, std::function<void(T const&)> set,
|
||||||
|
float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, ImGuiSliderFlags flags = 0)
|
||||||
|
{
|
||||||
|
T value = get();
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
const bool hasChange = ImGui::DragScalar("##", data_type, &value, speed, &p_min, &p_max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
|
{
|
||||||
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), startRecording);
|
||||||
|
if (!startRecording)
|
||||||
|
startRecording = true;
|
||||||
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool DragFloat(const std::string_view& label, std::function<float(void)> get, std::function<void(float const&)> set, std::string_view const& tooltip = {},
|
||||||
float speed = 0.1f, float p_min = float(), float p_max = float(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
float speed = 0.1f, float p_min = float(), float p_max = float(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
float value = get();
|
float value = get();
|
||||||
//bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags);
|
ImGui::BeginGroup();
|
||||||
if (ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
const bool hasChange = ImGui::DragFloat("##", &value, speed, p_min, p_max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true);
|
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
return false;
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if(!tooltip.empty())
|
||||||
|
{
|
||||||
|
if(ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragInt(const std::string& fieldLabel, std::function<int(void)> get, std::function<void(int const&)> set,
|
static bool DragInt(const std::string& label, std::function<int(void)> get, std::function<void(int const&)> set, std::string_view const& tooltip = {},
|
||||||
float speed = 1.0f, int p_min = int(), int p_max = int(), const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
|
float speed = 1.0f, int p_min = int(), int p_max = int(), const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
int value = get();
|
int value = get();
|
||||||
//bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags);
|
ImGui::BeginGroup();
|
||||||
if (ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
const bool hasChange = ImGui::DragInt("##", &value, speed, p_min, p_max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), true);
|
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
return false;
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static bool SliderScalar(const std::string& fieldLabel, ImGuiDataType data_type, T min, T max, std::function<T(void)> get, std::function<void(T const&)> set,
|
static bool SliderScalar(const std::string& label, ImGuiDataType data_type, T min, T max, std::function<T(void)> get, std::function<void(T const&)> set, std::string_view const& tooltip = {},
|
||||||
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
T value = get();
|
T value = get();
|
||||||
if (ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags))
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
bool const hasChange = ImGui::SliderScalar("##", data_type, &value, &min, &max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
return false;
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool SliderFloat(const std::string& fieldLabel, float min, float max, std::function<float(void)> get, std::function<void(float const&)> set,
|
static bool SliderFloat(const std::string& label, float const& min, float const& max, std::function<float(void)> get, std::function<void(float const&)> set, std::string_view const& tooltip = {},
|
||||||
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
float value = get();
|
float value = get();
|
||||||
if (ImGui::SliderFloat(fieldLabel.c_str(), &value, min, max, displayFormat, flags))
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
bool const hasChange = ImGui::SliderFloat("##", &value, min, max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true);
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
return false;
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool SliderInt(const std::string& fieldLabel, int min, int max, std::function<int(void)> get, std::function<void(int const&)> set,
|
static bool SliderInt(const std::string& label, int min, int max, std::function<int(void)> get, std::function<void(int const&)> set, std::string_view const& tooltip = {},
|
||||||
const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
|
const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
int value = get();
|
int value = get();
|
||||||
if (ImGui::SliderInt(fieldLabel.c_str(), &value, min, max, displayFormat, flags))
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
bool const hasChange = ImGui::SliderInt("##", &value, min, max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
|
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), true);
|
|
||||||
|
|
||||||
return true;
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), startRecording);
|
||||||
|
if (!startRecording)
|
||||||
|
startRecording = true;
|
||||||
}
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
return false;
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ComboBox(const std::string& fieldLabel, std::vector<const char*> list, std::function<int(void)> get, std::function<void(int const&)> set)
|
static bool ComboBox(const std::string& label, std::vector<const char*> list, std::function<int(void)> get, std::function<void(int const&)> set, std::string_view const& tooltip = {})
|
||||||
{
|
{
|
||||||
bool edited = false;
|
bool edited = false;
|
||||||
int selected = get();
|
int selected = get();
|
||||||
ImGui::PushID(fieldLabel.c_str());
|
ImGui::BeginGroup();
|
||||||
ImGui::Text(fieldLabel.c_str()); ImGui::SameLine();
|
ImGui::PushID(label.c_str());
|
||||||
|
TextLabel(label);
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
if (edited = ImGui::Combo("##Combo", &selected, list.data(), static_cast<int>(list.size())))
|
if (edited = ImGui::Combo("##Combo", &selected, list.data(), static_cast<int>(list.size())))
|
||||||
{
|
{
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), selected, set)), false);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), selected, set)), false);
|
||||||
}
|
}
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
return edited;
|
return edited;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,3 +11,6 @@ constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT { 2 };
|
||||||
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 };
|
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 };
|
||||||
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 };
|
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 };
|
||||||
constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 };
|
constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 };
|
||||||
|
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_ADDED_EVENT { 6 };
|
||||||
|
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_REMOVED_EVENT { 7 };
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "SHpch.h"
|
#include "SHpch.h"
|
||||||
#include "SHEvent.h"
|
#include "SHEvent.h"
|
||||||
#include "SHEventReceiver.h"
|
#include "SHEventReceiver.h"
|
||||||
|
#include "SH_API.h"
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
INSTRUCTIONS FOR USE:
|
INSTRUCTIONS FOR USE:
|
||||||
|
@ -67,7 +68,7 @@ namespace SHADE
|
||||||
using EventManagerListener = std::function<void(SHEvent)>;
|
using EventManagerListener = std::function<void(SHEvent)>;
|
||||||
|
|
||||||
|
|
||||||
class SHEventManager
|
class SH_API SHEventManager
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace SHADE
|
||||||
SHVkSampler::~SHVkSampler() noexcept
|
SHVkSampler::~SHVkSampler() noexcept
|
||||||
{
|
{
|
||||||
if (vkSampler)
|
if (vkSampler)
|
||||||
device->GetVkLogicalDevice().destroySampler();
|
device->GetVkLogicalDevice().destroySampler(vkSampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -155,7 +155,7 @@ namespace SHADE
|
||||||
SHVkDebugMessenger::GenMessengerType(SH_DEBUG_MSG_TYPE::T_GENERAL, SH_DEBUG_MSG_TYPE::T_VALIDATION, SH_DEBUG_MSG_TYPE::T_PERFORMANCE));
|
SHVkDebugMessenger::GenMessengerType(SH_DEBUG_MSG_TYPE::T_GENERAL, SH_DEBUG_MSG_TYPE::T_VALIDATION, SH_DEBUG_MSG_TYPE::T_PERFORMANCE));
|
||||||
|
|
||||||
instanceDbgInfo.pfnUserCallback = SHVulkanDebugUtil::GenericDebugCallback;
|
instanceDbgInfo.pfnUserCallback = SHVulkanDebugUtil::GenericDebugCallback;
|
||||||
instanceInfo.pNext = static_cast<vk::DebugUtilsMessengerCreateInfoEXT*>(&instanceDbgInfo);
|
//instanceInfo.pNext = static_cast<vk::DebugUtilsMessengerCreateInfoEXT*>(&instanceDbgInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally create the instance
|
// Finally create the instance
|
||||||
|
|
|
@ -30,185 +30,214 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* SHBatch - Usage Functions */
|
/* SHBatch - Usage Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
SHBatch::SHBatch(Handle<SHVkPipeline> pipeline)
|
SHBatch::SHBatch(Handle<SHVkPipeline> pipeline)
|
||||||
: pipeline{ pipeline }
|
: pipeline{ pipeline }
|
||||||
{
|
{
|
||||||
if (!pipeline)
|
if (!pipeline)
|
||||||
throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!");
|
throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!");
|
||||||
|
|
||||||
// Mark all as dirty
|
// Mark all as dirty
|
||||||
setAllDirtyFlags();
|
setAllDirtyFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::Add(const SHRenderable* renderable)
|
||||||
|
{
|
||||||
|
// Ignore if null
|
||||||
|
if (!renderable->GetMesh())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check if we have a SubBatch with the same mesh yet
|
||||||
|
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
||||||
|
{
|
||||||
|
return batch.Mesh == renderable->GetMesh();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create one if not found
|
||||||
|
if (subBatch == subBatches.end())
|
||||||
|
{
|
||||||
|
subBatches.emplace_back(renderable->GetMesh());
|
||||||
|
subBatch = subBatches.end() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::Add(const SHRenderable* renderable)
|
// Add renderable in
|
||||||
|
subBatch->Renderables.insert(renderable->GetEID());
|
||||||
|
|
||||||
|
// Also add material instance in
|
||||||
|
referencedMatInstances.insert(renderable->GetMaterial());
|
||||||
|
|
||||||
|
// Mark all as dirty
|
||||||
|
setAllDirtyFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::Remove(const SHRenderable* renderable)
|
||||||
|
{
|
||||||
|
// Check if we have a SubBatch with the same mesh yet
|
||||||
|
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
||||||
|
{
|
||||||
|
return batch.Mesh == renderable->GetMesh();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Attempt to remove if it exists
|
||||||
|
if (subBatch == subBatches.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
subBatch->Renderables.erase(renderable->GetEID());
|
||||||
|
|
||||||
|
// Check if other renderables in subBatches contain the same material instance
|
||||||
|
bool matUnused = true;
|
||||||
|
|
||||||
|
Handle<SHMaterialInstance> matToCheck = renderable->HasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial();
|
||||||
|
|
||||||
|
for (const auto& sb : subBatches)
|
||||||
{
|
{
|
||||||
// Check if we have a SubBatch with the same mesh yet
|
// Check material usage
|
||||||
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
for (const auto& rendId : sb.Renderables)
|
||||||
|
{
|
||||||
|
auto rend = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
|
if (rend)
|
||||||
{
|
{
|
||||||
return batch.Mesh == renderable->Mesh;
|
if (rend->GetMaterial() == matToCheck)
|
||||||
});
|
{
|
||||||
|
matUnused = false;
|
||||||
// Create one if not found
|
break;
|
||||||
if (subBatch == subBatches.end())
|
}
|
||||||
{
|
|
||||||
subBatches.emplace_back(renderable->Mesh);
|
|
||||||
subBatch = subBatches.end() - 1;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Add renderable in
|
{
|
||||||
subBatch->Renderables.insert(renderable);
|
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
||||||
|
}
|
||||||
// Also add material instance in
|
}
|
||||||
referencedMatInstances.insert(renderable->GetMaterial());
|
|
||||||
|
|
||||||
// Mark all as dirty
|
|
||||||
setAllDirtyFlags();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::Remove(const SHRenderable* renderable)
|
// Material is no longer in this library, so we remove it
|
||||||
|
if (matUnused)
|
||||||
|
referencedMatInstances.erase(renderable->HasChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial());
|
||||||
|
|
||||||
|
// Mesh is no longer in this batch, so we remove the associated sub batch
|
||||||
|
if (subBatch->Renderables.empty())
|
||||||
|
subBatches.erase(subBatch);
|
||||||
|
|
||||||
|
// Mark all as dirty
|
||||||
|
setAllDirtyFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::Clear()
|
||||||
|
{
|
||||||
|
subBatches.clear();
|
||||||
|
|
||||||
|
// Clear CPU buffers
|
||||||
|
drawData.clear();
|
||||||
|
transformData.clear();
|
||||||
|
instancedIntegerData.clear();
|
||||||
|
matPropsData.reset();
|
||||||
|
matPropsDataSize = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// Clear GPU buffers
|
||||||
|
for (int i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
||||||
{
|
{
|
||||||
// Check if we have a SubBatch with the same mesh yet
|
drawDataBuffer[i].Free();
|
||||||
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
transformDataBuffer[i].Free();
|
||||||
{
|
instancedIntegerBuffer[i].Free();
|
||||||
return batch.Mesh == renderable->Mesh;
|
matPropsBuffer[i].Free();
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Attempt to remove if it exists
|
void SHBatch::UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||||
if (subBatch == subBatches.end())
|
{
|
||||||
return;
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
|
{
|
||||||
subBatch->Renderables.erase(renderable);
|
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
|
||||||
|
return;
|
||||||
// Check if other renderables in subBatches contain the same material instance
|
|
||||||
bool matUnused = true;
|
|
||||||
for (const auto& sb : subBatches)
|
|
||||||
for (const auto& rend : sb.Renderables)
|
|
||||||
{
|
|
||||||
if (rend->GetMaterial() == renderable->GetMaterial())
|
|
||||||
{
|
|
||||||
matUnused = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Material is no longer in this library, so we remove it
|
|
||||||
if (matUnused)
|
|
||||||
referencedMatInstances.erase(renderable->GetMaterial());
|
|
||||||
|
|
||||||
// Mark all as dirty
|
|
||||||
for (bool& dirt : isDirty)
|
|
||||||
dirt = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::Clear()
|
// Check if there are even material properties to update
|
||||||
|
if (!matPropsData)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check if any materials have changed
|
||||||
|
bool hasChanged = false;
|
||||||
|
for (const auto& material : referencedMatInstances)
|
||||||
{
|
{
|
||||||
subBatches.clear();
|
if (material->HasChanged())
|
||||||
|
{
|
||||||
// Clear CPU buffers
|
hasChanged = true;
|
||||||
drawData.clear();
|
break;
|
||||||
transformData.clear();
|
}
|
||||||
eidData.clear();
|
|
||||||
matPropsData.reset();
|
|
||||||
matPropsDataSize = 0;
|
|
||||||
|
|
||||||
|
|
||||||
// Clear GPU buffers
|
|
||||||
for (int i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
|
||||||
{
|
|
||||||
drawDataBuffer[i].Free();
|
|
||||||
transformDataBuffer[i].Free();
|
|
||||||
eidBuffer[i].Free();
|
|
||||||
matPropsBuffer[i].Free();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
// We need to update all the material buffers if the materials have changed
|
||||||
{
|
if (hasChanged)
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if there are even material properties to update
|
|
||||||
if (!matPropsData)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Check if any materials have changed
|
|
||||||
bool hasChanged = false;
|
|
||||||
for (const auto& material : referencedMatInstances)
|
|
||||||
{
|
|
||||||
if (material->HasChanged())
|
|
||||||
{
|
|
||||||
hasChanged = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to update all the material buffers if the materials have changed
|
|
||||||
if (hasChanged)
|
|
||||||
{
|
|
||||||
for (auto& dirt : matBufferDirty)
|
|
||||||
dirt = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if this frame's buffer is dirty
|
|
||||||
if (!matBufferDirty[frameIndex])
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Build CPU Buffer
|
|
||||||
char* propsCurrPtr = matPropsData.get();
|
|
||||||
for (auto& subBatch : subBatches)
|
|
||||||
for (const SHRenderable* renderable : subBatch.Renderables)
|
|
||||||
{
|
|
||||||
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
|
||||||
propsCurrPtr += singleMatPropAlignedSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transfer to GPU
|
|
||||||
rebuildMaterialBuffers(frameIndex, descPool);
|
|
||||||
|
|
||||||
// This frame is updated
|
|
||||||
matBufferDirty[frameIndex] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHBatch::UpdateTransformBuffer(uint32_t frameIndex)
|
|
||||||
{
|
{
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
for (auto& dirt : matBufferDirty)
|
||||||
{
|
dirt = true;
|
||||||
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset Transform Data
|
|
||||||
transformData.clear();
|
|
||||||
|
|
||||||
// Populate on the CPU
|
|
||||||
for (auto& subBatch : subBatches)
|
|
||||||
for (const SHRenderable* renderable : subBatch.Renderables)
|
|
||||||
{
|
|
||||||
// Transform
|
|
||||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(renderable->GetEID());
|
|
||||||
if (!transform)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
|
||||||
transformData.emplace_back();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
transformData.emplace_back(transform->GetTRS());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transfer to GPU
|
|
||||||
if (transformDataBuffer[frameIndex])
|
|
||||||
transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)), 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::UpdateEIDBuffer(uint32_t frameIndex)
|
// Check if this frame's buffer is dirty
|
||||||
|
if (!matBufferDirty[frameIndex])
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Build CPU Buffer
|
||||||
|
char* propsCurrPtr = matPropsData.get();
|
||||||
|
for (auto& subBatch : subBatches)
|
||||||
|
for (auto rendId : subBatch.Renderables)
|
||||||
|
{
|
||||||
|
const SHRenderable* renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
|
if (renderable)
|
||||||
|
{
|
||||||
|
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
||||||
|
}
|
||||||
|
propsCurrPtr += singleMatPropAlignedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer to GPU
|
||||||
|
rebuildMaterialBuffers(frameIndex, descPool);
|
||||||
|
|
||||||
|
// This frame is updated
|
||||||
|
matBufferDirty[frameIndex] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::UpdateTransformBuffer(uint32_t frameIndex)
|
||||||
|
{
|
||||||
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset Transform Data
|
||||||
|
transformData.clear();
|
||||||
|
|
||||||
|
// Populate on the CPU
|
||||||
|
for (auto& subBatch : subBatches)
|
||||||
|
for (auto rendId : subBatch.Renderables)
|
||||||
|
{
|
||||||
|
// Transform
|
||||||
|
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(rendId);
|
||||||
|
if (transform)
|
||||||
|
{
|
||||||
|
transformData.emplace_back(transform->GetTRS());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
||||||
|
transformData.emplace_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer to GPU
|
||||||
|
if (transformDataBuffer[frameIndex])
|
||||||
|
transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::UpdateInstancedIntegerBuffer(uint32_t frameIndex)
|
||||||
{
|
{
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
{
|
{
|
||||||
|
@ -217,224 +246,244 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset Transform Data
|
// Reset Transform Data
|
||||||
eidData.clear();
|
instancedIntegerData.clear();
|
||||||
|
|
||||||
// Populate on the CPU
|
// Populate on the CPU
|
||||||
for (auto& subBatch : subBatches)
|
for (auto& subBatch : subBatches)
|
||||||
for (const SHRenderable* renderable : subBatch.Renderables)
|
for (auto rendId : subBatch.Renderables)
|
||||||
{
|
{
|
||||||
eidData.emplace_back(renderable->GetEID());
|
auto* renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
|
instancedIntegerData.emplace_back(SHInstancedIntegerData
|
||||||
|
{
|
||||||
|
rendId,
|
||||||
|
renderable->GetLightLayer()
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transfer to GPU
|
// Transfer to GPU
|
||||||
if (eidBuffer[frameIndex])
|
if (instancedIntegerBuffer[frameIndex])
|
||||||
eidBuffer[frameIndex]->WriteToMemory(eidData.data(), static_cast<EntityID>(eidData.size() * sizeof(EntityID)), 0, 0);
|
instancedIntegerBuffer[frameIndex]->WriteToMemory(instancedIntegerData.data(), static_cast<uint32_t>(instancedIntegerData.size() * sizeof(SHInstancedIntegerData)), 0, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::Build(Handle<SHVkLogicalDevice> _device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex)
|
void SHBatch::Build(Handle<SHVkLogicalDevice> _device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex)
|
||||||
|
{
|
||||||
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
{
|
{
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
SHLOG_WARNING("[SHBatch] Attempted to update build batch buffers with an invalid frame index.");
|
||||||
{
|
return;
|
||||||
SHLOG_WARNING("[SHBatch] Attempted to update build batch buffers with an invalid frame index.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save logical device
|
|
||||||
device = _device;
|
|
||||||
|
|
||||||
// No need to build as there are no changes
|
|
||||||
if (!isDirty[frameIndex])
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Count number of elements
|
|
||||||
size_t numTotalElements = 0;
|
|
||||||
for (const auto& subBatch : subBatches)
|
|
||||||
{
|
|
||||||
numTotalElements += subBatch.Renderables.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate CPU buffers if there are changes
|
|
||||||
if (isCPUBuffersDirty)
|
|
||||||
{
|
|
||||||
// - Draw data
|
|
||||||
drawData.reserve(subBatches.size());
|
|
||||||
drawData.clear();
|
|
||||||
// - Transform data
|
|
||||||
transformData.reserve(numTotalElements);
|
|
||||||
transformData.clear();
|
|
||||||
// - EID data
|
|
||||||
eidData.reserve(numTotalElements);
|
|
||||||
eidData.clear();
|
|
||||||
|
|
||||||
|
|
||||||
// - Material Properties Data
|
|
||||||
const Handle<SHShaderBlockInterface> SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
|
||||||
(
|
|
||||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
|
||||||
vk::ShaderStageFlagBits::eFragment
|
|
||||||
);
|
|
||||||
const bool EMPTY_MAT_PROPS = !SHADER_INFO;
|
|
||||||
Byte matPropTotalBytes = 0;
|
|
||||||
if (!EMPTY_MAT_PROPS)
|
|
||||||
{
|
|
||||||
singleMatPropSize = SHADER_INFO->GetBytesRequired();
|
|
||||||
singleMatPropAlignedSize = device->PadSSBOSize(static_cast<uint32_t>(singleMatPropSize));
|
|
||||||
matPropTotalBytes = numTotalElements * singleMatPropAlignedSize;
|
|
||||||
if (matPropsDataSize < matPropTotalBytes)
|
|
||||||
{
|
|
||||||
matPropsData.reset(new char[matPropTotalBytes]);
|
|
||||||
matPropsDataSize = matPropTotalBytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build Sub Batches
|
|
||||||
uint32_t nextInstanceIndex = 0;
|
|
||||||
char* propsCurrPtr = matPropsData.get();
|
|
||||||
for (auto& subBatch : subBatches)
|
|
||||||
{
|
|
||||||
// Create command
|
|
||||||
drawData.emplace_back(vk::DrawIndexedIndirectCommand
|
|
||||||
{
|
|
||||||
.indexCount = subBatch.Mesh->IndexCount,
|
|
||||||
.instanceCount = static_cast<uint32_t>(subBatch.Renderables.size()),
|
|
||||||
.firstIndex = subBatch.Mesh->FirstIndex,
|
|
||||||
.vertexOffset = subBatch.Mesh->FirstVertex,
|
|
||||||
.firstInstance = nextInstanceIndex++
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fill in buffers (CPU)
|
|
||||||
for (const SHRenderable* renderable : subBatch.Renderables)
|
|
||||||
{
|
|
||||||
// Transform
|
|
||||||
EntityID eid = renderable->GetEID();
|
|
||||||
auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
|
|
||||||
if (!transform)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
|
||||||
transformData.emplace_back();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
transformData.emplace_back(transform->GetTRS());
|
|
||||||
}
|
|
||||||
|
|
||||||
eidData.emplace_back(eid);
|
|
||||||
|
|
||||||
// Material Properties
|
|
||||||
if (!EMPTY_MAT_PROPS)
|
|
||||||
{
|
|
||||||
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
|
||||||
propsCurrPtr += singleMatPropAlignedSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Successfully update CPU buffers
|
|
||||||
isCPUBuffersDirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send all buffered data to the GPU buffers
|
|
||||||
using BuffUsage = vk::BufferUsageFlagBits;
|
|
||||||
// - Draw Data
|
|
||||||
const uint32_t DRAW_DATA_BYTES = static_cast<uint32_t>(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand));
|
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
|
||||||
(
|
|
||||||
device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES,
|
|
||||||
BuffUsage::eIndirectBuffer
|
|
||||||
);
|
|
||||||
// - Transform Buffer
|
|
||||||
const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix));
|
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
|
||||||
(
|
|
||||||
device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
|
|
||||||
BuffUsage::eVertexBuffer
|
|
||||||
);
|
|
||||||
const uint32_t EID_DATA_BYTES = static_cast<uint32_t>(eidData.size() * sizeof(EntityID));
|
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
|
||||||
(
|
|
||||||
device, eidBuffer[frameIndex], eidData.data(), EID_DATA_BYTES,
|
|
||||||
BuffUsage::eVertexBuffer
|
|
||||||
);
|
|
||||||
// - Material Properties Buffer
|
|
||||||
rebuildMaterialBuffers(frameIndex, descPool);
|
|
||||||
|
|
||||||
// Mark this frame as no longer dirty
|
|
||||||
isDirty[frameIndex] = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
// Save logical device
|
||||||
/* SHBatch - Usage Functions */
|
device = _device;
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex)
|
|
||||||
{
|
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Attempted to draw a batch with an invalid frame index.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind all required objects before drawing
|
// No need to build as there are no changes
|
||||||
static std::array<uint32_t, 1> dynamicOffset { 0 };
|
if (!isDirty[frameIndex])
|
||||||
cmdBuffer->BindPipeline(pipeline);
|
return;
|
||||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
|
|
||||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::EID, eidBuffer[frameIndex], 0);
|
// Count number of elements
|
||||||
if (matPropsDescSet[frameIndex])
|
size_t numTotalElements = 0;
|
||||||
|
for (const auto& subBatch : subBatches)
|
||||||
|
{
|
||||||
|
numTotalElements += subBatch.Renderables.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate CPU buffers if there are changes
|
||||||
|
if (isCPUBuffersDirty)
|
||||||
|
{
|
||||||
|
// - Draw data
|
||||||
|
drawData.reserve(subBatches.size());
|
||||||
|
drawData.clear();
|
||||||
|
// - Transform data
|
||||||
|
transformData.reserve(numTotalElements);
|
||||||
|
transformData.clear();
|
||||||
|
// - EID data
|
||||||
|
instancedIntegerData.reserve(numTotalElements);
|
||||||
|
instancedIntegerData.clear();
|
||||||
|
|
||||||
|
|
||||||
|
// - Material Properties Data
|
||||||
|
const Handle<SHShaderBlockInterface> SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
||||||
|
(
|
||||||
|
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
|
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
||||||
|
vk::ShaderStageFlagBits::eFragment
|
||||||
|
);
|
||||||
|
const bool EMPTY_MAT_PROPS = !SHADER_INFO;
|
||||||
|
Byte matPropTotalBytes = 0;
|
||||||
|
if (!EMPTY_MAT_PROPS)
|
||||||
|
{
|
||||||
|
singleMatPropSize = SHADER_INFO->GetBytesRequired();
|
||||||
|
singleMatPropAlignedSize = device->PadSSBOSize(static_cast<uint32_t>(singleMatPropSize));
|
||||||
|
matPropTotalBytes = numTotalElements * singleMatPropAlignedSize;
|
||||||
|
if (matPropsDataSize < matPropTotalBytes)
|
||||||
{
|
{
|
||||||
cmdBuffer->BindDescriptorSet
|
matPropsData.reset(new char[matPropTotalBytes]);
|
||||||
(
|
matPropsDataSize = matPropTotalBytes;
|
||||||
matPropsDescSet[frameIndex],
|
}
|
||||||
SH_PIPELINE_TYPE::GRAPHICS,
|
}
|
||||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
|
||||||
dynamicOffset
|
// Build Sub Batches
|
||||||
|
uint32_t nextInstanceIndex = 0;
|
||||||
|
char* propsCurrPtr = matPropsData.get();
|
||||||
|
for (auto& subBatch : subBatches)
|
||||||
|
{
|
||||||
|
// Create command
|
||||||
|
const uint32_t CURR_INSTANCES = static_cast<uint32_t>(subBatch.Renderables.size());
|
||||||
|
drawData.emplace_back(vk::DrawIndexedIndirectCommand
|
||||||
|
{
|
||||||
|
.indexCount = subBatch.Mesh->IndexCount,
|
||||||
|
.instanceCount = CURR_INSTANCES,
|
||||||
|
.firstIndex = subBatch.Mesh->FirstIndex,
|
||||||
|
.vertexOffset = subBatch.Mesh->FirstVertex,
|
||||||
|
.firstInstance = nextInstanceIndex
|
||||||
|
});
|
||||||
|
nextInstanceIndex += CURR_INSTANCES;
|
||||||
|
|
||||||
|
// Fill in buffers (CPU)
|
||||||
|
for (auto rendId : subBatch.Renderables)
|
||||||
|
{
|
||||||
|
// Transform
|
||||||
|
auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(rendId);
|
||||||
|
if (!transform)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
||||||
|
transformData.emplace_back();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
transformData.emplace_back(transform->GetTRS());
|
||||||
|
}
|
||||||
|
|
||||||
|
const SHRenderable* renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
|
instancedIntegerData.emplace_back(SHInstancedIntegerData
|
||||||
|
{
|
||||||
|
rendId,
|
||||||
|
renderable->GetLightLayer()
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
|
||||||
cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast<uint32_t>(drawData.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
// Material Properties
|
||||||
/* SHBatch - Helper Functions */
|
if (!EMPTY_MAT_PROPS)
|
||||||
/*---------------------------------------------------------------------------------*/
|
{
|
||||||
void SHBatch::setAllDirtyFlags()
|
if (renderable)
|
||||||
{
|
|
||||||
for (bool& dirt : isDirty)
|
|
||||||
dirt = true;
|
|
||||||
isCPUBuffersDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHBatch::rebuildMaterialBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
|
||||||
{
|
|
||||||
if (matPropsData)
|
|
||||||
{
|
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
|
||||||
(
|
|
||||||
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
|
|
||||||
vk::BufferUsageFlagBits::eStorageBuffer
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!matPropsDescSet[frameIndex])
|
|
||||||
{
|
{
|
||||||
matPropsDescSet[frameIndex] = descPool->Allocate
|
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
||||||
(
|
|
||||||
{ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE] },
|
|
||||||
{ 0 }
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
std::array<Handle<SHVkBuffer>, 1> bufferList = { matPropsBuffer[frameIndex] };
|
else
|
||||||
matPropsDescSet[frameIndex]->ModifyWriteDescBuffer
|
{
|
||||||
(
|
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
||||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
}
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
propsCurrPtr += singleMatPropAlignedSize;
|
||||||
bufferList,
|
}
|
||||||
0, static_cast<uint32_t>(matPropsDataSize)
|
|
||||||
);
|
|
||||||
matPropsDescSet[frameIndex]->UpdateDescriptorSetBuffer
|
|
||||||
(
|
|
||||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Successfully update CPU buffers
|
||||||
|
isCPUBuffersDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send all buffered data to the GPU buffers
|
||||||
|
using BuffUsage = vk::BufferUsageFlagBits;
|
||||||
|
// - Draw Data
|
||||||
|
const uint32_t DRAW_DATA_BYTES = static_cast<uint32_t>(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand));
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES,
|
||||||
|
BuffUsage::eIndirectBuffer
|
||||||
|
);
|
||||||
|
// - Transform Buffer
|
||||||
|
const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix));
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
|
||||||
|
BuffUsage::eVertexBuffer
|
||||||
|
);
|
||||||
|
const uint32_t EID_DATA_BYTES = static_cast<uint32_t>(instancedIntegerData.size() * sizeof(SHInstancedIntegerData));
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, instancedIntegerBuffer[frameIndex], instancedIntegerData.data(), EID_DATA_BYTES,
|
||||||
|
BuffUsage::eVertexBuffer
|
||||||
|
);
|
||||||
|
// - Material Properties Buffer
|
||||||
|
rebuildMaterialBuffers(frameIndex, descPool);
|
||||||
|
|
||||||
|
// Mark this frame as no longer dirty
|
||||||
|
isDirty[frameIndex] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* SHBatch - Usage Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex)
|
||||||
|
{
|
||||||
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Attempted to draw a batch with an invalid frame index.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind all required objects before drawing
|
||||||
|
static std::array<uint32_t, 1> dynamicOffset{ 0 };
|
||||||
|
cmdBuffer->BindPipeline(pipeline);
|
||||||
|
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
|
||||||
|
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0);
|
||||||
|
if (matPropsDescSet[frameIndex])
|
||||||
|
{
|
||||||
|
cmdBuffer->BindDescriptorSet
|
||||||
|
(
|
||||||
|
matPropsDescSet[frameIndex],
|
||||||
|
SH_PIPELINE_TYPE::GRAPHICS,
|
||||||
|
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
|
dynamicOffset
|
||||||
|
);
|
||||||
|
}
|
||||||
|
cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast<uint32_t>(drawData.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* SHBatch - Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void SHBatch::setAllDirtyFlags()
|
||||||
|
{
|
||||||
|
for (bool& dirt : isDirty)
|
||||||
|
dirt = true;
|
||||||
|
isCPUBuffersDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::rebuildMaterialBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||||
|
{
|
||||||
|
if (matPropsData)
|
||||||
|
{
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
|
||||||
|
vk::BufferUsageFlagBits::eStorageBuffer
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!matPropsDescSet[frameIndex])
|
||||||
|
{
|
||||||
|
matPropsDescSet[frameIndex] = descPool->Allocate
|
||||||
|
(
|
||||||
|
{ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE] },
|
||||||
|
{ 0 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
std::array<Handle<SHVkBuffer>, 1> bufferList = { matPropsBuffer[frameIndex] };
|
||||||
|
matPropsDescSet[frameIndex]->ModifyWriteDescBuffer
|
||||||
|
(
|
||||||
|
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
|
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
||||||
|
bufferList,
|
||||||
|
0, static_cast<uint32_t>(matPropsDataSize)
|
||||||
|
);
|
||||||
|
matPropsDescSet[frameIndex]->UpdateDescriptorSetBuffer
|
||||||
|
(
|
||||||
|
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
|
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Math/SHMatrix.h"
|
#include "Math/SHMatrix.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||||
#include "ECS_Base/SHECSMacros.h"
|
#include "ECS_Base/SHECSMacros.h"
|
||||||
|
#include "Graphics/MiddleEnd/Interface/SHInstancedIntegerData.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -55,7 +56,7 @@ namespace SHADE
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
Handle<SHMesh> Mesh;
|
Handle<SHMesh> Mesh;
|
||||||
std::unordered_set<const SHRenderable*> Renderables;
|
std::unordered_set<EntityID> Renderables;
|
||||||
};
|
};
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
|
@ -79,7 +80,7 @@ namespace SHADE
|
||||||
void Clear();
|
void Clear();
|
||||||
void UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
void UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||||
void UpdateTransformBuffer(uint32_t frameIndex);
|
void UpdateTransformBuffer(uint32_t frameIndex);
|
||||||
void UpdateEIDBuffer(uint32_t frameIndex);
|
void UpdateInstancedIntegerBuffer(uint32_t frameIndex);
|
||||||
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) ;
|
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) ;
|
||||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
|
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
|
||||||
|
|
||||||
|
@ -111,7 +112,7 @@ namespace SHADE
|
||||||
// CPU Buffers
|
// CPU Buffers
|
||||||
std::vector<vk::DrawIndexedIndirectCommand> drawData;
|
std::vector<vk::DrawIndexedIndirectCommand> drawData;
|
||||||
std::vector<SHMatrix> transformData;
|
std::vector<SHMatrix> transformData;
|
||||||
std::vector<EntityID> eidData;
|
std::vector<SHInstancedIntegerData> instancedIntegerData;
|
||||||
std::unique_ptr<char> matPropsData;
|
std::unique_ptr<char> matPropsData;
|
||||||
Byte matPropsDataSize = 0;
|
Byte matPropsDataSize = 0;
|
||||||
Byte singleMatPropAlignedSize = 0;
|
Byte singleMatPropAlignedSize = 0;
|
||||||
|
@ -120,7 +121,7 @@ namespace SHADE
|
||||||
// GPU Buffers
|
// GPU Buffers
|
||||||
TripleBuffer drawDataBuffer;
|
TripleBuffer drawDataBuffer;
|
||||||
TripleBuffer transformDataBuffer;
|
TripleBuffer transformDataBuffer;
|
||||||
TripleBuffer eidBuffer;
|
TripleBuffer instancedIntegerBuffer;
|
||||||
TripleBuffer matPropsBuffer;
|
TripleBuffer matPropsBuffer;
|
||||||
TripleDescSet matPropsDescSet;
|
TripleDescSet matPropsDescSet;
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
batch.UpdateMaterialBuffer(frameIndex, descPool);
|
batch.UpdateMaterialBuffer(frameIndex, descPool);
|
||||||
batch.UpdateTransformBuffer(frameIndex);
|
batch.UpdateTransformBuffer(frameIndex);
|
||||||
batch.UpdateEIDBuffer(frameIndex);
|
batch.UpdateInstancedIntegerBuffer(frameIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "Graphics/Pipeline/SHPipelineState.h"
|
#include "Graphics/Pipeline/SHPipelineState.h"
|
||||||
#include "Graphics/Pipeline/SHVkPipelineLayout.h"
|
#include "Graphics/Pipeline/SHVkPipelineLayout.h"
|
||||||
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
|
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
|
||||||
|
#include "Graphics/MiddleEnd/Lights/SHLightData.h"
|
||||||
|
#include "Tools/SHUtilities.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -45,16 +47,35 @@ namespace SHADE
|
||||||
// For global data (generic data and textures)
|
// For global data (generic data and textures)
|
||||||
Handle<SHVkDescriptorSetLayout> staticGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,{ genericDataBinding, texturesBinding });
|
Handle<SHVkDescriptorSetLayout> staticGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,{ genericDataBinding, texturesBinding });
|
||||||
|
|
||||||
SHVkDescriptorSetLayout::Binding lightBinding
|
std::vector<SHVkDescriptorSetLayout::Binding> lightBindings{};
|
||||||
|
for (uint32_t i = 0; i < SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES); ++i)
|
||||||
{
|
{
|
||||||
.Type = vk::DescriptorType::eStorageBufferDynamic,
|
lightBindings.push_back (SHVkDescriptorSetLayout::Binding
|
||||||
.Stage = vk::ShaderStageFlagBits::eFragment,
|
{
|
||||||
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::LIGHTS_DATA,
|
.Type = vk::DescriptorType::eStorageBufferDynamic,
|
||||||
.DescriptorCount = 1,
|
.Stage = vk::ShaderStageFlagBits::eFragment,
|
||||||
};
|
.BindPoint = i,
|
||||||
|
.DescriptorCount = 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//SHVkDescriptorSetLayout::Binding pointLightBinding
|
||||||
|
//{
|
||||||
|
// .Type = vk::DescriptorType::eStorageBufferDynamic,
|
||||||
|
// .Stage = vk::ShaderStageFlagBits::eFragment,
|
||||||
|
// .BindPoint = SHGraphicsConstants::DescriptorSetBindings::POINT_LIGHT_DATA,
|
||||||
|
// .DescriptorCount = 1,
|
||||||
|
//};
|
||||||
|
|
||||||
|
//SHVkDescriptorSetLayout::Binding spotLightBinding
|
||||||
|
//{
|
||||||
|
// .Type = vk::DescriptorType::eStorageBufferDynamic,
|
||||||
|
// .Stage = vk::ShaderStageFlagBits::eFragment,
|
||||||
|
// .BindPoint = SHGraphicsConstants::DescriptorSetBindings::SPOT_LIGHT_DATA,
|
||||||
|
// .DescriptorCount = 1,
|
||||||
|
//};
|
||||||
|
|
||||||
// For Dynamic global data (lights)
|
// For Dynamic global data (lights)
|
||||||
Handle<SHVkDescriptorSetLayout> dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, { lightBinding });
|
Handle<SHVkDescriptorSetLayout> dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, lightBindings);
|
||||||
|
|
||||||
SHVkDescriptorSetLayout::Binding cameraDataBinding
|
SHVkDescriptorSetLayout::Binding cameraDataBinding
|
||||||
{
|
{
|
||||||
|
@ -94,7 +115,7 @@ namespace SHADE
|
||||||
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Normals at binding 2
|
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Normals at binding 2
|
||||||
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Tangents at binding 3
|
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Tangents at binding 3
|
||||||
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }); // Transform at binding 4 - 7 (4 slots)
|
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }); // Transform at binding 4 - 7 (4 slots)
|
||||||
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::UINT32_1D) }); // EID at binding 8
|
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::UINT32_2D) }); // Instanced integer data at index 8
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHGraphicsGlobalData::Init(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
void SHGraphicsGlobalData::Init(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
||||||
|
|
|
@ -94,14 +94,32 @@ namespace SHADE
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
static constexpr uint32_t IMAGE_AND_SAMPLERS_DATA = 1;
|
static constexpr uint32_t IMAGE_AND_SAMPLERS_DATA = 1;
|
||||||
|
|
||||||
/***************************************************************************/
|
///***************************************************************************/
|
||||||
/*!
|
///*!
|
||||||
\brief
|
// \brief
|
||||||
DescriptorSet binding for lights.
|
// DescriptorSet binding for directional lights.
|
||||||
|
|
||||||
*/
|
//*/
|
||||||
/***************************************************************************/
|
///***************************************************************************/
|
||||||
static constexpr uint32_t LIGHTS_DATA = 0;
|
//static constexpr uint32_t DIRECTIONAL_LIGHT_DATA = 0;
|
||||||
|
|
||||||
|
///***************************************************************************/
|
||||||
|
///*!
|
||||||
|
// \brief
|
||||||
|
// DescriptorSet binding for directional lights.
|
||||||
|
|
||||||
|
//*/
|
||||||
|
///***************************************************************************/
|
||||||
|
//static constexpr uint32_t POINT_LIGHT_DATA = 1;
|
||||||
|
|
||||||
|
///***************************************************************************/
|
||||||
|
///*!
|
||||||
|
// \brief
|
||||||
|
// DescriptorSet binding for directional lights.
|
||||||
|
|
||||||
|
//*/
|
||||||
|
///***************************************************************************/
|
||||||
|
//static constexpr uint32_t SPOT_LIGHT_DATA = 2;
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
|
@ -164,7 +182,7 @@ namespace SHADE
|
||||||
Vertex buffer bindings for the eid buffer.
|
Vertex buffer bindings for the eid buffer.
|
||||||
*/
|
*/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
static constexpr uint32_t EID = 5;
|
static constexpr uint32_t INTEGER_DATA = 5;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Graphics/Images/SHVkSampler.h"
|
#include "Graphics/Images/SHVkSampler.h"
|
||||||
#include "Assets/Asset Types/SHTextureAsset.h"
|
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
|
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
|
||||||
|
#include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -117,21 +118,8 @@ namespace SHADE
|
||||||
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
|
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
|
||||||
|
|
||||||
|
|
||||||
// TODO: This is VERY temporarily here until a more solid resource management system is implemented
|
shaderModuleLibrary.ImportAllShaderSource(device);
|
||||||
shaderSourceLibrary.Init("../../TempShaderFolder/");
|
shaderModuleLibrary.ReflectAllShaderModules();
|
||||||
|
|
||||||
shaderSourceLibrary.LoadShader(0, "TestCubeVs.glsl", SH_SHADER_TYPE::VERTEX, true);
|
|
||||||
shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, true);
|
|
||||||
|
|
||||||
shaderSourceLibrary.LoadShader(2, "KirschCs.glsl", SH_SHADER_TYPE::COMPUTE, true);
|
|
||||||
|
|
||||||
shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
|
|
||||||
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
|
|
||||||
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
|
|
||||||
auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
|
|
||||||
cubeVS->Reflect();
|
|
||||||
cubeFS->Reflect();
|
|
||||||
greyscale->Reflect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
|
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
|
||||||
|
@ -172,21 +160,32 @@ namespace SHADE
|
||||||
|
|
||||||
// Initialize world render graph
|
// Initialize world render graph
|
||||||
worldRenderGraph->Init(device, swapchain);
|
worldRenderGraph->Init(device, swapchain);
|
||||||
worldRenderGraph->AddResource("Scene Pre-Process", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
worldRenderGraph->AddResource("Scene Pre-Process", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
||||||
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
||||||
worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
||||||
worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||||
|
worldRenderGraph->AddResource("Light Layer Indices", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||||
|
|
||||||
auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene", "Scene Pre-Process"}, {}); // no predecessors
|
auto gBufferNode = worldRenderGraph->AddNode("G-Buffer", { "Light Layer Indices", "Entity ID", "Depth Buffer", "Scene", "Scene Pre-Process"}, {}); // no predecessors
|
||||||
|
auto gBufferSubpass = gBufferNode->AddSubpass("G-Buffer Write");
|
||||||
|
gBufferSubpass->AddColorOutput("Scene Pre-Process");
|
||||||
|
gBufferSubpass->AddColorOutput("Entity ID");
|
||||||
|
gBufferSubpass->AddColorOutput("Light Layer Indices");
|
||||||
|
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
|
||||||
|
|
||||||
//First subpass to write to G-Buffer
|
//// kirsch
|
||||||
auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
|
//auto kirschShader = shaderModuleLibrary.GetShaderModule("KirschCs");
|
||||||
gBufferWriteSubpass->AddColorOutput("Scene Pre-Process");
|
//gBufferNode->AddNodeCompute(kirschShader, { "Scene Pre-Process", "Scene" });
|
||||||
gBufferWriteSubpass->AddColorOutput("Entity ID");
|
|
||||||
gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
|
// copy
|
||||||
|
auto pureCopyShader = shaderModuleLibrary.GetBuiltInShaderModule("PureCopy_CS");
|
||||||
|
gBufferNode->AddNodeCompute(pureCopyShader, { "Scene Pre-Process", "Scene" });
|
||||||
|
|
||||||
|
|
||||||
|
auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, {"G-Buffer"}); // no predecessors
|
||||||
|
auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass");
|
||||||
|
dummySubpass->AddInput("Scene");
|
||||||
|
|
||||||
auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
|
|
||||||
node->AddNodeCompute (greyscale, {"Scene Pre-Process", "Scene"});
|
|
||||||
|
|
||||||
// Generate world render graph
|
// Generate world render graph
|
||||||
worldRenderGraph->Generate();
|
worldRenderGraph->Generate();
|
||||||
|
@ -197,11 +196,10 @@ namespace SHADE
|
||||||
|
|
||||||
worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
|
worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
|
||||||
|
|
||||||
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
|
auto cubeVS = shaderModuleLibrary.GetBuiltInShaderModule("TestCube_VS");
|
||||||
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
|
auto cubeFS = shaderModuleLibrary.GetBuiltInShaderModule("TestCube_FS");
|
||||||
|
|
||||||
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass);
|
|
||||||
|
|
||||||
|
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferSubpass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHGraphicsSystem::InitMiddleEnd(void) noexcept
|
void SHGraphicsSystem::InitMiddleEnd(void) noexcept
|
||||||
|
@ -231,11 +229,15 @@ namespace SHADE
|
||||||
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
|
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
|
||||||
cmdPools.push_back(renderContext.GetFrameData(i).cmdPoolHdls[0]);
|
cmdPools.push_back(renderContext.GetFrameData(i).cmdPoolHdls[0]);
|
||||||
|
|
||||||
|
// Mouse picking system for the editor (Will still run with editor disabled)
|
||||||
mousePickSystem->Init(device, cmdPools, worldRenderGraph->GetRenderGraphResource("Entity ID"));
|
mousePickSystem->Init(device, cmdPools, worldRenderGraph->GetRenderGraphResource("Entity ID"));
|
||||||
|
|
||||||
// Register the post offscreen render to the system
|
// Register the post offscreen render to the system
|
||||||
postOffscreenRender = resourceManager.Create<SHPostOffscreenRenderSystem>();
|
postOffscreenRender = resourceManager.Create<SHPostOffscreenRenderSystem>();
|
||||||
postOffscreenRender->Init(device, worldRenderGraph->GetRenderGraphResource("Scene"), descPool);
|
postOffscreenRender->Init(device, worldRenderGraph->GetRenderGraphResource("Scene"), descPool);
|
||||||
|
|
||||||
|
lightingSubSystem = resourceManager.Create<SHLightingSubSystem>();
|
||||||
|
lightingSubSystem->Init(device, descPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
|
@ -353,10 +355,12 @@ namespace SHADE
|
||||||
// Begin recording the command buffer
|
// Begin recording the command buffer
|
||||||
currentCmdBuffer->BeginRecording();
|
currentCmdBuffer->BeginRecording();
|
||||||
|
|
||||||
|
// set viewport and scissor
|
||||||
uint32_t w = static_cast<uint32_t>(viewports[vpIndex]->GetWidth());
|
uint32_t w = static_cast<uint32_t>(viewports[vpIndex]->GetWidth());
|
||||||
uint32_t h = static_cast<uint32_t>(viewports[vpIndex]->GetHeight());
|
uint32_t h = static_cast<uint32_t>(viewports[vpIndex]->GetHeight());
|
||||||
currentCmdBuffer->SetViewportScissor (static_cast<float>(w), static_cast<float>(h), w, h);
|
currentCmdBuffer->SetViewportScissor (static_cast<float>(w), static_cast<float>(h), w, h);
|
||||||
|
|
||||||
|
// Force set the pipeline layout
|
||||||
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout(), SH_PIPELINE_TYPE::GRAPHICS);
|
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout(), SH_PIPELINE_TYPE::GRAPHICS);
|
||||||
|
|
||||||
// Bind all the buffers required for meshes
|
// Bind all the buffers required for meshes
|
||||||
|
@ -368,6 +372,8 @@ namespace SHADE
|
||||||
currentCmdBuffer->BindIndexBuffer(buffer, 0);
|
currentCmdBuffer->BindIndexBuffer(buffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bind the descriptor set for lights
|
||||||
|
lightingSubSystem->Run(currentCmdBuffer, frameIndex);
|
||||||
|
|
||||||
// Bind textures
|
// Bind textures
|
||||||
auto textureDescSet = texLibrary.GetTextureDescriptorSetGroup();
|
auto textureDescSet = texLibrary.GetTextureDescriptorSetGroup();
|
||||||
|
@ -401,7 +407,7 @@ namespace SHADE
|
||||||
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
|
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Draw first
|
// Draw the scene
|
||||||
renderers[renIndex]->Draw(frameIndex, descPool);
|
renderers[renIndex]->Draw(frameIndex, descPool);
|
||||||
|
|
||||||
// End the command buffer recording
|
// End the command buffer recording
|
||||||
|
@ -673,14 +679,14 @@ namespace SHADE
|
||||||
auto& renderables = SHComponentManager::GetDense<SHRenderable>();
|
auto& renderables = SHComponentManager::GetDense<SHRenderable>();
|
||||||
for (auto& renderable : renderables)
|
for (auto& renderable : renderables)
|
||||||
{
|
{
|
||||||
if (!renderable.WasMaterialChanged())
|
if (!renderable.HasChanged())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Remove from old material's SuperBatch
|
// Remove from old material's SuperBatch
|
||||||
Handle<SHMaterial> prevMaterial = renderable.GetPrevMaterial();
|
Handle<SHMaterialInstance> prevMaterial = renderable.GetPrevMaterial();
|
||||||
if (prevMaterial)
|
if (prevMaterial)
|
||||||
{
|
{
|
||||||
Handle<SHSuperBatch> oldSuperBatch = prevMaterial->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
Handle<SHSuperBatch> oldSuperBatch = prevMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
||||||
oldSuperBatch->Remove(&renderable);
|
oldSuperBatch->Remove(&renderable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,5 +767,10 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Handle<SHRenderGraphNode> SHGraphicsSystem::GetPrimaryRenderpass() const noexcept
|
||||||
|
{
|
||||||
|
return worldRenderGraph->GetNode(G_BUFFER_RENDER_GRAPH_NODE_NAME.data());
|
||||||
|
}
|
||||||
|
|
||||||
#pragma endregion MISC
|
#pragma endregion MISC
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,13 +25,13 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||||
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
|
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
|
||||||
#include "Graphics/RenderGraph/SHRenderGraph.h"
|
#include "Graphics/RenderGraph/SHRenderGraph.h"
|
||||||
#include "Graphics/MiddleEnd/Shaders/SHShaderSourceLibrary.h"
|
|
||||||
#include "Graphics/MiddleEnd/Shaders/SHShaderModuleLibrary.h"
|
#include "Graphics/MiddleEnd/Shaders/SHShaderModuleLibrary.h"
|
||||||
#include "SHMeshLibrary.h"
|
#include "SHMeshLibrary.h"
|
||||||
#include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h"
|
#include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h"
|
||||||
#include "../Textures/SHTextureLibrary.h"
|
#include "../Textures/SHTextureLibrary.h"
|
||||||
#include "../Textures/SHVkSamplerCache.h"
|
#include "../Textures/SHVkSamplerCache.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h"
|
#include "Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h"
|
||||||
|
#include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -135,7 +135,7 @@ namespace SHADE
|
||||||
void RemoveViewport(Handle<SHViewport> viewport);
|
void RemoveViewport(Handle<SHViewport> viewport);
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Material Creation Functions */
|
/* Material Functions */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
Handle<SHMaterial> AddMaterial(Handle<SHVkShaderModule> vertShader, Handle<SHVkShaderModule> fragShader, Handle<SHSubpass> subpass);
|
Handle<SHMaterial> AddMaterial(Handle<SHVkShaderModule> vertShader, Handle<SHVkShaderModule> fragShader, Handle<SHSubpass> subpass);
|
||||||
void RemoveMaterial(Handle<SHMaterial> material);
|
void RemoveMaterial(Handle<SHMaterial> material);
|
||||||
|
@ -143,6 +143,8 @@ namespace SHADE
|
||||||
Handle<SHMaterialInstance> AddOrGetBaseMaterialInstance(Handle<SHMaterial> material);
|
Handle<SHMaterialInstance> AddOrGetBaseMaterialInstance(Handle<SHMaterial> material);
|
||||||
Handle<SHMaterialInstance> AddMaterialInstanceCopy(Handle<SHMaterialInstance> materialInst);
|
Handle<SHMaterialInstance> AddMaterialInstanceCopy(Handle<SHMaterialInstance> materialInst);
|
||||||
void RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance);
|
void RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance);
|
||||||
|
Handle<SHMaterial> GetDefaultMaterial() { return defaultMaterial; }
|
||||||
|
Handle<SHMaterialInstance> GetDefaultMaterialInstance() { return AddOrGetBaseMaterialInstance(defaultMaterial); }
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Mesh Registration Functions */
|
/* Mesh Registration Functions */
|
||||||
|
@ -286,12 +288,17 @@ namespace SHADE
|
||||||
#endif
|
#endif
|
||||||
Handle<SHMousePickSystem> GetMousePickSystem(void) const noexcept {return mousePickSystem;};
|
Handle<SHMousePickSystem> GetMousePickSystem(void) const noexcept {return mousePickSystem;};
|
||||||
Handle<SHPostOffscreenRenderSystem> GetPostOffscreenRenderSystem(void) const noexcept {return postOffscreenRender;};
|
Handle<SHPostOffscreenRenderSystem> GetPostOffscreenRenderSystem(void) const noexcept {return postOffscreenRender;};
|
||||||
|
Handle<SHRenderGraphNode> GetPrimaryRenderpass() const noexcept;
|
||||||
//SHRenderGraph const& GetRenderGraph(void) const noexcept;
|
//SHRenderGraph const& GetRenderGraph(void) const noexcept;
|
||||||
|
|
||||||
//Handle<SHVkRenderpass> GetRenderPass() const { return renderPass; }
|
//Handle<SHVkRenderpass> GetRenderPass() const { return renderPass; }
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constants */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
static constexpr std::string_view G_BUFFER_RENDER_GRAPH_NODE_NAME = "G-Buffer";
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
|
@ -318,7 +325,7 @@ namespace SHADE
|
||||||
SHTextureLibrary texLibrary;
|
SHTextureLibrary texLibrary;
|
||||||
SHSamplerCache samplerCache;
|
SHSamplerCache samplerCache;
|
||||||
SHMaterialInstanceCache materialInstanceCache;
|
SHMaterialInstanceCache materialInstanceCache;
|
||||||
// Viewports
|
// Viewports
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
Handle<SHViewport> editorViewport;
|
Handle<SHViewport> editorViewport;
|
||||||
Handle<SHRenderer> editorRenderer;
|
Handle<SHRenderer> editorRenderer;
|
||||||
|
@ -338,9 +345,7 @@ namespace SHADE
|
||||||
// Temp Cameras
|
// Temp Cameras
|
||||||
Handle<SHCamera> worldCamera;
|
Handle<SHCamera> worldCamera;
|
||||||
Handle<SHCamera> screenCamera;
|
Handle<SHCamera> screenCamera;
|
||||||
|
|
||||||
// TODO: Temporary only until resource library from Xiao Qi is implemented
|
|
||||||
SHShaderSourceLibrary shaderSourceLibrary;
|
|
||||||
SHShaderModuleLibrary shaderModuleLibrary;
|
SHShaderModuleLibrary shaderModuleLibrary;
|
||||||
|
|
||||||
// Temp Materials
|
// Temp Materials
|
||||||
|
@ -351,6 +356,7 @@ namespace SHADE
|
||||||
// Sub systems
|
// Sub systems
|
||||||
Handle<SHMousePickSystem> mousePickSystem;
|
Handle<SHMousePickSystem> mousePickSystem;
|
||||||
Handle<SHPostOffscreenRenderSystem> postOffscreenRender;
|
Handle<SHPostOffscreenRenderSystem> postOffscreenRender;
|
||||||
|
Handle<SHLightingSubSystem> lightingSubSystem;
|
||||||
|
|
||||||
uint32_t resizeWidth;
|
uint32_t resizeWidth;
|
||||||
uint32_t resizeHeight;
|
uint32_t resizeHeight;
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ECS_Base/SHECSMacros.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SHInstancedIntegerData
|
||||||
|
{
|
||||||
|
EntityID eid;
|
||||||
|
uint32_t lightLayer;
|
||||||
|
};
|
||||||
|
}
|
|
@ -4,6 +4,8 @@
|
||||||
#include "Graphics/Pipeline/SHVkPipeline.h"
|
#include "Graphics/Pipeline/SHVkPipeline.h"
|
||||||
#include "SHGraphicsConstants.h"
|
#include "SHGraphicsConstants.h"
|
||||||
#include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h"
|
#include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h"
|
||||||
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
#include "Math/Vector/SHVec4.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -23,7 +25,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate memory for properties
|
// Allocate memory for properties
|
||||||
const Handle<SHShaderBlockInterface> SHADER_INFO = getShaderBlockInterface();
|
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
|
||||||
propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
|
propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
|
||||||
if (propMemorySize <= 0)
|
if (propMemorySize <= 0)
|
||||||
{
|
{
|
||||||
|
@ -49,6 +51,22 @@ namespace SHADE
|
||||||
// Reset all the properties to default values
|
// Reset all the properties to default values
|
||||||
if (propMemory)
|
if (propMemory)
|
||||||
memset(propMemory.get(), 0, propMemorySize);
|
memset(propMemory.get(), 0, propMemorySize);
|
||||||
|
|
||||||
|
// Initialize Vectors to all 1.0 by default
|
||||||
|
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
|
||||||
|
for (int i = 0; i < SHADER_INFO->GetVariableCount(); ++i)
|
||||||
|
{
|
||||||
|
const auto& VAR = SHADER_INFO->GetVariable(i);
|
||||||
|
switch (VAR->type)
|
||||||
|
{
|
||||||
|
case SHShaderBlockInterface::Variable::Type::VECTOR3:
|
||||||
|
setPropertyUnsafe(VAR->offset, SHVec3::One);
|
||||||
|
break;
|
||||||
|
case SHShaderBlockInterface::Variable::Type::VECTOR4:
|
||||||
|
setPropertyUnsafe(VAR->offset, SHVec4::One);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHMaterial::ExportProperties(void* dest) const noexcept
|
void SHMaterial::ExportProperties(void* dest) const noexcept
|
||||||
|
@ -59,14 +77,14 @@ namespace SHADE
|
||||||
|
|
||||||
size_t SHMaterial::GetPropertiesMemorySize() const noexcept
|
size_t SHMaterial::GetPropertiesMemorySize() const noexcept
|
||||||
{
|
{
|
||||||
const Handle<SHShaderBlockInterface> SHADER_INFO = getShaderBlockInterface();
|
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
|
||||||
return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
|
return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Helper Functions */
|
/* Helper Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
Handle<SHShaderBlockInterface> SHMaterial::getShaderBlockInterface() const noexcept
|
Handle<SHShaderBlockInterface> SHMaterial::GetShaderBlockInterface() const noexcept
|
||||||
{
|
{
|
||||||
return pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
return pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
||||||
(
|
(
|
||||||
|
|
|
@ -50,13 +50,24 @@ namespace SHADE
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void SetProperty(const std::string& key, const T& value);
|
void SetProperty(const std::string& key, const T& value);
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
void SetProperty(uint32_t memOffset, const T& value);
|
||||||
|
template<typename T>
|
||||||
T& GetProperty(const std::string& key);
|
T& GetProperty(const std::string& key);
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const T& GetProperty(const std::string& key) const;
|
const T& GetProperty(const std::string& key) const;
|
||||||
|
template<typename T>
|
||||||
|
T& GetProperty(uint32_t memOffset);
|
||||||
|
template<typename T>
|
||||||
|
const T& GetProperty(uint32_t memOffset) const;
|
||||||
void ResetProperties();
|
void ResetProperties();
|
||||||
void ExportProperties(void* dest) const noexcept;
|
void ExportProperties(void* dest) const noexcept;
|
||||||
Byte GetPropertiesMemorySize() const noexcept;
|
Byte GetPropertiesMemorySize() const noexcept;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Query Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
Handle<SHShaderBlockInterface> GetShaderBlockInterface() const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
|
@ -68,7 +79,8 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Helper Functions */
|
/* Helper Functions */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
Handle<SHShaderBlockInterface> getShaderBlockInterface() const noexcept;
|
template<typename T>
|
||||||
|
inline void setPropertyUnsafe(uint32_t memOffset, const T& value); // SetProperty() but without checks
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace SHADE
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void SHMaterial::SetProperty(const std::string& key, const T& value)
|
void SHMaterial::SetProperty(const std::string& key, const T& value)
|
||||||
{
|
{
|
||||||
const auto SHADER_INFO = getShaderBlockInterface();
|
const auto SHADER_INFO = GetShaderBlockInterface();
|
||||||
const auto PROP_INFO = SHADER_INFO->GetVariable(key);
|
const auto PROP_INFO = SHADER_INFO->GetVariable(key);
|
||||||
if (PROP_INFO == nullptr)
|
if (PROP_INFO == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -33,21 +33,32 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get offset and modify the memory directly
|
// Get offset and modify the memory directly
|
||||||
T* dataPtr = propMemory.get() + PROP_INFO->offset;
|
T* dataPtr = reinterpret_cast<T*>(propMemory.get() + PROP_INFO->offset);
|
||||||
*dataPtr = value;
|
*dataPtr = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void SHMaterial::SetProperty(uint32_t memOffset, const T& value)
|
||||||
|
{
|
||||||
|
// Check if out of bounds
|
||||||
|
if (memOffset + sizeof(T) > propMemorySize)
|
||||||
|
throw std::invalid_argument("Attempted to set an invalid property!");
|
||||||
|
// Set
|
||||||
|
setPropertyUnsafe(memOffset, value);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T& SHMaterial::GetProperty(const std::string& key)
|
T& SHMaterial::GetProperty(const std::string& key)
|
||||||
{
|
{
|
||||||
const auto SHADER_INFO = getShaderBlockInterface();
|
const auto SHADER_INFO = GetShaderBlockInterface();
|
||||||
const auto PROP_INFO = SHADER_INFO->GetVariable(key);
|
const auto PROP_INFO = SHADER_INFO->GetVariable(key);
|
||||||
if (PROP_INFO == nullptr)
|
if (PROP_INFO == nullptr)
|
||||||
{
|
{
|
||||||
throw std::invalid_argument("Attempted to set an invalid property!");
|
throw std::invalid_argument("Attempted to retrieve an invalid property!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get offset and return the memory directly
|
// Get offset and return the memory directly
|
||||||
T* dataPtr = propMemory.get() + PROP_INFO->offset;
|
T* dataPtr = reinterpret_cast<T*>(propMemory.get() + PROP_INFO->offset);
|
||||||
return *dataPtr;
|
return *dataPtr;
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -55,5 +66,25 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
return const_cast<const T&>(const_cast<SHMaterial*>(this)->GetProperty(key));
|
return const_cast<const T&>(const_cast<SHMaterial*>(this)->GetProperty(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const T& SHMaterial::GetProperty(uint32_t memOffset) const
|
||||||
|
{
|
||||||
|
// Check if out of bounds
|
||||||
|
if (memOffset + sizeof(T) > propMemorySize)
|
||||||
|
throw std::invalid_argument("Attempted to retrieve an invalid property!");
|
||||||
|
return *(reinterpret_cast<T*>(propMemory.get() + memOffset));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T& SHMaterial::GetProperty(uint32_t memOffset)
|
||||||
|
{
|
||||||
|
return const_cast<const T&>(const_cast<SHMaterial*>(this)->GetProperty(memOffset));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void SHMaterial::setPropertyUnsafe(uint32_t memOffset, const T& value)
|
||||||
|
{
|
||||||
|
(*reinterpret_cast<T*>(propMemory.get() + memOffset)) = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,15 +69,15 @@ namespace SHADE
|
||||||
|
|
||||||
// Search Override Data for the property
|
// Search Override Data for the property
|
||||||
uint32_t PROP_IDX = SHADER_INFO->GetVariableIndex(key);
|
uint32_t PROP_IDX = SHADER_INFO->GetVariableIndex(key);
|
||||||
auto prop = std::find(overrideData.begin(), overrideData.end(), [&](const OverrideData& data)
|
auto prop = std::find_if(overrideData.begin(), overrideData.end(), [&](const OverrideData& data)
|
||||||
{
|
{
|
||||||
return PROP_IDX == data.Index;
|
return PROP_IDX == data.Index;
|
||||||
});
|
});
|
||||||
if (prop == overrideData.end())
|
if (prop == overrideData.end())
|
||||||
throw std::invalid_argument("Attempted to get an property that was not set previously!");
|
throw std::invalid_argument("Attempted to get an property that was not set previously!");
|
||||||
|
|
||||||
// Get offset and return the memory directly
|
// Get offset and return the memory directly
|
||||||
T* dataPtr = dataStore.get() + prop->StoredDataOffset;
|
T* dataPtr = reinterpret_cast<T*>(dataStore.get() + prop->StoredDataOffset);
|
||||||
return *dataPtr;
|
return *dataPtr;
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
@ -17,7 +17,8 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
// Project Includes
|
// Project Includes
|
||||||
#include "Resource/SHHandle.h"
|
#include "Resource/SHHandle.h"
|
||||||
#include "Resource/SHResourceLibrary.h"
|
#include "Resource/SHResourceLibrary.h"
|
||||||
#include "Math/SHMath.h"
|
#include "Math/Vector/SHVec2.h"
|
||||||
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "Graphics/Buffers/SHVkBuffer.h"
|
#include "Graphics/Buffers/SHVkBuffer.h"
|
||||||
#include "Graphics/SHVkUtil.h"
|
#include "Graphics/SHVkUtil.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHViewport.h"
|
#include "Graphics/MiddleEnd/Interface/SHViewport.h"
|
||||||
|
//#include "Graphics/MiddleEnd/Interface/SHInstancedIntegerData.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -53,7 +54,7 @@ namespace SHADE
|
||||||
// wait for the copy to be done
|
// wait for the copy to be done
|
||||||
afterCopyFence->Wait(true, std::numeric_limits<uint64_t>::max());
|
afterCopyFence->Wait(true, std::numeric_limits<uint64_t>::max());
|
||||||
|
|
||||||
pickedEID = imageDataDstBuffer->GetDataFromMappedPointer<uint32_t>(static_cast<uint32_t>(viewportMousePos.y) * entityIDAttachment->GetWidth() + static_cast<uint32_t>(viewportMousePos.x));
|
pickedEID = imageDataDstBuffer->GetDataFromMappedPointer<EntityID>(static_cast<uint32_t>(viewportMousePos.y) * entityIDAttachment->GetWidth() + static_cast<uint32_t>(viewportMousePos.x));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
std::vector combinedImageSampler
|
std::vector combinedImageSampler
|
||||||
{
|
{
|
||||||
std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eGeneral),
|
std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eShaderReadOnlyOptimal),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Register the image view and sampler with the descriptor set. Now whenever rendering to the offscreen image is done, the descriptor set will see the change
|
// Register the image view and sampler with the descriptor set. Now whenever rendering to the offscreen image is done, the descriptor set will see the change
|
||||||
|
|
|
@ -23,23 +23,26 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
void SHRenderable::OnCreate()
|
void SHRenderable::OnCreate()
|
||||||
{
|
{
|
||||||
materialChanged = true;
|
matChanged = true;
|
||||||
sharedMaterial = {};
|
sharedMaterial = {};
|
||||||
material = {};
|
material = {};
|
||||||
oldMaterial = {};
|
oldMaterial = {};
|
||||||
|
|
||||||
|
lightLayer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRenderable::OnDestroy()
|
void SHRenderable::OnDestroy()
|
||||||
{
|
{
|
||||||
|
// Remove from SuperBatch
|
||||||
|
Handle<SHSuperBatch> superBatch = sharedMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
||||||
|
superBatch->Remove(this);
|
||||||
|
|
||||||
|
// Free resources
|
||||||
if (material)
|
if (material)
|
||||||
{
|
{
|
||||||
material.Free();
|
material.Free();
|
||||||
material = {};
|
material = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove from SuperBatch
|
|
||||||
Handle<SHSuperBatch> superBatch = sharedMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
|
||||||
superBatch->Remove(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -51,20 +54,23 @@ namespace SHADE
|
||||||
if (!material && sharedMaterial == materialInstance)
|
if (!material && sharedMaterial == materialInstance)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Flag that material was changed
|
||||||
|
matChanged = true;
|
||||||
|
|
||||||
// Free copies of materials if any
|
// Free copies of materials if any
|
||||||
if (material)
|
if (material)
|
||||||
{
|
{
|
||||||
|
oldMaterial = material;
|
||||||
material.Free();
|
material.Free();
|
||||||
material = {};
|
material = {};
|
||||||
}
|
}
|
||||||
|
else if (sharedMaterial)
|
||||||
// Flag that material was changed
|
{
|
||||||
materialChanged = true;
|
oldMaterial = sharedMaterial;
|
||||||
if (sharedMaterial)
|
}
|
||||||
oldMaterial = sharedMaterial->GetBaseMaterial();
|
|
||||||
|
|
||||||
// Update the material
|
// Update the material
|
||||||
sharedMaterial = materialInstance;
|
sharedMaterial = materialInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<SHMaterialInstance> SHRenderable::GetMaterial() const
|
Handle<SHMaterialInstance> SHRenderable::GetMaterial() const
|
||||||
|
@ -86,10 +92,41 @@ namespace SHADE
|
||||||
|
|
||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Mesh Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
void SHRenderable::SetMesh(Handle<SHMesh> newMesh)
|
||||||
|
{
|
||||||
|
oldMesh = mesh;
|
||||||
|
mesh = newMesh;
|
||||||
|
meshChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Light Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
uint8_t SHRenderable::GetLightLayer(void) const noexcept
|
||||||
|
{
|
||||||
|
return lightLayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Batcher Dispatcher Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
void SHRenderable::ResetChangedFlag()
|
void SHRenderable::ResetChangedFlag()
|
||||||
{
|
{
|
||||||
materialChanged = false;
|
matChanged = false;
|
||||||
oldMaterial = {};
|
meshChanged = false;
|
||||||
|
oldMaterial = {};
|
||||||
|
oldMesh = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RTTR_REGISTRATION
|
||||||
|
{
|
||||||
|
using namespace SHADE;
|
||||||
|
using namespace rttr;
|
||||||
|
|
||||||
|
registration::class_<SHRenderable>("Renderable Component");
|
||||||
|
}
|
|
@ -11,9 +11,10 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
*//*************************************************************************************/
|
*//*************************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
// External Dependencies
|
||||||
|
#include <rttr/registration>
|
||||||
// Project Includes
|
// Project Includes
|
||||||
#include "Resource/SHHandle.h"
|
#include "Resource/SHHandle.h"
|
||||||
//#include "SHTransform.h"
|
|
||||||
#include "ECS_Base/Components/SHComponent.h"
|
#include "ECS_Base/Components/SHComponent.h"
|
||||||
#include "Math/SHMatrix.h"
|
#include "Math/SHMatrix.h"
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
|
@ -50,31 +51,42 @@ namespace SHADE
|
||||||
void SetMaterial(Handle<SHMaterialInstance> materialInstance);
|
void SetMaterial(Handle<SHMaterialInstance> materialInstance);
|
||||||
Handle<SHMaterialInstance> GetMaterial() const;
|
Handle<SHMaterialInstance> GetMaterial() const;
|
||||||
Handle<SHMaterialInstance> GetModifiableMaterial();
|
Handle<SHMaterialInstance> GetModifiableMaterial();
|
||||||
|
Handle<SHMaterialInstance> GetPrevMaterial() const noexcept { return oldMaterial; }
|
||||||
|
bool HasMaterialChanged() const noexcept { return matChanged; }
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
/* Getter Functions */
|
/* Mesh Functions */
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
bool WasMaterialChanged() const noexcept { return materialChanged; }
|
void SetMesh(Handle<SHMesh> newMesh);
|
||||||
Handle<SHMaterial> GetPrevMaterial() const noexcept { return oldMaterial; }
|
Handle<SHMesh> GetMesh() const noexcept { return mesh; }
|
||||||
|
Handle<SHMesh> GetPrevMesh() const noexcept { return oldMesh; }
|
||||||
|
bool HasMeshChanged() const noexcept { return meshChanged; }
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Light Functions */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
uint8_t GetLightLayer (void) const noexcept;
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
/* Batcher Dispatcher Functions */
|
/* Batcher Dispatcher Functions */
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
bool HasChanged() const noexcept { return matChanged || meshChanged; } // Whether or not the mesh or material has changed
|
||||||
void ResetChangedFlag(); // TODO: Lock it so that only SHBatcherDispatcher can access this
|
void ResetChangedFlag(); // TODO: Lock it so that only SHBatcherDispatcher can access this
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
/* Data Members */
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
Handle<SHMesh> Mesh;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
Handle<SHMesh> mesh;
|
||||||
|
Handle<SHMesh> oldMesh;
|
||||||
|
bool meshChanged = true;
|
||||||
Handle<SHMaterialInstance> sharedMaterial;
|
Handle<SHMaterialInstance> sharedMaterial;
|
||||||
Handle<SHMaterialInstance> material;
|
Handle<SHMaterialInstance> material;
|
||||||
bool materialChanged = true;
|
bool matChanged = true;
|
||||||
Handle<SHMaterial> oldMaterial;
|
Handle<SHMaterialInstance> oldMaterial;
|
||||||
|
uint8_t lightLayer;
|
||||||
|
|
||||||
|
RTTR_ENABLE()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHLightComponent.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::OnCreate(void)
|
||||||
|
{
|
||||||
|
lightData.Reset();
|
||||||
|
SetType(SH_LIGHT_TYPE::DIRECTIONAL);
|
||||||
|
indexInBuffer = std::numeric_limits<uint32_t>::max();
|
||||||
|
active = true;
|
||||||
|
Unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::OnDestroy(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::SetPosition(SHVec3 position) noexcept
|
||||||
|
{
|
||||||
|
lightData.position = position;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::SetType(SH_LIGHT_TYPE type) noexcept
|
||||||
|
{
|
||||||
|
lightData.type = type;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::SetDirection(SHVec3 direction) noexcept
|
||||||
|
{
|
||||||
|
lightData.direction = direction;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::SetDiffuseColor(SHVec4 diffuseColor) noexcept
|
||||||
|
{
|
||||||
|
lightData.diffuseColor = diffuseColor;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::ModifyLayer(uint8_t layerIndex, bool value) noexcept
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
lightData.cullingMask |= (1u << layerIndex);
|
||||||
|
else
|
||||||
|
lightData.cullingMask &= ~(1u << layerIndex);
|
||||||
|
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::SetAllLayers(void) noexcept
|
||||||
|
{
|
||||||
|
lightData.cullingMask = std::numeric_limits<uint32_t>::max();
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::ClearAllLayers(void) noexcept
|
||||||
|
{
|
||||||
|
lightData.cullingMask = 0;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::MakeDirty(void) noexcept
|
||||||
|
{
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::ClearDirtyFlag(void) noexcept
|
||||||
|
{
|
||||||
|
dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::Unbind(void) noexcept
|
||||||
|
{
|
||||||
|
bound = false;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::SetBound(uint32_t inIndexInBuffer) noexcept
|
||||||
|
{
|
||||||
|
bound = true;
|
||||||
|
indexInBuffer = inIndexInBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::SetActive(bool flag) noexcept
|
||||||
|
{
|
||||||
|
MakeDirty();
|
||||||
|
active = flag;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SHLightData const& SHLightComponent::GetLightData(void) const noexcept
|
||||||
|
{
|
||||||
|
return lightData;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHLightComponent::IsDirty(void) const noexcept
|
||||||
|
{
|
||||||
|
return dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHLightComponent::GetBound(void) const noexcept
|
||||||
|
{
|
||||||
|
return bound;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SHLightComponent::GetIndexInBuffer(void) const noexcept
|
||||||
|
{
|
||||||
|
return indexInBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ECS_Base/Components/SHComponent.h"
|
||||||
|
#include "SHLightData.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
|
||||||
|
class SH_API SHLightComponent final : public SHComponent
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
//! General data for the light. This will purely be CPU bound. Whatever gets sent to the
|
||||||
|
//! GPU depends on the type of the light.
|
||||||
|
SHLightData lightData;
|
||||||
|
|
||||||
|
//! Since the lighting system is gonna be self contained and light weight, we store this
|
||||||
|
//! so that we only write this to the CPU buffer when this light component change, we don't
|
||||||
|
//! rewrite everything. However we still write to the GPU buffer when everything changes.
|
||||||
|
uint32_t indexInBuffer;
|
||||||
|
|
||||||
|
//! If the light component changed some value we mark this true.
|
||||||
|
bool dirty;
|
||||||
|
|
||||||
|
//! If the light's data is already in the buffers, this will be set to true.
|
||||||
|
bool bound;
|
||||||
|
|
||||||
|
//! If the light is active, this is true.
|
||||||
|
bool active;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* LIFECYCLE FUNCTIONS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void OnCreate (void) override final;
|
||||||
|
void OnDestroy (void) override final;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* SETTERS AND GETTERS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void SetPosition (SHVec3 position) noexcept;
|
||||||
|
void SetType (SH_LIGHT_TYPE type) noexcept;
|
||||||
|
void SetDirection (SHVec3 direction) noexcept;
|
||||||
|
void SetDiffuseColor (SHVec4 diffuseColor) noexcept;
|
||||||
|
void ModifyLayer (uint8_t layerIndex, bool value) noexcept;
|
||||||
|
void SetAllLayers (void) noexcept;
|
||||||
|
void ClearAllLayers (void) noexcept;
|
||||||
|
void MakeDirty (void) noexcept;
|
||||||
|
void ClearDirtyFlag (void) noexcept;
|
||||||
|
void Unbind (void) noexcept;
|
||||||
|
void SetBound (uint32_t inIndexInBuffer) noexcept;
|
||||||
|
void SetActive (bool flag) noexcept;
|
||||||
|
|
||||||
|
|
||||||
|
SHLightData const& GetLightData (void) const noexcept;
|
||||||
|
bool IsDirty (void) const noexcept;
|
||||||
|
bool GetBound (void) const noexcept;
|
||||||
|
uint32_t GetIndexInBuffer (void) const noexcept;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHLightData.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
void SHLightData::Reset(void) noexcept
|
||||||
|
{
|
||||||
|
// no culling is done.
|
||||||
|
cullingMask = std::numeric_limits<uint32_t>::max();
|
||||||
|
|
||||||
|
// reset position to 0
|
||||||
|
position = SHVec3::Zero;
|
||||||
|
|
||||||
|
// direction just point in positive z axis
|
||||||
|
direction = SHVec3::Forward;
|
||||||
|
|
||||||
|
// Diffuse color set to 1
|
||||||
|
diffuseColor = SHVec4::One;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
#include "Math/Vector/SHVec4.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
enum class SH_LIGHT_TYPE : uint32_t
|
||||||
|
{
|
||||||
|
DIRECTIONAL = 0,
|
||||||
|
POINT,
|
||||||
|
SPOT,
|
||||||
|
NUM_TYPES
|
||||||
|
};
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\class
|
||||||
|
Every light will essentially be using this struct. However, when passing
|
||||||
|
light data over to the GPU, the light data will be split according to
|
||||||
|
type for more optimal cache access.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
struct SHLightData
|
||||||
|
{
|
||||||
|
//! position of the light
|
||||||
|
SHVec3 position;
|
||||||
|
|
||||||
|
//! Type of the light
|
||||||
|
SH_LIGHT_TYPE type;
|
||||||
|
|
||||||
|
//! direction of the light
|
||||||
|
SHVec3 direction;
|
||||||
|
|
||||||
|
//! Each bit in this 32 bit field will represent a layer. If the bit is set,
|
||||||
|
//! when a fragment is being evaluated, the shader will use the fragment's
|
||||||
|
//! layer value to AND with the light's. If result is 1, do lighting calculations.
|
||||||
|
uint32_t cullingMask;
|
||||||
|
|
||||||
|
//! Diffuse color emitted by the light
|
||||||
|
SHVec4 diffuseColor;
|
||||||
|
|
||||||
|
void Reset (void) noexcept;
|
||||||
|
//! TODO:
|
||||||
|
//! - Add cut off. (inner and outer).
|
||||||
|
//! - Add constant, linear and quadratic for attenuation
|
||||||
|
//! - Specular color if needed. see below.
|
||||||
|
|
||||||
|
//! Specular color
|
||||||
|
//SHVec4 specularColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,431 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHLightingSubSystem.h"
|
||||||
|
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
|
||||||
|
#include "Tools/SHUtilities.h"
|
||||||
|
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||||
|
#include "Graphics/Buffers/SHVkBuffer.h"
|
||||||
|
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||||
|
#include "SHLightComponent.h"
|
||||||
|
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||||
|
#include "SHLightComponent.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
This function takes an address in the CPU container and writes light
|
||||||
|
component data to it. What gets written depends on the light type.
|
||||||
|
|
||||||
|
\param address
|
||||||
|
The address to write to.
|
||||||
|
|
||||||
|
\param lightComp
|
||||||
|
The light component with the data to write from.
|
||||||
|
|
||||||
|
\param lightType
|
||||||
|
The type of the light
|
||||||
|
|
||||||
|
\return
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::PerTypeData::WriteLightToAddress(void* address, SHLightComponent* lightComp) noexcept
|
||||||
|
{
|
||||||
|
auto const& lightData = lightComp->GetLightData();
|
||||||
|
switch (lightData.type)
|
||||||
|
{
|
||||||
|
case SH_LIGHT_TYPE::DIRECTIONAL:
|
||||||
|
{
|
||||||
|
SHDirectionalLightData* lightPtr = reinterpret_cast<SHDirectionalLightData*>(address);
|
||||||
|
|
||||||
|
lightPtr->cullingMask = lightData.cullingMask;
|
||||||
|
lightPtr->direction = lightData.direction;
|
||||||
|
lightPtr->diffuseColor = lightData.diffuseColor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SH_LIGHT_TYPE::POINT:
|
||||||
|
break;
|
||||||
|
case SH_LIGHT_TYPE::SPOT:
|
||||||
|
break;
|
||||||
|
case SH_LIGHT_TYPE::NUM_TYPES:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Initializes type, intermediate data and buffer. dirty will be true.
|
||||||
|
|
||||||
|
\param lightType
|
||||||
|
type of the light.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::PerTypeData::InitializeData(Handle<SHVkLogicalDevice> logicalDevice, SH_LIGHT_TYPE type) noexcept
|
||||||
|
{
|
||||||
|
// initialize the type
|
||||||
|
lightType = type;
|
||||||
|
|
||||||
|
// boilerplate
|
||||||
|
intermediateData = nullptr;
|
||||||
|
|
||||||
|
// initialize alignment
|
||||||
|
lightDataAlignmentSize = logicalDevice->PadSSBOSize(GetLightTypeSize(type));
|
||||||
|
|
||||||
|
// So create some data!
|
||||||
|
Expand(logicalDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Expands both the CPU container and the GPU buffer when the number of
|
||||||
|
lights have exceeded the capacity.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::PerTypeData::Expand(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
||||||
|
{
|
||||||
|
if (lightDataAlignmentSize == 0)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR ("One of the types of lights have not been accounted for. Make sure lightDataAlignmentSize is not nullptr.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we want to wait for the command buffers to finish using the buffers first
|
||||||
|
logicalDevice->WaitIdle();
|
||||||
|
|
||||||
|
// First time we are initializing lights
|
||||||
|
if (intermediateData == nullptr)
|
||||||
|
{
|
||||||
|
// max lights should start of at STARTING_NUM_LIGHTS lights
|
||||||
|
maxLights = STARTING_NUM_LIGHTS;
|
||||||
|
numLights = 0;
|
||||||
|
|
||||||
|
// Initialize the data for lights
|
||||||
|
intermediateData = std::make_unique<uint8_t[]>(lightDataAlignmentSize * maxLights);
|
||||||
|
|
||||||
|
// We want to initialize 3 times the amount of data required.
|
||||||
|
dataBuffer = logicalDevice->CreateBuffer(maxLights * lightDataAlignmentSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, nullptr, maxLights * lightDataAlignmentSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, vk::BufferUsageFlagBits::eStorageBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// save old number of lights
|
||||||
|
uint32_t const OLD_MAX_LIGHTS = maxLights;
|
||||||
|
|
||||||
|
// before we increase the number of lights, create space to store old data.
|
||||||
|
std::unique_ptr<uint8_t[]> oldData = std::make_unique<uint8_t[]>(lightDataAlignmentSize * OLD_MAX_LIGHTS);
|
||||||
|
|
||||||
|
// copy data over.
|
||||||
|
std::memcpy (oldData.get(), intermediateData.get(), lightDataAlignmentSize * OLD_MAX_LIGHTS);
|
||||||
|
|
||||||
|
// now we start to expand....
|
||||||
|
|
||||||
|
// double space for lights
|
||||||
|
maxLights *= 2;
|
||||||
|
|
||||||
|
// destroy old data and initialize container for double the amount of data.
|
||||||
|
intermediateData = std::make_unique<uint8_t[]>(lightDataAlignmentSize * maxLights);
|
||||||
|
|
||||||
|
// copy old data to new container
|
||||||
|
std::memcpy(intermediateData.get(), oldData.get(), lightDataAlignmentSize * OLD_MAX_LIGHTS);
|
||||||
|
|
||||||
|
// Resize the GPU buffer. TODO: Replace with Resize no copy here
|
||||||
|
dataBuffer->ResizeReplace(maxLights * lightDataAlignmentSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, oldData.get(), lightDataAlignmentSize * OLD_MAX_LIGHTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Gets the size required to store data for a light type.
|
||||||
|
|
||||||
|
\param type
|
||||||
|
Type of a light.
|
||||||
|
|
||||||
|
\return
|
||||||
|
Size required to store a light based on type.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
uint32_t SHLightingSubSystem::PerTypeData::GetLightTypeSize(SH_LIGHT_TYPE type) noexcept
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case SH_LIGHT_TYPE::DIRECTIONAL:
|
||||||
|
// TOOD: Change after creating point light struct
|
||||||
|
return sizeof(SHDirectionalLightData);
|
||||||
|
case SH_LIGHT_TYPE::POINT:
|
||||||
|
return 4;
|
||||||
|
case SH_LIGHT_TYPE::SPOT:
|
||||||
|
// TOOD: Change after creating spot light struct
|
||||||
|
return 4;
|
||||||
|
case SH_LIGHT_TYPE::NUM_TYPES:
|
||||||
|
default:
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Handle<SHVkBuffer> SHLightingSubSystem::PerTypeData::GetDataBuffer(void) const noexcept
|
||||||
|
{
|
||||||
|
return dataBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SHLightingSubSystem::PerTypeData::GetAlignmentSize(void) const noexcept
|
||||||
|
{
|
||||||
|
return lightDataAlignmentSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SHLightingSubSystem::PerTypeData::GetNumLights(void) const noexcept
|
||||||
|
{
|
||||||
|
return numLights;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SHLightingSubSystem::PerTypeData::GetMaxLights(void) const noexcept
|
||||||
|
{
|
||||||
|
return maxLights;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
This function takes in a light comp in the event that its data has not
|
||||||
|
been placed in the buffer yet. It also checks if the size of the buffer
|
||||||
|
is big enough to hold the new light. If the buffer is too small, expand
|
||||||
|
it.
|
||||||
|
|
||||||
|
\param lightComp
|
||||||
|
The light component to add.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::PerTypeData::AddLight(Handle<SHVkLogicalDevice> logicalDevice, SHLightComponent* unboundLight, bool expanded) noexcept
|
||||||
|
{
|
||||||
|
if (unboundLight)
|
||||||
|
{
|
||||||
|
// capacity is full
|
||||||
|
if (numLights == maxLights)
|
||||||
|
{
|
||||||
|
// expand first
|
||||||
|
Expand(logicalDevice);
|
||||||
|
|
||||||
|
expanded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that the container is big enough, bind the new light
|
||||||
|
|
||||||
|
// Get address of write location
|
||||||
|
void* writeLocation = reinterpret_cast<uint8_t*>(intermediateData.get()) + (lightDataAlignmentSize * numLights);
|
||||||
|
|
||||||
|
// Write the light data to address
|
||||||
|
WriteLightToAddress(writeLocation, unboundLight);
|
||||||
|
|
||||||
|
// Set the light component to be bound to that location
|
||||||
|
unboundLight->SetBound(numLights);
|
||||||
|
|
||||||
|
// Increase light count
|
||||||
|
++numLights;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Modify the data at a specific light address.
|
||||||
|
|
||||||
|
\param lightComp
|
||||||
|
The light component to write.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::PerTypeData::ModifyLight(SHLightComponent* lightComp) noexcept
|
||||||
|
{
|
||||||
|
void* writeLocation = reinterpret_cast<uint8_t*>(intermediateData.get()) + (lightDataAlignmentSize * lightComp->GetIndexInBuffer());
|
||||||
|
WriteLightToAddress(writeLocation, lightComp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightingSubSystem::PerTypeData::WriteToGPU(uint32_t frameIndex) noexcept
|
||||||
|
{
|
||||||
|
if (intermediateData)
|
||||||
|
{
|
||||||
|
// we want to write to the offset of the current frame
|
||||||
|
dataBuffer->WriteToMemory(intermediateData.get(), lightDataAlignmentSize * numLights, 0, lightDataAlignmentSize * maxLights * frameIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Update descriptor sets. We want to call this every time we expand buffers.
|
||||||
|
|
||||||
|
\param binding
|
||||||
|
The binding in the set we want to update.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::UpdateDescSet(uint32_t binding) noexcept
|
||||||
|
{
|
||||||
|
auto buffer = perTypeData[binding].GetDataBuffer();
|
||||||
|
|
||||||
|
// We bind the buffer with the correct desc set binding
|
||||||
|
lightingDataDescSet->ModifyWriteDescBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS,
|
||||||
|
binding,
|
||||||
|
{ &buffer, 1 },
|
||||||
|
0,
|
||||||
|
perTypeData[binding].GetAlignmentSize() * perTypeData[binding].GetMaxLights());
|
||||||
|
|
||||||
|
lightingDataDescSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, binding);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Computes dynamic offsets.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::ComputeDynamicOffsets(void) noexcept
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
||||||
|
{
|
||||||
|
for (uint32_t j = 0; j < dynamicOffsets.size(); ++j)
|
||||||
|
{
|
||||||
|
auto const& typeData = perTypeData[j];
|
||||||
|
{
|
||||||
|
dynamicOffsets[i][j] = j * typeData.GetAlignmentSize() * typeData.GetMaxLights();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Initializes per light type data. This includes buffers and descriptor
|
||||||
|
sets.
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::Init(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool) noexcept
|
||||||
|
{
|
||||||
|
SHComponentManager::CreateComponentSparseSet<SHLightComponent>();
|
||||||
|
|
||||||
|
logicalDevice = device;
|
||||||
|
uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES);
|
||||||
|
|
||||||
|
std::vector<uint32_t> variableSizes{ NUM_LIGHT_TYPES };
|
||||||
|
std::fill (variableSizes.begin(), variableSizes.end(), 1);
|
||||||
|
|
||||||
|
// Create the descriptor set
|
||||||
|
lightingDataDescSet = descPool->Allocate({SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS]}, variableSizes);
|
||||||
|
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < NUM_LIGHT_TYPES; ++i)
|
||||||
|
{
|
||||||
|
// initialize all the data first. We add more lights here as we add more types.
|
||||||
|
perTypeData[i].InitializeData(logicalDevice, static_cast<SH_LIGHT_TYPE>(i));
|
||||||
|
UpdateDescSet(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
||||||
|
{
|
||||||
|
dynamicOffsets[i].resize(NUM_LIGHT_TYPES);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Loops through every single light component and checks for dirty light
|
||||||
|
data. If light data is dirty, rewrite to the CPU container. We also want
|
||||||
|
to bind the descriptor set for the light data.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::Run(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
||||||
|
{
|
||||||
|
auto& lightComps = SHComponentManager::GetDense<SHLightComponent>();
|
||||||
|
bool expanded = false;
|
||||||
|
for (auto& light : lightComps)
|
||||||
|
{
|
||||||
|
auto enumValue = SHUtilities::ToUnderlying(light.GetLightData().type);
|
||||||
|
|
||||||
|
// First we want to make sure the light is already bound to the system. if it
|
||||||
|
// isn't, we write it to the correct buffer.
|
||||||
|
if (!light.GetBound())
|
||||||
|
{
|
||||||
|
perTypeData[enumValue].AddLight(logicalDevice, &light, expanded);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there was modification to the light data
|
||||||
|
if (light.IsDirty())
|
||||||
|
{
|
||||||
|
// Write the data to the CPU
|
||||||
|
perTypeData[enumValue].ModifyLight(&light);
|
||||||
|
|
||||||
|
// Light is now updated in the container
|
||||||
|
light.ClearDirtyFlag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write data to GPU
|
||||||
|
for (auto& data : perTypeData)
|
||||||
|
{
|
||||||
|
data.WriteToGPU(frameIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any of the buffers got expanded, the descriptor set is invalid because the expanded buffer
|
||||||
|
// is a new buffer. If some expansion was detected, update descriptor sets.
|
||||||
|
if (expanded)
|
||||||
|
{
|
||||||
|
uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES);
|
||||||
|
for (uint32_t i = 0; i < NUM_LIGHT_TYPES; ++i)
|
||||||
|
{
|
||||||
|
UpdateDescSet(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute dynamic offsets. We don't actually have to compute every frame but its pretty lightweight,
|
||||||
|
// so we do it anyway. #NoteToSelf: if at any point it affects performance, do a check before computing.
|
||||||
|
ComputeDynamicOffsets();
|
||||||
|
|
||||||
|
// Bind descriptor set (We bind at an offset because the buffer holds NUM_FRAME_BUFFERS sets of data).
|
||||||
|
cmdBuffer->BindDescriptorSet(lightingDataDescSet, SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, {dynamicOffsets[frameIndex]});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Does nothing for now.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::Exit(void) noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Resource/SHHandle.h"
|
||||||
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
#include "Math/Vector/SHVec4.h"
|
||||||
|
#include "SHLightData.h"
|
||||||
|
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHVkLogicalDevice;
|
||||||
|
class SHVkDescriptorPool;
|
||||||
|
class SHVkDescriptorSetGroup;
|
||||||
|
class SHVkDescriptorSetLayout;
|
||||||
|
class SHVkBuffer;
|
||||||
|
class SHLightComponent;
|
||||||
|
class SHVkCommandBuffer;
|
||||||
|
|
||||||
|
// Represents how the data will be interpreted in GPU. we want to copy to a container of these before passing to GPU.
|
||||||
|
struct SHDirectionalLightData
|
||||||
|
{
|
||||||
|
//! Direction of the light
|
||||||
|
SHVec3 direction;
|
||||||
|
|
||||||
|
//! Represents if the light is active or not
|
||||||
|
uint32_t active;
|
||||||
|
|
||||||
|
//! Each bit in this 32 bit field will represent a layer. If the bit is set,
|
||||||
|
//! when a fragment is being evaluated, the shader will use the fragment's
|
||||||
|
//! layer value to AND with the light's. If result is 1, do lighting calculations.
|
||||||
|
uint32_t cullingMask;
|
||||||
|
|
||||||
|
//! Diffuse color emitted by the light
|
||||||
|
SHVec4 diffuseColor;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class SH_API SHLightingSubSystem
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
class PerTypeData
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* STATIC MEMBER VARIABLES */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
static constexpr uint32_t STARTING_NUM_LIGHTS = 20;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PRIVATE MEMBER VARIABLES */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
//! Capacity of the container.
|
||||||
|
uint32_t maxLights;
|
||||||
|
|
||||||
|
//! SSBOs need to be aligned. This is to pad lighting structs
|
||||||
|
uint32_t lightDataAlignmentSize;
|
||||||
|
|
||||||
|
//! type of the light. Will be used later when we want to expand
|
||||||
|
SH_LIGHT_TYPE lightType;
|
||||||
|
|
||||||
|
//! number of lights currently alive.
|
||||||
|
uint32_t numLights;
|
||||||
|
|
||||||
|
//! GPU buffer required to store GPU data
|
||||||
|
Handle<SHVkBuffer> dataBuffer;
|
||||||
|
|
||||||
|
//! Before data gets copied to the GPU, it goes into here first. Data here is aligned to whatever struct is
|
||||||
|
//! used to represent data in this container. Note this will store only 1 copy of all the lights, compared
|
||||||
|
//! to the GPU that stores NUM_FRAME_BUFFERS copies.
|
||||||
|
std::unique_ptr<uint8_t[]> intermediateData;
|
||||||
|
|
||||||
|
void WriteLightToAddress (void* address, SHLightComponent* lightComp) noexcept;
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PUBLIC MEMBER FUNCTIONS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void InitializeData (Handle<SHVkLogicalDevice> logicalDevice, SH_LIGHT_TYPE type) noexcept;
|
||||||
|
void Expand (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||||
|
void AddLight (Handle<SHVkLogicalDevice> logicalDevice, SHLightComponent* unboundLight, bool expanded) noexcept;
|
||||||
|
void ModifyLight (SHLightComponent* lightComp) noexcept;
|
||||||
|
void WriteToGPU (uint32_t frameIndex) noexcept;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* GETTERS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
static uint32_t GetLightTypeSize (SH_LIGHT_TYPE type) noexcept;
|
||||||
|
Handle<SHVkBuffer> GetDataBuffer (void) const noexcept;
|
||||||
|
uint32_t GetAlignmentSize (void) const noexcept;
|
||||||
|
uint32_t GetNumLights (void) const noexcept;
|
||||||
|
uint32_t GetMaxLights (void) const noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
//! logical device used for creation
|
||||||
|
Handle<SHVkLogicalDevice> logicalDevice;
|
||||||
|
|
||||||
|
//! The descriptor set that will hold the lighting data. Each binding will hold a buffer, NUM_FRAMES times the size required.
|
||||||
|
Handle<SHVkDescriptorSetGroup> lightingDataDescSet;
|
||||||
|
|
||||||
|
//! Each type will have some data associated with it for processing
|
||||||
|
std::array<PerTypeData, static_cast<uint32_t>(SH_LIGHT_TYPE::NUM_TYPES)> perTypeData;
|
||||||
|
|
||||||
|
//! Container to store dynamic offsets for binding descriptor sets
|
||||||
|
std::array<std::vector<uint32_t>, static_cast<uint32_t>(SHGraphicsConstants::NUM_FRAME_BUFFERS)> dynamicOffsets;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PRIVATE MEMBER FUNCTIONS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void UpdateDescSet (uint32_t binding) noexcept;
|
||||||
|
void ComputeDynamicOffsets (void) noexcept;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PUBLIC MEMBER FUNCTIONS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void Init (Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||||
|
void Run (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
|
||||||
|
void Exit (void) noexcept;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
#include "SHPch.h"
|
#include "SHPch.h"
|
||||||
#include "SHShaderModuleLibrary.h"
|
#include "SHShaderModuleLibrary.h"
|
||||||
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||||
|
#include "Assets/SHAssetManager.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -18,33 +19,33 @@ namespace SHADE
|
||||||
|
|
||||||
*/
|
*/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
void SHShaderModuleLibrary::ImportFromSourceLibrary(Handle<SHVkLogicalDevice>& logicalDeviceHdl, SHShaderSourceLibrary const& sourceLib) noexcept
|
//void SHShaderModuleLibrary::ImportFromSourceLibrary(Handle<SHVkLogicalDevice>& logicalDeviceHdl, SHShaderSourceLibrary const& sourceLib) noexcept
|
||||||
{
|
//{
|
||||||
auto const& sources = sourceLib.GetSourceLibrary();
|
// auto const& sources = sourceLib.GetSourceLibrary();
|
||||||
for (auto const& source : sources)
|
// for (auto const& source : sources)
|
||||||
{
|
// {
|
||||||
vk::ShaderStageFlagBits shaderType{};
|
// vk::ShaderStageFlagBits shaderType{};
|
||||||
switch (source.shaderType)
|
// switch (source.shaderType)
|
||||||
{
|
// {
|
||||||
case SH_SHADER_TYPE::VERTEX:
|
// case SH_SHADER_TYPE::VERTEX:
|
||||||
shaderType = vk::ShaderStageFlagBits::eVertex;
|
// shaderType = vk::ShaderStageFlagBits::eVertex;
|
||||||
break;
|
// break;
|
||||||
case SH_SHADER_TYPE::FRAGMENT:
|
// case SH_SHADER_TYPE::FRAGMENT:
|
||||||
shaderType = vk::ShaderStageFlagBits::eFragment;
|
// shaderType = vk::ShaderStageFlagBits::eFragment;
|
||||||
break;
|
// break;
|
||||||
case SH_SHADER_TYPE::COMPUTE:
|
// case SH_SHADER_TYPE::COMPUTE:
|
||||||
shaderType = vk::ShaderStageFlagBits::eCompute;
|
// shaderType = vk::ShaderStageFlagBits::eCompute;
|
||||||
break;
|
// break;
|
||||||
default:
|
// default:
|
||||||
shaderType = vk::ShaderStageFlagBits::eVertex;
|
// shaderType = vk::ShaderStageFlagBits::eVertex;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
Handle<SHVkShaderModule> newShaderModule = logicalDeviceHdl->CreateShaderModule(source.spirvBinary, "main", shaderType, source.name);
|
// Handle<SHVkShaderModule> newShaderModule = logicalDeviceHdl->CreateShaderModule(source.spirvBinary, "main", shaderType, source.name);
|
||||||
shaderModules.emplace(source.id, newShaderModule);
|
// shaderModules.emplace(source.id, newShaderModule);
|
||||||
stringToID.emplace(source.name, source.id);
|
// stringToID.emplace(source.name, source.id);
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
|
@ -58,12 +59,81 @@ namespace SHADE
|
||||||
|
|
||||||
*/
|
*/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
Handle<SHVkShaderModule> SHShaderModuleLibrary::GetShaderModule(std::string shaderName) const noexcept
|
//Handle<SHVkShaderModule> SHShaderModuleLibrary::GetShaderModule(std::string shaderName) const noexcept
|
||||||
|
//{
|
||||||
|
// if (stringToID.contains(shaderName))
|
||||||
|
// return shaderModules.at(stringToID.at(shaderName));
|
||||||
|
// else
|
||||||
|
// return {};
|
||||||
|
//}
|
||||||
|
|
||||||
|
vk::ShaderStageFlagBits SHShaderModuleLibrary::GetVkShaderFlag(SH_SHADER_TYPE type) noexcept
|
||||||
{
|
{
|
||||||
if (stringToID.contains(shaderName))
|
vk::ShaderStageFlagBits shaderType{};
|
||||||
return shaderModules.at(stringToID.at(shaderName));
|
switch (type)
|
||||||
else
|
{
|
||||||
return {};
|
case SH_SHADER_TYPE::VERTEX:
|
||||||
|
shaderType = vk::ShaderStageFlagBits::eVertex;
|
||||||
|
break;
|
||||||
|
case SH_SHADER_TYPE::FRAGMENT:
|
||||||
|
shaderType = vk::ShaderStageFlagBits::eFragment;
|
||||||
|
break;
|
||||||
|
case SH_SHADER_TYPE::COMPUTE:
|
||||||
|
shaderType = vk::ShaderStageFlagBits::eCompute;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
shaderType = vk::ShaderStageFlagBits::eVertex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shaderType;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
Handle<SHVkShaderModule> SHShaderModuleLibrary::GetBuiltInShaderModule(std::string shaderName) const noexcept
|
||||||
|
{
|
||||||
|
if (builtInShaderModules.contains(shaderName))
|
||||||
|
return builtInShaderModules.at(shaderName);
|
||||||
|
else
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHShaderModuleLibrary::ImportAllShaderSource(Handle<SHVkLogicalDevice>& logicalDeviceHdl) noexcept
|
||||||
|
{
|
||||||
|
uint32_t idCounter{ 0 };
|
||||||
|
|
||||||
|
auto const data = SHAssetManager::GetAllDataOfType(AssetType::SHADER);
|
||||||
|
for (auto const& dataPtr : data)
|
||||||
|
{
|
||||||
|
auto const shader = dynamic_cast<SHShaderAsset const*>(dataPtr);
|
||||||
|
|
||||||
|
Handle<SHVkShaderModule> newShaderModule =
|
||||||
|
logicalDeviceHdl->CreateShaderModule(shader->spirvBinary, "main", GetVkShaderFlag(shader->shaderType), shader->name);
|
||||||
|
|
||||||
|
shaderModules.emplace(idCounter++, newShaderModule);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const builtIn = SHAssetManager::GetAllDataOfType(AssetType::SHADER_BUILT_IN);
|
||||||
|
for (auto const& dataPtr : builtIn)
|
||||||
|
{
|
||||||
|
auto const shader = dynamic_cast<SHShaderAsset const*>(dataPtr);
|
||||||
|
|
||||||
|
Handle<SHVkShaderModule> newShaderModule =
|
||||||
|
logicalDeviceHdl->CreateShaderModule(shader->spirvBinary, "main", GetVkShaderFlag(shader->shaderType), shader->name);
|
||||||
|
|
||||||
|
builtInShaderModules.emplace(shader->name, newShaderModule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHShaderModuleLibrary::ReflectAllShaderModules() noexcept
|
||||||
|
{
|
||||||
|
for (auto& module : shaderModules)
|
||||||
|
{
|
||||||
|
module.second->Reflect();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& module : builtInShaderModules)
|
||||||
|
{
|
||||||
|
module.second->Reflect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
#define SH_SHADER_MODULE_LIBRARY_H
|
#define SH_SHADER_MODULE_LIBRARY_H
|
||||||
|
|
||||||
#include "Graphics/Shaders/SHVkShaderModule.h"
|
#include "Graphics/Shaders/SHVkShaderModule.h"
|
||||||
#include "SHShaderSourceLibrary.h"
|
#include "Assets/Asset Types/SHShaderAsset.h"
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -22,20 +21,23 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
//! Stored shader modules
|
//! Stored shader modules
|
||||||
std::unordered_map<uint32_t, Handle<SHVkShaderModule>> shaderModules;
|
std::unordered_map<uint32_t, Handle<SHVkShaderModule>> shaderModules;
|
||||||
|
std::unordered_map<std::string, Handle<SHVkShaderModule>> builtInShaderModules;
|
||||||
|
|
||||||
//! We want some sort of interface with strings, instead of ints
|
inline vk::ShaderStageFlagBits GetVkShaderFlag(SH_SHADER_TYPE type) noexcept;
|
||||||
std::map<std::string, uint32_t> stringToID;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* PUBLIC MEMBER FUNCTIONS */
|
/* PUBLIC MEMBER FUNCTIONS */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
void ImportFromSourceLibrary(Handle<SHVkLogicalDevice>& logicalDeviceHdl, SHShaderSourceLibrary const& sourceLib) noexcept;
|
//void ImportFromSourceLibrary(Handle<SHVkLogicalDevice>& logicalDeviceHdl, SHShaderSourceLibrary const& sourceLib) noexcept;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* SETTERS AND GETTERS */
|
/* SETTERS AND GETTERS */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
Handle<SHVkShaderModule> GetShaderModule(std::string shaderName) const noexcept;
|
Handle<SHVkShaderModule> GetBuiltInShaderModule(std::string shaderName) const noexcept;
|
||||||
|
|
||||||
|
void ImportAllShaderSource(Handle<SHVkLogicalDevice>& logicalDeviceHdl) noexcept;
|
||||||
|
void ReflectAllShaderModules() noexcept;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,308 +0,0 @@
|
||||||
#include "SHPch.h"
|
|
||||||
#include <filesystem>
|
|
||||||
#include <fstream>
|
|
||||||
#include "SHShaderSourceLibrary.h"
|
|
||||||
#include "Tools/SHLogger.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
/***************************************************************************/
|
|
||||||
/*!
|
|
||||||
|
|
||||||
\brief
|
|
||||||
Initializes the directory to take assets from. TODO: Only temporary until
|
|
||||||
the resource manager is implemented.
|
|
||||||
|
|
||||||
\param directory
|
|
||||||
|
|
||||||
\return
|
|
||||||
|
|
||||||
*/
|
|
||||||
/***************************************************************************/
|
|
||||||
void SHShaderSourceLibrary::Init (std::string directory) noexcept
|
|
||||||
{
|
|
||||||
shaderDirectory = directory;
|
|
||||||
if (shaderDirectory.back() != '/')
|
|
||||||
{
|
|
||||||
shaderDirectory += '/';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/*!
|
|
||||||
|
|
||||||
\brief
|
|
||||||
Private member function to compile a shader STRING source to binary and
|
|
||||||
returns a vector of 4 bytes.
|
|
||||||
|
|
||||||
\param glslSource
|
|
||||||
The GLSL string source.
|
|
||||||
|
|
||||||
\param type
|
|
||||||
Type of the shader: vertex, fragment, compute, etc.
|
|
||||||
|
|
||||||
\param opLevel
|
|
||||||
Optimization level.
|
|
||||||
|
|
||||||
\return
|
|
||||||
Returns a vector of the binary data.
|
|
||||||
|
|
||||||
*/
|
|
||||||
/***************************************************************************/
|
|
||||||
std::vector<uint32_t> SHShaderSourceLibrary::CompileToBinary(std::string const& glslSource, char const* const spirvFilename, SH_SHADER_TYPE type, shaderc_optimization_level opLevel /*= shaderc_optimization_level_zero*/)
|
|
||||||
{
|
|
||||||
// shaderc compiler
|
|
||||||
shaderc::Compiler compiler;
|
|
||||||
shaderc::CompileOptions options;
|
|
||||||
|
|
||||||
options.AddMacroDefinition("MY_DEFINE", "1");
|
|
||||||
|
|
||||||
// Set optimization levels
|
|
||||||
if (opLevel != shaderc_optimization_level_zero)
|
|
||||||
options.SetOptimizationLevel(opLevel);
|
|
||||||
|
|
||||||
// Attempt to get the shaderc equivalent shader stage
|
|
||||||
shaderc_shader_kind shaderKind;
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case SH_SHADER_TYPE::VERTEX:
|
|
||||||
shaderKind = shaderc_shader_kind::shaderc_glsl_vertex_shader;
|
|
||||||
break;
|
|
||||||
case SH_SHADER_TYPE::FRAGMENT:
|
|
||||||
shaderKind = shaderc_shader_kind::shaderc_glsl_fragment_shader;
|
|
||||||
break;
|
|
||||||
case SH_SHADER_TYPE::COMPUTE:
|
|
||||||
shaderKind = shaderc_shader_kind::shaderc_glsl_compute_shader;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
shaderKind = shaderc_shader_kind::shaderc_glsl_vertex_shader;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compile the shader and get the result
|
|
||||||
shaderc::SpvCompilationResult compileResult = compiler.CompileGlslToSpv(glslSource, shaderKind, spirvFilename, options);
|
|
||||||
|
|
||||||
if (compileResult.GetCompilationStatus() != shaderc_compilation_status_success)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Shaderc failed to compile GLSL shader to binary | " + compileResult.GetErrorMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return { compileResult.begin(), compileResult.end() };
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/*!
|
|
||||||
|
|
||||||
\brief
|
|
||||||
TODO: Delete after file IO is implemented. Loads a shader from disk.
|
|
||||||
|
|
||||||
\param filePath
|
|
||||||
file path to the shader in the asset directory.
|
|
||||||
|
|
||||||
\return
|
|
||||||
Returns the data in the file in string form.
|
|
||||||
|
|
||||||
*/
|
|
||||||
/***************************************************************************/
|
|
||||||
std::string SHShaderSourceLibrary::GetStringFromFile(char const* filePath) noexcept
|
|
||||||
{
|
|
||||||
// Retrieve contents from filePath
|
|
||||||
// Ensure ifstream objects can throw exceptions
|
|
||||||
std::ifstream iFile;
|
|
||||||
iFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
|
||||||
std::string fileContent = "";
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Open file
|
|
||||||
// Read file's buffer contents into streams
|
|
||||||
iFile.open(filePath);
|
|
||||||
std::stringstream fileStream;
|
|
||||||
fileStream << iFile.rdbuf();
|
|
||||||
|
|
||||||
fileContent = fileStream.str();
|
|
||||||
|
|
||||||
// Close file handler
|
|
||||||
iFile.close();
|
|
||||||
}
|
|
||||||
catch (std::ifstream::failure e)
|
|
||||||
{
|
|
||||||
std::cerr << "File was not successfully read" << filePath << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fileContent;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/*!
|
|
||||||
|
|
||||||
\brief
|
|
||||||
Load a shader into the library.
|
|
||||||
|
|
||||||
\param filePath
|
|
||||||
file path to the shader in the asset directory.
|
|
||||||
|
|
||||||
*/
|
|
||||||
/***************************************************************************/
|
|
||||||
bool SHShaderSourceLibrary::LoadShader (uint32_t id, std::string glslFile, SH_SHADER_TYPE type, bool checkSpirvOutdated/* = true*/, bool recompileAnyway /*= false*/) noexcept
|
|
||||||
{
|
|
||||||
//if (sourceLibrary.contains(id))
|
|
||||||
//{
|
|
||||||
// SHLOG_ERROR("Shader with ID passed in already exists. Use a different ID");
|
|
||||||
// return false;
|
|
||||||
//}
|
|
||||||
|
|
||||||
std::string fullGLSLPath = shaderDirectory + glslFile;
|
|
||||||
auto path = std::filesystem::path(fullGLSLPath);
|
|
||||||
|
|
||||||
if (path.extension() != ".glsl")
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Shader is not GLSL file, failed to load shader. ");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string spirvFilepath = path.replace_extension("spv").string();
|
|
||||||
|
|
||||||
SHShaderData newShaderData{};
|
|
||||||
newShaderData.shaderType = type;
|
|
||||||
|
|
||||||
// spirv file
|
|
||||||
std::ifstream spirvFile(spirvFilepath, std::ios::ate | std::ios::binary);
|
|
||||||
|
|
||||||
// If we disable spirv validation, file is not checked
|
|
||||||
if (!recompileAnyway &&
|
|
||||||
spirvFile.is_open() &&
|
|
||||||
(checkSpirvOutdated ? (std::filesystem::last_write_time(spirvFilepath) > std::filesystem::last_write_time(fullGLSLPath)) : true))
|
|
||||||
{
|
|
||||||
// Get file size of binary
|
|
||||||
uint32_t fileSize = static_cast<uint32_t>(spirvFile.tellg());
|
|
||||||
|
|
||||||
// resize container to store binary
|
|
||||||
newShaderData.spirvBinary.resize(fileSize / sizeof(uint32_t));
|
|
||||||
|
|
||||||
// Read data from binary file to container
|
|
||||||
spirvFile.seekg(0);
|
|
||||||
spirvFile.read(reinterpret_cast<char*>(newShaderData.spirvBinary.data()), fileSize);
|
|
||||||
|
|
||||||
// close file
|
|
||||||
spirvFile.close();
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Use glslc to generate spirv file
|
|
||||||
newShaderData.spirvBinary = CompileToBinary(GetStringFromFile(fullGLSLPath.c_str()), spirvFilepath.c_str(), type);
|
|
||||||
|
|
||||||
std::ofstream binaryFile(spirvFilepath, std::ios::binary);
|
|
||||||
|
|
||||||
if (binaryFile.is_open())
|
|
||||||
{
|
|
||||||
// write all data to binary file
|
|
||||||
binaryFile.write(reinterpret_cast<const char*>(newShaderData.spirvBinary.data()), newShaderData.spirvBinary.size() * sizeof(uint32_t));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Failed to modify spirv file. ");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newShaderData.name = glslFile;
|
|
||||||
newShaderData.id = id;
|
|
||||||
|
|
||||||
sourceLibrary.emplace_back(std::move (newShaderData));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/*!
|
|
||||||
|
|
||||||
\brief
|
|
||||||
Gets the entire source library.
|
|
||||||
|
|
||||||
\return
|
|
||||||
The container of binary data.
|
|
||||||
|
|
||||||
*/
|
|
||||||
/***************************************************************************/
|
|
||||||
std::vector<SHShaderData> const& SHShaderSourceLibrary::GetSourceLibrary(void) const noexcept
|
|
||||||
{
|
|
||||||
return sourceLibrary;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/*!
|
|
||||||
|
|
||||||
\brief
|
|
||||||
Move ctor for shader data.
|
|
||||||
|
|
||||||
\param rhs
|
|
||||||
The other shader data
|
|
||||||
|
|
||||||
*/
|
|
||||||
/***************************************************************************/
|
|
||||||
SHShaderData::SHShaderData(SHShaderData&& rhs) noexcept
|
|
||||||
: spirvBinary{ std::move (rhs.spirvBinary)}
|
|
||||||
, shaderType{std::move (rhs.shaderType)}
|
|
||||||
, name{ std::move (rhs.name)}
|
|
||||||
, id {std::move (rhs.id)}
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/*!
|
|
||||||
|
|
||||||
\brief
|
|
||||||
Default ctor for shader data. Does nothing.
|
|
||||||
|
|
||||||
*/
|
|
||||||
/***************************************************************************/
|
|
||||||
SHShaderData::SHShaderData(void) noexcept
|
|
||||||
: spirvBinary{}
|
|
||||||
, shaderType{SH_SHADER_TYPE::VERTEX}
|
|
||||||
, name{ }
|
|
||||||
, id{ }
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
SHShaderData::SHShaderData(SHShaderData const& rhs) noexcept
|
|
||||||
: spirvBinary{rhs.spirvBinary}
|
|
||||||
, shaderType{ rhs.shaderType}
|
|
||||||
, name{rhs.name }
|
|
||||||
, id{rhs.id }
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
SHShaderData& SHShaderData::operator=(SHShaderData const& rhs) noexcept
|
|
||||||
{
|
|
||||||
if (this == &rhs)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
spirvBinary = rhs.spirvBinary;
|
|
||||||
shaderType = rhs.shaderType;
|
|
||||||
name = rhs.name;
|
|
||||||
id = rhs.id;
|
|
||||||
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHShaderData& SHShaderData::operator=(SHShaderData&& rhs) noexcept
|
|
||||||
{
|
|
||||||
if (this == &rhs)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
spirvBinary = std::move(rhs.spirvBinary);
|
|
||||||
shaderType = std::move (rhs.shaderType);
|
|
||||||
name = std::move (rhs.name);
|
|
||||||
id = std::move (rhs.id);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
#ifndef SH_SHADER_SOURCE_LIBRARY_H
|
|
||||||
#define SH_SHADER_SOURCE_LIBRARY_H
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include "SHShaderType.h"
|
|
||||||
#include "shaderc/shaderc.hpp"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
struct SHShaderData
|
|
||||||
{
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* MEMBER VARIABLES */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
//! container storing the spirv binary
|
|
||||||
std::vector<uint32_t> spirvBinary;
|
|
||||||
|
|
||||||
//! For the compilation of the shader. Vulkan backend will use it too
|
|
||||||
SH_SHADER_TYPE shaderType;
|
|
||||||
|
|
||||||
//! Name of the shader file (without parent path)
|
|
||||||
std::string name;
|
|
||||||
|
|
||||||
//! id of the shader
|
|
||||||
uint32_t id;
|
|
||||||
|
|
||||||
SHShaderData(void) noexcept;
|
|
||||||
SHShaderData(SHShaderData const& rhs) noexcept;
|
|
||||||
SHShaderData(SHShaderData&& rhs) noexcept;
|
|
||||||
SHShaderData& operator= (SHShaderData&& rhs) noexcept;
|
|
||||||
SHShaderData& operator= (SHShaderData const& rhs) noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: This class is purely temporary and will be converted/changed when XQ implements his resource manager
|
|
||||||
class SHShaderSourceLibrary
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* PRIVATE MEMBER VARIABLES */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
//! Stores all the source data. Take note that the source here is GLSL source and NOT binary data.
|
|
||||||
//! Binary data gets passed to the backend to convert to spirv.
|
|
||||||
std::vector<SHShaderData> sourceLibrary;
|
|
||||||
|
|
||||||
//! The directory where the shaders are located.
|
|
||||||
std::string shaderDirectory;
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* PRIVATE MEMBER FUNCTIONS */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
std::vector<uint32_t> CompileToBinary(std::string const& glslSource, char const* const spirvFilename, SH_SHADER_TYPE type, shaderc_optimization_level opLevel = shaderc_optimization_level_zero);
|
|
||||||
|
|
||||||
// TODO: Delete after file IO is implemented
|
|
||||||
std::string GetStringFromFile(char const* filePath) noexcept;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* PUBLIC MEMBER FUNCTIONS */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
void Init (std::string directory) noexcept;
|
|
||||||
bool LoadShader (uint32_t id, std::string glslFile, SH_SHADER_TYPE type, bool checkSpirvOutdated = true, bool recompileAnyway = false) noexcept;
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* SETTERS AND GETTERS */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
std::vector<SHShaderData> const& GetSourceLibrary(void) const noexcept;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue