code:
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
Copyright (c) 2009      Valentin Milea
Copyright (c) 2011      Zynga Inc.

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 "CCNode.h"
#include "CCPointExtension.h"
#include "support/TransformUtils.h"
#include "CCCamera.h"
#include "effects/CCGrid.h"
#include "CCDirector.h"
#include "CCScheduler.h"
#include "CCTouch.h"
#include "CCActionManager.h"
#include "CCScriptSupport.h"

#if CC_COCOSNODE_RENDER_SUBPIXEL
#define RENDER_IN_SUBPIXEL
#else
#define RENDER_IN_SUBPIXEL (int)
#endif

namespace   cocos2d {

CCNode::CCNode(void)
: m_nZOrder(0)
, m_fVertexZ(0.0f)
, m_fRotation(0.0f)
, m_fScaleX(1.0f)
, m_fScaleY(1.0f)
, m_tPosition(CCPointZero)
, m_tPositionInPixels(CCPointZero)
, m_fSkewX(0.0)
, m_fSkewY(0.0)
// children (lazy allocs)
, m_pChildren(NULL)
// lazy alloc
, m_pCamera(NULL)
, m_pGrid(NULL)
, m_bIsVisible(true)
, m_tAnchorPoint(CCPointZero)
, m_tAnchorPointInPixels(CCPointZero)
, m_tContentSize(CCSizeZero)
, m_tContentSizeInPixels(CCSizeZero)
, m_bIsRunning(false)
, m_pParent(NULL)
// "whole screen" objects. like Scenes and Layers, should set isRelativeAnchorPoint to false
, m_bIsRelativeAnchorPoint(true)
, m_nTag(kCCNodeTagInvalid)
// userData is always inited as nil
, m_pUserData(NULL)
, m_bIsTransformDirty(true)
, m_bIsInverseDirty(true)
#ifdef CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
, m_bIsTransformGLDirty(true)
#endif
, m_nScriptHandler(0)
{
    // nothing
}
CCNode::~CCNode(void)
{
	CCLOGINFO( "cocos2d: deallocing" );

	// attributes
	CC_SAFE_RELEASE(m_pCamera);

	CC_SAFE_RELEASE(m_pGrid);

	if(m_pChildren && m_pChildren->count() > 0)
	{
        CCObject* child;
        CCARRAY_FOREACH(m_pChildren, child)
        {
            CCNode* pChild = (CCNode*) child;
            if (pChild)
            {
                pChild->m_pParent = NULL;
            }
        }
	}

	// children
	CC_SAFE_RELEASE(m_pChildren);

}

void CCNode::arrayMakeObjectsPerformSelector(CCArray* pArray, callbackFunc func)
{
	if(pArray && pArray->count() > 0)
	{
        CCObject* child;
        CCARRAY_FOREACH(pArray, child)
        {
            CCNode* pNode = (CCNode*) child;
            if(pNode && (0 != func))
            {
                (pNode->*func)();
            }
        }
	}
}

float CCNode::getSkewX()
{
	return m_fSkewX;
}

void CCNode::setSkewX(float newSkewX)
{
	m_fSkewX = newSkewX;
	m_bIsTransformDirty = m_bIsInverseDirty = true;
#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
	m_bIsTransformGLDirty = true;
#endif
}

float CCNode::getSkewY()
{
	return m_fSkewY;
}

void CCNode::setSkewY(float newSkewY)
{
	m_fSkewY = newSkewY;

	m_bIsTransformDirty = m_bIsInverseDirty = true;
#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
	m_bIsTransformGLDirty = true;
#endif
}

/// zOrder getter
int CCNode::getZOrder()
{
	return m_nZOrder;
}

/// zOrder setter : private method
/// used internally to alter the zOrder variable. DON'T call this method manually
void CCNode::setZOrder(int z)
{
	m_nZOrder = z;
}

/// ertexZ getter
float CCNode::getVertexZ()
{
	return m_fVertexZ / CC_CONTENT_SCALE_FACTOR();
}

/// vertexZ setter
void CCNode::setVertexZ(float var)
{
	m_fVertexZ = var * CC_CONTENT_SCALE_FACTOR();
}

/// rotation getter
float CCNode::getRotation()
{
	return m_fRotation;
}

/// rotation setter
void CCNode::setRotation(float newRotation)
{
	m_fRotation = newRotation;
	m_bIsTransformDirty = m_bIsInverseDirty = true;
#ifdef CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
	m_bIsTransformGLDirty = true;
#endif
}

/// scale getter
float CCNode::getScale(void)
{
	CCAssert( m_fScaleX == m_fScaleY, "CCNode#scale. ScaleX != ScaleY. Don't know which one to return");
	return m_fScaleX;
}

/// scale setter
void CCNode::setScale(float scale)
{
	m_fScaleX = m_fScaleY = scale;
	m_bIsTransformDirty = m_bIsInverseDirty = true;
#ifdef CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
	m_bIsTransformGLDirty = true;
#endif
}

/// scaleX getter
float CCNode::getScaleX()
{
	return m_fScaleX;
}

/// scaleX setter
void CCNode::setScaleX(float newScaleX)
{
	m_fScaleX = newScaleX;
	m_bIsTransformDirty = m_bIsInverseDirty = true;
#ifdef CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
	m_bIsTransformGLDirty = true;
#endif
}

/// scaleY getter
float CCNode::getScaleY()
{
	return m_fScaleY;
}

/// scaleY setter
void CCNode::setScaleY(float newScaleY)
{
	m_fScaleY = newScaleY;
	m_bIsTransformDirty = m_bIsInverseDirty = true;
#ifdef CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
	m_bIsTransformGLDirty = true;
#endif
}

/// position getter
const CCPoint& CCNode::getPosition()
{
	return m_tPosition;
}

/// position setter
void CCNode::setPosition(const CCPoint& newPosition)
{
	m_tPosition = newPosition;
	if (CC_CONTENT_SCALE_FACTOR() == 1)
	{
		m_tPositionInPixels = m_tPosition;
	}
	else
	{
		m_tPositionInPixels = ccpMult(newPosition, CC_CONTENT_SCALE_FACTOR());
	}

	m_bIsTransformDirty = m_bIsInverseDirty = true;
#ifdef CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
	m_bIsTransformGLDirty = true;
#endif
}

void CCNode::setPositionInPixels(const CCPoint& newPosition)
{
    m_tPositionInPixels = newPosition;

	if ( CC_CONTENT_SCALE_FACTOR() == 1)
	{
		m_tPosition = m_tPositionInPixels;
	}
	else
	{
		m_tPosition = ccpMult(newPosition, 1/CC_CONTENT_SCALE_FACTOR());
	}

	m_bIsTransformDirty = m_bIsInverseDirty = true;

#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
	m_bIsTransformGLDirty = true;
#endif // CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
}

const CCPoint& CCNode::getPositionInPixels()
{
	return m_tPositionInPixels;
}

const CCPoint& CCNode::getPositionLua(void)
{
    return m_tPosition;
}

void CCNode::getPosition(float* x, float* y)
{
    *x = m_tPosition.x;
    *y = m_tPosition.y;
}

float CCNode::getPositionX(void)
{
    return m_tPosition.x;
}

float CCNode::getPositionY(void)
{
    return  m_tPosition.y;
}

void CCNode::setPositionX(float x)
{
    setPosition(ccp(x, m_tPosition.y));
}

void CCNode::setPositionY(float y)
{
    setPosition(ccp(m_tPosition.x, y));
}

void CCNode::setPosition(float x, float y)
{
    setPosition(ccp(x, y));
}

void CCNode::setPositionInPixels(float x, float y)
{
    setPositionInPixels(ccp(x, y));
}

/// children getter
CCArray* CCNode::getChildren()
{
	return m_pChildren;
}

unsigned int CCNode::getChildrenCount(void)
{
    return m_pChildren ? m_pChildren->count() : 0;
}

/// camera getter: lazy alloc
CCCamera* CCNode::getCamera()
{
	if (!m_pCamera)
	{
		m_pCamera = new CCCamera();
	}

	return m_pCamera;
}

/// grid getter
CCGridBase* CCNode::getGrid()
{
	return m_pGrid;
}

/// grid setter
void CCNode::setGrid(CCGridBase* pGrid)
{
	CC_SAFE_RETAIN(pGrid);
	CC_SAFE_RELEASE(m_pGrid);
	m_pGrid = pGrid;
}

/// isVisible getter
bool CCNode::getIsVisible()
{
	return m_bIsVisible;
}

/// isVisible setter
void CCNode::setIsVisible(bool var)
{
	m_bIsVisible = var;
}

/// anchorPoint getter
const CCPoint& CCNode::getAnchorPoint()
{
	return m_tAnchorPoint;
}

void CCNode::setAnchorPoint(const CCPoint& point)
{
	if( ! CCPoint::CCPointEqualToPoint(point, m_tAnchorPoint) )
	{
		m_tAnchorPoint = point;
		m_tAnchorPointInPixels = ccp( m_tContentSizeInPixels.width * m_tAnchorPoint.x, m_tContentSizeInPixels.height * m_tAnchorPoint.y );
		m_bIsTransformDirty = m_bIsInverseDirty = true;
#ifdef CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
		m_bIsTransformGLDirty = true;
#endif
	}
}

/// anchorPointInPixels getter
const CCPoint& CCNode::getAnchorPointInPixels()
{
	return m_tAnchorPointInPixels;
}

/// contentSize getter
const CCSize& CCNode::getContentSize()
{
	return m_tContentSize;
}

void CCNode::setContentSize(const CCSize& size)
{
	if( ! CCSize::CCSizeEqualToSize(size, m_tContentSize) )
	{
		m_tContentSize = size;

        if( CC_CONTENT_SCALE_FACTOR() == 1 )
        {
            m_tContentSizeInPixels = m_tContentSize;
        }
        else
        {
            m_tContentSizeInPixels = CCSizeMake( size.width * CC_CONTENT_SCALE_FACTOR(), size.height * CC_CONTENT_SCALE_FACTOR() );
        }

		m_tAnchorPointInPixels = ccp( m_tContentSizeInPixels.width * m_tAnchorPoint.x, m_tContentSizeInPixels.height * m_tAnchorPoint.y );
		m_bIsTransformDirty = m_bIsInverseDirty = true;
#ifdef CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
		m_bIsTransformGLDirty = true;
#endif
	}
}

void CCNode::setContentSizeInPixels(const CCSize& size)
{
	if (! CCSize::CCSizeEqualToSize(size, m_tContentSizeInPixels))
	{
        m_tContentSizeInPixels = size;

		if (CC_CONTENT_SCALE_FACTOR() == 1)
		{
			m_tContentSize = m_tContentSizeInPixels;
		}
		else
		{
			m_tContentSize = CCSizeMake(size.width / CC_CONTENT_SCALE_FACTOR(), size.height / CC_CONTENT_SCALE_FACTOR());
		}

		m_tAnchorPointInPixels = ccp(m_tContentSizeInPixels.width * m_tAnchorPoint.x, m_tContentSizeInPixels.height * m_tAnchorPoint.y);
		m_bIsTransformDirty = m_bIsInverseDirty = true;

#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
		m_bIsTransformGLDirty = true;
#endif // CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
	}
}

const CCSize& CCNode::getContentSizeInPixels()
{
	return m_tContentSizeInPixels;
}

// isRunning getter
bool CCNode::getIsRunning()
{
	return m_bIsRunning;
}

/// parent getter
CCNode * CCNode::getParent()
{
	return m_pParent;
}
/// parent setter
void CCNode::setParent(CCNode * var)
{
	m_pParent = var;
}

/// isRelativeAnchorPoint getter
bool CCNode::getIsRelativeAnchorPoint()
{
	return m_bIsRelativeAnchorPoint;
}
/// isRelativeAnchorPoint setter
void CCNode::setIsRelativeAnchorPoint(bool newValue)
{
	m_bIsRelativeAnchorPoint = newValue;
	m_bIsTransformDirty = m_bIsInverseDirty = true;
#ifdef CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
	m_bIsTransformGLDirty = true;
#endif
}

/// tag getter
int CCNode::getTag()
{
	return m_nTag;
}

/// tag setter
void CCNode::setTag(int var)
{
	m_nTag = var;
}

/// userData getter
void * CCNode::getUserData()
{
	return m_pUserData;
}

/// userData setter
void CCNode::setUserData(void *var)
{
	m_pUserData = var;
}

CCRect CCNode::boundingBox()
{
	CCRect ret = boundingBoxInPixels();
	return CC_RECT_PIXELS_TO_POINTS(ret);
}

CCRect CCNode::boundingBoxInPixels()
{
	CCRect rect = CCRectMake(0, 0, m_tContentSizeInPixels.width, m_tContentSizeInPixels.height);
	return CCRectApplyAffineTransform(rect, nodeToParentTransform());
}

CCNode * CCNode::node(void)
{
	CCNode * pRet = new CCNode();
	pRet->autorelease();
	return pRet;
}

void CCNode::cleanup()
{
	// actions
	this->stopAllActions();
	this->unscheduleAllSelectors();

	// timers
	arrayMakeObjectsPerformSelector(m_pChildren, &CCNode::cleanup);
}

char * CCNode::description()
{
	char *ret = new char[100] ;
	sprintf(ret, "<CCNode | Tag = %d>", m_nTag);
	return ret;
}

// lazy allocs
void CCNode::childrenAlloc(void)
{
    m_pChildren = CCArray::arrayWithCapacity(4);
    m_pChildren->retain();
}

CCNode* CCNode::getChildByTag(int aTag)
{
	CCAssert( aTag != kCCNodeTagInvalid, "Invalid tag");

	if(m_pChildren && m_pChildren->count() > 0)
	{
        CCObject* child;
        CCARRAY_FOREACH(m_pChildren, child)
        {
            CCNode* pNode = (CCNode*) child;
			if(pNode && pNode->m_nTag == aTag)
				return pNode;
		}
	}
	return NULL;
}

/* "add" logic MUST only be on this method
* If a class want's to extend the 'addChild' behaviour it only needs
* to override this method
*/
void CCNode::addChild(CCNode *child, int zOrder, int tag)
{
	CCAssert( child != NULL, "Argument must be non-nil");
	CCAssert( child->m_pParent == NULL, "child already added. It can't be added again");

	if( ! m_pChildren )
	{
		this->childrenAlloc();
	}

	this->insertChild(child, zOrder);

	child->m_nTag = tag;

	child->setParent(this);

	if( m_bIsRunning )
	{
		child->onEnter();
		child->onEnterTransitionDidFinish();
	}
}

void CCNode::addChild(CCNode *child, int zOrder)
{
	CCAssert( child != NULL, "Argument must be non-nil");
	this->addChild(child, zOrder, child->m_nTag);
}

void CCNode::addChild(CCNode *child)
{
	CCAssert( child != NULL, "Argument must be non-nil");
	this->addChild(child, child->m_nZOrder, child->m_nTag);
}

void CCNode::removeFromParentAndCleanup(bool cleanup)
{
	this->m_pParent->removeChild(this,cleanup);
}

/* "remove" logic MUST only be on this method
* If a class want's to extend the 'removeChild' behavior it only needs
* to override this method
*/
void CCNode::removeChild(CCNode* child, bool cleanup)
{
	// explicit nil handling
	if (m_pChildren == NULL)
	{
		return;
	}

	if ( m_pChildren->containsObject(child) )
	{
		this->detachChild(child,cleanup);
	}
}

void CCNode::removeChildByTag(int tag, bool cleanup)
{
	CCAssert( tag != kCCNodeTagInvalid, "Invalid tag");

	CCNode *child = this->getChildByTag(tag);

	if (child == NULL)
	{
		CCLOG("cocos2d: removeChildByTag: child not found!");
	}
	else
	{
		this->removeChild(child, cleanup);
	}
}

void CCNode::removeAllChildrenWithCleanup(bool cleanup)
{
	// not using detachChild improves speed here
	if ( m_pChildren && m_pChildren->count() > 0 )
	{
        CCObject* child;
        CCARRAY_FOREACH(m_pChildren, child)
		{
            CCNode* pNode = (CCNode*) child;
			if (pNode)
			{
				// IMPORTANT:
				//  -1st do onExit
				//  -2nd cleanup
				if(m_bIsRunning)
				{
					pNode->onExit();
				}

				if (cleanup)
				{
					pNode->cleanup();
				}
				// set parent nil at the end
				pNode->setParent(NULL);
			}
		}

		m_pChildren->removeAllObjects();
	}

}

void CCNode::detachChild(CCNode *child, bool doCleanup)
{
	// IMPORTANT:
	//  -1st do onExit
	//  -2nd cleanup
	if (m_bIsRunning)
	{
		child->onExit();
	}

	// If you don't do cleanup, the child's actions will not get removed and the
	// its scheduledSelectors_ dict will not get released!
	if (doCleanup)
	{
		child->cleanup();
	}

	// set parent nil at the end
	child->setParent(NULL);

	m_pChildren->removeObject(child);
}

// helper used by reorderChild & add
void CCNode::insertChild(CCNode* child, int z)
{
    unsigned int index = 0;
    CCNode* a = (CCNode*) m_pChildren->lastObject();
    if (!a || a->getZOrder() <= z)
    {
        m_pChildren->addObject(child);
    }
    else
    {
        CCObject* pObject;
        CCARRAY_FOREACH(m_pChildren, pObject)
        {
            CCNode* pNode = (CCNode*) pObject;
            if ( pNode && (pNode->m_nZOrder > z ))
            {
                m_pChildren->insertObject(child, index);
                break;
            }
            index++;
        }
    }

    child->setZOrder(z);
}

void CCNode::reorderChild(CCNode *child, int zOrder)
{
	CCAssert( child != NULL, "Child must be non-nil");

	child->retain();
	m_pChildren->removeObject(child);

	insertChild(child, zOrder);
	child->release();
}

