Merge pull request #153 from SHADE-DP/SP3-2-Physics

SP3-2 Reworked Physics Component Removal, Added Editor State Change events

NEW

Events for editor state change added:
SH_EDITOR_ON_PLAY_EVENT,
SH_EDITOR_ON_PAUSE_EVENT,
SH_EDITOR_ON_STOP_EVENT
BUGFIX

Reworked physics component removal to match ECS update
This commit is contained in:
XiaoQiDigipen 2022-11-01 15:36:34 +08:00 committed by GitHub
commit 294e61a549
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 124 additions and 50 deletions

View File

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

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

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

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

@ -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& posOffset) 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
@ -182,7 +184,7 @@ namespace SHADE
rp3dCollider->setIsTrigger(collider.IsTrigger()); rp3dCollider->setIsTrigger(collider.IsTrigger());
// Update offsets // Update offsets
rp3dCollider->setLocalToBodyTransform(rp3d::Transform(collider.GetPositionOffset(), SHQuaternion::Identity)); rp3dCollider->setLocalToBodyTransform(rp3d::Transform(collider.GetPositionOffset(), collider.GetRotationOffset()));
switch (collider.GetType()) switch (collider.GetType())
{ {

View File

@ -17,7 +17,6 @@
#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 "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Scene/SHSceneManager.h" #include "Scene/SHSceneManager.h"
@ -212,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()
@ -289,16 +294,6 @@ namespace SHADE
if (rigidBodyComponent) if (rigidBodyComponent)
{ {
// 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);
}
// Sync active states // Sync active states
const bool COMPONENT_ACTIVE = rigidBodyComponent->isActive; const bool COMPONENT_ACTIVE = rigidBodyComponent->isActive;
SyncActiveStates(physicsObject, COMPONENT_ACTIVE); SyncActiveStates(physicsObject, COMPONENT_ACTIVE);
@ -324,11 +319,11 @@ namespace SHADE
void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept
{ {
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem()); auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
auto scriptSys = SHSystemManager::GetSystem<SHScriptEngine>(); auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
if (!scriptSys) if (scriptingSystem == nullptr)
{ {
SHLOG_WARNING("[SHPhysicsSystem] Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!"); SHLOGV_WARNING("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!");
} }
fixedTimeStep = 1.0 / physicsSystem->fixedDT; fixedTimeStep = 1.0 / physicsSystem->fixedDT;
@ -337,10 +332,9 @@ namespace SHADE
int count = 0; int count = 0;
while (accumulatedTime > fixedTimeStep) while (accumulatedTime > fixedTimeStep)
{ {
if (scriptSys) if (scriptingSystem != nullptr)
{ scriptingSystem->ExecuteFixedUpdates();
scriptSys->ExecuteFixedUpdates();
}
physicsSystem->world->update(static_cast<rp3d::decimal>(fixedTimeStep)); physicsSystem->world->update(static_cast<rp3d::decimal>(fixedTimeStep));
accumulatedTime -= fixedTimeStep; accumulatedTime -= fixedTimeStep;
@ -356,6 +350,11 @@ namespace SHADE
void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept
{ {
auto* physicsSystem = 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 (physicsSystem->worldUpdated) if (physicsSystem->worldUpdated)
@ -363,15 +362,8 @@ namespace SHADE
physicsSystem->SyncTransforms(); physicsSystem->SyncTransforms();
// Collision & Trigger messages // Collision & Trigger messages
auto scriptSys = SHSystemManager::GetSystem<SHScriptEngine>(); if (scriptingSystem != nullptr)
if (scriptSys) scriptingSystem->ExecuteCollisionFunctions();
{
scriptSys->ExecuteCollisionFunctions();
}
else
{
SHLOG_WARNING("[SHPhysicsSystem] Unable to invoke collision and trigger script events due to missing SHScriptEngine!");
}
physicsSystem->ClearInvalidCollisions(); physicsSystem->ClearInvalidCollisions();
} }
@ -630,19 +622,17 @@ namespace SHADE
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ENTITY_ID); auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ENTITY_ID);
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(ENTITY_ID); auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(ENTITY_ID);
SHASSERT(physicsObject != nullptr, "Physics object " + std::to_string(ENTITY_ID) + " has been lost from the world!") // Wake up all physics objects
for (auto& [entityID, object] : map)
if (REMOVED_ID == RIGID_BODY_ID)
{ {
// Wake up all physics objects if (SHComponentManager::HasComponent<SHRigidBodyComponent>(entityID))
for (auto& [entityID, object] : map) reinterpret_cast<rp3d::RigidBody*>(object.rp3dBody)->setIsSleeping(false);
{ }
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;
if (colliderComponent != nullptr) if (colliderComponent != nullptr)
{ {
@ -657,7 +647,7 @@ namespace SHADE
} }
} }
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());
@ -673,11 +663,30 @@ namespace SHADE
physicsObject->rp3dBody = 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

@ -189,6 +189,7 @@ namespace SHADE
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 template <typename RP3DCollisionPair, typename = std::enable_if_t
<std::is_same_v<RP3DCollisionPair, rp3d::CollisionCallback::ContactPair> <std::is_same_v<RP3DCollisionPair, rp3d::CollisionCallback::ContactPair>