code:
#
# Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved.
#
# For the applicable distribution terms see the license text file included in
# the distribution.
#

# build shared or static libraries, or static_and_shared (this is not supported
# by Symbian toolchains)
#
CONFIG += static

# Uncomment the following define to enable a very ugly hack to set the
# volume level on Symbian devices higher. By default, on Symbian, the volume
# level is very low when audio is played using QAudioOutput class. For now,
# this ugly hack is the only way to set the volume louder.
#
# WARNING: The volume hack (see the PullAudioOut.cpp file) is VERY DANGEROUS
# because the data to access the volume interface is retrieved manually with
# pointer manipulation. Should the library, in which the interface is
# implemented, be modified even a tiny bit, the application using this hack
# might crash.
#
#DEFINES += QTGAMEENABLER_USE_VOLUME_HACK

# Uncomment to decode ogg vorbis files on-the-fly. If this is commented out,
# the ogg vorbis files are decoded into memory when loading them.
#
DEFINES += USE_VORBIS_SOURCE

#-----------------------------------------------------------------------------

# Do not touch these

MOC_DIR = .moc
OBJECTS_DIR = .obj
DESTDIR = .lib

QT += core
contains(QT_CONFIG, reduce_exports): CONFIG += hide_symbols
QMAKE_CFLAGS += -std=c99

DEFINES += \
    SYSTEM_QT \
    COCOS2DXQT_LIBRARY

symbian {
    DEFINES += Q_OS_SYMBIAN
}

contains(MEEGO_EDITION,harmattan) {
    DEFINES += MEEGO_EDITION_HARMATTAN
}


code:
#
# Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved.
#
# For the applicable distribution terms see the license text file included in
# the distribution.
#

QMAKE_CFLAGS += -std=c99

DEFINES += SYSTEM_QT

contains(MEEGO_EDITION,harmattan) {
    QT += core gui xml meegographicssystemhelper
    CONFIG += mobility
    MOBILITY += multimedia systeminfo sensors
}

symbian {
    QT += core gui xml
    CONFIG += mobility
    MOBILITY += multimedia systeminfo sensors
    DEFINES += Q_OS_SYMBIAN
}

contains(COCOSBUILDMODE, inc) {
    DEFINES += COCOS2DXQT_LIBRARY

    contains(COCOSMODULES, cocosdenshion) {
        include(CocosDenshion/proj.qt/cocosdenshion.pri)
    }

    contains(COCOSMODULES, box2d) {
        include(Box2D/proj.qt/box2d.pri)
    }

    contains(COCOSMODULES, chipmunk) {
        include(chipmunk/proj.qt/chipmunk.pri)
    }

    contains(COCOSMODULES, lua) {
        include(lua/proj.qt/lua.pri)
    }

    include(cocos2dx/proj.qt/cocos2dx-qt.pri)
} else {
    contains(COCOSBUILDMODE, shared) {
        contains(COCOSMODULES, cocosdenshion) {
            include(CocosDenshion/proj.qt/cocosdenshion.pri)
            LIBS += -lcocosdenshion-qt
        }

        # FIXME: box2d and chipmunk libs do not export anything
        # usefull. The sources are included into the
        # project for now.
        contains(COCOSMODULES, box2d) {
            include(Box2D/proj.qt/box2d.pri)
        }

        contains(COCOSMODULES, chipmunk) {
            include(chipmunk/proj.qt/chipmunk.pri)
        }

        contains(COCOSMODULES, lua) {
            include(lua/proj.qt/lua.pri)
            LIBS += -llua-qt
        }

        include(cocos2dx/proj.qt/cocos2dx-qt.pri)
        LIBS += -lcocos2dx-qt
    } else {
        contains(COCOSBUILDMODE, static) {
            contains(MEEGO_EDITION,harmattan) {
                contains(COCOSMODULES, cocosdenshion) {
                    include(CocosDenshion/proj.qt/cocosdenshion.pri)
                    LIBS += -l:libcocosdenshion-qt.a
                }

                contains(COCOSMODULES, box2d) {
                    DEFINES += DONT_INCLUDE_BOX2D_SOURCES
                    include(Box2D/proj.qt/box2d.pri)
                    LIBS += -l:libbox2d-qt.a
                }

                contains(COCOSMODULES, chipmunk) {
                    DEFINES += DONT_INCLUDE_CHIPMUNK_SOURCES
                    include(chipmunk/proj.qt/chipmunk.pri)
                    LIBS += -l:libchipmunk-qt.a
                }

                contains(COCOSMODULES, lua) {
                    include(lua/proj.qt/lua.pri)
                    LIBS += -l:liblua-qt.a
                }

                include(cocos2dx/proj.qt/cocos2dx-qt.pri)
                LIBS += -l:libcocos2dx-qt.a
            }

            symbian {
                contains(COCOSMODULES, cocosdenshion) {
                    include(CocosDenshion/proj.qt/cocosdenshion.pri)
                    LIBS += -lcocosdenshion-qt.lib
                }

                contains(COCOSMODULES, box2d) {
                    DEFINES += DONT_INCLUDE_BOX2D_SOURCES
                    include(Box2D/proj.qt/box2d.pri)
                    LIBS += -lbox2d-qt.lib
                }

                contains(COCOSMODULES, chipmunk) {
                    DEFINES += DONT_INCLUDE_CHIPMUNK_SOURCES
                    include(chipmunk/proj.qt/chipmunk.pri)
                    LIBS += -lchipmunk-qt.lib
                }

                contains(COCOSMODULES, lua) {
                    include(lua/proj.qt/lua.pri)
                    LIBS += -llua-qt.lib
                }

                include(cocos2dx/proj.qt/cocos2dx-qt.pri)
                LIBS += -lcocos2dx-qt.lib
            }
        } else {
            error("COCOSBUILDMODE not defined!");
        }
    }
}

license: mit


code:
#
# Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved.
#
# For the applicable distribution terms see the license text file included in
# the distribution.
#

TEMPLATE = subdirs

CONFIG += ordered

SUBDIRS = CocosDenshion/proj.qt/cocosdenshion.pro
SUBDIRS += Box2D/proj.qt/box2d.pro
SUBDIRS += chipmunk/proj.qt/chipmunk.pro
SUBDIRS += cocos2dx/proj.qt/cocos2dx-qt.pro
SUBDIRS += lua/proj.qt/lua.pro

OTHER_FILES += \
    qtc_packaging/debian_harmattan/rules \
    qtc_packaging/debian_harmattan/README \
    qtc_packaging/debian_harmattan/manifest.aegis \
    qtc_packaging/debian_harmattan/copyright \
    qtc_packaging/debian_harmattan/control \
    qtc_packaging/debian_harmattan/compat \
    qtc_packaging/debian_harmattan/changelog


code:
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libBox2D", "Box2D\proj.win32\Box2D.win32.vcproj", "{929480E7-23C0-4DF6-8456-096D71547116}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libchipmunk", "chipmunk\proj.win32\chipmunk.win32.vcproj", "{207BC7A9-CCF1-4F2F-A04D-45F72242AE25}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libCocosDenshion", "CocosDenshion\proj.win32\CocosDenshion.win32.vcproj", "{F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcocos2d", "cocos2dx\proj.win32\cocos2d-win32.vcproj", "{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HelloWorld", "HelloWorld\win32\HelloWorld.win32.vcproj", "{B8BF9E81-35FD-4582-BA1C-B85FA365BABB}"
	ProjectSection(ProjectDependencies) = postProject
		{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E} = {98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}
	EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tests", "tests\test.win32\test.win32.vcproj", "{76A39BB2-9B84-4C65-98A5-654D86B86F2A}"
	ProjectSection(ProjectDependencies) = postProject
		{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E} = {98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}
		{207BC7A9-CCF1-4F2F-A04D-45F72242AE25} = {207BC7A9-CCF1-4F2F-A04D-45F72242AE25}
		{929480E7-23C0-4DF6-8456-096D71547116} = {929480E7-23C0-4DF6-8456-096D71547116}
		{F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6} = {F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}
	EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HelloLua", "HelloLua\win32\HelloLua.win32.vcproj", "{13E55395-94A2-4CD9-BFC2-1A051F80C17D}"
	ProjectSection(ProjectDependencies) = postProject
		{DDC3E27F-004D-4DD4-9DD3-931A013D2159} = {DDC3E27F-004D-4DD4-9DD3-931A013D2159}
		{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E} = {98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}
		{F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6} = {F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}
	EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblua", "lua\proj.win32\liblua.vcproj", "{DDC3E27F-004D-4DD4-9DD3-931A013D2159}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Win32 = Debug|Win32
		Release|Win32 = Release|Win32
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{929480E7-23C0-4DF6-8456-096D71547116}.Debug|Win32.ActiveCfg = Debug|Win32
		{929480E7-23C0-4DF6-8456-096D71547116}.Debug|Win32.Build.0 = Debug|Win32
		{929480E7-23C0-4DF6-8456-096D71547116}.Release|Win32.ActiveCfg = Release|Win32
		{929480E7-23C0-4DF6-8456-096D71547116}.Release|Win32.Build.0 = Release|Win32
		{207BC7A9-CCF1-4F2F-A04D-45F72242AE25}.Debug|Win32.ActiveCfg = Debug|Win32
		{207BC7A9-CCF1-4F2F-A04D-45F72242AE25}.Debug|Win32.Build.0 = Debug|Win32
		{207BC7A9-CCF1-4F2F-A04D-45F72242AE25}.Release|Win32.ActiveCfg = Release|Win32
		{207BC7A9-CCF1-4F2F-A04D-45F72242AE25}.Release|Win32.Build.0 = Release|Win32
		{F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}.Debug|Win32.ActiveCfg = Debug|Win32
		{F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}.Debug|Win32.Build.0 = Debug|Win32
		{F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}.Release|Win32.ActiveCfg = Release|Win32
		{F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}.Release|Win32.Build.0 = Release|Win32
		{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}.Debug|Win32.ActiveCfg = Debug|Win32
		{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}.Debug|Win32.Build.0 = Debug|Win32
		{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}.Release|Win32.ActiveCfg = Release|Win32
		{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}.Release|Win32.Build.0 = Release|Win32
		{B8BF9E81-35FD-4582-BA1C-B85FA365BABB}.Debug|Win32.ActiveCfg = Debug|Win32
		{B8BF9E81-35FD-4582-BA1C-B85FA365BABB}.Debug|Win32.Build.0 = Debug|Win32
		{B8BF9E81-35FD-4582-BA1C-B85FA365BABB}.Release|Win32.ActiveCfg = Release|Win32
		{B8BF9E81-35FD-4582-BA1C-B85FA365BABB}.Release|Win32.Build.0 = Release|Win32
		{76A39BB2-9B84-4C65-98A5-654D86B86F2A}.Debug|Win32.ActiveCfg = Debug|Win32
		{76A39BB2-9B84-4C65-98A5-654D86B86F2A}.Debug|Win32.Build.0 = Debug|Win32
		{76A39BB2-9B84-4C65-98A5-654D86B86F2A}.Release|Win32.ActiveCfg = Release|Win32
		{76A39BB2-9B84-4C65-98A5-654D86B86F2A}.Release|Win32.Build.0 = Release|Win32
		{13E55395-94A2-4CD9-BFC2-1A051F80C17D}.Debug|Win32.ActiveCfg = Debug|Win32
		{13E55395-94A2-4CD9-BFC2-1A051F80C17D}.Debug|Win32.Build.0 = Debug|Win32
		{13E55395-94A2-4CD9-BFC2-1A051F80C17D}.Release|Win32.ActiveCfg = Release|Win32
		{13E55395-94A2-4CD9-BFC2-1A051F80C17D}.Release|Win32.Build.0 = Release|Win32
		{DDC3E27F-004D-4DD4-9DD3-931A013D2159}.Debug|Win32.ActiveCfg = Debug|Win32
		{DDC3E27F-004D-4DD4-9DD3-931A013D2159}.Debug|Win32.Build.0 = Debug|Win32
		{DDC3E27F-004D-4DD4-9DD3-931A013D2159}.Release|Win32.ActiveCfg = Release|Win32
		{DDC3E27F-004D-4DD4-9DD3-931A013D2159}.Release|Win32.Build.0 = Release|Win32
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal


code:
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libBox2D", "Box2D\proj.win32\Box2D.win32.vcxproj", "{929480E7-23C0-4DF6-8456-096D71547116}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libchipmunk", "chipmunk\proj.win32\chipmunk.win32.vcxproj", "{207BC7A9-CCF1-4F2F-A04D-45F72242AE25}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libCocosDenshion", "CocosDenshion\proj.win32\CocosDenshion.win32.vcxproj", "{F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcocos2d", "cocos2dx\proj.win32\cocos2d-win32.vcxproj", "{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HelloWorld", "HelloWorld\win32\HelloWorld.win32.vcxproj", "{B8BF9E81-35FD-4582-BA1C-B85FA365BABB}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tests", "tests\test.win32\test.win32.vcxproj", "{76A39BB2-9B84-4C65-98A5-654D86B86F2A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HelloLua", "HelloLua\win32\HelloLua.win32.vcxproj", "{13E55395-94A2-4CD9-BFC2-1A051F80C17D}"
	ProjectSection(ProjectDependencies) = postProject
		{F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6} = {F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}
	EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblua", "lua\proj.win32\liblua.vcxproj", "{DDC3E27F-004D-4DD4-9DD3-931A013D2159}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Win32 = Debug|Win32
		Release|Win32 = Release|Win32
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{929480E7-23C0-4DF6-8456-096D71547116}.Debug|Win32.ActiveCfg = Debug|Win32
		{929480E7-23C0-4DF6-8456-096D71547116}.Debug|Win32.Build.0 = Debug|Win32
		{929480E7-23C0-4DF6-8456-096D71547116}.Release|Win32.ActiveCfg = Release|Win32
		{929480E7-23C0-4DF6-8456-096D71547116}.Release|Win32.Build.0 = Release|Win32
		{207BC7A9-CCF1-4F2F-A04D-45F72242AE25}.Debug|Win32.ActiveCfg = Debug|Win32
		{207BC7A9-CCF1-4F2F-A04D-45F72242AE25}.Debug|Win32.Build.0 = Debug|Win32
		{207BC7A9-CCF1-4F2F-A04D-45F72242AE25}.Release|Win32.ActiveCfg = Release|Win32
		{207BC7A9-CCF1-4F2F-A04D-45F72242AE25}.Release|Win32.Build.0 = Release|Win32
		{F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}.Debug|Win32.ActiveCfg = Debug|Win32
		{F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}.Debug|Win32.Build.0 = Debug|Win32
		{F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}.Release|Win32.ActiveCfg = Release|Win32
		{F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}.Release|Win32.Build.0 = Release|Win32
		{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}.Debug|Win32.ActiveCfg = Debug|Win32
		{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}.Debug|Win32.Build.0 = Debug|Win32
		{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}.Release|Win32.ActiveCfg = Release|Win32
		{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}.Release|Win32.Build.0 = Release|Win32
		{B8BF9E81-35FD-4582-BA1C-B85FA365BABB}.Debug|Win32.ActiveCfg = Debug|Win32
		{B8BF9E81-35FD-4582-BA1C-B85FA365BABB}.Debug|Win32.Build.0 = Debug|Win32
		{B8BF9E81-35FD-4582-BA1C-B85FA365BABB}.Release|Win32.ActiveCfg = Release|Win32
		{B8BF9E81-35FD-4582-BA1C-B85FA365BABB}.Release|Win32.Build.0 = Release|Win32
		{76A39BB2-9B84-4C65-98A5-654D86B86F2A}.Debug|Win32.ActiveCfg = Debug|Win32
		{76A39BB2-9B84-4C65-98A5-654D86B86F2A}.Debug|Win32.Build.0 = Debug|Win32
		{76A39BB2-9B84-4C65-98A5-654D86B86F2A}.Release|Win32.ActiveCfg = Release|Win32
		{76A39BB2-9B84-4C65-98A5-654D86B86F2A}.Release|Win32.Build.0 = Release|Win32
		{13E55395-94A2-4CD9-BFC2-1A051F80C17D}.Debug|Win32.ActiveCfg = Debug|Win32
		{13E55395-94A2-4CD9-BFC2-1A051F80C17D}.Debug|Win32.Build.0 = Debug|Win32
		{13E55395-94A2-4CD9-BFC2-1A051F80C17D}.Release|Win32.ActiveCfg = Release|Win32
		{13E55395-94A2-4CD9-BFC2-1A051F80C17D}.Release|Win32.Build.0 = Release|Win32
		{DDC3E27F-004D-4DD4-9DD3-931A013D2159}.Debug|Win32.ActiveCfg = Debug|Win32
		{DDC3E27F-004D-4DD4-9DD3-931A013D2159}.Debug|Win32.Build.0 = Debug|Win32
		{DDC3E27F-004D-4DD4-9DD3-931A013D2159}.Release|Win32.ActiveCfg = Release|Win32
		{DDC3E27F-004D-4DD4-9DD3-931A013D2159}.Release|Win32.Build.0 = Release|Win32
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal


code:
LOCAL_PATH := $(call my-dir)

## Static Library

include $(CLEAR_VARS)

LOCAL_MODULE := cocos2dx_static

LOCAL_MODULE_FILENAME := libcocos2dx

LOCAL_SRC_FILES := \
CCConfiguration.cpp \
CCDrawingPrimitives.cpp \
CCScheduler.cpp \
CCCamera.cpp \
actions/CCAction.cpp \
actions/CCActionCamera.cpp \
actions/CCActionEase.cpp \
actions/CCActionGrid.cpp \
actions/CCActionGrid3D.cpp \
actions/CCActionInstant.cpp \
actions/CCActionInterval.cpp \
actions/CCActionManager.cpp \
actions/CCActionPageTurn3D.cpp \
actions/CCActionProgressTimer.cpp \
actions/CCActionTiledGrid.cpp \
base_nodes/CCAtlasNode.cpp \
base_nodes/CCNode.cpp \
cocoa/CCAffineTransform.cpp \
cocoa/CCGeometry.cpp \
cocoa/CCAutoreleasePool.cpp \
cocoa/CCData.cpp \
cocoa/CCNS.cpp \
cocoa/CCObject.cpp \
cocoa/CCSet.cpp \
cocoa/CCZone.cpp \
cocos2d.cpp \
CCDirector.cpp \
effects/CCGrabber.cpp \
effects/CCGrid.cpp \
extensions/CCNotificationCenter.cpp \
keypad_dispatcher/CCKeypadDelegate.cpp \
keypad_dispatcher/CCKeypadDispatcher.cpp \
label_nodes/CCLabelAtlas.cpp \
label_nodes/CCLabelBMFont.cpp \
label_nodes/CCLabelTTF.cpp \
layers_scenes_transitions_nodes/CCLayer.cpp \
layers_scenes_transitions_nodes/CCScene.cpp \
layers_scenes_transitions_nodes/CCTransitionPageTurn.cpp \
layers_scenes_transitions_nodes/CCTransitionRadial.cpp \
layers_scenes_transitions_nodes/CCTransition.cpp \
menu_nodes/CCMenu.cpp \
menu_nodes/CCMenuItem.cpp \
misc_nodes/CCMotionStreak.cpp \
misc_nodes/CCProgressTimer.cpp \
misc_nodes/CCRenderTexture.cpp \
misc_nodes/CCRibbon.cpp \
particle_nodes/CCParticleExamples.cpp \
particle_nodes/CCParticleSystem.cpp \
particle_nodes/CCParticleSystemPoint.cpp \
particle_nodes/CCParticleSystemQuad.cpp \
platform/CCFileUtils.cpp \
platform/CCGL.cpp \
platform/CCImage.cpp \
platform/CCStdC.cpp \
platform/CCSAXParser.cpp \
platform/CCThread.cpp \
platform/CCCommon.cpp \
platform/platform.cpp \
platform/android/CCEGLView_android.cpp \
platform/android/CCAccelerometer_android.cpp \
platform/android/CCApplication_android.cpp \
platform/android/jni/JniHelper.cpp \
platform/android/jni/IMEJni.cpp \
platform/android/jni/MessageJni.cpp \
platform/android/jni/SensorJni.cpp \
platform/android/jni/SystemInfoJni.cpp \
platform/android/jni/TouchesJni.cpp \
script_support/CCScriptSupport.cpp \
sprite_nodes/CCAnimation.cpp \
sprite_nodes/CCAnimationCache.cpp \
sprite_nodes/CCSprite.cpp \
sprite_nodes/CCSpriteBatchNode.cpp \
sprite_nodes/CCSpriteFrame.cpp \
sprite_nodes/CCSpriteFrameCache.cpp \
support/CCArray.cpp \
support/CCProfiling.cpp \
support/CCPointExtension.cpp \
support/TransformUtils.cpp \
support/CCUserDefault.cpp \
support/base64.cpp \
support/ccUtils.cpp \
support/image_support/TGAlib.cpp \
support/zip_support/ZipUtils.cpp \
support/zip_support/ioapi.cpp \
support/zip_support/unzip.cpp \
text_input_node/CCIMEDispatcher.cpp \
text_input_node/CCTextFieldTTF.cpp \
textures/CCTexture2D.cpp \
textures/CCTextureAtlas.cpp \
textures/CCTextureCache.cpp \
textures/CCTexturePVR.cpp \
tileMap_parallax_nodes/CCParallaxNode.cpp \
tileMap_parallax_nodes/CCTMXLayer.cpp \
tileMap_parallax_nodes/CCTMXObjectGroup.cpp \
tileMap_parallax_nodes/CCTMXTiledMap.cpp \
tileMap_parallax_nodes/CCTMXXMLParser.cpp \
tileMap_parallax_nodes/CCTileMapAtlas.cpp \
touch_dispatcher/CCTouchDispatcher.cpp \
touch_dispatcher/CCTouchHandler.cpp

LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ \
                           $(LOCAL_PATH)/include \
                           $(LOCAL_PATH)/platform

LOCAL_EXPORT_LDLIBS := -llog\
                       -lz \
                       -lGLESv1_CM

LOCAL_C_INCLUDES := $(LOCAL_PATH)/ \
                    $(LOCAL_PATH)/include \
                    $(LOCAL_PATH)/platform

LOCAL_LDLIBS := -lGLESv1_CM \
                -llog \
                -lz

LOCAL_WHOLE_STATIC_LIBRARIES := cocos_libpng_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_jpeg_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_libxml2_static

# define the macro to compile through support/zip_support/ioapi.c
LOCAL_CFLAGS := -DUSE_FILE32API

include $(BUILD_STATIC_LIBRARY)

## Shared Library

include $(CLEAR_VARS)

LOCAL_MODULE := cocos2dx_shared

LOCAL_MODULE_FILENAME := libcocos2dx

LOCAL_SRC_FILES := \
CCConfiguration.cpp \
CCDrawingPrimitives.cpp \
CCScheduler.cpp \
CCCamera.cpp \
actions/CCAction.cpp \
actions/CCActionCamera.cpp \
actions/CCActionEase.cpp \
actions/CCActionGrid.cpp \
actions/CCActionGrid3D.cpp \
actions/CCActionInstant.cpp \
actions/CCActionInterval.cpp \
actions/CCActionManager.cpp \
actions/CCActionPageTurn3D.cpp \
actions/CCActionProgressTimer.cpp \
actions/CCActionTiledGrid.cpp \
base_nodes/CCAtlasNode.cpp \
base_nodes/CCNode.cpp \
cocoa/CCAffineTransform.cpp \
cocoa/CCGeometry.cpp \
cocoa/CCAutoreleasePool.cpp \
cocoa/CCData.cpp \
cocoa/CCNS.cpp \
cocoa/CCObject.cpp \
cocoa/CCSet.cpp \
cocoa/CCZone.cpp \
cocos2d.cpp \
CCDirector.cpp \
effects/CCGrabber.cpp \
effects/CCGrid.cpp \
extensions/CCNotificationCenter.cpp \
keypad_dispatcher/CCKeypadDelegate.cpp \
keypad_dispatcher/CCKeypadDispatcher.cpp \
label_nodes/CCLabelAtlas.cpp \
label_nodes/CCLabelBMFont.cpp \
label_nodes/CCLabelTTF.cpp \
layers_scenes_transitions_nodes/CCLayer.cpp \
layers_scenes_transitions_nodes/CCScene.cpp \
layers_scenes_transitions_nodes/CCTransitionPageTurn.cpp \
layers_scenes_transitions_nodes/CCTransitionRadial.cpp \
layers_scenes_transitions_nodes/CCTransition.cpp \
menu_nodes/CCMenu.cpp \
menu_nodes/CCMenuItem.cpp \
misc_nodes/CCMotionStreak.cpp \
misc_nodes/CCProgressTimer.cpp \
misc_nodes/CCRenderTexture.cpp \
misc_nodes/CCRibbon.cpp \
particle_nodes/CCParticleExamples.cpp \
particle_nodes/CCParticleSystem.cpp \
particle_nodes/CCParticleSystemPoint.cpp \
particle_nodes/CCParticleSystemQuad.cpp \
platform/CCFileUtils.cpp \
platform/CCGL.cpp \
platform/CCImage.cpp \
platform/CCStdC.cpp \
platform/CCSAXParser.cpp \
platform/CCThread.cpp \
platform/CCCommon.cpp \
platform/platform.cpp \
platform/android/CCEGLView_android.cpp \
platform/android/CCAccelerometer_android.cpp \
platform/android/CCApplication_android.cpp \
platform/android/jni/JniHelper.cpp \
platform/android/jni/IMEJni.cpp \
platform/android/jni/MessageJni.cpp \
platform/android/jni/SensorJni.cpp \
platform/android/jni/SystemInfoJni.cpp \
platform/android/jni/TouchesJni.cpp \
script_support/CCScriptSupport.cpp \
sprite_nodes/CCAnimation.cpp \
sprite_nodes/CCAnimationCache.cpp \
sprite_nodes/CCSprite.cpp \
sprite_nodes/CCSpriteBatchNode.cpp \
sprite_nodes/CCSpriteFrame.cpp \
sprite_nodes/CCSpriteFrameCache.cpp \
support/CCArray.cpp \
support/CCProfiling.cpp \
support/CCPointExtension.cpp \
support/TransformUtils.cpp \
support/CCUserDefault.cpp \
support/base64.cpp \
support/ccUtils.cpp \
support/image_support/TGAlib.cpp \
support/zip_support/ZipUtils.cpp \
support/zip_support/ioapi.cpp \
support/zip_support/unzip.cpp \
text_input_node/CCIMEDispatcher.cpp \
text_input_node/CCTextFieldTTF.cpp \
textures/CCTexture2D.cpp \
textures/CCTextureAtlas.cpp \
textures/CCTextureCache.cpp \
textures/CCTexturePVR.cpp \
tileMap_parallax_nodes/CCParallaxNode.cpp \
tileMap_parallax_nodes/CCTMXLayer.cpp \
tileMap_parallax_nodes/CCTMXObjectGroup.cpp \
tileMap_parallax_nodes/CCTMXTiledMap.cpp \
tileMap_parallax_nodes/CCTMXXMLParser.cpp \
tileMap_parallax_nodes/CCTileMapAtlas.cpp \
touch_dispatcher/CCTouchDispatcher.cpp \
touch_dispatcher/CCTouchHandler.cpp

LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ \
                           $(LOCAL_PATH)/include \
                           $(LOCAL_PATH)/platform

LOCAL_EXPORT_LDLIBS := -llog\
                       -lz \
                       -lGLESv1_CM

LOCAL_C_INCLUDES := $(LOCAL_PATH)/ \
                    $(LOCAL_PATH)/include \
                    $(LOCAL_PATH)/platform

LOCAL_LDLIBS := -lGLESv1_CM \
                -llog \
                -lz

LOCAL_WHOLE_STATIC_LIBRARIES := cocos_libpng_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_jpeg_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_libxml2_static

# define the macro to compile through support/zip_support/ioapi.c
LOCAL_CFLAGS := -DUSE_FILE32API

include $(BUILD_SHARED_LIBRARY)

$(call import-module,libjpeg)
$(call import-module,libpng)
$(call import-module,libxml2)


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

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 "CCCamera.h"
//#include "CCDirector.h"
#include "CCGL.h"

#include "CCDrawingPrimitives.h"
#include "CCDirector.h"

using namespace std;
namespace   cocos2d {

CCCamera::CCCamera(void)
{
	init();
}

CCCamera::~CCCamera(void)
{
}

char * CCCamera::description(void)
{
	char *ret = new char[100];
	sprintf(ret, "<CCCamera | center = (%.2f,%.2f,%.2f)>", m_fCenterX, m_fCenterY, m_fCenterZ);
	return ret;
}

void CCCamera::init(void)
{
	restore();
}

void CCCamera::restore(void)
{
	m_fEyeX = m_fEyeY = 0.0f;
	m_fEyeZ = getZEye();

	m_fCenterX = m_fCenterY = m_fCenterZ = 0.0f;

	m_fUpX = 0.0f;
	m_fUpY = 1.0f;
	m_fUpZ = 0.0f;

	m_bDirty = false;
}

void CCCamera::locate(void)
{
	if (m_bDirty)
	{
		gluLookAt(m_fEyeX, m_fEyeY, m_fEyeZ,
			m_fCenterX, m_fCenterY, m_fCenterZ,
			m_fUpX, m_fUpY, m_fUpZ);
	}
}

float CCCamera::getZEye(void)
{
	return FLT_EPSILON;
}

void CCCamera::setEyeXYZ(float fEyeX, float fEyeY, float fEyeZ)
{
	m_fEyeX = fEyeX * CC_CONTENT_SCALE_FACTOR();
	m_fEyeY = fEyeY * CC_CONTENT_SCALE_FACTOR();
	m_fEyeZ = fEyeZ * CC_CONTENT_SCALE_FACTOR();

	m_bDirty = true;
}

void CCCamera::setCenterXYZ(float fCenterX, float fCenterY, float fCenterZ)
{
	m_fCenterX = fCenterX * CC_CONTENT_SCALE_FACTOR();
	m_fCenterY = fCenterY * CC_CONTENT_SCALE_FACTOR();
	m_fCenterZ = fCenterZ * CC_CONTENT_SCALE_FACTOR();

	m_bDirty = true;
}

void CCCamera::setUpXYZ(float fUpX, float fUpY, float fUpZ)
{
	m_fUpX = fUpX;
	m_fUpY = fUpY;
	m_fUpZ = fUpZ;

	m_bDirty = true;
}

void CCCamera::getEyeXYZ(float *pEyeX, float *pEyeY, float *pEyeZ)
{
	*pEyeX = m_fEyeX / CC_CONTENT_SCALE_FACTOR();
	*pEyeY = m_fEyeY / CC_CONTENT_SCALE_FACTOR();
	*pEyeZ = m_fEyeZ / CC_CONTENT_SCALE_FACTOR();
}

void CCCamera::getCenterXYZ(float *pCenterX, float *pCenterY, float *pCenterZ)
{
	*pCenterX = m_fCenterX / CC_CONTENT_SCALE_FACTOR();
	*pCenterY = m_fCenterY / CC_CONTENT_SCALE_FACTOR();
	*pCenterZ = m_fCenterZ / CC_CONTENT_SCALE_FACTOR();
}

void CCCamera::getUpXYZ(float *pUpX, float *pUpY, float *pUpZ)
{
	*pUpX = m_fUpX;
	*pUpY = m_fUpY;
	*pUpZ = m_fUpZ;
}
}//namespace   cocos2d


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

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 "CCConfiguration.h"
#include "ccMacros.h"
#include "ccConfig.h"
#include <string.h>
using namespace std;
namespace   cocos2d {

CCConfiguration::CCConfiguration(void)
:m_nMaxTextureSize(0)
, m_nMaxModelviewStackDepth(0)
, m_bSupportsPVRTC(false)
, m_bSupportsNPOT(false)
, m_bSupportsBGRA8888(false)
, m_bSupportsDiscardFramebuffer(false)
, m_bInited(false)
, m_uOSVersion(0)
, m_nMaxSamplesAllowed(0)
, m_pGlExtensions(NULL)
{
}

bool CCConfiguration::init(void)
{
	CCLOG("cocos2d: GL_VENDOR:     %s", glGetString(GL_VENDOR));
	CCLOG("cocos2d: GL_RENDERER:   %s", glGetString(GL_RENDERER));
	CCLOG("cocos2d: GL_VERSION:    %s", glGetString(GL_VERSION));

	m_pGlExtensions = (char *)glGetString(GL_EXTENSIONS);

	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_nMaxTextureSize);
	glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, &m_nMaxModelviewStackDepth);

	m_bSupportsPVRTC = checkForGLExtension("GL_IMG_texture_compression_pvrtc");
	m_bSupportsNPOT = checkForGLExtension("GL_APPLE_texture_2D_limited_npot");
	m_bSupportsBGRA8888 = checkForGLExtension("GL_IMG_texture_format_BGRA888");
	m_bSupportsDiscardFramebuffer = checkForGLExtension("GL_EXT_discard_framebuffer");

	CCLOG("cocos2d: GL_MAX_TEXTURE_SIZE: %d", m_nMaxTextureSize);
	CCLOG("cocos2d: GL_MAX_MODELVIEW_STACK_DEPTH: %d",m_nMaxModelviewStackDepth);
	CCLOG("cocos2d: GL supports PVRTC: %s", (m_bSupportsPVRTC ? "YES" : "NO"));
	CCLOG("cocos2d: GL supports BGRA8888 textures: %s", (m_bSupportsBGRA8888 ? "YES" : "NO"));
	CCLOG("cocos2d: GL supports NPOT textures: %s", (m_bSupportsNPOT ? "YES" : "NO"));
	CCLOG("cocos2d: GL supports discard_framebuffer: %s", (m_bSupportsDiscardFramebuffer ? "YES" : "NO"));

#if CC_TEXTURE_NPOT_SUPPORT
	CCLOG("cocos2d: compiled with NPOT support: %s", "YES");
#else
	CCLOG("cocos2d: compiled with NPOT support: %s", "NO");
#endif // CC_TEXTURE_NPOT_SUPPORT

#if CC_TEXTURE_ATLAS_USES_VBO
	CCLOG("cocos2d: compiled with VBO support in TextureAtlas : %s", "YES");
#else
	CCLOG("cocos2d: compiled with VBO support in TextureAtlas : %s", "NO");
#endif // CC_TEXTURE_ATLAS_USES_VBO

	return true;
}

CCGlesVersion CCConfiguration::getGlesVersion()
{
	// To get the Opengl ES version
	std::string strVersion((char *)glGetString(GL_VERSION));
	if ((int)strVersion.find("1.0") != -1)
	{
		return GLES_VER_1_0;
	}
	else if ((int)strVersion.find("1.1") != -1)
	{
		return GLES_VER_1_1;
	}
	else if ((int)strVersion.find("2.0") != -1)
	{
		return GLES_VER_2_0;
	}
#if (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
	return GLES_VER_2_0;
#else

	return GLES_VER_INVALID;
#endif
}

CCConfiguration* CCConfiguration::sharedConfiguration(void)
{
    static CCConfiguration sharedConfiguration;
    if (!sharedConfiguration.m_bInited)
    {
        sharedConfiguration.init();
        sharedConfiguration.m_bInited = true;
    }

    return &sharedConfiguration;
}

bool CCConfiguration::checkForGLExtension(const string &searchName)
{
	bool bRet = false;
	const char *kSearchName = searchName.c_str();

	if (m_pGlExtensions &&
		strstr(m_pGlExtensions, kSearchName))
	{
		bRet = true;
	}

	return bRet;
}
}//namespace   cocos2d


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

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 __CCCONFIGURATION_H__
#define __CCCONFIGURATION_H__

#include "CCObject.h"
#include <string>
#include "CCGL.h"

namespace   cocos2d {

	/** OS version definitions.
	*/
	enum {
		kCCiOSVersion_3_0   = 0x03000000,
		kCCiOSVersion_3_1   = 0x03010000,
		kCCiOSVersion_3_1_1 = 0x03010100,
		kCCiOSVersion_3_1_2 = 0x03010200,
		kCCiOSVersion_3_1_3 = 0x03010300,
		kCCiOSVersion_3_2   = 0x03020000,
		kCCiOSVersion_3_2_1 = 0x03020100,
		kCCiOSVersion_4_0   = 0x04000000,
		kCCiOSVersion_4_0_1 = 0x04000100,
		kCCiOSVersion_4_1   = 0x04010000,
		kCCiOSVersion_4_2   = 0x04020000,
		kCCiOSVersion_4_3   = 0x04030000,
		kCCiOSVersion_4_3_1 = 0x04030100,
		kCCiOSVersion_4_3_2 = 0x04030200,
		kCCiOSVersion_4_3_3 = 0x04030300,
	};

	typedef enum
	{
		GLES_VER_INVALID,
		GLES_VER_1_0,
		GLES_VER_1_1,
		GLES_VER_2_0,
	} CCGlesVersion;

/**
 @brief CCConfiguration contains some openGL variables
 @since v0.99.0
 */
class CC_DLL CCConfiguration : public CCObject
{
protected:
	GLint			m_nMaxTextureSize;
	GLint			m_nMaxModelviewStackDepth;
	bool			m_bSupportsPVRTC;
	bool			m_bSupportsNPOT;
	bool			m_bSupportsBGRA8888;
	bool			m_bSupportsDiscardFramebuffer;
    bool            m_bInited;
	unsigned int	m_uOSVersion;
	GLint           m_nMaxSamplesAllowed;
    char *          m_pGlExtensions;

private:

    CCConfiguration(void);

public:

	CCGlesVersion getGlesVersion();

	/** OpenGL Max texture size. */
	inline int getMaxTextureSize(void)
	{
		return m_nMaxTextureSize;
	}

	/** OpenGL Max Modelview Stack Depth */
	inline int getMaxModelviewStackDepth(void)
	{
		return m_nMaxModelviewStackDepth;
	}

	/** Whether or not the GPU supports NPOT (Non Power Of Two) textures.
	 NPOT textures have the following limitations:
	 - They can't have mipmaps
	 - They only accept GL_CLAMP_TO_EDGE in GL_TEXTURE_WRAP_{S,T}

	 @since v0.99.2
	 */
	inline bool isSupportsNPOT(void)
	{
		return m_bSupportsNPOT;
	}

	/** Whether or not PVR Texture Compressed is supported */
	inline bool isSupportsPVRTC(void)
	{
		return m_bSupportsPVRTC;
	}

	/** Whether or not BGRA8888 textures are supported.
	 @since v0.99.2
	 */
	inline bool isSupportsBGRA8888(void)
	{
		return m_bSupportsBGRA8888;
	}

	/** Whether or not glDiscardFramebufferEXT is supported
	 @since v0.99.2
	 */
	inline bool isSupportsDiscardFramebuffer(void)
	{
		return m_bSupportsDiscardFramebuffer;
	}

	/** returns the OS version.
	- On iOS devices it returns the firmware version.
	- On Mac returns the OS version

	@since v0.99.5
	*/
	inline unsigned int getOSVersion() { return m_uOSVersion; }

	/** returns whether or not an OpenGL is supported */
	bool checkForGLExtension(const std::string &searchName);

	bool init(void);

public:
	/** returns a shared instance of the CCConfiguration */
	static CCConfiguration *sharedConfiguration(void);
};
}//namespace   cocos2d

#endif // __CCCONFIGURATION_H__


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 "cocoa/CCNS.h"
#include "CCDirector.h"
#include "CCScene.h"
#include "CCMutableArray.h"
#include "CCScheduler.h"
#include "ccMacros.h"
#include "CCTouchDispatcher.h"
#include "CCPointExtension.h"
#include "CCTransition.h"
#include "CCTextureCache.h"
#include "CCTransition.h"
#include "CCSpriteFrameCache.h"
#include "CCAutoreleasePool.h"
#include "platform/platform.h"
#include "CCApplication.h"
#include "CCLabelBMFont.h"
#include "CCActionManager.h"
#include "CCLabelTTF.h"
#include "CCConfiguration.h"
#include "CCKeypadDispatcher.h"
#include "CCGL.h"
#include "CCAnimationCache.h"
#include "CCTouch.h"
#include "CCUserDefault.h"
#include "extensions/CCNotificationCenter.h"

#if CC_ENABLE_PROFILERS
#include "support/CCProfiling.h"
#endif // CC_ENABLE_PROFILERS

#include <string>

using namespace std;
using namespace cocos2d;
namespace  cocos2d
{

// singleton stuff
static CCDisplayLinkDirector s_sharedDirector;
static bool s_bFirstRun = true;

#define kDefaultFPS		60  // 60 frames per second
extern const char* cocos2dVersion(void);

CCDirector* CCDirector::sharedDirector(void)
{
	if (s_bFirstRun)
	{
		s_sharedDirector.init();
        s_bFirstRun = false;
	}

	return &s_sharedDirector;
}

bool CCDirector::init(void)
{
	CCLOG("cocos2d: %s", cocos2dVersion());

	// scenes
	m_pRunningScene = NULL;
	m_pNextScene = NULL;

	m_pNotificationNode = NULL;

	m_dOldAnimationInterval = m_dAnimationInterval = 1.0 / kDefaultFPS;
	m_pobScenesStack = new CCMutableArray<CCScene*>();

	// Set default projection (3D)
	m_eProjection = kCCDirectorProjectionDefault;

	// projection delegate if "Custom" projection is used
	m_pProjectionDelegate = NULL;

	// FPS
	m_bDisplayFPS = false;
	m_uTotalFrames = m_uFrames = 0;
	m_pszFPS = new char[10];
	m_pLastUpdate = new struct cc_timeval();

	// paused ?
	m_bPaused = false;

	// purge ?
	m_bPurgeDirecotorInNextLoop = false;

	m_obWinSizeInPixels = m_obWinSizeInPoints = CCSizeZero;

	// portrait mode default
	m_eDeviceOrientation = CCDeviceOrientationPortrait;

	m_pobOpenGLView = NULL;

    m_bRetinaDisplay = false;
    m_fContentScaleFactor = 1;
	m_bIsContentScaleSupported = false;

	// create autorelease pool
	CCPoolManager::getInstance()->push();

	return true;
}

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

#if CC_DIRECTOR_FAST_FPS
	CC_SAFE_RELEASE(m_pFPSLabel);
#endif

	CC_SAFE_RELEASE(m_pRunningScene);
	CC_SAFE_RELEASE(m_pNotificationNode);
	CC_SAFE_RELEASE(m_pobScenesStack);

	// pop the autorelease pool
	CCPoolManager::getInstance()->pop();

	// delete m_pLastUpdate
	CC_SAFE_DELETE(m_pLastUpdate);

    CCKeypadDispatcher::purgeSharedDispatcher();

	// delete fps string
	delete []m_pszFPS;
}

void CCDirector::setGLDefaultValues(void)
{
	// This method SHOULD be called only after openGLView_ was initialized
	CCAssert(m_pobOpenGLView, "opengl view should not be null");

	setAlphaBlending(true);
	setDepthTest(true);
	setProjection(m_eProjection);

	// set other opengl default values
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

#if CC_DIRECTOR_FAST_FPS
	if (! m_pFPSLabel)
	{
        m_pFPSLabel = CCLabelTTF::labelWithString("00.0", "Arial", 24);
		m_pFPSLabel->retain();
	}
#endif
}

// Draw the SCene
void CCDirector::drawScene(void)
{
	// calculate "global" dt
	calculateDeltaTime();

	//tick before glClear: issue #533
	if (! m_bPaused)
	{
		CCScheduler::sharedScheduler()->tick(m_fDeltaTime);
	}

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    /* to avoid flickr, nextScene MUST be here: after tick and before draw.
	 XXX: Which bug is this one. It seems that it can't be reproduced with v0.9 */
	if (m_pNextScene)
	{
		setNextScene();
	}

	glPushMatrix();

	applyOrientation();

	// By default enable VertexArray, ColorArray, TextureCoordArray and Texture2D
	CC_ENABLE_DEFAULT_GL_STATES();

	// draw the scene
    if (m_pRunningScene)
    {
        m_pRunningScene->visit();
    }

	// draw the notifications node
	if (m_pNotificationNode)
	{
		m_pNotificationNode->visit();
	}

	if (m_bDisplayFPS)
	{
		showFPS();
	}

#if CC_ENABLE_PROFILERS
	showProfilers();
#endif

	CC_DISABLE_DEFAULT_GL_STATES();

	glPopMatrix();

	m_uTotalFrames++;

	// swap buffers
	if (m_pobOpenGLView)
    {
        m_pobOpenGLView->swapBuffers();
    }
}

void CCDirector::calculateDeltaTime(void)
{
    struct cc_timeval now;

	if (CCTime::gettimeofdayCocos2d(&now, NULL) != 0)
	{
		CCLOG("error in gettimeofday");
        m_fDeltaTime = 0;
		return;
	}

	// new delta time
	if (m_bNextDeltaTimeZero)
	{
		m_fDeltaTime = 0;
		m_bNextDeltaTimeZero = false;
	}
	else
	{
		m_fDeltaTime = (now.tv_sec - m_pLastUpdate->tv_sec) + (now.tv_usec - m_pLastUpdate->tv_usec) / 1000000.0f;
		m_fDeltaTime = MAX(0, m_fDeltaTime);
	}

#ifdef DEBUG
	// If we are debugging our code, prevent big delta time
	if(m_fDeltaTime > 0.2f)
	{
		m_fDeltaTime = 1 / 60.0f;
	}
#endif

	*m_pLastUpdate = now;
}

// m_pobOpenGLView

void CCDirector::setOpenGLView(CC_GLVIEW *pobOpenGLView)
{
	CCAssert(pobOpenGLView, "opengl view should not be null");

	if (m_pobOpenGLView != pobOpenGLView)
	{
		// because EAGLView is not kind of CCObject
		delete m_pobOpenGLView; // [openGLView_ release]
		m_pobOpenGLView = pobOpenGLView;

		// set size
		m_obWinSizeInPoints = m_pobOpenGLView->getSize();
		m_obWinSizeInPixels = CCSizeMake(m_obWinSizeInPoints.width * m_fContentScaleFactor, m_obWinSizeInPoints.height * m_fContentScaleFactor);
        setGLDefaultValues();

		if (m_fContentScaleFactor != 1)
		{
			updateContentScaleFactor();
		}

 		CCTouchDispatcher *pTouchDispatcher = CCTouchDispatcher::sharedDispatcher();
 		m_pobOpenGLView->setTouchDelegate(pTouchDispatcher);
        pTouchDispatcher->setDispatchEvents(true);
	}
}

void CCDirector::setNextDeltaTimeZero(bool bNextDeltaTimeZero)
{
	m_bNextDeltaTimeZero = bNextDeltaTimeZero;
}

void CCDirector::setProjection(ccDirectorProjection kProjection)
{
	CCSize size = m_obWinSizeInPixels;
	float zeye = this->getZEye();
	switch (kProjection)
	{
	case kCCDirectorProjection2D:
        if (m_pobOpenGLView)
        {
            m_pobOpenGLView->setViewPortInPoints(0, 0, size.width, size.height);
        }
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		ccglOrtho(0, size.width, 0, size.height, -1024 * CC_CONTENT_SCALE_FACTOR(),
			1024 * CC_CONTENT_SCALE_FACTOR());
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		break;

	case kCCDirectorProjection3D:
        if (m_pobOpenGLView)
        {
            m_pobOpenGLView->setViewPortInPoints(0, 0, size.width, size.height);
        }
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		// accommodate iPad retina while keep backward compatibility
		if (m_pobOpenGLView && m_pobOpenGLView->isIpad() && m_pobOpenGLView->getMainScreenScale() > 1.0)
		{
			gluPerspective(60, (GLfloat)size.width/size.height, zeye-size.height/2, zeye+size.height/2);
		}
		else
		{
			gluPerspective(60, (GLfloat)size.width/size.height, 0.5f, 1500.0f);
		}

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		gluLookAt( size.width/2, size.height/2, zeye,
				 size.width/2, size.height/2, 0,
				 0.0f, 1.0f, 0.0f);
		break;

	case kCCDirectorProjectionCustom:
		if (m_pProjectionDelegate)
		{
			m_pProjectionDelegate->updateProjection();
		}
		break;

	default:
		CCLOG("cocos2d: Director: unrecognized projecgtion");
		break;
	}

	m_eProjection = kProjection;
}

void CCDirector::purgeCachedData(void)
{
    CCLabelBMFont::purgeCachedData();
	CCTextureCache::sharedTextureCache()->removeUnusedTextures();
}

float CCDirector::getZEye(void)
{
    return (m_obWinSizeInPixels.height / 1.1566f);
}

void CCDirector::setAlphaBlending(bool bOn)
{
	if (bOn)
	{
		glEnable(GL_BLEND);
		glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
	}
	else
	{
		glDisable(GL_BLEND);
	}
}

void CCDirector::setDepthTest(bool bOn)
{
	if (bOn)
	{
		ccglClearDepth(1.0f);
		glEnable(GL_DEPTH_TEST);
		glDepthFunc(GL_LEQUAL);
//		glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	}
	else
	{
		glDisable(GL_DEPTH_TEST);
	}
}

CCPoint CCDirector::convertToGL(const CCPoint& obPoint)
{
	CCSize s = m_obWinSizeInPoints;
	float newY = s.height - obPoint.y;
	float newX = s.width - obPoint.x;

	CCPoint ret = CCPointZero;
	switch (m_eDeviceOrientation)
	{
	case CCDeviceOrientationPortrait:
		ret = ccp(obPoint.x, newY);
		break;
	case CCDeviceOrientationPortraitUpsideDown:
		ret = ccp(newX, obPoint.y);
		break;
	case CCDeviceOrientationLandscapeLeft:
		ret.x = obPoint.y;
		ret.y = obPoint.x;
		break;
	case CCDeviceOrientationLandscapeRight:
		ret.x = newY;
		ret.y = newX;
		break;
	}

	return ret;
}

CCPoint CCDirector::convertToUI(const CCPoint& obPoint)
{
	CCSize winSize = m_obWinSizeInPoints;
	float oppositeX = winSize.width - obPoint.x;
	float oppositeY = winSize.height - obPoint.y;
	CCPoint uiPoint = CCPointZero;

	switch (m_eDeviceOrientation)
	{
	case CCDeviceOrientationPortrait:
		uiPoint = ccp(obPoint.x, oppositeY);
		break;
	case CCDeviceOrientationPortraitUpsideDown:
		uiPoint = ccp(oppositeX, obPoint.y);
		break;
	case CCDeviceOrientationLandscapeLeft:
		uiPoint = ccp(obPoint.y, obPoint.x);
		break;
	case CCDeviceOrientationLandscapeRight:
		// Can't use oppositeX/Y because x/y are flipped
		uiPoint = ccp(winSize.width - obPoint.y, winSize.height - obPoint.x);
		break;
	}

	return uiPoint;
}

CCSize CCDirector::getWinSize(void)
{
	CCSize s = m_obWinSizeInPoints;

	if (m_eDeviceOrientation == CCDeviceOrientationLandscapeLeft
		|| m_eDeviceOrientation == CCDeviceOrientationLandscapeRight)
	{
		// swap x,y in landspace mode
		CCSize tmp = s;
		s.width = tmp.height;
		s.height = tmp.width;
	}

	return s;
}

CCSize CCDirector::getWinSizeInPixels()
{
	CCSize s = getWinSize();

	s.width *= CC_CONTENT_SCALE_FACTOR();
	s.height *= CC_CONTENT_SCALE_FACTOR();

	return s;
}

// return the current frame size
CCSize CCDirector::getDisplaySizeInPixels(void)
{
	return m_obWinSizeInPixels;
}

void CCDirector::reshapeProjection(const CCSize& newWindowSize)
{
    CC_UNUSED_PARAM(newWindowSize);
    m_obWinSizeInPoints = m_pobOpenGLView->getSize();
	m_obWinSizeInPixels = CCSizeMake(m_obWinSizeInPoints.width * m_fContentScaleFactor,
		                             m_obWinSizeInPoints.height * m_fContentScaleFactor);

	setProjection(m_eProjection);
}

// scene management

void CCDirector::runWithScene(CCScene *pScene)
{
	CCAssert(pScene != NULL, "running scene should not be null");
	CCAssert(m_pRunningScene == NULL, "m_pRunningScene should be null");

	pushScene(pScene);
	startAnimation();
}

void CCDirector::replaceScene(CCScene *pScene)
{
	CCAssert(pScene != NULL, "the scene should not be null");

	unsigned int index = m_pobScenesStack->count();

	m_bSendCleanupToScene = true;
	m_pobScenesStack->replaceObjectAtIndex(index - 1, pScene);

	m_pNextScene = pScene;
}

void CCDirector::pushScene(CCScene *pScene)
{
	CCAssert(pScene, "the scene should not null");

	m_bSendCleanupToScene = false;

	m_pobScenesStack->addObject(pScene);
	m_pNextScene = pScene;
}

void CCDirector::popScene(void)
{
	CCAssert(m_pRunningScene != NULL, "running scene should not null");

	m_pobScenesStack->removeLastObject();
	unsigned int c = m_pobScenesStack->count();

	if (c == 0)
	{
		end();
	}
	else
	{
		m_bSendCleanupToScene = true;
		m_pNextScene = m_pobScenesStack->getObjectAtIndex(c - 1);
	}
}

void CCDirector::end()
{
	m_bPurgeDirecotorInNextLoop = true;
}

void CCDirector::resetDirector()
{
	// don't release the event handlers
	// They are needed in case the director is run again
	CCTouchDispatcher::sharedDispatcher()->removeAllDelegates();

    if (m_pRunningScene)
    {
    	m_pRunningScene->onExit();
    	m_pRunningScene->cleanup();
    	m_pRunningScene->release();
    }

	m_pRunningScene = NULL;
	m_pNextScene = NULL;

	// remove all objects, but don't release it.
	// runWithScene might be executed after 'end'.
	m_pobScenesStack->removeAllObjects();

	stopAnimation();

    CCObject* pProjectionDelegate = (CCObject*)m_pProjectionDelegate;
	CC_SAFE_RELEASE_NULL(pProjectionDelegate);

	// purge bitmap cache
	CCLabelBMFont::purgeCachedData();

	// purge all managers
	CCAnimationCache::purgeSharedAnimationCache();
 	CCSpriteFrameCache::purgeSharedSpriteFrameCache();
	CCActionManager::sharedManager()->purgeSharedManager();
	CCScheduler::purgeSharedScheduler();
	CCTextureCache::purgeSharedTextureCache();
}

void CCDirector::purgeDirector()
{
	// don't release the event handlers
	// They are needed in case the director is run again
	CCTouchDispatcher::sharedDispatcher()->removeAllDelegates();

    if (m_pRunningScene)
    {
    	m_pRunningScene->onExit();
    	m_pRunningScene->cleanup();
    	m_pRunningScene->release();
    }

	m_pRunningScene = NULL;
	m_pNextScene = NULL;

	// remove all objects, but don't release it.
	// runWithScene might be executed after 'end'.
	m_pobScenesStack->removeAllObjects();

	stopAnimation();

#if CC_DIRECTOR_FAST_FPS
	CC_SAFE_RELEASE_NULL(m_pFPSLabel);
#endif

    CCObject* pProjectionDelegate = (CCObject*)m_pProjectionDelegate;
    CC_SAFE_RELEASE_NULL(pProjectionDelegate);

	// purge bitmap cache
	CCLabelBMFont::purgeCachedData();

	// purge all managers
	CCAnimationCache::purgeSharedAnimationCache();
 	CCSpriteFrameCache::purgeSharedSpriteFrameCache();
	CCActionManager::sharedManager()->purgeSharedManager();
	CCScheduler::purgeSharedScheduler();
	CCTextureCache::purgeSharedTextureCache();
	CCUserDefault::purgeSharedUserDefault();
    CCNotificationCenter::purgeNotifCenter();
	// OpenGL view
	m_pobOpenGLView->release();
	m_pobOpenGLView = NULL;
}

void CCDirector::setNextScene(void)
{
	bool runningIsTransition = dynamic_cast<CCTransitionScene*>(m_pRunningScene) != NULL;
	bool newIsTransition = dynamic_cast<CCTransitionScene*>(m_pNextScene) != NULL;

	// If it is not a transition, call onExit/cleanup
 	if (! newIsTransition)
 	{
         if (m_pRunningScene)
         {
             m_pRunningScene->onExit();
         }

 		// issue #709. the root node (scene) should receive the cleanup message too
 		// otherwise it might be leaked.
 		if (m_bSendCleanupToScene && m_pRunningScene)
 		{
 			m_pRunningScene->cleanup();
 		}
 	}

    if (m_pRunningScene)
    {
        m_pRunningScene->release();
    }
    m_pRunningScene = m_pNextScene;
	m_pNextScene->retain();
	m_pNextScene = NULL;

	if ((! runningIsTransition) && m_pRunningScene)
	{
		m_pRunningScene->onEnter();
		m_pRunningScene->onEnterTransitionDidFinish();
	}
}

void CCDirector::pause(void)
{
	if (m_bPaused)
	{
		return;
	}

	m_dOldAnimationInterval = m_dAnimationInterval;

	// when paused, don't consume CPU
	setAnimationInterval(1 / 4.0);
	m_bPaused = true;
}

void CCDirector::resume(void)
{
	if (! m_bPaused)
	{
		return;
	}

	setAnimationInterval(m_dOldAnimationInterval);

	if (CCTime::gettimeofdayCocos2d(m_pLastUpdate, NULL) != 0)
	{
		CCLOG("cocos2d: Director: Error in gettimeofday");
	}

	m_bPaused = false;
	m_fDeltaTime = 0;
}

#if CC_DIRECTOR_FAST_FPS
// display the FPS using a LabelAtlas
// updates the FPS every frame
void CCDirector::showFPS(void)
{
	m_uFrames++;
	m_fAccumDt += m_fDeltaTime;

	if (m_fAccumDt > CC_DIRECTOR_FPS_INTERVAL)
	{
		m_fFrameRate = m_uFrames / m_fAccumDt;
		m_uFrames = 0;
		m_fAccumDt = 0;

		sprintf(m_pszFPS, "%.1f", m_fFrameRate);
		m_pFPSLabel->setString(m_pszFPS);
	}

    m_pFPSLabel->draw();
}
#endif // CC_DIRECTOR_FAST_FPS

void CCDirector::showProfilers()
{
#if CC_ENABLE_PROFILERS
	m_fAccumDtForProfiler += m_fDeltaTime;
	if (m_fAccumDtForProfiler > 1.0f)
	{
		m_fAccumDtForProfiler = 0;
		CCProfiler::sharedProfiler()->displayTimers();
	}
#endif
}

/***************************************************
* mobile platforms specific functions
**************************************************/

void CCDirector::updateContentScaleFactor()
{
	// [openGLView responseToSelector:@selector(setContentScaleFactor)]
	if (m_pobOpenGLView->canSetContentScaleFactor())
	{
		m_pobOpenGLView->setContentScaleFactor(m_fContentScaleFactor);
		m_bIsContentScaleSupported = true;
	}
	else
	{
		CCLOG("cocos2d: setContentScaleFactor:'is not supported on this device");
	}
}

bool CCDirector::setDirectorType(ccDirectorType obDirectorType)
{
    CC_UNUSED_PARAM(obDirectorType);
	// we only support CCDisplayLinkDirector
	CCDirector::sharedDirector();

	return true;
}

bool CCDirector::enableRetinaDisplay(bool enabled)
{
	// Already enabled?
	if (enabled && m_fContentScaleFactor == 2)
	{
		return true;
	}

	// Already diabled?
	if (!enabled && m_fContentScaleFactor == 1)
	{
		return false;
	}

	// setContentScaleFactor is not supported
	if (! m_pobOpenGLView->canSetContentScaleFactor())
	{
		return false;
	}

	// SD device
	if (m_pobOpenGLView->getMainScreenScale() == 1.0)
	{
		return false;
	}

	float newScale = (float)(enabled ? 2 : 1);
	setContentScaleFactor(newScale);

    // release cached texture
    CCTextureCache::purgeSharedTextureCache();

#if CC_DIRECTOR_FAST_FPS
    if (m_pFPSLabel)
    {
        CC_SAFE_RELEASE_NULL(m_pFPSLabel);
        m_pFPSLabel = CCLabelTTF::labelWithString("00.0", "Arial", 24);
        m_pFPSLabel->retain();
    }
#endif

    if (m_fContentScaleFactor == 2)
    {
        m_bRetinaDisplay = true;
    }
    else
    {
        m_bRetinaDisplay = false;
    }

	return true;
}

CGFloat CCDirector::getContentScaleFactor(void)
{
	return m_fContentScaleFactor;
}

void CCDirector::setContentScaleFactor(CGFloat scaleFactor)
{
	if (scaleFactor != m_fContentScaleFactor)
	{
		m_fContentScaleFactor = scaleFactor;
		m_obWinSizeInPixels = CCSizeMake(m_obWinSizeInPoints.width * scaleFactor, m_obWinSizeInPoints.height * scaleFactor);

		if (m_pobOpenGLView)
		{
			updateContentScaleFactor();
		}

		// update projection
		setProjection(m_eProjection);
	}
}

CCNode* CCDirector::getNotificationNode()
{
	return m_pNotificationNode;
}

void CCDirector::setNotificationNode(CCNode *node)
{
	CC_SAFE_RELEASE(m_pNotificationNode);
	m_pNotificationNode = node;
	CC_SAFE_RETAIN(m_pNotificationNode);
}

void CCDirector::applyOrientation(void)
{
	CCSize s = m_obWinSizeInPixels;
	float w = s.width / 2;
	float h = s.height / 2;

	// XXX it's using hardcoded values.
	// What if the the screen size changes in the future?
	switch (m_eDeviceOrientation)
	{
	case CCDeviceOrientationPortrait:
		// nothing
		break;
	case CCDeviceOrientationPortraitUpsideDown:
		// upside down
		glTranslatef(w,h,0);
		glRotatef(180,0,0,1);
		glTranslatef(-w,-h,0);
		break;
	case CCDeviceOrientationLandscapeRight:
		glTranslatef(w,h,0);
		glRotatef(90,0,0,1);
		glTranslatef(-h,-w,0);
		break;
	case CCDeviceOrientationLandscapeLeft:
		glTranslatef(w,h,0);
		glRotatef(-90,0,0,1);
		glTranslatef(-h,-w,0);
		break;
	}
}

ccDeviceOrientation CCDirector::getDeviceOrientation(void)
{
	return m_eDeviceOrientation;
}

void CCDirector::setDeviceOrientation(ccDeviceOrientation kDeviceOrientation)
{
	ccDeviceOrientation eNewOrientation;

	eNewOrientation = (ccDeviceOrientation)CCApplication::sharedApplication().setOrientation(
        (CCApplication::Orientation)kDeviceOrientation);

	if (m_eDeviceOrientation != eNewOrientation)
	{
		m_eDeviceOrientation = eNewOrientation;
	}
    else
    {
        // this logic is only run on win32 now
        // On win32,the return value of CCApplication::setDeviceOrientation is always kCCDeviceOrientationPortrait
        // So,we should calculate the Projection and window size again.
        m_obWinSizeInPoints = m_pobOpenGLView->getSize();
        m_obWinSizeInPixels = CCSizeMake(m_obWinSizeInPoints.width * m_fContentScaleFactor, m_obWinSizeInPoints.height * m_fContentScaleFactor);
        setProjection(m_eProjection);
    }
}

/***************************************************
* implementation of DisplayLinkDirector
**************************************************/

// should we afford 4 types of director ??
// I think DisplayLinkDirector is enough
// so we now only support DisplayLinkDirector
void CCDisplayLinkDirector::startAnimation(void)
{
	if (CCTime::gettimeofdayCocos2d(m_pLastUpdate, NULL) != 0)
	{
		CCLOG("cocos2d: DisplayLinkDirector: Error on gettimeofday");
	}

	m_bInvalid = false;
	CCApplication::sharedApplication().setAnimationInterval(m_dAnimationInterval);
}

void CCDisplayLinkDirector::mainLoop(void)
{
	if (m_bPurgeDirecotorInNextLoop)
	{
		purgeDirector();
        m_bPurgeDirecotorInNextLoop = false;
	}
	else if (! m_bInvalid)
 	{
 		drawScene();

 		// release the objects
 		CCPoolManager::getInstance()->pop();
 	}
}

void CCDisplayLinkDirector::stopAnimation(void)
{
	m_bInvalid = true;
}

void CCDisplayLinkDirector::setAnimationInterval(double dValue)
{
	m_dAnimationInterval = dValue;
	if (! m_bInvalid)
	{
		stopAnimation();
		startAnimation();
	}
}

} //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 "CCDrawingPrimitives.h"
#include "ccTypes.h"
#include "ccMacros.h"
#include "CCGL.h"
#include "CCDirector.h"

#include <string.h>
#include <cmath>

#ifndef M_PI
	#define M_PI       3.14159265358979323846
#endif

namespace   cocos2d {

void ccDrawPoint(const CCPoint& point)
{
	ccVertex2F p = {point.x * CC_CONTENT_SCALE_FACTOR(), point.y * CC_CONTENT_SCALE_FACTOR() };
	// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
	// Needed states: GL_VERTEX_ARRAY,
	// Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
	glDisable(GL_TEXTURE_2D);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);

	glVertexPointer(2, GL_FLOAT, 0, &p);
	glDrawArrays(GL_POINTS, 0, 1);

	// restore default state
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnable(GL_TEXTURE_2D);
}

void ccDrawPoints(const CCPoint *points, unsigned int numberOfPoints)
{
	// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
	// Needed states: GL_VERTEX_ARRAY,
	// Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
	glDisable(GL_TEXTURE_2D);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);

	ccVertex2F *newPoints = new ccVertex2F[numberOfPoints];

	// iPhone and 32-bit machines optimization
	if( sizeof(CCPoint) == sizeof(ccVertex2F) )
	{
		// points ?
		if( CC_CONTENT_SCALE_FACTOR() != 1 )
		{
			for( unsigned int i= 0; i < numberOfPoints; i++)
			{
				newPoints[i].x = points[i].x * CC_CONTENT_SCALE_FACTOR();
				newPoints[i].y = points[i].y * CC_CONTENT_SCALE_FACTOR();
			}

			glVertexPointer(2, GL_FLOAT, 0, newPoints);

		} else
		{
			glVertexPointer(2, GL_FLOAT, 0, points);
		}

		glDrawArrays(GL_POINTS, 0, (GLsizei)numberOfPoints);

	} else
	{

		// Mac on 64-bit
		for( unsigned int i = 0; i < numberOfPoints; i++)
		{
			newPoints[i].x = points[i].x;
			newPoints[i].y = points[i].y;
		}

		glVertexPointer(2, GL_FLOAT, 0, newPoints);
		glDrawArrays(GL_POINTS, 0, (GLsizei)numberOfPoints);
	}

	delete[] newPoints;

	// restore default state
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnable(GL_TEXTURE_2D);
}

void ccDrawLine(const CCPoint& origin, const CCPoint& destination)
{
	ccVertex2F vertices[2] =
    {
        {origin.x * CC_CONTENT_SCALE_FACTOR(), origin.y * CC_CONTENT_SCALE_FACTOR()},
        {destination.x * CC_CONTENT_SCALE_FACTOR(), destination.y * CC_CONTENT_SCALE_FACTOR()},
    };

	// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
	// Needed states: GL_VERTEX_ARRAY,
	// Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
	glDisable(GL_TEXTURE_2D);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);

	glVertexPointer(2, GL_FLOAT, 0, vertices);
	glDrawArrays(GL_LINES, 0, 2);

	// restore default state
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnable(GL_TEXTURE_2D);
}

void ccDrawPoly(const CCPoint *poli, int numberOfPoints, bool closePolygon){
	ccDrawPoly(poli,numberOfPoints,closePolygon,false);
}
void ccDrawPoly(const CCPoint *poli, int numberOfPoints, bool closePolygon, bool fill)
{
    ccVertex2F* newPoint = new ccVertex2F[numberOfPoints];
    if (! newPoint)
    {
        return;
    }
    // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
    // Needed states: GL_VERTEX_ARRAY,
    // Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
    glDisable(GL_TEXTURE_2D);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);

    // iPhone and 32-bit machines
    if( sizeof(CCPoint) == sizeof(ccVertex2F) )
	{
        // convert to pixels ?
        if( CC_CONTENT_SCALE_FACTOR() != 1 )
		{
            memcpy( newPoint, poli, numberOfPoints * sizeof(ccVertex2F) );
            for( int i=0; i<numberOfPoints;i++)
            {
                newPoint[i].x = poli[i].x * CC_CONTENT_SCALE_FACTOR();
                newPoint[i].y = poli[i].y * CC_CONTENT_SCALE_FACTOR();
            }
            glVertexPointer(2, GL_FLOAT, 0, newPoint);

        }
		else
		{
            glVertexPointer(2, GL_FLOAT, 0, poli);
		}

    }
	else
	{
        // 64-bit machines (Mac)

        for( int i=0; i<numberOfPoints;i++)
        {
            newPoint[i].x = poli[i].x;
            newPoint[i].y = poli[i].y;
        }

        glVertexPointer(2, GL_FLOAT, 0, newPoint );

    }

    if( closePolygon )
	{
        glDrawArrays(fill? GL_TRIANGLE_FAN : GL_LINE_LOOP, 0, numberOfPoints);
	}
    else
	{
		glDrawArrays(fill? GL_TRIANGLE_FAN : GL_LINE_STRIP, 0, numberOfPoints);
	}

    // restore default state
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnable(GL_TEXTURE_2D);
    delete[] newPoint;
}

void ccDrawCircle(const CCPoint& center, float r, float a, int segs, bool drawLineToCenter)
{
	int additionalSegment = 1;
	if (drawLineToCenter)
	{
		++additionalSegment;
	}

	const float coef = 2.0f * (float) (M_PI) /segs;

	float *vertices = new float[2*(segs+2)]; //	float *vertices = (float *)malloc( sizeof(float)*2*(segs+2));
	if( ! vertices )
	{
		return;
	}

	memset( vertices,0, sizeof(float)*2*(segs+2));

	for(int i=0;i<=segs;i++)
	{
		float rads = i*coef;
		float j = r * cosf(rads + a) + center.x;
		float k = r * sinf(rads + a) + center.y;

		vertices[i*2] = j * CC_CONTENT_SCALE_FACTOR();
		vertices[i*2+1] =k * CC_CONTENT_SCALE_FACTOR();
	}
	vertices[(segs+1)*2] = center.x * CC_CONTENT_SCALE_FACTOR();
	vertices[(segs+1)*2+1] = center.y * CC_CONTENT_SCALE_FACTOR();

	// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
	// Needed states: GL_VERTEX_ARRAY,
	// Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
	glDisable(GL_TEXTURE_2D);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);

	glVertexPointer(2, GL_FLOAT, 0, vertices);
	glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) segs+additionalSegment);

	// restore default state
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnable(GL_TEXTURE_2D);

	delete[] vertices; //	free(vertices);
}

