Merge branch 'main' into SP3-141-Camera-System
This commit is contained in:
commit
acf52c77ce
|
@ -1,3 +1,3 @@
|
||||||
Name: Cube.003
|
Name: Cube.003
|
||||||
ID: 110152941
|
ID: 71245919
|
||||||
Type: 6
|
Type: 4
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
Name: Cube.012
|
Name: Cube.012
|
||||||
ID: 107348815
|
ID: 80365422
|
||||||
Type: 6
|
Type: 4
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
||||||
|
Name: RaccoonBag_Color_Ver4
|
||||||
|
ID: 58303057
|
||||||
|
Type: 3
|
|
@ -1,3 +1,3 @@
|
||||||
Name: RaccoonPreTexturedVer1_Base9
|
Name: RaccoonPreTexturedVer1_Base9
|
||||||
ID: 91918845
|
ID: 64651793
|
||||||
Type: 4
|
Type: 3
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
struct DirectionalLightStruct
|
||||||
|
{
|
||||||
|
vec3 direction;
|
||||||
|
uint isActive;
|
||||||
|
uint cullingMask;
|
||||||
|
vec4 diffuseColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AmbientLightStruct
|
||||||
|
{
|
||||||
|
vec4 ambientColor;
|
||||||
|
float strength;
|
||||||
|
uint isActive;
|
||||||
|
uint cullingMask;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(local_size_x = 16, local_size_y = 16) in;
|
||||||
|
layout(set = 4, binding = 0, rgba32f) uniform image2D positions;
|
||||||
|
layout(set = 4, binding = 1, rgba32f) uniform image2D normals;
|
||||||
|
layout(set = 4, binding = 2, rgba8) uniform image2D albedo;
|
||||||
|
layout(set = 4, binding = 3, r32ui) uniform uimage2D lightLayerData;
|
||||||
|
layout(set = 4, binding = 4, rgba8) uniform image2D targetImage;
|
||||||
|
|
||||||
|
layout(set = 1, binding = 0) uniform LightCounts
|
||||||
|
{
|
||||||
|
uint directionalLights;
|
||||||
|
uint pointLights;
|
||||||
|
uint spotLights;
|
||||||
|
uint ambientLights;
|
||||||
|
|
||||||
|
} lightCounts;
|
||||||
|
|
||||||
|
layout(std430, set = 1, binding = 1) buffer DirectionalLightData
|
||||||
|
{
|
||||||
|
DirectionalLightStruct dLightData[];
|
||||||
|
} DirLightData;
|
||||||
|
|
||||||
|
layout(std430, set = 1, binding = 4) buffer AmbientLightData
|
||||||
|
{
|
||||||
|
AmbientLightStruct aLightData[];
|
||||||
|
} AmbLightData;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// convenient variables
|
||||||
|
ivec2 globalThread = ivec2(gl_GlobalInvocationID);
|
||||||
|
|
||||||
|
// Get the diffuse color of the pixel
|
||||||
|
vec3 pixelDiffuse = imageLoad (albedo, globalThread).rgb;
|
||||||
|
|
||||||
|
// Get position of fragment in world space
|
||||||
|
vec3 positionWorld = imageLoad (positions, globalThread).rgb;
|
||||||
|
|
||||||
|
// normal of fragment
|
||||||
|
vec3 normalWorld = imageLoad(normals, globalThread).rgb;
|
||||||
|
|
||||||
|
vec3 fragColor = vec3 (0.0f);
|
||||||
|
|
||||||
|
for (int i = 0; i < lightCounts.directionalLights; ++i)
|
||||||
|
{
|
||||||
|
// get normalized direction of light
|
||||||
|
vec3 dLightNormalized = normalize (DirLightData.dLightData[i].direction);
|
||||||
|
|
||||||
|
// Get diffuse strength
|
||||||
|
float diffuseStrength = max (0, dot (dLightNormalized, normalWorld));
|
||||||
|
|
||||||
|
// Calculate the fragment color
|
||||||
|
fragColor += DirLightData.dLightData[i].diffuseColor.rgb * diffuseStrength.rrr * pixelDiffuse;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < lightCounts.ambientLights; ++i)
|
||||||
|
{
|
||||||
|
// Just do some add
|
||||||
|
//fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (0.5f);
|
||||||
|
fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (AmbLightData.aLightData[i].strength);
|
||||||
|
}
|
||||||
|
|
||||||
|
// store result into result image
|
||||||
|
imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor, 1.0f));
|
||||||
|
|
||||||
|
}
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
||||||
|
Name: DeferredComposite_CS
|
||||||
|
ID: 42814284
|
||||||
|
Type: 2
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
||||||
|
Name: Kirsch_CS
|
||||||
|
ID: 39301863
|
||||||
|
Type: 2
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
||||||
|
Name: PureCopy_CS
|
||||||
|
ID: 34987209
|
||||||
|
Type: 2
|
|
@ -13,37 +13,38 @@ struct MatPropData
|
||||||
|
|
||||||
layout(location = 0) in struct
|
layout(location = 0) in struct
|
||||||
{
|
{
|
||||||
vec4 vertColor;
|
vec4 vertPos; // location 0
|
||||||
vec2 uv;
|
vec2 uv; // location = 1
|
||||||
|
vec4 normal; // location = 2
|
||||||
|
|
||||||
} In;
|
} In;
|
||||||
|
|
||||||
// material stuff
|
// material stuff
|
||||||
layout(location = 2) flat in struct
|
layout(location = 3) flat in struct
|
||||||
{
|
{
|
||||||
int materialIndex;
|
int materialIndex;
|
||||||
uint eid;
|
uint eid;
|
||||||
uint lightLayerIndex;
|
uint lightLayerIndex;
|
||||||
} In2;
|
} In2;
|
||||||
|
|
||||||
//layout (set = 0, binding = )
|
|
||||||
|
|
||||||
layout (set = 0, binding = 1) uniform sampler2D textures[]; // for textures (global)
|
layout (set = 0, binding = 1) uniform sampler2D textures[]; // for textures (global)
|
||||||
layout (set = 3, binding = 0) buffer MaterialProperties // For materials
|
layout (std430, set = 3, binding = 0) buffer MaterialProperties // For materials
|
||||||
{
|
{
|
||||||
MatPropData data[];
|
MatPropData data[];
|
||||||
} MatProp;
|
} MatProp;
|
||||||
|
|
||||||
layout(location = 0) out vec4 outColor;
|
layout(location = 0) out vec4 position;
|
||||||
layout(location = 1) out uint outEntityID;
|
layout(location = 1) out uint outEntityID;
|
||||||
layout(location = 2) out uint lightLayerIndices;
|
layout(location = 2) out uint lightLayerIndices;
|
||||||
|
layout(location = 3) out vec4 normals;
|
||||||
|
layout(location = 4) out vec4 albedo;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
outColor = texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv) +
|
position = In.vertPos;
|
||||||
MatProp.data[In2.materialIndex].color / MatProp.data[In2.materialIndex].alpha;
|
normals = In.normal;
|
||||||
|
albedo = texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv) + MatProp.data[In2.materialIndex].color / MatProp.data[In2.materialIndex].alpha;
|
||||||
|
|
||||||
outEntityID = In2.eid;
|
outEntityID = In2.eid;
|
||||||
lightLayerIndices = In2.lightLayerIndex;
|
lightLayerIndices = In2.lightLayerIndex;
|
||||||
//outColor = vec4 (1.0f);
|
|
||||||
}
|
}
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
||||||
|
Name: TestCube_FS
|
||||||
|
ID: 37450402
|
||||||
|
Type: 2
|
|
@ -14,13 +14,14 @@ layout(location = 8) in uvec2 integerData;
|
||||||
|
|
||||||
layout(location = 0) out struct
|
layout(location = 0) out struct
|
||||||
{
|
{
|
||||||
vec4 vertColor; // location 0
|
vec4 vertPos; // location 0
|
||||||
vec2 uv; // location = 1
|
vec2 uv; // location = 1
|
||||||
|
vec4 normal; // location = 2
|
||||||
|
|
||||||
} Out;
|
} Out;
|
||||||
|
|
||||||
// material stuff
|
// material stuff
|
||||||
layout(location = 2) out struct
|
layout(location = 3) out struct
|
||||||
{
|
{
|
||||||
int materialIndex;
|
int materialIndex;
|
||||||
uint eid;
|
uint eid;
|
||||||
|
@ -36,10 +37,14 @@ layout(set = 2, binding = 0) uniform CameraData
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
Out.uv = aUV;
|
|
||||||
Out2.materialIndex = gl_InstanceIndex;
|
Out2.materialIndex = gl_InstanceIndex;
|
||||||
Out2.eid = integerData[0];
|
Out2.eid = integerData[0];
|
||||||
Out2.lightLayerIndex = integerData[1];
|
Out2.lightLayerIndex = integerData[1];
|
||||||
|
|
||||||
|
Out.vertPos = worldTransform * vec4(aVertexPos, 1.0f);
|
||||||
|
Out.uv = aUV;
|
||||||
|
Out.normal.rgb = mat3(transpose(inverse(worldTransform))) * aNormal.rgb;
|
||||||
|
Out.normal.rgb = normalize (Out.normal.rgb);
|
||||||
gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f);
|
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: 41688429
|
||||||
|
Type: 2
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
||||||
|
Name: TD_Checker_Base_Color
|
||||||
|
ID: 51995224
|
||||||
|
Type: 3
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
//#define SHEDITOR
|
//#define SHEDITOR
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
#include "Editor/SHEditor.hpp"
|
#include "Editor/SHEditor.h"
|
||||||
//#include "Scenes/SBEditorScene.h"
|
//#include "Scenes/SBEditorScene.h"
|
||||||
#endif // SHEDITOR
|
#endif // SHEDITOR
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ namespace Sandbox
|
||||||
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>();
|
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>();
|
||||||
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();
|
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();
|
||||||
|
|
||||||
SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::EditorCameraUpdate>();
|
//SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::EditorCameraUpdate>();
|
||||||
SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::CameraSystemUpdate>();
|
SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::CameraSystemUpdate>();
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
|
@ -110,14 +110,7 @@ namespace Sandbox
|
||||||
SHComponentManager::CreateComponentSparseSet<SHRenderable>();
|
SHComponentManager::CreateComponentSparseSet<SHRenderable>();
|
||||||
//SHComponentManager::CreateComponentSparseSet<SHCameraComponent>();
|
//SHComponentManager::CreateComponentSparseSet<SHCameraComponent>();
|
||||||
|
|
||||||
//TODO: REMOVE AFTER PRESENTATION
|
SHAssetManager::Load();
|
||||||
//SHAssetManager::LoadDataTemp("../../Assets/racoon.gltf");
|
|
||||||
//SHAssetManager::LoadDataTemp("../../Assets/Cube.012.shmesh");
|
|
||||||
//SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds");
|
|
||||||
//SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds");
|
|
||||||
//SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.shtex");
|
|
||||||
//TODO: REMOVE AFTER PRESENTATION
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SHSystemManager::RegisterRoutine<SHAudioSystem, SHAudioSystem::AudioRoutine>();
|
SHSystemManager::RegisterRoutine<SHAudioSystem, SHAudioSystem::AudioRoutine>();
|
||||||
|
@ -130,8 +123,6 @@ namespace Sandbox
|
||||||
SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
|
SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
|
||||||
|
|
||||||
SHFrameRateController::UpdateFRC();
|
SHFrameRateController::UpdateFRC();
|
||||||
|
|
||||||
SHAssetManager::Load();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SBApplication::Update(void)
|
void SBApplication::Update(void)
|
||||||
|
@ -165,7 +156,7 @@ namespace Sandbox
|
||||||
|
|
||||||
SHSceneManager::Exit();
|
SHSceneManager::Exit();
|
||||||
SHSystemManager::Exit();
|
SHSystemManager::Exit();
|
||||||
SHAssetManager::Unload();
|
SHAssetManager::Exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,8 @@ namespace Sandbox
|
||||||
if (asset.name == "Cube.012")
|
if (asset.name == "Cube.012")
|
||||||
handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id));
|
handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id));
|
||||||
break;
|
break;
|
||||||
case AssetType::IMAGE:
|
case AssetType::TEXTURE:
|
||||||
|
if (asset.name == "RaccoonPreTexturedVer1_Base9")
|
||||||
texHandles.emplace_back(SHResourceManager::LoadOrGet<SHTexture>(asset.id));
|
texHandles.emplace_back(SHResourceManager::LoadOrGet<SHTexture>(asset.id));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +84,7 @@ namespace Sandbox
|
||||||
auto& collider = *SHComponentManager::GetComponent_s<SHColliderComponent>(entity);
|
auto& collider = *SHComponentManager::GetComponent_s<SHColliderComponent>(entity);
|
||||||
|
|
||||||
//renderable.Mesh = handles.front();
|
//renderable.Mesh = handles.front();
|
||||||
renderable.Mesh = CUBE_MESH;
|
renderable.SetMesh(CUBE_MESH);
|
||||||
renderable.SetMaterial(customMat);
|
renderable.SetMaterial(customMat);
|
||||||
|
|
||||||
if (y == 50)
|
if (y == 50)
|
||||||
|
@ -95,11 +96,7 @@ namespace Sandbox
|
||||||
transform.SetWorldRotation(SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f));
|
transform.SetWorldRotation(SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f));
|
||||||
transform.SetWorldScale(TEST_OBJ_SCALE);
|
transform.SetWorldScale(TEST_OBJ_SCALE);
|
||||||
|
|
||||||
//if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN)
|
collider.AddBoundingBox(SHVec3::One, SHVec3::Zero);
|
||||||
collider.AddBoundingBox(SHVec3::One * 0.5f, SHVec3::Zero);
|
|
||||||
//else
|
|
||||||
// collider.AddBoundingSphere(0.5f, SHVec3::Zero);
|
|
||||||
|
|
||||||
stressTestObjects.emplace_back(entity);
|
stressTestObjects.emplace_back(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +104,7 @@ namespace Sandbox
|
||||||
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonSpin);
|
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonSpin);
|
||||||
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonSpin);
|
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonSpin);
|
||||||
|
|
||||||
renderable.Mesh = handles.front();
|
renderable.SetMesh(handles.front());
|
||||||
renderable.SetMaterial(customMat);
|
renderable.SetMaterial(customMat);
|
||||||
renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||||
renderable.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
|
renderable.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
|
||||||
|
@ -122,9 +119,8 @@ namespace Sandbox
|
||||||
auto& floorRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(floor);
|
auto& floorRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(floor);
|
||||||
auto& floorCollider = *SHComponentManager::GetComponent_s<SHColliderComponent>(floor);
|
auto& floorCollider = *SHComponentManager::GetComponent_s<SHColliderComponent>(floor);
|
||||||
|
|
||||||
floorRenderable.Mesh = CUBE_MESH;
|
floorRenderable.SetMesh(CUBE_MESH);
|
||||||
floorRenderable.SetMaterial(customMat);
|
floorRenderable.SetMaterial(graphicsSystem->GetDefaultMaterialInstance());
|
||||||
floorRenderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
|
||||||
|
|
||||||
floorTransform.SetWorldScale({ 7.5f, 0.5f, 7.5 });
|
floorTransform.SetWorldScale({ 7.5f, 0.5f, 7.5 });
|
||||||
floorTransform.SetWorldPosition({ 0.0f, -3.0f, -5.0f });
|
floorTransform.SetWorldPosition({ 0.0f, -3.0f, -5.0f });
|
||||||
|
@ -148,7 +144,7 @@ namespace Sandbox
|
||||||
auto& renderableShowcase = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonShowcase);
|
auto& renderableShowcase = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonShowcase);
|
||||||
auto& transformShowcase = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonShowcase);
|
auto& transformShowcase = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonShowcase);
|
||||||
|
|
||||||
renderableShowcase.Mesh = handles.front();
|
renderableShowcase.SetMesh(handles.front());
|
||||||
renderableShowcase.SetMaterial(customMat);
|
renderableShowcase.SetMaterial(customMat);
|
||||||
renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||||
renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
|
renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
|
||||||
|
@ -162,12 +158,22 @@ namespace Sandbox
|
||||||
SHComponentManager::AddComponent<SHLightComponent>(0);
|
SHComponentManager::AddComponent<SHLightComponent>(0);
|
||||||
SHComponentManager::RemoveComponent <SHRigidBodyComponent>(0);
|
SHComponentManager::RemoveComponent <SHRigidBodyComponent>(0);
|
||||||
SHComponentManager::RemoveComponent <SHColliderComponent>(0);
|
SHComponentManager::RemoveComponent <SHColliderComponent>(0);
|
||||||
|
|
||||||
|
auto ambientLight = SHEntityManager::CreateEntity<SHLightComponent>();
|
||||||
|
SHComponentManager::GetComponent<SHLightComponent>(ambientLight)->SetColor(SHVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
|
SHComponentManager::GetComponent<SHLightComponent>(ambientLight)->SetStrength(0.25f);
|
||||||
|
SHComponentManager::GetComponent<SHLightComponent>(ambientLight)->SetType(SH_LIGHT_TYPE::AMBIENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SBTestScene::Update(float dt)
|
void SBTestScene::Update(float dt)
|
||||||
{
|
{
|
||||||
static float rotation = 0.0f;
|
static float rotation = 0.0f;
|
||||||
|
SHVec3 direction{0.0f, 0.0f, 1.0f};
|
||||||
|
direction = SHVec3::RotateY(direction, rotation);
|
||||||
|
|
||||||
|
auto* lightComp =SHComponentManager::GetComponent<SHLightComponent>(0);
|
||||||
|
lightComp->SetDirection (direction);
|
||||||
|
rotation += 0.005f;
|
||||||
//auto& transform = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHTransformComponent>(testObj);
|
//auto& transform = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHTransformComponent>(testObj);
|
||||||
|
|
||||||
//transform.SetWorldPosition({1.0f, 1.0f, -1.0f});
|
//transform.SetWorldPosition({1.0f, 1.0f, -1.0f});
|
||||||
|
|
|
@ -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)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,149 @@
|
||||||
|
<#
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\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 static
|
||||||
|
/// method.
|
||||||
|
/// </summary>
|
||||||
|
/// <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(MethodInfo method)
|
||||||
|
{
|
||||||
|
// No errors, assign
|
||||||
|
targetMethod = method;
|
||||||
|
|
||||||
|
// Create storage for parameters for calling
|
||||||
|
parameters = new Object[<#=i#>];
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a CallbackAction that represents a call to a specified member
|
||||||
|
/// 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[<#=i#>];
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a Callback action based on an action.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">Action that wraps a function to be called.</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 (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() }");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ project "SHADE_Engine"
|
||||||
pchheader "SHpch.h"
|
pchheader "SHpch.h"
|
||||||
pchsource "%{prj.location}/src/SHpch.cpp"
|
pchsource "%{prj.location}/src/SHpch.cpp"
|
||||||
staticruntime "off"
|
staticruntime "off"
|
||||||
|
buildoptions{"/bigobj"}
|
||||||
files
|
files
|
||||||
{
|
{
|
||||||
"%{prj.location}/src/**.h",
|
"%{prj.location}/src/**.h",
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* \file SHMaterialAsset.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 29 October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* \copyright Copyright (c) 2021 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/Asset Types/SHAssetData.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SHMaterialAsset : SHAssetData
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
std::string data;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* \file SHPrefabAsset.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 28 October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* \copyright Copyright (c) 2021 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 <string>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SHPrefabAsset : SHAssetData
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
std::string data;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* \file SHSceneAsset.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 28 October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* \copyright Copyright (c) 2021 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 <string>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SHSceneAsset : SHAssetData
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
std::string data;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHShaderAsset.cpp
|
||||||
|
* \author Brandon Mak
|
||||||
|
* \date 24 October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHShaderAsset.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
SHShaderAsset::SHShaderAsset() noexcept
|
||||||
|
: spirvBinary{},
|
||||||
|
shaderType{SH_SHADER_TYPE::VERTEX},
|
||||||
|
name{}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SHShaderAsset::SHShaderAsset(SHShaderAsset const& rhs) noexcept
|
||||||
|
: spirvBinary{rhs.spirvBinary},
|
||||||
|
shaderType{ rhs.shaderType },
|
||||||
|
name{rhs.name}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SHShaderAsset::SHShaderAsset(SHShaderAsset&& rhs) noexcept
|
||||||
|
: spirvBinary{ std::move(rhs.spirvBinary) },
|
||||||
|
shaderType{ std::move(rhs.shaderType) },
|
||||||
|
name{ std::move(rhs.name) }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SHShaderAsset& SHShaderAsset::operator=(SHShaderAsset&& rhs) noexcept
|
||||||
|
{
|
||||||
|
if (this == &rhs)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
spirvBinary = std::move(rhs.spirvBinary);
|
||||||
|
shaderType = std::move(rhs.shaderType);
|
||||||
|
name = std::move(rhs.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
SHShaderAsset& SHShaderAsset::operator=(SHShaderAsset const& rhs) noexcept
|
||||||
|
{
|
||||||
|
if (this == &rhs)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
spirvBinary = rhs.spirvBinary;
|
||||||
|
shaderType = rhs.shaderType;
|
||||||
|
name = rhs.name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHShaderAsset.h
|
||||||
|
* \author Brandon Mak
|
||||||
|
* \date 24 October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SHAssetData.h"
|
||||||
|
#include "SH_API.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
enum class SH_SHADER_TYPE : uint8_t
|
||||||
|
{
|
||||||
|
VERTEX,
|
||||||
|
FRAGMENT,
|
||||||
|
COMPUTE,
|
||||||
|
INAVLID_TYPE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SH_API SHShaderAsset : SHAssetData
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* MEMBER VARIABLES */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
//! container storing the spirv binary
|
||||||
|
std::vector<uint32_t> spirvBinary;
|
||||||
|
|
||||||
|
//! For the compilation of the shader. Vulkan backend will use it too
|
||||||
|
SH_SHADER_TYPE shaderType;
|
||||||
|
|
||||||
|
//! Name of the shader file (without parent path)
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
SHShaderAsset() noexcept;
|
||||||
|
SHShaderAsset(SHShaderAsset const& rhs) noexcept;
|
||||||
|
SHShaderAsset(SHShaderAsset&& rhs) noexcept;
|
||||||
|
SHShaderAsset& operator= (SHShaderAsset&& rhs) noexcept;
|
||||||
|
SHShaderAsset& operator= (SHShaderAsset const& rhs) noexcept;
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,24 +1,30 @@
|
||||||
/*************************************************************************//**
|
/*************************************************************************//**
|
||||||
* \file SHAssimpLibrary.cpp
|
* \file SHMeshCompiler.cpp
|
||||||
* \author Loh Xiao Qi
|
* \author Loh Xiao Qi
|
||||||
* \date October 2022
|
* \date 30 September 2022
|
||||||
* \brief
|
* \brief Library to write data in SHMeshAsset into binary file for faster
|
||||||
|
* loading in the future
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
* disclosure of this file or its contents without the prior written consent
|
* disclosure of this file or its contents without the prior written consent
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#include "SHpch.h"
|
#include "SHpch.h"
|
||||||
#include "SHAssimpLibrary.h"
|
#include "SHMeshCompiler.h"
|
||||||
|
#include "Graphics/MiddleEnd/Meshes/SHMeshData.h"
|
||||||
#include <assimp/postprocess.h>
|
#include <assimp/postprocess.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
Assimp::Importer SHAssimpLibrary::aiImporter;
|
|
||||||
|
|
||||||
void SHAssimpLibrary::ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept
|
Assimp::Importer SHMeshCompiler::aiImporter;
|
||||||
{
|
|
||||||
for (size_t i {0}; i < node.mNumMeshes; ++i)
|
void SHMeshCompiler::ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept
|
||||||
|
{
|
||||||
|
for (size_t i{ 0 }; i < node.mNumMeshes; ++i)
|
||||||
{
|
{
|
||||||
aiMesh* mesh = scene.mMeshes[node.mMeshes[i]];
|
aiMesh* mesh = scene.mMeshes[node.mMeshes[i]];
|
||||||
meshes.push_back(ProcessMesh(*mesh));
|
meshes.push_back(ProcessMesh(*mesh));
|
||||||
|
@ -28,16 +34,16 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
ProcessNode(*node.mChildren[i], scene, meshes);
|
ProcessNode(*node.mChildren[i], scene, meshes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssimpLibrary::ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept
|
void SHMeshCompiler::ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept
|
||||||
{
|
{
|
||||||
if (scene.HasAnimations())
|
if (scene.HasAnimations())
|
||||||
{
|
{
|
||||||
std::vector<SHAnimationAsset> anims(scene.mNumAnimations);
|
std::vector<SHAnimationAsset> anims(scene.mNumAnimations);
|
||||||
for (auto i{0}; i < scene.mNumAnimations; ++i)
|
for (auto i{ 0 }; i < scene.mNumAnimations; ++i)
|
||||||
{
|
{
|
||||||
auto const& anim {*scene.mAnimations[i]};
|
auto const& anim{ *scene.mAnimations[i] };
|
||||||
|
|
||||||
anims[i].name = anim.mName.C_Str();
|
anims[i].name = anim.mName.C_Str();
|
||||||
|
|
||||||
|
@ -47,17 +53,17 @@ namespace SHADE
|
||||||
std::copy_n(anim.mChannels, anim.mNumChannels, anims[i].nodeChannels.data());
|
std::copy_n(anim.mChannels, anim.mNumChannels, anims[i].nodeChannels.data());
|
||||||
std::copy_n(anim.mMeshChannels, anim.mNumMeshChannels, anims[i].meshChannels.data());
|
std::copy_n(anim.mMeshChannels, anim.mNumMeshChannels, anims[i].meshChannels.data());
|
||||||
std::copy_n(anim.mMorphMeshChannels, anim.mNumMorphMeshChannels, anims[i].morphMeshChannels.data());
|
std::copy_n(anim.mMorphMeshChannels, anim.mNumMorphMeshChannels, anims[i].morphMeshChannels.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMeshAsset* SHAssimpLibrary::ProcessMesh(aiMesh const& mesh) noexcept
|
SHMeshAsset* SHMeshCompiler::ProcessMesh(aiMesh const& mesh) noexcept
|
||||||
{
|
{
|
||||||
SHMeshAsset* result = new SHMeshAsset();
|
SHMeshAsset* result = new SHMeshAsset();
|
||||||
result->compiled = false;
|
result->compiled = false;
|
||||||
result->changed = false;
|
result->changed = false;
|
||||||
|
|
||||||
for (size_t i{0}; i < mesh.mNumVertices; ++i)
|
for (size_t i{ 0 }; i < mesh.mNumVertices; ++i)
|
||||||
{
|
{
|
||||||
// Vertex position
|
// Vertex position
|
||||||
SHVec3 vertex;
|
SHVec3 vertex;
|
||||||
|
@ -67,7 +73,7 @@ namespace SHADE
|
||||||
result->vertexPosition.push_back(vertex);
|
result->vertexPosition.push_back(vertex);
|
||||||
|
|
||||||
// Tex coords
|
// Tex coords
|
||||||
SHVec2 texCoord{0.f, 0.f};
|
SHVec2 texCoord{ 0.f, 0.f };
|
||||||
if (mesh.mTextureCoords[0])
|
if (mesh.mTextureCoords[0])
|
||||||
{
|
{
|
||||||
texCoord.x = mesh.mTextureCoords[0][i].x;
|
texCoord.x = mesh.mTextureCoords[0][i].x;
|
||||||
|
@ -76,7 +82,7 @@ namespace SHADE
|
||||||
result->texCoords.push_back(texCoord);
|
result->texCoords.push_back(texCoord);
|
||||||
|
|
||||||
// Normals
|
// Normals
|
||||||
SHVec3 normal{0.f, 0.f, 0.f};
|
SHVec3 normal{ 0.f, 0.f, 0.f };
|
||||||
if (mesh.mNormals)
|
if (mesh.mNormals)
|
||||||
{
|
{
|
||||||
normal.x = mesh.mNormals[i].x;
|
normal.x = mesh.mNormals[i].x;
|
||||||
|
@ -86,7 +92,7 @@ namespace SHADE
|
||||||
result->vertexNormal.push_back(normal);
|
result->vertexNormal.push_back(normal);
|
||||||
|
|
||||||
// Tangent
|
// Tangent
|
||||||
SHVec3 tangent{0.f, 0.f, 0.f};
|
SHVec3 tangent{ 0.f, 0.f, 0.f };
|
||||||
if (mesh.mTangents)
|
if (mesh.mTangents)
|
||||||
{
|
{
|
||||||
tangent.x = mesh.mTangents[i].x;
|
tangent.x = mesh.mTangents[i].x;
|
||||||
|
@ -96,10 +102,10 @@ namespace SHADE
|
||||||
result->vertexTangent.push_back(tangent);
|
result->vertexTangent.push_back(tangent);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i {0}; i < mesh.mNumFaces; ++i)
|
for (size_t i{ 0 }; i < mesh.mNumFaces; ++i)
|
||||||
{
|
{
|
||||||
aiFace face = mesh.mFaces[i];
|
aiFace face = mesh.mFaces[i];
|
||||||
for (size_t j{0}; j < face.mNumIndices; ++j)
|
for (size_t j{ 0 }; j < face.mNumIndices; ++j)
|
||||||
{
|
{
|
||||||
result->indices.push_back(face.mIndices[j]);
|
result->indices.push_back(face.mIndices[j]);
|
||||||
}
|
}
|
||||||
|
@ -110,10 +116,10 @@ namespace SHADE
|
||||||
result->header.name = mesh.mName.C_Str();
|
result->header.name = mesh.mName.C_Str();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssimpLibrary::LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept
|
void SHMeshCompiler::LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept
|
||||||
{
|
{
|
||||||
const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
|
const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
|
||||||
aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
|
aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
|
||||||
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
|
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
|
||||||
|
@ -132,10 +138,64 @@ namespace SHADE
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtractAnimations(*scene, anims);
|
//ExtractAnimations(*scene, anims);
|
||||||
|
|
||||||
ProcessNode(*scene->mRootNode, *scene, meshes);
|
ProcessNode(*scene->mRootNode, *scene, meshes);
|
||||||
|
|
||||||
aiImporter.FreeScene();
|
aiImporter.FreeScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<AssetPath> SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept
|
||||||
|
{
|
||||||
|
std::string newPath{ path.parent_path().string() + '/' };
|
||||||
|
newPath += asset.header.name + MESH_EXTENSION.data();
|
||||||
|
|
||||||
|
std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc };
|
||||||
|
if (!file.is_open())
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Unable to open file for writing mesh file: {}", path.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&(asset.header.vertexCount)),
|
||||||
|
sizeof(uint32_t)
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<const char*>(&(asset.header.indexCount)),
|
||||||
|
sizeof(uint32_t)
|
||||||
|
);
|
||||||
|
|
||||||
|
auto const vertexVec3Byte{ sizeof(SHVec3) * asset.header.vertexCount };
|
||||||
|
auto const vertexVec2Byte{ sizeof(SHVec2) * asset.header.vertexCount };
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.vertexPosition.data()),
|
||||||
|
vertexVec3Byte
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.vertexTangent.data()),
|
||||||
|
vertexVec3Byte
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.vertexNormal.data()),
|
||||||
|
vertexVec3Byte
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.texCoords.data()),
|
||||||
|
vertexVec2Byte
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.indices.data()),
|
||||||
|
sizeof(uint32_t) * asset.header.indexCount
|
||||||
|
);
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
return newPath;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHMeshCompiler.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 30 September 2022
|
||||||
|
* \brief Library to write data in SHMeshAsset into binary file for faster
|
||||||
|
* loading in the future
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <assimp/Importer.hpp>
|
||||||
|
#include <assimp/scene.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Assets/Asset Types/SHAnimationAsset.h"
|
||||||
|
#include "Assets/Asset Types/SHMeshAsset.h"
|
||||||
|
#include "Assets/SHAssetMacros.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHMeshCompiler
|
||||||
|
{
|
||||||
|
|
||||||
|
using MeshVectorRef = std::vector<SHMeshAsset*>&;
|
||||||
|
using AnimVectorRef = std::vector<SHAnimationAsset*>&;
|
||||||
|
|
||||||
|
static Assimp::Importer aiImporter;
|
||||||
|
static void ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept;
|
||||||
|
static void ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept;
|
||||||
|
static SHMeshAsset* ProcessMesh(aiMesh const& mesh) noexcept;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept;
|
||||||
|
static std::optional<AssetPath> CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,162 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHShaderSourceCompiler.cpp
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 23 10 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHShaderSourceCompiler.h"
|
||||||
|
#include "shaderc/shaderc.hpp"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
std::string SHShaderSourceCompiler::CompileShaderSourceToBinary(AssetPath path, SHShaderAsset const& data) noexcept
|
||||||
|
{
|
||||||
|
std::string newPath{ path.string() };
|
||||||
|
newPath = newPath.substr(0, newPath.find_last_of('.'));
|
||||||
|
newPath += SHADER_BUILT_IN_EXTENSION.data();
|
||||||
|
|
||||||
|
std::ofstream file{ newPath, std::ios::binary | std::ios::out | std::ios::trunc };
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(& data.shaderType), sizeof(uint8_t)
|
||||||
|
);
|
||||||
|
|
||||||
|
size_t const byteCount = sizeof(uint32_t) * data.spirvBinary.size();
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&byteCount), sizeof(size_t)
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(data.spirvBinary.data()), byteCount
|
||||||
|
);
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
return newPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHShaderAsset const* SHShaderSourceCompiler::CompileShaderSourceToMemory(std::string const& data, std::string const& name, SH_SHADER_TYPE type) noexcept
|
||||||
|
{
|
||||||
|
// shaderc compiler
|
||||||
|
shaderc::Compiler compiler;
|
||||||
|
shaderc::CompileOptions options;
|
||||||
|
|
||||||
|
options.AddMacroDefinition("MY_DEFINE", "1");
|
||||||
|
|
||||||
|
//TODO: Check if we need optimisation levels when compiling into spirv
|
||||||
|
// Set optimization levels
|
||||||
|
//if (opLevel != shaderc_optimization_level_zero)
|
||||||
|
// options.SetOptimizationLevel(opLevel);
|
||||||
|
|
||||||
|
// Attempt to get the shaderc equivalent shader stage
|
||||||
|
shaderc_shader_kind shaderKind;
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case SH_SHADER_TYPE::VERTEX:
|
||||||
|
shaderKind = shaderc_shader_kind::shaderc_glsl_vertex_shader;
|
||||||
|
break;
|
||||||
|
case SH_SHADER_TYPE::FRAGMENT:
|
||||||
|
shaderKind = shaderc_shader_kind::shaderc_glsl_fragment_shader;
|
||||||
|
break;
|
||||||
|
case SH_SHADER_TYPE::COMPUTE:
|
||||||
|
shaderKind = shaderc_shader_kind::shaderc_glsl_compute_shader;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
shaderKind = shaderc_shader_kind::shaderc_glsl_vertex_shader;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile the shader and get the result
|
||||||
|
shaderc::SpvCompilationResult compileResult = compiler.CompileGlslToSpv(data, shaderKind, name.c_str(), options);
|
||||||
|
|
||||||
|
if (compileResult.GetCompilationStatus() != shaderc_compilation_status_success)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Shaderc failed to compile GLSL shader to binary | " + compileResult.GetErrorMessage());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = new SHShaderAsset();
|
||||||
|
result->spirvBinary.resize(compileResult.end() - compileResult.begin());
|
||||||
|
|
||||||
|
std::ranges::copy(compileResult.begin(), compileResult.end(), result->spirvBinary.data());
|
||||||
|
|
||||||
|
result->name = name;
|
||||||
|
result->shaderType = type;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SH_SHADER_TYPE SHShaderSourceCompiler::GetShaderTypeFromFilename(std::string name) noexcept
|
||||||
|
{
|
||||||
|
for (auto i { 0}; i < SHADER_TYPE_MAX_COUNT; ++i)
|
||||||
|
{
|
||||||
|
if (name.find(SHADER_IDENTIFIERS[i].data()) != std::string::npos)
|
||||||
|
{
|
||||||
|
return static_cast<SH_SHADER_TYPE>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SH_SHADER_TYPE::INAVLID_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<AssetPath> SHShaderSourceCompiler::LoadAndCompileShader(AssetPath path) noexcept
|
||||||
|
{
|
||||||
|
auto type = GetShaderTypeFromFilename(path.filename().string());
|
||||||
|
|
||||||
|
if (type == SH_SHADER_TYPE::INAVLID_TYPE)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Invalid filename for shaders, follow suffix in SHAssetMacros.h: {}", path.string());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
path.make_preferred();
|
||||||
|
|
||||||
|
std::ifstream file{ path.string(), std::ios::in };
|
||||||
|
|
||||||
|
if (file.is_open())
|
||||||
|
{
|
||||||
|
std::stringstream stream;
|
||||||
|
|
||||||
|
stream << file.rdbuf();
|
||||||
|
|
||||||
|
std::string const content = stream.str();
|
||||||
|
|
||||||
|
auto data = CompileShaderSourceToMemory(content, path.filename().string(), type);
|
||||||
|
|
||||||
|
if (data == nullptr)
|
||||||
|
{
|
||||||
|
return{};
|
||||||
|
}
|
||||||
|
|
||||||
|
return CompileShaderSourceToBinary(path, *data);
|
||||||
|
}
|
||||||
|
|
||||||
|
SHLOG_ERROR("Unable to open shader file: {}", path.string());
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<AssetPath> SHShaderSourceCompiler::CompileShaderFromString
|
||||||
|
(std::string const& string, AssetPath path, SH_SHADER_TYPE type) noexcept
|
||||||
|
{
|
||||||
|
auto const data = CompileShaderSourceToMemory(string, path.filename().string(), type);
|
||||||
|
|
||||||
|
if (data == nullptr)
|
||||||
|
{
|
||||||
|
return{};
|
||||||
|
}
|
||||||
|
|
||||||
|
return CompileShaderSourceToBinary(path, *data);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHShaderSourceCompiler.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 23 10 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Assets/SHAssetMacros.h"
|
||||||
|
#include "Assets/Asset Types/SHShaderAsset.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHShaderSourceCompiler
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static std::string CompileShaderSourceToBinary(AssetPath path, SHShaderAsset const& data) noexcept;
|
||||||
|
static SHShaderAsset const* CompileShaderSourceToMemory(std::string const& data, std::string const& name, SH_SHADER_TYPE type) noexcept;
|
||||||
|
|
||||||
|
static SH_SHADER_TYPE GetShaderTypeFromFilename(std::string name) noexcept;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static std::optional<AssetPath> LoadAndCompileShader(AssetPath path) noexcept;
|
||||||
|
static std::optional<AssetPath> CompileShaderFromString
|
||||||
|
(std::string const& string, AssetPath path, SH_SHADER_TYPE type) noexcept;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,171 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHTextureCompiler.cpp
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 30 September 2022
|
||||||
|
* \brief Library to write data in SHTextureAsset into binary file for
|
||||||
|
* faster loading in the future
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHTextureCompiler.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
|
||||||
|
std::string SHTextureCompiler::TinyDDSResultToString(tinyddsloader::Result value)
|
||||||
|
{
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case tinyddsloader::Result::ErrorFileOpen:
|
||||||
|
return "File open err";
|
||||||
|
case tinyddsloader::Result::ErrorRead:
|
||||||
|
return "File read err";
|
||||||
|
case tinyddsloader::Result::ErrorMagicWord:
|
||||||
|
return "File header magic word err";
|
||||||
|
case tinyddsloader::Result::ErrorSize:
|
||||||
|
return "File size err";
|
||||||
|
case tinyddsloader::Result::ErrorVerify:
|
||||||
|
return "Pixel format err";
|
||||||
|
case tinyddsloader::Result::ErrorNotSupported:
|
||||||
|
return "Unsupported format";
|
||||||
|
case tinyddsloader::Result::ErrorInvalidData:
|
||||||
|
return "Invalid data";
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::Format SHTextureCompiler::ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm:
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm_SRGB:
|
||||||
|
return isLinear ? vk::Format::eBc1RgbaUnormBlock : vk::Format::eBc1RgbaSrgbBlock;
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm:
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm_SRGB:
|
||||||
|
return isLinear ? vk::Format::eBc2UnormBlock : vk::Format::eBc2SrgbBlock;
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm:
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm_SRGB:
|
||||||
|
return isLinear ? vk::Format::eBc3UnormBlock : vk::Format::eBc3SrgbBlock;
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::BC5_UNorm:
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::BC5_SNorm:
|
||||||
|
return isLinear ? vk::Format::eBc5UnormBlock : vk::Format::eBc5SnormBlock;
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm:
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm_SRGB:
|
||||||
|
return isLinear ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR8G8B8A8Srgb;
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_SNorm:
|
||||||
|
return vk::Format::eR8G8B8A8Snorm;
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm:
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm_SRGB:
|
||||||
|
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8A8Srgb;
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm:
|
||||||
|
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm_SRGB:
|
||||||
|
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8Srgb;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("Unsupported DDS format.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHTextureCompiler::LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept
|
||||||
|
{
|
||||||
|
tinyddsloader::Result loadResult = tinyddsloader::Result::Success;
|
||||||
|
tinyddsloader::DDSFile file;
|
||||||
|
loadResult = file.Load(path.string().c_str());
|
||||||
|
if (loadResult != tinyddsloader::Result::Success)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Unable to load Texture file: {} at {}", TinyDDSResultToString(loadResult), path.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t totalBytes{ 0 };
|
||||||
|
|
||||||
|
std::vector<uint32_t> mipOff(file.GetMipCount());
|
||||||
|
|
||||||
|
for (size_t i{ 0 }; i < file.GetMipCount(); ++i)
|
||||||
|
{
|
||||||
|
mipOff[i] = static_cast<uint32_t>(totalBytes);
|
||||||
|
totalBytes += file.GetImageData(static_cast<uint32_t>(i), 0)->m_memSlicePitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHTexture::PixelChannel* pixel = new SHTexture::PixelChannel[totalBytes];
|
||||||
|
std::memcpy(pixel, file.GetImageData()->m_mem, totalBytes);
|
||||||
|
//pixel = std::move(reinterpret_cast<SHTexture::PixelChannel const*>(file.GetDDSData()));
|
||||||
|
|
||||||
|
asset.name = path.stem().string();
|
||||||
|
asset.compiled = false;
|
||||||
|
asset.numBytes = static_cast<uint32_t>(totalBytes);
|
||||||
|
asset.width = file.GetWidth();
|
||||||
|
asset.height = file.GetHeight();
|
||||||
|
asset.format = ddsLoaderToVkFormat(file.GetFormat(), true);
|
||||||
|
asset.mipOffsets = std::move(mipOff);
|
||||||
|
asset.pixelData = std::move(pixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SHTextureCompiler::WriteToFile(SHTextureAsset const& asset, AssetPath path) noexcept
|
||||||
|
{
|
||||||
|
std::string newPath{ path.string() };
|
||||||
|
newPath = newPath.substr(0, newPath.find_last_of('.'));
|
||||||
|
newPath += TEXTURE_EXTENSION;
|
||||||
|
|
||||||
|
std::ofstream file{ newPath, std::ios::out | std::ios::binary };
|
||||||
|
if (!file.is_open())
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Unable to open file for writing texture file: {}", path.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto intBytes{ sizeof(uint32_t) };
|
||||||
|
|
||||||
|
uint32_t const mipOffsetCount{ static_cast<uint32_t>(asset.mipOffsets.size()) };
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&asset.numBytes),
|
||||||
|
intBytes
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&asset.width),
|
||||||
|
intBytes
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&asset.height),
|
||||||
|
intBytes
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&asset.format),
|
||||||
|
sizeof(SHTexture::TextureFormat)
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&mipOffsetCount),
|
||||||
|
intBytes
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.mipOffsets.data()),
|
||||||
|
intBytes * asset.mipOffsets.size()
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.pixelData),
|
||||||
|
asset.numBytes
|
||||||
|
);
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
return newPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<AssetPath> SHTextureCompiler::CompileTextureAsset(AssetPath path)
|
||||||
|
{
|
||||||
|
auto data = new SHTextureAsset();
|
||||||
|
LoadTinyDDS(path, *data);
|
||||||
|
return WriteToFile(*data, path);
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,14 +11,23 @@
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#define TINYDDSLOADER_IMPLEMENTATION
|
||||||
|
|
||||||
#include "Assets/Asset Types/SHTextureAsset.h"
|
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||||
#include "Assets/SHAssetMacros.h"
|
#include "Assets/SHAssetMacros.h"
|
||||||
|
#include "tinyddsloader.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
struct SHTextureCompiler
|
class SHTextureCompiler
|
||||||
{
|
{
|
||||||
static std::string CompileTextureBinary(SHTextureAsset const& asset, AssetPath path);
|
private:
|
||||||
|
static std::string TinyDDSResultToString(tinyddsloader::Result value);
|
||||||
|
static vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
|
||||||
|
static void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept;
|
||||||
|
|
||||||
|
static std::string WriteToFile(SHTextureAsset const& asset, AssetPath path) noexcept;
|
||||||
|
public:
|
||||||
|
static std::optional<AssetPath> CompileTextureAsset(AssetPath path);
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -10,6 +10,7 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Assets/SHAssetMacros.h"
|
||||||
#include "Assets/Asset Types/SHAssetData.h"
|
#include "Assets/Asset Types/SHAssetData.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
|
@ -17,5 +18,6 @@ namespace SHADE
|
||||||
struct SHAssetLoader
|
struct SHAssetLoader
|
||||||
{
|
{
|
||||||
virtual SHAssetData* Load(AssetPath path) = 0;
|
virtual SHAssetData* Load(AssetPath path) = 0;
|
||||||
|
virtual void Write(SHAssetData const* data, AssetPath path) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -22,6 +22,7 @@ namespace SHADE
|
||||||
if (!file.is_open())
|
if (!file.is_open())
|
||||||
{
|
{
|
||||||
SHLOG_ERROR("Unable to open SHMesh File: {}", path.string());
|
SHLOG_ERROR("Unable to open SHMesh File: {}", path.string());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string name{ path.stem().string() };
|
const std::string name{ path.stem().string() };
|
||||||
|
@ -75,4 +76,55 @@ namespace SHADE
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHMeshLoader::Write(SHAssetData const* data, AssetPath path)
|
||||||
|
{
|
||||||
|
std::ofstream file{ path, 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto asset = *dynamic_cast<SHMeshAsset const*>(data);
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -10,15 +10,15 @@
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../SHAssetMacros.h"
|
#include "Assets/Asset Types/SHMeshAsset.h"
|
||||||
#include "../Asset Types/SHMeshAsset.h"
|
|
||||||
#include "SHAssetLoader.h"
|
#include "SHAssetLoader.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
struct SHMeshLoader : public SHAssetLoader
|
struct SHMeshLoader : SHAssetLoader
|
||||||
{
|
{
|
||||||
void LoadSHMesh(AssetPath path, SHMeshAsset& meshes) noexcept;
|
void LoadSHMesh(AssetPath path, SHMeshAsset& meshes) noexcept;
|
||||||
SHAssetData* Load(AssetPath path) override;
|
SHAssetData* Load(AssetPath path) override;
|
||||||
|
void Write(SHAssetData const* data, AssetPath path) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHShaderSourceLoader::Write(SHAssetData const* data, AssetPath path)
|
||||||
|
{
|
||||||
|
std::ofstream file{ path, std::ios::binary | std::ios::out | std::ios::trunc };
|
||||||
|
|
||||||
|
auto asset = *dynamic_cast<SHShaderAsset const*>(data);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&asset.shaderType), sizeof(uint8_t)
|
||||||
|
);
|
||||||
|
|
||||||
|
size_t const byteCount = sizeof(uint32_t) * asset.spirvBinary.size();
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&byteCount), sizeof(size_t)
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.spirvBinary.data()), byteCount
|
||||||
|
);
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*************************************************************************//**
|
/*************************************************************************//**
|
||||||
* \file SHAnimationAsset.h
|
* \file SHShaderSourceLoader.h
|
||||||
* \author Loh Xiao Qi
|
* \author Loh Xiao Qi
|
||||||
* \date October 2022
|
* \date 23 10 2022
|
||||||
* \brief
|
* \brief
|
||||||
*
|
*
|
||||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
@ -10,21 +10,13 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include "Assets/Libraries/Loaders/SHAssetLoader.h"
|
||||||
#include <assimp/anim.h>
|
|
||||||
#include "SH_API.power h"
|
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
struct SH_API SHAnimationAsset
|
struct SHShaderSourceLoader : SHAssetLoader
|
||||||
{
|
{
|
||||||
std::string name;
|
SHAssetData* Load(AssetPath path) override;
|
||||||
|
void Write(SHAssetData const* data, AssetPath path) override;
|
||||||
std::vector<aiNodeAnim*> nodeChannels;
|
|
||||||
std::vector<aiMeshAnim*> meshChannels;
|
|
||||||
std::vector<aiMeshMorphAnim*> morphMeshChannels;
|
|
||||||
|
|
||||||
double duration;
|
|
||||||
double ticksPerSecond;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* \file SHTextBasedLoader.cpp
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 28 October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* \copyright Copyright (c) 2021 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 "SHTextBasedLoader.h"
|
||||||
|
|
||||||
|
#include "Assets/Asset Types/SHSceneAsset.h"
|
||||||
|
#include "Assets/Asset Types/SHPrefabAsset.h"
|
||||||
|
#include "Assets/Asset Types/SHMaterialAsset.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
SHAssetData* SHTextBasedLoader::Load(AssetPath path)
|
||||||
|
{
|
||||||
|
std::ifstream file{ path, std::ios::in };
|
||||||
|
|
||||||
|
if (!file.is_open())
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Unable to open text File: {}", path.string());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
std::stringstream stream;
|
||||||
|
|
||||||
|
stream << file.rdbuf();
|
||||||
|
|
||||||
|
std::string content = stream.str();
|
||||||
|
|
||||||
|
SHAssetData* result;
|
||||||
|
|
||||||
|
if (path.extension().string() == SCENE_EXTENSION)
|
||||||
|
{
|
||||||
|
auto data = new SHSceneAsset();
|
||||||
|
data->name = path.stem().string();
|
||||||
|
data->data = std::move(content);
|
||||||
|
result = data;
|
||||||
|
}
|
||||||
|
else if (path.extension().string() == PREFAB_EXTENSION)
|
||||||
|
{
|
||||||
|
auto data = new SHPrefabAsset();
|
||||||
|
data->name = path.stem().string();
|
||||||
|
data->data = std::move(content);
|
||||||
|
result = data;
|
||||||
|
}
|
||||||
|
else if (path.extension().string() == MATERIAL_EXTENSION)
|
||||||
|
{
|
||||||
|
auto data = new SHMaterialAsset();
|
||||||
|
data->name = path.stem().string();
|
||||||
|
data->data = std::move(content);
|
||||||
|
result = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHTextBasedLoader::Write(SHAssetData const* data, AssetPath path)
|
||||||
|
{
|
||||||
|
std::ofstream file{ path, std::ios::out | std::ios::trunc };
|
||||||
|
|
||||||
|
if (!file.is_open())
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Unable to open text File: {}", path.string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.extension().string() == SCENE_EXTENSION)
|
||||||
|
{
|
||||||
|
auto scene = dynamic_cast<SHSceneAsset const*>(data);
|
||||||
|
file << scene->data;
|
||||||
|
}
|
||||||
|
else if (path.extension().string() == PREFAB_EXTENSION)
|
||||||
|
{
|
||||||
|
auto prefab = dynamic_cast<SHPrefabAsset const*>(data);
|
||||||
|
file << prefab->data;
|
||||||
|
}
|
||||||
|
else if (path.extension().string() == MATERIAL_EXTENSION)
|
||||||
|
{
|
||||||
|
auto material = dynamic_cast<SHMaterialAsset const*>(data);
|
||||||
|
file << material->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* \file Header.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 28 October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* \copyright Copyright (c) 2021 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 "SHAssetLoader.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SHTextBasedLoader : SHAssetLoader
|
||||||
|
{
|
||||||
|
SHAssetData* Load(AssetPath path) override;
|
||||||
|
void Write(SHAssetData const* data, AssetPath path) override;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHTextureLoader::Write(SHAssetData const* data, AssetPath path)
|
||||||
|
{
|
||||||
|
std::ofstream file{ path, std::ios::out | std::ios::binary };
|
||||||
|
if (!file.is_open())
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Unable to open file for writing texture file: {}", path.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto asset = *dynamic_cast<SHTextureAsset const*>(data);
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,25 +10,15 @@
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
#define TINYDDSLOADER_IMPLEMENTATION
|
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||||
|
|
||||||
#include "../SHAssetMacros.h"
|
|
||||||
#include "../Asset Types/SHTextureAsset.h"
|
|
||||||
#include "tinyddsloader.h"
|
|
||||||
#include "SHAssetLoader.h"
|
#include "SHAssetLoader.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
class SHTextureLoader : public SHAssetLoader
|
class SHTextureLoader : public SHAssetLoader
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
std::string TinyDDSResultToString(tinyddsloader::Result value);
|
|
||||||
vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
|
|
||||||
|
|
||||||
void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept;
|
|
||||||
public:
|
|
||||||
void LoadImageAsset(AssetPath paths, SHTextureAsset& image);
|
|
||||||
void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
|
void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
|
||||||
SHAssetData* Load(AssetPath path) override;
|
SHAssetData* Load(AssetPath path) override;
|
||||||
|
void Write(SHAssetData const* data, AssetPath path) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -1,36 +0,0 @@
|
||||||
/*************************************************************************//**
|
|
||||||
* \file SHAssimpLibrary.h
|
|
||||||
* \author Loh Xiao Qi
|
|
||||||
* \date October 2022
|
|
||||||
* \brief
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
|
||||||
* disclosure of this file or its contents without the prior written consent
|
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include <assimp/Importer.hpp>
|
|
||||||
#include <assimp/scene.h>
|
|
||||||
#include <vector>
|
|
||||||
#include "../SHAssetMacros.h"
|
|
||||||
#include "../Asset Types/SHMeshAsset.h"
|
|
||||||
#include "../Asset Types/SHAnimationAsset.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
class SHAssimpLibrary
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
using MeshVectorRef = std::vector<SHMeshAsset*>&;
|
|
||||||
using AnimVectorRef = std::vector<SHAnimationAsset*>&;
|
|
||||||
|
|
||||||
static Assimp::Importer aiImporter;
|
|
||||||
static void ProcessNode(aiNode const& node, aiScene const& scene,MeshVectorRef meshes) noexcept;
|
|
||||||
static void ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept;
|
|
||||||
static SHMeshAsset* ProcessMesh(aiMesh const& mesh) noexcept;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static void LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*************************************************************************//**
|
|
||||||
* \file SHMeshCompiler.cpp
|
|
||||||
* \author Loh Xiao Qi
|
|
||||||
* \date 30 September 2022
|
|
||||||
* \brief Library to write data in SHMeshAsset into binary file for faster
|
|
||||||
* loading in the future
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
|
||||||
* disclosure of this file or its contents without the prior written consent
|
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
|
||||||
*****************************************************************************/
|
|
||||||
#include "SHpch.h"
|
|
||||||
#include "SHMeshCompiler.h"
|
|
||||||
#include "Graphics/MiddleEnd/Meshes/SHMeshData.h"
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
std::string SHADE::SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept
|
|
||||||
{
|
|
||||||
std::string newPath{ path.string() };
|
|
||||||
newPath = newPath.substr(0, newPath.find_last_of('/') + 1);
|
|
||||||
newPath += asset.header.name + MESH_EXTENSION.data();
|
|
||||||
|
|
||||||
std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc };
|
|
||||||
if (!file.is_open())
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Unable to open file for writing mesh file: {}", path.string());
|
|
||||||
}
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&(asset.header.vertexCount)),
|
|
||||||
sizeof(uint32_t)
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<const char*>(&(asset.header.indexCount)),
|
|
||||||
sizeof(uint32_t)
|
|
||||||
);
|
|
||||||
|
|
||||||
auto const vertexVec3Byte {sizeof(SHVec3) * asset.header.vertexCount};
|
|
||||||
auto const vertexVec2Byte {sizeof(SHVec2) * asset.header.vertexCount};
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.vertexPosition.data()),
|
|
||||||
vertexVec3Byte
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.vertexTangent.data()),
|
|
||||||
vertexVec3Byte
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.vertexNormal.data()),
|
|
||||||
vertexVec3Byte
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.texCoords.data()),
|
|
||||||
vertexVec2Byte
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.indices.data()),
|
|
||||||
sizeof(uint32_t) * asset.header.indexCount
|
|
||||||
);
|
|
||||||
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
return newPath;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*************************************************************************//**
|
|
||||||
* \file SHMeshCompiler.h
|
|
||||||
* \author Loh Xiao Qi
|
|
||||||
* \date 30 September 2022
|
|
||||||
* \brief Library to write data in SHMeshAsset into binary file for faster
|
|
||||||
* loading in the future
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
|
||||||
* disclosure of this file or its contents without the prior written consent
|
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
|
||||||
*****************************************************************************/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../Asset Types/SHMeshAsset.h"
|
|
||||||
#include "../SHAssetMacros.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
class SHMeshCompiler
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
public:
|
|
||||||
static std::string CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
/*************************************************************************//**
|
|
||||||
* \file SHTextureCompiler.cpp
|
|
||||||
* \author Loh Xiao Qi
|
|
||||||
* \date 30 September 2022
|
|
||||||
* \brief Library to write data in SHTextureAsset into binary file for
|
|
||||||
* faster loading in the future
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
|
||||||
* disclosure of this file or its contents without the prior written consent
|
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
|
||||||
*****************************************************************************/
|
|
||||||
#include "SHpch.h"
|
|
||||||
#include "SHTextureCompiler.h"
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
std::string SHTextureCompiler::CompileTextureBinary(SHTextureAsset const& asset, AssetPath path)
|
|
||||||
{
|
|
||||||
std::string newPath{ path.string() };
|
|
||||||
newPath = newPath.substr(0, newPath.find_last_of('.'));
|
|
||||||
newPath += TEXTURE_EXTENSION;
|
|
||||||
|
|
||||||
std::ofstream file{ newPath, std::ios::out | std::ios::binary };
|
|
||||||
if (!file.is_open())
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Unable to open file for writing texture file: {}", path.string());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto const intBytes{sizeof(uint32_t)};
|
|
||||||
|
|
||||||
uint32_t mipOffsetCount{ static_cast<uint32_t>(asset.mipOffsets.size()) };
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&asset.numBytes),
|
|
||||||
intBytes
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&asset.width),
|
|
||||||
intBytes
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&asset.height),
|
|
||||||
intBytes
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&asset.format),
|
|
||||||
sizeof(SHTexture::TextureFormat)
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&mipOffsetCount),
|
|
||||||
intBytes
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.mipOffsets.data()),
|
|
||||||
intBytes * asset.mipOffsets.size()
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.pixelData),
|
|
||||||
asset.numBytes
|
|
||||||
);
|
|
||||||
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
return newPath;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,156 +0,0 @@
|
||||||
/*************************************************************************//**
|
|
||||||
* \file SHTextureLoader.cpp
|
|
||||||
* \author Loh Xiao Qi
|
|
||||||
* \date 30 September 2022
|
|
||||||
* \brief Library to load dds textures and custom binary format
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
|
||||||
* disclosure of this file or its contents without the prior written consent
|
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
|
||||||
*****************************************************************************/
|
|
||||||
#include "SHpch.h"
|
|
||||||
#include "SHTextureLoader.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
std::string SHTextureLoader::TinyDDSResultToString(tinyddsloader::Result value)
|
|
||||||
{
|
|
||||||
switch (value)
|
|
||||||
{
|
|
||||||
case tinyddsloader::Result::ErrorFileOpen:
|
|
||||||
return "File open err";
|
|
||||||
case tinyddsloader::Result::ErrorRead:
|
|
||||||
return "File read err";
|
|
||||||
case tinyddsloader::Result::ErrorMagicWord:
|
|
||||||
return "File header magic word err";
|
|
||||||
case tinyddsloader::Result::ErrorSize:
|
|
||||||
return "File size err";
|
|
||||||
case tinyddsloader::Result::ErrorVerify:
|
|
||||||
return "Pixel format err";
|
|
||||||
case tinyddsloader::Result::ErrorNotSupported:
|
|
||||||
return "Unsupported format";
|
|
||||||
case tinyddsloader::Result::ErrorInvalidData:
|
|
||||||
return "Invalid data";
|
|
||||||
default:
|
|
||||||
return "Unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vk::Format SHTextureLoader::ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear)
|
|
||||||
{
|
|
||||||
switch (format)
|
|
||||||
{
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm:
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm_SRGB:
|
|
||||||
return isLinear ? vk::Format::eBc1RgbaUnormBlock : vk::Format::eBc1RgbaSrgbBlock;
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm:
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm_SRGB:
|
|
||||||
return isLinear ? vk::Format::eBc2UnormBlock : vk::Format::eBc2SrgbBlock;
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm:
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm_SRGB:
|
|
||||||
return isLinear ? vk::Format::eBc3UnormBlock : vk::Format::eBc3SrgbBlock;
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::BC5_UNorm:
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::BC5_SNorm:
|
|
||||||
return isLinear ? vk::Format::eBc5UnormBlock : vk::Format::eBc5SnormBlock;
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm:
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm_SRGB:
|
|
||||||
return isLinear ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR8G8B8A8Srgb;
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_SNorm:
|
|
||||||
return vk::Format::eR8G8B8A8Snorm;
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm:
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm_SRGB:
|
|
||||||
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8A8Srgb;
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm:
|
|
||||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm_SRGB:
|
|
||||||
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8Srgb;
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Unsupported DDS format.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHTextureLoader::LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept
|
|
||||||
{
|
|
||||||
tinyddsloader::Result loadResult = tinyddsloader::Result::Success;
|
|
||||||
tinyddsloader::DDSFile file;
|
|
||||||
loadResult = file.Load(path.string().c_str());
|
|
||||||
if (loadResult != tinyddsloader::Result::Success)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Unable to load Texture file: {} at {}", TinyDDSResultToString(loadResult), path.string());
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t totalBytes{ 0 };
|
|
||||||
|
|
||||||
std::vector<uint32_t> mipOff(file.GetMipCount());
|
|
||||||
|
|
||||||
for (size_t i{0}; i < file.GetMipCount(); ++i)
|
|
||||||
{
|
|
||||||
mipOff[i] = static_cast<uint32_t>(totalBytes);
|
|
||||||
totalBytes += file.GetImageData(static_cast<uint32_t>(i), 0)->m_memSlicePitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHTexture::PixelChannel* pixel = new SHTexture::PixelChannel[totalBytes];
|
|
||||||
std::memcpy(pixel, file.GetImageData()->m_mem, totalBytes);
|
|
||||||
//pixel = std::move(reinterpret_cast<SHTexture::PixelChannel const*>(file.GetDDSData()));
|
|
||||||
|
|
||||||
asset.name = path.stem().string();
|
|
||||||
asset.compiled = false;
|
|
||||||
asset.numBytes = static_cast<uint32_t>(totalBytes);
|
|
||||||
asset.width = file.GetWidth();
|
|
||||||
asset.height = file.GetHeight();
|
|
||||||
asset.format = ddsLoaderToVkFormat(file.GetFormat(), true);
|
|
||||||
asset.mipOffsets = std::move(mipOff);
|
|
||||||
asset.pixelData = std::move(pixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHTextureLoader::LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept
|
|
||||||
{
|
|
||||||
std::ifstream file{path.string(), std::ios::in | std::ios::binary};
|
|
||||||
if (!file.is_open())
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Error opening SHTexture file: {}", path.string());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto const intBytes{ sizeof(uint32_t) };
|
|
||||||
uint32_t mipCount;
|
|
||||||
|
|
||||||
file.read(reinterpret_cast<char*>(&asset.numBytes), intBytes);
|
|
||||||
file.read(reinterpret_cast<char*>(&asset.width), intBytes);
|
|
||||||
file.read(reinterpret_cast<char*>(&asset.height), intBytes);
|
|
||||||
file.read(reinterpret_cast<char*>(&asset.format), sizeof(SHTexture::TextureFormat));
|
|
||||||
|
|
||||||
file.read(reinterpret_cast<char*>(&mipCount), intBytes);
|
|
||||||
std::vector<uint32_t> mips(mipCount);
|
|
||||||
file.read(reinterpret_cast<char*>(mips.data()), intBytes * mipCount);
|
|
||||||
|
|
||||||
auto pixel = new SHTexture::PixelChannel[asset.numBytes];
|
|
||||||
file.read(reinterpret_cast<char*>(pixel), asset.numBytes);
|
|
||||||
|
|
||||||
asset.mipOffsets = std::move(mips);
|
|
||||||
asset.pixelData = std::move( pixel );
|
|
||||||
|
|
||||||
asset.compiled = true;
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
SHAssetData* SHTextureLoader::Load(AssetPath path)
|
|
||||||
{
|
|
||||||
auto result = new SHTextureAsset();
|
|
||||||
|
|
||||||
LoadImageAsset(path, *result);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHTextureLoader::LoadImageAsset(AssetPath path, SHTextureAsset& asset)
|
|
||||||
{
|
|
||||||
if (path.extension().string() == DDS_EXTENSION)
|
|
||||||
{
|
|
||||||
LoadTinyDDS(path, asset);
|
|
||||||
}
|
|
||||||
else if (path.extension().string() == TEXTURE_EXTENSION)
|
|
||||||
{
|
|
||||||
LoadSHTexture(path, asset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,7 +11,6 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Filesystem/SHFileSystem.h"
|
|
||||||
#include "Assets/SHAssetMacros.h"
|
#include "Assets/SHAssetMacros.h"
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
|
|
||||||
|
@ -23,6 +22,5 @@ namespace SHADE
|
||||||
AssetID id;
|
AssetID id;
|
||||||
AssetType type;
|
AssetType type;
|
||||||
AssetPath path;
|
AssetPath path;
|
||||||
FolderLocation location;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -42,62 +42,84 @@ constexpr std::string_view ASSET_META_VER { "1.0" };
|
||||||
// Asset type enum
|
// Asset type enum
|
||||||
enum class AssetType : AssetTypeMeta
|
enum class AssetType : AssetTypeMeta
|
||||||
{
|
{
|
||||||
INVALID = 0,
|
INVALID,
|
||||||
AUDIO = 1,
|
|
||||||
SHADER,
|
SHADER,
|
||||||
MATERIAL,
|
SHADER_BUILT_IN,
|
||||||
IMAGE,
|
TEXTURE,
|
||||||
TEXTURE,
|
MESH,
|
||||||
MESH,
|
SCENE,
|
||||||
SCRIPT,
|
PREFAB,
|
||||||
SCENE,
|
MATERIAL,
|
||||||
PREFAB,
|
|
||||||
AUDIO_WAV,
|
|
||||||
DDS,
|
|
||||||
MAX_COUNT
|
MAX_COUNT
|
||||||
};
|
};
|
||||||
|
constexpr size_t TYPE_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) };
|
||||||
|
|
||||||
//Directory
|
//Directory
|
||||||
#ifdef _PUBLISH
|
#ifdef _PUBLISH
|
||||||
constexpr std::string_view ASSET_ROOT {"Assets"};
|
constexpr std::string_view ASSET_ROOT{ "Assets" };
|
||||||
|
constexpr std::string_view BUILT_IN_ASSET_ROOT {"Built_In"};
|
||||||
#else
|
#else
|
||||||
constexpr std::string_view ASSET_ROOT {"../../Assets"};
|
constexpr std::string_view ASSET_ROOT {"../../Assets"};
|
||||||
|
constexpr std::string_view BUILT_IN_ASSET_ROOT{ "../../Built_In" };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// INTERNAL ASSET PATHS
|
||||||
|
constexpr std::string_view SCENE_FOLDER{ "/Scenes/" };
|
||||||
|
constexpr std::string_view PREFAB_FOLDER{ "/Prefabs/" };
|
||||||
|
constexpr std::string_view MATERIAL_FOLDER{ "/Materials/" };
|
||||||
|
|
||||||
|
|
||||||
// ASSET EXTENSIONS
|
// ASSET EXTENSIONS
|
||||||
constexpr std::string_view META_EXTENSION {".shmeta"};
|
constexpr std::string_view META_EXTENSION {".shmeta"};
|
||||||
constexpr std::string_view IMAGE_EXTENSION {".png"};
|
|
||||||
constexpr std::string_view AUDIO_EXTENSION {".ogg"};
|
constexpr std::string_view AUDIO_EXTENSION {".ogg"};
|
||||||
constexpr std::string_view AUDIO_WAV_EXTENSION {".wav"};
|
constexpr std::string_view AUDIO_WAV_EXTENSION {".wav"};
|
||||||
constexpr std::string_view SHADER_EXTENSION {".glsl"};
|
constexpr std::string_view SHADER_EXTENSION{ ".shshader" };
|
||||||
|
constexpr std::string_view SHADER_BUILT_IN_EXTENSION{".shshaderb"};
|
||||||
constexpr std::string_view SCRIPT_EXTENSION {".cs"};
|
constexpr std::string_view SCRIPT_EXTENSION {".cs"};
|
||||||
constexpr std::string_view SCENE_EXTENSION {".SHADE"};
|
constexpr std::string_view SCENE_EXTENSION {".shade"};
|
||||||
constexpr std::string_view PREFAB_EXTENSION {".SHPrefab"};
|
constexpr std::string_view PREFAB_EXTENSION {".shprefab"};
|
||||||
constexpr std::string_view MATERIAL_EXTENSION {".SHMat"};
|
constexpr std::string_view MATERIAL_EXTENSION {".shmat"};
|
||||||
constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
|
constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
|
||||||
constexpr std::string_view DDS_EXTENSION {".dds"};
|
|
||||||
constexpr std::string_view FBX_EXTENSION {".fbx"};
|
|
||||||
constexpr std::string_view GLTF_EXTENSION {".gltf"};
|
|
||||||
constexpr std::string_view MESH_EXTENSION {".shmesh"};
|
constexpr std::string_view MESH_EXTENSION {".shmesh"};
|
||||||
|
|
||||||
constexpr std::string_view EXTENSIONS[] = {
|
constexpr std::string_view EXTENSIONS[] = {
|
||||||
AUDIO_EXTENSION,
|
AUDIO_EXTENSION,
|
||||||
SHADER_EXTENSION,
|
SHADER_EXTENSION,
|
||||||
|
SHADER_BUILT_IN_EXTENSION,
|
||||||
MATERIAL_EXTENSION,
|
MATERIAL_EXTENSION,
|
||||||
IMAGE_EXTENSION,
|
|
||||||
TEXTURE_EXTENSION,
|
TEXTURE_EXTENSION,
|
||||||
DDS_EXTENSION,
|
|
||||||
MESH_EXTENSION,
|
MESH_EXTENSION,
|
||||||
SCRIPT_EXTENSION,
|
SCRIPT_EXTENSION,
|
||||||
SCENE_EXTENSION,
|
SCENE_EXTENSION,
|
||||||
PREFAB_EXTENSION,
|
PREFAB_EXTENSION,
|
||||||
AUDIO_WAV_EXTENSION,
|
AUDIO_WAV_EXTENSION,
|
||||||
|
};
|
||||||
|
|
||||||
|
// EXTERNAL EXTENSIONS
|
||||||
|
constexpr std::string_view GLSL_EXTENSION{ ".glsl" };
|
||||||
|
constexpr std::string_view DDS_EXTENSION{ ".dds" };
|
||||||
|
constexpr std::string_view FBX_EXTENSION{ ".fbx" };
|
||||||
|
constexpr std::string_view GLTF_EXTENSION{ ".gltf" };
|
||||||
|
|
||||||
|
constexpr std::string_view EXTERNALS[] = {
|
||||||
|
GLSL_EXTENSION,
|
||||||
|
DDS_EXTENSION,
|
||||||
FBX_EXTENSION,
|
FBX_EXTENSION,
|
||||||
GLTF_EXTENSION
|
GLTF_EXTENSION
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr size_t TYPE_COUNT {static_cast<size_t>(AssetType::MAX_COUNT) };
|
// SHADER IDENTIFIERS
|
||||||
|
constexpr std::string_view VERTEX_SHADER{ "_VS" };
|
||||||
|
constexpr std::string_view FRAGMENT_SHADER{ "_FS" };
|
||||||
|
constexpr std::string_view COMPUTER_SHADER{ "_CS" };
|
||||||
|
|
||||||
|
constexpr std::string_view SHADER_IDENTIFIERS[] = {
|
||||||
|
VERTEX_SHADER,
|
||||||
|
FRAGMENT_SHADER,
|
||||||
|
COMPUTER_SHADER
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr size_t SHADER_TYPE_MAX_COUNT{ 3 };
|
||||||
|
|
||||||
// Error flags
|
// Error flags
|
||||||
constexpr std::string_view FILE_NOT_FOUND_ERR {"FILE NOT FOUND"};
|
constexpr std::string_view FILE_NOT_FOUND_ERR {"FILE NOT FOUND"};
|
||||||
|
|
|
@ -10,26 +10,33 @@
|
||||||
#include "SHpch.h"
|
#include "SHpch.h"
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <ranges>
|
||||||
#include "SHAssetManager.h"
|
#include "SHAssetManager.h"
|
||||||
#include "SHAssetMetaHandler.h"
|
#include "SHAssetMetaHandler.h"
|
||||||
|
|
||||||
|
#include "Libraries/Loaders/SHMeshLoader.h"
|
||||||
|
#include "Libraries/Loaders/SHTextureLoader.h"
|
||||||
|
#include "Libraries/Loaders/SHShaderSourceLoader.h"
|
||||||
|
#include "Libraries/Loaders/SHTextBasedLoader.h"
|
||||||
|
|
||||||
|
#include "Libraries/Compilers/SHMeshCompiler.h"
|
||||||
|
#include "Libraries/Compilers/SHTextureCompiler.h"
|
||||||
|
#include "Libraries/Compilers/SHShaderSourceCompiler.h"
|
||||||
|
|
||||||
#include "Filesystem/SHFileSystem.h"
|
#include "Filesystem/SHFileSystem.h"
|
||||||
|
|
||||||
#include "Libraries/SHAssimpLibrary.h"
|
|
||||||
#include "Libraries/SHMeshLoader.h"
|
|
||||||
#include "Libraries/SHTextureLoader.h"
|
|
||||||
|
|
||||||
#include "Libraries/SHMeshCompiler.h"
|
|
||||||
#include "Libraries/SHTextureCompiler.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
FolderPointer SHAssetManager::folderRoot{ nullptr };
|
||||||
|
|
||||||
FMOD::System* SHAssetManager::audioSystem;
|
FMOD::System* SHAssetManager::audioSystem;
|
||||||
std::unordered_map<AssetID, SHSound >* SHAssetManager::audioSoundList;
|
std::unordered_map<AssetID, SHSound >* SHAssetManager::audioSoundList;
|
||||||
|
|
||||||
std::vector<SHAssetLoader*> SHAssetManager::loaders(TYPE_COUNT);
|
std::vector<SHAssetLoader*> SHAssetManager::loaders(TYPE_COUNT);
|
||||||
|
|
||||||
std::vector<SHAsset> SHAssetManager::assetCollection;
|
std::unordered_map<AssetID, SHAsset> SHAssetManager::assetCollection;
|
||||||
std::unordered_map<AssetID, SHAssetData * const> SHAssetManager::assetData;
|
std::unordered_map<AssetID, SHAssetData * const> SHAssetManager::assetData;
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Static function to generate asset ID.
|
* \brief Static function to generate asset ID.
|
||||||
|
@ -44,7 +51,7 @@ namespace SHADE
|
||||||
|
|
||||||
result |= unique;
|
result |= unique;
|
||||||
|
|
||||||
while (result == 0)
|
while (result == 0 || assetCollection.contains(result))
|
||||||
{
|
{
|
||||||
result = GenerateAssetID(type);
|
result = GenerateAssetID(type);
|
||||||
}
|
}
|
||||||
|
@ -54,17 +61,25 @@ namespace SHADE
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Deallocate all memory used by asset data
|
* \brief Deallocate all memory used by asset data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void SHAssetManager::Unload() noexcept
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHAssetManager::Unload(AssetID assetId) noexcept
|
void SHAssetManager::Unload(AssetID assetId) noexcept
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept
|
void SHAssetManager::Exit() noexcept
|
||||||
|
{
|
||||||
|
delete loaders[static_cast<size_t>(AssetType::SHADER)];
|
||||||
|
delete loaders[static_cast<size_t>(AssetType::TEXTURE)];
|
||||||
|
delete loaders[static_cast<size_t>(AssetType::MESH)];
|
||||||
|
delete loaders[static_cast<size_t>(AssetType::SCENE)];
|
||||||
|
|
||||||
|
for (auto const& data : std::ranges::views::values(assetData))
|
||||||
|
{
|
||||||
|
delete data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept
|
||||||
{
|
{
|
||||||
if (!IsRecognised(path.extension().string().c_str()))
|
if (!IsRecognised(path.extension().string().c_str()))
|
||||||
{
|
{
|
||||||
|
@ -91,16 +106,9 @@ namespace SHADE
|
||||||
|
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case AssetType::SCENE:
|
case AssetType::SHADER:
|
||||||
folder = "scenes/";
|
case AssetType::SHADER_BUILT_IN:
|
||||||
break;
|
folder = "Shaders/";
|
||||||
|
|
||||||
case AssetType::PREFAB:
|
|
||||||
folder = "prefabs/";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AssetType::MATERIAL:
|
|
||||||
folder = "materials/";
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -120,9 +128,17 @@ namespace SHADE
|
||||||
*
|
*
|
||||||
* \return const& to unordered_map<AssetName, AssetID>
|
* \return const& to unordered_map<AssetName, AssetID>
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
std::vector<SHAsset> const& SHAssetManager::GetAllAssets() noexcept
|
std::vector<SHAsset> SHAssetManager::GetAllAssets() noexcept
|
||||||
{
|
{
|
||||||
return assetCollection;
|
std::vector<SHAsset> result;
|
||||||
|
result.reserve(assetCollection.size());
|
||||||
|
|
||||||
|
for (auto const& asset : std::ranges::views::values(assetCollection))
|
||||||
|
{
|
||||||
|
result.push_back(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -135,41 +151,113 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
AssetID SHAssetManager::CreateNewAsset(AssetType type, AssetName name) noexcept
|
AssetID SHAssetManager::CreateNewAsset(AssetType type, AssetName name) noexcept
|
||||||
{
|
{
|
||||||
AssetID id{ GenerateAssetID(type) };
|
std::string newPath{ ASSET_ROOT };
|
||||||
SHAsset meta;
|
switch (type)
|
||||||
meta.id = id;
|
{
|
||||||
meta.type = type;
|
case AssetType::PREFAB:
|
||||||
|
newPath += PREFAB_FOLDER;
|
||||||
|
break;
|
||||||
|
|
||||||
std::string folder;
|
case AssetType::SCENE:
|
||||||
//TODO implement folder choosing
|
newPath += SCENE_FOLDER;
|
||||||
//switch (type)
|
break;
|
||||||
//{
|
|
||||||
//default:
|
|
||||||
// folder = "";
|
|
||||||
// break;
|
|
||||||
//}
|
|
||||||
AssetPath path{ std::string{ASSET_ROOT} + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) };
|
|
||||||
|
|
||||||
SHAssetMetaHandler::WriteMetaData(meta);
|
case AssetType::MATERIAL:
|
||||||
|
newPath += MATERIAL_FOLDER;
|
||||||
|
break;
|
||||||
|
|
||||||
assetCollection.push_back(meta);
|
default:
|
||||||
|
SHLOG_ERROR("Asset type of {} not an internal asset type, cannot be created", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto id = GenerateAssetID(type);
|
||||||
|
SHAsset asset{
|
||||||
|
name,
|
||||||
|
id,
|
||||||
|
type,
|
||||||
|
newPath
|
||||||
|
};
|
||||||
|
|
||||||
|
assetCollection.insert({
|
||||||
|
id,
|
||||||
|
SHAsset(
|
||||||
|
name,
|
||||||
|
id,
|
||||||
|
type,
|
||||||
|
newPath
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetID SHAssetManager::CreateAsset(AssetName name, AssetType type) noexcept
|
bool SHAssetManager::SaveAsset(AssetID id) noexcept
|
||||||
{
|
{
|
||||||
AssetID id = GenerateAssetID(type);
|
if (assetCollection.contains(id))
|
||||||
|
{
|
||||||
|
auto const& asset = assetCollection[id];
|
||||||
|
if (
|
||||||
|
asset.type == AssetType::SCENE ||
|
||||||
|
asset.type == AssetType::PREFAB ||
|
||||||
|
asset.type == AssetType::MATERIAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (assetData.contains(id))
|
||||||
|
{
|
||||||
|
auto const data = assetData.at(id);
|
||||||
|
loaders[static_cast<size_t>(asset.type)]->Write(data, asset.path);
|
||||||
|
SHAssetMetaHandler::WriteMetaData(asset);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHLOG_ERROR("Asset data has not been written into, cannot be saved: {}",
|
||||||
|
asset.path.filename().string());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SHLOG_WARNING("Asset id: {} not an internal asset type, save cannot be triggered", id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHAssetManager::DeleteAsset(AssetID id) noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
if (assetCollection.contains(id))
|
||||||
|
{
|
||||||
|
auto const& asset = assetCollection[id];
|
||||||
|
if (
|
||||||
|
asset.type == AssetType::SCENE ||
|
||||||
|
asset.type == AssetType::PREFAB ||
|
||||||
|
asset.type == AssetType::MATERIAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return (DeleteLocalFile(asset.path) && DeleteLocalFile(asset.path.string() + META_EXTENSION.data()));
|
||||||
|
}
|
||||||
|
SHLOG_WARNING("Asset id: {} not an internal asset type, file deletion not allowed", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
SHLOG_WARNING("Asset id does not exist, nothing was deleted: {}", id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//AssetID SHAssetManager::CreateAsset(AssetName name, AssetType type) noexcept
|
||||||
|
//{
|
||||||
|
// AssetID id = GenerateAssetID(type);
|
||||||
|
|
||||||
|
// assetCollection.emplace_back(
|
||||||
|
// name,
|
||||||
|
// id,
|
||||||
|
// type,
|
||||||
|
// GenerateNewPath(name, type)
|
||||||
|
// );
|
||||||
|
// return id;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
assetCollection.emplace_back(
|
|
||||||
name,
|
|
||||||
id,
|
|
||||||
type,
|
|
||||||
GenerateNewPath(name, type),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Import new asset from outside editor window.
|
* \brief Import new asset from outside editor window.
|
||||||
*
|
*
|
||||||
|
@ -192,7 +280,8 @@ namespace SHADE
|
||||||
|
|
||||||
std::filesystem::copy(path, newPath);
|
std::filesystem::copy(path, newPath);
|
||||||
|
|
||||||
assetCollection.push_back(CreateAssetFromPath(newPath));
|
auto asset = CreateAssetFromPath(newPath);
|
||||||
|
assetCollection.insert({asset.id, asset});
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -206,7 +295,60 @@ namespace SHADE
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHAssetManager::IsRecognised(char const* ext) noexcept
|
std::vector<SHAssetData const*> SHAssetManager::GetAllDataOfType(AssetType type) noexcept
|
||||||
|
{
|
||||||
|
auto const toRetrieve = GetAllRecordOfType(type);
|
||||||
|
std::vector<SHAssetData const*> result;
|
||||||
|
result.reserve(toRetrieve.size());
|
||||||
|
for (auto const& get : toRetrieve)
|
||||||
|
{
|
||||||
|
result.push_back(LoadData(get));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<SHAsset> SHAssetManager::GetAllRecordOfType(AssetType type) noexcept
|
||||||
|
{
|
||||||
|
std::vector<SHAsset> result;
|
||||||
|
for (auto const& asset : std::ranges::views::values(assetCollection))
|
||||||
|
{
|
||||||
|
if (asset.type == type)
|
||||||
|
{
|
||||||
|
result.push_back(asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetID SHAssetManager::CompileAsset(AssetPath const& path) noexcept
|
||||||
|
{
|
||||||
|
SHAsset newAsset
|
||||||
|
{
|
||||||
|
.name = path.stem().string()
|
||||||
|
};
|
||||||
|
|
||||||
|
auto const ext{ path.extension().string() };
|
||||||
|
if (ext == GLSL_EXTENSION.data())
|
||||||
|
{
|
||||||
|
newAsset.path = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
|
||||||
|
newAsset.id = GenerateAssetID(AssetType::SHADER_BUILT_IN);
|
||||||
|
newAsset.type = AssetType::SHADER_BUILT_IN;
|
||||||
|
}
|
||||||
|
|
||||||
|
assetCollection.insert({ newAsset.id, newAsset });
|
||||||
|
SHAssetMetaHandler::WriteMetaData(newAsset);
|
||||||
|
|
||||||
|
return newAsset.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
FolderPointer SHAssetManager::GetRootFolder() noexcept
|
||||||
|
{
|
||||||
|
return folderRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHAssetManager::IsRecognised(char const* ext) noexcept
|
||||||
{
|
{
|
||||||
for (auto const& e : EXTENSIONS)
|
for (auto const& e : EXTENSIONS)
|
||||||
{
|
{
|
||||||
|
@ -231,19 +373,84 @@ namespace SHADE
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetManager::InitLoaders() noexcept
|
void SHAssetManager::CompileAll() noexcept
|
||||||
{
|
{
|
||||||
loaders[static_cast<size_t>(AssetType::AUDIO)] = nullptr;
|
std::vector<AssetPath> paths;
|
||||||
loaders[static_cast<size_t>(AssetType::SHADER)] = nullptr;
|
|
||||||
loaders[static_cast<size_t>(AssetType::MATERIAL)] = nullptr;
|
for (auto const& dir : std::filesystem::recursive_directory_iterator{ ASSET_ROOT })
|
||||||
loaders[static_cast<size_t>(AssetType::IMAGE)] = dynamic_cast<SHAssetLoader*>(new SHTextureLoader());
|
{
|
||||||
loaders[static_cast<size_t>(AssetType::TEXTURE)] = nullptr;
|
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()
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
meshAsset.path = SHMeshCompiler::CompileMeshBinary(*mesh, path).value();
|
||||||
|
meshAsset.id = GenerateAssetID(AssetType::MESH);
|
||||||
|
meshAsset.type = AssetType::MESH;
|
||||||
|
assetCollection.insert({ meshAsset.id, meshAsset });
|
||||||
|
SHAssetMetaHandler::WriteMetaData(meshAsset);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
assetCollection.insert({ newAsset.id, newAsset });
|
||||||
|
SHAssetMetaHandler::WriteMetaData(newAsset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHAssetManager::DeleteLocalFile(AssetPath path) noexcept
|
||||||
|
{
|
||||||
|
//TODO Move this to dedicated library
|
||||||
|
return std::filesystem::remove(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetManager:: InitLoaders() noexcept
|
||||||
|
{
|
||||||
|
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());
|
loaders[static_cast<size_t>(AssetType::MESH)] = dynamic_cast<SHAssetLoader*>(new SHMeshLoader());
|
||||||
loaders[static_cast<size_t>(AssetType::SCRIPT)] = nullptr;
|
loaders[static_cast<size_t>(AssetType::SCENE)] = dynamic_cast<SHAssetLoader*>(new SHTextBasedLoader());
|
||||||
loaders[static_cast<size_t>(AssetType::SCENE)] = nullptr;
|
loaders[static_cast<size_t>(AssetType::PREFAB)] = loaders[static_cast<size_t>(AssetType::SCENE)];
|
||||||
loaders[static_cast<size_t>(AssetType::PREFAB)] = nullptr;
|
loaders[static_cast<size_t>(AssetType::MATERIAL)] = loaders[static_cast<size_t>(AssetType::SCENE)];
|
||||||
loaders[static_cast<size_t>(AssetType::AUDIO_WAV)] = nullptr;
|
|
||||||
loaders[static_cast<size_t>(AssetType::DDS)] = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -251,8 +458,9 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void SHAssetManager::Load() noexcept
|
void SHAssetManager::Load() noexcept
|
||||||
{
|
{
|
||||||
|
//CompileAll();
|
||||||
|
BuildAssetCollection();
|
||||||
InitLoaders();
|
InitLoaders();
|
||||||
BuildAssetCollection();
|
|
||||||
//LoadAllData();
|
//LoadAllData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +469,7 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void SHAssetManager::LoadAllData() noexcept
|
void SHAssetManager::LoadAllData() noexcept
|
||||||
{
|
{
|
||||||
for (auto const& asset : assetCollection)
|
for (auto const& asset : std::ranges::views::values(assetCollection))
|
||||||
{
|
{
|
||||||
SHAssetData* data = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
|
SHAssetData* data = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
|
||||||
assetData.emplace(asset.id, data);
|
assetData.emplace(asset.id, data);
|
||||||
|
@ -284,17 +492,8 @@ namespace SHADE
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetManager::BuildAssetCollection() noexcept
|
void SHAssetManager::BuildAssetCollection() noexcept
|
||||||
{
|
{
|
||||||
for (auto const& dir : std::filesystem::recursive_directory_iterator{ASSET_ROOT})
|
SHFileSystem::BuildDirectory(ASSET_ROOT.data(), folderRoot, assetCollection);
|
||||||
{
|
}
|
||||||
if (dir.is_regular_file())
|
|
||||||
{
|
|
||||||
if (dir.path().extension().string() == META_EXTENSION.data())
|
|
||||||
{
|
|
||||||
assetCollection.push_back(SHAssetMetaHandler::RetrieveMetaData(dir.path()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,12 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "tinyddsloader.h"
|
#include "tinyddsloader.h"
|
||||||
|
|
||||||
#include "SHAsset.h"
|
#include "SHAsset.h"
|
||||||
#include "Asset Types/SHAssetData.h"
|
#include "Asset Types/SHAssetData.h"
|
||||||
#include "Libraries/SHAssetLoader.h"
|
#include "Assets/Libraries/Loaders/SHAssetLoader.h"
|
||||||
#include <memory>
|
|
||||||
|
#include "Filesystem/SHFolder.h"
|
||||||
|
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
|
|
||||||
|
@ -26,16 +28,16 @@ namespace SHADE
|
||||||
* \brief Static function to generate resource ID.
|
* \brief Static function to generate resource ID.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
static AssetID GenerateAssetID(AssetType type) noexcept;
|
static AssetID GenerateAssetID(AssetType type) noexcept;
|
||||||
|
|
||||||
static AssetPath GenerateLocalPath(AssetPath path) noexcept;
|
static AssetPath GenerateLocalPath(AssetPath path) noexcept;
|
||||||
|
|
||||||
static AssetPath GenerateNewPath(AssetName name, AssetType type);
|
static AssetPath GenerateNewPath(AssetName name, AssetType type);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Deallocate all memory used by resource data
|
* \brief Deallocate all memory used by resource data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
static void Unload() noexcept;
|
static void Exit() noexcept;
|
||||||
static void Unload(AssetID assetId) noexcept;
|
|
||||||
|
|
||||||
|
static void Unload(AssetID assetId) noexcept;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Load all resources that are in the folder
|
* \brief Load all resources that are in the folder
|
||||||
|
@ -47,7 +49,7 @@ namespace SHADE
|
||||||
*
|
*
|
||||||
* \return const& to unordered_map<AssetName, AssetID>
|
* \return const& to unordered_map<AssetName, AssetID>
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
static std::vector<SHAsset> const& GetAllAssets() noexcept;
|
static std::vector<SHAsset> GetAllAssets() noexcept;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Create record for new resource. CAN ONLY CREATE FOR CUSTOM
|
* \brief Create record for new resource. CAN ONLY CREATE FOR CUSTOM
|
||||||
|
@ -57,8 +59,9 @@ namespace SHADE
|
||||||
* \param name of resource
|
* \param name of resource
|
||||||
* \return resource id generated for new asset
|
* \return resource id generated for new asset
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
static AssetID CreateNewAsset(AssetType, AssetName) noexcept;
|
static AssetID CreateNewAsset(AssetType type, AssetName name) noexcept;
|
||||||
static AssetID CreateAsset(AssetName name, AssetType type) noexcept;
|
static bool SaveAsset(AssetID id) noexcept;
|
||||||
|
static bool DeleteAsset(AssetID id) noexcept;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Import new resource from outside editor window.
|
* \brief Import new resource from outside editor window.
|
||||||
|
@ -76,22 +79,37 @@ namespace SHADE
|
||||||
// -------------------------------------------------------------------------/
|
// -------------------------------------------------------------------------/
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T const* const> GetData(AssetID id) noexcept;
|
static std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T* const> GetData(AssetID id) noexcept;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T const* const> GetConstData(AssetID id) noexcept;
|
||||||
|
|
||||||
|
static std::vector<SHAssetData const*> GetAllDataOfType(AssetType type) noexcept;
|
||||||
|
static std::vector<SHAsset> GetAllRecordOfType(AssetType type) noexcept;
|
||||||
|
|
||||||
|
static AssetID CompileAsset(AssetPath const& path) noexcept;
|
||||||
|
|
||||||
|
static FolderPointer GetRootFolder() noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/****************************************************************************
|
|
||||||
* \brief Load resource data into memory
|
static void InitLoaders() noexcept;
|
||||||
****************************************************************************/
|
|
||||||
static void LoadAllData() noexcept;
|
static void LoadAllData() noexcept;
|
||||||
|
|
||||||
static SHAssetData* LoadData(SHAsset const& asset) noexcept;
|
static SHAssetData* LoadData(SHAsset const& asset) noexcept;
|
||||||
|
|
||||||
inline static void BuildAssetCollection() noexcept;
|
inline static void BuildAssetCollection() noexcept;
|
||||||
|
|
||||||
static bool IsRecognised(char const*) noexcept;
|
static bool IsRecognised(char const*) noexcept;
|
||||||
|
|
||||||
static SHAsset CreateAssetFromPath(AssetPath path) noexcept;
|
static SHAsset CreateAssetFromPath(AssetPath path) noexcept;
|
||||||
|
|
||||||
static void InitLoaders() noexcept;
|
static void CompileAll() noexcept;
|
||||||
|
|
||||||
|
static bool DeleteLocalFile(AssetPath path) noexcept;
|
||||||
|
|
||||||
|
//TODO use this function to create asset data internall at all calls to generate id
|
||||||
|
//static AssetID CreateAsset(AssetName name, AssetType type) noexcept;
|
||||||
|
|
||||||
|
static FolderPointer folderRoot;
|
||||||
|
|
||||||
static FMOD::System* audioSystem;
|
static FMOD::System* audioSystem;
|
||||||
static std::unordered_map<AssetID,SHSound>* audioSoundList;
|
static std::unordered_map<AssetID,SHSound>* audioSoundList;
|
||||||
|
@ -99,7 +117,7 @@ namespace SHADE
|
||||||
static std::vector<SHAssetLoader*> loaders;
|
static std::vector<SHAssetLoader*> loaders;
|
||||||
|
|
||||||
// For all resources
|
// For all resources
|
||||||
static std::vector<SHAsset> assetCollection;
|
static std::unordered_map<AssetID, SHAsset> assetCollection;
|
||||||
static std::unordered_map<AssetID, SHAssetData * const> assetData;
|
static std::unordered_map<AssetID, SHAssetData * const> assetData;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,16 +4,16 @@
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T const* const> SHAssetManager::GetData(AssetID id) noexcept
|
std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T* const> SHAssetManager::GetData(AssetID id) noexcept
|
||||||
{
|
{
|
||||||
if (!assetData.contains(id))
|
if (!assetData.contains(id))
|
||||||
{
|
{
|
||||||
for (auto const& asset : assetCollection)
|
for (auto const& asset : std::ranges::views::values(assetCollection))
|
||||||
{
|
{
|
||||||
if (asset.id == id)
|
if (asset.id == id)
|
||||||
{
|
{
|
||||||
assetData.emplace(id, LoadData(asset));
|
assetData.emplace(id, LoadData(asset));
|
||||||
return dynamic_cast<T const* const>(assetData[id]);
|
return dynamic_cast<T* const>(assetData[id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,27 @@ namespace SHADE
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dynamic_cast<T const* const>(assetData[id]);
|
return dynamic_cast<T* const>(assetData[id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T const * const> SHAssetManager::GetConstData(AssetID id) noexcept
|
||||||
|
{
|
||||||
|
if (!assetData.contains(id))
|
||||||
|
{
|
||||||
|
for (auto const& asset : std::ranges::views::values(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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,5 +213,14 @@ namespace SHADE
|
||||||
return SHSerialization::DeserializeEntityToSceneFromString(data);
|
return SHSerialization::DeserializeEntityToSceneFromString(data);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
EntityID SHEntityManager::GetEntityByName(std::string const& name) noexcept
|
||||||
|
{
|
||||||
|
EntityID result = MAX_EID;
|
||||||
|
for (auto& entity : entityVec)
|
||||||
|
{
|
||||||
|
if (entity->name == name)
|
||||||
|
result = entity->GetEID();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,6 +209,8 @@ namespace SHADE
|
||||||
|
|
||||||
//static EntityID DuplicateEntity(EntityID eid) noexcept;
|
//static EntityID DuplicateEntity(EntityID eid) noexcept;
|
||||||
|
|
||||||
|
static EntityID GetEntityByName(std::string const& name) noexcept;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,12 @@
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
//TODO: Convert to RTTR?
|
//TODO: Convert to RTTR?
|
||||||
constexpr auto DRAG_EID = "DragEID";
|
|
||||||
constexpr auto DRAG_RESOURCE = "DragResource";
|
|
||||||
|
|
||||||
|
|
||||||
struct SHDragDrop
|
struct SHDragDrop
|
||||||
{
|
{
|
||||||
|
using DragDropTag = std::string_view;
|
||||||
|
static constexpr DragDropTag DRAG_EID = "DragEID";
|
||||||
|
static constexpr DragDropTag DRAG_RESOURCE = "DragResource";
|
||||||
static bool BeginSource(ImGuiDragDropFlags const flags = 0);
|
static bool BeginSource(ImGuiDragDropFlags const flags = 0);
|
||||||
/**
|
/**
|
||||||
* \brief Ends the DragDrop Source. ONLY CALL IF BeginSource returns true
|
* \brief Ends the DragDrop Source. ONLY CALL IF BeginSource returns true
|
||||||
|
|
|
@ -4,14 +4,16 @@
|
||||||
#include "Editor/IconsMaterialDesign.h"
|
#include "Editor/IconsMaterialDesign.h"
|
||||||
#include "Editor/SHImGuiHelpers.hpp"
|
#include "Editor/SHImGuiHelpers.hpp"
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
#include <imgui_internal.h>
|
||||||
|
|
||||||
#include "Assets/SHAssetManager.h"
|
#include "Assets/SHAssetManager.h"
|
||||||
|
#include "Editor/IconsFontAwesome6.h"
|
||||||
#include "Editor/DragDrop/SHDragDrop.hpp"
|
#include "Editor/DragDrop/SHDragDrop.hpp"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
SHAssetBrowser::SHAssetBrowser()
|
SHAssetBrowser::SHAssetBrowser()
|
||||||
:SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar)
|
:SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar), rootFolder(SHAssetManager::GetRootFolder()), prevFolder(rootFolder), currentFolder(rootFolder)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,62 +25,140 @@ namespace SHADE
|
||||||
void SHAssetBrowser::Update()
|
void SHAssetBrowser::Update()
|
||||||
{
|
{
|
||||||
SHEditorWindow::Update();
|
SHEditorWindow::Update();
|
||||||
if(Begin())
|
if (Begin())
|
||||||
{
|
{
|
||||||
|
RecursivelyDrawTree(rootFolder);
|
||||||
DrawMenuBar();
|
DrawMenuBar();
|
||||||
auto const& assets = SHAssetManager::GetAllAssets();
|
DrawCurrentFolder();
|
||||||
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();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetBrowser::DrawMenuBar()
|
void SHAssetBrowser::DrawMenuBar()
|
||||||
{
|
{
|
||||||
if(ImGui::BeginMenuBar())
|
if (ImGui::BeginMenuBar())
|
||||||
{
|
{
|
||||||
|
|
||||||
ImGui::EndMenuBar();
|
ImGui::EndMenuBar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetBrowser::DrawAsset(SHAsset const& asset)
|
ImRect SHAssetBrowser::RecursivelyDrawTree(FolderPointer folder)
|
||||||
{
|
{
|
||||||
ImGui::PushID(asset.id);
|
auto const& subFolders = folder->subFolders;
|
||||||
ImGui::BeginGroup();
|
auto const& files = folder->files;
|
||||||
|
const bool isSelected = std::ranges::find(selectedFolders, folder) != selectedFolders.end();
|
||||||
ImGui::TableNextColumn();
|
ImGuiTreeNodeFlags flags = (subFolders.empty() && files.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow;
|
||||||
ImGui::Selectable(std::format("{}", asset.id).data(), false, ImGuiSelectableFlags_SpanAllColumns);
|
if (isSelected)
|
||||||
if(SHDragDrop::BeginSource())
|
flags |= ImGuiTreeNodeFlags_Selected;
|
||||||
|
if (folder == rootFolder)
|
||||||
|
flags |= ImGuiTreeNodeFlags_DefaultOpen;
|
||||||
|
|
||||||
|
bool isOpen = ImGui::TreeNodeEx(folder, flags, "%s %s", ICON_MD_FOLDER, folder->name.data());
|
||||||
|
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
|
if(ImGui::IsItemClicked())
|
||||||
{
|
{
|
||||||
auto id = asset.id;
|
selectedFolders.clear();
|
||||||
ImGui::Text("Moving Asset: %zu", id);
|
selectedFolders.push_back(folder);
|
||||||
SHDragDrop::SetPayload<AssetID>(DRAG_RESOURCE, &id);
|
}
|
||||||
SHDragDrop::EndSource();
|
if (isOpen)
|
||||||
|
{
|
||||||
|
const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark);
|
||||||
|
const float horizontalOffset = 0.0f;
|
||||||
|
ImDrawList* drawList = ImGui::GetWindowDrawList();
|
||||||
|
ImVec2 vertLineStart = ImGui::GetCursorScreenPos();
|
||||||
|
vertLineStart.x += horizontalOffset;
|
||||||
|
ImVec2 vertLineEnd = vertLineStart;
|
||||||
|
for (auto const& subFolder : subFolders)
|
||||||
|
{
|
||||||
|
const float horizontalLineSize = 8.0f;
|
||||||
|
const ImRect childRect = RecursivelyDrawTree(subFolder);
|
||||||
|
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
|
||||||
|
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
|
||||||
|
vertLineEnd.y = midPoint;
|
||||||
|
}
|
||||||
|
for (auto const& file : files)
|
||||||
|
{
|
||||||
|
const float horizontalLineSize = 25.0f;
|
||||||
|
const ImRect childRect = DrawFile(file);
|
||||||
|
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
|
||||||
|
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
|
||||||
|
vertLineEnd.y = midPoint;
|
||||||
|
}
|
||||||
|
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1);
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
return nodeRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::DrawCurrentFolder()
|
||||||
|
{
|
||||||
|
//auto const& subFolders = currentFolder->subFolders;
|
||||||
|
//ImVec2 initialCursorPos = ImGui::GetCursorPos();
|
||||||
|
//ImVec2 initialRegionAvail = ImGui::GetContentRegionAvail();
|
||||||
|
//int maxTiles = initialRegionAvail.x / tileWidth;
|
||||||
|
//float maxX = (maxTiles - 1)*tileWidth;
|
||||||
|
//ImVec2 tilePos = initialCursorPos;
|
||||||
|
//for (auto const& subFolder : subFolders)
|
||||||
|
//{
|
||||||
|
// ImGui::SetCursorPos(tilePos);
|
||||||
|
// ImGui::BeginGroup();
|
||||||
|
// ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, {0.0f, 0.0f});
|
||||||
|
// ImGui::Button(ICON_MD_FOLDER, {tileWidth});
|
||||||
|
// ImGui::Text(subFolder->name.data());
|
||||||
|
// ImGui::PopStyleVar();
|
||||||
|
// ImGui::EndGroup();
|
||||||
|
// if(tilePos.x >= maxX)
|
||||||
|
// {
|
||||||
|
// tilePos.x = initialCursorPos.x;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// ImGui::SameLine();
|
||||||
|
// tilePos.x += tileWidth;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImRect SHAssetBrowser::DrawFile(SHFile const& file) noexcept
|
||||||
|
{
|
||||||
|
if (file.assetMeta == nullptr)
|
||||||
|
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
|
const bool isSelected = std::ranges::find(selectedAssets, file.assetMeta->id) != selectedAssets.end();
|
||||||
|
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf;
|
||||||
|
if (isSelected)
|
||||||
|
flags |= ImGuiTreeNodeFlags_Selected;
|
||||||
|
std::string icon{};
|
||||||
|
|
||||||
|
switch(file.assetMeta->type)
|
||||||
|
{
|
||||||
|
case AssetType::INVALID: break;
|
||||||
|
case AssetType::SHADER: icon = ICON_FA_FILE_CODE; break;
|
||||||
|
case AssetType::SHADER_BUILT_IN: icon = ICON_FA_FILE_CODE; break;
|
||||||
|
case AssetType::TEXTURE: icon = ICON_FA_IMAGES; break;
|
||||||
|
case AssetType::MESH: icon = ICON_FA_CUBES; break;
|
||||||
|
case AssetType::SCENE: icon = ICON_MD_IMAGE; break;
|
||||||
|
case AssetType::PREFAB: icon = ICON_FA_BOX_OPEN; break;
|
||||||
|
case AssetType::MATERIAL: break;
|
||||||
|
case AssetType::MAX_COUNT: break;
|
||||||
|
default: ;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TreeNodeEx(file.assetMeta, flags, "%s %s", icon.data(), file.assetMeta->name.data());
|
||||||
ImGui::Text("%s", asset.name.c_str());
|
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
|
if(SHDragDrop::BeginSource())
|
||||||
ImGui::TableNextColumn();
|
{
|
||||||
ImGui::Text("%s", "Type");
|
auto id = file.assetMeta->id;
|
||||||
|
ImGui::Text("Moving Asset: %s [%zu]", file.name.data(), file.assetMeta->id);
|
||||||
ImGui::EndGroup();
|
SHDragDrop::SetPayload<AssetID>(SHDragDrop::DRAG_RESOURCE, &id);
|
||||||
ImGui::PopID();
|
SHDragDrop::EndSource();
|
||||||
|
}
|
||||||
|
if(ImGui::IsItemClicked())
|
||||||
|
{
|
||||||
|
selectedAssets.clear();
|
||||||
|
selectedAssets.push_back(file.assetMeta->id);
|
||||||
|
}
|
||||||
|
ImGui::TreePop();
|
||||||
|
return nodeRect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "imgui_internal.h"
|
||||||
#include "Assets/SHAsset.h"
|
#include "Assets/SHAsset.h"
|
||||||
#include "Editor/EditorWindow/SHEditorWindow.h"
|
#include "Editor/EditorWindow/SHEditorWindow.h"
|
||||||
|
#include "Filesystem/SHFolder.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -16,9 +18,14 @@ namespace SHADE
|
||||||
void Refresh();
|
void Refresh();
|
||||||
private:
|
private:
|
||||||
void DrawMenuBar();
|
void DrawMenuBar();
|
||||||
void DrawAsset(SHAsset const& asset);
|
ImRect RecursivelyDrawTree(FolderPointer folder);
|
||||||
|
void DrawCurrentFolder();
|
||||||
|
ImRect DrawFile(SHFile const& file) noexcept;
|
||||||
|
|
||||||
float idColumnWidth, nameColumnWidth, typeColumnWidth;
|
FolderPointer rootFolder, prevFolder, currentFolder;
|
||||||
|
std::vector<FolderPointer> selectedFolders;
|
||||||
|
std::vector<AssetID> selectedAssets;
|
||||||
|
static constexpr float tileWidth = 50.0f;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
//|| SHADE Includes ||
|
//|| SHADE Includes ||
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
#include "Editor/SHEditor.hpp"
|
#include "Editor/SHEditor.h"
|
||||||
#include "Editor/SHImGuiHelpers.hpp"
|
#include "Editor/SHImGuiHelpers.hpp"
|
||||||
#include "Editor/SHEditorWidgets.hpp"
|
#include "Editor/SHEditorWidgets.hpp"
|
||||||
#include "SHHierarchyPanel.h"
|
#include "SHHierarchyPanel.h"
|
||||||
|
@ -48,15 +48,28 @@ namespace SHADE
|
||||||
|
|
||||||
if (Begin())
|
if (Begin())
|
||||||
{
|
{
|
||||||
|
if (skipFrame)
|
||||||
|
{
|
||||||
|
ImGui::End();
|
||||||
|
skipFrame = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
DrawMenuBar();
|
DrawMenuBar();
|
||||||
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||||
if(const auto root = sceneGraph.GetRoot())
|
|
||||||
|
if (const auto root = sceneGraph.GetRoot())
|
||||||
{
|
{
|
||||||
auto const& children = root->GetChildren();
|
auto const& children = root->GetChildren();
|
||||||
|
|
||||||
for (const auto child : children)
|
for (const auto child : children)
|
||||||
{
|
{
|
||||||
RecursivelyDrawEntityNode(child);
|
if (child)
|
||||||
|
RecursivelyDrawEntityNode(child);
|
||||||
|
if (skipFrame)
|
||||||
|
{
|
||||||
|
ImGui::End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -64,12 +77,36 @@ namespace SHADE
|
||||||
SHLOG_WARNING("Scene Graph root is null! Unable to render hierarchy.")
|
SHLOG_WARNING("Scene Graph root is null! Unable to render hierarchy.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::IsWindowHovered() && !SHDragDrop::hasDragDrop && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
if (ImGui::IsWindowHovered() && !SHDragDrop::hasDragDrop && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
{
|
{
|
||||||
if(auto editor = SHSystemManager::GetSystem<SHEditor>())
|
if (auto editor = SHSystemManager::GetSystem<SHEditor>())
|
||||||
editor->selectedEntities.clear();
|
editor->selectedEntities.clear();
|
||||||
}
|
}
|
||||||
ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal);
|
ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal);
|
||||||
|
if (ImGui::IsWindowFocused())
|
||||||
|
{
|
||||||
|
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_A))
|
||||||
|
{
|
||||||
|
SelectAllEntities();
|
||||||
|
}
|
||||||
|
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_C))
|
||||||
|
{
|
||||||
|
CopySelectedEntities();
|
||||||
|
}
|
||||||
|
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && !ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyReleased(ImGuiKey_V))
|
||||||
|
{
|
||||||
|
PasteEntities();
|
||||||
|
}
|
||||||
|
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyReleased(ImGuiKey_V))
|
||||||
|
{
|
||||||
|
const auto editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
if (editor->selectedEntities.size() == 1)
|
||||||
|
{
|
||||||
|
PasteEntities(editor->selectedEntities.back());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
@ -81,7 +118,7 @@ namespace SHADE
|
||||||
|
|
||||||
void SHHierarchyPanel::SetScrollTo(EntityID eid)
|
void SHHierarchyPanel::SetScrollTo(EntityID eid)
|
||||||
{
|
{
|
||||||
if(eid == MAX_EID)
|
if (eid == MAX_EID)
|
||||||
return;
|
return;
|
||||||
scrollTo = eid;
|
scrollTo = eid;
|
||||||
}
|
}
|
||||||
|
@ -93,8 +130,10 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
if (ImGui::BeginMenuBar())
|
if (ImGui::BeginMenuBar())
|
||||||
{
|
{
|
||||||
ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x * 0.75f);
|
auto size = ImGui::GetWindowSize();
|
||||||
if(ImGui::SmallButton(ICON_MD_DESELECT))
|
auto g = ImGui::GetCurrentContext();
|
||||||
|
ImGui::SetCursorPosX(size.x - g->Style.FramePadding.x * 15.0f);
|
||||||
|
if (ImGui::SmallButton(ICON_MD_CLEAR_ALL))
|
||||||
{
|
{
|
||||||
auto editor = SHSystemManager::GetSystem<SHEditor>();
|
auto editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
editor->selectedEntities.clear();
|
editor->selectedEntities.clear();
|
||||||
|
@ -119,15 +158,17 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImRect SHHierarchyPanel::RecursivelyDrawEntityNode(SHSceneNode* currentNode)
|
ImRect SHHierarchyPanel::RecursivelyDrawEntityNode(SHSceneNode* const currentNode)
|
||||||
{
|
{
|
||||||
|
if (currentNode == nullptr)
|
||||||
|
return {};
|
||||||
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||||
|
|
||||||
//Get node data (Children, eid, selected)
|
//Get node data (Children, eid, selected)
|
||||||
auto& children = currentNode->GetChildren();
|
auto& children = currentNode->GetChildren();
|
||||||
EntityID eid = currentNode->GetEntityID();
|
EntityID eid = currentNode->GetEntityID();
|
||||||
|
|
||||||
if(scrollTo != MAX_EID && eid == scrollTo)
|
if (scrollTo != MAX_EID && eid == scrollTo)
|
||||||
{
|
{
|
||||||
ImGui::SetScrollHereY();
|
ImGui::SetScrollHereY();
|
||||||
scrollTo = MAX_EID;
|
scrollTo = MAX_EID;
|
||||||
|
@ -154,23 +195,23 @@ namespace SHADE
|
||||||
if (SHDragDrop::BeginSource())
|
if (SHDragDrop::BeginSource())
|
||||||
{
|
{
|
||||||
std::string moveLabel = "Moving EID: ";
|
std::string moveLabel = "Moving EID: ";
|
||||||
if(!isSelected)
|
if (!isSelected)
|
||||||
editor->selectedEntities.push_back(eid);
|
editor->selectedEntities.push_back(eid);
|
||||||
for(int i = 0; i < static_cast<int>(editor->selectedEntities.size()); ++i)
|
for (int i = 0; i < static_cast<int>(editor->selectedEntities.size()); ++i)
|
||||||
{
|
{
|
||||||
moveLabel.append(std::to_string(editor->selectedEntities[i]));
|
moveLabel.append(std::to_string(editor->selectedEntities[i]));
|
||||||
if(i + 1 < static_cast<int>(editor->selectedEntities.size()))
|
if (i + 1 < static_cast<int>(editor->selectedEntities.size()))
|
||||||
{
|
{
|
||||||
moveLabel.append(", ");
|
moveLabel.append(", ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::Text(moveLabel.c_str());
|
ImGui::Text(moveLabel.c_str());
|
||||||
SHDragDrop::SetPayload<std::vector<EntityID>>(DRAG_EID, &editor->selectedEntities);
|
SHDragDrop::SetPayload<std::vector<EntityID>>(SHDragDrop::DRAG_EID, &editor->selectedEntities);
|
||||||
SHDragDrop::EndSource();
|
SHDragDrop::EndSource();
|
||||||
}
|
}
|
||||||
else if (SHDragDrop::BeginTarget()) //If Received DragDrop
|
else if (SHDragDrop::BeginTarget()) //If Received DragDrop
|
||||||
{
|
{
|
||||||
if (const std::vector<EntityID>* eidPayload = SHDragDrop::AcceptPayload<std::vector<EntityID>>(DRAG_EID)) //If payload is valid
|
if (const std::vector<EntityID>* eidPayload = SHDragDrop::AcceptPayload<std::vector<EntityID>>(SHDragDrop::DRAG_EID)) //If payload is valid
|
||||||
{
|
{
|
||||||
ParentSelectedEntities(eid);
|
ParentSelectedEntities(eid);
|
||||||
SHDragDrop::EndTarget();
|
SHDragDrop::EndTarget();
|
||||||
|
@ -178,37 +219,43 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
//Context menu
|
//Context menu
|
||||||
if(ImGui::BeginPopupContextItem(std::to_string(eid).c_str()))
|
if (ImGui::BeginPopupContextItem(std::to_string(eid).c_str()))
|
||||||
{
|
{
|
||||||
if(!isSelected)
|
if (!isSelected)
|
||||||
{
|
{
|
||||||
editor->selectedEntities.clear();
|
editor->selectedEntities.clear();
|
||||||
editor->selectedEntities.push_back(eid);
|
editor->selectedEntities.push_back(eid);
|
||||||
}
|
}
|
||||||
if(ImGui::Selectable("Copy"))
|
if (ImGui::Selectable("Copy"))
|
||||||
{
|
{
|
||||||
SHClipboardUtilities::WriteToClipboard(SHSerialization::SerializeEntitiesToString(editor->selectedEntities));
|
CopySelectedEntities();
|
||||||
}
|
}
|
||||||
if(ImGui::Selectable("Paste"))
|
if (ImGui::Selectable("Paste"))
|
||||||
{
|
{
|
||||||
SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard()));
|
PasteEntities();
|
||||||
|
skipFrame = true;
|
||||||
|
ImGui::EndPopup();
|
||||||
|
if (isNodeOpen)
|
||||||
|
ImGui::TreePop();
|
||||||
|
return nodeRect;
|
||||||
}
|
}
|
||||||
if(ImGui::Selectable("Paste as Child"))
|
if (ImGui::Selectable("Paste as Child"))
|
||||||
{
|
{
|
||||||
SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard(), eid));
|
PasteEntities(eid);
|
||||||
|
skipFrame = true;
|
||||||
}
|
}
|
||||||
if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data()))
|
if (ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data()))
|
||||||
{
|
{
|
||||||
SHEntityManager::DestroyEntity(eid);
|
SHEntityManager::DestroyEntity(eid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if((currentNode->GetParent() != sceneGraph.GetRoot()) && ImGui::Selectable(std::format("{} Unparent Selected", ICON_MD_NORTH_WEST).data()))
|
if ((currentNode->GetParent() != sceneGraph.GetRoot()) && ImGui::Selectable(std::format("{} Unparent Selected", ICON_MD_NORTH_WEST).data()))
|
||||||
{
|
{
|
||||||
ParentSelectedEntities(MAX_EID);
|
ParentSelectedEntities(MAX_EID);
|
||||||
}
|
}
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Handle node selection
|
//Handle node selection
|
||||||
if (ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
{
|
{
|
||||||
|
@ -216,11 +263,11 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
if (!isSelected)
|
if (!isSelected)
|
||||||
{
|
{
|
||||||
if(ImGui::IsKeyDown(ImGuiKey_LeftShift))
|
if (ImGui::IsKeyDown(ImGuiKey_LeftShift))
|
||||||
{
|
{
|
||||||
if(editor->selectedEntities.size() >= 1)
|
if (editor->selectedEntities.size() >= 1)
|
||||||
{
|
{
|
||||||
SelectRangeOfEntities(editor->selectedEntities[0], eid);
|
SelectRangeOfEntities(editor->selectedEntities[0], eid);
|
||||||
}
|
}
|
||||||
else editor->selectedEntities.clear();
|
else editor->selectedEntities.clear();
|
||||||
}
|
}
|
||||||
|
@ -278,12 +325,12 @@ namespace SHADE
|
||||||
auto const editor = SHSystemManager::GetSystem<SHEditor>();
|
auto const editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
SHEntityParentCommand::EntityParentData entityParentData;
|
SHEntityParentCommand::EntityParentData entityParentData;
|
||||||
std::vector<EntityID> parentedEIDS;
|
std::vector<EntityID> parentedEIDS;
|
||||||
for(auto const& eid : editor->selectedEntities)
|
for (auto const& eid : editor->selectedEntities)
|
||||||
{
|
{
|
||||||
if(sceneGraph.GetChild(eid, parentEID) == nullptr)
|
if (sceneGraph.GetChild(eid, parentEID) == nullptr)
|
||||||
{
|
{
|
||||||
parentedEIDS.push_back(eid);
|
parentedEIDS.push_back(eid);
|
||||||
if(auto parent = sceneGraph.GetParent(eid))
|
if (auto parent = sceneGraph.GetParent(eid))
|
||||||
entityParentData[eid].oldParentEID = parent->GetEntityID();
|
entityParentData[eid].oldParentEID = parent->GetEntityID();
|
||||||
entityParentData[eid].newParentEID = parentEID;
|
entityParentData[eid].newParentEID = parentEID;
|
||||||
}
|
}
|
||||||
|
@ -298,34 +345,57 @@ namespace SHADE
|
||||||
editor->selectedEntities.clear();
|
editor->selectedEntities.clear();
|
||||||
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||||
sceneGraph.Traverse([&](SHSceneNode* nodePtr)
|
sceneGraph.Traverse([&](SHSceneNode* nodePtr)
|
||||||
{
|
|
||||||
auto eid = nodePtr->GetEntityID();
|
|
||||||
if(!startSelecting)
|
|
||||||
{
|
{
|
||||||
if(eid == beginEID || eid == endEID)
|
auto eid = nodePtr->GetEntityID();
|
||||||
|
if (!startSelecting)
|
||||||
{
|
{
|
||||||
startSelecting = true;
|
if (eid == beginEID || eid == endEID)
|
||||||
editor->selectedEntities.push_back(eid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(!endSelecting)
|
|
||||||
{
|
|
||||||
editor->selectedEntities.push_back(eid);
|
|
||||||
if(eid == endEID || eid == beginEID)
|
|
||||||
{
|
{
|
||||||
endSelecting = true;
|
startSelecting = true;
|
||||||
|
editor->selectedEntities.push_back(eid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
});
|
{
|
||||||
|
if (!endSelecting)
|
||||||
|
{
|
||||||
|
editor->selectedEntities.push_back(eid);
|
||||||
|
if (eid == endEID || eid == beginEID)
|
||||||
|
{
|
||||||
|
endSelecting = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHHierarchyPanel::SelectAllEntities()
|
||||||
|
{
|
||||||
|
const auto editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
editor->selectedEntities.clear();
|
||||||
|
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||||
|
sceneGraph.Traverse([&](SHSceneNode* nodePtr)
|
||||||
|
{
|
||||||
|
auto eid = nodePtr->GetEntityID();
|
||||||
|
editor->selectedEntities.push_back(eid);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHHierarchyPanel::CopySelectedEntities()
|
||||||
|
{
|
||||||
|
const auto editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
SHClipboardUtilities::WriteToClipboard(SHSerialization::SerializeEntitiesToString(editor->selectedEntities));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHHierarchyPanel::PasteEntities(EntityID parentEID)
|
||||||
|
{
|
||||||
|
SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard(), parentEID));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCreateEntityCommand::Execute()
|
void SHCreateEntityCommand::Execute()
|
||||||
{
|
{
|
||||||
EntityID newEID = SHEntityManager::CreateEntity(eid);
|
EntityID newEID = SHEntityManager::CreateEntity(eid);
|
||||||
if(eid == MAX_EID)
|
if (eid == MAX_EID)
|
||||||
eid = newEID;
|
eid = newEID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,9 +407,9 @@ namespace SHADE
|
||||||
void SHEntityParentCommand::Execute()
|
void SHEntityParentCommand::Execute()
|
||||||
{
|
{
|
||||||
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||||
for(auto const& eid : entities)
|
for (auto const& eid : entities)
|
||||||
{
|
{
|
||||||
if(entityParentData[eid].newParentEID == MAX_EID)
|
if (entityParentData[eid].newParentEID == MAX_EID)
|
||||||
sceneGraph.SetParent(eid, nullptr);
|
sceneGraph.SetParent(eid, nullptr);
|
||||||
else
|
else
|
||||||
sceneGraph.SetParent(eid, entityParentData[eid].newParentEID);
|
sceneGraph.SetParent(eid, entityParentData[eid].newParentEID);
|
||||||
|
@ -349,9 +419,9 @@ namespace SHADE
|
||||||
void SHEntityParentCommand::Undo()
|
void SHEntityParentCommand::Undo()
|
||||||
{
|
{
|
||||||
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||||
for(auto const& eid : entities)
|
for (auto const& eid : entities)
|
||||||
{
|
{
|
||||||
if(entityParentData[eid].oldParentEID == MAX_EID)
|
if (entityParentData[eid].oldParentEID == MAX_EID)
|
||||||
sceneGraph.SetParent(eid, nullptr);
|
sceneGraph.SetParent(eid, nullptr);
|
||||||
else
|
else
|
||||||
sceneGraph.SetParent(eid, entityParentData[eid].oldParentEID);
|
sceneGraph.SetParent(eid, entityParentData[eid].oldParentEID);
|
||||||
|
|
|
@ -26,10 +26,14 @@ namespace SHADE
|
||||||
void SetScrollTo(EntityID eid);
|
void SetScrollTo(EntityID eid);
|
||||||
private:
|
private:
|
||||||
void DrawMenuBar() const noexcept;
|
void DrawMenuBar() const noexcept;
|
||||||
ImRect RecursivelyDrawEntityNode(SHSceneNode*);
|
ImRect RecursivelyDrawEntityNode(SHSceneNode* const);
|
||||||
void CreateChildEntity(EntityID parentEID) const noexcept;
|
void CreateChildEntity(EntityID parentEID) const noexcept;
|
||||||
void ParentSelectedEntities(EntityID parentEID) const noexcept;
|
void ParentSelectedEntities(EntityID parentEID) const noexcept;
|
||||||
void SelectRangeOfEntities(EntityID beginEID, EntityID EndEID);
|
void SelectRangeOfEntities(EntityID beginEID, EntityID EndEID);
|
||||||
|
void SelectAllEntities();
|
||||||
|
void CopySelectedEntities();
|
||||||
|
void PasteEntities(EntityID parentEID = MAX_EID);
|
||||||
|
bool skipFrame = false;
|
||||||
std::string filter;
|
std::string filter;
|
||||||
bool isAnyNodeSelected = false;
|
bool isAnyNodeSelected = false;
|
||||||
EntityID scrollTo = MAX_EID;
|
EntityID scrollTo = MAX_EID;
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
#include "ECS_Base/Components/SHComponent.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
template<typename T, std::enable_if_t<std::is_base_of<SHComponent, T>::value, bool> = true>
|
||||||
|
static void DrawContextMenu(T* component);
|
||||||
|
template<typename T, std::enable_if_t<std::is_base_of_v<SHComponent, T>, bool> = true>
|
||||||
|
static void DrawComponent(T* component);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "SHEditorComponentView.hpp"
|
|
@ -13,11 +13,28 @@
|
||||||
#include "Editor/IconsFontAwesome6.h"
|
#include "Editor/IconsFontAwesome6.h"
|
||||||
#include "ECS_Base/Components/SHComponent.h"
|
#include "ECS_Base/Components/SHComponent.h"
|
||||||
#include "Editor/SHEditorWidgets.hpp"
|
#include "Editor/SHEditorWidgets.hpp"
|
||||||
|
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||||
|
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Components/SHColliderComponent.h"
|
||||||
#include "Reflection/SHReflectionMetadata.h"
|
#include "Reflection/SHReflectionMetadata.h"
|
||||||
|
#include "Resource/SHResourceManager.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
template<typename T, std::enable_if_t<std::is_base_of<SHComponent, T>::value, bool> = true>
|
template<typename T>
|
||||||
|
std::vector<const char*> GetRTTREnumNames()
|
||||||
|
{
|
||||||
|
auto const rttrType = rttr::type::get<T>();
|
||||||
|
if (!rttrType.is_enumeration())
|
||||||
|
return {};
|
||||||
|
auto const enumAlign = rttrType.get_enumeration();
|
||||||
|
auto const names = enumAlign.get_names();
|
||||||
|
std::vector<const char*> result;
|
||||||
|
std::transform(names.begin(), names.end(), std::back_inserter(result), [](rttr::string_view const& name) {return name.data(); });
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::enable_if_t<std::is_base_of<SHComponent, T>::value, bool>>
|
||||||
static void DrawContextMenu(T* component)
|
static void DrawContextMenu(T* component)
|
||||||
{
|
{
|
||||||
if (!component)
|
if (!component)
|
||||||
|
@ -46,13 +63,15 @@ namespace SHADE
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<typename T, std::enable_if_t<std::is_base_of_v<SHComponent, T>, bool> = true>
|
template<typename T, std::enable_if_t<std::is_base_of_v<SHComponent, T>, bool>>
|
||||||
static void DrawComponent(T* component)
|
static void DrawComponent(T* component)
|
||||||
{
|
{
|
||||||
if (!component)
|
if (!component)
|
||||||
return;
|
return;
|
||||||
const auto componentType = rttr::type::get(*component);
|
const auto componentType = rttr::type::get<T>();
|
||||||
|
ImGui::PushID(SHFamilyID<SHComponent>::GetID<T>());
|
||||||
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active");
|
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active");
|
||||||
|
ImGui::PopID();
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::CollapsingHeader(componentType.get_name().data()))
|
if (ImGui::CollapsingHeader(componentType.get_name().data()))
|
||||||
{
|
{
|
||||||
|
@ -61,7 +80,8 @@ namespace SHADE
|
||||||
for (auto const& property : properties)
|
for (auto const& property : properties)
|
||||||
{
|
{
|
||||||
auto const& type = property.get_type();
|
auto const& type = property.get_type();
|
||||||
|
auto tooltip = property.get_metadata(META::tooltip);
|
||||||
|
bool const& isAngleInRad = property.get_metadata(META::angleInRad).is_valid() ? property.get_metadata(META::angleInRad).template get_value<bool>() : false;
|
||||||
if (type.is_enumeration())
|
if (type.is_enumeration())
|
||||||
{
|
{
|
||||||
auto enumAlign = type.get_enumeration();
|
auto enumAlign = type.get_enumeration();
|
||||||
|
@ -75,29 +95,25 @@ namespace SHADE
|
||||||
auto values = enumAlign.get_values();
|
auto values = enumAlign.get_values();
|
||||||
auto it = std::next(values.begin(), idx);
|
auto it = std::next(values.begin(), idx);
|
||||||
property.set_value(component, *it);
|
property.set_value(component, *it);
|
||||||
});
|
}, tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string());
|
||||||
}
|
}
|
||||||
else if (type.is_arithmetic())
|
else if (type.is_arithmetic())
|
||||||
{
|
{
|
||||||
if (type == rttr::type::get<bool>())
|
if (type == rttr::type::get<bool>())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::CheckBox(property.get_name().data(), [component, property] {return property.get_value(component).to_bool(); }, [component, property](bool const& result) {property.set_value(component, result); });
|
SHEditorWidgets::CheckBox(property.get_name().data(), [component, property] {return property.get_value(component).to_bool(); }, [component, property](bool const& result) {property.set_value(component, result); }, tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string());
|
||||||
}
|
}
|
||||||
//else if (type == rttr::type::get<char>())
|
|
||||||
//{
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
else if (type == rttr::type::get<int8_t>() || type == rttr::type::get<int16_t>() || type == rttr::type::get<int32_t>() || type == rttr::type::get<int64_t>())
|
else if (type == rttr::type::get<int8_t>() || type == rttr::type::get<int16_t>() || type == rttr::type::get<int32_t>() || type == rttr::type::get<int64_t>())
|
||||||
{
|
{
|
||||||
auto metaMin = property.get_metadata(META::min);
|
auto metaMin = property.get_metadata(META::min);
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin && metaMax)
|
if (metaMin && metaMax)
|
||||||
{
|
{
|
||||||
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); });
|
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); }, tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragInt(property.get_name().data(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); });
|
SHEditorWidgets::DragInt(property.get_name().data(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); }, tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == rttr::type::get<uint8_t>())
|
else if (type == rttr::type::get<uint8_t>())
|
||||||
|
@ -106,11 +122,11 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderScalar<uint8_t>(property.get_name().data(), ImGuiDataType_U8, metaMin.template get_value<uint8_t>(), metaMax.template get_value<uint8_t>(), [component, property] {return property.get_value(component).to_uint8(); }, [component, property](uint8_t const& result) {property.set_value(component, result); }, "%zu");
|
SHEditorWidgets::SliderScalar<uint8_t>(property.get_name().data(), ImGuiDataType_U8, metaMin.template get_value<uint8_t>(), metaMax.template get_value<uint8_t>(), [component, property] {return property.get_value(component).to_uint8(); }, [component, property](uint8_t const& result) {property.set_value(component, result); }, tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string(), "%zu");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragScalar<uint8_t>(property.get_name().data(), ImGuiDataType_U8, [component, property] {return property.get_value(component).to_uint8(); }, [component, property](uint8_t const& result) {property.set_value(component, result); }, 0.1f, 0, 0, "%zu");
|
SHEditorWidgets::DragScalar<uint8_t>(property.get_name().data(), ImGuiDataType_U8, [component, property] {return property.get_value(component).to_uint8(); }, [component, property](uint8_t const& result) {property.set_value(component, result); }, 0.1f, 0, 0, "%zu", tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == rttr::type::get<uint16_t>())
|
else if (type == rttr::type::get<uint16_t>())
|
||||||
|
@ -119,11 +135,11 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value<uint16_t>(), 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");
|
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); }, tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string(), "%zu");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, 0.1f, 0, 0, "%zu");
|
SHEditorWidgets::DragScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, 0.1f, 0, 0, "%zu", tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == rttr::type::get<uint32_t>())
|
else if (type == rttr::type::get<uint32_t>())
|
||||||
|
@ -132,11 +148,11 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value<uint32_t>(), 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");
|
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); }, tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string(), "%zu");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, 0.1f, 0, 0, "%zu");
|
SHEditorWidgets::DragScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, 0.1f, 0, 0, "%zu", tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == rttr::type::get<uint64_t>())
|
else if (type == rttr::type::get<uint64_t>())
|
||||||
|
@ -145,11 +161,11 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value<uint64_t>(), 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");
|
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); }, tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string(), "%zu");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, 0.1f, 0, 0, "%zu");
|
SHEditorWidgets::DragScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, 0.1f, 0, 0, "%zu", tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == rttr::type::get<float>())
|
else if (type == rttr::type::get<float>())
|
||||||
|
@ -157,17 +173,17 @@ namespace SHADE
|
||||||
auto metaMin = property.get_metadata(META::min);
|
auto metaMin = property.get_metadata(META::min);
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
float min{}, max{};
|
float min{}, max{};
|
||||||
if(metaMin.is_valid())
|
if (metaMin.is_valid())
|
||||||
min = std::max(metaMin.template get_value<float>(), -FLT_MAX * 0.5f);
|
min = std::max(metaMin.template get_value<float>(), -FLT_MAX * 0.5f);
|
||||||
if(metaMax.is_valid())
|
if (metaMax.is_valid())
|
||||||
max = std::min(metaMax.template get_value<float>(), FLT_MAX * 0.5f);
|
max = std::min(metaMax.template get_value<float>(), FLT_MAX * 0.5f);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderFloat(property.get_name().data(), min, max, [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); }, tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragFloat(property.get_name().data(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }, "Test");
|
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); }, tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == rttr::type::get<double>())
|
else if (type == rttr::type::get<double>())
|
||||||
|
@ -176,25 +192,25 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderScalar<double>(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value<double>(), metaMax.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); }, tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragScalar<double>(property.get_name().data(), ImGuiDataType_Double, [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); }, 0.1f);
|
SHEditorWidgets::DragScalar<double>(property.get_name().data(), ImGuiDataType_Double, [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); }, 0.1f, {}, {}, "%.3f", tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == rttr::type::get<SHVec4>())
|
else if (type == rttr::type::get<SHVec4>())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragVec4(property.get_name().data(), { "X", "Y", "Z", "W" }, [component, property]() {return property.get_value(component).template convert<SHVec4>(); }, [component, property](SHVec4 vec) {return property.set_value(component, vec); });
|
SHEditorWidgets::DragVec4(property.get_name().data(), { "X", "Y", "Z", "W" }, [component, property]() {return property.get_value(component).template convert<SHVec4>(); }, [component, property](SHVec4 vec) {return property.set_value(component, vec); }, isAngleInRad, tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string());
|
||||||
}
|
}
|
||||||
else if (type == rttr::type::get<SHVec3>())
|
else if (type == rttr::type::get<SHVec3>())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragVec3(property.get_name().data(), { "X", "Y", "Z" }, [component, property]() {return property.get_value(component).template convert<SHVec3>(); }, [component, property](SHVec3 vec) {return property.set_value(component, vec); });
|
SHEditorWidgets::DragVec3(property.get_name().data(), { "X", "Y", "Z" }, [component, property]() {return property.get_value(component).template convert<SHVec3>(); }, [component, property](SHVec3 vec) {return property.set_value(component, vec); }, isAngleInRad, tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string());
|
||||||
}
|
}
|
||||||
else if (type == rttr::type::get<SHVec2>())
|
else if (type == rttr::type::get<SHVec2>())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragVec2(property.get_name().data(), { "X", "Y" }, [component, property]() {return property.get_value(component).template convert<SHVec2>(); }, [component, property](SHVec2 vec) {return property.set_value(component, vec); });
|
SHEditorWidgets::DragVec2(property.get_name().data(), { "X", "Y" }, [component, property]() {return property.get_value(component).template convert<SHVec2>(); }, [component, property](SHVec2 vec) {return property.set_value(component, vec); }, isAngleInRad, tooltip.is_valid() ? tooltip.template get_value<std::string>() : std::string());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -207,8 +223,12 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
if (!component)
|
if (!component)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Get transform component for extrapolating relative sizes
|
||||||
|
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(component->GetEID());
|
||||||
|
|
||||||
const auto componentType = rttr::type::get(*component);
|
const auto componentType = rttr::type::get(*component);
|
||||||
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; });
|
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::CollapsingHeader(componentType.get_name().data()))
|
if (ImGui::CollapsingHeader(componentType.get_name().data()))
|
||||||
{
|
{
|
||||||
|
@ -216,43 +236,56 @@ namespace SHADE
|
||||||
|
|
||||||
auto& colliders = component->GetColliders();
|
auto& colliders = component->GetColliders();
|
||||||
int const size = static_cast<int>(colliders.size());
|
int const size = static_cast<int>(colliders.size());
|
||||||
ImGui::BeginChild("Colliders", {0.0f, colliders.empty() ? 1.0f : 250.0f}, true);
|
ImGui::BeginChild("Colliders", { 0.0f, colliders.empty() ? 1.0f : 250.0f }, true);
|
||||||
std::optional<int> colliderToDelete{std::nullopt};
|
std::optional<int> colliderToDelete{ std::nullopt };
|
||||||
for (int i{}; i < size; ++i)
|
for (int i{}; i < size; ++i)
|
||||||
{
|
{
|
||||||
ImGui::PushID(i);
|
ImGui::PushID(i);
|
||||||
SHCollider& collider = component->GetCollider(i);
|
SHCollider* collider = &component->GetCollider(i);
|
||||||
auto cursorPos = ImGui::GetCursorPos();
|
auto cursorPos = ImGui::GetCursorPos();
|
||||||
|
|
||||||
if (collider.GetType() == SHCollider::Type::BOX)
|
if (collider->GetType() == SHCollider::Type::BOX)
|
||||||
{
|
{
|
||||||
SHEditorWidgets::BeginPanel( std::format("{} Box Collider #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
SHEditorWidgets::BeginPanel(std::format("{} Box Collider #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
||||||
auto box = reinterpret_cast<SHBoundingBox*>(collider.GetShape());
|
auto box = reinterpret_cast<SHBoundingBox*>(collider->GetShape());
|
||||||
SHEditorWidgets::DragVec3("Half Extents", { "X", "Y", "Z" }, [box] {return box->GetHalfExtents(); }, [box](SHVec3 const& vec) {box->SetHalfExtents(vec);});
|
SHEditorWidgets::DragVec3
|
||||||
|
(
|
||||||
|
"Half Extents", { "X", "Y", "Z" },
|
||||||
|
[box, transformComponent] { return (transformComponent->GetWorldScale() * 2.0f) * box->GetHalfExtents(); },
|
||||||
|
[collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); });
|
||||||
}
|
}
|
||||||
else if (collider.GetType() == SHCollider::Type::SPHERE)
|
else if (collider->GetType() == SHCollider::Type::SPHERE)
|
||||||
{
|
{
|
||||||
SHEditorWidgets::BeginPanel(std::format("{} Sphere Collider #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
SHEditorWidgets::BeginPanel(std::format("{} Sphere Collider #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
||||||
auto sphere = reinterpret_cast<SHBoundingSphere*>(collider.GetShape());
|
auto sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape());
|
||||||
SHEditorWidgets::DragFloat("Radius", [sphere] {return sphere->GetRadius(); }, [sphere](float const& value) {sphere->SetRadius(value);});
|
SHEditorWidgets::DragFloat
|
||||||
|
(
|
||||||
|
"Radius",
|
||||||
|
[sphere, transformComponent]
|
||||||
|
{
|
||||||
|
const SHVec3& TF_WORLD_SCALE = transformComponent->GetWorldScale();
|
||||||
|
const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z });
|
||||||
|
return sphere->GetRadius() / MAX_SCALE;
|
||||||
|
},
|
||||||
|
[collider](float const& value) { collider->SetBoundingSphere(value); });
|
||||||
}
|
}
|
||||||
else if (collider.GetType() == SHCollider::Type::CAPSULE)
|
else if (collider->GetType() == SHCollider::Type::CAPSULE)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
SHEditorWidgets::BeginPanel("Offset", { ImGui::GetContentRegionAvail().x, 30.0f });
|
SHEditorWidgets::BeginPanel("Offset", { ImGui::GetContentRegionAvail().x, 30.0f });
|
||||||
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [&collider] {return collider.GetPositionOffset(); }, [&collider](SHVec3 const& vec) {collider.SetPositionOffset(vec); });
|
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [&collider] {return collider->GetPositionOffset(); }, [&collider](SHVec3 const& vec) {collider->SetPositionOffset(vec); });
|
||||||
SHEditorWidgets::EndPanel();
|
SHEditorWidgets::EndPanel();
|
||||||
}
|
}
|
||||||
if(ImGui::Button(std::format("{} Remove Collider #{}", ICON_MD_REMOVE, i).data()))
|
if (ImGui::Button(std::format("{} Remove Collider #{}", ICON_MD_REMOVE, i).data()))
|
||||||
{
|
{
|
||||||
colliderToDelete = i;
|
colliderToDelete = i;
|
||||||
}
|
}
|
||||||
SHEditorWidgets::EndPanel();
|
SHEditorWidgets::EndPanel();
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
if(colliderToDelete.has_value())
|
if (colliderToDelete.has_value())
|
||||||
{
|
{
|
||||||
component->RemoveCollider(colliderToDelete.value());
|
component->RemoveCollider(colliderToDelete.value());
|
||||||
}
|
}
|
||||||
|
@ -260,11 +293,11 @@ namespace SHADE
|
||||||
|
|
||||||
if (ImGui::BeginMenu("Add Collider"))
|
if (ImGui::BeginMenu("Add Collider"))
|
||||||
{
|
{
|
||||||
if(ImGui::Selectable("Box Collider"))
|
if (ImGui::Selectable("Box Collider"))
|
||||||
{
|
{
|
||||||
component->AddBoundingBox();
|
component->AddBoundingBox();
|
||||||
}
|
}
|
||||||
if(ImGui::Selectable("Sphere Collider"))
|
if (ImGui::Selectable("Sphere Collider"))
|
||||||
{
|
{
|
||||||
component->AddBoundingSphere();
|
component->AddBoundingSphere();
|
||||||
}
|
}
|
||||||
|
@ -273,4 +306,63 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
else DrawContextMenu(component);
|
else DrawContextMenu(component);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
template<>
|
||||||
|
static void DrawComponent(SHLightComponent* component)
|
||||||
|
{
|
||||||
|
if (!component)
|
||||||
|
return;
|
||||||
|
const auto componentType = rttr::type::get(*component);
|
||||||
|
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()))
|
||||||
|
{
|
||||||
|
DrawContextMenu(component);
|
||||||
|
|
||||||
|
static auto const enumAlign = rttr::type::get<SH_LIGHT_TYPE>().get_enumeration();
|
||||||
|
static std::vector<const char*> list(GetRTTREnumNames<SH_LIGHT_TYPE>());
|
||||||
|
|
||||||
|
SHEditorWidgets::ComboBox("Type", list, [component] {return static_cast<int>(component->GetType()); }, [component](int const& idx)
|
||||||
|
{
|
||||||
|
component->SetType(static_cast<SH_LIGHT_TYPE>(idx));
|
||||||
|
});
|
||||||
|
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [component]() {return component->GetPosition(); }, [component](SHVec3 const& vec) {component->SetPosition(vec); });
|
||||||
|
SHEditorWidgets::DragVec3("Direction", { "X", "Y", "Z" }, [component]() {return component->GetDirection(); }, [component](SHVec3 const& vec) {component->SetDirection(vec); });
|
||||||
|
SHEditorWidgets::ColorPicker("Color", [component]() {return component->GetColor(); }, [component](SHVec4 const& rgba) {component->SetColor(rgba); });
|
||||||
|
SHEditorWidgets::DragFloat("Strength", [component]() {return component->GetStrength(); }, [component](float const& value) {component->SetStrength(value); });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawContextMenu(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
static void DrawComponent(SHRenderable* component)
|
||||||
|
{
|
||||||
|
if (!component)
|
||||||
|
return;
|
||||||
|
const auto componentType = rttr::type::get(*component);
|
||||||
|
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()))
|
||||||
|
{
|
||||||
|
DrawContextMenu(component);
|
||||||
|
Handle<SHMesh> const& mesh = component->GetMesh();
|
||||||
|
|
||||||
|
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Mesh", std::to_string(SHResourceManager::GetAssetID<SHMesh>(mesh).value_or(0)).data(), [component]()
|
||||||
|
{
|
||||||
|
Handle<SHMesh> const& mesh = component->GetMesh();
|
||||||
|
return SHResourceManager::GetAssetID<SHMesh>(mesh).value_or(0);
|
||||||
|
},
|
||||||
|
[component](AssetID const& id)
|
||||||
|
{
|
||||||
|
component->SetMesh(SHResourceManager::LoadOrGet<SHMesh>(id));
|
||||||
|
}, SHDragDrop::DRAG_RESOURCE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawContextMenu(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "SHpch.h"
|
#include "SHpch.h"
|
||||||
|
|
||||||
#include "Editor/SHEditor.hpp"
|
#include "Editor/SHEditor.h"
|
||||||
#include "SHEditorInspector.h"
|
#include "SHEditorInspector.h"
|
||||||
|
|
||||||
#include "ECS_Base/SHECSMacros.h"
|
#include "ECS_Base/SHECSMacros.h"
|
||||||
|
@ -10,18 +10,15 @@
|
||||||
|
|
||||||
#include "Editor/SHImGuiHelpers.hpp"
|
#include "Editor/SHImGuiHelpers.hpp"
|
||||||
#include "Editor/SHEditorWidgets.hpp"
|
#include "Editor/SHEditorWidgets.hpp"
|
||||||
#include "SHEditorComponentView.hpp"
|
|
||||||
#include "ECS_Base/UnitTesting/SHTestComponents.h"
|
|
||||||
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||||
#include "Scripting/SHScriptEngine.h"
|
#include "Scripting/SHScriptEngine.h"
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
|
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
|
||||||
#include "AudioSystem/SHAudioSystem.h"
|
|
||||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
#include "Physics/Components/SHRigidBodyComponent.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Components/SHColliderComponent.h"
|
||||||
#include "Camera/SHCameraComponent.h"
|
#include "Camera/SHCameraComponent.h"
|
||||||
#include "Camera/SHCameraArmComponent.h"
|
#include "Camera/SHCameraArmComponent.h"
|
||||||
|
#include "SHEditorComponentView.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -31,8 +28,17 @@ namespace SHADE
|
||||||
bool selected = false;
|
bool selected = false;
|
||||||
if(!SHComponentManager::HasComponent<ComponentType>(eid))
|
if(!SHComponentManager::HasComponent<ComponentType>(eid))
|
||||||
{
|
{
|
||||||
if(selected = ImGui::Selectable(std::format("Add {}", rttr::type::get<ComponentType>().get_name().data()).data()); selected)
|
const char* componentName = rttr::type::get<ComponentType>().get_name().data();
|
||||||
|
if(selected = ImGui::Selectable(std::format("Add {}", componentName).data()); selected)
|
||||||
SHComponentManager::AddComponent<ComponentType>(eid);
|
SHComponentManager::AddComponent<ComponentType>(eid);
|
||||||
|
if(ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("Adds", componentName); ImGui::SameLine();
|
||||||
|
ImGui::TextColored(ImGuiColors::green, "%s", componentName); ImGui::SameLine();
|
||||||
|
ImGui::Text("to this entity", componentName);
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
|
@ -43,13 +49,26 @@ namespace SHADE
|
||||||
bool selected = false;
|
bool selected = false;
|
||||||
if (!SHComponentManager::HasComponent<ComponentType>(eid))
|
if (!SHComponentManager::HasComponent<ComponentType>(eid))
|
||||||
{
|
{
|
||||||
if(selected = ImGui::Selectable(std::format("Add {}", rttr::type::get<ComponentType>().get_name().data()).data()); selected)
|
const char* componentName = rttr::type::get<ComponentType>().get_name().data();
|
||||||
|
|
||||||
|
if(selected = ImGui::Selectable(std::format("Add {}", componentName).data()); selected)
|
||||||
{
|
{
|
||||||
if(SHComponentManager::GetComponent_s<EnforcedComponent>(eid) == nullptr)
|
if(SHComponentManager::GetComponent_s<EnforcedComponent>(eid) == nullptr)
|
||||||
SHComponentManager::AddComponent<EnforcedComponent>(eid);
|
SHComponentManager::AddComponent<EnforcedComponent>(eid);
|
||||||
|
|
||||||
SHComponentManager::AddComponent<ComponentType>(eid);
|
SHComponentManager::AddComponent<ComponentType>(eid);
|
||||||
}
|
}
|
||||||
|
if(ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("Adds", componentName); ImGui::SameLine();
|
||||||
|
ImGui::TextColored(ImGuiColors::green, "%s", componentName); ImGui::SameLine();
|
||||||
|
ImGui::Text("to this entity", componentName);
|
||||||
|
ImGui::Text("Adds"); ImGui::SameLine();
|
||||||
|
ImGui::TextColored(ImGuiColors::red, "%s", rttr::type::get<EnforcedComponent>().get_name().data()); ImGui::SameLine();
|
||||||
|
ImGui::Text("if the entity does not already have it");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
|
@ -101,6 +120,10 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
DrawComponent(rigidbodyComponent);
|
DrawComponent(rigidbodyComponent);
|
||||||
}
|
}
|
||||||
|
if(auto lightComponent = SHComponentManager::GetComponent_s<SHLightComponent>(eid))
|
||||||
|
{
|
||||||
|
DrawComponent(lightComponent);
|
||||||
|
}
|
||||||
if (auto cameraComponent = SHComponentManager::GetComponent_s<SHCameraComponent>(eid))
|
if (auto cameraComponent = SHComponentManager::GetComponent_s<SHCameraComponent>(eid))
|
||||||
{
|
{
|
||||||
DrawComponent(cameraComponent);
|
DrawComponent(cameraComponent);
|
||||||
|
@ -118,6 +141,7 @@ namespace SHADE
|
||||||
DrawAddComponentButton<SHTransformComponent>(eid);
|
DrawAddComponentButton<SHTransformComponent>(eid);
|
||||||
DrawAddComponentButton<SHCameraComponent>(eid);
|
DrawAddComponentButton<SHCameraComponent>(eid);
|
||||||
DrawAddComponentButton<SHCameraArmComponent>(eid);
|
DrawAddComponentButton<SHCameraArmComponent>(eid);
|
||||||
|
DrawAddComponentButton<SHLightComponent>(eid);
|
||||||
|
|
||||||
// Components that require Transforms
|
// Components that require Transforms
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
//|| SHADE Includes ||
|
//|| SHADE Includes ||
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
#include "Editor/SHEditor.hpp"
|
#include "Editor/SHEditor.h"
|
||||||
#include "SHEditorMenuBar.h"
|
#include "SHEditorMenuBar.h"
|
||||||
#include "Editor/IconsMaterialDesign.h"
|
#include "Editor/IconsMaterialDesign.h"
|
||||||
#include "Editor/Command/SHCommandManager.h"
|
#include "Editor/Command/SHCommandManager.h"
|
||||||
|
|
|
@ -5,13 +5,16 @@
|
||||||
#include "ImGuizmo.h"
|
#include "ImGuizmo.h"
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
#include "Editor/IconsMaterialDesign.h"
|
#include "Editor/IconsMaterialDesign.h"
|
||||||
#include "Editor/SHEditor.hpp"
|
#include "Editor/SHEditor.h"
|
||||||
#include "Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h"
|
#include "Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
|
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
|
||||||
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
|
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
|
||||||
#include <Editor/IconsFontAwesome6.h>
|
#include <Editor/IconsFontAwesome6.h>
|
||||||
|
|
||||||
|
#include "Camera/SHCameraSystem.h"
|
||||||
|
#include "FRC/SHFramerateController.h"
|
||||||
|
|
||||||
constexpr std::string_view windowName = "\xef\x80\x95 Viewport";
|
constexpr std::string_view windowName = "\xef\x80\x95 Viewport";
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
|
@ -30,8 +33,15 @@ namespace SHADE
|
||||||
void SHEditorViewport::Update()
|
void SHEditorViewport::Update()
|
||||||
{
|
{
|
||||||
SHEditorWindow::Update();
|
SHEditorWindow::Update();
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f,0.0f));
|
if (shouldUpdateCamera)
|
||||||
if(Begin())
|
{
|
||||||
|
auto camSystem = SHSystemManager::GetSystem<SHCameraSystem>();
|
||||||
|
camSystem->UpdateEditorCamera(SHFrameRateController::GetRawDeltaTime());
|
||||||
|
shouldUpdateCamera = false;
|
||||||
|
}
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||||
|
|
||||||
|
if (Begin())
|
||||||
{
|
{
|
||||||
ImGuizmo::SetDrawlist();
|
ImGuizmo::SetDrawlist();
|
||||||
DrawMenuBar();
|
DrawMenuBar();
|
||||||
|
@ -39,21 +49,38 @@ namespace SHADE
|
||||||
auto const& descriptorSet = gfxSystem->GetPostOffscreenRenderSystem()->GetDescriptorSetGroup()->GetVkHandle()[0];
|
auto const& descriptorSet = gfxSystem->GetPostOffscreenRenderSystem()->GetDescriptorSetGroup()->GetVkHandle()[0];
|
||||||
auto mousePos = ImGui::GetMousePos();
|
auto mousePos = ImGui::GetMousePos();
|
||||||
beginCursorPos = ImGui::GetCursorScreenPos();
|
beginCursorPos = ImGui::GetCursorScreenPos();
|
||||||
viewportMousePos = {mousePos.x - beginCursorPos.x, mousePos.y - beginCursorPos.y};
|
viewportMousePos = { mousePos.x - beginCursorPos.x, mousePos.y - beginCursorPos.y };
|
||||||
gfxSystem->GetMousePickSystem ()->SetViewportMousePos (viewportMousePos);
|
gfxSystem->GetMousePickSystem()->SetViewportMousePos(viewportMousePos);
|
||||||
|
|
||||||
ImGui::Image((ImTextureID)descriptorSet, {beginContentRegionAvailable.x, beginContentRegionAvailable.y});
|
ImGui::Image((ImTextureID)descriptorSet, { beginContentRegionAvailable.x, beginContentRegionAvailable.y });
|
||||||
|
|
||||||
if(ImGui::IsWindowHovered() && ImGui::IsMouseDown(ImGuiMouseButton_Right))
|
if (ImGui::IsWindowHovered() && ImGui::IsMouseDown(ImGuiMouseButton_Right))
|
||||||
{
|
{
|
||||||
ImGui::SetMouseCursor(ImGuiMouseCursor_None);
|
ImGui::SetMouseCursor(ImGuiMouseCursor_None);
|
||||||
ImGui::SetCursorScreenPos(ImGui::GetMousePos());
|
ImGui::SetCursorScreenPos(ImGui::GetMousePos());
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImGuiColors::green);
|
ImGui::PushStyleColor(ImGuiCol_Text, ImGuiColors::green);
|
||||||
ImGui::Text(ICON_FA_EYE);
|
ImGui::Text(ICON_FA_EYE);
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
|
shouldUpdateCamera = true;
|
||||||
|
}
|
||||||
|
if (ImGui::IsWindowFocused() && !ImGui::IsMouseDown(ImGuiMouseButton_Right))
|
||||||
|
{
|
||||||
|
if (ImGui::IsKeyReleased(ImGuiKey_Q))
|
||||||
|
{
|
||||||
|
transformGizmo.operation = SHTransformGizmo::Operation::TRANSLATE;
|
||||||
|
}
|
||||||
|
if (ImGui::IsKeyReleased(ImGuiKey_W))
|
||||||
|
{
|
||||||
|
transformGizmo.operation = SHTransformGizmo::Operation::ROTATE;
|
||||||
|
}
|
||||||
|
if (ImGui::IsKeyReleased(ImGuiKey_E))
|
||||||
|
{
|
||||||
|
transformGizmo.operation = SHTransformGizmo::Operation::SCALE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGuizmo::SetRect(beginCursorPos.x , beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y);
|
ImGuizmo::SetRect(beginCursorPos.x, beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y);
|
||||||
transformGizmo.Draw();
|
transformGizmo.Draw();
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
|
@ -72,11 +99,12 @@ namespace SHADE
|
||||||
|
|
||||||
//auto pos = ImGui::GetCursorPos();
|
//auto pos = ImGui::GetCursorPos();
|
||||||
//windowCursorPos = {}
|
//windowCursorPos = {}
|
||||||
if(beginContentRegionAvailable.x == 0 || beginContentRegionAvailable.y == 0)
|
if (beginContentRegionAvailable.x == 0 || beginContentRegionAvailable.y == 0)
|
||||||
{
|
{
|
||||||
beginContentRegionAvailable = windowSize;
|
beginContentRegionAvailable = windowSize;
|
||||||
}
|
}
|
||||||
gfxSystem->PrepareResize(static_cast<uint32_t>(beginContentRegionAvailable.x), static_cast<uint32_t>(beginContentRegionAvailable.y));
|
gfxSystem->PrepareResize(static_cast<uint32_t>(beginContentRegionAvailable.x), static_cast<uint32_t>(beginContentRegionAvailable.y));
|
||||||
|
shouldUpdateCamera = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHEditorViewport::OnPosChange()
|
void SHEditorViewport::OnPosChange()
|
||||||
|
@ -86,44 +114,63 @@ namespace SHADE
|
||||||
|
|
||||||
void SHEditorViewport::DrawMenuBar() noexcept
|
void SHEditorViewport::DrawMenuBar() noexcept
|
||||||
{
|
{
|
||||||
if(ImGui::BeginMenuBar())
|
if (ImGui::BeginMenuBar())
|
||||||
{
|
{
|
||||||
|
ImGui::BeginDisabled(ImGui::IsWindowFocused() && ImGui::IsMouseDown(ImGuiMouseButton_Right));
|
||||||
bool const isTranslate = transformGizmo.operation == SHTransformGizmo::Operation::TRANSLATE;
|
bool const isTranslate = transformGizmo.operation == SHTransformGizmo::Operation::TRANSLATE;
|
||||||
ImGui::BeginDisabled(isTranslate);
|
ImGui::BeginDisabled(isTranslate);
|
||||||
if(isTranslate)
|
if (isTranslate)
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_CheckMark]);
|
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_CheckMark]);
|
||||||
if(ImGui::Button(ICON_MD_OPEN_WITH))
|
if (ImGui::Button(ICON_MD_OPEN_WITH))
|
||||||
{
|
{
|
||||||
transformGizmo.operation = SHTransformGizmo::Operation::TRANSLATE;
|
transformGizmo.operation = SHTransformGizmo::Operation::TRANSLATE;
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
if(isTranslate)
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("Translate [Q]");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
if (isTranslate)
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
bool const isRotate = transformGizmo.operation == SHTransformGizmo::Operation::ROTATE;
|
bool const isRotate = transformGizmo.operation == SHTransformGizmo::Operation::ROTATE;
|
||||||
ImGui::BeginDisabled(isRotate);
|
ImGui::BeginDisabled(isRotate);
|
||||||
if(isRotate)
|
if (isRotate)
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_CheckMark]);
|
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_CheckMark]);
|
||||||
if(ImGui::Button(ICON_MD_AUTORENEW))
|
if (ImGui::Button(ICON_MD_AUTORENEW))
|
||||||
{
|
{
|
||||||
transformGizmo.operation = SHTransformGizmo::Operation::ROTATE;
|
transformGizmo.operation = SHTransformGizmo::Operation::ROTATE;
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
if(isRotate)
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("Rotate [W]");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
if (isRotate)
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
bool const isScale = transformGizmo.operation == SHTransformGizmo::Operation::SCALE;
|
bool const isScale = transformGizmo.operation == SHTransformGizmo::Operation::SCALE;
|
||||||
ImGui::BeginDisabled(isScale);
|
ImGui::BeginDisabled(isScale);
|
||||||
if(isScale)
|
if (isScale)
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_CheckMark]);
|
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_CheckMark]);
|
||||||
if(ImGui::Button(ICON_MD_EXPAND))
|
if (ImGui::Button(ICON_MD_EXPAND))
|
||||||
{
|
{
|
||||||
transformGizmo.operation = SHTransformGizmo::Operation::SCALE;
|
transformGizmo.operation = SHTransformGizmo::Operation::SCALE;
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
if(isScale)
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("Scale [E]");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
if (isScale)
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
ImGui::EndDisabled();
|
||||||
ImGui::EndMenuBar();
|
ImGui::EndMenuBar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
class SHEditorViewport final : public SHEditorWindow
|
class SHEditorViewport final : public SHEditorWindow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SHEditorViewport();
|
SHEditorViewport();
|
||||||
|
@ -28,5 +28,6 @@ namespace SHADE
|
||||||
private:
|
private:
|
||||||
void DrawMenuBar() noexcept;
|
void DrawMenuBar() noexcept;
|
||||||
SHVec2 beginCursorPos;
|
SHVec2 beginCursorPos;
|
||||||
|
bool shouldUpdateCamera = false;
|
||||||
};//class SHEditorViewport
|
};//class SHEditorViewport
|
||||||
}//namespace SHADE
|
}//namespace SHADE
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
#include "Editor/SHEditor.hpp"
|
#include "Editor/SHEditor.h"
|
||||||
#include "Editor/SHImGuiHelpers.hpp"
|
#include "Editor/SHImGuiHelpers.hpp"
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <ImGuizmo.h>
|
#include <ImGuizmo.h>
|
||||||
|
@ -63,6 +63,9 @@ namespace SHADE
|
||||||
if (selectedEntityTransformComponent == nullptr)
|
if (selectedEntityTransformComponent == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(!selectedEntityTransformComponent->isActive)
|
||||||
|
return;
|
||||||
|
|
||||||
SHMatrix mat = selectedEntityTransformComponent->GetTRS();
|
SHMatrix mat = selectedEntityTransformComponent->GetTRS();
|
||||||
useSnap = ImGui::IsKeyDown(ImGuiKey_LeftCtrl);
|
useSnap = ImGui::IsKeyDown(ImGuiKey_LeftCtrl);
|
||||||
if(useSnap)
|
if(useSnap)
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "Graphics/MiddleEnd/Interface/SHViewport.h"
|
#include "Graphics/MiddleEnd/Interface/SHViewport.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHRenderer.h"
|
#include "Graphics/MiddleEnd/Interface/SHRenderer.h"
|
||||||
|
|
||||||
#include "SHEditor.hpp"
|
#include "SHEditor.h"
|
||||||
#include "SHEditorWidgets.hpp"
|
#include "SHEditorWidgets.hpp"
|
||||||
|
|
||||||
#include "Math/Transform/SHTransformSystem.h"
|
#include "Math/Transform/SHTransformSystem.h"
|
||||||
|
@ -175,7 +175,7 @@ namespace SHADE
|
||||||
ImFontConfig icons_config{}; icons_config.MergeMode = true; icons_config.GlyphOffset.y = 5.f;
|
ImFontConfig icons_config{}; icons_config.MergeMode = true; icons_config.GlyphOffset.y = 5.f;
|
||||||
constexpr ImWchar icon_ranges_fa[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
|
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
|
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 };
|
constexpr ImWchar icon_ranges_md[] = { ICON_MIN_MD, ICON_MAX_16_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
|
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();
|
io->Fonts->Build();
|
||||||
}
|
}
|
||||||
|
@ -293,6 +293,7 @@ namespace SHADE
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
void SHEditor::InitBackend()
|
void SHEditor::InitBackend()
|
||||||
{
|
{
|
||||||
|
#ifdef SHEDITOR
|
||||||
if(ImGui_ImplSDL2_InitForVulkan(sdlWindow) == false)
|
if(ImGui_ImplSDL2_InitForVulkan(sdlWindow) == false)
|
||||||
{
|
{
|
||||||
SHLOG_CRITICAL("Editor backend initialisation; Failed to perform SDL initialisation for Vulkan")
|
SHLOG_CRITICAL("Editor backend initialisation; Failed to perform SDL initialisation for Vulkan")
|
||||||
|
@ -339,6 +340,7 @@ namespace SHADE
|
||||||
renderGraph->GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer>& cmd) {
|
renderGraph->GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer>& cmd) {
|
||||||
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd->GetVkCommandBuffer());
|
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd->GetVkCommandBuffer());
|
||||||
});
|
});
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHEditor::PollPicking()
|
void SHEditor::PollPicking()
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||||
#include "Resource/SHHandle.h"
|
#include "Resource/SHHandle.h"
|
||||||
#include "EditorWindow/SHEditorWindow.h"
|
#include "EditorWindow/SHEditorWindow.h"
|
||||||
#include "Tools/SHLogger.h"
|
#include "Tools/SHLog.h"
|
||||||
#include "Gizmos/SHTransformGizmo.h"
|
#include "Gizmos/SHTransformGizmo.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Attempt to create duplicate of Editor window type")
|
SHLog::Warning("Attempt to create duplicate of Editor window type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
bool SHEditorUI::CollapsingHeader(const std::string& title)
|
bool SHEditorUI::CollapsingHeader(const std::string& title)
|
||||||
{
|
{
|
||||||
return ImGui::CollapsingHeader(title.c_str());
|
return ImGui::CollapsingHeader(title.c_str(), ImGuiTreeNodeFlags_DefaultOpen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHEditorUI::SameLine()
|
void SHEditorUI::SameLine()
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#include <misc/cpp/imgui_stdlib.h>
|
#include <misc/cpp/imgui_stdlib.h>
|
||||||
#include <rttr/type.h>
|
#include <rttr/type.h>
|
||||||
|
|
||||||
|
#include "DragDrop/SHDragDrop.hpp"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
class SH_API SHEditorWidgets
|
class SH_API SHEditorWidgets
|
||||||
|
@ -41,7 +43,7 @@ namespace SHADE
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
|
|
||||||
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
|
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.2f));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
||||||
|
|
||||||
auto frameHeight = ImGui::GetFrameHeight();
|
auto frameHeight = ImGui::GetFrameHeight();
|
||||||
|
@ -86,7 +88,7 @@ namespace SHADE
|
||||||
|
|
||||||
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
|
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
|
||||||
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.2f));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
||||||
|
|
||||||
auto frameHeight = ImGui::GetFrameHeight();
|
auto frameHeight = ImGui::GetFrameHeight();
|
||||||
|
@ -127,7 +129,7 @@ namespace SHADE
|
||||||
|
|
||||||
ImGui::GetWindowDrawList()->AddRect(
|
ImGui::GetWindowDrawList()->AddRect(
|
||||||
frameRect.Min, frameRect.Max,
|
frameRect.Min, frameRect.Max,
|
||||||
ImColor(ImGui::GetStyleColorVec4(ImGuiCol_Button)),
|
ImColor(ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled)),
|
||||||
halfFrame.x);
|
halfFrame.x);
|
||||||
|
|
||||||
ImGui::PopClipRect();
|
ImGui::PopClipRect();
|
||||||
|
@ -174,15 +176,19 @@ namespace SHADE
|
||||||
ImGui::SetColumnWidth(-1, 80.0f);
|
ImGui::SetColumnWidth(-1, 80.0f);
|
||||||
ImGui::Text(label.c_str());
|
ImGui::Text(label.c_str());
|
||||||
if (isHovered)
|
if (isHovered)
|
||||||
*isHovered = ImGui::IsItemHovered();
|
*isHovered |= ImGui::IsItemHovered();
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
for (std::size_t i = 0; i < N; ++i)
|
for (std::size_t i = 0; i < N; ++i)
|
||||||
{
|
{
|
||||||
ImGui::PushID(static_cast<int>(i));
|
ImGui::PushID(static_cast<int>(i));
|
||||||
ImGui::TextUnformatted(componentLabels[i].c_str(), ImGui::FindRenderedTextEnd(componentLabels[i].c_str())); ImGui::SameLine();
|
ImGui::TextUnformatted(componentLabels[i].c_str(), ImGui::FindRenderedTextEnd(componentLabels[i].c_str()));
|
||||||
|
if (isHovered)
|
||||||
|
*isHovered |= ImGui::IsItemHovered();
|
||||||
|
ImGui::SameLine();
|
||||||
ImGui::SetNextItemWidth(80.0f);
|
ImGui::SetNextItemWidth(80.0f);
|
||||||
valueChanged |= ImGui::DragFloat("##v", values[i], speed, valueMin, valueMax, displayFormat, flags);
|
valueChanged |= ImGui::DragFloat("##v", values[i], speed, valueMin, valueMax, displayFormat, flags);
|
||||||
|
if (isHovered)
|
||||||
|
*isHovered |= ImGui::IsItemHovered();
|
||||||
const ImVec2 min = ImGui::GetItemRectMin();
|
const ImVec2 min = ImGui::GetItemRectMin();
|
||||||
const ImVec2 max = ImGui::GetItemRectMax();
|
const ImVec2 max = ImGui::GetItemRectMax();
|
||||||
const float spacing = g.Style.FrameRounding;
|
const float spacing = g.Style.FrameRounding;
|
||||||
|
@ -192,8 +198,8 @@ namespace SHADE
|
||||||
ImGuiColors::colors[i], 4);
|
ImGuiColors::colors[i], 4);
|
||||||
|
|
||||||
ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
|
ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
|
||||||
ImGui::PopID();
|
|
||||||
ImGui::PopItemWidth();
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
ImGui::EndColumns();
|
ImGui::EndColumns();
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
|
@ -203,23 +209,31 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragVec2(const std::string& label, std::vector<std::string>const& componentLabels, std::function<SHVec2(void)> get,
|
static bool DragVec2(const std::string& label, std::vector<std::string>const& componentLabels, std::function<SHVec2(void)> get,
|
||||||
std::function<void(SHVec2)> set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f,
|
std::function<void(SHVec2)> set, bool const& isAnAngleInRad = false, std::string_view const& tooltip = {}, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
||||||
ImGuiSliderFlags flags = 0)
|
ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
SHVec2 values = get();
|
SHVec2 values = get();
|
||||||
|
if(isAnAngleInRad)
|
||||||
|
{
|
||||||
|
values = {SHMath::RadiansToDegrees(values.x), SHMath::RadiansToDegrees(values.y)};
|
||||||
|
}
|
||||||
bool const changed = DragN<float, 2>(label, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags);
|
bool const changed = DragN<float, 2>(label, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags);
|
||||||
static bool startRecording = false;
|
static bool startRecording = false;
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
|
if(isAnAngleInRad)
|
||||||
|
{
|
||||||
|
values = {SHMath::DegreesToRadians(values.x), SHMath::DegreesToRadians(values.y)};
|
||||||
|
}
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), startRecording);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), startRecording);
|
||||||
if (!startRecording)
|
if (!startRecording)
|
||||||
startRecording = true;
|
startRecording = true;
|
||||||
}
|
}
|
||||||
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
startRecording = false;
|
startRecording = false;
|
||||||
if(!tooltip.empty())
|
if (!tooltip.empty())
|
||||||
{
|
{
|
||||||
if(ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
{
|
{
|
||||||
ImGui::BeginTooltip();
|
ImGui::BeginTooltip();
|
||||||
ImGui::Text(tooltip.data());
|
ImGui::Text(tooltip.data());
|
||||||
|
@ -230,17 +244,24 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragVec3(const std::string& label, std::vector<std::string>const& componentLabels, std::function<SHVec3(void)> get,
|
static bool DragVec3(const std::string& label, std::vector<std::string>const& componentLabels, std::function<SHVec3(void)> get,
|
||||||
std::function<void(SHVec3)> set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f,
|
std::function<void(SHVec3)> set, bool const& isAnAngleInRad = false, std::string_view const& tooltip = {}, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
||||||
ImGuiSliderFlags flags = 0)
|
ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
SHVec3 values = get();
|
SHVec3 values = get();
|
||||||
bool const changed = DragN<float, 3>(label, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags);
|
if(isAnAngleInRad)
|
||||||
|
{
|
||||||
|
values = {SHMath::RadiansToDegrees(values.x), SHMath::RadiansToDegrees(values.y), SHMath::RadiansToDegrees(values.z)};
|
||||||
|
}
|
||||||
|
bool isHovered = false;
|
||||||
|
bool const changed = DragN<float, 3>(label, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags, &isHovered);
|
||||||
static bool startRecording = false;
|
static bool startRecording = false;
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
SHVec3 old = get();
|
SHVec3 old = get();
|
||||||
|
if(isAnAngleInRad)
|
||||||
|
{
|
||||||
|
values = {SHMath::DegreesToRadians(values.x), SHMath::DegreesToRadians(values.y), SHMath::DegreesToRadians(values.z)};
|
||||||
|
}
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(old, values, set)), startRecording);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(old, values, set)), startRecording);
|
||||||
if (!startRecording)
|
if (!startRecording)
|
||||||
startRecording = true;
|
startRecording = true;
|
||||||
|
@ -249,9 +270,9 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
startRecording = false;
|
startRecording = false;
|
||||||
}
|
}
|
||||||
if(!tooltip.empty())
|
if (!tooltip.empty())
|
||||||
{
|
{
|
||||||
if(ImGui::IsItemHovered())
|
if (isHovered)
|
||||||
{
|
{
|
||||||
ImGui::BeginTooltip();
|
ImGui::BeginTooltip();
|
||||||
ImGui::Text(tooltip.data());
|
ImGui::Text(tooltip.data());
|
||||||
|
@ -262,14 +283,22 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragVec4(const std::string& label, std::vector<std::string>const& componentLabels, std::function<SHVec4(void)> get,
|
static bool DragVec4(const std::string& label, std::vector<std::string>const& componentLabels, std::function<SHVec4(void)> get,
|
||||||
std::function<void(SHVec4)> set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f,
|
std::function<void(SHVec4)> set, bool const& isAnAngleInRad = false, std::string_view const& tooltip = {}, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
||||||
ImGuiSliderFlags flags = 0)
|
ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
SHVec4 values = get();
|
SHVec4 values = get();
|
||||||
|
if(isAnAngleInRad)
|
||||||
|
{
|
||||||
|
values = {SHMath::RadiansToDegrees(values.x), SHMath::RadiansToDegrees(values.y), SHMath::RadiansToDegrees(values.z), SHMath::RadiansToDegrees(values.w)};
|
||||||
|
}
|
||||||
bool const changed = DragN<float, 4>(label, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags);
|
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;
|
static bool startRecording = false;
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
|
if(isAnAngleInRad)
|
||||||
|
{
|
||||||
|
values = {SHMath::DegreesToRadians(values.x), SHMath::DegreesToRadians(values.y), SHMath::DegreesToRadians(values.z), SHMath::DegreesToRadians(values.w)};
|
||||||
|
}
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), startRecording);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), startRecording);
|
||||||
if (!startRecording)
|
if (!startRecording)
|
||||||
startRecording = true;
|
startRecording = true;
|
||||||
|
@ -278,9 +307,9 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
startRecording = false;
|
startRecording = false;
|
||||||
}
|
}
|
||||||
if(!tooltip.empty())
|
if (!tooltip.empty())
|
||||||
{
|
{
|
||||||
if(ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
{
|
{
|
||||||
ImGui::BeginTooltip();
|
ImGui::BeginTooltip();
|
||||||
ImGui::Text(tooltip.data());
|
ImGui::Text(tooltip.data());
|
||||||
|
@ -297,7 +326,7 @@ namespace SHADE
|
||||||
static void TextLabel(std::string_view const& text, bool sameLine = true)
|
static void TextLabel(std::string_view const& text, bool sameLine = true)
|
||||||
{
|
{
|
||||||
const ImVec2 textSize = ImGui::CalcTextSize(text.data(), NULL, true);
|
const ImVec2 textSize = ImGui::CalcTextSize(text.data(), NULL, true);
|
||||||
if(textSize.x > 0.0f)
|
if (textSize.x > 0.0f)
|
||||||
{
|
{
|
||||||
ImGui::Text(text.data());
|
ImGui::Text(text.data());
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
@ -310,32 +339,32 @@ namespace SHADE
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
ImGui::PushID(label.data());
|
ImGui::PushID(label.data());
|
||||||
TextLabel(label);
|
TextLabel(label);
|
||||||
if (ImGui::Checkbox("##", &value))
|
bool const changed = ImGui::Checkbox("##", &value);
|
||||||
|
if (changed)
|
||||||
{
|
{
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
if(!tooltip.empty())
|
if (!tooltip.empty())
|
||||||
{
|
{
|
||||||
if(ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
{
|
{
|
||||||
ImGui::BeginTooltip();
|
ImGui::BeginTooltip();
|
||||||
ImGui::Text(tooltip.data());
|
ImGui::Text(tooltip.data());
|
||||||
ImGui::EndTooltip();
|
ImGui::EndTooltip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
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 = {})
|
static bool RadioButton(std::vector<std::string> const& label, std::vector<T> const& listTypes, std::function<T(void)> get, std::function<void(T const&)> set, std::string_view const& tooltip = {})
|
||||||
{
|
{
|
||||||
T type = get();
|
T type = get();
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
ImGui::PushID(label.data());
|
ImGui::PushID(label.data());
|
||||||
TextLabel(label);
|
//TextLabel(label);
|
||||||
for (size_t i = 0; i < listTypes.size(); i++)
|
for (size_t i = 0; i < listTypes.size(); i++)
|
||||||
{
|
{
|
||||||
if (ImGui::RadioButton(label[i].c_str(), type == listTypes[i]))
|
if (ImGui::RadioButton(label[i].c_str(), type == listTypes[i]))
|
||||||
|
@ -366,12 +395,11 @@ namespace SHADE
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
ImGui::PushID(label.data());
|
ImGui::PushID(label.data());
|
||||||
TextLabel(label);
|
TextLabel(label);
|
||||||
if (ImGui::InputText("##", &text, flag, callback, userData))
|
bool const changed = ImGui::InputText("##", &text, flag, callback, userData);
|
||||||
|
if (changed)
|
||||||
{
|
{
|
||||||
if (ImGui::IsItemDeactivatedAfterEdit())
|
if (ImGui::IsItemDeactivatedAfterEdit())
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<std::string>>(get(), text, set)), false);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<std::string>>(get(), text, set)), false);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
|
@ -384,7 +412,37 @@ namespace SHADE
|
||||||
ImGui::EndTooltip();
|
ImGui::EndTooltip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static bool DragDropReadOnlyField(std::string const& label, std::string_view const& fieldVTextValue, std::function<T (void)> const& get, std::function<void(T const&)> const& set, SHDragDrop::DragDropTag const& dragDropTag, std::string_view const& tooltip = {})
|
||||||
|
{
|
||||||
|
std::string text = fieldVTextValue.data();
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
bool const changed = ImGui::InputText("##", &text, ImGuiInputTextFlags_ReadOnly, nullptr, nullptr);
|
||||||
|
if(SHDragDrop::BeginTarget())
|
||||||
|
{
|
||||||
|
if(T* payload = SHDragDrop::AcceptPayload<T>(dragDropTag))
|
||||||
|
{
|
||||||
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), *payload, set)), false);
|
||||||
|
SHDragDrop::EndTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -442,9 +500,9 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
if(!tooltip.empty())
|
if (!tooltip.empty())
|
||||||
{
|
{
|
||||||
if(ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
{
|
{
|
||||||
ImGui::BeginTooltip();
|
ImGui::BeginTooltip();
|
||||||
ImGui::Text(tooltip.data());
|
ImGui::Text(tooltip.data());
|
||||||
|
@ -615,5 +673,43 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
return edited;
|
return edited;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ColorPicker(const std::string_view& label, std::function<SHVec4(void)> get, std::function<void(SHVec4 const&)> set, std::string_view const& tooltip = {}, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
||||||
|
ImGuiSliderFlags flags = 0)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
|
||||||
|
SHVec4 values = get();
|
||||||
|
//changed |= DragN<float, 4>(label.data(), {"R", "G", "B", "A"}, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags);
|
||||||
|
//ImGui::SameLine();
|
||||||
|
TextLabel(label);
|
||||||
|
changed = ImGui::ColorEdit4("##Col4", &values.x, ImGuiColorEditFlags_AlphaPreviewHalf | ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_DisplayRGB );
|
||||||
|
static bool startRecording = false;
|
||||||
|
if(changed)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}//namespace SHADE
|
}//namespace SHADE
|
||||||
|
|
|
@ -1,159 +1,82 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHFileSystem.cpp
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 30 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 "SHpch.h"
|
||||||
#include "SHFileSystem.h"
|
#include "SHFileSystem.h"
|
||||||
#include "fileapi.h"
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
#include "Assets/SHAssetMetaHandler.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
char const FOLDER_MAX_COUNT {15};
|
|
||||||
|
|
||||||
std::unordered_map<FolderLocation, std::unique_ptr<SHFolder>> SHFileSystem::folders;
|
|
||||||
FolderPointer SHFileSystem::root {nullptr};
|
|
||||||
|
|
||||||
SHFolder::SHFolder(FolderHandle id, FolderName name)
|
|
||||||
:id{ id }, name{ name }, subFolders(0), folded{ false }, path{""}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderLocation SHFileSystem::CreateNewFolderHere(FolderName name, FolderLocation here) noexcept
|
|
||||||
{
|
|
||||||
if (here == 0)
|
|
||||||
{
|
|
||||||
if (!folders.contains(0))
|
|
||||||
{
|
|
||||||
folders[0] = std::make_unique<SHFolder>(0, "root");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto const count = static_cast<FolderCounter>(folders[here]->subFolders.size());
|
|
||||||
|
|
||||||
if (count >= FOLDER_MAX_COUNT)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Max subfolder reached: {}\n", name);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto const location = static_cast<FolderLocation>(count);
|
|
||||||
|
|
||||||
CreateFolder(folders[0]->path, here, location, name);
|
|
||||||
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!folders.contains(here))
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Folder creation location does not exist/invalid: {}\n", here);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto const count = static_cast<FolderCounter>(folders[here]->subFolders.size());
|
|
||||||
|
|
||||||
FolderHandle location = here;
|
|
||||||
location <<= FOLDER_BIT_ALLOCATE;
|
|
||||||
location |= count;
|
|
||||||
|
|
||||||
if (count >= FOLDER_MAX_COUNT)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Max subfolder reached: {}\n", name);
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateFolder(folders[0]->path, here, location, name);
|
|
||||||
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SHFileSystem::DeleteFolder(FolderPointer location) noexcept
|
bool SHFileSystem::DeleteFolder(FolderPointer location) noexcept
|
||||||
{
|
{
|
||||||
if (!folders.contains(location->id))
|
//TODO IMPLEMENT
|
||||||
{
|
|
||||||
SHLOG_ERROR("Delete target does not exist/invalid: {}\n", location->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto const& subFolder : folders[location->id]->subFolders)
|
|
||||||
{
|
|
||||||
DeleteFolder(subFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoveDirectoryA(folders[location->id]->path.c_str());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHFileSystem::StartupFillDirectories(FolderPath path) noexcept
|
void SHFileSystem::BuildDirectory(FolderPath path, FolderPointer& root, std::unordered_map<AssetID, SHAsset>& assetCollection) noexcept
|
||||||
{
|
{
|
||||||
std::queue<FolderPointer> folderQueue;
|
std::queue<FolderPointer> folderQueue;
|
||||||
|
root = new SHFolder("root");
|
||||||
folderQueue.push(RegisterFolder(path, 0, 0, "Root"));
|
root->path = path;
|
||||||
|
folderQueue.push(root);
|
||||||
|
|
||||||
while (!folderQueue.empty())
|
while (!folderQueue.empty())
|
||||||
{
|
{
|
||||||
auto folder = folderQueue.front();
|
auto const folder = folderQueue.front();
|
||||||
folderQueue.pop();
|
folderQueue.pop();
|
||||||
FolderCounter count = 0;
|
|
||||||
|
std::vector<SHAsset> assets;
|
||||||
|
|
||||||
for (auto const& dirEntry : std::filesystem::directory_iterator(folder->path))
|
for (auto const& dirEntry : std::filesystem::directory_iterator(folder->path))
|
||||||
{
|
{
|
||||||
|
auto const& path = dirEntry.path();
|
||||||
if (!dirEntry.is_directory())
|
if (!dirEntry.is_directory())
|
||||||
{
|
{
|
||||||
folder->files.emplace_back(
|
if (path.extension().string() == META_EXTENSION)
|
||||||
dirEntry.path().filename().string(),
|
{
|
||||||
dirEntry.path().string(),
|
//auto asset = SHAssetMetaHandler::RetrieveMetaData(path);
|
||||||
dirEntry.path().extension().string()
|
//assetCollection.insert({ asset.id, asset });
|
||||||
);
|
assets.push_back(SHAssetMetaHandler::RetrieveMetaData(path));
|
||||||
|
}
|
||||||
continue;
|
else
|
||||||
|
{
|
||||||
|
folder->files.emplace_back(
|
||||||
|
path.stem().string(),
|
||||||
|
path.string(),
|
||||||
|
path.extension().string(),
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
FolderLocation location = folder->id;
|
auto newFolder{ folder->CreateSubFolderHere(path.stem().string()) };
|
||||||
location <<= FOLDER_BIT_ALLOCATE;
|
folderQueue.push(newFolder);
|
||||||
location |= ++count;
|
|
||||||
|
|
||||||
std::string name = dirEntry.path().string();
|
|
||||||
name = name.substr(name.find_last_of('/') + 1, name.length() - name.find_last_of('/'));
|
|
||||||
|
|
||||||
FolderPointer newFolder{ RegisterFolder(
|
|
||||||
dirEntry.path().string(),
|
|
||||||
folder->id,
|
|
||||||
location,
|
|
||||||
name)
|
|
||||||
};
|
|
||||||
|
|
||||||
folderQueue.push(newFolder);
|
|
||||||
folder->subFolders.push_back(newFolder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto const& asset : assets)
|
||||||
|
{
|
||||||
|
assetCollection.emplace(asset.id, asset);
|
||||||
|
for(auto& file : folder->files)
|
||||||
|
{
|
||||||
|
if (file.name == asset.name)
|
||||||
|
{
|
||||||
|
file.assetMeta = &assetCollection[asset.id];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FolderPointer SHFileSystem::GetRoot() noexcept
|
|
||||||
{
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderPointer SHFileSystem::CreateFolder(FolderPath path, FolderLocation parent, FolderHandle location, FolderName name) noexcept
|
|
||||||
{
|
|
||||||
|
|
||||||
if (!CreateDirectoryA(path.c_str(), nullptr))
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Failed to create folder: {}\n", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
folders[location] = std::make_unique<SHFolder>(location, name);
|
|
||||||
folders[location]->path = path;
|
|
||||||
folders[parent]->subFolders.push_back(folders[location].get());
|
|
||||||
|
|
||||||
return FolderMakeHelper(path, parent, location, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderPointer SHFileSystem::RegisterFolder(FolderPath path, FolderLocation parent, FolderHandle location,
|
|
||||||
FolderName name) noexcept
|
|
||||||
{
|
|
||||||
return FolderMakeHelper(path, parent, location, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderPointer SHFileSystem::FolderMakeHelper(FolderPath path, FolderLocation parent, FolderHandle location,
|
|
||||||
FolderName name) noexcept
|
|
||||||
{
|
|
||||||
folders[location] = std::make_unique<SHFolder>(location, name);
|
|
||||||
folders[location]->path = path;
|
|
||||||
folders[parent]->subFolders.push_back(folders[location].get());
|
|
||||||
|
|
||||||
return folders[location].get();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,70 +1,28 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* \file SHFileSystem.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 28 October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* \copyright Copyright (c) 2021 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
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include "SHFolder.h"
|
||||||
#include <vector>
|
|
||||||
#include <memory>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
class SHFolder;
|
|
||||||
|
|
||||||
typedef unsigned char FolderCounter;
|
|
||||||
typedef unsigned char FileCounter;
|
|
||||||
typedef uint64_t FolderLocation;
|
|
||||||
typedef uint64_t FolderHandle;
|
|
||||||
typedef std::string FolderName;
|
|
||||||
typedef std::string FileName;
|
|
||||||
typedef std::string FolderPath;
|
|
||||||
typedef std::string FilePath;
|
|
||||||
typedef std::string FileExt;
|
|
||||||
typedef SHFolder* FolderPointer;
|
|
||||||
|
|
||||||
constexpr char FOLDER_BIT_ALLOCATE{ 4 };
|
|
||||||
constexpr char FOLDER_MAX_DEPTH{ 16 };
|
|
||||||
|
|
||||||
struct SHFile
|
|
||||||
{
|
|
||||||
FileName name;
|
|
||||||
FilePath path;
|
|
||||||
FileExt ext;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SHFolder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SHFolder(FolderHandle id, FolderName name);
|
|
||||||
|
|
||||||
FolderHandle id;
|
|
||||||
FolderName name;
|
|
||||||
std::vector<FolderPointer> subFolders;
|
|
||||||
std::vector<SHFile> files;
|
|
||||||
|
|
||||||
bool folded;
|
|
||||||
|
|
||||||
private:
|
|
||||||
FolderPath path;
|
|
||||||
friend class SHFileSystem;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SHFileSystem
|
class SHFileSystem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static FolderLocation CreateNewFolderHere(FolderName name, FolderLocation here = 0) noexcept;
|
static void BuildDirectory(FolderPath path, FolderPointer& root, std::unordered_map<AssetID, SHAsset>& assetCollection) noexcept;
|
||||||
|
|
||||||
static bool DeleteFolder(FolderPointer location) noexcept;
|
|
||||||
|
|
||||||
static void StartupFillDirectories(FolderPath path) noexcept;
|
|
||||||
|
|
||||||
static FolderPointer GetRoot() noexcept;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static FolderPointer root;
|
static bool DeleteFolder(FolderPointer location) noexcept;
|
||||||
|
|
||||||
static std::unordered_map<FolderLocation, std::unique_ptr<SHFolder>> folders;
|
|
||||||
|
|
||||||
static FolderPointer CreateFolder(FolderPath path, FolderLocation parent, FolderHandle location, FolderName name) noexcept;
|
|
||||||
static FolderPointer RegisterFolder(FolderPath path, FolderLocation parent, FolderHandle location, FolderName name) noexcept;
|
|
||||||
static FolderPointer FolderMakeHelper(FolderPath path, FolderLocation parent, FolderHandle location, FolderName name) noexcept;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHFolder.cpp
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 30 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 "SHFolder.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
SHFolder::SHFolder(FolderName name)
|
||||||
|
:name{ name }, subFolders(0), folded{ false }, path{ "" }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FolderPointer SHFolder::CreateSubFolderHere(FolderName name)
|
||||||
|
{
|
||||||
|
for (auto const& folder : subFolders)
|
||||||
|
{
|
||||||
|
if (name == folder->name)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Unable to create subfolder {} at {} as it already exists", name, folder->name);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = new SHFolder(name);
|
||||||
|
result->path = path + "/" + name;
|
||||||
|
subFolders.push_back(result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* \file SHFolder.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 28 October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* \copyright Copyright (c) 2021 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 <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "Assets/SHAsset.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHFolder;
|
||||||
|
|
||||||
|
typedef unsigned char FolderCounter;
|
||||||
|
typedef unsigned char FileCounter;
|
||||||
|
typedef std::string FolderName;
|
||||||
|
typedef std::string FileName;
|
||||||
|
typedef std::string FolderPath;
|
||||||
|
typedef std::string FilePath;
|
||||||
|
typedef std::string FileExt;
|
||||||
|
typedef SHFolder* FolderPointer;
|
||||||
|
|
||||||
|
struct SHFile
|
||||||
|
{
|
||||||
|
FileName name;
|
||||||
|
FilePath path;
|
||||||
|
FileExt ext;
|
||||||
|
SHAsset const* assetMeta;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SHFolder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SHFolder(FolderName name);
|
||||||
|
|
||||||
|
FolderName name;
|
||||||
|
std::vector<FolderPointer> subFolders;
|
||||||
|
std::vector<SHFile> files;
|
||||||
|
|
||||||
|
bool folded;
|
||||||
|
|
||||||
|
FolderPointer CreateSubFolderHere(FolderName name);
|
||||||
|
FolderPath path;
|
||||||
|
};
|
||||||
|
}
|
|
@ -186,9 +186,10 @@ namespace SHADE
|
||||||
vk::PhysicalDeviceFeatures features{}; // ADD MORE FEATURES HERE IF NEEDED
|
vk::PhysicalDeviceFeatures features{}; // ADD MORE FEATURES HERE IF NEEDED
|
||||||
|
|
||||||
// point and lines fill mode
|
// point and lines fill mode
|
||||||
features.fillModeNonSolid = true;
|
features.fillModeNonSolid = VK_TRUE;
|
||||||
features.samplerAnisotropy = VK_TRUE;
|
features.samplerAnisotropy = VK_TRUE;
|
||||||
features.multiDrawIndirect = true;
|
features.multiDrawIndirect = VK_TRUE;
|
||||||
|
features.independentBlend = VK_TRUE;
|
||||||
|
|
||||||
// for wide lines
|
// for wide lines
|
||||||
features.wideLines = true;
|
features.wideLines = true;
|
||||||
|
|
|
@ -45,16 +45,20 @@ namespace SHADE
|
||||||
|
|
||||||
void SHBatch::Add(const SHRenderable* renderable)
|
void SHBatch::Add(const SHRenderable* renderable)
|
||||||
{
|
{
|
||||||
|
// Ignore if null
|
||||||
|
if (!renderable->GetMesh())
|
||||||
|
return;
|
||||||
|
|
||||||
// Check if we have a SubBatch with the same mesh yet
|
// Check if we have a SubBatch with the same mesh yet
|
||||||
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
||||||
{
|
{
|
||||||
return batch.Mesh == renderable->Mesh;
|
return batch.Mesh == renderable->GetMesh();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create one if not found
|
// Create one if not found
|
||||||
if (subBatch == subBatches.end())
|
if (subBatch == subBatches.end())
|
||||||
{
|
{
|
||||||
subBatches.emplace_back(renderable->Mesh);
|
subBatches.emplace_back(renderable->GetMesh());
|
||||||
subBatch = subBatches.end() - 1;
|
subBatch = subBatches.end() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +77,7 @@ namespace SHADE
|
||||||
// Check if we have a SubBatch with the same mesh yet
|
// Check if we have a SubBatch with the same mesh yet
|
||||||
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
||||||
{
|
{
|
||||||
return batch.Mesh == renderable->Mesh;
|
return batch.Mesh == renderable->GetMesh();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Attempt to remove if it exists
|
// Attempt to remove if it exists
|
||||||
|
@ -84,13 +88,18 @@ namespace SHADE
|
||||||
|
|
||||||
// Check if other renderables in subBatches contain the same material instance
|
// Check if other renderables in subBatches contain the same material instance
|
||||||
bool matUnused = true;
|
bool matUnused = true;
|
||||||
|
|
||||||
|
Handle<SHMaterialInstance> matToCheck = renderable->HasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial();
|
||||||
|
|
||||||
for (const auto& sb : subBatches)
|
for (const auto& sb : subBatches)
|
||||||
|
{
|
||||||
|
// Check material usage
|
||||||
for (const auto& rendId : sb.Renderables)
|
for (const auto& rendId : sb.Renderables)
|
||||||
{
|
{
|
||||||
auto rend = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
auto rend = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
if (rend)
|
if (rend)
|
||||||
{
|
{
|
||||||
if (rend->GetMaterial() == renderable->GetMaterial())
|
if (rend->GetMaterial() == matToCheck)
|
||||||
{
|
{
|
||||||
matUnused = false;
|
matUnused = false;
|
||||||
break;
|
break;
|
||||||
|
@ -101,10 +110,15 @@ namespace SHADE
|
||||||
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Material is no longer in this library, so we remove it
|
// Material is no longer in this library, so we remove it
|
||||||
if (matUnused)
|
if (matUnused)
|
||||||
referencedMatInstances.erase(renderable->WasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial());
|
referencedMatInstances.erase(renderable->HasChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial());
|
||||||
|
|
||||||
|
// Mesh is no longer in this batch, so we remove the associated sub batch
|
||||||
|
if (subBatch->Renderables.empty())
|
||||||
|
subBatches.erase(subBatch);
|
||||||
|
|
||||||
// Mark all as dirty
|
// Mark all as dirty
|
||||||
setAllDirtyFlags();
|
setAllDirtyFlags();
|
||||||
|
@ -180,7 +194,8 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
||||||
}
|
}
|
||||||
propsCurrPtr += singleMatPropAlignedSize;
|
//propsCurrPtr += singleMatPropAlignedSize;
|
||||||
|
propsCurrPtr += singleMatPropSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transfer to GPU
|
// Transfer to GPU
|
||||||
|
@ -302,7 +317,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
singleMatPropSize = SHADER_INFO->GetBytesRequired();
|
singleMatPropSize = SHADER_INFO->GetBytesRequired();
|
||||||
singleMatPropAlignedSize = device->PadSSBOSize(static_cast<uint32_t>(singleMatPropSize));
|
singleMatPropAlignedSize = device->PadSSBOSize(static_cast<uint32_t>(singleMatPropSize));
|
||||||
matPropTotalBytes = numTotalElements * singleMatPropAlignedSize;
|
matPropTotalBytes = numTotalElements * singleMatPropSize;
|
||||||
if (matPropsDataSize < matPropTotalBytes)
|
if (matPropsDataSize < matPropTotalBytes)
|
||||||
{
|
{
|
||||||
matPropsData.reset(new char[matPropTotalBytes]);
|
matPropsData.reset(new char[matPropTotalBytes]);
|
||||||
|
@ -361,7 +376,8 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
||||||
}
|
}
|
||||||
propsCurrPtr += singleMatPropAlignedSize;
|
//propsCurrPtr += singleMatPropAlignedSize;
|
||||||
|
propsCurrPtr += singleMatPropSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,36 +47,35 @@ namespace SHADE
|
||||||
// For global data (generic data and textures)
|
// For global data (generic data and textures)
|
||||||
Handle<SHVkDescriptorSetLayout> staticGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,{ genericDataBinding, texturesBinding });
|
Handle<SHVkDescriptorSetLayout> staticGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,{ genericDataBinding, texturesBinding });
|
||||||
|
|
||||||
|
|
||||||
std::vector<SHVkDescriptorSetLayout::Binding> lightBindings{};
|
std::vector<SHVkDescriptorSetLayout::Binding> lightBindings{};
|
||||||
for (uint32_t i = 0; i < SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES); ++i)
|
|
||||||
|
// This is the binding we use to count the lights (binding 0)
|
||||||
|
lightBindings.push_back(SHVkDescriptorSetLayout::Binding
|
||||||
|
{
|
||||||
|
.Type = vk::DescriptorType::eUniformBufferDynamic,
|
||||||
|
.Stage = vk::ShaderStageFlagBits::eCompute,
|
||||||
|
.BindPoint = 0,
|
||||||
|
.DescriptorCount = 1,
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
for (uint32_t i = 1; i <= SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES); ++i)
|
||||||
{
|
{
|
||||||
lightBindings.push_back (SHVkDescriptorSetLayout::Binding
|
lightBindings.push_back (SHVkDescriptorSetLayout::Binding
|
||||||
{
|
{
|
||||||
.Type = vk::DescriptorType::eStorageBufferDynamic,
|
.Type = vk::DescriptorType::eStorageBufferDynamic,
|
||||||
.Stage = vk::ShaderStageFlagBits::eFragment,
|
.Stage = vk::ShaderStageFlagBits::eCompute,
|
||||||
.BindPoint = i,
|
.BindPoint = i,
|
||||||
.DescriptorCount = 1,
|
.DescriptorCount = 1,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//SHVkDescriptorSetLayout::Binding pointLightBinding
|
|
||||||
//{
|
|
||||||
// .Type = vk::DescriptorType::eStorageBufferDynamic,
|
|
||||||
// .Stage = vk::ShaderStageFlagBits::eFragment,
|
|
||||||
// .BindPoint = SHGraphicsConstants::DescriptorSetBindings::POINT_LIGHT_DATA,
|
|
||||||
// .DescriptorCount = 1,
|
|
||||||
//};
|
|
||||||
|
|
||||||
//SHVkDescriptorSetLayout::Binding spotLightBinding
|
|
||||||
//{
|
|
||||||
// .Type = vk::DescriptorType::eStorageBufferDynamic,
|
|
||||||
// .Stage = vk::ShaderStageFlagBits::eFragment,
|
|
||||||
// .BindPoint = SHGraphicsConstants::DescriptorSetBindings::SPOT_LIGHT_DATA,
|
|
||||||
// .DescriptorCount = 1,
|
|
||||||
//};
|
|
||||||
|
|
||||||
// For Dynamic global data (lights)
|
// For Dynamic global data (lights)
|
||||||
Handle<SHVkDescriptorSetLayout> dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, lightBindings);
|
Handle<SHVkDescriptorSetLayout> dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, lightBindings);
|
||||||
|
|
||||||
|
|
||||||
SHVkDescriptorSetLayout::Binding cameraDataBinding
|
SHVkDescriptorSetLayout::Binding cameraDataBinding
|
||||||
{
|
{
|
||||||
.Type = vk::DescriptorType::eUniformBufferDynamic,
|
.Type = vk::DescriptorType::eUniformBufferDynamic,
|
||||||
|
|
|
@ -94,32 +94,14 @@ namespace SHADE
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
static constexpr uint32_t IMAGE_AND_SAMPLERS_DATA = 1;
|
static constexpr uint32_t IMAGE_AND_SAMPLERS_DATA = 1;
|
||||||
|
|
||||||
///***************************************************************************/
|
/***************************************************************************/
|
||||||
///*!
|
/*!
|
||||||
// \brief
|
\brief
|
||||||
// DescriptorSet binding for directional lights.
|
DescriptorSet binding for combined image sampler data.
|
||||||
|
|
||||||
//*/
|
*/
|
||||||
///***************************************************************************/
|
/***************************************************************************/
|
||||||
//static constexpr uint32_t DIRECTIONAL_LIGHT_DATA = 0;
|
static constexpr uint32_t LIGHTING_COUNT = 0;
|
||||||
|
|
||||||
///***************************************************************************/
|
|
||||||
///*!
|
|
||||||
// \brief
|
|
||||||
// DescriptorSet binding for directional lights.
|
|
||||||
|
|
||||||
//*/
|
|
||||||
///***************************************************************************/
|
|
||||||
//static constexpr uint32_t POINT_LIGHT_DATA = 1;
|
|
||||||
|
|
||||||
///***************************************************************************/
|
|
||||||
///*!
|
|
||||||
// \brief
|
|
||||||
// DescriptorSet binding for directional lights.
|
|
||||||
|
|
||||||
//*/
|
|
||||||
///***************************************************************************/
|
|
||||||
//static constexpr uint32_t SPOT_LIGHT_DATA = 2;
|
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -17,7 +17,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Graphics/Windowing/Surface/SHVkSurface.h"
|
#include "Graphics/Windowing/Surface/SHVkSurface.h"
|
||||||
#include "Graphics/Swapchain/SHVkSwapchain.h"
|
#include "Graphics/Swapchain/SHVkSwapchain.h"
|
||||||
#include "Camera/SHCameraSystem.h"
|
#include "Camera/SHCameraSystem.h"
|
||||||
#include "Editor/SHEditor.hpp"
|
#include "Editor/SHEditor.h"
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
//#include "SHRenderer.h"
|
//#include "SHRenderer.h"
|
||||||
#include "Graphics/Windowing/SHWindow.h"
|
#include "Graphics/Windowing/SHWindow.h"
|
||||||
|
@ -73,15 +73,7 @@ namespace SHADE
|
||||||
if (width == 0 || height == 0)
|
if (width == 0 || height == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
PrepareResize(resizeWidth, resizeHeight);
|
||||||
|
|
||||||
//PrepareResize(1, 1, SHVec2(0, 0));
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
PrepareResize(resizeWidth, resizeHeight, SHVec2(0, 0));
|
|
||||||
|
|
||||||
#endif
|
|
||||||
});
|
});
|
||||||
|
|
||||||
window->RegisterWindowCloseCallback([&](void)
|
window->RegisterWindowCloseCallback([&](void)
|
||||||
|
@ -118,24 +110,8 @@ namespace SHADE
|
||||||
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
|
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
|
||||||
|
|
||||||
|
|
||||||
// TODO: This is VERY temporarily here until a more solid resource management system is implemented
|
shaderModuleLibrary.ImportAllShaderSource(device);
|
||||||
shaderSourceLibrary.Init("../../TempShaderFolder/");
|
shaderModuleLibrary.ReflectAllShaderModules();
|
||||||
|
|
||||||
shaderSourceLibrary.LoadShader(0, "TestCubeVs.glsl", SH_SHADER_TYPE::VERTEX, true);
|
|
||||||
shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, true);
|
|
||||||
|
|
||||||
shaderSourceLibrary.LoadShader(2, "KirschCs.glsl", SH_SHADER_TYPE::COMPUTE, true);
|
|
||||||
shaderSourceLibrary.LoadShader(3, "PureCopyCs.glsl", SH_SHADER_TYPE::COMPUTE, true);
|
|
||||||
|
|
||||||
shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
|
|
||||||
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
|
|
||||||
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
|
|
||||||
auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
|
|
||||||
auto pureCopy = shaderModuleLibrary.GetShaderModule("PureCopyCs.glsl");
|
|
||||||
cubeVS->Reflect();
|
|
||||||
cubeFS->Reflect();
|
|
||||||
greyscale->Reflect();
|
|
||||||
pureCopy->Reflect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
|
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
|
||||||
|
@ -176,26 +152,45 @@ namespace SHADE
|
||||||
|
|
||||||
// Initialize world render graph
|
// Initialize world render graph
|
||||||
worldRenderGraph->Init(device, swapchain);
|
worldRenderGraph->Init(device, swapchain);
|
||||||
worldRenderGraph->AddResource("Scene Pre-Process", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
worldRenderGraph->AddResource("Position", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||||
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
worldRenderGraph->AddResource("Normals", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||||
|
worldRenderGraph->AddResource("Albedo", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
||||||
worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
||||||
worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||||
worldRenderGraph->AddResource("Light Layer Indices", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
worldRenderGraph->AddResource("Light Layer Indices", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||||
|
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
||||||
|
|
||||||
|
auto gBufferNode = worldRenderGraph->AddNode("G-Buffer",
|
||||||
|
{
|
||||||
|
"Position",
|
||||||
|
"Entity ID",
|
||||||
|
"Light Layer Indices",
|
||||||
|
"Normals",
|
||||||
|
"Albedo",
|
||||||
|
"Depth Buffer",
|
||||||
|
"Scene"
|
||||||
|
},
|
||||||
|
{}); // no predecessors
|
||||||
|
|
||||||
auto gBufferNode = worldRenderGraph->AddNode("G-Buffer", { "Light Layer Indices", "Entity ID", "Depth Buffer", "Scene", "Scene Pre-Process"}, {}); // no predecessors
|
|
||||||
auto gBufferSubpass = gBufferNode->AddSubpass("G-Buffer Write");
|
auto gBufferSubpass = gBufferNode->AddSubpass("G-Buffer Write");
|
||||||
gBufferSubpass->AddColorOutput("Scene Pre-Process");
|
gBufferSubpass->AddColorOutput("Position");
|
||||||
gBufferSubpass->AddColorOutput("Entity ID");
|
gBufferSubpass->AddColorOutput("Entity ID");
|
||||||
gBufferSubpass->AddColorOutput("Light Layer Indices");
|
gBufferSubpass->AddColorOutput("Light Layer Indices");
|
||||||
|
gBufferSubpass->AddColorOutput("Normals");
|
||||||
|
gBufferSubpass->AddColorOutput("Albedo");
|
||||||
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
|
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
|
||||||
|
|
||||||
//// kirsch
|
//// kirsch
|
||||||
//auto kirschShader = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
|
//auto kirschShader = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
|
||||||
//gBufferNode->AddNodeCompute(kirschShader, { "Scene Pre-Process", "Scene" });
|
//gBufferNode->AddNodeCompute(kirschShader, { "Position", "Scene" });
|
||||||
|
|
||||||
// copy
|
//// copy
|
||||||
auto pureCopyShader = shaderModuleLibrary.GetShaderModule("PureCopyCs.glsl");
|
//auto pureCopyShader = shaderModuleLibrary.GetShaderModule("PureCopyCs.glsl");
|
||||||
gBufferNode->AddNodeCompute(pureCopyShader, { "Scene Pre-Process", "Scene" });
|
//gBufferNode->AddNodeCompute(pureCopyShader, { "Position", "Scene" });
|
||||||
|
|
||||||
|
// deferred composite
|
||||||
|
auto deferredCompositeShader = shaderModuleLibrary.GetBuiltInShaderModule("DeferredComposite_CS");
|
||||||
|
gBufferNode->AddNodeCompute(deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "Scene" });
|
||||||
|
|
||||||
|
|
||||||
auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, {"G-Buffer"}); // no predecessors
|
auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, {"G-Buffer"}); // no predecessors
|
||||||
|
@ -212,11 +207,10 @@ namespace SHADE
|
||||||
|
|
||||||
worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
|
worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
|
||||||
|
|
||||||
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
|
auto cubeVS = shaderModuleLibrary.GetBuiltInShaderModule("TestCube_VS");
|
||||||
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
|
auto cubeFS = shaderModuleLibrary.GetBuiltInShaderModule("TestCube_FS");
|
||||||
|
|
||||||
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferSubpass);
|
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferSubpass);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHGraphicsSystem::InitMiddleEnd(void) noexcept
|
void SHGraphicsSystem::InitMiddleEnd(void) noexcept
|
||||||
|
@ -328,6 +322,12 @@ namespace SHADE
|
||||||
void SHGraphicsSystem::Run(double) noexcept
|
void SHGraphicsSystem::Run(double) noexcept
|
||||||
{
|
{
|
||||||
if (window->IsMinimized() || renderContext.GetWindowIsDead())
|
if (window->IsMinimized() || renderContext.GetWindowIsDead())
|
||||||
|
{
|
||||||
|
restoredFromMinimize = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (restoredFromMinimize)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Frame data for the current frame
|
// Frame data for the current frame
|
||||||
|
@ -379,6 +379,7 @@ namespace SHADE
|
||||||
|
|
||||||
// Force set the pipeline layout
|
// Force set the pipeline layout
|
||||||
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout(), SH_PIPELINE_TYPE::GRAPHICS);
|
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout(), SH_PIPELINE_TYPE::GRAPHICS);
|
||||||
|
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout(), SH_PIPELINE_TYPE::COMPUTE);
|
||||||
|
|
||||||
// Bind all the buffers required for meshes
|
// Bind all the buffers required for meshes
|
||||||
for (auto& [buffer, bindingPoint] : MESH_DATA)
|
for (auto& [buffer, bindingPoint] : MESH_DATA)
|
||||||
|
@ -461,7 +462,15 @@ namespace SHADE
|
||||||
void SHGraphicsSystem::BeginRender()
|
void SHGraphicsSystem::BeginRender()
|
||||||
{
|
{
|
||||||
if (window->IsMinimized() || renderContext.GetWindowIsDead())
|
if (window->IsMinimized() || renderContext.GetWindowIsDead())
|
||||||
|
{
|
||||||
|
restoredFromMinimize = true;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (restoredFromMinimize)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Finalise all batches
|
// Finalise all batches
|
||||||
for (auto vp : viewports)
|
for (auto vp : viewports)
|
||||||
|
@ -510,7 +519,17 @@ namespace SHADE
|
||||||
void SHGraphicsSystem::EndRender()
|
void SHGraphicsSystem::EndRender()
|
||||||
{
|
{
|
||||||
if (window->IsMinimized() || renderContext.GetWindowIsDead())
|
if (window->IsMinimized() || renderContext.GetWindowIsDead())
|
||||||
|
{
|
||||||
|
restoredFromMinimize = true;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (restoredFromMinimize)
|
||||||
|
{
|
||||||
|
restoredFromMinimize = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
|
const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
|
||||||
auto& currFrameData = renderContext.GetCurrentFrameData();
|
auto& currFrameData = renderContext.GetCurrentFrameData();
|
||||||
|
@ -696,7 +715,7 @@ namespace SHADE
|
||||||
auto& renderables = SHComponentManager::GetDense<SHRenderable>();
|
auto& renderables = SHComponentManager::GetDense<SHRenderable>();
|
||||||
for (auto& renderable : renderables)
|
for (auto& renderable : renderables)
|
||||||
{
|
{
|
||||||
if (!renderable.WasMaterialChanged())
|
if (!renderable.HasChanged())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Remove from old material's SuperBatch
|
// Remove from old material's SuperBatch
|
||||||
|
@ -784,5 +803,10 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Handle<SHRenderGraphNode> SHGraphicsSystem::GetPrimaryRenderpass() const noexcept
|
||||||
|
{
|
||||||
|
return worldRenderGraph->GetNode(G_BUFFER_RENDER_GRAPH_NODE_NAME.data());
|
||||||
|
}
|
||||||
|
|
||||||
#pragma endregion MISC
|
#pragma endregion MISC
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||||
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
|
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
|
||||||
#include "Graphics/RenderGraph/SHRenderGraph.h"
|
#include "Graphics/RenderGraph/SHRenderGraph.h"
|
||||||
#include "Graphics/MiddleEnd/Shaders/SHShaderSourceLibrary.h"
|
|
||||||
#include "Graphics/MiddleEnd/Shaders/SHShaderModuleLibrary.h"
|
#include "Graphics/MiddleEnd/Shaders/SHShaderModuleLibrary.h"
|
||||||
#include "SHMeshLibrary.h"
|
#include "SHMeshLibrary.h"
|
||||||
#include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h"
|
#include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h"
|
||||||
|
@ -136,7 +135,7 @@ namespace SHADE
|
||||||
void RemoveViewport(Handle<SHViewport> viewport);
|
void RemoveViewport(Handle<SHViewport> viewport);
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Material Creation Functions */
|
/* Material Functions */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
Handle<SHMaterial> AddMaterial(Handle<SHVkShaderModule> vertShader, Handle<SHVkShaderModule> fragShader, Handle<SHSubpass> subpass);
|
Handle<SHMaterial> AddMaterial(Handle<SHVkShaderModule> vertShader, Handle<SHVkShaderModule> fragShader, Handle<SHSubpass> subpass);
|
||||||
void RemoveMaterial(Handle<SHMaterial> material);
|
void RemoveMaterial(Handle<SHMaterial> material);
|
||||||
|
@ -144,6 +143,8 @@ namespace SHADE
|
||||||
Handle<SHMaterialInstance> AddOrGetBaseMaterialInstance(Handle<SHMaterial> material);
|
Handle<SHMaterialInstance> AddOrGetBaseMaterialInstance(Handle<SHMaterial> material);
|
||||||
Handle<SHMaterialInstance> AddMaterialInstanceCopy(Handle<SHMaterialInstance> materialInst);
|
Handle<SHMaterialInstance> AddMaterialInstanceCopy(Handle<SHMaterialInstance> materialInst);
|
||||||
void RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance);
|
void RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance);
|
||||||
|
Handle<SHMaterial> GetDefaultMaterial() { return defaultMaterial; }
|
||||||
|
Handle<SHMaterialInstance> GetDefaultMaterialInstance() { return AddOrGetBaseMaterialInstance(defaultMaterial); }
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Mesh Registration Functions */
|
/* Mesh Registration Functions */
|
||||||
|
@ -287,12 +288,21 @@ namespace SHADE
|
||||||
#endif
|
#endif
|
||||||
Handle<SHMousePickSystem> GetMousePickSystem(void) const noexcept {return mousePickSystem;};
|
Handle<SHMousePickSystem> GetMousePickSystem(void) const noexcept {return mousePickSystem;};
|
||||||
Handle<SHPostOffscreenRenderSystem> GetPostOffscreenRenderSystem(void) const noexcept {return postOffscreenRender;};
|
Handle<SHPostOffscreenRenderSystem> GetPostOffscreenRenderSystem(void) const noexcept {return postOffscreenRender;};
|
||||||
|
Handle<SHRenderGraphNode> GetPrimaryRenderpass() const noexcept;
|
||||||
//SHRenderGraph const& GetRenderGraph(void) const noexcept;
|
//SHRenderGraph const& GetRenderGraph(void) const noexcept;
|
||||||
|
|
||||||
//Handle<SHVkRenderpass> GetRenderPass() const { return renderPass; }
|
//Handle<SHVkRenderpass> GetRenderPass() const { return renderPass; }
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Getters */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
SHWindow* GetWindow() noexcept { return window; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constants */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
static constexpr std::string_view G_BUFFER_RENDER_GRAPH_NODE_NAME = "G-Buffer";
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
|
@ -314,12 +324,12 @@ namespace SHADE
|
||||||
SHWindow* window = nullptr;
|
SHWindow* window = nullptr;
|
||||||
|
|
||||||
// Middle End Resources
|
// Middle End Resources
|
||||||
SHResourceHub resourceManager;
|
SHResourceHub resourceManager;
|
||||||
SHMeshLibrary meshLibrary;
|
SHMeshLibrary meshLibrary;
|
||||||
SHTextureLibrary texLibrary;
|
SHTextureLibrary texLibrary;
|
||||||
SHSamplerCache samplerCache;
|
SHSamplerCache samplerCache;
|
||||||
SHMaterialInstanceCache materialInstanceCache;
|
SHMaterialInstanceCache materialInstanceCache;
|
||||||
// Viewports
|
// Viewports
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
Handle<SHViewport> editorViewport;
|
Handle<SHViewport> editorViewport;
|
||||||
Handle<SHRenderer> editorRenderer;
|
Handle<SHRenderer> editorRenderer;
|
||||||
|
@ -339,9 +349,7 @@ namespace SHADE
|
||||||
// Temp Cameras
|
// Temp Cameras
|
||||||
Handle<SHCamera> worldCamera;
|
Handle<SHCamera> worldCamera;
|
||||||
Handle<SHCamera> screenCamera;
|
Handle<SHCamera> screenCamera;
|
||||||
|
|
||||||
// TODO: Temporary only until resource library from Xiao Qi is implemented
|
|
||||||
SHShaderSourceLibrary shaderSourceLibrary;
|
|
||||||
SHShaderModuleLibrary shaderModuleLibrary;
|
SHShaderModuleLibrary shaderModuleLibrary;
|
||||||
|
|
||||||
// Temp Materials
|
// Temp Materials
|
||||||
|
@ -356,5 +364,7 @@ namespace SHADE
|
||||||
|
|
||||||
uint32_t resizeWidth;
|
uint32_t resizeWidth;
|
||||||
uint32_t resizeHeight;
|
uint32_t resizeHeight;
|
||||||
|
bool restoredFromMinimize = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHGraphicsSystemInterface.cpp
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 31, 2022
|
||||||
|
\brief Contains the definitions of the functions of the static
|
||||||
|
SHGraphicsSystemInterface class.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Headers
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "SHGraphicsSystemInterface.h"
|
||||||
|
// Project Includes
|
||||||
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
|
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
|
||||||
|
#include "Graphics/Windowing/SHWindow.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Static Usage Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
uint32_t SHGraphicsSystemInterface::GetWindowWidth()
|
||||||
|
{
|
||||||
|
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
|
||||||
|
if (gfxSystem)
|
||||||
|
{
|
||||||
|
const auto WND = gfxSystem->GetWindow();
|
||||||
|
return WND->GetWindowSize().first;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHLOG_WARNING("[SHGraphicsSystemInterface] Failed to get window width. Value of 0 returned instead.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SHGraphicsSystemInterface::GetWindowHeight()
|
||||||
|
{
|
||||||
|
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
|
||||||
|
if (gfxSystem)
|
||||||
|
{
|
||||||
|
const auto WND = gfxSystem->GetWindow();
|
||||||
|
return WND->GetWindowSize().second;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHLOG_WARNING("[SHGraphicsSystemInterface] Failed to get window height. Value of 0 returned instead.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHGraphicsSystemInterface::IsFullscreen()
|
||||||
|
{
|
||||||
|
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
|
||||||
|
if (gfxSystem)
|
||||||
|
{
|
||||||
|
const auto WND = gfxSystem->GetWindow();
|
||||||
|
return WND->GetWindowData().isFullscreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHLOG_WARNING("[SHGraphicsSystemInterface] Failed to get window fullscreen status. Value of false returned instead.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHGraphicsSystemInterface::CloseWindow()
|
||||||
|
{
|
||||||
|
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
|
||||||
|
if (gfxSystem)
|
||||||
|
{
|
||||||
|
auto WND = gfxSystem->GetWindow();
|
||||||
|
return WND->Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
SHLOG_WARNING("[SHGraphicsSystemInterface] Failed to close window.");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHGraphicsSystemInterface.h
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 31, 2022
|
||||||
|
\brief Contains the definition of the SHGraphicsSystemInterface static class.
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Static class that wraps up certain functions in the SHGraphicsSystem so that
|
||||||
|
/// accessing it from SHADE_Managed would not cause issues due to C++20 features.
|
||||||
|
/// </summary>
|
||||||
|
class SH_API SHGraphicsSystemInterface final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructor */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
SHGraphicsSystemInterface() = delete;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Static Usage Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the current window width.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The current window width.</returns>
|
||||||
|
static uint32_t GetWindowWidth();
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the current window height.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The current window height.</returns>
|
||||||
|
static uint32_t GetWindowHeight();
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the current window fullscreen status.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The current window fullscreen status..</returns>
|
||||||
|
static bool IsFullscreen();
|
||||||
|
/// <summary>
|
||||||
|
/// Closes the current window, and depending on the implementation, should also
|
||||||
|
/// close the application.
|
||||||
|
/// </summary>
|
||||||
|
static void CloseWindow();
|
||||||
|
};
|
||||||
|
}
|
|
@ -4,6 +4,8 @@
|
||||||
#include "Graphics/Pipeline/SHVkPipeline.h"
|
#include "Graphics/Pipeline/SHVkPipeline.h"
|
||||||
#include "SHGraphicsConstants.h"
|
#include "SHGraphicsConstants.h"
|
||||||
#include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h"
|
#include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h"
|
||||||
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
#include "Math/Vector/SHVec4.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -23,7 +25,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate memory for properties
|
// Allocate memory for properties
|
||||||
const Handle<SHShaderBlockInterface> SHADER_INFO = getShaderBlockInterface();
|
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
|
||||||
propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
|
propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
|
||||||
if (propMemorySize <= 0)
|
if (propMemorySize <= 0)
|
||||||
{
|
{
|
||||||
|
@ -49,6 +51,22 @@ namespace SHADE
|
||||||
// Reset all the properties to default values
|
// Reset all the properties to default values
|
||||||
if (propMemory)
|
if (propMemory)
|
||||||
memset(propMemory.get(), 0, propMemorySize);
|
memset(propMemory.get(), 0, propMemorySize);
|
||||||
|
|
||||||
|
// Initialize Vectors to all 1.0 by default
|
||||||
|
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
|
||||||
|
for (int i = 0; i < SHADER_INFO->GetVariableCount(); ++i)
|
||||||
|
{
|
||||||
|
const auto& VAR = SHADER_INFO->GetVariable(i);
|
||||||
|
switch (VAR->type)
|
||||||
|
{
|
||||||
|
case SHShaderBlockInterface::Variable::Type::VECTOR3:
|
||||||
|
setPropertyUnsafe(VAR->offset, SHVec3::One);
|
||||||
|
break;
|
||||||
|
case SHShaderBlockInterface::Variable::Type::VECTOR4:
|
||||||
|
setPropertyUnsafe(VAR->offset, SHVec4::One);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHMaterial::ExportProperties(void* dest) const noexcept
|
void SHMaterial::ExportProperties(void* dest) const noexcept
|
||||||
|
@ -59,14 +77,14 @@ namespace SHADE
|
||||||
|
|
||||||
size_t SHMaterial::GetPropertiesMemorySize() const noexcept
|
size_t SHMaterial::GetPropertiesMemorySize() const noexcept
|
||||||
{
|
{
|
||||||
const Handle<SHShaderBlockInterface> SHADER_INFO = getShaderBlockInterface();
|
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
|
||||||
return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
|
return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Helper Functions */
|
/* Helper Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
Handle<SHShaderBlockInterface> SHMaterial::getShaderBlockInterface() const noexcept
|
Handle<SHShaderBlockInterface> SHMaterial::GetShaderBlockInterface() const noexcept
|
||||||
{
|
{
|
||||||
return pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
return pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
||||||
(
|
(
|
||||||
|
|
|
@ -50,13 +50,24 @@ namespace SHADE
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void SetProperty(const std::string& key, const T& value);
|
void SetProperty(const std::string& key, const T& value);
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
void SetProperty(uint32_t memOffset, const T& value);
|
||||||
|
template<typename T>
|
||||||
T& GetProperty(const std::string& key);
|
T& GetProperty(const std::string& key);
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const T& GetProperty(const std::string& key) const;
|
const T& GetProperty(const std::string& key) const;
|
||||||
|
template<typename T>
|
||||||
|
T& GetProperty(uint32_t memOffset);
|
||||||
|
template<typename T>
|
||||||
|
const T& GetProperty(uint32_t memOffset) const;
|
||||||
void ResetProperties();
|
void ResetProperties();
|
||||||
void ExportProperties(void* dest) const noexcept;
|
void ExportProperties(void* dest) const noexcept;
|
||||||
Byte GetPropertiesMemorySize() const noexcept;
|
Byte GetPropertiesMemorySize() const noexcept;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Query Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
Handle<SHShaderBlockInterface> GetShaderBlockInterface() const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
|
@ -68,7 +79,8 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Helper Functions */
|
/* Helper Functions */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
Handle<SHShaderBlockInterface> getShaderBlockInterface() const noexcept;
|
template<typename T>
|
||||||
|
inline void setPropertyUnsafe(uint32_t memOffset, const T& value); // SetProperty() but without checks
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace SHADE
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void SHMaterial::SetProperty(const std::string& key, const T& value)
|
void SHMaterial::SetProperty(const std::string& key, const T& value)
|
||||||
{
|
{
|
||||||
const auto SHADER_INFO = getShaderBlockInterface();
|
const auto SHADER_INFO = GetShaderBlockInterface();
|
||||||
const auto PROP_INFO = SHADER_INFO->GetVariable(key);
|
const auto PROP_INFO = SHADER_INFO->GetVariable(key);
|
||||||
if (PROP_INFO == nullptr)
|
if (PROP_INFO == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -33,21 +33,32 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get offset and modify the memory directly
|
// Get offset and modify the memory directly
|
||||||
T* dataPtr = propMemory.get() + PROP_INFO->offset;
|
T* dataPtr = reinterpret_cast<T*>(propMemory.get() + PROP_INFO->offset);
|
||||||
*dataPtr = value;
|
*dataPtr = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void SHMaterial::SetProperty(uint32_t memOffset, const T& value)
|
||||||
|
{
|
||||||
|
// Check if out of bounds
|
||||||
|
if (memOffset + sizeof(T) > propMemorySize)
|
||||||
|
throw std::invalid_argument("Attempted to set an invalid property!");
|
||||||
|
// Set
|
||||||
|
setPropertyUnsafe(memOffset, value);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T& SHMaterial::GetProperty(const std::string& key)
|
T& SHMaterial::GetProperty(const std::string& key)
|
||||||
{
|
{
|
||||||
const auto SHADER_INFO = getShaderBlockInterface();
|
const auto SHADER_INFO = GetShaderBlockInterface();
|
||||||
const auto PROP_INFO = SHADER_INFO->GetVariable(key);
|
const auto PROP_INFO = SHADER_INFO->GetVariable(key);
|
||||||
if (PROP_INFO == nullptr)
|
if (PROP_INFO == nullptr)
|
||||||
{
|
{
|
||||||
throw std::invalid_argument("Attempted to set an invalid property!");
|
throw std::invalid_argument("Attempted to retrieve an invalid property!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get offset and return the memory directly
|
// Get offset and return the memory directly
|
||||||
T* dataPtr = propMemory.get() + PROP_INFO->offset;
|
T* dataPtr = reinterpret_cast<T*>(propMemory.get() + PROP_INFO->offset);
|
||||||
return *dataPtr;
|
return *dataPtr;
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -55,5 +66,25 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
return const_cast<const T&>(const_cast<SHMaterial*>(this)->GetProperty(key));
|
return const_cast<const T&>(const_cast<SHMaterial*>(this)->GetProperty(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const T& SHMaterial::GetProperty(uint32_t memOffset) const
|
||||||
|
{
|
||||||
|
// Check if out of bounds
|
||||||
|
if (memOffset + sizeof(T) > propMemorySize)
|
||||||
|
throw std::invalid_argument("Attempted to retrieve an invalid property!");
|
||||||
|
return *(reinterpret_cast<T*>(propMemory.get() + memOffset));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T& SHMaterial::GetProperty(uint32_t memOffset)
|
||||||
|
{
|
||||||
|
return const_cast<const T&>(const_cast<SHMaterial*>(this)->GetProperty(memOffset));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void SHMaterial::setPropertyUnsafe(uint32_t memOffset, const T& value)
|
||||||
|
{
|
||||||
|
(*reinterpret_cast<T*>(propMemory.get() + memOffset)) = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,15 +69,15 @@ namespace SHADE
|
||||||
|
|
||||||
// Search Override Data for the property
|
// Search Override Data for the property
|
||||||
uint32_t PROP_IDX = SHADER_INFO->GetVariableIndex(key);
|
uint32_t PROP_IDX = SHADER_INFO->GetVariableIndex(key);
|
||||||
auto prop = std::find(overrideData.begin(), overrideData.end(), [&](const OverrideData& data)
|
auto prop = std::find_if(overrideData.begin(), overrideData.end(), [&](const OverrideData& data)
|
||||||
{
|
{
|
||||||
return PROP_IDX == data.Index;
|
return PROP_IDX == data.Index;
|
||||||
});
|
});
|
||||||
if (prop == overrideData.end())
|
if (prop == overrideData.end())
|
||||||
throw std::invalid_argument("Attempted to get an property that was not set previously!");
|
throw std::invalid_argument("Attempted to get an property that was not set previously!");
|
||||||
|
|
||||||
// Get offset and return the memory directly
|
// Get offset and return the memory directly
|
||||||
T* dataPtr = dataStore.get() + prop->StoredDataOffset;
|
T* dataPtr = reinterpret_cast<T*>(dataStore.get() + prop->StoredDataOffset);
|
||||||
return *dataPtr;
|
return *dataPtr;
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
@ -17,7 +17,8 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
// Project Includes
|
// Project Includes
|
||||||
#include "Resource/SHHandle.h"
|
#include "Resource/SHHandle.h"
|
||||||
#include "Resource/SHResourceLibrary.h"
|
#include "Resource/SHResourceLibrary.h"
|
||||||
#include "Math/SHMath.h"
|
#include "Math/Vector/SHVec2.h"
|
||||||
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,12 +23,12 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
void SHRenderable::OnCreate()
|
void SHRenderable::OnCreate()
|
||||||
{
|
{
|
||||||
materialChanged = true;
|
matChanged = true;
|
||||||
sharedMaterial = {};
|
sharedMaterial = {};
|
||||||
material = {};
|
material = {};
|
||||||
oldMaterial = {};
|
oldMaterial = {};
|
||||||
|
|
||||||
lightLayer = 0;
|
lightLayer = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRenderable::OnDestroy()
|
void SHRenderable::OnDestroy()
|
||||||
|
@ -55,7 +55,7 @@ namespace SHADE
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Flag that material was changed
|
// Flag that material was changed
|
||||||
materialChanged = true;
|
matChanged = true;
|
||||||
|
|
||||||
// Free copies of materials if any
|
// Free copies of materials if any
|
||||||
if (material)
|
if (material)
|
||||||
|
@ -92,15 +92,41 @@ namespace SHADE
|
||||||
|
|
||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Mesh Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
void SHRenderable::SetMesh(Handle<SHMesh> newMesh)
|
||||||
|
{
|
||||||
|
oldMesh = mesh;
|
||||||
|
mesh = newMesh;
|
||||||
|
meshChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Light Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
uint8_t SHRenderable::GetLightLayer(void) const noexcept
|
uint8_t SHRenderable::GetLightLayer(void) const noexcept
|
||||||
{
|
{
|
||||||
return lightLayer;
|
return lightLayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Batcher Dispatcher Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
void SHRenderable::ResetChangedFlag()
|
void SHRenderable::ResetChangedFlag()
|
||||||
{
|
{
|
||||||
materialChanged = false;
|
matChanged = false;
|
||||||
oldMaterial = {};
|
meshChanged = false;
|
||||||
|
oldMaterial = {};
|
||||||
|
oldMesh = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RTTR_REGISTRATION
|
||||||
|
{
|
||||||
|
using namespace SHADE;
|
||||||
|
using namespace rttr;
|
||||||
|
|
||||||
|
registration::class_<SHRenderable>("Renderable Component");
|
||||||
|
}
|
|
@ -11,9 +11,10 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
*//*************************************************************************************/
|
*//*************************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
// External Dependencies
|
||||||
|
#include <rttr/registration>
|
||||||
// Project Includes
|
// Project Includes
|
||||||
#include "Resource/SHHandle.h"
|
#include "Resource/SHHandle.h"
|
||||||
//#include "SHTransform.h"
|
|
||||||
#include "ECS_Base/Components/SHComponent.h"
|
#include "ECS_Base/Components/SHComponent.h"
|
||||||
#include "Math/SHMatrix.h"
|
#include "Math/SHMatrix.h"
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
|
@ -50,33 +51,42 @@ namespace SHADE
|
||||||
void SetMaterial(Handle<SHMaterialInstance> materialInstance);
|
void SetMaterial(Handle<SHMaterialInstance> materialInstance);
|
||||||
Handle<SHMaterialInstance> GetMaterial() const;
|
Handle<SHMaterialInstance> GetMaterial() const;
|
||||||
Handle<SHMaterialInstance> GetModifiableMaterial();
|
Handle<SHMaterialInstance> GetModifiableMaterial();
|
||||||
|
Handle<SHMaterialInstance> GetPrevMaterial() const noexcept { return oldMaterial; }
|
||||||
|
bool HasMaterialChanged() const noexcept { return matChanged; }
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
/* Getter Functions */
|
/* Mesh Functions */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
void SetMesh(Handle<SHMesh> newMesh);
|
||||||
|
Handle<SHMesh> GetMesh() const noexcept { return mesh; }
|
||||||
|
Handle<SHMesh> GetPrevMesh() const noexcept { return oldMesh; }
|
||||||
|
bool HasMeshChanged() const noexcept { return meshChanged; }
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Light Functions */
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
bool WasMaterialChanged() const noexcept { return materialChanged; }
|
|
||||||
Handle<SHMaterialInstance> GetPrevMaterial() const noexcept { return oldMaterial; }
|
|
||||||
uint8_t GetLightLayer (void) const noexcept;
|
uint8_t GetLightLayer (void) const noexcept;
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
/* Batcher Dispatcher Functions */
|
/* Batcher Dispatcher Functions */
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
bool HasChanged() const noexcept { return matChanged || meshChanged; } // Whether or not the mesh or material has changed
|
||||||
void ResetChangedFlag(); // TODO: Lock it so that only SHBatcherDispatcher can access this
|
void ResetChangedFlag(); // TODO: Lock it so that only SHBatcherDispatcher can access this
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
/* Data Members */
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
Handle<SHMesh> Mesh;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
Handle<SHMesh> mesh;
|
||||||
|
Handle<SHMesh> oldMesh;
|
||||||
|
bool meshChanged = true;
|
||||||
Handle<SHMaterialInstance> sharedMaterial;
|
Handle<SHMaterialInstance> sharedMaterial;
|
||||||
Handle<SHMaterialInstance> material;
|
Handle<SHMaterialInstance> material;
|
||||||
bool materialChanged = true;
|
bool matChanged = true;
|
||||||
Handle<SHMaterialInstance> oldMaterial;
|
Handle<SHMaterialInstance> oldMaterial;
|
||||||
uint8_t lightLayer;
|
uint8_t lightLayer;
|
||||||
|
|
||||||
|
RTTR_ENABLE()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace SHADE
|
||||||
lightData.Reset();
|
lightData.Reset();
|
||||||
SetType(SH_LIGHT_TYPE::DIRECTIONAL);
|
SetType(SH_LIGHT_TYPE::DIRECTIONAL);
|
||||||
indexInBuffer = std::numeric_limits<uint32_t>::max();
|
indexInBuffer = std::numeric_limits<uint32_t>::max();
|
||||||
active = true;
|
isActive = true;
|
||||||
Unbind();
|
Unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ namespace SHADE
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHLightComponent::SetPosition(SHVec3 position) noexcept
|
void SHLightComponent::SetPosition(SHVec3 const& position) noexcept
|
||||||
{
|
{
|
||||||
lightData.position = position;
|
lightData.position = position;
|
||||||
MakeDirty();
|
MakeDirty();
|
||||||
|
@ -34,20 +34,20 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SHLightComponent::SetDirection(SHVec3 direction) noexcept
|
void SHLightComponent::SetDirection(SHVec3 const& direction) noexcept
|
||||||
{
|
{
|
||||||
lightData.direction = direction;
|
lightData.direction = direction;
|
||||||
MakeDirty();
|
MakeDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SHLightComponent::SetDiffuseColor(SHVec4 diffuseColor) noexcept
|
void SHLightComponent::SetColor(SHVec4 const& color) noexcept
|
||||||
{
|
{
|
||||||
lightData.diffuseColor = diffuseColor;
|
lightData.color = color;
|
||||||
MakeDirty();
|
MakeDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHLightComponent::ModifyLayer(uint8_t layerIndex, bool value) noexcept
|
void SHLightComponent::ModifyCullingMask(uint8_t layerIndex, bool value) noexcept
|
||||||
{
|
{
|
||||||
if (value)
|
if (value)
|
||||||
lightData.cullingMask |= (1u << layerIndex);
|
lightData.cullingMask |= (1u << layerIndex);
|
||||||
|
@ -57,6 +57,10 @@ namespace SHADE
|
||||||
MakeDirty();
|
MakeDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::SetCullingMask(uint32_t const& value) noexcept
|
||||||
|
{
|
||||||
|
lightData.cullingMask = value;
|
||||||
|
}
|
||||||
|
|
||||||
void SHLightComponent::SetAllLayers(void) noexcept
|
void SHLightComponent::SetAllLayers(void) noexcept
|
||||||
{
|
{
|
||||||
|
@ -93,11 +97,11 @@ namespace SHADE
|
||||||
indexInBuffer = inIndexInBuffer;
|
indexInBuffer = inIndexInBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHLightComponent::SetActive(bool flag) noexcept
|
|
||||||
{
|
|
||||||
MakeDirty();
|
|
||||||
active = flag;
|
|
||||||
|
|
||||||
|
void SHLightComponent::SetStrength(float value) noexcept
|
||||||
|
{
|
||||||
|
lightData.strength = value;
|
||||||
|
MakeDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
SHLightData const& SHLightComponent::GetLightData(void) const noexcept
|
SHLightData const& SHLightComponent::GetLightData(void) const noexcept
|
||||||
|
@ -105,6 +109,32 @@ namespace SHADE
|
||||||
return lightData;
|
return lightData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHVec3 const& SHLightComponent::GetPosition(void) const noexcept
|
||||||
|
{
|
||||||
|
return lightData.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
SH_LIGHT_TYPE SHLightComponent::GetType(void) const noexcept
|
||||||
|
{
|
||||||
|
return lightData.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHVec3 const& SHLightComponent::GetDirection(void) const noexcept
|
||||||
|
{
|
||||||
|
return lightData.direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHVec4 const& SHLightComponent::GetColor(void) const noexcept
|
||||||
|
{
|
||||||
|
return lightData.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t const& SHLightComponent::GetCullingMask(void) const noexcept
|
||||||
|
{
|
||||||
|
return lightData.cullingMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SHLightComponent::IsDirty(void) const noexcept
|
bool SHLightComponent::IsDirty(void) const noexcept
|
||||||
{
|
{
|
||||||
return dirty;
|
return dirty;
|
||||||
|
@ -120,4 +150,32 @@ namespace SHADE
|
||||||
return indexInBuffer;
|
return indexInBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float SHLightComponent::GetStrength(void) const noexcept
|
||||||
|
{
|
||||||
|
return lightData.strength;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RTTR_REGISTRATION
|
||||||
|
{
|
||||||
|
using namespace SHADE;
|
||||||
|
using namespace rttr;
|
||||||
|
|
||||||
|
registration::enumeration<SH_LIGHT_TYPE>("Light Type")
|
||||||
|
(
|
||||||
|
value("Directional", SH_LIGHT_TYPE::DIRECTIONAL),
|
||||||
|
value("Point", SH_LIGHT_TYPE::POINT),
|
||||||
|
value("Spot", SH_LIGHT_TYPE::SPOT),
|
||||||
|
value("Ambient", SH_LIGHT_TYPE::AMBIENT)
|
||||||
|
);
|
||||||
|
|
||||||
|
registration::class_<SHLightComponent>("Light Component")
|
||||||
|
.property("Position", &SHLightComponent::GetPosition, &SHLightComponent::SetPosition)
|
||||||
|
.property("Type", &SHLightComponent::GetType, &SHLightComponent::SetType)
|
||||||
|
.property("Direction", &SHLightComponent::GetDirection, &SHLightComponent::SetDirection)
|
||||||
|
.property("Color", &SHLightComponent::GetColor, &SHLightComponent::SetColor)
|
||||||
|
.property("Layer", &SHLightComponent::GetCullingMask, &SHLightComponent::SetCullingMask)
|
||||||
|
.property("Strength", &SHLightComponent::GetStrength, &SHLightComponent::SetStrength)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <rttr/registration>
|
||||||
#include "ECS_Base/Components/SHComponent.h"
|
#include "ECS_Base/Components/SHComponent.h"
|
||||||
#include "SHLightData.h"
|
#include "SHLightData.h"
|
||||||
|
|
||||||
|
@ -24,8 +25,6 @@ namespace SHADE
|
||||||
//! If the light's data is already in the buffers, this will be set to true.
|
//! If the light's data is already in the buffers, this will be set to true.
|
||||||
bool bound;
|
bool bound;
|
||||||
|
|
||||||
//! If the light is active, this is true.
|
|
||||||
bool active;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
@ -37,24 +36,31 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* SETTERS AND GETTERS */
|
/* SETTERS AND GETTERS */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
void SetPosition (SHVec3 position) noexcept;
|
void SetPosition (SHVec3 const& position) noexcept; // serialized
|
||||||
void SetType (SH_LIGHT_TYPE type) noexcept;
|
void SetType (SH_LIGHT_TYPE type) noexcept; // serialized
|
||||||
void SetDirection (SHVec3 direction) noexcept;
|
void SetDirection (SHVec3 const& direction) noexcept; // serialized
|
||||||
void SetDiffuseColor (SHVec4 diffuseColor) noexcept;
|
void SetColor (SHVec4 const& color) noexcept; // serialized
|
||||||
void ModifyLayer (uint8_t layerIndex, bool value) noexcept;
|
void ModifyCullingMask (uint8_t layerIndex, bool value) noexcept; // serialized
|
||||||
void SetAllLayers (void) noexcept;
|
void SetCullingMask (uint32_t const& value) noexcept;
|
||||||
void ClearAllLayers (void) noexcept;
|
void SetAllLayers (void) noexcept; // serialized
|
||||||
void MakeDirty (void) noexcept;
|
void ClearAllLayers (void) noexcept; // serialized
|
||||||
void ClearDirtyFlag (void) noexcept;
|
void MakeDirty (void) noexcept;
|
||||||
void Unbind (void) noexcept;
|
void ClearDirtyFlag (void) noexcept;
|
||||||
void SetBound (uint32_t inIndexInBuffer) noexcept;
|
void Unbind (void) noexcept;
|
||||||
void SetActive (bool flag) noexcept;
|
void SetBound (uint32_t inIndexInBuffer) noexcept;
|
||||||
|
void SetStrength (float value) noexcept; // serialized
|
||||||
|
|
||||||
|
|
||||||
SHLightData const& GetLightData (void) const noexcept;
|
SHLightData const& GetLightData (void) const noexcept;
|
||||||
|
SHVec3 const& GetPosition (void) const noexcept; // serialized
|
||||||
|
SH_LIGHT_TYPE GetType (void) const noexcept; // serialized
|
||||||
|
SHVec3 const& GetDirection (void) const noexcept; // serialized
|
||||||
|
SHVec4 const& GetColor (void) const noexcept; // serialized
|
||||||
|
uint32_t const& GetCullingMask (void) const noexcept; // serialized
|
||||||
bool IsDirty (void) const noexcept;
|
bool IsDirty (void) const noexcept;
|
||||||
bool GetBound (void) const noexcept;
|
bool GetBound (void) const noexcept;
|
||||||
uint32_t GetIndexInBuffer (void) const noexcept;
|
uint32_t GetIndexInBuffer (void) const noexcept;
|
||||||
|
float GetStrength (void) const noexcept;
|
||||||
|
RTTR_ENABLE()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue