2012-03-14 10:55:17 +04:00
/*
* Copyright ( C ) 2009 Matt Oswald
* Copyright ( c ) 2009 - 2010 Ricardo Quesada
2014-01-07 07:25:07 +04:00
* Copyright ( c ) 2010 - 2012 cocos2d - x . org
* Copyright ( c ) 2011 Zynga Inc .
* Copyright ( c ) 2011 Marco Tillemans
2017-02-14 09:36:57 +03:00
* Copyright ( c ) 2013 - 2017 Chukong Technologies Inc .
2012-03-14 10:55:17 +04: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 .
*
*/
2014-05-10 05:39:25 +04:00
# include "2d/CCParticleBatchNode.h"
# include "2d/CCGrid.h"
# include "2d/CCParticleSystem.h"
2014-05-17 01:36:00 +04:00
# include "renderer/CCTextureCache.h"
2014-04-30 04:37:36 +04:00
# include "renderer/CCQuadCommand.h"
# include "renderer/CCRenderer.h"
2014-08-28 13:03:29 +04:00
# include "renderer/CCTextureAtlas.h"
2016-06-06 11:25:00 +03:00
# include "base/CCProfiling.h"
2016-06-15 10:01:26 +03:00
# include "base/ccUTF8.h"
2014-05-10 05:39:25 +04:00
2012-03-14 10:55:17 +04:00
NS_CC_BEGIN
2013-06-20 10:13:12 +04:00
ParticleBatchNode : : ParticleBatchNode ( )
2013-12-18 13:47:20 +04:00
: _textureAtlas ( nullptr )
2012-03-14 10:55:17 +04:00
{
}
2013-06-20 10:13:12 +04:00
ParticleBatchNode : : ~ ParticleBatchNode ( )
2012-03-14 10:55:17 +04:00
{
2013-06-15 10:03:30 +04:00
CC_SAFE_RELEASE ( _textureAtlas ) ;
2012-03-14 10:55:17 +04:00
}
/*
2013-06-20 10:13:12 +04:00
* creation with Texture2D
2012-03-14 10:55:17 +04:00
*/
2013-11-15 05:19:16 +04:00
ParticleBatchNode * ParticleBatchNode : : createWithTexture ( Texture2D * tex , int capacity /* = kParticleDefaultCapacity*/ )
2012-03-14 10:55:17 +04:00
{
2014-08-28 03:31:57 +04:00
ParticleBatchNode * p = new ( std : : nothrow ) ParticleBatchNode ( ) ;
2012-04-19 10:35:52 +04:00
if ( p & & p - > initWithTexture ( tex , capacity ) )
{
p - > autorelease ( ) ;
return p ;
}
CC_SAFE_DELETE ( p ) ;
2013-12-18 13:47:20 +04:00
return nullptr ;
2012-03-14 10:55:17 +04:00
}
/*
* creation with File Image
*/
2013-11-15 05:19:16 +04:00
ParticleBatchNode * ParticleBatchNode : : create ( const std : : string & imageFile , int capacity /* = kParticleDefaultCapacity*/ )
2012-03-14 10:55:17 +04:00
{
2014-08-28 03:31:57 +04:00
ParticleBatchNode * p = new ( std : : nothrow ) ParticleBatchNode ( ) ;
2012-06-14 11:13:16 +04:00
if ( p & & p - > initWithFile ( imageFile , capacity ) )
2012-04-19 10:35:52 +04:00
{
p - > autorelease ( ) ;
return p ;
}
CC_SAFE_DELETE ( p ) ;
2013-12-18 13:47:20 +04:00
return nullptr ;
2012-03-14 10:55:17 +04:00
}
/*
2013-06-20 10:13:12 +04:00
* init with Texture2D
2012-03-14 10:55:17 +04:00
*/
2013-11-15 05:19:16 +04:00
bool ParticleBatchNode : : initWithTexture ( Texture2D * tex , int capacity )
2012-03-14 10:55:17 +04:00
{
2014-08-28 03:31:57 +04:00
_textureAtlas = new ( std : : nothrow ) TextureAtlas ( ) ;
2013-06-15 10:03:30 +04:00
_textureAtlas - > initWithTexture ( tex , capacity ) ;
2012-03-14 10:55:17 +04:00
2013-12-05 06:35:10 +04:00
_children . reserve ( capacity ) ;
2013-11-28 12:02:03 +04:00
2013-07-26 04:47:42 +04:00
_blendFunc = BlendFunc : : ALPHA_PREMULTIPLIED ;
2012-03-14 10:55:17 +04:00
2016-07-25 12:31:54 +03:00
setGLProgramState ( GLProgramState : : getOrCreateWithGLProgramName ( GLProgram : : SHADER_NAME_POSITION_TEXTURE_COLOR , tex ) ) ;
2013-11-29 21:09:38 +04:00
2012-04-19 10:35:52 +04:00
return true ;
2012-03-14 10:55:17 +04:00
}
/*
* init with FileImage
*/
2013-11-15 05:19:16 +04:00
bool ParticleBatchNode : : initWithFile ( const std : : string & fileImage , int capacity )
2012-03-14 10:55:17 +04:00
{
2013-11-07 15:11:09 +04:00
Texture2D * tex = Director : : getInstance ( ) - > getTextureCache ( ) - > addImage ( fileImage ) ;
2012-04-19 10:35:52 +04:00
return initWithTexture ( tex , capacity ) ;
2012-03-14 10:55:17 +04:00
}
2013-06-20 10:13:12 +04:00
// ParticleBatchNode - composition
2012-03-14 10:55:17 +04:00
// override visit.
// Don't call visit on it's children
2014-05-31 03:42:05 +04:00
void ParticleBatchNode : : visit ( Renderer * renderer , const Mat4 & parentTransform , uint32_t parentFlags )
2012-03-14 10:55:17 +04:00
{
2012-04-19 10:35:52 +04:00
// CAREFUL:
2013-06-20 10:13:12 +04:00
// This visit is almost identical to Node#visit
2012-04-19 10:35:52 +04:00
// with the exception that it doesn't call visit on it's children
//
2013-06-20 10:13:12 +04:00
// The alternative is to have a void Sprite#visit, but
2012-09-17 11:02:24 +04:00
// although this is less maintainable, is faster
2012-04-19 10:35:52 +04:00
//
2015-06-18 05:32:30 +03:00
if ( ! _visible )
2012-03-29 07:25:08 +04:00
{
2012-04-19 10:35:52 +04:00
return ;
2012-03-29 07:25:08 +04:00
}
2012-03-14 10:55:17 +04:00
2014-05-31 03:42:05 +04:00
uint32_t flags = processParentFlags ( parentTransform , parentFlags ) ;
2014-02-28 23:20:53 +04:00
2015-06-18 05:32:30 +03:00
if ( isVisitableByVisitingCamera ( ) )
{
// IMPORTANT:
// To ease the migration to v3.0, we still support the Mat4 stack,
// but it is deprecated and your code should not rely on it
Director * director = Director : : getInstance ( ) ;
director - > pushMatrix ( MATRIX_STACK_TYPE : : MATRIX_STACK_MODELVIEW ) ;
director - > loadMatrix ( MATRIX_STACK_TYPE : : MATRIX_STACK_MODELVIEW , _modelViewTransform ) ;
draw ( renderer , _modelViewTransform , flags ) ;
director - > popMatrix ( MATRIX_STACK_TYPE : : MATRIX_STACK_MODELVIEW ) ;
}
2012-03-14 10:55:17 +04:00
}
// override addChild:
2013-07-26 03:27:24 +04:00
void ParticleBatchNode : : addChild ( Node * aChild , int zOrder , int tag )
2012-03-14 10:55:17 +04:00
{
2013-12-18 13:47:20 +04:00
CCASSERT ( aChild ! = nullptr , " Argument must be non-nullptr " ) ;
CCASSERT ( dynamic_cast < ParticleSystem * > ( aChild ) ! = nullptr , " CCParticleBatchNode only supports QuadParticleSystems as children " ) ;
2013-07-26 03:27:24 +04:00
ParticleSystem * child = static_cast < ParticleSystem * > ( aChild ) ;
CCASSERT ( child - > getTexture ( ) - > getName ( ) = = _textureAtlas - > getTexture ( ) - > getName ( ) , " CCParticleSystem is not using the same texture id " ) ;
2014-06-25 07:27:48 +04:00
addChildByTagOrName ( child , zOrder , tag , " " , true ) ;
}
void ParticleBatchNode : : addChild ( Node * aChild , int zOrder , const std : : string & name )
{
CCASSERT ( aChild ! = nullptr , " Argument must be non-nullptr " ) ;
CCASSERT ( dynamic_cast < ParticleSystem * > ( aChild ) ! = nullptr , " 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 " ) ;
addChildByTagOrName ( child , zOrder , 0 , name , false ) ;
}
void ParticleBatchNode : : addChildByTagOrName ( ParticleSystem * child , int zOrder , int tag , const std : : string & name , bool setTag )
{
2012-04-19 10:35:52 +04:00
// If this is the 1st children, then copy blending function
2013-11-28 14:23:06 +04:00
if ( _children . empty ( ) )
2012-03-27 09:48:14 +04:00
{
2013-07-26 03:27:24 +04:00
setBlendFunc ( child - > getBlendFunc ( ) ) ;
2012-04-19 10:35:52 +04:00
}
2014-06-25 07:27:48 +04:00
2013-11-29 21:09:38 +04:00
CCASSERT ( _blendFunc . src = = child - > getBlendFunc ( ) . src & & _blendFunc . dst = = child - > getBlendFunc ( ) . dst , " Can't add a ParticleSystem that uses a different blending function " ) ;
2014-06-25 07:27:48 +04:00
2012-04-19 10:35:52 +04:00
//no lazy sorting, so don't call super addChild, call helper instead
2014-06-25 07:27:48 +04:00
int pos = 0 ;
if ( setTag )
pos = addChildHelper ( child , zOrder , tag , " " , true ) ;
else
pos = addChildHelper ( child , zOrder , 0 , name , false ) ;
2012-04-19 10:35:52 +04:00
//get new atlasIndex
2013-07-20 09:01:27 +04:00
int atlasIndex = 0 ;
2014-06-25 07:27:48 +04:00
2013-11-29 21:09:38 +04:00
if ( pos ! = 0 )
2012-03-27 09:48:14 +04:00
{
2013-12-05 06:35:10 +04:00
ParticleSystem * p = static_cast < ParticleSystem * > ( _children . at ( pos - 1 ) ) ;
2012-04-19 10:35:52 +04:00
atlasIndex = p - > getAtlasIndex ( ) + p - > getTotalParticles ( ) ;
}
else
2012-03-27 09:48:14 +04:00
{
2012-04-19 10:35:52 +04:00
atlasIndex = 0 ;
}
2014-06-25 07:27:48 +04:00
2013-07-26 03:27:24 +04:00
insertChild ( child , atlasIndex ) ;
2014-06-25 07:27:48 +04:00
2012-04-19 10:35:52 +04:00
// update quad info
2013-07-26 03:27:24 +04:00
child - > setBatchNode ( this ) ;
2012-03-14 10:55:17 +04:00
}
// don't use lazy sorting, reordering the particle systems quads afterwards would be too complex
2014-08-29 23:54:24 +04:00
// FIXME: research whether lazy sorting + freeing current quads and calloc a new block with size of capacity would be faster
// FIXME: or possibly using vertexZ for reordering, that would be fastest
2013-06-20 10:13:12 +04:00
// this helper is almost equivalent to Node's addChild, but doesn't make use of the lazy sorting
2014-06-25 07:27:48 +04:00
int ParticleBatchNode : : addChildHelper ( ParticleSystem * child , int z , int aTag , const std : : string & name , bool setTag )
2012-03-14 10:55:17 +04:00
{
2013-12-18 13:47:20 +04: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 10:55:17 +04:00
2013-12-05 06:35:10 +04:00
_children . reserve ( 4 ) ;
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
//don't use a lazy insert
2013-12-05 13:19:01 +04:00
auto pos = searchNewPositionInChildrenForZ ( z ) ;
2012-03-14 10:55:17 +04:00
2013-12-05 06:35:10 +04:00
_children . insert ( pos , child ) ;
2012-03-14 10:55:17 +04:00
2014-06-25 07:27:48 +04:00
if ( setTag )
child - > setTag ( aTag ) ;
else
child - > setName ( name ) ;
2014-09-03 13:26:50 +04:00
child - > setLocalZOrder ( z ) ;
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
child - > setParent ( this ) ;
2012-03-14 10:55:17 +04:00
2013-11-29 21:09:38 +04:00
if ( _running )
2012-03-29 07:25:08 +04:00
{
2012-04-19 10:35:52 +04:00
child - > onEnter ( ) ;
child - > onEnterTransitionDidFinish ( ) ;
}
return pos ;
2012-03-14 10:55:17 +04:00
}
// Reorder will be done in this function, no "lazy" reorder to particles
2013-07-26 03:27:24 +04:00
void ParticleBatchNode : : reorderChild ( Node * aChild , int zOrder )
2012-03-14 10:55:17 +04:00
{
2013-12-18 13:47:20 +04:00
CCASSERT ( aChild ! = nullptr , " Child must be non-nullptr " ) ;
CCASSERT ( dynamic_cast < ParticleSystem * > ( aChild ) ! = nullptr , " CCParticleBatchNode only supports QuadParticleSystems as children " ) ;
2013-12-05 06:35:10 +04:00
CCASSERT ( _children . contains ( aChild ) , " Child doesn't belong to batch " ) ;
2012-03-14 10:55:17 +04:00
2013-07-26 03:27:24 +04:00
ParticleSystem * child = static_cast < ParticleSystem * > ( aChild ) ;
2012-03-29 07:25:08 +04:00
2014-01-20 11:03:30 +04:00
if ( zOrder = = child - > getLocalZOrder ( ) )
2012-03-29 07:25:08 +04:00
{
2012-04-19 10:35:52 +04:00
return ;
}
2012-03-29 07:25:08 +04:00
2012-04-19 10:35:52 +04:00
// no reordering if only 1 child
2013-11-28 14:23:06 +04:00
if ( ! _children . empty ( ) )
2012-04-19 10:35:52 +04:00
{
2013-12-05 13:19:01 +04:00
int newIndex = 0 , oldIndex = 0 ;
2012-03-14 10:55:17 +04:00
2013-07-26 03:27:24 +04:00
getCurrentIndex ( & oldIndex , & newIndex , child , zOrder ) ;
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
if ( oldIndex ! = newIndex )
2012-03-29 07:25:08 +04:00
{
2012-03-14 10:55:17 +04:00
2013-06-15 10:03:30 +04:00
// reorder _children->array
2013-07-26 03:27:24 +04:00
child - > retain ( ) ;
2013-12-11 13:53:45 +04:00
_children . erase ( oldIndex ) ;
2013-12-05 06:35:10 +04:00
_children . insert ( newIndex , child ) ;
2013-07-26 03:27:24 +04:00
child - > release ( ) ;
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
// save old altasIndex
2013-07-26 03:27:24 +04:00
int oldAtlasIndex = child - > getAtlasIndex ( ) ;
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
// update atlas index
updateAllAtlasIndexes ( ) ;
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
// Find new AtlasIndex
2013-07-20 09:01:27 +04:00
int newAtlasIndex = 0 ;
2017-02-04 05:38:22 +03:00
for ( const auto & iter : _children )
2012-03-29 07:25:08 +04:00
{
2017-02-04 05:38:22 +03:00
auto node = static_cast < ParticleSystem * > ( iter ) ;
2013-11-28 12:02:03 +04:00
if ( node = = child )
2012-03-29 07:25:08 +04:00
{
2013-07-26 03:27:24 +04:00
newAtlasIndex = child - > getAtlasIndex ( ) ;
2012-04-19 10:35:52 +04:00
break ;
}
}
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
// reorder textureAtlas quads
2013-07-26 03:27:24 +04:00
_textureAtlas - > moveQuadsFromIndex ( oldAtlasIndex , child - > getTotalParticles ( ) , newAtlasIndex ) ;
2012-03-14 10:55:17 +04:00
2013-07-26 03:27:24 +04:00
child - > updateWithNoTime ( ) ;
2012-04-19 10:35:52 +04:00
}
}
2012-03-14 10:55:17 +04:00
2014-09-03 13:26:50 +04:00
child - > setLocalZOrder ( zOrder ) ;
2012-03-14 10:55:17 +04:00
}
2013-12-05 13:19:01 +04:00
void ParticleBatchNode : : getCurrentIndex ( int * oldIndex , int * newIndex , Node * child , int z )
2012-03-14 10:55:17 +04:00
{
2012-04-19 10:35:52 +04:00
bool foundCurrentIdx = false ;
bool foundNewIdx = false ;
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
int minusOne = 0 ;
2013-12-05 13:19:01 +04:00
auto count = _children . size ( ) ;
2012-03-14 10:55:17 +04:00
2013-12-05 13:19:01 +04:00
for ( int i = 0 ; i < count ; i + + )
2012-03-29 07:25:08 +04:00
{
2013-12-05 06:35:10 +04:00
Node * pNode = _children . at ( i ) ;
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
// new index
2014-01-20 11:03:30 +04:00
if ( pNode - > getLocalZOrder ( ) > z & & ! foundNewIdx )
2012-03-29 07:25:08 +04:00
{
2012-04-19 10:35:52 +04:00
* newIndex = i ;
foundNewIdx = true ;
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
if ( foundCurrentIdx & & foundNewIdx )
2012-03-29 07:25:08 +04:00
{
2012-04-19 10:35:52 +04:00
break ;
2012-03-29 07:25:08 +04:00
}
2012-04-19 10:35:52 +04:00
}
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
// current index
2013-11-29 21:09:38 +04:00
if ( child = = pNode )
2012-03-29 07:25:08 +04:00
{
2012-04-19 10:35:52 +04:00
* oldIndex = i ;
foundCurrentIdx = true ;
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
if ( ! foundNewIdx )
2012-03-29 07:25:08 +04:00
{
2012-04-19 10:35:52 +04:00
minusOne = - 1 ;
2012-03-29 07:25:08 +04:00
}
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
if ( foundCurrentIdx & & foundNewIdx )
2012-03-29 07:25:08 +04:00
{
2012-04-19 10:35:52 +04:00
break ;
2012-03-29 07:25:08 +04:00
}
2012-04-19 10:35:52 +04:00
}
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
}
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
if ( ! foundNewIdx )
2012-03-29 07:25:08 +04:00
{
2013-12-05 13:19:01 +04:00
* newIndex = static_cast < int > ( count ) ;
2012-03-29 07:25:08 +04:00
}
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
* newIndex + = minusOne ;
2012-03-14 10:55:17 +04:00
}
2013-12-05 13:19:01 +04:00
int ParticleBatchNode : : searchNewPositionInChildrenForZ ( int z )
2012-03-14 10:55:17 +04:00
{
2013-12-05 13:19:01 +04:00
auto count = _children . size ( ) ;
2012-03-14 10:55:17 +04:00
2013-12-05 13:19:01 +04:00
for ( int i = 0 ; i < count ; i + + )
2012-03-29 07:25:08 +04:00
{
2013-12-05 06:35:10 +04:00
Node * child = _children . at ( i ) ;
2014-01-20 11:03:30 +04:00
if ( child - > getLocalZOrder ( ) > z )
2012-03-29 07:25:08 +04:00
{
2012-04-19 10:35:52 +04:00
return i ;
2012-03-29 07:25:08 +04:00
}
2012-04-19 10:35:52 +04:00
}
2013-12-05 13:19:01 +04:00
return static_cast < int > ( count ) ;
2012-03-14 10:55:17 +04:00
}
// override removeChild:
2013-07-26 03:27:24 +04:00
void ParticleBatchNode : : removeChild ( Node * aChild , bool cleanup )
2012-03-14 10:55:17 +04:00
{
2012-04-19 10:35:52 +04:00
// explicit nil handling
2013-12-18 13:47:20 +04:00
if ( aChild = = nullptr )
2012-04-19 10:35:52 +04:00
return ;
2013-11-29 21:09:38 +04:00
2013-12-18 13:47:20 +04:00
CCASSERT ( dynamic_cast < ParticleSystem * > ( aChild ) ! = nullptr , " CCParticleBatchNode only supports QuadParticleSystems as children " ) ;
2013-12-05 06:35:10 +04:00
CCASSERT ( _children . contains ( aChild ) , " CCParticleBatchNode doesn't contain the sprite. Can't remove it " ) ;
2012-03-14 10:55:17 +04:00
2013-07-26 03:27:24 +04:00
ParticleSystem * child = static_cast < ParticleSystem * > ( aChild ) ;
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
// remove child helper
2013-07-26 03:27:24 +04:00
_textureAtlas - > removeQuadsAtIndex ( child - > getAtlasIndex ( ) , child - > getTotalParticles ( ) ) ;
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
// after memmove of data, empty the quads at the end of array
2013-07-26 03:27:24 +04:00
_textureAtlas - > fillWithEmptyQuadsFromIndex ( _textureAtlas - > getTotalQuads ( ) , child - > getTotalParticles ( ) ) ;
2012-03-14 10:55:17 +04:00
2012-09-17 11:02:24 +04:00
// particle could be reused for self rendering
2013-12-18 13:47:20 +04:00
child - > setBatchNode ( nullptr ) ;
2014-03-05 10:32:22 +04:00
Node : : removeChild ( child , cleanup ) ;
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
updateAllAtlasIndexes ( ) ;
2012-03-14 10:55:17 +04:00
}
2013-12-05 13:19:01 +04:00
void ParticleBatchNode : : removeChildAtIndex ( int index , bool doCleanup )
2012-03-14 10:55:17 +04:00
{
2013-12-05 06:35:10 +04:00
removeChild ( _children . at ( index ) , doCleanup ) ;
2012-03-14 10:55:17 +04:00
}
2013-06-20 10:13:12 +04:00
void ParticleBatchNode : : removeAllChildrenWithCleanup ( bool doCleanup )
2012-03-14 10:55:17 +04:00
{
2013-12-20 01:34:41 +04:00
for ( const auto & child : _children )
2013-11-28 12:02:03 +04:00
static_cast < ParticleSystem * > ( child ) - > setBatchNode ( nullptr ) ;
2012-03-14 10:55:17 +04:00
2013-06-20 10:13:12 +04:00
Node : : removeAllChildrenWithCleanup ( doCleanup ) ;
2012-03-14 10:55:17 +04:00
2013-06-15 10:03:30 +04:00
_textureAtlas - > removeAllQuads ( ) ;
2012-03-14 10:55:17 +04:00
}
2016-11-09 05:34:50 +03:00
void ParticleBatchNode : : draw ( Renderer * renderer , const Mat4 & /*transform*/ , uint32_t flags )
2012-03-14 10:55:17 +04:00
{
2013-03-22 10:53:58 +04:00
CC_PROFILER_START ( " CCParticleBatchNode - draw " ) ;
2012-03-14 10:55:17 +04:00
2013-06-15 10:03:30 +04:00
if ( _textureAtlas - > getTotalQuads ( ) = = 0 )
2012-03-29 07:25:08 +04:00
{
2012-04-19 10:35:52 +04:00
return ;
2012-03-29 07:25:08 +04:00
}
2015-01-16 01:00:49 +03:00
_batchCommand . init ( _globalZOrder , getGLProgram ( ) , _blendFunc , _textureAtlas , _modelViewTransform , flags ) ;
2014-03-01 04:10:48 +04:00
renderer - > addCommand ( & _batchCommand ) ;
2012-04-19 10:35:52 +04:00
CC_PROFILER_STOP ( " CCParticleBatchNode - draw " ) ;
2012-03-14 10:55:17 +04:00
}
2013-12-12 08:07:20 +04:00
void ParticleBatchNode : : increaseAtlasCapacityTo ( ssize_t quantity )
2012-03-14 10:55:17 +04:00
{
2013-06-20 10:13:12 +04:00
CCLOG ( " cocos2d: ParticleBatchNode: resizing TextureAtlas capacity from [%lu] to [%lu]. " ,
2013-06-15 10:03:30 +04:00
( long ) _textureAtlas - > getCapacity ( ) ,
2012-04-19 10:35:52 +04:00
( long ) quantity ) ;
2013-06-15 10:03:30 +04:00
if ( ! _textureAtlas - > resizeCapacity ( quantity ) ) {
2012-04-19 10:35:52 +04:00
// serious problems
2012-06-08 10:11:48 +04:00
CCLOGWARN ( " cocos2d: WARNING: Not enough memory to resize the atlas " ) ;
2013-07-20 09:01:27 +04:00
CCASSERT ( false , " XXX: ParticleBatchNode #increaseAtlasCapacity SHALL handle this assert " ) ;
2012-04-19 10:35:52 +04:00
}
2012-03-14 10:55:17 +04:00
}
//sets a 0'd quad into the quads array
2013-12-05 13:19:01 +04:00
void ParticleBatchNode : : disableParticle ( int particleIndex )
2012-03-14 10:55:17 +04:00
{
2013-07-05 12:49:22 +04:00
V3F_C4B_T2F_Quad * quad = & ( ( _textureAtlas - > getQuads ( ) ) [ particleIndex ] ) ;
2012-04-19 10:35:52 +04: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 10:55:17 +04:00
}
2013-06-20 10:13:12 +04:00
// ParticleBatchNode - add / remove / reorder helper methods
2012-03-14 10:55:17 +04:00
// add child helper
2013-07-26 03:27:24 +04:00
void ParticleBatchNode : : insertChild ( ParticleSystem * system , int index )
2012-03-14 10:55:17 +04:00
{
2013-07-26 03:27:24 +04:00
system - > setAtlasIndex ( index ) ;
2012-03-14 10:55:17 +04:00
2013-07-26 03:27:24 +04:00
if ( _textureAtlas - > getTotalQuads ( ) + system - > getTotalParticles ( ) > _textureAtlas - > getCapacity ( ) )
2012-04-19 10:35:52 +04:00
{
2013-07-26 03:27:24 +04:00
increaseAtlasCapacityTo ( _textureAtlas - > getTotalQuads ( ) + system - > getTotalParticles ( ) ) ;
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04: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 03:27:24 +04:00
_textureAtlas - > fillWithEmptyQuadsFromIndex ( _textureAtlas - > getCapacity ( ) - system - > getTotalParticles ( ) , system - > getTotalParticles ( ) ) ;
2012-04-19 10:35:52 +04:00
}
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
// make room for quads, not necessary for last child
2013-07-26 03:27:24 +04:00
if ( system - > getAtlasIndex ( ) + system - > getTotalParticles ( ) ! = _textureAtlas - > getTotalQuads ( ) )
2012-04-04 17:58:04 +04:00
{
2013-07-26 03:27:24 +04:00
_textureAtlas - > moveQuadsFromIndex ( index , index + system - > getTotalParticles ( ) ) ;
2012-04-04 17:58:04 +04:00
}
2012-03-14 10:55:17 +04:00
2012-09-17 11:02:24 +04:00
// increase totalParticles here for new particles, update method of particle-system will fill the quads
2013-07-26 03:27:24 +04:00
_textureAtlas - > increaseTotalQuadsWith ( system - > getTotalParticles ( ) ) ;
2012-03-14 10:55:17 +04:00
2012-04-19 10:35:52 +04:00
updateAllAtlasIndexes ( ) ;
2012-03-14 10:55:17 +04:00
}
//rebuild atlas indexes
2013-06-20 10:13:12 +04:00
void ParticleBatchNode : : updateAllAtlasIndexes ( )
2012-03-14 10:55:17 +04:00
{
2013-12-05 13:19:01 +04:00
int index = 0 ;
2013-11-28 12:02:03 +04:00
2013-12-20 01:34:41 +04:00
for ( const auto & child : _children ) {
2013-11-28 12:02:03 +04:00
ParticleSystem * partiSys = static_cast < ParticleSystem * > ( child ) ;
partiSys - > setAtlasIndex ( index ) ;
index + = partiSys - > getTotalParticles ( ) ;
2013-12-20 01:34:41 +04:00
}
2012-03-14 10:55:17 +04:00
}
2013-06-20 10:13:12 +04:00
// ParticleBatchNode - CocosNodeTexture protocol
2012-03-14 10:55:17 +04:00
2013-12-05 13:19:01 +04:00
void ParticleBatchNode : : updateBlendFunc ( )
2012-03-14 10:55:17 +04:00
{
2013-07-26 00:36:19 +04:00
if ( ! _textureAtlas - > getTexture ( ) - > hasPremultipliedAlpha ( ) )
_blendFunc = BlendFunc : : ALPHA_NON_PREMULTIPLIED ;
2012-03-14 10:55:17 +04:00
}
2013-06-20 10:13:12 +04:00
void ParticleBatchNode : : setTexture ( Texture2D * texture )
2012-03-14 10:55:17 +04:00
{
2013-06-15 10:03:30 +04:00
_textureAtlas - > setTexture ( texture ) ;
2012-04-19 10:35:52 +04:00
// If the new texture has No premultiplied alpha, AND the blendFunc hasn't been changed, then update it
2013-06-15 10:03:30 +04:00
if ( texture & & ! texture - > hasPremultipliedAlpha ( ) & & ( _blendFunc . src = = CC_BLEND_SRC & & _blendFunc . dst = = CC_BLEND_DST ) )
2012-04-19 10:35:52 +04:00
{
2013-07-26 00:36:19 +04:00
_blendFunc = BlendFunc : : ALPHA_NON_PREMULTIPLIED ;
2012-04-19 10:35:52 +04:00
}
2012-03-14 10:55:17 +04:00
}
2013-12-05 13:19:01 +04:00
Texture2D * ParticleBatchNode : : getTexture ( ) const
2012-03-14 10:55:17 +04:00
{
2013-06-15 10:03:30 +04:00
return _textureAtlas - > getTexture ( ) ;
2012-03-14 10:55:17 +04:00
}
2013-07-05 12:49:22 +04:00
void ParticleBatchNode : : setBlendFunc ( const BlendFunc & blendFunc )
2012-04-19 10:35:52 +04:00
{
2013-06-15 10:03:30 +04:00
_blendFunc = blendFunc ;
2012-04-19 10:35:52 +04:00
}
// returns the blending function used for the texture
2013-12-05 13:19:01 +04:00
const BlendFunc & ParticleBatchNode : : getBlendFunc ( ) const
2012-03-14 10:55:17 +04:00
{
2013-06-15 10:03:30 +04:00
return _blendFunc ;
2012-03-14 10:55:17 +04:00
}
NS_CC_END