Merge remote-tracking branch 'origin/main' into SP3-1-Rendering

This commit is contained in:
Brandon Mak 2022-11-02 17:04:31 +08:00
parent 73be299aae
commit ebc94225e7
156 changed files with 20008 additions and 1476 deletions

View File

@ -0,0 +1,17 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
#extension GL_EXT_nonuniform_qualifier : require
layout(location = 0) in struct
{
vec4 vertColor;
} In;
layout(location = 0) out vec4 outColor;
void main()
{
outColor = In.vertColor;
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: DebugDraw_FS
ID: 36671027
Type: 2

View File

@ -0,0 +1,24 @@
#version 450
#extension GL_KHR_vulkan_glsl : enable
layout(location = 0) in vec4 aVertexPos;
layout(location = 1) in vec4 aVertColor;
layout(location = 0) out struct
{
vec4 vertColor; // location 0
} Out;
layout(set = 2, binding = 0) uniform CameraData
{
vec4 position;
mat4 vpMat;
} cameraData;
void main()
{
gl_Position = cameraData.vpMat * vec4 (aVertexPos.xyz, 1.0f);
Out.vertColor = aVertColor;
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: DebugDraw_VS
ID: 48002439
Type: 2

View File

@ -1,3 +1,3 @@
Name: DeferredComposite_CS Name: DeferredComposite_CS
ID: 42814284 ID: 45072428
Type: 2 Type: 2

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,3 +1,3 @@
Name: TestCube_FS Name: TestCube_FS
ID: 37450402 ID: 46377769
Type: 2 Type: 2

Binary file not shown.

View File

@ -1,3 +1,3 @@
Name: TestCube_VS Name: TestCube_VS
ID: 41688429 ID: 39210065
Type: 2 Type: 2

View File

@ -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
@ -31,6 +31,7 @@
#include "FRC/SHFramerateController.h" #include "FRC/SHFramerateController.h"
#include "AudioSystem/SHAudioSystem.h" #include "AudioSystem/SHAudioSystem.h"
#include "Camera/SHCameraSystem.h" #include "Camera/SHCameraSystem.h"
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
// Components // Components
#include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h"
@ -42,6 +43,7 @@
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
#include "Tools/SHDebugDraw.h"
using namespace SHADE; using namespace SHADE;
@ -69,6 +71,7 @@ namespace Sandbox
SHGraphicsSystem* graphicsSystem = static_cast<SHGraphicsSystem*>(SHSystemManager::GetSystem<SHGraphicsSystem>()); SHGraphicsSystem* graphicsSystem = static_cast<SHGraphicsSystem*>(SHSystemManager::GetSystem<SHGraphicsSystem>());
SHSystemManager::CreateSystem<SHAudioSystem>(); SHSystemManager::CreateSystem<SHAudioSystem>();
SHSystemManager::CreateSystem<SHCameraSystem>(); SHSystemManager::CreateSystem<SHCameraSystem>();
SHSystemManager::CreateSystem<SHDebugDrawSystem>();
#ifdef SHEDITOR #ifdef SHEDITOR
SDL_Init(SDL_INIT_VIDEO); SDL_Init(SDL_INIT_VIDEO);
@ -90,11 +93,12 @@ namespace Sandbox
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>(); SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
SHSystemManager::RegisterRoutine<SHDebugDrawSystem, SHDebugDrawSystem::ProcessPointsRoutine>();
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
@ -108,13 +112,10 @@ namespace Sandbox
SHComponentManager::CreateComponentSparseSet<SHColliderComponent>(); SHComponentManager::CreateComponentSparseSet<SHColliderComponent>();
SHComponentManager::CreateComponentSparseSet<SHTransformComponent>(); SHComponentManager::CreateComponentSparseSet<SHTransformComponent>();
SHComponentManager::CreateComponentSparseSet<SHRenderable>(); SHComponentManager::CreateComponentSparseSet<SHRenderable>();
SHComponentManager::CreateComponentSparseSet<SHCameraComponent>(); //SHComponentManager::CreateComponentSparseSet<SHCameraComponent>();
SHAssetManager::Load(); SHAssetManager::Load();
auto id = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
auto id2 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
auto id3 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
SHSystemManager::RegisterRoutine<SHAudioSystem, SHAudioSystem::AudioRoutine>(); SHSystemManager::RegisterRoutine<SHAudioSystem, SHAudioSystem::AudioRoutine>();
@ -126,6 +127,9 @@ namespace Sandbox
SHSceneManager::InitSceneManager<SBTestScene>("TestScene"); SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
SHFrameRateController::UpdateFRC(); SHFrameRateController::UpdateFRC();
// Link up SHDebugDraw
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
} }
void SBApplication::Update(void) void SBApplication::Update(void)

View File

@ -16,7 +16,10 @@
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include "Camera/SHCameraComponent.h" #include "Camera/SHCameraComponent.h"
#include "Math/SHColour.h"
#include "Resource/SHResourceManager.h" #include "Resource/SHResourceManager.h"
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
#include "Tools/SHDebugDraw.h"
using namespace SHADE; using namespace SHADE;
@ -128,7 +131,6 @@ namespace Sandbox
floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC); floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC);
auto* floorBox = floorCollider.AddBoundingBox(); auto* floorBox = floorCollider.AddBoundingBox();
floorBox->SetHalfExtents(floorTransform.GetWorldScale() * 0.5f);
// Create blank entity with a script // Create blank entity with a script
//testObj = SHADE::SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>(); //testObj = SHADE::SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
@ -160,7 +162,7 @@ namespace Sandbox
SHComponentManager::RemoveComponent <SHColliderComponent>(0); SHComponentManager::RemoveComponent <SHColliderComponent>(0);
auto ambientLight = SHEntityManager::CreateEntity<SHLightComponent>(); auto ambientLight = SHEntityManager::CreateEntity<SHLightComponent>();
SHComponentManager::GetComponent<SHLightComponent>(ambientLight)->SetColor(SHVec4(1.0f, 1.0f, 1.0f, 1.0f)); SHComponentManager::GetComponent<SHLightComponent>(ambientLight)->SetColor(SHColour::WHITE);
SHComponentManager::GetComponent<SHLightComponent>(ambientLight)->SetStrength(0.25f); SHComponentManager::GetComponent<SHLightComponent>(ambientLight)->SetStrength(0.25f);
SHComponentManager::GetComponent<SHLightComponent>(ambientLight)->SetType(SH_LIGHT_TYPE::AMBIENT); SHComponentManager::GetComponent<SHLightComponent>(ambientLight)->SetType(SH_LIGHT_TYPE::AMBIENT);
} }
@ -187,6 +189,8 @@ namespace Sandbox
SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>()); SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>());
scriptEngine->RemoveAllScripts(testObj); scriptEngine->RemoveAllScripts(testObj);
} }
SHDebugDraw::Cube(SHColour::CRIMSON, SHVec3(1.0f, 0.0f, 0.0f), SHVec3(1.0f, 1.0f, 1.0f));
} }
void SBTestScene::Render() void SBTestScene::Render()

View File

@ -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",

View File

@ -10,6 +10,7 @@
*****************************************************************************/ *****************************************************************************/
#pragma once #pragma once
#include <vulkan/vulkan.hpp>
#include "SHAssetData.h" #include "SHAssetData.h"
#include "SH_API.h" #include "SH_API.h"
#include <vector> #include <vector>
@ -17,12 +18,14 @@
namespace SHADE namespace SHADE
{ {
//! Tighter control over types of shaders. Maps directly to their
//! equivalent vk::ShaderStageFlagBits.
enum class SH_SHADER_TYPE : uint8_t enum class SH_SHADER_TYPE : uint8_t
{ {
VERTEX, VERTEX = static_cast<uint8_t>(vk::ShaderStageFlagBits::eVertex),
FRAGMENT, FRAGMENT = static_cast<uint8_t>(vk::ShaderStageFlagBits::eFragment),
COMPUTE, COMPUTE = static_cast<uint8_t>(vk::ShaderStageFlagBits::eCompute),
INAVLID_TYPE INAVLID_TYPE = std::numeric_limits<uint8_t>::max()
}; };
struct SH_API SHShaderAsset : SHAssetData struct SH_API SHShaderAsset : SHAssetData

View File

@ -99,11 +99,12 @@ namespace SHADE
SH_SHADER_TYPE SHShaderSourceCompiler::GetShaderTypeFromFilename(std::string name) noexcept SH_SHADER_TYPE SHShaderSourceCompiler::GetShaderTypeFromFilename(std::string name) noexcept
{ {
for (auto i { 0}; i < SHADER_TYPE_MAX_COUNT; ++i) for (auto i { 0 }; i < SHADER_TYPE_MAX_COUNT; ++i)
{ {
if (name.find(SHADER_IDENTIFIERS[i].data()) != std::string::npos) const auto& [SHADER_SUFFIX, SHADER_TYPE] = SHADER_IDENTIFIERS[i];
if (name.find(SHADER_SUFFIX.data()) != std::string::npos)
{ {
return static_cast<SH_SHADER_TYPE>(i); return SHADER_TYPE;
} }
} }

View File

@ -11,6 +11,10 @@
#pragma once #pragma once
#include "SHAssetLoader.h" #include "SHAssetLoader.h"
#include "Assets/Asset Types/SHPrefabAsset.h"
#include "Assets/Asset Types/SHSceneAsset.h"
#include "Assets/Asset Types/SHMaterialAsset.h"
namespace SHADE namespace SHADE
{ {
struct SHTextBasedLoader : SHAssetLoader struct SHTextBasedLoader : SHAssetLoader

View File

@ -13,6 +13,7 @@
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <filesystem> #include <filesystem>
#include "Asset Types/SHShaderAsset.h"
// FMOD Fwd Declare // FMOD Fwd Declare
namespace FMOD namespace FMOD
@ -113,10 +114,10 @@ constexpr std::string_view VERTEX_SHADER{ "_VS" };
constexpr std::string_view FRAGMENT_SHADER{ "_FS" }; constexpr std::string_view FRAGMENT_SHADER{ "_FS" };
constexpr std::string_view COMPUTER_SHADER{ "_CS" }; constexpr std::string_view COMPUTER_SHADER{ "_CS" };
constexpr std::string_view SHADER_IDENTIFIERS[] = { constexpr std::pair<std::string_view, SHADE::SH_SHADER_TYPE> SHADER_IDENTIFIERS[] = {
VERTEX_SHADER, std::make_pair(VERTEX_SHADER, SHADE::SH_SHADER_TYPE::VERTEX),
FRAGMENT_SHADER, std::make_pair(FRAGMENT_SHADER, SHADE::SH_SHADER_TYPE::FRAGMENT),
COMPUTER_SHADER std::make_pair(COMPUTER_SHADER, SHADE::SH_SHADER_TYPE::COMPUTE)
}; };
constexpr size_t SHADER_TYPE_MAX_COUNT{ 3 }; constexpr size_t SHADER_TYPE_MAX_COUNT{ 3 };

View File

@ -151,19 +151,23 @@ namespace SHADE
****************************************************************************/ ****************************************************************************/
AssetID SHAssetManager::CreateNewAsset(AssetType type, AssetName name) noexcept AssetID SHAssetManager::CreateNewAsset(AssetType type, AssetName name) noexcept
{ {
SHAssetData* data = nullptr;
std::string newPath{ ASSET_ROOT }; std::string newPath{ ASSET_ROOT };
switch (type) switch (type)
{ {
case AssetType::PREFAB: case AssetType::PREFAB:
newPath += PREFAB_FOLDER; newPath += PREFAB_FOLDER;
data = new SHPrefabAsset();
break; break;
case AssetType::SCENE: case AssetType::SCENE:
newPath += SCENE_FOLDER; newPath += SCENE_FOLDER;
data = new SHSceneAsset();
break; break;
case AssetType::MATERIAL: case AssetType::MATERIAL:
newPath += MATERIAL_FOLDER; newPath += MATERIAL_FOLDER;
data = new SHMaterialAsset();
break; break;
default: default:
@ -189,6 +193,8 @@ namespace SHADE
) )
}); });
assetData.emplace(id, data);
return id; return id;
} }

View File

@ -0,0 +1,68 @@
#include "SHpch.h"
#include "SHCameraArmComponent.h"
namespace SHADE
{
SHCameraArmComponent::SHCameraArmComponent()
:pitch(0.0f), yaw(0.0f), armLength(1.0f),offset(), dirty(true), lookAtCameraOrigin(true)
{
}
SHVec3 const& SHCameraArmComponent::GetOffset() const noexcept
{
return offset;
}
float SHCameraArmComponent::GetPitch() const noexcept
{
return pitch;
}
float SHCameraArmComponent::GetYaw() const noexcept
{
return yaw;
}
float SHCameraArmComponent::GetArmLength() const noexcept
{
return armLength;
}
void SHCameraArmComponent::SetPitch(float pitch) noexcept
{
this->pitch = pitch;
dirty = true;
}
void SHCameraArmComponent::SetYaw(float yaw) noexcept
{
this->yaw = yaw;
dirty = true;
}
void SHCameraArmComponent::SetArmLength(float length) noexcept
{
this->armLength = length;
dirty = true;
}
}//namespace SHADE
RTTR_REGISTRATION
{
using namespace SHADE;
using namespace rttr;
registration::class_<SHCameraArmComponent>("Camera Arm Component")
.property("Arm Pitch", &SHCameraArmComponent::GetPitch, &SHCameraArmComponent::SetPitch)
.property("Arm Yaw", &SHCameraArmComponent::GetYaw, &SHCameraArmComponent::SetYaw)
.property("Arm Length", &SHCameraArmComponent::GetArmLength, &SHCameraArmComponent::SetArmLength)
.property("Look At Camera Origin", &SHCameraArmComponent::lookAtCameraOrigin);
}

View File

@ -0,0 +1,44 @@
#pragma once
#include <rttr/registration>
#include "ECS_Base/Components/SHComponent.h"
#include "Math/SHMatrix.h"
#include "SH_API.h"
namespace SHADE
{
class SH_API SHCameraArmComponent final: public SHComponent
{
private:
float pitch;
float yaw;
float armLength;
bool dirty;
SHVec3 offset;
public:
friend class SHCameraSystem;
SHCameraArmComponent();
virtual ~SHCameraArmComponent() = default;
bool lookAtCameraOrigin;
//Getters
//SHMatrix const& GetMatrix() const noexcept;
SHVec3 const& GetOffset() const noexcept;
float GetPitch() const noexcept;
float GetYaw() const noexcept;
float GetArmLength() const noexcept;
//Setters
void SetPitch(float pitch) noexcept;
void SetYaw(float yaw) noexcept;
void SetArmLength(float length) noexcept;
protected:
};
}//namespace SHADE

View File

@ -13,7 +13,7 @@ namespace SHADE
, width(1920.0f), height(1080.0f), zNear(0.01f), zFar(10000.0f), fov(90.0f), movementSpeed(1.0f), turnSpeed(0.5f) , width(1920.0f), height(1080.0f), zNear(0.01f), zFar(10000.0f), fov(90.0f), movementSpeed(1.0f), turnSpeed(0.5f)
, perspProj(true), dirtyView(true), dirtyProj(true) , perspProj(true), dirtyView(true), dirtyProj(true)
, viewMatrix(), projMatrix() , viewMatrix(), projMatrix()
, position() , position(), offset()
{ {
ComponentFamily::GetID<SHCameraComponent>(); ComponentFamily::GetID<SHCameraComponent>();
} }

View File

@ -33,7 +33,7 @@ namespace SHADE
SHVec3 position; SHVec3 position;
bool perspProj; bool perspProj;
SHVec3 offset;
@ -41,7 +41,7 @@ namespace SHADE
friend class SHCameraSystem; friend class SHCameraSystem;
SHCameraComponent(); SHCameraComponent();
~SHCameraComponent(); virtual ~SHCameraComponent();
//Getters and setters. //Getters and setters.

View File

@ -1,6 +1,7 @@
#include "SHpch.h" #include "SHpch.h"
#include "SHCameraDirector.h" #include "SHCameraDirector.h"
#include "SHCameraComponent.h" #include "SHCameraComponent.h"
#include "SHCameraArmComponent.h"
#include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHComponentManager.h"
#include "ECS_Base/SHECSMacros.h" #include "ECS_Base/SHECSMacros.h"
#include "ECS_Base/Managers/SHEntityManager.h" #include "ECS_Base/Managers/SHEntityManager.h"
@ -48,6 +49,7 @@ namespace SHADE
viewMatrix = camComponent->GetViewMatrix(); viewMatrix = camComponent->GetViewMatrix();
projMatrix = camComponent->GetProjMatrix(); projMatrix = camComponent->GetProjMatrix();
} }
} }
void SHCameraDirector::SetMainCamera(SHCameraComponent& camera) noexcept void SHCameraDirector::SetMainCamera(SHCameraComponent& camera) noexcept

View File

@ -22,6 +22,7 @@ namespace SHADE
EntityID mainCameraEID; EntityID mainCameraEID;
EntityID transitionCameraEID; EntityID transitionCameraEID;
SHMatrix GetViewMatrix() const noexcept; SHMatrix GetViewMatrix() const noexcept;
SHMatrix GetProjMatrix() const noexcept; SHMatrix GetProjMatrix() const noexcept;
SHMatrix GetVPMatrix() const noexcept; SHMatrix GetVPMatrix() const noexcept;

View File

