Merge remote-tracking branch 'origin/main' into SP3-12-SceneGraph
This commit is contained in:
commit
5bcf20142e
|
@ -0,0 +1,5 @@
|
|||
root = true
|
||||
|
||||
[*.{c,cpp,h,hpp}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
|
@ -1,3 +1,3 @@
|
|||
Name: Cube.003
|
||||
ID: 110152941
|
||||
Type:
|
||||
Name: Cube.003
|
||||
ID: 71245919
|
||||
Type: 4
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
Name: Cube.012
|
||||
ID: 107348815
|
||||
Type:
|
||||
Name: Cube.012
|
||||
ID: 80365422
|
||||
Type: 4
|
||||
|
|
Binary file not shown.
|
@ -4,13 +4,13 @@ Size=1920,20
|
|||
Collapsed=0
|
||||
|
||||
[Window][SHEditorMenuBar]
|
||||
Pos=0,24
|
||||
Size=1920,1036
|
||||
Pos=0,48
|
||||
Size=1920,1012
|
||||
Collapsed=0
|
||||
|
||||
[Window][Hierarchy Panel]
|
||||
Pos=0,120
|
||||
Size=225,940
|
||||
Pos=0,197
|
||||
Size=308,863
|
||||
Collapsed=0
|
||||
DockId=0x00000004,0
|
||||
|
||||
|
@ -20,29 +20,96 @@ Size=400,400
|
|||
Collapsed=0
|
||||
|
||||
[Window][Inspector]
|
||||
Pos=1686,24
|
||||
Size=234,1036
|
||||
Pos=1528,48
|
||||
Size=392,1012
|
||||
Collapsed=0
|
||||
DockId=0x00000006,0
|
||||
|
||||
[Window][Profiler]
|
||||
Pos=0,24
|
||||
Size=225,94
|
||||
Pos=0,48
|
||||
Size=308,147
|
||||
Collapsed=0
|
||||
DockId=0x00000003,0
|
||||
|
||||
[Window][Viewport]
|
||||
Pos=227,24
|
||||
Size=1457,1036
|
||||
Pos=227,48
|
||||
Size=1457,1012
|
||||
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]
|
||||
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,55 Size=1920,1036 Split=X
|
||||
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1684,1036 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=225,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=1293,1036 CentralNode=1 Selected=0x13926F0B
|
||||
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=234,1036 Selected=0xE7039252
|
||||
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X
|
||||
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1526,1036 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=308,1036 Split=Y Selected=0x1E6EB881
|
||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,147 Selected=0x1E6EB881
|
||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,863 Selected=0xE096E5AE
|
||||
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1216,1036 Split=Y Selected=0xB41284E7
|
||||
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,48 +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=571,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=571,92
|
||||
Collapsed=0
|
||||
DockId=0x00000003,0
|
||||
|
||||
[Window][Viewport]
|
||||
Pos=573,48
|
||||
Size=1074,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=571,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=1074,1036 CentralNode=1 Selected=0x13926F0B
|
||||
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
|
||||
ID: 91918845
|
||||
Type:
|
||||
Name: RaccoonPreTexturedVer1_Base9
|
||||
ID: 64651793
|
||||
Type: 3
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
//#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
|
||||
|
||||
#define MASK_WIDTH 3
|
||||
#define HALF_M_WIDTH MASK_WIDTH / 2
|
||||
#define SHM_WIDTH 18
|
||||
#define NUM_MASKS 8
|
||||
|
||||
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 resultImage;
|
||||
|
||||
const float kirsch[8][3][3] = {
|
||||
{
|
||||
{5, 5, 5},
|
||||
{-3, 0, -3}, /*rotation 1 */
|
||||
{-3, -3, -3}
|
||||
},
|
||||
{
|
||||
{5, 5, -3},
|
||||
{5, 0, -3}, /*rotation 2 */
|
||||
{-3, -3, -3}
|
||||
},
|
||||
{
|
||||
{5, -3, -3},
|
||||
{5, 0, -3}, /*rotation 3 */
|
||||
{5, -3, -3}
|
||||
},
|
||||
{
|
||||
{-3, -3, -3},
|
||||
{5, 0, -3}, /*rotation 4 */
|
||||
{5, 5, -3}
|
||||
},
|
||||
{
|
||||
{-3, -3, -3},
|
||||
{-3, 0, -3}, /*rotation 5 */
|
||||
{5, 5, 5}
|
||||
},
|
||||
{
|
||||
{-3, -3, -3},
|
||||
{-3, 0, 5}, /*rotation 6 */
|
||||
{-3, 5, 5}
|
||||
},
|
||||
{
|
||||
{-3, -3, 5},
|
||||
{-3, 0, 5}, /*rotation 7 */
|
||||
{-3, -3, 5}
|
||||
},
|
||||
{
|
||||
{-3, 5, 5},
|
||||
{-3, 0, 5}, /*rotation 8 */
|
||||
{-3, -3, -3}
|
||||
}
|
||||
};
|
||||
|
||||
vec3 GetImageValues(ivec2 uv, ivec2 inputImageSize)
|
||||
{
|
||||
if (uv.x >= 0 && uv.y >= 0 && uv.x < inputImageSize.x && uv.y < inputImageSize.y)
|
||||
{
|
||||
return imageLoad(inputImage, uv).rgb;
|
||||
}
|
||||
else
|
||||
return vec3(0.0f);
|
||||
}
|
||||
|
||||
//two extra row/col
|
||||
shared vec3 sData[16 + 2][16 + 2];
|
||||
|
||||
void main()
|
||||
{
|
||||
// convenient variables
|
||||
ivec3 globalThread = ivec3(gl_GlobalInvocationID);
|
||||
ivec3 localThread = ivec3(gl_LocalInvocationID);
|
||||
ivec2 inputImageSize = imageSize(inputImage);
|
||||
|
||||
// load shared memory
|
||||
ivec2 start = ivec2(gl_WorkGroupID) * ivec2(gl_WorkGroupSize) - ivec2(HALF_M_WIDTH);
|
||||
for (int i = localThread.x; i < SHM_WIDTH; i += int(gl_WorkGroupSize.x))
|
||||
{
|
||||
for (int j = localThread.y; j < SHM_WIDTH; j += int(gl_WorkGroupSize.y))
|
||||
{
|
||||
// get from source image (either real values or 0)
|
||||
vec3 sourceValue = GetImageValues(start + ivec2(i, j), inputImageSize);
|
||||
sData[i][j] = sourceValue;
|
||||
}
|
||||
}
|
||||
|
||||
// wait for shared memory to finish loading
|
||||
barrier();
|
||||
|
||||
// max (between all 8 masks)
|
||||
vec3 maxSum = vec3(0.0f);
|
||||
|
||||
// loop through all masks
|
||||
for (int i = 0; i < NUM_MASKS; ++i)
|
||||
{
|
||||
vec3 sum = vec3(0.0f);
|
||||
|
||||
// start of shared memory
|
||||
ivec2 shmStart = ivec2(localThread + HALF_M_WIDTH);
|
||||
for (int j = -1; j < HALF_M_WIDTH + 1; ++j)
|
||||
{
|
||||
for (int k = -1; k < HALF_M_WIDTH + 1; ++k)
|
||||
{
|
||||
// Perform convolution using shared_memory
|
||||
sum += sData[shmStart.x + j][shmStart.y + k] * kirsch[i][j + 1][k + 1];
|
||||
}
|
||||
}
|
||||
|
||||
// Get highest sum
|
||||
maxSum = max(sum, maxSum);
|
||||
}
|
||||
|
||||
// average the max sum
|
||||
maxSum = min(max(maxSum / 8, 0), 1.0f);
|
||||
|
||||
// store result into result image
|
||||
imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), vec4(maxSum, 1.0f));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
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;
|
||||
uint eid;
|
||||
uint lightLayerIndex;
|
||||
} In2;
|
||||
|
||||
//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 = 1) out uint outEntityID;
|
||||
layout(location = 2) out uint lightLayerIndices;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
@ -42,5 +44,6 @@ void main()
|
|||
MatProp.data[In2.materialIndex].color / MatProp.data[In2.materialIndex].alpha;
|
||||
|
||||
outEntityID = In2.eid;
|
||||
lightLayerIndices = In2.lightLayerIndex;
|
||||
//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"
|
||||
|
||||
|
||||
layout(location = 0) in vec3 aVertexPos;
|
||||
layout(location = 1) in vec2 aUV;
|
||||
layout(location = 2) in vec3 aNormal;
|
||||
layout(location = 3) in vec3 aTangent;
|
||||
layout(location = 4) in mat4 worldTransform;
|
||||
layout(location = 8) in uint eid;
|
||||
layout(location = 8) in uvec2 integerData;
|
||||
|
||||
|
||||
layout(location = 0) out struct
|
||||
|
@ -23,6 +24,7 @@ layout(location = 2) out struct
|
|||
{
|
||||
int materialIndex;
|
||||
uint eid;
|
||||
uint lightLayerIndex;
|
||||
|
||||
} Out2;
|
||||
|
||||
|
@ -36,7 +38,8 @@ void main()
|
|||
{
|
||||
Out.uv = aUV;
|
||||
Out2.materialIndex = gl_InstanceIndex;
|
||||
Out2.eid = eid;
|
||||
Out2.eid = integerData[0];
|
||||
Out2.lightLayerIndex = integerData[1];
|
||||
gl_Position = cameraData.vpMat * worldTransform * 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
|
||||
)
|
||||
{
|
||||
// Set working directory
|
||||
SHFileUtilities::SetWorkDirToExecDir();
|
||||
// Set working directory
|
||||
SHFileUtilities::SetWorkDirToExecDir();
|
||||
|
||||
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
|
||||
|
||||
|
@ -83,16 +83,19 @@ namespace Sandbox
|
|||
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::LateUpdateRoutine>();
|
||||
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::FrameCleanUpRoutine>();
|
||||
|
||||
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostLogicUpdate>();
|
||||
|
||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>();
|
||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>();
|
||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
|
||||
|
||||
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformUpdateRoutine>();
|
||||
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
|
||||
|
||||
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>();
|
||||
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();
|
||||
|
||||
SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::EditorCameraUpdate>();
|
||||
SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::CameraSystemUpdate>();
|
||||
|
||||
#ifdef SHEDITOR
|
||||
SHSystemManager::RegisterRoutine<SHEditor, SHEditor::EditorRoutine>();
|
||||
|
@ -107,14 +110,7 @@ namespace Sandbox
|
|||
SHComponentManager::CreateComponentSparseSet<SHRenderable>();
|
||||
SHComponentManager::CreateComponentSparseSet<SHCameraComponent>();
|
||||
|
||||
//TODO: REMOVE AFTER PRESENTATION
|
||||
//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
|
||||
|
||||
SHAssetManager::Load();
|
||||
|
||||
auto id = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
|
||||
auto id2 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
|
||||
|
@ -130,8 +126,6 @@ namespace Sandbox
|
|||
SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
|
||||
|
||||
SHFrameRateController::UpdateFRC();
|
||||
|
||||
SHAssetManager::Load();
|
||||
}
|
||||
|
||||
void SBApplication::Update(void)
|
||||
|
@ -151,15 +145,14 @@ namespace Sandbox
|
|||
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
|
||||
editor->PollPicking();
|
||||
}
|
||||
|
||||
// Finish all graphics jobs first
|
||||
graphicsSystem->AwaitGraphicsExecution();
|
||||
graphicsSystem->AwaitGraphicsExecution();
|
||||
}
|
||||
|
||||
|
||||
void SBApplication::Exit(void)
|
||||
{
|
||||
#ifdef SHEDITOR
|
||||
#ifdef SHEDITOR
|
||||
SDL_DestroyWindow(sdlWindow);
|
||||
SDL_Quit();
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "SBpch.h"
|
||||
#include "SBpch.h"
|
||||
#include "SBTestScene.h"
|
||||
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
|
@ -12,8 +12,11 @@
|
|||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
||||
#include "Physics/Components/SHColliderComponent.h"
|
||||
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||
|
||||
#include "Assets/SHAssetManager.h"
|
||||
#include "Camera/SHCameraComponent.h"
|
||||
#include "Resource/SHResourceManager.h"
|
||||
|
||||
using namespace SHADE;
|
||||
|
||||
|
@ -40,34 +43,23 @@ namespace Sandbox
|
|||
const auto CUBE_MESH = SHADE::SHPrimitiveGenerator::Cube(*graphicsSystem);
|
||||
|
||||
//Test Racoon mesh
|
||||
auto meshes = SHADE::SHAssetManager::GetAllMeshes();
|
||||
std::vector<Handle<SHMesh>> handles;
|
||||
for (auto const& mesh : meshes)
|
||||
std::vector<Handle<SHTexture>> texHandles;
|
||||
for (const auto& asset : SHAssetManager::GetAllAssets())
|
||||
{
|
||||
if (mesh.header.meshName == "Cube.012")
|
||||
switch (asset.type)
|
||||
{
|
||||
handles.push_back(graphicsSystem->AddMesh(
|
||||
mesh.header.vertexCount,
|
||||
mesh.vertexPosition.data(),
|
||||
mesh.texCoords.data(),
|
||||
mesh.vertexTangent.data(),
|
||||
mesh.vertexNormal.data(),
|
||||
mesh.header.indexCount,
|
||||
mesh.indices.data()
|
||||
));
|
||||
case AssetType::MESH:
|
||||
if (asset.name == "Cube.012")
|
||||
handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id));
|
||||
break;
|
||||
case AssetType::TEXTURE:
|
||||
if (asset.name == "RaccoonPreTexturedVer1_Base9")
|
||||
texHandles.emplace_back(SHResourceManager::LoadOrGet<SHTexture>(asset.id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
graphicsSystem->BuildMeshBuffers();
|
||||
|
||||
// Load Textures
|
||||
auto textures = SHADE::SHAssetManager::GetAllTextures();
|
||||
std::vector<Handle<SHTexture>> texHandles;
|
||||
for (const auto& tex : textures)
|
||||
{
|
||||
auto texture = graphicsSystem->Add(tex);
|
||||
texHandles.push_back(texture);
|
||||
}
|
||||
graphicsSystem->BuildTextures();
|
||||
SHResourceManager::FinaliseChanges();
|
||||
|
||||
// Create Materials
|
||||
auto matInst = graphicsSystem->AddOrGetBaseMaterialInstance();
|
||||
|
@ -77,9 +69,9 @@ namespace Sandbox
|
|||
customMat->SetProperty("data.alpha", 0.1f);
|
||||
|
||||
// Create Stress Test Objects
|
||||
static const SHVec3 TEST_OBJ_SCALE = SHVec3::One * 0.5f;
|
||||
constexpr int NUM_ROWS = 10;
|
||||
constexpr int NUM_COLS = 10;
|
||||
static const SHVec3 TEST_OBJ_SCALE = SHVec3::One;
|
||||
constexpr int NUM_ROWS = 3;
|
||||
constexpr int NUM_COLS = 1;
|
||||
static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f };
|
||||
static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f };
|
||||
|
||||
|
@ -92,7 +84,7 @@ namespace Sandbox
|
|||
auto& collider = *SHComponentManager::GetComponent_s<SHColliderComponent>(entity);
|
||||
|
||||
//renderable.Mesh = handles.front();
|
||||
renderable.Mesh = CUBE_MESH;
|
||||
renderable.SetMesh(CUBE_MESH);
|
||||
renderable.SetMaterial(customMat);
|
||||
|
||||
if (y == 50)
|
||||
|
@ -101,13 +93,13 @@ namespace Sandbox
|
|||
//Set initial positions
|
||||
transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, y * TEST_OBJ_SPACING.y, SHMath::GenerateRandomNumber(-3.5f, -5.0f) });
|
||||
//transform.SetWorldPosition({-1.0f, -1.0f, -1.0f});
|
||||
transform.SetWorldRotation(SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber());
|
||||
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);
|
||||
|
||||
if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN)
|
||||
//if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN)
|
||||
collider.AddBoundingBox(SHVec3::One * 0.5f, SHVec3::Zero);
|
||||
else
|
||||
collider.AddBoundingSphere(0.5f, SHVec3::Zero);
|
||||
//else
|
||||
// collider.AddBoundingSphere(0.5f, SHVec3::Zero);
|
||||
|
||||
stressTestObjects.emplace_back(entity);
|
||||
}
|
||||
|
@ -116,7 +108,7 @@ namespace Sandbox
|
|||
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonSpin);
|
||||
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonSpin);
|
||||
|
||||
renderable.Mesh = handles.front();
|
||||
renderable.SetMesh(handles.front());
|
||||
renderable.SetMaterial(customMat);
|
||||
renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
renderable.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
|
||||
|
@ -131,7 +123,7 @@ namespace Sandbox
|
|||
auto& floorRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(floor);
|
||||
auto& floorCollider = *SHComponentManager::GetComponent_s<SHColliderComponent>(floor);
|
||||
|
||||
floorRenderable.Mesh = CUBE_MESH;
|
||||
floorRenderable.SetMesh(CUBE_MESH);
|
||||
floorRenderable.SetMaterial(customMat);
|
||||
floorRenderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
|
||||
|
@ -157,7 +149,7 @@ namespace Sandbox
|
|||
auto& renderableShowcase = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonShowcase);
|
||||
auto& transformShowcase = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonShowcase);
|
||||
|
||||
renderableShowcase.Mesh = handles.front();
|
||||
renderableShowcase.SetMesh(handles.front());
|
||||
renderableShowcase.SetMaterial(customMat);
|
||||
renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
|
||||
|
@ -166,6 +158,11 @@ namespace Sandbox
|
|||
transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f });
|
||||
transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f });
|
||||
scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase");
|
||||
|
||||
SHComponentManager::AddComponent<SHCameraComponent>(0);
|
||||
SHComponentManager::AddComponent<SHLightComponent>(0);
|
||||
SHComponentManager::RemoveComponent <SHRigidBodyComponent>(0);
|
||||
SHComponentManager::RemoveComponent <SHColliderComponent>(0);
|
||||
}
|
||||
|
||||
void SBTestScene::Update(float dt)
|
||||
|
|
|
@ -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,30 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHAnimationAsset.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 <vector>
|
||||
#include <assimp/anim.h>
|
||||
#include "SHAssetData.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SH_API SHAnimationAsset : SHAssetData
|
||||
{
|
||||
std::string name;
|
||||
|
||||
std::vector<aiNodeAnim*> nodeChannels;
|
||||
std::vector<aiMeshAnim*> meshChannels;
|
||||
std::vector<aiMeshMorphAnim*> morphMeshChannels;
|
||||
|
||||
double duration;
|
||||
double ticksPerSecond;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHAssetDataBase.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
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHAssetData
|
||||
{
|
||||
virtual ~SHAssetData(){}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
#include "SHMeshAsset.h"
|
||||
#include "SHTextureAsset.h"
|
|
@ -0,0 +1,21 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHInternalAsset.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 "SHAsset.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHInternalAsset : SHAsset
|
||||
{
|
||||
|
||||
};
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include <vector>
|
||||
#include "Math/SHMath.h"
|
||||
#include "SH_API.h"
|
||||
#include "SHAssetData.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -22,10 +22,10 @@ namespace SHADE
|
|||
{
|
||||
uint32_t vertexCount;
|
||||
uint32_t indexCount;
|
||||
std::string meshName;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct SH_API SHMeshAsset
|
||||
struct SH_API SHMeshAsset : SHAssetData
|
||||
{
|
||||
bool compiled;
|
||||
bool changed;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
|
@ -2,10 +2,11 @@
|
|||
|
||||
#include "tinyddsloader.h"
|
||||
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
|
||||
#include "SHAssetData.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHTextureAsset
|
||||
struct SHTextureAsset : SHAssetData
|
||||
{
|
||||
bool compiled;
|
||||
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
/*************************************************************************//**
|
||||
* \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 <assimp/postprocess.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
||||
Assimp::Importer SHMeshCompiler::aiImporter;
|
||||
|
||||
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]];
|
||||
meshes.push_back(ProcessMesh(*mesh));
|
||||
}
|
||||
|
||||
for (size_t i{ 0 }; i < node.mNumChildren; ++i)
|
||||
{
|
||||
ProcessNode(*node.mChildren[i], scene, meshes);
|
||||
}
|
||||
}
|
||||
|
||||
void SHMeshCompiler::ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept
|
||||
{
|
||||
if (scene.HasAnimations())
|
||||
{
|
||||
std::vector<SHAnimationAsset> anims(scene.mNumAnimations);
|
||||
for (auto i{ 0 }; i < scene.mNumAnimations; ++i)
|
||||
{
|
||||
auto const& anim{ *scene.mAnimations[i] };
|
||||
|
||||
anims[i].name = anim.mName.C_Str();
|
||||
|
||||
anims[i].duration = anim.mDuration;
|
||||
anims[i].ticksPerSecond = anim.mTicksPerSecond;
|
||||
|
||||
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.mMorphMeshChannels, anim.mNumMorphMeshChannels, anims[i].morphMeshChannels.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SHMeshAsset* SHMeshCompiler::ProcessMesh(aiMesh const& mesh) noexcept
|
||||
{
|
||||
SHMeshAsset* result = new SHMeshAsset();
|
||||
result->compiled = false;
|
||||
result->changed = false;
|
||||
|
||||
for (size_t i{ 0 }; i < mesh.mNumVertices; ++i)
|
||||
{
|
||||
// Vertex position
|
||||
SHVec3 vertex;
|
||||
vertex.x = mesh.mVertices[i].x;
|
||||
vertex.y = mesh.mVertices[i].y;
|
||||
vertex.z = mesh.mVertices[i].z;
|
||||
result->vertexPosition.push_back(vertex);
|
||||
|
||||
// Tex coords
|
||||
SHVec2 texCoord{ 0.f, 0.f };
|
||||
if (mesh.mTextureCoords[0])
|
||||
{
|
||||
texCoord.x = mesh.mTextureCoords[0][i].x;
|
||||
texCoord.y = mesh.mTextureCoords[0][i].y;
|
||||
}
|
||||
result->texCoords.push_back(texCoord);
|
||||
|
||||
// Normals
|
||||
SHVec3 normal{ 0.f, 0.f, 0.f };
|
||||
if (mesh.mNormals)
|
||||
{
|
||||
normal.x = mesh.mNormals[i].x;
|
||||
normal.y = mesh.mNormals[i].y;
|
||||
normal.z = mesh.mNormals[i].z;
|
||||
}
|
||||
result->vertexNormal.push_back(normal);
|
||||
|
||||
// Tangent
|
||||
SHVec3 tangent{ 0.f, 0.f, 0.f };
|
||||
if (mesh.mTangents)
|
||||
{
|
||||
tangent.x = mesh.mTangents[i].x;
|
||||
tangent.y = mesh.mTangents[i].y;
|
||||
tangent.z = mesh.mTangents[i].z;
|
||||
}
|
||||
result->vertexTangent.push_back(tangent);
|
||||
}
|
||||
|
||||
for (size_t i{ 0 }; i < mesh.mNumFaces; ++i)
|
||||
{
|
||||
aiFace face = mesh.mFaces[i];
|
||||
for (size_t j{ 0 }; j < face.mNumIndices; ++j)
|
||||
{
|
||||
result->indices.push_back(face.mIndices[j]);
|
||||
}
|
||||
}
|
||||
|
||||
result->header.vertexCount = static_cast<uint32_t>(result->vertexPosition.size());
|
||||
result->header.indexCount = static_cast<uint32_t>(result->indices.size());
|
||||
result->header.name = mesh.mName.C_Str();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SHMeshCompiler::LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept
|
||||
{
|
||||
const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
|
||||
aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
|
||||
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
|
||||
| aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...)
|
||||
| aiProcess_FindInstances // search for instanced meshes and remove them by references to one master
|
||||
| aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible
|
||||
| aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing
|
||||
| aiProcess_RemoveRedundantMaterials // remove redundant materials
|
||||
| aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors
|
||||
| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
|
||||
);
|
||||
|
||||
if (!scene || !scene->HasMeshes())
|
||||
{
|
||||
SHLOG_ERROR("ERROR in GLTF::ASSIMP: {}\nFile: {}", aiImporter.GetErrorString(), path.string());
|
||||
return;
|
||||
}
|
||||
|
||||
//ExtractAnimations(*scene, anims);
|
||||
|
||||
ProcessNode(*scene->mRootNode, *scene, meshes);
|
||||
|
||||
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);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHAssetLoader.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 "Assets/SHAssetMacros.h"
|
||||
#include "Assets/Asset Types/SHAssetData.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHAssetLoader
|
||||
{
|
||||
virtual SHAssetData* Load(AssetPath path) = 0;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshLoader.cpp
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Implementation for Mesh loader. Accounts for custom binary format
|
||||
* as well as GLTF file 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 "SHMeshLoader.h"
|
||||
#include <fstream>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
void SHMeshLoader::LoadSHMesh(AssetPath path, SHMeshAsset& mesh) noexcept
|
||||
{
|
||||
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("Unable to open SHMesh File: {}", path.string());
|
||||
}
|
||||
|
||||
const std::string name{ path.stem().string() };
|
||||
|
||||
file.seekg(0);
|
||||
|
||||
uint32_t vertCount, indexCount;
|
||||
std::vector<SHVec3> vertPos, vertTan, vertNorm;
|
||||
std::vector<SHVec2> texCoord;
|
||||
std::vector<uint32_t> indices;
|
||||
|
||||
file.read(reinterpret_cast<char*>(&vertCount), sizeof(uint32_t));
|
||||
file.read(reinterpret_cast<char*>(&indexCount), sizeof(uint32_t));
|
||||
|
||||
auto const vertexVec3Byte{ sizeof(SHVec3) * vertCount };
|
||||
auto const vertexVec2Byte{ sizeof(SHVec2) * vertCount };
|
||||
|
||||
vertPos.resize(vertCount);
|
||||
vertTan.resize(vertCount);
|
||||
vertNorm.resize(vertCount);
|
||||
texCoord.resize(vertCount);
|
||||
indices.resize(indexCount);
|
||||
|
||||
file.read(reinterpret_cast<char *>(vertPos.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char *>(vertTan.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char *>(vertNorm.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char *>(texCoord.data()), vertexVec2Byte);
|
||||
file.read(reinterpret_cast<char *>(indices.data()), sizeof(uint32_t) * indexCount);
|
||||
|
||||
mesh.compiled = true;
|
||||
mesh.changed = false;
|
||||
|
||||
mesh.header.indexCount = indexCount;
|
||||
mesh.header.vertexCount = vertCount;
|
||||
mesh.header.name = name;
|
||||
|
||||
mesh.vertexPosition = std::move(vertPos);
|
||||
mesh.vertexTangent = std::move(vertTan);
|
||||
mesh.vertexNormal = std::move(vertNorm);
|
||||
mesh.texCoords = std::move(texCoord);
|
||||
mesh.indices = std::move(indices);
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
SHAssetData* SHMeshLoader::Load(AssetPath path)
|
||||
{
|
||||
auto result = new SHMeshAsset();
|
||||
|
||||
LoadSHMesh(path, *result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshCompiler.h
|
||||
* \file SHMeshLoader.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
|
||||
* \brief Library to load gltf mesh files and custom binary format
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
|
@ -11,16 +10,15 @@
|
|||
* of DigiPen Institute of Technology is prohibited.
|
||||
*****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "../Asset Types/SHMeshAsset.h"
|
||||
#include "../SHAssetMacros.h"
|
||||
#include "Assets/SHAssetMacros.h"
|
||||
#include "Assets/Asset Types/SHMeshAsset.h"
|
||||
#include "SHAssetLoader.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHMeshCompiler
|
||||
struct SHMeshLoader : SHAssetLoader
|
||||
{
|
||||
private:
|
||||
public:
|
||||
static std::string CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept;
|
||||
void LoadSHMesh(AssetPath path, SHMeshAsset& meshes) noexcept;
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHShaderSourceLoader.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/Libraries/Loaders/SHAssetLoader.h"
|
||||
#include "Assets/SHAssetMacros.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHShaderSourceLoader : SHAssetLoader
|
||||
{
|
||||
SHAssetData* Load(AssetPath path) override;
|
||||
};
|
||||
}
|
|
@ -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
|
||||
* \date 30 September 2022
|
||||
* \brief Library to write data in SHTextureAsset into binary file for
|
||||
* faster loading in the future
|
||||
* \brief Library to load dds textures and custom binary format
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
|
@ -12,13 +11,15 @@
|
|||
*****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||
#include "Assets/SHAssetMacros.h"
|
||||
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||
#include "SHAssetLoader.h"
|
||||
|
||||
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,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.meshName + MESH_EXTENSION;
|
||||
|
||||
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,231 +0,0 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshLoader.cpp
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Implementation for Mesh loader. Accounts for custom binary format
|
||||
* as well as GLTF file 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 "SHMeshLoader.h"
|
||||
#include <assimp/postprocess.h>
|
||||
#include <fstream>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
Assimp::Importer SHMeshLoader::aiImporter;
|
||||
|
||||
void SHMeshLoader::ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes) noexcept
|
||||
{
|
||||
for (size_t i {0}; i < node.mNumMeshes; ++i)
|
||||
{
|
||||
aiMesh* mesh = scene.mMeshes[node.mMeshes[i]];
|
||||
meshes.push_back(ProcessMesh(*mesh, scene));
|
||||
}
|
||||
|
||||
for (size_t i{ 0 }; i < node.mNumChildren; ++i)
|
||||
{
|
||||
ProcessNode(*node.mChildren[i], scene, meshes);
|
||||
}
|
||||
}
|
||||
|
||||
SHMeshAsset SHMeshLoader::ProcessMesh(aiMesh const& mesh, aiScene const& scene) noexcept
|
||||
{
|
||||
(void)scene;
|
||||
|
||||
SHMeshAsset result
|
||||
{
|
||||
.compiled { false},
|
||||
.changed { false }
|
||||
};
|
||||
|
||||
for (size_t i{0}; i < mesh.mNumVertices; ++i)
|
||||
{
|
||||
// Vertex position
|
||||
SHVec3 vertex;
|
||||
vertex.x = mesh.mVertices[i].x;
|
||||
vertex.y = mesh.mVertices[i].y;
|
||||
vertex.z = mesh.mVertices[i].z;
|
||||
result.vertexPosition.push_back(vertex);
|
||||
|
||||
// Tex coords
|
||||
SHVec2 texCoord{0.f, 0.f};
|
||||
if (mesh.mTextureCoords[0])
|
||||
{
|
||||
texCoord.x = mesh.mTextureCoords[0][i].x;
|
||||
texCoord.y = mesh.mTextureCoords[0][i].y;
|
||||
}
|
||||
result.texCoords.push_back(texCoord);
|
||||
|
||||
// Normals
|
||||
SHVec3 normal{0.f, 0.f, 0.f};
|
||||
if (mesh.mNormals)
|
||||
{
|
||||
normal.x = mesh.mNormals[i].x;
|
||||
normal.y = mesh.mNormals[i].y;
|
||||
normal.z = mesh.mNormals[i].z;
|
||||
}
|
||||
result.vertexNormal.push_back(normal);
|
||||
|
||||
// Tangent
|
||||
SHVec3 tangent{0.f, 0.f, 0.f};
|
||||
if (mesh.mTangents)
|
||||
{
|
||||
tangent.x = mesh.mTangents[i].x;
|
||||
tangent.y = mesh.mTangents[i].y;
|
||||
tangent.z = mesh.mTangents[i].z;
|
||||
}
|
||||
result.vertexTangent.push_back(tangent);
|
||||
}
|
||||
|
||||
for (size_t i {0}; i < mesh.mNumFaces; ++i)
|
||||
{
|
||||
aiFace face = mesh.mFaces[i];
|
||||
for (size_t j{0}; j < face.mNumIndices; ++j)
|
||||
{
|
||||
result.indices.push_back(face.mIndices[j]);
|
||||
}
|
||||
}
|
||||
|
||||
result.header.vertexCount = static_cast<uint32_t>(result.vertexPosition.size());
|
||||
result.header.indexCount = static_cast<uint32_t>(result.indices.size());
|
||||
result.header.meshName = mesh.mName.C_Str();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SHMeshLoader::LoadExternal(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept
|
||||
{
|
||||
const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
|
||||
aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
|
||||
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
|
||||
| aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...)
|
||||
| aiProcess_FindInstances // search for instanced meshes and remove them by references to one master
|
||||
| aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible
|
||||
| aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing
|
||||
| aiProcess_RemoveRedundantMaterials // remove redundant materials
|
||||
| aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors
|
||||
| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
|
||||
);
|
||||
|
||||
if (!scene || !scene->HasMeshes())
|
||||
{
|
||||
SHLOG_ERROR("ERROR in GLTF::ASSIMP: {}\nFile: {}", aiImporter.GetErrorString(), path.string());
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO MATERIALS FROM MESHES
|
||||
//if (scene->HasMaterials())
|
||||
//{
|
||||
// for (int i{0}; i < scene->mNumMaterials; ++i)
|
||||
// {
|
||||
// if (scene->mMaterials[i]->mNumProperties > 0)
|
||||
// {
|
||||
// for (int j{0}; j < scene->mMaterials[i]->mProperties[j].)
|
||||
// }
|
||||
//std::cout << scene->mMaterials[i]->;
|
||||
// }
|
||||
//}
|
||||
|
||||
ProcessNode(*scene->mRootNode, *scene, meshes);
|
||||
}
|
||||
|
||||
void SHMeshLoader::LoadSHMesh(SHMeshAsset& mesh, AssetPath path) noexcept
|
||||
{
|
||||
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("Unable to open SHMesh File: {}", path.string());
|
||||
}
|
||||
|
||||
const std::string name{ path.stem().string() };
|
||||
|
||||
file.seekg(0);
|
||||
|
||||
uint32_t vertCount, indexCount;
|
||||
std::vector<SHVec3> vertPos, vertTan, vertNorm;
|
||||
std::vector<SHVec2> texCoord;
|
||||
std::vector<uint32_t> indices;
|
||||
|
||||
file.read(reinterpret_cast<char*>(&vertCount), sizeof(uint32_t));
|
||||
file.read(reinterpret_cast<char*>(&indexCount), sizeof(uint32_t));
|
||||
|
||||
auto const vertexVec3Byte{ sizeof(SHVec3) * vertCount };
|
||||
auto const vertexVec2Byte{ sizeof(SHVec2) * vertCount };
|
||||
|
||||
vertPos.resize(vertCount);
|
||||
vertTan.resize(vertCount);
|
||||
vertNorm.resize(vertCount);
|
||||
texCoord.resize(vertCount);
|
||||
indices.resize(indexCount);
|
||||
|
||||
file.read(reinterpret_cast<char *>(vertPos.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char *>(vertTan.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char *>(vertNorm.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char *>(texCoord.data()), vertexVec2Byte);
|
||||
file.read(reinterpret_cast<char *>(indices.data()), sizeof(uint32_t) * indexCount);
|
||||
|
||||
//for (auto i{ 0 }; i < vertCount; ++i)
|
||||
//{
|
||||
// file >> vertPos[i].x;
|
||||
// file >> vertPos[i].y;
|
||||
// file >> vertPos[i].z;
|
||||
//}
|
||||
//
|
||||
//for (auto i{ 0 }; i < vertCount; ++i)
|
||||
//{
|
||||
// file >> vertTan[i].x;
|
||||
// file >> vertTan[i].y;
|
||||
// file >> vertTan[i].z;
|
||||
//}
|
||||
|
||||
//for (auto i{ 0 }; i < vertCount; ++i)
|
||||
//{
|
||||
// file >> vertNorm[i].x;
|
||||
// file >> vertNorm[i].y;
|
||||
// file >> vertNorm[i].z;
|
||||
//}
|
||||
|
||||
//for (auto i{ 0 }; i < vertCount; ++i)
|
||||
//{
|
||||
// file >> texCoord[i].x;
|
||||
// file >> texCoord[i].y;
|
||||
//}
|
||||
|
||||
//for (auto i{ 0 }; i < indexCount; ++i)
|
||||
//{
|
||||
// file >> indices[i];
|
||||
//}
|
||||
|
||||
mesh.compiled = true;
|
||||
mesh.changed = false;
|
||||
|
||||
mesh.header.indexCount = indexCount;
|
||||
mesh.header.vertexCount = vertCount;
|
||||
mesh.header.meshName = name;
|
||||
|
||||
mesh.vertexPosition = std::move(vertPos);
|
||||
mesh.vertexTangent = std::move(vertTan);
|
||||
mesh.vertexNormal = std::move(vertNorm);
|
||||
mesh.texCoords = std::move(texCoord);
|
||||
mesh.indices = std::move(indices);
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
void SHMeshLoader::LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept
|
||||
{
|
||||
if (path.extension().string() == GLTF_EXTENSION)
|
||||
{
|
||||
LoadExternal(meshes, path);
|
||||
return;
|
||||
}
|
||||
|
||||
meshes.emplace_back();
|
||||
LoadSHMesh(meshes.back(), path);
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshLoader.h
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to load gltf mesh files 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
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/scene.h>
|
||||
#include "../SHAssetMacros.h"
|
||||
#include "../Asset Types/SHMeshAsset.h"
|
||||
#include <vector>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHMeshLoader
|
||||
{
|
||||
private:
|
||||
static Assimp::Importer aiImporter;
|
||||
|
||||
static void ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes) noexcept;
|
||||
|
||||
static SHMeshAsset ProcessMesh(aiMesh const& mesh, aiScene const& scene) noexcept;
|
||||
|
||||
static void LoadExternal(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
|
||||
|
||||
public:
|
||||
static void LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
|
||||
static void LoadSHMesh(SHMeshAsset& meshes, 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,147 +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();
|
||||
}
|
||||
|
||||
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,33 +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"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHTextureLoader
|
||||
{
|
||||
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;
|
||||
public:
|
||||
static void LoadImageAsset(AssetPath paths, SHTextureAsset& image);
|
||||
static void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
|
||||
};
|
||||
}
|
|
@ -12,11 +12,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "Filesystem/SHFileSystem.h"
|
||||
#include "SHAssetMacros.h"
|
||||
#include "Assets/SHAssetMacros.h"
|
||||
#include "SH_API.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHAsset
|
||||
struct SH_API SHAsset
|
||||
{
|
||||
AssetName name;
|
||||
AssetID id;
|
||||
|
|
|
@ -32,74 +32,89 @@ typedef std::filesystem::path AssetPath;
|
|||
typedef unsigned char* AssetData;
|
||||
typedef std::string AssetMetaVersion;
|
||||
typedef std::string AssetExtension;
|
||||
typedef unsigned char AssetTypeMeta;
|
||||
typedef size_t AssetTypeMeta;
|
||||
|
||||
typedef FMOD::Sound* SHSound;
|
||||
|
||||
// Asset Meta Version
|
||||
#define ASSET_META_VER "1.0"
|
||||
constexpr std::string_view ASSET_META_VER { "1.0" };
|
||||
|
||||
// Asset type enum
|
||||
enum class AssetType : AssetTypeMeta
|
||||
{
|
||||
INVALID = 0,
|
||||
AUDIO = 1,
|
||||
INVALID,
|
||||
SHADER,
|
||||
MATERIAL,
|
||||
IMAGE,
|
||||
TEXTURE,
|
||||
MESH,
|
||||
SCRIPT,
|
||||
SCENE,
|
||||
PREFAB,
|
||||
AUDIO_WAV,
|
||||
DDS
|
||||
SHADER_BUILT_IN,
|
||||
TEXTURE,
|
||||
MESH,
|
||||
MAX_COUNT
|
||||
};
|
||||
constexpr size_t TYPE_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) };
|
||||
|
||||
//Directory
|
||||
#ifdef _PUBLISH
|
||||
#define ASSET_ROOT "Assets"
|
||||
constexpr std::string_view ASSET_ROOT {"Assets"};
|
||||
#else
|
||||
#define ASSET_ROOT "../../Assets"
|
||||
constexpr std::string_view ASSET_ROOT {"../../Assets"};
|
||||
#endif
|
||||
|
||||
|
||||
// ASSET EXTENSIONS
|
||||
#define META_EXTENSION ".shmeta"
|
||||
#define IMAGE_EXTENSION ".png"
|
||||
#define AUDIO_EXTENSION ".ogg"
|
||||
#define AUDIO_WAV_EXTENSION ".wav"
|
||||
#define SHADER_EXTENSION ".glsl"
|
||||
#define SCRIPT_EXTENSION ".cs"
|
||||
#define SCENE_EXTENSION ".SHADE"
|
||||
#define PREFAB_EXTENSION ".SHPrefab"
|
||||
#define MATERIAL_EXTENSION ".SHMat"
|
||||
#define TEXTURE_EXTENSION ".shtex"
|
||||
#define DDS_EXTENSION ".dds"
|
||||
#define FBX_EXTENSION ".fbx"
|
||||
#define GLTF_EXTENSION ".gltf"
|
||||
#define MESH_EXTENSION ".shmesh"
|
||||
constexpr std::string_view META_EXTENSION {".shmeta"};
|
||||
constexpr std::string_view AUDIO_EXTENSION {".ogg"};
|
||||
constexpr std::string_view AUDIO_WAV_EXTENSION {".wav"};
|
||||
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 SCENE_EXTENSION {".shade"};
|
||||
constexpr std::string_view PREFAB_EXTENSION {".shprefab"};
|
||||
constexpr std::string_view MATERIAL_EXTENSION {".shmat"};
|
||||
constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
|
||||
constexpr std::string_view MESH_EXTENSION {".shmesh"};
|
||||
|
||||
std::string const EXTENSIONS[] = {
|
||||
constexpr std::string_view EXTENSIONS[] = {
|
||||
AUDIO_EXTENSION,
|
||||
SHADER_EXTENSION,
|
||||
SHADER_BUILT_IN_EXTENSION,
|
||||
MATERIAL_EXTENSION,
|
||||
IMAGE_EXTENSION,
|
||||
TEXTURE_EXTENSION,
|
||||
DDS_EXTENSION,
|
||||
MESH_EXTENSION,
|
||||
SCRIPT_EXTENSION,
|
||||
SCENE_EXTENSION,
|
||||
PREFAB_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,
|
||||
GLTF_EXTENSION
|
||||
};
|
||||
|
||||
// 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
|
||||
#define FILE_NOT_FOUND_ERR "FILE NOT FOUND"
|
||||
#define META_NOT_FOUND_ERR "META NOT FOUND"
|
||||
#define ASSET_NOT_FOUND_ERR "ASSET NOT FOUND"
|
||||
#define EXT_DOES_NOT_EXIST "TYPE DOES NOT HAVE EXTENSION DEFINED"
|
||||
constexpr std::string_view FILE_NOT_FOUND_ERR {"FILE NOT FOUND"};
|
||||
constexpr std::string_view META_NOT_FOUND_ERR {"META NOT FOUND"};
|
||||
constexpr std::string_view ASSET_NOT_FOUND_ERR {"ASSET NOT FOUND"};
|
||||
constexpr std::string_view EXT_DOES_NOT_EXIST {"TYPE DOES NOT HAVE EXTENSION DEFINED"};
|
||||
|
||||
#endif // !SH_ASSET_MACROS_H
|
||||
|
|
|
@ -14,22 +14,23 @@
|
|||
#include "SHAssetMetaHandler.h"
|
||||
#include "Filesystem/SHFileSystem.h"
|
||||
|
||||
#include "Libraries/SHMeshLoader.h"
|
||||
#include "Libraries/SHTextureLoader.h"
|
||||
#include "Libraries/Loaders/SHMeshLoader.h"
|
||||
#include "Libraries/Loaders/SHTextureLoader.h"
|
||||
#include "Libraries/Loaders/SHShaderSourceLoader.h"
|
||||
|
||||
#include "Libraries/SHMeshCompiler.h"
|
||||
#include "Libraries/SHTextureCompiler.h"
|
||||
#include "Libraries/Compilers/SHMeshCompiler.h"
|
||||
#include "Libraries/Compilers/SHTextureCompiler.h"
|
||||
#include "Libraries/Compilers/SHShaderSourceCompiler.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
FMOD::System* SHAssetManager::audioSystem;
|
||||
std::unordered_map<AssetID, SHSound >* SHAssetManager::audioSoundList;
|
||||
|
||||
std::vector<SHAsset> SHAssetManager::assetCollection;
|
||||
std::unordered_map<AssetID, SHAsset> SHAssetManager::assetRegistry;
|
||||
std::vector<SHAssetLoader*> SHAssetManager::loaders(TYPE_COUNT);
|
||||
|
||||
std::unordered_map<AssetID, SHMeshAsset> SHAssetManager::meshCollection;
|
||||
std::unordered_map<AssetID, SHTextureAsset> SHAssetManager::textureCollection;
|
||||
std::vector<SHAsset> SHAssetManager::assetCollection;
|
||||
std::unordered_map<AssetID, SHAssetData * const> SHAssetManager::assetData;
|
||||
|
||||
/****************************************************************************
|
||||
* \brief Static function to generate asset ID.
|
||||
|
@ -44,7 +45,13 @@ namespace SHADE
|
|||
|
||||
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);
|
||||
}
|
||||
|
@ -56,9 +63,24 @@ namespace SHADE
|
|||
****************************************************************************/
|
||||
void SHAssetManager::Unload() noexcept
|
||||
{
|
||||
for (auto const& asset : assetCollection)
|
||||
|
||||
}
|
||||
|
||||
void SHAssetManager::Unload(AssetID assetId) noexcept
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void SHAssetManager::Exit() noexcept
|
||||
{
|
||||
for (auto const& loader : loaders)
|
||||
{
|
||||
SHAssetMetaHandler::WriteMetaData(asset);
|
||||
delete loader;
|
||||
}
|
||||
|
||||
for (auto const& data : assetData)
|
||||
{
|
||||
delete data.second;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,7 +102,30 @@ namespace SHADE
|
|||
// return std::filesystem::path();
|
||||
//}
|
||||
|
||||
return std::filesystem::path(ASSET_ROOT + folder + path.filename().string());
|
||||
return std::filesystem::path(std::string(ASSET_ROOT) + folder + path.filename().string());
|
||||
}
|
||||
|
||||
AssetPath SHAssetManager::GenerateNewPath(AssetName name, AssetType type)
|
||||
{
|
||||
std::string folder;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case AssetType::SHADER:
|
||||
case AssetType::SHADER_BUILT_IN:
|
||||
folder = "Shaders/";
|
||||
break;
|
||||
|
||||
default:
|
||||
folder = "/";
|
||||
}
|
||||
|
||||
return std::filesystem::path{
|
||||
std::string(ASSET_ROOT) +
|
||||
folder +
|
||||
name +
|
||||
std::string(EXTENSIONS[static_cast<size_t>(type)])
|
||||
};
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -116,7 +161,7 @@ namespace SHADE
|
|||
// folder = "";
|
||||
// break;
|
||||
//}
|
||||
AssetPath path{ ASSET_ROOT + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) };
|
||||
AssetPath path{ std::string{ASSET_ROOT} + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) };
|
||||
|
||||
SHAssetMetaHandler::WriteMetaData(meta);
|
||||
|
||||
|
@ -125,6 +170,19 @@ namespace SHADE
|
|||
return id;
|
||||
}
|
||||
|
||||
AssetID SHAssetManager::CreateAsset(AssetName name, AssetType type) noexcept
|
||||
{
|
||||
AssetID id = GenerateAssetID(type);
|
||||
|
||||
assetCollection.emplace_back(
|
||||
name,
|
||||
id,
|
||||
type,
|
||||
GenerateNewPath(name, type),
|
||||
0
|
||||
);
|
||||
return id;
|
||||
}
|
||||
/****************************************************************************
|
||||
* \brief Import new asset from outside editor window.
|
||||
*
|
||||
|
@ -133,7 +191,10 @@ namespace SHADE
|
|||
****************************************************************************/
|
||||
AssetID SHAssetManager::ImportNewAsset(char const* p) noexcept
|
||||
{
|
||||
std::filesystem::path const path{ p };
|
||||
std::filesystem::path const path{ p };
|
||||
|
||||
auto const type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string());
|
||||
auto const id = GenerateAssetID(type);
|
||||
|
||||
std::filesystem::path const newPath{ GenerateLocalPath(path) };
|
||||
if (newPath.empty())
|
||||
|
@ -144,11 +205,7 @@ namespace SHADE
|
|||
|
||||
std::filesystem::copy(path, newPath);
|
||||
|
||||
AssetID id{ RetrieveAsset(newPath.string().c_str()) };
|
||||
if (id != 0)
|
||||
{
|
||||
LoadData(id);
|
||||
}
|
||||
assetCollection.push_back(CreateAssetFromPath(newPath));
|
||||
|
||||
return id;
|
||||
}
|
||||
|
@ -159,158 +216,63 @@ namespace SHADE
|
|||
****************************************************************************/
|
||||
void SHAssetManager::RefreshAllAssets() noexcept
|
||||
{
|
||||
std::vector<AssetPath> metaFiles;
|
||||
std::vector<AssetPath> AssetFiles;
|
||||
|
||||
//SHFileSystem::LoadAllFiles(metaFiles, AssetFiles);
|
||||
//std::vector<AssetPath> AssetFilesVerified;
|
||||
std::vector<AssetPath> AssetFilesNew;
|
||||
}
|
||||
|
||||
for (auto const& asset : AssetFiles)
|
||||
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)
|
||||
{
|
||||
bool found = false;
|
||||
for (auto it {metaFiles.begin()}; it != metaFiles.end(); ++it)
|
||||
{
|
||||
std::string fileExtCheck{ asset.filename().string() };
|
||||
fileExtCheck += META_EXTENSION;
|
||||
if (it->filename().string() == fileExtCheck)
|
||||
{
|
||||
metaFiles.erase(it);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
result.push_back(LoadData(get));
|
||||
}
|
||||
|
||||
if (!found && IsRecognised(asset.extension().string().c_str()))
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<SHAsset> SHAssetManager::GetAllRecordOfType(AssetType type) noexcept
|
||||
{
|
||||
std::vector<SHAsset> result;
|
||||
for (auto const& asset : assetCollection)
|
||||
{
|
||||
if (asset.type == type)
|
||||
{
|
||||
AssetFilesNew.push_back(asset);
|
||||
result.push_back(asset);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<SHAsset> newLoad;
|
||||
newLoad.reserve(AssetFilesNew.size());
|
||||
|
||||
//TODO: Handle if meta does not match all assets (if meta exist and asset doesnt, vice versa)
|
||||
for (auto const& file : AssetFilesNew)
|
||||
{
|
||||
newLoad.push_back(RegisterAssetNew(file));
|
||||
}
|
||||
|
||||
//UpdateAllSpriteSets();
|
||||
|
||||
}
|
||||
|
||||
void SHAssetManager::LoadDataTemp(std::string p) noexcept
|
||||
{
|
||||
AssetPath path{ p };
|
||||
|
||||
if (path.extension().string() == FBX_EXTENSION
|
||||
|| path.extension().string() == GLTF_EXTENSION
|
||||
|| path.extension().string() == MESH_EXTENSION)
|
||||
{
|
||||
LoadGLTF(
|
||||
{
|
||||
.name {path.filename().string()},
|
||||
.id {0},
|
||||
.type {AssetType::MESH},
|
||||
.path {path},
|
||||
.location {0}
|
||||
}
|
||||
);
|
||||
}
|
||||
else if (path.extension().string() == DDS_EXTENSION
|
||||
|| path.extension().string() == TEXTURE_EXTENSION)
|
||||
{
|
||||
LoadDDS(
|
||||
{
|
||||
.name {path.filename().string()},
|
||||
.id {0},
|
||||
.type {AssetType::DDS},
|
||||
.path {path},
|
||||
.location {0}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<SHMeshAsset> SHAssetManager::GetAllMeshes() noexcept
|
||||
{
|
||||
std::vector<SHMeshAsset> result;
|
||||
for (auto const& mesh : meshCollection)
|
||||
{
|
||||
result.push_back(mesh.second);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<SHTextureAsset> SHAssetManager::GetAllTextures() noexcept
|
||||
{
|
||||
std::vector<SHTextureAsset> result;
|
||||
for (auto const& dds : textureCollection)
|
||||
{
|
||||
result.push_back(dds.second);
|
||||
}
|
||||
AssetID SHAssetManager::CompileAsset(AssetPath path) noexcept
|
||||
{
|
||||
SHAsset newAsset
|
||||
{
|
||||
.name = path.stem().string(),
|
||||
.location = 0
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
SHMeshAsset const* SHAssetManager::GetMesh(AssetID id) noexcept
|
||||
{
|
||||
if (meshCollection.find(id) == meshCollection.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
assetCollection.push_back(newAsset);
|
||||
SHAssetMetaHandler::WriteMetaData(newAsset);
|
||||
|
||||
return &meshCollection[id];
|
||||
}
|
||||
return newAsset.id;
|
||||
}
|
||||
|
||||
SHTextureAsset const* SHAssetManager::GetTexture(AssetID id) noexcept
|
||||
{
|
||||
if (textureCollection.find(id) == textureCollection.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &textureCollection[id];
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* \param Path for meta data file
|
||||
* \param Path for asset file
|
||||
|
||||
* \brief Links meta data to asset in registries. Meta data should
|
||||
* already exist
|
||||
****************************************************************************/
|
||||
void SHAssetManager::RegisterAsset(AssetPath const& metaPath, AssetPath const& path) noexcept
|
||||
{
|
||||
SHAsset const meta = SHAssetMetaHandler::RetrieveMetaData(metaPath);
|
||||
|
||||
assetCollection.push_back(meta);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* \param Path for asset file
|
||||
|
||||
* \brief Creates new meta data for new asset.
|
||||
****************************************************************************/
|
||||
SHAsset SHAssetManager::RegisterAssetNew(AssetPath const& asset) noexcept
|
||||
{
|
||||
SHAsset meta;
|
||||
meta.type = SHAssetMetaHandler::GetTypeFromExtension(asset.extension().string());
|
||||
meta.id = GenerateAssetID(meta.type);
|
||||
|
||||
assetCollection.push_back(meta);
|
||||
|
||||
SHAssetMetaHandler::WriteMetaData(meta);
|
||||
return assetCollection.back();
|
||||
}
|
||||
|
||||
bool SHAssetManager::IsRecognised(char const* ext) noexcept
|
||||
bool SHAssetManager::IsRecognised(char const* ext) noexcept
|
||||
{
|
||||
for (auto const& e : EXTENSIONS)
|
||||
{
|
||||
if (strcmp(ext, e.c_str()) == 0)
|
||||
if (strcmp(ext, e.data()) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -319,54 +281,90 @@ namespace SHADE
|
|||
return false;
|
||||
}
|
||||
|
||||
void SHAssetManager::LoadGLTF(SHAsset asset) noexcept
|
||||
SHAsset SHAssetManager::CreateAssetFromPath(AssetPath path) noexcept
|
||||
{
|
||||
std::vector<SHMeshAsset> meshes;
|
||||
SHAsset result;
|
||||
|
||||
SHMeshLoader::LoadMesh(meshes, asset.path);
|
||||
result.name = path.stem().string();
|
||||
result.type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string());
|
||||
result.id = GenerateAssetID(result.type);
|
||||
result.path = path;
|
||||
result.location = 0;
|
||||
|
||||
for (auto const& mesh : meshes)
|
||||
{
|
||||
auto id{ GenerateAssetID(AssetType::MESH) };
|
||||
meshCollection.emplace(id, mesh);
|
||||
|
||||
AssetPath path;
|
||||
if (!mesh.compiled)
|
||||
{
|
||||
path = SHMeshCompiler::CompileMeshBinary(mesh, asset.path);
|
||||
}
|
||||
|
||||
assetCollection.emplace_back(
|
||||
mesh.header.meshName,
|
||||
id,
|
||||
AssetType::MESH,
|
||||
path,
|
||||
0
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void SHAssetManager::LoadDDS(SHAsset asset) 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
|
||||
{
|
||||
SHTextureAsset image;
|
||||
|
||||
SHTextureLoader::LoadImageAsset(asset.path, image);
|
||||
|
||||
if (!image.compiled)
|
||||
{
|
||||
auto id{ GenerateAssetID(AssetType::TEXTURE) };
|
||||
textureCollection.emplace(id, image);
|
||||
|
||||
auto path{ SHTextureCompiler::CompileTextureBinary(image, asset.path) };
|
||||
|
||||
assetCollection.emplace_back(
|
||||
image.name,
|
||||
id,
|
||||
AssetType::TEXTURE,
|
||||
path,
|
||||
0
|
||||
);
|
||||
}
|
||||
loaders[static_cast<size_t>(AssetType::SHADER)] = dynamic_cast<SHAssetLoader*>(new SHShaderSourceLoader());
|
||||
loaders[static_cast<size_t>(AssetType::SHADER_BUILT_IN)] = loaders[static_cast<size_t>(AssetType::SHADER)];
|
||||
loaders[static_cast<size_t>(AssetType::TEXTURE)] = dynamic_cast<SHAssetLoader*>(new SHTextureLoader());
|
||||
loaders[static_cast<size_t>(AssetType::MESH)] = dynamic_cast<SHAssetLoader*>(new SHMeshLoader());
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -374,8 +372,10 @@ namespace SHADE
|
|||
****************************************************************************/
|
||||
void SHAssetManager::Load() noexcept
|
||||
{
|
||||
RetrieveAssets();
|
||||
LoadAllData();
|
||||
//CompileAll();
|
||||
InitLoaders();
|
||||
BuildAssetCollection();
|
||||
//LoadAllData();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -383,143 +383,40 @@ namespace SHADE
|
|||
****************************************************************************/
|
||||
void SHAssetManager::LoadAllData() noexcept
|
||||
{
|
||||
//TODO Remove when on demand loading is done
|
||||
for (auto const& asset : assetCollection)
|
||||
{
|
||||
switch (asset.type)
|
||||
{
|
||||
case AssetType::MESH:
|
||||
meshCollection.emplace(asset.id, SHMeshAsset());
|
||||
SHMeshLoader::LoadSHMesh(meshCollection[asset.id], asset.path);
|
||||
break;
|
||||
|
||||
case AssetType::TEXTURE:
|
||||
textureCollection.emplace(asset.id, SHTextureAsset());
|
||||
SHTextureLoader::LoadSHTexture(asset.path, textureCollection[asset.id]);
|
||||
break;
|
||||
|
||||
default:
|
||||
void;
|
||||
}
|
||||
SHAssetData* data = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
|
||||
assetData.emplace(asset.id, data);
|
||||
}
|
||||
}
|
||||
|
||||
void SHAssetManager::LoadData(AssetID id) noexcept
|
||||
SHAssetData* SHAssetManager::LoadData(SHAsset const& asset) noexcept
|
||||
{
|
||||
(void)id;
|
||||
}
|
||||
SHAssetData* data = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
|
||||
|
||||
/****************************************************************************
|
||||
* \brief Retrieve all asset files and meta files from filesystem
|
||||
****************************************************************************/
|
||||
void SHAssetManager::RetrieveAssets() noexcept
|
||||
{
|
||||
std::vector<AssetPath> metaFiles;
|
||||
std::vector<AssetPath> AssetFiles;
|
||||
|
||||
for (auto const dir : std::filesystem::recursive_directory_iterator(ASSET_ROOT))
|
||||
if (data == nullptr)
|
||||
{
|
||||
if (dir.path().extension().string() == META_EXTENSION)
|
||||
{
|
||||
auto meta{ SHAssetMetaHandler::RetrieveMetaData(dir.path()) };
|
||||
|
||||
assetCollection.push_back(meta);
|
||||
assetRegistry.emplace(meta.id, meta);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Write new function for file manager to loop through all files
|
||||
//SHFileSystem::StartupFillDirectories(ASSET_ROOT);
|
||||
//FolderPointer rootFolder = SHFileSystem::GetRoot();
|
||||
|
||||
//for (auto const& meta : metaFiles)
|
||||
//{
|
||||
// for (std::vector<AssetPath>::const_iterator it{ AssetFiles.cbegin() };
|
||||
// it != AssetFiles.cend();
|
||||
// ++it)
|
||||
// {
|
||||
// // Asset exists for meta file
|
||||
// std::string fileExtCheck{ it->filename().string() };
|
||||
// fileExtCheck += META_EXTENSION;
|
||||
// if (meta.filename().string() == fileExtCheck)
|
||||
// {
|
||||
// RegisterAsset(meta, *it);
|
||||
// AssetFiles.erase(it);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//TODO: Handle if meta does not match all assets (if meta exist and asset doesnt, vice versa)
|
||||
//for (auto const& file : AssetFiles)
|
||||
//{
|
||||
// if (IsRecognised(file.extension().string().c_str()))
|
||||
// {
|
||||
// SHAssetMetaHandler::WriteMetaData(RegisterAssetNew(file));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// std::cout << "Unsupported File Format: " << file.filename() << "\n";
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
AssetID SHAssetManager::RetrieveAsset(char const* path) noexcept
|
||||
{
|
||||
std::filesystem::path p{ path };
|
||||
if (IsRecognised(p.extension().string().c_str()))
|
||||
{
|
||||
SHAsset const& meta{ RegisterAssetNew(p) };
|
||||
SHAssetMetaHandler::WriteMetaData(meta);
|
||||
return meta.id;
|
||||
SHLOG_ERROR("Unable to load asset into memory: {}\n", asset.path.string());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Unsupported File Format: " << p.filename() << "\n";
|
||||
assetData.emplace(asset.id, data);
|
||||
}
|
||||
|
||||
// Assert that file imported is not recognised
|
||||
return 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* \param Full path of file
|
||||
|
||||
* \brief Extracts file name from path. Formats file name into readable
|
||||
* with spaces and capitalises first letter of every word
|
||||
****************************************************************************/
|
||||
AssetName SHAssetManager::GetNameFromPath(AssetPath filepath) noexcept
|
||||
void SHAssetManager::BuildAssetCollection() noexcept
|
||||
{
|
||||
std::string name{ filepath.filename().string() };
|
||||
name = name.substr(0, name.find_last_of('.'));
|
||||
|
||||
//if (name[0] <= 122 && name[0] >= 97)
|
||||
//{
|
||||
// name[0] -= 32;
|
||||
//}
|
||||
|
||||
//for (size_t i{ 1 }; i < name.length(); ++i)
|
||||
//{
|
||||
// // Replace all underscores with spaces
|
||||
// if (name[i] == '_')
|
||||
// {
|
||||
// name[i] = ' ';
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// if (name[i + 1] <= 'Z' && name[i + 1] >= 'A'
|
||||
// && name[i] <= 'z' && name[i] >= 'a')
|
||||
// {
|
||||
// name.insert(i + 1, 1, ' ');
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// if (name[i - 1] == ' ' && name[i] <= 'z' && name[i] >= 'a')
|
||||
// {
|
||||
// name[i] -= 32;
|
||||
// }
|
||||
//}
|
||||
|
||||
return name;
|
||||
for (auto const& dir : std::filesystem::recursive_directory_iterator{ASSET_ROOT})
|
||||
{
|
||||
if (dir.is_regular_file())
|
||||
{
|
||||
if (dir.path().extension().string() == META_EXTENSION.data())
|
||||
{
|
||||
assetCollection.push_back(SHAssetMetaHandler::RetrieveMetaData(dir.path()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,10 @@
|
|||
#pragma once
|
||||
#include "tinyddsloader.h"
|
||||
#include "SHAsset.h"
|
||||
#include "Asset Types/SHAssetData.h"
|
||||
#include "Assets/Libraries/Loaders/SHAssetLoader.h"
|
||||
#include <memory>
|
||||
|
||||
#include "Asset Types/SHMeshAsset.h"
|
||||
#include "Asset Types/SHTextureAsset.h"
|
||||
#include "SH_API.h"
|
||||
|
||||
namespace SHADE
|
||||
|
@ -28,10 +29,15 @@ namespace SHADE
|
|||
|
||||
static AssetPath GenerateLocalPath(AssetPath path) noexcept;
|
||||
|
||||
static AssetPath GenerateNewPath(AssetName name, AssetType type);
|
||||
|
||||
/****************************************************************************
|
||||
* \brief Deallocate all memory used by resource data
|
||||
****************************************************************************/
|
||||
static void Unload() noexcept;
|
||||
static void Unload(AssetID assetId) noexcept;
|
||||
|
||||
static void Exit() noexcept;
|
||||
|
||||
/****************************************************************************
|
||||
* \brief Load all resources that are in the folder
|
||||
|
@ -54,6 +60,7 @@ namespace SHADE
|
|||
* \return resource id generated for new asset
|
||||
****************************************************************************/
|
||||
static AssetID CreateNewAsset(AssetType, AssetName) noexcept;
|
||||
static AssetID CreateAsset(AssetName name, AssetType type) noexcept;
|
||||
|
||||
/****************************************************************************
|
||||
* \brief Import new resource from outside editor window.
|
||||
|
@ -70,66 +77,36 @@ namespace SHADE
|
|||
static void RefreshAllAssets() noexcept;
|
||||
// -------------------------------------------------------------------------/
|
||||
|
||||
//TODO: TEMPORARY FOR TESTING GLTF & DDS
|
||||
static void LoadDataTemp(std::string path) noexcept;
|
||||
static std::vector<SHMeshAsset> GetAllMeshes() noexcept;
|
||||
static std::vector<SHTextureAsset> GetAllTextures() noexcept;
|
||||
template<typename T>
|
||||
static std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T const* const> GetData(AssetID id) noexcept;
|
||||
|
||||
static SHMeshAsset const* GetMesh(AssetID id) noexcept;
|
||||
static SHTextureAsset const* GetTexture(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:
|
||||
/****************************************************************************
|
||||
* \brief Load resource data into memory
|
||||
****************************************************************************/
|
||||
|
||||
static void InitLoaders() noexcept;
|
||||
static void LoadAllData() noexcept;
|
||||
|
||||
static void LoadData(AssetID id) noexcept;
|
||||
|
||||
/****************************************************************************
|
||||
* \brief Retrieve all resource files and meta files from filesystem
|
||||
****************************************************************************/
|
||||
static void RetrieveAssets() noexcept;
|
||||
|
||||
static AssetID RetrieveAsset(char const* path) noexcept;
|
||||
|
||||
/****************************************************************************
|
||||
* \param Full path of file
|
||||
|
||||
* \brief Extracts file name from path. Formats file name into readable
|
||||
* with spaces and capitalises first letter of every word
|
||||
****************************************************************************/
|
||||
static AssetName GetNameFromPath(AssetPath) noexcept;
|
||||
|
||||
/****************************************************************************
|
||||
* \param Path for meta data file
|
||||
* \param Path for resource file
|
||||
|
||||
* \brief Links meta data to resource in registries. Meta data should
|
||||
* already exist
|
||||
****************************************************************************/
|
||||
static void RegisterAsset(AssetPath const&, AssetPath const&) noexcept;
|
||||
|
||||
/****************************************************************************
|
||||
* \param Path for resource file
|
||||
|
||||
* \brief Creates new meta data for new resource.
|
||||
****************************************************************************/
|
||||
static SHAsset RegisterAssetNew(AssetPath const&) noexcept;
|
||||
static SHAssetData* LoadData(SHAsset const& asset) noexcept;
|
||||
inline static void BuildAssetCollection() noexcept;
|
||||
|
||||
static bool IsRecognised(char const*) noexcept;
|
||||
|
||||
static SHAsset CreateAssetFromPath(AssetPath path) noexcept;
|
||||
|
||||
// Specialised load calls
|
||||
static void LoadGLTF(SHAsset asset) noexcept;
|
||||
static void LoadDDS(SHAsset asset) noexcept;
|
||||
static void CompileAll() noexcept;
|
||||
|
||||
static FMOD::System* audioSystem;
|
||||
static std::unordered_map<AssetID,SHSound>* audioSoundList;
|
||||
|
||||
static std::vector<SHAssetLoader*> loaders;
|
||||
|
||||
// For all resources
|
||||
static std::vector<SHAsset> assetCollection;
|
||||
static std::unordered_map<AssetID, SHAsset> assetRegistry;
|
||||
|
||||
static std::unordered_map<AssetID, SHMeshAsset> meshCollection;
|
||||
static std::unordered_map<AssetID, SHTextureAsset> textureCollection;
|
||||
static std::unordered_map<AssetID, SHAssetData * const> assetData;
|
||||
};
|
||||
}
|
||||
|
||||
#include "SHAssetManager.hpp"
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
#include "SHAssetManager.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T const* const> SHAssetManager::GetData(AssetID id) noexcept
|
||||
{
|
||||
if (!assetData.contains(id))
|
||||
{
|
||||
for (auto const& asset : assetCollection)
|
||||
{
|
||||
if (asset.id == id)
|
||||
{
|
||||
assetData.emplace(id, LoadData(asset));
|
||||
return dynamic_cast<T const* const>(assetData[id]);
|
||||
}
|
||||
}
|
||||
|
||||
SHLOG_ERROR("Asset ID provided does not exist: {}", id);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return dynamic_cast<T const* const>(assetData[id]);
|
||||
}
|
||||
}
|
|
@ -37,7 +37,7 @@ namespace SHADE
|
|||
{
|
||||
for (int i{0}; i < EXTENSIONS->size(); ++i)
|
||||
{
|
||||
if (ext == EXTENSIONS[i])
|
||||
if (strcmp(ext.c_str(), EXTENSIONS[i].data()) == 0)
|
||||
{
|
||||
return static_cast<AssetType>(i);
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ namespace SHADE
|
|||
****************************************************************************/
|
||||
AssetExtension SHAssetMetaHandler::GetExtensionFromType(AssetType type) noexcept
|
||||
{
|
||||
return EXTENSIONS[static_cast<size_t>(type)];
|
||||
return AssetExtension(EXTENSIONS[static_cast<size_t>(type)]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -124,16 +124,6 @@ namespace SHADE
|
|||
metaFile << "ID: " << meta.id << "\n";
|
||||
metaFile << "Type: " << static_cast<AssetTypeMeta>(meta.type) << std::endl;
|
||||
|
||||
////TODO Add in information that is specific to types like mesh
|
||||
//switch(meta.type)
|
||||
//{
|
||||
//case AssetType::MESH:
|
||||
// break;
|
||||
|
||||
//default:
|
||||
// break;
|
||||
//}
|
||||
|
||||
metaFile.close();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHCameraComponent.h"
|
||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||
|
||||
#include "SHCameraSystem.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#include "Math/SHMath.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -22,33 +25,69 @@ namespace SHADE
|
|||
void SHCameraComponent::SetYaw(float yaw) noexcept
|
||||
{
|
||||
this->yaw = yaw;
|
||||
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
|
||||
{
|
||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
||||
SHVec3 rotation = transform->GetWorldRotation();
|
||||
transform->SetWorldRotation(SHVec3{rotation.x,SHMath::DegreesToRadians(yaw), rotation.z});
|
||||
}
|
||||
dirtyView = true;
|
||||
}
|
||||
|
||||
void SHCameraComponent::SetPitch(float pitch) noexcept
|
||||
{
|
||||
this->pitch = pitch;
|
||||
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
|
||||
{
|
||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
||||
SHVec3 rotation = transform->GetWorldRotation();
|
||||
transform->SetWorldRotation(SHVec3{ SHMath::DegreesToRadians(pitch),rotation.y, rotation.z });
|
||||
}
|
||||
dirtyView = true;
|
||||
}
|
||||
|
||||
void SHCameraComponent::SetRoll(float roll) noexcept
|
||||
{
|
||||
this->roll = roll;
|
||||
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
|
||||
{
|
||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
||||
SHVec3 rotation = transform->GetWorldRotation();
|
||||
transform->SetWorldRotation(SHVec3{ rotation.x,rotation.y, SHMath::DegreesToRadians(roll)});
|
||||
}
|
||||
dirtyView = true;
|
||||
}
|
||||
void SHCameraComponent::SetPositionX(float x) noexcept
|
||||
{
|
||||
position.x = x;
|
||||
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
|
||||
{
|
||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
||||
SHVec3 position = transform->GetWorldPosition();
|
||||
transform->SetWorldRotation(SHVec3{ x,position.y, position.z});
|
||||
}
|
||||
dirtyView = true;
|
||||
}
|
||||
void SHCameraComponent::SetPositionY(float y) noexcept
|
||||
{
|
||||
position.y = y;
|
||||
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
|
||||
{
|
||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
||||
SHVec3 position = transform->GetWorldPosition();
|
||||
transform->SetWorldRotation(SHVec3{ position.x,y, position.z });
|
||||
}
|
||||
dirtyView = true;
|
||||
}
|
||||
void SHCameraComponent::SetPositionZ(float z) noexcept
|
||||
{
|
||||
position.z = z;
|
||||
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
|
||||
{
|
||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
||||
SHVec3 position = transform->GetWorldPosition();
|
||||
transform->SetWorldRotation(SHVec3{ position.x,position.y, z });
|
||||
}
|
||||
dirtyView = true;
|
||||
}
|
||||
void SHCameraComponent::SetPosition(float x,float y, float z) noexcept
|
||||
|
@ -56,11 +95,23 @@ namespace SHADE
|
|||
position.x = x;
|
||||
position.y = y;
|
||||
position.z = z;
|
||||
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
|
||||
{
|
||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
||||
SHVec3 position = transform->GetWorldPosition();
|
||||
transform->SetWorldRotation(SHVec3{ x,y, z });
|
||||
}
|
||||
dirtyView = true;
|
||||
}
|
||||
void SHCameraComponent::SetPosition(SHVec3& pos) noexcept
|
||||
void SHCameraComponent::SetPosition(SHVec3 pos) noexcept
|
||||
{
|
||||
this->position = pos;
|
||||
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
|
||||
{
|
||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
||||
SHVec3 position = transform->GetWorldPosition();
|
||||
transform->SetWorldRotation(pos);
|
||||
}
|
||||
dirtyView = true;
|
||||
}
|
||||
|
||||
|
@ -95,6 +146,17 @@ namespace SHADE
|
|||
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
|
||||
{
|
||||
return yaw;
|
||||
|
@ -108,6 +170,27 @@ namespace SHADE
|
|||
{
|
||||
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
|
||||
{
|
||||
return width/height;
|
||||
|
@ -118,6 +201,11 @@ namespace SHADE
|
|||
return fov;
|
||||
}
|
||||
|
||||
bool SHCameraComponent::GetIsPerspective() const noexcept
|
||||
{
|
||||
return perspProj;
|
||||
}
|
||||
|
||||
const SHMatrix& SHCameraComponent::GetViewMatrix() const noexcept
|
||||
{
|
||||
return viewMatrix;
|
||||
|
@ -128,4 +216,32 @@ namespace SHADE
|
|||
return projMatrix;
|
||||
}
|
||||
|
||||
//void SHCameraComponent::SetMainCamera(size_t directorCameraIndex) noexcept
|
||||
//{
|
||||
// auto system = SHSystemManager::GetSystem<SHCameraSystem>();
|
||||
// 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
|
||||
|
||||
#include <rttr/registration>
|
||||
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
#include "Math/Vector/SHVec3.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
|
@ -50,35 +52,44 @@ namespace SHADE
|
|||
void SetPositionY(float y) noexcept;
|
||||
void SetPositionZ(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 SetHeight(float height) noexcept;
|
||||
void SetNear(float znear) noexcept;
|
||||
void SetFar(float zfar) noexcept;
|
||||
void SetFOV(float fov) noexcept;
|
||||
void SetIsPerspective(bool persp) noexcept;
|
||||
|
||||
|
||||
|
||||
SHVec3 GetPosition() const noexcept;
|
||||
float GetYaw() const noexcept;
|
||||
float GetPitch() 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 GetFOV() const noexcept;
|
||||
bool GetIsPerspective() const noexcept;
|
||||
|
||||
const SHMatrix& GetViewMatrix() const noexcept;
|
||||
const SHMatrix& GetProjMatrix() const noexcept;
|
||||
|
||||
//void SetMainCamera(size_t cameraDirectorIndex = 0) noexcept;
|
||||
|
||||
|
||||
float movementSpeed;
|
||||
SHVec3 turnSpeed;
|
||||
|
||||
RTTR_ENABLE()
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHCameraDirector.h"
|
||||
#include "SHCameraComponent.h"
|
||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||
#include "ECS_Base/SHECSMacros.h"
|
||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||
#include "Tools/SHLog.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
SHCameraDirector::SHCameraDirector()
|
||||
:mainCameraEID(MAX_EID), transitionCameraEID(MAX_EID)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
SHMatrix SHCameraDirector::GetViewMatrix() const noexcept
|
||||
{
|
||||
return viewMatrix;
|
||||
}
|
||||
SHMatrix SHCameraDirector::GetProjMatrix() const noexcept
|
||||
{
|
||||
return projMatrix;
|
||||
}
|
||||
SHMatrix SHCameraDirector::GetVPMatrix() const noexcept
|
||||
{
|
||||
return projMatrix * viewMatrix;
|
||||
}
|
||||
|
||||
void SHCameraDirector::UpdateMatrix() noexcept
|
||||
{
|
||||
if (mainCameraEID == MAX_EID)
|
||||
{
|
||||
auto& dense = SHComponentManager::GetDense<SHCameraComponent>();
|
||||
if (dense.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
mainCameraEID = dense[0].GetEID();
|
||||
}
|
||||
SHCameraComponent* camComponent = SHComponentManager::GetComponent_s<SHCameraComponent>(mainCameraEID);
|
||||
if (!camComponent)
|
||||
{
|
||||
SHLOG_WARNING("Camera Director warning: Entity does not have a camera");
|
||||
}
|
||||
else
|
||||
{
|
||||
viewMatrix = camComponent->GetViewMatrix();
|
||||
projMatrix = camComponent->GetProjMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
void SHCameraDirector::SetMainCamera(SHCameraComponent& camera) noexcept
|
||||
{
|
||||
if (SHEntityManager::IsValidEID(camera.GetEID()) == false)
|
||||
{
|
||||
SHLOG_WARNING("Camera Director Warning: Attempting to set an invalid entity as main camera.")
|
||||
return;
|
||||
}
|
||||
mainCameraEID = camera.GetEID();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
|
||||
#include "SH_API.h"
|
||||
#include "ECS_Base/Entity/SHEntity.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
#include "Resource/SHHandle.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHCameraComponent;
|
||||
|
||||
|
||||
|
||||
class SH_API SHCameraDirector
|
||||
{
|
||||
public:
|
||||
SHCameraDirector();
|
||||
~SHCameraDirector() = default;
|
||||
|
||||
|
||||
EntityID mainCameraEID;
|
||||
EntityID transitionCameraEID;
|
||||
|
||||
SHMatrix GetViewMatrix() const noexcept;
|
||||
SHMatrix GetProjMatrix() const noexcept;
|
||||
SHMatrix GetVPMatrix() const noexcept;
|
||||
void UpdateMatrix() noexcept;
|
||||
void SetMainCamera(SHCameraComponent& cam) noexcept;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
protected:
|
||||
SHMatrix viewMatrix;
|
||||
SHMatrix projMatrix;
|
||||
|
||||
};
|
||||
|
||||
typedef Handle<SHCameraDirector> DirectorHandle;
|
||||
|
||||
}
|
|
@ -3,12 +3,63 @@
|
|||
#include "Math/SHMathHelpers.h"
|
||||
#include "Input/SHInputManager.h"
|
||||
#include "Math/Vector/SHVec2.h"
|
||||
|
||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
void SHCameraSystem::UpdateEditorCamera(double dt) noexcept
|
||||
{
|
||||
|
||||
auto& camera = editorCamera;
|
||||
SHVec3 view, right, UP;
|
||||
GetCameraAxis(camera, view, right, UP);
|
||||
|
||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::A))
|
||||
{
|
||||
camera.position -= right * dt * camera.movementSpeed;
|
||||
camera.dirtyView = true;
|
||||
}
|
||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::D))
|
||||
{
|
||||
camera.position += right * dt * camera.movementSpeed;
|
||||
camera.dirtyView = true;
|
||||
}
|
||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::W))
|
||||
{
|
||||
camera.position += view * dt * camera.movementSpeed;
|
||||
camera.dirtyView = true;
|
||||
}
|
||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::S))
|
||||
{
|
||||
camera.position -= view * dt * camera.movementSpeed;
|
||||
camera.dirtyView = true;
|
||||
}
|
||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::Q))
|
||||
{
|
||||
camera.position += UP * dt * camera.movementSpeed;
|
||||
camera.dirtyView = true;
|
||||
}
|
||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::E))
|
||||
{
|
||||
camera.position -= UP * dt * camera.movementSpeed;
|
||||
camera.dirtyView = true;
|
||||
}
|
||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::RMB))
|
||||
{
|
||||
double mouseX, mouseY;
|
||||
SHInputManager::GetMouseVelocity(&mouseX, &mouseY);
|
||||
|
||||
//std::cout << camera.yaw << std::endl;
|
||||
|
||||
camera.pitch -= mouseY * dt * camera.turnSpeed.x;
|
||||
camera.yaw -= mouseX * dt * camera.turnSpeed.y;
|
||||
camera.dirtyView = true;
|
||||
}
|
||||
|
||||
UpdateCameraComponent(editorCamera);
|
||||
}
|
||||
void SHCameraSystem::EditorCameraUpdate::Execute(double dt) noexcept
|
||||
{
|
||||
SHCameraSystem* system = static_cast<SHCameraSystem*>(GetSystem());
|
||||
|
@ -18,6 +69,7 @@ namespace SHADE
|
|||
|
||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::A))
|
||||
{
|
||||
//std::cout << "Camera movement: "<<right.x<<", " << right.y << std::endl;
|
||||
camera.position -= right * dt * camera.movementSpeed;
|
||||
camera.dirtyView = true;
|
||||
}
|
||||
|
@ -58,6 +110,7 @@ namespace SHADE
|
|||
camera.dirtyView = true;
|
||||
}
|
||||
|
||||
//std::cout << "Camera position: " << camera.position.x << " " << camera.position.y << std::endl;
|
||||
system->UpdateCameraComponent(system->editorCamera);
|
||||
}
|
||||
|
||||
|
@ -83,10 +136,26 @@ namespace SHADE
|
|||
|
||||
void SHCameraSystem::UpdateCameraComponent(SHCameraComponent& camera) noexcept
|
||||
{
|
||||
if (SHComponentManager::HasComponent<SHTransformComponent>(camera.GetEID()) == true && &camera != &editorCamera)
|
||||
{
|
||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(camera.GetEID());
|
||||
SHVec3 rotation = transform->GetWorldRotation();
|
||||
camera.pitch = SHMath::RadiansToDegrees(rotation.x);
|
||||
camera.yaw = SHMath::RadiansToDegrees(rotation.y);
|
||||
camera.roll = SHMath::RadiansToDegrees(rotation.z);
|
||||
camera.position = transform->GetWorldPosition();
|
||||
camera.dirtyView = true;
|
||||
}
|
||||
|
||||
|
||||
if (camera.dirtyView)
|
||||
{
|
||||
|
||||
SHVec3 view, right, UP;
|
||||
|
||||
|
||||
ClampCameraRotation(camera);
|
||||
|
||||
GetCameraAxis(camera, view, right, UP);
|
||||
|
||||
camera.viewMatrix = SHMatrix::Identity;
|
||||
|
@ -152,9 +221,8 @@ namespace SHADE
|
|||
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::RotateX(target, SHMath::DegreesToRadians(camera.pitch));
|
||||
std::cout << "Target vec: " << target.x<<", "<<target.y<<", "<<target.z << std::endl;
|
||||
target += camera.position;
|
||||
////SHVec3::RotateZ(target, SHMath::DegreesToRadians(camera.roll));
|
||||
|
||||
|
@ -169,5 +237,55 @@ namespace SHADE
|
|||
upVec = SHVec3::Cross(forward, right);
|
||||
}
|
||||
|
||||
void SHCameraSystem::CameraSystemUpdate::Execute(double dt) noexcept
|
||||
{
|
||||
SHCameraSystem* system = static_cast<SHCameraSystem*>(GetSystem());
|
||||
auto& dense = SHComponentManager::GetDense<SHCameraComponent>();
|
||||
for (auto& cam : dense)
|
||||
{
|
||||
system->UpdateCameraComponent(cam);
|
||||
}
|
||||
for (auto& handle : system->directorHandleList)
|
||||
{
|
||||
handle->UpdateMatrix();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
DirectorHandle SHCameraSystem::CreateDirector() noexcept
|
||||
{
|
||||
auto handle = directorLibrary.Create();
|
||||
directorHandleList.emplace_back(handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
DirectorHandle SHCameraSystem::GetDirector(size_t index) noexcept
|
||||
{
|
||||
if (index < directorHandleList.size())
|
||||
{
|
||||
return directorHandleList[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
return CreateDirector();
|
||||
}
|
||||
}
|
||||
void SHCameraSystem::ClampCameraRotation(SHCameraComponent& camera) noexcept
|
||||
{
|
||||
|
||||
|
||||
|
||||
if (camera.pitch > 85)
|
||||
camera.SetPitch(85);
|
||||
if (camera.pitch < -85)
|
||||
camera.SetPitch(-85);
|
||||
if (camera.roll > 85)
|
||||
camera.SetRoll(85);
|
||||
if (camera.roll < -85)
|
||||
camera.SetRoll(-85);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
#include "ECS_Base/System/SHSystem.h"
|
||||
#include "SHCameraComponent.h"
|
||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||
#include "Resource/SHResourceLibrary.h"
|
||||
#include "SHCameraDirector.h"
|
||||
#include "SH_API.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SH_API SHCameraSystem final : public SHSystem
|
||||
|
@ -14,8 +15,9 @@ namespace SHADE
|
|||
//A camera component that represents editor camera.
|
||||
//This is not tied to any entity. Hence this EID should not be used.
|
||||
SHCameraComponent editorCamera;
|
||||
|
||||
|
||||
SHResourceLibrary<SHCameraDirector> directorLibrary;
|
||||
std::vector<DirectorHandle> directorHandleList;
|
||||
|
||||
public:
|
||||
SHCameraSystem(void) = default;
|
||||
|
@ -34,13 +36,26 @@ namespace SHADE
|
|||
};
|
||||
friend class EditorCameraUpdate;
|
||||
|
||||
SHCameraComponent* GetEditorCamera (void) noexcept;
|
||||
class SH_API CameraSystemUpdate final: public SHSystemRoutine
|
||||
{
|
||||
public:
|
||||
CameraSystemUpdate() : SHSystemRoutine("Camera System Update", false) {};
|
||||
virtual void Execute(double dt)noexcept override final;
|
||||
};
|
||||
friend class CameraSystemUpdate;
|
||||
|
||||
|
||||
SHCameraComponent* GetEditorCamera (void) noexcept;
|
||||
void GetCameraAxis(SHCameraComponent const& camera, SHVec3& forward, SHVec3& right, SHVec3& up) const noexcept;
|
||||
DirectorHandle CreateDirector() noexcept;
|
||||
DirectorHandle GetDirector(size_t index) noexcept;
|
||||
void ClampCameraRotation(SHCameraComponent& camera) noexcept;
|
||||
void UpdateEditorCamera(double dt) noexcept;
|
||||
protected:
|
||||
|
||||
void UpdateCameraComponent(SHCameraComponent& camera) noexcept;
|
||||
|
||||
void GetCameraAxis(SHCameraComponent const& camera, SHVec3& forward, SHVec3& right, SHVec3& up) const noexcept;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace SHADE
|
|||
class SHCommand : SHBaseCommand
|
||||
{
|
||||
public:
|
||||
using SHCommandPtr = std::unique_ptr<T>;
|
||||
typedef std::function<void(T const&)> SetterFunction;
|
||||
|
||||
SHCommand(T const& oldVal, T const& value, SetterFunction setFnc)
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace SHADE
|
|||
SHCommandManager::CommandStack SHCommandManager::undoStack{};
|
||||
SHCommandManager::CommandStack SHCommandManager::redoStack{};
|
||||
|
||||
void SHCommandManager::PerformCommand(CommandPtr commandPtr, bool const& overrideValue)
|
||||
void SHCommandManager::PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue)
|
||||
{
|
||||
redoStack = CommandStack();
|
||||
commandPtr->Execute();
|
||||
|
@ -27,9 +27,9 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHCommandManager::RegisterCommand(CommandPtr commandPtr)
|
||||
void SHCommandManager::RegisterCommand(BaseCommandPtr commandPtr)
|
||||
{
|
||||
undoStack.push(commandPtr);
|
||||
undoStack.push(commandPtr);
|
||||
}
|
||||
|
||||
void SHCommandManager::UndoCommand()
|
||||
|
@ -59,4 +59,14 @@ namespace SHADE
|
|||
{
|
||||
return redoStack.size();
|
||||
}
|
||||
|
||||
void SHCommandManager::PopLatestCommandFromRedoStack()
|
||||
{
|
||||
redoStack.pop();
|
||||
}
|
||||
|
||||
void SHCommandManager::PopLatestCommandFromUndoStack()
|
||||
{
|
||||
undoStack.pop();
|
||||
}
|
||||
}//namespace SHADE
|
||||
|
|
|
@ -19,16 +19,21 @@ namespace SHADE
|
|||
//#==============================================================#
|
||||
//|| Type Aliases ||
|
||||
//#==============================================================#
|
||||
using CommandPtr = std::shared_ptr<SHBaseCommand>;
|
||||
using CommandStack = std::stack<CommandPtr>;
|
||||
using BaseCommandPtr = std::shared_ptr<SHBaseCommand>;
|
||||
template<typename T>
|
||||
using SHCommandPtr = std::shared_ptr<SHCommand<T>>;
|
||||
using CommandStack = std::stack<BaseCommandPtr>;
|
||||
|
||||
static void PerformCommand(CommandPtr commandPtr, bool const& overrideValue = false);
|
||||
static void RegisterCommand(CommandPtr commandPtr);
|
||||
static void PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue = false);
|
||||
static void RegisterCommand(BaseCommandPtr commandPtr);
|
||||
static void UndoCommand();
|
||||
static void RedoCommand();
|
||||
static std::size_t GetUndoStackSize();
|
||||
static std::size_t GetRedoStackSize();
|
||||
|
||||
static void PopLatestCommandFromRedoStack();
|
||||
static void PopLatestCommandFromUndoStack();
|
||||
|
||||
private:
|
||||
static CommandStack undoStack;
|
||||
static CommandStack redoStack;
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
}
|
|
@ -22,6 +22,7 @@
|
|||
#include <imgui.h>
|
||||
|
||||
#include "Serialization/SHSerialization.h"
|
||||
#include "Tools/SHClipboardUtilities.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
|
@ -52,6 +53,7 @@ namespace SHADE
|
|||
if(const auto root = sceneGraph.GetRoot())
|
||||
{
|
||||
auto const& children = root->GetChildren();
|
||||
|
||||
for (const auto child : children)
|
||||
{
|
||||
RecursivelyDrawEntityNode(child);
|
||||
|
@ -79,6 +81,8 @@ namespace SHADE
|
|||
|
||||
void SHHierarchyPanel::SetScrollTo(EntityID eid)
|
||||
{
|
||||
if(eid == MAX_EID)
|
||||
return;
|
||||
scrollTo = eid;
|
||||
}
|
||||
|
||||
|
@ -89,8 +93,7 @@ namespace SHADE
|
|||
{
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
|
||||
ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x - 35.0f);
|
||||
ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x * 0.75f);
|
||||
if(ImGui::SmallButton(ICON_MD_DESELECT))
|
||||
{
|
||||
auto editor = SHSystemManager::GetSystem<SHEditor>();
|
||||
|
@ -104,7 +107,7 @@ namespace SHADE
|
|||
}
|
||||
if (ImGui::SmallButton(ICON_MD_ADD_CIRCLE))
|
||||
{
|
||||
SHEntityManager::CreateEntity();
|
||||
SHCommandManager::PerformCommand(std::make_shared<SHCreateEntityCommand>());
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
|
@ -144,23 +147,32 @@ namespace SHADE
|
|||
|
||||
auto* entity = SHEntityManager::GetEntityByID(currentNode->GetEntityID());
|
||||
//Draw Node
|
||||
bool isNodeOpen = ImGui::TreeNodeEx(reinterpret_cast<void*>(entity), nodeFlags, "%u: %s", EntityHandleGenerator::GetIndex(eid), entity->name.c_str());
|
||||
bool isNodeOpen = ImGui::TreeNodeEx(reinterpret_cast<void*>(entity), nodeFlags, "%u: %s", SHEntityManager::GetEntityIndex(eid), entity->name.c_str());
|
||||
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||
|
||||
//Check For Begin Drag
|
||||
if (SHDragDrop::BeginSource())
|
||||
{
|
||||
ImGui::Text("Moving EID: %zu", eid);
|
||||
SHDragDrop::SetPayload<EntityID>(DRAG_EID, &eid);
|
||||
std::string moveLabel = "Moving EID: ";
|
||||
if(!isSelected)
|
||||
editor->selectedEntities.push_back(eid);
|
||||
for(int i = 0; i < static_cast<int>(editor->selectedEntities.size()); ++i)
|
||||
{
|
||||
moveLabel.append(std::to_string(editor->selectedEntities[i]));
|
||||
if(i + 1 < static_cast<int>(editor->selectedEntities.size()))
|
||||
{
|
||||
moveLabel.append(", ");
|
||||
}
|
||||
}
|
||||
ImGui::Text(moveLabel.c_str());
|
||||
SHDragDrop::SetPayload<std::vector<EntityID>>(DRAG_EID, &editor->selectedEntities);
|
||||
SHDragDrop::EndSource();
|
||||
}
|
||||
else if (SHDragDrop::BeginTarget()) //If Received DragDrop
|
||||
{
|
||||
if (const EntityID* eidPayload = SHDragDrop::AcceptPayload<EntityID>(DRAG_EID)) //If payload is valid
|
||||
if (const std::vector<EntityID>* eidPayload = SHDragDrop::AcceptPayload<std::vector<EntityID>>(DRAG_EID)) //If payload is valid
|
||||
{
|
||||
EntityID const dropEID = *eidPayload;
|
||||
if(!sceneGraph.GetChild(dropEID, eid))
|
||||
sceneGraph.SetParent(dropEID, eid); //Set dropEID parent to eid (belonging to current Node)
|
||||
ParentSelectedEntities(eid);
|
||||
SHDragDrop::EndTarget();
|
||||
}
|
||||
}
|
||||
|
@ -175,7 +187,15 @@ namespace SHADE
|
|||
}
|
||||
if(ImGui::Selectable("Copy"))
|
||||
{
|
||||
SHLOG_INFO(SHSerialization::SerializeEntitiesToString(editor->selectedEntities))
|
||||
SHClipboardUtilities::WriteToClipboard(SHSerialization::SerializeEntitiesToString(editor->selectedEntities));
|
||||
}
|
||||
if(ImGui::Selectable("Paste"))
|
||||
{
|
||||
SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard()));
|
||||
}
|
||||
if(ImGui::Selectable("Paste as Child"))
|
||||
{
|
||||
SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard(), eid));
|
||||
}
|
||||
if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data()))
|
||||
{
|
||||
|
@ -184,7 +204,7 @@ namespace SHADE
|
|||
|
||||
if((currentNode->GetParent() != sceneGraph.GetRoot()) && ImGui::Selectable(std::format("{} Unparent Selected", ICON_MD_NORTH_WEST).data()))
|
||||
{
|
||||
sceneGraph.SetParent(currentNode->GetEntityID(), nullptr);
|
||||
ParentSelectedEntities(MAX_EID);
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
@ -196,7 +216,15 @@ namespace SHADE
|
|||
{
|
||||
if (!isSelected)
|
||||
{
|
||||
if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
|
||||
if(ImGui::IsKeyDown(ImGuiKey_LeftShift))
|
||||
{
|
||||
if(editor->selectedEntities.size() >= 1)
|
||||
{
|
||||
SelectRangeOfEntities(editor->selectedEntities[0], eid);
|
||||
}
|
||||
else editor->selectedEntities.clear();
|
||||
}
|
||||
else if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
|
||||
editor->selectedEntities.clear();
|
||||
editor->selectedEntities.push_back(eid);
|
||||
}//if not selected
|
||||
|
@ -243,4 +271,90 @@ namespace SHADE
|
|||
{
|
||||
SHEntityManager::CreateEntity(MAX_EID, "DefaultChild", parentEID);
|
||||
}
|
||||
|
||||
void SHHierarchyPanel::ParentSelectedEntities(EntityID parentEID) const noexcept
|
||||
{
|
||||
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||
auto const editor = SHSystemManager::GetSystem<SHEditor>();
|
||||
SHEntityParentCommand::EntityParentData entityParentData;
|
||||
std::vector<EntityID> parentedEIDS;
|
||||
for(auto const& eid : editor->selectedEntities)
|
||||
{
|
||||
if(sceneGraph.GetChild(eid, parentEID) == nullptr)
|
||||
{
|
||||
parentedEIDS.push_back(eid);
|
||||
if(auto parent = sceneGraph.GetParent(eid))
|
||||
entityParentData[eid].oldParentEID = parent->GetEntityID();
|
||||
entityParentData[eid].newParentEID = parentEID;
|
||||
}
|
||||
}
|
||||
SHCommandManager::PerformCommand(std::make_shared<SHEntityParentCommand>(parentedEIDS, entityParentData));
|
||||
}
|
||||
|
||||
void SHHierarchyPanel::SelectRangeOfEntities(EntityID beginEID, EntityID endEID)
|
||||
{
|
||||
bool startSelecting = false; bool endSelecting = false;
|
||||
auto const editor = SHSystemManager::GetSystem<SHEditor>();
|
||||
editor->selectedEntities.clear();
|
||||
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||
sceneGraph.Traverse([&](SHSceneNode* nodePtr)
|
||||
{
|
||||
auto eid = nodePtr->GetEntityID();
|
||||
if(!startSelecting)
|
||||
{
|
||||
if(eid == beginEID || eid == endEID)
|
||||
{
|
||||
startSelecting = true;
|
||||
editor->selectedEntities.push_back(eid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!endSelecting)
|
||||
{
|
||||
editor->selectedEntities.push_back(eid);
|
||||
if(eid == endEID || eid == beginEID)
|
||||
{
|
||||
endSelecting = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void SHCreateEntityCommand::Execute()
|
||||
{
|
||||
EntityID newEID = SHEntityManager::CreateEntity(eid);
|
||||
if(eid == MAX_EID)
|
||||
eid = newEID;
|
||||
}
|
||||
|
||||
void SHCreateEntityCommand::Undo()
|
||||
{
|
||||
SHEntityManager::DestroyEntity(eid);
|
||||
}
|
||||
|
||||
void SHEntityParentCommand::Execute()
|
||||
{
|
||||
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||
for(auto const& eid : entities)
|
||||
{
|
||||
if(entityParentData[eid].newParentEID == MAX_EID)
|
||||
sceneGraph.SetParent(eid, nullptr);
|
||||
else
|
||||
sceneGraph.SetParent(eid, entityParentData[eid].newParentEID);
|
||||
}
|
||||
}
|
||||
|
||||
void SHEntityParentCommand::Undo()
|
||||
{
|
||||
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||
for(auto const& eid : entities)
|
||||
{
|
||||
if(entityParentData[eid].oldParentEID == MAX_EID)
|
||||
sceneGraph.SetParent(eid, nullptr);
|
||||
else
|
||||
sceneGraph.SetParent(eid, entityParentData[eid].oldParentEID);
|
||||
}
|
||||
}
|
||||
}//namespace SHADE
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "imgui_internal.h"
|
||||
#include "ECS_Base/SHECSMacros.h"
|
||||
#include "Editor/EditorWindow/SHEditorWindow.h"
|
||||
|
||||
#include "Editor/Command/SHCommand.hpp"
|
||||
namespace SHADE
|
||||
{
|
||||
class SHSceneNode;
|
||||
|
@ -28,8 +28,40 @@ namespace SHADE
|
|||
void DrawMenuBar() const noexcept;
|
||||
ImRect RecursivelyDrawEntityNode(SHSceneNode*);
|
||||
void CreateChildEntity(EntityID parentEID) const noexcept;
|
||||
void ParentSelectedEntities(EntityID parentEID) const noexcept;
|
||||
void SelectRangeOfEntities(EntityID beginEID, EntityID EndEID);
|
||||
std::string filter;
|
||||
bool isAnyNodeSelected = false;
|
||||
EntityID scrollTo = MAX_EID;
|
||||
};//class SHHierarchyPanel
|
||||
|
||||
//Might move to a different file
|
||||
class SHCreateEntityCommand final : public SHBaseCommand
|
||||
{
|
||||
public:
|
||||
void Execute() override;
|
||||
void Undo() override;
|
||||
private:
|
||||
EntityID eid = MAX_EID;
|
||||
};
|
||||
|
||||
class SHEntityParentCommand final : public SHBaseCommand
|
||||
{
|
||||
public:
|
||||
struct Data
|
||||
{
|
||||
EntityID oldParentEID = MAX_EID;
|
||||
EntityID newParentEID = MAX_EID;
|
||||
};
|
||||
using EntityParentData = std::unordered_map<EntityID, Data>;
|
||||
|
||||
SHEntityParentCommand(std::vector<EntityID> entityIDs, EntityParentData inEntityParentData):entities(entityIDs),entityParentData(inEntityParentData){}
|
||||
|
||||
void Execute() override;
|
||||
void Undo() override;
|
||||
private:
|
||||
std::vector<EntityID> entities;
|
||||
std::unordered_map<EntityID, Data> entityParentData;
|
||||
};
|
||||
|
||||
}//namespace SHADE
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
//|| SHADE Includes ||
|
||||
//#==============================================================#
|
||||
#include "Editor/IconsMaterialDesign.h"
|
||||
#include "Editor/IconsFontAwesome6.h"
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
#include "Editor/SHEditorWidgets.hpp"
|
||||
#include "Physics/Components/SHColliderComponent.h"
|
||||
|
@ -38,6 +39,10 @@ namespace SHADE
|
|||
{
|
||||
SHComponentManager::RemoveComponent<T>(component->GetEID());
|
||||
}
|
||||
if (ImGui::Selectable(std::format("{} Reset {}", ICON_MD_RESTART_ALT, componentName.data()).data()))
|
||||
{
|
||||
*component = T();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +52,7 @@ namespace SHADE
|
|||
if (!component)
|
||||
return;
|
||||
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();
|
||||
if (ImGui::CollapsingHeader(componentType.get_name().data()))
|
||||
{
|
||||
|
@ -88,7 +93,7 @@ namespace SHADE
|
|||
auto metaMax = property.get_metadata(META::max);
|
||||
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
|
||||
{
|
||||
|
@ -114,7 +119,7 @@ namespace SHADE
|
|||
auto metaMax = property.get_metadata(META::max);
|
||||
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
|
||||
{
|
||||
|
@ -127,7 +132,7 @@ namespace SHADE
|
|||
auto metaMax = property.get_metadata(META::max);
|
||||
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
|
||||
{
|
||||
|
@ -140,7 +145,7 @@ namespace SHADE
|
|||
auto metaMax = property.get_metadata(META::max);
|
||||
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
|
||||
{
|
||||
|
@ -151,13 +156,18 @@ namespace SHADE
|
|||
{
|
||||
auto metaMin = property.get_metadata(META::min);
|
||||
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())
|
||||
{
|
||||
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
|
||||
{
|
||||
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>())
|
||||
|
@ -166,7 +176,7 @@ namespace SHADE
|
|||
auto metaMax = property.get_metadata(META::max);
|
||||
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
|
||||
{
|
||||
|
@ -216,7 +226,7 @@ namespace SHADE
|
|||
|
||||
if (collider.GetType() == SHCollider::Type::BOX)
|
||||
{
|
||||
SHEditorWidgets::BeginPanel( std::format("{} Box Collider #{}", ICON_MD_VIEW_IN_AR, 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());
|
||||
SHEditorWidgets::DragVec3("Half Extents", { "X", "Y", "Z" }, [box] {return box->GetHalfExtents(); }, [box](SHVec3 const& vec) {box->SetHalfExtents(vec);});
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "AudioSystem/SHAudioSystem.h"
|
||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
||||
#include "Physics/Components/SHColliderComponent.h"
|
||||
#include "Camera/SHCameraComponent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -35,6 +36,23 @@ namespace SHADE
|
|||
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()
|
||||
:SHEditorWindow("Inspector", ImGuiWindowFlags_MenuBar)
|
||||
{
|
||||
|
@ -55,7 +73,11 @@ namespace SHADE
|
|||
{
|
||||
EntityID const& eid = editor->selectedEntities[0];
|
||||
SHEntity* entity = SHEntityManager::GetEntityByID(eid);
|
||||
|
||||
if(!entity)
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid);
|
||||
SHEditorWidgets::CheckBox("##IsActive", [entity]()->bool {return entity->GetActive(); }, [entity](bool const& active) {entity->SetActive(active); });
|
||||
ImGui::SameLine();
|
||||
|
@ -78,23 +100,27 @@ namespace SHADE
|
|||
{
|
||||
DrawComponent(rigidbodyComponent);
|
||||
}
|
||||
if (auto cameraComponent = SHComponentManager::GetComponent_s<SHCameraComponent>(eid))
|
||||
{
|
||||
DrawComponent(cameraComponent);
|
||||
}
|
||||
ImGui::Separator();
|
||||
// Render Scripts
|
||||
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||
scriptEngine->RenderScriptsInInspector(eid);
|
||||
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||
scriptEngine->RenderScriptsInInspector(eid);
|
||||
ImGui::Separator();
|
||||
if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data()))
|
||||
{
|
||||
DrawAddComponentButton<SHTransformComponent>(eid);
|
||||
DrawAddComponentButton<SHRenderable>(eid);
|
||||
DrawAddComponentButton<SHColliderComponent>(eid);
|
||||
if(DrawAddComponentButton<SHRigidBodyComponent>(eid))
|
||||
{
|
||||
if(SHComponentManager::GetComponent_s<SHTransformComponent>(eid) == nullptr)
|
||||
{
|
||||
SHComponentManager::AddComponent<SHTransformComponent>(eid);
|
||||
}
|
||||
}
|
||||
DrawAddComponentButton<SHCameraComponent>(eid);
|
||||
|
||||
// Components that require Transforms
|
||||
|
||||
DrawAddComponentWithEnforcedComponentButton<SHRenderable, SHTransformComponent>(eid);
|
||||
DrawAddComponentWithEnforcedComponentButton<SHRigidBodyComponent, SHTransformComponent>(eid);
|
||||
DrawAddComponentWithEnforcedComponentButton<SHColliderComponent, SHTransformComponent>(eid);
|
||||
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <imgui.h>
|
||||
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Editor/Command/SHCommandManager.h"
|
||||
#include "FRC/SHFramerateController.h"
|
||||
|
||||
namespace SHADE
|
||||
|
@ -38,6 +39,11 @@ namespace SHADE
|
|||
{
|
||||
ImGui::PlotLines("DT", frames.data(), static_cast<int>(frames.size()), 0, nullptr, 0.0f, 16.0f);
|
||||
}
|
||||
if(ImGui::CollapsingHeader("Command Manager"))
|
||||
{
|
||||
ImGui::Text("Undo: %zu", SHCommandManager::GetUndoStackSize());
|
||||
ImGui::Text("Redo: %zu", SHCommandManager::GetRedoStackSize());
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,9 +43,12 @@ namespace SHADE
|
|||
bool result = ImGui::Begin(windowName.data(), &isOpen, windowFlags);
|
||||
|
||||
auto wndSize = ImGui::GetWindowSize();
|
||||
if(windowSize.x != wndSize.x || windowSize.y != wndSize.y)
|
||||
auto contentRegionAvail = ImGui::GetContentRegionAvail();
|
||||
if( beginContentRegionAvailable.x != contentRegionAvail.x || beginContentRegionAvailable.y != contentRegionAvail.y || windowSize.x != wndSize.x || windowSize.y != wndSize.y)
|
||||
{
|
||||
windowSize = {wndSize.x, wndSize.y};
|
||||
beginContentRegionAvailable = {contentRegionAvail.x, contentRegionAvail.y};
|
||||
|
||||
OnResize();
|
||||
}
|
||||
auto wndPos = ImGui::GetWindowPos();
|
||||
|
|
|
@ -26,6 +26,10 @@ namespace SHADE
|
|||
bool isOpen;
|
||||
bool isWindowHovered;
|
||||
std::string_view windowName;
|
||||
SHVec2 windowSize;
|
||||
SHVec2 windowPos;
|
||||
SHVec2 viewportMousePos;
|
||||
SHVec2 beginContentRegionAvailable;
|
||||
protected:
|
||||
virtual bool Begin();
|
||||
virtual void OnResize();
|
||||
|
@ -33,8 +37,6 @@ namespace SHADE
|
|||
|
||||
ImGuiWindowFlags windowFlags = 0;
|
||||
ImGuiIO& io;
|
||||
SHVec2 windowSize;
|
||||
SHVec2 windowPos;
|
||||
SHVec2 viewportMousePos;
|
||||
|
||||
};//class SHEditorWindow
|
||||
}//namespace SHADE
|
||||
|
|
|
@ -3,4 +3,5 @@
|
|||
#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel
|
||||
#include "Inspector/SHEditorInspector.h" //Inspector
|
||||
#include "Profiling/SHEditorProfiler.h" //Profiler
|
||||
#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport
|
||||
#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport
|
||||
#include "AssetBrowser/SHAssetBrowser.h" //Asset Browser
|
|
@ -1,56 +1,62 @@
|
|||
#include "SHpch.h"
|
||||
#include "Editor/SHImGuiHelpers.hpp"
|
||||
#include "SHEditorViewport.h"
|
||||
|
||||
#include "ImGuizmo.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Editor/IconsMaterialDesign.h"
|
||||
#include "Editor/SHEditor.hpp"
|
||||
#include "Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
|
||||
#include <Editor/IconsFontAwesome6.h>
|
||||
|
||||
constexpr std::string_view windowName = "\xef\x80\x95 Viewport";
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
SHEditorViewport::SHEditorViewport()
|
||||
:SHEditorWindow("Viewport", ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoScrollbar)
|
||||
:SHEditorWindow("\xee\x90\x8b Viewport", ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoScrollbar)
|
||||
{
|
||||
}
|
||||
|
||||
void SHEditorViewport::Init()
|
||||
{
|
||||
SHEditorWindow::Init();
|
||||
|
||||
transformGizmo.Init();
|
||||
}
|
||||
|
||||
void SHEditorViewport::Update()
|
||||
{
|
||||
SHEditorWindow::Update();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f,0.0f));
|
||||
if(Begin())
|
||||
{
|
||||
ImGuizmo::SetDrawlist();
|
||||
DrawMenuBar();
|
||||
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
|
||||
auto const& descriptorSet = gfxSystem->GetPostOffscreenRenderSystem()->GetDescriptorSetGroup()->GetVkHandle()[0];
|
||||
auto mousePos = ImGui::GetMousePos();
|
||||
auto cursorPos = ImGui::GetCursorScreenPos();
|
||||
viewportMousePos = {mousePos.x - cursorPos.x, mousePos.y - cursorPos.y};
|
||||
beginCursorPos = ImGui::GetCursorScreenPos();
|
||||
viewportMousePos = {mousePos.x - beginCursorPos.x, mousePos.y - beginCursorPos.y};
|
||||
gfxSystem->GetMousePickSystem ()->SetViewportMousePos (viewportMousePos);
|
||||
//if (ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||
//{
|
||||
// auto eid = gfxSystem->GetMousePickSystem ()->GetPickedEntity();
|
||||
// if(eid != MAX_EID)
|
||||
// {
|
||||
// auto editor = SHSystemManager::GetSystem<SHEditor>();
|
||||
// editor->selectedEntities.clear();
|
||||
// editor->selectedEntities.push_back(eid);
|
||||
// if (const auto hierarchyPanel = SHEditorWindowManager::GetEditorWindow<SHHierarchyPanel>())
|
||||
// {
|
||||
// hierarchyPanel->SetScrollTo(eid);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
ImGui::Image((ImTextureID)descriptorSet, ImGui::GetWindowSize());
|
||||
ImGui::Image((ImTextureID)descriptorSet, {beginContentRegionAvailable.x, beginContentRegionAvailable.y});
|
||||
|
||||
if(ImGui::IsWindowHovered() && ImGui::IsMouseDown(ImGuiMouseButton_Right))
|
||||
{
|
||||
ImGui::SetMouseCursor(ImGuiMouseCursor_None);
|
||||
ImGui::SetCursorScreenPos(ImGui::GetMousePos());
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImGuiColors::green);
|
||||
ImGui::Text(ICON_FA_EYE);
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
}
|
||||
ImGuizmo::SetRect(beginCursorPos.x , beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y);
|
||||
transformGizmo.Draw();
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
void SHEditorViewport::Exit()
|
||||
|
@ -66,7 +72,11 @@ namespace SHADE
|
|||
|
||||
//auto pos = ImGui::GetCursorPos();
|
||||
//windowCursorPos = {}
|
||||
gfxSystem->PrepareResize(static_cast<uint32_t>(windowSize.x), static_cast<uint32_t>(windowSize.y));
|
||||
if(beginContentRegionAvailable.x == 0 || beginContentRegionAvailable.y == 0)
|
||||
{
|
||||
beginContentRegionAvailable = windowSize;
|
||||
}
|
||||
gfxSystem->PrepareResize(static_cast<uint32_t>(beginContentRegionAvailable.x), static_cast<uint32_t>(beginContentRegionAvailable.y));
|
||||
}
|
||||
|
||||
void SHEditorViewport::OnPosChange()
|
||||
|
@ -74,10 +84,46 @@ namespace SHADE
|
|||
SHEditorWindow::OnPosChange();
|
||||
}
|
||||
|
||||
void SHEditorViewport::DrawMenuBar() const noexcept
|
||||
void SHEditorViewport::DrawMenuBar() noexcept
|
||||
{
|
||||
if(ImGui::BeginMenuBar())
|
||||
{
|
||||
bool const isTranslate = transformGizmo.operation == SHTransformGizmo::Operation::TRANSLATE;
|
||||
ImGui::BeginDisabled(isTranslate);
|
||||
if(isTranslate)
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_CheckMark]);
|
||||
if(ImGui::Button(ICON_MD_OPEN_WITH))
|
||||
{
|
||||
transformGizmo.operation = SHTransformGizmo::Operation::TRANSLATE;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
if(isTranslate)
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
bool const isRotate = transformGizmo.operation == SHTransformGizmo::Operation::ROTATE;
|
||||
ImGui::BeginDisabled(isRotate);
|
||||
if(isRotate)
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_CheckMark]);
|
||||
if(ImGui::Button(ICON_MD_AUTORENEW))
|
||||
{
|
||||
transformGizmo.operation = SHTransformGizmo::Operation::ROTATE;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
if(isRotate)
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
bool const isScale = transformGizmo.operation == SHTransformGizmo::Operation::SCALE;
|
||||
ImGui::BeginDisabled(isScale);
|
||||
if(isScale)
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_CheckMark]);
|
||||
if(ImGui::Button(ICON_MD_EXPAND))
|
||||
{
|
||||
transformGizmo.operation = SHTransformGizmo::Operation::SCALE;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
if(isScale)
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "imgui_internal.h"
|
||||
#include "ECS_Base/SHECSMacros.h"
|
||||
#include "Editor/EditorWindow/SHEditorWindow.h"
|
||||
#include "Editor/Gizmos/SHTransformGizmo.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -20,10 +21,12 @@ namespace SHADE
|
|||
void Init() override;
|
||||
void Update() override;
|
||||
void Exit() override;
|
||||
SHTransformGizmo transformGizmo;
|
||||
protected:
|
||||
void OnResize() override;
|
||||
void OnPosChange() override;
|
||||
private:
|
||||
void DrawMenuBar() const noexcept;
|
||||
void DrawMenuBar() noexcept;
|
||||
SHVec2 beginCursorPos;
|
||||
};//class SHEditorViewport
|
||||
}//namespace SHADE
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHTransformGizmo.h"
|
||||
|
||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Editor/SHEditor.hpp"
|
||||
#include "Editor/SHImGuiHelpers.hpp"
|
||||
#include <imgui.h>
|
||||
#include <ImGuizmo.h>
|
||||
|
||||
#include "Camera/SHCameraSystem.h"
|
||||
#include "Editor/Command/SHCommandManager.h"
|
||||
#include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h"
|
||||
namespace SHADE
|
||||
{
|
||||
void SHTransformGizmo::Init()
|
||||
{
|
||||
auto& style = ImGuizmo::GetStyle();
|
||||
style.RotationLineThickness = 2.5f;
|
||||
}
|
||||
|
||||
void SHTransformGizmo::Draw()
|
||||
{
|
||||
bool justChangedTfm = false;
|
||||
if (!editorCamera)
|
||||
{
|
||||
auto const cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
|
||||
editorCamera = cameraSystem->GetEditorCamera();
|
||||
}
|
||||
auto viewportWindow = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>();
|
||||
ImGuizmo::SetOrthographic(false);
|
||||
|
||||
SHMatrix view = SHMatrix::Transpose(editorCamera->GetViewMatrix());
|
||||
SHMatrix proj = SHMatrix::Transpose(editorCamera->GetProjMatrix());
|
||||
|
||||
//Invert projection y-axis
|
||||
proj(1, 1) *= -1;
|
||||
|
||||
static SHMatrix gridMat = SHMatrix::Translate(0, -0.5f, 0.f) * SHMatrix::Identity;
|
||||
|
||||
if (selectedEntityTransformComponent == nullptr)
|
||||
{
|
||||
SHEditor* editor = SHSystemManager::GetSystem<SHEditor>();
|
||||
if (editor->selectedEntities.empty())
|
||||
return;
|
||||
EntityID eid = editor->selectedEntities.back();
|
||||
selectedEntityTransformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
|
||||
justChangedTfm = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditor* editor = SHSystemManager::GetSystem<SHEditor>();
|
||||
if (editor->selectedEntities.empty())
|
||||
return;
|
||||
EntityID eid = editor->selectedEntities.back();
|
||||
auto tfmComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
|
||||
if (selectedEntityTransformComponent != tfmComponent)
|
||||
{
|
||||
selectedEntityTransformComponent = tfmComponent;
|
||||
justChangedTfm = true;
|
||||
}
|
||||
}
|
||||
if (selectedEntityTransformComponent == nullptr)
|
||||
return;
|
||||
|
||||
SHMatrix mat = selectedEntityTransformComponent->GetTRS();
|
||||
useSnap = ImGui::IsKeyDown(ImGuiKey_LeftCtrl);
|
||||
if(useSnap)
|
||||
{
|
||||
switch (operation)
|
||||
{
|
||||
case Operation::TRANSLATE: snap = &translationSnap.x; break;
|
||||
case Operation::ROTATE: snap = &rotationSnap; break;
|
||||
case Operation::SCALE: snap = &scaleSnap; break;
|
||||
default: snap = &translationSnap.x;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
#pragma once
|
||||
#include "Camera/SHCameraComponent.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHTransformGizmo
|
||||
{
|
||||
public:
|
||||
enum class Mode
|
||||
{
|
||||
WORLD,
|
||||
LOCAL
|
||||
};
|
||||
|
||||
enum class Operation
|
||||
{
|
||||
TRANSLATE_X = (1u << 0),
|
||||
TRANSLATE_Y = (1u << 1),
|
||||
TRANSLATE_Z = (1u << 2),
|
||||
ROTATE_X = (1u << 3),
|
||||
ROTATE_Y = (1u << 4),
|
||||
ROTATE_Z = (1u << 5),
|
||||
ROTATE_SCREEN = (1u << 6),
|
||||
SCALE_X = (1u << 7),
|
||||
SCALE_Y = (1u << 8),
|
||||
SCALE_Z = (1u << 9),
|
||||
BOUNDS = (1u << 10),
|
||||
SCALE_XU = (1u << 11),
|
||||
SCALE_YU = (1u << 12),
|
||||
SCALE_ZU = (1u << 13),
|
||||
|
||||
TRANSLATE = TRANSLATE_X | TRANSLATE_Y | TRANSLATE_Z,
|
||||
ROTATE = ROTATE_X | ROTATE_Y | ROTATE_Z | ROTATE_SCREEN,
|
||||
SCALE = SCALE_X | SCALE_Y | SCALE_Z,
|
||||
SCALEU = SCALE_XU | SCALE_YU | SCALE_ZU, // universal
|
||||
UNIVERSAL = TRANSLATE | ROTATE | SCALEU
|
||||
};
|
||||
|
||||
void Init();
|
||||
void Draw();
|
||||
bool isManipulating = false;
|
||||
bool useSnap = false;
|
||||
Mode mode = Mode::WORLD;
|
||||
Operation operation = Operation::TRANSLATE;
|
||||
private:
|
||||
float scaleSnap = 0.25f;
|
||||
float rotationSnap = 1.0f;
|
||||
SHVec3 translationSnap = SHVec3(0.25f, 0.25f, 0.25f);
|
||||
float* snap = nullptr;
|
||||
SHTransformComponent* selectedEntityTransformComponent{nullptr};
|
||||
SHCameraComponent* editorCamera{nullptr};
|
||||
};
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -4,6 +4,7 @@
|
|||
#include "SHpch.h"
|
||||
|
||||
#include "IconsMaterialDesign.h"
|
||||
#include "IconsFontAwesome6.h"
|
||||
#include "DragDrop/SHDragDrop.hpp"
|
||||
|
||||
//#==============================================================#
|
||||
|
@ -36,6 +37,7 @@
|
|||
#include <imgui.h>
|
||||
#include <SDL.h>
|
||||
#include <rttr/registration>
|
||||
#include <ImGuizmo.h>
|
||||
|
||||
//#==============================================================#
|
||||
//|| ImGui Backend Includes ||
|
||||
|
@ -87,10 +89,11 @@ namespace SHADE
|
|||
|
||||
//Add editor windows
|
||||
SHEditorWindowManager::CreateEditorWindow<SHEditorMenuBar>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHAssetBrowser>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
|
||||
|
||||
io = &ImGui::GetIO();
|
||||
|
||||
|
@ -98,7 +101,7 @@ namespace SHADE
|
|||
io->ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; //Enable for Multi-Viewports
|
||||
io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; //Enable docking
|
||||
io->IniFilename = "../../Assets/Editor/Layouts/UserLayout.ini";
|
||||
|
||||
io->ConfigWindowsMoveFromTitleBarOnly = true;
|
||||
InitLayout();
|
||||
|
||||
InitFonts();
|
||||
|
@ -127,9 +130,13 @@ namespace SHADE
|
|||
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
|
||||
{
|
||||
if(window->isOpen)
|
||||
{
|
||||
window->Update();
|
||||
}
|
||||
}
|
||||
|
||||
//PollPicking();
|
||||
|
||||
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
|
||||
{
|
||||
SHCommandManager::RedoCommand();
|
||||
|
@ -165,10 +172,11 @@ namespace SHADE
|
|||
{
|
||||
ImFont* mainFont = io->Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/Segoe UI.ttf", 20.f);//TODO: Change to config based assets path
|
||||
|
||||
constexpr ImWchar icon_ranges[] = { ICON_MIN_MD, ICON_MAX_16_MD, 0 };
|
||||
ImFontConfig icons_config{}; icons_config.MergeMode = true; icons_config.GlyphOffset.y = 5.f;
|
||||
ImFont* UIFont = io->Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/MaterialIcons-Regular.ttf", 20.f, &icons_config, icon_ranges); //TODO: Change to config based assets path
|
||||
|
||||
constexpr ImWchar icon_ranges_fa[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
|
||||
ImFont* UIFontFA = io->Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/fa-solid-900.ttf", 20.f, &icons_config, icon_ranges_fa); //TODO: Change to config based assets path
|
||||
constexpr ImWchar icon_ranges_md[] = { ICON_MIN_MD, ICON_MAX_MD, 0 };
|
||||
ImFont* UIFontMD = io->Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/MaterialIcons-Regular.ttf", 20.f, &icons_config, icon_ranges_md); //TODO: Change to config based assets path
|
||||
io->Fonts->Build();
|
||||
}
|
||||
|
||||
|
@ -338,7 +346,7 @@ namespace SHADE
|
|||
if (auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>())
|
||||
{
|
||||
auto viewportWindow = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>();
|
||||
if (viewportWindow->isWindowHovered && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||
if (viewportWindow->isWindowHovered && !viewportWindow->transformGizmo.isManipulating && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||
{
|
||||
EntityID pickedEID = gfxSystem->GetMousePickSystem()->GetPickedEntity();
|
||||
if(pickedEID == MAX_EID)
|
||||
|
@ -366,6 +374,7 @@ namespace SHADE
|
|||
ImGui_ImplVulkan_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
ImGuizmo::BeginFrame();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -13,9 +13,11 @@
|
|||
#include "ECS_Base/SHECSMacros.h"
|
||||
#include "ECS_Base/System/SHSystem.h"
|
||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||
#include "Resource/Handle.h"
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "EditorWindow/SHEditorWindow.h"
|
||||
#include "Tools/SHLogger.h"
|
||||
#include "Gizmos/SHTransformGizmo.h"
|
||||
|
||||
|
||||
//#==============================================================#
|
||||
//|| Library Includes ||
|
||||
|
@ -200,5 +202,7 @@ namespace SHADE
|
|||
SDL_Window* sdlWindow {nullptr};
|
||||
|
||||
ImGuiIO* io{nullptr};
|
||||
|
||||
//SHTransformGizmo transformGizmo;
|
||||
};//class SHEditor
|
||||
}//namespace SHADE
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
bool SHEditorUI::CollapsingHeader(const std::string& title)
|
||||
{
|
||||
return ImGui::CollapsingHeader(title.c_str());
|
||||
return ImGui::CollapsingHeader(title.c_str(), ImGuiTreeNodeFlags_DefaultOpen);
|
||||
}
|
||||
|
||||
void SHEditorUI::SameLine()
|
||||
|
|
|
@ -40,7 +40,6 @@ namespace SHADE
|
|||
{
|
||||
ImGui::BeginGroup();
|
||||
|
||||
auto cursorPos = ImGui::GetCursorScreenPos();
|
||||
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, 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>
|
||||
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(),
|
||||
ImGuiSliderFlags flags = 0, bool* isHovered = nullptr)
|
||||
{
|
||||
|
@ -169,13 +168,13 @@ namespace SHADE
|
|||
const ImGuiContext& g = *GImGui;
|
||||
bool valueChanged = false;
|
||||
ImGui::BeginGroup();
|
||||
ImGui::PushID(fieldLabel.c_str());
|
||||
ImGui::PushID(label.c_str());
|
||||
PushMultiItemsWidthsAndLabels(componentLabels, 0.0f);
|
||||
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
|
||||
ImGui::SetColumnWidth(-1, 80.0f);
|
||||
ImGui::Text(fieldLabel.c_str());
|
||||
ImGui::Text(label.c_str());
|
||||
if (isHovered)
|
||||
*isHovered = ImGui::IsItemHovered();
|
||||
*isHovered = ImGui::IsItemHovered();
|
||||
ImGui::NextColumn();
|
||||
for (std::size_t i = 0; i < N; ++i)
|
||||
{
|
||||
|
@ -203,75 +202,91 @@ namespace SHADE
|
|||
return valueChanged;
|
||||
}
|
||||
|
||||
static bool DragVec2(const std::string& fieldLabel, 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,
|
||||
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", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f,
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
SHVec2 values = get();
|
||||
bool changed = false;
|
||||
if (DragN<float, 2>(fieldLabel, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
|
||||
bool const changed = DragN<float, 2>(label, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags);
|
||||
static bool startRecording = false;
|
||||
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)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), true);
|
||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), startRecording);
|
||||
if (!startRecording)
|
||||
startRecording = true;
|
||||
}
|
||||
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||
startRecording = false;
|
||||
if(!tooltip.empty())
|
||||
{
|
||||
if(ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text(tooltip.data());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static bool DragVec3(const std::string& fieldLabel, 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,
|
||||
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", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f,
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
SHVec3 values = get();
|
||||
bool changed = false;
|
||||
if (DragN<float, 3>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
bool const changed = DragN<float, 3>(label, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags);
|
||||
|
||||
|
||||
static bool startRecording = false;
|
||||
if (changed)
|
||||
{
|
||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), true);
|
||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
|
||||
SHVec3 old = get();
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(old, values, set)), startRecording);
|
||||
if (!startRecording)
|
||||
startRecording = true;
|
||||
}
|
||||
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||
{
|
||||
startRecording = false;
|
||||
}
|
||||
if(!tooltip.empty())
|
||||
{
|
||||
if(ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text(tooltip.data());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static bool DragVec4(const std::string& fieldLabel, 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,
|
||||
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", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f,
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
SHVec4 values = get();
|
||||
bool changed = false;
|
||||
if (DragN<float, 4>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
|
||||
bool const changed = DragN<float, 4>(label, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags);
|
||||
static bool startRecording = false;
|
||||
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)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), true);
|
||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), startRecording);
|
||||
if (!startRecording)
|
||||
startRecording = true;
|
||||
}
|
||||
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||
{
|
||||
startRecording = false;
|
||||
}
|
||||
if(!tooltip.empty())
|
||||
{
|
||||
if(ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text(tooltip.data());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
@ -279,173 +294,325 @@ namespace SHADE
|
|||
//|| 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();
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
ImGui::PopID();
|
||||
ImGui::EndGroup();
|
||||
if(!tooltip.empty())
|
||||
{
|
||||
if(ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text(tooltip.data());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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();
|
||||
ImGui::BeginGroup();
|
||||
ImGui::PushID(label.data());
|
||||
TextLabel(label);
|
||||
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);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
}
|
||||
ImGui::PopID();
|
||||
ImGui::EndGroup();
|
||||
if (!tooltip.empty())
|
||||
{
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text(tooltip.data());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool InputText(const std::string& label, const std::function<std::string(void)> get,
|
||||
const std::function<void(std::string)> set, ImGuiInputTextFlags flag = 0,
|
||||
ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0)
|
||||
const std::function<void(std::string)> set, std::string_view const& tooltip = {},
|
||||
ImGuiInputTextFlags flag = 0, ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0)
|
||||
{
|
||||
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())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<std::string>>(get(), text, set)), false);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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))
|
||||
ImGui::PopID();
|
||||
ImGui::EndGroup();
|
||||
if (!tooltip.empty())
|
||||
{
|
||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true);
|
||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
|
||||
|
||||
return true;
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text(tooltip.data());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
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 value = get();
|
||||
//bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags);
|
||||
if (ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
|
||||
ImGui::BeginGroup();
|
||||
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)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
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;
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), startRecording);
|
||||
if (!startRecording)
|
||||
startRecording = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
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 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)
|
||||
{
|
||||
int value = get();
|
||||
//bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags);
|
||||
if (ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
|
||||
ImGui::BeginGroup();
|
||||
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)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
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;
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), startRecording);
|
||||
if (!startRecording)
|
||||
startRecording = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
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)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true);
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), startRecording);
|
||||
if (!startRecording)
|
||||
startRecording = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
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 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)
|
||||
{
|
||||
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)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true);
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), startRecording);
|
||||
if (!startRecording)
|
||||
startRecording = true;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
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 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
return false;
|
||||
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 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;
|
||||
int selected = get();
|
||||
ImGui::PushID(fieldLabel.c_str());
|
||||
ImGui::Text(fieldLabel.c_str()); ImGui::SameLine();
|
||||
ImGui::BeginGroup();
|
||||
ImGui::PushID(label.c_str());
|
||||
TextLabel(label);
|
||||
ImGui::SameLine();
|
||||
|
||||
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);
|
||||
}
|
||||
ImGui::PopID();
|
||||
ImGui::EndGroup();
|
||||
if (!tooltip.empty())
|
||||
{
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text(tooltip.data());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
return edited;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
//#==============================================================#
|
||||
#ifndef SH_IM_MATH
|
||||
#define IM_VEC2_CLASS_EXTRA \
|
||||
ImVec2(const SHADE::SHVec2& vec) {x = vec.x; y = vec.y;} \
|
||||
ImVec2(const SHADE::SHVec2& vec) {x = vec.x; y = vec.y;} \
|
||||
operator SHADE::SHVec2() const {return SHADE::SHVec2(x,y);}
|
||||
#define IM_VEC3_CLASS_EXTRA \
|
||||
ImVec3(const SHADE::SHVec3& vec) {x = vec.x; y = vec.y; z = vec.z;} \
|
||||
|
@ -43,6 +43,10 @@ namespace SHADE
|
|||
constexpr ImVec4 blue = {0.0f, 0.0f, 1.0f, 1.f};
|
||||
constexpr ImVec4 white = {1.0f, 1.0f, 1.0f, 1.f};
|
||||
|
||||
constexpr int colors_red = 0;
|
||||
constexpr int colors_green = 1;
|
||||
constexpr int colors_blue = 2;
|
||||
constexpr int colors_white = 3;
|
||||
constexpr ImU32 colors[] = {
|
||||
0xBB0000FF, // red
|
||||
0xBB00FF00, // green
|
||||
|
|
|
@ -11,3 +11,6 @@ constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT { 2 };
|
|||
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 };
|
||||
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 };
|
||||
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 "SHEvent.h"
|
||||
#include "SHEventReceiver.h"
|
||||
#include "SH_API.h"
|
||||
|
||||
/******************************************************************************
|
||||
INSTRUCTIONS FOR USE:
|
||||
|
@ -67,7 +68,7 @@ namespace SHADE
|
|||
using EventManagerListener = std::function<void(SHEvent)>;
|
||||
|
||||
|
||||
class SHEventManager
|
||||
class SH_API SHEventManager
|
||||
{
|
||||
private:
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "Graphics/SHVulkanIncludes.h"
|
||||
#include "vk_mem_alloc.h"
|
||||
#include "Resource/Handle.h"
|
||||
#include "Resource/SHHandle.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "Graphics/Buffers/SHVkBuffer.h"
|
||||
#include "Graphics/Images/SHVkImage.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||
#include "Graphics/SHVkUtil.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
|
@ -299,7 +300,7 @@ namespace SHADE
|
|||
SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound. ");
|
||||
return;
|
||||
}
|
||||
boundPipelineLayoutHdl = pipelineHdl->GetPipelineLayout();
|
||||
bindPointData[static_cast<uint32_t>(pipelineHdl->GetPipelineType())].boundPipelineLayoutHdl = pipelineHdl->GetPipelineLayout();
|
||||
vkCommandBuffer.bindPipeline(pipelineHdl->GetPipelineBindPoint(), pipelineHdl->GetVkPipeline());
|
||||
}
|
||||
|
||||
|
@ -358,9 +359,10 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHVkCommandBuffer::BindDescriptorSet(Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets)
|
||||
void SHVkCommandBuffer::BindDescriptorSet(Handle<SHVkDescriptorSetGroup> descSetGroup, SH_PIPELINE_TYPE bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets)
|
||||
{
|
||||
vkCommandBuffer.bindDescriptorSets(bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets);
|
||||
uint32_t bindPointIndex = static_cast<uint32_t>(bindPoint);
|
||||
vkCommandBuffer.bindDescriptorSets(SHVkUtil::GetPipelineBindPointFromType(bindPoint), bindPointData[bindPointIndex].boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -452,6 +454,11 @@ namespace SHADE
|
|||
vkCommandBuffer.drawIndexedIndirect(indirectDrawData->GetVkBuffer(), 0, drawCount, sizeof(vk::DrawIndexedIndirectCommand));
|
||||
}
|
||||
|
||||
void SHVkCommandBuffer::ComputeDispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) noexcept
|
||||
{
|
||||
vkCommandBuffer.dispatch (groupCountX, groupCountY, groupCountZ);
|
||||
}
|
||||
|
||||
void SHVkCommandBuffer::CopyBufferToImage(const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo)
|
||||
{
|
||||
vkCommandBuffer.copyBufferToImage
|
||||
|
@ -500,9 +507,9 @@ namespace SHADE
|
|||
// //vkCommandBuffer.pipelineBarrier()
|
||||
//}
|
||||
|
||||
void SHVkCommandBuffer::ForceSetPipelineLayout(Handle<SHVkPipelineLayout> pipelineLayout) noexcept
|
||||
void SHVkCommandBuffer::ForceSetPipelineLayout(Handle<SHVkPipelineLayout> pipelineLayout, SH_PIPELINE_TYPE pipelineType) noexcept
|
||||
{
|
||||
boundPipelineLayoutHdl = pipelineLayout;
|
||||
bindPointData[static_cast<uint32_t>(pipelineType)].boundPipelineLayoutHdl = pipelineLayout;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -513,12 +520,13 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHVkCommandBuffer::SubmitPushConstants(void) const noexcept
|
||||
void SHVkCommandBuffer::SubmitPushConstants(SH_PIPELINE_TYPE bindPoint) const noexcept
|
||||
{
|
||||
vkCommandBuffer.pushConstants(boundPipelineLayoutHdl->GetVkPipelineLayout(),
|
||||
boundPipelineLayoutHdl->GetPushConstantInterface().GetShaderStageFlags(),
|
||||
auto layoutHdl = bindPointData[static_cast<uint32_t>(bindPoint)].boundPipelineLayoutHdl;
|
||||
vkCommandBuffer.pushConstants(layoutHdl->GetVkPipelineLayout(),
|
||||
layoutHdl->GetPushConstantInterface().GetShaderStageFlags(),
|
||||
0,
|
||||
boundPipelineLayoutHdl->GetPushConstantInterface().GetSize(), pushConstantData);
|
||||
layoutHdl->GetPushConstantInterface().GetSize(), pushConstantData);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -695,7 +703,7 @@ namespace SHADE
|
|||
, usageFlags{ rhs.usageFlags }
|
||||
, commandBufferCount{ rhs.commandBufferCount }
|
||||
, parentPool{ rhs.parentPool }
|
||||
, boundPipelineLayoutHdl{ rhs.boundPipelineLayoutHdl }
|
||||
, bindPointData{ std::move (rhs.bindPointData)}
|
||||
{
|
||||
memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
|
||||
|
||||
|
@ -728,7 +736,7 @@ namespace SHADE
|
|||
usageFlags = rhs.usageFlags;
|
||||
commandBufferCount = rhs.commandBufferCount;
|
||||
parentPool = rhs.parentPool;
|
||||
boundPipelineLayoutHdl = rhs.boundPipelineLayoutHdl;
|
||||
bindPointData = std::move(rhs.bindPointData);
|
||||
memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
|
||||
|
||||
rhs.vkCommandBuffer = VK_NULL_HANDLE;
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
#include "Graphics/SHVulkanIncludes.h"
|
||||
#include "Graphics/SHVulkanDefines.h"
|
||||
#include "SHCommandPoolResetMode.h"
|
||||
#include "Resource/ResourceLibrary.h"
|
||||
#include "Resource/SHResourceLibrary.h"
|
||||
#include "Graphics/Pipeline/SHVkPipelineLayout.h"
|
||||
#include "Graphics/Pipeline/SHPipelineType.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -36,10 +37,17 @@ namespace SHADE
|
|||
class SHVkCommandBuffer
|
||||
{
|
||||
friend class SHVkCommandPool;
|
||||
friend class ResourceLibrary<SHVkCommandBuffer>;
|
||||
friend class SHResourceLibrary<SHVkCommandBuffer>;
|
||||
|
||||
static constexpr uint16_t PUSH_CONSTANT_SIZE = 512;
|
||||
|
||||
private:
|
||||
struct PipelineBindPointData
|
||||
{
|
||||
//! The currently bound pipeline
|
||||
Handle<SHVkPipelineLayout> boundPipelineLayoutHdl;
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER VARIABLES */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -66,8 +74,8 @@ namespace SHADE
|
|||
//! The command pool that this command buffer belongs to
|
||||
Handle<SHVkCommandPool> parentPool;
|
||||
|
||||
//! The currently bound pipeline
|
||||
Handle<SHVkPipelineLayout> boundPipelineLayoutHdl;
|
||||
//! Every command buffer will have a set of pipeline bind point specific data
|
||||
std::array<PipelineBindPointData, static_cast<uint32_t>(SH_PIPELINE_TYPE::NUM_TYPES)> bindPointData;
|
||||
|
||||
//! The push constant data for the command buffer
|
||||
uint8_t pushConstantData[PUSH_CONSTANT_SIZE];
|
||||
|
@ -112,13 +120,16 @@ namespace SHADE
|
|||
void BindPipeline (Handle<SHVkPipeline> const& pipelineHdl) noexcept;
|
||||
void BindVertexBuffer (uint32_t bindingPoint, Handle<SHVkBuffer> const& buffer, vk::DeviceSize offset) noexcept;
|
||||
void BindIndexBuffer (Handle<SHVkBuffer> const& buffer, uint32_t startingIndex) const noexcept;
|
||||
void BindDescriptorSet (Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets);
|
||||
void BindDescriptorSet (Handle<SHVkDescriptorSetGroup> descSetGroup, SH_PIPELINE_TYPE bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets);
|
||||
|
||||
// Draw Commands
|
||||
void DrawArrays (uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept;
|
||||
void DrawIndexed (uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept;
|
||||
void DrawMultiIndirect (Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount);
|
||||
|
||||
// Compute Commands
|
||||
void ComputeDispatch (uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) noexcept;
|
||||
|
||||
// Buffer Copy
|
||||
void CopyBufferToImage (const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo);
|
||||
void CopyImageToBuffer (const vk::Image& src, const vk::Buffer& dst, const std::vector<vk::BufferImageCopy>& copyInfo);
|
||||
|
@ -138,13 +149,13 @@ namespace SHADE
|
|||
|
||||
// Push Constant variable setting
|
||||
template <typename T>
|
||||
void SetPushConstantVariable(std::string variableName, T const& data) noexcept
|
||||
void SetPushConstantVariable(std::string variableName, T const& data, SH_PIPELINE_TYPE bindPoint) noexcept
|
||||
{
|
||||
memcpy (static_cast<uint8_t*>(pushConstantData) + boundPipelineLayoutHdl->GetPushConstantInterface().GetOffset(variableName), &data, sizeof (T));
|
||||
memcpy (static_cast<uint8_t*>(pushConstantData) + bindPointData[static_cast<uint32_t>(bindPoint)].boundPipelineLayoutHdl->GetPushConstantInterface().GetOffset(variableName), &data, sizeof (T));
|
||||
};
|
||||
void ForceSetPipelineLayout (Handle<SHVkPipelineLayout> pipelineLayout) noexcept;
|
||||
void ForceSetPipelineLayout (Handle<SHVkPipelineLayout> pipelineLayout, SH_PIPELINE_TYPE pipelineType) noexcept;
|
||||
|
||||
void SubmitPushConstants (void) const noexcept;
|
||||
void SubmitPushConstants (SH_PIPELINE_TYPE bindPoint) const noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* GETTERS AND SETTERS */
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "SHVkCommandPool.h"
|
||||
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||
#include "Graphics/Instance/SHVkInstance.h"
|
||||
#include "Resource/ResourceLibrary.h"
|
||||
#include "Resource/SHResourceLibrary.h"
|
||||
#include "Tools/SHLogger.h"
|
||||
|
||||
namespace SHADE
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "Graphics/Queues/SHVkQueue.h"
|
||||
#include "SHCommandPoolResetMode.h"
|
||||
#include "SHVkCommandBuffer.h"
|
||||
#include "Resource/ResourceLibrary.h"
|
||||
#include "Resource/SHResourceLibrary.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue