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

View File

@ -20,4 +20,10 @@ namespace SHADE
float menuBarHeight = 20.0f;
std::vector<std::filesystem::path> layoutPaths;
};//class SHEditorMenuBar
struct SHEditorStateChangeEvent
{
SHEditor::State previousState;
};
}//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_PHYSICS_COLLIDER_ADDED_EVENT { 6 };
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;
registration::class_<SHTransformComponent>("Transform Component")
.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("Scale" ,&SHTransformComponent::GetLocalScale ,&SHTransformComponent::SetLocalScale ) (metadata(META::tooltip, "Scale"));
.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("Scale" ,&SHTransformComponent::GetLocalScale ,&SHTransformComponent::SetLocalScale ) (metadata(META::tooltip, "Scale"));
}

View File

@ -17,6 +17,7 @@
#include "Math/Geometry/SHBoundingSphere.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Math/SHMathHelpers.h"
#include "Reflection/SHReflectionMetadata.h"
namespace SHADE
{
@ -158,6 +159,11 @@ namespace SHADE
return positionOffset;
}
const SHVec3& SHCollider::GetRotationOffset() const noexcept
{
return rotationOffset;
}
SHShape* SHCollider::GetShape() noexcept
{
dirty = true;
@ -275,6 +281,12 @@ namespace SHADE
}
}
void SHCollider::SetRotationOffset(const SHVec3& rotOffset) noexcept
{
dirty = true;
rotationOffset = rotOffset;
}
/*-----------------------------------------------------------------------------------*/
/* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
@ -316,5 +328,6 @@ RTTR_REGISTRATION
);
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 SHVec3& GetPositionOffset () const noexcept;
[[nodiscard]] const SHVec3& GetRotationOffset () const noexcept;
[[nodiscard]] SHShape* GetShape () noexcept;
@ -96,7 +97,8 @@ namespace SHADE
void SetDensity (float density) 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:
/*---------------------------------------------------------------------------------*/
@ -110,6 +112,7 @@ namespace SHADE
SHShape* shape;
SHPhysicsMaterial material;
SHVec3 positionOffset;
SHVec3 rotationOffset;
/*---------------------------------------------------------------------------------*/
/* Function Members */

View File

@ -130,6 +130,8 @@ namespace SHADE
int SHPhysicsObject::AddCollider(SHCollider* collider)
{
const rp3d::Transform OFFSETS{ collider->GetPositionOffset(), collider->GetRotationOffset() };
switch (collider->GetType())
{
case SHCollider::Type::BOX:
@ -137,7 +139,7 @@ namespace SHADE
const auto* box = reinterpret_cast<SHBoundingBox*>(collider->GetShape());
rp3d::BoxShape* newBox = factory->createBoxShape(box->GetHalfExtents());
rp3dBody->addCollider(newBox, rp3d::Transform{ collider->GetPositionOffset(), SHQuaternion::Identity });
rp3dBody->addCollider(newBox, OFFSETS);
break;
}
case SHCollider::Type::SPHERE:
@ -145,7 +147,7 @@ namespace SHADE
const auto* sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape());
rp3d::SphereShape* newSphere = factory->createSphereShape(sphere->GetRadius());
rp3dBody->addCollider(newSphere, rp3d::Transform{ collider->GetPositionOffset(), SHQuaternion::Identity });
rp3dBody->addCollider(newSphere, OFFSETS);
break;
}
// TODO(Diren): Add more collider shapes
@ -182,7 +184,7 @@ namespace SHADE
rp3dCollider->setIsTrigger(collider.IsTrigger());
// Update offsets
rp3dCollider->setLocalToBodyTransform(rp3d::Transform(collider.GetPositionOffset(), SHQuaternion::Identity));
rp3dCollider->setLocalToBodyTransform(rp3d::Transform(collider.GetPositionOffset(), collider.GetRotationOffset()));
switch (collider.GetType())
{

View File

@ -17,7 +17,6 @@
#include "ECS_Base/Managers/SHComponentManager.h"
#include "ECS_Base/Managers/SHEntityManager.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/SHEditor.h"
#include "Math/SHMathHelpers.h"
#include "Math/Transform/SHTransformComponent.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 ReceiverPtr REMOVE_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(REMOVE_COMPONENT_RECEIVER);
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()
@ -289,16 +294,6 @@ namespace SHADE
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
const bool COMPONENT_ACTIVE = rigidBodyComponent->isActive;
SyncActiveStates(physicsObject, COMPONENT_ACTIVE);
@ -324,11 +319,11 @@ namespace SHADE
void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept
{
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
auto scriptSys = SHSystemManager::GetSystem<SHScriptEngine>();
if (!scriptSys)
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
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;
@ -337,10 +332,9 @@ namespace SHADE
int count = 0;
while (accumulatedTime > fixedTimeStep)
{
if (scriptSys)
{
scriptSys->ExecuteFixedUpdates();
}
if (scriptingSystem != nullptr)
scriptingSystem->ExecuteFixedUpdates();
physicsSystem->world->update(static_cast<rp3d::decimal>(fixedTimeStep));
accumulatedTime -= fixedTimeStep;
@ -356,6 +350,11 @@ namespace SHADE
void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept
{
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
if (physicsSystem->worldUpdated)
@ -363,15 +362,8 @@ namespace SHADE
physicsSystem->SyncTransforms();
// Collision & Trigger messages
auto scriptSys = SHSystemManager::GetSystem<SHScriptEngine>();
if (scriptSys)
{
scriptSys->ExecuteCollisionFunctions();
}
else
{
SHLOG_WARNING("[SHPhysicsSystem] Unable to invoke collision and trigger script events due to missing SHScriptEngine!");
}
if (scriptingSystem != nullptr)
scriptingSystem->ExecuteCollisionFunctions();
physicsSystem->ClearInvalidCollisions();
}
@ -630,19 +622,17 @@ namespace SHADE
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(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!")
if (REMOVED_ID == RIGID_BODY_ID)
// Wake up all physics objects
for (auto& [entityID, object] : map)
{
// Wake up all physics objects
for (auto& [entityID, object] : map)
{
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(entityID))
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));
physicsObject->rp3dBody = nullptr;
physicsObject->rp3dBody = 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
const int NUM_COLLIDERS = static_cast<int>(physicsObject->rp3dBody->getNbColliders());
@ -673,11 +663,30 @@ namespace SHADE
physicsObject->rp3dBody = nullptr;
}
if (physicsObject->rp3dBody == nullptr)
DestroyPhysicsObject(ENTITY_ID);
if (physicsObject != nullptr && physicsObject->rp3dBody == nullptr)
DestroyPhysicsObject(ENTITY_ID);
}
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

View File

@ -189,6 +189,7 @@ namespace SHADE
SHEventHandle AddPhysicsComponent (SHEventPtr addComponentEvent);
SHEventHandle RemovePhysicsComponent (SHEventPtr removeComponentEvent);
SHEventHandle ResetWorld (SHEventPtr editorStopEvent);
template <typename RP3DCollisionPair, typename = std::enable_if_t
<std::is_same_v<RP3DCollisionPair, rp3d::CollisionCallback::ContactPair>