@ -1,10 +1,12 @@
#include "SHpch.h" #include "SHpch.h"
#include "SHCameraSystem.h" #include "SHCameraSystem.h"
#include "SHCameraArmComponent.h"
#include "Math/SHMathHelpers.h" #include "Math/SHMathHelpers.h"
#include "Input/SHInputManager.h" #include "Input/SHInputManager.h"
#include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec2.h"
#include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHComponentManager.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include <math.h>
namespace SHADE namespace SHADE
@ -59,6 +61,7 @@ namespace SHADE
} }
UpdateCameraComponent(editorCamera); UpdateCameraComponent(editorCamera);
} }
void SHCameraSystem::EditorCameraUpdate::Execute(double dt) noexcept void SHCameraSystem::EditorCameraUpdate::Execute(double dt) noexcept
{ {
@ -112,6 +115,8 @@ namespace SHADE
//std::cout << "Camera position: " << camera.position.x << " " << camera.position.y << std::endl; //std::cout << "Camera position: " << camera.position.x << " " << camera.position.y << std::endl;
system->UpdateCameraComponent(system->editorCamera); system->UpdateCameraComponent(system->editorCamera);
system->DecomposeViewMatrix(camera.viewMatrix, camera.pitch, camera.yaw, camera.roll, camera.position);
} }
void SHCameraSystem::Init(void) void SHCameraSystem::Init(void)
@ -122,6 +127,9 @@ namespace SHADE
editorCamera.SetRoll(0.0f); editorCamera.SetRoll(0.0f);
editorCamera.movementSpeed = 2.0f; editorCamera.movementSpeed = 2.0f;
SHComponentManager::CreateComponentSparseSet<SHCameraComponent>();
SHComponentManager::CreateComponentSparseSet<SHCameraArmComponent>();
} }
void SHCameraSystem::Exit(void) void SHCameraSystem::Exit(void)
@ -134,6 +142,26 @@ namespace SHADE
return &editorCamera; return &editorCamera;
} }
void SHCameraSystem::UpdatePivotArmComponent(SHCameraArmComponent& pivot) noexcept
{
if (pivot.dirty)
{
SHVec3 offset{ 0.0f,0.0f, pivot.GetArmLength() };
offset = SHVec3::RotateX(offset, -(SHMath::DegreesToRadians(pivot.GetPitch())));
offset = SHVec3::RotateY(offset, (SHMath::DegreesToRadians(pivot.GetYaw())));
//pivot.rtMatrix = SHMatrix::RotateX(SHMath::DegreesToRadians(pivot.GetPitch()))
// * SHMatrix::RotateY(SHMath::DegreesToRadians(pivot.GetYaw()))
// * SHMatrix::Translate(SHVec3(0.0f , 0.0f, pivot.GetArmLength()));
pivot.offset = offset;
// pivot.rtMatrix = SHMatrix::Inverse(pivot.rtMatrix);
}
}
void SHCameraSystem::UpdateCameraComponent(SHCameraComponent& camera) noexcept void SHCameraSystem::UpdateCameraComponent(SHCameraComponent& camera) noexcept
{ {
if (SHComponentManager::HasComponent<SHTransformComponent>(camera.GetEID()) == true && &camera != &editorCamera) if (SHComponentManager::HasComponent<SHTransformComponent>(camera.GetEID()) == true && &camera != &editorCamera)
@ -151,6 +179,15 @@ namespace SHADE
if (camera.dirtyView) if (camera.dirtyView)
{ {
camera.offset = SHVec3{ 0.0f };
if (SHComponentManager::HasComponent<SHCameraArmComponent>(camera.GetEID()))
{
auto arm = SHComponentManager::GetComponent<SHCameraArmComponent>(camera.GetEID());
camera.offset = arm->GetOffset();
if(arm->lookAtCameraOrigin)
CameraLookAt(camera, camera.position);
}
SHVec3 view, right, UP; SHVec3 view, right, UP;
@ -171,9 +208,12 @@ namespace SHADE
camera.viewMatrix(2, 1) = view[1]; camera.viewMatrix(2, 1) = view[1];
camera.viewMatrix(2, 2) = view[2]; camera.viewMatrix(2, 2) = view[2];
camera.viewMatrix(0, 3) = -right.Dot(camera.position); camera.viewMatrix(0, 3) = -right.Dot(camera.position + camera.offset);
camera.viewMatrix(1, 3) = -UP.Dot(camera.position); camera.viewMatrix(1, 3) = -UP.Dot(camera.position + camera.offset);
camera.viewMatrix(2, 3) = -view.Dot(camera.position); camera.viewMatrix(2, 3) = -view.Dot(camera.position + camera.offset);
camera.dirtyView = false; camera.dirtyView = false;
} }
@ -221,6 +261,8 @@ namespace SHADE
SHVec3 up = { 0.0f,1.0f,0.0f }; SHVec3 up = { 0.0f,1.0f,0.0f };
target = SHVec3::RotateX(target, SHMath::DegreesToRadians(camera.pitch)); target = SHVec3::RotateX(target, SHMath::DegreesToRadians(camera.pitch));
target = SHVec3::RotateY(target, SHMath::DegreesToRadians(camera.yaw)); target = SHVec3::RotateY(target, SHMath::DegreesToRadians(camera.yaw));
target += camera.position; target += camera.position;
@ -241,6 +283,13 @@ namespace SHADE
{ {
SHCameraSystem* system = static_cast<SHCameraSystem*>(GetSystem()); SHCameraSystem* system = static_cast<SHCameraSystem*>(GetSystem());
auto& dense = SHComponentManager::GetDense<SHCameraComponent>(); auto& dense = SHComponentManager::GetDense<SHCameraComponent>();
auto& pivotDense = SHComponentManager::GetDense<SHCameraArmComponent>();
for (auto& pivot : pivotDense)
{
system->UpdatePivotArmComponent(pivot);
}
for (auto& cam : dense) for (auto& cam : dense)
{ {
system->UpdateCameraComponent(cam); system->UpdateCameraComponent(cam);
@ -274,18 +323,115 @@ namespace SHADE
} }
void SHCameraSystem::ClampCameraRotation(SHCameraComponent& camera) noexcept void SHCameraSystem::ClampCameraRotation(SHCameraComponent& camera) noexcept
{ {
constexpr float clampVal = 85.0f;
if (camera.pitch > clampVal)
camera.SetPitch(clampVal);
if (camera.pitch < -clampVal)
camera.SetPitch(-clampVal);
if (camera.roll > clampVal)
camera.SetRoll(clampVal);
if (camera.roll < -clampVal)
camera.SetRoll(-clampVal);
if (camera.pitch > 85) while (camera.yaw > 360)
camera.SetPitch(85); camera.yaw -= 360;
if (camera.pitch < -85) while (camera.yaw < -360)
camera.SetPitch(-85); camera.yaw += 360;
if (camera.roll > 85)
camera.SetRoll(85);
if (camera.roll < -85)
camera.SetRoll(-85);
} }
void SHCameraSystem::SetMainCamera(EntityID eid, size_t directorIndex) noexcept
{
if (SHComponentManager::HasComponent<SHCameraComponent>(eid) && directorIndex < directorHandleList.size())
directorHandleList[directorIndex]->SetMainCamera(*SHComponentManager::GetComponent<SHCameraComponent>(eid));
else
{
SHLOG_WARNING("Set Main Camera warning: Entity does not have camera component or director does not exist.")
}
}
void SHCameraSystem::DecomposeViewMatrix(SHMatrix const& viewMatrix, float& pitch, float& yaw, float& roll, SHVec3& pos) noexcept
{
float initPitch = pitch;
SHVec3 initPos = pos;
SHVec3 translate3, scale;
SHQuaternion quat;
//SHMatrix viewInverse = viewMatrix;
viewMatrix.Decompose(translate3, quat, scale);
yaw = 180+ SHMath::RadiansToDegrees(quat.ToEuler().y);
pitch = -SHMath::RadiansToDegrees(quat.ToEuler().x);
SHVec4 dotPos{ -viewMatrix(0,3),-viewMatrix(1,3), -viewMatrix(2,3), 1.0f };
SHMatrix mtx = viewMatrix;
mtx(0, 3) = 0.0f;
mtx(1, 3) = 0.0f;
mtx(2, 3) = 0.0f;
mtx.Transpose();
mtx = SHMatrix::Inverse(mtx);
SHVec4 translate = mtx* dotPos;
pos.x = translate.x;
pos.y = translate.y;
pos.z = translate.z;
}
void SHCameraSystem::SetCameraViewMatrix(SHCameraComponent& camera, SHMatrix const& viewMatrix) noexcept
{
DecomposeViewMatrix(viewMatrix, camera.pitch, camera.yaw, camera.roll, camera.position);
camera.dirtyView = true;
}
void SHCameraSystem::CameraLookAt(SHCameraComponent& camera, SHVec3 target) noexcept
{
if (camera.position == target)
{
//lets off set it abit so the view is nt fked
target.z -= 0.0001f;
}
SHVec3 forward, right, upVec;
SHVec3 up = { 0.0f,1.0f,0.0f };
////SHVec3::RotateZ(target, SHMath::DegreesToRadians(camera.roll));
//target = SHVec3::Normalise(target);
SHVec3::RotateZ(up, camera.roll);
up = SHVec3::Normalise(up);
forward = target - (camera.position + camera.offset); forward = SHVec3::Normalise(forward);
right = SHVec3::Cross(forward, up); right = SHVec3::Normalise(right);
upVec = SHVec3::Cross(forward, right);
SHMatrix viewMtx;
viewMtx = SHMatrix::Identity;
viewMtx(0, 0) = right[0];
viewMtx(0, 1) = right[1];
viewMtx(0, 2) = right[2];
viewMtx(1, 0) = upVec[0];
viewMtx(1, 1) = upVec[1];
viewMtx(1, 2) = upVec[2];
viewMtx(2, 0) = forward[0];
viewMtx(2, 1) = forward[1];
viewMtx(2, 2) = forward[2];
viewMtx(0, 3) = -right.Dot(camera.position + camera.offset);
viewMtx(1, 3) = -upVec.Dot(camera.position + camera.offset);
viewMtx(2, 3) = -forward.Dot(camera.position + camera.offset);
SetCameraViewMatrix(camera, viewMtx);
}
} }

View File

@ -9,6 +9,9 @@
namespace SHADE namespace SHADE
{ {
class SHCameraArmComponent;
class SH_API SHCameraSystem final : public SHSystem class SH_API SHCameraSystem final : public SHSystem
{ {
private: private:
@ -19,6 +22,11 @@ namespace SHADE
SHResourceLibrary<SHCameraDirector> directorLibrary; SHResourceLibrary<SHCameraDirector> directorLibrary;
std::vector<DirectorHandle> directorHandleList; std::vector<DirectorHandle> directorHandleList;
void UpdateCameraComponent(SHCameraComponent& camera) noexcept;
void UpdatePivotArmComponent(SHCameraArmComponent& pivot) noexcept;
public: public:
SHCameraSystem(void) = default; SHCameraSystem(void) = default;
virtual ~SHCameraSystem(void) = default; virtual ~SHCameraSystem(void) = default;
@ -39,7 +47,7 @@ namespace SHADE
class SH_API CameraSystemUpdate final: public SHSystemRoutine class SH_API CameraSystemUpdate final: public SHSystemRoutine
{ {
public: public:
CameraSystemUpdate() : SHSystemRoutine("Camera System Update", false) {}; CameraSystemUpdate() : SHSystemRoutine("Camera System Update", true) {};
virtual void Execute(double dt)noexcept override final; virtual void Execute(double dt)noexcept override final;
}; };
friend class CameraSystemUpdate; friend class CameraSystemUpdate;
@ -51,12 +59,10 @@ namespace SHADE
DirectorHandle GetDirector(size_t index) noexcept; DirectorHandle GetDirector(size_t index) noexcept;
void ClampCameraRotation(SHCameraComponent& camera) noexcept; void ClampCameraRotation(SHCameraComponent& camera) noexcept;
void UpdateEditorCamera(double dt) noexcept; void UpdateEditorCamera(double dt) noexcept;
protected: void SetMainCamera(EntityID eid, size_t directorIndex) noexcept;
void DecomposeViewMatrix(SHMatrix const& matrix, float& pitch, float& yaw, float& roll, SHVec3& pos) noexcept;
void UpdateCameraComponent(SHCameraComponent& camera) noexcept; void SetCameraViewMatrix(SHCameraComponent& camera, SHMatrix const& viewMatrix) noexcept;
void CameraLookAt(SHCameraComponent& camera, SHVec3 target) noexcept;
}; };

View File

@ -33,12 +33,18 @@ namespace SHADE
return; return;
} }
std::vector<SHComponentRemovedEvent> eventVec;
for (uint32_t i = 0; i < componentSet.Size(); ++i) for (uint32_t i = 0; i < componentSet.Size(); ++i)
{ {
SHComponent* comp = (SHComponent*) componentSet.GetElement(i, EntityHandleGenerator::GetIndex(entityID)); SHComponent* comp = (SHComponent*) componentSet.GetElement(i, EntityHandleGenerator::GetIndex(entityID));
if (comp) if (comp)
{ {
comp->OnDestroy(); comp->OnDestroy();
SHComponentRemovedEvent eventData;
eventData.eid = entityID;
eventData.removedComponentType = i;
eventVec.push_back(eventData);
} }
} }
@ -51,8 +57,15 @@ namespace SHADE
componentSet.RemoveElements(EntityHandleGenerator::GetIndex(entityID)); componentSet.RemoveElements(EntityHandleGenerator::GetIndex(entityID));
for (auto& eventData : eventVec)
{
SHEventManager::BroadcastEvent<SHComponentRemovedEvent>(eventData, SH_COMPONENT_REMOVED_EVENT);
}
//entityHandle.RemoveHandle(entityID); //entityHandle.RemoveHandle(entityID);
} }

View File

@ -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;
}
} }

View File

@ -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:

View File

@ -29,7 +29,7 @@ namespace SHADE
{ {
system.second->Init(); system.second->Init();
#ifdef _DEBUG #ifdef _DEBUG
std::cout << system.first << " Init" << std::endl; SHLOG_INFO("Initialising System {}...", system.first)
#endif #endif
} }
} }

View File

@ -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

View File

@ -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();
ImGuiTreeNodeFlags flags = (subFolders.empty() && files.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow;
if (isSelected)
flags |= ImGuiTreeNodeFlags_Selected;
if (folder == rootFolder)
flags |= ImGuiTreeNodeFlags_DefaultOpen;
ImGui::TableNextColumn(); bool isOpen = ImGui::TreeNodeEx(folder, flags, "%s %s", ICON_MD_FOLDER, folder->name.data());
ImGui::Selectable(std::format("{}", asset.id).data(), false, ImGuiSelectableFlags_SpanAllColumns); const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
if(ImGui::IsItemClicked())
{
selectedFolders.clear();
selectedFolders.push_back(folder);
}
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::TreeNodeEx(file.assetMeta, flags, "%s %s", icon.data(), file.assetMeta->name.data());
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
if(SHDragDrop::BeginSource()) if(SHDragDrop::BeginSource())
{ {
auto id = asset.id; auto id = file.assetMeta->id;
ImGui::Text("Moving Asset: %zu", id); ImGui::Text("Moving Asset: %s [%zu]", file.name.data(), file.assetMeta->id);
SHDragDrop::SetPayload<AssetID>(DRAG_RESOURCE, &id); SHDragDrop::SetPayload<AssetID>(SHDragDrop::DRAG_RESOURCE, &id);
SHDragDrop::EndSource(); SHDragDrop::EndSource();
} }
if(ImGui::IsItemClicked())
ImGui::TableNextColumn(); {
ImGui::Text("%s", asset.name.c_str()); selectedAssets.clear();
selectedAssets.push_back(file.assetMeta->id);
ImGui::TableNextColumn(); }
ImGui::Text("%s", "Type"); ImGui::TreePop();
return nodeRect;
ImGui::EndGroup();
ImGui::PopID();
} }
} }

View File

@ -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;
}; };
} }

View File

@ -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)
{ {
if (child)
RecursivelyDrawEntityNode(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,27 @@ namespace SHADE
if (SHDragDrop::BeginSource()) if (SHDragDrop::BeginSource())
{ {
std::string moveLabel = "Moving EID: "; std::string moveLabel = "Moving EID: ";
if(!isSelected) static std::vector<EntityID> draggingEntities = editor->selectedEntities;
editor->selectedEntities.push_back(eid); if (!isSelected)
for(int i = 0; i < static_cast<int>(editor->selectedEntities.size()); ++i)
{ {
moveLabel.append(std::to_string(editor->selectedEntities[i])); draggingEntities.clear();
if(i + 1 < static_cast<int>(editor->selectedEntities.size())) draggingEntities.push_back(eid);
}
for (int i = 0; i < static_cast<int>(draggingEntities.size()); ++i)
{
moveLabel.append(std::to_string(draggingEntities[i]));
if (i + 1 < static_cast<int>(draggingEntities.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, &draggingEntities);
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,31 +223,37 @@ 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);
} }
@ -216,9 +267,9 @@ 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);
} }
@ -278,12 +329,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;
} }
@ -300,9 +351,9 @@ namespace SHADE
sceneGraph.Traverse([&](SHSceneNode* nodePtr) sceneGraph.Traverse([&](SHSceneNode* nodePtr)
{ {
auto eid = nodePtr->GetEntityID(); auto eid = nodePtr->GetEntityID();
if(!startSelecting) if (!startSelecting)
{ {
if(eid == beginEID || eid == endEID) if (eid == beginEID || eid == endEID)
{ {
startSelecting = true; startSelecting = true;
editor->selectedEntities.push_back(eid); editor->selectedEntities.push_back(eid);
@ -310,10 +361,10 @@ namespace SHADE
} }
else else
{ {
if(!endSelecting) if (!endSelecting)
{ {
editor->selectedEntities.push_back(eid); editor->selectedEntities.push_back(eid);
if(eid == endEID || eid == beginEID) if (eid == endEID || eid == beginEID)
{ {
endSelecting = true; endSelecting = true;
} }
@ -322,10 +373,33 @@ namespace SHADE
}); });
} }
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 +411,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 +423,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);

View File

@ -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;

View File

@ -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"

View File

@ -13,25 +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 "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> template<typename T>
std::vector<const char*> GetRTTREnumNames() std::vector<const char*> GetRTTREnumNames()
{ {
auto const rttrType = rttr::type::get<T>(); auto const rttrType = rttr::type::get<T>();
if(!rttrType.is_enumeration()) if (!rttrType.is_enumeration())
return {}; return {};
auto const enumAlign = rttrType.get_enumeration(); auto const enumAlign = rttrType.get_enumeration();
auto const names = enumAlign.get_names(); auto const names = enumAlign.get_names();
std::vector<const char*> result; std::vector<const char*> result;
std::transform(names.begin(), names.end(), std::back_inserter(result), [](rttr::string_view const& name){return name.data();}); std::transform(names.begin(), names.end(), std::back_inserter(result), [](rttr::string_view const& name) {return name.data(); });
return result; return result;
} }
template<typename T, std::enable_if_t<std::is_base_of<SHComponent, T>::value, bool> = true> 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)
@ -60,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()))
{ {
@ -75,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();
@ -89,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>())
@ -120,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>())
@ -133,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>())
@ -146,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>())
@ -159,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>())
@ -171,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>())
@ -190,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());
} }
} }
@ -223,10 +225,10 @@ namespace SHADE
return; return;
// Get transform component for extrapolating relative sizes // Get transform component for extrapolating relative sizes
auto* transformComponent = SHComponentManager::GetComponent<SHTransformComponent>(component->GetEID()); 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()))
{ {
@ -234,8 +236,8 @@ 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);
@ -244,12 +246,12 @@ namespace SHADE
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 SHEditorWidgets::DragVec3
( (
"Half Extents", { "X", "Y", "Z" }, "Half Extents", { "X", "Y", "Z" },
[box, transformComponent] { return (transformComponent->GetWorldScale() * 2.0f) * box->GetHalfExtents(); }, [box, transformComponent] { return (box->GetHalfExtents() * 2.0f) / transformComponent->GetWorldScale(); },
[collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); }); [collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); });
} }
else if (collider->GetType() == SHCollider::Type::SPHERE) else if (collider->GetType() == SHCollider::Type::SPHERE)
@ -265,25 +267,44 @@ namespace SHADE
const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z }); const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z });
return sphere->GetRadius() / MAX_SCALE; return sphere->GetRadius() / MAX_SCALE;
}, },
[collider](float const& value) { collider->SetBoundingSphere(value);}); [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("Offsets",{ 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::DragVec3("Rotation", { "X", "Y", "Z" },
[&collider]
{
auto offset = collider->GetRotationOffset();
offset.x = SHMath::RadiansToDegrees(offset.x);
offset.y = SHMath::RadiansToDegrees(offset.y);
offset.z = SHMath::RadiansToDegrees(offset.z);
return offset;
},
[&collider](SHVec3 const& vec)
{
const SHVec3 vecInRad
{
SHMath::DegreesToRadians(vec.x)
, SHMath::DegreesToRadians(vec.y)
, SHMath::DegreesToRadians(vec.z)
};
collider->SetRotationOffset(vecInRad);
});
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());
} }
@ -291,11 +312,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();
} }
@ -311,7 +332,7 @@ namespace SHADE
if (!component) if (!component)
return; return;
const auto componentType = rttr::type::get(*component); const auto componentType = rttr::type::get(*component);
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }); SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active");
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::CollapsingHeader(componentType.get_name().data())) if (ImGui::CollapsingHeader(componentType.get_name().data()))
{ {
@ -324,10 +345,40 @@ namespace SHADE
{ {
component->SetType(static_cast<SH_LIGHT_TYPE>(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("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::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::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);}); 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));
SHResourceManager::FinaliseChanges();
}, SHDragDrop::DRAG_RESOURCE);
} }
else else
{ {

View File

@ -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,17 +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 "SHEditorComponentView.h"
namespace SHADE namespace SHADE
{ {
@ -30,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;
} }
@ -42,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;
} }
@ -107,6 +127,9 @@ namespace SHADE
if (auto cameraComponent = SHComponentManager::GetComponent_s<SHCameraComponent>(eid)) if (auto cameraComponent = SHComponentManager::GetComponent_s<SHCameraComponent>(eid))
{ {
DrawComponent(cameraComponent); DrawComponent(cameraComponent);
}if (auto cameraArmComponent = SHComponentManager::GetComponent_s<SHCameraArmComponent>(eid))
{
DrawComponent(cameraArmComponent);
} }
ImGui::Separator(); ImGui::Separator();
// Render Scripts // Render Scripts
@ -117,6 +140,8 @@ namespace SHADE
{ {
DrawAddComponentButton<SHTransformComponent>(eid); DrawAddComponentButton<SHTransformComponent>(eid);
DrawAddComponentButton<SHCameraComponent>(eid); DrawAddComponentButton<SHCameraComponent>(eid);
DrawAddComponentButton<SHCameraArmComponent>(eid);
DrawAddComponentButton<SHLightComponent>(eid);
// Components that require Transforms // Components that require Transforms

View File

@ -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"
@ -175,19 +175,37 @@ namespace SHADE
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PLAY); ImGui::BeginDisabled(editor->editorState == SHEditor::State::PLAY);
if(ImGui::SmallButton(ICON_MD_PLAY_ARROW)) if(ImGui::SmallButton(ICON_MD_PLAY_ARROW))
{ {
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
{
.previousState = editor->editorState
};
editor->editorState = SHEditor::State::PLAY; editor->editorState = SHEditor::State::PLAY;
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PLAY_EVENT);
} }
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PAUSE); ImGui::BeginDisabled(editor->editorState == SHEditor::State::PAUSE);
if(ImGui::SmallButton(ICON_MD_PAUSE)) if(ImGui::SmallButton(ICON_MD_PAUSE))
{ {
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
{
.previousState = editor->editorState
};
editor->editorState = SHEditor::State::PAUSE; editor->editorState = SHEditor::State::PAUSE;
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PAUSE_EVENT);
} }
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::BeginDisabled(editor->editorState == SHEditor::State::STOP); ImGui::BeginDisabled(editor->editorState == SHEditor::State::STOP);
if(ImGui::SmallButton(ICON_MD_STOP)) if(ImGui::SmallButton(ICON_MD_STOP))
{ {
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
{
.previousState = editor->editorState
};
editor->editorState = SHEditor::State::STOP; editor->editorState = SHEditor::State::STOP;
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT);
} }
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::EndMenuBar(); ImGui::EndMenuBar();

View File

@ -20,4 +20,10 @@ namespace SHADE
float menuBarHeight = 20.0f; float menuBarHeight = 20.0f;
std::vector<std::filesystem::path> layoutPaths; std::vector<std::filesystem::path> layoutPaths;
};//class SHEditorMenuBar };//class SHEditorMenuBar
struct SHEditorStateChangeEvent
{
SHEditor::State previousState;
};
}//namespace SHADE }//namespace SHADE

View File

@ -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();
} }
} }

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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");
} }
} }

View File

