Merge branch 'main' into SP3-12-SceneGraph

This commit is contained in:
Diren D Bharwani 2022-11-01 19:00:12 +08:00
commit 40be8a7962
105 changed files with 17732 additions and 925 deletions

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.

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

@ -108,13 +108,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>();

View File

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

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

@ -19,144 +19,145 @@
namespace SHADE namespace SHADE
{ {
std::string SHShaderSourceCompiler::CompileShaderSourceToBinary(AssetPath path, SHShaderAsset const& data) noexcept std::string SHShaderSourceCompiler::CompileShaderSourceToBinary(AssetPath path, SHShaderAsset const& data) noexcept
{ {
std::string newPath{ path.string() }; std::string newPath{ path.string() };
newPath = newPath.substr(0, newPath.find_last_of('.')); newPath = newPath.substr(0, newPath.find_last_of('.'));
newPath += SHADER_BUILT_IN_EXTENSION.data(); newPath += SHADER_BUILT_IN_EXTENSION.data();
std::ofstream file{ newPath, std::ios::binary | std::ios::out | std::ios::trunc }; std::ofstream file{ newPath, std::ios::binary | std::ios::out | std::ios::trunc };
file.write( file.write(
reinterpret_cast<char const*>(& data.shaderType), sizeof(uint8_t) reinterpret_cast<char const*>(& data.shaderType), sizeof(uint8_t)
); );
size_t const byteCount = sizeof(uint32_t) * data.spirvBinary.size(); size_t const byteCount = sizeof(uint32_t) * data.spirvBinary.size();
file.write( file.write(
reinterpret_cast<char const*>(&byteCount), sizeof(size_t) reinterpret_cast<char const*>(&byteCount), sizeof(size_t)
); );
file.write( file.write(
reinterpret_cast<char const*>(data.spirvBinary.data()), byteCount reinterpret_cast<char const*>(data.spirvBinary.data()), byteCount
); );
file.close(); file.close();
return newPath; return newPath;
} }
SHShaderAsset const* SHShaderSourceCompiler::CompileShaderSourceToMemory(std::string const& data, std::string const& name, SH_SHADER_TYPE type) noexcept SHShaderAsset const* SHShaderSourceCompiler::CompileShaderSourceToMemory(std::string const& data, std::string const& name, SH_SHADER_TYPE type) noexcept
{ {
// shaderc compiler // shaderc compiler
shaderc::Compiler compiler; shaderc::Compiler compiler;
shaderc::CompileOptions options; shaderc::CompileOptions options;
options.AddMacroDefinition("MY_DEFINE", "1"); options.AddMacroDefinition("MY_DEFINE", "1");
//TODO: Check if we need optimisation levels when compiling into spirv //TODO: Check if we need optimisation levels when compiling into spirv
// Set optimization levels // Set optimization levels
//if (opLevel != shaderc_optimization_level_zero) //if (opLevel != shaderc_optimization_level_zero)
// options.SetOptimizationLevel(opLevel); // options.SetOptimizationLevel(opLevel);
// Attempt to get the shaderc equivalent shader stage // Attempt to get the shaderc equivalent shader stage
shaderc_shader_kind shaderKind; shaderc_shader_kind shaderKind;
switch (type) switch (type)
{ {
case SH_SHADER_TYPE::VERTEX: case SH_SHADER_TYPE::VERTEX:
shaderKind = shaderc_shader_kind::shaderc_glsl_vertex_shader; shaderKind = shaderc_shader_kind::shaderc_glsl_vertex_shader;
break; break;
case SH_SHADER_TYPE::FRAGMENT: case SH_SHADER_TYPE::FRAGMENT:
shaderKind = shaderc_shader_kind::shaderc_glsl_fragment_shader; shaderKind = shaderc_shader_kind::shaderc_glsl_fragment_shader;
break; break;
case SH_SHADER_TYPE::COMPUTE: case SH_SHADER_TYPE::COMPUTE:
shaderKind = shaderc_shader_kind::shaderc_glsl_compute_shader; shaderKind = shaderc_shader_kind::shaderc_glsl_compute_shader;
break; break;
default: default:
shaderKind = shaderc_shader_kind::shaderc_glsl_vertex_shader; shaderKind = shaderc_shader_kind::shaderc_glsl_vertex_shader;
break; break;
} }
// Compile the shader and get the result // Compile the shader and get the result
shaderc::SpvCompilationResult compileResult = compiler.CompileGlslToSpv(data, shaderKind, name.c_str(), options); shaderc::SpvCompilationResult compileResult = compiler.CompileGlslToSpv(data, shaderKind, name.c_str(), options);
if (compileResult.GetCompilationStatus() != shaderc_compilation_status_success) if (compileResult.GetCompilationStatus() != shaderc_compilation_status_success)
{ {
SHLOG_ERROR("Shaderc failed to compile GLSL shader to binary | " + compileResult.GetErrorMessage()); SHLOG_ERROR("Shaderc failed to compile GLSL shader to binary | " + compileResult.GetErrorMessage());
return nullptr; return nullptr;
} }
auto result = new SHShaderAsset(); auto result = new SHShaderAsset();
result->spirvBinary.resize(compileResult.end() - compileResult.begin()); result->spirvBinary.resize(compileResult.end() - compileResult.begin());
std::ranges::copy(compileResult.begin(), compileResult.end(), result->spirvBinary.data()); std::ranges::copy(compileResult.begin(), compileResult.end(), result->spirvBinary.data());
result->name = name; result->name = name;
result->shaderType = type; result->shaderType = type;
return result; return result;
} }
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;
} }
}
return SH_SHADER_TYPE::INAVLID_TYPE; return SH_SHADER_TYPE::INAVLID_TYPE;
} }
std::optional<AssetPath> SHShaderSourceCompiler::LoadAndCompileShader(AssetPath path) noexcept std::optional<AssetPath> SHShaderSourceCompiler::LoadAndCompileShader(AssetPath path) noexcept
{ {
auto type = GetShaderTypeFromFilename(path.filename().string()); auto type = GetShaderTypeFromFilename(path.filename().string());
if (type == SH_SHADER_TYPE::INAVLID_TYPE) if (type == SH_SHADER_TYPE::INAVLID_TYPE)
{ {
SHLOG_ERROR("Invalid filename for shaders, follow suffix in SHAssetMacros.h: {}", path.string()); SHLOG_ERROR("Invalid filename for shaders, follow suffix in SHAssetMacros.h: {}", path.string());
return {}; return {};
} }
path.make_preferred(); path.make_preferred();
std::ifstream file{ path.string(), std::ios::in }; std::ifstream file{ path.string(), std::ios::in };
if (file.is_open()) if (file.is_open())
{ {
std::stringstream stream; std::stringstream stream;
stream << file.rdbuf(); stream << file.rdbuf();
std::string const content = stream.str(); std::string const content = stream.str();
auto data = CompileShaderSourceToMemory(content, path.filename().string(), type); auto data = CompileShaderSourceToMemory(content, path.filename().string(), type);
if (data == nullptr) if (data == nullptr)
{ {
return{}; return{};
} }
return CompileShaderSourceToBinary(path, *data); return CompileShaderSourceToBinary(path, *data);
} }
SHLOG_ERROR("Unable to open shader file: {}", path.string()); SHLOG_ERROR("Unable to open shader file: {}", path.string());
return {}; return {};
} }
std::optional<AssetPath> SHShaderSourceCompiler::CompileShaderFromString std::optional<AssetPath> SHShaderSourceCompiler::CompileShaderFromString
(std::string const& string, AssetPath path, SH_SHADER_TYPE type) noexcept (std::string const& string, AssetPath path, SH_SHADER_TYPE type) noexcept
{ {
auto const data = CompileShaderSourceToMemory(string, path.filename().string(), type); auto const data = CompileShaderSourceToMemory(string, path.filename().string(), type);
if (data == nullptr) if (data == nullptr)
{ {
return{}; return{};
} }
return CompileShaderSourceToBinary(path, *data); return CompileShaderSourceToBinary(path, *data);
} }
} }

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

@ -21,6 +21,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;
@ -35,7 +36,7 @@ namespace SHADE
protected: protected:
SHMatrix viewMatrix; SHMatrix viewMatrix;
SHMatrix projMatrix; SHMatrix projMatrix;
}; };
typedef Handle<SHCameraDirector> DirectorHandle; typedef Handle<SHCameraDirector> DirectorHandle;

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)
@ -121,6 +126,9 @@ namespace SHADE
editorCamera.SetYaw(0.0f); editorCamera.SetYaw(0.0f);
editorCamera.SetRoll(0.0f); editorCamera.SetRoll(0.0f);
editorCamera.movementSpeed = 2.0f; editorCamera.movementSpeed = 2.0f;
SHComponentManager::CreateComponentSparseSet<SHCameraComponent>();
SHComponentManager::CreateComponentSparseSet<SHCameraArmComponent>();
} }
@ -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

@ -195,18 +195,22 @@ namespace SHADE
if (SHDragDrop::BeginSource()) if (SHDragDrop::BeginSource())
{ {
std::string moveLabel = "Moving EID: "; std::string moveLabel = "Moving EID: ";
static std::vector<EntityID> draggingEntities = editor->selectedEntities;
if (!isSelected) if (!isSelected)
editor->selectedEntities.push_back(eid);
for (int i = 0; i < static_cast<int>(editor->selectedEntities.size()); ++i)
{ {
moveLabel.append(std::to_string(editor->selectedEntities[i])); 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>>(SHDragDrop::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

View File

@ -251,7 +251,7 @@ namespace SHADE
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)
@ -274,8 +274,27 @@ namespace SHADE
} }
{ {
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()))
@ -358,6 +377,7 @@ namespace SHADE
[component](AssetID const& id) [component](AssetID const& id)
{ {
component->SetMesh(SHResourceManager::LoadOrGet<SHMesh>(id)); component->SetMesh(SHResourceManager::LoadOrGet<SHMesh>(id));
SHResourceManager::FinaliseChanges();
}, SHDragDrop::DRAG_RESOURCE); }, SHDragDrop::DRAG_RESOURCE);
} }
else else

View File

@ -17,6 +17,7 @@
#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" #include "SHEditorComponentView.h"
namespace SHADE namespace SHADE
@ -126,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
@ -136,6 +140,7 @@ namespace SHADE
{ {
DrawAddComponentButton<SHTransformComponent>(eid); DrawAddComponentButton<SHTransformComponent>(eid);
DrawAddComponentButton<SHCameraComponent>(eid); DrawAddComponentButton<SHCameraComponent>(eid);
DrawAddComponentButton<SHCameraArmComponent>(eid);
DrawAddComponentButton<SHLightComponent>(eid); DrawAddComponentButton<SHLightComponent>(eid);
// Components that require Transforms // Components that require Transforms

View File

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

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

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

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

@ -74,11 +74,12 @@ 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
if (subBatch == subBatches.end()) if (subBatch == subBatches.end())
@ -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

@ -37,9 +37,9 @@ namespace SHADE
// Check if we have a batch with the same pipeline first // Check if we have a batch with the same pipeline first
auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch) auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
{ {
return batch.GetPipeline() == PIPELINE; return batch.GetPipeline() == PIPELINE;
}); });
// Create one if not found // Create one if not found

View File

@ -37,6 +37,8 @@ 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 "Assets/SHAssetManager.h"
#include "Resource/SHResourceManager.h"
namespace SHADE namespace SHADE
{ {
@ -104,14 +106,12 @@ 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);
// Load Built In Shaders
shaderModuleLibrary.ImportAllShaderSource(device); static constexpr AssetID VS_DEFAULT = 39210065; defaultVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEFAULT);
shaderModuleLibrary.ReflectAllShaderModules(); static constexpr AssetID FS_DEFAULT = 46377769; defaultFragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(FS_DEFAULT);
static constexpr AssetID CS_COMPOSITE = 45072428; deferredCompositeShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(CS_COMPOSITE);
} }
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
@ -180,16 +180,7 @@ namespace SHADE
gBufferSubpass->AddColorOutput("Albedo"); gBufferSubpass->AddColorOutput("Albedo");
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL); gBufferSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
//// kirsch
//auto kirschShader = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
//gBufferNode->AddNodeCompute(kirschShader, { "Position", "Scene" });
//// copy
//auto pureCopyShader = shaderModuleLibrary.GetShaderModule("PureCopyCs.glsl");
//gBufferNode->AddNodeCompute(pureCopyShader, { "Position", "Scene" });
// deferred composite // deferred composite
auto deferredCompositeShader = shaderModuleLibrary.GetBuiltInShaderModule("DeferredComposite_CS");
gBufferNode->AddNodeCompute(deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "Scene" }); gBufferNode->AddNodeCompute(deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "Scene" });
@ -207,10 +198,7 @@ namespace SHADE
worldRenderer->SetCameraDirector(cameraSystem->CreateDirector()); worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
auto cubeVS = shaderModuleLibrary.GetBuiltInShaderModule("TestCube_VS"); defaultMaterial = AddMaterial(defaultVertShader, defaultFragShader, gBufferSubpass);
auto cubeFS = shaderModuleLibrary.GetBuiltInShaderModule("TestCube_FS");
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferSubpass);
} }
void SHGraphicsSystem::InitMiddleEnd(void) noexcept void SHGraphicsSystem::InitMiddleEnd(void) noexcept
@ -630,10 +618,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 = {};
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -658,10 +650,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
@ -701,6 +697,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();
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -718,8 +715,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"
@ -293,6 +292,10 @@ namespace SHADE
//Handle<SHVkRenderpass> GetRenderPass() const { return renderPass; } //Handle<SHVkRenderpass> GetRenderPass() const { return renderPass; }
/*-----------------------------------------------------------------------------*/
/* Getters */
/*-----------------------------------------------------------------------------*/
SHWindow* GetWindow() noexcept { return window; }
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -320,11 +323,12 @@ namespace SHADE
SHWindow* window = nullptr; SHWindow* window = nullptr;
// Middle End Resources // Middle End Resources
SHResourceHub resourceManager; SHResourceHub resourceManager;
SHMeshLibrary meshLibrary; SHMeshLibrary meshLibrary;
SHTextureLibrary texLibrary; SHTextureLibrary texLibrary;
SHSamplerCache samplerCache; SHSamplerCache samplerCache;
SHMaterialInstanceCache materialInstanceCache; SHMaterialInstanceCache materialInstanceCache;
// Viewports // Viewports
#ifdef SHEDITOR #ifdef SHEDITOR
Handle<SHViewport> editorViewport; Handle<SHViewport> editorViewport;
@ -345,10 +349,13 @@ namespace SHADE
// Temp Cameras // Temp Cameras
Handle<SHCamera> worldCamera; Handle<SHCamera> worldCamera;
Handle<SHCamera> screenCamera; Handle<SHCamera> screenCamera;
SHShaderModuleLibrary shaderModuleLibrary;
// Temp Materials // Built-In Shaders
Handle<SHVkShaderModule> defaultVertShader;
Handle<SHVkShaderModule> defaultFragShader;
Handle<SHVkShaderModule> deferredCompositeShader;
// Built-In Materials
Handle<SHMaterial> defaultMaterial; Handle<SHMaterial> defaultMaterial;
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

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

@ -260,7 +260,7 @@ namespace SHADE
return wndHWND; return wndHWND;
} }
const WindowData SHWindow::GetWindowData() const WindowData SHWindow::GetWindowData() const
{ {
return wndData; return wndData;
} }

View File

@ -123,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);

View File

@ -185,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 ) (metadata(META::tooltip, "Translate")) .property("Translate" ,&SHTransformComponent::GetLocalPosition ,&SHTransformComponent::SetLocalPosition ) (metadata(META::tooltip, "Translate"))
.property("Rotate" ,&SHTransformComponent::GetLocalRotation ,select_overload<void(const SHVec3&)>(&SHTransformComponent::SetLocalRotation) ) (metadata(META::tooltip, "Rotate"), metadata(META::angleInRad, true)) .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 ) (metadata(META::tooltip, "Scale")); .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

@ -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 auto& ANGULAR_CONSTRAINTS = rp3dBody->getAngularLockAxisFactor();
return SHMath::CompareFloat(ANGULAR_CONSTRAINTS.z, 0.0f);
} }
const SHVec3& SHRigidBodyComponent::GetForce() const noexcept SHVec3 SHRigidBodyComponent::GetForce() const noexcept
{ {
return force; if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
}
return rp3dBody->getForce();
} }
const SHVec3& SHRigidBodyComponent::GetTorque() const noexcept SHVec3 SHRigidBodyComponent::GetTorque() const noexcept
{ {
return torque; if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return SHVec3::Zero;
}
return rp3dBody->getTorque();
} }
const SHVec3& SHRigidBodyComponent::GetLinearVelocity() const noexcept SHVec3 SHRigidBodyComponent::GetLinearVelocity() const noexcept
{ {
return linearVelocity; if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return SHVec3::Zero;
}
return rp3dBody->getLinearVelocity();
} }
const SHVec3& SHRigidBodyComponent::GetAngularVelocity() const noexcept SHVec3 SHRigidBodyComponent::GetAngularVelocity() const noexcept
{ {
return angularVelocity; 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
@ -283,11 +415,16 @@ namespace SHADE
if (type != Type::DYNAMIC) if (type != Type::DYNAMIC)
{ {
SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID()) SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID())
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;
@ -149,28 +149,13 @@ namespace SHADE
static constexpr size_t NUM_FLAGS = 8; static constexpr size_t NUM_FLAGS = 8;
static constexpr size_t NUM_DIRTY_FLAGS = 16; static constexpr size_t NUM_DIRTY_FLAGS = 16;
Type type; Type type;
bool interpolate;
// 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;
reactphysics3d::RigidBody* rp3dBody; reactphysics3d::RigidBody* rp3dBody;
float mass; SHVec3 position;
float drag; SHQuaternion orientation;
float angularDrag;
SHVec3 force;
SHVec3 linearVelocity;
SHVec3 torque;
SHVec3 angularVelocity;
SHVec3 position;
SHQuaternion orientation;
RTTR_ENABLE() RTTR_ENABLE()
}; };

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.h"
#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()
@ -246,7 +263,10 @@ namespace SHADE
if (physicsObject.rp3dBody == nullptr) if (physicsObject.rp3dBody == nullptr)
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;
} }
} }
}
// Update bodies and colliders if component is dirty // Sync rigid bodies
system->SyncRigidBodyComponents(SHComponentManager::GetDense<SHRigidBodyComponent>());
system->SyncColliderComponents(SHComponentManager::GetDense<SHColliderComponent>()); if (rigidBodyComponent)
{
// Sync active states
const bool COMPONENT_ACTIVE = rigidBodyComponent->isActive;
SyncActiveStates(physicsObject, COMPONENT_ACTIVE);
if (!COMPONENT_ACTIVE)
continue;
}
// Sync colliders
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);
transformComponent->SetWorldPosition(rp3dPos);
transformComponent->SetWorldOrientation(rp3dRot); if (transformComponent != nullptr)
{
transformComponent->SetWorldPosition(rp3dPos);
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 */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -57,13 +61,16 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] double GetFixedDT () const noexcept; [[nodiscard]] double GetFixedDT () const noexcept;
[[nodiscard]] bool IsSleepingEnabled () const noexcept; [[nodiscard]] bool IsSleepingEnabled () const noexcept;
[[nodiscard]] SHVec3 GetWorldGravity () const noexcept; [[nodiscard]] SHVec3 GetWorldGravity () const noexcept;
[[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;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -82,16 +89,14 @@ namespace SHADE
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void Init () override; void Init () override;
void Exit () override; void Exit () override;
//void AddRigidBody (EntityID entityID) noexcept; void AddCollisionShape (EntityID entityID, SHCollider* collider);
//void AddCollider (EntityID entityID) noexcept; void RemoveCollisionShape (EntityID entityID, int index);
//void RemoveRigidBody (EntityID entityID) noexcept;
//void RemoveCollider (EntityID entityID) noexcept;
void AddCollisionShape (EntityID entityID, SHCollider* collider); void onContact (const rp3d::CollisionCallback::CallbackData& callbackData) override;
void RemoveCollisionShape (EntityID entityID, int index); void onTrigger (const rp3d::OverlapCallback::CallbackData& callbackData) override;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* System Routines */ /* System Routines */
@ -156,49 +161,41 @@ namespace SHADE
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
bool worldUpdated; bool worldUpdated;
double interpolationFactor; double interpolationFactor;
double fixedDT; double fixedDT;
rp3d::PhysicsWorld* world;
rp3d::PhysicsCommon factory;
EntityObjectMap map;
rp3d::PhysicsWorld* world;
rp3d::PhysicsCommon factory;
EntityObjectMap map;
CollisionEvents collisionInfo;
CollisionEvents triggerInfo;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHPhysicsObject* EnsurePhysicsObject (EntityID entityID) noexcept;
SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
void DestroyPhysicsObject (EntityID entityID) noexcept;
void SyncActiveStates (SHPhysicsObject* physicsObject, bool componentActive) noexcept; SHPhysicsObject* EnsurePhysicsObject (EntityID entityID) noexcept;
void SyncRigidBodyComponents (std::vector<SHRigidBodyComponent>& denseArray) noexcept; SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
void SyncColliderComponents (std::vector<SHColliderComponent>& denseArray) noexcept; void DestroyPhysicsObject (EntityID entityID) noexcept;
static void SyncActiveStates (SHPhysicsObject& physicsObject, bool componentActive) 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;
}; };
} // namespace SHADE
/*-----------------------------------------------------------------------------------*/ #include "SHPhysicsSystem.hpp"
/* Event Data Definitions */
/*-----------------------------------------------------------------------------------*/
struct SHPhysicsColliderAddedEvent
{
EntityID entityID;
SHCollider::Type colliderType;
int colliderIndex;
};
struct SHPhysicsColliderRemovedEvent
{
EntityID entityID;
int colliderIndex;
};
} // namespace SHADE

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