void ccDrawQuadBezier(const CCPoint& origin, const CCPoint& control, const CCPoint& destination, int segments)
{
	CCPoint *vertices = new CCPoint[segments + 1];

	float t = 0.0f;
	for(int i = 0; i < segments; i++)
	{
		float x = powf(1 - t, 2) * origin.x + 2.0f * (1 - t) * t * control.x + t * t * destination.x;
		float y = powf(1 - t, 2) * origin.y + 2.0f * (1 - t) * t * control.y + t * t * destination.y;
		vertices[i] = CCPointMake(x * CC_CONTENT_SCALE_FACTOR(), y * CC_CONTENT_SCALE_FACTOR());
		t += 1.0f / segments;
	}
	vertices[segments] = CCPointMake(destination.x  * CC_CONTENT_SCALE_FACTOR(), destination.y * CC_CONTENT_SCALE_FACTOR());

	// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
	// Needed states: GL_VERTEX_ARRAY,
	// Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
	glDisable(GL_TEXTURE_2D);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);

	glVertexPointer(2, GL_FLOAT, 0, vertices);
	glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) segments + 1);
	delete[] vertices;

	// restore default state
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnable(GL_TEXTURE_2D);
}

void ccDrawCubicBezier(const CCPoint& origin, const CCPoint& control1, const CCPoint& control2, const CCPoint& destination, int segments)
{
	CCPoint *vertices = new CCPoint[segments + 1];

	float t = 0;
	for(int i = 0; i < segments; ++i)
	{
		float x = powf(1 - t, 3) * origin.x + 3.0f * powf(1 - t, 2) * t * control1.x + 3.0f * (1 - t) * t * t * control2.x + t * t * t * destination.x;
		float y = powf(1 - t, 3) * origin.y + 3.0f * powf(1 - t, 2) * t * control1.y + 3.0f * (1 - t) * t * t * control2.y + t * t * t * destination.y;
		vertices[i] = CCPointMake(x * CC_CONTENT_SCALE_FACTOR(), y * CC_CONTENT_SCALE_FACTOR());
		t += 1.0f / segments;
	}
	vertices[segments] = CCPointMake(destination.x * CC_CONTENT_SCALE_FACTOR(), destination.y * CC_CONTENT_SCALE_FACTOR());

	// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
	// Needed states: GL_VERTEX_ARRAY,
	// Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
	glDisable(GL_TEXTURE_2D);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);

	glVertexPointer(2, GL_FLOAT, 0, vertices);
	glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) segments + 1);
	delete[] vertices;

	// restore default state
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnable(GL_TEXTURE_2D);
}
}//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 "CCScheduler.h"
#include "ccMacros.h"
#include "support/data_support/utlist.h"
#include "support/data_support/ccCArray.h"
#include "CCArray.h"
#include "CCScriptSupport.h"