 void CCNode::draw()
 {
	 //CCAssert(0);
 	// override me
 	// Only use- this function to draw your staff.
 	// DON'T draw your stuff outside this method
 }

void CCNode::visit()
{
	// quick return if not visible
	if (!m_bIsVisible)
	{
		return;
	}
	glPushMatrix();

 	if (m_pGrid && m_pGrid->isActive())
 	{
 		m_pGrid->beforeDraw();
 		this->transformAncestors();
 	}

	this->transform();

    CCNode* pNode = NULL;
    unsigned int i = 0;

	if(m_pChildren && m_pChildren->count() > 0)
	{
		// draw children zOrder < 0
        ccArray *arrayData = m_pChildren->data;
        for( ; i < arrayData->num; i++ )
        {
            pNode = (CCNode*) arrayData->arr[i];

			if ( pNode && pNode->m_nZOrder < 0 )
			{
				pNode->visit();
			}
			else
			{
				break;
			}
		}
    }

	// self draw
	this->draw();

	// draw children zOrder >= 0
    if (m_pChildren && m_pChildren->count() > 0)
    {
        ccArray *arrayData = m_pChildren->data;
        for( ; i < arrayData->num; i++ )
        {
            pNode = (CCNode*) arrayData->arr[i];
            if (pNode)
            {
                pNode->visit();
            }
		}
	}

 	if (m_pGrid && m_pGrid->isActive())
 	{
 		m_pGrid->afterDraw(this);
	}

	glPopMatrix();
}

void CCNode::transformAncestors()
{
	if( m_pParent != NULL  )
	{
		m_pParent->transformAncestors();
		m_pParent->transform();
	}
}

void CCNode::transform()
{
	// transformations

#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
	// BEGIN alternative -- using cached transform
	//
	if( m_bIsTransformGLDirty ) {
		CCAffineTransform t = this->nodeToParentTransform();
		CGAffineToGL(&t, m_pTransformGL);
		m_bIsTransformGLDirty = false;
	}

	glMultMatrixf(m_pTransformGL);
	if( m_fVertexZ )
	{
		glTranslatef(0, 0, m_fVertexZ);
	}

	// XXX: Expensive calls. Camera should be integrated into the cached affine matrix
	if (m_pCamera && !(m_pGrid && m_pGrid->isActive())) {
		bool translate = (m_tAnchorPointInPixels.x != 0.0f || m_tAnchorPointInPixels.y != 0.0f);

		if( translate )
		{
			ccglTranslate(RENDER_IN_SUBPIXEL(m_tAnchorPointInPixels.x), RENDER_IN_SUBPIXEL(m_tAnchorPointInPixels.y), 0);
		}

		m_pCamera->locate();

		if( translate )
		{
			ccglTranslate(RENDER_IN_SUBPIXEL(-m_tAnchorPointInPixels.x), RENDER_IN_SUBPIXEL(-m_tAnchorPointInPixels.y), 0);
		}
	}

	// END alternative

#else
	// BEGIN original implementation
	//
	// translate
	if ( m_bIsRelativeAnchorPoint && (m_tAnchorPointInPixels.x != 0 || m_tAnchorPointInPixels.y != 0 ) )
		glTranslatef( RENDER_IN_SUBPIXEL(-m_tAnchorPointInPixels.x), RENDER_IN_SUBPIXEL(-m_tAnchorPointInPixels.y), 0);

	if (m_tAnchorPointInPixels.x != 0 || m_tAnchorPointInPixels.y != 0)
		glTranslatef( RENDER_IN_SUBPIXEL(m_tPositionInPixels.x + m_tAnchorPointInPixels.x), RENDER_IN_SUBPIXEL(m_tPositionInPixels.y + m_tAnchorPointInPixels.y), m_fVertexZ);
	else if ( m_tPositionInPixels.x !=0 || m_tPositionInPixels.y !=0 || m_fVertexZ != 0)
		glTranslatef( RENDER_IN_SUBPIXEL(m_tPositionInPixels.x), RENDER_IN_SUBPIXEL(m_tPositionInPixels.y), m_fVertexZ );

	// rotate
	if (m_fRotation != 0.0f )
		glRotatef( -m_fRotation, 0.0f, 0.0f, 1.0f );

	// skew
	if ( (skewX_ != 0.0f) || (skewY_ != 0.0f) )
	{
		CCAffineTransform skewMatrix = CCAffineTransformMake( 1.0f, tanf(CC_DEGREES_TO_RADIANS(skewY_)), tanf(CC_DEGREES_TO_RADIANS(skewX_)), 1.0f, 0.0f, 0.0f );
		GLfloat	glMatrix[16];
		CCAffineToGL(&skewMatrix, glMatrix);
		glMultMatrixf(glMatrix);
	}

	// scale
	if (m_fScaleX != 1.0f || m_fScaleY != 1.0f)
		glScalef( m_fScaleX, m_fScaleY, 1.0f );

	if ( m_pCamera  && !(m_pGrid && m_pGrid->isActive()) )
		m_pCamera->locate();

	// restore and re-position point
	if (m_tAnchorPointInPixels.x != 0.0f || m_tAnchorPointInPixels.y != 0.0f)
		glTranslatef(RENDER_IN_SUBPIXEL(-m_tAnchorPointInPixels.x), RENDER_IN_SUBPIXEL(-m_tAnchorPointInPixels.y), 0);

	//
	// END original implementation
#endif

}

void CCNode::onEnter()
{
	arrayMakeObjectsPerformSelector(m_pChildren, &CCNode::onEnter);

	this->resumeSchedulerAndActions();

	m_bIsRunning = true;

    if (m_nScriptHandler)
    {
        CCScriptEngineManager::sharedManager()->getScriptEngine()->executeFunctionWithIntegerData(m_nScriptHandler, kCCNodeOnEnter);
    }
}

void CCNode::onEnterTransitionDidFinish()
{
	arrayMakeObjectsPerformSelector(m_pChildren, &CCNode::onEnterTransitionDidFinish);
}

void CCNode::onExit()
{
	this->pauseSchedulerAndActions();

	m_bIsRunning = false;

    if (m_nScriptHandler)
    {
        CCScriptEngineManager::sharedManager()->getScriptEngine()->executeFunctionWithIntegerData(m_nScriptHandler, kCCNodeOnExit);
    }

	arrayMakeObjectsPerformSelector(m_pChildren, &CCNode::onExit);
}

void CCNode::registerScriptHandler(int nHandler)
{
    unregisterScriptHandler();
    m_nScriptHandler = nHandler;
    LUALOG("[LUA] Add CCNode event handler: %d", m_nScriptHandler);
}

void CCNode::unregisterScriptHandler(void)
{
    if (m_nScriptHandler)
    {
        CCScriptEngineManager::sharedManager()->getScriptEngine()->removeLuaHandler(m_nScriptHandler);
        LUALOG("[LUA] Remove CCNode event handler: %d", m_nScriptHandler);
        m_nScriptHandler = 0;
    }
}

CCAction * CCNode::runAction(CCAction* action)
{
	CCAssert( action != NULL, "Argument must be non-nil");
	CCActionManager::sharedManager()->addAction(action, this, !m_bIsRunning);
	return action;
}

void CCNode::stopAllActions()
{
	CCActionManager::sharedManager()->removeAllActionsFromTarget(this);
}

void CCNode::stopAction(CCAction* action)
{
	CCActionManager::sharedManager()->removeAction(action);
}

void CCNode::stopActionByTag(int tag)
{
	CCAssert( tag != kCCActionTagInvalid, "Invalid tag");
	CCActionManager::sharedManager()->removeActionByTag(tag, this);
}

CCAction * CCNode::getActionByTag(int tag)
{
	CCAssert( tag != kCCActionTagInvalid, "Invalid tag");
	return CCActionManager::sharedManager()->getActionByTag(tag, this);
}

unsigned int CCNode::numberOfRunningActions()
{
	return CCActionManager::sharedManager()->numberOfRunningActionsInTarget(this);
}

// CCNode - Callbacks

void CCNode::scheduleUpdate()
{
	scheduleUpdateWithPriority(0);
}

void CCNode::scheduleUpdateWithPriority(int priority)
{
	CCScheduler::sharedScheduler()->scheduleUpdateForTarget(this, priority, !m_bIsRunning);
}

void CCNode::unscheduleUpdate()
{
	CCScheduler::sharedScheduler()->unscheduleUpdateForTarget(this);
}

void CCNode::schedule(SEL_SCHEDULE selector)
{
	this->schedule(selector, 0);
}

void CCNode::schedule(SEL_SCHEDULE selector, ccTime interval)
{
	CCAssert( selector, "Argument must be non-nil");
	CCAssert( interval >=0, "Argument must be positive");

	CCScheduler::sharedScheduler()->scheduleSelector(selector, this, interval, !m_bIsRunning);
}

void CCNode::unschedule(SEL_SCHEDULE selector)
{
	// explicit nil handling
	if (selector == 0)
		return;

	CCScheduler::sharedScheduler()->unscheduleSelector(selector, this);
}

void CCNode::unscheduleAllSelectors()
{
	CCScheduler::sharedScheduler()->unscheduleAllSelectorsForTarget(this);
}

void CCNode::resumeSchedulerAndActions()
{
	CCScheduler::sharedScheduler()->resumeTarget(this);
	CCActionManager::sharedManager()->resumeTarget(this);
}

void CCNode::pauseSchedulerAndActions()
{
	CCScheduler::sharedScheduler()->pauseTarget(this);
	CCActionManager::sharedManager()->pauseTarget(this);
}

CCAffineTransform CCNode::nodeToParentTransform(void)
{
	if (m_bIsTransformDirty) {

		m_tTransform = CCAffineTransformIdentity;

		if( ! m_bIsRelativeAnchorPoint && ! CCPoint::CCPointEqualToPoint(m_tAnchorPointInPixels, CCPointZero) )
		{
			m_tTransform = CCAffineTransformTranslate(m_tTransform, m_tAnchorPointInPixels.x, m_tAnchorPointInPixels.y);
		}

		if(! CCPoint::CCPointEqualToPoint(m_tPositionInPixels, CCPointZero))
		{
			m_tTransform = CCAffineTransformTranslate(m_tTransform, m_tPositionInPixels.x, m_tPositionInPixels.y);
		}

		if(m_fRotation != 0)
		{
			m_tTransform = CCAffineTransformRotate(m_tTransform, -CC_DEGREES_TO_RADIANS(m_fRotation));
		}

		if(m_fSkewX != 0 || m_fSkewY != 0)
		{
			// create a skewed coordinate system
			CCAffineTransform skew = CCAffineTransformMake(1.0f, tanf(CC_DEGREES_TO_RADIANS(m_fSkewY)), tanf(CC_DEGREES_TO_RADIANS(m_fSkewX)), 1.0f, 0.0f, 0.0f);
			// apply the skew to the transform
			m_tTransform = CCAffineTransformConcat(skew, m_tTransform);
		}

		if(! (m_fScaleX == 1 && m_fScaleY == 1))
		{
			m_tTransform = CCAffineTransformScale(m_tTransform, m_fScaleX, m_fScaleY);
		}

		if(! CCPoint::CCPointEqualToPoint(m_tAnchorPointInPixels, CCPointZero))
		{
			m_tTransform = CCAffineTransformTranslate(m_tTransform, -m_tAnchorPointInPixels.x, -m_tAnchorPointInPixels.y);
		}

		m_bIsTransformDirty = false;
	}

	return m_tTransform;
}

CCAffineTransform CCNode::parentToNodeTransform(void)
{
	if ( m_bIsInverseDirty ) {
		m_tInverse = CCAffineTransformInvert(this->nodeToParentTransform());
		m_bIsInverseDirty = false;
	}

	return m_tInverse;
}

CCAffineTransform CCNode::nodeToWorldTransform()
{
	CCAffineTransform t = this->nodeToParentTransform();

	for (CCNode *p = m_pParent; p != NULL; p = p->getParent())
		t = CCAffineTransformConcat(t, p->nodeToParentTransform());

	return t;
}

CCAffineTransform CCNode::worldToNodeTransform(void)
{
	return CCAffineTransformInvert(this->nodeToWorldTransform());
}

CCPoint CCNode::convertToNodeSpace(const CCPoint& worldPoint)
{
	CCPoint ret;
	if(CC_CONTENT_SCALE_FACTOR() == 1)
	{
		ret = CCPointApplyAffineTransform(worldPoint, worldToNodeTransform());
	}
	else
	{
		ret = ccpMult(worldPoint, CC_CONTENT_SCALE_FACTOR());
		ret = CCPointApplyAffineTransform(ret, worldToNodeTransform());
		ret = ccpMult(ret, 1/CC_CONTENT_SCALE_FACTOR());
	}

	return ret;
}

CCPoint CCNode::convertToWorldSpace(const CCPoint& nodePoint)
{
	CCPoint ret;
	if(CC_CONTENT_SCALE_FACTOR() == 1)
	{
		ret = CCPointApplyAffineTransform(nodePoint, nodeToWorldTransform());
	}
	else
	{
		ret = ccpMult( nodePoint, CC_CONTENT_SCALE_FACTOR() );
		ret = CCPointApplyAffineTransform(ret, nodeToWorldTransform());
		ret = ccpMult( ret, 1/CC_CONTENT_SCALE_FACTOR() );
	}

	return ret;
}

CCPoint CCNode::convertToNodeSpaceAR(const CCPoint& worldPoint)
{
	CCPoint nodePoint = convertToNodeSpace(worldPoint);
	CCPoint anchorInPoints;
	if( CC_CONTENT_SCALE_FACTOR() == 1 )
	{
		anchorInPoints = m_tAnchorPointInPixels;
	}
	else
	{
		anchorInPoints = ccpMult( m_tAnchorPointInPixels, 1/CC_CONTENT_SCALE_FACTOR() );
	}

	return ccpSub(nodePoint, anchorInPoints);
}

CCPoint CCNode::convertToWorldSpaceAR(const CCPoint& nodePoint)
{
	CCPoint anchorInPoints;
	if( CC_CONTENT_SCALE_FACTOR() == 1 )
	{
		anchorInPoints = m_tAnchorPointInPixels;
	}
	else
	{
		anchorInPoints = ccpMult( m_tAnchorPointInPixels, 1/CC_CONTENT_SCALE_FACTOR() );
	}

	CCPoint pt = ccpAdd(nodePoint, anchorInPoints);
	return convertToWorldSpace(pt);
}
CCPoint CCNode::convertToWindowSpace(const CCPoint& nodePoint)
{
	CCPoint worldPoint = this->convertToWorldSpace(nodePoint);
	return CCDirector::sharedDirector()->convertToUI(worldPoint);
}

// convenience methods which take a CCTouch instead of CCPoint
CCPoint CCNode::convertTouchToNodeSpace(CCTouch *touch)
{
	CCPoint point = touch->locationInView();
	point = CCDirector::sharedDirector()->convertToGL(point);
	return this->convertToNodeSpace(point);
}
CCPoint CCNode::convertTouchToNodeSpaceAR(CCTouch *touch)
{
	CCPoint point = touch->locationInView();
	point = CCDirector::sharedDirector()->convertToGL(point);
	return this->convertToNodeSpaceAR(point);
}

}//namespace   cocos2d