@ -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.");
gfxSystem->BuildMeshBuffers();
gfxSystem->BuildTextures(); if (meshChanged)
{
gfxSystem->BuildMeshBuffers();
meshChanged = false;
}
if (textureChanged)
{
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

@ -3,7 +3,7 @@
\author Tng Kah Wei, kahwei.tng, 390009620 \author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu \par email: kahwei.tng\@digipen.edu
\date Oct 21, 2022 \date Oct 21, 2022
\brief Contains the definition of the function templates of the \brief Contains the definition of the function templates of the
SHResourceManager static class. SHResourceManager static class.
Copyright (C) 2022 DigiPen Institute of Technology. Copyright (C) 2022 DigiPen Institute of Technology.
@ -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);
if (assetData == nullptr)
{ {
// Get system SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID.");
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>(); return {};
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)
{
SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID.");
return {};
}
loadedAssetData.emplace_back(assetId);
Handle<SHMesh> meshHandle = gfxSystem->AddMesh
(
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);
typedAssetIdMap.get().emplace(genericHandle, assetId);
return meshHandle;
} }
// 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 auto handle = load<ResourceType>(assetId, *assetData);
const SHTextureAsset* assetData = SHAssetManager::GetData<SHTextureAsset>(assetId); Handle genericHandle = Handle(handle);
if (assetData == nullptr) typedHandleMap.get().emplace(assetId, genericHandle);
{ typedAssetIdMap.get().emplace(genericHandle, assetId);
SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID."); return handle;
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>
@ -152,7 +109,7 @@ namespace SHADE
template<typename ResourceType> template<typename ResourceType>
std::pair<SHResourceManager::AssetHandleMapRef, SHResourceManager::HandleAssetMapRef> SHResourceManager::getAssetHandleMap() std::pair<SHResourceManager::AssetHandleMapRef, SHResourceManager::HandleAssetMapRef> SHResourceManager::getAssetHandleMap()
{ {
const std::type_index TYPE = typeid(ResourceType); const std::type_index TYPE = typeid(ResourceType);
if (!handlesMap.contains(TYPE)) if (!handlesMap.contains(TYPE))
{ {
@ -160,7 +117,7 @@ namespace SHADE
assetIdMap.emplace(TYPE, HandleAssetMap{}); assetIdMap.emplace(TYPE, HandleAssetMap{});
typedFreeFuncMap.emplace typedFreeFuncMap.emplace
( (
TYPE, TYPE,
[TYPE](AssetID assetId) [TYPE](AssetID assetId)
{ {
static_cast<Handle<ResourceType>>(SHResourceManager::handlesMap[TYPE][assetId]).Free(); static_cast<Handle<ResourceType>>(SHResourceManager::handlesMap[TYPE][assetId]).Free();
@ -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,

View File

@ -98,6 +98,11 @@ namespace SHADE
/// </summary> /// </summary>
void ExecuteFixedUpdates(); void ExecuteFixedUpdates();
/// <summary> /// <summary>
/// Executes the OnCollision*()s and OnTrigger*()s of the Scripts that are attached
/// to Entities.
/// </summary>
void ExecuteCollisionFunctions();
/// <summary>
/// Shuts down the DotNetRuntime. /// Shuts down the DotNetRuntime.
/// </summary> /// </summary>
void Exit() override; void Exit() override;
@ -245,6 +250,7 @@ namespace SHADE
CsFuncPtr csScriptsExecuteFixedUpdate = nullptr; CsFuncPtr csScriptsExecuteFixedUpdate = nullptr;
CsFuncPtr csScriptsExecuteUpdate = nullptr; CsFuncPtr csScriptsExecuteUpdate = nullptr;
CsFuncPtr csScriptsExecuteLateUpdate = nullptr; CsFuncPtr csScriptsExecuteLateUpdate = nullptr;
CsFuncPtr csScriptsExecutePhysicsEvents = nullptr;
CsFuncPtr csScriptsFrameCleanUp = nullptr; CsFuncPtr csScriptsFrameCleanUp = nullptr;
CsScriptManipFuncPtr csScriptsAdd = nullptr; CsScriptManipFuncPtr csScriptsAdd = nullptr;
CsScriptBasicFuncPtr csScriptsRemoveAll = nullptr; CsScriptBasicFuncPtr csScriptsRemoveAll = nullptr;

View File

@ -54,7 +54,7 @@ namespace SHADE
/* System Routine Functions - FrameCleanUpRoutine */ /* System Routine Functions - FrameCleanUpRoutine */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHScriptEngine::FrameCleanUpRoutine::FrameCleanUpRoutine() SHScriptEngine::FrameCleanUpRoutine::FrameCleanUpRoutine()
: SHSystemRoutine("Script Engine Frame Clean Up", false) : SHSystemRoutine("Script Engine Frame Clean Up", true)
{} {}
void SHScriptEngine::FrameCleanUpRoutine::Execute(double) noexcept void SHScriptEngine::FrameCleanUpRoutine::Execute(double) noexcept
{ {

View File

@ -12,8 +12,11 @@
#include "Resource/SHResourceManager.h" #include "Resource/SHResourceManager.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Graphics/MiddleEnd/Interface/SHMaterial.h" #include "Graphics/MiddleEnd/Interface/SHMaterial.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "SHSerializationTools.h" #include "SHSerializationTools.h"
#include "Physics/Components/SHColliderComponent.h" #include "Physics/Components/SHColliderComponent.h"
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
#include "Tools/SHLog.h"
namespace YAML namespace YAML
{ {
@ -303,104 +306,45 @@ namespace YAML
// Write Material // Write Material
YAML::Node node; YAML::Node node;
node[VERT_SHADER_YAML_TAG.data()] = 0; // SHResourceManager::GetAssetID<SHVkShaderModule>(vertexShader).value_or(0); node[VERT_SHADER_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHVkShaderModule>(vertexShader).value_or(0);
node[FRAG_SHADER_YAML_TAG.data()] = 0; // SHResourceManager::GetAssetID<SHVkShaderModule>(fragShader).value_or(0); node[FRAG_SHADER_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHVkShaderModule>(fragShader).value_or(0);
node[SUBPASS_YAML_TAG.data()] = rhs.GetPipeline()->GetPipelineState().GetSubpass()->GetName(); node[SUBPASS_YAML_TAG.data()] = rhs.GetPipeline()->GetPipelineState().GetSubpass()->GetName();
node[PROPS_YAML_TAG.data()] = propertiesNode; node[PROPS_YAML_TAG.data()] = propertiesNode;
return node; return node;
} }
static bool decode(YAML::Node const& node, SHMaterial& rhs) };
{
/*
// Retrieve Shader Asset IDs
AssetID vertShaderId = 0;
AssetID fragShaderId = 0;
if (node[VERT_SHADER_YAML_TAG.data()])
vertShaderId = node[VERT_SHADER_YAML_TAG.data()].as<AssetID>();
if (node[FRAG_SHADER_YAML_TAG.data()])
fragShaderId = node[FRAG_SHADER_YAML_TAG.data()].as<AssetID>();
// Ensure that both shaders are present template<>
if (vertShaderId == 0 || fragShaderId == 0) struct convert<SHMaterialSpec>
return false; // No pipeline {
static constexpr std::string_view VERT_SHADER_YAML_TAG = "VertexShader";
static constexpr std::string_view FRAG_SHADER_YAML_TAG = "FragmentShader";
static constexpr std::string_view SUBPASS_YAML_TAG = "SubPass";
static constexpr std::string_view PROPS_YAML_TAG = "Properties";
// Get Shader Modules static bool decode(YAML::Node const& node, SHMaterialSpec& rhs)
Handle<SHVkShaderModule> vertexShader, fragShader; {
vertexShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(vertShaderId); // Retrieve Shader Asset IDs
fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(fragShaderId); if (!node[VERT_SHADER_YAML_TAG.data()])
return false;
rhs.vertexShader = node[VERT_SHADER_YAML_TAG.data()].as<AssetID>();
if (!node[FRAG_SHADER_YAML_TAG.data()])
return false;
rhs.fragShader = node[FRAG_SHADER_YAML_TAG.data()].as<AssetID>();
// Get Pipeline Library // Retrieve Subpass
if (node[SUBPASS_YAML_TAG.data()]) if (!node[SUBPASS_YAML_TAG.data()])
{ return false;
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>(); rhs.subpassName = node[SUBPASS_YAML_TAG.data()].as<std::string>();
if (!gfxSystem)
return false;
// Grab subpass from worldRenderer // Retrieve
auto renderPass = gfxSystem->GetPrimaryRenderpass(); if (!node[PROPS_YAML_TAG.data()])
if (!renderPass) return false;
return false; rhs.properties = node[PROPS_YAML_TAG.data()];
auto subPass = renderPass->GetSubpass(node[SUBPASS_YAML_TAG.data()].as<std::string>());
if (!subPass)
return false;
// Set Pipeline return true;
rhs.SetPipeline(renderPass->GetOrCreatePipeline }
(
std::make_pair(vertexShader, fragShader),
subPass
));
}
*/
// TODO: Load Proper Material!
// Set default material
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (!gfxSystem)
return false;
rhs.SetPipeline(gfxSystem->GetDefaultMaterial()->GetPipeline());
if (node[PROPS_YAML_TAG.data()].IsDefined())
{
// Loop through all properties
Handle<SHShaderBlockInterface> pipelineProperties = rhs.GetShaderBlockInterface();
const YAML::Node& PROPS_NODE = node[PROPS_YAML_TAG.data()];
for (int i = 0; i < static_cast<int>(pipelineProperties->GetVariableCount()); ++i)
{
const std::string& PROP_NAME = pipelineProperties->GetVariableName(i);
const auto& PROP_NODE = PROPS_NODE[PROP_NAME.data()];
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:
rhs.SetProperty(VARIABLE->offset, PROP_NODE.as<float>());
break;
case SHADE::SHShaderBlockInterface::Variable::Type::INT:
rhs.SetProperty(VARIABLE->offset, PROP_NODE.as<int>());
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2:
rhs.SetProperty(VARIABLE->offset, SHSerializationTools::YAMLToVec2(PROP_NODE));
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR3:
rhs.SetProperty(VARIABLE->offset, SHSerializationTools::YAMLToVec3(PROP_NODE));
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR4:
rhs.SetProperty(VARIABLE->offset, SHSerializationTools::YAMLToVec4(PROP_NODE));
break;
case SHADE::SHShaderBlockInterface::Variable::Type::OTHER:
default:
continue;
break;
}
}
}
}
return true;
}
}; };
template<> template<>
@ -413,7 +357,7 @@ namespace YAML
{ {
YAML::Node node; YAML::Node node;
node[MESH_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHMesh>(rhs.GetMesh()).value_or(0); node[MESH_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHMesh>(rhs.GetMesh()).value_or(0);
node[MAT_YAML_TAG.data()] = 0; // TODO: Asset ID node[MAT_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHMaterial>(rhs.GetMaterial()->GetBaseMaterial()).value_or(0);
return node; return node;
} }
static bool decode(YAML::Node const& node, SHRenderable& rhs) static bool decode(YAML::Node const& node, SHRenderable& rhs)
@ -424,12 +368,17 @@ namespace YAML
} }
if (node[MAT_YAML_TAG.data()].IsDefined()) if (node[MAT_YAML_TAG.data()].IsDefined())
{ {
// TODO: Convert Asset ID To Material HAndle
// Temporarily, use default material // Temporarily, use default material
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>(); auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (!gfxSystem) if (!gfxSystem)
return false; return false;
rhs.SetMaterial(gfxSystem->AddOrGetBaseMaterialInstance(gfxSystem->GetDefaultMaterial())); Handle<SHMaterial> baseMat = SHResourceManager::LoadOrGet<SHMaterial>(node[MAT_YAML_TAG.data()].as<AssetID>());
if (!baseMat)
{
baseMat = gfxSystem->GetDefaultMaterial();
SHLog::Warning("[SHSerializationHelper] Unable to load specified material. Falling back to default material.");
}
rhs.SetMaterial(gfxSystem->AddOrGetBaseMaterialInstance(baseMat));
} }
return true; return true;
} }

View File

@ -9,7 +9,7 @@ Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited. of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/ *//*************************************************************************************/
#pragma once
// Standard Library // Standard Library
#include <string> #include <string>
// Project Headers // Project Headers

View File

@ -25,11 +25,16 @@ project "SHADE_Managed"
includedirs includedirs
{ {
"%{prj.location}/src", "%{prj.location}/src",
}
externalincludedirs
{
"%{IncludeDir.spdlog}/include", "%{IncludeDir.spdlog}/include",
"%{IncludeDir.imgui}", "%{IncludeDir.imgui}",
"%{IncludeDir.imguizmo}", "%{IncludeDir.imguizmo}",
"%{IncludeDir.imnodes}", "%{IncludeDir.imnodes}",
"%{IncludeDir.yamlcpp}", "%{IncludeDir.yamlcpp}",
"%{IncludeDir.SDL}\\include",
"%{IncludeDir.RTTR}/include", "%{IncludeDir.RTTR}/include",
"%{IncludeDir.dotnet}\\include", "%{IncludeDir.dotnet}\\include",
"%{IncludeDir.reactphysics3d}\\include", "%{IncludeDir.reactphysics3d}\\include",
@ -38,13 +43,16 @@ project "SHADE_Managed"
libdirs libdirs
{ {
"%{IncludeDir.RTTR}/lib" "%{IncludeDir.RTTR}/lib",
"%{IncludeDir.SDL}/lib"
} }
links links
{ {
"yaml-cpp", "yaml-cpp",
"imgui", "imgui",
"SDL2.lib",
"SDL2main.lib",
"SHADE_Engine", "SHADE_Engine",
"SHADE_CSharp" "SHADE_CSharp"
} }

View File

@ -0,0 +1,127 @@
#include "SHpch.h"
#include "Camera.hxx"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Camera/SHCameraSystem.h"
namespace SHADE
{
Camera::Camera(Entity entity)
:Component(entity)
{
}
float Camera::Pitch::get()
{
return (GetNativeComponent()->GetPitch());
}
void Camera::Pitch::set(float val)
{
GetNativeComponent()->SetPitch(val);
}
float Camera::Yaw::get()
{
return (GetNativeComponent()->GetYaw());
}
void Camera::Yaw::set(float val)
{
GetNativeComponent()->SetYaw(val);
}
float Camera::Roll::get()
{
return (GetNativeComponent()->GetRoll());
}
void Camera::Roll::set(float val)
{
GetNativeComponent()->SetRoll(val);
}
float Camera::Width::get()
{
return (GetNativeComponent()->GetWidth());
}
void Camera::Width::set(float val)
{
GetNativeComponent()->SetWidth(val);
}
float Camera::Height::get()
{
return (GetNativeComponent()->GetHeight());
}
void Camera::Height::set(float val)
{
GetNativeComponent()->SetHeight(val);
}
float Camera::Near::get()
{
return (GetNativeComponent()->GetNear());
}
void Camera::Near::set(float val)
{
GetNativeComponent()->SetNear(val);
}
float Camera::Far::get()
{
return (GetNativeComponent()->GetFar());
}
void Camera::Far::set(float val)
{
GetNativeComponent()->SetFar(val);
}
float Camera::FOV::get()
{
return (GetNativeComponent()->GetFOV());
}
void Camera::FOV::set(float val)
{
GetNativeComponent()->SetFOV(val);
}
Vector3 Camera::Position::get()
{
return Convert::ToCLI(GetNativeComponent()->GetPosition());
}
void Camera::Position::set(Vector3 val)
{
GetNativeComponent()->SetPosition(Convert::ToNative(val));
}
void Camera::SetMainCamera(size_t directorIndex)
{
auto system = SHSystemManager::GetSystem<SHCameraSystem>();
system->SetMainCamera(GetNativeComponent()->GetEID(), directorIndex);
}
void Camera::SetMainCamera()
{
SetMainCamera(0);
}
void Camera::LookAt(Vector3 targetPosition)
{
auto system = SHSystemManager::GetSystem<SHCameraSystem>();
system->CameraLookAt(*GetNativeComponent(), Convert::ToNative(targetPosition));
}
Vector3 Camera::GetForward()
{
auto system = SHSystemManager::GetSystem<SHCameraSystem>();
SHVec3 forward, up, right;
system->GetCameraAxis(*GetNativeComponent(), forward, right, up);
return Convert::ToCLI(forward);
}
}

View File

@ -0,0 +1,70 @@
#pragma once
// Project Includes
#include "Components/Component.hxx"
#include "Math/Vector3.hxx"
#include "Math/Quaternion.hxx"
// External Dependencies
#include "Camera/SHCameraComponent.h"
namespace SHADE
{
public ref class Camera : public Component<SHCameraComponent>
{
internal:
Camera(Entity entity);
public:
property float Pitch
{
float get();
void set(float val);
}
property float Yaw
{
float get();
void set(float val);
}
property float Roll
{
float get();
void set(float val);
}
property float Width
{
float get();
void set(float val);
}
property float Height
{
float get();
void set(float val);
}
property float Near
{
float get();
void set(float val);
}
property float Far
{
float get();
void set(float val);
}
property float FOV
{
float get();
void set(float val);
}
property Vector3 Position
{
Vector3 get();
void set(Vector3 val);
}
void SetMainCamera(size_t directorIndex);
void SetMainCamera();
void LookAt(Vector3 targetPosition);
Vector3 GetForward();
};
}

View File

@ -0,0 +1,51 @@
#include "SHpch.h"
#include "CameraArm.hxx"
namespace SHADE
{
CameraArm::CameraArm(Entity entity)
:Component(entity)
{
}
float CameraArm::Pitch::get()
{
return (GetNativeComponent()->GetPitch());
}
void CameraArm::Pitch::set(float val)
{
GetNativeComponent()->SetPitch(val);
}
float CameraArm::Yaw::get()
{
return (GetNativeComponent()->GetYaw());
}
void CameraArm::Yaw::set(float val)
{
GetNativeComponent()->SetYaw(val);
}
float CameraArm::ArmLength::get()
{
return (GetNativeComponent()->GetArmLength());
}
void CameraArm::ArmLength::set(float val)
{
GetNativeComponent()->SetArmLength(val);
}
bool CameraArm::LookAtCameraOrigin::get()
{
return GetNativeComponent()->lookAtCameraOrigin;
}
void CameraArm::LookAtCameraOrigin::set(bool val)
{
GetNativeComponent()->lookAtCameraOrigin = val;
}
}

View File

@ -0,0 +1,40 @@
#pragma once
// Project Includes
#include "Components/Component.hxx"
#include "Math/Vector3.hxx"
// External Dependencies
#include "Camera/SHCameraArmComponent.h"
namespace SHADE
{
public ref class CameraArm : public Component<SHCameraArmComponent>
{
internal:
CameraArm(Entity entity);
public:
property float Pitch
{
float get();
void set(float val);
}
property float Yaw
{
float get();
void set(float val);
}
property float ArmLength
{
float get();
void set(float val);
}
property bool LookAtCameraOrigin
{
bool get();
void set(bool val);
}
};
}

View File

@ -67,6 +67,11 @@ namespace SHADE
ScriptStore::RemoveScript<T>(owner.GetEntity()); ScriptStore::RemoveScript<T>(owner.GetEntity());
} }
BaseComponent::operator bool(BaseComponent^ c)
{
return c != nullptr;
}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constructors */ /* Constructors */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -101,6 +101,15 @@ namespace SHADE
generic<typename T> where T : ref class, Script generic<typename T> where T : ref class, Script
void RemoveScript(); void RemoveScript();
/*-----------------------------------------------------------------------------*/
/* Operator Overloads */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Implicit conversion operator to enable checking if a component is null.
/// </summary>
/// <param name="c">Component to check.</param>
static operator bool(BaseComponent^ c);
protected: protected:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Constructors */ /* Constructors */

View File

@ -260,7 +260,7 @@ namespace SHADE
int val = safe_cast<int>(field->GetValue(object)); int val = safe_cast<int>(field->GetValue(object));
int oldVal = val; int oldVal = val;
if (SHEditorUI::InputEnumCombo(Convert::ToNative(field->Name), val, nativeEnumNames)) if (SHEditorUI::InputEnumCombo(Convert::ToNative(field->Name), val, nativeEnumNames, &isHovered))
{ {
field->SetValue(object, val); field->SetValue(object, val);
registerUndoAction(object, field, val, oldVal); registerUndoAction(object, field, val, oldVal);
@ -280,12 +280,23 @@ namespace SHADE
// Actual Field // Actual Field
std::string val = Convert::ToNative(stringVal); std::string val = Convert::ToNative(stringVal);
std::string oldVal = val; std::string oldVal = val;
if (SHEditorUI::InputTextField(Convert::ToNative(field->Name), val)) if (SHEditorUI::InputTextField(Convert::ToNative(field->Name), val, &isHovered))
{ {
field->SetValue(object, Convert::ToCLI(val)); field->SetValue(object, Convert::ToCLI(val));
registerUndoAction(object, field, Convert::ToCLI(val), Convert::ToCLI(oldVal)); registerUndoAction(object, field, Convert::ToCLI(val), Convert::ToCLI(oldVal));
} }
} }
else if (field->FieldType == GameObject::typeid)
{
GameObject gameObj = safe_cast<GameObject>(field->GetValue(object));
uint32_t entityId = gameObj.GetEntity();
if (SHEditorUI::InputGameObjectField(Convert::ToNative(field->Name), entityId, &isHovered))
{
GameObject newVal = GameObject(entityId);
field->SetValue(object, newVal);
registerUndoAction(object, field, newVal, gameObj);
}
}
else else
{ {
array<System::Type^>^ interfaces = field->FieldType->GetInterfaces(); array<System::Type^>^ interfaces = field->FieldType->GetInterfaces();

View File

@ -0,0 +1,71 @@
/************************************************************************************//*!
\file Application.cxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 31, 2022
\brief Contains the definitions of the functions in the static managed
Application class.
Note: This file is written in C++17/CLI.
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 "Application.hxx"
// External Dependencies
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/SHEditor.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystemInterface.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Properties */
/*---------------------------------------------------------------------------------*/
bool Application::IsPlaying::get()
{
auto editor = SHSystemManager::GetSystem<SHEditor>();
if (editor)
return editor->editorState == SHEditor::State::PLAY
||
editor->editorState == SHEditor::State::PAUSE;
return true;
}
bool Application::IsPaused::get()
{
auto editor = SHSystemManager::GetSystem<SHEditor>();
if (editor)
return editor->editorState == SHEditor::State::PAUSE;
return false;
}
int Application::WindowWidth::get()
{
return SHGraphicsSystemInterface::GetWindowWidth();
}
int Application::WindowHeight::get()
{
return SHGraphicsSystemInterface::GetWindowWidth();
}
bool Application::IsFullscreen::get()
{
return SHGraphicsSystemInterface::IsFullscreen();
}
/*void Application::IsFullscreen::set(bool value)
{
return SHGraphicsSystemInterface::SetFullscreen(value);
}*/
/*---------------------------------------------------------------------------------*/
/* Usage Functions */
/*---------------------------------------------------------------------------------*/
void Application::Quit()
{
SHGraphicsSystemInterface::CloseWindow();
}
}

View File

@ -0,0 +1,77 @@
/************************************************************************************//*!
\file Application.hxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 31, 2022
\brief Contains the definitions of a managed static Application class.
Note: This file is written in C++17/CLI.
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 contains useful properties for querying the state of the
/// engine.
/// </summary>
public ref class Application abstract sealed
{
public:
/*-----------------------------------------------------------------------------*/
/* Properties */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Whether or not the engine is playing. This will always be true on Publish.
/// On Debug/Release builds, this is true when the editor is in Play Mode. It
/// will also be true even if the editor is in Play Mode but is paused.
/// </summary>
static property bool IsPlaying
{
bool get();
}
/// <summary>
/// Whether or not the engine is in a paused state where script updates and
/// physics are not in play.
/// </summary>
static property bool IsPaused
{
bool get();
}
/// <summary>
/// Retrieves the designated width of the current window.
/// </summary>
static property int WindowWidth
{
int get();
}
/// <summary>
/// Retrieves the designated height of the current window.
/// </summary>
static property int WindowHeight
{
int get();
}
/// <summary>
/// Whether or not the application is currently in fullscreen mode or not.
/// </summary>
static property bool IsFullscreen
{
bool get();
// TODO: once implemented on SHADE_Engine
//void set(bool value);
}
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Marks the application to stop at the end of the current frame.
/// </summary>
static void Quit();
};
}

View File

@ -33,6 +33,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Components/Transform.hxx" #include "Components/Transform.hxx"
#include "Components\RigidBody.hxx" #include "Components\RigidBody.hxx"
#include "Components\Collider.hxx" #include "Components\Collider.hxx"
#include "Components/Camera.hxx"
#include "Components/CameraArm.hxx"
namespace SHADE namespace SHADE
{ {
@ -248,6 +250,8 @@ namespace SHADE
componentMap.Add(createComponentSet<SHTransformComponent, Transform>()); componentMap.Add(createComponentSet<SHTransformComponent, Transform>());
componentMap.Add(createComponentSet<SHColliderComponent, Collider>()); componentMap.Add(createComponentSet<SHColliderComponent, Collider>());
componentMap.Add(createComponentSet<SHRigidBodyComponent, RigidBody>()); componentMap.Add(createComponentSet<SHRigidBodyComponent, RigidBody>());
componentMap.Add(createComponentSet<SHCameraComponent, Camera>());
componentMap.Add(createComponentSet<SHCameraArmComponent, CameraArm>());
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -20,7 +20,9 @@ of DigiPen Institute of Technology is prohibited.
#include "Scene/SHSceneGraph.h" #include "Scene/SHSceneGraph.h"
// Project Headers // Project Headers
#include "ECS.hxx" #include "ECS.hxx"
#include "Utility/Convert.hxx"
#include "Scripts/ScriptStore.hxx" #include "Scripts/ScriptStore.hxx"
#include "Utility/Debug.hxx"
namespace SHADE namespace SHADE
{ {
@ -40,7 +42,13 @@ namespace SHADE
System::Nullable<GameObject> GameObject::Find(System::String ^ name) System::Nullable<GameObject> GameObject::Find(System::String ^ name)
{ {
// Search the GameObjectLibrary for an Entity with the specified name // Search the GameObjectLibrary for an Entity with the specified name
throw gcnew System::NotImplementedException(); const auto ENTITY_ID = SHEntityManager::GetEntityByName(Convert::ToNative(name));
if (ENTITY_ID == MAX_EID)
{
return {};
}
return GameObject(ENTITY_ID);
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -57,7 +65,17 @@ namespace SHADE
} }
bool GameObject::IsActiveInHierarchy::get() bool GameObject::IsActiveInHierarchy::get()
{ {
return true; // TODO: Update once we have an equivalent on the Entity object auto node = SHSceneManager::GetCurrentSceneGraph().GetNode(GetEntity());
if (!node)
{
Debug::LogWarning("Attempting to access a GameObject's ActiveInHierarchy state which does not exist. Assuming inactive.");
return false;
}
return node->IsActive();
}
Entity GameObject::EntityId::get()
{
return entity;
} }
GameObject^ GameObject::Parent::get() GameObject^ GameObject::Parent::get()
{ {

View File

@ -86,6 +86,13 @@ namespace SHADE
{ {
bool get(); bool get();
} }
/// <summary>
/// Native Entity ID value for this GameObject.
/// </summary>
property Entity EntityId
{
Entity get();
}
property GameObject^ Parent property GameObject^ Parent
{ {
GameObject^ get(); GameObject^ get();

View File

@ -14,6 +14,9 @@ of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/ *//*************************************************************************************/
// Precompiled Headers // Precompiled Headers
#include "SHpch.h" #include "SHpch.h"
// External Dependencies
#include "FRC/SHFramerateController.h"
#include "Physics/SHPhysicsSystemInterface.h"
// Primary Header // Primary Header
#include "Time.hxx" #include "Time.hxx"
@ -26,4 +29,14 @@ namespace SHADE
{ {
return SHFrameRateController::GetRawDeltaTime(); return SHFrameRateController::GetRawDeltaTime();
} }
float Time::DeltaTimeF::get()
{
return static_cast<float>(SHFrameRateController::GetRawDeltaTime());
}
double Time::FixedDeltaTime::get()
{
return SHPhysicsSystemInterface::GetFixedDT();
}
} }

View File

@ -14,8 +14,6 @@ of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/ *//*************************************************************************************/
#pragma once #pragma once
#include "FRC/SHFramerateController.h"
namespace SHADE namespace SHADE
{ {
/// <summary> /// <summary>
@ -29,13 +27,28 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/// <summary> /// <summary>
/// Time taken to process the previous frame. /// Time taken to process the previous frame.
/// Note, is affected by TimeScale. Use UnscaledDeltaTime if you wish to retrieve
/// real world time. This is also affected by MaxDeltaTime clamping that
/// UnscaledDeltaTime is subject to.
/// </summary> /// </summary>
static property double DeltaTime static property double DeltaTime
{ {
double get(); double get();
} }
/*-----------------------------------------------------------------------------*/
/* Properties */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Time taken to process the previous frame.
/// </summary>
static property float DeltaTimeF
{
float get();
}
/// <summary>
/// Time taken for Physics simulations. You should use this for operations
/// within Script.FixedUpdate()
/// </summary>
static property double FixedDeltaTime
{
double get();
}
}; };
} }

View File

@ -99,4 +99,11 @@ namespace SHADE
return SHInputManager::GetKeyReleasedTime(static_cast<SHInputManager::SH_KEYCODE>(key)); return SHInputManager::GetKeyReleasedTime(static_cast<SHInputManager::SH_KEYCODE>(key));
} }
Vector2 Input::GetMouseVelocity()
{
double velX, velY;
SHInputManager::GetMouseVelocity(&velX, &velY);
return Convert::ToCLI(SHVec2{ (float)velX,(float)velY });
}
} }

View File

@ -31,10 +31,159 @@ namespace SHADE
/// <summary> /// <summary>
/// Represents the available supported keycodes that can be passed into the /// Represents the available supported keycodes that can be passed into the
/// key-based Input functions. /// key-based Input functions.
///
/// Attempting to follow https://docs.unity3d.com/ScriptReference/KeyCode.html
/// Win32 keycodes are shift-insensitive, i.e. 'A' and 'a' are the same keycode and '1' and '!' are the same keycode
/// </summary> /// </summary>
enum class KeyCode : int enum class KeyCode : int
{ {
Backspace = static_cast<int>(SHInputManager::SH_KEYCODE::BACKSPACE),
Delete = static_cast<int>(SHInputManager::SH_KEYCODE::DEL),
Tab = static_cast<int>(SHInputManager::SH_KEYCODE::TAB),
Clear = static_cast<int>(SHInputManager::SH_KEYCODE::CLEAR),
Return = static_cast<int>(SHInputManager::SH_KEYCODE::ENTER),
Pause = static_cast<int>(SHInputManager::SH_KEYCODE::PAUSE),
Escape = static_cast<int>(SHInputManager::SH_KEYCODE::ESCAPE),
Space = static_cast<int>(SHInputManager::SH_KEYCODE::SPACE), Space = static_cast<int>(SHInputManager::SH_KEYCODE::SPACE),
Keypad0 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_0),
Keypad1 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_1),
Keypad2 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_2),
Keypad3 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_3),
Keypad4 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_4),
Keypad5 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_5),
Keypad6 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_6),
Keypad7 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_7),
Keypad8 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_8),
Keypad9 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_9),
KeypadPeriod = static_cast<int>(SHInputManager::SH_KEYCODE::DECIMAL),
KeypadDivide = static_cast<int>(SHInputManager::SH_KEYCODE::DIVIDE),
KeypadMultiply = static_cast<int>(SHInputManager::SH_KEYCODE::MULTIPLY),
KeypadMinus = static_cast<int>(SHInputManager::SH_KEYCODE::SUBTRACT),
KeypadPlus = static_cast<int>(SHInputManager::SH_KEYCODE::ADD),
KeypadEnter = static_cast<int>(SHInputManager::SH_KEYCODE::ENTER),
//KeypadEquals
UpArrow = static_cast<int>(SHInputManager::SH_KEYCODE::UP_ARROW),
DownArrow = static_cast<int>(SHInputManager::SH_KEYCODE::DOWN_ARROW),
RightArrow = static_cast<int>(SHInputManager::SH_KEYCODE::RIGHT_ARROW),
LeftArrow = static_cast<int>(SHInputManager::SH_KEYCODE::LEFT_ARROW),
Insert = static_cast<int>(SHInputManager::SH_KEYCODE::INSERT),
Home = static_cast<int>(SHInputManager::SH_KEYCODE::HOME),
End = static_cast<int>(SHInputManager::SH_KEYCODE::END),
PageUp = static_cast<int>(SHInputManager::SH_KEYCODE::PAGE_UP),
PageDown = static_cast<int>(SHInputManager::SH_KEYCODE::PAGE_DOWN),
F1 = static_cast<int>(SHInputManager::SH_KEYCODE::F1),
F2 = static_cast<int>(SHInputManager::SH_KEYCODE::F2),
F3 = static_cast<int>(SHInputManager::SH_KEYCODE::F3),
F4 = static_cast<int>(SHInputManager::SH_KEYCODE::F4),
F5 = static_cast<int>(SHInputManager::SH_KEYCODE::F5),
F6 = static_cast<int>(SHInputManager::SH_KEYCODE::F6),
F7 = static_cast<int>(SHInputManager::SH_KEYCODE::F7),
F8 = static_cast<int>(SHInputManager::SH_KEYCODE::F8),
F9 = static_cast<int>(SHInputManager::SH_KEYCODE::F9),
F10 = static_cast<int>(SHInputManager::SH_KEYCODE::F10),
F11 = static_cast<int>(SHInputManager::SH_KEYCODE::F11),
F12 = static_cast<int>(SHInputManager::SH_KEYCODE::F12),
F13 = static_cast<int>(SHInputManager::SH_KEYCODE::F13),
F14 = static_cast<int>(SHInputManager::SH_KEYCODE::F14),
F15 = static_cast<int>(SHInputManager::SH_KEYCODE::F15),
F16 = static_cast<int>(SHInputManager::SH_KEYCODE::F16),
F17 = static_cast<int>(SHInputManager::SH_KEYCODE::F17),
F18 = static_cast<int>(SHInputManager::SH_KEYCODE::F18),
F19 = static_cast<int>(SHInputManager::SH_KEYCODE::F19),
F20 = static_cast<int>(SHInputManager::SH_KEYCODE::F20),
F21 = static_cast<int>(SHInputManager::SH_KEYCODE::F21),
F22 = static_cast<int>(SHInputManager::SH_KEYCODE::F22),
F23 = static_cast<int>(SHInputManager::SH_KEYCODE::F23),
F24 = static_cast<int>(SHInputManager::SH_KEYCODE::F24),
Alpha0 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_0),
Alpha1 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_1),
Alpha2 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_2),
Alpha3 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_3),
Alpha4 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_4),
Alpha5 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_5),
Alpha6 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_6),
Alpha7 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_7),
Alpha8 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_8),
Alpha9 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_9),
//Exclaim
//DoubleQuote
//Hash
//Dollar
//Percent
//Ampersand
Quote = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_7),
//LeftParen
//RightParen
//Asterisk
//Plus
Comma = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_COMMA),
Minus = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_MINUS),
Period = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_PERIOD),
Slash = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_2),
//Colon
Semicolon = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_1),
//Less
Equals = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_PLUS),
//Greater
//Question
//At
LeftBracket = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_4),
Backslash = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_5),
RightBracket = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_6),
//Caret
//Underscore
BackQuote = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_3),
A = static_cast<int>(SHInputManager::SH_KEYCODE::A),
B = static_cast<int>(SHInputManager::SH_KEYCODE::B),
C = static_cast<int>(SHInputManager::SH_KEYCODE::C),
D = static_cast<int>(SHInputManager::SH_KEYCODE::D),
E = static_cast<int>(SHInputManager::SH_KEYCODE::E),
F = static_cast<int>(SHInputManager::SH_KEYCODE::F),
G = static_cast<int>(SHInputManager::SH_KEYCODE::G),
H = static_cast<int>(SHInputManager::SH_KEYCODE::H),
I = static_cast<int>(SHInputManager::SH_KEYCODE::I),
J = static_cast<int>(SHInputManager::SH_KEYCODE::J),
K = static_cast<int>(SHInputManager::SH_KEYCODE::K),
L = static_cast<int>(SHInputManager::SH_KEYCODE::L),
M = static_cast<int>(SHInputManager::SH_KEYCODE::M),
N = static_cast<int>(SHInputManager::SH_KEYCODE::N),
O = static_cast<int>(SHInputManager::SH_KEYCODE::O),
P = static_cast<int>(SHInputManager::SH_KEYCODE::P),
Q = static_cast<int>(SHInputManager::SH_KEYCODE::Q),
R = static_cast<int>(SHInputManager::SH_KEYCODE::R),
S = static_cast<int>(SHInputManager::SH_KEYCODE::S),
T = static_cast<int>(SHInputManager::SH_KEYCODE::T),
U = static_cast<int>(SHInputManager::SH_KEYCODE::U),
V = static_cast<int>(SHInputManager::SH_KEYCODE::V),
W = static_cast<int>(SHInputManager::SH_KEYCODE::W),
X = static_cast<int>(SHInputManager::SH_KEYCODE::X),
Y = static_cast<int>(SHInputManager::SH_KEYCODE::Y),
Z = static_cast<int>(SHInputManager::SH_KEYCODE::Z),
//LeftCurlyBracket
//Pipe
//RightCurlyBracket
//Tilde
NumLock = static_cast<int>(SHInputManager::SH_KEYCODE::NUM_LOCK),
CapsLock = static_cast<int>(SHInputManager::SH_KEYCODE::CAPS_LOCK),
ScrollLock = static_cast<int>(SHInputManager::SH_KEYCODE::SCROLL_LOCK),
RightShift = static_cast<int>(SHInputManager::SH_KEYCODE::RIGHT_SHIFT),
LeftShift = static_cast<int>(SHInputManager::SH_KEYCODE::LEFT_SHIFT),
RightControl = static_cast<int>(SHInputManager::SH_KEYCODE::RIGHT_CTRL),
LeftControl = static_cast<int>(SHInputManager::SH_KEYCODE::LEFT_CTRL),
RightAlt = static_cast<int>(SHInputManager::SH_KEYCODE::RIGHT_ALT),
LeftAlt = static_cast<int>(SHInputManager::SH_KEYCODE::LEFT_ALT),
LeftWindows = static_cast<int>(SHInputManager::SH_KEYCODE::LEFT_WINDOWS),
RightWindows = static_cast<int>(SHInputManager::SH_KEYCODE::RIGHT_WINDOWS),
//AltGr
Help = static_cast<int>(SHInputManager::SH_KEYCODE::HELP),
Print = static_cast<int>(SHInputManager::SH_KEYCODE::PRINT),
SysReq = static_cast<int>(SHInputManager::SH_KEYCODE::PRINT_SCREEN),
//Break
//Menu
//Mouse buttons use mouse codes, which are enums declared later
//TODO Controller input
#if 0
Space = static_cast<int>(SHInputManager::SH_KEYCODE::SPACE),
//Apostrophe = static_cast<int>(SHInputManager::SH_KEYCODE::APOSTROPHE), //Apostrophe = static_cast<int>(SHInputManager::SH_KEYCODE::APOSTROPHE),
Comma = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_COMMA), Comma = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_COMMA),
Minus = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_MINUS), Minus = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_MINUS),
@ -190,7 +339,8 @@ namespace SHADE
JoystickButton6 = JoystickView, JoystickButton6 = JoystickView,
JoystickButton7 = JoystickMenu, JoystickButton7 = JoystickMenu,
JoystickButton8 = JoystickLeftStick, JoystickButton8 = JoystickLeftStick,
JoystickButton9 = JoystickRightStick JoystickButton9 = JoystickRightStick
#endif
}; };
/// <summary> /// <summary>
@ -321,5 +471,7 @@ namespace SHADE
/// <param name="key">The key to check.</param> /// <param name="key">The key to check.</param>
/// <returns>Time in seconds that the key was held.</returns> /// <returns>Time in seconds that the key was held.</returns>
static double GetMouseReleasedTime(MouseCode mouseButton); static double GetMouseReleasedTime(MouseCode mouseButton);
static Vector2 GetMouseVelocity();
}; };
} }

