Files
ogre-prototype/src/gamedata/EventTriggerModule.cpp

363 lines
9.7 KiB
C++

#include <iostream>
#include <OgreMeshManager.h>
#include "Components.h"
#include "GameData.h"
#include "LuaData.h"
#include "EventModule.h"
#include "EventTriggerModule.h"
#include <tracy/Tracy.hpp>
struct TriggerBody {
void *data;
};
#if 0
struct TriggerBody {
btPairCachingGhostObject *mBody;
btCylinderShape *shape;
Ogre::SceneNode *mSceneNode;
std::set<const btCollisionObject *> contactBodies;
};
struct DeepPenetrationContactResultCallback : public btManifoldResult {
DeepPenetrationContactResultCallback(
const btCollisionObjectWrapper *body0Wrap,
const btCollisionObjectWrapper *body1Wrap)
: btManifoldResult(body0Wrap, body1Wrap)
, mPenetrationDistance(0)
, mOtherIndex(0)
{
}
float mPenetrationDistance;
int mOtherIndex;
btVector3 mNormal, mPoint;
void reset()
{
mPenetrationDistance = 0.0f;
}
bool hasHit()
{
return mPenetrationDistance < 0.0f;
}
virtual void addContactPoint(const btVector3 &normalOnBInWorld,
const btVector3 &pointInWorldOnB,
btScalar depth)
{
#ifdef VDEBUG
std::cout
<< "contact: " << Ogre::Bullet::convert(pointInWorldOnB)
<< " " << Ogre::Bullet::convert(normalOnBInWorld)
<< "\n";
#endif
if (mPenetrationDistance > depth) { // Has penetration?
const bool isSwapped =
m_manifoldPtr->getBody0() !=
m_body0Wrap->getCollisionObject();
mPenetrationDistance = depth;
mOtherIndex = isSwapped ? m_index0 : m_index1;
mPoint = isSwapped ? (pointInWorldOnB +
(normalOnBInWorld * depth)) :
pointInWorldOnB;
mNormal = isSwapped ? normalOnBInWorld * -1 :
normalOnBInWorld;
}
}
};
#endif
ECS::EventTriggerModule::EventTriggerModule(flecs::world &ecs)
{
ecs.module<EventTriggerModule>();
ecs.component<EventTrigger>();
ecs.component<EventTriggerData>();
ecs.component<InTrigger>();
ecs.component<TriggeredBy>();
ecs.import <EventModule>();
ecs.import <LuaModule>();
ecs.observer<const EngineData, const EventTrigger>("CreateTrigger")
.event(flecs::OnSet)
.each([](flecs::entity e, const EngineData &eng,
const EventTrigger &trigger) {
ZoneScoped;
e.set<EventTriggerData>({});
e.set<EventData>({});
});
ecs.observer<const EventTrigger, EventData>("CreateTriggerEvent")
.event(flecs::OnSet)
.each([](flecs::entity e, const EventTrigger &trigger,
EventData &evt) {
ZoneScoped;
evt.add(e, "actuator_created", e, e);
});
ecs.system<const EventTrigger, EventData>("HandleEventSystem")
.kind(flecs::OnUpdate)
.each([](flecs::entity e, const EventTrigger &trigger,
EventData &evt) {
ZoneScoped;
if (e.parent().is_valid() &&
e.parent().has<EventData>()) {
bool added = false;
for (auto ev : evt.events) {
e.parent().get_mut<EventData>().add(
ev.sender, ev.event, ev.e1,
ev.e2);
added = true;
}
evt.events.clear();
if (added)
e.parent().modified<EventData>();
}
});
#if 0
ecs.component<EventTriggerData>();
ecs.component<TriggerBody>().on_add([](flecs::entity e,
TriggerBody &body) {
bool kinematic = false;
if (e.get<EventTrigger>().parent) {
body.mSceneNode =
e.get<EventTrigger>()
.parent->createChildSceneNode(
e.get<EventTrigger>().position,
Ogre::Quaternion(0, 0, 0, 1));
kinematic = true;
} else {
body.mSceneNode =
ECS::get<EngineData>()
.mScnMgr->getRootSceneNode()
->createChildSceneNode(
e.get<EventTrigger>().position,
Ogre::Quaternion(0, 0, 0, 1));
}
body.mBody = new btPairCachingGhostObject();
body.mBody->getWorldTransform().setOrigin(Ogre::Bullet::convert(
body.mSceneNode->_getDerivedPosition()));
float h = e.get<EventTrigger>().halfheight;
float r = e.get<EventTrigger>().radius;
Ogre::Vector3 position = e.get<EventTrigger>().position;
body.shape = new btCylinderShape(btVector3(r, h, r));
body.mBody->setCollisionShape(body.shape);
int flags = body.mBody->getCollisionFlags();
flags |= btCollisionObject::CF_NO_CONTACT_RESPONSE;
if (kinematic)
flags |= btCollisionObject::CF_STATIC_OBJECT;
body.mBody->setCollisionFlags(flags);
ECS::get<EngineData>().mWorld->getBtWorld()->addCollisionObject(
body.mBody, 16, 0x1);
struct EntityCollisionListener {
const Ogre::MovableObject *entity;
Ogre::Bullet::CollisionListener *listener;
};
body.mBody->setUserPointer(
new EntityCollisionListener{ nullptr, nullptr });
class CollisionObject {
protected:
btCollisionObject *mBtBody;
btCollisionWorld *mBtWorld;
public:
CollisionObject(btCollisionObject *btBody,
btCollisionWorld *btWorld)
: mBtBody(btBody)
, mBtWorld(btWorld)
{
}
virtual ~CollisionObject()
{
mBtWorld->removeCollisionObject(mBtBody);
delete mBtBody->getCollisionShape();
delete mBtBody;
}
};
auto objWrapper = std::make_shared<CollisionObject>(
body.mBody,
ECS::get<EngineData>().mWorld->getBtWorld());
body.mSceneNode->getUserObjectBindings().setUserAny(
"BtCollisionObject", objWrapper);
});
ecs.component<EventTrigger>().on_set([](flecs::entity e,
EventTrigger &ev) {
e.add<TriggerBody>();
e.set<EventTriggerData>({});
ECS::get<LuaBase>().mLua->call_handler("actuator_created", e,
e);
});
ecs.system<const EngineData, const EventTrigger, TriggerBody,
EventTriggerData>("CheckCollisions")
.kind(flecs::OnUpdate)
.each([](flecs::entity e, const EngineData &eng,
const EventTrigger &evt, TriggerBody &body,
EventTriggerData &data) {
btDispatcher *dispatch =
eng.mWorld->getBtWorld()->getDispatcher();
btHashedOverlappingPairCache *cache =
body.mBody->getOverlappingPairCache();
int i;
int count = cache->getNumOverlappingPairs();
std::set<const btCollisionObject *> currentContactBodies;
if (count > 0) {
btManifoldArray contacts;
btBroadphasePairArray &collisionPairs =
cache->getOverlappingPairArray();
for (i = 0; i < count; i++) {
contacts.resize(0);
if (collisionPairs[i].m_algorithm) {
collisionPairs[i]
.m_algorithm
->getAllContactManifolds(
contacts);
OgreAssert(false,
"Not implemented");
} else {
const btBroadphasePair *collisionPairPtr =
eng.mWorld->getBtWorld()
->getBroadphase()
->getOverlappingPairCache()
->findPair(
collisionPairs[i]
.m_pProxy0,
collisionPairs[i]
.m_pProxy1);
if (collisionPairPtr) {
const btBroadphasePair
&collisionPair =
*collisionPairPtr;
const btCollisionObject *objA = static_cast<
btCollisionObject
*>(
collisionPair
.m_pProxy0
->m_clientObject);
const btCollisionObject *objB = static_cast<
btCollisionObject
*>(
collisionPair
.m_pProxy1
->m_clientObject);
const btCollisionObject
*me,
*other;
if (objA ==
static_cast<
btCollisionObject
*>(
body.mBody)) {
me = objA;
other = objB;
} else {
me = objB;
other = objA;
}
const btCollisionShape *my_shape =
me->getCollisionShape();
const btCollisionShape *other_shape =
other->getCollisionShape();
btCollisionObjectWrapper obA(
NULL, my_shape,
body.mBody,
body.mBody
->getWorldTransform(),
-1, i);
btCollisionObjectWrapper obB(
NULL,
other_shape,
other,
other->getWorldTransform(),
-1, 0);
btCollisionAlgorithm *algorithm =
dispatch->findAlgorithm(
&obA,
&obB,
NULL,
BT_CONTACT_POINT_ALGORITHMS);
DeepPenetrationContactResultCallback
contactPointResult(
&obA,
&obB);
algorithm->processCollision(
&obA, &obB,
eng.mWorld
->getBtWorld()
->getDispatchInfo(),
&contactPointResult);
algorithm
->~btCollisionAlgorithm();
dispatch->freeCollisionAlgorithm(
algorithm);
if (contactPointResult
.hasHit()) {
currentContactBodies
.insert(other);
if (body.contactBodies
.find(other) ==
body.contactBodies
.end()) {
body.contactBodies
.insert(other);
OgreAssert(
ECS::get<
Body2Entity>()
.entities
.find(const_cast<
btCollisionObject
*>(
other)) !=
ECS::get<
Body2Entity>()
.entities
.end(),
"No body to entity mapping");
flecs::entity obj_e =
ECS::get<
Body2Entity>()
.entities
.at(const_cast<
btCollisionObject
*>(
other));
ECS::get<
LuaBase>()
.mLua
->call_handler(
evt.event +
"_enter",
e,
obj_e);
obj_e.add<
InTrigger>(
e);
e.add<TriggeredBy>(
obj_e);
}
}
}
}
}
}
std::set<const btCollisionObject *>::iterator it =
body.contactBodies.begin();
while (it != body.contactBodies.end()) {
if (currentContactBodies.find(*it) ==
currentContactBodies.end()) {
flecs::entity obj_e =
ECS::get<Body2Entity>()
.entities
.at(const_cast<
btCollisionObject
*>(
*it));
ECS::get<LuaBase>().mLua->call_handler(
evt.event + "_exit", e, obj_e);
obj_e.remove<InTrigger>(e);
e.remove<TriggeredBy>(obj_e);
std::cout << "body exited" << std::endl;
it = body.contactBodies.erase(it);
if (it == body.contactBodies.end())
break;
}
it++;
}
});
#endif
}