using namespace std;

namespace   cocos2d {

// data structures

// A list double-linked list used for "updates with priority"
typedef struct _listEntry
{
	struct	_listEntry	*prev, *next;
	CCObject	*target;		// not retained (retained by hashUpdateEntry)
	int				    priority;
	bool				paused;
	bool				markedForDeletion; // selector will no longer be called and entry will be removed at end of the next tick

} tListEntry;

typedef struct _hashUpdateEntry
{
	tListEntry			**list;		// Which list does it belong to ?
	tListEntry			*entry;		// entry in the list
	CCObject	*target;		// hash key (retained)
	UT_hash_handle		hh;
} tHashUpdateEntry;

// Hash Element used for "selectors with interval"
typedef struct _hashSelectorEntry
{
	ccArray          	        *timers;
	CCObject			*target;	// hash key (retained)
	unsigned int				timerIndex;
	CCTimer						*currentTimer;
	bool						currentTimerSalvaged;
	bool						paused;
	UT_hash_handle				hh;
} tHashSelectorEntry;

// implementation CCTimer

CCTimer::CCTimer()
: m_pfnSelector(NULL)
, m_fInterval(0.0f)
, m_pTarget(NULL)
, m_fElapsed(0.0f)
, m_nScriptHandler(0)
{

}

CCTimer* CCTimer::timerWithTarget(CCObject *pTarget, SEL_SCHEDULE pfnSelector)
{
	CCTimer *pTimer = new CCTimer();

	pTimer->initWithTarget(pTarget, pfnSelector);
	pTimer->autorelease();

	return pTimer;
}

CCTimer* CCTimer::timerWithTarget(CCObject *pTarget, SEL_SCHEDULE pfnSelector, ccTime fSeconds)
{
	CCTimer *pTimer = new CCTimer();

	pTimer->initWithTarget(pTarget, pfnSelector, fSeconds);
	pTimer->autorelease();

	return pTimer;
}

CCTimer* CCTimer::timerWithScriptHandler(int nHandler, ccTime fSeconds)
{
	CCTimer *pTimer = new CCTimer();

    pTimer->initWithScriptHandler(nHandler, fSeconds);
	pTimer->autorelease();

	return pTimer;
}

bool CCTimer::initWithScriptHandler(int nHandler, ccTime fSeconds)
{
    m_nScriptHandler = nHandler;
	m_fElapsed = -1;
    m_fInterval = fSeconds;

	return true;
}

bool CCTimer::initWithTarget(CCObject *pTarget, SEL_SCHEDULE pfnSelector)
{
    return initWithTarget(pTarget, pfnSelector, 0);
}

bool CCTimer::initWithTarget(CCObject *pTarget, SEL_SCHEDULE pfnSelector, ccTime fSeconds)
{
	m_pTarget = pTarget;
	m_pfnSelector = pfnSelector;
	m_fElapsed = -1;
	m_fInterval = fSeconds;

	return true;
}

void CCTimer::update(ccTime dt)
{
	if (m_fElapsed == -1)
	{
		m_fElapsed = 0;
	}
	else
	{
		m_fElapsed += dt;
	}

	if (m_fElapsed >= m_fInterval)
	{
        if (0 != m_pfnSelector)
		{
			(m_pTarget->*m_pfnSelector)(m_fElapsed);
		}
        if (m_nScriptHandler)
		{
            CCScriptEngineManager::sharedManager()->getScriptEngine()->executeSchedule(m_nScriptHandler, m_fElapsed);
		}
        m_fElapsed = 0;
	}
}

// implementation of CCScheduler

static CCScheduler *pSharedScheduler;

CCScheduler::CCScheduler(void)
: m_fTimeScale(0.0)
, m_pUpdatesNegList(NULL)
, m_pUpdates0List(NULL)
, m_pUpdatesPosList(NULL)
, m_pHashForUpdates(NULL)
, m_pHashForSelectors(NULL)
, m_pCurrentTarget(NULL)
, m_bCurrentTargetSalvaged(false)
, m_pScriptHandlerEntries(NULL)
{
	CCAssert(pSharedScheduler == NULL, "");
}

CCScheduler::~CCScheduler(void)
{
	unscheduleAllSelectors();

	pSharedScheduler = NULL;
    CC_SAFE_RELEASE(m_pScriptHandlerEntries);
}

CCScheduler* CCScheduler::sharedScheduler(void)
{
	if (! pSharedScheduler)
	{
		pSharedScheduler = new CCScheduler();
		pSharedScheduler->init();
	}

	return pSharedScheduler;
}

bool CCScheduler::init(void)
{
	m_fTimeScale = 1.0f;

	// used to trigger CCTimer#update
	// m_pfnUpdateSelector = &CCScheduler::update;
	// impMethod = (TICK_IMP) [CCTimer instanceMethodForSelector:updateSelector];

	// updates with priority
	m_pUpdates0List = NULL;
	m_pUpdatesNegList = NULL;
	m_pUpdatesPosList = NULL;
	m_pHashForUpdates = NULL;

	// selectors with interval
	m_pCurrentTarget = NULL;
    m_bCurrentTargetSalvaged = false;
	m_pHashForSelectors = NULL;
	m_bUpdateHashLocked = false;

	return true;
}

void CCScheduler::removeHashElement(_hashSelectorEntry *pElement)
{
	ccArrayFree(pElement->timers);
	pElement->target->release();
	pElement->target = NULL;
	HASH_DEL(m_pHashForSelectors, pElement);
	free(pElement);
}

void CCScheduler::scheduleSelector(SEL_SCHEDULE pfnSelector, CCObject *pTarget, float fInterval, bool bPaused)
{
	CCAssert(pfnSelector, "");
	CCAssert(pTarget, "");

	tHashSelectorEntry *pElement = NULL;
	HASH_FIND_INT(m_pHashForSelectors, &pTarget, pElement);

	if (! pElement)
	{
		pElement = (tHashSelectorEntry *)calloc(sizeof(*pElement), 1);
		pElement->target = pTarget;
		if (pTarget)
		{
		    pTarget->retain();
		}
		HASH_ADD_INT(m_pHashForSelectors, target, pElement);

		// Is this the 1st element ? Then set the pause level to all the selectors of this target
		pElement->paused = bPaused;
	}
	else
	{
		CCAssert(pElement->paused == bPaused, "");
	}

	if (pElement->timers == NULL)
	{
		pElement->timers = ccArrayNew(10);
	}
	else
	{
		for (unsigned int i = 0; i < pElement->timers->num; ++i)
		{
			CCTimer *timer = (CCTimer*)pElement->timers->arr[i];

			if (pfnSelector == timer->m_pfnSelector)
			{
				CCLOG("CCSheduler#scheduleSelector. Selector already scheduled.");
				timer->m_fInterval = fInterval;
				return;
			}
		}
		ccArrayEnsureExtraCapacity(pElement->timers, 1);
	}

	CCTimer *pTimer = new CCTimer();
	pTimer->initWithTarget(pTarget, pfnSelector, fInterval);
	ccArrayAppendObject(pElement->timers, pTimer);
	pTimer->release();
}

void CCScheduler::unscheduleSelector(SEL_SCHEDULE pfnSelector, CCObject *pTarget)
{
	// explicity handle nil arguments when removing an object
	if (pTarget == 0 || pfnSelector == 0)
	{
		return;
	}

	//CCAssert(pTarget);
	//CCAssert(pfnSelector);

	tHashSelectorEntry *pElement = NULL;
	HASH_FIND_INT(m_pHashForSelectors, &pTarget, pElement);

	if (pElement)
	{
		for (unsigned int i = 0; i < pElement->timers->num; ++i)
		{
			CCTimer *pTimer = (CCTimer*)(pElement->timers->arr[i]);

			if (pfnSelector == pTimer->m_pfnSelector)
			{
				if (pTimer == pElement->currentTimer && (! pElement->currentTimerSalvaged))
				{
					pElement->currentTimer->retain();
					pElement->currentTimerSalvaged = true;
				}

				ccArrayRemoveObjectAtIndex(pElement->timers, i );

				// update timerIndex in case we are in tick:, looping over the actions
				if (pElement->timerIndex >= i)
				{
					pElement->timerIndex--;
				}

				if (pElement->timers->num == 0)
				{
					if (m_pCurrentTarget == pElement)
					{
						m_bCurrentTargetSalvaged = true;
					}
					else
					{
						removeHashElement(pElement);
					}
				}

				return;
			}
		}
	}
}

void CCScheduler::priorityIn(tListEntry **ppList, CCObject *pTarget, int nPriority, bool bPaused)
{
	tListEntry *pListElement = (tListEntry *)malloc(sizeof(*pListElement));

	pListElement->target = pTarget;
	pListElement->priority = nPriority;
	pListElement->paused = bPaused;
	pListElement->next = pListElement->prev = NULL;
	pListElement->markedForDeletion = false;

	// empey list ?
	if (! *ppList)
	{
		DL_APPEND(*ppList, pListElement);
	}
	else
	{
		bool bAdded = false;

		for (tListEntry *pElement = *ppList; pElement; pElement = pElement->next)
		{
			if (nPriority < pElement->priority)
			{
				if (pElement == *ppList)
				{
					DL_PREPEND(*ppList, pListElement);
				}
				else
				{
					pListElement->next = pElement;
					pListElement->prev = pElement->prev;

					pElement->prev->next = pListElement;
					pElement->prev = pListElement;
				}

				bAdded = true;
				break;
			}
		}

		// Not added? priority has the higher value. Append it.
		if (! bAdded)
		{
			DL_APPEND(*ppList, pListElement);
		}
	}

	// update hash entry for quick access
	tHashUpdateEntry *pHashElement = (tHashUpdateEntry *)calloc(sizeof(*pHashElement), 1);
	pHashElement->target = pTarget;
	pTarget->retain();
	pHashElement->list = ppList;
	pHashElement->entry = pListElement;
	HASH_ADD_INT(m_pHashForUpdates, target, pHashElement);
}

void CCScheduler::appendIn(_listEntry **ppList, CCObject *pTarget, bool bPaused)
{
	tListEntry *pListElement = (tListEntry *)malloc(sizeof(*pListElement));

	pListElement->target = pTarget;
	pListElement->paused = bPaused;
	pListElement->markedForDeletion = false;

	DL_APPEND(*ppList, pListElement);

	// update hash entry for quicker access
	tHashUpdateEntry *pHashElement = (tHashUpdateEntry *)calloc(sizeof(*pHashElement), 1);
	pHashElement->target = pTarget;
	pTarget->retain();
	pHashElement->list = ppList;
	pHashElement->entry = pListElement;
	HASH_ADD_INT(m_pHashForUpdates, target, pHashElement);
}

void CCScheduler::scheduleUpdateForTarget(CCObject *pTarget, int nPriority, bool bPaused)
{

	tHashUpdateEntry *pHashElement = NULL;
	HASH_FIND_INT(m_pHashForUpdates, &pTarget, pHashElement);
	if (pHashElement)
	{
#if COCOS2D_DEBUG >= 1
		CCAssert(pHashElement->entry->markedForDeletion,"");
#endif
		// TODO: check if priority has changed!

		pHashElement->entry->markedForDeletion = false;
		return;
	}

	// most of the updates are going to be 0, that's way there
	// is an special list for updates with priority 0
	if (nPriority == 0)
	{
		appendIn(&m_pUpdates0List, pTarget, bPaused);
	} else
	if (nPriority < 0)
	{
		priorityIn(&m_pUpdatesNegList, pTarget, nPriority, bPaused);
	}
	else
	{
		// priority > 0
		priorityIn(&m_pUpdatesPosList, pTarget, nPriority, bPaused);
	}
}

void CCScheduler::removeUpdateFromHash(struct _listEntry *entry)
{
	tHashUpdateEntry *element = NULL;

	HASH_FIND_INT(m_pHashForUpdates, &entry->target, element);
	if (element)
	{
		// list entry
		DL_DELETE(*element->list, element->entry);
		free(element->entry);

		// hash entry
		element->target->release();
		HASH_DEL(m_pHashForUpdates, element);
		free(element);
	}
}

void CCScheduler::unscheduleUpdateForTarget(const CCObject *pTarget)
{
	if (pTarget == NULL)
	{
		return;
	}

	tHashUpdateEntry *pElement = NULL;
	HASH_FIND_INT(m_pHashForUpdates, &pTarget, pElement);
	if (pElement)
	{
		if (m_bUpdateHashLocked)
		{
			pElement->entry->markedForDeletion = true;
		}
		else
		{
			this->removeUpdateFromHash(pElement->entry);
		}
	}
}

void CCScheduler::unscheduleAllSelectors(void)
{
	// Custom Selectors
    tHashSelectorEntry *pElement = NULL;
	tHashSelectorEntry *pNextElement = NULL;
	for (pElement = m_pHashForSelectors; pElement != NULL;)
	{
		// pElement may be removed in unscheduleAllSelectorsForTarget
		pNextElement = (tHashSelectorEntry *)pElement->hh.next;
		unscheduleAllSelectorsForTarget(pElement->target);

        pElement = pNextElement;
	}

	// Updates selectors
	tListEntry *pEntry, *pTmp;
	DL_FOREACH_SAFE(m_pUpdates0List, pEntry, pTmp)
	{
		unscheduleUpdateForTarget(pEntry->target);
	}
	DL_FOREACH_SAFE(m_pUpdatesNegList, pEntry, pTmp)
	{
        unscheduleUpdateForTarget(pEntry->target);
	}
	DL_FOREACH_SAFE(m_pUpdatesPosList, pEntry, pTmp)
	{
        unscheduleUpdateForTarget(pEntry->target);
	}

    if (m_pScriptHandlerEntries)
    {
        m_pScriptHandlerEntries->removeAllObjects();
    }
}

void CCScheduler::unscheduleAllSelectorsForTarget(CCObject *pTarget)
{
	// explicit NULL handling
	if (pTarget == NULL)
	{
		return;
	}

	// Custom Selectors
	tHashSelectorEntry *pElement = NULL;
	HASH_FIND_INT(m_pHashForSelectors, &pTarget, pElement);

	if (pElement)
	{
		if (ccArrayContainsObject(pElement->timers, pElement->currentTimer)
			&& (! pElement->currentTimerSalvaged))
		{
			pElement->currentTimer->retain();
			pElement->currentTimerSalvaged = true;
		}
		ccArrayRemoveAllObjects(pElement->timers);

		if (m_pCurrentTarget == pElement)
		{
			m_bCurrentTargetSalvaged = true;
		}
		else
		{
			removeHashElement(pElement);
		}
	}

	// update selector
	unscheduleUpdateForTarget(pTarget);
}

unsigned int CCScheduler::scheduleScriptFunc(int nHandler, ccTime fInterval, bool bPaused)
{
    CCSchedulerScriptHandlerEntry* pEntry = CCSchedulerScriptHandlerEntry::entryWithHandler(nHandler, fInterval, bPaused);
    if (!m_pScriptHandlerEntries)
    {
        m_pScriptHandlerEntries = CCArray::arrayWithCapacity(20);
        m_pScriptHandlerEntries->retain();
    }
    m_pScriptHandlerEntries->addObject(pEntry);
    return pEntry->getEntryID();
}

void CCScheduler::unscheduleScriptEntry(unsigned int uScheduleScriptEntryID)
{
    for (int i = m_pScriptHandlerEntries->count() - 1; i >= 0; i--)
    {
        CCSchedulerScriptHandlerEntry* pEntry = static_cast<CCSchedulerScriptHandlerEntry*>(m_pScriptHandlerEntries->objectAtIndex(i));
        if (pEntry->getEntryID() == uScheduleScriptEntryID)
        {
            pEntry->markedForDeletion();
            break;
        }
    }
}

void CCScheduler::resumeTarget(CCObject *pTarget)
{
	CCAssert(pTarget != NULL, "");

	// custom selectors
	tHashSelectorEntry *pElement = NULL;
	HASH_FIND_INT(m_pHashForSelectors, &pTarget, pElement);
	if (pElement)
	{
		pElement->paused = false;
	}

	// update selector
	tHashUpdateEntry *pElementUpdate = NULL;
	HASH_FIND_INT(m_pHashForUpdates, &pTarget, pElementUpdate);
	if (pElementUpdate)
	{
		CCAssert(pElementUpdate->entry != NULL, "");
		pElementUpdate->entry->paused = false;
	}
}

void CCScheduler::pauseTarget(CCObject *pTarget)
{
	CCAssert(pTarget != NULL, "");

	// custom selectors
	tHashSelectorEntry *pElement = NULL;
	HASH_FIND_INT(m_pHashForSelectors, &pTarget, pElement);
	if (pElement)
	{
		pElement->paused = true;
	}

	// update selector
	tHashUpdateEntry *pElementUpdate = NULL;
	HASH_FIND_INT(m_pHashForUpdates, &pTarget, pElementUpdate);
	if (pElementUpdate)
	{
		CCAssert(pElementUpdate->entry != NULL, "");
		pElementUpdate->entry->paused = true;
	}
}

bool CCScheduler::isTargetPaused(CCObject *pTarget)
{
    CCAssert( pTarget != NULL, "target must be non nil" );

    // Custom selectors
    tHashSelectorEntry *pElement = NULL;
    HASH_FIND_INT(m_pHashForSelectors, &pTarget, pElement);
    if( pElement )
    {
        return pElement->paused;
    }
    return false;  // should never get here
}

// main loop
void CCScheduler::tick(ccTime dt)
{
	m_bUpdateHashLocked = true;

	if (m_fTimeScale != 1.0f)
	{
		dt *= m_fTimeScale;
	}

	// Iterate all over the Updates selectors
	tListEntry *pEntry, *pTmp;

	// updates with priority < 0
	DL_FOREACH_SAFE(m_pUpdatesNegList, pEntry, pTmp)
	{
		if ((! pEntry->paused) && (! pEntry->markedForDeletion))
		{
			pEntry->target->update(dt);
		}
	}

	// updates with priority == 0
	DL_FOREACH_SAFE(m_pUpdates0List, pEntry, pTmp)
	{
		if ((! pEntry->paused) && (! pEntry->markedForDeletion))
		{
			pEntry->target->update(dt);
		}
	}

	// updates with priority > 0
	DL_FOREACH_SAFE(m_pUpdatesPosList, pEntry, pTmp)
	{
		if ((! pEntry->paused) && (! pEntry->markedForDeletion))
		{
			pEntry->target->update(dt);
		}
	}

	// Interate all over the custom selectors
	for (tHashSelectorEntry *elt = m_pHashForSelectors; elt != NULL; )
	{
		m_pCurrentTarget = elt;
		m_bCurrentTargetSalvaged = false;

		if (! m_pCurrentTarget->paused)
		{
			// The 'timers' array may change while inside this loop
			for (elt->timerIndex = 0; elt->timerIndex < elt->timers->num; ++(elt->timerIndex))
			{
				elt->currentTimer = (CCTimer*)(elt->timers->arr[elt->timerIndex]);
				elt->currentTimerSalvaged = false;

				elt->currentTimer->update(dt);

				if (elt->currentTimerSalvaged)
				{
					// The currentTimer told the remove itself. To prevent the timer from
					// accidentally deallocating itself before finishing its step, we retained
					// it. Now that step is done, it's safe to release it.
					elt->currentTimer->release();
				}

				elt->currentTimer = NULL;
			}
		}

		// elt, at this moment, is still valid
		// so it is safe to ask this here (issue #490)
		elt = (tHashSelectorEntry *)elt->hh.next;

		// only delete currentTarget if no actions were scheduled during the cycle (issue #481)
		if (m_bCurrentTargetSalvaged && m_pCurrentTarget->timers->num == 0)
		{
			removeHashElement(m_pCurrentTarget);
		}
	}

    // Interate all over the script callbacks
    if (m_pScriptHandlerEntries)
    {
        for (int i = m_pScriptHandlerEntries->count() - 1; i >= 0; i--)
        {
            CCSchedulerScriptHandlerEntry* pEntry = static_cast<CCSchedulerScriptHandlerEntry*>(m_pScriptHandlerEntries->objectAtIndex(i));
            if (pEntry->isMarkedForDeletion())
            {
                m_pScriptHandlerEntries->removeObjectAtIndex(i);
            }
            else if (!pEntry->isPaused())
            {
                pEntry->getTimer()->update(dt);
            }
        }
    }

	// delete all updates that are morked for deletion
	// updates with priority < 0
	DL_FOREACH_SAFE(m_pUpdatesNegList, pEntry, pTmp)
	{
		if (pEntry->markedForDeletion)
		{
			this->removeUpdateFromHash(pEntry);
		}
	}

	// updates with priority == 0
	DL_FOREACH_SAFE(m_pUpdates0List, pEntry, pTmp)
	{
		if (pEntry->markedForDeletion)
		{
			this->removeUpdateFromHash(pEntry);
		}
	}

	// updates with priority > 0
	DL_FOREACH_SAFE(m_pUpdatesPosList, pEntry, pTmp)
	{
		if (pEntry->markedForDeletion)
		{
			this->removeUpdateFromHash(pEntry);
		}
	}

	m_bUpdateHashLocked = false;

	m_pCurrentTarget = NULL;
		}

void CCScheduler::purgeSharedScheduler(void)
{
	pSharedScheduler->release();
	pSharedScheduler = NULL;
}
}//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 "CCAction.h"
#include "CCActionInterval.h"
#include "CCNode.h"
#include "CCPointExtension.h"
#include "CCDirector.h"
#include "CCZone.h"