View File

@ -236,6 +236,22 @@ namespace SHADE
lhs.y * rhs.y lhs.y * rhs.y
); );
} }
Vector2 Vector2::operator*(Vector2 lhs, double rhs)
{
return Vector2
(
lhs.x * static_cast<float>(rhs),
lhs.y * static_cast<float>(rhs)
);
}
Vector2 Vector2::operator/(Vector2 lhs, double rhs)
{
return Vector2
(
lhs.x / static_cast<float>(rhs),
lhs.y / static_cast<float>(rhs)
);
}
Vector2 Vector2::operator*(Vector2 lhs, float rhs) Vector2 Vector2::operator*(Vector2 lhs, float rhs)
{ {
return Vector2 return Vector2

View File

@ -361,6 +361,22 @@ namespace SHADE
/// <param name="lhs">Vector2 to multiply with.</param> /// <param name="lhs">Vector2 to multiply with.</param>
/// <param name="rhs">Scalar to multiply with.</param> /// <param name="rhs">Scalar to multiply with.</param>
/// <returns>The result of the scalar multiplication.</returns> /// <returns>The result of the scalar multiplication.</returns>
static Vector2 operator*(Vector2 lhs, double rhs);
/// <summary>
/// Calculates the division of a Vector2 with a scalar value and returns
/// the result.
/// </summary>
/// <param name="lhs">Scalar to divide with.</param>
/// <param name="rhs">Vector2 to divide with.</param>
/// <returns>The result of the scalar division.</returns>
static Vector2 operator/(Vector2 lhs, double rhs);
/// <summary>
/// Calculates the multiplication of a Vector2 with a scalar value and returns
/// the result.
/// </summary>
/// <param name="lhs">Vector2 to multiply with.</param>
/// <param name="rhs">Scalar to multiply with.</param>
/// <returns>The result of the scalar multiplication.</returns>
static Vector2 operator*(Vector2 lhs, float rhs); static Vector2 operator*(Vector2 lhs, float rhs);
/// <summary> /// <summary>
/// Calculates the division of a Vector2 with a scalar value and returns /// Calculates the division of a Vector2 with a scalar value and returns

View File

@ -237,6 +237,24 @@ namespace SHADE
lhs.z * rhs.z lhs.z * rhs.z
); );
} }
Vector3 Vector3::operator*(Vector3 lhs, double rhs)
{
return Vector3
(
lhs.x * static_cast<float>(rhs),
lhs.y * static_cast<float>(rhs),
lhs.z * static_cast<float>(rhs)
);
}
Vector3 Vector3::operator/(Vector3 lhs, double rhs)
{
return Vector3
(
lhs.x / static_cast<float>(rhs),
lhs.y / static_cast<float>(rhs),
lhs.z / static_cast<float>(rhs)
);
}
Vector3 Vector3::operator*(Vector3 lhs, float rhs) Vector3 Vector3::operator*(Vector3 lhs, float rhs)
{ {
return Vector3 return Vector3

View File

@ -375,6 +375,22 @@ namespace SHADE
/// <param name="lhs">Vector3 to multiply with.</param> /// <param name="lhs">Vector3 to multiply with.</param>
/// <param name="rhs">Scalar to multiply with.</param> /// <param name="rhs">Scalar to multiply with.</param>
/// <returns>The result of the scalar multiplication.</returns> /// <returns>The result of the scalar multiplication.</returns>
static Vector3 operator*(Vector3 lhs, double rhs);
/// <summary>
/// Calculates the division of a Vector3 with a scalar value and returns
/// the result.
/// </summary>
/// <param name="lhs">Scalar to divide with.</param>
/// <param name="rhs">Vector3 to divide with.</param>
/// <returns>The result of the scalar division.</returns>
static Vector3 operator/(Vector3 lhs, double rhs);
/// <summary>
/// Calculates the multiplication of a Vector3 with a scalar value and returns
/// the result.
/// </summary>
/// <param name="lhs">Vector3 to multiply with.</param>
/// <param name="rhs">Scalar to multiply with.</param>
/// <returns>The result of the scalar multiplication.</returns>
static Vector3 operator*(Vector3 lhs, float rhs); static Vector3 operator*(Vector3 lhs, float rhs);
/// <summary> /// <summary>
/// Calculates the division of a Vector3 with a scalar value and returns /// Calculates the division of a Vector3 with a scalar value and returns

View File

@ -0,0 +1,36 @@
/************************************************************************************//*!
\file CollisionInfo.cxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 31, 2022
\brief Contains the definition of the functions of the managed CollisionInfo
struct.
Note: This file is written in C++17/CLI.
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 "CollisionInfo.hxx"
#include "Components/RigidBody.hxx"
#include "Components/Collider.hxx"
namespace SHADE
{
Collider^ CollisionInfo::Collider::get()
{
return GameObject.GetComponent<SHADE::Collider^>();
}
CollisionShape^ CollisionInfo::CollisionShape::get()
{
throw gcnew System::NotImplementedException();
}
RigidBody^ CollisionInfo::RigidBody::get()
{
return GameObject.GetComponent<SHADE::RigidBody^>();
}
}

View File

@ -0,0 +1,66 @@
/************************************************************************************//*!
\file CollisionInfo.hxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 31, 2022
\brief Contains the definition of the managed CollisionInfo struct with the
definition of its properties and declaration of functions.
Note: This file is written in C++17/CLI.
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 Includes
#include "Engine/GameObject.hxx"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
ref class RigidBody;
ref class Collider;
ref class CollisionShape;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Struct that describes a collision
/// </summary>
public value struct CollisionInfo
{
public:
/*-----------------------------------------------------------------------------*/
/* Properties */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// The GameObject whose collider you are colliding with.
/// </summary>
property GameObject GameObject;
/// <summary>
/// The Collider that you are colliding with.
/// </summary>
property Collider^ Collider
{
SHADE::Collider^ get();
}
/// <summary>
/// The CollisionShape of the Collider that you are colliding with.
/// </summary>
property CollisionShape^ CollisionShape
{
SHADE::CollisionShape^ get();
}
/// <summary>
/// The RigidBody that you are colliding with.
/// </summary>
property RigidBody^ RigidBody
{
SHADE::RigidBody^ get();
}
};
}