@ -16,6 +16,7 @@ of DigiPen Institute of Technology is prohibited.
// External Dependencies // External Dependencies
#include <imgui.h> #include <imgui.h>
#include "SHEditorWidgets.hpp" #include "SHEditorWidgets.hpp"
#include "ECS_Base/Managers/SHEntityManager.h"
namespace SHADE namespace SHADE
{ {
@ -156,7 +157,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::Checkbox("#", &value); return ImGui::Checkbox("##", &value);
} }
bool SHEditorUI::InputInt(const std::string& label, int& value, bool* isHovered) bool SHEditorUI::InputInt(const std::string& label, int& value, bool* isHovered)
{ {
@ -164,7 +165,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::InputInt("#", &value, return ImGui::InputInt("##", &value,
1, 10, 1, 10,
ImGuiInputTextFlags_EnterReturnsTrue); ImGuiInputTextFlags_EnterReturnsTrue);
} }
@ -175,7 +176,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
const bool CHANGED = InputInt("#", signedVal); const bool CHANGED = InputInt("##", signedVal);
if (CHANGED) if (CHANGED)
{ {
signedVal = std::clamp(signedVal, 0, std::numeric_limits<int>::max()); signedVal = std::clamp(signedVal, 0, std::numeric_limits<int>::max());
@ -189,7 +190,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::InputFloat("#", &value, return ImGui::InputFloat("##", &value,
0.1f, 1.0f, "%.3f", 0.1f, 1.0f, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue); ImGuiInputTextFlags_EnterReturnsTrue);
} }
@ -199,7 +200,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::InputDouble("#", &value, return ImGui::InputDouble("##", &value,
0.1, 1.0, "%.3f", 0.1, 1.0, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue); ImGuiInputTextFlags_EnterReturnsTrue);
} }
@ -209,7 +210,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::InputDouble("#", &value, return ImGui::InputDouble("##", &value,
1.0, 45.0, "%.3f", 1.0, 45.0, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue); ImGuiInputTextFlags_EnterReturnsTrue);
} }
@ -279,7 +280,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
const bool CHANGED = ImGui::InputText("#", &buffer[0], TEXT_FIELD_MAX_LENGTH); const bool CHANGED = ImGui::InputText("##", &buffer[0], TEXT_FIELD_MAX_LENGTH);
if (CHANGED) if (CHANGED)
{ {
value = std::string(buffer.data(), buffer.data() + TEXT_FIELD_MAX_LENGTH); value = std::string(buffer.data(), buffer.data() + TEXT_FIELD_MAX_LENGTH);
@ -287,6 +288,35 @@ namespace SHADE
return CHANGED; return CHANGED;
} }
bool SHEditorUI::InputGameObjectField(const std::string& label, uint32_t& value, bool* isHovered)
{
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
SHEntity* entity = SHEntityManager::GetEntityByID(value);
std::ostringstream oss;
if (entity)
{
oss << value << ": " << entity->name;
}
std::string entityName = oss.str();
bool changed = ImGui::InputText("##", &entityName, ImGuiInputTextFlags_ReadOnly);
if (SHDragDrop::BeginTarget())
{
if (const std::vector<EntityID>* payload = SHDragDrop::AcceptPayload<std::vector<EntityID>>(SHDragDrop::DRAG_EID))
{
if (!payload->empty())
{
value = payload->at(0);
changed = true;
}
SHDragDrop::EndTarget();
}
}
return changed;
}
bool SHEditorUI::InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames, bool* isHovered) bool SHEditorUI::InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames, bool* isHovered)
{ {
// Clamp input value // Clamp input value
@ -297,7 +327,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::BeginCombo("#", INITIAL_NAME.c_str(), ImGuiComboFlags_None)) if (ImGui::BeginCombo("##", INITIAL_NAME.c_str(), ImGuiComboFlags_None))
{ {
for (int i = 0; i < enumNames.size(); ++i) for (int i = 0; i < enumNames.size(); ++i)
{ {

View File

@ -308,6 +308,14 @@ namespace SHADE
/// <returns>True if the value was changed.</returns> /// <returns>True if the value was changed.</returns>
static bool InputTextField(const std::string& label, std::string& value, bool* isHovered = nullptr); static bool InputTextField(const std::string& label, std::string& value, bool* isHovered = nullptr);
/// <summary> /// <summary>
/// Creates a drag field widget for int input.
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputGameObjectField(const std::string& label, uint32_t& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a combo box for enumeration input. /// Creates a combo box for enumeration input.
/// </summary> /// </summary>
/// <typeparam name="Enum">The type of enum to input.</typeparam> /// <typeparam name="Enum">The type of enum to input.</typeparam>

View File

@ -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;
@ -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());

View File

@ -13,4 +13,7 @@ constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 };
constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 }; constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 };
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_ADDED_EVENT { 6 }; constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_ADDED_EVENT { 6 };
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_REMOVED_EVENT { 7 }; constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_REMOVED_EVENT { 7 };
constexpr SHEventIdentifier SH_EDITOR_ON_PLAY_EVENT { 8 };
constexpr SHEventIdentifier SH_EDITOR_ON_PAUSE_EVENT { 9 };
constexpr SHEventIdentifier SH_EDITOR_ON_STOP_EVENT { 10 };

View File

@ -282,6 +282,11 @@ namespace SHADE
} }
void SHVkCommandBuffer::SetLineWidth(float lineWidth) noexcept
{
vkCommandBuffer.setLineWidth(lineWidth);
}
/***************************************************************************/ /***************************************************************************/
/*! /*!

View File

@ -115,6 +115,7 @@ namespace SHADE
// Dynamic State // Dynamic State
void SetViewportScissor (float vpWidth, float vpHeight, uint32_t sWidth, uint32_t sHeight, float vpX = 0.0f, float vpY = 0.0f, int32_t sX = 0.0f, int32_t sY = 0.0f, float vpMinDepth = 0.0f, float vpMaxDepth = 1.0f) noexcept; void SetViewportScissor (float vpWidth, float vpHeight, uint32_t sWidth, uint32_t sHeight, float vpX = 0.0f, float vpY = 0.0f, int32_t sX = 0.0f, int32_t sY = 0.0f, float vpMinDepth = 0.0f, float vpMaxDepth = 1.0f) noexcept;
void SetLineWidth (float lineWidth) noexcept;
// Binding Commands // Binding Commands
void BindPipeline (Handle<SHVkPipeline> const& pipelineHdl) noexcept; void BindPipeline (Handle<SHVkPipeline> const& pipelineHdl) noexcept;

View File

@ -74,10 +74,11 @@ namespace SHADE
void SHBatch::Remove(const SHRenderable* renderable) void SHBatch::Remove(const SHRenderable* renderable)
{ {
// Check if we have a SubBatch with the same mesh yet // Check if we have a SubBatch with the existing mesh yet (if changed, we use the old mesh)
Handle<SHMesh> prevSubBatchMesh = renderable->HasMeshChanged() ? renderable->GetPrevMesh() : renderable->GetMesh();
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->GetMesh(); return batch.Mesh == prevSubBatchMesh;
}); });
// Attempt to remove if it exists // Attempt to remove if it exists
@ -88,9 +89,7 @@ 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(); Handle<SHMaterialInstance> matToCheck = renderable->HasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial();
for (const auto& sb : subBatches) for (const auto& sb : subBatches)
{ {
// Check material usage // Check material usage

View File

@ -0,0 +1,202 @@
/************************************************************************************//*!
\file SHDebugDrawSystem.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 16, 2022
\brief Contains the definition of functions of the SHDebugDrawSystem 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.
*//*************************************************************************************/
#include "SHpch.h"
#include "SHDebugDrawSystem.h"
// STL Includes
#include <algorithm>
// Project Includes
#include "../Meshes/SHMeshData.h"
#include "../Meshes/SHPrimitiveGenerator.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "SHGraphicsSystem.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "../../SHVkUtil.h"
#include "Graphics/MiddleEnd/Interface/SHViewport.h"
#include "Graphics/MiddleEnd/Interface/SHRenderer.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* DrawRoutine */
/*---------------------------------------------------------------------------------*/
SHDebugDrawSystem::ProcessPointsRoutine::ProcessPointsRoutine()
: SHSystemRoutine("Debug Draw", true)
{
SystemFamily::GetID<SHDebugDrawSystem>();
}
void SHDebugDrawSystem::ProcessPointsRoutine::Execute(double dt) noexcept
{
auto gfxSys = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (!gfxSys)
{
SHLOG_WARNING("[DebugDraw] Attempted to do debug draw without a graphics system.");
return;
}
// Get current frame index
const uint32_t FRAME_IDX = gfxSys->GetCurrentFrameIndex();
// Create the buffer if it doesn't exist or just update it
SHDebugDrawSystem* system = static_cast<SHDebugDrawSystem*>(GetSystem());
system->numPoints[FRAME_IDX] = system->points.size();
const uint32_t DATA_SIZE = sizeof(PointVertex) * system->points.size();
if (DATA_SIZE > 0)
{
system->vertexBuffers[FRAME_IDX]->WriteToMemory(system->points.data(), DATA_SIZE, 0, 0);
}
// Reset for next frame
system->points.clear();
}
/*---------------------------------------------------------------------------------*/
/* SHSystem overrides */
/*---------------------------------------------------------------------------------*/
void SHDebugDrawSystem::Init()
{
// Register function for subpass
const auto* GFX_SYSTEM = SHSystemManager::GetSystem<SHGraphicsSystem>();
auto const& RENDERERS = GFX_SYSTEM->GetDefaultViewport()->GetRenderers();
auto renderGraph = RENDERERS[SHGraphicsConstants::RenderGraphIndices::WORLD]->GetRenderGraph();
auto subPass = renderGraph->GetNode("Debug Draw")->GetSubpass("Debug Draw");
subPass->AddExteriorDrawCalls([this, GFX_SYSTEM](Handle<SHVkCommandBuffer>& cmdBuffer)
{
// Get Current frame index
const uint32_t FRAME_IDX = GFX_SYSTEM->GetCurrentFrameIndex();
// Don't draw if no points
if (numPoints[FRAME_IDX] <= 0)
return;
cmdBuffer->BindPipeline(GFX_SYSTEM->GetDebugDrawPipeline());
cmdBuffer->SetLineWidth(LineWidth);
cmdBuffer->BindVertexBuffer(0, vertexBuffers[FRAME_IDX], 0);
cmdBuffer->DrawArrays(numPoints[FRAME_IDX], 1, 0, 0);
});
// Reset trackers
std::fill_n(numPoints.begin(), numPoints.size(), 0);
// Allocate buffers
static constexpr uint32_t BUFFER_SIZE = MAX_POINTS * sizeof(PointVertex);
for (Handle<SHVkBuffer>& bufHandle : vertexBuffers)
{
bufHandle = GFX_SYSTEM->GetDevice()->CreateBuffer
(
BUFFER_SIZE,
nullptr,
0,
vk::BufferUsageFlagBits::eVertexBuffer,
VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO,
VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT
);
}
}
void SHDebugDrawSystem::Exit()
{
for (auto vertexBuffer : vertexBuffers)
{
if (vertexBuffer)
vertexBuffer.Free();
}
}
/*---------------------------------------------------------------------------------*/
/* Draw Functions */
/*---------------------------------------------------------------------------------*/
void SHDebugDrawSystem::DrawLine(const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt)
{
if (points.size() > MAX_POINTS)
{
SHLOG_WARNING("[DebugDraw] Exceeded maximum size of drawable debug elements.");
return;
}
points.emplace_back(PointVertex{ startPt, color });
points.emplace_back(PointVertex{ endPt, color });
}
void SHDebugDrawSystem::DrawTri(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3)
{
DrawPoly(color, { pt1, pt2, pt3 });
}
void SHDebugDrawSystem::DrawQuad(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3, const SHVec3& pt4)
{
DrawPoly(color, { pt1, pt2, pt3, pt4 });
}
void SHDebugDrawSystem::DrawPoly(const SHVec4& color, std::initializer_list<SHVec3> pointList)
{
DrawPoly(color, pointList.begin(), pointList.end());
}
void SHDebugDrawSystem::DrawCube(const SHVec4& color, const SHVec3& pos, const SHVec3& size)
{
static const SHVec3 EXTENTS = SHVec3 { 0.5f, 0.5f, 0.5f };
static const SHVec3 UNIT_BOT_LEFT_FRONT = SHVec3 { pos - EXTENTS };
static const SHVec3 UNIT_BOT_RIGHT_FRONT = SHVec3 { pos + SHVec3 { EXTENTS.x, -EXTENTS.y, -EXTENTS.z } };
static const SHVec3 UNIT_BOT_RIGHT_BACK = SHVec3 { pos + SHVec3 { EXTENTS.x, -EXTENTS.y, EXTENTS.z } };
static const SHVec3 UNIT_BOT_LEFT_BACK = SHVec3 { pos + SHVec3 { -EXTENTS.x, -EXTENTS.y, EXTENTS.z } };
static const SHVec3 UNIT_TOP_LEFT_BACK = SHVec3 { pos + SHVec3 { -EXTENTS.x, EXTENTS.y, EXTENTS.z } };
static const SHVec3 UNIT_TOP_RIGHT_FRONT = SHVec3 { pos + SHVec3 { EXTENTS.x, EXTENTS.y, -EXTENTS.z } };
static const SHVec3 UNIT_TOP_LEFT_FRONT = SHVec3 { pos + SHVec3 { -EXTENTS.x, EXTENTS.y, -EXTENTS.z } };
static const SHVec3 UNIT_TOP_RIGHT_BACK = SHVec3 { pos + EXTENTS };
const SHVec3 BOT_LEFT_BACK = UNIT_BOT_LEFT_BACK * size;
const SHVec3 BOT_RIGHT_BACK = UNIT_BOT_RIGHT_BACK * size;
const SHVec3 BOT_LEFT_FRONT = UNIT_BOT_LEFT_FRONT * size;
const SHVec3 BOT_RIGHT_FRONT = UNIT_BOT_RIGHT_FRONT * size;
const SHVec3 TOP_LEFT_BACK = UNIT_TOP_LEFT_BACK * size;
const SHVec3 TOP_RIGHT_BACK = UNIT_TOP_RIGHT_BACK * size;
const SHVec3 TOP_LEFT_FRONT = UNIT_TOP_LEFT_FRONT * size;
const SHVec3 TOP_RIGHT_FRONT = UNIT_TOP_RIGHT_FRONT * size;
DrawPoly
(
color,
{
// Bottom Square
BOT_LEFT_BACK , BOT_RIGHT_BACK,
BOT_RIGHT_BACK , BOT_RIGHT_FRONT,
BOT_RIGHT_FRONT, BOT_LEFT_FRONT,
BOT_LEFT_FRONT , BOT_LEFT_BACK,
// Top Square
TOP_LEFT_BACK , TOP_RIGHT_BACK,
TOP_RIGHT_BACK , TOP_RIGHT_FRONT,
TOP_RIGHT_FRONT, TOP_LEFT_FRONT,
TOP_LEFT_FRONT , TOP_LEFT_BACK,
// Middle Lines
TOP_LEFT_BACK , BOT_LEFT_BACK,
TOP_RIGHT_BACK , BOT_RIGHT_BACK,
TOP_RIGHT_FRONT, BOT_RIGHT_FRONT,
TOP_LEFT_FRONT , BOT_LEFT_FRONT
}
);
}
void SHDebugDrawSystem::DrawSphere(const SHVec4& color, const SHVec3& pos, double radius)
{
if (spherePoints.empty())
{
// Generate
static const SHMeshData SPHERE = SHPrimitiveGenerator::Sphere();
for (const auto& idx : SPHERE.Indices)
{
spherePoints.emplace_back(SPHERE.VertexPositions[idx]);
}
}
DrawPoly(color, spherePoints.begin(), spherePoints.end());
}
}

View File

@ -0,0 +1,159 @@
/************************************************************************************//*!
\file SHDebugDrawSystem.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 16, 2022
\brief Contains the definition of the SHDebugDrawSystem 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
// STL Includes
#include <vector>
// Project Includes
#include "SH_API.h"
#include "Math/Vector/SHVec2.h"
#include "Math/Vector/SHVec3.h"
#include "Math/Vector/SHVec4.h"
#include "ECS_Base/System/SHSystem.h"
#include "ECS_Base/System/SHSystemRoutine.h"
#include "Resource/SHHandle.h"
#include "Graphics/Buffers/SHVkBuffer.h"
#include "SHGraphicsConstants.h"
#include "Math/SHColour.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHVkBuffer;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/// <summary>
/// Manages the Debug Draw system.
/// </summary>
class SH_API SHDebugDrawSystem final : public SHSystem
{
public:
/*---------------------------------------------------------------------------------*/
/* System Routines */
/*---------------------------------------------------------------------------------*/
class SH_API ProcessPointsRoutine final : public SHSystemRoutine
{
public:
ProcessPointsRoutine();
virtual void Execute(double dt) noexcept override final;
};
/*---------------------------------------------------------------------------------*/
/* SHSystem overrides */
/*---------------------------------------------------------------------------------*/
virtual void Init() override final;
virtual void Exit() override final;
/*---------------------------------------------------------------------------------*/
/* Configuration Functions */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Configures the line width used to draw all lines in the Debug Draw system.
/// </summary>
float LineWidth = 1.0f;
/*---------------------------------------------------------------------------------*/
/* Draw Functions */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Renders a line between two points in world space.
/// </summary>
/// <param name="color">Colour of the line.</param>
/// <param name="startPt">First point of the line.</param>
/// <param name="endPt">Second point of the line.</param>
void DrawLine(const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt);
/// <summary>
/// Renders a triangle indicated by three points in world space.
/// </summary>
/// <param name="color">Colour of the triangle.</param>
/// <param name="pt1">First point of the triangle.</param>
/// <param name="pt2">Second point of the triangle.</param>
/// <param name="pt3">Third point of the triangle.</param>
void DrawTri(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3);
/// <summary>
/// Renders a quadrilateral indicated by four points in world space.
/// </summary>
/// <param name="color">Colour of the quadrilateral.</param>
/// <param name="pt1">First point of the triangle.</param>
/// <param name="pt2">Second point of the quadrilateral.</param>
/// <param name="pt3">Third point of the quadrilateral.</param>
/// <param name="pt4">Third point of the quadrilateral.</param>
void DrawQuad(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3, const SHVec3& pt4);
/// <summary>
/// Renders a polygon indicated by the specified set of points in world space.
/// </summary>
/// <param name="color">Colour of the polygon.</param>
/// <param name="pointList">List of points for the polygon.</param>
void DrawPoly(const SHVec4& color, std::initializer_list<SHVec3> pointList);
/// <summary>
/// Renders a polygon indicated by the specified set of points in world space.
/// </summary>
/// <typeparam name="IterType">Iterator for a STL-like container.</typeparam>
/// <param name="color">Colour of the polygon.</param>
/// <param name="pointListBegin">
/// Iterator to the first point of the point container.
/// </param>
/// <param name="pointListEnd">
/// One past last iterator of the point container.
/// </param>
template<typename IterType>
void DrawPoly(const SHVec4& color, IterType pointListBegin, IterType pointListEnd);
/// <summary>
/// Renders a wireframe cube centered around the position specified in world space.
/// </summary>
/// <param name="color">Colour of the cube.</param>
/// <param name="pos">Position where the cube wil be centered at.</param>
/// <param name="size">Size of the rendered cube.</param>
void DrawCube(const SHVec4& color, const SHVec3& pos, const SHVec3& size);
/// <summary>
/// Renders a wireframe sphere centered around the position specified in world space.
/// </summary>
/// <param name="color">Colour of the sphere.</param>
/// <param name="pos">Position where the sphere wil be centered at.</param>
/// <param name="size">Size of the rendered sphere.</param>
void DrawSphere(const SHVec4& color, const SHVec3& pos, double radius);
private:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
struct SH_API PointVertex
{
SHVec4 Position;
SHVec4 Color;
};
using TripleBuffer = std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS>;
using TripleUInt = std::array<uint32_t, SHGraphicsConstants::NUM_FRAME_BUFFERS>;
/*---------------------------------------------------------------------------------*/
/* Constants */
/*---------------------------------------------------------------------------------*/
static constexpr uint32_t MAX_POINTS = 100'000;
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
// CPU Buffers
std::vector<PointVertex> points;
// GPU Buffers
TripleBuffer vertexBuffers;
TripleUInt numPoints;
// Cached Points for polygon drawing
std::vector<SHVec3> spherePoints;
};
}
#include "SHDebugDrawSystem.hpp"

View File

@ -0,0 +1,48 @@
/************************************************************************************//*!
\file SHDebugDrawSystem.hpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 16, 2022
\brief Contains the definition of template functions the SHDebugDrawSystem
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
#include "SHDebugDrawSystem.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Draw Functions */
/*-----------------------------------------------------------------------------------*/
template<typename IterType>
void SHDebugDrawSystem::DrawPoly(const SHVec4& color, IterType pointListBegin, IterType pointListEnd)
{
// Ensure dereferenced type is SHVec3
static_assert(std::is_same_v<SHVec3, std::remove_cvref_t<decltype(*pointListBegin)>>, "Parameters to DrawPoly must be SHVec3.");
// Check if points exceeded max
if (points.size() > MAX_POINTS)
{
SHLOG_WARNING("[DebugDraw] Exceeded maximum size of drawable debug elements.");
return;
}
const size_t POINTS_COUNT = pointListEnd - pointListBegin;
// Invalid polygon
if (POINTS_COUNT < 2)
{
SHLOG_WARNING("[SHDebugDraw] Invalid polygon provided to DrawPoly().");
return;
}
const size_t POINTS_ROUNDED_COUNT = POINTS_COUNT / 2 * 2;
for (auto pointIter = pointListBegin; pointIter != (pointListBegin + POINTS_ROUNDED_COUNT); ++pointIter)
{
points.emplace_back(PointVertex{ *pointIter, color });
}
}
}

View File