namespace   cocos2d {
//
// Action Base Class
//

CCAction::CCAction()
:m_pOriginalTarget(NULL)
,m_pTarget(NULL)
,m_nTag(kCCActionTagInvalid)
{
}
CCAction::~CCAction()
{
	CCLOGINFO("cocos2d: deallocing");
}
CCAction * CCAction::action()
{
	CCAction * pRet = new CCAction();
	pRet->autorelease();
	return pRet;
}

char * CCAction::description()
{
	char *ret = new char[100] ;
	sprintf(ret,"<CCAction | Tag = %d>", m_nTag);
	return ret;
}
CCObject* CCAction::copyWithZone(CCZone *pZone)
{
	CCZone *pNewZone = NULL;
	CCAction *pRet = NULL;
	if (pZone && pZone->m_pCopyObject)
	{
		pRet = (CCAction*)(pZone->m_pCopyObject);
	}
	else
	{
		pRet = new CCAction();
		pZone = pNewZone = new CCZone(pRet);
	}
	//copy member data
	pRet->m_nTag = m_nTag;
	CC_SAFE_DELETE(pNewZone);
	return pRet;
}

void CCAction::startWithTarget(CCNode *aTarget)
{
	m_pOriginalTarget = m_pTarget = aTarget;
}

void CCAction::stop()
{
	m_pTarget = NULL;
}

bool CCAction::isDone()
{
	return true;
}

void CCAction::step(ccTime dt)
{
    CC_UNUSED_PARAM(dt);
	CCLOG("[Action step]. override me");
}

void CCAction::update(ccTime time)
{
    CC_UNUSED_PARAM(time);
	CCLOG("[Action update]. override me");
}

//
// FiniteTimeAction
//

CCFiniteTimeAction *CCFiniteTimeAction::reverse()
{
	CCLOG("cocos2d: FiniteTimeAction#reverse: Implement me");
	return NULL;
}

//
// Speed
//
CCSpeed::~CCSpeed()
{
	CC_SAFE_RELEASE(m_pInnerAction);
}

CCSpeed * CCSpeed::actionWithAction(CCActionInterval *pAction, float fRate)
{
	CCSpeed *pRet = new CCSpeed();
	if (pRet && pRet->initWithAction(pAction, fRate))
	{
		pRet->autorelease();
		return pRet;
	}
	CC_SAFE_DELETE(pRet)
	return NULL;
}

bool CCSpeed::initWithAction(CCActionInterval *pAction, float fRate)
{
	CCAssert(pAction != NULL, "");
	pAction->retain();
	m_pInnerAction = pAction;
	m_fSpeed = fRate;
	return true;
}

CCObject *CCSpeed::copyWithZone(CCZone *pZone)
{
	CCZone* pNewZone = NULL;
	CCSpeed* pRet = NULL;
	if(pZone && pZone->m_pCopyObject) //in case of being called at sub class
	{
		pRet = (CCSpeed*)(pZone->m_pCopyObject);
	}
	else
	{
		pRet = new CCSpeed();
		pZone = pNewZone = new CCZone(pRet);
	}
	CCAction::copyWithZone(pZone);

	pRet->initWithAction( (CCActionInterval*)(m_pInnerAction->copy()->autorelease()) , m_fSpeed );

	CC_SAFE_DELETE(pNewZone);
	return pRet;
}

void CCSpeed::startWithTarget(CCNode* pTarget)
{
	CCAction::startWithTarget(pTarget);
	m_pInnerAction->startWithTarget(pTarget);
}

void CCSpeed::stop()
{
	m_pInnerAction->stop();
	CCAction::stop();
}

void CCSpeed::step(ccTime dt)
{
    m_pInnerAction->step(dt * m_fSpeed);
}

bool CCSpeed::isDone()
{
	return m_pInnerAction->isDone();
}

CCActionInterval *CCSpeed::reverse()
{
	 return (CCActionInterval*)(CCSpeed::actionWithAction(m_pInnerAction->reverse(), m_fSpeed));
}

void CCSpeed::setInnerAction(CCActionInterval *pAction)
{
	if (m_pInnerAction != pAction)
	{
		CC_SAFE_RELEASE(m_pInnerAction);
		m_pInnerAction = pAction;
		CC_SAFE_RETAIN(m_pInnerAction);
	}
}

//
// Follow
//
CCFollow::~CCFollow()
{
	CC_SAFE_RELEASE(m_pobFollowedNode);
}

CCFollow *CCFollow::actionWithTarget(CCNode *pFollowedNode)
{
	CCFollow *pRet = new CCFollow();
	if (pRet && pRet->initWithTarget(pFollowedNode))
	{
		pRet->autorelease();
		return pRet;
	}
	CC_SAFE_DELETE(pRet)
	return NULL;
}
CCFollow *CCFollow::actionWithTarget(CCNode *pFollowedNode, const CCRect& rect)
{
	CCFollow *pRet = new CCFollow();
	if (pRet && pRet->initWithTarget(pFollowedNode, rect))
	{
		pRet->autorelease();
		return pRet;
	}
	CC_SAFE_DELETE(pRet)
	return NULL;
}

bool CCFollow::initWithTarget(CCNode *pFollowedNode)
{
	CCAssert(pFollowedNode != NULL, "");
	pFollowedNode->retain();
	m_pobFollowedNode = pFollowedNode;
	m_bBoundarySet = false;
	m_bBoundaryFullyCovered = false;

	CCSize winSize = CCDirector::sharedDirector()->getWinSize();
	m_obFullScreenSize = CCPointMake(winSize.width, winSize.height);
	m_obHalfScreenSize = ccpMult(m_obFullScreenSize, 0.5f);
	return true;
}

bool CCFollow::initWithTarget(CCNode *pFollowedNode, const CCRect& rect)
{
	CCAssert(pFollowedNode != NULL, "");
	pFollowedNode->retain();
	m_pobFollowedNode = pFollowedNode;
	m_bBoundarySet = true;
	m_bBoundaryFullyCovered = false;

	CCSize winSize = CCDirector::sharedDirector()->getWinSize();
	m_obFullScreenSize = CCPointMake(winSize.width, winSize.height);
	m_obHalfScreenSize = ccpMult(m_obFullScreenSize, 0.5f);

	m_fLeftBoundary = -((rect.origin.x+rect.size.width) - m_obFullScreenSize.x);
	m_fRightBoundary = -rect.origin.x ;
	m_fTopBoundary = -rect.origin.y;
	m_fBottomBoundary = -((rect.origin.y+rect.size.height) - m_obFullScreenSize.y);

	if(m_fRightBoundary < m_fLeftBoundary)
	{
		// screen width is larger than world's boundary width
		//set both in the middle of the world
		m_fRightBoundary = m_fLeftBoundary = (m_fLeftBoundary + m_fRightBoundary) / 2;
	}
	if(m_fTopBoundary < m_fBottomBoundary)
	{
		// screen width is larger than world's boundary width
		//set both in the middle of the world
		m_fTopBoundary = m_fBottomBoundary = (m_fTopBoundary + m_fBottomBoundary) / 2;
	}

	if( (m_fTopBoundary == m_fBottomBoundary) && (m_fLeftBoundary == m_fRightBoundary) )
	{
		m_bBoundaryFullyCovered = true;
	}
	return true;
}
CCObject *CCFollow::copyWithZone(CCZone *pZone)
{
	CCZone *pNewZone = NULL;
	CCFollow *pRet = NULL;
	if(pZone && pZone->m_pCopyObject) //in case of being called at sub class
	{
		pRet = (CCFollow*)(pZone->m_pCopyObject);
	}
	else
	{
		pRet = new CCFollow();
		pZone = pNewZone = new CCZone(pRet);
	}
	CCAction::copyWithZone(pZone);
	// copy member data
	pRet->m_nTag = m_nTag;
	CC_SAFE_DELETE(pNewZone);
	return pRet;
}
void CCFollow::step(ccTime dt)
{
    CC_UNUSED_PARAM(dt);

	if(m_bBoundarySet)
	{
		// whole map fits inside a single screen, no need to modify the position - unless map boundaries are increased
		if(m_bBoundaryFullyCovered)
			return;

		CCPoint tempPos = ccpSub( m_obHalfScreenSize, m_pobFollowedNode->getPosition());

		m_pTarget->setPosition(ccp(clampf(tempPos.x, m_fLeftBoundary, m_fRightBoundary),
								   clampf(tempPos.y, m_fBottomBoundary, m_fTopBoundary)));
	}
	else
	{
		m_pTarget->setPosition(ccpSub(m_obHalfScreenSize, m_pobFollowedNode->getPosition()));
	}
}

bool CCFollow::isDone()
{
	return ( !m_pobFollowedNode->getIsRunning() );
}
void CCFollow::stop()
{
	m_pTarget = NULL;
	CCAction::stop();
}

}//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 "CCActionCamera.h"
#include "CCNode.h"
#include "CCCamera.h"
#include "CCStdC.h"