View File

@ -18,6 +18,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Script.hxx" #include "Script.hxx"
// Project Headers // Project Headers
#include "Utility/Debug.hxx" #include "Utility/Debug.hxx"
#include "ScriptStore.hxx"
#include "Engine/ECS.hxx"
namespace SHADE namespace SHADE
{ {
@ -49,8 +51,7 @@ namespace SHADE
generic <typename T> generic <typename T>
void Script::RemoveComponent() void Script::RemoveComponent()
{ {
throw gcnew System::NotImplementedException; owner.RemoveComponent<T>();
//ECS::RemoveComponent<T>(owner.GetNativeEntity());
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -59,37 +60,37 @@ namespace SHADE
generic <typename T> generic <typename T>
T Script::AddScript() T Script::AddScript()
{ {
throw gcnew System::NotImplementedException; return ScriptStore::AddScript<T>(owner.GetEntity());
//return ScriptStore::AddScript<T>(owner.GetEntity());
} }
generic <typename T> generic <typename T>
T Script::GetScript() T Script::GetScript()
{ {
throw gcnew System::NotImplementedException; return ScriptStore::GetScript<T>(owner.GetEntity());
//return ScriptStore::GetScript<T>(owner.GetEntity());
} }
generic <typename T> generic <typename T>
T Script::GetScriptInChildren() T Script::GetScriptInChildren()
{ {
throw gcnew System::NotImplementedException; return ScriptStore::GetScriptInChildren<T>(owner.GetEntity());
//return ScriptStore::GetScriptInChildren<T>(owner.GetEntity());
} }
generic <typename T> generic <typename T>
System::Collections::Generic::IEnumerable<T>^ Script::GetScripts() System::Collections::Generic::IEnumerable<T>^ Script::GetScripts()
{ {
throw gcnew System::NotImplementedException; return ScriptStore::GetScripts<T>(owner.GetEntity());
//return ScriptStore::GetScripts<T>(owner.GetEntity());
} }
generic <typename T> generic <typename T>
void Script::RemoveScript() void Script::RemoveScript()
{ {
throw gcnew System::NotImplementedException; ScriptStore::RemoveScript<T>(owner.GetEntity());
//ScriptStore::RemoveScript<T>(owner.GetEntity());
} }
Script::operator bool(Script^ s)
{
return s != nullptr;
}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* "All-time" Lifecycle Functions */ /* "All-time" Lifecycle Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -146,6 +147,48 @@ namespace SHADE
SAFE_NATIVE_CALL_END(this) SAFE_NATIVE_CALL_END(this)
} }
void Script::OnCollisionEnter(CollisionInfo collision)
{
SAFE_NATIVE_CALL_BEGIN
onCollisionEnter(collision);
SAFE_NATIVE_CALL_END(this)
}
void Script::OnCollisionStay(CollisionInfo collision)
{
SAFE_NATIVE_CALL_BEGIN
onCollisionStay(collision);
SAFE_NATIVE_CALL_END(this)
}
void Script::OnCollisionExit(CollisionInfo collision)
{
SAFE_NATIVE_CALL_BEGIN
onCollisionExit(collision);
SAFE_NATIVE_CALL_END(this)
}
void Script::OnTriggerEnter(CollisionInfo collision)
{
SAFE_NATIVE_CALL_BEGIN
onTriggerEnter(collision);
SAFE_NATIVE_CALL_END(this)
}
void Script::OnTriggerStay(CollisionInfo collision)
{
SAFE_NATIVE_CALL_BEGIN
onTriggerStay(collision);
SAFE_NATIVE_CALL_END(this)
}
void Script::OnTriggerExit(CollisionInfo collision)
{
SAFE_NATIVE_CALL_BEGIN
onTriggerExit(collision);
SAFE_NATIVE_CALL_END(this)
}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constructors */ /* Constructors */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -168,4 +211,14 @@ namespace SHADE
void Script::update() {} void Script::update() {}
void Script::lateUpdate() {} void Script::lateUpdate() {}
void Script::onDestroy() {} void Script::onDestroy() {}
}// namespace PlushieAPI
/*---------------------------------------------------------------------------------*/
/* Virtual Event Functions */
/*---------------------------------------------------------------------------------*/
void Script::onTriggerEnter(CollisionInfo) {}
void Script::onTriggerStay(CollisionInfo) {}
void Script::onTriggerExit(CollisionInfo) {}
void Script::onCollisionEnter(CollisionInfo) {}
void Script::onCollisionStay(CollisionInfo) {}
void Script::onCollisionExit(CollisionInfo) {}
}

View File

@ -15,6 +15,7 @@ of DigiPen Institute of Technology is prohibited.
// Project Includes // Project Includes
#include "Engine/GameObject.hxx" #include "Engine/GameObject.hxx"
#include "Physics/CollisionInfo.hxx"
namespace SHADE namespace SHADE
{ {
@ -153,6 +154,15 @@ namespace SHADE
generic<typename T> where T : ref class, Script generic<typename T> where T : ref class, Script
void RemoveScript(); void RemoveScript();
/*-----------------------------------------------------------------------------*/
/* Operator Overloads */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Implicit conversion operator to enable checking if a component is null.
/// </summary>
/// <param name="c">Component to check.</param>
static operator bool(Script^ s);
internal: internal:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* "All-Time" Lifecycle Functions */ /* "All-Time" Lifecycle Functions */
@ -204,6 +214,46 @@ namespace SHADE
/// </summary> /// </summary>
void OnDestroy(); void OnDestroy();
/*-----------------------------------------------------------------------------*/
/* Event Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Used to call onCollisionEnter(). This should be called when a collision is
/// detected between the attached GameObject and another GameObject.
/// </summary>
/// <param name="collision">Information on the collision event.</param>
void OnCollisionEnter(CollisionInfo collision);
/// <summary>
/// Used to call onCollisionStay(). This should be called when a collision is
/// persistent between the attached GameObject and another GameObject.
/// </summary>
/// <param name="collision">Information on the collision event.</param>
void OnCollisionStay(CollisionInfo collision);
/// <summary>
/// Used to call onCollisionExit(). This should be called when a collision ends
/// between the attached GameObject and another GameObject.
/// </summary>
/// <param name="collision">Information on the collision event.</param>
void OnCollisionExit(CollisionInfo collision);
/// <summary>
/// Used to call onTriggerEnter(). This should be called when a trigger-type
/// collision is detected between the attached GameObject and another GameObject.
/// </summary>
/// <param name="collision">Information on the collision event.</param>
void OnTriggerEnter(CollisionInfo collision);
/// <summary>
/// Used to call onTriggerStay(). This should be called when a trigger-type
/// collision is detected between the attached GameObject and another GameObject.
/// </summary>
/// <param name="collision">Information on the collision event.</param>
void OnTriggerStay(CollisionInfo collision);
/// <summary>
/// Used to call onTriggerExit(). This should be called when a trigger-type
/// collision is detected between the attached GameObject and another GameObject.
/// </summary>
/// <param name="collision">Information on the collision event.</param>
void OnTriggerExit(CollisionInfo collision);
protected: protected:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Constructors */ /* Constructors */
@ -264,6 +314,46 @@ namespace SHADE
/// </summary> /// </summary>
virtual void onDestroy(); virtual void onDestroy();
/*-----------------------------------------------------------------------------*/
/* Virtual Event Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Called when the attached GameObject has a trigger Collider and collides with
/// another GameObject with a Collider in the first frame of collision.
/// </summary>
/// <param name="info">Information on the collision event.</param>
virtual void onTriggerEnter(CollisionInfo info);
/// <summary>
/// Called when the attached GameObject has a trigger Collider and collides with
/// another GameObject with a Collider in subsequent frames of collision.
/// </summary>
/// <param name="info">Information on the collision event.</param>
virtual void onTriggerStay(CollisionInfo info);
/// <summary>
/// Called when the attached GameObject has a trigger Collider and leaves a
/// collision with another GameObject with a Collider2D.
/// </summary>
/// <param name="info">Information on the collision event.</param>
virtual void onTriggerExit(CollisionInfo info);
/// <summary>
/// Called when the attached GameObject has a Collider and collides with
/// another GameObject with a Collider in the first frame of collision.
/// </summary>
/// <param name="info">Information on the collision event.</param>
virtual void onCollisionEnter(CollisionInfo info);
/// <summary>
/// Called when the attached GameObject has a Collider and collides with
/// another GameObject with a Collider in subsequent frames of collision.
/// </summary>
/// <param name="info">Information on the collision event.</param>
virtual void onCollisionStay(CollisionInfo info);
/// <summary>
/// Called when the attached GameObject has a Collider and leaves a
/// collision with another GameObject with a Collider2D.
/// </summary>
/// <param name="info">Information on the collision event.</param>
virtual void onCollisionExit(CollisionInfo info);
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
@ -271,4 +361,4 @@ namespace SHADE
GameObject owner; GameObject owner;
}; };
} // namespace PlushieAPI }

View File

@ -27,6 +27,9 @@ of DigiPen Institute of Technology is prohibited.
#include "Script.hxx" #include "Script.hxx"
#include "Engine/Entity.hxx" #include "Engine/Entity.hxx"
#include "Serialisation/ReflectionUtilities.hxx" #include "Serialisation/ReflectionUtilities.hxx"
#include "Engine/Application.hxx"
#include "Physics/SHPhysicsSystemInterface.h"
#include "Physics/SHPhysicsUtils.h"
namespace SHADE namespace SHADE
{ {
@ -70,7 +73,7 @@ namespace SHADE
SAFE_NATIVE_CALL_BEGIN SAFE_NATIVE_CALL_BEGIN
Script^ script; Script^ script;
return AddScriptViaNameWithRef(entity, scriptName, script); return AddScriptViaNameWithRef(entity, scriptName, script);
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
return false; return false;
} }
@ -300,7 +303,7 @@ namespace SHADE
removeScript(script); removeScript(script);
} }
scriptList->Clear(); scriptList->Clear();
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
} }
void ScriptStore::RemoveAllScriptsImmediately(Entity entity, bool callOnDestroy) void ScriptStore::RemoveAllScriptsImmediately(Entity entity, bool callOnDestroy)
{ {
@ -325,7 +328,7 @@ namespace SHADE
startList.Remove(script); startList.Remove(script);
} }
scriptList->Clear(); scriptList->Clear();
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -364,7 +367,7 @@ namespace SHADE
startList.AddRange(%inactiveStartList); startList.AddRange(%inactiveStartList);
inactiveStartList.Clear(); inactiveStartList.Clear();
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
} }
void ScriptStore::FrameCleanUp() void ScriptStore::FrameCleanUp()
{ {
@ -372,8 +375,11 @@ namespace SHADE
// Clear the queue // Clear the queue
while (disposalQueue.Count > 0) while (disposalQueue.Count > 0)
{ {
Script^ script = disposalQueue.Dequeue(); Script^ script = disposalQueue.Dequeue();
script->OnDestroy(); if (Application::IsPlaying)
{
script->OnDestroy();
}
auto entity = script->Owner.GetEntity(); auto entity = script->Owner.GetEntity();
auto scriptList = scripts[script->Owner.GetEntity()]; auto scriptList = scripts[script->Owner.GetEntity()];
scriptList->Remove(script); scriptList->Remove(script);
@ -382,13 +388,13 @@ namespace SHADE
scripts.Remove(entity); scripts.Remove(entity);
} }
} }
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
} }
void ScriptStore::Exit() void ScriptStore::Exit()
{ {
SAFE_NATIVE_CALL_BEGIN SAFE_NATIVE_CALL_BEGIN
// Run the deinit all scripts if needed // Run the deinit all scripts if needed
//if (Application::IsPlaying) if (Application::IsPlaying)
{ {
Debug::Log("Running OnDestroy() for scripts."); Debug::Log("Running OnDestroy() for scripts.");
for each (System::Collections::Generic::KeyValuePair<Entity, ScriptList^> entity in scripts) for each (System::Collections::Generic::KeyValuePair<Entity, ScriptList^> entity in scripts)
@ -406,7 +412,7 @@ namespace SHADE
startList.Clear(); startList.Clear();
disposalQueue.Clear(); disposalQueue.Clear();
scriptTypeList = nullptr; scriptTypeList = nullptr;
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -435,7 +441,7 @@ namespace SHADE
script->FixedUpdate(); script->FixedUpdate();
} }
} }
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
} }
void ScriptStore::ExecuteUpdate() void ScriptStore::ExecuteUpdate()
{ {
@ -452,7 +458,7 @@ namespace SHADE
script->Update(); script->Update();
} }
} }
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
} }
void ScriptStore::ExecuteLateUpdate() void ScriptStore::ExecuteLateUpdate()
{ {
@ -469,7 +475,95 @@ namespace SHADE
script->LateUpdate(); script->LateUpdate();
} }
} }
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
}
void ScriptStore::ExecuteCollisionFunctions()
{
SAFE_NATIVE_CALL_BEGIN
/* Collisions */
const auto& collisions = SHPhysicsSystemInterface::GetCollisionInfo();
for (const auto& collisionInfo : collisions)
{
auto entities =
{
std::make_pair(collisionInfo.GetEntityA(), collisionInfo.GetEntityB()),
std::make_pair(collisionInfo.GetEntityB(), collisionInfo.GetEntityA())
};
for (auto entity : entities)
{
// Don't bother if this object has no scripts or is inactive
if (!isEntityActive(entity.first) || !scripts.ContainsKey(entity.first))
continue;
// Construct the collision state object
CollisionInfo info;
info.GameObject = GameObject(entity.second);
// Call all of the script's functions
auto entityScripts = scripts[entity.first];
if (entityScripts->Count > 0)
{
for each (Script ^ script in entityScripts)
{
switch (collisionInfo.GetCollisionState())
{
case SHCollisionEvent::State::ENTER:
script->OnCollisionEnter(info);
break;
case SHCollisionEvent::State::STAY:
script->OnCollisionStay(info);
break;
case SHCollisionEvent::State::EXIT:
script->OnCollisionExit(info);
break;
}
}
}
}
}
/* Triggers */
const auto& triggers = SHPhysicsSystemInterface::GetTriggerInfo();
for (const auto& triggerInfo : triggers)
{
auto entities =
{
std::make_pair(triggerInfo.GetEntityA(), triggerInfo.GetEntityB()),
std::make_pair(triggerInfo.GetEntityB(), triggerInfo.GetEntityA())
};
for (auto entity : entities)
{
// Don't bother if this object has no scripts or is inactive
if (!isEntityActive(entity.first) || !scripts.ContainsKey(entity.first))
continue;
// Construct the collision state object
CollisionInfo info;
info.GameObject = GameObject(entity.second);
// Call all of the script's functions
auto entityScripts = scripts[entity.first];
if (entityScripts->Count > 0)
{
for each (Script ^ script in entityScripts)
{
switch (triggerInfo.GetCollisionState())
{
case SHCollisionEvent::State::ENTER:
script->OnTriggerEnter(info);
break;
case SHCollisionEvent::State::STAY:
script->OnTriggerStay(info);
break;
case SHCollisionEvent::State::EXIT:
script->OnTriggerExit(info);
break;
}
}
}
}
}
SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
} }
bool ScriptStore::SerialiseScripts(Entity entity, System::IntPtr yamlNodePtr) bool ScriptStore::SerialiseScripts(Entity entity, System::IntPtr yamlNodePtr)
@ -505,7 +599,7 @@ namespace SHADE
} }
return true; return true;
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
return false; return false;
} }
@ -555,7 +649,7 @@ namespace SHADE
} }
return true; return true;
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
return false; return false;
} }
@ -663,14 +757,10 @@ namespace SHADE
bool ScriptStore::isEntityActive(Entity entity) bool ScriptStore::isEntityActive(Entity entity)
{ {
// Get native Entity // Invalid entity
SHEntity* nativeEntity = SHEntityManager::GetEntityByID(entity); if (!EntityUtils::IsValid(entity))
// Entity Validity Check
if (nativeEntity == nullptr)
return false; return false;
// Check active state return GameObject(entity).IsActiveInHierarchy;
return nativeEntity->GetActive();
} }
} }