@ -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"
@ -37,8 +37,10 @@ of DigiPen Institute of Technology is prohibited.
#include "Assets/Asset Types/SHTextureAsset.h" #include "Assets/Asset Types/SHTextureAsset.h"
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h" #include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
#include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h" #include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h"
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include "Resource/SHResourceManager.h"
#include "Graphics/SHVkUtil.h"
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
namespace SHADE namespace SHADE
{ {
@ -106,19 +108,16 @@ namespace SHADE
descPool = device->CreateDescriptorPools(); descPool = device->CreateDescriptorPools();
// Create generic command buffer // Create generic command buffer
//transferCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
graphicsCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true); graphicsCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_VS.glsl"); // Load Built In Shaders
SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_FS.glsl"); static constexpr AssetID VS_DEFAULT = 39210065; defaultVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEFAULT);
SHAssetManager::CompileAsset("../../Assets/Shaders/DeferredComposite_CS.glsl"); static constexpr AssetID FS_DEFAULT = 46377769; defaultFragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(FS_DEFAULT);
SHAssetManager::CompileAsset("../../Assets/Shaders/SSAO_CS.glsl"); static constexpr AssetID VS_DEBUG = 48002439; debugVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEBUG);
SHAssetManager::CompileAsset("../../Assets/Shaders/SSAOBlur_CS.glsl"); static constexpr AssetID FS_DEBUG = 36671027; debugFragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(FS_DEBUG);
static constexpr AssetID CS_COMPOSITE = 45072428; deferredCompositeShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(CS_COMPOSITE);
shaderModuleLibrary.ImportAllShaderSource(device); static constexpr AssetID SSAO = 38430899; ssaoShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(SSAO);
shaderModuleLibrary.ReflectAllShaderModules(); static constexpr AssetID SSAO_BLUR = 39760835; ssaoBlurShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(SSAO_BLUR);
} }
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
@ -220,7 +219,6 @@ namespace SHADE
ssaoStorage->PrepareRotationVectorsVkData(device); ssaoStorage->PrepareRotationVectorsVkData(device);
auto ssaoShader = shaderModuleLibrary.GetBuiltInShaderModule("SSAO_CS");
Handle<SHRenderGraphNodeCompute> ssaoPass = gBufferNode->AddNodeCompute(ssaoShader, {"Position", "Normals", "SSAO"}); Handle<SHRenderGraphNodeCompute> ssaoPass = gBufferNode->AddNodeCompute(ssaoShader, {"Position", "Normals", "SSAO"});
auto ssaoDataBuffer = ssaoStorage->GetBuffer(); auto ssaoDataBuffer = ssaoStorage->GetBuffer();
ssaoPass->ModifyWriteDescBufferComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_BUFFER_BINDING, { &ssaoDataBuffer, 1 }, 0, ssaoStorage->GetBuffer()->GetSizeStored()); ssaoPass->ModifyWriteDescBufferComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_BUFFER_BINDING, { &ssaoDataBuffer, 1 }, 0, ssaoStorage->GetBuffer()->GetSizeStored());
@ -228,21 +226,21 @@ namespace SHADE
auto viewSamplerLayout = ssaoStorage->GetViewSamplerLayout(); auto viewSamplerLayout = ssaoStorage->GetViewSamplerLayout();
ssaoPass->ModifyWriteDescImageComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_IMAGE_BINDING, {&viewSamplerLayout, 1}); ssaoPass->ModifyWriteDescImageComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_IMAGE_BINDING, {&viewSamplerLayout, 1});
auto ssaoBlurShader = shaderModuleLibrary.GetBuiltInShaderModule("SSAOBlur_CS");
Handle<SHRenderGraphNodeCompute> ssaoBlurPass = gBufferNode->AddNodeCompute(ssaoBlurShader, { "SSAO", "SSAO Blur"}); Handle<SHRenderGraphNodeCompute> ssaoBlurPass = gBufferNode->AddNodeCompute(ssaoBlurShader, { "SSAO", "SSAO Blur"});
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* DEFERRED COMPOSITE SUBPASS INIT */ /* DEFERRED COMPOSITE SUBPASS INIT */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
auto deferredCompositeShader = shaderModuleLibrary.GetBuiltInShaderModule("DeferredComposite_CS");
gBufferNode->AddNodeCompute(deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Scene" }); gBufferNode->AddNodeCompute(deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Scene" });
/*-----------------------------------------------------------------------*/ // Set up Debug Draw Pass
/* DUMMY SUBPASS TO TRANSITION SCENE FOR PRESENT USAGE */ auto debugDrawNode = worldRenderGraph->AddNode("Debug Draw", { "Scene" }, {"G-Buffer"});
/*-----------------------------------------------------------------------*/ auto debugDrawSubpass = debugDrawNode->AddSubpass("Debug Draw");
// Dummy to transition scene to be used for shader read debugDrawSubpass->AddColorOutput("Scene");
auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, {"G-Buffer"}); // no predecessors
// Dummy Node
auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, { "Debug Draw" }); // no predecessors
auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass"); auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass");
dummySubpass->AddInput("Scene"); dummySubpass->AddInput("Scene");
@ -262,10 +260,57 @@ namespace SHADE
worldRenderer->SetCameraDirector(cameraSystem->CreateDirector()); worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
auto cubeVS = shaderModuleLibrary.GetBuiltInShaderModule("TestCube_VS"); // Create default materials
auto cubeFS = shaderModuleLibrary.GetBuiltInShaderModule("TestCube_FS"); defaultMaterial = AddMaterial(defaultVertShader, defaultFragShader, gBufferSubpass);
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferSubpass); // Create debug draw pipeline
auto debugDrawPipelineLayout = resourceManager.Create<SHVkPipelineLayout>
(
device, SHPipelineLayoutParams
{
.shaderModules = { debugVertShader, debugFragShader },
.globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts()
}
);
debugDrawPipeline = resourceManager.Create<SHVkPipeline>(device, debugDrawPipelineLayout, nullptr, debugDrawNode->GetRenderpass(), debugDrawSubpass);
debugDrawPipeline->GetPipelineState().SetRasterizationState(SHRasterizationState
{
.polygonMode = vk::PolygonMode::eLine,
.cull_mode = vk::CullModeFlagBits::eNone
});
debugDrawPipeline->GetPipelineState().SetInputAssemblyState(SHInputAssemblyState
{
.topology = vk::PrimitiveTopology::eLineList
});
SHVertexInputState debugDrawVertexInputState;
debugDrawVertexInputState.AddBinding(false, true, { SHVertexAttribute(SHAttribFormat::FLOAT_4D), SHVertexAttribute(SHAttribFormat::FLOAT_4D) });
debugDrawPipeline->GetPipelineState().SetVertexInputState(debugDrawVertexInputState);
SHColorBlendState colorBlendState{};
colorBlendState.logic_op_enable = VK_FALSE;
colorBlendState.logic_op = vk::LogicOp::eCopy;
auto const& subpassColorReferences = debugDrawSubpass->GetColorAttachmentReferences();
colorBlendState.attachments.reserve(subpassColorReferences.size());
for (auto& att : subpassColorReferences)
{
colorBlendState.attachments.push_back(vk::PipelineColorBlendAttachmentState
{
.blendEnable = SHVkUtil::IsBlendCompatible(debugDrawSubpass->GetFormatFromAttachmentReference(att.attachment)),
.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha,
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
.colorBlendOp = vk::BlendOp::eAdd,
.srcAlphaBlendFactor = vk::BlendFactor::eOne,
.dstAlphaBlendFactor = vk::BlendFactor::eZero,
.alphaBlendOp = vk::BlendOp::eAdd,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
}
);
}
debugDrawPipeline->GetPipelineState().SetColorBlenState(colorBlendState);
debugDrawPipeline->ConstructPipeline();
} }
void SHGraphicsSystem::InitMiddleEnd(void) noexcept void SHGraphicsSystem::InitMiddleEnd(void) noexcept
@ -696,10 +741,14 @@ namespace SHADE
void SHGraphicsSystem::BuildMeshBuffers() void SHGraphicsSystem::BuildMeshBuffers()
{ {
transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
device->WaitIdle();
transferCmdBuffer->BeginRecording(); transferCmdBuffer->BeginRecording();
meshLibrary.BuildBuffers(device, transferCmdBuffer); meshLibrary.BuildBuffers(device, transferCmdBuffer);
transferCmdBuffer->EndRecording(); transferCmdBuffer->EndRecording();
graphicsQueue->SubmitCommandBuffer({ transferCmdBuffer }); graphicsQueue->SubmitCommandBuffer({ transferCmdBuffer });
device->WaitIdle();
transferCmdBuffer.Free(); transferCmdBuffer = {};
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -724,10 +773,14 @@ namespace SHADE
void SHGraphicsSystem::BuildTextures() void SHGraphicsSystem::BuildTextures()
{ {
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
device->WaitIdle();
texLibrary.BuildTextures texLibrary.BuildTextures
( (
device, graphicsTexCmdBuffer, graphicsQueue, descPool device, graphicsTexCmdBuffer, graphicsQueue, descPool
); );
device->WaitIdle();
graphicsTexCmdBuffer.Free(); graphicsTexCmdBuffer = {};
} }
#pragma endregion ADD_REMOVE #pragma endregion ADD_REMOVE
@ -767,6 +820,7 @@ namespace SHADE
void SHGraphicsSystem::EndRoutine::Execute(double) noexcept void SHGraphicsSystem::EndRoutine::Execute(double) noexcept
{ {
reinterpret_cast<SHGraphicsSystem*>(system)->EndRender(); reinterpret_cast<SHGraphicsSystem*>(system)->EndRender();
SHResourceManager::FinaliseChanges();
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -784,8 +838,13 @@ namespace SHADE
if (!renderable.HasChanged()) if (!renderable.HasChanged())
continue; continue;
// Remove from old material's SuperBatch if (!renderable.GetMesh())
Handle<SHMaterialInstance> prevMaterial = renderable.GetPrevMaterial(); {
SHLOG_CRITICAL("NULL Mesh provided!");
}
// Remove from the SuperBatch it is previously in (prevMat if mat has changed)
Handle<SHMaterialInstance> prevMaterial = renderable.HasMaterialChanged() ? renderable.GetPrevMaterial() : renderable.GetMaterial();
if (prevMaterial) if (prevMaterial)
{ {
Handle<SHSuperBatch> oldSuperBatch = prevMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); Handle<SHSuperBatch> oldSuperBatch = prevMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();

View File

@ -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/SHShaderModuleLibrary.h"
#include "SHMeshLibrary.h" #include "SHMeshLibrary.h"
#include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h" #include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h"
#include "../Textures/SHTextureLibrary.h" #include "../Textures/SHTextureLibrary.h"
@ -290,10 +289,13 @@ namespace SHADE
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; Handle<SHRenderGraphNode> GetPrimaryRenderpass() const noexcept;
//SHRenderGraph const& GetRenderGraph(void) const noexcept; Handle<SHVkPipeline> GetDebugDrawPipeline(void) const noexcept { return debugDrawPipeline; }
uint32_t GetCurrentFrameIndex(void) const noexcept { return renderContext.GetCurrentFrame(); }
//Handle<SHVkRenderpass> GetRenderPass() const { return renderPass; }
/*-----------------------------------------------------------------------------*/
/* Getters */
/*-----------------------------------------------------------------------------*/
SHWindow* GetWindow() noexcept { return window; }
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -327,6 +329,7 @@ namespace SHADE
SHTextureLibrary texLibrary; SHTextureLibrary texLibrary;
SHSamplerCache samplerCache; SHSamplerCache samplerCache;
SHMaterialInstanceCache materialInstanceCache; SHMaterialInstanceCache materialInstanceCache;
// Viewports // Viewports
#ifdef SHEDITOR #ifdef SHEDITOR
Handle<SHViewport> editorViewport; Handle<SHViewport> editorViewport;
@ -337,10 +340,6 @@ namespace SHADE
Handle<SHViewport> worldViewport; // Whole screen Handle<SHViewport> worldViewport; // Whole screen
std::vector<Handle<SHViewport>> viewports; // Additional viewports std::vector<Handle<SHViewport>> viewports; // Additional viewports
// Debug Renderers
Handle<SHRenderer> debugWorldRenderer;
Handle<SHRenderer> debugScreenRenderer;
// Temp renderers // Temp renderers
Handle<SHRenderer> worldRenderer; Handle<SHRenderer> worldRenderer;
@ -348,10 +347,19 @@ namespace SHADE
Handle<SHCamera> worldCamera; Handle<SHCamera> worldCamera;
Handle<SHCamera> screenCamera; Handle<SHCamera> screenCamera;
SHShaderModuleLibrary shaderModuleLibrary; // Built-In Shaders
Handle<SHVkShaderModule> defaultVertShader;
Handle<SHVkShaderModule> defaultFragShader;
Handle<SHVkShaderModule> debugVertShader;
Handle<SHVkShaderModule> debugFragShader;
Handle<SHVkShaderModule> deferredCompositeShader;
Handle<SHVkShaderModule> ssaoShader;
Handle<SHVkShaderModule> ssaoBlurShader;
// Temp Materials
// Built-In Materials
Handle<SHMaterial> defaultMaterial; Handle<SHMaterial> defaultMaterial;
Handle<SHVkPipeline> debugDrawPipeline;
Handle<SHRenderGraph> worldRenderGraph; Handle<SHRenderGraph> worldRenderGraph;

View File

@ -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.");
}
}

View File

@ -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();
};
}

View File

@ -0,0 +1,36 @@
/************************************************************************************//*!
\file SHMaterialSpec.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 31, 2022
\brief Contains the struct definition of SHMaterialSpec.
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
// Standard Library
#include <string>
#include <vector>
#include <utility>
// Project Includes
#include "Assets/SHAssetMacros.h"
namespace SHADE
{
/*************************************************************************************/
/*!
\brief
Describes a Material's serialized properties. A representation of a material that is
independent of GPU resources.
*/
/*************************************************************************************/
struct SHMaterialSpec
{
AssetID vertexShader;
AssetID fragShader;
std::string subpassName;
YAML::Node properties;
};
}

View File

