From c119fb6e51b07faec288c5b20739b773f24cc748 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Thu, 16 Oct 2008 23:33:40 +0000 Subject: BGE showstopper bug fix: - Reset hit object pointer at end of frame of touch sensor to avoid returning invalid pointer to getHitObject(). - Clear all references in KX_TouchSensor::m_colliders when the sensor is disabled to avoid loose references. - Test GetSGNode() systematically for all KX_GameObject functions that can be called from python in case a python controller keeps a reference in GameLogic (bad practice anyway). --- source/gameengine/Ketsji/KX_GameObject.cpp | 57 ++++++++++++++++++++------ source/gameengine/Ketsji/KX_Scene.cpp | 5 ++- source/gameengine/Ketsji/KX_TouchSensor.cpp | 8 ++++ source/gameengine/Ketsji/KX_TouchSensor.h | 1 + source/gameengine/Ketsji/KX_VehicleWrapper.cpp | 43 ++++++++++--------- 5 files changed, 80 insertions(+), 34 deletions(-) (limited to 'source/gameengine') diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 1b57b9acc1d..8b2feca53a3 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -214,7 +214,8 @@ KX_GameObject* KX_GameObject::GetParent() void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) { - if (obj && GetSGNode()->GetSGParent() != obj->GetSGNode()) + // check on valid node in case a python controller holds a reference to a deleted object + if (obj && GetSGNode() && obj->GetSGNode() && GetSGNode()->GetSGParent() != obj->GetSGNode()) { // Make sure the objects have some scale MT_Vector3 scale1 = NodeGetWorldScaling(); @@ -256,7 +257,8 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) void KX_GameObject::RemoveParent(KX_Scene *scene) { - if (GetSGNode()->GetSGParent()) + // check on valid node in case a python controller holds a reference to a deleted object + if (GetSGNode() && GetSGNode()->GetSGParent()) { // Set us to the right spot GetSGNode()->SetLocalScale(GetSGNode()->GetWorldScaling()); @@ -642,6 +644,10 @@ void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac) MT_Vector3 vect,ori,z,x,y; MT_Scalar len; + // check on valid node in case a python controller holds a reference to a deleted object + if (!GetSGNode()) + return; + vect = dir; len = vect.length(); if (MT_fuzzyZero(len)) @@ -785,7 +791,11 @@ MT_Vector3 KX_GameObject::GetVelocity(const MT_Point3& point) void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans) { - if (m_pPhysicsController1 && (!GetSGNode() || !GetSGNode()->GetSGParent())) + // check on valid node in case a python controller holds a reference to a deleted object + if (!GetSGNode()) + return; + + if (m_pPhysicsController1 && !GetSGNode()->GetSGParent()) { // don't update physic controller if the object is a child: // 1) the transformation will not be right @@ -794,35 +804,39 @@ void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans) m_pPhysicsController1->setPosition(trans); } - if (GetSGNode()) - GetSGNode()->SetLocalPosition(trans); + GetSGNode()->SetLocalPosition(trans); } void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot) { - if (m_pPhysicsController1 && (!GetSGNode() || !GetSGNode()->GetSGParent())) + // check on valid node in case a python controller holds a reference to a deleted object + if (!GetSGNode()) + return; + + if (m_pPhysicsController1 && !GetSGNode()->GetSGParent()) { // see note above m_pPhysicsController1->setOrientation(rot); } - if (GetSGNode()) - GetSGNode()->SetLocalOrientation(rot); + GetSGNode()->SetLocalOrientation(rot); } void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale) { - if (m_pPhysicsController1 && (!GetSGNode() || !GetSGNode()->GetSGParent())) + // check on valid node in case a python controller holds a reference to a deleted object + if (!GetSGNode()) + return; + + if (m_pPhysicsController1 && !GetSGNode()->GetSGParent()) { // see note above m_pPhysicsController1->setScaling(scale); } - - if (GetSGNode()) - GetSGNode()->SetLocalScale(scale); + GetSGNode()->SetLocalScale(scale); } @@ -880,6 +894,13 @@ void KX_GameObject::NodeUpdateGS(double time,bool bInitiator) const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const { + static MT_Matrix3x3 defaultOrientation = MT_Matrix3x3( 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0); + + // check on valid node in case a python controller holds a reference to a deleted object + if (!GetSGNode()) + return defaultOrientation; return GetSGNode()->GetWorldOrientation(); } @@ -887,6 +908,12 @@ const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const { + static MT_Vector3 defaultScaling = MT_Vector3(1.0, 1.0, 1.0); + + // check on valid node in case a python controller holds a reference to a deleted object + if (!GetSGNode()) + return defaultScaling; + return GetSGNode()->GetWorldScaling(); } @@ -894,6 +921,12 @@ const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const const MT_Point3& KX_GameObject::NodeGetWorldPosition() const { + static MT_Point3 defaultPosition = MT_Point3(0.0, 0.0, 0.0); + + // check on valid node in case a python controller holds a reference to a deleted object + if (!GetSGNode()) + return defaultPosition; + return GetSGNode()->GetWorldPosition(); } diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index f5d6d7e8e0a..caa71441b1d 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -614,7 +614,8 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) GroupObject *go; vector duplilist; - if (!groupobj->IsDupliGroup() || + if (!groupobj->GetSGNode() || + !groupobj->IsDupliGroup() || level>MAX_DUPLI_RECUR) return; @@ -1232,7 +1233,7 @@ void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool vi void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Camera* cam,int layer) { // User (Python/Actuator) has forced object invisible... - if (!gameobj->GetVisible()) + if (!gameobj->GetSGNode() || !gameobj->GetVisible()) return; // Shadow lamp layers diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index 41757a23f7a..2802da2723d 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -55,9 +55,17 @@ void KX_TouchSensor::SynchronizeTransform() void KX_TouchSensor::EndFrame() { m_colliders->ReleaseAndRemoveAll(); + m_hitObject = NULL; m_bTriggered = false; } +void KX_TouchSensor::UnregisterToManager() +{ + // before unregistering the sensor, make sure we release all references + EndFrame(); + m_eventmgr->RemoveSensor(this); +} + bool KX_TouchSensor::Evaluate(CValue* event) { bool result = false; diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h index b611d296939..8fbb1c676ba 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.h +++ b/source/gameengine/Ketsji/KX_TouchSensor.h @@ -77,6 +77,7 @@ public: virtual void RegisterSumo(KX_TouchEventManager* touchman); virtual void UnregisterSumo(KX_TouchEventManager* touchman); + virtual void UnregisterToManager(); // virtual DT_Bool HandleCollision(void* obj1,void* obj2, // const DT_CollData * coll_data); diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index 342e71c5093..028f96f6c5b 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -49,26 +49,29 @@ PyObject* KX_VehicleWrapper::PyAddWheel(PyObject* self, if (PyArg_ParseTuple(args,"OOOOffi",&wheelGameObject,&pylistPos,&pylistDir,&pylistAxleDir,&suspensionRestLength,&wheelRadius,&hasSteering)) { KX_GameObject* gameOb = (KX_GameObject*) wheelGameObject; - - PHY_IMotionState* motionState = new KX_MotionState(gameOb->GetSGNode()); - - MT_Vector3 attachPos,attachDir,attachAxle; - PyVecTo(pylistPos,attachPos); - PyVecTo(pylistDir,attachDir); - PyVecTo(pylistAxleDir,attachAxle); - PHY__Vector3 aPos,aDir,aAxle; - aPos[0] = attachPos[0]; - aPos[1] = attachPos[1]; - aPos[2] = attachPos[2]; - aDir[0] = attachDir[0]; - aDir[1] = attachDir[1]; - aDir[2] = attachDir[2]; - aAxle[0] = -attachAxle[0];//someone reverse some conventions inside Bullet (axle winding) - aAxle[1] = -attachAxle[1]; - aAxle[2] = -attachAxle[2]; - - printf("attempt for addWheel: suspensionRestLength%f wheelRadius %f, hasSteering:%d\n",suspensionRestLength,wheelRadius,hasSteering); - m_vehicle->AddWheel(motionState,aPos,aDir,aAxle,suspensionRestLength,wheelRadius,hasSteering); + + if (gameOb->GetSGNode()) + { + PHY_IMotionState* motionState = new KX_MotionState(gameOb->GetSGNode()); + + MT_Vector3 attachPos,attachDir,attachAxle; + PyVecTo(pylistPos,attachPos); + PyVecTo(pylistDir,attachDir); + PyVecTo(pylistAxleDir,attachAxle); + PHY__Vector3 aPos,aDir,aAxle; + aPos[0] = attachPos[0]; + aPos[1] = attachPos[1]; + aPos[2] = attachPos[2]; + aDir[0] = attachDir[0]; + aDir[1] = attachDir[1]; + aDir[2] = attachDir[2]; + aAxle[0] = -attachAxle[0];//someone reverse some conventions inside Bullet (axle winding) + aAxle[1] = -attachAxle[1]; + aAxle[2] = -attachAxle[2]; + + printf("attempt for addWheel: suspensionRestLength%f wheelRadius %f, hasSteering:%d\n",suspensionRestLength,wheelRadius,hasSteering); + m_vehicle->AddWheel(motionState,aPos,aDir,aAxle,suspensionRestLength,wheelRadius,hasSteering); + } } else { return NULL; -- cgit v1.2.3