code:
/****************************************************************************
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 "CCAffineTransform.h"
#include <algorithm>
#include <math.h>

using namespace std;

namespace   cocos2d {

CCAffineTransform __CCAffineTransformMake(CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty)
{
  CCAffineTransform t;
  t.a = a; t.b = b; t.c = c; t.d = d; t.tx = tx; t.ty = ty;
  return t;
}

CCPoint __CCPointApplyAffineTransform(const CCPoint& point, const CCAffineTransform& t)
{
  CCPoint p;
  p.x = (CGFloat)((double)t.a * point.x + (double)t.c * point.y + t.tx);
  p.y = (CGFloat)((double)t.b * point.x + (double)t.d * point.y + t.ty);
  return p;
}

CCSize __CCSizeApplyAffineTransform(const CCSize& size, const CCAffineTransform& t)
{
  CCSize s;
  s.width = (CGFloat)((double)t.a * size.width + (double)t.c * size.height);
  s.height = (CGFloat)((double)t.b * size.width + (double)t.d * size.height);
  return s;
}

CCAffineTransform CCAffineTransformMakeIdentity()
{
	return __CCAffineTransformMake(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
}

extern const CCAffineTransform CCAffineTransformIdentity = CCAffineTransformMakeIdentity();

CCRect CCRectApplyAffineTransform(const CCRect& rect, const CCAffineTransform& anAffineTransform)
{
	CGFloat top = CCRect::CCRectGetMinY(rect);
    CGFloat left = CCRect::CCRectGetMinX(rect);
	CGFloat right = CCRect::CCRectGetMaxX(rect);
	CGFloat bottom = CCRect::CCRectGetMaxY(rect);

	CCPoint topLeft = CCPointApplyAffineTransform(CCPointMake(left, top), anAffineTransform);
    CCPoint topRight = CCPointApplyAffineTransform(CCPointMake(right, top), anAffineTransform);
    CCPoint bottomLeft = CCPointApplyAffineTransform(CCPointMake(left, bottom), anAffineTransform);
    CCPoint bottomRight = CCPointApplyAffineTransform(CCPointMake(right, bottom), anAffineTransform);

    CGFloat minX = min(min(topLeft.x, topRight.x), min(bottomLeft.x, bottomRight.x));
    CGFloat maxX = max(max(topLeft.x, topRight.x), max(bottomLeft.x, bottomRight.x));
    CGFloat minY = min(min(topLeft.y, topRight.y), min(bottomLeft.y, bottomRight.y));
    CGFloat maxY = max(max(topLeft.y, topRight.y), max(bottomLeft.y, bottomRight.y));

    return CCRectMake(minX, minY, (maxX - minX), (maxY - minY));
}

CCAffineTransform CCAffineTransformTranslate(const CCAffineTransform& t, float tx, float ty)
{
	return __CCAffineTransformMake(t.a, t.b, t.c, t.d, t.tx + t.a * tx + t.c * ty, t.ty + t.b * tx + t.d * ty);
}

CCAffineTransform CCAffineTransformScale(const CCAffineTransform& t, CGFloat sx, CGFloat sy)
{
	return __CCAffineTransformMake(t.a * sx, t.b * sx, t.c * sy, t.d * sy, t.tx, t.ty);
}

CCAffineTransform CCAffineTransformRotate(const CCAffineTransform& t, CGFloat anAngle)
{
    float fSin = sin(anAngle);
    float fCos = cos(anAngle);

	return __CCAffineTransformMake(	t.a * fCos + t.c * fSin,
									t.b * fCos + t.d * fSin,
									t.c * fCos - t.a * fSin,
									t.d * fCos - t.b * fSin,
									t.tx,
									t.ty);
}

/* Concatenate `t2' to `t1' and return the result:
     t' = t1 * t2 */