@ -18,6 +18,15 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/
/* Static Member Definitions */
/*-----------------------------------------------------------------------------------*/
SHMeshData SHPrimitiveGenerator::cubeMesh;
SHMeshData SHPrimitiveGenerator::sphereMesh;
/*-----------------------------------------------------------------------------------*/
/* Primitive Generation Functions */
/*-----------------------------------------------------------------------------------*/
SHMeshData SHPrimitiveGenerator::Cube() noexcept SHMeshData SHPrimitiveGenerator::Cube() noexcept
{ {
SHMeshData mesh; SHMeshData mesh;
@ -26,26 +35,26 @@ namespace SHADE
{ {
// front // front
SHVec3(-0.5f, -0.5f, 0.5f), SHVec3(-0.5f, -0.5f, 0.5f),
SHVec3( 0.5f, -0.5f, 0.5f), SHVec3(0.5f, -0.5f, 0.5f),
SHVec3( 0.5f, 0.5f, 0.5f), SHVec3(0.5f, 0.5f, 0.5f),
SHVec3(-0.5f, 0.5f, 0.5f), SHVec3(-0.5f, 0.5f, 0.5f),
// back // back
SHVec3(-0.5f, -0.5f, -0.5f), SHVec3(-0.5f, -0.5f, -0.5f),
SHVec3(-0.5f, 0.5f, -0.5f), SHVec3(-0.5f, 0.5f, -0.5f),
SHVec3( 0.5f, 0.5f, -0.5f), SHVec3(0.5f, 0.5f, -0.5f),
SHVec3( 0.5f, -0.5f, -0.5f), SHVec3(0.5f, -0.5f, -0.5f),
// top // top
SHVec3(-0.5f, 0.5f, -0.5f), SHVec3(-0.5f, 0.5f, -0.5f),
SHVec3(-0.5f, 0.5f, 0.5f), SHVec3(-0.5f, 0.5f, 0.5f),
SHVec3( 0.5f, 0.5f, 0.5f), SHVec3(0.5f, 0.5f, 0.5f),
SHVec3( 0.5f, 0.5f, -0.5f), SHVec3(0.5f, 0.5f, -0.5f),
// bottom // bottom
SHVec3(-0.5f, -0.5f, -0.5f), SHVec3(-0.5f, -0.5f, -0.5f),
SHVec3( 0.5f, -0.5f, -0.5f), SHVec3(0.5f, -0.5f, -0.5f),
SHVec3( 0.5f, -0.5f, 0.5f), SHVec3(0.5f, -0.5f, 0.5f),
SHVec3(-0.5f, -0.5f, 0.5f), SHVec3(-0.5f, -0.5f, 0.5f),
// right // right
@ -193,7 +202,90 @@ namespace SHADE
Handle<SHMesh> SHPrimitiveGenerator::Cube(SHMeshLibrary& meshLibrary) noexcept Handle<SHMesh> SHPrimitiveGenerator::Cube(SHMeshLibrary& meshLibrary) noexcept
{ {
static SHMeshData meshData = Cube(); if (cubeMesh.VertexPositions.empty())
cubeMesh = Cube();
return addMeshDataTo(cubeMesh, meshLibrary);
}
Handle<SHADE::SHMesh> SHPrimitiveGenerator::Cube(SHGraphicsSystem& gfxSystem) noexcept
{
if (cubeMesh.VertexPositions.empty())
cubeMesh = Cube();
return addMeshDataTo(cubeMesh, gfxSystem);
}
SHADE::SHMeshData SHPrimitiveGenerator::Sphere() noexcept
{
SHMeshData meshData;
const int LAT_SLICES = 12;
const int LONG_SLICES = 12;
float radius = 1;
for (int latNum = 0; latNum <= LAT_SLICES; ++latNum)
{
float theta = static_cast<float>(latNum * std::numbers::pi / LAT_SLICES);
float sinTheta = sin(theta);
float cosTheta = cos(theta);
for (int longNum = 0; longNum <= LONG_SLICES; ++longNum)
{
float phi = static_cast<float>(longNum * 2 * std::numbers::pi / LONG_SLICES);
float sinPhi = sin(phi);
float cosPhi = cos(phi);
const SHVec3 NORMAL = SHVec3(cosPhi * sinTheta, cosTheta, sinPhi * sinTheta);
meshData.VertexNormals.emplace_back(NORMAL);
meshData.VertexTangents.emplace_back(/* TODO */);
meshData.VertexTexCoords.emplace_back
(
1.0f - (longNum / static_cast<float>(LONG_SLICES)),
1.0f - (latNum / static_cast<float>(LAT_SLICES))
);
meshData.VertexPositions.emplace_back(radius * NORMAL.x, radius * NORMAL.y, radius * NORMAL.z);
}
}
for (int latNumber{}; latNumber < LAT_SLICES; latNumber++)
{
for (int longNumber{}; longNumber < LONG_SLICES; longNumber++)
{
const auto FIRST = (latNumber * (LONG_SLICES + 1)) + longNumber;
const auto SECOND = (FIRST + LONG_SLICES + 1);
meshData.Indices.emplace_back(FIRST);
meshData.Indices.emplace_back(SECOND);
meshData.Indices.emplace_back(FIRST + 1);
meshData.Indices.emplace_back(SECOND);
meshData.Indices.emplace_back(SECOND + 1);
meshData.Indices.emplace_back(FIRST + 1);
}
}
return meshData;
}
SHADE::Handle<SHADE::SHMesh> SHPrimitiveGenerator::Sphere(SHMeshLibrary& meshLibrary) noexcept
{
if (sphereMesh.VertexPositions.empty())
sphereMesh = Sphere();
return addMeshDataTo(sphereMesh, meshLibrary);
}
SHADE::Handle<SHADE::SHMesh> SHPrimitiveGenerator::Sphere(SHGraphicsSystem& gfxSystem) noexcept
{
if (sphereMesh.VertexPositions.empty())
sphereMesh = Sphere();
return addMeshDataTo(sphereMesh, gfxSystem);
}
/*-----------------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------------*/
SHADE::Handle<SHADE::SHMesh> SHPrimitiveGenerator::addMeshDataTo(const SHMeshData& meshData, SHMeshLibrary& meshLibrary) noexcept
{
return meshLibrary.AddMesh return meshLibrary.AddMesh
( (
static_cast<uint32_t>(meshData.VertexPositions.size()), static_cast<uint32_t>(meshData.VertexPositions.size()),
@ -206,9 +298,8 @@ namespace SHADE
); );
} }
Handle<SHADE::SHMesh> SHPrimitiveGenerator::Cube(SHGraphicsSystem& gfxSystem) noexcept SHADE::Handle<SHADE::SHMesh> SHPrimitiveGenerator::addMeshDataTo(const SHMeshData& meshData, SHGraphicsSystem& gfxSystem) noexcept
{ {
static SHMeshData meshData = Cube();
return gfxSystem.AddMesh return gfxSystem.AddMesh
( (
static_cast<uint32_t>(meshData.VertexPositions.size()), static_cast<uint32_t>(meshData.VertexPositions.size()),

View File

@ -59,7 +59,7 @@ namespace SHADE
Produces a cube and constructs a SHMesh using the SHMeshLibrary provided. Produces a cube and constructs a SHMesh using the SHMeshLibrary provided.
\param meshLibrary \param meshLibrary
Reference to the SHMeshLibrary to procude and store a cube mesh in. Reference to the SHMeshLibrary to produce and store a cube mesh in.
\return \return
SHMesh object that points to the generated cube mesh in the SHMeshLibrary. SHMesh object that points to the generated cube mesh in the SHMeshLibrary.
@ -79,11 +79,54 @@ namespace SHADE
*/ */
/***********************************************************************************/ /***********************************************************************************/
[[nodiscard]] static Handle<SHMesh> Cube(SHGraphicsSystem& gfxSystem) noexcept; [[nodiscard]] static Handle<SHMesh> Cube(SHGraphicsSystem& gfxSystem) noexcept;
/***********************************************************************************/
/*!
\brief
Produces a sphere and stores the data in a SHMeshData object.
\return
SHMeshData object containing vertex data for the sphere.
*/
/***********************************************************************************/
[[nodiscard]] static SHMeshData Sphere() noexcept;
/***********************************************************************************/
/*!
\brief
Produces a sphere and constructs a SHMesh using the SHMeshLibrary provided.
\param meshLibrary
Reference to the SHMeshLibrary to produce and store a sphere mesh in.
\return
SHMesh object that points to the generated sphere mesh in the SHMeshLibrary.
*/
/***********************************************************************************/
[[nodiscard]] static Handle<SHMesh> Sphere(SHMeshLibrary& meshLibrary) noexcept;
/***********************************************************************************/
/*!
\brief
Produces a sphere and constructs a SHMesh using the SHGraphicsSystem provided.
\param gfxSystem
Reference to the SHGraphicsSystem to produce and store a sphere mesh in.
\return
SHMesh object that points to the generated sphere mesh in the SHGraphicsSystem.
*/
/***********************************************************************************/
[[nodiscard]] static Handle<SHMesh> Sphere(SHGraphicsSystem& gfxSystem) noexcept;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] static SHMeshData genCubeData() noexcept; static Handle<SHMesh> addMeshDataTo(const SHMeshData& meshData, SHMeshLibrary& meshLibrary) noexcept;
static Handle<SHMesh> addMeshDataTo(const SHMeshData& meshData, SHGraphicsSystem& gfxSystem) noexcept;
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
static SHMeshData cubeMesh;
static SHMeshData sphereMesh;
}; };
} }

View File

@ -1,139 +0,0 @@
#include "SHPch.h"
#include "SHShaderModuleLibrary.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Assets/SHAssetManager.h"
namespace SHADE
{
/***************************************************************************/
/*!
\brief
Imports all shader binaries from the source library.
\param logicalDeviceHdl
For creating shader modules.
\param sourceLib
The source library class that stores the container of shader binary data.
*/
/***************************************************************************/
//void SHShaderModuleLibrary::ImportFromSourceLibrary(Handle<SHVkLogicalDevice>& logicalDeviceHdl, SHShaderSourceLibrary const& sourceLib) noexcept
//{
// auto const& sources = sourceLib.GetSourceLibrary();
// for (auto const& source : sources)
// {
// vk::ShaderStageFlagBits shaderType{};
// switch (source.shaderType)
// {
// case SH_SHADER_TYPE::VERTEX:
// shaderType = vk::ShaderStageFlagBits::eVertex;
// break;
// case SH_SHADER_TYPE::FRAGMENT:
// shaderType = vk::ShaderStageFlagBits::eFragment;
// break;
// case SH_SHADER_TYPE::COMPUTE:
// shaderType = vk::ShaderStageFlagBits::eCompute;
// break;
// default:
// shaderType = vk::ShaderStageFlagBits::eVertex;
// break;
// }
// Handle<SHVkShaderModule> newShaderModule = logicalDeviceHdl->CreateShaderModule(source.spirvBinary, "main", shaderType, source.name);
// shaderModules.emplace(source.id, newShaderModule);
// stringToID.emplace(source.name, source.id);
// }
//}
/***************************************************************************/
/*!
\brief
Gets the shader module based on module name.
\param shaderName
\return
*/
/***************************************************************************/
//Handle<SHVkShaderModule> SHShaderModuleLibrary::GetShaderModule(std::string shaderName) const noexcept
//{
// if (stringToID.contains(shaderName))
// return shaderModules.at(stringToID.at(shaderName));
// else
// return {};
//}
vk::ShaderStageFlagBits SHShaderModuleLibrary::GetVkShaderFlag(SH_SHADER_TYPE type) noexcept
{
vk::ShaderStageFlagBits shaderType{};
switch (type)
{
case SH_SHADER_TYPE::VERTEX:
shaderType = vk::ShaderStageFlagBits::eVertex;
break;
case SH_SHADER_TYPE::FRAGMENT:
shaderType = vk::ShaderStageFlagBits::eFragment;
break;
case SH_SHADER_TYPE::COMPUTE:
shaderType = vk::ShaderStageFlagBits::eCompute;
break;
default:
shaderType = vk::ShaderStageFlagBits::eVertex;
break;
}
return shaderType;
}
Handle<SHVkShaderModule> SHShaderModuleLibrary::GetBuiltInShaderModule(std::string shaderName) const noexcept
{
if (builtInShaderModules.contains(shaderName))
return builtInShaderModules.at(shaderName);
else
return {};
}
void SHShaderModuleLibrary::ImportAllShaderSource(Handle<SHVkLogicalDevice>& logicalDeviceHdl) noexcept
{
uint32_t idCounter{ 0 };
auto const data = SHAssetManager::GetAllDataOfType(AssetType::SHADER);
for (auto const& dataPtr : data)
{
auto const shader = dynamic_cast<SHShaderAsset const*>(dataPtr);
Handle<SHVkShaderModule> newShaderModule =
logicalDeviceHdl->CreateShaderModule(shader->spirvBinary, "main", GetVkShaderFlag(shader->shaderType), shader->name);
shaderModules.emplace(idCounter++, newShaderModule);
}
auto const builtIn = SHAssetManager::GetAllDataOfType(AssetType::SHADER_BUILT_IN);
for (auto const& dataPtr : builtIn)
{
auto const shader = dynamic_cast<SHShaderAsset const*>(dataPtr);
Handle<SHVkShaderModule> newShaderModule =
logicalDeviceHdl->CreateShaderModule(shader->spirvBinary, "main", GetVkShaderFlag(shader->shaderType), shader->name);
builtInShaderModules.emplace(shader->name, newShaderModule);
}
}
void SHShaderModuleLibrary::ReflectAllShaderModules() noexcept
{
for (auto& module : shaderModules)
{
module.second->Reflect();
}
for (auto& module : builtInShaderModules)
{
module.second->Reflect();
}
}
}

View File

@ -1,44 +0,0 @@
#ifndef SH_SHADER_MODULE_LIBRARY_H
#define SH_SHADER_MODULE_LIBRARY_H
#include "Graphics/Shaders/SHVkShaderModule.h"
#include "Assets/Asset Types/SHShaderAsset.h"
namespace SHADE
{
class SHVkLogicalDevice;
/*
* The purpose of this shader module library is to be separate from the source library. The source library contains
* pure shader binary data that contains no vulkan related objects. Every time we load on unload a scene/level,
* this class and the source library class is cleared of its modules and recreated.
*/
class SHShaderModuleLibrary
{
private:
/*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/
//! Stored shader modules
std::unordered_map<uint32_t, Handle<SHVkShaderModule>> shaderModules;
std::unordered_map<std::string, Handle<SHVkShaderModule>> builtInShaderModules;
inline vk::ShaderStageFlagBits GetVkShaderFlag(SH_SHADER_TYPE type) noexcept;
public:
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
//void ImportFromSourceLibrary(Handle<SHVkLogicalDevice>& logicalDeviceHdl, SHShaderSourceLibrary const& sourceLib) noexcept;
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
Handle<SHVkShaderModule> GetBuiltInShaderModule(std::string shaderName) const noexcept;
void ImportAllShaderSource(Handle<SHVkLogicalDevice>& logicalDeviceHdl) noexcept;
void ReflectAllShaderModules() noexcept;
};
}
#endif

View File

@ -47,12 +47,13 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
//! For constructing a graphics pipeline
SHVkPipeline (Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, SHVkPipeline (Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl,
Handle<SHVkPipelineLayout> const& inPipelineLayout, Handle<SHVkPipelineLayout> const& inPipelineLayout,
SHVkPipelineState const* const state, SHVkPipelineState const* const state,
Handle<SHVkRenderpass> const& renderpassHdl, Handle<SHVkRenderpass> const& renderpassHdl,
Handle<SHSubpass> subpass) noexcept; Handle<SHSubpass> subpass) noexcept;
//! For constructing a compute pipeline
SHVkPipeline(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, SHVkPipeline(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl,
Handle<SHVkPipelineLayout> const& inPipelineLayout) noexcept; Handle<SHVkPipelineLayout> const& inPipelineLayout) noexcept;

View File

@ -54,13 +54,14 @@ namespace SHADE
if (wndData.isFullscreen) if (wndData.isFullscreen)
{ {
dwExStyle = WS_EX_APPWINDOW | WS_EX_ACCEPTFILES; dwExStyle = WS_EX_APPWINDOW;
dwStyle = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; dwStyle = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
dwExStyle |= WS_EX_ACCEPTFILES;
} }
else else
{ {
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE | WS_EX_ACCEPTFILES; dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwExStyle |= WS_EX_ACCEPTFILES;
if (wndData.frameEnabled) if (wndData.frameEnabled)
{ {
dwStyle = WNDSTYLE::SHWS_WINDOWED; dwStyle = WNDSTYLE::SHWS_WINDOWED;
@ -87,7 +88,7 @@ namespace SHADE
} }
} }
//DPI_AWARENESS_CONTEXT prevDPIContext = SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); DPI_AWARENESS_CONTEXT prevDPIContext = SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
RECT windowRect; RECT windowRect;
windowRect.left = wndData.x; //or CW_USEDEFAULT ? windowRect.left = wndData.x; //or CW_USEDEFAULT ?
@ -97,13 +98,16 @@ namespace SHADE
AdjustWindowRectEx(&windowRect, dwStyle, false, dwExStyle); AdjustWindowRectEx(&windowRect, dwStyle, false, dwExStyle);
//Create window //Create window
wndHWND = CreateWindowEx(0, (LPWSTR) wndData.name.c_str(), (LPWSTR)wndData.title.c_str(), dwStyle, 0, 0, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, parent, NULL, hInstance, NULL); wndHWND = CreateWindowEx(dwExStyle, (LPWSTR) wndData.name.c_str(), (LPWSTR)wndData.title.c_str(), dwStyle, 0, 0, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, parent, NULL, hInstance, NULL);
if (!wndHWND) if (!wndHWND)
{ {
//DWORD err = GetLastError(); //DWORD err = GetLastError();
return false; return false;
} }
BOOL help = ChangeWindowMessageFilter (WM_DROPFILES, MSGFLT_ADD);
help &= ChangeWindowMessageFilter (WM_COPYDATA, MSGFLT_ADD);
help &= ChangeWindowMessageFilter (0x0049, MSGFLT_ADD);
if (wndData.isVisible) if (wndData.isVisible)
{ {
@ -256,7 +260,7 @@ namespace SHADE
return wndHWND; return wndHWND;
} }
const WindowData SHWindow::GetWindowData() const WindowData SHWindow::GetWindowData() const
{ {
return wndData; return wndData;
} }
@ -318,13 +322,13 @@ namespace SHADE
case WM_CREATE: case WM_CREATE:
OnCreate(hwnd, reinterpret_cast<LPCREATESTRUCT>(wparam)); OnCreate(hwnd, reinterpret_cast<LPCREATESTRUCT>(wparam));
break; break;
case WM_QUIT:
case WM_CLOSE: case WM_CLOSE:
case WM_DESTROY: case WM_DESTROY:
OnDestroy(); OnDestroy();
return 0; return 0;
case WM_DROPFILES: case WM_DROPFILES:
//OnFileDrop(reinterpret_cast<HDROP>(wparam)); OnFileDrop(reinterpret_cast<HDROP>(wparam));
break; break;
case WM_ENTERSIZEMOVE: case WM_ENTERSIZEMOVE:
case WM_EXITSIZEMOVE: case WM_EXITSIZEMOVE:
@ -386,12 +390,25 @@ namespace SHADE
void SHWindow::OnDestroy() void SHWindow::OnDestroy()
{ {
OnClose(); OnClose();
DragAcceptFiles(wndHWND, false);
this->Destroy(); this->Destroy();
} }
//void SHWindow::OnFileDrop(HDROP drop) void SHWindow::OnFileDrop(HDROP drop)
//{ {
//}
int const numFiles = static_cast<int>(DragQueryFile(drop, 0xFFFFFFFF, nullptr, 0));
for(int i = 0; i < numFiles; ++i)
{
//char fileNameBuffer[MAX_PATH];
std::wstring fileNameBuffer;
fileNameBuffer.reserve(MAX_PATH);
DragQueryFile(drop, static_cast<UINT>(i), fileNameBuffer.data(), MAX_PATH);
std::string name(fileNameBuffer.begin(), fileNameBuffer.end());
SHLOG_INFO("Dropped: {}", name)
}
DragFinish(drop);
}
void SHWindow::OnSize([[maybe_unused]] UINT msg,[[maybe_unused]] UINT type, SIZE size) void SHWindow::OnSize([[maybe_unused]] UINT msg,[[maybe_unused]] UINT type, SIZE size)
{ {

View File

@ -2,6 +2,7 @@
#define SH_WINDOW_H #define SH_WINDOW_H
#include <Windows.h> #include <Windows.h>
#include <shellapi.h>
#include <functional> #include <functional>
#include <unordered_map> #include <unordered_map>
#include "SHWindowMap.h" #include "SHWindowMap.h"
@ -47,7 +48,7 @@ namespace SHADE
//bool canFullscreen = true; //bool canFullscreen = true;
unsigned bgColor = WHITE_BRUSH; unsigned bgColor = DKGRAY_BRUSH;
//bool transparent = false; //bool transparent = false;
@ -122,7 +123,7 @@ namespace SHADE
HWND GetHWND(); HWND GetHWND();
const WindowData GetWindowData(); const WindowData GetWindowData() const;
CALLBACKID RegisterWindowSizeCallback(WindowResizeCallbackFn); CALLBACKID RegisterWindowSizeCallback(WindowResizeCallbackFn);
void UnregisterWindowSizeCallback(CALLBACKID const& callbackid); void UnregisterWindowSizeCallback(CALLBACKID const& callbackid);
@ -168,7 +169,7 @@ namespace SHADE
void OnCreate(HWND hwnd, LPCREATESTRUCT create_struct); void OnCreate(HWND hwnd, LPCREATESTRUCT create_struct);
void OnClose(); void OnClose();
void OnDestroy(); void OnDestroy();
//void OnFileDrop(HDROP drop); void OnFileDrop(HDROP drop);
void OnSize(UINT msg, UINT type, SIZE size); void OnSize(UINT msg, UINT type, SIZE size);
void OnPosChange(LPWINDOWPOS pos); void OnPosChange(LPWINDOWPOS pos);
void OnPaint(HDC hdc, LPPAINTSTRUCT paint); void OnPaint(HDC hdc, LPPAINTSTRUCT paint);

View File

@ -87,19 +87,19 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHColour::SHColour() noexcept SHColour::SHColour() noexcept
: SHVec4 { 0.0f, 0.0f, 0.0f, 1.0f } : XMFLOAT4 { 0.0f, 0.0f, 0.0f, 1.0f }
{} {}
SHColour::SHColour(float r, float g, float b) noexcept SHColour::SHColour(float r, float g, float b) noexcept
: SHVec4 { r, g, b, 1.0f } : XMFLOAT4 { r, g, b, 1.0f }
{} {}
SHColour::SHColour(float r, float g, float b, float a) noexcept SHColour::SHColour(float r, float g, float b, float a) noexcept
: SHVec4 { r, g, b, a } : XMFLOAT4 { r, g, b, a }
{} {}
SHColour::SHColour(uint8_t r, uint8_t g, uint8_t b) noexcept SHColour::SHColour(uint8_t r, uint8_t g, uint8_t b) noexcept
: SHVec4 : XMFLOAT4
{ {
static_cast<float>(r) / 255.0f, static_cast<float>(r) / 255.0f,
static_cast<float>(g) / 255.0f, static_cast<float>(g) / 255.0f,
@ -109,7 +109,7 @@ namespace SHADE
{} {}
SHColour::SHColour(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept SHColour::SHColour(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept
: SHVec4 : XMFLOAT4
{ {
static_cast<float>(r) / 255.0f, static_cast<float>(r) / 255.0f,
static_cast<float>(g) / 255.0f, static_cast<float>(g) / 255.0f,
@ -118,12 +118,24 @@ namespace SHADE
} }
{} {}
SHColour::SHColour(const DirectX::XMFLOAT3& colour) noexcept SHColour::SHColour(const SHVec3& rgb) noexcept
: SHVec4 { colour.x, colour.y, colour.z, 1.0f } : XMFLOAT4 { rgb.x, rgb.y, rgb.z, 1.0f }
{}
SHColour::SHColour(const SHVec4& rgba) noexcept
: XMFLOAT4 { rgba.x, rgba.y, rgba.z, rgba.w }
{}
SHColour::SHColour(const DirectX::XMFLOAT3& rgb) noexcept
: XMFLOAT4 { rgb.x, rgb.y, rgb.z, 1.0f }
{}
SHColour::SHColour(const DirectX::XMFLOAT4& rgba) noexcept
: XMFLOAT4 { rgba.x, rgba.y, rgba.z, rgba.w }
{} {}
SHColour::SHColour(const DirectX::XMVECTORF32& colour) noexcept SHColour::SHColour(const DirectX::XMVECTORF32& colour) noexcept
: SHVec4 : XMFLOAT4
{ {
XMVectorGetX(colour), XMVectorGetX(colour),
XMVectorGetY(colour), XMVectorGetY(colour),
@ -136,6 +148,86 @@ namespace SHADE
/* Operator Overload Definitions */ /* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHColour::operator XMVECTOR() const noexcept
{
return XMLoadFloat4(this);
}
SHColour::operator SHVec4() const noexcept
{
return SHVec4{ *this };
}
SHColour& SHColour::operator+=(const SHColour& rhs) noexcept
{
return *this = *this + rhs;
}
SHColour& SHColour::operator-=(const SHColour& rhs) noexcept
{
return *this = *this - rhs;
}
SHColour& SHColour::operator*=(const SHColour& rhs) noexcept
{
return *this = *this * rhs;
}
SHColour& SHColour::operator*=(float rhs) noexcept
{
return *this = *this * rhs;
}
SHColour& SHColour::operator/=(const SHColour& rhs) noexcept
{
return *this = *this / rhs;
}
SHColour SHColour::operator+(const SHColour& rhs) const noexcept
{
SHColour result;
XMStoreFloat4(&result, XMVectorAdd(*this, rhs));
return result;
}
SHColour SHColour::operator-(const SHColour& rhs) const noexcept
{
SHColour result;
XMStoreFloat4(&result, XMVectorSubtract(*this, rhs));
return result;
}
SHColour SHColour::operator-() const noexcept
{
return SHColour{ -x, -y, -z, -w };
}
SHColour SHColour::operator*(const SHColour& rhs) const noexcept
{
SHColour result;
XMStoreFloat4(&result, XMVectorMultiply(*this, rhs));
return result;
}
SHColour SHColour::operator*(float rhs) const noexcept
{
SHColour result;
XMStoreFloat4(&result, XMVectorScale(*this, rhs));
return result;
}
SHColour SHColour::operator/(const SHColour& rhs) const noexcept
{
SHColour result;
XMStoreFloat4(&result, XMVectorDivide(*this, rhs));
return result;
}
bool SHColour::operator==(const SHColour& rhs) const noexcept bool SHColour::operator==(const SHColour& rhs) const noexcept
{ {
return XMColorEqual(*this, rhs); return XMColorEqual(*this, rhs);
@ -146,6 +238,70 @@ namespace SHADE
return XMColorNotEqual(*this, rhs); return XMColorNotEqual(*this, rhs);
} }
float& SHColour::operator[](int index)
{
if (index >= SIZE || index < 0)
throw std::invalid_argument("Index out of range!");
switch (index)
{
case 0: return x;
case 1: return y;
case 2: return z;
case 3: return w;
}
}
float& SHColour::operator[](size_t index)
{
if (index >= SIZE || index < 0)
throw std::invalid_argument("Index out of range!");
switch (index)
{
case 0: return x;
case 1: return y;
case 2: return z;
case 3: return w;
}
}
float SHColour::operator[](int index) const
{
if (index >= SIZE || index < 0)
throw std::invalid_argument("Index out of range!");
switch (index)
{
case 0: return x;
case 1: return y;
case 2: return z;
case 3: return w;
}
}
float SHColour::operator[](size_t index) const
{
if (index >= SIZE || index < 0)
throw std::invalid_argument("Index out of range!");
switch (index)
{
case 0: return x;
case 1: return y;
case 2: return z;
case 3: return w;
}
}
SHColour operator* (float lhs, const SHColour& rhs) noexcept
{
SHColour result;
XMStoreFloat4(&result, XMVectorScale(rhs, lhs));
return result;
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Function Member Definitions */ /* Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/

View File

@ -19,12 +19,6 @@
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHColour;
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -40,7 +34,7 @@ namespace SHADE
float v = 0.0f; float v = 0.0f;
}; };
class SH_API SHColour : private SHVec4 class SH_API SHColour : public DirectX::XMFLOAT4
{ {
public: public:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -53,9 +47,11 @@ namespace SHADE
SHColour (uint8_t r, uint8_t g, uint8_t b) noexcept; SHColour (uint8_t r, uint8_t g, uint8_t b) noexcept;
SHColour (uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept; SHColour (uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept;
SHColour (const SHVec3& colour) noexcept; SHColour (const SHVec3& rgb) noexcept;
SHColour (const DirectX::XMFLOAT3& colour) noexcept; SHColour (const SHVec4& rgba) noexcept;
SHColour (const DirectX::XMVECTORF32& colour) noexcept; SHColour (const DirectX::XMFLOAT3& rgb) noexcept;
SHColour (const DirectX::XMFLOAT4& rgba) noexcept;
SHColour (const DirectX::XMVECTORF32& rgba) noexcept;
SHColour (const SHColour&) = default; SHColour (const SHColour&) = default;
SHColour (SHColour&&) = default; SHColour (SHColour&&) = default;
@ -69,8 +65,29 @@ namespace SHADE
SHColour& operator= (const SHColour&) = default; SHColour& operator= (const SHColour&) = default;
SHColour& operator= (SHColour&&) = default; SHColour& operator= (SHColour&&) = default;
bool operator== (const SHColour& rhs) const noexcept; operator DirectX::XMVECTOR () const noexcept;
bool operator!= (const SHColour& rhs) const noexcept; operator SHVec4 () const noexcept;
SHColour& operator+= (const SHColour& rhs) noexcept;
SHColour& operator-= (const SHColour& rhs) noexcept;
SHColour& operator*= (const SHColour& rhs) noexcept;
SHColour& operator*= (float rhs) noexcept;
SHColour& operator/= (const SHColour& rhs) noexcept;
[[nodiscard]] SHColour operator+ (const SHColour& rhs) const noexcept;
[[nodiscard]] SHColour operator- (const SHColour& rhs) const noexcept;
[[nodiscard]] SHColour operator- () const noexcept;
[[nodiscard]] SHColour operator* (const SHColour& rhs) const noexcept;
[[nodiscard]] SHColour operator* (float rhs) const noexcept;
[[nodiscard]] SHColour operator/ (const SHColour& rhs) const noexcept;
[[nodiscard]] bool operator== (const SHColour& rhs) const noexcept;
[[nodiscard]] bool operator!= (const SHColour& rhs) const noexcept;
[[nodiscard]] float& operator[] (int index);
[[nodiscard]] float& operator[] (size_t index);
[[nodiscard]] float operator[] (int index) const;
[[nodiscard]] float operator[] (size_t index) const;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Properties */ /* Properties */
@ -105,6 +122,8 @@ namespace SHADE
/* Static Data Members */ /* Static Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
static constexpr size_t SIZE = 4U;
static const SHColour BEIGE ; static const SHColour BEIGE ;
static const SHColour BLACK ; static const SHColour BLACK ;
static const SHColour BLUE ; static const SHColour BLUE ;
@ -159,8 +178,9 @@ namespace SHADE
static const SHColour TURQUOISE ; static const SHColour TURQUOISE ;
static const SHColour VIOLET ; static const SHColour VIOLET ;
static const SHColour WHITE ; static const SHColour WHITE ;
static const SHColour YELLOW; static const SHColour YELLOW ;
}; };
SHColour operator* (float lhs, const SHColour& rhs) noexcept;
} // namespace SHADE } // namespace SHADE

View File

@ -9,4 +9,6 @@
#include "SHQuaternion.h" #include "SHQuaternion.h"
#include "SHMatrix.h" #include "SHMatrix.h"
#include "SHColour.h"
#include "Transform/SHTransform.h" #include "Transform/SHTransform.h"

View File

@ -14,6 +14,7 @@
#include "SHTransformComponent.h" #include "SHTransformComponent.h"
// Project Headers // Project Headers
#include "Math/SHMathHelpers.h" #include "Math/SHMathHelpers.h"
#include "Reflection/SHReflectionMetadata.h"
namespace SHADE namespace SHADE
{ {
@ -184,7 +185,7 @@ RTTR_REGISTRATION
using namespace rttr; using namespace rttr;
registration::class_<SHTransformComponent>("Transform Component") registration::class_<SHTransformComponent>("Transform Component")
.property("Translate" , &SHTransformComponent::GetLocalPosition , &SHTransformComponent::SetLocalPosition ) .property("Translate" ,&SHTransformComponent::GetLocalPosition ,&SHTransformComponent::SetLocalPosition ) (metadata(META::tooltip, "Translate"))
.property("Rotate" , &SHTransformComponent::GetLocalRotation , select_overload<void(const SHVec3&)>(&SHTransformComponent::SetLocalRotation) ) .property("Rotate" ,&SHTransformComponent::GetLocalRotation ,select_overload<void(const SHVec3&)>(&SHTransformComponent::SetLocalRotation)) (metadata(META::tooltip, "Rotate"), metadata(META::angleInRad, true))
.property("Scale" , &SHTransformComponent::GetLocalScale , &SHTransformComponent::SetLocalScale ); .property("Scale" ,&SHTransformComponent::GetLocalScale ,&SHTransformComponent::SetLocalScale ) (metadata(META::tooltip, "Scale"));
} }

View File

@ -47,16 +47,14 @@ namespace SHADE
{ {
// Get the current scene graph to traverse and update // Get the current scene graph to traverse and update
const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph();
UpdateEntity(SCENE_GRAPH.GetRoot(), !IsRunInEditorPause);
// TODO(Diren): Consider how to clear dirty in pause / stop mode and update physics, but do not clear in play mode.
UpdateEntity(SCENE_GRAPH.GetRoot(), false);
} }
void SHTransformSystem::TransformPostPhysicsUpdate::Execute(double) noexcept void SHTransformSystem::TransformPostPhysicsUpdate::Execute(double) noexcept
{ {
// Get the current scene graph to traverse and update // Get the current scene graph to traverse and update
const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph();
UpdateEntity(SCENE_GRAPH.GetRoot(), true); UpdateEntity(SCENE_GRAPH.GetRoot(), IsRunInEditorPause);
} }
void SHTransformSystem::Init() void SHTransformSystem::Init()

View File

@ -14,6 +14,7 @@
#include "SHVec4.h" #include "SHVec4.h"
// Project Headers // Project Headers
#include "Math/SHMatrix.h" #include "Math/SHMatrix.h"
#include "Math/SHColour.h"
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
using namespace DirectX; using namespace DirectX;

View File

@ -23,7 +23,9 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Forward Declarations */ /* Forward Declarations */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
class SHMatrix; class SHMatrix;
class SHColour;
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */

View File

@ -147,3 +147,11 @@ namespace SHADE
} }
} // namespace SHADE } // namespace SHADE
RTTR_REGISTRATION
{
using namespace rttr;
using namespace SHADE;
registration::class_<SHColliderComponent>("Collider Component");
}

View File

@ -100,5 +100,6 @@ namespace SHADE
SHQuaternion orientation; SHQuaternion orientation;
Colliders colliders; Colliders colliders;
RTTR_ENABLE()
}; };
} // namespace SHADE } // namespace SHADE

