Prechádzať zdrojové kódy

Fixes false memory leak being reported in Game as a result of declaring a vector of Gamepads. Now just store the pointer to the vector in Game and clean it up in Game::finalize().
Fixes bug where collision object's transform was not being updated when enabling physics on the collision object.
Changes PhysicsCollisionObject::setEnabled(bool) so that it does not remove the listener's on the collision object.
Asserts in PhysicsController::addCollisionObject() and PhysicsController::removeCollisionObject() that the PhysicsController is not in currently in an update.
Adds note to the collision object's listener's collisionEvent() callback to indicate that physics objects should not be removed from the physics world from within the callback.

Kieran Cunney 13 rokov pred
rodič
commit
fc49fae4d6

+ 9 - 4
gameplay/src/Game.cpp

@@ -23,6 +23,7 @@ Game::Game()
 {
     GP_ASSERT(__gameInstance == NULL);
     __gameInstance = this;
+    _gamepads = new std::vector<Gamepad*>;
     _timeEvents = new std::priority_queue<TimeEvent, std::vector<TimeEvent>, std::less<TimeEvent> >();
 }
 
@@ -148,11 +149,15 @@ void Game::shutdown()
         Platform::signalShutdown();
         finalize();
         
-        for (std::vector<Gamepad*>::iterator itr = _gamepads.begin(); itr != _gamepads.end(); itr++)
+        std::vector<Gamepad*>::iterator itr = _gamepads->begin();
+        std::vector<Gamepad*>::iterator end = _gamepads->end();
+        while (itr != end)
         {
-            SAFE_DELETE((*itr));
+            SAFE_DELETE(*itr);
+            itr++;
         }
-        _gamepads.clear();
+        _gamepads->clear();
+        SAFE_DELETE(_gamepads);
         
         _animationController->finalize();
         SAFE_DELETE(_animationController);
@@ -446,7 +451,7 @@ Gamepad* Game::createGamepad(const char* gamepadId, const char* gamepadFormPath)
     GP_ASSERT(gamepadFormPath);
     Gamepad* gamepad = new Gamepad(gamepadId, gamepadFormPath);
     GP_ASSERT(gamepad);
-    _gamepads.push_back(gamepad);
+    _gamepads->push_back(gamepad);
 
     return gamepad;
 }

+ 1 - 1
gameplay/src/Game.h

@@ -503,7 +503,7 @@ private:
     AudioController* _audioController;          // Controls audio sources that are playing in the game.
     PhysicsController* _physicsController;      // Controls the simulation of a physics scene and entities.
     AudioListener* _audioListener;              // The audio listener in 3D space.
-    std::vector<Gamepad*> _gamepads;            // The connected gamepads.
+    std::vector<Gamepad*>* _gamepads;           // The connected gamepads.
     std::priority_queue<TimeEvent, std::vector<TimeEvent>, std::less<TimeEvent> >* _timeEvents;     // Contains the scheduled time events.
 
     // Note: Do not add STL object member variables on the stack; this will cause false memory leaks to be reported.

+ 4 - 4
gameplay/src/Game.inl

@@ -79,15 +79,15 @@ inline void Game::displayKeyboard(bool display)
 
 inline unsigned int Game::getGamepadCount() const
 {
-    return _gamepads.size();
+    return _gamepads->size();
 }
 
 inline Gamepad* Game::getGamepad(unsigned int index) const
 {
-    GP_ASSERT(index < _gamepads.size());
+    GP_ASSERT(index < _gamepads->size());
 
-    if (!_gamepads.empty())
-        return _gamepads[index];
+    if (!_gamepads->empty())
+        return _gamepads->at(index);
     else
         return NULL;
 }

+ 3 - 2
gameplay/src/Gamepad.cpp

@@ -56,14 +56,15 @@ Gamepad::~Gamepad()
     {
         SAFE_RELEASE((*itr));
     }
+    _joysticks.clear();
 
     for (std::vector<Button*>::iterator itr = _buttons.begin(); itr!= _buttons.end(); itr++)
     {
         SAFE_RELEASE((*itr));
     }
+    _buttons.clear();
 
-    if (_gamepadForm)
-        SAFE_RELEASE(_gamepadForm);
+    SAFE_RELEASE(_gamepadForm);
 }
 
 const char* Gamepad::getId() const

+ 2 - 1
gameplay/src/PhysicsCollisionObject.cpp

@@ -87,6 +87,7 @@ void PhysicsCollisionObject::setEnabled(bool enable)
         if (!_enabled)
         {
             Game::getInstance()->getPhysicsController()->addCollisionObject(this);
+            _motionState->updateTransformFromNode();
             _enabled = true;
         }
     }
@@ -94,7 +95,7 @@ void PhysicsCollisionObject::setEnabled(bool enable)
     {
         if (_enabled)
         {
-            Game::getInstance()->getPhysicsController()->removeCollisionObject(this);
+            Game::getInstance()->getPhysicsController()->removeCollisionObject(this, false);
             _enabled = false;
         }
     }

+ 4 - 1
gameplay/src/PhysicsCollisionObject.h

@@ -110,6 +110,9 @@ public:
         /**
          * Called when a collision occurs between two objects in the physics world.
          * 
+         * NOTE: You are not permitted to disable physics objects from within this callback. Disabling physics on a collision object
+         *  removes the object from the physics world. This is not permitted during the PhysicsController::update.
+         *
          * @param type The type of collision event.
          * @param collisionPair The two collision objects involved in the collision.
          * @param contactPointA The contact point with the first object (in world space).
@@ -176,7 +179,7 @@ public:
     bool isEnabled() const;
 
     /**
-     * Sets the collision object be enabled or disabled.
+     * Sets the collision object to be enabled or disabled.
      *
      * @param enable true enables the collision object, false disables it.
      */

