Ver código fonte

Fix to AudioBuffer (buffers weren't being removed from the global cache when they were destroyed) - (also, changed tabs to spaces).
Added Game::updateOnce (useful for animating loading screens).
Fixed a bug where AudioSource, ParticleEmitter, and Model objects could not be reused across Node object lifetimes.
Minor optimization in ParticleEmitter.
Changed PhysicsController::rayTest to take a distance parameter (old implementation would not work in most cases).
Changed the rendering of the Slider to be more general (should work with more themes, but needs more testing).
Fixed a memory leak issue with SpriteBatch.

Chris Culy 14 anos atrás
pai
commit
a9fc4bb7d1

+ 48 - 37
gameplay/src/AudioBuffer.cpp

@@ -25,6 +25,17 @@ AudioBuffer::AudioBuffer(const char* path) : _filePath(path)
 
 
 AudioBuffer::~AudioBuffer()
 AudioBuffer::~AudioBuffer()
 {
 {
+    // Remove the buffer from the cache.
+    unsigned int bufferCount = (unsigned int)__buffers.size();
+    for (unsigned int i = 0; i < bufferCount; i++)
+    {
+        if (this == __buffers[i])
+        {
+            __buffers.erase(__buffers.begin() + i);
+            break;
+        }
+    }
+
 #ifndef __ANDROID__
 #ifndef __ANDROID__
     if (_alBuffer)
     if (_alBuffer)
     {
     {
@@ -247,40 +258,40 @@ bool AudioBuffer::loadWav(FILE* file, ALuint buffer)
     // Check against the size of the format header as there may be more data that we need to read
     // Check against the size of the format header as there may be more data that we need to read
     if (section_size > 16)
     if (section_size > 16)
     {
     {
-    	unsigned int length = section_size - 16;
+        unsigned int length = section_size - 16;
 
 
-    	// extension size is 2 bytes
-    	if (fread(stream, 1, length, file) != length)
-    		return false;
+        // extension size is 2 bytes
+        if (fread(stream, 1, length, file) != length)
+            return false;
     }
     }
 
 
     if (fread(stream, 1, 4, file) != 4)
     if (fread(stream, 1, 4, file) != 4)
-    	return false;
+        return false;
 
 
     // read the next chunk, could be fact section or the data section
     // read the next chunk, could be fact section or the data section
     if (memcmp(stream, "fact", 4) == 0)
     if (memcmp(stream, "fact", 4) == 0)
     {
     {
-    	if (fread(stream, 1, 4, file) != 4)
-    		return false;
+        if (fread(stream, 1, 4, file) != 4)
+            return false;
 
 
-    	section_size  = stream[3]<<24;
-    	section_size |= stream[2]<<16;
-    	section_size |= stream[1]<<8;
-    	section_size |= stream[0];
+        section_size  = stream[3]<<24;
+        section_size |= stream[2]<<16;
+        section_size |= stream[1]<<8;
+        section_size |= stream[0];
 
 
-    	// read in the rest of the fact section
-    	if (fread(stream, 1, section_size, file) != section_size)
-    		return false;
+        // read in the rest of the fact section
+        if (fread(stream, 1, section_size, file) != section_size)
+            return false;
 
 
-    	if (fread(stream, 1, 4, file) != 4)
-    		return false;
+        if (fread(stream, 1, 4, file) != 4)
+            return false;
     }
     }
 
 
     // should now be the data section which holds the decoded sample data
     // should now be the data section which holds the decoded sample data
     if (memcmp(stream, "data", 4) != 0)
     if (memcmp(stream, "data", 4) != 0)
     {
     {
-    	LOG_ERROR("WAV file has no data.");
-    	return false;
+        LOG_ERROR("WAV file has no data.");
+        return false;
     }
     }
 
 
     // Read how much data is remaining and buffer it up.
     // Read how much data is remaining and buffer it up.
@@ -325,34 +336,34 @@ bool AudioBuffer::loadOgg(FILE* file, ALuint buffer)
     else
     else
         format = AL_FORMAT_STEREO16;
         format = AL_FORMAT_STEREO16;
 
 
-	// size = #samples * #channels * 2 (for 16 bit)
+    // size = #samples * #channels * 2 (for 16 bit)
     unsigned int data_size = ov_pcm_total(&ogg_file, -1) * info->channels * 2;
     unsigned int data_size = ov_pcm_total(&ogg_file, -1) * info->channels * 2;
     char* data = new char[data_size];
     char* data = new char[data_size];
 
 
     while (size < data_size)
     while (size < data_size)
     {
     {
-    	result = ov_read(&ogg_file, data + size, data_size - size, 0, 2, 1, &section);
-    	if (result > 0)
-    	{
-    		size += result;
-    	}
-    	else if (result < 0)
-    	{
-    		SAFE_DELETE_ARRAY(data);
-    		LOG_ERROR("OGG file missing data.");
-    		return false;
-    	}
-    	else
-    	{
-    		break;
-    	}
+        result = ov_read(&ogg_file, data + size, data_size - size, 0, 2, 1, &section);
+        if (result > 0)
+        {
+            size += result;
+        }
+        else if (result < 0)
+        {
+            SAFE_DELETE_ARRAY(data);
+            LOG_ERROR("OGG file missing data.");
+            return false;
+        }
+        else
+        {
+            break;
+        }
     }
     }
     
     
     if (size == 0)
     if (size == 0)
     {
     {
-    	SAFE_DELETE_ARRAY(data);
-    	LOG_ERROR("Unable to read OGG data.");
-    	return false;
+        SAFE_DELETE_ARRAY(data);
+        LOG_ERROR("Unable to read OGG data.");
+        return false;
     }
     }
 
 
     alBufferData(buffer, format, data, data_size, info->rate);
     alBufferData(buffer, format, data, data_size, info->rate);

+ 14 - 0
gameplay/src/Game.cpp

@@ -263,4 +263,18 @@ bool Game::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
     return false;
     return false;
 }
 }
 
 
+void Game::updateOnce()
+{
+    // Update Time.
+    static long lastFrameTime = Game::getGameTime();
+    long frameTime = Game::getGameTime();
+    long elapsedTime = (frameTime - lastFrameTime);
+    lastFrameTime = frameTime;
+
+    // Update the internal controllers.
+    _animationController->update(elapsedTime);
+    _physicsController->update(elapsedTime);
+    _audioController->update(elapsedTime);
+}
+
 }
 }

+ 15 - 0
gameplay/src/Game.h

@@ -299,6 +299,21 @@ protected:
     template <class T>
     template <class T>
     void renderOnce(T* instance, void (T::*method)(void*), void* cookie);
     void renderOnce(T* instance, void (T::*method)(void*), void* cookie);
 
 
+    /**
+     * Updates the game once.
+     *
+     * This is useful for rendering animated splash screens.
+     */
+    template <class T>
+    void updateOnce(T* instance, void (T::*method)(void*), void* cookie);
+
+    /**
+     * Updates the game once.
+     *
+     * This is useful for rendering animated splash screens.
+     */
+    void updateOnce();
+
 private:
 private:
 
 
     /**
     /**

+ 8 - 1
gameplay/src/Game.inl

@@ -40,12 +40,19 @@ inline PhysicsController* Game::getPhysicsController() const
 }
 }
 
 
 template <class T>
 template <class T>
-void  Game::renderOnce(T* instance, void (T::*method)(void*), void* cookie)
+void Game::renderOnce(T* instance, void (T::*method)(void*), void* cookie)
 {
 {
     (instance->*method)(cookie);
     (instance->*method)(cookie);
     Platform::swapBuffers();
     Platform::swapBuffers();
 }
 }
 
 
+template <class T>
+void Game::updateOnce(T* instance, void (T::*method)(void*), void* cookie)
+{
+    updateOnce();
+    (instance->*method)(cookie);
+}
+
 inline void Game::setMultiTouch(bool enabled)
 inline void Game::setMultiTouch(bool enabled)
 {
 {
     Platform::setMultiTouch(enabled);
     Platform::setMultiTouch(enabled);

+ 7 - 0
gameplay/src/Node.cpp

@@ -30,6 +30,13 @@ Node::~Node()
 {
 {
     removeAllChildren();
     removeAllChildren();
 
 
+    if (_model)
+        _model->setNode(NULL);
+    if (_audioSource)
+        _audioSource->setNode(NULL);
+    if (_particleEmitter)
+        _particleEmitter->setNode(NULL);
+
     SAFE_RELEASE(_camera);
     SAFE_RELEASE(_camera);
     SAFE_RELEASE(_light);
     SAFE_RELEASE(_light);
     SAFE_RELEASE(_model);
     SAFE_RELEASE(_model);

+ 9 - 0
gameplay/src/ParticleEmitter.cpp

@@ -240,6 +240,9 @@ bool ParticleEmitter::isActive() const
     if (_started)
     if (_started)
         return true;
         return true;
 
 
+    if (!_node)
+        return false;
+
     bool active = false;
     bool active = false;
     for (unsigned int i = 0; i < _particleCount; i++)
     for (unsigned int i = 0; i < _particleCount; i++)
     {
     {
@@ -760,6 +763,9 @@ ParticleEmitter::TextureBlending ParticleEmitter::getTextureBlendingFromString(c
 
 
 void ParticleEmitter::update(long elapsedTime)
 void ParticleEmitter::update(long elapsedTime)
 {
 {
+    if (!isActive())
+        return;
+
     // Calculate the time passed since last update.
     // Calculate the time passed since last update.
     float elapsedSecs = (float)elapsedTime / 1000.0f;
     float elapsedSecs = (float)elapsedTime / 1000.0f;
 
 
@@ -866,6 +872,9 @@ void ParticleEmitter::update(long elapsedTime)
 
 
 void ParticleEmitter::draw()
 void ParticleEmitter::draw()
 {
 {
+    if (!isActive())
+        return;
+
     if (_particleCount > 0)
     if (_particleCount > 0)
     {
     {
         // Set our node's view projection matrix to this emitter's effect.
         // Set our node's view projection matrix to this emitter's effect.

+ 3 - 3
gameplay/src/PhysicsController.cpp

@@ -129,10 +129,10 @@ void PhysicsController::drawDebug(const Matrix& viewProjection)
     _debugDrawer->end();
     _debugDrawer->end();
 }
 }
 
 
-PhysicsRigidBody* PhysicsController::rayTest(const Ray& ray)
+PhysicsRigidBody* PhysicsController::rayTest(const Ray& ray, float distance)
 {
 {
-    btCollisionWorld::ClosestRayResultCallback callback(BV(ray.getOrigin()), BV(ray.getDirection()));
-    _world->rayTest(BV(ray.getOrigin()), BV(ray.getDirection()), callback);
+    btCollisionWorld::ClosestRayResultCallback callback(BV(ray.getOrigin()), BV(distance * ray.getDirection()));
+    _world->rayTest(BV(ray.getOrigin()), BV(distance * ray.getDirection()), callback);
     if (callback.hasHit())
     if (callback.hasHit())
         return getRigidBody(callback.m_collisionObject);
         return getRigidBody(callback.m_collisionObject);
 
 

+ 2 - 1
gameplay/src/PhysicsController.h

@@ -193,9 +193,10 @@ public:
      * Gets the first rigid body that the given ray intersects.
      * Gets the first rigid body that the given ray intersects.
      * 
      * 
      * @param ray The ray to test intersection with.
      * @param ray The ray to test intersection with.
+     * @param distance How far along the given ray to test for intersections.
      * @return The first rigid body that the ray intersects.
      * @return The first rigid body that the ray intersects.
      */
      */
-    PhysicsRigidBody* rayTest(const Ray& ray);
+    PhysicsRigidBody* rayTest(const Ray& ray, float distance);
 
 
 protected:
 protected:
 
 

+ 5 - 4
gameplay/src/Slider.cpp

@@ -135,16 +135,17 @@ void Slider::drawSprites(SpriteBatch* spriteBatch, const Vector2& position)
         Vector2 pos(position.x + _position.x + border.left + padding.left, midY - trackSize.y / 2.0f);
         Vector2 pos(position.x + _position.x + border.left + padding.left, midY - trackSize.y / 2.0f);
         spriteBatch->draw(pos.x, pos.y, _size.x, trackSize.y, track.u1, track.v1, track.u2, track.v2, color);
         spriteBatch->draw(pos.x, pos.y, _size.x, trackSize.y, track.u1, track.v1, track.u2, track.v2, color);
 
 
-        pos.y = midY - minCapSize.y / 2.0f;
+        pos.y = midY - minCapSize.y * 0.5f;
+        pos.x -= minCapSize.x * 0.5f;
         spriteBatch->draw(pos.x, pos.y, minCapSize.x, minCapSize.y, minCap.u1, minCap.v1, minCap.u2, minCap.v2, color);
         spriteBatch->draw(pos.x, pos.y, minCapSize.x, minCapSize.y, minCap.u1, minCap.v1, minCap.u2, minCap.v2, color);
         
         
-        pos.x = position.x + _position.x + _size.x - border.left - padding.left - maxCapSize.x;
+        pos.x = position.x + _position.x + _size.x - border.right - padding.right - maxCapSize.x * 0.5f;
         spriteBatch->draw(pos.x, pos.y, maxCapSize.x, maxCapSize.y, maxCap.u1, maxCap.v1, maxCap.u2, maxCap.v2, color);
         spriteBatch->draw(pos.x, pos.y, maxCapSize.x, maxCapSize.y, maxCap.u1, maxCap.v1, maxCap.u2, maxCap.v2, color);
 
 
         // Percent across.
         // Percent across.
         float markerPosition = _value / (_max - _min);
         float markerPosition = _value / (_max - _min);
-        markerPosition *= _size.x - border.left - padding.left - border.right - padding.right - minCapSize.x - maxCapSize.x - markerSize.x;
-        pos.x = position.x + _position.x + border.left + padding.left +  minCapSize.x + markerPosition;
+        markerPosition *= _size.x - border.left - padding.left - border.right - padding.right - minCapSize.x * 0.5f - maxCapSize.x * 0.5f - markerSize.x;
+        pos.x = position.x + _position.x + border.left + padding.left + minCapSize.x * 0.5f + markerPosition;
         pos.y = midY - markerSize.y / 2.0f;
         pos.y = midY - markerSize.y / 2.0f;
         spriteBatch->draw(pos.x, pos.y, markerSize.x, markerSize.y, marker.u1, marker.v1, marker.u2, marker.v2, color);
         spriteBatch->draw(pos.x, pos.y, markerSize.x, markerSize.y, marker.u1, marker.v1, marker.u2, marker.v2, color);
     }
     }

