2012-03-14 14:55:17 +08:00
/*
2012-06-14 15:13:16 +08:00
* Copyright ( c ) 2010 - 2012 cocos2d - x . org
2012-03-14 14:55:17 +08:00
* Copyright ( C ) 2009 Matt Oswald
* Copyright ( c ) 2009 - 2010 Ricardo Quesada
* Copyright ( c ) 2011 Zynga Inc .
* Copyright ( c ) 2011 Marco Tillemans
*
* 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"
2012-06-19 16:20:46 +08:00
# include "textures/CCTextureCache.h"
# include "textures/CCTextureAtlas.h"
2012-03-14 14:55:17 +08:00
# include "ccConfig.h"
# include "ccMacros.h"
# include "effects/CCGrid.h"
# include "CCParticleSystem.h"
2012-06-19 16:20:46 +08:00
# include "shaders/CCShaderCache.h"
# include "shaders/CCGLProgram.h"
# include "shaders/ccGLStateCache.h"
2012-03-14 14:55:17 +08:00
# include "support/base64.h"
# include "support/zip_support/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-03-22 14:53:58 +08:00
# include "support/CCProfiling.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-06-15 14:03:30 +08:00
: _textureAtlas ( NULL )
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-06-20 14:13:12 +08:00
ParticleBatchNode * ParticleBatchNode : : createWithTexture ( Texture2D * tex , unsigned 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 ) ;
return NULL ;
2012-03-14 14:55:17 +08:00
}
/*
* creation with File Image
*/
2013-06-20 14:13:12 +08:00
ParticleBatchNode * ParticleBatchNode : : create ( const char * imageFile , unsigned 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 ) ;
return NULL ;
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-06-20 14:13:12 +08:00
bool ParticleBatchNode : : initWithTexture ( Texture2D * tex , unsigned 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
2012-04-19 14:35:52 +08:00
// no lazy alloc in this node
2013-06-20 14:13:12 +08:00
_children = new Array ( ) ;
2013-06-15 14:03:30 +08:00
_children - > initWithCapacity ( capacity ) ;
2012-03-14 14:55:17 +08:00
2013-07-26 08:47:42 +08:00
_blendFunc = BlendFunc : : ALPHA_PREMULTIPLIED ;
2012-03-14 14:55:17 +08:00
2013-07-25 17:48:22 +08:00
setShaderProgram ( ShaderCache : : getInstance ( ) - > programForKey ( GLProgram : : SHADER_NAME_POSITION_TEXTURE_COLOR ) ) ;
2012-04-19 14:35:52 +08:00
return true ;
2012-03-14 14:55:17 +08:00
}
/*
* init with FileImage
*/
2013-06-20 14:13:12 +08:00
bool ParticleBatchNode : : initWithFile ( const char * fileImage , unsigned int capacity )
2012-03-14 14:55:17 +08:00
{
2013-07-12 06:24:23 +08:00
Texture2D * tex = TextureCache : : getInstance ( ) - > 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
2013-06-20 14:13:12 +08:00
void ParticleBatchNode : : visit ( )
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
2012-04-19 14:35:52 +08:00
kmGLPushMatrix ( ) ;
2012-03-14 14:55:17 +08:00
2013-06-15 14:03:30 +08:00
if ( _grid & & _grid - > isActive ( ) )
2012-03-29 11:25:08 +08:00
{
2013-06-15 14:03:30 +08:00
_grid - > beforeDraw ( ) ;
2012-04-19 14:35:52 +08:00
transformAncestors ( ) ;
}
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
transform ( ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
draw ( ) ;
2012-03-14 14:55:17 +08:00
2013-06-15 14:03:30 +08:00
if ( _grid & & _grid - > isActive ( ) )
2012-03-29 11:25:08 +08:00
{
2013-06-15 14:03:30 +08:00
_grid - > afterDraw ( this ) ;
2012-03-29 11:25:08 +08:00
}
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
kmGLPopMatrix ( ) ;
2012-03-14 14:55:17 +08:00
}
// override addChild:
2013-06-20 14:13:12 +08:00
void ParticleBatchNode : : addChild ( Node * child )
2012-03-22 18:29:07 +08:00
{
2013-06-20 14:13:12 +08:00
Node : : addChild ( child ) ;
2012-03-22 18:29:07 +08:00
}
2013-06-20 14:13:12 +08:00
void ParticleBatchNode : : addChild ( Node * child , int zOrder )
2012-03-22 18:29:07 +08:00
{
2013-06-20 14:13:12 +08:00
Node : : addChild ( child , zOrder ) ;
2012-03-22 18:29:07 +08:00
}
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-07-26 07:27:24 +08:00
CCASSERT ( aChild ! = NULL , " Argument must be non-NULL " ) ;
CCASSERT ( dynamic_cast < ParticleSystem * > ( aChild ) ! = NULL , " CCParticleBatchNode only supports QuadParticleSystems as children " ) ;
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-06-15 14:03:30 +08:00
if ( _children - > count ( ) = = 0 )
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-07-26 07:27:24 +08:00
CCASSERT ( _blendFunc . src = = child - > getBlendFunc ( ) . src & & _blendFunc . dst = = child - > getBlendFunc ( ) . dst , " Can't add a PaticleSystem 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-07-26 07:27:24 +08:00
unsigned int 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
2012-04-19 14:35:52 +08:00
if ( pos ! = 0 )
2012-03-27 13:48:14 +08:00
{
2013-08-22 10:45:47 +08:00
ParticleSystem * p = ( ParticleSystem * ) _children - > getObjectAtIndex ( pos - 1 ) ;
2012-04-19 14:35:52 +08:00
atlasIndex = p - > getAtlasIndex ( ) + p - > getTotalParticles ( ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
}
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
unsigned int ParticleBatchNode : : addChildHelper ( ParticleSystem * child , int z , int aTag )
2012-03-14 14:55:17 +08:00
{
2013-07-20 13:01:27 +08:00
CCASSERT ( child ! = NULL , " Argument must be non-nil " ) ;
CCASSERT ( child - > getParent ( ) = = NULL , " child already added. It can't be added again " ) ;
2012-03-14 14:55:17 +08:00
2013-06-15 14:03:30 +08:00
if ( ! _children )
2012-03-29 11:25:08 +08:00
{
2013-06-20 14:13:12 +08:00
_children = new Array ( ) ;
2013-06-15 14:03:30 +08:00
_children - > initWithCapacity ( 4 ) ;
2012-04-19 14:35:52 +08:00
}
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
//don't use a lazy insert
unsigned int pos = searchNewPositionInChildrenForZ ( z ) ;
2012-03-14 14:55:17 +08:00
2013-06-15 14:03:30 +08:00
_children - > insertObject ( child , pos ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
child - > setTag ( aTag ) ;
child - > _setZOrder ( 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-06-15 14:03:30 +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-07-26 07:27:24 +08:00
CCASSERT ( aChild ! = NULL , " Child must be non-NULL " ) ;
CCASSERT ( dynamic_cast < ParticleSystem * > ( aChild ) ! = NULL , " CCParticleBatchNode only supports QuadParticleSystems as children " ) ;
CCASSERT ( _children - > containsObject ( 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
2012-04-19 14:35:52 +08:00
if ( zOrder = = child - > getZOrder ( ) )
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-06-15 14:03:30 +08:00
if ( _children - > count ( ) > 1 )
2012-04-19 14:35:52 +08:00
{
unsigned 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-06-15 14:03:30 +08:00
_children - > removeObjectAtIndex ( oldIndex ) ;
2013-07-26 07:27:24 +08:00
_children - > insertObject ( child , newIndex ) ;
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-06-15 14:03:30 +08:00
for ( unsigned int i = 0 ; i < _children - > count ( ) ; i + + )
2012-03-29 11:25:08 +08:00
{
2013-08-22 10:45:47 +08:00
ParticleSystem * pNode = ( ParticleSystem * ) _children - > getObjectAtIndex ( i ) ;
2013-07-26 07:27:24 +08:00
if ( pNode = = 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
2013-07-26 07:27:24 +08:00
child - > _setZOrder ( zOrder ) ;
2012-03-14 14:55:17 +08:00
}
2013-06-20 14:13:12 +08:00
void ParticleBatchNode : : getCurrentIndex ( unsigned int * oldIndex , unsigned 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-06-15 14:03:30 +08:00
unsigned int count = _children - > count ( ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
for ( unsigned int i = 0 ; i < count ; i + + )
2012-03-29 11:25:08 +08:00
{
2013-08-22 10:45:47 +08:00
Node * pNode = ( Node * ) _children - > getObjectAtIndex ( i ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
// new index
if ( pNode - > getZOrder ( ) > 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
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
{
2012-04-19 14:35:52 +08:00
* newIndex = 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-06-20 14:13:12 +08:00
unsigned int ParticleBatchNode : : searchNewPositionInChildrenForZ ( int z )
2012-03-14 14:55:17 +08:00
{
2013-06-15 14:03:30 +08:00
unsigned int count = _children - > count ( ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
for ( unsigned int i = 0 ; i < count ; i + + )
2012-03-29 11:25:08 +08:00
{
2013-08-22 10:45:47 +08:00
Node * child = ( Node * ) _children - > getObjectAtIndex ( i ) ;
2012-04-19 14:35:52 +08:00
if ( child - > getZOrder ( ) > 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
}
return 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-07-26 07:27:24 +08:00
if ( aChild = = NULL )
2012-04-19 14:35:52 +08:00
return ;
2013-07-26 07:27:24 +08:00
CCASSERT ( dynamic_cast < ParticleSystem * > ( aChild ) ! = NULL , " CCParticleBatchNode only supports QuadParticleSystems as children " ) ;
CCASSERT ( _children - > containsObject ( 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 ) ;
Node : : removeChild ( child , cleanup ) ;
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-07-26 07:27:24 +08:00
child - > setBatchNode ( NULL ) ;
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-06-20 14:13:12 +08:00
void ParticleBatchNode : : removeChildAtIndex ( unsigned int index , bool doCleanup )
2012-03-14 14:55:17 +08:00
{
2013-08-22 10:45:47 +08:00
removeChild ( ( ParticleSystem * ) _children - > getObjectAtIndex ( 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-06-20 14:13:12 +08:00
arrayMakeObjectsPerformSelectorWithObject ( _children , setBatchNode , NULL , ParticleSystem * ) ;
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
}
2013-06-20 14:13:12 +08:00
void ParticleBatchNode : : draw ( void )
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
2012-04-19 14:35:52 +08:00
CC_NODE_DRAW_SETUP ( ) ;
2012-03-14 14:55:17 +08:00
2013-07-26 09:42:53 +08:00
GL : : blendFunc ( _blendFunc . src , _blendFunc . dst ) ;
2012-03-14 14:55:17 +08:00
2013-06-15 14:03:30 +08:00
_textureAtlas - > drawQuads ( ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
CC_PROFILER_STOP ( " CCParticleBatchNode - draw " ) ;
2012-03-14 14:55:17 +08:00
}
2013-06-20 14:13:12 +08:00
void ParticleBatchNode : : increaseAtlasCapacityTo ( unsigned int 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-06-20 14:13:12 +08:00
void ParticleBatchNode : : disableParticle ( unsigned 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-06-20 14:13:12 +08:00
Object * pObj = NULL ;
2012-04-19 14:35:52 +08:00
unsigned int index = 0 ;
2013-06-15 14:03:30 +08:00
CCARRAY_FOREACH ( _children , pObj )
2012-04-19 14:35:52 +08:00
{
2013-07-09 14:29:51 +08:00
ParticleSystem * child = static_cast < ParticleSystem * > ( pObj ) ;
2012-04-19 14:35:52 +08:00
child - > setAtlasIndex ( index ) ;
index + = child - > getTotalParticles ( ) ;
}
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-06-20 14:13:12 +08:00
void ParticleBatchNode : : updateBlendFunc ( void )
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-07-23 18:26:26 +08:00
Texture2D * ParticleBatchNode : : getTexture ( void ) 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-07-05 16:49:22 +08:00
const BlendFunc & ParticleBatchNode : : getBlendFunc ( void ) 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