CCActionInterval* CCAnimate::reverse(void)
{
	NSMutableArray<CCSpriteFrame*> *pOldArray = m_pAnimation->getFrames();
	NSMutableArray<CCSpriteFrame*> *pNewArray = new NSMutableArray<CCSpriteFrame*>(pOldArray->count());
   
	if (pOldArray->count() > 0)
	{
		CCSpriteFrame *pElement;
		NSMutableArray<CCSpriteFrame*>::NSMutableArrayRevIterator iter;
		for (iter = pOldArray->rbegin(); iter != pOldArray->rend(); iter++)
		{
			pElement = *iter;
			if (! pElement)
			{
				break;
			}

			pNewArray->addObject((CCSpriteFrame*)(pElement->copy()->autorelease()));
		}
	}

	CCAnimation *pNewAnim = CCAnimation::animationWithName(m_pAnimation->getName(),
		m_pAnimation->getDelay(), pNewArray);

	pNewArray->release();

	return CCAnimate::actionWithDuration(m_fDuration, pNewAnim, m_bRestoreOriginalFrame);
}
	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;
	}
	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);
			}
		}
	}
	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)));
		}
	}
	bool CCTMXTiledMap::initWithTMXFile(const char *tmxFile)
	{
		NSAssert(tmxFile != NULL && strlen(tmxFile)>0, "TMXTiledMap: tmx file should not bi nil");
		
		setContentSize(CGSizeZero);

		CCTMXMapInfo *mapInfo = CCTMXMapInfo::formatWithTMXFile(tmxFile);

		NSAssert( mapInfo->getTilesets()->count() != 0, "TMXTiledMap: Map not found. Please check the filename.");

		m_tMapSize = mapInfo->getMapSize();
		m_tTileSize = mapInfo->getTileSize();
		m_nMapOrientation = mapInfo->getOrientation();
		setObjectGroups(mapInfo->getObjectGroups());
		setProperties(mapInfo->getProperties());
		CCX_SAFE_RELEASE(m_pTileProperties);
		m_pTileProperties = mapInfo->getTileProperties();
		CCX_SAFE_RETAIN(m_pTileProperties);

		int idx = 0;

		NSMutableArray<CCTMXLayerInfo*>* layers = mapInfo->getLayers();
		if (layers && layers->count()>0)
		{
			CCTMXLayerInfo *layerInfo = NULL;
			NSMutableArray<CCTMXLayerInfo*>::NSMutableArrayIterator it;
			for (it = layers->begin(); it != layers->end(); ++it)
			{
				layerInfo = *it;
				if (layerInfo && layerInfo->m_bVisible)
				{
					CCTMXLayer *child = parseLayer(layerInfo, mapInfo);
					addChild((CCNode*)child, idx, idx);

					// update content size with the max size
					CGSize childSize = child->getContentSize();
					CGSize currentSize = this->getContentSize();
					currentSize.width = MAX( currentSize.width, childSize.width );
					currentSize.height = MAX( currentSize.height, childSize.height );
					this->setContentSize(currentSize);

					idx++;
				}
			}
		}
		return true;
	}
	CCTMXTilesetInfo * CCTMXTiledMap::tilesetForLayer(CCTMXLayerInfo *layerInfo, CCTMXMapInfo *mapInfo)
	{
		CCTMXTilesetInfo *tileset = NULL;
		//CFByteOrder o = CFByteOrderGetCurrent();

		CGSize size = layerInfo->m_tLayerSize;
		NSMutableArray<CCTMXTilesetInfo*>* tilesets = mapInfo->getTilesets();
		if (tilesets && tilesets->count()>0)
		{
			CCTMXTilesetInfo *tileset = NULL;
			NSMutableArray<CCTMXTilesetInfo*>::NSMutableArrayRevIterator rit;
			for (rit = tilesets->rbegin(); rit != tilesets->rend(); ++rit)
			{
				tileset = *rit;
				if (tileset)
				{
					for( unsigned int y=0; y < size.height; y++ )
					{
						for( unsigned int x=0; x < size.width; x++ ) 
						{
							unsigned int pos = (unsigned int)(x + size.width * y);
							unsigned int gid = layerInfo->m_pTiles[ pos ];

							// gid are stored in little endian.
							// if host is big endian, then swap
							//if( o == CFByteOrderBigEndian )
							//	gid = CFSwapInt32( gid );
							/* We support little endian.*/

							// XXX: gid == 0 --> empty tile
							if( gid != 0 ) 
							{
								// Optimization: quick return
								// if the layer is invalid (more than 1 tileset per layer) an assert will be thrown later
								if( gid >= tileset->m_uFirstGid )
									return tileset;
							}
						}
					}		
				}
			}
		}

		// If all the tiles are 0, return empty tileset
		CCLOG("cocos2d: Warning: TMX Layer '%@' has no tiles", layerInfo.name);
		return tileset;
	}
void CCAnimate::update(cocos2d::ccTime time)
{
	NSMutableArray<CCSpriteFrame*> *pFrames = m_pAnimation->getFrames();
	unsigned int numberOfFrames = pFrames->count();

	unsigned int idx = (unsigned int)(time * numberOfFrames);

	if (idx >= numberOfFrames)
	{
		idx = numberOfFrames - 1;
	}

	CCSprite *pSprite = (CCSprite*)(m_pTarget);
	if (! pSprite->isFrameDisplayed(pFrames->getObjectAtIndex(idx)))
	{
		pSprite->setDisplayFrame(pFrames->getObjectAtIndex(idx));
	}
}
	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);
			}
		}
	}