namespace cocos2d{
	//
	// CameraAction
	//
	void CCActionCamera::startWithTarget(CCNode *pTarget)
	{
		CCActionInterval::startWithTarget(pTarget);

		CCCamera *camera = pTarget->getCamera();
		camera->getCenterXYZ(&m_fCenterXOrig, &m_fCenterYOrig, &m_fCenterZOrig);
		camera->getEyeXYZ(&m_fEyeXOrig, &m_fEyeYOrig, &m_fEyeZOrig);
		camera->getUpXYZ(&m_fUpXOrig, &m_fUpYOrig, &m_fUpZOrig);
	}

	CCActionInterval * CCActionCamera::reverse()
	{
		return CCReverseTime::actionWithAction(this);
	}
	//
	// CCOrbitCamera
	//
	CCOrbitCamera * CCOrbitCamera::actionWithDuration(float t, float radius, float deltaRadius, float angleZ, float deltaAngleZ, float angleX, float deltaAngleX)
	{
		CCOrbitCamera * pRet = new CCOrbitCamera();
		if(pRet->initWithDuration(t, radius, deltaRadius, angleZ, deltaAngleZ, angleX, deltaAngleX))
		{
			pRet->autorelease();
			return pRet;
		}
		CC_SAFE_DELETE(pRet);
		return NULL;
	}