CCAffineTransform CCAffineTransformConcat(const CCAffineTransform& t1, const CCAffineTransform& t2)
{
	return __CCAffineTransformMake(	t1.a * t2.a + t1.b * t2.c, t1.a * t2.b + t1.b * t2.d, //a,b
									t1.c * t2.a + t1.d * t2.c, t1.c * t2.b + t1.d * t2.d, //c,d
									t1.tx * t2.a + t1.ty * t2.c + t2.tx,				  //tx
									t1.tx * t2.b + t1.ty * t2.d + t2.ty);				  //ty
}

/* Return true if `t1' and `t2' are equal, false otherwise. */
bool CCAffineTransformEqualToTransform(const CCAffineTransform& t1, const CCAffineTransform& t2)
{
	return (t1.a == t2.a && t1.b == t2.b && t1.c == t2.c && t1.d == t2.d && t1.tx == t2.tx && t1.ty == t2.ty);
}

CCAffineTransform CCAffineTransformInvert(const CCAffineTransform& t)
{
    float determinant = 1 / (t.a * t.d - t.b * t.c);

    return __CCAffineTransformMake(determinant * t.d, -determinant * t.b, -determinant * t.c, determinant * t.a,
							determinant * (t.c * t.ty - t.d * t.tx), determinant * (t.b * t.tx - t.a * t.ty) );
}
}//namespace   cocos2d

license: mit


code:
/****************************************************************************
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 "CCAutoreleasePool.h"
#include "ccMacros.h"

namespace cocos2d
{

CCPoolManager	g_PoolManager;

CCAutoreleasePool::CCAutoreleasePool(void)
{
	m_pManagedObjectArray = new CCMutableArray<CCObject*>();
}

CCAutoreleasePool::~CCAutoreleasePool(void)
{
	CC_SAFE_DELETE(m_pManagedObjectArray);
}

void CCAutoreleasePool::addObject(CCObject* pObject)
{
	m_pManagedObjectArray->addObject(pObject);

	CCAssert(pObject->m_uReference > 1, "reference count should greager than 1");

	pObject->release(); // no ref count, in this case autorelease pool added.
}

void CCAutoreleasePool::removeObject(CCObject* pObject)
{
	m_pManagedObjectArray->removeObject(pObject, false);
}

void CCAutoreleasePool::clear()
{
	if(m_pManagedObjectArray->count() > 0)
	{
		//CCAutoreleasePool* pReleasePool;
#ifdef _DEBUG
		int nIndex = m_pManagedObjectArray->count() - 1;
#endif
		CCMutableArray<CCObject*>::CCMutableArrayRevIterator it;
		for(it = m_pManagedObjectArray->rbegin(); it != m_pManagedObjectArray->rend(); ++it)
		{
			if(!*it)
				break;

			(*it)->m_bManaged = false;
			//(*it)->release();
			//delete (*it);
#ifdef _DEBUG
			nIndex--;
#endif
		}

		m_pManagedObjectArray->removeAllObjects();
	}
}

//--------------------------------------------------------------------
//
// CCPoolManager
//
//--------------------------------------------------------------------

CCPoolManager* CCPoolManager::getInstance()
{
	return &g_PoolManager;
}

CCPoolManager::CCPoolManager()
{
	m_pReleasePoolStack = new CCMutableArray<CCAutoreleasePool*>();
        m_pCurReleasePool = 0;
}

CCPoolManager::~CCPoolManager()
{

	finalize();

	// we only release the last autorelease pool here
        m_pCurReleasePool = 0;
	m_pReleasePoolStack->removeObjectAtIndex(0);

	CC_SAFE_DELETE(m_pReleasePoolStack);
}

void CCPoolManager::finalize()
{
	if(m_pReleasePoolStack->count() > 0)
	{
		//CCAutoreleasePool* pReleasePool;
		CCMutableArray<CCAutoreleasePool*>::CCMutableArrayIterator it;
		for(it = m_pReleasePoolStack->begin(); it != m_pReleasePoolStack->end(); ++it)
		{
			if(!*it)
				break;

			(*it)->clear();
		}
	}
}

void CCPoolManager::push()
{
	CCAutoreleasePool* pPool = new CCAutoreleasePool();	   //ref = 1
	m_pCurReleasePool = pPool;

	m_pReleasePoolStack->addObject(pPool);				   //ref = 2

	pPool->release();									   //ref = 1
}

void CCPoolManager::pop()
{
    if (! m_pCurReleasePool)
    {
        return;
    }

 	int nCount = m_pReleasePoolStack->count();

	m_pCurReleasePool->clear();

  	if(nCount > 1)
  	{
		m_pReleasePoolStack->removeObjectAtIndex(nCount-1);

// 		if(nCount > 1)
// 		{
// 			m_pCurReleasePool = m_pReleasePoolStack->getObjectAtIndex(nCount - 2);
// 			return;
// 		}
		m_pCurReleasePool = m_pReleasePoolStack->getObjectAtIndex(nCount - 2);
	}

	/*m_pCurReleasePool = NULL;*/
}

void CCPoolManager::removeObject(CCObject* pObject)
{
	CCAssert(m_pCurReleasePool, "current auto release pool should not be null");

	m_pCurReleasePool->removeObject(pObject);
}

void CCPoolManager::addObject(CCObject* pObject)
{
	getCurReleasePool()->addObject(pObject);
}

CCAutoreleasePool* CCPoolManager::getCurReleasePool()
{
	if(!m_pCurReleasePool)
	{
		push();
	}

	CCAssert(m_pCurReleasePool, "current auto release pool should not be null");

	return m_pCurReleasePool;
}

}