View File

@ -233,6 +233,10 @@ namespace SHADE
/// Executes LateUpdate() for all scripts. /// Executes LateUpdate() for all scripts.
/// </summary> /// </summary>
static void ExecuteLateUpdate(); static void ExecuteLateUpdate();
/// <summary>
/// Executes OnCollision*() and OnTrigger*() for all scripts.
/// </summary>
static void ExecuteCollisionFunctions();
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Serialisation Functions */ /* Serialisation Functions */

View File

@ -22,6 +22,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Math/Vector2.hxx" #include "Math/Vector2.hxx"
#include "Math/Vector3.hxx" #include "Math/Vector3.hxx"
#include "Utility/Debug.hxx" #include "Utility/Debug.hxx"
#include "Engine/GameObject.hxx"
/*-------------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------------*/
/* Macro Functions */ /* Macro Functions */
@ -167,6 +168,11 @@ namespace SHADE
fieldNode.push_back(vec.y); fieldNode.push_back(vec.y);
fieldNode.push_back(vec.z); fieldNode.push_back(vec.z);
} }
else if (fieldInfo->FieldType == GameObject::typeid)
{
GameObject gameObj = safe_cast<GameObject>(fieldInfo->GetValue(object));
fieldNode = gameObj.GetEntity();
}
else // Not any of the supported types else // Not any of the supported types
{ {
Debug::LogWarning(Convert::ToNative(System::String::Format Debug::LogWarning(Convert::ToNative(System::String::Format
@ -242,6 +248,10 @@ namespace SHADE
); );
} }
} }
else if (fieldInfo->FieldType == GameObject::typeid)
{
fieldInfo->SetValue(object, GameObject(node.as<uint32_t>()));
}
else // Not any of the supported types else // Not any of the supported types
{ {
Debug::LogWarning(Convert::ToNative(System::String::Format Debug::LogWarning(Convert::ToNative(System::String::Format

View File

@ -0,0 +1,22 @@
using System;
using SHADE;
namespace SHADE_Scripting
{
public class CameraControl :Script
{
public float turnSpeed = 0.5f;
public CameraControl(GameObject go) : base(go) { }
protected override void update()
{
//Camera
Camera cam = GetComponent<Camera>();
Vector2 mouseVel = Input.GetMouseVelocity();
cam.Pitch -= mouseVel.y * turnSpeed * (float)Time.DeltaTime;
cam.Yaw += mouseVel.x * turnSpeed * (float)Time.DeltaTime;
}
}
}

View File

@ -38,6 +38,35 @@ public class PhysicsTest : Script
RigidBody.AddForce(Force); RigidBody.AddForce(Force);
Debug.Log($"Jump!"); Debug.Log($"Jump!");
} }
Debug.Log($"{Transform.LocalPosition.y}"); }
protected override void fixedUpdate()
{
Debug.Log("Fixed Update");
}
protected override void onCollisionEnter(CollisionInfo info)
{
Debug.Log($"Collision Enter: {info.GameObject.Name}");
}
protected override void onCollisionStay(CollisionInfo info)
{
Debug.Log($"Collision Stay: {info.GameObject.Name}");
}
protected override void onCollisionExit(CollisionInfo info)
{
Debug.Log($"Collision Exit: {info.GameObject.Name}");
}
protected override void onTriggerEnter(CollisionInfo info)
{
Debug.Log($"Trigger Enter: {info.GameObject.Name}");
}
protected override void onTriggerStay(CollisionInfo info)
{
Debug.Log($"Trigger Stay: {info.GameObject.Name}");
}
protected override void onTriggerExit(CollisionInfo info)
{
Debug.Log($"Trigger Exit: {info.GameObject.Name}");
} }
} }

View File

@ -0,0 +1,11 @@
using SHADE;
public class PrintWhenActive : Script
{
public PrintWhenActive(GameObject gameObj) : base(gameObj) { }
protected override void update()
{
Debug.Log("Active!");
}
}

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