diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Ragdoll.h b/Code/Framework/AzFramework/AzFramework/Physics/Ragdoll.h index 239d93cf32..97c841e8f8 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Ragdoll.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/Ragdoll.h @@ -102,7 +102,7 @@ namespace Physics /// Is the ragdoll currently simulated? /// @result True in case the ragdoll is simulated, false if not. - virtual bool IsSimulated() = 0; + virtual bool IsSimulated() const = 0; /// Writes the state for all of the bodies in the ragdoll to the provided output. /// The caller owns the output state and can safely manipulate it without affecting the physics simulation. diff --git a/Gems/EMotionFX/Code/Tests/Mocks/PhysicsRagdoll.h b/Gems/EMotionFX/Code/Tests/Mocks/PhysicsRagdoll.h index b3acb73e19..446abbf6af 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/PhysicsRagdoll.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/PhysicsRagdoll.h @@ -26,7 +26,7 @@ namespace EMotionFX MOCK_METHOD0(DisableSimulation, void()); MOCK_METHOD0(DisableSimulationQueued, void()); - MOCK_METHOD0(IsSimulated, bool()); + MOCK_CONST_METHOD0(IsSimulated, bool()); MOCK_CONST_METHOD1(GetState, void(Physics::RagdollState&)); MOCK_METHOD1(SetState, void(const Physics::RagdollState&)); diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/API/Ragdoll.cpp b/Gems/PhysX/Code/Source/PhysXCharacters/API/Ragdoll.cpp index 5249781e31..02ebe7281c 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/API/Ragdoll.cpp +++ b/Gems/PhysX/Code/Source/PhysXCharacters/API/Ragdoll.cpp @@ -274,7 +274,7 @@ namespace PhysX m_queuedDisableSimulation = true; } - bool Ragdoll::IsSimulated() + bool Ragdoll::IsSimulated() const { return m_simulating; } diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/API/Ragdoll.h b/Gems/PhysX/Code/Source/PhysXCharacters/API/Ragdoll.h index 7bf807bcc5..7182a3a44c 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/API/Ragdoll.h +++ b/Gems/PhysX/Code/Source/PhysXCharacters/API/Ragdoll.h @@ -46,7 +46,7 @@ namespace PhysX void EnableSimulationQueued(const Physics::RagdollState& initialState) override; void DisableSimulation() override; void DisableSimulationQueued() override; - bool IsSimulated() override; + bool IsSimulated() const override; void GetState(Physics::RagdollState& ragdollState) const override; void SetState(const Physics::RagdollState& ragdollState) override; void SetStateQueued(const Physics::RagdollState& ragdollState) override; diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.cpp b/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.cpp index 431dbd9ac4..86c60565a0 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.cpp +++ b/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.cpp @@ -465,7 +465,7 @@ namespace PhysX PhysX::CharacterController* CharacterControllerComponent::GetController() { - return const_cast(GetControllerConst()); + return const_cast(static_cast(*this).GetControllerConst()); } void CharacterControllerComponent::CreateController() diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/Components/RagdollComponent.cpp b/Gems/PhysX/Code/Source/PhysXCharacters/Components/RagdollComponent.cpp index 4c58187fb8..8da512647f 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/Components/RagdollComponent.cpp +++ b/Gems/PhysX/Code/Source/PhysXCharacters/Components/RagdollComponent.cpp @@ -170,63 +170,88 @@ namespace PhysX // RagdollPhysicsBus void RagdollComponent::EnableSimulation(const Physics::RagdollState& initialState) { - m_ragdoll->EnableSimulation(initialState); + if (auto* ragdoll = GetPhysXRagdoll()) + { + ragdoll->EnableSimulation(initialState); + } } void RagdollComponent::EnableSimulationQueued(const Physics::RagdollState& initialState) { - m_ragdoll->EnableSimulationQueued(initialState); + if (auto* ragdoll = GetPhysXRagdoll()) + { + ragdoll->EnableSimulationQueued(initialState); + } } void RagdollComponent::DisableSimulation() { - if (m_ragdoll) + if (auto* ragdoll = GetPhysXRagdoll()) { - m_ragdoll->DisableSimulation(); + ragdoll->DisableSimulation(); } } void RagdollComponent::DisableSimulationQueued() { - if (m_ragdoll) + if (auto* ragdoll = GetPhysXRagdoll()) { - m_ragdoll->DisableSimulationQueued(); + ragdoll->DisableSimulationQueued(); } } Physics::Ragdoll* RagdollComponent::GetRagdoll() { - return m_ragdoll; + return GetPhysXRagdoll(); } void RagdollComponent::GetState(Physics::RagdollState& ragdollState) const { - m_ragdoll->GetState(ragdollState); + if (const auto* ragdoll = GetPhysXRagdollConst()) + { + ragdoll->GetState(ragdollState); + } } void RagdollComponent::SetState(const Physics::RagdollState& ragdollState) { - m_ragdoll->SetState(ragdollState); + if (auto* ragdoll = GetPhysXRagdoll()) + { + ragdoll->SetState(ragdollState); + } } void RagdollComponent::SetStateQueued(const Physics::RagdollState& ragdollState) { - m_ragdoll->SetStateQueued(ragdollState); + if (auto* ragdoll = GetPhysXRagdoll()) + { + ragdoll->SetStateQueued(ragdollState); + } } void RagdollComponent::GetNodeState(size_t nodeIndex, Physics::RagdollNodeState& nodeState) const { - m_ragdoll->GetNodeState(nodeIndex, nodeState); + if (const auto* ragdoll = GetPhysXRagdollConst()) + { + ragdoll->GetNodeState(nodeIndex, nodeState); + } } void RagdollComponent::SetNodeState(size_t nodeIndex, const Physics::RagdollNodeState& nodeState) { - m_ragdoll->SetNodeState(nodeIndex, nodeState); + if (auto* ragdoll = GetPhysXRagdoll()) + { + ragdoll->SetNodeState(nodeIndex, nodeState); + } } Physics::RagdollNode* RagdollComponent::GetNode(size_t nodeIndex) const { - return m_ragdoll->GetNode(nodeIndex); + if (const auto* ragdoll = GetPhysXRagdollConst()) + { + return ragdoll->GetNode(nodeIndex); + } + return nullptr; } void RagdollComponent::EnablePhysics() @@ -245,14 +270,19 @@ namespace PhysX bool RagdollComponent::IsPhysicsEnabled() const { - return m_ragdoll && m_ragdoll->IsSimulated(); + if (const auto* ragdoll = GetPhysXRagdollConst()) + { + return ragdoll->IsSimulated(); + } + return false; + } AZ::Aabb RagdollComponent::GetAabb() const { - if (m_ragdoll) + if (const auto* ragdoll = GetPhysXRagdollConst()) { - return m_ragdoll->GetAabb(); + return ragdoll->GetAabb(); } return AZ::Aabb::CreateNull(); } @@ -264,18 +294,14 @@ namespace PhysX AzPhysics::SimulatedBodyHandle RagdollComponent::GetSimulatedBodyHandle() const { - if (m_ragdoll) - { - return m_ragdoll->m_bodyHandle; - } - return AzPhysics::InvalidSimulatedBodyHandle; + return m_ragdollHandle; } AzPhysics::SceneQueryHit RagdollComponent::RayCast(const AzPhysics::RayCastRequest& request) { - if (m_ragdoll) + if (auto* ragdoll = GetPhysXRagdoll()) { - return m_ragdoll->RayCast(request); + return ragdoll->RayCast(request); } return AzPhysics::SceneQueryHit(); } @@ -323,23 +349,24 @@ namespace PhysX AZ::TransformBus::EventResult(entityTransform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); ragdollConfiguration.m_initialState = GetBindPoseWorld(bindPose, entityTransform); - AzPhysics::SceneHandle defaultSceneHandle = AzPhysics::InvalidSceneHandle; - Physics::DefaultWorldBus::BroadcastResult(defaultSceneHandle, &Physics::DefaultWorldRequests::GetDefaultSceneHandle); + m_attachedSceneHandle = AzPhysics::InvalidSceneHandle; + Physics::DefaultWorldBus::BroadcastResult(m_attachedSceneHandle, &Physics::DefaultWorldRequests::GetDefaultSceneHandle); if (auto* sceneInterface = AZ::Interface::Get()) { - AzPhysics::SimulatedBodyHandle bodyHandle = sceneInterface->AddSimulatedBody(defaultSceneHandle, &ragdollConfiguration); - m_ragdoll = azdynamic_cast(sceneInterface->GetSimulatedBodyFromHandle(defaultSceneHandle, bodyHandle)); + m_ragdollHandle = sceneInterface->AddSimulatedBody(m_attachedSceneHandle, &ragdollConfiguration); } - if (m_ragdoll == nullptr) + auto* ragdoll = GetPhysXRagdoll(); + if (ragdoll == nullptr || + m_ragdollHandle == AzPhysics::InvalidSimulatedBodyHandle) { AZ_Error("PhysX Ragdoll Component", false, "Failed to create ragdoll."); return; } - + for (size_t nodeIndex = 0; nodeIndex < numNodes; nodeIndex++) { - if (physx::PxRigidDynamic* pxRigidBody = m_ragdoll->GetPxRigidDynamic(nodeIndex)) + if (physx::PxRigidDynamic* pxRigidBody = ragdoll->GetPxRigidDynamic(nodeIndex)) { pxRigidBody->setSolverIterationCounts(m_positionIterations, m_velocityIterations); } @@ -352,7 +379,7 @@ namespace PhysX for (size_t nodeIndex = 0; nodeIndex < numNodes; nodeIndex++) { - if (const AZStd::shared_ptr& joint = m_ragdoll->GetNode(nodeIndex)->GetJoint()) + if (const AZStd::shared_ptr& joint = ragdoll->GetNode(nodeIndex)->GetJoint()) { if (auto* pxJoint = static_cast(joint->GetNativePointer())) { @@ -374,20 +401,41 @@ namespace PhysX void RagdollComponent::DestroyRagdoll() { - if (m_ragdoll) + if (m_ragdollHandle != AzPhysics::InvalidSimulatedBodyHandle && + m_attachedSceneHandle != AzPhysics::InvalidSceneHandle) { AzFramework::RagdollPhysicsRequestBus::Handler::BusDisconnect(); - AzFramework::RagdollPhysicsNotificationBus::Event(GetEntityId(), - &AzFramework::RagdollPhysicsNotifications::OnRagdollDeactivated); + AzFramework::RagdollPhysicsNotificationBus::Event( + GetEntityId(), &AzFramework::RagdollPhysicsNotifications::OnRagdollDeactivated); if (auto* sceneInterface = AZ::Interface::Get()) { - sceneInterface->RemoveSimulatedBody(m_ragdoll->m_sceneOwner, m_ragdoll->m_bodyHandle); + sceneInterface->RemoveSimulatedBody(m_attachedSceneHandle, m_ragdollHandle); + m_attachedSceneHandle = AzPhysics::InvalidSceneHandle; } - m_ragdoll = nullptr; } } + Ragdoll* RagdollComponent::GetPhysXRagdoll() + { + return const_cast(static_cast(*this).GetPhysXRagdollConst()); + } + + const Ragdoll* RagdollComponent::GetPhysXRagdollConst() const + { + if (m_ragdollHandle == AzPhysics::InvalidSimulatedBodyHandle || + m_attachedSceneHandle == AzPhysics::InvalidSceneHandle) + { + return nullptr; + } + + if (auto* sceneInterface = AZ::Interface::Get()) + { + return azdynamic_cast(sceneInterface->GetSimulatedBodyFromHandle(m_attachedSceneHandle, m_ragdollHandle)); + } + return nullptr; + } + // deprecated Cry functions void RagdollComponent::EnterRagdoll() { diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/Components/RagdollComponent.h b/Gems/PhysX/Code/Source/PhysXCharacters/Components/RagdollComponent.h index a02e9c47fb..2c265b0f73 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/Components/RagdollComponent.h +++ b/Gems/PhysX/Code/Source/PhysXCharacters/Components/RagdollComponent.h @@ -104,10 +104,13 @@ namespace PhysX private: void CreateRagdoll(const Physics::RagdollConfiguration& ragdollConfiguration); void DestroyRagdoll(); + Ragdoll* GetPhysXRagdoll(); + const Ragdoll* GetPhysXRagdollConst() const; bool IsJointProjectionVisible(); - Ragdoll* m_ragdoll; + AzPhysics::SimulatedBodyHandle m_ragdollHandle = AzPhysics::InvalidSimulatedBodyHandle; + AzPhysics::SceneHandle m_attachedSceneHandle = AzPhysics::InvalidSceneHandle; /// Minimum number of position iterations to perform in the PhysX solver. /// Lower iteration counts are less expensive but may behave less realistically. AZ::u32 m_positionIterations = 16;