// override removeChild: void CCParticleBatchNode::removeChild(CCNode* child, bool cleanup) { // explicit nil handling if (child == NULL) { return; } 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"); CCParticleSystem* pChild = (CCParticleSystem*)child; CCNode::removeChild(pChild, cleanup); // remove child helper m_pTextureAtlas->removeQuadsAtIndex(pChild->getAtlasIndex(), pChild->getTotalParticles()); // after memmove of data, empty the quads at the end of array m_pTextureAtlas->fillWithEmptyQuadsFromIndex(m_pTextureAtlas->getTotalQuads(), pChild->getTotalParticles()); // particle could be reused for self rendering pChild->setBatchNode(NULL); updateAllAtlasIndexes(); }
// Reorder will be done in this function, no "lazy" reorder to particles void ParticleBatchNode::reorderChild(Node * aChild, int zOrder) { CCASSERT( aChild != nullptr, "Child must be non-nullptr"); CCASSERT( dynamic_cast<ParticleSystem*>(aChild) != nullptr, "CCParticleBatchNode only supports QuadParticleSystems as children"); CCASSERT( _children.contains(aChild), "Child doesn't belong to batch" ); ParticleSystem* child = static_cast<ParticleSystem*>(aChild); if( zOrder == child->getLocalZOrder() ) { return; } // no reordering if only 1 child if (!_children.empty()) { int newIndex = 0, oldIndex = 0; getCurrentIndex(&oldIndex, &newIndex, child, zOrder); if( oldIndex != newIndex ) { // reorder _children->array child->retain(); _children.erase(oldIndex); _children.insert(newIndex, child); child->release(); // save old altasIndex int oldAtlasIndex = child->getAtlasIndex(); // update atlas index updateAllAtlasIndexes(); // Find new AtlasIndex int newAtlasIndex = 0; int i = 0; for(auto size = _children.size(); i < size; i++) { ParticleSystem* node = static_cast<ParticleSystem*>(_children.at(i)); if( node == child ) { newAtlasIndex = child->getAtlasIndex(); break; } } // reorder textureAtlas quads _textureAtlas->moveQuadsFromIndex(oldAtlasIndex, child->getTotalParticles(), newAtlasIndex); child->updateWithNoTime(); } } child->setLocalZOrder(zOrder); }
// Reorder will be done in this function, no "lazy" reorder to particles void CCParticleBatchNode::reorderChild(CCNode * child, int zOrder) { 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" ); CCParticleSystem* pChild = (CCParticleSystem*)(child); if( zOrder == child->getZOrder() ) { return; } // no reordering if only 1 child if( m_pChildren->count() > 1) { unsigned int newIndex = 0, oldIndex = 0; getCurrentIndex(&oldIndex, &newIndex, pChild, zOrder); if( oldIndex != newIndex ) { // reorder m_pChildren->array pChild->retain(); m_pChildren->removeObjectAtIndex(oldIndex); m_pChildren->insertObject(pChild, newIndex); pChild->release(); // save old altasIndex unsigned int oldAtlasIndex = pChild->getAtlasIndex(); // update atlas index updateAllAtlasIndexes(); // Find new AtlasIndex unsigned int newAtlasIndex = 0; for( unsigned int i=0; i < m_pChildren->count(); i++) { CCParticleSystem* pNode = (CCParticleSystem*)m_pChildren->objectAtIndex(i); if( pNode == pChild ) { newAtlasIndex = pChild->getAtlasIndex(); break; } } // reorder textureAtlas quads m_pTextureAtlas->moveQuadsFromIndex(oldAtlasIndex, pChild->getTotalParticles(), newAtlasIndex); pChild->updateWithNoTime(); } } pChild->setZOrder(zOrder); }
// Reorder will be done in this function, no "lazy" reorder to particles void ParticleBatchNode::reorderChild(Node * aChild, int zOrder) { 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" ); ParticleSystem* child = static_cast<ParticleSystem*>(aChild); if( zOrder == child->getZOrder() ) { return; } // no reordering if only 1 child if( _children->count() > 1) { unsigned int newIndex = 0, oldIndex = 0; getCurrentIndex(&oldIndex, &newIndex, child, zOrder); if( oldIndex != newIndex ) { // reorder _children->array child->retain(); _children->removeObjectAtIndex(oldIndex); _children->insertObject(child, newIndex); child->release(); // save old altasIndex int oldAtlasIndex = child->getAtlasIndex(); // update atlas index updateAllAtlasIndexes(); // Find new AtlasIndex int newAtlasIndex = 0; for( int i=0;i < _children->count();i++) { ParticleSystem* pNode = (ParticleSystem*)_children->getObjectAtIndex(i); if( pNode == child ) { newAtlasIndex = child->getAtlasIndex(); break; } } // reorder textureAtlas quads _textureAtlas->moveQuadsFromIndex(oldAtlasIndex, child->getTotalParticles(), newAtlasIndex); child->updateWithNoTime(); } } child->_setZOrder(zOrder); }
// add child helper void ParticleBatchNode::insertChild(ParticleSystem* system, int index) { system->setAtlasIndex(index); if(_textureAtlas->getTotalQuads() + system->getTotalParticles() > _textureAtlas->getCapacity()) { increaseAtlasCapacityTo(_textureAtlas->getTotalQuads() + system->getTotalParticles()); // after a realloc empty quads of textureAtlas can be filled with gibberish (realloc doesn't perform calloc), insert empty quads to prevent it _textureAtlas->fillWithEmptyQuadsFromIndex(_textureAtlas->getCapacity() - system->getTotalParticles(), system->getTotalParticles()); } // make room for quads, not necessary for last child if (system->getAtlasIndex() + system->getTotalParticles() != _textureAtlas->getTotalQuads()) { _textureAtlas->moveQuadsFromIndex(index, index+system->getTotalParticles()); } // increase totalParticles here for new particles, update method of particle-system will fill the quads _textureAtlas->increaseTotalQuadsWith(system->getTotalParticles()); updateAllAtlasIndexes(); }
// override removeChild: void ParticleBatchNode::removeChild(Node* aChild, bool cleanup) { // explicit nil handling if (aChild == nullptr) return; CCASSERT( dynamic_cast<ParticleSystem*>(aChild) != nullptr, "CCParticleBatchNode only supports QuadParticleSystems as children"); CCASSERT(_children.contains(aChild), "CCParticleBatchNode doesn't contain the sprite. Can't remove it"); ParticleSystem* child = static_cast<ParticleSystem*>(aChild); // remove child helper _textureAtlas->removeQuadsAtIndex(child->getAtlasIndex(), child->getTotalParticles()); // after memmove of data, empty the quads at the end of array _textureAtlas->fillWithEmptyQuadsFromIndex(_textureAtlas->getTotalQuads(), child->getTotalParticles()); // particle could be reused for self rendering child->setBatchNode(nullptr); Node::removeChild(child, cleanup); updateAllAtlasIndexes(); }
// add child helper void CCParticleBatchNode::insertChild(CCParticleSystem* pSystem, unsigned int index) { pSystem->setAtlasIndex(index); if(m_pTextureAtlas->getTotalQuads() + pSystem->getTotalParticles() > m_pTextureAtlas->getCapacity()) { increaseAtlasCapacityTo(m_pTextureAtlas->getTotalQuads() + pSystem->getTotalParticles()); // 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()); } // make room for quads, not necessary for last child if (pSystem->getAtlasIndex() + pSystem->getTotalParticles() != m_pTextureAtlas->getTotalQuads()) { m_pTextureAtlas->moveQuadsFromIndex(index, index+pSystem->getTotalParticles()); } // increase totalParticles here for new particles, update method of particlesystem will fill the quads m_pTextureAtlas->increaseTotalQuadsWith(pSystem->getTotalParticles()); updateAllAtlasIndexes(); }