code:
/****************************************************************************
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 "CCData.h"
#include "CCFileUtils.h"

#include <stdio.h>

using namespace std;
namespace   cocos2d {

CCData::CCData(void)
: m_pData(NULL)
{
}

CCData::~CCData(void)
{
	CC_SAFE_DELETE_ARRAY(m_pData);
}

CCData* CCData::dataWithContentsOfFile(const string &strPath)
{
    CCFileData data(strPath.c_str(), "rb");
    unsigned long  nSize = data.getSize();
    unsigned char* pBuffer = data.getBuffer();

    if (! pBuffer)
    {
        return NULL;
    }

	CCData *pRet = new CCData();
    pRet->m_pData = new char[nSize];
    memcpy(pRet->m_pData, pBuffer, nSize);

	return pRet;
}

void* CCData::bytes(void)
{
	return m_pData;
}

//@todo implement
CCData* CCData::dataWithBytes(unsigned char *pBytes, int size)
{
    CC_UNUSED_PARAM(pBytes);
    CC_UNUSED_PARAM(size);
	return NULL;
}
}//namespace   cocos2d


code:
/****************************************************************************
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 "CCGeometry.h"

// implementation of CCPoint
namespace   cocos2d {

CCPoint::CCPoint(void)
{
	x = 0;
	y = 0;
}

CCPoint::CCPoint(float x, float y)
{
	this->x = x;
	this->y = y;
}

bool CCPoint::CCPointEqualToPoint(const CCPoint& point1, const CCPoint& point2)
{
	return ((point1.x == point2.x) && (point1.y == point2.y));
}

// implementation of CCSize

CCSize::CCSize(void)
{
	width = 0;
	height = 0;
}

CCSize::CCSize(float width, float height)
{
	this->width = width;
	this->height = height;
}

bool CCSize::CCSizeEqualToSize(const CCSize& size1, const CCSize& size2)
{
	return ((size1.width == size2.width) && (size1.height == size2.height));
}

// implementation of CCRect

CCRect::CCRect(void)
{
	origin.x = 0;
	origin.y = 0;

	size.width = 0;
	size.height = 0;
}

CCRect::CCRect(float x, float y, float width, float height)
{
	// Only support that, the width and height > 0
	CC_ASSERT(width >= 0 && height >= 0);

	origin.x = x;
	origin.y = y;

	size.width = width;
	size.height = height;
}

bool CCRect::CCRectEqualToRect(const CCRect& rect1, const CCRect& rect2)
{
	return (CCPoint::CCPointEqualToPoint(rect1.origin, rect2.origin)
		&& CCSize::CCSizeEqualToSize(rect1.size, rect2.size));
}

CGFloat CCRect::CCRectGetMaxX(const CCRect& rect)
{
	return rect.origin.x + rect.size.width;
}

CGFloat CCRect::CCRectGetMidX(const CCRect& rect)
{
	return (float)(rect.origin.x + rect.size.width / 2.0);
}

CGFloat CCRect::CCRectGetMinX(const CCRect& rect)
{
	return rect.origin.x;
}

CGFloat CCRect::CCRectGetMaxY(const CCRect& rect)
{
	return rect.origin.y + rect.size.height;
}

CGFloat CCRect::CCRectGetMidY(const CCRect& rect)
{
	return (float)(rect.origin.y + rect.size.height / 2.0);
}

CGFloat CCRect::CCRectGetMinY(const CCRect& rect)
{
	return rect.origin.y;
}

bool CCRect::CCRectContainsPoint(const CCRect& rect, const CCPoint& point)
{
    bool bRet = false;

	if (point.x >= CCRectGetMinX(rect) && point.x <= CCRectGetMaxX(rect)
		&& point.y >= CCRectGetMinY(rect) && point.y <= CCRectGetMaxY(rect))
	{
		bRet = true;
	}

	return bRet;
}

bool CCRect::CCRectIntersectsRect(const CCRect& rectA, const CCRect& rectB)
{
	return !(CCRectGetMaxX(rectA) < CCRectGetMinX(rectB)||
			CCRectGetMaxX(rectB) < CCRectGetMinX(rectA)||
			CCRectGetMaxY(rectA) < CCRectGetMinY(rectB)||
			CCRectGetMaxY(rectB) < CCRectGetMinY(rectA));
}

}//namespace   cocos2d {


code:
/****************************************************************************
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 "CCNS.h"
#include <string>
#include <vector>
#include <string.h>
#include <stdlib.h>

using namespace std;

typedef std::vector<std::string> strArray;

// string toolkit
static inline void split(std::string src, const char* token, strArray& vect)
{
    int nend=0;
    int nbegin=0;
    while(nend != -1)
    {
        nend = src.find(token, nbegin);
        if(nend == -1)
            vect.push_back(src.substr(nbegin, src.length()-nbegin));
        else
            vect.push_back(src.substr(nbegin, nend-nbegin));
        nbegin = nend + strlen(token);
    }
}

// first, judge whether the form of the string like this: {x,y}
// if the form is right,the string will be splited into the parameter strs;
// or the parameter strs will be empty.
// if the form is right return true,else return false.
static bool splitWithForm(const char* pStr, strArray& strs)
{
    bool bRet = false;

    do
    {
        CC_BREAK_IF(!pStr);

        // string is empty
        std::string content = pStr;
        CC_BREAK_IF(content.length() == 0);

        int nPosLeft  = content.find('{');
        int nPosRight = content.find('}');

        // don't have '{' and '}'
        CC_BREAK_IF(nPosLeft == (int)std::string::npos || nPosRight == (int)std::string::npos);
        // '}' is before '{'
        CC_BREAK_IF(nPosLeft > nPosRight);

        std::string pointStr = content.substr(nPosLeft + 1, nPosRight - nPosLeft - 1);
        // nothing between '{' and '}'
        CC_BREAK_IF(pointStr.length() == 0);

        int nPos1 = pointStr.find('{');
        int nPos2 = pointStr.find('}');
        // contain '{' or '}'
        CC_BREAK_IF(nPos1 != (int)std::string::npos || nPos2 != (int)std::string::npos);

        split(pointStr, ",", strs);
        if (strs.size() != 2 || strs[0].length() == 0 || strs[1].length() == 0)
        {
            strs.clear();
            break;
        }

        bRet = true;
    } while (0);

    return bRet;
}

// implement the functions
namespace cocos2d
{
    CCRect CCRectFromString(const char* pszContent)
    {
        CCRect result = CCRectZero;

        do
        {
            CC_BREAK_IF(!pszContent);
            std::string content = pszContent;

            // find the first '{' and the third '}'
            int nPosLeft  = content.find('{');
            int nPosRight = content.find('}');
            for (int i = 1; i < 3; ++i)
            {
                if (nPosRight == (int)std::string::npos)
                {
                    break;
                }
                nPosRight = content.find('}', nPosRight + 1);
            }
            CC_BREAK_IF(nPosLeft == (int)std::string::npos || nPosRight == (int)std::string::npos);

            content = content.substr(nPosLeft + 1, nPosRight - nPosLeft - 1);
            int nPointEnd = content.find('}');
            CC_BREAK_IF(nPointEnd == (int)std::string::npos);
            nPointEnd = content.find(',', nPointEnd);
            CC_BREAK_IF(nPointEnd == (int)std::string::npos);

            // get the point string and size string
            std::string pointStr = content.substr(0, nPointEnd);
            std::string sizeStr  = content.substr(nPointEnd + 1, content.length() - nPointEnd);

            // split the string with ','
            strArray pointInfo;
            CC_BREAK_IF(!splitWithForm(pointStr.c_str(), pointInfo));
            strArray sizeInfo;
            CC_BREAK_IF(!splitWithForm(sizeStr.c_str(), sizeInfo));

            float x = (float) atof(pointInfo[0].c_str());
            float y = (float) atof(pointInfo[1].c_str());
            float width  = (float) atof(sizeInfo[0].c_str());
            float height = (float) atof(sizeInfo[1].c_str());

            result = CCRectMake(x, y, width, height);
        } while (0);

        return result;
    }

    CCPoint CCPointFromString(const char* pszContent)
    {
        CCPoint ret = CCPointZero;

        do
        {
            strArray strs;
            CC_BREAK_IF(!splitWithForm(pszContent, strs));

            float x = (float) atof(strs[0].c_str());
            float y = (float) atof(strs[1].c_str());

            ret = CCPointMake(x, y);
        } while (0);

        return ret;
    }

    CCSize CCSizeFromString(const char* pszContent)
    {
        CCSize ret = CCSizeZero;

        do
        {
            strArray strs;
            CC_BREAK_IF(!splitWithForm(pszContent, strs));

            float width  = (float) atof(strs[0].c_str());
            float height = (float) atof(strs[1].c_str());

            ret = CCSizeMake(width, height);
        } while (0);

        return ret;
    }
}


code:
/****************************************************************************
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.
****************************************************************************/

#ifndef __PLATFOMR_CCNS_H__
#define __PLATFOMR_CCNS_H__

#include "CCGeometry.h"

namespace cocos2d
{
    /**
    @brief Returns a Core Graphics rectangle structure corresponding to the data in a given string.
    @param pszContent   A string object whose contents are of the form "{{x,y},{w, h}}",
                        where x is the x coordinate, y is the y coordinate, w is the width, and h is the height.
                        These components can represent integer or float values.
                        An example of a valid string is "{{3,2},{4,5}}".
                        The string is not localized, so items are always separated with a comma.
    @return A Core Graphics structure that represents a rectangle.
            If the string is not well-formed, the function returns CCRectZero.
    */
    CCRect CC_DLL CCRectFromString(const char* pszContent);

    /**
    @brief Returns a Core Graphics point structure corresponding to the data in a given string.
    @param pszContent   A string object whose contents are of the form "{x,y}",
                        where x is the x coordinate and y is the y coordinate.
                        The x and y values can represent integer or float values.
                        An example of a valid string is "{3.0,2.5}".
                        The string is not localized, so items are always separated with a comma.
    @return A Core Graphics structure that represents a point.
            If the string is not well-formed, the function returns CCPointZero.
    */
	CCPoint CC_DLL CCPointFromString(const char* pszContent);

    /**
    @brief Returns a Core Graphics size structure corresponding to the data in a given string.
    @param pszContent   A string object whose contents are of the form "{w, h}",
                        where w is the width and h is the height.
                        The w and h values can be integer or float values.
                        An example of a valid string is "{3.0,2.5}".
                        The string is not localized, so items are always separated with a comma.
    @return A Core Graphics structure that represents a size.
            If the string is not well-formed, the function returns CCSizeZero.
    */
	CCSize CC_DLL CCSizeFromString(const char* pszContent);
}

#endif // __PLATFOMR_CCNS_H__


code:
/****************************************************************************
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 "CCObject.h"
#include "CCAutoreleasePool.h"
#include "ccMacros.h"
#include "CCScriptSupport.h"

namespace   cocos2d {

CCObject* CCCopying::copyWithZone(CCZone *pZone)
{
    CC_UNUSED_PARAM(pZone);
    CCAssert(0, "not implement");
    return 0;
}

CCObject::CCObject(void)
{
	static unsigned int uObjectCount = 0;

	m_uID = ++uObjectCount;
    m_nLuaID = 0;

	// when the object is created, the refrence count of it is 1
	m_uReference = 1;
	m_bManaged = false;
}

CCObject::~CCObject(void)
{
	// if the object is managed, we should remove it
	// from pool manager
	if (m_bManaged)
	{
		CCPoolManager::getInstance()->removeObject(this);
	}

    // if the object is referenced by Lua engine, remove it
    if (m_nLuaID)
    {
        CCScriptEngineManager::sharedManager()->getScriptEngine()->removeCCObjectByID(m_nLuaID);
    }
}

CCObject* CCObject::copy()
{
    return copyWithZone(0);
}

void CCObject::release(void)
{
	CCAssert(m_uReference > 0, "reference count should greater than 0");
	--m_uReference;

	if (m_uReference == 0)
	{
		delete this;
	}
}

void CCObject::retain(void)
{
	CCAssert(m_uReference > 0, "reference count should greater than 0");

	++m_uReference;
}

CCObject* CCObject::autorelease(void)
{
	CCPoolManager::getInstance()->addObject(this);

	m_bManaged = true;
	return this;
}

bool CCObject::isSingleRefrence(void)
{
	return m_uReference == 1;
}

unsigned int CCObject::retainCount(void)
{
	return m_uReference;
}

bool CCObject::isEqual(const CCObject *pObject)
{
	return this == pObject;
}

}//namespace   cocos2d


code:
/****************************************************************************
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 "CCSet.h"

using namespace std;

namespace   cocos2d {

CCSet::CCSet(void)
{
    m_pSet = new set<CCObject *>;
}

CCSet::CCSet(const CCSet &rSetObject)
{
    m_pSet = new set<CCObject *>(*rSetObject.m_pSet);

	// call retain of members
	CCSetIterator iter;
	for (iter = m_pSet->begin(); iter != m_pSet->end(); ++iter)
	{
		if (! (*iter))
		{
			break;
		}

		(*iter)->retain();
	}
}

CCSet::~CCSet(void)
{
	// call release() of elements
	CCSetIterator iter;
	for (iter = m_pSet->begin(); iter != m_pSet->end(); ++iter)
	{
		if (! (*iter))
		{
			break;
		}

		(*iter)->release();
	}

	CC_SAFE_DELETE(m_pSet);
}

CCSet* CCSet::copy(void)
{
	CCSet *pSet = new CCSet(*this);

	return pSet;
}

CCSet* CCSet::mutableCopy(void)
{
	return copy();
}

int CCSet::count(void)
{
	return (int)m_pSet->size();
}

void CCSet::addObject(CCObject *pObject)
{
	CC_SAFE_RETAIN(pObject);
	m_pSet->insert(pObject);
}

void CCSet::removeObject(CCObject *pObject)
{
	m_pSet->erase(pObject);
	CC_SAFE_RELEASE(pObject);
}

bool CCSet::containsObject(CCObject *pObject)
{
	return m_pSet->find(pObject) != m_pSet->end();
}

CCSetIterator CCSet::begin(void)
{
	return m_pSet->begin();
}

CCSetIterator CCSet::end(void)
{
	return m_pSet->end();
}

CCObject* CCSet::anyObject()
{
    if (!m_pSet || m_pSet->empty())
    {
        return 0;
    }

    CCSetIterator it;

    for( it = m_pSet->begin(); it != m_pSet->end(); ++it)
    {
        if (*it)
        {
            return (*it);
        }
    }

    return 0;
}

}//namespace   cocos2d


code:
/****************************************************************************
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 "CCZone.h"
#include "CCObject.h"
namespace   cocos2d {

CCZone::CCZone(CCObject *pObject)
{
	m_pCopyObject = pObject;
}
}//namespace   cocos2d


code:
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
Copyright (c) 2011      Zynga Inc.

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 "cocos2d.h"
namespace   cocos2d {

const char* cocos2dVersion()
{
	return "cocos2d-1.0.1-x-0.12.0";
}

}//namespace   cocos2d


code:
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Copyright (c) 2009      On-Core

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 "CCGrabber.h"
#include "ccMacros.h"
#include "CCTexture2D.h"
#include "platform/platform.h"

namespace cocos2d
{
	CCGrabber::CCGrabber(void)
		: m_fbo(0)
		, m_oldFBO(0)
	{
		m_eGlesVersion = CCConfiguration::sharedConfiguration()->getGlesVersion();

		// If the gles version is lower than GLES_VER_1_0,
		// all the functions in CCGrabber return directly.
		if (m_eGlesVersion <= GLES_VER_1_0)
		{
			return ;
		}

		// generate FBO
		ccglGenFramebuffers(1, &m_fbo);
	}

	void CCGrabber::grab(CCTexture2D *pTexture)
	{
		// If the gles version is lower than GLES_VER_1_0,
		// all the functions in CCGrabber return directly.
		if (m_eGlesVersion <= GLES_VER_1_0)
		{
			return ;
		}

		glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &m_oldFBO);

		// bind
		ccglBindFramebuffer(CC_GL_FRAMEBUFFER, m_fbo);

		// associate texture with FBO
		ccglFramebufferTexture2D(CC_GL_FRAMEBUFFER, CC_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
			pTexture->getName(), 0);

		// check if it worked (probably worth doing :) )
		GLuint status = ccglCheckFramebufferStatus(CC_GL_FRAMEBUFFER);
		if (status != CC_GL_FRAMEBUFFER_COMPLETE)
		{
			CCLOG("Frame Grabber: could not attach texture to frmaebuffer");
		}

		ccglBindFramebuffer(CC_GL_FRAMEBUFFER, m_oldFBO);
	}

	void CCGrabber::beforeRender(CCTexture2D *pTexture)
	{
        CC_UNUSED_PARAM(pTexture);
		// If the gles version is lower than GLES_VER_1_0,
		// all the functions in CCGrabber return directly.
		if (m_eGlesVersion <= GLES_VER_1_0)
		{
			return ;
		}

		glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &m_oldFBO);
		ccglBindFramebuffer(CC_GL_FRAMEBUFFER, m_fbo);

		// BUG XXX: doesn't work with RGB565.

		/*glClearColor(0, 0, 0, 0);*/

		// BUG #631: To fix #631, uncomment the lines with #631
		// Warning: But it CCGrabber won't work with 2 effects at the same time
		glClearColor(0.0f,0.0f,0.0f,1.0f);	// #631

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		glColorMask(true, true, true, false);	// #631
	}

	void CCGrabber::afterRender(cocos2d::CCTexture2D *pTexture)
	{
        CC_UNUSED_PARAM(pTexture);
		// If the gles version is lower than GLES_VER_1_0,
		// all the functions in CCGrabber return directly.
		if (m_eGlesVersion <= GLES_VER_1_0)
		{
			return ;
		}

		ccglBindFramebuffer(CC_GL_FRAMEBUFFER, m_oldFBO);
		glColorMask(true, true, true, true);	// #631
	}

	CCGrabber::~CCGrabber()
	{
		// If the gles version is lower than GLES_VER_1_0,
		// all the functions in CCGrabber return directly.
		if (m_eGlesVersion <= GLES_VER_1_0)
		{
			return ;
		}

		CCLOGINFO("cocos2d: deallocing %p", this);
		ccglDeleteFramebuffers(1, &m_fbo);
	}
} // end of namespace cocos2d