+ 14 - 4
gameplay/src/SpriteBatch.cpp

@@ -69,7 +69,16 @@ SpriteBatch::SpriteBatch(const SpriteBatch& copy)
 SpriteBatch::~SpriteBatch()
 SpriteBatch::~SpriteBatch()
 {
 {
     SAFE_DELETE(_batch);
     SAFE_DELETE(_batch);
-    SAFE_RELEASE(__spriteEffect);
+    if (!_customEffect)
+    {
+        if (__spriteEffect->getRefCount() == 1)
+        {
+            __spriteEffect->release();
+            __spriteEffect = NULL;
+        }
+        else
+            __spriteEffect->release();
+    }
 }
 }
 
 
 SpriteBatch* SpriteBatch::create(const char* texturePath, Effect* effect, unsigned int initialCapacity)
 SpriteBatch* SpriteBatch::create(const char* texturePath, Effect* effect, unsigned int initialCapacity)
@@ -84,7 +93,8 @@ SpriteBatch* SpriteBatch::create(Texture* texture, Effect* effect, unsigned int
 {
 {
     assert(texture != NULL);
     assert(texture != NULL);
 
 
-    if (effect == NULL)
+    bool customEffect = (effect != NULL);
+    if (!customEffect)
     {
     {
         // Create our static sprite effect.
         // Create our static sprite effect.
         if (__spriteEffect == NULL)
         if (__spriteEffect == NULL)
@@ -141,8 +151,7 @@ SpriteBatch* SpriteBatch::create(Texture* texture, Effect* effect, unsigned int
     {
     {
         VertexFormat::Element(VertexFormat::POSITION, 3),
         VertexFormat::Element(VertexFormat::POSITION, 3),
         VertexFormat::Element(VertexFormat::TEXCOORD0, 2),
         VertexFormat::Element(VertexFormat::TEXCOORD0, 2),
-        VertexFormat::Element(VertexFormat::COLOR, 4),
-        
+        VertexFormat::Element(VertexFormat::COLOR, 4)
     };
     };
     VertexFormat vertexFormat(vertexElements, 3);
     VertexFormat vertexFormat(vertexElements, 3);
 
 
@@ -152,6 +161,7 @@ SpriteBatch* SpriteBatch::create(Texture* texture, Effect* effect, unsigned int
 
 
     // Create the batch
     // Create the batch
     SpriteBatch* batch = new SpriteBatch();
     SpriteBatch* batch = new SpriteBatch();
+    batch->_customEffect = customEffect;
     batch->_batch = meshBatch;
     batch->_batch = meshBatch;
     batch->_textureWidthRatio = 1.0f / (float)texture->getWidth();
     batch->_textureWidthRatio = 1.0f / (float)texture->getWidth();
     batch->_textureHeightRatio = 1.0f / (float)texture->getHeight();
     batch->_textureHeightRatio = 1.0f / (float)texture->getHeight();