diff --git a/Assets/Scenes/M2Scene.shade b/Assets/Scenes/M2Scene.shade index 21050428..bf910737 100644 --- a/Assets/Scenes/M2Scene.shade +++ b/Assets/Scenes/M2Scene.shade @@ -223,9 +223,4 @@ Bounciness: 0 Density: 1 Position Offset: {x: 0, y: 0.5, z: 0} - Scripts: - - Type: Item - currCategory: 0 - - Type: PickAndThrow - throwForce: [100, 200, 100] - item: 51000 \ No newline at end of file + Scripts: ~ \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp index 4c920bbc..0b0dd7a7 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp @@ -26,10 +26,11 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ SHPhysicsObject::SHPhysicsObject(EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept - : entityID { eid } - , factory { physicsFactory } - , world { physicsWorld } - , rp3dBody { nullptr } + : entityID { eid } + , collidersActive { true } + , factory { physicsFactory } + , world { physicsWorld } + , rp3dBody { nullptr } { // Implicitly create a static body. diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h index f18a0738..fefc983f 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h @@ -84,12 +84,13 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ EntityID entityID; + bool collidersActive; // Only used to sync with SHADE components rp3d::PhysicsCommon* factory; rp3d::PhysicsWorld* world; rp3d::RigidBody* rp3dBody; - rp3d::Transform prevTransform; // Cached transform for interpolation + rp3d::Transform prevTransform; // Cached transform for interpolation /*---------------------------------------------------------------------------------*/ /* Function Members */ diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp index ff441ac2..72bcd13f 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp @@ -16,6 +16,7 @@ // Project Headers #include "ECS_Base/Managers/SHSystemManager.h" #include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h" +#include "Scene/SHSceneManager.h" namespace SHADE { @@ -122,6 +123,10 @@ namespace SHADE const auto& COLLIDER_SET = SHComponentManager::GetDense(); for (const auto& COLLIDER : COLLIDER_SET) { + // Skip inactive colliders + //if (!SHSceneManager::CheckNodeAndComponentsActive(COLLIDER.GetEID())) + // continue; + for (auto& collisionShape : COLLIDER.GetCollisionShapes()) { switch (collisionShape.GetType()) diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index d94cfb58..0a7555b1 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -387,7 +387,7 @@ namespace SHADE , SHColliderComponent* colliderComponent ) noexcept { - if (!transformComponent) + if (!transformComponent || !SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) return; const SHVec3& WORLD_POS = transformComponent->GetWorldPosition(); @@ -397,13 +397,13 @@ namespace SHADE const rp3d::Transform RP3D_TRANSFORM { WORLD_POS, WORLD_ROT }; physicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM); - if (rigidBodyComponent) + if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) { rigidBodyComponent->position = WORLD_POS; rigidBodyComponent->orientation = WORLD_ROT; } - if (colliderComponent) + if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) { colliderComponent->position = WORLD_POS; colliderComponent->orientation = WORLD_ROT; @@ -422,15 +422,16 @@ namespace SHADE , double interpolationFactor ) noexcept { - const rp3d::Transform& CURRENT_TF = physicsObject.rp3dBody->getTransform(); + const rp3d::Transform& CURRENT_TF = physicsObject.GetRigidBody()->getTransform(); auto renderPos = CURRENT_TF.getPosition(); auto renderRot = CURRENT_TF.getOrientation(); // Cache transforms - physicsObject.prevTransform = CURRENT_TF; + if (physicsObject.GetRigidBody()->isActive()) + physicsObject.prevTransform = CURRENT_TF; // Sync with rigid bodies - if (rigidBodyComponent) + if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) { // Skip static bodies if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC) @@ -453,14 +454,14 @@ namespace SHADE } // Sync with colliders - if (colliderComponent) + if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) { colliderComponent->position = CURRENT_TF.getPosition(); colliderComponent->orientation = CURRENT_TF.getOrientation(); } // Set transform for rendering - if (transformComponent) + if (transformComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) { transformComponent->SetWorldPosition(renderPos); transformComponent->SetWorldOrientation(renderRot); diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h index 6059970d..3891ff48 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h @@ -122,7 +122,9 @@ namespace SHADE /* Function Members */ /*-------------------------------------------------------------------------------*/ - static void syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept; + void syncRigidBodyActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept; + void syncColliderActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept; + static void syncOnPlay (EntityID eid, SHPhysicsObject& physicsObject) noexcept; }; class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp index d2c23006..3376159b 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp @@ -15,6 +15,7 @@ // Project Headers #include "ECS_Base/Managers/SHSystemManager.h" #include "Editor/SHEditor.h" +#include "Scene/SHSceneManager.h" #include "Scripting/SHScriptEngine.h" namespace SHADE @@ -43,65 +44,13 @@ namespace SHADE { auto* physicsSystem = reinterpret_cast(GetSystem()); - #ifdef SHEDITOR - - auto* editor = SHSystemManager::GetSystem(); - - // Only Sync on Play. - // Otherwise, Components are only holding data until the world is built on play. - - if (editor) - { - if (editor->editorState != SHEditor::State::STOP) - { - physicsSystem->objectManager.UpdateCommands(); - - for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) - { - // Ensure a valid physics Object - if (physicsObject.rp3dBody == nullptr) - continue; - - syncOnPlay(entityID, physicsObject); - } - } - else - { - auto& rigidBodyDense = SHComponentManager::GetDense(); - auto& colliderDense = SHComponentManager::GetDense(); - - for (auto& rigidBodyComponent : rigidBodyDense) - { - const auto* TRANSFORM = SHComponentManager::GetComponent_s(rigidBodyComponent.GetEID()); - - if (TRANSFORM && TRANSFORM->HasChanged()) - { - rigidBodyComponent.position = TRANSFORM->GetWorldPosition(); - rigidBodyComponent.orientation = TRANSFORM->GetWorldOrientation(); - } - } - - for (auto& colliderComponent : colliderDense) - { - const auto* TRANSFORM = SHComponentManager::GetComponent_s(colliderComponent.GetEID()); - - if (TRANSFORM && TRANSFORM->HasChanged()) - { - colliderComponent.position = TRANSFORM->GetWorldPosition(); - colliderComponent.orientation = TRANSFORM->GetWorldOrientation(); - colliderComponent.scale = TRANSFORM->GetWorldScale(); - - colliderComponent.RecomputeCollisionShapes(); - } - } - } - } - - #else - - // Always sync Rigid Body & Collider Components with Physics Objects - // Do not check for an editor here + #ifdef SHEDITOR + // Only Sync on Play. + // Otherwise, Components are only holding data until the world is built on play. + const auto* EDITOR = SHSystemManager::GetSystem(); + if (EDITOR && EDITOR->editorState != SHEditor::State::STOP) + { physicsSystem->objectManager.UpdateCommands(); for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) @@ -110,10 +59,64 @@ namespace SHADE if (physicsObject.rp3dBody == nullptr) continue; + // Sync active states between SHADE & RP3D + syncRigidBodyActive(entityID, physicsObject); + syncColliderActive(entityID, physicsObject); + syncOnPlay(entityID, physicsObject); } + } + else + { + auto& rigidBodyDense = SHComponentManager::GetDense(); + auto& colliderDense = SHComponentManager::GetDense(); - #endif + for (auto& rigidBodyComponent : rigidBodyDense) + { + const auto* TRANSFORM = SHComponentManager::GetComponent_s(rigidBodyComponent.GetEID()); + + if (TRANSFORM && TRANSFORM->HasChanged()) + { + rigidBodyComponent.position = TRANSFORM->GetWorldPosition(); + rigidBodyComponent.orientation = TRANSFORM->GetWorldOrientation(); + } + } + + for (auto& colliderComponent : colliderDense) + { + const auto* TRANSFORM = SHComponentManager::GetComponent_s(colliderComponent.GetEID()); + + if (TRANSFORM && TRANSFORM->HasChanged()) + { + colliderComponent.position = TRANSFORM->GetWorldPosition(); + colliderComponent.orientation = TRANSFORM->GetWorldOrientation(); + colliderComponent.scale = TRANSFORM->GetWorldScale(); + + colliderComponent.RecomputeCollisionShapes(); + } + } + } + + #else + + // Always sync Rigid Body & Collider Components with Physics Objects + // Do not check for an editor here + + physicsSystem->objectManager.UpdateCommands(); + + for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) + { + // Ensure a valid physics Object + if (physicsObject.rp3dBody == nullptr) + continue; + + syncRigidBodyActive(entityID, physicsObject); + syncColliderActive(entityID, physicsObject); + + syncOnPlay(entityID, physicsObject); + } + + #endif } void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept @@ -188,6 +191,48 @@ namespace SHADE /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ + void SHPhysicsSystem::PhysicsPreUpdate::syncRigidBodyActive(EntityID eid, SHPhysicsObject& physicsObject) const noexcept + { + if (!SHComponentManager::HasComponent(eid)) + return; + + const bool IS_ACTIVE_IN_SCENE = SHSceneManager::CheckNodeAndComponentsActive(eid); + const bool IS_RP3D_BODY_ACTIVE = physicsObject.GetRigidBody()->isActive(); + + if (IS_ACTIVE_IN_SCENE != IS_RP3D_BODY_ACTIVE) + physicsObject.GetRigidBody()->setIsActive(IS_ACTIVE_IN_SCENE); + } + + void SHPhysicsSystem::PhysicsPreUpdate::syncColliderActive(EntityID eid, SHPhysicsObject& physicsObject) const noexcept + { + const auto* COLLIDER = SHComponentManager::GetComponent_s(eid); + if (!COLLIDER) + return; + + const bool IS_ACTIVE_IN_SCENE = SHSceneManager::CheckNodeAndComponentsActive(eid); + const bool IS_RP3D_COLLIDER_ACTIVE = physicsObject.collidersActive; + + if (IS_ACTIVE_IN_SCENE != IS_RP3D_COLLIDER_ACTIVE) + { + // HACK: If active state turned off, remove all collision shapes. If turned on, add them back. + auto* physicsSystem = reinterpret_cast(GetSystem()); + + const int NUM_SHAPES = static_cast(COLLIDER->GetCollisionShapes().size()); + if (IS_ACTIVE_IN_SCENE) + { + for (int i = 0; i < NUM_SHAPES; ++i) + physicsSystem->objectManager.AddCollisionShape(eid, i); + } + else + { + for (int i = NUM_SHAPES - 1; i >= 0; --i) + physicsSystem->objectManager.RemoveCollisionShape(eid, i); + } + + physicsObject.collidersActive = IS_ACTIVE_IN_SCENE; + } + } + void SHPhysicsSystem::PhysicsPreUpdate::syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept { auto* transformComponent = SHComponentManager::GetComponent_s(eid);