feat(physics): added collision detection with Touched/TouchEnded
This commit is contained in:
parent
e0ac5398f3
commit
cc87d08dad
6 changed files with 60 additions and 13 deletions
|
@ -88,8 +88,6 @@ protected:
|
|||
// NOTE: This value is not necessarily present if dataModel is present
|
||||
// Objects under services other than workspace will NOT have this field set
|
||||
std::optional<std::shared_ptr<Workspace>> workspace();
|
||||
|
||||
template <typename T> inline std::shared_ptr<T> shared() { return std::dynamic_pointer_cast<T>(this->shared_from_this()); }
|
||||
public:
|
||||
const static InstanceType TYPE;
|
||||
std::string name;
|
||||
|
@ -108,6 +106,8 @@ public:
|
|||
bool IsA(std::string className);
|
||||
template <typename T> bool IsA() { return IsA(T::TYPE.className); }
|
||||
|
||||
template <typename T> inline std::shared_ptr<T> shared() { return std::dynamic_pointer_cast<T>(this->shared_from_this()); }
|
||||
|
||||
DescendantsIterator GetDescendantsStart();
|
||||
DescendantsIterator GetDescendantsEnd();
|
||||
// Utility functions
|
||||
|
|
|
@ -60,8 +60,6 @@ void Part::onUpdated(std::string property) {
|
|||
// When position/rotation/size is manually edited, break all joints, they don't apply anymore
|
||||
if (property != "Anchored")
|
||||
BreakJoints();
|
||||
|
||||
OnParentUpdated->Fire();
|
||||
}
|
||||
|
||||
// Expands provided extents to fit point
|
||||
|
|
|
@ -92,7 +92,8 @@ public:
|
|||
DEF_PROP float frontParamB = 0.5;
|
||||
DEF_PROP float backParamB = 0.5;
|
||||
|
||||
DEF_SIGNAL SignalSource OnParentUpdated;
|
||||
DEF_SIGNAL SignalSource Touched;
|
||||
DEF_SIGNAL SignalSource TouchEnded;
|
||||
|
||||
rp::RigidBody* rigidBody = nullptr;
|
||||
|
||||
|
|
|
@ -15,9 +15,14 @@ int script_wait(lua_State*);
|
|||
int script_delay(lua_State*);
|
||||
|
||||
Script::Script(): Instance(&TYPE) {
|
||||
source = "workspace.Part.OnParentUpdated:Connect(function()\n\
|
||||
print(\"Yeux d'enfants\")\n\
|
||||
end)";
|
||||
source = "workspace.Part.Touched:Connect(function(otherPart)\n"
|
||||
" print(\"Touched by: \", otherPart.Name)\n"
|
||||
"end)\n"
|
||||
"\n"
|
||||
"workspace.Part.TouchEnded:Connect(function(otherPart)\n"
|
||||
" print(\"Touched ended with: \", otherPart.Name)\n"
|
||||
"end)\n"
|
||||
"\n";
|
||||
}
|
||||
|
||||
Script::~Script() {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include "workspace.h"
|
||||
#include "datatypes/meta.h"
|
||||
#include "datatypes/ref.h"
|
||||
#include "datatypes/vector.h"
|
||||
#include "objects/base/instance.h"
|
||||
#include "objects/jointsservice.h"
|
||||
|
@ -6,11 +8,12 @@
|
|||
#include "objects/datamodel.h"
|
||||
#include "physics/util.h"
|
||||
#include <memory>
|
||||
#include <reactphysics3d/collision/CollisionCallback.h>
|
||||
#include <reactphysics3d/engine/PhysicsCommon.h>
|
||||
|
||||
rp::PhysicsCommon* Workspace::physicsCommon = new rp::PhysicsCommon;
|
||||
|
||||
Workspace::Workspace(): Service(&TYPE) {
|
||||
Workspace::Workspace(): Service(&TYPE), physicsEventListener(this) {
|
||||
}
|
||||
|
||||
Workspace::~Workspace() {
|
||||
|
@ -18,6 +21,27 @@ Workspace::~Workspace() {
|
|||
physicsCommon->destroyPhysicsWorld(physicsWorld);
|
||||
}
|
||||
|
||||
PhysicsEventListener::PhysicsEventListener(Workspace* parent) : workspace(parent) {}
|
||||
|
||||
void PhysicsEventListener::onContact(const rp::CollisionCallback::CallbackData& data) {
|
||||
for (int i = 0; i < data.getNbContactPairs(); i++) {
|
||||
auto pair = data.getContactPair(i);
|
||||
auto type = pair.getEventType();
|
||||
if (type == rp::CollisionCallback::ContactPair::EventType::ContactStay) continue;
|
||||
|
||||
auto part0 = reinterpret_cast<Part*>(pair.getBody1()->getUserData())->shared<Part>();
|
||||
auto part1 = reinterpret_cast<Part*>(pair.getBody2()->getUserData())->shared<Part>();
|
||||
|
||||
if (type == reactphysics3d::CollisionCallback::ContactPair::EventType::ContactStart) {
|
||||
part0->Touched->Fire({ (Data::Variant)Data::InstanceRef(part1) });
|
||||
part1->Touched->Fire({ (Data::Variant)Data::InstanceRef(part0) });
|
||||
} else if (type == reactphysics3d::CollisionCallback::ContactPair::EventType::ContactExit) {
|
||||
part0->TouchEnded->Fire({ (Data::Variant)Data::InstanceRef(part1) });
|
||||
part1->TouchEnded->Fire({ (Data::Variant)Data::InstanceRef(part0) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Workspace::InitService() {
|
||||
if (initialized) return;
|
||||
initialized = true;
|
||||
|
@ -31,7 +55,7 @@ void Workspace::InitService() {
|
|||
// physicsWorld->setSleepLinearVelocity(10);
|
||||
// physicsWorld->setSleepAngularVelocity(5);
|
||||
|
||||
// physicsWorld->setEventListener(&eventListener);
|
||||
physicsWorld->setEventListener(&physicsEventListener);
|
||||
|
||||
// Sync all parts
|
||||
for (auto it = this->GetDescendantsStart(); it != this->GetDescendantsEnd(); it++) {
|
||||
|
@ -71,10 +95,17 @@ void Workspace::SyncPartPhysics(std::shared_ptr<Part> part) {
|
|||
|
||||
rp::BoxShape* shape = physicsCommon->createBoxShape(glmToRp(part->size * glm::vec3(0.5f)));
|
||||
|
||||
if (part->rigidBody->getNbColliders() > 0)
|
||||
// Recreate the rigidbody if the shape changes
|
||||
if (part->rigidBody->getNbColliders() > 0
|
||||
&& dynamic_cast<rp::BoxShape*>(part->rigidBody->getCollider(0)->getCollisionShape())->getHalfExtents() != shape->getHalfExtents()) {
|
||||
// TODO: This causes Touched to get called twice. Fix this.
|
||||
part->rigidBody->removeCollider(part->rigidBody->getCollider(0));
|
||||
|
||||
part->rigidBody->addCollider(shape, rp::Transform());
|
||||
}
|
||||
|
||||
if (part->rigidBody->getNbColliders() == 0)
|
||||
part->rigidBody->addCollider(shape, rp::Transform());
|
||||
|
||||
part->rigidBody->setType(part->anchored ? rp::BodyType::STATIC : rp::BodyType::DYNAMIC);
|
||||
part->rigidBody->getCollider(0)->setCollisionCategoryBits(0b11);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <glm/ext/vector_float3.hpp>
|
||||
#include <memory>
|
||||
#include <reactphysics3d/body/RigidBody.h>
|
||||
#include <reactphysics3d/engine/EventListener.h>
|
||||
#include <reactphysics3d/engine/PhysicsCommon.h>
|
||||
#include <reactphysics3d/engine/PhysicsWorld.h>
|
||||
|
||||
|
@ -35,11 +36,22 @@ class RotateV;
|
|||
|
||||
typedef std::function<FilterResult(std::shared_ptr<Part>)> RaycastFilter;
|
||||
|
||||
class Workspace;
|
||||
class PhysicsEventListener : public rp::EventListener {
|
||||
friend Workspace;
|
||||
Workspace* workspace;
|
||||
|
||||
PhysicsEventListener(Workspace*);
|
||||
|
||||
void onContact(const rp::CollisionCallback::CallbackData&) override;
|
||||
};
|
||||
|
||||
class DEF_INST_SERVICE_(explorer_icon="workspace") Workspace : public Service {
|
||||
AUTOGEN_PREAMBLE
|
||||
|
||||
rp::PhysicsWorld* physicsWorld = nullptr;
|
||||
static rp::PhysicsCommon* physicsCommon;
|
||||
PhysicsEventListener physicsEventListener;
|
||||
|
||||
friend Part;
|
||||
friend Snap;
|
||||
|
|
Loading…
Add table
Reference in a new issue