+ 13 - 6
gameplay/src/PhysicsController.cpp

@@ -23,7 +23,7 @@ PhysicsController::PhysicsController()
   : _collisionConfiguration(NULL), _dispatcher(NULL),
     _overlappingPairCache(NULL), _solver(NULL), _world(NULL), _ghostPairCallback(NULL),
     _debugDrawer(NULL), _status(PhysicsController::Listener::DEACTIVATED), _listeners(NULL),
-    _gravity(btScalar(0.0), btScalar(-9.8), btScalar(0.0)), _collisionCallback(NULL)
+    _gravity(btScalar(0.0), btScalar(-9.8), btScalar(0.0)), _collisionCallback(NULL), _isUpdating(false)
 {
     // Default gravity is 9.8 along the negative Y axis.
     _collisionCallback = new CollisionCallback(this);
@@ -464,6 +464,7 @@ void PhysicsController::resume()
 void PhysicsController::update(float elapsedTime)
 {
     GP_ASSERT(_world);
+    _isUpdating = true;
 
     // Update the physics simulation, with a maximum
     // of 10 simulation steps being performed in a given frame.
@@ -575,6 +576,8 @@ void PhysicsController::update(float elapsedTime)
             iter->second._status &= ~COLLISION;
         }
     }
+
+    _isUpdating = false;
 }
 
 void PhysicsController::addCollisionListener(PhysicsCollisionObject::CollisionListener* listener, PhysicsCollisionObject* objectA, PhysicsCollisionObject* objectB)
@@ -634,10 +637,11 @@ void PhysicsController::addCollisionObject(PhysicsCollisionObject* object)
     }
 }
 
-void PhysicsController::removeCollisionObject(PhysicsCollisionObject* object)
+void PhysicsController::removeCollisionObject(PhysicsCollisionObject* object, bool removeListeners)
 {
     GP_ASSERT(object);
     GP_ASSERT(_world);
+    GP_ASSERT(!_isUpdating);
 
     // Remove the collision object from the world.
     if (object->getCollisionObject())
@@ -660,11 +664,14 @@ void PhysicsController::removeCollisionObject(PhysicsCollisionObject* object)
     }
 
     // Find all references to the object in the collision status cache and mark them for removal.
-    std::map<PhysicsCollisionObject::CollisionPair, CollisionInfo>::iterator iter = _collisionStatus.begin();
-    for (; iter != _collisionStatus.end(); iter++)
+    if (removeListeners)
     {
-        if (iter->first.objectA == object || iter->first.objectB == object)
-            iter->second._status |= REMOVE;
+        std::map<PhysicsCollisionObject::CollisionPair, CollisionInfo>::iterator iter = _collisionStatus.begin();
+        for (; iter != _collisionStatus.end(); iter++)
+        {
+            if (iter->first.objectA == object || iter->first.objectB == object)
+                iter->second._status |= REMOVE;
+        }
     }
 }
 

+ 2 - 1
gameplay/src/PhysicsController.h

@@ -407,7 +407,7 @@ private:
     void addCollisionObject(PhysicsCollisionObject* object);
     
     // Removes the given collision object from the simulated physics world.
-    void removeCollisionObject(PhysicsCollisionObject* object);
+    void removeCollisionObject(PhysicsCollisionObject* object, bool removeListeners);
     
     // Gets the corresponding GamePlay object for the given Bullet object.
     PhysicsCollisionObject* getCollisionObject(const btCollisionObject* collisionObject) const;
@@ -534,6 +534,7 @@ private:
     Vector3 _gravity;
     std::map<PhysicsCollisionObject::CollisionPair, CollisionInfo> _collisionStatus;
     CollisionCallback* _collisionCallback;
+    bool _isUpdating;
 
 };
 

+ 1 - 1
gameplay/src/PhysicsGhostObject.cpp

@@ -39,7 +39,7 @@ PhysicsGhostObject::~PhysicsGhostObject()
     _node->removeListener(this);
 
     GP_ASSERT(Game::getInstance()->getPhysicsController());
-    Game::getInstance()->getPhysicsController()->removeCollisionObject(this);
+    Game::getInstance()->getPhysicsController()->removeCollisionObject(this, true);
 
     SAFE_DELETE(_ghostObject);
 }

+ 8 - 1
gameplay/src/PhysicsRigidBody.cpp

@@ -73,7 +73,7 @@ PhysicsRigidBody::~PhysicsRigidBody()
     }
 
     // Remove collision object from physics controller.
-    Game::getInstance()->getPhysicsController()->removeCollisionObject(this);
+    Game::getInstance()->getPhysicsController()->removeCollisionObject(this, true);
 
     // Clean up the rigid body and its related objects.
     SAFE_DELETE(_body);
@@ -258,6 +258,13 @@ void PhysicsRigidBody::setKinematic(bool kinematic)
     }
 }
 
+void PhysicsRigidBody::setEnabled(bool enable)
+{
+    PhysicsCollisionObject::setEnabled(enable);
+    if (enable)
+        _body->setMotionState(_motionState);
+}
+
 float PhysicsRigidBody::getHeight(float x, float y) const
 {
     GP_ASSERT(_collisionShape);

+ 7 - 0
gameplay/src/PhysicsRigidBody.h

@@ -218,6 +218,13 @@ public:
      */
     void setKinematic(bool kinematic);
 
+    /**
+     * Sets whether the rigid body is enabled or disabled in the physics world.
+     *
+     * @param enable true enables the collision object, false disables it.
+     */
+    void setEnabled(bool enable);
+
     /**
      * Gets the height at the given point (only for rigid bodies of type HEIGHTFIELD).
      *