code:
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Copyright (c) 2009      On-Core

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.
****************************************************************************/
#ifndef __EFFECTS_CCGRABBER_H__
#define __EFFECTS_CCGRABBER_H__

#include "CCConfiguration.h"
#include "CCObject.h"
#include "CCGL.h"

namespace cocos2d
{
	class CCTexture2D;

	/** FBO class that grabs the the contents of the screen */
	class CCGrabber : public CCObject
	{
	public:
		CCGrabber(void);
		~CCGrabber(void);

		void grab(CCTexture2D *pTexture);
		void beforeRender(CCTexture2D *pTexture);
		void afterRender(CCTexture2D *pTexture);

	protected:
		GLuint m_fbo;
		GLint m_oldFBO;
		CCGlesVersion m_eGlesVersion;
	};

} // end of namespace cocos2d

#endif // __EFFECTS_CCGRABBER_H__


code:
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Copyright (c) 2009      On-Core

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 "ccMacros.h"
#include "effects/CCGrid.h"
#include "CCDirector.h"
#include "effects/CCGrabber.h"
#include "support/ccUtils.h"

#include "CCGL.h"
#include "CCPointExtension.h"

namespace cocos2d
{
	// implementation of CCGridBase

	CCGridBase* CCGridBase::gridWithSize(const ccGridSize& gridSize)
	{
        CCGridBase *pGridBase = new CCGridBase();

		if (pGridBase)
		{
            if (pGridBase->initWithSize(gridSize))
			{
				pGridBase->autorelease();
			}
			else
			{
				CC_SAFE_RELEASE_NULL(pGridBase);
			}
		}

		return pGridBase;
	}

	CCGridBase* CCGridBase::gridWithSize(const ccGridSize& gridSize, CCTexture2D *texture, bool flipped)
	{
		CCGridBase *pGridBase = new CCGridBase();

		if (pGridBase)
		{
			if (pGridBase->initWithSize(gridSize, texture, flipped))
			{
				pGridBase->autorelease();
			}
			else
			{
				CC_SAFE_RELEASE_NULL(pGridBase);
			}
		}

		return pGridBase;
	}

	bool CCGridBase::initWithSize(const ccGridSize& gridSize, CCTexture2D *pTexture, bool bFlipped)
	{
		bool bRet = true;

		m_bActive = false;
		m_nReuseGrid = 0;
		m_sGridSize = gridSize;

		m_pTexture = pTexture;
		CC_SAFE_RETAIN(m_pTexture);
		m_bIsTextureFlipped = bFlipped;

		const CCSize& texSize = m_pTexture->getContentSizeInPixels();
		m_obStep.x = texSize.width / m_sGridSize.x;
		m_obStep.y = texSize.height / m_sGridSize.y;

		m_pGrabber = new CCGrabber();
		if (m_pGrabber)
		{
			m_pGrabber->grab(m_pTexture);
		}
		else
		{
            bRet = false;
		}

		calculateVertexPoints();

		return bRet;
	}

	bool CCGridBase::initWithSize(const ccGridSize& gridSize)
	{
    	CCDirector *pDirector = CCDirector::sharedDirector();
		CCSize s = pDirector->getWinSizeInPixels();

		unsigned long POTWide = ccNextPOT((unsigned int)s.width);
		unsigned long POTHigh = ccNextPOT((unsigned int)s.height);

		// we only use rgba8888
		CCTexture2DPixelFormat format = kCCTexture2DPixelFormat_RGBA8888;

		void *data = calloc((int)(POTWide * POTHigh * 4), 1);
		if (! data)
		{
			CCLOG("cocos2d: CCGrid: not enough memory.");
			this->release();
			return false;
		}

		CCTexture2D *pTexture = new CCTexture2D();
		pTexture->initWithData(data, format, POTWide, POTHigh, s);

		free(data);

		if (! pTexture)
		{
			CCLOG("cocos2d: CCGrid: error creating texture");
			delete this;
			return false;
		}

		initWithSize(gridSize, pTexture, false);

		pTexture->release();

		return true;
	}

	CCGridBase::~CCGridBase(void)
	{
		CCLOGINFO("cocos2d: deallocing %p", this);

		setActive(false);
		CC_SAFE_RELEASE(m_pTexture);
		CC_SAFE_RELEASE(m_pGrabber);
	}

	// properties
	void CCGridBase::setActive(bool bActive)
	{
		m_bActive = bActive;
		if (! bActive)
		{
			CCDirector *pDirector = CCDirector::sharedDirector();
			ccDirectorProjection proj = pDirector->getProjection();
			pDirector->setProjection(proj);
		}
	}

	void CCGridBase::setIsTextureFlipped(bool bFlipped)
	{
		if (m_bIsTextureFlipped != bFlipped)
		{
			m_bIsTextureFlipped = bFlipped;
			calculateVertexPoints();
		}
	}

	// This routine can be merged with Director
	void CCGridBase::applyLandscape(void)
	{
		CCDirector *pDirector = CCDirector::sharedDirector();

		CCSize winSize = pDirector->getDisplaySizeInPixels();
		float w = winSize.width / 2;
		float h = winSize.height / 2;

		ccDeviceOrientation orientation = pDirector->getDeviceOrientation();

		switch (orientation)
		{
		case CCDeviceOrientationLandscapeLeft:
 			glTranslatef(w,h,0);
 			glRotatef(-90,0,0,1);
 			glTranslatef(-h,-w,0);
            break;
		case CCDeviceOrientationLandscapeRight:
			glTranslatef(w,h,0);
			glRotatef(90,0,0,1);
			glTranslatef(-h,-w,0);
			break;
		case CCDeviceOrientationPortraitUpsideDown:
			glTranslatef(w,h,0);
			glRotatef(180,0,0,1);
			glTranslatef(-w,-h,0);
			break;
		default:
			break;
		}
	}

	void CCGridBase::set2DProjection()
	{
		CCSize winSize = CCDirector::sharedDirector()->getWinSizeInPixels();

		glLoadIdentity();

        // set view port for user FBO, fixed bug #543 #544
		glViewport((GLsizei)0, (GLsizei)0, (GLsizei)winSize.width, (GLsizei)winSize.height);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		ccglOrtho(0, winSize.width, 0, winSize.height, -1024, 1024);
		glMatrixMode(GL_MODELVIEW);
	}

	// This routine can be merged with Director
	void CCGridBase::set3DProjection()
	{
		CCSize	winSize = CCDirector::sharedDirector()->getDisplaySizeInPixels();

        // set view port for user FBO, fixed bug #543 #544
		glViewport(0, 0, (GLsizei)winSize.width, (GLsizei)winSize.height);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(60, (GLfloat)winSize.width/winSize.height, 0.5f, 1500.0f);

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		gluLookAt( winSize.width/2, winSize.height/2, CCDirector::sharedDirector()->getZEye(),
			winSize.width/2, winSize.height/2, 0,
			0.0f, 1.0f, 0.0f
			);
	}

	void CCGridBase::beforeDraw(void)
	{
		set2DProjection();
		m_pGrabber->beforeRender(m_pTexture);
	}

	void CCGridBase::afterDraw(cocos2d::CCNode *pTarget)
	{
		m_pGrabber->afterRender(m_pTexture);

		set3DProjection();
		applyLandscape();

		if (pTarget->getCamera()->getDirty())
		{
			const CCPoint& offset = pTarget->getAnchorPointInPixels();

			//
			// XXX: Camera should be applied in the AnchorPoint
			//
			ccglTranslate(offset.x, offset.y, 0);
			pTarget->getCamera()->locate();
			ccglTranslate(-offset.x, -offset.y, 0);
		}

		glBindTexture(GL_TEXTURE_2D, m_pTexture->getName());

        // restore projection for default FBO .fixed bug #543 #544
        CCDirector::sharedDirector()->setProjection(CCDirector::sharedDirector()->getProjection());
        CCDirector::sharedDirector()->applyOrientation();
		blit();
	}

