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"
2012-06-19 16:20:46 +08:00
# include "support/CCPointExtension.h"
2012-03-14 14:55:17 +08:00
# 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"
2012-03-29 11:25:08 +08:00
2012-03-14 14:55:17 +08:00
NS_CC_BEGIN
CCParticleBatchNode : : CCParticleBatchNode ( )
: m_pTextureAtlas ( NULL )
{
}
CCParticleBatchNode : : ~ CCParticleBatchNode ( )
{
2012-04-19 14:35:52 +08:00
CC_SAFE_RELEASE ( m_pTextureAtlas ) ;
2012-03-14 14:55:17 +08:00
}
/*
* creation with CCTexture2D
*/
2012-06-14 17:18:05 +08:00
CCParticleBatchNode * CCParticleBatchNode : : batchNodeWithTexture ( CCTexture2D * tex , unsigned int capacity /* = kCCParticleDefaultCapacity*/ )
{
2012-07-23 22:49:11 +08:00
return CCParticleBatchNode : : createWithTexture ( tex , capacity ) ;
2012-06-14 17:18:05 +08:00
}
2012-03-14 14:55:17 +08:00
2012-07-23 22:49:11 +08:00
CCParticleBatchNode * CCParticleBatchNode : : createWithTexture ( CCTexture2D * tex , unsigned int capacity /* = kCCParticleDefaultCapacity*/ )
2012-03-14 14:55:17 +08:00
{
2012-04-19 14:35:52 +08:00
CCParticleBatchNode * p = new CCParticleBatchNode ( ) ;
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
*/
2012-06-14 17:18:05 +08:00
CCParticleBatchNode * CCParticleBatchNode : : batchNodeWithFile ( const char * imageFile , unsigned int capacity /* = kCCParticleDefaultCapacity*/ )
{
return CCParticleBatchNode : : create ( imageFile , capacity ) ;
}
2012-03-14 14:55:17 +08:00
2012-06-14 15:13:16 +08:00
CCParticleBatchNode * CCParticleBatchNode : : create ( const char * imageFile , unsigned int capacity /* = kCCParticleDefaultCapacity*/ )
2012-03-14 14:55:17 +08:00
{
2012-04-19 14:35:52 +08:00
CCParticleBatchNode * p = new CCParticleBatchNode ( ) ;
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
}
/*
* init with CCTexture2D
*/
bool CCParticleBatchNode : : initWithTexture ( CCTexture2D * tex , unsigned int capacity )
{
2012-04-19 14:35:52 +08:00
m_pTextureAtlas = new CCTextureAtlas ( ) ;
m_pTextureAtlas - > 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
m_pChildren = new CCArray ( ) ;
m_pChildren - > initWithCapacity ( capacity ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
m_tBlendFunc . src = CC_BLEND_SRC ;
m_tBlendFunc . dst = CC_BLEND_DST ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
setShaderProgram ( CCShaderCache : : sharedShaderCache ( ) - > programForKey ( kCCShader_PositionTextureColor ) ) ;
return true ;
2012-03-14 14:55:17 +08:00
}
/*
* init with FileImage
*/
bool CCParticleBatchNode : : initWithFile ( const char * fileImage , unsigned int capacity )
{
2012-04-19 14:35:52 +08:00
CCTexture2D * tex = CCTextureCache : : sharedTextureCache ( ) - > addImage ( fileImage ) ;
return initWithTexture ( tex , capacity ) ;
2012-03-14 14:55:17 +08:00
}
// CCParticleBatchNode - composition
// override visit.
// Don't call visit on it's children
void CCParticleBatchNode : : visit ( )
{
2012-04-19 14:35:52 +08:00
// CAREFUL:
// This visit is almost identical to CCNode#visit
// with the exception that it doesn't call visit on it's children
//
// The alternative is to have a void CCSprite#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
//
2012-11-14 18:05:15 +08:00
if ( ! m_bVisible )
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
2012-04-19 14:35:52 +08:00
if ( m_pGrid & & m_pGrid - > isActive ( ) )
2012-03-29 11:25:08 +08:00
{
2012-04-19 14:35:52 +08:00
m_pGrid - > beforeDraw ( ) ;
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
2012-04-19 14:35:52 +08:00
if ( m_pGrid & & m_pGrid - > isActive ( ) )
2012-03-29 11:25:08 +08:00
{
2012-04-19 14:35:52 +08:00
m_pGrid - > 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:
2012-03-22 18:29:07 +08:00
void CCParticleBatchNode : : addChild ( CCNode * child )
{
2012-04-19 14:35:52 +08:00
CCNode : : addChild ( child ) ;
2012-03-22 18:29:07 +08:00
}
void CCParticleBatchNode : : addChild ( CCNode * child , int zOrder )
{
2012-04-19 14:35:52 +08:00
CCNode : : addChild ( child , zOrder ) ;
2012-03-22 18:29:07 +08:00
}
2012-03-14 14:55:17 +08:00
void CCParticleBatchNode : : addChild ( CCNode * child , int zOrder , int tag )
{
2012-04-19 14:35:52 +08:00
CCAssert ( child ! = NULL , " Argument must be non-NULL " ) ;
CCAssert ( dynamic_cast < CCParticleSystem * > ( child ) ! = NULL , " CCParticleBatchNode only supports CCQuadParticleSystems as children " ) ;
2012-03-27 13:48:14 +08:00
CCParticleSystem * pChild = ( CCParticleSystem * ) child ;
CCAssert ( pChild - > getTexture ( ) - > getName ( ) = = m_pTextureAtlas - > 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
if ( m_pChildren - > count ( ) = = 0 )
2012-03-27 13:48:14 +08:00
{
2012-04-19 14:35:52 +08:00
setBlendFunc ( pChild - > getBlendFunc ( ) ) ;
}
2012-03-14 14:55:17 +08:00
2012-09-17 15:02:24 +08:00
CCAssert ( m_tBlendFunc . src = = pChild - > getBlendFunc ( ) . src & & m_tBlendFunc . dst = = pChild - > 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
unsigned int pos = addChildHelper ( pChild , zOrder , tag ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
//get new atlasIndex
unsigned 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
{
2012-04-19 14:35:52 +08:00
CCParticleSystem * p = ( CCParticleSystem * ) m_pChildren - > objectAtIndex ( pos - 1 ) ;
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
2012-04-19 14:35:52 +08:00
insertChild ( pChild , atlasIndex ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
// update quad info
pChild - > 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
// this helper is almost equivalent to CCNode's addChild, but doesn't make use of the lazy sorting
unsigned int CCParticleBatchNode : : addChildHelper ( CCParticleSystem * child , int z , int aTag )
{
2012-04-19 14:35:52 +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
2012-04-19 14:35:52 +08:00
if ( ! m_pChildren )
2012-03-29 11:25:08 +08:00
{
2012-04-19 14:35:52 +08:00
m_pChildren = new CCArray ( ) ;
2012-03-29 11:25:08 +08:00
m_pChildren - > 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
2012-04-19 14:35:52 +08:00
m_pChildren - > 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
2012-11-14 18:05:15 +08:00
if ( m_bRunning )
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
void CCParticleBatchNode : : reorderChild ( CCNode * child , int zOrder )
{
2012-04-19 14:35:52 +08:00
CCAssert ( child ! = NULL , " Child must be non-NULL " ) ;
CCAssert ( dynamic_cast < CCParticleSystem * > ( child ) ! = NULL , " CCParticleBatchNode only supports CCQuadParticleSystems as children " ) ;
CCAssert ( m_pChildren - > containsObject ( child ) , " Child doesn't belong to batch " ) ;
2012-03-14 14:55:17 +08:00
2012-03-29 11:25:08 +08:00
CCParticleSystem * pChild = ( CCParticleSystem * ) ( child ) ;
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
if ( m_pChildren - > count ( ) > 1 )
{
unsigned int newIndex = 0 , oldIndex = 0 ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
getCurrentIndex ( & oldIndex , & newIndex , pChild , 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
2012-04-19 14:35:52 +08:00
// reorder m_pChildren->array
pChild - > retain ( ) ;
m_pChildren - > removeObjectAtIndex ( oldIndex ) ;
m_pChildren - > insertObject ( pChild , newIndex ) ;
pChild - > release ( ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
// save old altasIndex
unsigned int oldAtlasIndex = pChild - > 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
unsigned int newAtlasIndex = 0 ;
for ( unsigned int i = 0 ; i < m_pChildren - > count ( ) ; i + + )
2012-03-29 11:25:08 +08:00
{
2012-04-19 14:35:52 +08:00
CCParticleSystem * pNode = ( CCParticleSystem * ) m_pChildren - > objectAtIndex ( i ) ;
if ( pNode = = pChild )
2012-03-29 11:25:08 +08:00
{
2012-04-19 14:35:52 +08:00
newAtlasIndex = pChild - > getAtlasIndex ( ) ;
break ;
}
}
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
// reorder textureAtlas quads
m_pTextureAtlas - > moveQuadsFromIndex ( oldAtlasIndex , pChild - > getTotalParticles ( ) , newAtlasIndex ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
pChild - > updateWithNoTime ( ) ;
}
}
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
pChild - > _setZOrder ( zOrder ) ;
2012-03-14 14:55:17 +08:00
}
void CCParticleBatchNode : : getCurrentIndex ( unsigned int * oldIndex , unsigned int * newIndex , CCNode * child , int z )
{
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 ;
unsigned int count = m_pChildren - > 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
{
2012-04-19 14:35:52 +08:00
CCNode * pNode = ( CCNode * ) m_pChildren - > objectAtIndex ( 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
}
unsigned int CCParticleBatchNode : : searchNewPositionInChildrenForZ ( int z )
{
2012-04-19 14:35:52 +08:00
unsigned int count = m_pChildren - > 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
{
2012-04-19 14:35:52 +08:00
CCNode * child = ( CCNode * ) m_pChildren - > objectAtIndex ( i ) ;
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:
void CCParticleBatchNode : : removeChild ( CCNode * child , bool cleanup )
{
2012-04-19 14:35:52 +08:00
// explicit nil handling
if ( child = = NULL )
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
CCAssert ( dynamic_cast < CCParticleSystem * > ( child ) ! = NULL , " CCParticleBatchNode only supports CCQuadParticleSystems as children " ) ;
CCAssert ( m_pChildren - > containsObject ( child ) , " CCParticleBatchNode doesn't contain the sprite. Can't remove it " ) ;
2012-03-14 14:55:17 +08:00
2012-03-29 11:25:08 +08:00
CCParticleSystem * pChild = ( CCParticleSystem * ) child ;
2012-04-19 14:35:52 +08:00
CCNode : : removeChild ( pChild , cleanup ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
// remove child helper
m_pTextureAtlas - > removeQuadsAtIndex ( pChild - > getAtlasIndex ( ) , pChild - > 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
m_pTextureAtlas - > fillWithEmptyQuadsFromIndex ( m_pTextureAtlas - > getTotalQuads ( ) , pChild - > getTotalParticles ( ) ) ;
2012-03-14 14:55:17 +08:00
2012-09-17 15:02:24 +08:00
// particle could be reused for self rendering
2012-04-19 14:35:52 +08:00
pChild - > 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
}
void CCParticleBatchNode : : removeChildAtIndex ( unsigned int index , bool doCleanup )
{
2012-04-19 14:35:52 +08:00
removeChild ( ( CCParticleSystem * ) m_pChildren - > objectAtIndex ( index ) , doCleanup ) ;
2012-03-14 14:55:17 +08:00
}
void CCParticleBatchNode : : removeAllChildrenWithCleanup ( bool doCleanup )
{
2012-04-19 14:35:52 +08:00
arrayMakeObjectsPerformSelectorWithObject ( m_pChildren , setBatchNode , NULL , CCParticleSystem * ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
CCNode : : removeAllChildrenWithCleanup ( doCleanup ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
m_pTextureAtlas - > removeAllQuads ( ) ;
2012-03-14 14:55:17 +08:00
}
void CCParticleBatchNode : : draw ( void )
{
2012-04-19 14:35:52 +08:00
CC_PROFILER_STOP ( " CCParticleBatchNode - draw " ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
if ( m_pTextureAtlas - > 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
2012-04-19 14:35:52 +08:00
ccGLBlendFunc ( m_tBlendFunc . src , m_tBlendFunc . dst ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
m_pTextureAtlas - > 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
}
void CCParticleBatchNode : : increaseAtlasCapacityTo ( unsigned int quantity )
{
2012-04-19 14:35:52 +08:00
CCLOG ( " cocos2d: CCParticleBatchNode: resizing TextureAtlas capacity from [%lu] to [%lu]. " ,
( long ) m_pTextureAtlas - > getCapacity ( ) ,
( long ) quantity ) ;
if ( ! m_pTextureAtlas - > resizeCapacity ( quantity ) ) {
// serious problems
2012-06-08 14:11:48 +08:00
CCLOGWARN ( " cocos2d: WARNING: Not enough memory to resize the atlas " ) ;
2012-04-19 14:35:52 +08:00
CCAssert ( false , " XXX: CCParticleBatchNode #increaseAtlasCapacity SHALL handle this assert " ) ;
}
2012-03-14 14:55:17 +08:00
}
//sets a 0'd quad into the quads array
void CCParticleBatchNode : : disableParticle ( unsigned int particleIndex )
{
2012-04-19 14:35:52 +08:00
ccV3F_C4B_T2F_Quad * quad = & ( ( m_pTextureAtlas - > getQuads ( ) ) [ particleIndex ] ) ;
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
}
// CCParticleBatchNode - add / remove / reorder helper methods
// add child helper
void CCParticleBatchNode : : insertChild ( CCParticleSystem * pSystem , unsigned int index )
{
2012-04-19 14:35:52 +08:00
pSystem - > setAtlasIndex ( index ) ;
2012-03-14 14:55:17 +08:00
2012-04-19 14:35:52 +08:00
if ( m_pTextureAtlas - > getTotalQuads ( ) + pSystem - > getTotalParticles ( ) > m_pTextureAtlas - > getCapacity ( ) )
{
increaseAtlasCapacityTo ( m_pTextureAtlas - > getTotalQuads ( ) + pSystem - > 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
m_pTextureAtlas - > fillWithEmptyQuadsFromIndex ( m_pTextureAtlas - > getCapacity ( ) - pSystem - > getTotalParticles ( ) , pSystem - > getTotalParticles ( ) ) ;
}
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
if ( pSystem - > getAtlasIndex ( ) + pSystem - > getTotalParticles ( ) ! = m_pTextureAtlas - > getTotalQuads ( ) )
2012-04-04 21:58:04 +08:00
{
2012-04-19 14:35:52 +08:00
m_pTextureAtlas - > moveQuadsFromIndex ( index , index + pSystem - > 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
2012-04-19 14:35:52 +08:00
m_pTextureAtlas - > increaseTotalQuadsWith ( pSystem - > 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
void CCParticleBatchNode : : updateAllAtlasIndexes ( )
{
2012-04-19 14:35:52 +08:00
CCObject * pObj = NULL ;
unsigned int index = 0 ;
CCARRAY_FOREACH ( m_pChildren , pObj )
{
CCParticleSystem * child = ( CCParticleSystem * ) pObj ;
child - > setAtlasIndex ( index ) ;
index + = child - > getTotalParticles ( ) ;
}
2012-03-14 14:55:17 +08:00
}
// CCParticleBatchNode - CocosNodeTexture protocol
void CCParticleBatchNode : : updateBlendFunc ( void )
{
2012-06-15 15:10:40 +08:00
if ( ! m_pTextureAtlas - > getTexture ( ) - > hasPremultipliedAlpha ( ) ) {
2012-04-19 14:35:52 +08:00
m_tBlendFunc . src = GL_SRC_ALPHA ;
m_tBlendFunc . dst = GL_ONE_MINUS_SRC_ALPHA ;
}
2012-03-14 14:55:17 +08:00
}
void CCParticleBatchNode : : setTexture ( CCTexture2D * texture )
{
2012-04-19 14:35:52 +08:00
m_pTextureAtlas - > setTexture ( texture ) ;
// If the new texture has No premultiplied alpha, AND the blendFunc hasn't been changed, then update it
2012-06-15 15:10:40 +08:00
if ( texture & & ! texture - > hasPremultipliedAlpha ( ) & & ( m_tBlendFunc . src = = CC_BLEND_SRC & & m_tBlendFunc . dst = = CC_BLEND_DST ) )
2012-04-19 14:35:52 +08:00
{
m_tBlendFunc . src = GL_SRC_ALPHA ;
m_tBlendFunc . dst = GL_ONE_MINUS_SRC_ALPHA ;
}
2012-03-14 14:55:17 +08:00
}
CCTexture2D * CCParticleBatchNode : : getTexture ( void )
{
2012-04-19 14:35:52 +08:00
return m_pTextureAtlas - > getTexture ( ) ;
2012-03-14 14:55:17 +08:00
}
2012-04-19 14:35:52 +08:00
void CCParticleBatchNode : : setBlendFunc ( ccBlendFunc blendFunc )
{
m_tBlendFunc = blendFunc ;
}
// returns the blending function used for the texture
2012-03-14 14:55:17 +08:00
ccBlendFunc CCParticleBatchNode : : getBlendFunc ( void )
{
2012-04-19 14:35:52 +08:00
return m_tBlendFunc ;
2012-03-14 14:55:17 +08:00
}
NS_CC_END