2012-03-14 14:55:17 +08:00
/*
* Copyright ( C ) 2009 Matt Oswald
* Copyright ( c ) 2009 - 2010 Ricardo Quesada
2014-01-07 11:25:07 +08:00
* Copyright ( c ) 2010 - 2012 cocos2d - x . org
* Copyright ( c ) 2011 Zynga Inc .
* Copyright ( c ) 2011 Marco Tillemans
* Copyright ( c ) 2013 - 2014 Chukong Technologies Inc .
2012-03-14 14:55:17 +08:00
*
* http : //www.cocos2d-x.org
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*
*/
# include "CCParticleBatchNode.h"
2013-10-14 14:01:00 +08:00
# include "CCTextureCache.h"
# include "CCTextureAtlas.h"
2012-03-14 14:55:17 +08:00
# include "ccConfig.h"
# include "ccMacros.h"
2013-10-14 14:01:00 +08:00
# include "CCGrid.h"
2012-03-14 14:55:17 +08:00
# include "CCParticleSystem.h"
2013-10-14 14:01:00 +08:00
# include "CCShaderCache.h"
# include "CCGLProgram.h"
# include "ccGLStateCache.h"
# include "base64.h"
# include "ZipUtils.h"
2012-06-19 16:20:46 +08:00
# include "platform/CCFileUtils.h"
2012-03-14 14:55:17 +08:00
# include "kazmath/GL/matrix.h"
2013-10-14 14:01:00 +08:00
# include "CCProfiling.h"
2013-12-26 16:36:03 +08:00
# include "renderer/CCQuadCommand.h"
2014-01-17 13:35:58 +08:00
# include "renderer/CCRenderer.h"
2012-03-29 11:25:08 +08:00
2012-03-14 14:55:17 +08:00
NS_CC_BEGIN
2013-06-20 14:13:12 +08:00
ParticleBatchNode : : ParticleBatchNode ( )
2013-12-18 17:47:20 +08:00
: _textureAtlas ( nullptr )
2012-03-14 14:55:17 +08:00
{
}
2013-06-20 14:13:12 +08:00
ParticleBatchNode : : ~ ParticleBatchNode ( )
2012-03-14 14:55:17 +08:00
{
2013-06-15 14:03:30 +08:00
CC_SAFE_RELEASE ( _textureAtlas ) ;
2012-03-14 14:55:17 +08:00
}
/*
2013-06-20 14:13:12 +08:00
* creation with Texture2D
2012-03-14 14:55:17 +08:00
*/
2013-11-15 09:19:16 +08:00
ParticleBatchNode * ParticleBatchNode : : createWithTexture ( Texture2D * tex , int capacity /* = kParticleDefaultCapacity*/ )
2012-03-14 14:55:17 +08:00
{
2013-06-20 14:13:12 +08:00
ParticleBatchNode * p = new ParticleBatchNode ( ) ;
2012-04-19 14:35:52 +08:00
if ( p & & p - > initWithTexture ( tex , capacity ) )
{
p - > autorelease ( ) ;
return p ;
}
CC_SAFE_DELETE ( p ) ;
2013-12-18 17:47:20 +08:00
return nullptr ;
2012-03-14 14:55:17 +08:00
}
/*
* creation with File Image
*/
2013-11-15 09:19:16 +08:00
ParticleBatchNode * ParticleBatchNode : : create ( const std : : string & imageFile , int capacity /* = kParticleDefaultCapacity*/ )
2012-03-14 14:55:17 +08:00
{
2013-06-20 14:13:12 +08:00
ParticleBatchNode * p = new ParticleBatchNode ( ) ;
2012-06-14 15:13:16 +08:00
if ( p & & p - > initWithFile ( imageFile , capacity ) )
2012-04-19 14:35:52 +08:00
{
p - > autorelease ( ) ;
return p ;
}
CC_SAFE_DELETE ( p ) ;
2013-12-18 17:47:20 +08:00
return nullptr ;
2012-03-14 14:55:17 +08:00
}
/*
2013-06-20 14:13:12 +08:00
* init with Texture2D
2012-03-14 14:55:17 +08:00
*/
2013-11-15 09:19:16 +08:00
bool ParticleBatchNode : : initWithTexture ( Texture2D * tex , int capacity )
2012-03-14 14:55:17 +08:00
{
2013-06-20 14:13:12 +08:00
_textureAtlas = new TextureAtlas ( ) ;
2013-06-15 14:03:30 +08:00
_textureAtlas - > initWithTexture ( tex , capacity ) ;
2012-03-14 14:55:17 +08:00
2013-12-05 10:35:10 +08:00
_children . reserve ( capacity ) ;
2013-11-28 16:02:03 +08:00
2013-07-26 08:47:42 +08:00
_blendFunc = BlendFunc : : ALPHA_PREMULTIPLIED ;
2012-03-14 14:55:17 +08:00
2013-09-16 20:38:03 +08:00
setShaderProgram ( ShaderCache : : getInstance ( ) - > getProgram ( GLProgram : : SHADER_NAME_POSITION_TEXTURE_COLOR ) ) ;
2013-11-30 01:09:38 +08:00
2012-04-19 14:35:52 +08:00
return true ;
2012-03-14 14:55:17 +08:00
}
/*
* init with FileImage
*/
2013-11-15 09:19:16 +08:00
bool ParticleBatchNode : : initWithFile ( const std : : string & fileImage , int capacity )
2012-03-14 14:55:17 +08:00
{
2013-11-07 19:11:09 +08:00
Texture2D * tex = Director : : getInstance ( ) - > getTextureCache ( ) - > addImage ( fileImage ) ;
2012-04-19 14:35:52 +08:00
return initWithTexture ( tex , capacity ) ;
2012-03-14 14:55:17 +08:00
}
2013-06-20 14:13:12 +08:00
// ParticleBatchNode - composition
2012-03-14 14:55:17 +08:00
// override visit.
// Don't call visit on it's children
2014-03-01 08:10:48 +08:00
void ParticleBatchNode : : visit ( Renderer * renderer , const kmMat4 & parentTransform , bool parentTransformUpdated )
2012-03-14 14:55:17 +08:00
{
2012-04-19 14:35:52 +08:00
// CAREFUL:
2013-06-20 14:13:12 +08:00
// This visit is almost identical to Node#visit
2012-04-19 14:35:52 +08:00
// with the exception that it doesn't call visit on it's children
//
2013-06-20 14:13:12 +08:00
// The alternative is to have a void Sprite#visit, but
2012-09-17 15:02:24 +08:00
// although this is less maintainable, is faster
2012-04-19 14:35:52 +08:00
//
2013-06-15 14:03:30 +08:00
if ( ! _visible )
2012-03-29 11:25:08 +08:00
{
2012-04-19 14:35:52 +08:00
return ;
2012-03-29 11:25:08 +08:00
}
2012-03-14 14:55:17 +08:00
2014-03-01 08:10:48 +08:00
bool dirty = parentTransformUpdated | | _transformUpdated ;
2014-02-28 13:43:54 +08:00
if ( dirty )
2014-03-01 03:20:53 +08:00
_modelViewTransform = transform ( parentTransform ) ;
2014-03-01 08:10:48 +08:00
_transformUpdated = false ;
2014-03-01 03:20:53 +08:00
// IMPORTANT:
// To ease the migration to v3.0, we still support the kmGL stack,
// but it is deprecated and your code should not rely on it
kmGLPushMatrix ( ) ;
kmGLLoadMatrix ( & _modelViewTransform ) ;
2012-03-14 14:55:17 +08:00
2014-02-28 13:43:54 +08:00
draw ( renderer , _modelViewTransform , dirty ) ;
2013-11-30 01:09:38 +08:00
2012-04-19 14:35:52 +08:00
kmGLPopMatrix ( ) ;
2012-03-14 14:55:17 +08:00
}
// override addChild:
2013-07-26 07:27:24 +08:00
void ParticleBatchNode : : addChild ( Node * aChild , int zOrder , int tag )
2012-03-14 14:55:17 +08:00
{
2013-12-18 17:47:20 +08:00
CCASSERT ( aChild ! = nullptr , " Argument must be non-nullptr " ) ;
CCASSERT ( dynamic_cast < ParticleSystem * > ( aChild ) ! = nullptr , " CCParticleBatchNode only supports QuadParticleSystems as children " ) ;
2013-07-26 07:27:24 +08:00
ParticleSystem * child = static_cast < ParticleSystem * > ( aChild ) ;
CCASSERT ( child - > getTexture ( ) - > getName ( ) = = _textureAtlas - > getTexture ( ) - > getName ( ) , " CCParticleSystem is not using the same texture id " ) ;
2012-04-19 14:35:52 +08:00
// If this is the 1st children, then copy blending function
2013-11-28 18:23:06 +08:00
if ( _children . empty ( ) )
2012-03-27 13:48:14 +08:00
{
2013-07-26 07:27:24 +08:00
setBlendFunc ( child - > getBlendFunc ( ) ) ;
2012-04-19 14:35:52 +08:00
}
2012-03-14 14:55:17 +08:00
2013-11-30 01:09:38 +08:00
CCASSERT ( _blendFunc . src = = child - > getBlendFunc ( ) . src & & _blendFunc . dst = = child - > getBlendFunc ( ) . dst , " Can't add a ParticleSystem that uses a different blending function " ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
//no lazy sorting, so don't call super addChild, call helper instead
2013-12-05 17:19:01 +08:00
auto pos = addChildHelper ( child , zOrder , tag ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
//get new atlasIndex
2013-07-20 13:01:27 +08:00
int atlasIndex = 0 ;
2012-03-14 14:55:17 +08:00
2013-11-30 01:09:38 +08:00
if ( pos ! = 0 )
2012-03-27 13:48:14 +08:00
{
2013-12-05 10:35:10 +08:00
ParticleSystem * p = static_cast < ParticleSystem * > ( _children . at ( pos - 1 ) ) ;
2012-04-19 14:35:52 +08:00
atlasIndex = p - > getAtlasIndex ( ) + p - > getTotalParticles ( ) ;
}
else
2012-03-27 13:48:14 +08:00
{
2012-04-19 14:35:52 +08:00
atlasIndex = 0 ;
}
2012-03-14 14:55:17 +08:00
2013-07-26 07:27:24 +08:00
insertChild ( child , atlasIndex ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
// update quad info
2013-07-26 07:27:24 +08:00
child - > setBatchNode ( this ) ;
2012-03-14 14:55:17 +08:00
}
// don't use lazy sorting, reordering the particle systems quads afterwards would be too complex
// XXX research whether lazy sorting + freeing current quads and calloc a new block with size of capacity would be faster
// XXX or possibly using vertexZ for reordering, that would be fastest
2013-06-20 14:13:12 +08:00
// this helper is almost equivalent to Node's addChild, but doesn't make use of the lazy sorting
2013-12-05 17:19:01 +08:00
int ParticleBatchNode : : addChildHelper ( ParticleSystem * child , int z , int aTag )
2012-03-14 14:55:17 +08:00
{
2013-12-18 17:47:20 +08:00
CCASSERT ( child ! = nullptr , " Argument must be non-nil " ) ;
CCASSERT ( child - > getParent ( ) = = nullptr , " child already added. It can't be added again " ) ;
2012-03-14 14:55:17 +08:00
2013-12-05 10:35:10 +08:00
_children . reserve ( 4 ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
//don't use a lazy insert
2013-12-05 17:19:01 +08:00
auto pos = searchNewPositionInChildrenForZ ( z ) ;
2012-03-14 14:55:17 +08:00
2013-12-05 10:35:10 +08:00
_children . insert ( pos , child ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
child - > setTag ( aTag ) ;
2014-01-19 03:35:27 +08:00
child - > _setLocalZOrder ( z ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
child - > setParent ( this ) ;
2012-03-14 14:55:17 +08:00
2013-11-30 01:09:38 +08:00
if ( _running )
2012-03-29 11:25:08 +08:00
{
2012-04-19 14:35:52 +08:00
child - > onEnter ( ) ;
child - > onEnterTransitionDidFinish ( ) ;
}
return pos ;
2012-03-14 14:55:17 +08:00
}
// Reorder will be done in this function, no "lazy" reorder to particles
2013-07-26 07:27:24 +08:00
void ParticleBatchNode : : reorderChild ( Node * aChild , int zOrder )
2012-03-14 14:55:17 +08:00
{
2013-12-18 17:47:20 +08:00
CCASSERT ( aChild ! = nullptr , " Child must be non-nullptr " ) ;
CCASSERT ( dynamic_cast < ParticleSystem * > ( aChild ) ! = nullptr , " CCParticleBatchNode only supports QuadParticleSystems as children " ) ;
2013-12-05 10:35:10 +08:00
CCASSERT ( _children . contains ( aChild ) , " Child doesn't belong to batch " ) ;
2012-03-14 14:55:17 +08:00
2013-07-26 07:27:24 +08:00
ParticleSystem * child = static_cast < ParticleSystem * > ( aChild ) ;
2012-03-29 11:25:08 +08:00
2014-01-20 15:03:30 +08:00
if ( zOrder = = child - > getLocalZOrder ( ) )
2012-03-29 11:25:08 +08:00
{
2012-04-19 14:35:52 +08:00
return ;
}
2012-03-29 11:25:08 +08:00
2012-04-19 14:35:52 +08:00
// no reordering if only 1 child
2013-11-28 18:23:06 +08:00
if ( ! _children . empty ( ) )
2012-04-19 14:35:52 +08:00
{
2013-12-05 17:19:01 +08:00
int newIndex = 0 , oldIndex = 0 ;
2012-03-14 14:55:17 +08:00
2013-07-26 07:27:24 +08:00
getCurrentIndex ( & oldIndex , & newIndex , child , zOrder ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
if ( oldIndex ! = newIndex )
2012-03-29 11:25:08 +08:00
{
2012-03-14 14:55:17 +08:00
2013-06-15 14:03:30 +08:00
// reorder _children->array
2013-07-26 07:27:24 +08:00
child - > retain ( ) ;
2013-12-11 17:53:45 +08:00
_children . erase ( oldIndex ) ;
2013-12-05 10:35:10 +08:00
_children . insert ( newIndex , child ) ;
2013-07-26 07:27:24 +08:00
child - > release ( ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
// save old altasIndex
2013-07-26 07:27:24 +08:00
int oldAtlasIndex = child - > getAtlasIndex ( ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
// update atlas index
updateAllAtlasIndexes ( ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
// Find new AtlasIndex
2013-07-20 13:01:27 +08:00
int newAtlasIndex = 0 ;
2013-12-05 10:35:10 +08:00
for ( int i = 0 ; i < _children . size ( ) ; i + + )
2012-03-29 11:25:08 +08:00
{
2013-12-05 10:35:10 +08:00
ParticleSystem * node = static_cast < ParticleSystem * > ( _children . at ( i ) ) ;
2013-11-28 16:02:03 +08:00
if ( node = = child )
2012-03-29 11:25:08 +08:00
{
2013-07-26 07:27:24 +08:00
newAtlasIndex = child - > getAtlasIndex ( ) ;
2012-04-19 14:35:52 +08:00
break ;
}
}
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
// reorder textureAtlas quads
2013-07-26 07:27:24 +08:00
_textureAtlas - > moveQuadsFromIndex ( oldAtlasIndex , child - > getTotalParticles ( ) , newAtlasIndex ) ;
2012-03-14 14:55:17 +08:00
2013-07-26 07:27:24 +08:00
child - > updateWithNoTime ( ) ;
2012-04-19 14:35:52 +08:00
}
}
2012-03-14 14:55:17 +08:00
2014-01-19 03:35:27 +08:00
child - > _setLocalZOrder ( zOrder ) ;
2012-03-14 14:55:17 +08:00
}
2013-12-05 17:19:01 +08:00
void ParticleBatchNode : : getCurrentIndex ( int * oldIndex , int * newIndex , Node * child , int z )
2012-03-14 14:55:17 +08:00
{
2012-04-19 14:35:52 +08:00
bool foundCurrentIdx = false ;
bool foundNewIdx = false ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
int minusOne = 0 ;
2013-12-05 17:19:01 +08:00
auto count = _children . size ( ) ;
2012-03-14 14:55:17 +08:00
2013-12-05 17:19:01 +08:00
for ( int i = 0 ; i < count ; i + + )
2012-03-29 11:25:08 +08:00
{
2013-12-05 10:35:10 +08:00
Node * pNode = _children . at ( i ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
// new index
2014-01-20 15:03:30 +08:00
if ( pNode - > getLocalZOrder ( ) > z & & ! foundNewIdx )
2012-03-29 11:25:08 +08:00
{
2012-04-19 14:35:52 +08:00
* newIndex = i ;
foundNewIdx = true ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
if ( foundCurrentIdx & & foundNewIdx )
2012-03-29 11:25:08 +08:00
{
2012-04-19 14:35:52 +08:00
break ;
2012-03-29 11:25:08 +08:00
}
2012-04-19 14:35:52 +08:00
}
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
// current index
2013-11-30 01:09:38 +08:00
if ( child = = pNode )
2012-03-29 11:25:08 +08:00
{
2012-04-19 14:35:52 +08:00
* oldIndex = i ;
foundCurrentIdx = true ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
if ( ! foundNewIdx )
2012-03-29 11:25:08 +08:00
{
2012-04-19 14:35:52 +08:00
minusOne = - 1 ;
2012-03-29 11:25:08 +08:00
}
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
if ( foundCurrentIdx & & foundNewIdx )
2012-03-29 11:25:08 +08:00
{
2012-04-19 14:35:52 +08:00
break ;
2012-03-29 11:25:08 +08:00
}
2012-04-19 14:35:52 +08:00
}
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
}
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
if ( ! foundNewIdx )
2012-03-29 11:25:08 +08:00
{
2013-12-05 17:19:01 +08:00
* newIndex = static_cast < int > ( count ) ;
2012-03-29 11:25:08 +08:00
}
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
* newIndex + = minusOne ;
2012-03-14 14:55:17 +08:00
}
2013-12-05 17:19:01 +08:00
int ParticleBatchNode : : searchNewPositionInChildrenForZ ( int z )
2012-03-14 14:55:17 +08:00
{
2013-12-05 17:19:01 +08:00
auto count = _children . size ( ) ;
2012-03-14 14:55:17 +08:00
2013-12-05 17:19:01 +08:00
for ( int i = 0 ; i < count ; i + + )
2012-03-29 11:25:08 +08:00
{
2013-12-05 10:35:10 +08:00
Node * child = _children . at ( i ) ;
2014-01-20 15:03:30 +08:00
if ( child - > getLocalZOrder ( ) > z )
2012-03-29 11:25:08 +08:00
{
2012-04-19 14:35:52 +08:00
return i ;
2012-03-29 11:25:08 +08:00
}
2012-04-19 14:35:52 +08:00
}
2013-12-05 17:19:01 +08:00
return static_cast < int > ( count ) ;
2012-03-14 14:55:17 +08:00
}
// override removeChild:
2013-07-26 07:27:24 +08:00
void ParticleBatchNode : : removeChild ( Node * aChild , bool cleanup )
2012-03-14 14:55:17 +08:00
{
2012-04-19 14:35:52 +08:00
// explicit nil handling
2013-12-18 17:47:20 +08:00
if ( aChild = = nullptr )
2012-04-19 14:35:52 +08:00
return ;
2013-11-30 01:09:38 +08:00
2013-12-18 17:47:20 +08:00
CCASSERT ( dynamic_cast < ParticleSystem * > ( aChild ) ! = nullptr , " CCParticleBatchNode only supports QuadParticleSystems as children " ) ;
2013-12-05 10:35:10 +08:00
CCASSERT ( _children . contains ( aChild ) , " CCParticleBatchNode doesn't contain the sprite. Can't remove it " ) ;
2012-03-14 14:55:17 +08:00
2013-07-26 07:27:24 +08:00
ParticleSystem * child = static_cast < ParticleSystem * > ( aChild ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
// remove child helper
2013-07-26 07:27:24 +08:00
_textureAtlas - > removeQuadsAtIndex ( child - > getAtlasIndex ( ) , child - > getTotalParticles ( ) ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
// after memmove of data, empty the quads at the end of array
2013-07-26 07:27:24 +08:00
_textureAtlas - > fillWithEmptyQuadsFromIndex ( _textureAtlas - > getTotalQuads ( ) , child - > getTotalParticles ( ) ) ;
2012-03-14 14:55:17 +08:00
2012-09-17 15:02:24 +08:00
// particle could be reused for self rendering
2013-12-18 17:47:20 +08:00
child - > setBatchNode ( nullptr ) ;
2014-03-05 14:32:22 +08:00
Node : : removeChild ( child , cleanup ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
updateAllAtlasIndexes ( ) ;
2012-03-14 14:55:17 +08:00
}
2013-12-05 17:19:01 +08:00
void ParticleBatchNode : : removeChildAtIndex ( int index , bool doCleanup )
2012-03-14 14:55:17 +08:00
{
2013-12-05 10:35:10 +08:00
removeChild ( _children . at ( index ) , doCleanup ) ;
2012-03-14 14:55:17 +08:00
}
2013-06-20 14:13:12 +08:00
void ParticleBatchNode : : removeAllChildrenWithCleanup ( bool doCleanup )
2012-03-14 14:55:17 +08:00
{
2013-12-20 05:34:41 +08:00
for ( const auto & child : _children )
2013-11-28 16:02:03 +08:00
static_cast < ParticleSystem * > ( child ) - > setBatchNode ( nullptr ) ;
2012-03-14 14:55:17 +08:00
2013-06-20 14:13:12 +08:00
Node : : removeAllChildrenWithCleanup ( doCleanup ) ;
2012-03-14 14:55:17 +08:00
2013-06-15 14:03:30 +08:00
_textureAtlas - > removeAllQuads ( ) ;
2012-03-14 14:55:17 +08:00
}
2014-03-01 08:10:48 +08:00
void ParticleBatchNode : : draw ( Renderer * renderer , const kmMat4 & transform , bool transformUpdated )
2012-03-14 14:55:17 +08:00
{
2013-03-22 14:53:58 +08:00
CC_PROFILER_START ( " CCParticleBatchNode - draw " ) ;
2012-03-14 14:55:17 +08:00
2013-06-15 14:03:30 +08:00
if ( _textureAtlas - > getTotalQuads ( ) = = 0 )
2012-03-29 11:25:08 +08:00
{
2012-04-19 14:35:52 +08:00
return ;
2012-03-29 11:25:08 +08:00
}
2012-03-14 14:55:17 +08:00
2014-01-18 08:08:29 +08:00
_batchCommand . init (
2014-01-19 03:35:27 +08:00
_globalZOrder ,
2014-01-16 08:07:38 +08:00
_shaderProgram ,
_blendFunc ,
_textureAtlas ,
_modelViewTransform ) ;
2014-03-01 08:10:48 +08:00
renderer - > addCommand ( & _batchCommand ) ;
2012-04-19 14:35:52 +08:00
CC_PROFILER_STOP ( " CCParticleBatchNode - draw " ) ;
2012-03-14 14:55:17 +08:00
}
2013-12-12 12:07:20 +08:00
void ParticleBatchNode : : increaseAtlasCapacityTo ( ssize_t quantity )
2012-03-14 14:55:17 +08:00
{
2013-06-20 14:13:12 +08:00
CCLOG ( " cocos2d: ParticleBatchNode: resizing TextureAtlas capacity from [%lu] to [%lu]. " ,
2013-06-15 14:03:30 +08:00
( long ) _textureAtlas - > getCapacity ( ) ,
2012-04-19 14:35:52 +08:00
( long ) quantity ) ;
2013-06-15 14:03:30 +08:00
if ( ! _textureAtlas - > resizeCapacity ( quantity ) ) {
2012-04-19 14:35:52 +08:00
// serious problems
2012-06-08 14:11:48 +08:00
CCLOGWARN ( " cocos2d: WARNING: Not enough memory to resize the atlas " ) ;
2013-07-20 13:01:27 +08:00
CCASSERT ( false , " XXX: ParticleBatchNode #increaseAtlasCapacity SHALL handle this assert " ) ;
2012-04-19 14:35:52 +08:00
}
2012-03-14 14:55:17 +08:00
}
//sets a 0'd quad into the quads array
2013-12-05 17:19:01 +08:00
void ParticleBatchNode : : disableParticle ( int particleIndex )
2012-03-14 14:55:17 +08:00
{
2013-07-05 16:49:22 +08:00
V3F_C4B_T2F_Quad * quad = & ( ( _textureAtlas - > getQuads ( ) ) [ particleIndex ] ) ;
2012-04-19 14:35:52 +08:00
quad - > br . vertices . x = quad - > br . vertices . y = quad - > tr . vertices . x = quad - > tr . vertices . y = quad - > tl . vertices . x = quad - > tl . vertices . y = quad - > bl . vertices . x = quad - > bl . vertices . y = 0.0f ;
2012-03-14 14:55:17 +08:00
}
2013-06-20 14:13:12 +08:00
// ParticleBatchNode - add / remove / reorder helper methods
2012-03-14 14:55:17 +08:00
// add child helper
2013-07-26 07:27:24 +08:00
void ParticleBatchNode : : insertChild ( ParticleSystem * system , int index )
2012-03-14 14:55:17 +08:00
{
2013-07-26 07:27:24 +08:00
system - > setAtlasIndex ( index ) ;
2012-03-14 14:55:17 +08:00
2013-07-26 07:27:24 +08:00
if ( _textureAtlas - > getTotalQuads ( ) + system - > getTotalParticles ( ) > _textureAtlas - > getCapacity ( ) )
2012-04-19 14:35:52 +08:00
{
2013-07-26 07:27:24 +08:00
increaseAtlasCapacityTo ( _textureAtlas - > getTotalQuads ( ) + system - > getTotalParticles ( ) ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
// after a realloc empty quads of textureAtlas can be filled with gibberish (realloc doesn't perform calloc), insert empty quads to prevent it
2013-07-26 07:27:24 +08:00
_textureAtlas - > fillWithEmptyQuadsFromIndex ( _textureAtlas - > getCapacity ( ) - system - > getTotalParticles ( ) , system - > getTotalParticles ( ) ) ;
2012-04-19 14:35:52 +08:00
}
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
// make room for quads, not necessary for last child
2013-07-26 07:27:24 +08:00
if ( system - > getAtlasIndex ( ) + system - > getTotalParticles ( ) ! = _textureAtlas - > getTotalQuads ( ) )
2012-04-04 21:58:04 +08:00
{
2013-07-26 07:27:24 +08:00
_textureAtlas - > moveQuadsFromIndex ( index , index + system - > getTotalParticles ( ) ) ;
2012-04-04 21:58:04 +08:00
}
2012-03-14 14:55:17 +08:00
2012-09-17 15:02:24 +08:00
// increase totalParticles here for new particles, update method of particle-system will fill the quads
2013-07-26 07:27:24 +08:00
_textureAtlas - > increaseTotalQuadsWith ( system - > getTotalParticles ( ) ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
updateAllAtlasIndexes ( ) ;
2012-03-14 14:55:17 +08:00
}
//rebuild atlas indexes
2013-06-20 14:13:12 +08:00
void ParticleBatchNode : : updateAllAtlasIndexes ( )
2012-03-14 14:55:17 +08:00
{
2013-12-05 17:19:01 +08:00
int index = 0 ;
2013-11-28 16:02:03 +08:00
2013-12-20 05:34:41 +08:00
for ( const auto & child : _children ) {
2013-11-28 16:02:03 +08:00
ParticleSystem * partiSys = static_cast < ParticleSystem * > ( child ) ;
partiSys - > setAtlasIndex ( index ) ;
index + = partiSys - > getTotalParticles ( ) ;
2013-12-20 05:34:41 +08:00
}
2012-03-14 14:55:17 +08:00
}
2013-06-20 14:13:12 +08:00
// ParticleBatchNode - CocosNodeTexture protocol
2012-03-14 14:55:17 +08:00
2013-12-05 17:19:01 +08:00
void ParticleBatchNode : : updateBlendFunc ( )
2012-03-14 14:55:17 +08:00
{
2013-07-26 04:36:19 +08:00
if ( ! _textureAtlas - > getTexture ( ) - > hasPremultipliedAlpha ( ) )
_blendFunc = BlendFunc : : ALPHA_NON_PREMULTIPLIED ;
2012-03-14 14:55:17 +08:00
}
2013-06-20 14:13:12 +08:00
void ParticleBatchNode : : setTexture ( Texture2D * texture )
2012-03-14 14:55:17 +08:00
{
2013-06-15 14:03:30 +08:00
_textureAtlas - > setTexture ( texture ) ;
2012-04-19 14:35:52 +08:00
// If the new texture has No premultiplied alpha, AND the blendFunc hasn't been changed, then update it
2013-06-15 14:03:30 +08:00
if ( texture & & ! texture - > hasPremultipliedAlpha ( ) & & ( _blendFunc . src = = CC_BLEND_SRC & & _blendFunc . dst = = CC_BLEND_DST ) )
2012-04-19 14:35:52 +08:00
{
2013-07-26 04:36:19 +08:00
_blendFunc = BlendFunc : : ALPHA_NON_PREMULTIPLIED ;
2012-04-19 14:35:52 +08:00
}
2012-03-14 14:55:17 +08:00
}
2013-12-05 17:19:01 +08:00
Texture2D * ParticleBatchNode : : getTexture ( ) const
2012-03-14 14:55:17 +08:00
{
2013-06-15 14:03:30 +08:00
return _textureAtlas - > getTexture ( ) ;
2012-03-14 14:55:17 +08:00
}
2013-07-05 16:49:22 +08:00
void ParticleBatchNode : : setBlendFunc ( const BlendFunc & blendFunc )
2012-04-19 14:35:52 +08:00
{
2013-06-15 14:03:30 +08:00
_blendFunc = blendFunc ;
2012-04-19 14:35:52 +08:00
}
// returns the blending function used for the texture
2013-12-05 17:19:01 +08:00
const BlendFunc & ParticleBatchNode : : getBlendFunc ( ) const
2012-03-14 14:55:17 +08:00
{
2013-06-15 14:03:30 +08:00
return _blendFunc ;
2012-03-14 14:55:17 +08:00
}
NS_CC_END