	void CCGridBase::blit(void)
	{
		CCAssert(0, "");
	}

	void CCGridBase::reuse(void)
	{
		CCAssert(0, "");
	}

	void CCGridBase::calculateVertexPoints(void)
	{
		CCAssert(0, "");
	}

	// implementation of CCGrid3D

	CCGrid3D* CCGrid3D::gridWithSize(const ccGridSize& gridSize, CCTexture2D *pTexture, bool bFlipped)
	{
		CCGrid3D *pRet= new CCGrid3D();

		if (pRet)
		{
			if (pRet->initWithSize(gridSize, pTexture, bFlipped))
			{
			    pRet->autorelease();
			}
			else
			{
				delete pRet;
				pRet = NULL;
			}
		}

		return pRet;
	}

	CCGrid3D* CCGrid3D::gridWithSize(const ccGridSize& gridSize)
	{
		CCGrid3D *pRet= new CCGrid3D();

		if (pRet)
		{
			if (pRet->initWithSize(gridSize))
			{
			    pRet->autorelease();
			}
			else
			{
				delete pRet;
				pRet = NULL;
			}
		}

		return pRet;
	}

	CCGrid3D::~CCGrid3D(void)
	{
		CC_SAFE_FREE(m_pTexCoordinates);
        CC_SAFE_FREE(m_pVertices);
		CC_SAFE_FREE(m_pIndices);
		CC_SAFE_FREE(m_pOriginalVertices);
	}

	void CCGrid3D::blit(void)
	{
		int n = m_sGridSize.x * m_sGridSize.y;

		// 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_TEXTURE_COORD_ARRAY
		// Unneeded states: GL_COLOR_ARRAY
		glDisableClientState(GL_COLOR_ARRAY);

		glVertexPointer(3, GL_FLOAT, 0, m_pVertices);
		glTexCoordPointer(2, GL_FLOAT, 0, m_pTexCoordinates);
		glDrawElements(GL_TRIANGLES, (GLsizei)n * 6, GL_UNSIGNED_SHORT, m_pIndices);

		// restore GL default state
		glEnableClientState(GL_COLOR_ARRAY);
	}