View File

@ -18,6 +18,7 @@
// Project Headers // Project Headers
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Math/SHMathHelpers.h"
#include "Physics/SHPhysicsSystem.h" #include "Physics/SHPhysicsSystem.h"
namespace SHADE namespace SHADE
@ -28,21 +29,9 @@ namespace SHADE
SHRigidBodyComponent::SHRigidBodyComponent() noexcept SHRigidBodyComponent::SHRigidBodyComponent() noexcept
: type { Type::DYNAMIC } : type { Type::DYNAMIC }
, flags { 0 }
, dirtyFlags { 0 }
, interpolate { true } , interpolate { true }
, rp3dBody { nullptr } , rp3dBody { nullptr }
, mass { 1.0f } {}
, drag { 0.01f }
, angularDrag { 0.01f }
{
// Set default flags: Gravity & Sleeping enabled
flags |= 1U << 0;
flags |= 1U << 1;
// Set all dirty flags to true
dirtyFlags = 1023;
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */ /* Getter Function Definitions */
@ -50,12 +39,24 @@ namespace SHADE
bool SHRigidBodyComponent::IsGravityEnabled() const noexcept bool SHRigidBodyComponent::IsGravityEnabled() const noexcept
{ {
return flags & (1U << 0); if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
}
return rp3dBody->isGravityEnabled();
} }
bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept
{ {
return flags & (1U << 1); if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
}
return rp3dBody->isAllowedToSleep();
} }
bool SHRigidBodyComponent::IsInterpolating() const noexcept bool SHRigidBodyComponent::IsInterpolating() const noexcept
@ -70,67 +71,151 @@ namespace SHADE
float SHRigidBodyComponent::GetMass() const noexcept float SHRigidBodyComponent::GetMass() const noexcept
{ {
return mass; if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return 0.0f;
}
return rp3dBody->getMass();
} }
float SHRigidBodyComponent::GetDrag() const noexcept float SHRigidBodyComponent::GetDrag() const noexcept
{ {
return drag; if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return 0.0f;
}
return rp3dBody->getLinearDamping();
} }
float SHRigidBodyComponent::GetAngularDrag() const noexcept float SHRigidBodyComponent::GetAngularDrag() const noexcept
{ {
return angularDrag; if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return 0.0f;
}
return rp3dBody->getAngularDamping();
} }
bool SHRigidBodyComponent::GetFreezePositionX() const noexcept bool SHRigidBodyComponent::GetFreezePositionX() const noexcept
{ {
return flags & (1U << 2); if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
}
const auto& LINEAR_CONSTRAINTS = rp3dBody->getLinearLockAxisFactor();
return SHMath::CompareFloat(LINEAR_CONSTRAINTS.x, 0.0f);
} }
bool SHRigidBodyComponent::GetFreezePositionY() const noexcept bool SHRigidBodyComponent::GetFreezePositionY() const noexcept
{ {
return flags & (1U << 3); if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
}
const auto& LINEAR_CONSTRAINTS = rp3dBody->getLinearLockAxisFactor();
return SHMath::CompareFloat(LINEAR_CONSTRAINTS.y, 0.0f);
} }
bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept
{ {
return flags & (1U << 4); if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
}
const auto& LINEAR_CONSTRAINTS = rp3dBody->getLinearLockAxisFactor();
return SHMath::CompareFloat(LINEAR_CONSTRAINTS.z, 0.0f);
} }
bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept
{ {
return flags & (1U << 5); if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
}
const auto& ANGULAR_CONSTRAINTS = rp3dBody->getAngularLockAxisFactor();
return SHMath::CompareFloat(ANGULAR_CONSTRAINTS.x, 0.0f);
} }
bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept
{ {
return flags & (1U << 6); if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
}
const auto& ANGULAR_CONSTRAINTS = rp3dBody->getAngularLockAxisFactor();
return SHMath::CompareFloat(ANGULAR_CONSTRAINTS.y, 0.0f);
} }
bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept
{ {
return flags & (1U << 7); if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
} }
const SHVec3& SHRigidBodyComponent::GetForce() const noexcept const auto& ANGULAR_CONSTRAINTS = rp3dBody->getAngularLockAxisFactor();
{ return SHMath::CompareFloat(ANGULAR_CONSTRAINTS.z, 0.0f);
return force;
} }
const SHVec3& SHRigidBodyComponent::GetTorque() const noexcept SHVec3 SHRigidBodyComponent::GetForce() const noexcept
{ {
return torque; if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
} }
const SHVec3& SHRigidBodyComponent::GetLinearVelocity() const noexcept return rp3dBody->getForce();
{
return linearVelocity;
} }
const SHVec3& SHRigidBodyComponent::GetAngularVelocity() const noexcept SHVec3 SHRigidBodyComponent::GetTorque() const noexcept
{ {
return angularVelocity; if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return SHVec3::Zero;
}
return rp3dBody->getTorque();
}
SHVec3 SHRigidBodyComponent::GetLinearVelocity() const noexcept
{
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return SHVec3::Zero;
}
return rp3dBody->getLinearVelocity();
}
SHVec3 SHRigidBodyComponent::GetAngularVelocity() const noexcept
{
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return SHVec3::Zero;
}
return rp3dBody->getAngularVelocity();
} }
const SHVec3& SHRigidBodyComponent::GetPosition() const noexcept const SHVec3& SHRigidBodyComponent::GetPosition() const noexcept
@ -157,8 +242,15 @@ namespace SHADE
if (type == newType) if (type == newType)
return; return;
dirtyFlags |= 1U << 4;
type = newType; type = newType;
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
rp3dBody->setType(static_cast<rp3d::BodyType>(type));
} }
void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept
@ -171,8 +263,13 @@ namespace SHADE
return; return;
} }
dirtyFlags |= 1U << FLAG_POS; if (rp3dBody == nullptr)
enableGravity ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS); {
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
rp3dBody->enableGravity(enableGravity);
} }
void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept
@ -185,92 +282,127 @@ namespace SHADE
return; return;
} }
dirtyFlags |= 1U << 1; if (rp3dBody == nullptr)
isAllowedToSleep ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS); {
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
rp3dBody->setIsAllowedToSleep(isAllowedToSleep);
} }
void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept
{ {
static constexpr int FLAG_POS = 2;
if (type == Type::STATIC) if (type == Type::STATIC)
{ {
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID()) SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
return; return;
} }
dirtyFlags |= 1U << 2; if (rp3dBody == nullptr)
freezePositionX ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS); {
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
auto linearConstraints = rp3dBody->getLinearLockAxisFactor();
linearConstraints.x = freezePositionX ? 0.0f : 1.0f;
rp3dBody->setLinearLockAxisFactor(linearConstraints);
} }
void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept
{ {
static constexpr int FLAG_POS = 3;
if (type == Type::STATIC) if (type == Type::STATIC)
{ {
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID()) SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
return; return;
} }
dirtyFlags |= 1U << 2; if (rp3dBody == nullptr)
freezePositionY ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS); {
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
auto linearConstraints = rp3dBody->getLinearLockAxisFactor();
linearConstraints.y = freezePositionY ? 0.0f : 1.0f;
rp3dBody->setLinearLockAxisFactor(linearConstraints);
} }
void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept
{ {
static constexpr int FLAG_POS = 4;
if (type == Type::STATIC) if (type == Type::STATIC)
{ {
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID()) SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
return; return;
} }
dirtyFlags |= 1U << 2; if (rp3dBody == nullptr)
freezePositionZ ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS); {
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
auto linearConstraints = rp3dBody->getLinearLockAxisFactor();
linearConstraints.z = freezePositionZ ? 0.0f : 1.0f;
rp3dBody->setLinearLockAxisFactor(linearConstraints);
} }
void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept
{ {
static constexpr int FLAG_POS = 5;
if (type == Type::STATIC) if (type == Type::STATIC)
{ {
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID()) SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
return; return;
} }
dirtyFlags |= 1U << 3; if (rp3dBody == nullptr)
freezeRotationX ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS); {
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
auto angularConstraints = rp3dBody->getAngularLockAxisFactor();
angularConstraints.x = freezeRotationX ? 0.0f : 1.0f;
rp3dBody->setAngularLockAxisFactor(angularConstraints);
} }
void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept
{ {
static constexpr int FLAG_POS = 6;
if (type == Type::STATIC) if (type == Type::STATIC)
{ {
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID()) SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
return; return;
} }
dirtyFlags |= 1U << 3; if (rp3dBody == nullptr)
freezeRotationY ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS); {
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
auto angularConstraints = rp3dBody->getAngularLockAxisFactor();
angularConstraints.y = freezeRotationY ? 0.0f : 1.0f;
rp3dBody->setAngularLockAxisFactor(angularConstraints);
} }
void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept
{ {
static constexpr int FLAG_POS = 7;
if (type == Type::STATIC) if (type == Type::STATIC)
{ {
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID()) SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
return; return;
} }
dirtyFlags |= 1U << 3; if (rp3dBody == nullptr)
freezeRotationZ ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS); {
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
auto angularConstraints = rp3dBody->getAngularLockAxisFactor();
angularConstraints.z = freezeRotationZ ? 0.0f : 1.0f;
rp3dBody->setAngularLockAxisFactor(angularConstraints);
} }
void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept
@ -286,8 +418,13 @@ namespace SHADE
return; return;
} }
dirtyFlags |= 1U << 5; if (rp3dBody == nullptr)
mass = newMass; {
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
rp3dBody->setMass(newMass);
} }
void SHRigidBodyComponent::SetDrag(float newDrag) noexcept void SHRigidBodyComponent::SetDrag(float newDrag) noexcept
@ -298,8 +435,13 @@ namespace SHADE
return; return;
} }
dirtyFlags |= 1U << 6; if (rp3dBody == nullptr)
drag = newDrag; {
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
rp3dBody->setLinearDamping(newDrag);
} }
void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept
@ -310,8 +452,13 @@ namespace SHADE
return; return;
} }
dirtyFlags |= 1U << 7; if (rp3dBody == nullptr)
angularDrag = newAngularDrag; {
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
rp3dBody->setLinearDamping(newAngularDrag);
} }
void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
@ -322,8 +469,13 @@ namespace SHADE
return; return;
} }
dirtyFlags |= 1U << 8; if (rp3dBody == nullptr)
linearVelocity = newLinearVelocity; {
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
rp3dBody->setLinearVelocity(newLinearVelocity);
} }
void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept
@ -334,8 +486,13 @@ namespace SHADE
return; return;
} }
dirtyFlags |= 1U << 9; if (rp3dBody == nullptr)
angularVelocity = newAngularVelocity; {
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
rp3dBody->setAngularVelocity(newAngularVelocity);
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -346,7 +503,7 @@ namespace SHADE
{ {
if (rp3dBody == nullptr) if (rp3dBody == nullptr)
{ {
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID()) SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return; return;
} }
@ -357,7 +514,7 @@ namespace SHADE
{ {
if (rp3dBody == nullptr) if (rp3dBody == nullptr)
{ {
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID()) SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return; return;
} }
@ -368,7 +525,7 @@ namespace SHADE
{ {
if (rp3dBody == nullptr) if (rp3dBody == nullptr)
{ {
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID()) SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return; return;
} }
@ -379,7 +536,7 @@ namespace SHADE
{ {
if (rp3dBody == nullptr) if (rp3dBody == nullptr)
{ {
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID()) SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return; return;
} }
@ -390,7 +547,7 @@ namespace SHADE
{ {
if (rp3dBody == nullptr) if (rp3dBody == nullptr)
{ {
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID()) SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return; return;
} }
@ -401,7 +558,7 @@ namespace SHADE
{ {
if (rp3dBody == nullptr) if (rp3dBody == nullptr)
{ {
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID()) SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return; return;
} }
@ -412,7 +569,7 @@ namespace SHADE
{ {
if (rp3dBody == nullptr) if (rp3dBody == nullptr)
{ {
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID()) SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return; return;
} }
@ -423,7 +580,7 @@ namespace SHADE
{ {
if (rp3dBody == nullptr) if (rp3dBody == nullptr)
{ {
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID()) SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return; return;
} }

View File

@ -94,10 +94,10 @@ namespace SHADE
[[nodiscard]] bool GetFreezeRotationY () const noexcept; [[nodiscard]] bool GetFreezeRotationY () const noexcept;
[[nodiscard]] bool GetFreezeRotationZ () const noexcept; [[nodiscard]] bool GetFreezeRotationZ () const noexcept;
[[nodiscard]] const SHVec3& GetForce () const noexcept; [[nodiscard]] SHVec3 GetForce () const noexcept;
[[nodiscard]] const SHVec3& GetTorque () const noexcept; [[nodiscard]] SHVec3 GetTorque () const noexcept;
[[nodiscard]] const SHVec3& GetLinearVelocity () const noexcept; [[nodiscard]] SHVec3 GetLinearVelocity () const noexcept;
[[nodiscard]] const SHVec3& GetAngularVelocity () const noexcept; [[nodiscard]] SHVec3 GetAngularVelocity () const noexcept;
[[nodiscard]] const SHVec3& GetPosition () const noexcept; [[nodiscard]] const SHVec3& GetPosition () const noexcept;
[[nodiscard]] const SHQuaternion& GetOrientation () const noexcept; [[nodiscard]] const SHQuaternion& GetOrientation () const noexcept;
@ -150,25 +150,10 @@ namespace SHADE
static constexpr size_t NUM_DIRTY_FLAGS = 16; static constexpr size_t NUM_DIRTY_FLAGS = 16;
Type type; Type type;
// rX rY rZ pX pY pZ slp g
uint8_t flags;
// 0 0 0 0 0 0 aV lV aD d m t ag lc slp g
uint16_t dirtyFlags;
bool interpolate; bool interpolate;
reactphysics3d::RigidBody* rp3dBody; reactphysics3d::RigidBody* rp3dBody;
float mass;
float drag;
float angularDrag;
SHVec3 force;
SHVec3 linearVelocity;
SHVec3 torque;
SHVec3 angularVelocity;
SHVec3 position; SHVec3 position;
SHQuaternion orientation; SHQuaternion orientation;

View File

@ -17,6 +17,7 @@
#include "Math/Geometry/SHBoundingSphere.h" #include "Math/Geometry/SHBoundingSphere.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Math/SHMathHelpers.h" #include "Math/SHMathHelpers.h"
#include "Reflection/SHReflectionMetadata.h"
namespace SHADE namespace SHADE
{ {
@ -158,6 +159,11 @@ namespace SHADE
return positionOffset; return positionOffset;
} }
const SHVec3& SHCollider::GetRotationOffset() const noexcept
{
return rotationOffset;
}
SHShape* SHCollider::GetShape() noexcept SHShape* SHCollider::GetShape() noexcept
{ {
dirty = true; dirty = true;
@ -275,6 +281,12 @@ namespace SHADE
} }
} }
void SHCollider::SetRotationOffset(const SHVec3& rotOffset) noexcept
{
dirty = true;
rotationOffset = rotOffset;
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Private Function Member Definitions */ /* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -316,5 +328,6 @@ RTTR_REGISTRATION
); );
registration::class_<SHCollider>("Collider") registration::class_<SHCollider>("Collider")
.property("Position Offset", &SHCollider::GetPositionOffset, &SHCollider::SetPositionOffset); .property("Position Offset", &SHCollider::GetPositionOffset, &SHCollider::SetPositionOffset)
.property("Rotation Offset", &SHCollider::GetRotationOffset, &SHCollider::SetRotationOffset) (metadata(META::angleInRad, true));
} }

View File

@ -80,6 +80,7 @@ namespace SHADE
[[nodiscard]] const SHPhysicsMaterial& GetMaterial () const noexcept; [[nodiscard]] const SHPhysicsMaterial& GetMaterial () const noexcept;
[[nodiscard]] const SHVec3& GetPositionOffset () const noexcept; [[nodiscard]] const SHVec3& GetPositionOffset () const noexcept;
[[nodiscard]] const SHVec3& GetRotationOffset () const noexcept;
[[nodiscard]] SHShape* GetShape () noexcept; [[nodiscard]] SHShape* GetShape () noexcept;
@ -96,7 +97,8 @@ namespace SHADE
void SetDensity (float density) noexcept; void SetDensity (float density) noexcept;
void SetMaterial (const SHPhysicsMaterial& newMaterial) noexcept; void SetMaterial (const SHPhysicsMaterial& newMaterial) noexcept;
void SetPositionOffset (const SHVec3& positionOffset) noexcept; void SetPositionOffset (const SHVec3& posOffset) noexcept;
void SetRotationOffset (const SHVec3& rotOffset) noexcept;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -110,6 +112,7 @@ namespace SHADE
SHShape* shape; SHShape* shape;
SHPhysicsMaterial material; SHPhysicsMaterial material;
SHVec3 positionOffset; SHVec3 positionOffset;
SHVec3 rotationOffset;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */

View File

@ -130,6 +130,8 @@ namespace SHADE
int SHPhysicsObject::AddCollider(SHCollider* collider) int SHPhysicsObject::AddCollider(SHCollider* collider)
{ {
const rp3d::Transform OFFSETS{ collider->GetPositionOffset(), collider->GetRotationOffset() };
switch (collider->GetType()) switch (collider->GetType())
{ {
case SHCollider::Type::BOX: case SHCollider::Type::BOX:
@ -137,7 +139,7 @@ namespace SHADE
const auto* box = reinterpret_cast<SHBoundingBox*>(collider->GetShape()); const auto* box = reinterpret_cast<SHBoundingBox*>(collider->GetShape());
rp3d::BoxShape* newBox = factory->createBoxShape(box->GetHalfExtents()); rp3d::BoxShape* newBox = factory->createBoxShape(box->GetHalfExtents());
rp3dBody->addCollider(newBox, rp3d::Transform{ collider->GetPositionOffset(), SHQuaternion::Identity }); rp3dBody->addCollider(newBox, OFFSETS);
break; break;
} }
case SHCollider::Type::SPHERE: case SHCollider::Type::SPHERE:
@ -145,7 +147,7 @@ namespace SHADE
const auto* sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape()); const auto* sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape());
rp3d::SphereShape* newSphere = factory->createSphereShape(sphere->GetRadius()); rp3d::SphereShape* newSphere = factory->createSphereShape(sphere->GetRadius());
rp3dBody->addCollider(newSphere, rp3d::Transform{ collider->GetPositionOffset(), SHQuaternion::Identity }); rp3dBody->addCollider(newSphere, OFFSETS);
break; break;
} }
// TODO(Diren): Add more collider shapes // TODO(Diren): Add more collider shapes
@ -168,96 +170,6 @@ namespace SHADE
rp3dBody->removeCollider(collider); rp3dBody->removeCollider(collider);
} }
void SHPhysicsObject::SyncRigidBody(SHRigidBodyComponent* rb) const noexcept
{
SHASSERT(rp3dBody != nullptr, "ReactPhysics body does not exist!")
if (rb->dirtyFlags == 0)
return;
auto* rigidBody = reinterpret_cast<rp3d::RigidBody*>(rp3dBody);
const uint16_t RB_FLAGS = rb->dirtyFlags;
for (size_t i = 0; i < SHRigidBodyComponent::NUM_DIRTY_FLAGS; ++i)
{
// Check if current dirty flag has been set to true
if (RB_FLAGS & 1U << i)
{
switch (i)
{
case 0: // Gravity
{
rigidBody->enableGravity(rb->IsGravityEnabled());
break;
}
case 1: // Sleeping
{
rigidBody->setIsAllowedToSleep(rb->IsAllowedToSleep());
break;
}
case 2: // Linear Constraints
{
const rp3d::Vector3 CONSTRAINTS
{
rb->flags & 1U << 2 ? 0.0f : 1.0f,
rb->flags & 1U << 3 ? 0.0f : 1.0f,
rb->flags & 1U << 4 ? 0.0f : 1.0f
};
rigidBody->setLinearLockAxisFactor(CONSTRAINTS);
break;
}
case 3: // Angular Constraints
{
const rp3d::Vector3 CONSTRAINTS
{
rb->flags & 1U << 5 ? 0.0f : 1.0f,
rb->flags & 1U << 6 ? 0.0f : 1.0f,
rb->flags & 1U << 7 ? 0.0f : 1.0f
};
rigidBody->setAngularLockAxisFactor(CONSTRAINTS);
break;
}
case 4: // Type
{
rigidBody->setType(static_cast<rp3d::BodyType>(rb->GetType()));
break;
}
case 5: // Mass
{
rigidBody->setMass(rb->GetMass());
break;
}
case 6: // Drag
{
rigidBody->setLinearDamping(rb->GetDrag());
break;
}
case 7: // Angular Drag
{
rigidBody->setAngularDamping(rb->GetAngularDrag());
break;
}
case 8: // Linear Velocity
{
rigidBody->setLinearVelocity(rb->GetLinearVelocity());
break;
}
case 9: // Angular Velocity
{
rigidBody->setAngularVelocity(rb->GetAngularVelocity());
break;
}
default: break;
}
}
}
rb->dirtyFlags = 0;
}
void SHPhysicsObject::SyncColliders(SHColliderComponent* c) const noexcept void SHPhysicsObject::SyncColliders(SHColliderComponent* c) const noexcept
{ {
int index = 0; int index = 0;
@ -266,9 +178,13 @@ namespace SHADE
if (!collider.dirty) if (!collider.dirty)
continue; continue;
// Update offsets
auto* rp3dCollider = rp3dBody->getCollider(index); auto* rp3dCollider = rp3dBody->getCollider(index);
rp3dCollider->setLocalToBodyTransform(rp3d::Transform(collider.GetPositionOffset(), SHQuaternion::Identity));
// Update trigger flag
rp3dCollider->setIsTrigger(collider.IsTrigger());
// Update offsets
rp3dCollider->setLocalToBodyTransform(rp3d::Transform(collider.GetPositionOffset(), collider.GetRotationOffset()));
switch (collider.GetType()) switch (collider.GetType())
{ {
@ -293,6 +209,8 @@ namespace SHADE
default: break; default: break;
} }
// TODO(Diren): Update Material
collider.dirty = false; collider.dirty = false;
++index; ++index;
} }

View File

@ -72,7 +72,6 @@ namespace SHADE
int AddCollider (SHCollider* collider); int AddCollider (SHCollider* collider);
void RemoveCollider (int index); void RemoveCollider (int index);
void SyncRigidBody (SHRigidBodyComponent* rb) const noexcept;
void SyncColliders (SHColliderComponent* c) const noexcept; void SyncColliders (SHColliderComponent* c) const noexcept;
private: private:

View File

@ -17,10 +17,10 @@
#include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHComponentManager.h"
#include "ECS_Base/Managers/SHEntityManager.h" #include "ECS_Base/Managers/SHEntityManager.h"
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/SHEditor.hpp"
#include "Math/SHMathHelpers.h" #include "Math/SHMathHelpers.h"
#include "Scene/SHSceneManager.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Scene/SHSceneManager.h"
#include "Scripting/SHScriptEngine.h"
namespace SHADE namespace SHADE
{ {
@ -99,6 +99,16 @@ namespace SHADE
return 0; return 0;
} }
const SHPhysicsSystem::CollisionEvents& SHPhysicsSystem::GetCollisionInfo() const noexcept
{
return collisionInfo;
}
const SHPhysicsSystem::CollisionEvents& SHPhysicsSystem::GetTriggerInfo() const noexcept
{
return triggerInfo;
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */ /* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -187,6 +197,7 @@ namespace SHADE
settings.defaultBounciness = 0.0f; settings.defaultBounciness = 0.0f;
world = factory.createPhysicsWorld(settings); world = factory.createPhysicsWorld(settings);
world->setEventListener(this);
// Set up solvers // Set up solvers
world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::SPLIT_IMPULSES); world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::SPLIT_IMPULSES);
@ -200,6 +211,12 @@ namespace SHADE
const std::shared_ptr REMOVE_COMPONENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::RemovePhysicsComponent) }; const std::shared_ptr REMOVE_COMPONENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::RemovePhysicsComponent) };
const ReceiverPtr REMOVE_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(REMOVE_COMPONENT_RECEIVER); const ReceiverPtr REMOVE_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(REMOVE_COMPONENT_RECEIVER);
SHEventManager::SubscribeTo(SH_COMPONENT_REMOVED_EVENT, REMOVE_COMPONENT_RECEIVER_PTR); SHEventManager::SubscribeTo(SH_COMPONENT_REMOVED_EVENT, REMOVE_COMPONENT_RECEIVER_PTR);
#ifdef SHEDITOR
const std::shared_ptr EDITOR_STOP_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::ResetWorld) };
const ReceiverPtr EDITOR_STOP_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(EDITOR_STOP_RECEIVER);
SHEventManager::SubscribeTo(SH_EDITOR_ON_STOP_EVENT, EDITOR_STOP_RECEIVER_PTR);
#endif
} }
void SHPhysicsSystem::Exit() void SHPhysicsSystem::Exit()
@ -247,6 +264,9 @@ namespace SHADE
continue; continue;
const auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID); const auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
if (transformComponent && transformComponent->HasChanged()) if (transformComponent && transformComponent->HasChanged())
{ {
const auto WORLD_POS = transformComponent->GetWorldPosition(); const auto WORLD_POS = transformComponent->GetWorldPosition();
@ -255,68 +275,119 @@ namespace SHADE
physicsObject.SetPosition(WORLD_POS); physicsObject.SetPosition(WORLD_POS);
physicsObject.SetOrientation(WORLD_ROT); physicsObject.SetOrientation(WORLD_ROT);
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID); // Sync physics component transforms
if (rigidBodyComponent) if (rigidBodyComponent)
{ {
rigidBodyComponent->position = WORLD_POS; rigidBodyComponent->position = WORLD_POS;
rigidBodyComponent->orientation = WORLD_ROT; rigidBodyComponent->orientation = WORLD_ROT;
// Clear all forces and velocities if editor is stopped
if (SHSystemManager::GetSystem<SHEditor>()->editorState == SHEditor::State::STOP)
{
auto* rp3dRigidBody = reinterpret_cast<rp3d::RigidBody*>(physicsObject.rp3dBody);
rp3dRigidBody->resetForce();
rp3dRigidBody->resetTorque();
rp3dRigidBody->setLinearVelocity(SHVec3::Zero);
rp3dRigidBody->setAngularVelocity(SHVec3::Zero);
}
} }
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
if (colliderComponent) if (colliderComponent)
{ {
colliderComponent->position = WORLD_POS; colliderComponent->position = WORLD_POS;
colliderComponent->orientation = WORLD_ROT; colliderComponent->orientation = WORLD_ROT;
} }
} }
// Sync rigid bodies
if (rigidBodyComponent)
{
// Sync active states
const bool COMPONENT_ACTIVE = rigidBodyComponent->isActive;
SyncActiveStates(physicsObject, COMPONENT_ACTIVE);
if (!COMPONENT_ACTIVE)
continue;
} }
// Update bodies and colliders if component is dirty // Sync colliders
system->SyncRigidBodyComponents(SHComponentManager::GetDense<SHRigidBodyComponent>());
system->SyncColliderComponents(SHComponentManager::GetDense<SHColliderComponent>()); if (colliderComponent)
{
const bool COMPONENT_ACTIVE = colliderComponent->isActive;
SyncActiveStates(physicsObject, colliderComponent->isActive);
if (!COMPONENT_ACTIVE)
continue;
physicsObject.SyncColliders(colliderComponent);
}
}
} }
void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept
{ {
auto* system = reinterpret_cast<SHPhysicsSystem*>(GetSystem()); auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
fixedTimeStep = 1.0 / system->fixedDT; auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
if (scriptingSystem == nullptr)
{
SHLOGV_WARNING("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!");
}
fixedTimeStep = 1.0 / physicsSystem->fixedDT;
accumulatedTime += dt; accumulatedTime += dt;
int count = 0; int count = 0;
while (accumulatedTime > fixedTimeStep) while (accumulatedTime > fixedTimeStep)
{ {
system->world->update(static_cast<rp3d::decimal>(fixedTimeStep)); if (scriptingSystem != nullptr)
scriptingSystem->ExecuteFixedUpdates();
physicsSystem->world->update(static_cast<rp3d::decimal>(fixedTimeStep));
accumulatedTime -= fixedTimeStep; accumulatedTime -= fixedTimeStep;
++count; ++count;
} }
stats.numSteps = count; stats.numSteps = count;
system->worldUpdated = count > 0; physicsSystem->worldUpdated = count > 0;
system->interpolationFactor = accumulatedTime / fixedTimeStep; physicsSystem->interpolationFactor = accumulatedTime / fixedTimeStep;
} }
void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept
{ {
auto* system = reinterpret_cast<SHPhysicsSystem*>(GetSystem()); auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
if (scriptingSystem == nullptr)
{
SHLOGV_WARNING("Unable to invoke collision and trigger script events due to missing SHScriptEngine!");
}
// Interpolate transforms for rendering // Interpolate transforms for rendering
if (system->worldUpdated) if (physicsSystem->worldUpdated)
{ {
system->SyncTransforms(); physicsSystem->SyncTransforms();
// TODO(Diren): Handle trigger messages for scripting // Collision & Trigger messages
if (scriptingSystem != nullptr)
scriptingSystem->ExecuteCollisionFunctions();
physicsSystem->ClearInvalidCollisions();
}
}
void SHPhysicsSystem::onContact(const CallbackData& callbackData)
{
for (uint32_t i = 0; i < callbackData.getNbContactPairs(); ++i)
{
const auto CONTACT_PAIR = callbackData.getContactPair(i);
const SHCollisionEvent NEW_EVENT = GenerateCollisionEvent(CONTACT_PAIR);
UpdateEventContainers(NEW_EVENT, collisionInfo);
}
}
void SHPhysicsSystem::onTrigger(const rp3d::OverlapCallback::CallbackData& callbackData)
{
for (uint32_t i = 0; i < callbackData.getNbOverlappingPairs(); ++i)
{
const auto& OVERLAP_PAIR = callbackData.getOverlappingPair(i);
const SHCollisionEvent NEW_EVENT = GenerateCollisionEvent(OVERLAP_PAIR);
UpdateEventContainers(NEW_EVENT, triggerInfo);
} }
} }
@ -353,58 +424,11 @@ namespace SHADE
map.erase(entityID); map.erase(entityID);
} }
void SHPhysicsSystem::SyncActiveStates(SHPhysicsObject* physicsObject, bool componentActive) noexcept void SHPhysicsSystem::SyncActiveStates(SHPhysicsObject& physicsObject, bool componentActive) noexcept
{ {
const bool RP3D_ACTIVE = physicsObject->rp3dBody->isActive(); const bool RP3D_ACTIVE = physicsObject.rp3dBody->isActive();
if (RP3D_ACTIVE != componentActive) if (RP3D_ACTIVE != componentActive)
physicsObject->rp3dBody->setIsActive(componentActive); physicsObject.rp3dBody->setIsActive(componentActive);
}
void SHPhysicsSystem::SyncRigidBodyComponents(std::vector<SHRigidBodyComponent>& denseArray) noexcept
{
if (denseArray.empty())
return;
for (auto& comp : denseArray)
{
const EntityID ENTITY_ID = comp.GetEID();
// Get physicsObject
auto* physicsObject = GetPhysicsObject(ENTITY_ID);
// TODO(Diren): Check if active in hierarchy
const bool COMPONENT_ACTIVE = comp.isActive;
SyncActiveStates(physicsObject, COMPONENT_ACTIVE);
if (!COMPONENT_ACTIVE)
continue;
physicsObject->SyncRigidBody(&comp);
}
}
void SHPhysicsSystem::SyncColliderComponents(std::vector<SHColliderComponent>& denseArray) noexcept
{
if (denseArray.empty())
return;
for (auto& comp : denseArray)
{
const EntityID ENTITY_ID = comp.GetEID();
// Get physicsObject
auto* physicsObject = GetPhysicsObject(ENTITY_ID);
// TODO(Diren): Check if active in hierarchy
const bool COMPONENT_ACTIVE = comp.isActive;
SyncActiveStates(physicsObject, COMPONENT_ACTIVE);
if (!COMPONENT_ACTIVE)
continue;
physicsObject->SyncColliders(&comp);
}
} }
void SHPhysicsSystem::SyncTransforms() noexcept void SHPhysicsSystem::SyncTransforms() noexcept
@ -459,15 +483,54 @@ namespace SHADE
} }
// Convert RP3D Transform to SHADE // Convert RP3D Transform to SHADE
auto* transformComponent = SHComponentManager::GetComponent<SHTransformComponent>(entityID); auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
if (transformComponent != nullptr)
{
transformComponent->SetWorldPosition(rp3dPos); transformComponent->SetWorldPosition(rp3dPos);
transformComponent->SetWorldOrientation(rp3dRot); transformComponent->SetWorldOrientation(rp3dRot);
}
// Cache transforms // Cache transforms
physicsObject.prevTransform = CURRENT_TF; physicsObject.prevTransform = CURRENT_TF;
} }
} }
void SHPhysicsSystem::UpdateEventContainers(const SHCollisionEvent& collisionEvent, CollisionEvents& container) noexcept
{
const auto IT = std::ranges::find_if(container.begin(), container.end(), [&](const SHCollisionEvent& e)
{
const bool ENTITY_MATCH = e.value[0] == collisionEvent.value[0];
const bool COLLIDERS_MATCH = e.value[1] == collisionEvent.value[1];
return ENTITY_MATCH && COLLIDERS_MATCH;
});
if (IT == container.end())
container.emplace_back(collisionEvent);
else
IT->collisionState = collisionEvent.collisionState;
}
void SHPhysicsSystem::ClearInvalidCollisions() noexcept
{
static const auto CLEAR = [](CollisionEvents& container)
{
for (auto eventIter = container.begin(); eventIter != container.end();)
{
const bool CLEAR_EVENT = eventIter->GetCollisionState() == SHCollisionEvent::State::EXIT
|| eventIter->GetCollisionState() == SHCollisionEvent::State::INVALID;
if (CLEAR_EVENT)
eventIter = container.erase(eventIter);
else
++eventIter;
}
};
CLEAR(collisionInfo);
CLEAR(triggerInfo);
}
SHEventHandle SHPhysicsSystem::AddPhysicsComponent(SHEventPtr addComponentEvent) SHEventHandle SHPhysicsSystem::AddPhysicsComponent(SHEventPtr addComponentEvent)
{ {
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHComponentAddedEvent>*>(addComponentEvent.get()); const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHComponentAddedEvent>*>(addComponentEvent.get());
@ -556,14 +619,21 @@ namespace SHADE
const EntityID ENTITY_ID = EVENT_DATA->data->eid; const EntityID ENTITY_ID = EVENT_DATA->data->eid;
auto* physicsObject = GetPhysicsObject(ENTITY_ID); auto* physicsObject = GetPhysicsObject(ENTITY_ID);
SHASSERT(physicsObject != nullptr, "Physics object has been lost from the world!") auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ENTITY_ID);
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(ENTITY_ID);
if (REMOVED_ID == RIGID_BODY_ID) // Wake up all physics objects
for (auto& [entityID, object] : map)
{
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(entityID))
reinterpret_cast<rp3d::RigidBody*>(object.rp3dBody)->setIsSleeping(false);
}
if (REMOVED_ID == RIGID_BODY_ID && physicsObject != nullptr)
{ {
world->destroyRigidBody(reinterpret_cast<rp3d::RigidBody*>(physicsObject->rp3dBody)); world->destroyRigidBody(reinterpret_cast<rp3d::RigidBody*>(physicsObject->rp3dBody));
physicsObject->rp3dBody = nullptr; physicsObject->rp3dBody = nullptr;
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(ENTITY_ID);
if (colliderComponent != nullptr) if (colliderComponent != nullptr)
{ {
// Preserve colliders as a collision body // Preserve colliders as a collision body
@ -575,16 +645,9 @@ namespace SHADE
for (auto& collider : colliderComponent->colliders) for (auto& collider : colliderComponent->colliders)
physicsObject->AddCollider(&collider); physicsObject->AddCollider(&collider);
} }
// Wake up all physics objects
for (auto& [entityID, object] : map)
{
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(entityID))
reinterpret_cast<rp3d::RigidBody*>(object.rp3dBody)->setIsSleeping(false);
}
} }
if (REMOVED_ID == COLLIDER_ID) if (REMOVED_ID == COLLIDER_ID && physicsObject != nullptr)
{ {
// Remove all colliders // Remove all colliders
const int NUM_COLLIDERS = static_cast<int>(physicsObject->rp3dBody->getNbColliders()); const int NUM_COLLIDERS = static_cast<int>(physicsObject->rp3dBody->getNbColliders());
@ -594,13 +657,36 @@ namespace SHADE
auto* collider = physicsObject->rp3dBody->getCollider(i); auto* collider = physicsObject->rp3dBody->getCollider(i);
physicsObject->rp3dBody->removeCollider(collider); physicsObject->rp3dBody->removeCollider(collider);
} }
// Check for a rigidbody component
if (rigidBodyComponent == nullptr)
physicsObject->rp3dBody = nullptr;
} }
if (physicsObject->rp3dBody == nullptr) if (physicsObject != nullptr && physicsObject->rp3dBody == nullptr)
DestroyPhysicsObject(ENTITY_ID); DestroyPhysicsObject(ENTITY_ID);
} }
return EVENT_DATA->handle; return EVENT_DATA->handle;
} }
SHEventHandle SHPhysicsSystem::ResetWorld(SHEventPtr editorStopEvent)
{
// TODO(Diren): Rebuild world based on how scene reloading is done
for (auto& [entityID, physicsObject] : map)
{
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(entityID))
{
auto* rp3dRigidBody = reinterpret_cast<rp3d::RigidBody*>(physicsObject.rp3dBody);
rp3dRigidBody->resetForce();
rp3dRigidBody->resetTorque();
rp3dRigidBody->setLinearVelocity(SHVec3::Zero);
rp3dRigidBody->setAngularVelocity(SHVec3::Zero);
}
}
return editorStopEvent->handle;
}
} // namespace SHADE } // namespace SHADE

View File

@ -23,16 +23,18 @@
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Scene/SHSceneGraph.h" #include "Scene/SHSceneGraph.h"
#include "SHPhysicsObject.h" #include "SHPhysicsObject.h"
#include "SHPhysicsUtils.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
class SH_API SHPhysicsSystem final : public SHSystem class SH_API SHPhysicsSystem final : public SHSystem
, public rp3d::EventListener
{ {
public: public:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -47,6 +49,8 @@ namespace SHADE
bool sleepingEnabled; bool sleepingEnabled;
}; };
using CollisionEvents = std::vector<SHCollisionEvent>;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */ /* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -65,6 +69,9 @@ namespace SHADE
[[nodiscard]] uint16_t GetNumberVelocityIterations () const noexcept; [[nodiscard]] uint16_t GetNumberVelocityIterations () const noexcept;
[[nodiscard]] uint16_t GetNumberPositionIterations () const noexcept; [[nodiscard]] uint16_t GetNumberPositionIterations () const noexcept;
[[nodiscard]] const CollisionEvents& GetCollisionInfo () const noexcept;
[[nodiscard]] const CollisionEvents& GetTriggerInfo () const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Setter Functions */ /* Setter Functions */
@ -85,14 +92,12 @@ namespace SHADE
void Init () override; void Init () override;
void Exit () override; void Exit () override;
//void AddRigidBody (EntityID entityID) noexcept;
//void AddCollider (EntityID entityID) noexcept;
//void RemoveRigidBody (EntityID entityID) noexcept;
//void RemoveCollider (EntityID entityID) noexcept;
void AddCollisionShape (EntityID entityID, SHCollider* collider); void AddCollisionShape (EntityID entityID, SHCollider* collider);
void RemoveCollisionShape (EntityID entityID, int index); void RemoveCollisionShape (EntityID entityID, int index);
void onContact (const rp3d::CollisionCallback::CallbackData& callbackData) override;
void onTrigger (const rp3d::OverlapCallback::CallbackData& callbackData) override;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* System Routines */ /* System Routines */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -165,40 +170,32 @@ namespace SHADE
rp3d::PhysicsCommon factory; rp3d::PhysicsCommon factory;
EntityObjectMap map; EntityObjectMap map;
CollisionEvents collisionInfo;
CollisionEvents triggerInfo;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHPhysicsObject* EnsurePhysicsObject (EntityID entityID) noexcept; SHPhysicsObject* EnsurePhysicsObject (EntityID entityID) noexcept;
SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept; SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
void DestroyPhysicsObject (EntityID entityID) noexcept; void DestroyPhysicsObject (EntityID entityID) noexcept;
void SyncActiveStates (SHPhysicsObject* physicsObject, bool componentActive) noexcept; static void SyncActiveStates (SHPhysicsObject& physicsObject, bool componentActive) noexcept;
void SyncRigidBodyComponents (std::vector<SHRigidBodyComponent>& denseArray) noexcept;
void SyncColliderComponents (std::vector<SHColliderComponent>& denseArray) noexcept;
void SyncTransforms () noexcept; void SyncTransforms () noexcept;
static void UpdateEventContainers (const SHCollisionEvent& collisionEvent, CollisionEvents& container) noexcept;
void ClearInvalidCollisions () noexcept;
SHEventHandle AddPhysicsComponent (SHEventPtr addComponentEvent); SHEventHandle AddPhysicsComponent (SHEventPtr addComponentEvent);
SHEventHandle RemovePhysicsComponent (SHEventPtr removeComponentEvent); SHEventHandle RemovePhysicsComponent (SHEventPtr removeComponentEvent);
SHEventHandle ResetWorld (SHEventPtr editorStopEvent);
template <typename RP3DCollisionPair, typename = std::enable_if_t
<std::is_same_v<RP3DCollisionPair, rp3d::CollisionCallback::ContactPair>
|| std::is_same_v<RP3DCollisionPair, rp3d::OverlapCallback::OverlapPair>>>
SHCollisionEvent GenerateCollisionEvent (const RP3DCollisionPair& cp) noexcept;
}; };
/*-----------------------------------------------------------------------------------*/
/* Event Data Definitions */
/*-----------------------------------------------------------------------------------*/
struct SHPhysicsColliderAddedEvent
{
EntityID entityID;
SHCollider::Type colliderType;
int colliderIndex;
};
struct SHPhysicsColliderRemovedEvent
{
EntityID entityID;
int colliderIndex;
};
} // namespace SHADE } // namespace SHADE
#include "SHPhysicsSystem.hpp"

View File

@ -0,0 +1,84 @@
/****************************************************************************************
* \file SHPhysicsSystem.hpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for templated functions the Physics System
*
* \copyright 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 <type_traits>
// Primary Header
#include "SHPhysicsSystem.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
template <typename RP3DCollisionPair, typename Condition>
SHCollisionEvent SHPhysicsSystem::GenerateCollisionEvent(const RP3DCollisionPair& cp) noexcept
{
static const auto MATCH_COLLIDER = []
(
const SHPhysicsObject& physicsObject
, const rp3d::Entity colliderID
)->uint32_t
{
for (uint32_t i = 0; i < physicsObject.rp3dBody->getNbColliders(); ++i)
{
const auto* collider = physicsObject.rp3dBody->getCollider(i);
if (collider->getEntity() == colliderID)
return i;
}
return std::numeric_limits<uint32_t>::max();
};
SHCollisionEvent cInfo;
// Update collision state
cInfo.collisionState = static_cast<SHCollisionEvent::State>(cp.getEventType());
// Match body and collider for collision event
const rp3d::Entity body1 = cp.getBody1()->getEntity();
const rp3d::Entity body2 = cp.getBody2()->getEntity();
const rp3d::Entity collider1 = cp.getCollider1()->getEntity();
const rp3d::Entity collider2 = cp.getCollider2()->getEntity();
// Find and match both ids
bool matched[2] = { false, false };
for (auto& [entityID, physicsObject] : map)
{
// Match body 1
if (matched[SHCollisionEvent::ENTITY_A] == false && physicsObject.rp3dBody->getEntity() == body1)
{
cInfo.ids[SHCollisionEvent::ENTITY_A] = entityID;
cInfo.ids[SHCollisionEvent::COLLIDER_A] = MATCH_COLLIDER(physicsObject, collider1);
matched[SHCollisionEvent::ENTITY_A] = true;
}
// Match body 2
if (matched[SHCollisionEvent::ENTITY_B] == false && physicsObject.rp3dBody->getEntity() == body2)
{
cInfo.ids[SHCollisionEvent::ENTITY_B] = entityID;
cInfo.ids[SHCollisionEvent::COLLIDER_B] = MATCH_COLLIDER(physicsObject, collider2);
matched[SHCollisionEvent::ENTITY_B] = true;
}
if (matched[SHCollisionEvent::ENTITY_A] == true && matched[SHCollisionEvent::ENTITY_B] == true)
return cInfo;
}
return cInfo;
}
} // namespace SHADE

View File

@ -0,0 +1,65 @@
/************************************************************************************//*!
\file SHPhysicsSystemInterface.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
SHPhysicsSystemInterface 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 "SHPhysicsSystemInterface.h"
// Project Includes
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Physics/SHPhysicsSystem.h"
#include "Physics/SHPhysicsUtils.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Static Usage Functions */
/*-----------------------------------------------------------------------------------*/
const std::vector<SHCollisionEvent>& SHPhysicsSystemInterface::GetCollisionInfo() noexcept
{
static std::vector<SHCollisionEvent> emptyVec;
auto phySystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
if (phySystem)
{
return phySystem->GetCollisionInfo();
}
SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get collision events. Empty vector returned instead.");
return emptyVec;
}
const std::vector<SHCollisionEvent>& SHPhysicsSystemInterface::GetTriggerInfo() noexcept
{
static std::vector<SHCollisionEvent> emptyVec;
auto phySystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
if (phySystem)
{
return phySystem->GetTriggerInfo();
}
SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get trigger events. Empty vector returned instead.");
return emptyVec;
}
double SHPhysicsSystemInterface::GetFixedDT() noexcept
{
auto phySystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
if (phySystem)
{
return phySystem->GetFixedDT();
}
SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get fixed delta time. 0.0 returned instead.");
return 0.0;
}
}

View File

@ -0,0 +1,46 @@
/************************************************************************************//*!
\file SHPhysicsSystemInterface.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
// STL Includes
#include <vector>
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHCollisionEvent;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/// <summary>
/// Static class that wraps up certain functions in the SHPhysicsSystem so that
/// accessing it from SHADE_Managed would not cause issues due to C++20 features.
/// </summary>
class SH_API SHPhysicsSystemInterface final
{
public:
/*---------------------------------------------------------------------------------*/
/* Constructor */
/*---------------------------------------------------------------------------------*/
SHPhysicsSystemInterface() = delete;
/*---------------------------------------------------------------------------------*/
/* Static Usage Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] static const std::vector<SHCollisionEvent>& GetCollisionInfo() noexcept;
[[nodiscard]] static const std::vector<SHCollisionEvent>& GetTriggerInfo() noexcept;
[[nodiscard]] static double GetFixedDT() noexcept;
};
}

View File

@ -0,0 +1,93 @@
/****************************************************************************************
* \file SHPhysicsUtils.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for some Physics Utilities
*
* \copyright 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>
// Primary Header
#include "SHPhysicsUtils.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHCollisionEvent::SHCollisionEvent() noexcept
: collisionState { State::INVALID }
{
ids[ENTITY_A] = MAX_EID;
ids[ENTITY_B] = MAX_EID;
ids[COLLIDER_A] = std::numeric_limits<uint32_t>::max();
ids[COLLIDER_B] = std::numeric_limits<uint32_t>::max();
}
SHCollisionEvent::SHCollisionEvent(EntityID entityA, EntityID entityB) noexcept
: collisionState { State::INVALID }
{
ids[ENTITY_A] = entityA;
ids[ENTITY_B] = entityB;
ids[COLLIDER_A] = std::numeric_limits<uint32_t>::max();
ids[COLLIDER_B] = std::numeric_limits<uint32_t>::max();
}
/*-----------------------------------------------------------------------------------*/
/* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/
bool SHCollisionEvent::operator==(const SHCollisionEvent& rhs) const noexcept
{
return value[0] == rhs.value[0] && value[1] == rhs.value[1];
}
bool SHCollisionEvent::operator!=(const SHCollisionEvent& rhs) const noexcept
{
return value[0] != rhs.value[0] || value[1] != rhs.value[1];
}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
EntityID SHCollisionEvent::GetEntityA() const noexcept
{
return ids[ENTITY_A];
}
EntityID SHCollisionEvent::GetEntityB() const noexcept
{
return ids[ENTITY_B];
}
const SHRigidBodyComponent* SHCollisionEvent::GetRigidBodyA() const noexcept
{
return SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ids[ENTITY_A]);
}
const SHRigidBodyComponent* SHCollisionEvent::GetRigidBodyB() const noexcept
{
return SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ids[ENTITY_B]);
}
const SHCollider* SHCollisionEvent::GetColliderA() const noexcept
{
return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_A])->GetCollider(ids[COLLIDER_A]);
}
const SHCollider* SHCollisionEvent::GetColliderB() const noexcept
{
return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_B])->GetCollider(ids[COLLIDER_B]);
}
SHCollisionEvent::State SHCollisionEvent::GetCollisionState() const noexcept
{
return collisionState;
}
} // namespace SHADE

View File

@ -0,0 +1,116 @@
/****************************************************************************************
* \file SHPhysicsUtils.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for some Physics Utilities
*
* \copyright 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
// Project Headers
#include "Components/SHColliderComponent.h"
#include "Components/SHRigidBodyComponent.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
struct SHPhysicsColliderAddedEvent
{
EntityID entityID;
SHCollider::Type colliderType;
int colliderIndex;
};
struct SHPhysicsColliderRemovedEvent
{
EntityID entityID;
int colliderIndex;
};
class SH_API SHCollisionEvent
{
private:
/*---------------------------------------------------------------------------------*/
/* Friends */
/*---------------------------------------------------------------------------------*/
friend class SHPhysicsSystem;
public:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
enum class State
{
ENTER
, STAY
, EXIT
, TOTAL
, INVALID = -1
};
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
SHCollisionEvent () noexcept;
SHCollisionEvent (EntityID entityA, EntityID entityB) noexcept;
SHCollisionEvent (const SHCollisionEvent& rhs) = default;
SHCollisionEvent (SHCollisionEvent&& rhs) = default;
~SHCollisionEvent () = default;
/*---------------------------------------------------------------------------------*/
/* Operator Overloads */
/*---------------------------------------------------------------------------------*/
bool operator== (const SHCollisionEvent& rhs) const noexcept;
bool operator!= (const SHCollisionEvent& rhs) const noexcept;
SHCollisionEvent& operator= (const SHCollisionEvent& rhs) = default;
SHCollisionEvent& operator= (SHCollisionEvent&& rhs) = default;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] EntityID GetEntityA () const noexcept;
[[nodiscard]] EntityID GetEntityB () const noexcept;
[[nodiscard]] const SHRigidBodyComponent* GetRigidBodyA () const noexcept;
[[nodiscard]] const SHRigidBodyComponent* GetRigidBodyB () const noexcept;
[[nodiscard]] const SHCollider* GetColliderA () const noexcept;
[[nodiscard]] const SHCollider* GetColliderB () const noexcept;
[[nodiscard]] State GetCollisionState () const noexcept;
private:
static constexpr uint32_t ENTITY_A = 0;
static constexpr uint32_t ENTITY_B = 1;
static constexpr uint32_t COLLIDER_A = 2;
static constexpr uint32_t COLLIDER_B = 3;
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
union
{
uint64_t value[2]; // EntityValue, ColliderIndexValue
uint32_t ids [4]; // EntityA, EntityB, ColliderIndexA, ColliderIndexB
};
State collisionState;
};
} // namespace SHADE