	CCObject * CCOrbitCamera::copyWithZone(CCZone *pZone)
	{
		CCZone* pNewZone = NULL;
		CCOrbitCamera* pRet = NULL;
		if(pZone && pZone->m_pCopyObject) //in case of being called at sub class
			pRet = (CCOrbitCamera*)(pZone->m_pCopyObject);
		else
		{
			pRet = new CCOrbitCamera();
			pZone = pNewZone = new CCZone(pRet);
		}

		CCActionInterval::copyWithZone(pZone);

		pRet->initWithDuration(m_fDuration, m_fRadius, m_fDeltaRadius, m_fAngleZ, m_fDeltaAngleZ, m_fAngleX, m_fDeltaAngleX);

		CC_SAFE_DELETE(pNewZone);
		return pRet;
	}

	bool CCOrbitCamera::initWithDuration(float t, float radius, float deltaRadius, float angleZ, float deltaAngleZ, float angleX, float deltaAngleX)
	{
		if ( CCActionInterval::initWithDuration(t) )
		{
			m_fRadius = radius;
			m_fDeltaRadius = deltaRadius;
			m_fAngleZ = angleZ;
			m_fDeltaAngleZ = deltaAngleZ;
			m_fAngleX = angleX;
			m_fDeltaAngleX = deltaAngleX;

			m_fRadDeltaZ = (CGFloat)CC_DEGREES_TO_RADIANS(deltaAngleZ);
			m_fRadDeltaX = (CGFloat)CC_DEGREES_TO_RADIANS(deltaAngleX);
			return true;
		}
		return false;
	}

	void CCOrbitCamera::startWithTarget(CCNode *pTarget)
	{
		CCActionInterval::startWithTarget(pTarget);
		float r, zenith, azimuth;
		this->sphericalRadius(&r, &zenith, &azimuth);
		if( isnan(m_fRadius) )
			m_fRadius = r;
		if( isnan(m_fAngleZ) )
			m_fAngleZ = (CGFloat)CC_RADIANS_TO_DEGREES(zenith);
		if( isnan(m_fAngleX) )
			m_fAngleX = (CGFloat)CC_RADIANS_TO_DEGREES(azimuth);

		m_fRadZ = (CGFloat)CC_DEGREES_TO_RADIANS(m_fAngleZ);
		m_fRadX = (CGFloat)CC_DEGREES_TO_RADIANS(m_fAngleX);
	}

	void CCOrbitCamera::update(ccTime dt)
	{
		float r = (m_fRadius + m_fDeltaRadius * dt) * CCCamera::getZEye();
		float za = m_fRadZ + m_fRadDeltaZ * dt;
		float xa = m_fRadX + m_fRadDeltaX * dt;

		float i = sinf(za) * cosf(xa) * r + m_fCenterXOrig;
		float j = sinf(za) * sinf(xa) * r + m_fCenterYOrig;
		float k = cosf(za) * r + m_fCenterZOrig;

		m_pTarget->getCamera()->setEyeXYZ(i,j,k);
	}

	void CCOrbitCamera::sphericalRadius(float *newRadius, float *zenith, float *azimuth)
	{
		float ex, ey, ez, cx, cy, cz, x, y, z;
		float r; // radius
		float s;

		CCCamera* pCamera = m_pTarget->getCamera();
		pCamera->getEyeXYZ(&ex, &ey, &ez);
		pCamera->getCenterXYZ(&cx, &cy, &cz);

		x = ex-cx;
		y = ey-cy;
		z = ez-cz;

		r = sqrtf( powf(x,2) + powf(y,2) + powf(z,2));
		s = sqrtf( powf(x,2) + powf(y,2));
		if( s == 0.0f )
			s = FLT_EPSILON;
		if(r==0.0f)
			r = FLT_EPSILON;

		*zenith = acosf( z/r);
		if( x < 0 )
			*azimuth= (CGFloat)M_PI - asinf(y/s);
		else
			*azimuth = asinf(y/s);

		*newRadius = r / CCCamera::getZEye();
	}
} // namespace cocos2d