mirror of https://github.com/axmolengine/axmol.git
628 lines
16 KiB
C++
628 lines
16 KiB
C++
|
/****************************************************************************
|
||
|
Copyright (c) 2010 cocos2d-x.org
|
||
|
|
||
|
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 "CCSpriteBatchNode.h"
|
||
|
#include "ccConfig.h"
|
||
|
#include "CCSprite.h"
|
||
|
#include "effects/CCGrid.h"
|
||
|
#include "CCDrawingPrimitives.h"
|
||
|
#include "CCTextureCache.h"
|
||
|
#include "CGPointExtension.h"
|
||
|
|
||
|
namespace cocos2d
|
||
|
{
|
||
|
const int defaultCapacity = 29;
|
||
|
|
||
|
/*
|
||
|
* creation with CCTexture2D
|
||
|
*/
|
||
|
CCSpriteBatchNode* CCSpriteBatchNode::batchNodeWithTexture(cocos2d::CCTexture2D *tex)
|
||
|
{
|
||
|
CCSpriteBatchNode *batchNode = new CCSpriteBatchNode();
|
||
|
batchNode->initWithTexture(tex, defaultCapacity);
|
||
|
batchNode->autorelease();
|
||
|
|
||
|
return batchNode;
|
||
|
}
|
||
|
|
||
|
CCSpriteBatchNode* CCSpriteBatchNode::spriteSheetWithTexture(cocos2d::CCTexture2D *tex)
|
||
|
{
|
||
|
return batchNodeWithTexture(tex);
|
||
|
}
|
||
|
|
||
|
CCSpriteBatchNode* CCSpriteBatchNode::batchNodeWithTexture(CCTexture2D* tex, unsigned int capacity)
|
||
|
{
|
||
|
CCSpriteBatchNode *batchNode = new CCSpriteBatchNode();
|
||
|
batchNode->initWithTexture(tex, capacity);
|
||
|
batchNode->autorelease();
|
||
|
|
||
|
return batchNode;
|
||
|
}
|
||
|
|
||
|
CCSpriteBatchNode* CCSpriteBatchNode::spriteSheetWithTexture(CCTexture2D *tex, unsigned int capacity)
|
||
|
{
|
||
|
return batchNodeWithTexture(tex, capacity);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* creation with File Image
|
||
|
*/
|
||
|
CCSpriteBatchNode* CCSpriteBatchNode::batchNodeWithFile(const char *fileImage, unsigned int capacity)
|
||
|
{
|
||
|
CCSpriteBatchNode *batchNode = new CCSpriteBatchNode();
|
||
|
batchNode->initWithFile(fileImage, capacity);
|
||
|
batchNode->autorelease();
|
||
|
|
||
|
return batchNode;
|
||
|
}
|
||
|
|
||
|
CCSpriteBatchNode* CCSpriteBatchNode::spriteSheetWithFile(const char *fileImage, unsigned int capacity)
|
||
|
{
|
||
|
return batchNodeWithFile(fileImage, capacity);
|
||
|
}
|
||
|
|
||
|
CCSpriteBatchNode* CCSpriteBatchNode::batchNodeWithFile(const char *fileImage)
|
||
|
{
|
||
|
CCSpriteBatchNode *batchNode = new CCSpriteBatchNode();
|
||
|
batchNode->initWithFile(fileImage, defaultCapacity);
|
||
|
batchNode->autorelease();
|
||
|
|
||
|
return batchNode;
|
||
|
}
|
||
|
|
||
|
CCSpriteBatchNode* CCSpriteBatchNode::spriteSheetWithFile(const char *fileImage)
|
||
|
{
|
||
|
return batchNodeWithFile(fileImage);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* init with CCTexture2D
|
||
|
*/
|
||
|
bool CCSpriteBatchNode::initWithTexture(cocos2d::CCTexture2D *tex, unsigned int capacity)
|
||
|
{
|
||
|
m_blendFunc.src = CC_BLEND_SRC;
|
||
|
m_blendFunc.dst = CC_BLEND_DST;
|
||
|
m_pobTextureAtlas = new CCTextureAtlas();
|
||
|
m_pobTextureAtlas->initWithTexture(tex, capacity);
|
||
|
|
||
|
updateBlendFunc();
|
||
|
|
||
|
// no lazy alloc in this node
|
||
|
m_pChildren = new NSMutableArray<CCNode*>();
|
||
|
m_pobDescendants = new NSMutableArray<CCSprite*>();
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* init with FileImage
|
||
|
*/
|
||
|
bool CCSpriteBatchNode::initWithFile(const char* fileImage, unsigned int capacity)
|
||
|
{
|
||
|
CCTexture2D *pTexture2D = CCTextureCache::sharedTextureCache()->addImage(fileImage);
|
||
|
return initWithTexture(pTexture2D, capacity);
|
||
|
}
|
||
|
|
||
|
CCSpriteBatchNode::~CCSpriteBatchNode()
|
||
|
{
|
||
|
m_pobTextureAtlas->release();
|
||
|
m_pobDescendants->release();
|
||
|
}
|
||
|
|
||
|
// override visit
|
||
|
// don't call visit on it's children
|
||
|
void CCSpriteBatchNode::visit(void)
|
||
|
{
|
||
|
// CAREFUL:
|
||
|
// This visit is almost identical to CocosNode#visit
|
||
|
// with the exception that it doesn't call visit on it's children
|
||
|
//
|
||
|
// The alternative is to have a void CCSprite#visit, but
|
||
|
// although this is less mantainable, is faster
|
||
|
//
|
||
|
if (! m_bIsVisible)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
glPushMatrix();
|
||
|
|
||
|
if (m_pGrid && m_pGrid->isActive())
|
||
|
{
|
||
|
m_pGrid->beforeDraw();
|
||
|
transformAncestors();
|
||
|
}
|
||
|
|
||
|
transform();
|
||
|
|
||
|
draw();
|
||
|
|
||
|
if (m_pGrid && m_pGrid->isActive())
|
||
|
{
|
||
|
m_pGrid->afterDraw(this);
|
||
|
}
|
||
|
|
||
|
glPopMatrix();
|
||
|
}
|
||
|
|
||
|
// xxx deprecated
|
||
|
CCSprite* CCSpriteBatchNode::createSpriteWithRect(CGRect rect)
|
||
|
{
|
||
|
CCSprite *pSprite = CCSprite::spriteWithTexture(m_pobTextureAtlas->getTexture(), rect);
|
||
|
pSprite->useBatchNode(this);
|
||
|
|
||
|
return pSprite;
|
||
|
}
|
||
|
|
||
|
// XXX deprecated
|
||
|
void CCSpriteBatchNode::initSprite(cocos2d::CCSprite *sprite, cocos2d::CGRect rect)
|
||
|
{
|
||
|
if (sprite)
|
||
|
{
|
||
|
sprite->initWithTexture(m_pobTextureAtlas->getTexture(), rect);
|
||
|
sprite->useBatchNode(this);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CCSpriteBatchNode::addChild(CCNode *child, int zOrder, int tag)
|
||
|
{
|
||
|
assert(child != NULL);
|
||
|
|
||
|
CCSprite *pSprite = (CCSprite*)(child);
|
||
|
// check CCSprite is using the same texture id
|
||
|
assert(pSprite->getTexture()->getName() == m_pobTextureAtlas->getTexture()->getName());
|
||
|
|
||
|
CCNode::addChild(child, zOrder, tag);
|
||
|
|
||
|
unsigned int uIndex = atlasIndexForChild(pSprite, zOrder);
|
||
|
insertChild(pSprite, uIndex);
|
||
|
}
|
||
|
|
||
|
void CCSpriteBatchNode::addChild(CCNode *child)
|
||
|
{
|
||
|
CCNode::addChild(child);
|
||
|
}
|
||
|
|
||
|
void CCSpriteBatchNode::addChild(CCNode *child, int zOrder)
|
||
|
{
|
||
|
CCNode::addChild(child, zOrder);
|
||
|
}
|
||
|
|
||
|
// override reorderChild
|
||
|
void CCSpriteBatchNode::reorderChild(CCNode *child, int zOrder)
|
||
|
{
|
||
|
assert(child != NULL);
|
||
|
assert(m_pChildren->containsObject(child));
|
||
|
|
||
|
if (zOrder == child->getZOrder())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// xxx: instead of removing/adding, it is more efficient ot reorder manually
|
||
|
child->retain();
|
||
|
removeChild(child, false);
|
||
|
addChild(child, zOrder);
|
||
|
child->release();
|
||
|
}
|
||
|
|
||
|
// override remove child
|
||
|
void CCSpriteBatchNode::removeChild(CCNode *child, bool cleanup)
|
||
|
{
|
||
|
CCSprite *pSprite = (CCSprite*)(child);
|
||
|
|
||
|
// explicit null handling
|
||
|
if (pSprite == NULL)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
assert(m_pChildren->containsObject(pSprite));
|
||
|
|
||
|
// cleanup before removing
|
||
|
removeSpriteFromAtlas(pSprite);
|
||
|
|
||
|
CCNode::removeChild(pSprite, cleanup);
|
||
|
}
|
||
|
|
||
|
void CCSpriteBatchNode::removeChildAtIndex(unsigned int uIndex, bool bDoCleanup)
|
||
|
{
|
||
|
removeChild((CCSprite*)(m_pChildren->getObjectAtIndex(uIndex)), bDoCleanup);
|
||
|
}
|
||
|
|
||
|
void CCSpriteBatchNode::removeAllChildrenWithCleanup(bool bCleanup)
|
||
|
{
|
||
|
// Invalidate atlas index. issue #569
|
||
|
if (m_pChildren && m_pChildren->count() > 0)
|
||
|
{
|
||
|
CCSprite *pSprite;
|
||
|
NSMutableArray<CCNode*>::NSMutableArrayIterator iter;
|
||
|
for (iter = m_pChildren->begin(); iter != m_pChildren->end(); ++iter)
|
||
|
{
|
||
|
pSprite = (CCSprite*)(*iter);
|
||
|
|
||
|
if (! pSprite)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
pSprite->useSelfRender();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CCNode::removeAllChildrenWithCleanup(bCleanup);
|
||
|
|
||
|
m_pobDescendants->removeAllObjects();
|
||
|
m_pobTextureAtlas->removeAllQuads();
|
||
|
}
|
||
|
|
||
|
// draw
|
||
|
void CCSpriteBatchNode::draw(void)
|
||
|
{
|
||
|
// Optimization: Fast Dispatch
|
||
|
if (m_pobTextureAtlas->getTotalQuads() == 0)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (m_pobDescendants && m_pobDescendants->count() > 0)
|
||
|
{
|
||
|
CCSprite *pSprite;
|
||
|
NSMutableArray<CCSprite*>::NSMutableArrayIterator iter;
|
||
|
for (iter = m_pobDescendants->begin(); iter != m_pobDescendants->end(); ++iter)
|
||
|
{
|
||
|
pSprite = *iter;
|
||
|
|
||
|
if (! pSprite)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// fast dispatch
|
||
|
pSprite->updateTransform();
|
||
|
|
||
|
|
||
|
#if CC_SPRITESHEET_DEBUG_DRAW
|
||
|
// issue #528
|
||
|
CGRect rect = pSprite->boundingBox();
|
||
|
CGPoint vertices[4]={
|
||
|
ccp(rect.origin.x,rect.origin.y),
|
||
|
ccp(rect.origin.x+rect.size.width,rect.origin.y),
|
||
|
ccp(rect.origin.x+rect.size.width,rect.origin.y+rect.size.height),
|
||
|
ccp(rect.origin.x,rect.origin.y+rect.size.height),
|
||
|
};
|
||
|
ccDrawPoly(vertices, 4, true);
|
||
|
#endif // CC_SPRITESHEET_DEBUG_DRAW
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
|
||
|
// Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
|
||
|
// Unneeded states: -
|
||
|
bool newBlend = m_blendFunc.src != CC_BLEND_SRC || m_blendFunc.dst != CC_BLEND_DST;
|
||
|
if (newBlend)
|
||
|
{
|
||
|
glBlendFunc(m_blendFunc.src, m_blendFunc.dst);
|
||
|
}
|
||
|
|
||
|
m_pobTextureAtlas->drawQuads();
|
||
|
if (newBlend)
|
||
|
{
|
||
|
glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CCSpriteBatchNode::increaseAtlasCapacity(void)
|
||
|
{
|
||
|
// if we're going beyond the current TextureAtlas's capacity,
|
||
|
// all the previously initialized sprites will need to redo their texture coords
|
||
|
// this is likely computationally expensive
|
||
|
unsigned int quantity = (m_pobTextureAtlas->getCapacity() + 1) * 4 / 3;
|
||
|
|
||
|
CCLOG("cocos2d: CCSpriteSheet: resizing TextureAtlas capacity from %u to %u.",
|
||
|
(unsigned int)m_pobTextureAtlas->getCapacity(), (unsigned int)quantity);
|
||
|
|
||
|
if (! m_pobTextureAtlas->resizeCapacity(quantity))
|
||
|
{
|
||
|
// serious problems
|
||
|
CCLOG("cocos2d: WARNING: Not enough memory to resize the atlas");
|
||
|
assert(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
unsigned int CCSpriteBatchNode::rebuildIndexInOrder(CCSprite *pobParent, unsigned int uIndex)
|
||
|
{
|
||
|
NSMutableArray<CCNode*> *pChildren = pobParent->getChildren();
|
||
|
|
||
|
if (pChildren && pChildren->count() > 0)
|
||
|
{
|
||
|
CCSprite *pSprite;
|
||
|
NSMutableArray<CCNode*>::NSMutableArrayIterator iter;
|
||
|
for (iter = pChildren->begin(); iter != pChildren->end(); ++iter)
|
||
|
{
|
||
|
pSprite = (CCSprite*)(*iter);
|
||
|
|
||
|
if (! pSprite)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (pSprite->getZOrder() < 0)
|
||
|
{
|
||
|
uIndex = rebuildIndexInOrder(pSprite, uIndex);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ignore self (batch node)
|
||
|
if (! pobParent->isEqual(this))
|
||
|
{
|
||
|
pobParent->setAtlasIndex(uIndex);
|
||
|
uIndex++;
|
||
|
}
|
||
|
|
||
|
if (pChildren && pChildren->count() > 0)
|
||
|
{
|
||
|
CCSprite *pSprite;
|
||
|
NSMutableArray<CCNode*>::NSMutableArrayIterator iter;
|
||
|
for (iter = pChildren->begin(); iter != pChildren->end(); ++iter)
|
||
|
{
|
||
|
pSprite = (CCSprite*)(*iter);
|
||
|
|
||
|
if (! pSprite)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (pSprite->getZOrder() >= 0)
|
||
|
{
|
||
|
uIndex = rebuildIndexInOrder(pSprite, uIndex);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return uIndex;
|
||
|
}
|
||
|
|
||
|
unsigned int CCSpriteBatchNode::highestAtlasIndexInChild(CCSprite *pSprite)
|
||
|
{
|
||
|
NSMutableArray<CCNode*> *pChildren = pSprite->getChildren();
|
||
|
|
||
|
if (! pChildren || pChildren->count() == 0)
|
||
|
{
|
||
|
return pSprite->getAtlasIndex();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return highestAtlasIndexInChild((CCSprite*)(pChildren->getLastObject()));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
unsigned int CCSpriteBatchNode::lowestAtlasIndexInChild(CCSprite *pSprite)
|
||
|
{
|
||
|
NSMutableArray<CCNode*> *pChildren = pSprite->getChildren();
|
||
|
|
||
|
if (! pChildren || pChildren->count() == 0)
|
||
|
{
|
||
|
return pSprite->getAtlasIndex();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return lowestAtlasIndexInChild((CCSprite*)(pChildren->getObjectAtIndex(0)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
unsigned int CCSpriteBatchNode::atlasIndexForChild(CCSprite *pobSprite, int nZ)
|
||
|
{
|
||
|
NSMutableArray<CCNode*> *pBrothers = pobSprite->getParent()->getChildren();
|
||
|
unsigned int uChildIndex = pBrothers->getIndexOfObject(pobSprite);
|
||
|
|
||
|
// ignore parent Z if parent is spriteSheet
|
||
|
bool bIgnoreParent = (CCSpriteBatchNode*)(pobSprite->getParent()) == this;
|
||
|
CCSprite *pPrevious = NULL;
|
||
|
if (uChildIndex > 0)
|
||
|
{
|
||
|
pPrevious = (CCSprite*)(pBrothers->getObjectAtIndex(uChildIndex - 1));
|
||
|
}
|
||
|
|
||
|
// first child of the sprite sheet
|
||
|
if (bIgnoreParent)
|
||
|
{
|
||
|
if (uChildIndex == 0)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return highestAtlasIndexInChild(pPrevious) + 1;
|
||
|
}
|
||
|
|
||
|
// parent is a CCSprite, so, it must be taken into account
|
||
|
|
||
|
// first child of an CCSprite ?
|
||
|
if (uChildIndex == 0)
|
||
|
{
|
||
|
CCSprite *p = (CCSprite*)(pobSprite->getParent());
|
||
|
|
||
|
// less than parent and brothers
|
||
|
if (nZ < 0)
|
||
|
{
|
||
|
return p->getAtlasIndex();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return p->getAtlasIndex() + 1;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// previous & sprite belong to the same branch
|
||
|
if ((pPrevious->getZOrder() < 0 && nZ < 0) || (pPrevious->getZOrder() >= 0 && nZ >= 0))
|
||
|
{
|
||
|
return highestAtlasIndexInChild(pPrevious) + 1;
|
||
|
}
|
||
|
|
||
|
// else (previous < 0 and sprite >= 0 )
|
||
|
CCSprite *p = (CCSprite*)(pobSprite->getParent());
|
||
|
return p->getAtlasIndex() + 1;
|
||
|
}
|
||
|
|
||
|
// Should not happen. Error calculating Z on SpriteSheet
|
||
|
assert(0);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// add child helper
|
||
|
|
||
|
void CCSpriteBatchNode::insertChild(CCSprite *pobSprite, unsigned int uIndex)
|
||
|
{
|
||
|
pobSprite->useBatchNode(this);
|
||
|
pobSprite->setAtlasIndex(uIndex);
|
||
|
pobSprite->setDirty(true);
|
||
|
|
||
|
if (m_pobTextureAtlas->getTotalQuads() == m_pobTextureAtlas->getCapacity())
|
||
|
{
|
||
|
increaseAtlasCapacity();
|
||
|
}
|
||
|
|
||
|
ccV3F_C4B_T2F_Quad quad = pobSprite->getQuad();
|
||
|
m_pobTextureAtlas->insertQuad(&quad, uIndex);
|
||
|
|
||
|
m_pobDescendants->insertObjectAtIndex(pobSprite, uIndex);
|
||
|
|
||
|
// update indices
|
||
|
unsigned int i = 0;
|
||
|
if (m_pobDescendants && m_pobDescendants->count() > 0)
|
||
|
{
|
||
|
NSMutableArray<CCSprite*>::NSMutableArrayIterator iter;
|
||
|
for (iter = m_pobDescendants->begin(); iter != m_pobDescendants->end(); ++iter)
|
||
|
{
|
||
|
if (! *iter)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (i > uIndex)
|
||
|
{
|
||
|
(*iter)->setAtlasIndex((*iter)->getAtlasIndex() + 1);
|
||
|
}
|
||
|
|
||
|
++i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// add children recursively
|
||
|
NSMutableArray<CCNode*> *pChildren = pobSprite->getChildren();
|
||
|
if (pChildren && pChildren->count() > 0)
|
||
|
{
|
||
|
NSMutableArray<CCNode*>::NSMutableArrayIterator iterNode;
|
||
|
CCSprite *pSprite;
|
||
|
for (iterNode = pChildren->begin(); iterNode != pChildren->end(); ++iterNode)
|
||
|
{
|
||
|
pSprite = (CCSprite*)(*iterNode);
|
||
|
|
||
|
if (! pSprite)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
unsigned int uIndex = atlasIndexForChild(pSprite, pSprite->getZOrder());
|
||
|
insertChild(pSprite, uIndex);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CCSpriteBatchNode::removeSpriteFromAtlas(CCSprite *pobSprite)
|
||
|
{
|
||
|
// remove from TextureAtlas
|
||
|
m_pobTextureAtlas->removeQuadAtIndex(pobSprite->getAtlasIndex());
|
||
|
|
||
|
// Cleanup sprite. It might be reused (issue #569)
|
||
|
pobSprite->useSelfRender();
|
||
|
|
||
|
unsigned int uIndex = m_pobDescendants->getIndexOfObject(pobSprite);
|
||
|
if (uIndex != -1)
|
||
|
{
|
||
|
m_pobDescendants->removeObjectAtIndex(uIndex);
|
||
|
|
||
|
// update all sprites beyond this one
|
||
|
unsigned int count = m_pobDescendants->count();
|
||
|
|
||
|
for(; uIndex < count; ++uIndex)
|
||
|
{
|
||
|
CCSprite* s = (CCSprite*)(m_pobDescendants->getObjectAtIndex(uIndex));
|
||
|
s->setAtlasIndex( s->getAtlasIndex() - 1 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// remove children recursively
|
||
|
NSMutableArray<CCNode*> *pChildren = pobSprite->getChildren();
|
||
|
if (pChildren && pChildren->count() > 0)
|
||
|
{
|
||
|
CCSprite *pSprite;
|
||
|
NSMutableArray<CCNode*>::NSMutableArrayIterator iter;
|
||
|
for (iter = pChildren->begin(); iter != pChildren->end(); ++iter)
|
||
|
{
|
||
|
pSprite = (CCSprite*)(*iter);
|
||
|
|
||
|
if (! pSprite)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
removeSpriteFromAtlas(pSprite);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CCSpriteBatchNode::updateBlendFunc(void)
|
||
|
{
|
||
|
if (! m_pobTextureAtlas->getTexture()->getHasPremultipliedAlpha())
|
||
|
{
|
||
|
m_blendFunc.src = GL_SRC_ALPHA;
|
||
|
m_blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// CocosNodeTexture protocol
|
||
|
void CCSpriteBatchNode::setBlendFunc(ccBlendFunc blendFunc)
|
||
|
{
|
||
|
m_blendFunc = blendFunc;
|
||
|
}
|
||
|
|
||
|
ccBlendFunc CCSpriteBatchNode::getBlendFunc(void)
|
||
|
{
|
||
|
return m_blendFunc;
|
||
|
}
|
||
|
|
||
|
CCTexture2D* CCSpriteBatchNode::getTexture(void)
|
||
|
{
|
||
|
return m_pobTextureAtlas->getTexture();
|
||
|
}
|
||
|
|
||
|
void CCSpriteBatchNode::setTexture(CCTexture2D *texture)
|
||
|
{
|
||
|
m_pobTextureAtlas->setTexture(texture);
|
||
|
updateBlendFunc();
|
||
|
}
|
||
|
|
||
|
}
|