View File

@ -7,5 +7,6 @@ namespace SHADE
constexpr const char* min = "MIN"; constexpr const char* min = "MIN";
constexpr const char* max = "MAX"; constexpr const char* max = "MAX";
constexpr const char* tooltip = "tooltip"; constexpr const char* tooltip = "tooltip";
constexpr const char* angleInRad = "angleInRad";
} }
} }

View File

@ -21,9 +21,11 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHResourceHub SHResourceManager::resourceHub; SHResourceHub SHResourceManager::resourceHub;
std::unordered_map<std::type_index, std::unordered_map<AssetID, Handle<void>>> SHResourceManager::handlesMap; std::unordered_map<std::type_index, std::unordered_map<AssetID, Handle<void>>> SHResourceManager::handlesMap;
std::unordered_map<std::type_index, SHADE::SHResourceManager::HandleAssetMap> SHResourceManager::assetIdMap; std::unordered_map<std::type_index, SHResourceManager::HandleAssetMap> SHResourceManager::assetIdMap;
std::unordered_map<std::type_index, std::function<void(AssetID)>> SHResourceManager::typedFreeFuncMap; std::unordered_map<std::type_index, std::function<void(AssetID)>> SHResourceManager::typedFreeFuncMap;
std::vector<AssetID> SHResourceManager::loadedAssetData; std::vector<AssetID> SHResourceManager::loadedAssetData;
bool SHResourceManager::textureChanged = false;
bool SHResourceManager::meshChanged = false;
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Function Definitions */ /* Function Definitions */
@ -63,8 +65,17 @@ namespace SHADE
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>(); SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (gfxSystem == nullptr) if (gfxSystem == nullptr)
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed."); throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
if (meshChanged)
{
gfxSystem->BuildMeshBuffers(); gfxSystem->BuildMeshBuffers();
meshChanged = false;
}
if (textureChanged)
{
gfxSystem->BuildTextures(); gfxSystem->BuildTextures();
textureChanged = false;
}
// Free CPU Resources // Free CPU Resources
for (auto assetId : loadedAssetData) for (auto assetId : loadedAssetData)