	void CCGrid3D::calculateVertexPoints(void)
	{
		float width = (float)m_pTexture->getPixelsWide();
		float height = (float)m_pTexture->getPixelsHigh();
		float imageH = m_pTexture->getContentSizeInPixels().height;

		int x, y, i;

		m_pVertices = malloc((m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(ccVertex3F));
		m_pOriginalVertices = malloc((m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(ccVertex3F));
		m_pTexCoordinates = malloc((m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(CCPoint));
		m_pIndices = (GLushort*)malloc(m_sGridSize.x * m_sGridSize.y * sizeof(GLushort) * 6);

		float *vertArray = (float*)m_pVertices;
		float *texArray = (float*)m_pTexCoordinates;
		GLushort *idxArray = m_pIndices;

		for (x = 0; x < m_sGridSize.x; ++x)
		{
			for (y = 0; y < m_sGridSize.y; ++y)
			{
				int idx = (y * m_sGridSize.x) + x;

				float x1 = x * m_obStep.x;
				float x2 = x1 + m_obStep.x;
				float y1 = y * m_obStep.y;
				float y2= y1 + m_obStep.y;

				GLushort a = (GLushort)(x * (m_sGridSize.y + 1) + y);
				GLushort b = (GLushort)((x + 1) * (m_sGridSize.y + 1) + y);
				GLushort c = (GLushort)((x + 1) * (m_sGridSize.y + 1) + (y + 1));
				GLushort d = (GLushort)(x * (m_sGridSize.y + 1) + (y + 1));

				GLushort tempidx[6] = {a, b, d, b, c, d};

				memcpy(&idxArray[6*idx], tempidx, 6*sizeof(GLushort));

				int l1[4] = {a*3, b*3, c*3, d*3};
				ccVertex3F e = {x1, y1, 0};
				ccVertex3F f = {x2, y1, 0};
				ccVertex3F g = {x2, y2, 0};
				ccVertex3F h = {x1, y2, 0};

				ccVertex3F l2[4] = {e, f, g, h};

				int tex1[4] = {a*2, b*2, c*2, d*2};
				CCPoint tex2[4] = {ccp(x1, y1), ccp(x2, y1), ccp(x2, y2), ccp(x1, y2)};

				for (i = 0; i < 4; ++i)
				{
					vertArray[l1[i]] = l2[i].x;
					vertArray[l1[i] + 1] = l2[i].y;
					vertArray[l1[i] + 2] = l2[i].z;

					texArray[tex1[i]] = tex2[i].x / width;
					if (m_bIsTextureFlipped)
					{
						texArray[tex1[i] + 1] = (imageH - tex2[i].y) / height;
					}
					else
					{
						texArray[tex1[i] + 1] = tex2[i].y / height;
					}
				}
			}
		}

		memcpy(m_pOriginalVertices, m_pVertices, (m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(ccVertex3F));
	}

	ccVertex3F CCGrid3D::vertex(const ccGridSize& pos)
	{
		int index = (pos.x * (m_sGridSize.y+1) + pos.y) * 3;
		float *vertArray = (float*)m_pVertices;

		ccVertex3F vert = {vertArray[index], vertArray[index+1], vertArray[index+2]};

		return vert;
	}

	ccVertex3F CCGrid3D::originalVertex(const ccGridSize& pos)
	{
		int index = (pos.x * (m_sGridSize.y+1) + pos.y) * 3;
		float *vertArray = (float*)m_pOriginalVertices;

		ccVertex3F vert = {vertArray[index], vertArray[index+1], vertArray[index+2]};

		return vert;
	}

	void CCGrid3D::setVertex(const ccGridSize& pos, const ccVertex3F& vertex)
	{
		int index = (pos.x * (m_sGridSize.y + 1) + pos.y) * 3;
		float *vertArray = (float*)m_pVertices;
		vertArray[index] = vertex.x;
		vertArray[index+1] = vertex.y;
		vertArray[index+2] = vertex.z;
	}

	void CCGrid3D::reuse(void)
	{
		if (m_nReuseGrid > 0)
		{
			memcpy(m_pOriginalVertices, m_pVertices, (m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(ccVertex3F));
			--m_nReuseGrid;
		}
	}

	// implementation of CCTiledGrid3D

	CCTiledGrid3D::~CCTiledGrid3D(void)
	{
		CC_SAFE_FREE(m_pTexCoordinates);
		CC_SAFE_FREE(m_pVertices);
		CC_SAFE_FREE(m_pOriginalVertices);
		CC_SAFE_FREE(m_pIndices);
	}

	CCTiledGrid3D* CCTiledGrid3D::gridWithSize(const ccGridSize& gridSize, CCTexture2D *pTexture, bool bFlipped)
	{
		CCTiledGrid3D *pRet= new CCTiledGrid3D();

		if (pRet)
		{
			if (pRet->initWithSize(gridSize, pTexture, bFlipped))
			{
			    pRet->autorelease();
			}
			else
			{
				delete pRet;
				pRet = NULL;
			}
		}

		return pRet;
	}

	CCTiledGrid3D* CCTiledGrid3D::gridWithSize(const ccGridSize& gridSize)
	{
		CCTiledGrid3D *pRet= new CCTiledGrid3D();

		if (pRet)
		{
			if (pRet->initWithSize(gridSize))
			{
			    pRet->autorelease();
			}
			else
			{
				delete pRet;
				pRet = NULL;
			}
		}

		return pRet;
	}

	void CCTiledGrid3D::blit(void)
	{
		int n = m_sGridSize.x * m_sGridSize.y;

		// 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_TEXTURE_COORD_ARRAY
		// Unneeded states: GL_COLOR_ARRAY
		glDisableClientState(GL_COLOR_ARRAY);

		glVertexPointer(3, GL_FLOAT, 0, m_pVertices);
		glTexCoordPointer(2, GL_FLOAT, 0, m_pTexCoordinates);
		glDrawElements(GL_TRIANGLES, (GLsizei)n*6, GL_UNSIGNED_SHORT, m_pIndices);

		// restore default GL state
		glEnableClientState(GL_COLOR_ARRAY);
	}

	void CCTiledGrid3D::calculateVertexPoints(void)
	{
 		float width = (float)m_pTexture->getPixelsWide();
 		float height = (float)m_pTexture->getPixelsHigh();
		float imageH = m_pTexture->getContentSizeInPixels().height;

		int numQuads = m_sGridSize.x * m_sGridSize.y;

		m_pVertices = malloc(numQuads * 12 * sizeof(GLfloat));
		m_pOriginalVertices = malloc(numQuads * 12 * sizeof(GLfloat));
		m_pTexCoordinates = malloc(numQuads * 8 * sizeof(GLfloat));
		m_pIndices = (GLushort *)malloc(numQuads * 6 * sizeof(GLushort));

		float *vertArray = (float*)m_pVertices;
		float *texArray = (float*)m_pTexCoordinates;
		GLushort *idxArray = m_pIndices;

		int x, y;

		for( x = 0; x < m_sGridSize.x; x++ )
		{
			for( y = 0; y < m_sGridSize.y; y++ )
			{
				float x1 = x * m_obStep.x;
				float x2 = x1 + m_obStep.x;
				float y1 = y * m_obStep.y;
				float y2 = y1 + m_obStep.y;

				*vertArray++ = x1;
				*vertArray++ = y1;
				*vertArray++ = 0;
				*vertArray++ = x2;
				*vertArray++ = y1;
				*vertArray++ = 0;
				*vertArray++ = x1;
				*vertArray++ = y2;
				*vertArray++ = 0;
				*vertArray++ = x2;
				*vertArray++ = y2;
				*vertArray++ = 0;

				float newY1 = y1;
				float newY2 = y2;

				if (m_bIsTextureFlipped)
				{
					newY1 = imageH - y1;
					newY2 = imageH - y2;
				}

				*texArray++ = x1 / width;
				*texArray++ = newY1 / height;
				*texArray++ = x2 / width;
				*texArray++ = newY1 / height;
				*texArray++ = x1 / width;
				*texArray++ = newY2 / height;
				*texArray++ = x2 / width;
				*texArray++ = newY2 / height;
			}
		}

		for (x = 0; x < numQuads; x++)
		{
			idxArray[x*6+0] = (GLushort)(x * 4 + 0);
			idxArray[x*6+1] = (GLushort)(x * 4 + 1);
			idxArray[x*6+2] = (GLushort)(x * 4 + 2);

			idxArray[x*6+3] = (GLushort)(x * 4 + 1);
			idxArray[x*6+4] = (GLushort)(x * 4 + 2);
			idxArray[x*6+5] = (GLushort)(x * 4 + 3);
		}

		memcpy(m_pOriginalVertices, m_pVertices, numQuads * 12 * sizeof(GLfloat));
	}

	void CCTiledGrid3D::setTile(const ccGridSize& pos, const ccQuad3& coords)
	{
		int idx = (m_sGridSize.y * pos.x + pos.y) * 4 * 3;
		float *vertArray = (float*)m_pVertices;
		memcpy(&vertArray[idx], &coords, sizeof(ccQuad3));
	}

	ccQuad3 CCTiledGrid3D::originalTile(const ccGridSize& pos)
	{
		int idx = (m_sGridSize.y * pos.x + pos.y) * 4 * 3;
		float *vertArray = (float*)m_pOriginalVertices;

		ccQuad3 ret;
		memcpy(&ret, &vertArray[idx], sizeof(ccQuad3));

		return ret;
	}

	ccQuad3 CCTiledGrid3D::tile(const ccGridSize& pos)
	{
		int idx = (m_sGridSize.y * pos.x + pos.y) * 4 * 3;
		float *vertArray = (float*)m_pVertices;

		ccQuad3 ret;
		memcpy(&ret, &vertArray[idx], sizeof(ccQuad3));

		return ret;
	}

	void CCTiledGrid3D::reuse(void)
	{
		if (m_nReuseGrid > 0)
		{
			int numQuads = m_sGridSize.x * m_sGridSize.y;

			memcpy(m_pOriginalVertices, m_pVertices, numQuads * 12 * sizeof(GLfloat));
			--m_nReuseGrid;
		}
	}
} // end of namespace cocos2d


code:
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Copyright (c) 2009      On-Core

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.
****************************************************************************/
#ifndef __EFFECTS_CCGRID_H__
#define __EFFECTS_CCGRID_H__

#include "CCObject.h"
#include "CCNode.h"
#include "CCCamera.h"
#include "ccTypes.h"
#include "CCTexture2D.h"

namespace cocos2d
{
	class CCTexture2D;
	class CCGrabber;

	/** Base class for other
	*/
	class CCGridBase : public CCObject
	{
	public:
		virtual ~CCGridBase(void);

		/** wheter or not the grid is active */
		inline bool isActive(void) { return m_bActive; }
		void setActive(bool bActive);

		/** number of times that the grid will be reused */
		inline int getReuseGrid(void) { return m_nReuseGrid; }
		inline void setReuseGrid(int nReuseGrid) { m_nReuseGrid = nReuseGrid; }

		/** size of the grid */
		inline const ccGridSize& getGridSize(void) { return m_sGridSize; }
		inline void setGridSize(const ccGridSize& gridSize) { m_sGridSize = gridSize; }

		/** pixels between the grids */
		inline const CCPoint& getStep(void) { return m_obStep; }
		inline void setStep(const CCPoint& step) { m_obStep = step; }

		/** is texture flipped */
		inline bool isTextureFlipped(void) { return m_bIsTextureFlipped; }
		void setIsTextureFlipped(bool bFlipped);

		bool initWithSize(const ccGridSize& gridSize, CCTexture2D *pTexture, bool bFlipped);
		bool initWithSize(const ccGridSize& gridSize);

		void beforeDraw(void);
		void afterDraw(CCNode *pTarget);
		virtual void blit(void);
		virtual void reuse(void);
		virtual void calculateVertexPoints(void);

	public:
		static CCGridBase* gridWithSize(const ccGridSize& gridSize, CCTexture2D *texture, bool flipped);
		static CCGridBase* gridWithSize(const ccGridSize& gridSize);
		void set2DProjection(void);
		void set3DProjection(void);

	protected:
		void applyLandscape(void);

	protected:
		bool m_bActive;
		int  m_nReuseGrid;
		ccGridSize m_sGridSize;
		CCTexture2D *m_pTexture;
		CCPoint m_obStep;
		CCGrabber *m_pGrabber;
		bool m_bIsTextureFlipped;
	};

	/**
	 CCGrid3D is a 3D grid implementation. Each vertex has 3 dimensions: x,y,z
	 */
	class CCGrid3D : public CCGridBase
	{
	public:
        ~CCGrid3D(void);

		/** returns the vertex at a given position */
		ccVertex3F vertex(const ccGridSize& pos);
		/** returns the original (non-transformed) vertex at a given position */
		ccVertex3F originalVertex(const ccGridSize& pos);
		/** sets a new vertex at a given position */
		void setVertex(const ccGridSize& pos, const ccVertex3F& vertex);

		virtual void blit(void);
		virtual void reuse(void);
		virtual void calculateVertexPoints(void);

	public:
		static CCGrid3D* gridWithSize(const ccGridSize& gridSize, CCTexture2D *pTexture, bool bFlipped);
		static CCGrid3D* gridWithSize(const ccGridSize& gridSize);

	protected:
		GLvoid *m_pTexCoordinates;
		GLvoid *m_pVertices;
		GLvoid *m_pOriginalVertices;
		GLushort *m_pIndices;
	};

	/**
	 CCTiledGrid3D is a 3D grid implementation. It differs from Grid3D in that
	 the tiles can be separated from the grid.
	*/
	class CCTiledGrid3D : public CCGridBase
	{
	public:
		~CCTiledGrid3D(void);

		/** returns the tile at the given position */
		ccQuad3 tile(const ccGridSize& pos);
		/** returns the original tile (untransformed) at the given position */
		ccQuad3 originalTile(const ccGridSize& pos);
		/** sets a new tile */
		void setTile(const ccGridSize& pos, const ccQuad3& coords);

		virtual void blit(void);
		virtual void reuse(void);
		virtual void calculateVertexPoints(void);

	public:
		static CCTiledGrid3D* gridWithSize(const ccGridSize& gridSize, CCTexture2D *pTexture, bool bFlipped);
		static CCTiledGrid3D* gridWithSize(const ccGridSize& gridSize);

	protected:
		GLvoid *m_pTexCoordinates;
		GLvoid *m_pVertices;
		GLvoid *m_pOriginalVertices;
		GLushort *m_pIndices;
	};
}

#endif // __EFFECTS_CCGRID_H__


code:
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Copyright (c) 2011      Erawppa
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 "CCNotificationCenter.h"

NS_CC_BEGIN;

static CCNotificationCenter *s_sharedNotifCenter = NULL;

CCNotificationCenter::CCNotificationCenter()
{
    m_observers = CCArray::arrayWithCapacity(3);
    m_observers->retain();
}

CCNotificationCenter::~CCNotificationCenter()
{
    m_observers->release();
}

CCNotificationCenter *CCNotificationCenter::sharedNotifCenter(void)
{
    if (!s_sharedNotifCenter)
    {
        s_sharedNotifCenter = new CCNotificationCenter;
    }
    return s_sharedNotifCenter;
}

void CCNotificationCenter::purgeNotifCenter(void)
{
    CC_SAFE_RELEASE_NULL(s_sharedNotifCenter);
}

//
// internal functions
//
bool CCNotificationCenter::observerExisted(CCObject *target,const char *name)
{
    CCObject* obj = NULL;
    CCARRAY_FOREACH(m_observers, obj)
    {
        CCNotificationObserver* observer = (CCNotificationObserver*) obj;
        if (!observer)
            continue;

        if (!strcmp(observer->getName(),name) && observer->getTarget() == target)
            return true;
    }
    return false;
}

//
// observer functions
//
void CCNotificationCenter::addObserver(CCObject *target,
                                       SEL_CallFuncO selector,
                                       const char *name,
                                       CCObject *obj)
{
    if (this->observerExisted(target, name))
        return;

    CCNotificationObserver *observer = new CCNotificationObserver(target, selector, name, obj);
    if (!observer)
        return;

    observer->autorelease();
    m_observers->addObject(observer);
}

void CCNotificationCenter::removeObserver(CCObject *target,const char *name)
{
    CCObject* obj = NULL;
    CCARRAY_FOREACH(m_observers, obj)
    {
        CCNotificationObserver* observer = (CCNotificationObserver*) obj;
        if (!observer)
            continue;

        if (!strcmp(observer->getName(),name) && observer->getTarget() == target)
        {
            m_observers->removeObject(observer);
            return;
        }
    }
}

void CCNotificationCenter::postNotification(const char *name, CCObject *object)
{
    CCObject* obj = NULL;
    CCARRAY_FOREACH(m_observers, obj)
    {
        CCNotificationObserver* observer = (CCNotificationObserver*) obj;
        if (!observer)
            continue;

        if (!strcmp(name,observer->getName()))
            observer->performSelector(object);
    }
}

void CCNotificationCenter::postNotification(const char *name)
{
    this->postNotification(name,NULL);
}

////////////////////////////////////////////////////////////////////////////////
///
/// CCNotificationObserver
///
////////////////////////////////////////////////////////////////////////////////
CCNotificationObserver::CCNotificationObserver(CCObject *target,
                                               SEL_CallFuncO selector,
                                               const char *name,
                                               CCObject *obj)
{
    m_target = target;
    m_selector = selector;
    m_object = obj;

    m_name = new char[strlen(name)+1];
    memset(m_name,0,strlen(name)+1);

    string orig (name);
    orig.copy(m_name,strlen(name),0);
}

CCNotificationObserver::~CCNotificationObserver()
{
    if (m_name)
        delete m_name;
}

void CCNotificationObserver::performSelector(CCObject *obj)
{
    if (m_target)
    {
        (m_target->*m_selector)(obj);
    }
}

CCObject *CCNotificationObserver::getTarget()
{
    return m_target;
}

SEL_CallFuncO CCNotificationObserver::getSelector()
{
    return m_selector;
}

char *CCNotificationObserver::getName()
{
    return m_name;
}

CCObject *CCNotificationObserver::getObject()
{
    return m_object;
}

NS_CC_END;


code:
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Copyright (c) 2011      Erawppa
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.
****************************************************************************/

#ifndef __CCNOTIFICATIONCENTER_H__
#define __CCNOTIFICATIONCENTER_H__

#include "cocos2d.h"

NS_CC_BEGIN;

class CC_DLL CCNotificationCenter : public CCObject
{
public:
    CCNotificationCenter();
    ~CCNotificationCenter();

    static CCNotificationCenter *sharedNotifCenter(void);
    static void purgeNotifCenter(void);

    void addObserver(CCObject *target,
                     SEL_CallFuncO selector,
                     const char *name,
                     CCObject *obj);

    void removeObserver(CCObject *target,const char *name);

    void postNotification(const char *name);
    void postNotification(const char *name, CCObject *object);

private:
    //
    // internal functions
    //
    bool observerExisted(CCObject *target,const char *name);

    //
    // variables
    //
    CCArray *m_observers;
};

class CC_DLL CCNotificationObserver : public CCObject
{
public:
    CCNotificationObserver(CCObject *target,
                           SEL_CallFuncO selector,
                           const char *name,
                           CCObject *obj);
    ~CCNotificationObserver();

    void performSelector(CCObject *obj);
private:
    CC_PROPERTY_READONLY(CCObject *, m_target, Target);
    CC_PROPERTY_READONLY(SEL_CallFuncO, m_selector, Selector);
    CC_PROPERTY_READONLY(char *, m_name, Name);
    CC_PROPERTY_READONLY(CCObject *, m_object, Object);
};

NS_CC_END;

#endif//__CCNOTIFICATIONCENTER_H__


code:
/****************************************************************************
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.
****************************************************************************/
#ifndef __CC_CCAccelerometer_H__
#define __CC_CCAccelerometer_H__

#include "platform/CCAccelerometer_platform.h"

#endif // __CC_CCAccelerometer_H__


code:
/****************************************************************************
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.
****************************************************************************/

#ifndef __CCACCELEROMETER_DELEGATE_H__
#define __CCACCELEROMETER_DELEGATE_H__

#include "CCCommon.h"

namespace   cocos2d {
/**
@brief The device accelerometer reports values for each axis in units of g-force
*/
typedef struct
{
    double x;
    double y;
    double z;

    double timestamp;
} CCAcceleration;

/**
@brief
The CCAccelerometerDelegate defines a single method for
receiving acceleration-related data from the system.
*/
class CC_DLL CCAccelerometerDelegate
{
public:
    virtual void didAccelerate(CCAcceleration* pAccelerationValue) {CC_UNUSED_PARAM(pAccelerationValue);}
};

} //namespace   cocos2d

#endif