View File

@ -17,9 +17,27 @@ of DigiPen Institute of Technology is prohibited.
#include "SH_API.h" #include "SH_API.h"
#include "SHResourceLibrary.h" #include "SHResourceLibrary.h"
#include "Assets/SHAssetMacros.h" #include "Assets/SHAssetMacros.h"
#include "Assets/Asset Types/SHMeshAsset.h"
#include "Assets/Asset Types/SHTextureAsset.h"
#include "Assets/Asset Types/SHShaderAsset.h"
#include "Graphics/Shaders/SHVkShaderModule.h"
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
#include "Graphics/MiddleEnd/Interface/SHMaterial.h"
#include "Assets/Asset Types/SHMaterialAsset.h"
namespace SHADE namespace SHADE
{ {
/// <summary>
/// Template structs that maps a resource to their loaded asset representation type.
/// </summary>
template<typename T = void>
struct SHResourceLoader { using AssetType = void; };
template<> struct SHResourceLoader<SHMesh> { using AssetType = SHMeshAsset; };
template<> struct SHResourceLoader<SHTexture> { using AssetType = SHTextureAsset; };
template<> struct SHResourceLoader<SHVkShaderModule> { using AssetType = SHShaderAsset; };
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialAsset; };
/// <summary> /// <summary>
/// Static class responsible for loading and caching runtime resources from their /// Static class responsible for loading and caching runtime resources from their
/// serialised Asset IDs. /// serialised Asset IDs.
@ -61,7 +79,7 @@ namespace SHADE
/// <param name="assetId">Handle to the resource to unload.</param> /// <param name="assetId">Handle to the resource to unload.</param>
static void Unload(AssetID assetId); static void Unload(AssetID assetId);
/// <summary> /// <summary>
/// Needs to be called to finalise all changes to loads. /// Needs to be called to finalise all changes to loads, unless at runtime.
/// </summary> /// </summary>
static void FinaliseChanges(); static void FinaliseChanges();
@ -111,6 +129,9 @@ namespace SHADE
static std::unordered_map<std::type_index, std::function<void(AssetID)>> typedFreeFuncMap; static std::unordered_map<std::type_index, std::function<void(AssetID)>> typedFreeFuncMap;
// Pointers to temp CPU resources // Pointers to temp CPU resources
static std::vector<AssetID> loadedAssetData; static std::vector<AssetID> loadedAssetData;
// Dirty Flags
static bool meshChanged;
static bool textureChanged;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */
@ -124,6 +145,14 @@ namespace SHADE
/// <returns>Reference to the AssetHandleMap of the specified type.</returns> /// <returns>Reference to the AssetHandleMap of the specified type.</returns>
template<typename ResourceType> template<typename ResourceType>
static std::pair<AssetHandleMapRef, HandleAssetMapRef> getAssetHandleMap(); static std::pair<AssetHandleMapRef, HandleAssetMapRef> getAssetHandleMap();
/// <summary>
///
/// </summary>
/// <typeparam name="ResourceType"></typeparam>
/// <param name="assetData"></param>
/// <returns></returns>
template<typename ResourceType>
static Handle<ResourceType> load(AssetID assetId, const typename SHResourceLoader<ResourceType>::AssetType& assetData);
}; };
} }

View File

@ -13,12 +13,17 @@ of DigiPen Institute of Technology is prohibited.
#pragma once #pragma once
// Primary Include // Primary Include
#include "SHResourceManager.h" #include "SHResourceManager.h"
// External Dependencies
#include <yaml-cpp/yaml.h>
// Project Includes // Project Includes
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include "Assets/Asset Types/SHAssetIncludes.h" #include "Assets/Asset Types/SHAssetIncludes.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Tools/SHLog.h" #include "Tools/SHLog.h"
#include "Graphics/Shaders/SHVkShaderModule.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
namespace SHADE namespace SHADE
{ {
@ -40,67 +45,19 @@ namespace SHADE
return Handle<ResourceType>(typedHandleMap.get()[assetId]); return Handle<ResourceType>(typedHandleMap.get()[assetId]);
/* Otherwise, we need to load it! */ /* Otherwise, we need to load it! */
// Meshes // Load Asset Data
if constexpr (std::is_same_v<ResourceType, SHMesh>) const auto* assetData = SHAssetManager::GetData<SHResourceLoader<ResourceType>::AssetType>(assetId);
{
// Get system
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (gfxSystem == nullptr)
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
// Load
const SHMeshAsset* assetData = SHAssetManager::GetData<SHMeshAsset>(assetId);
if (assetData == nullptr) if (assetData == nullptr)
{ {
SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID."); SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID.");
return {}; return {};
} }
loadedAssetData.emplace_back(assetId);
Handle<SHMesh> meshHandle = gfxSystem->AddMesh auto handle = load<ResourceType>(assetId, *assetData);
( Handle genericHandle = Handle(handle);
assetData->vertexPosition.size(),
assetData->vertexPosition.data(),
assetData->texCoords.data(),
assetData->vertexTangent.data(),
assetData->vertexNormal.data(),
assetData->indices.size(),
assetData->indices.data()
);
Handle genericHandle = Handle(meshHandle);
typedHandleMap.get().emplace(assetId, genericHandle); typedHandleMap.get().emplace(assetId, genericHandle);
typedAssetIdMap.get().emplace(genericHandle, assetId); typedAssetIdMap.get().emplace(genericHandle, assetId);
return meshHandle; return handle;
}
// Textures
else if constexpr (std::is_same_v<ResourceType, SHTexture>)
{
// Get system
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (gfxSystem == nullptr)
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
// Load
const SHTextureAsset* assetData = SHAssetManager::GetData<SHTextureAsset>(assetId);
if (assetData == nullptr)
{
SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID.");
return {};
}
loadedAssetData.emplace_back(assetId);
Handle<SHTexture> texHandle = gfxSystem->AddTexture
(
assetData->numBytes,
assetData->pixelData,
assetData->width,
assetData->height,
assetData->format,
assetData->mipOffsets
);
typedHandleMap.get().emplace(assetId, Handle(texHandle));
return texHandle;
}
} }
template<typename ResourceType> template<typename ResourceType>
@ -169,4 +126,131 @@ namespace SHADE
} }
return std::make_pair(std::ref(handlesMap[TYPE]), std::ref(assetIdMap[TYPE])); return std::make_pair(std::ref(handlesMap[TYPE]), std::ref(assetIdMap[TYPE]));
} }
template<typename ResourceType>
Handle<ResourceType> SHResourceManager::load(AssetID assetId, const typename SHResourceLoader<ResourceType>::AssetType& assetData)
{
// Get system
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (gfxSystem == nullptr)
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
// Meshes
if constexpr (std::is_same_v<ResourceType, SHMesh>)
{
loadedAssetData.emplace_back(assetId);
meshChanged = true;
return gfxSystem->AddMesh
(
assetData.vertexPosition.size(),
assetData.vertexPosition.data(),
assetData.texCoords.data(),
assetData.vertexTangent.data(),
assetData.vertexNormal.data(),
assetData.indices.size(),
assetData.indices.data()
);
}
// Textures
else if constexpr (std::is_same_v<ResourceType, SHTexture>)
{
loadedAssetData.emplace_back(assetId);
textureChanged = true;
return gfxSystem->AddTexture
(
assetData.numBytes,
assetData.pixelData,
assetData.width,
assetData.height,
assetData.format,
assetData.mipOffsets
);
}
// Shaders
else if constexpr (std::is_same_v<ResourceType, SHVkShaderModule>)
{
auto shader = gfxSystem->GetDevice()->CreateShaderModule
(
assetData.spirvBinary,
"main",
static_cast<vk::ShaderStageFlagBits>(assetData.shaderType),
assetData.name
);
shader->Reflect();
return shader;
}
// Materials
else if constexpr (std::is_same_v<ResourceType, SHMaterial>)
{
// Get the data we need to construct
SHMaterialSpec matSpec = YAML::Node(assetData.data).as<SHMaterialSpec>();
// Load shaders
auto vertexShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(matSpec.vertexShader);
auto fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(matSpec.fragShader);
// Ensure that both shaders are present
if (!(vertexShader && fragShader))
{
SHLOG_ERROR("[SHResourceManager] Failed to load material as shaders failed to be loaded.");
return {};
}
// Grab subpass from worldRenderer
auto renderPass = gfxSystem->GetPrimaryRenderpass();
if (!renderPass)
{
SHLOG_ERROR("[SHResourceManager] Failed to load material as RenderPass could not be found.");
return {};
}
auto subPass = renderPass->GetSubpass(matSpec.subpassName);
if (!subPass)
{
SHLOG_ERROR("[SHResourceManager] Failed to load material as SubPass could not be found.");
return {};
}
// Create material
auto matHandle = gfxSystem->AddMaterial(vertexShader, fragShader, subPass);
// Set properties for the material
Handle<SHShaderBlockInterface> pipelineProperties = matHandle->GetShaderBlockInterface();
for (int i = 0; i < static_cast<int>(pipelineProperties->GetVariableCount()); ++i)
{
const std::string& PROP_NAME = pipelineProperties->GetVariableName(i);
const auto& PROP_NODE = matSpec.properties;
if (PROP_NODE)
{
const std::string& VAR_NAME = pipelineProperties->GetVariableName(i);
const SHShaderBlockInterface::Variable* VARIABLE = pipelineProperties->GetVariable(i);
switch (VARIABLE->type)
{
case SHADE::SHShaderBlockInterface::Variable::Type::FLOAT:
matHandle->SetProperty(VARIABLE->offset, PROP_NODE.as<float>());
break;
case SHADE::SHShaderBlockInterface::Variable::Type::INT:
matHandle->SetProperty(VARIABLE->offset, PROP_NODE.as<int>());
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2:
matHandle->SetProperty(VARIABLE->offset, PROP_NODE.as<SHVec2>());
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR3:
matHandle->SetProperty(VARIABLE->offset, PROP_NODE.as<SHVec3>());
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR4:
matHandle->SetProperty(VARIABLE->offset, PROP_NODE.as<SHVec4>());
break;
case SHADE::SHShaderBlockInterface::Variable::Type::OTHER:
default:
continue;
break;
}
}
}
return matHandle;
}
}
} }

View File

@ -80,7 +80,10 @@ namespace SHADE
{ {
csScriptsExecuteFixedUpdate(); csScriptsExecuteFixedUpdate();
} }
void SHScriptEngine::ExecuteCollisionFunctions()
{
csScriptsExecutePhysicsEvents();
}
void SHScriptEngine::Exit() void SHScriptEngine::Exit()
{ {
// Do not allow deinitialization if not initialised // Do not allow deinitialization if not initialised
@ -377,6 +380,12 @@ namespace SHADE
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore", DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
"ExecuteLateUpdate" "ExecuteLateUpdate"
); );
csScriptsExecutePhysicsEvents = dotNet.GetFunctionPtr<CsFuncPtr>
(
DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
"ExecuteCollisionFunctions"
);
csScriptsFrameCleanUp = dotNet.GetFunctionPtr<CsFuncPtr> csScriptsFrameCleanUp = dotNet.GetFunctionPtr<CsFuncPtr>
( (
DEFAULT_CSHARP_LIB_NAME, DEFAULT_CSHARP_LIB_NAME,

Some files were not shown because too many files have changed in this diff Show More