Browse Source

1496438226

capellaresumo 7 years ago
parent
commit
fb9fb8ab84
100 changed files with 32689 additions and 1 deletions
  1. 2 1
      .gitignore
  2. 1385 0
      cocos2d/AUTHORS
  3. 2090 0
      cocos2d/CHANGELOG
  4. 131 0
      cocos2d/CMakeLists.txt
  5. 86 0
      cocos2d/CONTRIBUTING.md
  6. 40 0
      cocos2d/README.cmake
  7. 337 0
      cocos2d/README.md
  8. 95 0
      cocos2d/cmake/AndroidNdkGdb.cmake
  9. 58 0
      cocos2d/cmake/AndroidNdkModules.cmake
  10. 2 0
      cocos2d/cmake/BuildHelpers.CMakeLists.txt
  11. 154 0
      cocos2d/cmake/Modules/BuildModules.cmake
  12. 160 0
      cocos2d/cmake/Modules/CMakeParseArguments.cmake
  13. 163 0
      cocos2d/cmake/Modules/CocosBuildHelpers.cmake
  14. 220 0
      cocos2d/cmake/Modules/CocosUsePrebuiltLibs.cmake
  15. 86 0
      cocos2d/cmake/Modules/FindCURL.cmake
  16. 79 0
      cocos2d/cmake/Modules/FindChipmunk.cmake
  17. 51 0
      cocos2d/cmake/Modules/FindFMOD.cmake
  18. 17 0
      cocos2d/cmake/Modules/FindFontconfig.cmake
  19. 168 0
      cocos2d/cmake/Modules/FindFreetype.cmake
  20. 156 0
      cocos2d/cmake/Modules/FindGLFW3.cmake
  21. 56 0
      cocos2d/cmake/Modules/FindGTK3.cmake
  22. 49 0
      cocos2d/cmake/Modules/FindJPEG.cmake
  23. 60 0
      cocos2d/cmake/Modules/FindMINIZIP.cmake
  24. 17 0
      cocos2d/cmake/Modules/FindMPG123.cmake
  25. 20 0
      cocos2d/cmake/Modules/FindOgg.cmake
  26. 160 0
      cocos2d/cmake/Modules/FindPNG.cmake
  27. 351 0
      cocos2d/cmake/Modules/FindPackageHandleStandardArgs.cmake
  28. 57 0
      cocos2d/cmake/Modules/FindPackageMessage.cmake
  29. 435 0
      cocos2d/cmake/Modules/FindPkgConfig.cmake
  30. 32 0
      cocos2d/cmake/Modules/FindRecast.cmake
  31. 48 0
      cocos2d/cmake/Modules/FindSQLite3.cmake
  32. 88 0
      cocos2d/cmake/Modules/FindTIFF.cmake
  33. 51 0
      cocos2d/cmake/Modules/FindTinyXML2.cmake
  34. 29 0
      cocos2d/cmake/Modules/FindVorbis.cmake
  35. 48 0
      cocos2d/cmake/Modules/FindWEBSOCKETS.cmake
  36. 69 0
      cocos2d/cmake/Modules/FindWebP.cmake
  37. 32 0
      cocos2d/cmake/Modules/Findflatbuffers.cmake
  38. 32 0
      cocos2d/cmake/Modules/Findxxhash.cmake
  39. 81 0
      cocos2d/cmake/Modules/SelectLibraryConfigurations.cmake
  40. 54 0
      cocos2d/cmake/Modules/SelectModule.cmake
  41. 104 0
      cocos2d/cmake/Modules/SetCompilerOptions.cmake
  42. 1715 0
      cocos2d/cmake/android.toolchain.cmake
  43. 193 0
      cocos2d/cmake/ios.toolchain.cmake
  44. 318 0
      cocos2d/cocos/2d/CCAction.cpp
  45. 461 0
      cocos2d/cocos/2d/CCAction.h
  46. 246 0
      cocos2d/cocos/2d/CCActionCamera.cpp
  47. 182 0
      cocos2d/cocos/2d/CCActionCamera.h
  48. 555 0
      cocos2d/cocos/2d/CCActionCatmullRom.cpp
  49. 347 0
      cocos2d/cocos/2d/CCActionCatmullRom.h
  50. 324 0
      cocos2d/cocos/2d/CCActionEase.cpp
  51. 557 0
      cocos2d/cocos/2d/CCActionEase.h
  52. 442 0
      cocos2d/cocos/2d/CCActionGrid.cpp
  53. 445 0
      cocos2d/cocos/2d/CCActionGrid.h
  54. 731 0
      cocos2d/cocos/2d/CCActionGrid3D.cpp
  55. 619 0
      cocos2d/cocos/2d/CCActionGrid3D.h
  56. 633 0
      cocos2d/cocos/2d/CCActionInstant.cpp
  57. 556 0
      cocos2d/cocos/2d/CCActionInstant.h
  58. 2852 0
      cocos2d/cocos/2d/CCActionInterval.cpp
  59. 1685 0
      cocos2d/cocos/2d/CCActionInterval.h
  60. 503 0
      cocos2d/cocos/2d/CCActionManager.cpp
  61. 223 0
      cocos2d/cocos/2d/CCActionManager.h
  62. 132 0
      cocos2d/cocos/2d/CCActionPageTurn3D.cpp
  63. 73 0
      cocos2d/cocos/2d/CCActionPageTurn3D.h
  64. 132 0
      cocos2d/cocos/2d/CCActionProgressTimer.cpp
  65. 133 0
      cocos2d/cocos/2d/CCActionProgressTimer.h
  66. 871 0
      cocos2d/cocos/2d/CCActionTiledGrid.cpp
  67. 609 0
      cocos2d/cocos/2d/CCActionTiledGrid.h
  68. 80 0
      cocos2d/cocos/2d/CCActionTween.cpp
  69. 127 0
      cocos2d/cocos/2d/CCActionTween.h
  70. 202 0
      cocos2d/cocos/2d/CCAnimation.cpp
  71. 329 0
      cocos2d/cocos/2d/CCAnimation.h
  72. 242 0
      cocos2d/cocos/2d/CCAnimationCache.cpp
  73. 149 0
      cocos2d/cocos/2d/CCAnimationCache.h
  74. 257 0
      cocos2d/cocos/2d/CCAtlasNode.cpp
  75. 159 0
      cocos2d/cocos/2d/CCAtlasNode.h
  76. 725 0
      cocos2d/cocos/2d/CCAutoPolygon.cpp
  77. 287 0
      cocos2d/cocos/2d/CCAutoPolygon.h
  78. 542 0
      cocos2d/cocos/2d/CCCamera.cpp
  79. 340 0
      cocos2d/cocos/2d/CCCamera.h
  80. 498 0
      cocos2d/cocos/2d/CCCameraBackgroundBrush.cpp
  81. 276 0
      cocos2d/cocos/2d/CCCameraBackgroundBrush.h
  82. 367 0
      cocos2d/cocos/2d/CCClippingNode.cpp
  83. 174 0
      cocos2d/cocos/2d/CCClippingNode.h
  84. 84 0
      cocos2d/cocos/2d/CCClippingRectangleNode.cpp
  85. 117 0
      cocos2d/cocos/2d/CCClippingRectangleNode.h
  86. 152 0
      cocos2d/cocos/2d/CCComponent.cpp
  87. 94 0
      cocos2d/cocos/2d/CCComponent.h
  88. 149 0
      cocos2d/cocos/2d/CCComponentContainer.cpp
  89. 78 0
      cocos2d/cocos/2d/CCComponentContainer.h
  90. 951 0
      cocos2d/cocos/2d/CCDrawNode.cpp
  91. 370 0
      cocos2d/cocos/2d/CCDrawNode.h
  92. 447 0
      cocos2d/cocos/2d/CCDrawingPrimitives.cpp
  93. 272 0
      cocos2d/cocos/2d/CCDrawingPrimitives.h
  94. 898 0
      cocos2d/cocos/2d/CCFastTMXLayer.cpp
  95. 367 0
      cocos2d/cocos/2d/CCFastTMXLayer.h
  96. 261 0
      cocos2d/cocos/2d/CCFastTMXTiledMap.cpp
  97. 256 0
      cocos2d/cocos/2d/CCFastTMXTiledMap.h
  98. 0 0
      cocos2d/cocos/2d/CCFont.cpp
  99. 59 0
      cocos2d/cocos/2d/CCFont.h
  100. 490 0
      cocos2d/cocos/2d/CCFontAtlas.cpp

+ 2 - 1
.gitignore

@@ -18,4 +18,5 @@ tests/*/proj.android-studio/app/proguard-project.txt
 /templates/*-template-binary/
 /prebuilt/
 /*/build/
-/proj.android-studio/app/build/
+/proj.android-studio/app/build/
+/cocos2dx

+ 1385 - 0
cocos2d/AUTHORS

@@ -0,0 +1,1385 @@
+cocos2d-x authors & contributors
+
+(ordered by join time)
+
+Core Developers:
+    Ricardo Quesada
+    XiaoMing Zhang (Minggo)
+    JianHua Chen (James)
+    Zhe Wang (Walzer)
+    Hao Wu (Wu-Hao)
+    Qingkui Hu (samuele3hu)
+    Huabing Xu (dabingnn)
+    Wenhai Lin (WenhaiLin)
+    Guanghui Qu (zilongshanren)
+    Wensheng Yang (yangws)
+    Yulei Liao (dualface)
+    Huabin Ling (pandamicro)
+    Long Jiang (jianglong0156)
+    Sijie Fu (fusijie)
+
+Framework & Tools Developers:
+    Bin Zhang (natural-law)
+    LunHao Guo
+
+Web Developers:
+    Sijie Wang (VisualSJ)
+    Menghe Zhang (ZhangMenghe)
+
+3D Developers:
+    Xiao Yang (super626)
+    Yintao Hou (masterhou)
+
+Editor Support Developers:
+    Cheng Zhang (chengstory)
+    Feng Xiao (xiaofeng11)
+
+Windows Platforms Developers (Collaborators from Microsoft):
+    Dale Stammen (stammen)
+    Anniruddh (anniruddh)
+
+Community Evangelism / Programmers Guide Author:
+    Jason Slack-Moehrle (slackmoehrle)
+    
+Developers:
+    halx99(Guo Xiaodong)
+        Add ETC1 builtin alpha support.
+        Add findChild for cocos2d::utils.
+        Add script with utf-8 bom support for luabindings.
+        Add captureNode for cocos2d::utils.
+        fix AudioEngine bug for iOS, UTF8 filePath.
+        
+        
+    Rolando Abarca
+        Javascript Binding and testjs
+        
+    Squallium
+        Added ccFPSImages entity as linked resource on linux eclipse project setting.
+        Added CocosDenshion dependency to libextension project for eclipse project of linux.
+        
+    longlene
+        Improve android project creation script
+        
+    reneklacan
+        Hardware keyboard support
+    
+    liuyq
+        CCTextureAtlas::updateQuad modify for the memcpy hot spot.
+        
+    frranck 
+        adding norwegian language
+        Added "a unsupport image format!" log when creating a sprite in CCImage.cpp.
+    
+    varlucian
+        fix the bug that OnEnterTransitionDidFinish was called twice when a node is added in onEnter.
+        
+    carlomorgantinizynga
+        CCLabelTTF supports for shadow and stroke
+        Adding CCLabelTTF::createWithFontDefinition.
+        New label support.
+        
+    James Gregory (j4m3z0r, Zynga)
+        Maintainer of Emscripten port.
+        Initial Emscripten port.
+        Use browser font rendering instead of FreeType.
+        Add destructor to CCGLBufferedNode.
+        Asynchronous Image loading for Emscripten
+        
+    DarraghCoy
+        Fixed a potential crash SimpleAudioEngineOpenSL::playEffect
+        Fixed some bugs with Set class
+        Added ccDrawSolidCircle
+        Added Rect::unionWithRect
+        Fixed a memory leak in Set::removeAllObjects
+        Fixed for unaligned memory access crash in CCBReader::readFloat()
+        Fixed for loading custom fonts on iOS when referenced from a CCB file
+        Fixed CCUserDefault.cpp compiling on Android.
+        Fixed CCFileUtils 'createXXXXWithContentsOfFile' path lookup issue
+        Added CCDirector::popToSceneStackLevel(int level)
+        Fixed a bug that custom font can't be loaded correctly if using full path of filename on android
+        Fixed potential crashes in EventDispatch while using SceneGraphPriroity listeners and added helper function to check it
+        Fixed a protential crash in EventDispatch while unregistering listener right after it was registered
+        Adding an extra verification in Node's destructor
+        Added RefPtr<T> smart pointer support 
+
+    silverscania
+        Pass correct parameter to glPixelStorei when creating a texture
+
+    stari4ek
+        Fix VideoPlayer on Android ignore search paths
+        Label: Improve rendering of letter's inner shapes when outline is used
+        platform: Fixed issue that depth/stencil buffers attributes are ignored on iOS
+
+    FlagellumDei
+        Center the window correctly on windows
+
+    ggggamer
+        fixed memory leak of preloadEffect on windows
+        Some small performance improvements
+
+    CodeSnooker
+        Added Method to create a CCMenuItemToggle from a CCArray with a target selector
+
+    wagaf-d
+        Move ccpX functions to CCPoint methods and operators
+
+    sergey-shambir
+        Added CC_DISABLE_COPY macro
+        Added __attribute__(__format__()) for CCLog and CCString
+        Refactoring network extension and fixing unlikely memory leaks.
+        Adding PUT/DELETE methods for CCHttpRequest.
+        Adding project part for QtCreator.
+        Implemented pitch, pan and gain.
+        Using SDL backend instead of glfw for Linux.
+
+    savdalion 
+        Added example for russian language in TestCpp
+        Added const modifier for classes CCArray, CCObject
+        Deprecated method fixes
+
+    rodrigogolive
+        Fix broke linux build
+
+    kdejongh
+        Fix for spaces at the beginning of wrapped lines on Android
+
+    martell
+        use tinyxml2 to replace libxml2
+        Added Mingw-crt Support without breaking VS SDK
+        CMake support for windows.
+        Added support for x64 target of windows.
+        Added Dutch Language support.
+        Added clang support for Windows.
+        Cmake update and remove old scripts from build folder
+        Fixed building with system prebuilt libs on Linux
+
+    mchinen
+        fix emulator issue for OpenGL ES 2.0 on Android
+        Fix missing protocol method warning for iOS 6.0 addition
+
+    DenizPiri
+        use CCLOG to implement print() function in LUA
+
+    nickveri
+    nickkwalee
+        added some missing function for setting integer shader uniforms in CCGLProgram
+
+    biteforest
+        fix cc scale9 sprite bug
+
+    Jimmy Sambuo
+        fix the bug that SimpleAudioEngine::playEffect() and playBackgroundMusic() play twice on linux
+
+    Waiter
+        fix an error that OpenSLEngine can't load resources from SD card
+        add CCRemoveSelf action
+        Fixing a bug that CCLabelTTF setString crash on android.
+        Fixed a bug in Scheduler which may case Force Close.
+
+    billy1380
+        make CCLens3d support concave effect.
+        Adding 64bit target for Mac project.
+
+    benjamesward
+        add Portuguese and Arabic language support
+        Fixed linebreaks on Mac OSX
+
+    Victor K(fnz)
+        fix memory leak of CCTextureCache::addImageAsync() on iOS
+
+    tks2shimizu
+        add CCFloat, CCDouble and CCBool
+        Add append function for String class
+        Adding String::componentsSeparatedByString function for splitting string.
+
+    chenium
+        fix a bug that CCRenderTexture can not work when coming to foreground on Android
+
+    9re(Taro Kobayashi)
+        add Japanese language support
+
+    mingulov
+        improve the speed of accessing to files from apk
+
+    sburavtsov
+        fix for correct unscheduling and instance destruction of extensions/network/HttpClient.cpp
+
+    wenbin wang
+        add error handler when read image data using libjpeg
+        add korean language support
+        fix getDeviceModel bug in android CocosDenshion
+
+    Horcruxes
+        fix the bug that CCArray::createWithContentsOfFile() may not read file data on iOS
+
+    Hu Kaiou
+        contribute the new version of libcurl to support both armv7 & armv7s on iOS
+        fix some memory leak
+
+    ByungChoi
+         modify linux makefiles to fix compiling errors
+
+    edbartley
+         update MSVS and MAC projects to use project-relative path
+         CCControl* should not respond to touches if the control is not visible
+         Some improvements for CCScrollView and CCTableView.
+         Touch priority can't be set to the value specified by a call to CCMenu::setTouchPriority(int).
+         CCTableView crashes if a CCTableViewDelegate is not provided.
+         Fixing a bug that _realOpacity isn't assigned in CCLayerColor::initWithColor.
+         CCScrollView TouchPriority Fix
+         Add encrypted PVR.CCZ support to ZipUtils + Tests
+         Fix for broken of ccArrayGetIndexOfObject after merging this commit(076f38c).
+
+    Weeds (Andre Rudlaff)
+        Used fontconfig to enhance font rendering on linux.
+        Fixed a bug about missing horizontal alignment for Custom TTF fonts on linux.
+        Fixed a bug that the truetype fonts from resource directory can't be found on linux.
+        Fixed the size calculations for true type fonts (especially for italic fonts).
+        Added a very simple greedy line break algorithmfor true type labels.
+        Fixed font rendering crash for certain fonts on linux.
+        Fixed potential crash in CCScheduler::removeHashElement.
+        Fixed potential crash in CCSaxParser.
+        Added kResolutionFixedHeight and kResolutionFixedWidth resolution policy.
+        Use pthread mutex and condition variable instead of pthred semaphore to load image asynchronizely.
+        Fixed crash in HttpClient request on 64Bit.
+
+    Nat Weiss (iphonegamekit.com)
+        author of Mac port
+        add TMX polygon parsing
+        Properly resets the tile's Y flipping
+
+    XiaoLong Zhang (Chukong Inc)
+    Mike McGary (Zynga)
+    Di Wu (Zynga China)
+        CCBReader and cpp reflection mechanic
+
+    Angus Comrie
+        contributes cocos2d-x port of CCControlExtension.
+
+    Yannick Loriot
+        author of CCControlExtension in cocos2d-iphone.
+
+    Surith Thekkiam (folecr, Zynga)
+        contribute for Android module building
+        Simpler, correct handling of spritesheet sources for CCScale9Sprite.
+        Clean up linked libraries for android.
+        JavaScript debugger improved and bugfixed.
+        Fix flags for debugger server socket.
+        Fix flags for debugger server socket.
+        When user has built with JS Debugger support ScriptingCore will handle necessary runtime changes.
+
+    Nicolas Gramlich (nicolasgramlich, Zynga)
+        fixed CCDirector to use CCLabelBMFont instead of CCLabelTTF
+        added CCBReader (CCBI format)
+        Added cleanup and reset methods to ScriptingCore.
+        Fixed a bug in ScriptingCore::evalString not setting the outval.
+        Updated .classpath of Android project to latest ADT 22 build tool compatibility.
+
+    Rohan Kuruvilla (rohankuruvilla, Zynga)
+        Improvements to JS Bindings.
+        Synchronizing CCBReader to version 5.
+        Adding OpenGL Bindings to Javascript.
+        Fixing a bug that nested ccb-files are not positioned correctly.
+        Fixing a bug that crash when loading valid project.
+
+    Jianfeng Zou (NetDragon Inc)
+        contributes CCListView and CCTextureWatcher.
+
+    dducharme
+        author of blackberry port
+
+    ImperialPenguin
+        Added TTF support for blackberry port.
+
+    HuaXu Cai (Kongzhong Corporation)
+        author of linux port
+
+    ciaranj
+        add a build file that correctly generates LuaCocos2d.cpp
+        add a lua template
+        add particle systems to lua bindings
+        use ant to generate LuaCocos2d.cpp and lua projects
+
+    Marat Yakupov (moadib)
+        Adds ability of simulating android enter/resume background on win32
+        Adds ability of simulating android back/menu key on win32
+        Adds support for multiple background music sources to CocosDenshion for Blackberry
+
+    Eli Yukelzon (reflog)
+        add a helper method to draw filled polygons
+        improvements to CCUserDefaults
+
+    ZhuoShi Shun
+        contribute the lua binding of CocosDenshion
+
+    Jirka Fajfr
+    Chris Calm
+        authors of CCTexturePVR
+
+    RuiXiang Zhou (NetDragon)
+    XiDi Peng (NetDragon)
+    AiYu Ye (NetDragon)
+        authors of lua binding
+
+    Max Aksenov
+        author and maintainer of Airplay port
+
+    Giovanni Zito
+    Francis Styck
+        authors of Marmalade port
+
+    Mat Hopwood( Marmalade official engineer )
+        Marmalade support for gles20 branch
+
+    Carlos Sessa
+        implement the accelerometer module for Android port
+
+    James Chen(dumganhar)
+        author of Bada port
+        Fixed wrong callback setting for webview:setOnDidFailLoading in Lua.
+        Fixed life control for XMLHttpRequest.
+        Remove weak reference in ActionNode.
+        Bug fix for shouldStartLoading method, should return value from JS
+
+    Erawppa
+        implement CCNotificationCenter
+
+    YuLei Liao(dualface)
+        contribute the factor of lua binding
+
+    jreitman
+        fix the bug of asynchronous loading resources for iOS
+
+    Nat Weiss
+        minor enhancements to the Cocos2D-X codebase and Android build scripts
+
+    Qingyun Huang (greathqy)
+        implement CCHttpRequest
+
+    donaldalanmorrison
+        fix some warnings and memory leaks
+
+    Yinghui Peng(mustime)
+        use OpenSL ES to play effects
+        add TestLua sample
+
+    Dongyang Cai(John-cdy)
+        add automatically test tools
+
+    Sergey Vikhirev(BorMor)
+        Remove retina specific methods and logic.
+
+    johnangel
+        OpenGL framebuffer access violation fix.
+        Enable Windows XP support in Visual Studio 2012 Update 1.
+
+    Peter Farkas (fape)
+        contributes Marmalade port for gles20 branch
+        add Hungarian language support
+        fixed compilation errors after adding support of webp image format.
+
+    Tomoaki Shimizu (tks2shimizu)
+        Adding randomObject to CCDictionary.
+
+    Igor Zavorotkin (ivzave)
+        Adding lua support for linux platform.
+
+    Jozef Prídavok (jpridavok)
+        Adding CCEditBox implementation for Mac OSX.
+
+    tiantian20007
+        Fixing a crash for call runAnimation() in CCBAnimationManagerDelegate::completedAnimationSequenceNamed.
+        Fixing a bug that CCControl's touch priority is not set correctly; m_nDefaultTouchPriority is never used.
+        Fixing a syntax error for RENDER_IN_SUBPIXEL macro.
+        Implement CCDictionary::writeToFile().
+        Fixing a bug that unused spriteframes also need to be removed when purgeCachedData.
+        Adding a method to get duration of timeline for CCBAnimationManager class, it's easy for getting duration of animation in JSB.
+
+    xyhl515
+        Fixed a bug that CCControlSwitch::setOn(isOn,false) doesn't work.
+        Adds VS2012 Express template installing support.
+        Fixing a logical error in CCDrawNode::drawPolygon.
+        Fixing a bug that Jsb function getCPBody return type is not right.
+
+    Sergej Tatarincev (SevInf)
+        Making ScriptingCore.cpp compiled fine with C++11 on iOS.
+        Using shared NodeLoaderLibrary in CCBReader bindings.
+        CCEditBox iOS enchantments/bugfixes.
+        Support variable cell sizes in CCTableView.
+
+    ThePickleMan
+        Adding 'rotationIsDir' property to ParticleSystem.
+        DrawNode supports to draw triangle, quad bezier, cubic bezier.
+
+    Jianghua (jxhgzs)
+        Adding an additional transform for CCNode.
+
+    giginet
+        Fix CCRepeat#create is recieved bad argument on Lua binding.
+        Added a feature that CCSSceneReader can load name properties as node names.
+        Added Rect::intersectsCircle().
+
+    neokim
+        Adds 'setFont' and 'setAnchorPoint' to CCEditBox.
+        Workaround for some problems due to UITextField of CCEditBoxImplIOS is attached as a view above OpenGL view.
+        Enhance ScrollView with easing out scrolling.
+        Add scroll bar feature into ui::ScrollView.
+        Add RadioButton and RaidoButtonGroup widgets.
+        Add a setter for line width in DrawNode.
+        UI: Added a setter for line width in DrawNode
+        UI: Added ScrollViewBar for displaying a scroll bar at the side of ScrollView
+        UI: Added RadioButton widget
+        UI: Refined scroll event dispatching for ScrollView
+        platform: Fixed Android app occasionally freeze issue caused by Cocos2dxRenderer.nativeOnResume() is not called when the activity is resumed
+        Fixed an issue that list view's Magnetic::CENTER is not working well when non-bounceable.
+        Added APIs to scroll to specific item in list.
+        Added APIs to get an item in specific position like center, leftmost, rightmost, topmost and bottommost.
+        Added a feature for magnetic scrolling.
+        Merge logics of Scroll View for scroll by inertia and auto scroll into one.
+        Change PageView to derive from ListView.
+
+    Sam Clegg (sbc100)
+        Author of Native Client port.
+        Refactor linux build system and fix many warnings.
+        Fixing a bug where missing packages would cause the script to exit on linux.
+        Adding 'make run' target for linux projects.
+        Stripping newlines from log message and fixing linux library location.
+        Fixing a bug that CCPhysicsSprite was overriding only some of the getPosition methods.
+        Adding a macro USE_BOX2D to check whether to enable Box2D for linux and nacl port.
+        Adding Travis build support for linux and NaCl.
+        Logging assert messages to the console.
+        Renaming CCScriptSupport::executeAssert to CCScriptSupport::handleAssert.
+        Adding Native Client support for develop branch (cocos2d-x 3.0) and some warnings fixes.
+        Cleanup travis build scripts.
+        Refactoring emscripten building script.
+
+    Peter Young (young40)
+        Implements setVisible() for CCEditBox.
+        Fixing a bug that event will not be sent to server when paramMap parameter of logEvent function is nil in plugin-x.
+
+    csy1988525
+        Fixing a bug about display result is wrong when invoking CCControlButton:: setHighlighted.
+        fixed a bug when button's parent is hided, the button still can responce to clicked event.
+
+    Asad ur Rehman (AsadR)
+        Adding CCNotificationCenter::removeAllObservers(CCObject *target).
+
+    jedy
+        Fix of CCNode.h's document with doxygen 1.8.3 can't be generated.
+
+    whitegfx
+        Implementation of kEditBoxInputFlagSensitive setting for CCEditBoxImplIOS.
+
+    Zecken (gelldur)
+        Fixing a profiling compilation error in CCParticleBatchNode.
+        Fixing linking errors for TestCPP with libcurl on linux.
+        Fixing a bug that crash was triggered if there is not `textureFileName`section in particle plist file.
+
+    flamingo (flaming0)
+        Null pointer check in order to prevent crashes.
+        Updating spine-runtime to EsotericSoftware/spine-runtimes@5f90386.
+
+    rtissera (Romain TISSERAND)
+        Adding missing JNIEXPORT / JNICALL declarations.
+        Fix iOS 4.3 JPEG loading issue.
+
+    Yodesoft
+        Improving font rendering performance for linux platform.
+        Reducing function call in nativeInitBitmapDC to improve performance.
+        Refactoring writable path to "<user's home>/.config/<app name>" for linux platform.
+
+    sjchao
+        Fixing a display bug when a scrollView nested in another scrollView.
+
+    Éloi Rivard (azmeuk)
+        Linux OpenAL support.
+        Added some guards to prevent Eclipse to compile twice the same class.
+        Linux Eclipse projects updates
+        Refactored emscripten-build.sh, it's no longer need to be edited to make emscripten work.
+        Creation of CCDeprecated-ext.h
+        Use of a single emscripten HTML template file.
+        Added some guards in fileutils. Fixed a bug in emscripten file utils.
+        Added emscripten keyboard support
+        Clang support for Linux.
+        Multiple emscripten template support. Emscripten multiple resolutions support.
+        Toplevel Makefile refactoring.
+        Ignored files generated by cmake.
+        Added GLFW include path for Fedora.
+        Linux javascript bindings support.
+
+    elmiro
+        Correction of passed buffer size to readlink and verification of result return by readlink.
+
+    harikrishnar (Hari Krishna)
+        Wrong logic in CCArray::initWithObjects.
+        Fixing a bug that button should not get respond if its parent is invisable.
+
+    rogerzanoni
+        Fixing a linking error that libpthread and libGL libraries need to be linked on linux.
+        Fixing a compiling error of [-Werror=array-bounds] when compiling Box2dTestBed.
+
+    zhanghaojie
+        Fixing a bug that anchorPoint property of CCScale9Sprite doesn't work in CCBReader.
+
+    MarkEHenderson (Mark Henderson)
+        Fixing of variable initialization in SpriteBatchNode.
+
+    akira-cn
+        Adding response for back and menu keypad event for Android.
+
+    lgb (Oleg)
+        Fixing a compilation error for BlackBerry PlayBook.
+        Comparing float number by using epsilon and absolute difference.
+
+    jotel (Jaroslaw Lewandowski)
+        Fixing a bug that wrong type of argument signature is used in setAccelerometerIntervalJNI function.
+        Fix for broken of ccArrayGetIndexOfObject after merging this commit(076f38c).
+        Explicitly initialising CCAcceleration structure.
+        Add support to save/retrieve CCData into/from CCUserDefault.
+        Text Shadows fix
+        Solving 'black screen' on android.
+
+    MarcelBloemendaal
+        Adding secureTextEntry property to CCTextFieldTTF.
+
+    brawsome
+        Adding new macro CCB_MEMBERVARIABLEASSIGNER_GLUE_WEAK to CCBMemberVariableAssigner.h.
+        Adding CCLOG before original path is returned in CCFileUtils::fullPathForFileName to aid in debugging.
+        Optmization to ccArrayGetIndexOfObject.
+
+    sunzhuoshi
+        Adding support for javascript bytecode.
+        Fixing bad js constant names.
+
+    ptekchand (Pranav Tekchand)
+        Supporting negative node scales for CCScrollView.
+
+    coolengineer (Hojin Choi)
+        Refactoring callback selector for HttpResponse.
+
+    djh-
+        Fixing a bug that displayed color of CCDrawNode is incorrect when VAO is disabled.
+
+    acai (beingstudio)
+        Fix of null pointer access in CCBAnimationManager::getRunningSequenceName.
+
+    metalgit92
+        Adding const qualification to some CCNode's getters
+
+    Clarinexus
+        Fixing a bug that setColor and setOpacity of CCControlButton and CCScale9Sprite are broken.
+
+    Xander84
+        Fixing a bug in CCBValue::getByteValue.
+        
+    smshuja
+        Fixing a bug that pointQueryFirst returns invalid Shape when a shape is not found in JSB.
+        Fixing a bug that New PivotJoint can't access 4 parameters like in html5 version.
+        Fixing a bug that Pivotjoint constructor and pointQueryFirst in Space class will return false instead of invalid shape object.
+        
+    Carsten Sandtner (casarock)
+        Adding XMLHttpRequest support for JSB.
+        
+    Lee, Jae-Hong (pyrasis)
+        Maintainer of tizen port.
+        localStorageGetItem crashes when column text is NULL.
+        fix image bug on Android
+
+    lumendes
+        Updating spine-runtime to EsotericSoftware/spine-runtimes@5f90386.
+        
+    sunxiaoyu
+        Refactoring CCEditBox to add UITextField only when keyboard was opened, remove it when keyboard was closed.
+        
+    edwardzhou (Edward Zhou)
+        Correcting the type detecting order for Lua CCBProxy::getNodeTypeName.
+        Casting variables to their own type, and print warning info if no corresponding lua callback function instead of crash.
+        fix of WebSocket url parse error for 'ws://domain.com/websocket' pattern.
+        Fixed a bug that Websocket doesn't support send/receive data which larger than 4096 bytes.
+        Show detail class & function name in error message of lua-binding
+
+    musikov
+        Fixing a bug that missing precision when getting strokeColor and fontFillColor
+        added Turkish and Ukrainian language support
+        
+    hawkwood (Justin Hawkwood)
+        Fixing a bug that EditBox doesn't show any text if it's initialized with text.
+        Fixed a memory leak in new Audio.
+        
+    wtyqm (zhang peng)
+        Fixing a bug that ccbRootPath wasn't passed to sub ccb nodes.
+        
+    smilingpoplar (YangLe)
+        Fixing a bug that CCScale9Sprite doesn't support rotated spriteframe in atlas.
+        
+    xxuejie
+        Add namespace prefix to selector macros
+        
+    hannon235 (Chris)
+        Fixing a bug that the submenu of ExtensionTest in TestCpp can't scroll.
+        Implements a socket.io client extension and adds a test case.
+        Implements 'SIODelegate::fireEventToScript' method to integrate JSB event handling with the original native code.
+        Update socket.io network extension to correctly detect and manage connection to socket.io server versions 0.9.x-1.x
+        
+    pktangyue
+        Fixing a bug that CCScale9Sprite::setInsetLeft/XXX can't work for rotated sprite frame.
+        Fixing a bug that Color and Opacity of Scale9Sprite will not be changed when it's added to NodeRGBA and run with FadeIn/Out actions.
+        Adding *.xccheckout to gitignore.
+        
+    jllust
+        Fixing a bug that CCLabelBMFont crashes in glDrawElements of CCTextureAtlas::drawNumberOfQuads sometimes.
+        
+    Sam Gross (colesbury)
+        Ignoring formatting specifiers in JavaScript log messages.
+        Make bindings-generator supports to bind std::function argument.
+        
+    James Munro (jdmunro)
+        Added JSB support for ccpDistanceSQ.
+        
+    Rafael (rafaelx)
+        A warning fix of AL_INVALID_NAME and AL_INVALID_OPERATION in SimpleAudioEngineOpenAL.cpp.
+        
+    metalbass
+        Fixing an issue that sigslot::_connection_base# (from 0 to 8) don't have virtual destructors.
+        
+     thp
+         Port Cocos2D-X to Qt 5
+         
+    Nako Sung (nakosung)
+        Fixing a bug that wrong logic when pass an empty std::vector to WebSocket::init.
+        Exposing cc.RemoveSelf to JS.
+        exposed AssetsManager to javascript and added multiple-assetsManager support
+        
+    dotsquid
+        Fixed the crash caused by improper deletion of VBOs and VAO in ParticleSystemQuad.
+        
+    maciekczwa
+        Fixing a bug that stroke color with channel color values other than 255 doesn't take effect on android.
+        
+    zcgit
+        a potential bug fix in Layer::init.
+        
+    gkosciolek
+        Fixing a bug that observers with the same target and name but different sender are the same observer in NotificationCenter.
+
+    xbruce
+        Fixing a bug that crash appears when extending cc.ScrollView in JS.
+        Fixing a bug that cc.registerTargettedDelegate doesn't support pure js object as its target.
+        
+    elwinarens (Elwin Arens)
+        Minor spelling changes in description of CCScene.h
+        
+    signmotion (Andrey Syrokomsky)
+        Fixed some compiling-warnings (MSVC2012).
+        
+    michaelcontento
+        [Android] use onWindowFocusChanged(bool) instead of onResume()/onPause()
+        Prevent nullptr access in AssetsManager
+        [Android] re-introduce Cocos2dxHelper.runOnGLThread(Runnable)
+        [Android] added EGL_RENDERABLE_TYPE to OpenGL attributes
+        Android: add xlargeScreens="true" to supports-screens
+        Trigger onKeyReleased only after the key has been released.
+        Makes Colors are now comparable and explicit convertible
+        
+    bmanGH
+        Used gl caching functions in TexturePVR::createGLTexture()
+        Configuration of VAO in runtime
+        Added setUniformLocationWithMatrix2fv, setUniformLocationWithMatrix3fv mothed into GLProgram class
+        Fixed a bug that object which isn't in Vector would also be released when invoking Vector::eraseObject.
+        Fixed a bug that Timer::cancel always call Director::getInstance()->getScheduler() even in another Scheduler.
+        Fix crash if label's type is STRING_TEXTURE and label->sortAllChildren is called
+        
+    metadao
+        make create_project.py more pythonic and fix some typoes
+        
+    timothyqiu
+        Project creator: use absolute path for json config files
+        Documentation fixes
+        A better way to locate project creator
+        
+    rablwupei
+        Fixed a memory leak in ScriptingCore::runScript()
+        Fixed a memory leak in Spine.
+        Added support of passing array to cc.Sequence.create and cc.Spawn.create.
+        Fixed a bug that sys.localStorage.getItem() does not support non-ascii string.
+        Fixed a memory leak in XMLHttpRequest.
+        Fixed a bug that wrong convention to jsval in cccolor4f_to_jsval and cccolor3b_to_jsval.
+    
+    Keita Obo (ktaobo)
+        Avoid unnecessary object duplication for Scale9Sprite.
+        
+    jimmystar
+        Fixed a bug that cc.Scheduler.schedule(target, func) without repeat argument couldn't repeat schedule forever on device.
+        
+    XiaoLongHan (kpkhxlgy0)
+        Fixed a bug that outside of keyboard can't be responded to close keyboard when using EditBox.
+        
+    lettas
+        A fix for multi-platform template.
+        
+    HoGarfield (garfield_ho)
+        Fixed a bug that CCBReader can't play sequence automatically in JSB.
+        Could not set next animation in CCBAnimationCompleted callback.
+        Fixed missing to add JSAutoCompartment when invoking JS functions from C++.
+        CCBReader: To set anchor point to 0,0 when created by loader.
+        Potential crash when websocket connection closes.
+        
+    lite3
+        Fixed a bug that Node's anchor point was changed after being added to ScrollView.
+        Added HttpClient::sendImmediate()
+        Added operator == != for Value
+        Replace dynamic_cast to std::is_base_of in object_to_luaval
+        Added support normalize path on android
+        FileUtils: Remove old path while adding existing search path
+        
+    superrad
+        Clear NoSuchMethodError Exception when JniHelper fails to find methodID
+        
+    Nite Luo (darkdukey)
+        Added Mouse Support For Desktop Platforms.
+        
+    ledyba
+        Fixed a bug that EventListeners can't be removed sometimes.
+        Fixed a bug that the data size has to be specified when parsing XML using TinyXML.
+        Closed X display after getting DPI on Linux.
+        
+    Luis Parravicini (luisparravicini)
+        Fixed typos in create_project.py.
+        
+    xhcnb
+        Device::setAccelerometerEnabled needs to be invoked before adding ACC listener.
+        Fixed a bug that it will get wrong custom properties when use different count custom properties in CocosBuilder.
+        Correct TotalTime of ActionObject
+        
+    bopohaa
+        Fixed a bug that Webp test crashes.
+        
+    lajos
+        FontTest isn't rendered correctly with custom TTF font on Mac platform.
+        
+    hulefei
+        Added gui namespace before SEL_TouchEvent.
+        
+    zhiqiangxu
+        Fixed a logic error in ControlUtils::RectUnion.
+        Fixed an issue that there is an useless conversion in ScrollView::onTouchBegan.
+        Deleted several lines of useless code in ScrollView::deaccelerateScrolling.
+        Fixed that ScrollView should implement ActionTweenDelegate.
+        Fixed LabelBMFont::getBoundingBox() position error
+        
+    yinkaile (2youyouo2)
+        Maintainer of Armature Bone Animation.
+        
+    dmurtagh
+        Fixed a bug that UserDefault::getDoubleForKey() doesn't pass default value to Java.
+        Fixed a compile error when CC_SPRITE_DEBUG_DRAW is on
+        
+    seobyeongky
+        Updates spine runtime.
+        Fixed a potential bug in Data's copy constructor. 
+        Fixed the bug that MotionStreak can not work with MoveTo and MoveBy
+        Fixed a bug that  HttpAsynConnection can not get error content if response code less than 200 or response code greater or equal than 300
+        
+    luocker
+        Fix a bug that string itself is also modified in `String::componentsSeparatedByString`.
+        
+    omersaeed
+        Fix a bug that game will crash if connection breaks during download using AssetManager.
+        
+    SBKarr
+        AngelCode binary file format support for LabelBMFont.
+        
+    zarelaky
+        OpenAL context isn't destroyed correctly on mac and ios.
+        
+    kicktheken (Kenneth Chan)
+        Fixed a bug that the setBlendFunc method of some classes wasn't exposed to LUA.
+        Fix lua project template crash on iOS5.1 device
+        Fix layout constant syntax error in lua-binding
+        
+    zilongshanren
+        Fixed a bug that missing to check self assignment of Vector<T>, Map<K,V>, Value and String.
+        Fixed a bug that move assignment operator doesn't clear previous content bug.
+        Fixed the compile error of Map's getRandomObject.
+        
+    daltomi
+        Fixed a typo in Director class.
+        Removed an unnecessary boolean flag in CCFontAtlasCache.cpp.
+        Used 'cbegin/cend', 'const std::string' where it's reasonable.
+        
+    v1ctor
+        ControlSlider supports to set selected thumb sprite.
+        ControlButton supports to set scale ratio of touchdown state
+        
+    akof1314
+        TestCpp works by using CMake and mingw on Windows.
+        
+    Pisces000221
+        Corrected a few mistakes in the README file of project-creator.
+        Corrected a mistake in README.
+        Fixed a bug that a string which only contains CJK characters can't make a line-break when it's needed.
+        Fixed a bug that if the UISlider is faded, the slide ball won't fade together
+        
+    hbbalfred
+        Fixed a bug that crash if file doesn't exist when using FileUtils::getStringFromFile.
+        Fixed a bug that cc.BuilderReader.load( path, null, parentSize ); was not allowed.
+        
+    liang8305
+        Use multiple processes according the number of cores to build android project
+        
+    pandamicro
+        Exposed SAXParser to JS, it is used for parsing XML in JS.
+        
+    hanjukim
+        Fixed a bug that color and opacity settings were not applied when invoking Label::alignText.
+        Fixed the bug that FileUtils:getStringFromFile() may return a unterminated string
+        Skip BOM in DataReaderHelper::addDataFromJsonCache()
+
+    bagobor
+        Fixed a memory leak in AssetsManager::uncompress.
+        Code format fix and small optimizations in cocostudio/CCActionNode.cpp.
+        
+    ucchen
+        Exposed the missing data structures of Spine to JS.
+        
+    justmao945
+        Corrected the definition of CMake variables.
+        
+    maksqwe
+        Fixed string size check in BitmapDC::utf8ToUtf16 on win32 and assert condition in TriggerMng.
+        
+    wefiends
+        s3tc compressed textures with no mipmaps fail to be loaded.
+        Added createWithFullscreen overloaded method that sets video mode
+        
+    floatinghotpot
+        Fixed a bug that no callback is invoked when websocket connection fails
+        
+    Linghui
+        Updated README of template: fix wrong platform java path.
+        
+    seemk
+        Fixed crash if invoking Director::end() on WINDOWS.
+        
+    odedsh
+        Fixed a bug that loading custom fonts from ttf file fails on windows.
+        
+    Wilhansen
+        Fixed a bug that spine::Skeleton would not be updated after re-adding to scene.
+        
+    huangml
+        Fixed a bug that Node::removeAllChildrenWithCleanup() does not remove PhysicsBody.
+        
+    newnon
+        Adds getCurrentLanguageCode() which returns iso 639-1 language code.
+        Adds support for get response when Activity's onActivityResult is triggered.
+        Improve Android projects.
+        Android jni error clear & more readable log.
+        Add support of software PVRTC v1 decompression.
+        Fixed a bug that ttf font have not effect on Mac OS X.
+        Fixed a bug that before touchMove Touch::_prevPoint contains junk.
+        Added Device::setKeepScreenOn().
+        Fixed Label performance problem.
+        Added Node::stopAllActionsByTag && ActionManager::removeAllActionsByTag.
+        Added getAllTouches() in GLViewProtocol.
+        Precompiled headers improvements.
+        Added Application::openUrl for all supported platforms ecept WP8 and WinRT.
+        Scale9Sprite capInsets set fix.
+        Clang static analyzer crash fix.
+        Fix include in cocos network module.
+        Slider misprint fix.
+        Fix web socket crash.
+        Scale9Sprite cropped sprite frames support.
+
+    youknowone
+        Adds iOS-like elastic bounceback support for cocos2d::extension::ScrollView
+        
+    aeonmine
+        Fixed ActionObject memory leak in ActionManagerEx::initWithDictionary
+        Fixed memory leak in cocos studiov2.0 reader
+        
+    LoungeKatt
+        Corrected a mistake of building android project in README.md
+        
+    flashjay
+        Remove deprecated code in lua tests & template
+        luaLoadChunksFromZip should just remove .lua or .luac extension
+        
+    zukkun
+        Fixed incorrect function invocation in PhysicsBody::setAngularVelocityLimit
+        
+    dbaack
+        Fixed a bug that removing and re-adding an event listener will trigger assert
+        
+    zakmandhro
+        A typo fix in RELEASE_NOTES.md
+        
+    mgcL
+        A potential memory leak fix in value's default constructor
+        Added ScriptHandlerMgr::destroyInstance to avoid memory leak
+        
+    Mazyod
+        Fixed a bug that HTTPClient reports 2xx status codes as errors
+        Added missing Text Font and Placeholder feature of EditBox for Mac platform
+        HttpRequest uses std::function as callback
+        EditBox: mac secure input
+        Fix a bug that can not get/set text in password mode on Mac OS X
+        Make sure TableView parents are visible before handling touch
+        Fixed memory leak in HttpRequest
+        
+    iSevenDays
+        Fixed a bug that the result of 'malloc' is incompatible with type 'unsigned char *' in Image::saveImageToPNG
+        Fixed a potential memory leak in CCEditBoxImplIOS.mm
+        Fixed incompatible pointer conversion in external/chipmunk/src/cpArray.c
+        Fixed memory leak in 'Image'
+        Fixed loosing precision when using 'recv' in 'Console'
+        Fixed link error with Xcode 6 when building with 32-bit architecture
+        Fixed CMake for Mac OS X
+        
+    ololomax
+        Fixed a potential crash in SceneReader::createNodeWithSceneFile
+        
+    gaoxiaosong
+        Fixed a warning in cpCollision.c
+        
+    sachingarg05
+        Re-added orientation change callback in java activity
+        GLProgram should not abort() if shader compilation fails, returning false is better.
+        
+    dplusic
+        Fixed that cc.pGetAngle may return wrong value
+        
+    zifter
+        Fixed a bug that the effect of particle loaded from CocosBuilder is incorrectly
+        Fix twice calling onExit
+        Fixed bug with cascade opacity and color for control button
+        Fix Progress Action. Not working with charging from 100 to 0. 
+        
+    twhittock
+        Fixed a bug that Application::run returns wrong value on Mac platform
+        
+    asmodehn
+        Added SDK / NDK detection based on PATH in Setup.py
+        
+    myourys
+        Make cpp template support Eclipse c++ project
+        
+    NatWeiss
+        Fix compilation error using arch i386
+        Fixed debug-config crash if a FrameBuffer has no RenderTargetDepthStencil.
+        
+    favorcode
+        Correct some doxygen comment
+        
+    asuuma
+        Fix Repeat will run one more over in rare situations.
+        
+    uqtimes 
+        Fix NSNotificationCenter and NSTimer leaks
+        
+    ntotani
+        fix building error in lua-binding in release mode
+        Fixed WebView lua-bind method name.
+        
+    kezhuw
+        AutoReleasePool manager improvement
+        Fixed a bug that condition variable sleep on unrelated mutex in HttpClient
+        
+    zhouxiaoxiaoxujian
+        Added TextField::getStringLength()
+        Add shadow, outline, glow filter support for UIText
+        Fix UITextField IME can't auto detach
+        Add getChildByName method for get a node that can be cast to Type T
+        Improvement ImageViewReader don't necessary loadTexture when imageFilePath is empty
+        
+    QiuleiWang
+        Fix the bug that calculated height of multi-line string was incorrect on iOS
+        
+    Rumist
+        Fix the bug that the result of Director->convertToUI() is error.
+        
+    kyokomi
+        Fix the bug that UIButton doesn't support TTF font
+        Fix a bug of TextReader
+        Fix a bug that UITextField doesn't support TTF font
+        Setted contentSize in CSLoader
+        
+    gin0606
+        Add a new line at the end of a file
+        Fix a bug that crash happened when try to remove videoView(STATE_PLAYBACK_COMPLETED) in android
+        Fix video scale issue in iOS
+        Fix iOS VideoPlayer memory leak
+        Added c++11 random library support
+        Added WebView widget which supports iOS and Android
+        
+    billtt
+        Fixed a bug that Node::setScale(float) may not work properly
+        network: Fixed a problem where WebSocket messages may pile up
+        
+    Teivaz
+        Custom uniform search optimization
+        Fixed compiling error on WP8.
+        Added method for custom precompiled shader program loading on WP8
+        Enable screen orientation change handling on WP8
+        Enabled GLProgramState restoring on render recreated on WP8
+        
+    chareice
+        Make `setup.py` work on zsh
+        
+    taug
+        Could add seach path and resolution order path in front.
+        
+    CaiCQ
+        Fix a but that LabelTTF may lost chinese characters on linux
+        
+    chenguangqi
+        Fixed a compiling error on Android
+        Fixed an error when importing project using Eclipse on Android
+        
+    uorbe001
+        Allow setting bundle to use in file utils on iOS and Mac OS X
+        
+    yongkangchen
+        Fixed a bug that font size of EditBox is not scaled when glview is scaled on Mac OS X
+        Fixed a bug that Label::setTextColor does not have any effect on Mac OS X
+        
+    wagulu
+        Fixed a bug that particle effect is wrong when scaled
+        
+    reckhou
+        Optimize FPS control on Android
+        
+    dzl-ian
+        Added getter and setter for TextColor for UIText
+    
+    zii
+        Added utils::gettime()
+        
+    takaken1994
+        Added function for setting min/max scale for ScrollView
+        studio: Removed "using namespace cocos2d" from CCFrame.h
+        
+    maltium 
+        Added 3D rotation support to RotateTo action
+        
+    Hamken100per
+        Added a function getAssetManager() on CCFileUtilsAndroid
+        
+    rny
+        Fixed LabelTTF::getBoundingBox() position error
+        SpriteFrameCache load from plist file content data
+        
+    AppleJDay
+        Add Feature:EventMouse should support getDelta, getDeltaX, getDeltaY functions
+        
+    GavinThornton
+        Fixed a bug that when a sprite added into SpriteBatchNod it will turn black if setting opacity
+        
+    DavidPartouche
+        Fixed the bug that video player not showing on iOS if it's not in FullScreen mode
+        
+    zaWasp
+        Added support for applicationDidEnterBackground / applicationWillEnterForeground on win32
+        
+    xiangxw
+        Fixed the bug that Console::sendPrompt() will send extra `\0`
+        
+    kaishiqi
+        Fixed a but that cursor postion is wrong on desktop.
+        
+    jagd
+        Added setSubsteps() and getSubsteps() in PhysicsWorld
+        
+    denpen
+        Fixed a bug that scroll view hidden picks up the touch events.
+        
+    joewan
+        Fixed memory leak when use menu_selector
+        
+    zhongfq
+        Optimize decompress jpg data
+        Fixed memory leak of TextureCache::reloadTexture()
+        
+    wohaaitinciu
+        WebView support on windows.
+        Fix a fatal bug in EditBox implement for platform win32.
+        
+    guykogus
+        Implemented Application::openUrl for WP8 and WinRT
+        
+    tttreal
+        Fixed Label::getStringNumLines()
+        
+    hongliang-goudou
+        Fixed the bug that UI animation playing crash if GUI JSON file is loaded again
+        
+    yestein
+        Add Cocostudio Armature getOffsetPoints API for Lua
+        
+    coldfog
+        Fix bug that ActionManagerEx::initWithBinary can only load one UI animation
+        
+    timur-losev
+        Fix a bug that GLProgramCache::addGLProgram() can not replace existing program
+        
+    TimothyZhang
+        Fixed a potential memory leak in GLProgram::setGLProgram()
+        Add jsb.fileUtils.writeDataToFile().
+        
+    ahlwong
+        Fix Label Kerning on Single Characters
+        
+    Svenito
+        Add greater than operator to Vec2
+        
+    liamcindy
+        Update ui button size changed logic.
+        Added support for Cocos Studio Light3D.
+        Fix scrollview render errorl.
+        Update for text effect clone.
+        Update controlButton size calculate with new Scale9Sprite logic.
+        Update pageview to support adjust child size.
+        
+    vovkasm
+        Fix warnings for Xcode6.1
+        
+    nilium
+        Unignore libs dir in plugin and fix Travis script to descend into included directories
+        
+    shrimpz
+        Fix two typos in luaval_to_quaternion
+        Fix label crashed on android
+        
+    ton1517
+        Fix the issue that JumpTo can not be applied more than once
+    
+    takaokato
+        Fix wrong result in Node:getParenttoNodeTransform() if node is transformed
+    
+    AknEp
+        Fix FileUtils::fullPathForFilename return empty string if file not found
+        
+    kompjoefriek
+        Fix compiling warnings
+        Device: Added vibrate support to enable vibration for a duration.
+        
+    tmr111116
+        fix random int overflow
+        
+    flamefox
+        fix the bug that Sprite3D::getAttachNode() should failed when there is no bone with name
+        
+    ryule
+        Fixed HttpClient-ios request to work when the data is started by 0x00
+        
+    loadrunner
+        Added romanian languange support
+        Added sensor property for PhysicsShape
+        Added line spacing/leading feature to Label.
+        Changed label font size type to float.
+        Removed scale factor for label shadow.
+        Fixed a TMXLayer bug: When using float values (for example the actual position of the character) to get the current tile, the wrong tile is sometimes/usually returned.
+        
+    Almax27
+        RenderQueue command buffer optimize.
+        Removed ScrollView::_innerContainer pointer copy.
+        
+    IgorMats
+        Added MotionStreak::getStroke/setStroke
+        
+    matsuokah
+        Fixed the bug that JNI illegal start byte error causes crashing error on Android 5.0
+        
+    babcca
+        Fixed crashing when playing streamed MP4 file on iOS
+        
+    milos1290
+        Added Lerp for Vec3
+        Added ActionFloat
+        
+    perminovVS
+        Optimize Vec3 and Vec2
+        Added `UserDefault::setDelegate()`
+        FileUtils: Added FileUtils::getSuitableFOpen() for convert utf8 to locale, for specific platform
+        platform: Correct all usage of unicode version winapi in FileUtils for win32
+        FileUtils: Added FileUtils::getFileExtension for getting file's extension name
+        utils: Made utils::captureScreen saving file in another thread to improve the performance
+        Added check for glfwCreateWindow.
+        Refined AssetsManagerEx unzipping by using async.
+        Fixed a bug in FileUtilsWin32::removeDirectory when the file begins with ".".
+        Corrected the keyboard codes for Desktop and WinRT.
+        Added some support for mouse on WinRT.
+        Correct the convertion between unicode and utf8 on WinRT.
+        
+    qiutaoleo
+        Added a feature to check case characters for filename on windows
+        
+    HueyPark
+        Fixed memory leak in HttpClient on iOS
+        
+    Dimon4eg
+        Fixed crash on AssetsManager
+        Fixed memory leak of WebView on iOS
+        Fixed crahed that if url contains illegal characters on Android
+        log: Fixed crash on Windows if passing string more than 16kb to cocos2d::log
+        Fixed a crash bug when csb file is broken.
+        Fixed a crash bug in LoadingBar.
+        Fixed a crash bug in destructor of FontFreeType.
+        UI: Set focus to Widget when touched.
+        
+    tankorsmash
+        Fixed the bug that ProgressTimer::setSprite() doesn't take effect
+
+    namezero111111
+        ui: TextField add `getTextColor`, `getTextHorizontalAlignment` and `getTextVerticalAlignment` API
+        Physics: Fixed circle shape debug draw incorrect issue
+
+    shinhirota
+        JS: Fixed issue of iOS/JS reflection `callStaticMethod` with bool arg
+
+    oscr
+        Fix two issues with download-deps.py
+        Capitalize default option in download-deps.py
+        platform: Added debug flag -Wextra to linux CMakeFile
+
+    iris-wy
+        platform: Fixed warning "Service Intent must be explicit" on Android
+
+    alexpeak
+        Label: Fixed rendering LabelTTF characters as black boxes on Android by ensuring atlases are purged before resetting
+
+    ywxzm
+        Lua: Fixed onTouch begin don't return value
+
+    xpol
+        Sprite: Fixed some warnings and a related bug in CCSprite.
+        Fixes boring deprecated warning.
+
+    marzapower
+        UI: Fixed inertial scrolling for CCScrollView
+
+    MAUSMAUSgames
+        Action: Permitted setting bitwise flags to action
+
+    RUKD
+        ParticleSystem: performance improvement
+
+    m-yukio
+        UI: RichText support new line element.
+
+    Fraggle
+        Fix PMA Handling issue.
+
+    nhuanvd
+        Fix cannot add view to mFrameLayout when extends Cocos2dxActivity.
+
+    1scaR1
+        Add Scale9Sprite fade actions with cascade opacity enabled in js-test.
+
+    FrancoisDupayrat
+        Fix edit box setPlaceholderFontName and scale font size issue.
+
+    cesarpachon
+        AudioEngine on Linux replace the original SimpleAudioEngine with a new version of FMOD, now AudioEngine support all platforms!
+
+    cezheng
+        Fix Downloader bug for iOS & Android.
+
+    pandemosth
+        Fix crash when removing a remotely downloaded image from texture cache in js-binding.
+
+    GuoLunHao
+        Add quiet option for Cocos Toolkit.
+        
+
+Retired Core Developers:
+    WenSheng Yang
+        Author of windows port, CCTextField,
+        Designer of CCApplication/CCEGLView/platform structure.
+        He's working together with 2dx core team but leading FishingJoy game
+
+    RongHong Huang (flyingpaper)
+        Author of cocos2d-xna and spent all his time on wp7.
+
+    Bo Yu (boyu0)
+
+    anxi
+        Added UIEditBox support on linux platform.
+
+    avail
+        Fixed minor typo in README.
+
+    cpascal
+        Fixed a crash bug of AudioPlayer in Win32.
+
+    geron-cn
+        Removed redundant interface in CCSkeletonNode.
+        Fixed a bug that a same frame index is inserted after animation speed is scaled. 
+        Fixed crash when recall a cached timeline after scene exited.
+        Added ActionTimeline::setAnimationEndCallBack and ActionTimeline::addFrameEndCallFunc.
+        
+    igorzel
+        Fixed a crash bug caused by integer overflow in Device::getTextureDataForText on iOS.
+
+    KAIO2
+        Fixed typos and syntax errors.
+        
+    kammy
+        Moved initialization of image to an appropriate location, because it always called twice in SpriteFrameCache::addSpriteFramesWithFile()
+
+    lijinlong
+        Fixed a bug of luabinding enumerateChildren.
+
+    linguofeng
+        Added UPDATE_FAILED and ERROR_DECOMPRESS in Lua.
+        
+
+    lsybblll
+        Fixed a bug in CCPhysics3DComponent.cpp that oldBool is set with a wrong value.
+
+    mogemimi
+        Fixed various compiler warnings on Xcode 7.
+        Fixed some minor typos in lua bindings.
+        Fixed a minor typo and renamed INTIAL_CAPS_ALL_CHARACTERS to INITIAL_CAPS_ALL_CHARACTERS in UIEditBox.
+        Fixed some minor typos.
+        Fixed Wformat-security warning on Xcode.
+        Added missing override keyword.
+        Fix memory leak when initWithImage() failed.
+        Fix deprecation warning in SkeletonRenderer.
+        Fix typos in documentation and comments.
+
+    njh0602
+        Clean up the code of setRect() function.
+        Fixed syntax error in comment.
+        Add virtual keyword for some render related function.
+
+    noshbar
+        Changed the size of startFlag to 13.
+        Added checks to see if temp1 and temp2 are non-null before dereferencing them.
+        "Changed some delete operations to be deletions of arrays where applicable.
+        Changed some "free" operations to "delete" where memory was allocated with "new".
+
+    pabitrapadhy
+        Fixed spelling and grammar mistakes.
+
+    seivan
+        Fixed a bug that cocos2d::Map may cause Dangling Pointers when inserting Ref Object which already exist in the Map.
+        EventListenerMouse will dispatch EventMouse events.
+
+    songchengjiang
+        Fixed a bug of nomalize_point which caused particle rendering error.
+        Fixed a bug that lua Scene3DTest "back" button did not work.
+
+    TheCodez
+        Added missing getChildByTag<>() API.
+        Fixed a bug that RefPtr test wasn't executed even in debug build.
+        Added Application::getVersion() to get the app version.
+
+    thuydx55
+        Fixed a bug of loading pluginx lib when compile Android with --compile-script flag.
+
+    
+
+Cocos2d-x can not grow so fast without the active community.
+Thanks to all developers who report & trace bugs, discuss the engine usage in forum & QQ groups!
+Special thanks to Ricardo Quesada for giving us lots of guidances & suggestions.

+ 2090 - 0
cocos2d/CHANGELOG

@@ -0,0 +1,2090 @@
+cocos2d-x-3.15.1 May.27 2017
+
+[REFINE]        Add optimization codes for huawei devices
+
+cocos2d-x-3.15 Apr.21 2017
+
+[NEW]           Full support of Android Studio, can use Android Studio to edit, compile and debug C++ codes
+[NEW]           Audio Engine: use `tremolo` to decode audio files to be more adaptable to Android devices and improve performance on Android
+[NEW]           WebSockets and SocketIO supports SSL
+[NEW]           WebSockets: add methods to get url and server selected protocol
+[NEW]           Add `utils::getFileMD5Hash()`
+
+[REFINE]        EventDispatcher: use `std::stable_sort()` to sort nodes and listeners
+[REFINE]        FileUtils: add async version of common methods
+[REFINE]        Label: full unicode support
+[REFINE]        Renderer: enable VAO by default on Android
+[REFINE]        Renderer: use std::stable_sort() to sort commands
+[REFINE]        Scheduler: `unscheduleAll()` will unschedule selectors that scheduled with `performFunctionInCocosThread()`
+[REFINE]        SpriteFrameCache: avoid load frames if they are already loaded
+[REFENE]        Texfield: not use auto correction on iOS now
+[REFINE]        TextureCache: allow to unbind asynchronous texture loading callback with a custom key
+[REFINE]        WebSockets: each connection will create a virtual host
+[REFINE]        WebView: can clean cached data
+[REFINE]        WebSockets: allow self-assign certification
+[REFINE]        3rd: update OpenSSL to v1.1.0
+[REFINE]        3rd: update flatbuffer to v1.5
+[REFINE]        3rd: Update Spine runtime to v3.5.35
+[REFINE]        Remove support for Windows 8.1 store and phone
+[REFINE]        Remove 32-bit linux support
+
+
+[FIX]           Action: spawn action may be invoked more times than specified 
+[FIX]           Audio engine: can not play audios in the callback set in `AudioEngine::setFinishedCallback()` on iOS, Mac and win32
+[FIX]           Audio engine: crash if uncache audios in finish callback on Android
+[FIX]           Audio engine: crash if playing very small mp3 audios on Android
+[FIX]           Audio engine: may crash if repeat doing `play -> stop` on iOS and Mac
+[FIX]           Audio engine: play2d may still wait 2 seconds if preload is too fast
+[FIX]           Audio engine: preload many audios may cause crash on devices that use Samsung Exynos CPU
+[FIX]           Application: `openURL()` return wrong valueo on Linux
+[FIX]           Core: out scene's `onEnterTransitionDidFinish` is not triggered if using transition scene with `Director::runWithScene()`
+[FIX]           CheckBox: can receive touch up event that is released far from it
+[FIX]           Downloader: is not thread safe and may cause rondom crash on Android
+[FIX]           DrawNode: can't change opacity
+[FIX]           GLProgram: memory leak
+[FIX]           HttpClient: may crash on Android 4.2
+[FIX]           Label: ttf font line wrap
+[FIX]           Label: wrong effect if ttf font line gap is not 0
+[FIX]           Label: memory leak with ttf font
+[FIX]           Label: call `disableEffect()` many times will compress the label to one character
+[FIX]           Mesh: enable depth write by default
+[FIX]           Node: calling `reorderChild()` does not update touch lister with scene graph priority
+[FIX]           PageView: `getCurrentPageIndex()` returns -1 when created and haven't scrolled
+[FIX]           Physics2d: can not apply velocity to kinematic bodies
+[FIX]           Scheduler: an unscheduled selector may be invoked many times
+[FIX]           Scheduler: selector is not moved in time
+[FIX]           Simple Audio Engine: `unloadEffect()` doesn't work on Android 5.0.1 devices
+[FIX]           Simple Audio Engine: `ConcurrentModificationException`
+[FIX]           SokcetIO: use wrong default port for connection
+[FIX]           Sprite: texture and shader lost after restore from background on Android if using ETC1
+[FIX]           WebSockets: memory leak
+[FIX]           WebSockets: doesn't parse url correctly
+[FIX]           WebSockets: may crash in random
+[FIX]           Vec4: error logic of operator '<'
+[FIX]           Android: accelerometer uses wrong time accuracy
+[FIX]           iOS: may crashed if multiple OpenGL ES contexts coexist
+[FIX]           Windows: bad performance
+[FIX]           Windows: link error when compiling in release mode
+[FIX]           Lua: content after '\0' of a string is cut off when passing a string to C++ or vice versa
+[FIX]           Lua: lua_cocos2dx_Widget_addTouchEventListener crashed
+[FIX]           Lua: can not get binary data from file
+[FIX]           JSB: XMLHttpRequest supports notifying progression
+[FIX]           JSB: invoke `jsb.reflection.callStaticMethod` many times will cause `JNI max table=512` exception on Android
+[FIX]           Others: `download_deps.py` depends on git command
+
+cocos2d-x-3.14.1 Jan.19 2017
+
+[FIX]           May crash if using `Scene::createWithPhysics()` to create a scene and physics3d camera is not set
+[FIX]           May have link error because of glfw conflict on Linux
+[FIX]           Sprite: created from sprite frame with polygon information can not work correctly
+[FIX]           Lua: link error with VS2015
+[FIX]           Lua: compiling error if using `cocos compile/run -p android --android-studio` on Android    
+
+coocs2d-x-3.14 Dec 22 2016
+
+[NEW]           Add Spine binary file format support
+[NEW]           Action: add a method to get the number of actions running in a given node with specific tag
+[NEW]           Action: new actions: ResizeBy and ResizeTo
+[NEW]           Button: can set title label
+[NEW]           Can disable multi touch on Android
+[NEW]           EventDispatcher: Add hasEventListener to check listener existance
+[NEW]           EditBox: add horizontal text alignment
+[NEW]           EventDispatcher: added `hasEvent()` to check if an event is added
+[NEW]           Sprite: support slice9 feature
+[NEW]           Slider: add methods to get _slidBallNormalRenderer
+[NEW]           Desktop: add a method to toggle between fullscreen and windowed
+[NEW]           Desktop: add events for window resize, focus and unfocus
+[NEW]           Mac: supports game controller
+[NEW]           JSB: add cc.sys.now() and perfromance.now(), the last one is more accurate
+[NEW]           Lua: add cc.vec3 functions: add, sub and dot
+[NEW]           Lua: use luajit 2.1.0-beta2
+[NEW]           Web: Add cc.CONCURRENCY_HTTP_REQUEST_COUNT to control max concurrent task count for XMLHttpRequest
+
+[REFINE]        Add NDEBUG for cpp template Xcode project
+[REFINE]        DrawNode: support float line width
+[REFINE]        EditBoxDelegate: add reason for edit end
+[REFINE]        Improve XML parse performance
+[REFINE]        Make batch capacity resizing more efficiently
+[REFINE]        PageView: support custom scrollToPage time
+[REFINE]        Lua: cc.Ray:intersects addtionally returns the distance
+[REFINE]        Mac: system font enhancement
+[REFINE]        Linux: build shared lib with -fPIC
+[REFINE]        Android: use SharedPreferences.apply() to store data
+[REFINE]        JSB: Increase default JS heap to 32 mb
+[REFINE]        JSB: Support more system languages
+[REFINE]        JSB: Direct log/error for better understantding problems
+[REFINE]        JSB: Separate FinalizeHook for ref objects and non ref objects
+[REFINE]        Web: Improve overall node construction performance
+[REFINE]        Web: Improve overall loading process performance
+[REFINE]        Web: Reduce overall memory usage
+[REFINE]        Web: Made cc.LabelBMFont and cc.LabelAtlas support texture packing and auto batching
+[REFINE]        Web: Reimplement a much faster ccui.Scale9Sprite
+[REFINE]        Web: Reimplement a much faster cc.DrawNode WebGL renderer
+[REFINE]        Web: Use stack to avoid recursive call in transform, onEnter, onExit etc, reduce call stack depth
+
+
+[FIX]           AsstsManagerEx: project.manifest may be downloaded twice
+[FIX]           AudioEngine: can not play large ogg file
+[FIX]           AudioEngine: may have noise if playing mp3 files on iOS/Mac OS X
+[FIX]           AudioEngine: can not play effect/music entirely on iOS and Mac
+[FIX]           ClippingNode: effect is wrong if threshold is set to a value not equal to 1 first then set to 1
+[FIX]           Compiling error if `USE_STD_UNORDERED_MAP == 0`
+[FIX]           ControlSwitch::create() may cause crash
+[FIX]           Downloader: may crash if it is released before finishing downloading task
+[FIX]           EditBox: fix single line and multiline text alighment, now single line will be center and multiline will be top align vertically by default
+[FIX]           EditBox: placeholder font not being set corretly for multiline text field on iOS
+[FIX]           EditBox: doesn't show text on Mac OS 10.12
+[FIX]           EditBox: multiline overflow bounds of box
+[FIX]           FastTilemap: wrong effect when content scale factor is not 1
+[FIX]           FontFreeType: crash in destructor
+[FIX]           ImageView: wrong effect of using loadtexture() to load a ETC1 texture with alpha support
+[FIX]           Label: wrong blending effect of outline
+[FIX]           Label: some labels may not been shown
+[FIX]           Label: may crash when label string is empty an the overflow is shrink
+[FIX]           Label: possible memory leak when font size is 0
+[FIX]           MenuItemSprite: MenuItemSprite::unselected() on a disabled item show wrong image
+[FIX]           Node: the effect of setRotation+setSkewX is wrong
+[FIX]           Physics3d: effect of debug draw is wrong
+[FIX]           Renderer: indices count may overflow when drawing batching triangle commands which causes unexpected effect
+[FIX]           RenderTexture: Sprite3D is not shown
+[FIX]           TileMap: hexagonal map fails on TMXTiledMap::getTileAt()
+[FIX]           TMXMapInfo: tileGid may overflow when using horizontal flip
+[FIX]           TriangleCommand: triangle commands can't do batching when the glprogram using custom shader with custom uniforms
+[FIX]           UI: label atlas and BMFont rendering issue with ETC1 texture format
+[FIX]           3D: small .mtl files are not loaded
+[FIX]           3D: Sprite3D::getMesh() may cause crash if it doesn't have any mesh
+[FIX]           3D: wrong Skybox fov
+[FIX]           3D: Sprite3D can't release its texture
+[FIX]           AssetsManagerEx: Fail to decompress when sub directory is not created
+[FIX]           ScrollView: crash of scroll to top or left
+[FIX]           SoketIO: memory leak
+[FIX]           iOS: Vibrate effect can not work in not silent mode
+[FIX]           iOS: view size got with landscape orientation if run on iOS 7 and ealier
+[FIX]           iOS: iOS 9 OpengGL error
+[FIX]           iOS: if a scene includes 3d model with light and ListView may cause crash
+[FIX]           Android: cause compiling error with android-19 or lower
+[FIX]           Android: RapidJason crashes in release mode
+[FIX]           Android: may not pause background music after game enters background
+[FIX]           Android: adapt to Android pixel
+[FIX]           Android: MessageBox inverted parames
+[FIX]           Android: cause deadlock if preload the same file more than 3 times in preload callback
+[FIX]           Android: WebView: base url can not work
+[FIX]           Android: may crash if `AudioEngineManager.getProperty(PROPERTY_OUTPUT_FRAMES_PER_BUFFER)` returns null
+[FIX]           Mac: Downloader can not access https website
+[FIX]           Win32: fix crash caused by `Helper::getSubStringOfUTF8String()` in debug mode
+[FIX]           Linux: FMOD issue
+[FIX]           Linux: Application::openURL can not work
+[FIX]           Desktop: crash upon exit when NotificationNode exists
+[FIX]           Spine: color bug
+[FIX]           Console: doesn't support `--ap` parameter
+[FIX]           Lua: result of radian2angle is wrong
+[FIX]           Lua: iskindof_ doesn't work correctly
+[FIX]           Lua: new lua project crashes compiling with VS2015 release mode
+[FIX]           Lua: ComponentLua doesn't support binary code
+[FIX]           JSB: `jsb.addRoot is not a function` error caused by cc.GLProgramState.setUniformCallback
+[FIX]           JSB: Fix spine TrackEntry conversion crash issue
+[FIX]           JSB: Fix CallbackWrapper and FunctionWrapper crash during deallocation in new memory model
+[FIX]           JSB: Fix event object memory issue by manually bind EventDispatcher::addCustomEventListener
+[FIX]           JSB: Fix chipmunk crash issues when using setDefaultCollisionHandler
+[FIX]           JSB: Fix compilation issues when COCOS_DEBUG = 2
+[FIX]           JSB: Unify function name of Texture2D::releaseTexture
+[FIX]           Web: Fix spine blend function inconsistency between web and jsb
+[FIX]           Web: Fix particle system load from plist generated by x-studio365
+[FIX]           Web: Fix doEnumerateRecursive(node, name, callback) always return undefined issue
+[FIX]           Web: Change bright style on 'setEnabled' call of ccui.Widget
+[FIX]           Web: Fix Editbox can't input in full screen mode
+[FIX]           Web: Fix texture issue on some Android devices by always set vertexAttribPointer  
+[FIX]           Web: Make xhr ontimeout callback work on all browsers
+[FIX]           Web: Fix clear color not normalized issue
+[FIX]           Web: Fix clipping node rendering issue when alphaThreshold = 1
+[FIX]           Web: Fix nested scroll view rendering issue
+[FIX]           Web: Make orderDirty flag properly set for node
+[FIX]           Web: Fix ccui.Slider gray state not available issue
+
+cocos2d-x-3.13.1 Sep 13 2016
+
+[FIX]           Label color broken
+[FIX]           application will crash in debug mode if don't specify a design resolution
+[FIX]           application may crash if coming from background by clicking application icon on Android
+[FIX]           AudioEngine can not play audio if the audio lies outside APK on Android
+[FIX]           AudioEngine::stop() will trigger `finish` callback on Android
+[FIX]           application will crash if using SimpleAudioEngine or new AudioEngine to play audio on Android 2.3.x
+[FIX]           object.setString() has not effect if passing a number on JSB
+
+cocos2d-x-3.13 Aug 22 2016
+
+[HIGHLIGHT]     add VR plugin
+[HIGHLIGHT]     support ETC1 alpha channel
+[HIGHLIGHT]     fix AudioEngine performance for Android 4.2+
+[HIGHLIGHT]     improve canvas renderer performance with dirty region
+[HIGHLIGHT]     add Andorid arm-64 support
+[HIGHLIGHT]     use luajit for Android arm-64
+[HIGHLIGHT]     switch to use gcc 4.9
+[HIGHLIGHT]     upgrade CURL to 7.50.0
+[HIGHLIGHT]     upgrade Spine to 3.4
+[HIGHLIGHT]     upgrade glfw to 3.2
+
+[NEW]           add `Configuration::supportsMapBuffer()`
+[NEW]           support hexagonal tile maps
+[NEW]           add `ListView::setScrollDuration()`
+[NEW]           implement `SimpleAudioEngine::willPlayBackgroundMusic()` on Android
+[NEW]           implement `AudioEngine::preload()` on Android
+[NEW]           add `cc.Node['.classname']` to get class name for tolua C++ class in lua
+[NEW]           support direct load in web engine to show scene without loading all resources, resources will be loaded asynchronously
+[NEW]           add `cc.view.setOrientation` API to force orientation in web browser
+
+[REFINE]        move back to use gcc 4.9 on Android to fix some crash bugs
+[REFINE]        optimize Node sorting speed for 64-bit
+[REFINE]        using `chrono::steady_clock()` instread of gettimeofday for FPS calculation
+[REFINE]        use `fstat` instead of `fseek` and `ftell` for performance to read file content
+[REFINE]        use std::string reference instead of char* for `utils::findChild()`
+[REFINE]        make `MotionStreak` _maxPoints framerate independent
+[REFINE]        support utf-8 bom lua script
+[REFINE]        can show utf-8 characters in MessageBox and lua log on win32
+[REFINE]        improve stability of new WebGL renderer provided in v3.12
+[REFINE]        update js auto binding settings with new ndk version
+[REFINE]        improve evalString implementation which was rely on deprecated API
+[REFINE]        improve js bindings code quality by merging part of cocos2d-x-lite repo
+[REFINE]        sources path in sourcemap of web engine are now relative
+
+[FIX]           `GLProgram::link()` only check result in debug mode or WinRT
+[FIX]           PageView::clone() misses cloing some member variables
+[FIX]           potential crash of `AudioEngine::uncache()`
+[FIX]           websocket receives package size > 1023 error
+[FIX]           the color of underline is different from the text color
+[FIX]           memory leak in `MenuItemToggle::create()`
+[FIX]           crash after removing a physics body right after adding it
+[FIX]           SpriteBatchNode crash if CC_SPRITE_DEBUG_DRAW is enabled
+[FIX]           memory leak in `Data::move()`
+[FIX]           crash in `EaseExpoentialOut::clone()`
+[FIX]           buffer over-read in `GLProgram::updateUniformLocation()`
+[FIX]           `dirty` variable incorrectly reset with a multiple camera setup causing drawing issues on Sprite
+[FIX]           fix label text formatter right alignment
+[FIX]           `bsd_signal` link error on Android
+[FIX]           crash while decoding small MP3 file on Android
+[FIX]           `AppDelegate::applicationWillEnterForeground()` is invoked at launch on Android
+[FIX]           fix `relocation overflow in R_ARM_THM_CALL` on Android
+[FIX]           navigation bar doesn't hide if show and dismiss keyboard on Android
+[FIX]           `utils::getTimeInMilliseconds()` may return wrong value on Android
+[FiX]           link error that `bsd_sinal` is not defined if building with API level 21+ and uses libwebsockets on Android
+[FIX]           compiling error with Android 6.0(API 23)
+[FIX]           music is not resumed when app is reactived on iOS
+[FIX]           random crash in `alGenBuffers` at startup on iOS
+[FIX]           can not play audio if uncache and play audio many times on iOS
+[FIX]           `Text::create()` crash if it contains invalid string on iOS
+[FIX]           `FileUtils::removeDirectory()` can not work on all platforms except iOS and Mac
+[FIX]           can not compile cocos2d-x on Mac OS X 10.10 and lower
+[FIX]           new js project link error on linux
+[FIX]           AudioEngine can not play large ogg file on Windows
+[FIX]           design resolution broken after minimize on desk platforms
+[FIX]           can not get the `backClicked` in lua
+[FIX]           `cc.convertColor` issue in lua
+[FIX]           browser version detection
+[FIX]           compiling error with `cocos gen-libs`
+[FIX]           spine track entry can circle reference each other
+[FIX]           global object can leak during restart in JSB
+[FIX]           progress timer nested sprite can't change color in Canvas
+[FIX]           layout refresh issue in web engine
+[FIX]           dom element position synchronization issue in web engine
+[FIX]           armature position shake when parent node move in web engine
+[FIX]           rendering issue for Armature using sprite as display in bone in web engine
+[FIX]           Scale9Sprite GRAY state isn't correct in WebGL
+[FIX]           touch startPoint can be overwrote in web engine
+[FIX]           syncStatus transform dirty flag isn't resetting in web engine
+
+cocos2d-x-3.12 Jul 06 2016
+
+[HIGHLIGHT]     add VR support
+[HIGHLIGHT]     add Tizen support
+[HIGHLIGHT]     fix Android performance issue
+[HIGHLIGHT]     Web engine performance improved in WebGL mode
+[HIGHLIGHT]     support obb extension on Android
+
+[NEW]           Core: add `utils::findChild()`
+[NEW]           Core: add CSV format support to tile maps
+[NEW]           Core: add `FileUtils::getContents()`
+[NEW]           Core: cocos2d::Value supports unsigned
+[NEW]           Particle: add feature to pause/resume particle emitter
+[NEW]           Platform: support Windows 10 UWP x64
+[NEW]           UI: add clamp and shrunk feature for system fonts, currently only support iOS, Android and Mac
+[NEW]           UI: make ListView select item programmatically
+[NEW]           UI: add `EditBox::InputFlag::LOWERCASE_ALL_CHARACTERS` to lowercase characters
+[NEW]           UI: add `setBounce()` to WebView
+[NEW]           Web: refactor TMXLayer renderers
+[NEW]           Web: can force orientation in mobile browser
+[NEW]           Web: support high resolution TTF Label on retina display
+
+[REFINE]        Android: use clang instead of gcc to compile codes
+[REFINE]        Android: hide virtual button by default
+[REFINE]        Android: set music volume control as default
+[REFINE]        Android: usage clang insteand of gcc to compile codes
+[REFINE]        Audio: catch `IllegalStateException` exception to avoid crash when playing background music with SimpleAudioEngine on Android
+[REFINE]        Core: fix many warnings
+[REFINE]        Core: move StringUtils functions from deprecated header file to ccUTF8.h
+[REFINE]        Core: FontFNT will ignore chars that exceeds 65535 and print a warning information
+[REFINE]        Core: `Node::ignoreAnchorPointForPosition()` is deprecated and add `Node::setIgnoreAnchorPointForPosition()`
+[REFINE]        Core: allow inherit from platform FileUitils
+[REFINE]        Core: add optional alpha parameter to Color4B and Color4F
+[REFINE]        Core: Follow action can accept horizontal and vertical offset
+[REFINE]        Core: TMXXMLParse parse `id` element
+[REFINE]        Lua: rename all member functions named `end()` to `endLua()`
+[REFINE]        JSB: make selectedSprite opitional in MenuItemSprite
+[REFINE]        JSB: return null if read failed in `js_cocos2dx_CCFileUtils_getDataFromFile()`
+[REFINE]        Template: iOS tempalte is refined to make cocos2d-x game scene work better with other UIView
+[REFINE]        Template: remove `build_native.sh`
+[REFINE]        Template: ARC support on iOS and Mac OS
+[REFINE]        UI: TTF and BMFont label wrap mode will automanytically changed to char wrap mode when label's width is less than word's boundary
+[REFINE]        UI: UIWidget adds missing properties for clone
+[REFINE]        UI: UIScrollBar caches the texture created with base64 encoded images
+[REFINE]        UI: EditBox now prints lowercase letters by default
+[REFINE]        UI: enable WebView's local storage on Android
+[REFINE]        UI: improve EditBox implementation on WinRT
+[REFINE]        UI: make PageView indicator more tunable
+[REFINE]        UI: make PageView page turning event time tweak configurable
+[REFINE]        UI: RichText is improved: add effect of outline, shadow and glow; catch the event of open url; ability to extend tags; add anchor of image tag
+[REFINE]        3D: skeleton animation is more efficient when two animations switch frequently
+[REFINE]        3rd party: update webp to 0.5.0
+[REFINE]        Web: improve basic types to reduce memory usage
+[REFINE]        Web: Show line number in console statements
+[REFINE]        Web: Cache base64 image of PageViewIndicator and ScrollViewBar
+[REFINE]        Web: Pass error in cc.AsyncPool in onEnd callback
+[REFINE]        Web: Separate ccui.ListView event callback from ccui.ScrollView for its own events
+
+[FIX]           Android: fix compiling error if using NDK r11+
+[FIX]           Android: package name is `libcocos2dx` instead of application name if building with Android Studio
+[FIX]           Audio: AudioEngine can not work if the file path contains not ascii code on iOS
+[FIX]           Audio: SimpleAudioEngine::playEffect() doesn't work correctly on Linux
+[FIX]           AssetsManager: can not work
+[FIX]           AssetsManagerEx: use manifestUrl from remote version
+[FIX]           Core: `FileUtils::writeValueMap()` will crash on iOS if it contains `Value::Type::None` type element
+[FIX]           Core: `ClippgNode::setStencil()` may cause assert error if it is invoked before
+[FIX]           Core: `TextureCache::addImageAsync()` doesn't set pixel format corretly
+[FIX]           Core: `GL::SetBlending()` doesn't set dst correctly
+[FIX]           Core: vertex z can not work correctly if window size changed on desktop platforms
+[FIX]           Core: use `std::isnan()` instead of `isnan()` to fix compiling errors on some Linux platforms
+[FIX]           Core: crash on windows when using PolygonInfo
+[FIX]           Core: fix `libpng error: CgBI: unhandled critical chunk` error with Xcode 7.3
+[FIX]           Core: EXC_BAD_ACCESS random crash caused by reallocation of shared indices memory
+[FIX]           Core: memory leak of `utils::captureScreen()` on iOS and Mac OS
+[FIX]           Core: assert error if remove an event listener twice at the same time
+[FIX]           Core: FileUtils::getValueMapFromFile() returns wrong value if it is a number with scientific notation on Android
+[FIX]           Core: UIGrayScale shader is not reloaded when reloading shaders
+[FIX]           Core: `SpriteFrame::clone()` doesn't clone polygonInfo
+[FIX]           Core: `FileUtils::createDirectory()` fails on Mac OS with sandbox
+[FIX]           Core: `cocos2d::Value` operator overloading of comparison `==` returns wrong value in case Type::VECTOR 
+[FIX]           Core: wrong content size if minisize
+[FIX]           Core: can not have a class named `Game` on Windows
+[FIX]           Core: crash if load bad image on Windows
+[FIX]           Core: custom shader uniforms and attributes do not have effect in DrawNode
+[FIX]           Core: blend mode doesn't work with animated sprite
+[FIX]           Core: `FileUtils::removeDirectory()` can not work correctly when the path is not end of `/` on iOS and Mac
+[FIX]           JSB: fix some bugs related with JSB debegger
+[FIX]           JSB: scheduler callback target lost
+[FIX]           JSB: missing scroll widgets constants
+[FIX]           JSB: if obj is undefined or null then attempt to access obj.__nativeObj leads to incorrect behavior
+[FIX]           JSB: use `require()` to require the same script twice may crash
+[FIX]           Lua: lua function is not invoked when error happens in websocket
+[FIX]           Network: HttpClient Content-type limitation on iOS
+[FIX]           Network: downloader crash when storage path contains spaces
+[FIX]           Network: SocketIO crash on reconnect
+[FIX]           Physics: PhysicsBody damping doesn't wrok
+[FIX]           UI: EditBox may cause `java.lang.IndexOutOfBoundsException` exception on Android
+[FIX]           UI: TextFieldTTF doesn't show password correctly
+[FIX]           UI: RichText crash on Windows
+[FIX]           UI: EditBox can not use custom font on Android
+[FIX]           UI: can not use TTF font on Android
+[FIX]           RenderTexture: `setOpacity()` has not effect
+[FIX]           3D: `Sprite3D::createNode()` may not work correctly with particular model data
+[FIX]           Web: `getParentToNodeTransform` doesn't return result
+[FIX]           Web: remote image without extension in url can't be loaded as image
+[FIX]           Web: nested clipping nodes rendering issue in WebGL render mode
+[FIX]           Web: IMEDispatcher can't work in mobile Chrome
+
+
+cocos2d-x-3.11.1 May 27 2016
+
+[HIGHLIGHT]     Supports IPv6-only network
+
+[FIX]           Fix `cocos gen-libs` compiling issue
+
+cocos2d-x-3.11 May 11 2016
+
+[HIGHLIGHT]     Physics: upgrade chipmunk to v7.0.1
+[HIGHLIGHT]     JS: new memory model, don't have to use retain/release in JS
+[HIGHLIGHT]     Curl: upgrade to v7.48
+[HIGHLIGHT]     OpenSSL: upgrade to 1.0.2g
+[HIGHLIGHT]     JS: can use Firefox 30+ and VSCode to debug cocos2d-x JSB programs
+
+[NEW]           JS: web console is enabled debugging JSB projects via firefox
+[NEW]           UI: add a setter for touch total time threshold in ScrollView
+[NEW]           UI: add ability to get font family
+[NEW]           UI: add xml support in RichText
+[NEW]           UI: add ability to stop auto scrolling in ScrollView
+[NEW]           UI: EditBox supports multiline on Mac
+[NEW]           UI: Scale9Sprite allows to set custom shaders
+[NEW]           UI: ImageView allows to set custom shaders
+[NEW]           UI: TextFiled supports cursor
+[NEW]           FileUtils: add missing getFileSize() for winrt
+[NEW]           Network: close websocket connection by dispatching a resetDirector event
+[NEW]           Tool: cmake supports on Android        
+
+
+[REFINE]        Network: upgrated to latest libwebsockets, add more callbacks and bugs fixed
+[REFINE]        Network: replace char* with std::string in HttpRequest
+[REFINE]        Renderer: TriangleCommand and QuadCommand are merged
+[REFINE]        2D: SpriteFrameCache takes pixelFormat into account if specified
+[REFINE]        UI: let ScrollView swallow touch events by default
+[REFINE]        JSB: make selectedSprite optional
+
+[FIX]           JS: firefox v30+ can not debug cocos2d-x JSB projects
+[FIX]           UI: can not get event when PageView was turning
+[FIX]           UI: bitmap font sizes are not loaded from binary .fnt files
+[FIX]           UI: some fonts were rendered incorreclty
+[FIX]           Action: TargetedAction::isDone() always return false
+[FIX]           Action: Repeat: will run actions more than speicific times, instant action will run one frame later
+[FIX]           2D: drawing in incorrect app state on iOS
+[FIX]           Platform: FileUtils::getValueVectorFromFile() returns wrong value on iOS and Mac
+[FIX]           Network: downloader crashed when storage path contains spaces on iOS
+[FIX]           Network: downloader may crash on Android
+[FIX]           HTTPAsyncConnection: crash when custom SSL certification is set on iOS
+[FIX]           AssetsManagerEX: will stuck at UPDATING forever if last task fails
+[FIX]           AssetsManagerEX: may repeatly update some assets and cause file write conflict
+[FIX]           Lua: fix display.wrapScene()
+
+cocos2d-x-3.10 Jan 11 2016
+
+[HIGHLIGHT]     UI: Rewrite Scale9Sprite and improve the scale9sprite performance and reduce memory consumption.
+[HIGHLIGHT]     UI: Change PageView to derive from ListView.
+
+[NEW]           Core: Added Application::getVersion() to get the app version.
+[NEW]           UI: Add PageView indicator.
+[NEW]           UI: Label add three Overflow type to new label, see release note for more information.
+[NEW]           UI: UIText::clone supports clone the text effect.
+[NEW]           Label: Add methods to query label effect state.
+[NEW]           UI: UIRichText support the new line element.
+
+[REFINE]        3rd party: WebP loading improvements WebP loaded as premultiplied alpha if it has.
+[REFINE]        UI: Slider `setCapInsetProgressBarRebderer` change to `setCapInsetProgressBarRenderer`.
+[REFINE]        UI: RichText support new line element.
+[REFINE]        UI: Set focus to Widget when touched.
+[REFINE]        3D: Change char* to string in Terrain.
+[REFINE]        Studio: Merge Studio ActionTimeLine change back into engine.
+[REFINE]        Studio: Merge Studio changes for compatible withe 32bit Mac System.
+[REFINE]        Studio: Merge Studio changes for lua-binding, js-binding and simulator.
+[REFINE]        Mac: Make engine compatible for 32bit Mac.
+[REFINE]        3rd party: WebP loading improvements WebP loaded as premultiplied alpha if it has.
+[REFINE]        Audio: AudioEngine on Linux replace the original SimpleAudioEngine with a new version of FMOD, now AudioEngine support all platforms!
+[REFINE]        IOS: Add virtual keyword for some render related function.
+[REFINE]        UI: Fixes boring deprecated warning in HttpRequest.
+[REFINE]        Network: Fix Downloader bug on iOS & Android platform.
+[REFINE]        Studio: Fix deprecation warning in SkeletonRenderer.
+[REFINE]        JS: Add js test case for fix, improve template.
+[REFINE]        Network: Permit http access to cocos2d-x.org in test projects on iOS.
+[REFINE]        Network: Crash when removing a remotely downloaded image from texture cache in js-binding.
+[REFINE]        Win10: WinRT project update version to v3.10.
+[REFINE]        Console: Add quiet option for Cocos Toolkit.
+[REFINE]        JS: New GC model for js-binding.
+[REFINE]        Doc: Fix typos in documentation and comments.
+[REFINE]        UI: update controlButton size calculate with new Scale9Sprite logic.
+[REFINE]        Win10: Added missing _USRJSSTATIC preprocessor define for ARM builds.
+[REFINE]        JS: Added ccvector_to / ccmap_to converted to new js-binding API.
+[REFINE]        UI: Slider misprint fix.
+
+[FIX]           Network: fix possible websocket crash in its destructor.
+[FIX]           Core: Fix premultiplyAlpha for mipmaps and compressed textures.
+[FIX]           UI: Fix Scale9sprite rendering error when content size smaller than the sum of leftInset and rightInset.
+[FIX]           Win32: Fix EditBox crash when removing an EditBox in a scheduler.
+[FIX]           Android: Fix cannot add view to mFrameLayout when extends Cocos2dxActivity.
+[FIX]           2D: Fixed actionNode set at wrong position bug.
+[FIX]           3D: Fix the  movement of PUParticle lags one frame.
+[FIX]           UI: Fix the wront argument of setPlaceholderFontName in EditBox.
+[FIX]           UI: Fix EditBox editBoxEditingDidEnd may use the original text after change the text of EditBox in user script.
+[FIX]           Audio: Fix `FinishCallback` never be called in Windows.
+[FIX]           UI: Fix Layout stencil clipping nested with Clipping Node rendering issue.
+[FIX]           UI: Keyboard doesn't hide when click the screen outside of EditBox on iOS platform.
+[FIX]           UI: Fix a fatal bug in EditBox implement on Windows platform.
+[FIX]           UI: Fix edit box setPlaceholderFontName and scale font size issue.
+[FIX]           Core: Fix memory leak when initWithImage() failed.
+[FIX]           Network: CCDownloader on iOS is broken in v3.9 js-binding.
+[FIX]           JS: Bindings fixes for Menu, Sprite and Label.
+[FIX]           Studio: Remove weak reference in ActionNode.
+[FIX]           UI: shouldStartLoading method should return value to js in js-binding.
+[FIX]           UI: Fix scrollview render error.
+[FIX]           JS: Fix win32 js project crash issue.
+[FIX]           UI: Button touch doesn't work with scale9 enabled.
+[FIX]           JS: Fix evalString doesn't return result issue.
+[FIX]           JS: Fix ComponentJS proxy management issue in JSB.
+[FIX]           Android: Fix include in cocos network module.
+[FIX]           Network: Fix web socket crash.
+[FIX]           UI: Fix TextField missing default password style text setting.
+
+[TEST]          S9SpriteTest: Scale9Sprite fade actions with cascade opacity.
+[TEST]          Web: Remove default focus block from UIFocusTestVertical.
+[TEST]          Lua: Fix pageViewTest Horizontal scroll won't work in Lua-test.
+
+cocos2d-x-3.9 November.09 2015
+
+[NEW]           Label: Added line spacing/leading feature to Label.
+[NEW]           ListView: Added APIs to scroll to specific item in list.
+[NEW]           ListView: Added APIs to get an item in specific position like center, leftmost, rightmost, topmost and bottommost.
+[NEW]           ListView: Added a feature for magnetic scrolling.
+[NEW]           Animate: Added ActionTimeline::setAnimationEndCallBack and ActionTimeline::addFrameEndCallFunc.
+[NEW]           Animate: Added CSLoader::createNodeWithVisibleSize, CSLoader::createNodeWithVisibleSize and moved "ui::Helper::DoLayout" into them.
+[NEW]           Studio: Added Light3D support for Cocos Studio.
+[NEW]           Platform: Added the missing CURL support to the Windows 10 UWP version.
+[NEW]           Platform: Added UIEditBox support on linux platform.
+
+[REFINE]        3D: Added non-null checks in PUScriptCompiler::visit before dereferencing.
+[REFINE]        3D: Refined SkyboxBrush by making the shader parameter take effect at once.
+[REFINE]        Label: Changed label font size type to float to support high precision when font size is small.
+[REFINE]        ListView: Fixed an issue that list view's Magnetic::CENTER is not working well when non-bounceable.
+[REFINE]        ListView: Added feature of jumping to a specific item in list view.
+[REFINE]        Sprite: Added "a unsupport image format!" log when creating a sprite in CCImage.cpp.
+[REFINE]        ScrollView: Merge logics of Scroll View for scroll by inertia and auto scroll into one.
+[REFINE]        Animate: Moved initialization of image to an appropriate location, because it always called twice in SpriteFrameCache::addSpriteFramesWithFile().
+[REFINE]        Simulator: Changed the size of startFlag to 13.
+[REFINE]        Simulator: Show Node and Skeleton in the middle of the simulator.
+[REFINE]        Simulator: Removed screen direction check in simulator to avoid render error.
+[REFINE]        Pysics: Refined components to improve physics performance.
+[REFINE]        UI: Refined ComponentContainer to improve performance.
+[REFINE]        UI: EventListenerMouse will dispatch EventMouse events.
+[REFINE]        OpenGL: Added check for glfwCreateWindow.
+[REFINE]        Platform: Fixed a crash on xiaomi2 if Cocos2d-x is built as a dynamic library.
+[REFINE]        Platform: Updated libcococs2d name to v3.9 on WinRT platforms.
+[REFINE]        Platform: Added some support for mouse on WinRT. Include: Show/Hide mouse cursor; Mouse event implemented similar Desktop version; Left button send mouse event and touch; Support other mouse button and scroll wheel.
+[REFINE]        Platform: Correct the convertion between unicode and utf8 on WinRT.
+[REFINE]        Platform: Improved EditBox implement on Win32 platform.
+[REFINE]        JS: Add jsb.fileUtils.writeDataToFile().
+[REFINE]        JS: Set js templates Mac target platform from null to 10.7.
+[REFINE]        JS: Removed the static define of variable in headfile of ScriptingCore.
+[REFINE]        Lua: Added AssetsManagerEx constants UPDATE_FAILED and ERROR_DECOMPRESS in Lua.
+[REFINE]        Lua / JS: Refined lua/js binding tool.
+[REFINE]        I/O: Refined AssetsManagerEx unzipping by using async.
+[REFINE]        Web: Improved logic of jsb_boot.js to sync with the web engine behavior.
+[REFINE]        Web: Sync with CCBoot for web.
+[REFINE]        Build: Fixed various compiler warnings on Xcode 7.
+[REFINE]        Build: Fixed Wformat-security warning on Xcode.
+[REFINE]        Build: Fixed a compile error in __LayerRGBA.
+[REFINE]        Tool: Added tools for generating documents automatically.
+[REFINE]        Doc: Clean up the code of setRect() function.
+[REFINE]        Doc: Fixed a minor typo and renamed INTIAL_CAPS_ALL_CHARACTERS to INITIAL_CAPS_ALL_CHARACTERS in UIEditBox.
+
+[FIX]           3D: Fixed a bug that obb did not rotate with Sprite3d.
+[FIX]           3D: Corrected spot light init value.
+[FIX]           3D: Added the missing CCMotionStreak3D files.
+[FIX]           3D: Fixed a bug in CCPhysics3DComponent.cpp that oldBool is set with a wrong value.
+[FIX]           3D: Fixed shader light parameter bug that caused for that all the mesh share light parameter.
+[FIX]           Sprite: Fixed a bug that CC_SPRITE_DEBUG_DRAW did nothing in Cocos2d-x. 
+[FIX]           Button: Fixed an issue that when image size of variable button status texture are different, Helper::restrictCapInsetRect result may stop the pressed & disabled status picture from loading.
+[FIX]           Font: Fixed a crash bug in destructor of FontFreeType.
+[FIX]           Label: Removed scale factor for label shadow.
+[FIX]           Label: Added missing override keyword.
+[FIX]           LoadingBar: Fixed a crash bug in LoadingBar.
+[FIX]           ScrollView: Removed ScrollView::_innerContainer pointer copy.
+[FIX]           Particle: Fixed a bug of nomalize_point which caused particle rendering error.
+[FIX]           Tilemap: Fixed a TMXLayer bug: When using float values (for example the actual position of the character) to get the current tile, the wrong tile is sometimes/usually returned.
+[FIX]           Animate: Fixed a crash bug when csb file is broken.
+[FIX]           Animate: Fixed a bug that a same frame index is inserted after animation speed is scaled. 
+[FIX]           Animate: Fixed bug in v1.6 that bone animation crashed when performing getBoneAtPoint(0,0).
+[FIX]           Animate: Fixed crash when recall a cached timeline after scene exited.
+[FIX]           Animate: Fixed debug-config crash if a FrameBuffer has no RenderTargetDepthStencil.
+[FIX]           UI: Fixed an image bug caused by the _hasPremultipliedAlpha field.
+[FIX]           UI: Added missing getChildByTag<>() API.
+[FIX]           UI: Fixed a bug in Widget::isClippingParentContainsPoint: _hittedByCamera may be null.
+[FIX]           UI: Fixed a bug that cocos2d::Map may cause Dangling Pointers when inserting Ref Object which already exist in the Map.
+[FIX]           UI: Fixed a bug in Scheduler which may case Force Close.
+[FIX]           OpenGL: Fixed a bug of ui::WebView callback operate in OpenGL.
+[FIX]           Performance: Fixed a bug that NotificationNode was not entered and exited.
+[FIX]           Renderer: Fixed a bug that Material::clone failed to set the parent correctly.
+[FIX]           Simulator: Fixed a bug that when scene was set to a very large size(eg. 2048x1536), the simulator window was out of screen.
+[FIX]           Simulator: Fixed a compilation issue about simulator on Android x86.
+[FIX]           Skeleton: Removed redundant interface in CCSkeletonNode.
+[FIX]           Studio: Fixed a bug about Cocos Studio GUItest that MoveBy vertical direction under lua test project cannot scroll back to page 1 from page 2.
+[FIX]           Studio: Hide menu "cocostudio 2.1" for JSON exported from Cocos Studio 2.x is not supported in CocoStudio 1.6.
+[FIX]           Studio: Fixed bug that when create project from template, the app name of android-studio project is not changed.
+[FIX]           Platform: Fixed a bug that Android activity destroyed after reopening the app.
+[FIX]           Platform: Fixed a crash bug of AudioPlayer in Win32.
+[FIX]           Platform: Fixed an error about Chinese input in textfield with specific IME on Android.
+[FIX]           Platform: Fixed missing image asset in Win10 UWP manifest.
+[FIX]           Platform: Fixed Windows 10 UWP app manifest by correcting image asset paths.
+[FIX]           Platform: Fixed a bug that FileUtils::GetFileSize can't treat multi-char path.
+[FIX]           Platform: Fixed a bug of loading pluginx lib when compile Android with --compile-script flag.
+[FIX]           Platform: Fixed a crash bug caused by integer overflow in Device::getTextureDataForText on iOS.
+[FIX]           Platform: Fixed the broken v3 Win10 UWP build by removing CCComponentPhysics2d files from the libcocos2d project.
+[FIX]           Platform: Fixed travis-scripts/before-install.sh.
+[FIX]           Platform: Fixed a bug in FileUtilsWin32::removeDirectory when the file begins with ".".
+[FIX]           Platform: Corrected the keyboard codes for Desktop and WinRT.
+[FIX]           JS: Fixed a freeze bug of playing animation in JS projects.
+[FIX]           JS: Fixed build_native for JS default template.
+[FIX]           JS: Fixed wrong number of param in Place and RotateTo.
+[FIX]           Lua: Fixed a bug of luabinding enumerateChildren.
+[FIX]           Web: Fixed wrong callback setting for webview:setOnDidFailLoading in Lua.
+[FIX]           Web: Fixed life control for XMLHttpRequest.
+[FIX]           Web: Fixed WebView lua-bind method name.
+[FIX]           Build: Fixed msbuild by removing incorrect AppxBundle properties from project.
+[FIX]           Build: Fixed the Enable_Bitcode compile error on Xcode 7.
+[FIX]           Build: Fixed compile error for new project created by template.
+[FIX]           Changed some delete operations to be deletions of arrays where applicable.
+[FIX]           Changed some "free" operations to "delete" where memory was allocated with "new"."
+[FIX]           Revert "remove CCClippingRectangleNode transform error support.".
+
+[TEST]          3D: Fixed a bug that lua Scene3DTest "back" button did not work.
+[TEST]          Button: Added a testcase of Button opacity settings.
+[TEST]          PageView: Fixed a bug that UIPageViewVerticalTest in cpp-test failed to scroll back to page 1.
+[TEST]          Particle: Fixed a bug that particle test under lua has different display effects in different platforms.
+[TEST]          Scale9Sprite: Added a test case of opacity/color cascade for Scale9Sprite.
+[TEST]          Scale9Sprite: Added testcase for s9sprite action.
+[TEST]          ScrollView: Added testcase for multiple items in ScrollView.
+[TEST]          SliderBar: Fixed bug of slider bar that it doesn't refresh percentage value under project cpp-test.
+[TEST]          SliderBar: Fixed a crash bug  in "Scheduler->Scheduler ttimeScale Test" when drag slider to left then click the middle of slider bar.
+[TEST]          Animate: Added custom spine skeletonAnimation testcase.
+[TEST]          UI: Added DrawLabel Mode testcase.
+[TEST]          UI: Fixed a bug that Node:Text Input test in cpp-tests touch detection is wrong.
+[TEST]          UI: Improved UItestcase modification to make it user friendly.
+[TEST]          Physics: Fixed a bug that quickly click mouse in "41:Node:Physics -> 6:joints" in cpp-test may cause program crash.
+[TEST]          Studio: Fixed a crash bug of Cocos Studio 3d test under lua test project.
+[TEST]          Platform: Solved the crash of performance-tests on Windows.
+[TEST]          Debug: Fixed a bug that RefPtr test wasn't executed even in debug build.
+[TEST]          JS: Fixed crash bug when click "remove ui" in "native test-JSBExtendTest" under project js-test.
+[TEST]          JS: Updated testcase in js-test to show notificationNode to runAction.
+
+cocos2d-x-3.8.1     September.17 2015
+
+    [HIGHLIGHT]     platform: Supported Xcode 7 for iOS 9 deployment
+
+cocos2d-x-3.8 final September.6 2015
+cocos2d-x-3.8 rc0   August.26 2015
+cocos2d-x-3.8 beta0 August.14 2015
+    
+    [HIGHLIGHT]     3D: Added 3d physics collider
+    [HIGHLIGHT]     3D: Supported setting camera background brushes with color/depth/skybox 
+    [HIGHLIGHT]     3D: Added key frame event Callback in Animate3D
+    [HIGHLIGHT]     FileUtils: Added a set of file writing APIs: writeStringToFile, writeDataToFile, writeValueMapToFile, writeValueVectorToFile
+    [HIGHLIGHT]     UI: Refined UI system
+    [HIGHLIGHT]     UI: Added RadioButton widget (JSB/Lua ready)
+    [HIGHLIGHT]     UI: Reimplemented and enhanced EditBox on Android: display cursor; support copy, cut, paste and select actions; support multi-line input; pretty adjustment when virtual keyboard shown
+    [HIGHLIGHT]     JS: Bound new AudioEngine in JSB
+    [HIGHLIGHT]     JS: Merged JSB test project into cocos2d test project
+    [HIGHLIGHT]     network: Upgrade SocketIO support to v1.x
+    [HIGHLIGHT]     tools: Optimize Bindings Generator
+    [HIGHLIGHT]     Label: Added HANYI FullType font support
+
+    [NEW]           3D: Added light map support in Terrain
+    [NEW]           UI: Added ScrollViewBar for displaying a scroll bar at the side of ScrollView (JSB/Lua ready)
+    [NEW]           UI: Enhanced ScrollView with easing out scrolling
+    [NEW]           UI: Added PageView vertical scroll support
+    [NEW]           UI: Added PageView::JumpToPage API
+    [NEW]           UI: Added a setter for line width in DrawNode
+    [NEW]           Action: Permitted setting bitwise flags to action
+    [NEW]           Animate: Added Animate's getCurrentFrameIndex function
+    [NEW]           FileUtils: Added FileUtils::getFileExtension for getting file's extension name
+    [NEW]           Device: Added vibrate support to enable vibration for a duration
+    [NEW]           audio: AudioEngine supported audio preloading
+    [NEW]           UserDefault: Supported removing key pairs from UserDefault
+    [NEW]           spine: Supported Spine runtime 2.3 (Both native and web engine)
+    [NEW]           JS: Added auto binding for BlendFuncFrame
+    [NEW]           console: Supported new portrait projects from templates
+    [NEW]           console: Moved the framework-compile tools into cocos2d-console
+    [NEW]           framework: Support generate prebuilt libs of engine with debug mode
+    [NEW]           Supported Xcode 7
+
+    [REFINE]        3D: Supported composite 2D/3D scene by moving UI and camera far away
+    [REFINE]        3D: Improved Particle3D performance
+    [REFINE]        3D: Made SkyBox not transparent 
+    [REFINE]        3D: Enable depth write for SkyBox
+    [REFINE]        3D: Enable depth write for transparent object
+    [REFINE]        3D: Set depth test function of Skybox brush to always
+    [REFINE]        renderer: Enabled blending all the time for 2D render queue
+    [REFINE]        Director: Made types to handle time consistent by modifing setAnimationInterval argument from double to float
+    [REFINE]        Sprite: Made Sprite::setTexture accept nullptr as parameter
+    [REFINE]        TextureCache: Made addImageAsync function thread safe
+    [REFINE]        Label: Improved code readability
+    [REFINE]        Label: Supported adding child nodes in Label
+    [REFINE]        Label: Refine the implementation about text layout and support debug draw
+    [REFINE]        Label: Supported auto batch with bitmap font or char map
+    [REFINE]        UI: Improved Slider's precision
+    [REFINE]        UI: Made Label and Text share the same fontSize type
+    [REFINE]        UI: Reduced memory usage in Text
+    [REFINE]        UI: Refined scroll event dispatching for ScrollView
+    [REFINE]        UI: Made EditBox::setFontSize not rely on font name property
+    [REFINE]        UI: Made viewport constructor more compile friendly
+    [REFINE]        UI: Improved event handling in TextField
+    [REFINE]        studio: Avoid CSLoader from openning csb file multiple times with fopen
+    [REFINE]        studio: Added BlendFrame support to Skeleton Animation
+    [REFINE]        studio: Enabled blendfunc cascade to the skin of BoneNode 
+    [REFINE]        studio: Update reader with parse logic for valid attribute of SkyBox
+    [REFINE]        FileUtils: Remove old path while adding existing search path
+    [REFINE]        Device: Implemented Device::getDPI for Mac
+    [REFINE]        network: Refine NSLog in HttpAsynConnection in release mode
+    [REFINE]        network: Fixed a problem where WebSocket messages may pile up
+    [REFINE]        utils: Made utils::captureScreen saving file in another thread to improve the performance
+    [REFINE]        3rd party: Update Nibiru SDK to 2.6
+    [REFINE]        platform: Correct all usage of unicode version winapi in FileUtils for win32
+    [REFINE]        JS: Supported new construction for 3d classes in JS
+    [REFINE]        JS: Automatically add extend to need to extend classes in bindings generator
+    [REFINE]        JS: Made UI classes safely extendable in JSB
+    [REFINE]        JS: Improved NodeGrid binding
+    [REFINE]        JS: Refine performance for Cocos Studio JSON parser for 2.x
+    [REFINE]        JS: Made binding functions accept null in JS and convert to nullptr
+    [REFINE]        web: Avoid re-bake the content when the parent node's position get changed
+    [REFINE]        web: Solved repeat loading same resource issue when parsing cocos studio project
+    [REFINE]        web: Added GameNodeObjectData and GameLayerObjectData in JSON parser
+    [REFINE]        web: Updated skeleton animation to the latest version
+    [REFINE]        web: Optimized resources automatic loading in JSON parser
+    [REFINE]        web: Avoid cc.loader resource loading being terminated while encounter errors
+    [REFINE]        web: Throw new Error object instead of error message string
+    [REFINE]        web: Move setDepthTest to renderer
+    [REFINE]        web: Added BlendFuncFrame parser
+    [REFINE]        web: Permitted webp image loading on Chrome
+    [REFINE]        web: Suspended the video player when the browser is minimized
+    [REFINE]        framework: Optimized the lua & js templates
+    [REFINE]        simulator: Made Node, Skeleton needs shown in the middle of the simulator window
+    [REFINE]        Removed EMSCRIPTEN support
+    [REFINE]        Added template project daily build in Jenkins-ci
+    [REFINE]        Removed unused tool gen-prebuilt
+    [REFINE]        Removed deprecated API in templates
+
+    [FIX]           3D: Fixed Effect3DOutline issue when the Sprite3D is mirrored
+    [FIX]           3D: Fixed issue that Sprite3D::getAABBRecursively does not get AABB of Nodes with Sprite3d children
+    [FIX]           3D: Fixed Menu unusable in 3D scene
+    [FIX]           renderer: UI component can't click correctly by moving UI and camera far away of origin
+    [FIX]           renderer: ListView in Camera with custom mask isn't visible
+    [FIX]           renderer: Temporary fix for Sprite/Label/FastTMX auto-culling failure
+    [FIX]           renderer: Fixed shader issue by reloading shader when light number changed
+    [FIX]           Scheduler: Fixed timer's delta time is error when interval equals to zero
+    [FIX]           Scheduler: Fixed Pause/Resume act incorrectly
+    [FIX]           Scheduler: Fixed the callback will be executed multiple times if the value of delay parameter equal zero
+    [FIX]           Node: Fixed issue that euler angle is NaN when update Euler angle from quaternion and asin value is not between -1 and 1 by accident
+    [FIX]           Scene: Fixed bug that can't add custom member to Scene subclass
+    [FIX]           Sprite: Fixed some warnings and a related bug in CCSprite
+    [FIX]           AutoPolygon: Fixed copy construct & assignment operator memory leakage
+    [FIX]           SpriteBatchNode: Touch screen might cause rendering order disorder when the screen have numerous sprites
+    [FIX]           SpriteBatchNode: Fixed SpriteBatchNode doesn't support setFlipped
+    [FIX]           event: Fixed EventDispatcher wrong dispatch order bug
+    [FIX]           event: Fixed EventListenerKeyboard.onKeyPressed not firing for back button on Android
+    [FIX]           FileUtils: Fixed bug that FileUtils::isDirectoryExist result is not correct on Android while using relative path in 'assets'
+    [FIX]           Action: Fixed bug that CCTargetedAction executes callback twice
+    [FIX]           audio: Fixed playing new audio after stopping an incessant(loop) audio may fail on MAC/iOS
+    [FIX]           audio: Fixed bug that playing audio may fail(error code:-1) on iOS
+    [FIX]           audio: Fixed AudioEngine possible crash on iOS/Mac while playing multiply audio
+    [FIX]           Label: Fixed rendering LabelTTF characters as black boxes on Android by ensuring atlases are purged before resetting
+    [FIX]           Label: Fixed bug that characters are displayed incorrectly with "dark roast.ttf" font
+    [FIX]           Label: Fixed opacity setting is invalid with bitmap font
+    [FIX]           Label: Fixed the color of letter will be overridden by fade action
+    [FIX]           Label: Fixed Label with some specific font is cropped
+    [FIX]           Label: Fixed the content size of Label is incorrect with GLOW effect
+    [FIX]           Label: Fixed spaces is lost if label created with Fingerpop.ttf
+    [FIX]           Label: Fixed Label::getLetter(index)->setVisible(true) cause rendering duplicate letters
+    [FIX]           Label: Fixed Label::setGlobalZOrder invalid issue if label create with system font
+    [FIX]           UI: Fixed issue that Slider::addEventListener doesn't respect the button pressed and button release event
+    [FIX]           UI: Fixed bug that UI component can't be clicked correctly by moving UI and camera far away of origin
+    [FIX]           UI: Fixed inertial scrolling for CCScrollView
+    [FIX]           UI: Fixed bug that ListView::getCurSelectedIndex may cause out of range issue
+    [FIX]           UI: Fixed PageView scrollToPage bug and the curPageIndex bug
+    [FIX]           UI: Fixed game scene displays wrongly while clicking EditBox
+    [FIX]           UI: Fixed RichText layout cause infinite loop issue
+    [FIX]           UI: Fixed formarRenderers in RichText doesn’t update container size
+    [FIX]           UI: Fixed TextField hitTest not working as expected issue
+    [FIX]           UI: Fixed Widget::setHighlighted does not work after setBright
+    [FIX]           UI: Fixed Button touch doesn't work with setScale9Enabled
+    [FIX]           UI: Fixed calculation error of Layout viewing area's clipping position in SCISSOR mode
+    [FIX]           UI: Fixed logic error in isMaxLengthEnabled handling invoked by TextField::setString
+    [FIX]           UI: Fixed improper touch intercept event propagation in UI system
+    [FIX]           UI: Fixed EditBox input maxLength for Chinese character issue on iOS
+    [FIX]           UI: Fixed EditBox turning black when soft keyboard hiding
+    [FIX]           UI: Fixed scrollview innerContainer initial position error
+    [FIX]           UI: Fixed issue that Slider create function is not taking account of res type (TextureResType)
+    [FIX]           Scale9Sprite: Fixed Scale9Sprite default capInset bug
+    [FIX]           Scale9Sprite: Fixed issue that Scale9Sprite draw extra 1 pixel when creating from spritesheet
+    [FIX]           studio: Removed "using namespace cocos2d" from CCFrame.h
+    [FIX]           studio: Fixed the SkyBox display error while parsed from editor files
+    [FIX]           studio: Fixed userCamera flag error while parsing old version exported files
+    [FIX]           studio: Fixed GameNode3DReader parse failed error
+    [FIX]           studio: Fixed crash when loading cocostudio json files with null or empty fontName
+    [FIX]           studio: Fixed bug that setColor works on a whole armature, but not on an individual bone
+    [FIX]           studio: Fixed object size error while data is error
+    [FIX]           studio: Fixed issue that bone's color and opacity cannot cascade to bone
+    [FIX]           studio: Fixed issue that bone can be see by other cameras
+    [FIX]           ClippingNode: Removed CCClippingRectangleNode transform error support
+    [FIX]           spine: Fixed the position of debug draw of bones is incorrect
+    [FIX]           spine: Fixed memory leak caused by SkeletonRenderer::initialize
+    [FIX]           network: Fixed Downloader::getHeader failure on win32
+    [FIX]           AssetsManagerEx: Fix AssetsManager crash by protecting Downloader with shared_ptr
+    [FIX]           RenderTexture: Fixed RenderTexture switch foreground to background issue
+    [FIX]           Physics: Fixed circle shape debug draw incorrect issue
+    [FIX]           Physics: Fix transform issue of PhysicsSprite itself and its children
+    [FIX]           tilemap: Fixed small errors in the function TMXXMLParser::getRectForGID
+    [FIX]           tilemap: Fixed crash caused by creating TMX object when related image file is missing or broken
+    [FIX]           effect: Fixed PageTurn3D effect abnormal
+    [FIX]           ProgressTimer: Fixed SpriteProgressToRadialMidpointChanged bug
+    [FIX]           log: Fixed crash on Windows if passing string more than 16kb to cocos2d::log
+    [FIX]           utils: Fixed utils::captureScreen bug while using multiple camera
+    [FIX]           JS: Fixed issue of iOS/JS reflection `callStaticMethod` with bool arg
+    [FIX]           JS: Fixed Objective-C JS reflection bug while using callStaticMethod() with bool argument
+    [FIX]           JS: Fixed issue that subclass of ccui.Widget which overwrote onEnter will cause infinite recursion
+    [FIX]           JS: Fixed Node color property can not be used issue
+    [FIX]           JS: Fixed issue that SocketIO events don’t get fired when compile mode set to release
+    [FIX]           JS: Added the conversion for tmxTileFlags to fix TMXLayer::tileFlagsAt binding issue
+    [FIX]           JS: Fixed jsval_to_int and jsval_to_uint issue on 64 bit system
+    [FIX]           Lua: Fixed onTouch begin don't return value
+    [FIX]           Lua: Fixed memory leak in LuaMinXmlHttpRequest
+    [FIX]           Lua: Fixed checkbox Lua bindings issue
+    [FIX]           Lua: Fixed logic issue in cc.pIsSegmentIntersect
+    [FIX]           platform: Fixed issue that getStringUTFChars can not passing emotion from java to c++ on Android
+    [FIX]           platform: Fixed bug that paused game will be awaked by the Clock on Android
+    [FIX]           platform: Fixed bug that Cocos2dxHelper won't be initialized after activity recreate
+    [FIX]           platform: Fixed clipping node doesn't work on Android 5.0
+    [FIX]           platform: Fixed blur shader compliant on win8 universal
+    [FIX]           platform: Fixed the error when compiling android project with release mode on Windows
+    [FIX]           platform: Fixed issue that depth/stencil buffers attributes are ignored on iOS
+    [FIX]           platform: Fixed engine crash because of wrong initialisation on some android device
+    [FIX]           platform: Removed unneeded protocol for AppController on iOS
+    [FIX]           platform: Fixed link errors in release mode on win32
+    [FIX]           platform: Fixed Windows 10 UWP and WP8.1 app certification issue
+    [FIX]           platform: Fixed Android app occasionally freeze issue caused by Cocos2dxRenderer.nativeOnResume() is not called when the activity is resumed
+    [FIX]           web: Fixed a bug that VideoPlayer remove event throw error
+    [FIX]           web: Fixed Armature position error in studio JSON parser
+    [FIX]           web: Fixed default clearColor error in director
+    [FIX]           web: Fixed rotation value parsing error in the timeline parser
+    [FIX]           web: Fixed a bug that nested animation may be affected by outer animation
+    [FIX]           web: Made LabelAtlas ignoring invalid characters and updating correctly the content size
+    [FIX]           web: Fixed a bug that VideoPlayer remove event throw error
+    [FIX]           web: Fixed a bug that cc.director.setNotificationNode(null) doesn't take effect
+    [FIX]           web: Fixed texture rect update issue while changing sprite frame
+    [FIX]           web: Fixed effect issue in ActionGrid and NodeGrid
+    [FIX]           web: Fixed logic issue in Menu's _onTouchCancelled function
+    [FIX]           web: Fixed MenuItem crash when normal image is null
+    [FIX]           web: Fixed CCTouch's startPoint unset issue
+    [FIX]           web: Fixed incomplete fadeout effects
+    [FIX]           web: Fixed issue that return value of cc.screen.fullScreen is not boolean
+    [FIX]           web: Fixed a bug that SkeletonNode is not drawing children
+
+    [TEST]          3D: Avoid to trigger touch event multiple times in Physics3D Test and Physics3D Constraint Test
+    [TEST]          3D: Fixed Sprite3D test background to foreground bug
+    [TEST]          renderer: Added auto culling test case
+    [TEST]          renderer: Fixed material parsing test on wp8.1
+    [TEST]          OpenGL: Fixed shader-basic and OpenGL testcase 'center' uniform error
+    [TEST]          OpenGL: Fixed ShaderRetroEffect random crash issue
+    [TEST]          OpenGL: Fixed offset on retina screen in shaderTest
+    [TEST]          OpenGL: Fixed shader test crash on android device
+    [TEST]          OpenGL: Fixed retro effect pos bug in ShaderTest
+    [TEST]          UI: Improved UIScene testcase
+    [TEST]          studio: Fixed cocostudio 3d test crash on mobile platform
+    [TEST]          studio: Added blendfunc Frame test case for skeleton animation
+    [TEST]          spine: Fixed bug that spine animition can't be rendered in Scene3DTest
+    [TEST]          tilemap: Fixed the problem that white frame didn't move as map did in JSB TMXOrthoObjectsTest
+    [TEST]          JS: Fixed Button position error in UIPageViewTest
+    [TEST]          web: Rewrote testcase for stencil depth mask in RenderTextureTest
+    [TEST]          web: Improved renderTexture stencilDepth test
+    [TEST]          web: Fixed abnormal effects in effectsTest
+    [TEST]          web: Fixed invisiable testcase of effects
+
+cocos2d-x-3.7.1    August.12 2015
+    [HIGHLIGHT]     studio: Added new skeleton animation support and csb parser for cocos v2.3.2 beta
+    [HIGHLIGHT]     studio: Added new skeleton animation support and JSON parser in the web engine
+    [HIGHLIGHT]     studio: Added Skybox csb/JSON parser for cocos v2.3.2 beta
+
+    [NEW]           Node: Added getNodeToParentTransform with selected ancestor
+    [NEW]           studio: Parsed Touch/Click/Event callback in JSON parser
+    [NEW]           web: Added cc.director.setClearColor and support transparent background
+
+    [REFINE]        Widget: Synchronize enable state and bright state for Widget
+    [REFINE]        studio: Optimized JSON parser's performance by removing audio play
+    [REFINE]        studio: Optimized editor related extension data to a component instead of hosting in _userObject
+    [REFINE]        studio: Updated Game3DNodeReader & UserCameraReader
+    [REFINE]        Label: Remove file error notice label from TextBMFontReader
+    [REFINE]        JSB: Add firefox remote debugger support in JS templates
+    [REFINE]        web: Improved color/opacity manipulations in MenuItems
+
+    [FIX]           Scene: Fixed Scene can't be inherited with std::vector members
+    [FIX]           Sprite: Fixed a compile error when CC_SPRITE_DEBUG_DRAW is on
+    [FIX]           Label: Fixed creation fail if the font(TTF) contains a non-unicode charmap
+    [FIX]           Label: Fixed LabelAtlas rendering error for invalid characters and characters out of boundaries
+    [FIX]           Label: Fixed Mac system font crash issue
+    [FIX]           platform: Fixed building with system prebuilt libs on Linux
+    [FIX]           studio: Fixed ccs.Skin construction issue in JSON parser
+    [FIX]           studio: Fixed Particle3d crash while reading file with error
+    [FIX]           studio: Fixed parser crash when sprite 3d resource isn't correct
+    [FIX]           UI: Fixed CheckBox issue that _isSelected state is updated after event processing callbacks
+    [FIX]           JSB: Fixed JSON parser issue that 3d particle can not be displayed
+    [FIX]           web: Fixed an issue that loading process won't trigger callback problem
+    [FIX]           web: Fixed a bug where not resetting cc.Audio._ignoreEnded when replaying a sound caused it to stay in a "playing" state
+    [FIX]           web: cc.ScrollView and cc.TableView: added check for parent visibility in onTouchBegan method
+    [FIX]           web: Fixed TurnPageDown effect
+    [FIX]           web: Fixed Cocos Studio parser issue that all elements are missing while the timeline action contains rotation
+
+cocos2d-x-3.7final July.21 2015
+    [REFINE]        JS: Improve manual binding code for `retain`, `release`, `onEnter`, `onExit`, `onEnterTransitionDidFinish` and `onExitTransitionDidStart`
+    [REFINE]        web: Add compatible Uint16Array defintion
+
+    [FIX]           Scale9Sprite: Fixed Scale9Sprite gray state issue while `setCapInsets` called
+    [FIX]           studio: Fixed parser issue by checking texture existance
+    [FIX]           studio: Fixed Armature parser issue
+    [FIX]           JS: Fixed cleanup overriding issue in JS that it will cause `too much recursion` error
+    [FIX]           web: Fixed url check regular expression not supporting localhost issue
+    [FIX]           web: Fixed issue that sprite doesn't update texture rect correctly in some condition
+
+cocos2d-x-3.7rc1  July.14 2015
+    [REFINE]        framework: Used msbuild to generating engine prebuilt libs on win32.
+    [REFINE]        3d: Used shader with normal while creating mesh with normals
+    [REFINE]        3d: Set default 3d animation quality to low
+    [REFINE]        web: Improved localStorage warning when disabled
+
+    [FIX]           studio: Fixed percentage setting won't take effect when UISlider's background resource set to null
+    [FIX]           studio: Fixed a bug that SingleNode's color isn't set
+    [FIX]           studio: Fixed child nodes can't be rendered when particle and TiledMap as parent and their resource have been removed from disk
+    [FIX]           studio: Fixed a bug of JSON parser that texture address is wrong
+    [FIX]           studio: Fixed a bug that drawLine & drawPoints don't apply blend function in parser
+    [FIX]           studio: Fixed a bug that check box front cross texture will expand to normal size when change status between normal and disable frequently
+    [FIX]           studio: Fixed a bug that normal texture won't show when slider set to disable mode then clean slider ball disable texture
+    [FIX]           3d: Fixed obj loading failed on windows
+    [FIX]           3d: Fixed clipping node does not work for Sprite3D
+    [FIX]           platform: Fixed js template run error on linux
+    [FIX]           Tilemap: Fixed CCTMXXMLParser code negligence
+    [FIX]           JS: Fixed constant value error for ccui.Layout.BACKGROUND_IMAGE_ZORDER
+    [FIX]           JS: Fixed XMLHttpRequest can't be retain in JSB
+    [FIX]           JS: Added cc.path.mainFileName
+    [FIX]           JS: Fixed issue that override cleanup function in JS can't get invoked during node detaching
+    [FIX]           JS: Fixed cc.loader notification issue with image asynchonous loading
+    [FIX]           web: Fixed MenuItems' color/opacity setter issue with child nodes
+    [FIX]           web: Fixed page view's layout issue for JSON parser
+    [FIX]           web: Add ttc loader and prevent the pure digital fonts is invalid
+    [FIX]           web: Fixed Float32Array initialization
+    [FIX]           web: Fixed a bug that layout background is missing
+    [FIX]           web: Fixed a bug that ObjectExtensionData miss setCustomProperty and getCustomProperty function
+
+cocos2d-x-3.7rc0  July.1 2015
+    [HIGHLIGHT]     core: Added Material system (JS/Lua ready)
+    [HIGHLIGHT]     3d: Added Physics3d support (JS/Lua ready)
+    [HIGHLIGHT]     3d: Added NavMesh support (JS/Lua ready)
+    [HIGHLIGHT]     Scale9Sprite: Added Android 9-patch image support (JS/Lua ready)
+    [HIGHLIGHT]     sprite: Supported polygon sprite with AutoPolygon generator (JS/Lua ready)
+    [HIGHLIGHT]     platform: Added Windows 10.0 Universal App(UWP) support
+    [HIGHLIGHT]     platform: Add Samsung Enhanced API on Android for cocos, please refer to the release note for more details
+    [HIGHLIGHT]     C++: Added Android Studio support
+    [HIGHLIGHT]     JS: Merged JSB and web engine into Cocos2d-x for a All-in-one engine
+    [HIGHLIGHT]     JS: Added `ccui.VideoPlayer` and `ccui.WebView` for iOS/Android/Web
+    [HIGHLIGHT]     console: Supported build & run Android Studio project with cocos console
+    
+    [NEW]           C++: Added ActionFloat
+    [NEW]           C++: Supported physical keyboard on WinRT
+    [NEW]           FileUtils: checked filename case characters on windows
+    [NEW]           FileUitls: added supporting loading files that which file path include utf-8 characters
+    [NEW]           PhysicsShape: added sensor property
+    [NEW]           Sprite: used triangle command
+    [NEW]           3d: Added `getFarPlane` and `getNearPlane` in `Camera` class
+    [NEW]           3d: Added opengl version project/unproject function in camera
+    [NEW]           ui: button add BMFont title support
+    [NEW]           ui: TextField add `getTextColor`, `getTextHorizontalAlignment` and `getTextVerticalAlignment` API
+    [NEW]           ui: Reduce memory consumption of a few UI widgets.
+    [NEW]           audio: added support on WP8.1, now it supports wav format
+    [NEW]           audio: Added MP3 support to winrt audio
+    [NEW]           audio: Added OGG support to winrt audio
+    [NEW]           3rd: updated rapidjson to v1.0.2
+    [NEW]           web: SIMD.js optimization for kazmath functions (from Intel)
+    [NEW]           web: The json loader of Cocos Studio will automatically load dependencies resources
+    [NEW]           Framework: Added Cocos Framework compilation script tool (used by Cocos)
+    [NEW]           Simulator: Added Cocos Simulator project (used by Cocos)
+
+    [REFINE]        core: Use quaternion instead of euler angle in `Camera::lookAt`
+    [REFINE]        platform: Differentiated Windows Phone Application and Windows Store Application with `Application::getTargetPlatform`
+    [REFINE]        platform: Improved UserDefault's robustness on Android, now the converting behavior is the same as iOS platform
+    [REFINE]        platform: Added debug flag -Wextra to linux CMakeFile
+    [REFINE]        audio: Permitted to play large ogg files on windows
+    [REFINE]        ui: Use inch for childFocusCancelOffset in UIScrollView
+    [REFINE]        3d: Improved `Terrain::getIntersectionPoint` by calculating the intersection with triangles
+    [REFINE]        Label: Improve rendering of letter's inner shapes when outline is used
+    [REFINE]        console: Built engine with `LOCAL_ARM_MODE=arm` when building JS projects for android
+    [REFINE]        web: Deleted the redundant variables defined and log informations in ccui.RichText
+    [REFINE]        web: Allowed timeline animations with only one frame
+    [REFINE]        web: Improved property declaration of cc.Texture2D
+    
+    [FIX]           core: Fixed `Director::setClearColor` has no effect bug
+    [FIX]           platform: Fixed VideoPlayer on Android ignore search paths
+    [FIX]           platform: Fixed crash while using s3tc on Nexus 9 (Android 5.0.1)
+    [FIX]           platform: Fixed Application may be created more than once on Android
+    [FIX]           platform: Fixed the Windows 8.1 Universal Apps crash when there is no audio device
+    [FIX]           platform: Fixed android background and foreground switching bug with VertexAttributeBinding
+    [FIX]           platform: Fixed warning "Service Intent must be explicit" on Android
+    [FIX]           studio: Fixed ActionNode memory leaks
+    [FIX]           studio: Fixed CocoLoader destructor memory release bug
+    [FIX]           studio: Fixed cocos studio json reader's bug in percentage mode
+    [FIX]           studio: Fixed rapidjson assert error in cocos studio module
+    [FIX]           network: Win32 CURL doesn't support zlib
+    [FIX]           network: Fixed memory leak of HttpClient on iOS and Mac platform
+    [FIX]           audio: Fixed program may freeze if `AudioEngine::stop` or `AudioEngine::stopAll()` is invoked frequently on Android
+    [FIX]           audio: Fixed a freezing crash in Windows 10 with the new audio engine when pressing stop after play
+    [FIX]           audio: Fixed audio can't resume if it is interrupted by an incoming phone call
+    [FIX]           audio: Fixed `SimpleAudioEngine::playEffect` lagged on Android 5.0.x
+    [FIX]           audio: Fixed `SimpleAudioEngine` may cause application to crash on Android 5.0.x
+    [FIX]           audio: Fixed thread safety problem on Android
+    [FIX]           audio: Added guard to audio engine pointer in `SimpleAudioEngine::end`
+    [FIX]           ui: Text scale factor is wrong with multiline text
+    [FIX]           3d: skybox can't move to other position except origin point in world space
+    [FIX]           3d: terrain can't move to other position except origin point in world space
+    [FIX]           3d: Fixed Terrain lod computing bugs
+    [FIX]           3d: Fixed clipping node not working for Sprite3D
+    [FIX]           3rd: Fixed PIE link error on iOS caused by libpng and libtiff
+    [FIX]           3rd: Fixed iOS libtiff 32bit header file error
+    [FIX]           AssetsManager: crashed issue
+    [FIX]           EaseRateAction: no way to create an `EaseRateAction` instance
+    [FIX]           Label: Fixed compile error when enabling CC_ENABLE_BOX2D_INTEGRATION
+    [FIX]           Label: crashed if invoking `setString(text` after `getLetter(letterIndex)` and `letterIndex` is greater than the length of text
+    [FIX]           Label: position is wrong if label content is changed after invoking `getLetter(letterIndex)`
+    [FIX]           Label: shadow effect cause OpenGL error on iOS
+    [FIX]           Label: outline effect doesn't match characters well
+    [FIX]           Label: Fixed system font label line height calculation is wrong  on Android.
+    [FIX]           Label: Fixed IllegalArgumentException on Android 2.3.x
+    [FIX]           Label: Fixed line wrap error without space. 
+    [FIX]           Label: The texture of character have not cropped if character cross the axis-aligned bounding-box
+    [FIX]           Label: Fixed the top of character's texture may be tailored if enable outline effect
+    [FIX]           ProgressTimer: `setSprite()` doesn't take effect
+    [FIX]           Sprite3D: setGLProgram() does not work
+    [FIX]           Sprite3D: transition breaks when there is a Sprite3D in the scene
+    [FIX]           Terrain: terrain is on top of particles, particles can not be seen
+    [FIX]           TextureCache: unbindImageAsync failed to unbind all asynchronous callback for a specified bound image
+    [FIX]           TileMap: crashed if a layer contains nothing
+    [FIX]           WebView: memory leak on iOS
+    [FIX]           WebView: Fixed crash on Android
+    [FIX]           WebView: crashed if url contains illegal characters on Android
+    [FIX]           Lua: luaLoadChunksFromZip should just remove .lua or .luac extension
+    [FIX]           Lua: Added some skipped create functions for Sprite
+    [FIX]           Lua: Fixed some lua test case bugs
+    [FIX]           JS: Enabled touches support for Windows 8.1 platform
+    [FIX]           JS: Fixed keyboard support for Windows Phone 8.1 platform
+    [FIX]           web: Fixed positionType error of particle system in timeline parser
+    [FIX]           web: Fixed setAnimationName issue while the property is undefined in timeline parser
+    [FIX]           web: Fixed `cc.TMXObjectGroup#objectNamed` not returning the result bug
+    [FIX]           web: Fixed TransitionSlideX callback sequence issue
+    [FIX]           web: Fixed issue in music end event
+    [FIX]           web: Fixed bug that LayerColor's color will disappear when update transform after being baked
+    [FIX]           web: Fixed `inverse` function bug of `cc.math.Matrix4`
+    [FIX]           web: Fixed the webaudio's invalid loop attribute bug for chrome 42
+    [FIX]           web: Fixed crash when character not found into BMP font
+    [FIX]           web: Fixed spine's js parser issue by avoid NaN duration
+    [FIX]           web: Fixed LabelTTF multiline detection
+    [FIX]           web: Fixed issue in ccui.Widget#getScale
+    [FIX]           web: Fixed texture is not updated in some cases
+    [FIX]           web: PlayMusic should not use the search path (timeline 2.x)
+    [FIX]           web: Fixed bug of loading path of resources
+    [FIX]           web: Premultiply texture's alpha for png by default to fix Cocos Studio render issues
+    [FIX]           web: Fixed cache update issue of Layout after bake
+    [FIX]           web: Fixed isBaked returning undefined issue
+    [FIX]           web: Made CCProgressTimerCanvasRenderCmd to properly show colorized sprites
+    [FIX]           web: Fixed attributes being reset issue while baked cache canvas' size changed
+    [FIX]           web: Fixed texture does not rotate bug of ccui.LoadingBar
+    [FIX]           web: Fixed color not being set issue in timeline parser
+    [FIX]           web: Fixed custom easing animation bug
+    [FIX]           web: Fixed return empty texture2d bug when adding image with same url multiple times
+    [FIX]           web: Fixed actiontimeline can not step to last frame issue when loop play
+    [FIX]           web: Fixed the prompt can not be used in iOS wechat 6.2
+    [FIX]           web: Fixed restoring of sprite's color issue
+    [FIX]           web: Fixed Uint8Array initialize issue
+    [FIX]           web: Fixed cc.TextFieldTTF Delegate memory leaks
+    [FIX]           web: Fixed sorted result is wrong in cc.eventManager (_sortEventListenersOfSceneGraphPriorityDes)
+    [FIX]           web: Fixed BinaryLoader issue on IE11
+    [FIX]           web: Fixed the sprite's texture bug when frequently change the color
+    [FIX]           web: Fixed an issue that action will result in automatic termination
+    [FIX]           web: Fixed ScrollView initWithViewSize issue
+
+cocos2d-x-3.6  Apr.30 2015
+    [NEW]           3rd: update chipmunk to v 6.2.2 on Windows 8.1 Universal App
+    [NEW]           3rd: update freetype to v 2.5.5 on Windows 8.1 Universal App
+    [NEW]           C++: Added SpritePolygon
+    [NEW]           Label: added LabelEffect::ALL which can be used in disableEffect(LabelEffect) to disable all effects
+    [NEW]           Lua-binding: binded ui:WebView and added corresponidng test case
+    [NEW]           MathUtil: added `MathUtil::lerp()`
+    [NEW]           UserDefault: added `UserDefault::setDelegate()`
+    [NEW]           Vec2: added `Vec2::setZero()`
+    [NEW]           Vec3: added `Vec3::lerp()`
+    [NEW]           WP8: remove WP8 support because Angle don't support WP8 any more
+    [NEW]           WP8.1: added back button support
+
+    [FIX]           Animate3D: modify `Animate3D::setHighQuality()` Animate3D::setQuality(), add a new animation quality type none which means that will not update animation to the bone, it is useful when the Sprite3D is out of the screen, it can safe a lot of cpu time.
+    [FIX]           AnimationCurve: memory leak
+    [FIX]           Bundle3D: memory leak when failed to load file
+    [FIX]           HttpClient: memory leak on iOS
+    [FIX]           JNI: JNI illegal start byte error which causes crashing error on Android 5.0
+    [FIX]           PUParticleSystem3D: refactoring create function using initWithXXX
+    [FIX]           UI:VideoPlayer: crashed when playing streamed MP4 file on iOS
+    [FIX]           VideoPlayer: can not play videos on Android v2.3.x
+
+cocos2d-x-3.6beta0 Apr.14 2015
+    [NEW]           3rd: update Spine runtime to v2.1.25
+    [NEW]           MotionStreak: add `MotionStreak::getStroke()` and `MotionStreak::setStroke()`
+    [NEW]           Rect: added `Rect::intersectsCircle()`
+    [NEW]           UI:Text: add `Text::disableEffect(LabelEffect)` to disable a specific effect
+
+    [FIX]           3rd: link error on VS2012 caused by libpng
+    [FIX]           Label: position is wrong if it is visited by a new camera
+    [FIX]           Particle3D: crash on clone
+    [FIX]           Particle3D: "make local" now working correctly. "Make local" is a properties that toggles particle coordination between local and global.
+    [FIX]           Particle3D: particle rotation now no longer stacks up on each other
+    [FIX]           Particle3D: Ribbon Trail now positions correctly
+    [FIX]           Physics: rigid body's rotation is wrong if it is attatched to a node which rotation is not 0
+    [FIX]           Renderer: RenderQueue command buffer optimizing
+    [FIX]           UI:Button: use too much memory
+    [FIX]           UI:Text: content size is wrong after setting outline effect
+
+cocos2d-x-3.6alpha0 Apr.8 2015
+    [NEW]           3D: added texturecube support
+    [NEW]           3D: added skybox support
+    [NEW]           3D: added node animation support
+    [NEW]           3D: added terrian support
+    [NEW]           3rd: updated libcurl to v7.4 on all supported platforms except WP8/WP8.1 universal
+    [NEW]           3rd: updated chipmunk to v6.2.2
+    [NEW]           3rd: updated openssl to v1.0.11
+    [NEW]           3rd: updated freetype to v2.5.5
+    [NEW]           3rd: updated png to v1.6.16 on all supported platforms except WP8/WP8.1 universal because it is not needed on these two platforms
+    [NEW]           Animate3D: added `Animate3D::setHighQuality()` to set animation quality
+    [NEW]           Label: added disableEffect()
+    [NEW]           Lua-binding: used luajit arm64 version on iOS 64-bit devices
+    [NEW]           Sprite3D: getAABBRecursively return own aabb combining childeren's
+    [NEW]           Vec3: added `Vec3::add(float, float, float)` and `Vec3::setZero()`
+
+    [FIX]           Audio: memory leak
+    [FIX]           Audio: crashed on iOS 5.1.1
+    [FIX]           C++: lag issue if `Director::setContentScaleFactor` is called frequently
+    [FIX]           C++: CDT builder is enabled by default in cpp template on Android
+    [FIX]           Label: shadow color is incorrect
+    [FIX]           MenuItem: crash if `MenuItem::onExit` is called multiple times
+    [FIX]           Particle3D: particles' rotation affect particle system's rotation
+    [FIX]           Sprite3D: memory leak
+    [FIX]           Vec3: use inline function to improve performance
+    [FIX]           WebView: loadHTMLString() can not work if it is invoked in the same frame of creating a webview on iOS
+
+cocos2d-x-3.5 Mar.23 2015
+    [NEW]           EditBox: support Color4B
+
+    [FIX]           AutoRelasePool: memory leak if adding an element into pool when releasing auto release pool
+    [FIX]           EditBox: have a 100 bytes input limit on windows
+    [FIX]           FileUtils: getWritablePath() does not return correct writable path on Mac & Windows
+    [FIX]           HttpAsynConnection: can not get error content if response code less than 200 or response code greater or equal than 300
+    [FIX]           HttpResponse: reference count error causes assert error
+    [FIX]           Label: stroke color of system font is incorrect on iOS
+
+cocos2d-x-3.5rc0 Mar.13 2015
+    [NEW]           CocosStudio: add callback when loading a CSB file
+    [NEW]           Particle3D: more Particle Universe features are supported, add observers and event handlers
+    
+    [FIX]           Billboard: fix bug on transparent Billboard because of transparent queue
+    [FIX]           Bundle: bug that create bundle with empty path
+    [FIX]           Camera: camera is detroyed unexpectedly when call removeAllChildren
+    [FIX]           C++: use console in `build/build_native.sh`
+    [FIX]           Label: position is wrong if it is visited by a new camera
+    [FIX]           MotionStreak: can not work with MoveTo and MoveBy
+    [FIX]           MoveTo: disable reverse() because it is meaningless
+    [FIX]           Particle3D: to make path shorter, rename Particle Universe folder to PU, and files CCPUParticle3DXXX to CCPUXXX to fix compiling error on WP8
+    [FIX]           Particle3D: `loadMaterialsFromSearchPaths` bug on linux platform
+    [FIX]           Sprite3D: fix bug on transparent 3D Sprite because of transparent queue
+
+cocos2d-x-3.5beta0  Feb.27 2015
+    [NEW]           Added Particle3D
+    [NEW]           C++: add Romanian language support
+
+    [FIX]           Audio: audio can not resume if it is interrupted, and back from background
+    [FIX]           Cocos Studio UI: setCameraMask does not work for the Cocos Studio UI
+    [FIX]           C++: compiling error when using CC_USE_CULLING
+    [FIX]           Label: texture size of string has unexpected padding on iOS 7 and upper version
+    [FIX]           HttpClient: if the request data is started by a null character, it does not fill http body
+    [FIX]           HttpClient: memory leak on iOS
+    [FIX]           Sprite3D: `getAttachNode()` will fail when there is no bone with name
+    
+cocos2d-x-3.4 Jan.30 2015
+    [FIX]           Animate3D: `setSpeed` has not effect if `Animate3D` is used in Sequence
+    [FIX]           C++: will crash if built with armeabi-v7a enabled on Android devices that with armeabi-v7a architecture but doesn't support NEON instructions
+    [FIX]           C++: may crash if VAO is not supported
+    [FIX]           EditBox: content is not clipped correctly on windows
+    [FIX]           GLProgram: will cause crash on some devices that don't support more than 8 atrributes
+    [FIX]           HttpClient: not set response code when connecting failed on Android
+    [FIX]           Label: alpha channel of text color of system font has not effect
+    [FIX]           Label: use int for dimensions that will lose the precision
+    [FIX]           Label: labels will become white block after resume from background on some Android devices, such as xiaomi3
+    [FIX]           Label: improved parsing performance of bitmap font
+    [FIX]           Label: can not display `&` if using system font on windows
+    [FIX]           Lua-binding:studio-support: AnimationInfo is not binded 
+    [FIX]           New audio: not close file descriptor leads to that may causes game freeze if playing two many times(may be more than 1000) on Android
+    [FIX]           Node: anchor point has not effect to rotation, it always rotate along (0, 0)
+    [FIX]           Physics integration: Scale9Sprite can't run `Move` action and `Scale` action if used physical scene
+    [FIX]           SpriteFrameCache: `addSpriteFramesWithFil`e may crash if plist file doesn't exist
+    [FIX]           Sprite3D: material files (.mtl) are not loaded for any object when creating from an .obj file
+    [FIX]           UI::ImageView: rendered content size is wrong if `ignoreSize` is true and `Scale9` is not enabled
+    [FIX]           UI::Slider: when scale9 is enabled, the progress bar's rendering height is wrong
+    [FIX]           UI:Scale9Sprite: some position information will be lost when toggling `Scale9` state
+    [FIX]           UI::TextField: will get wrong event message if clicking `TextField` twice
+    [FIX]           UI::TextField: result of `getContentSize` is wrong if it is invoked in insert or delete event callback
+    [FIX]           UI::WebView: base URL can not work
+
+cocos2d-x-3.4rc1 Jan.15 2015
+    [NEW]           C++: added CC_USE_CULLING macro to control if enable auto culling or not 
+    [NEW]           FileUtils::fullPathForFilename will return empty string when file can not be found
+    [NEW]           VertexBuffer&IndexBuffer: allow setting usage(GL_STATIC_DRAW or GL_DYNAMIC_DRAW) in create method
+    [NEW]           Renderer: 3D rendering support for 2d objects
+    
+    [FIX]           DrawNode: fix random crash because of init opengl buffer wrongly 
+    [FIX]           DrawNode: drawPoints() can not set ponit size
+    [FIX]           EventDispatcher: crash if adding/removing event listeners and dispatching event in event callback function
+    [FIX]           GLProgramState: may cause GL_INVALID_VALUE error at start up on Android
+    [FIX]           LUA: 0x80000000 can not be converted by lua_tonumber correctly on some devices
+    [FIX]           PhysicsBody: can't get correct position in the same frame of adding PhysicsBody to PhysicsWorld
+    [FIX]           UI: fix crash when navigation controller is null
+
+cocos2d-x-3.4rc0  Jan.9 2015
+    [NEW]           3rd: update libcurl to v7.39
+    [NEW]           3rd: update luajit to v2.0.3
+    
+    [FIX]           C++: crash when run clang static analyzer in Xcode
+    [FIX]           DrawNode: can not set color when DrawPoints, wrong behavior of drawRect
+    [FIX]           FileUtils: getData() can't get data from file when file was using by other application on windows
+    [FIX]           FileUtils: getData() will cause memory leak if file size is 0 on windows
+    [FIX]           GLProgram: when there is a shader compile error in shader, it will crash on windows
+    [FIX]           GLProgramState: Assert error because uniforms and attribute is not refreshed when come to foreground on android
+    [FIX]           HttpClient: http requests will be lost in immediately mode on iOS
+    [FIX]           JumpTo: can not be applied more than once
+    [FIX]           Label: may cause infinite loop if using system font on Android
+    [FIX]           Particle: GL_INVALID_OPERATION error because VAO and VBOs is not reset when come to foreground on android
+    [FIX]           Physics integration: physics body is not still after disabling gravitational force by PhysicsBody::setGravityEnable()
+    [FIX]           Sprite3DTest: Sprite3DUVAnimationTest, Sprite3DFakeShadowTest, Sprite3DLightMapTest, Sprite3DBasicToonShaderTest will crash on android when switch to foreground from background
+    [FIX]           Template: multiple dex files define error on Android if using Eclipse to build new generated application
+    [FIX]           VideoPlayer: can not play video if passing path returned from FileUtils::fullPathForFilename() on Android
+    [FIX]           WP8: compiling error on ARM architecture
+
+cocos2d-x-3.4beta0  Dec.31 2014
+    [NEW]           3D: support frustum culling
+    [NEW]           Action: MoveTo and MoveBy support Vec3
+    [NEW]           Allocator: add custom allocator support, global, default, fixed block, object pool
+    [NEW]           Application: added Turkish and Ukrainian language support
+    [NEW]           UI:LoadingBar: add TextureResType to LoadingBar's create method
+    [NEW]           Director: add setClearColor() to set clear values for the color buffers
+    [NEW]           Node: rotation representation using quaternion
+    [NEW]           UI: Added new layout functionality for Cocos Studio, keeps widget margins a fixed set and adjusts the widget size according to the margins.
+    [NEW]           UI: Add gray shader to ui::Button, ui::CheckBox and ui::Slider when the disable state resources are not provided
+    [NEW]           UI: Modify the default behavior when ui::Button, ui::CheckBox and ui::Slider's selected state resources are not provided, the new behavior is scale the normal state texture when the selected state texture are missing.
+    [NEW]           3rd party libraries: Add prebuilt version of libcurl to Mac and upgrade iOS,Android,Mac and Win32 libcurl to 7.39.0.
+    [NEW]           Replace network module implementation from libcurl to system network API on IOS and Android
+
+    [FIX]           ui::Button: fix setTitleColor calls method setColor instead of setTextColor of title label.
+    [FIX]           AssetsManagerEx: Fix assetManager can't download file on Win32
+    [FIX]           FileUtils: WebP format with alpha channel displayed wrong
+    [FIX]           Label: content size of Label is incorrect if the string is set to empty string
+    [FIX]           GLProgramState: fix assert error caused by outdated uniform and attribute cache
+
+cocos2d-x-3.3 Dec.12 2014
+    [FIX]           Billboard: allow billboard rotate along z axis
+    [FIX]           Bundle3D: create aabb for mesh whose aabb does not exist (user custom mesh)
+    [FIX]           EditBox: text position and move animation error on iPhone6 Plus
+    [FIX]           FileUtils: createDirectory(): doesn't invoke closedir() after opendir on platforms other than WP8/WinRT/Windows
+
+cocos2d-x-3.3-rc2  Dec.5 2014
+    [FIX]           C++: use 100% of one core on Windows
+    [FIX]           Label: when a label is added to a invisible parent node, app will crash if switching from background
+    [FIX]           Label: label will not be shown when using system font on Mac
+    [FIX]           Studio reader: replace protocol buffer with flatbuffer 
+
+cocos2d-x-3.3-rc1  Nov.29 2014
+    [NEW]           Vec2: added greater than operator
+    [NEW]           Tools: Updated cocos console to v1.4 (from 1.2)
+    [NEW]           WP8: Win8.1 universal app support
+
+    [FIX]           Audio: `SimpleAudioEngine::sharedEngine()->playBackgroundMusic()` crashed freezen on Lollipop(Android5.0)
+    [FIX]           Button: when the dimension of button title is larger than the button, button will scale to fit the dimension of the button title
+    [FIX]           Button: when the dimension of button title is larger than the button, button will scale to fit the dimension of the button title
+    [FIX]           Camera: does not work correctly when the up is not (0, 1, 0)
+    [FIX]           Director: Uses a low-pass filter to diplay the FPS
+    [FIX]           DrawNode: drawPoint() may cause crash
+    [FIX]           EventKeyboard: can not check right Shift, right Ctrl and right ALT
+    [FIX]           GLProgramCache: doesn't release old program with the same key before adding a new one
+    [FIX]           GLProgramState: enabled GLProgramState restoring on render recreated on WP8
+    [FIX]           Label: label shifting when outline feature enabled
+    [FIX]           Label: when applying additionalKerning to a Label that displays a string with only 1 character, the character is shifted
+    [FIX]           Label: display incompletely with multiline text with outline feature enabled
+    [FIX]           Label: crash if using BMFont but missing corresponding png file
+    [FIX]           Lua: logical error in luaval_to_quaternion
+    [FIX]           New audio: can not loop on Android 2.3.x
+    [FIX]           Random: CCRANDOM_0_1() and CCRANDOM_MINUS_1_1() can be seeded using std::srand(seed)
+    [FIX]           Scale9Sprite: will be flipped if both flipX and flipY are false
+    [FIX]           Scale9Sprite: if scale and flip property are set at the same time, the result would be wrong
+    [FIX]           Scene: setScale() doesn't work as expected
+    [FIX]           Sprite3D: did not create attached sprite from cache
+    [FIX]           Tests: Sprite Performance Test automation works as expected
+    [FIX]           UI: Text: invoke ignoreContentAdatpSize(false) will cause wrong effect
+    [FIX]           VideoPlayer: showed in wrong place on Android v2.3.x
+    [FIX]           WebView: showed in wrong place on Android v2.3.x
+    [FIX]           WP: back key behaviour and Director::getInstance()->end() works not correctly
+
+    [FIX]           Lua-binding: XmlHttpRequest would truncate binary data
+
+cocos2d-x-3.3-rc0  Oct.21 2014
+    [NEW]           3d: added light support: direction light, point light, spot light and ambient light
+    [NEW]           Added ClippingRectangleNode
+    [NEW]           Added AssetsManagerEx, which is more powerful than AssetsManager
+    [NEW]           Added a test case of sprite lamp effect
+    [NEW]           Animate3D: can create with start frame and end frame
+    [NEW]           Audio: new audio supports Mac OS X and Windows
+    [NEW]           Application: added openUrl()
+    [NEW]           Armature: added getOffsetPoints()
+    [NEW]           Lua-binding: added Camera3DTest ,BillBoradTest
+    [NEW]           Node: schedule/unschedule lambda functions
+    [NEW]           Rect: added merge()
+    [NEW]           Spine: update to 2.0.18
+    [NEW]           TileMap: added staggered tile map support
+    [NEW]           Utils: added getCascadeBoundingBox()
+    [NEW]           WP8: enabled screen orientation change handling
+
+    [FIX]           Accelerometer: using Accelerometer will freeze app and then crash on WP8
+    [FIX]           Application: getCurrentLanguageCode() always return empty string
+    [FIX]           Action: kRepeatForever macro superseded by CC_REPEAT_FOREVER macro
+    [FIX]           C++: remove armv7s in VALID_ARCHS for Xcode projects
+    [FIX]           Cocos Studio reader: UI animation playing crash if GUI JSON file is loaded again
+    [FIX]           Cocos Studio reader: improvement ImageViewReader don't necessary loadTexture when imageFilePath is empty
+    [FIX]           EditBox: view rendered in wrong position if click EditBox on iOS 8
+    [FIX]           FileUtils: can not remove files/directory on iOS devices
+    [FIX]           GLProgram: crashed on some Android devices that do not support more than 8 attributes
+    [FIX]           Label: getStringNumLines() may returns wrong result if label is dirty
+    [FIX]           Label: can not change opacity if using FNT font
+    [FIX]           Label: endless loop if not using system font, and constrained length is less than one character width
+    [FIX]           LabelAtlas: opacity do not change when setting parent's opacity
+    [FIX]           Lua-bindings: may crash if passing two-dimensional table from lua to c++
+    [FIX]           New audio: can not play audio after playing some times on Android
+    [FIX]           Node: macro scheduler_selector() superseded by CC_SCHEDULER_SELECTOR(). The same is true for the other schedule_ macros
+    [FIX]           Node: unscheduleAllSelectors() deprecated in favor of unscheudleAllCallbacks()
+    [FIX]           Node: crashed if remove/add child too quickly when using integrated physics
+    [FIX]           TextFieldTTF: will get wrong characters if using Chinese input method on WP8
+    [FIX]           TextureCache: memory leak in reloadTexture()
+    [FIX]           UI: Button: button remains gray when releasing it, this issue only happened if enable scale9 and only has one texture
+    [FIX]           UI: Button: when creating a button with a title only, button content size is not immediately updated
+    [FIX]           UI: EditBox: setMaxLength is invalid on mac
+
+cocos2d-x-3.3-beta0  Sep.20 2014
+    [NEW]           3d: added `BillBoard`
+    [NEW]           ActionManager: added removeAllActionsByTag()
+    [NEW]           Audio: added new audio system for iOS and Android
+    [FIX]           DrawNode: has as many functions as `DrawPrimitive`
+    [NEW]           GLViewProtocol: added getAllTouches()
+    [NEW]           Node: added stopAllActionsByTag()
+    [NEW]           PhysicsWorld: add setSubsteps() and getSubsteps()
+    [NEW]           Renderer: added TriangleCommand
+    [NEW]           UI: added `WebView` on iOS and Android
+
+    [FIX]           C++: CMake works for Mac builds
+    [FIX]           C++: Reorganized cocos2d/platform folder. Easier to add new platforms
+    [FIX]           EditBox: moved to ui:EditBox
+    [FIX]           External: ScrollView: scroll view hidden picks up the touch events
+    [FIX]           FastTileMap: change indices to short because not all devices support int indices which will prevent drawing tilemap
+    [FIX]           FileUtils: can not create and delete directory on wp8
+    [FIX]           HttpClient: condition variable sleep on unrelated mutex
+    [FIX]           Image: optimize decompress jpg data
+    [FIX]           Label: outline effect may be wrong if outline width is big and font size is big too
+    [FIX]           MenuItem: memory leak if using menu_selector
+    [FIX]           MeshCommand: generate wrong meterial id which will cause problem that only first mesh is drawn
+    [FIX]           Node: create unneeded temple `Vec2` object in `setPosition(int, int)`, `setPositionX()` and `setPositionY()`
+    [FIX]           Node: skew effect is wrong
+    [FIX]           Node: setNormalizedPosition can not take effect if parent position is not changed
+    [FIX]           TextureAtlas: may crash if only drawing part of it
+    [FIX]           UI: Button: a button can not be touched if it only contains title
+    [FIX]           UI: Button: title can not be scaled if a button is scaled
+
+cocos2d-x-3.3alpha0  Aug.28 2014
+    [NEW]           3D: Added Camera, AABB, OBB and Ray
+    [NEW]           3D: Added better reskin model support
+    [NEW]           Core: c++11 random support
+    [NEW]	        Core: Using `(std::notrow)` for all the `new` statements
+    [NEW]           Desktop: Added support for applicationDidEnterBackground / applicationWillEnterForeground on desktop
+    [NEW]           Device: added setKeepScreenOn() for iOS and Android
+    [NEW]           EventMouse: support getDelta, getDeltaX, getDeltaY functions
+    [NEW]           FileUtils: add isDirectoryExist(), createDirectory(), removeDirectory(), removeFile(), renameFile(), getFileSize()
+    [NEW]           FileUtilsApple: allow setting bundle to use in file utils on iOS and Mac OS X
+    [NEW]           Image: support of software PVRTC v1 decompression
+    [NEW]           Lua-binding: added release_print that can print log even in release mode
+    [NEW]           Physics Integration: can invoke update in demand
+    [NEW]           Renderer: Added primitive and render primitive command, support passing point, line and triangle data
+    [NEW]           Renderer: Added method for custom precompiled shader program loading on WP8
+    [NEW]           Renderer: Added consistent way to set GL context attributes
+    [NEW]           RenderTexture: add a call back function for saveToFile()
+    [NEW]           RotateTo: added 3D rotation support
+    [NEW]           ScrollView: added `setMinScale()` and `setMaxScale()`
+    [NEW]           Sprite3D: added setCullFace() and setCullFaceEnabled()
+    [NEW]           Sprite3D: added getBoundingBox() and getAABB()
+    [NEW]           SpriteFrameCache: load from plist file content data
+    [NEW]           utils: added gettime()
+    [NEW]           UI: Added UIScale9Sprite
+    [NEW]           UI: ui::Button: support customize how much zoom scale is when pressing a button
+    [NEW]           UI: ui::PageView: added `customScrollThreshold`, could determine the swipe distance to trigger a PageView scroll event
+    [NEW]           UI: ui::TextField: support utf8
+    [NEW]           UI: ui::TextField: support set color and placeholder color
+    [NEW]           UI: ui::Widget: support swallowing touch events
+    [NEW]           Text: added getter and setter for TextColor
+
+    [FIX]           EditBox: font size is not scaled when GLview is scaled on Mac OS X
+    [FIX]           EditBox: began/end events not work
+    [FIX]           Label: can not set charmap after it is created
+    [FIX]           Label: setTextColor does not have any effect on Mac OS X
+    [FIX]           Label: result of LabelTTF::getBoundingBox() is wrong
+    [FIX]           Label: can not set outline color correctly if using system font on iOS
+    [FIX]           Label: character edge will be cut a little if character size is small
+    [FIX]           LabelBMFont: result of LabelBMFont::getBoundingBox() is wrong
+    [FIX]           ListView: can not insert an item in specific position, it is added at bottom
+    [FIX]           LoadingBar: position is changed if changing direction
+    [FIX]           ParticleSystem: effect is wrong if scene scaled
+    [FIX]           ParticleSystemQuad: setTotalParticles() can't set a value larger than initialized value
+    [FIX]           PhysicsBody: return wrong bitmask
+    [FIX]           Scale9Sprite: new added sprite will be hidden
+    [FIX]           Slider: if the UISlider is faded, the slide ball won't fade together
+    [FIX]           Sprite: will turn black if opacity is set other than 255 and be added into SpriteBatchNode
+    [FIX]           TableView: can handle touch event though its parents are invisible
+    [FIX]           TextField: can not use backspace to delete a character
+    [FIX]           Widget: may crash if remove itself in touch call back function
+    [FIX]           Widget: not support cascaded opacity and cascaded color by default
+    [FIX]           VideoPlayer: memory leak on iOS
+    [FIX]           VideoPlayer: video frame size is not calculated correctly on iOS
+    [FIX]           VideoPlayer: video player not showing on iOS if it's not in FullScreen mode
+
+    [FIX]           Others: can not import java library shift by engine correctly when using Eclispe on Android
+    [FIX]           Others: optimize FPS control algorithm on Android
+
+    [FIX]           Lua-binding: replace dynamic_cast to std::is_base_of in object_to_luaval
+
+    [3rd]           fbx-conv: complex FBX model support which is useful for reskin, multiple meshes and multiple materials support
+
+cocos2d-x-3.2  Jul.17 2014
+    [NEW]           Node: added getChildByName method for get a node that can be cast to Type T
+    [NEW]           FileUtils: could add search path and resolution order path in front
+
+    [FIX]           Animation3D: getOrCreate is deprecated and replaced with Animation3D::create
+    [FIX]           Animate3D: setSpeed() accept negative value, which means play reverse, getPlayback and setPlayBack are deprecated
+    [FIX]           EditBox: can not set/get text in password mode on Mac OS X
+    [FIX]           Game Controller: joystick y value inversed on iOS
+    [FIX]           GLView: cursor position is not correct if design resolution is different from device resolution
+    [FIX]           Label: color can not be set correctly if using system font on iOS
+    [FIX]           LabelTTF: may lost chinese characters on linux
+    [FIX]           Lua-binding: support UIVideoPlayer
+    [FIX]           Node: setRotation3D not work based on anchor point
+    [FIX]           Node: modify regular of enumerateChildren, now it just searchs its children
+    [FIX]           Physics integration: body shape will be wrong when using negative value to scale
+    [FIX]           ScrollViewDelegate: make the scrollView delegate methods optional
+    [FIX]           Setup.py: will crash on windows because of checking `zsh`
+    [FIX]           SpriteBatchNode: opacity can not work
+    [FIX]           Sprite3D: may crash on Android if playing animation and replace Scene after come from background
+    [FIX]           UIwidget: opacity is wrong when replace texture
+    [FIX]           UIRichText: will crash when using utf8 string and the length exceed specified length
+    [FIX]           UIText: can not wrap words automatically
+    [FIX]           UITextField: keyboard can not hide if touching space outside of keyboard
+    [FIX]           UITextField: can not wrap words automatically
+    [FIX]           UIVideoPlayer: can not exit full screen mode on Android
+
+    [FIX]           Others: don't release singleton objects correctly that are needed in the whole game, which will be treated
+    as memory leak when using VLD.
+    [FIX]           Others: compiling error when building for iOS 64-bit devices with Xcode6 beta3
+
+
+cocos2d-x-3.2rc0  Jul.7 2014
+    [NEW]           FastTMXTiledMap: added fast tmx, which is much more faster for static tiled map
+    [NEW]           GLProgramState: can use uniform location to get/set uniform values
+    [NEW]           HttpClient: added sendImmediate()
+    [NEW]           Label: support setting line height and additional kerning of label that not using system font
+    [NEW]           Lua-binding: Animation3D supported
+    [NEW]           Lua-binding: UIEditor test cases added
+    [NEW]           Lua-binding: UI focus test cases added
+    [NEW]           Node: added getName(), setName(), getChildByName(), enumerateChildren()
+    and addChild(Node* node, int localZOrder, const std::string &name)
+    [NEW]           Node: physical body supports rotation
+    [NEW]           Sprite3D: support c3b binary format
+    [NEW]           utils: added findChildren() to find all children by name
+    [NEW]           Value: added operator == !=
+
+
+    [FIX]           Armature: blend func has no effect
+    [FIX]           Armature:  crashed when remove armature in frame event
+    [FIX]           Animation3D: doesn't load original pose, which leads to wrong effect if not playing animation
+    [FIX]           Animation3D: animation for unskined bones lost
+    [FIX]           FileUtils: getStringFromFile may return a unterminated string
+    [FIX]           Lua-binding: Sequence:create will cause drop-dead issue
+    [FIX]           Lua-binding: lua-tests can’t be loaded on 64 bits iOS devices and Linux
+    [FIX]           Node: Node::setScale(float) may not work properly
+    [FIX]           Physics integration: child node can move with its father
+    [FIX]           Physics integration: support scale
+    [FIX]           Sprite3D: 20% performance improved, simplify shader, use VAO and batch draw
+    [FIX]           Studio support: NodeReader may cause crash
+    [FIX]           UIButton: doesn't support TTF font
+    [FIX]           UIButton: `getTitleColor()` doesn't equal to the value set by `setTitleColor()`
+    [FIX]           UIListView: addEventListener can not work
+    [FIX]           UIListView: element position is changed a little when you click and up a list view without move
+    [FIX]           UIListView: element will respond to item_end event when end of scrolling a list view
+    [FIX]           UIVideo: crash when try to remove videoView(STATE_PLAYBACK_COMPLETED) on android
+    [FIX]           WP8: crash of utils::captureScreen()
+
+cocos2d-x-3.2-alpha0 Jun.17 2014
+    [NEW]           Console: add a command to show engine version
+    [NEW]           Node: added setter/getter for NormalizedPosition(). Allows to set positions in normalized values (between 0 and 1)
+    [NEW]           Scene: Added createWithSize() method
+    [NEW]           TextField: added getStringLength()
+    [NEW]           TextureCache: added unbindImageAsync() and unbindAllImageAsync()
+    [NEW]           utils: added captureScreen()
+    [NEW]           UIText: added shadow, outline, glow filter support
+    [NEW]           Sprite3D: support 3d animation
+    [NEW]           Animation3D: 3d animation
+
+    [FIX]           Application.mk: not output debug message in release mode on Android
+    [FIX]           Android: 3d model will be black when coming from background
+    [FIX]           Android: don't trigger EVENT_COME_TO_BACKGROUND event when go to background
+    [FIX]           Cocos2dxGLSurfaceView.java: prevent flickering when opening another activity
+    [FIX]           Director: Director->convertToUI() returns wrong value.
+    [FIX]           GLProgram: not abort if shader compilation fails, just return false.
+    [FIX]           GLProgramState: sampler can not be changed
+    [FIX]           Image: Set jpeg save quality to 90
+    [FIX]           Image: premultiply alpha when loading png file to resolve black border issue
+    [FIX]           Label: label is unsharp if it's created by smaller font
+    [FIX]           Label: Label's display may go bonkers if invoking Label::setString() with outline feature enabled
+    [FIX]           Label: don't release cached texture in time
+    [FIX]           Label: calculated height of multi-line string was incorrect on iOS
+    [FIX]           Lua-binding: compiling error on release mode
+    [FIX]           Lua-binding: Add xxtea encrypt support
+    [FIX]           Node: setPhysicsBody() can not work correctly if it is added to a Node
+    [FIX]           Node: state of _transformUpdated, _transformDirty and _inverseDirty are wrong in setParent()
+    [FIX]           Node: _orderOfArrival is set to 0 after visit
+    [FIX]           Other: link error with Xcode 6 when building with 32-bit architecture
+    [FIX]           RenderTexture: saveToFile() lost alpha channel
+    [FIX]           Repeat: will run one more over in rare situations
+    [FIX]           Scale9Sprite: support culling
+    [FIX]           Schedule: schedulePerFrame() can not be called twice
+    [FIX]           ShaderTest: 7 times performance improved of blur effect
+    [FIX]           SpriteFrameCache: fix memory leak
+    [FIX]           Texture2D: use image's pixel format to create texture
+    [FIX]           TextureCache: addImageAsync() may repeatedly generate Image for the same image file
+    [FIX]           WP8: will restart if app goes to background, then touches icon to go to foreground
+    [FIX]           WP8: will be black if: 1. 3rd pops up a view; 2. go to background; 3. come to foreground
+    [FIX]           WP8: project name of new project created by console is wrong
+    [FIX]           WP8: missing texture after app switch
+
+    [3RD]           curl: will crash if use https request on iOS simulator
+    [3RD]           curl: update OpenSSL to v1.0.1h
+
+cocos2d-x-3.1.1 May.31 2014
+    [FIX]           GLProgramState: restores states after coming from background
+
+cocos2d-x-3.1  May.24 2014
+    [FIX]           EventKeyboard::KeyCode: key code for back button changed from KEY_BACKSPACE to KEY_ESCAPE
+    [FIX]           Label: may crash when using outline effect
+    [FIX]           Label: using outline and invoking 'Director::setContentScaleFactor' cause label show nothing
+    [FIX]           ProgressTo: will start from 0 when it reaches 100
+    [FIX]           Physics integration: may crashes if remove bodies at physics contact callback
+    [FIX]           UIWidget: copyProperties() lost copy some properties
+    [FIX]           WP8: orientation is not correct when it is set to portrait
+    [FIX]           WP8: fix for precompiled shaders and precompiled headers
+    [FIX]           WP8: template supports orientation
+
+cocos2d-x-3.1-rc0 May.18 2014
+    [NEW]           Cocos2dxActivity: Adds a virtual method to load native libraries.
+    [NEW]           Directory Structure: reorder some files within the cocos/ folder
+    [NEW]           Sprite3D: a node that renders 3d models
+    [NEW]           EditBox: support secure input on Mac
+
+    [FIX]           ControlButton: cascade opacity and color error
+    [FIX]           Director: twice calling of onExit
+    [FIX]           Math: Vector2->Vec2, Vector3->Vec3, Vector4->Vec4, Matrix->Mat4
+    [FIX]           GLProgram: uniform CC_Texture0 is pre-defined by cocos2d. MUST NOT be defined in shaders
+    [FIX]           GLProgramState: Supports multitexturing
+    [FIX]           Studio:ActionObject: correct TotalTime of ActionObject
+    [FIX]           Studio: FrameData::copy doesn't copy `isTween` property
+
+cocos2d-x-3.1-alpha1 May.9 2014
+    [NEW]           Animate: Dispatch a custom event after an animation frame is displayed
+    [NEW]           GLProgram: Easy to customize uniforms and attributes by using the new class GLProgramState
+    [NEW]           Template: cpp project support Eclipse c++ project
+    [NEW]           UI: add navigation support
+    [NEW]           UI: add a widget to play video
+    [NEW]           VS: support VS 2013
+
+    [FIX]           Audio: pause sound automatically when go to background on Android
+    [FIX]           Director: remove keepData and releaseData
+    [FIX]           Label: label is unsharp if it's created by system font with small size on iOS & Mac OS X
+    [FIX]           Label: Label created with system font is still visible when its opacity is 0
+    [FIX]           Label: Label created with system font havs black border on WP8/WINRT
+    [FIX]           Lua: A potential crash in the bindings of sp.SkeletonAnimation.setAnimation
+    [FIX]           Lua: Lua template should fail to launch on lua error
+    [FIX]           ParticleSystem: Particles can be created without a texture
+    [FIX]           ParticleSystem: yFlippedCoord behavior fixed.
+                      Added cocos2d/tools/particle to fix particles that were based on the old (broken) behaviour
+    [FIX]           Setup.py: Added SDK / NDK detection based on PATH
+    [FIX]           UIText: support TTF
+    [FIX]           Value: all types share the same union to reduce memory usage
+
+cocos2d-x-3.1-alpha0 May.1 2014
+     [NEW]          Android: Adds support for get response when Activity's onActivityResult is triggered
+     [NEW]          Core: Adds RefPtr<T> smart pointer support
+     [NEW]          Label: supports auto-culling
+     [NEW]          Math: New unified math library that supersedes Kazmath, CCGeometry and CCAffine*
+     [NEW]          Test: Adds a sample for making a outline sprite by using a custom shader
+
+     [FIX]          Application: Application::run returns wrong value on Mac platform
+     [FIX]          Build scripts: Improved cmake files for Linux, and Android.mk for Android
+     [FIX]          Image: saveToImage may cause memory leak
+     [FIX]          Lua: cc.pGetAngle may return wrong value
+     [FIX]          Network: HttpRequest uses std::function as callback
+     [FIX]          Particle: The effect of particle loaded from CocosBuilder is incorrectly
+     [FIX]          ParticleSystem: particle direction in verticality is opposite when "configName" has value and "yCoordFlipped" is -1
+     [FIX]          Physics: PhysicsSprite's transform couldn't be updated
+     [FIX]          Value: default value changed to false
+     [FIX]          WP8: Some bug fixes
+
+cocos2d-x-3.0 Apr.23 2014
+     [NEW]          Lua: add `RichText` test cases
+     [NEW]          EditBox: Added missing Text Font and Placeholder feature for Mac platform
+
+     [FIX]          cocos console: Zipalign the apk generated with release mode
+     [FIX]          Director: Application crashes on closing if CC_ENABLE_CACHE_TEXTURE_DATA is enabled
+     [FIX]          Image: memoery leak
+     [FIX]          Image: crashes when save a jpg file
+     [FIX]          Lua: 'EditBox' can't response 'changed','ended' and 'return' event on Windows
+     [FIX]          Lua: new project will crash on iOS 5.1 devices
+     [FIX]          Others: compiling error when CC_LABELBMFONT_DEBUG_DRAW or CC_LABELATLAS_DEBUG_DRAW is enabled
+
+     [3rd]          libcurl: support ssl again on iOS
+
+cocos2d-x-3.0rc2 Apr.15 2014
+     [NEW]          Event: Adds `EventListener::setEnabled/isEnabled` to support enable/disable event listeners
+     [NEW]          GLView: Added createWithFullscreen overloaded method for selecting monitor and setting video mode
+
+     [FIX]          Android: Cocos2dxHelper.runOnGLThread() can't work
+     [FIX]          Animation: Added 'loops' parameter to Animation::createWithSpriteFrames
+     [FIX]          Audio: can not resume after pausing on windows
+     [FIX]          Audio: stopalleffect lead to stop background music on WP8
+     [FIX]          Audio: play effect may lead to memory leak on WP8
+     [FIX]          CocoStudio: Potential crash in SceneReader::createNodeWithSceneFile
+     [FIX]          Control: ControlButton can't swallow touch event
+     [FIX]          Event: Removing and re-adding an event listener will trigger an assert
+     [FIX]          Event: A potential crash when unregistering listener right after its registration
+     [FIX]          Event: EventDispatcher::setDirtyForNode doesn't consider node's children
+     [FIX]          FileUtils: 'isFileExist' doesn't consider SearchPaths and ResolutionOrders
+     [FIX]          Image: The result of 'malloc' is incompatible with type 'unsigned char *' in Image::saveImageToPNG
+     [FIX]          JNI: doesn't cache classloader which may cause crash on Android devices with 4.2 or upper version
+     [FIX]          Network: HTTPClient reports 2xx status codes as errors
+     [FIX]          Lua: Added ScriptHandlerMgr::destroyInstance to avoid memory leak
+     [FIX]          Physics: Skips one frame when delta time is equal to zero
+     [FIX]          Physics: PhysicsShapeEdgeChain::init() always return false
+     [FIX]          Setup: Force updating environment variables in setup.py
+     [FIX]          Value: A potential memory leak in value's default constructor
+
+cocos2d-x-3.0rc1 April.2 2014
+     [NEW]          Application: Adds getCurrentLanguageCode() which returns iso 639-1 language code
+     [NEW]          cocos2d::extension::ScrollView: Elastic bounce back effect support
+     [NEW]          Constructor: Added CC_CONSTRUCTOR_ACCESS macro to re-define constructor/initXXX methods to 'public' access.
+     [NEW]          Label: Added new methods 'set(Anti)AliasTexParameters' for enabling/disabling antialias
+
+     [FIX]          Android: Reloaded texture is not shown if it has the mipmap
+     [FIX]          Android: Application may become black at first time entering on some devices
+     [FIX]          Audio: Stopped music could also be resumed on iOS
+     [FIX]          CCBReader: Wrong logic in CCBAnimationManager::moveAnimationsFromNode
+     [FIX]          CocoStudio: ActionObject memory leak in ActionManagerEx::initWithDictionary
+     [FIX]          Console: initialize some variables that are not initilized in destructor
+     [FIX]          Console: refactor 'upload' command, encode file with base64, detach 'upload' from main loop
+     [FIX]          EventDispatcher: Potential crashes in EventDispatcher while using SceneGraphPriroity listeners
+     [FIX]          FileUtils: addSearchResolutionsOrder doesn't check whether there is a 'slash' at the end of path
+     [FIX]          FileUtils: Boolean value could not be written to specified plist file
+     [FIX]          GLView: Can't receive touchEnded event when mouse up outside of window on desktop platforms
+     [FIX]          Image: Some functions and variables in Image class is private, it should be protected
+     [FIX]          Label: Crash if label's type is STRING_TEXTURE and label->sortAllChildren is called
+     [FIX]          Label: Display incorrect of multi-line label if invoking 'getLetter'
+     [FIX]          Label: Default Anchor point isn't in middle and shadow offset doesn't consider contentScaleFactor
+     [FIX]          Label: Label's color is incorrect if it's created by font name
+     [FIX]          Label: Missing letters if using old LabelTTF and running on iPhone 64bit simulator(device)
+     [FIX]          Label: Refactor implementation of label's shadow
+     [FIX]          Label: Stroke was not 'outside stroke' for Label which is generated by 'Font name'
+     [FIX]          Label: Wrong logic in Label::setFontAtlas
+     [FIX]          Label: Read file more than once for label created by different font size
+     [FIX]          Label: Getting wrong rectangle by LabelTTF(LabelBMFont)::getBoundingBox.
+     [FIX]          Label: Possible crash if invoking FontAtlasCache::purgeCachedData
+     [FIX]          LuaBinding: Adds `addCustomHandler` in the ScriptHandlerMgr
+     [FIX]          LuaBinding: Upgrading LuaSocket to the latest version
+     [FIX]          Menu: Added missed scaleZ feature in ScaleTo and ScaleBy.
+     [FIX]          Network: Implements 'SIODelegate::fireEventToScript' method to integrate JSB event handling with the original native code.
+     [FIX]          Network: WebsocketTest crashes on win32, mutex varible may be deleted while it's still locked
+     [FIX]          ParticleSystem: Particle will stop animating if it was removed and re-added to another node
+     [FIX]          ParticleSystem: Set particle visible to false then set to true cause crashes
+     [FIX]          Physics: Incorrect function invocation in PhysicsBody::setAngularVelocityLimit
+     [FIX]          Physics: PhysicsBody::setGravityEnable doesn't work correctly sometimes
+     [FIX]          Physics: PhysicsBody moves randomly when switch foreground/background
+     [FIX]          Physics: Refactors PhysicsDebugDraw
+     [FIX]          Tests: Memory leak in CocosDenshionTest
+     [FIX]          Texture2D: Support to update partial texture
+     [FIX]          Tools: The apk generated with release mode in cocos-console can't be installed
+     [FIX]          UI: Widget::addNode is confused, need to add ProtectedNode to remove addNode API.
+     [FIX]          UI: Adding HBox, VBox layouts, refactoring 'doLayout' function
+
+     [3RD]          Chipmunk: Upgraded to v6.2.1
+     [3RD]          libwebsockets: Upgraded to v1.23
+
+cocos2d-x-3.0rc0 March.14 2014
+[All]
+     [NEW]          Action: RotateBy supports 3D rotations
+     [NEW]          Bindings: Using python to automatically generate script bindings
+     [NEW]          ccConfig.h: removed support for CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
+     [NEW]          Console: Added command: 'autotest run|main|next|back|restart'.
+     [NEW]          Console: Added 'resolution', 'projection' commands. Improved API
+     [NEW]          Console: Added more commands: director resume|pause|stopanimation|startanimation.
+     [NEW]          Console: Added command: 'touch tap|swipe' to simulating touch events.
+     [NEW]          Console: Added command: 'upload filename filesize' to upload a file to writable path.
+     [NEW]          Director: Displays 'Vertices drawn' in the stats. Useful to measure performance.
+     [NEW]          GLProgram: initWithVertexShaderByteArray() -> initWithByteArrays()
+     [NEW]          GLProgram: initWithVertexShaderFilename()a -> initWithFilenames()
+     [NEW]          GLProgram: addAttribute() -> bindAttributeLocation()
+     [NEW]          Label: can custom shadow and outline size
+     [NEW]          Label: LabelTTF was re-implemented as a wrapper of Label
+     [NEW]          Node: Added set/get Position3D() and set/get Rotation3D()
+     [NEW]          Node: Calculates rotation X and Y correctly.
+     [NEW]          Node: set/get VertexZ() -> set/get PositionZ()
+     [NEW]          Node: setRotationX() -> setRotationSkewX()
+     [NEW]          Node: setRotationY() -> setRotationSkewY()
+     [NEW]          Node: visit() and draw() new arguments: Renderer, parentTransform, and whether or not the parentTransform has changed since the last frame
+     [NEW]          Language: Added Dutch support
+     [NEW]          Sprite: Added auto-culling support. Performance increased in about 100% when many sprites are outside the screen
+     [NEW]          Setup.sh: added script to set up environment needed for cocos2d-x
+     [NEW]          Scheduler: Added new API [ schedule(std::function, ...), schedule(member_func, ...) ], deprecated the old API [ scheduleSelector(member_func, ...) ]
+     [FIX]          Action: FadeIn and FadeOut behaviours is incorrect if it doesn't start from an edge value( 0 or 255)
+     [FIX]          Array: crash when invoking initWithObjects()
+     [FIX]          Action: Merge cocostudio/CCActionXxx to CCAction
+     [FIX]          Bindings: Adds a macro to disable inserting script binding relevant codes
+     [FIX]          Bindings: Supports 'setTimeout' and 'setInterval' in JSB
+     [FIX]          Bindngs: Exposes the missing data structures of Spine to JS
+     [FIX]          Bindings: cc.BuilderReader.load( path, null, parentSize ); was not allowed
+     [FIX]          Console: crashes on Windows
+     [FIX]          ControlButton: Crash if it was removed from parent in its callback
+     [FIX]          CocoStudio: Logical error in 'TriggerObj::detect()'
+     [FIX]          Director: Crash if invoking Director::end() on WINDOWS
+     [FIX]          Director: setAnimationInterval has not effect on Mac
+     [FIX]          EditBox: position would not be updated if its parent's position changed
+     [FIX]          EditBox: Voice recognition input would cause crash on ios7
+     [FIX]          EGLView: renamed to GLView, no longer a singleton, easier to customize
+     [FIX]          EventDispatcher: removeAllEventListeners() remove event listeners used internally, make textures not reload on Android when come from background
+     [FIX]          EventDispatcher: dispatchEventToListeners() causes "out of range" exception
+     [FIX]          Image: s3tc compressed textures with no mipmaps fail to be loaded
+     [FIX]          Label: A string which only contains CJK characters can't make a line-break when it's needed
+     [FIX]          Label: Character would not be aligned on the baseline when label using distance field
+     [FIX]          Label: Color and opacity can't take effect
+     [FIX]          Label: Font size passed to new Label didn't consider 'contentScaleFactor'
+     [FIX]          Label: loading custom fonts from ttf file fails on windows
+     [FIX]          Label: LabelAtlas::setColor takes no effect
+     [FIX]          MotionStreak: Added unimplemented position getter/setter
+     [FIX]          Node: setAdditionalTransform receives a pointer and not a const reference
+     [FIX]          Node: setRotation() moves opposite when node has a physics body
+     [FIX]          Node: Can not use Node::setPhysicsBody to reset a physics body
+     [FIX]          Object: Object -> Ref, and remove unneeded functions
+     [FIX]          Other: Removes samples except testcpp|testjavascript|testlua. Moves sample games to `cocos2d/samples` repo
+     [FIX]          Physics integration: Improves physical performance
+     [FIX]          Physics integration: PhysicsContact::_contactData may be double freed.
+     [FIX]          Physics integration: PhysicsShapeBox::getSize returns wrong value.
+     [FIX]          ParticleSystemQuad: setTotalParticles() can not set a value larger than initialized value
+     [FIX]          Renderer: Expand textureID bit from 18bits to 32bits. Resolves probably crash on Linux / Android
+     [FIX]          RenderTexture: save screen with RenderTexture got unexpected result
+     [FIX]          RenderTexture: saveToFile() can't write png file correctly
+     [FIX]          Spine: spine::Skeleton would not be updated after being re-added to scene
+     [FIX]          Sprite: not work as expected when CC_SPRITE_DEBUG_DRAW is 1
+     [FIX]          Scheduler: Thread deadlock if new functions are added in callback of Scheduler:: performFunctionInCocosThread
+     [FIX]          Tests: EditBoxText crashes on Win32 when being clicked many times
+     [FIX]          Tests: ChipmunkTest bounding box for debugging couldn't be shown
+     [FIX]          Tests: CocoStudioGuiTest/LabelBMFontTest crashes
+     [FIX]          Tests: Particle test/AddAndRemove test crashes
+     [FIX]          Tests: RenderTextureTest not drawn when coming from background
+     [FIX]          Tests: LabelTTFMultiline show nothing on mac
+     [FIX]          Timer::cancel always call Director::getInstance()->getScheduler() even in another Scheduler
+     [FIX]          Tests: Potential crash by switching repeatly between HttpClientTest, WebSocketTest, SocketIOTest
+     [FIX]          Tests: State is changed to RESUME when game comes back to foreground if pause button was clicked in Interval Test
+     [FIX]          TMXLayer: Removing child from TMXLayer may cause crash
+     [FIX]          TMXObjectGroup: Object values (x, y, width and height) from TMXObjectGroup are incorrect
+     [FIX]          TMXXMLParser: Refactored the codes of parsing pure xml layer format for tilemap
+     [FIX]          TMXXMLParser: 'y' value is parsed incorrectly
+     [FIX]          UI: Changes namespace from 'cocos2d::gui' to 'cocos2d::ui'.
+     [FIX]          UI: Supports RichText
+     [FIX]          Vector: Object which isn't in Vector would also be released when invoking Vector::eraseObject.
+     [FIX]          Websocket: Potential crash when websocket connection closes.
+     [FIX]          Websocket: No callback is invoked when websocket connection fails
+     [FIX]          Xcode 5.1: Added Xcode 5.1 to build arm64 version, but can not require socket module in lua, will fix it soon
+     [3RD]          Kazmath: Upgraded to latest version of Kazmath
+
+
+cocos2d-x-3.0beta2 Jan.24 2014
+[All]
+     [NEW]          Full screen support for desktop platforms.
+     [NEW]          Adds performance test for EventDispatcher.
+     [NEW]          Adds performance test for Containers(Vector<>, Array, Map<K,V>, Dictionary).
+     [NEW]          DrawNode supports to draw triangle, quad bezier, cubic bezier.
+     [NEW]          Console: added the 'textures', 'fileutils dump' and 'config' commands
+     [NEW]          GLCache: glActiveTexture() is cached with GL::activeTexture(). All code MUST call the cached version in order to work correctly
+     [NEW]          Label: Uses a struct of TTF configuration for Label::createWithTTF to reduce parameters and make this interface more easily to use.
+     [NEW]          Label: Integrates LabelAtlas into new Label.
+     [NEW]          Node: Added `setGlobalZOrder()`. Useful to change the Node's render order. Node::setZOrder() -> Node::setLocalZOrder()
+     [NEW]          Renderer: Added BatchCommand. This command is not "batchable" with other commands, but improves performance in about 10%
+     [FIX]          event->stopPropagation can't work for EventListenerTouchAllAtOnce.
+     [FIX]          Uses unified `desktop/CCEGLView.h/cpp` for desktop platforms (windows, mac, linux).
+     [FIX]          Bindings-generator supports Windows again and remove dependency of LLVM since we only need binary(libclang.so/dll).
+     [FIX]          Removes unused files for MAC platform after using glfw3 to create opengl context.
+     [FIX]          Wrong arithmetic of child's position in ParallaxNode::addChild()
+     [FIX]          CocoStudio: TestColliderDetector in ArmatureTest can't work.
+     [FIX]          CocoStudio: The order of transform calculation in Skin::getNodeToWorldTransform() is incorrect.
+     [FIX]          Crash if file doesn't exist when using FileUtils::getStringFromFile.
+     [FIX]          If setting a shorter string than before while using LabelAtlas, the effect will be wrong.
+     [FIX]          Label: Memory leak in FontFreeType::createFontAtlas().
+     [FIX]          Label: Crash when using unknown characters.
+     [FIX]          Label: Missing line breaks and wrong alignment.
+     [FIX]          Label: Corrupt looking characters and incorrect spacing between characters
+     [FIX]          Label: Label:color and opacity settings are invalid afeter these these properties changed: 1)text content changed 2)align style changed 3)max line width limited
+     [FIX]          Label: Crash when using unknown characters
+     [FIX]          Console: log(format, va_args) is private to prevent possible resolution errors
+     [FIX]          Configuration: dumpInfo() -> getInfo()
+     [FIX]          ControlSlider doesn't support to set selected thumb sprite.
+     [FIX]          ControlButton doesn't support to set scale ratio of touchdown state.
+     [FIX]          Particles: Crash was triggered if there is not `textureFileName`section in particle plist file.
+     [FIX]          Renderer: Uses a float as key with only the depth. Viewport, opaque are not needed now
+     [FIX]          Renderer Performance Fix: QuadCommand::init() does not copy the Quads, it only store a reference making the code faster
+     [FIX]          Renderer Performance Fix: Sprite and SpriteBatchNode (and subclasses) has much better performance
+     [FIX]          Renderer Performance Fix: When note using VAO, call glBufferData() instead of glBufferSubData().
+     [FIX]          Renderer Performance Fix: Doesn't sort z=0 elements. It also uses sort() instead of stable_sort() for z!=0.
+     [FIX]          Sprite: removed _hasChildren optimization. It uses !_children.empty() now which is super fast as well
+     [FIX]          Tests: Sprites Performance Test has 4 new tests
+     [FIX]          TextureCache: getTextureForKey and removeTextureForKey work as expected
+     [FIX]          TextureCache: dumpCachedTextureInfo() -> getCachedTextureInfo()
+     [FIX]          Websocket doesn't support send/receive data which larger than 4096 bytes.
+     [FIX]          Object: Remove _retainCount
+     [FIX]          ParallaxNode: Coordinate of Sprite may be wrong after being added into ParallaxNode
+     [FIX]          Crash if there is not `textureFileName`section in particle plist file
+     [FIX]          Websocket cannot send/receive more than 4096 bytes data
+     [FIX]          TextureCache::addImageAsync can't load first image
+     [FIX]          ControlSlider: Can not set "selected thumb sprite"
+     [FIX]          ControlSlider: Can not set "scale ratio"
+     [FIX]          Crash when loading tga format image
+     [FIX]          Keyboard pressed events are being repeatedly fired before keyboard is released
+[Android]
+     [FIX]          Background music can't be resumed when back from foreground
+     [FIX]          ANR (Application Not Responding) appears on android 2.3 when pressing hardware button.
+[lua binding]
+     [NEW]          Can bind classes that have the same class names but different namesapces
+     [FIX]          Use EventDispatcher to update some test cases
+     [FIX]          sp.SkeletonAnimation:registerScriptHandler should not override cc.Node:registerScriptHandler
+[javascript binding]
+     [NEW]          Bind SAXParser
+     [FIX]          Pure JS class that wants to inherite from cc.Class will trigger an irrelevant log
+     [FIX]          Mac and iOS Simulator should also use SpiderMonkey which was built in RELEASE mode
+     [FIX]          Crash when running JSB projects on iOS device in DEBUG mode
+     [FIX]          Crash when Firefox connects to JSB application on Mac platform.
+[Desktop]
+     [NEW]          Support fullscreen
+[Linux]
+     [FIX]          "Testing empty labels" in LabelTest crashes.
+[Mac]
+     [FIX]          Removes unused files after using glfw3 to create opengl context
+[Win32]
+     [FIX]          Compiling error when using x64 target
+     [FIX]          Tests: TestCpp works with CMake
+     [FIX]          Bindings-generator supports Windows again and remove dependency of LLVM since it only needs binary of libclang
+
+cocos2d-x-3.0beta Jan.7 2014
+[All]
+     [NEW]          New label: shadow, outline, glow support
+     [NEW]          AngelCode binary file format support for LabelBMFont
+     [NEW]          New spine runtime support
+     [NEW]          Add templated containers, such as `cocos2d::Map<>` and `cocos2d::Vector<>`
+     [NEW]          TextureCache::addImageAsync() uses std::function<> as call back
+     [NEW]          Namespace changed: network -> cocos2d::network, gui -> cocos2d::gui
+     [NEW]          Added more CocoStudioSceneTest samples.
+     [NEW]          Added UnitTest for Vector<T>, Map<K, V>, Value.
+     [NEW]          AngelCode binary file format support for LabelBMFont.
+     [NEW]          New renderer: Scene graph and Renderer are decoupled now.
+     [NEW]          Upgrated Box2D to 2.3.0
+     [NEW]          SChedule::performFunctionInCocosThread()
+     [NEW]          Added tga format support again.
+     [NEW]          Adds UnitTest for Template container and Value class
+     [FIX]          A Logic error in ControlUtils::RectUnion.
+     [FIX]          Bug fixes for Armature, use Vector<T>, Map<K, V> instead of Array, Dictionary.
+     [FIX]          Used c++11 range loop(highest performance) instead of other types of loop.
+     [FIX]          Removed most hungarian notations.
+     [FIX]          Merged NodeRGBA to Node.
+     [FIX]          Potential hash collision fix.
+     [FIX]          Updates spine runtime to the latest version.
+     [FIX]          Uses `const std::string&` instead of `const char*`.
+     [FIX]          LabelBMFont string can't be shown integrally.
+     [FIX]          Deprecates FileUtils::getFileData, adds FileUtils::getStringFromFile/getDataFromFile.
+     [FIX]          GUI refactoring: Removes UI prefix, Widget is inherited from Node, uses new containers(Vector<T>, Map<K,V>).
+     [FIX]          String itself is also modified in `String::componentsSeparatedByString`.
+     [FIX]          Sprites with PhysicsBody move to a wrong position when game resume from background.
+     [FIX]          Crash if connection breaks during download using AssetManager.
+     [FIX]          OpenAL context isn't destroyed correctly on mac and ios.
+     [FIX]          Useless conversion in ScrollView::onTouchBegan.
+     [FIX]          Two memory leak fixes in EventDispatcher::removeEventListener(s).
+     [FIX]          CCTMXMap doesn't support TMX files reference external TSX files
+     [FIX]          Logical error in `CallFuncN::clone()`
+     [FIX]          Child's opacity will not be changed when its parent's cascadeOpacityEnabled was set to true and opacity was changed
+     [FIX]          Disallow copy and assign for Scene Graph + Actions objects
+     [FIX]          XMLHttpRequest receives wrong binary array
+     [FIX]          XMLHttpRequest.status needs to be assigned even when connection fails
+     [FIX]          TextureCache::addImageAsync may load a image even it is loaded in GL thread
+     [FIX]          EventCustom shouldn't use std::hash to generate unique ID, because the result is not unique
+     [FIX]          CC_USE_PHYSICS is actually impossible to turn it off
+     [FIX]          Crash if connection breaks during download using AssetManager
+     [FIX]          Project_creator supports creating project at any folder and supports UI
+[Android]
+     [NEW]          build/android-build.sh: add supporting to generate .apk file
+     [NEW]          Bindings-generator supports to bind 'unsigned long'.
+     [FIX]          XMLHttpRequest receives wrong binary array.
+     [FIX]          'Test Frame Event' of TestJavascript/CocoStudioArmatureTest Crashes.
+     [FIX]          UserDefault::getDoubleForKey() doesn't pass default value to Java.
+[iOS]
+     [FIX]          Infinite loop in UserDefault's destructor
+[Windows]
+     [NEW]          CMake support for windows.
+[Bindings]
+     [NEW]          Support CocoStudio v1.2
+     [NEW]          Adds spine JS binding support.
+     [FIX]          Don't bind override functions for JSB and LuaBining since they aren't needed at all.
+     [FIX]          The order of onEnter and onExit is wrong.
+     [FIX]          The setBlendFunc method of some classes wasn't exposed to LUA.
+     [FIX]          Bindings-generator doesn't support 'unsigned long'
+     [FIX]          Potential hash collision by using typeid(T).hash_code() in JSB and LuaBinding
+[Lua binding]
+     [NEW]          New label support
+     [NEW]          Physcis integrated support
+     [NEW]          EventDispatcher support
+     [FIX]          CallFuncND + auto remove lua test case have no effect
+     [FIX]          Lua gc will cause correcsponding c++ object been released
+     [FIX]          Some lua manual binding functions don't remove unneeded element in the lua stack
+     [FIX]          The setBlendFunc method of some classes wasn't exposed to LUA
+[Javascript binding]
+     [FIX]          `onEnter` event is triggered after children's `onEnter` event
+
+cocos2d-x-3.0alpha1 Nov.19 2013
+[all platforms]
+     [DOC]          Added RELEASE_NOTES and CODING_STYLE.md files
+     [FIX]          Texture: use CCLOG to log when a texture is being decoded in software
+     [FIX]          Spine: fix memory leaks
+     [FIX]          fixed a memory leak in XMLHTTPRequest.cpp
+     [FIX]          removeSpriteFramesFromFile() crashes if file doesn't exist.
+     [FIX]          Avoid unnecessary object duplication for Scale9Sprite.
+     [FIX]          create_project.py does not rename/replace template projects completely.
+     [FIX]          Could not set next animation in CCBAnimationCompleted callback.
+     [FIX]          The Node's anchor point was changed after being added to ScrollView.
+     [FIX]          Refactored and improved EventDispatcher.
+     [FIX]          EventListeners can't be removed sometimes.
+     [FIX]          When parsing XML using TinyXML, the data size has to be specified.
+     [FIX]          Parameter type: const char* -> const string&
+     [FIX]          Armature: many bug fixed, add more samples, add function to skip some frames when playing animation
+     [FIX]          Configuration of VAO in runtime
+     [FIX]          Webp Test Crashes.
+     [FIX]          TransitionScenePageTurn: z fighting
+     [FIX]          AssetsManager: Adding test whether the file directory exists when uncompressing file entry,if does not exist then create directory
+     [FIX]          CCBReader: To set anchor point to 0,0 when loading Scale9Sprite
+     [FIX]          OpenGL Error 502 in Hole Demo
+     [FIX]          AssetsManager: downloading progress is not synchronized with actual download
+     [FIX]          SpriteFrameCache: memory leak when loading a plist file
+     [FIX]          removeSpriteFramesFromFile() crashes if file doesn't exist
+     [FIX]          EditBox: can't click the area that outside of keyboard to close keyboard
+     [FIX]          CCBReader: can not set next animation in AnimationCompleted callback
+     [FIX]          Node's anchor point was changed after being added to ScrollView
+     [FIX]          EventDispather: refactor method and fix some bugs
+     [FIX]          EventListner: cann't be removed sometimes
+     [FIX]          UserDefault: didn't set data size when parsing XML using TinyXML
+     [FIX]          Webp test crashed
+     [FIX]          CCHttpClient: The subthread of CCHttpClient interrupts main thread if timeout signal comes.
+     [NEW]          Arm64 support.
+     [NEW]          Added Mouse Support For Desktop Platforms.
+     [NEW]          Point: Adds ANCHOR_XXX constants like ANCHOR_MIDDLE, ANCHOR_TOP_RIGHT, etc.
+     [NEW]          Sprite: Override setScale(float scaleX, float scaleY)
+     [NEW]          External: added | operator for Control::EventType
+     [NEW]          Android & iOS screen size change support
+     [NEW]          GLProgram: setUniformLocationWithMatrix2fv, setUniformLocationWithMatrix3fv
+     [NEW]          Color[3|4][B|F]: comparable and explicit convertible
+     [NEW]          Contorl::EventType add | operation
+     [NEW]          Performance Test: Sprite drawing
+     [NEW]          Adjusted folder structure
+     [NEW]          Added tools to simplify upgrading game codes from v2.x to v3.x
+     [FIX]          Added virtual destructors on Interfaces
+[Android]
+     [FIX]          Added EGL_RENDERABLE_TYPE to OpenGL attributes
+     [FIX]          Fixed application will crash when pause and resume.
+     [FIX]          Clear NoSuchMethodError Exception when JniHelper fails to find method id
+     [FIX]          Fixed crash when backging from background
+     [FIX]          LabelTTF: crashed when setting dimension input height value less than the height of the font and the input width value is 0
+     [FIX]          Changed data type of 'char' to signed as default
+     [NEW]          Added xlargeScreens="true" to supports-screens
+     [NEW]          Added build/android-build.py to build all Android samples, and remove all build_native.sh/cmd
+     [NEW]          Added build_native.py to build template projects, and remove build_native.sh/cmd
+     [NEW]          Added Cocos2dxHelper.runOnGLThread(Runnable) again
+     [NEW]          Added support for orientation changed
+     [NEW]          Disabled CDT Builder on Eclipse
+[Mac]
+     [FIX]          Removed unused CCLOG() from GL initialization
+     [FIX]          HttpClientTest: crash
+[iOS]
+     [FIX]          Can't click the area that outside of keyboard to close keyboard when using EditBox.
+     [NEW]          Added support for orientation changed
+[Linux]
+     [NEW]          Used CMake to build linux projects.
+     [FIX]          Closed X display after getting DPI on Linux.
+[Win32]
+     [FIX]          Last test case of OpenglTest crashed
+[Desktop]
+     [FIX]          Trigger onKeyReleased only after the key has been released.
+     [NEW]          Added mouse support
+[Javascript binding]
+     [FIX]          Fixed a memory leak in ScriptingCore::runScript()
+     [FIX]          sys.localStorage.getItem() does not support non-ascii string.
+     [FIX]          cc.Scheduler.schedule(target, func) without repeat argument couldn't repeat schedule forever on device.
+     [FIX]          CCBReader can't play sequence automatically in JSB.
+     [FIX]          Wrong convention to jsval in cccolor4f_to_jsval and cccolor3b_to_jsval
+     [FIX]          sys.localStorage: doesn't support non-ascii string
+     [FIX]          BuilderReader: can't play sequence  automatically
+     [FIX]          Wrong conversion to javal in cccolor4f_to_jsval and cccolor3b_to_jsval
+     [NEW]          main.js -> cocos2d-jsb.js
+     [NEW]          Remote debugging using Firefox, "step into" can not work
+     [NEW]          Added binding for Node::setScale(float, float)
+     [NEW]          Impvoved armature binding
+     [NEW]          Added CocoStudio releated binding codes: gui, scene parser, and add corresponding samples
+[Lua Binding]
+     [NEW]          Added Armature lua binding and added test samples.
+     [NEW]          Added LuaObjectBridge & LuaJavaBridge to simplify invoking objective-c codes and java codes from lua
+     [NEW]          Added CocoStudio releated binding codes: gui, scene parser, and add corresponding samples
+     [NEW]          Added AssetsManager binding and corresponding sample
+     [NEW]          Added XMLHttpRequest lua binding and corresponding sample
+
+cocos2d-x-3.0alpha0 @Sep.19 2013
+[all platforms]
+     [FIX]          TargetAction::reverse() works as expected
+     [FIX]          Fixed crash in OpenGLTest
+     [FIX]          Fixed logic when passing an empty std::vector to WebSocket::init()
+     [FIX]          Fixed crash in ParticleSystemQuad due to improper deletion of VBO and VAO
+     [FIX]          Point::isSegmentIntersect() returns correct value
+     [FIX]          Improved UTF8 response code in XmlHttpRequest
+     [FIX]          Observers with the same target and name but different sender are the same observer in NotificationCenter
+     [NEW]          Added ATITC format support
+     [NEW]          Better integration with physics engine
+     [NEW]          New Event Dispatcher: supports Keybaord, Touches, Accelerometer, Custom events. Added Tests as well
+     [NEW]          New Label code: Faster and more efficient than previous code
+     [NEW]          Added S3TC support
+     [NEW]          Added a method to get duration of timeline for CCBAnimationManager class
+     [NEW]          Array is compatible with STL containers.
+     [3RD]          Upgraded SpiderMonkey to Firefox v23
+[Android]
+     [FIX]          Fixed When lock screen or entering background and resume the application textures from pvr.ccz file become black
+     [FIX]          Fixed Stroke font color
+     [NEW]          Uses Native Activity
+[iOS]
+     [FIX]          Status bar can be hidden on iOS 7
+     [FIX]          Added iOS7 icons to templates and tests
+[Mac OS X]
+     [NEW]          iOS and Mac tempaltes were merged into one single Xcode project file.
+     [NEW]          Added Lua template
+[JavaScript bindings]
+     [FIX]          CCBReader is able to set properties to owner if 'owner var' is setted
+     [FIX]          Fixed crash when extending cc.ScrollView in JS
+     [FIX]          cc.registerTargettedDelegate supports pure js object as its target
+     [FIX]          Fixed memory leak in the binding glue code of cc.FileUtils.getStringFromFile(getByteArrayFromFile)
+     [NEW]          Added bindigns for Sprite::getDisplayFrame(), ControlButton callback and RemoveSelf
+[Lua bindings]
+     [NEW]          Bind Sprite::getDisplayFrame()
+
+
+cocos2d-x-3.0alpha0-pre @Jul.30 2013
+[all platforms]
+     [FIX]      #2124: Image::initWithImageFileThreadSafe is not thread safe
+     [FIX]      #2230: Node::onEnterTransitionDidFinish was called twice when a node is added in Node::onEnter
+     [FIX]      #2237: calculation offset in font rendering
+     [FIX]      #2303: missing precision when getting strokeColor and fontFillColor
+     [FIX]      #2312: WebSocket can not parse url like "ws://domain.com/websocket

+ 131 - 0
cocos2d/CMakeLists.txt

@@ -0,0 +1,131 @@
+#/****************************************************************************
+# Copyright (c) 2013 cocos2d-x.org
+# Copyright (c) 2014 martell malone
+# Copyright (c) 2015-2017 Chukong Technologies 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.
+# ****************************************************************************/
+
+cmake_minimum_required(VERSION 3.1)
+# It ensures that when Find*.cmake files included from cmake's Modules dir
+# include another *.cmake file with relative path, that file will be included
+# also from cmake's Modules dir, to not clash with per-project files.
+cmake_policy(SET CMP0017 NEW)
+
+# Use new behaviour with cmake >= 3.1:
+# Only interpret if() arguments as variables or keywords when unquoted.
+if(CMAKE_VERSION VERSION_GREATER 3.1)
+    cmake_policy(SET CMP0054 NEW)
+endif()
+
+project (Cocos2d-X)
+
+# The version number
+set(COCOS2D_X_VERSION 3.13)
+
+# define some variables
+
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/Modules/")
+set(COCOS_EXTERNAL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external)
+# architecture
+if (CMAKE_SIZEOF_VOID_P EQUAL 8)
+  set(ARCH_DIR "64-bit")
+elseif (CMAKE_SIZEOF_VOID_P EQUAL 4)
+  set(ARCH_DIR "32-bit")
+else()
+  message(FATAL_ERROR "Unsupported architecture, CMake will exit")
+  return()
+endif()
+# CMAKE_BUILD_TYPE has precedence over DEBUG_MODE
+# Still supporting DEBUG_MODE for backwards compatibility
+if (NOT CMAKE_BUILD_TYPE)
+  if(DEBUG_MODE)
+    set(CMAKE_BUILD_TYPE DEBUG)
+  else(DEBUG_MODE)
+    set(CMAKE_BUILD_TYPE RELEASE)
+  endif(DEBUG_MODE)
+endif(NOT CMAKE_BUILD_TYPE)
+
+include(CocosBuildHelpers)
+
+message(${BUILDING_STRING})
+
+# SelectModule() is a macro to select building modules
+include(SelectModule)
+SelectModule()
+
+# set compiler options
+include(SetCompilerOptions)
+SetCompilerOptions()
+
+if (CMAKE_FIND_ROOT_PATH AND USE_PREBUILT_LIBS)
+  # Adds cocos2d-x external folder to the list of valid include/library paths when cross-compiling and using prebuilds
+  set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${COCOS_EXTERNAL_DIR})
+endif ()
+
+include_directories(
+  ${CMAKE_CURRENT_SOURCE_DIR}
+  ${CMAKE_CURRENT_SOURCE_DIR}/cocos
+  ${CMAKE_CURRENT_SOURCE_DIR}/deprecated
+  ${CMAKE_CURRENT_SOURCE_DIR}/cocos/platform
+  ${CMAKE_CURRENT_SOURCE_DIR}/extensions
+  ${CMAKE_CURRENT_SOURCE_DIR}/external
+)
+
+if(USE_PREBUILT_LIBS)
+  include(CocosUsePrebuiltLibs)
+endif()
+
+include(BuildModules)
+BuildModules()
+
+# build cpp-empty-test
+if(BUILD_CPP_EMPTY_TEST)
+  add_subdirectory(tests/cpp-empty-test)
+endif(BUILD_CPP_EMPTY_TEST)
+
+# build cpp-tests
+if(BUILD_CPP_TESTS)
+  add_subdirectory(tests/cpp-tests)
+endif(BUILD_CPP_TESTS)
+
+## Scripting
+if(BUILD_LUA_LIBS)
+    add_subdirectory(cocos/scripting/lua-bindings)
+
+  # build lua tests
+  if(BUILD_LUA_TESTS)
+    add_subdirectory(tests/lua-tests/project)
+    add_subdirectory(tests/lua-empty-test/project)
+  endif(BUILD_LUA_TESTS)
+
+endif(BUILD_LUA_LIBS)
+
+## JS
+if(BUILD_JS_LIBS)
+  add_subdirectory(cocos/scripting/js-bindings)
+
+  # build js tests
+  if(BUILD_JS_TESTS)
+    add_subdirectory(tests/js-tests/project)
+  endif(BUILD_JS_TESTS)
+
+endif(BUILD_JS_LIBS)

+ 86 - 0
cocos2d/CONTRIBUTING.md

@@ -0,0 +1,86 @@
+# Contributing to cocos2d-x
+
+
+## For general questions
+
+
+You can ask general questions by using:
+
+-   Forum (preferred way): http://discuss.cocos2d-x.org/
+-   IRC: https://webchat.freenode.net/ (Use the *cocos2d* or *cocos2d-x* channels)
+-   Weibo: http://t.sina.com.cn/cocos2dx
+-   Twitter: http://www.twitter.com/cocos2dx
+
+## Reporting bugs
+
+To report bugs, please use the [Issue Tracker](https://github.com/cocos2d/cocos2d-x/issues)
+
+Steps to report a bug:
+* Open the [url](https://github.com/cocos2d/cocos2d-x/issues/new)
+* Add all the needed information to reproduce the bug, the information include
+    * engine version
+    * steps to reproduce the bug
+    * some pseudocode
+    * resources link if needed
+
+
+## Submitting patches
+
+If you want to contribute code, please follow these steps:
+
+(If you are new to git and/or GitHub, you should read [Pro Git](http://progit.org/book/) , especially the section on [Contributing to a project:Small/Large Public Project](http://progit.org/book/ch5-2.html#public_small_project) )
+
+-   Download the latest cocos2d-x develop branch from github:
+
+```
+$ git clone git://github.com/cocos2d/cocos2d-x.git
+$ cd cocos2d-x
+$ git checkout v3
+$ ./download-deps.py
+$ git submodule update --init
+```
+
+-   Apply your changes in the recently downloaded repository
+-   Commit your changes in your own repository
+-   Create a new branch with your patch: `$ git checkout -b my_fix_branch`
+-   Push your new branch to your public repository
+-   Send a “pull request” to user “cocos2d”
+-   It must be _complete_. See the definition below
+-   It must follow the _Releases_ rules. See the definition below
+
+## Only _complete_ patches will be merged
+
+The patch must be _complete_. And by that, we mean:
+
+-   For C++ code follow the [Cocos2d C++ Coding Style][1]
+-   For Python code follow the [PEP8 guidelines][3]
+-   Describe what the patch does
+-   Include test cases if applicable
+-   Include unit tests if applicable
+-   Must be tested in all supported platforms [*]
+-   Must NOT degrade the performance
+-   Must NOT break existing tests cases
+-   Must NOT break the Continuous Integration build
+-   Must NOT break backward compatibility
+-   Must compile WITHOUT warnings
+-   New APIs MUST be **easy to use**, **familiar** to cocos2d-x users
+-   Code MUST be **easy to extend** and **maintain**
+-   Must have documentation: C++ APIs must use Doxygen strings, tools must have a README.md file that describe how to use the tool
+-   Must be efficient (fast / low memory needs)
+-   It must not duplicate existing code, unless the new code deprecates the old one
+-   Patches that refactor key components will only be merged in the next major versions.
+
+[*]: If you don't have access to test your code in all the supported platforms, let us know.
+
+__TBD__: Is this applicable for big features ? What is the best way to merge big features ?
+
+# Promoting cocos2d
+
+Help us promote cocos2d-x by using the cocos2d logo in your game, or by mentioning cocos2d in the credits.
+
+[Logo Resources of Cocos2d-x][2]
+
+
+[1]: https://github.com/cocos2d/cocos2d-x/blob/v3/docs/CODING_STYLE.md
+[2]: http://www.cocos2d-x.org/wiki/Logo_Resources_of_Cocos2d-x
+[3]: https://www.python.org/dev/peps/pep-0008

+ 40 - 0
cocos2d/README.cmake

@@ -0,0 +1,40 @@
+
+CMake Build Instructions
+
+NB. Depending on your host system your Generator flag -G may be different
+
+Typical -G options
+For using gcc and clang from a makefile
+
+msys2 = "MSYS Makefiles"
+windows = "MinGW Makefiles"
+nix and mac = "Unix Makefiles"
+
+For using and editor such as Visual Studio or xcode or sublime text there are different flags
+
+To like all available flags for your system run
+
+cmake --help
+
+
+More Examples
+
+mac build Instructions
+
+cd cocos2d-x
+mkdir macbuild && cd macbuild
+cmake -G "Unix Makefiles" -DBUILD_CPP_TESTS=OFF -DBUILD_LUA_LIBS=OFF ..
+
+Android Build Instructions
+
+cd cocos2d-x
+mkdir androidbuild && cd androidbuild
+cmake -G"MSYS Makefiles" -DANDROID_NDK=/path/to/android-ndk-r9d -DANDROID_NATIVE_API_LEVEL=android-9 -DCMAKE_TOOLCHAIN_FILE=../cmake/android.toolchain.cmake ..
+
+mingw64 with msys2 build Instructions
+
+cd cocos2d-x
+mkdir mingwbuild && cd mingwbuild
+cmake -G "MSYS Makefiles" -DBUILD_CPP_TESTS=OFF -DBUILD_LUA_LIBS=OFF ..
+
+todo: structure this document in markdown with better examples and more details

+ 337 - 0
cocos2d/README.md

@@ -0,0 +1,337 @@
+<img src="http://www.cocos2d-x.org/attachments/801/cocos2dx_portrait.png" width=200>
+
+
+cocos2d-x
+=========
+
+|  |iOS|Mac|Linux|Win32|Android|Win8.1-Universal|
+| ----|----|----- | ---|----|------|---|
+|v3|[![Build Status](http://45.56.80.45:8080/buildStatus/icon?job=daily-build-v3/node=ios)](http://45.56.80.45:8080/job/daily-build-v3/node=ios)|[![Build Status](http://45.56.80.45:8080/buildStatus/icon?job=daily-build-v3/node=mac)](http://45.56.80.45:8080/job/daily-build-v3/node=mac)|[![Build Status](http://45.56.80.45:8080/buildStatus/icon?job=daily-build-v3/node=linux)](http://45.56.80.45:8080/job/daily-build-v3/node=linux)|[![Build Status](http://45.56.80.45:8080/buildStatus/icon?job=daily-build-v3/node=win32_bak)](http://45.56.80.45:8080/job/daily-build-v3/node=win32_bak)|[![Build Status](http://45.56.80.45:8080/buildStatus/icon?job=daily-build-v3/node=android)](http://45.56.80.45:8080/job/daily-build-v3/node=android)|[![Build Status](http://45.56.80.45:8080/buildStatus/icon?job=daily-build-v3/node=windows-universal_bak)](http://45.56.80.45:8080/job/daily-build-v3/node=windows-universal_bak)|
+
+
+[cocos2d-x][1] is a multi-platform framework for building 2d games, interactive books, demos and other graphical applications.
+It is based on [cocos2d-iphone][2], but instead of using Objective-C, it uses C++.
+It works on iOS, Android, Tizen, Windows Phone and Store Apps, OS X, Windows, Linux and Web platforms.
+
+**Cocos2d-x Framework Architecture**:
+
+![](docs/framework_architecture.jpg "")
+
+cocos2d-x is:
+
+  * Fast
+  * Free
+  * Easy to use
+  * Community supported
+
+Git user attention
+-----------------------
+
+1. Clone the repo from GitHub.
+
+         $ git clone https://github.com/cocos2d/cocos2d-x.git
+
+2. After cloning the repo, please execute `download-deps.py` to download and install dependencies.
+
+         $ cd cocos2d-x
+         cocos2d-x $ python download-deps.py
+
+3. After running `download-deps.py`.
+
+         cocos2d-x $ git submodule update --init
+
+Download stable versions
+-----------------------
+
+* [Cocos2d-x stable versions](http://www.cocos2d-x.org/download)
+* [Cocos2d-JS Lite version](http://www.cocos2d-x.org/filecenter/jsbuilder)
+
+How to start a new game
+-----------------------
+
+1. Download the code from [cocos2d download site][4]
+2. Run `setup.py`
+3. Run the `cocos` script
+
+Example:
+
+    $ cd cocos2d-x
+    $ ./setup.py
+    $ source FILE_TO_SAVE_SYSTEM_VARIABLE
+    $ cocos new MyGame -p com.your_company.mygame -l cpp -d NEW_PROJECTS_DIR
+    $ cd NEW_PROJECTS_DIR/MyGame
+
+You can also create a JS project or Lua project with `-l js` or `-l lua`.
+
+### Build and run a new project for Android ###
+
+    $ cocos run -p android -j 4
+
+### Build and run a new project for iOS ###
+
+    $ cocos run -p ios
+
+### Build and run a new project for OSX ###
+
+    $ cocos run -p mac
+
+### Build and run a new project for Tizen ###
+
+The cocos command line tools doesn't support Tizen yet, you have to use Tizen IDE to do the build.
+
+Please refer to this [guide](http://cocos2d-x.org/docs/installation/Tizen/index.html ).
+
+
+### Build and run a new project for Linux ###
+
+If you never run cocos2d-x on Linux, you need to install all dependencies by the
+script in **cocos2d/build/install-deps-linux.sh**
+
+    $ cd cocos2d-x/build
+    $ ./install-deps-linux.sh
+
+Then
+
+    $ cd NEW_PROJECTS_DIR/MyGame
+    $ cocos run -p linux
+
+Run
+
+    $ bin/MyGame
+
+### Build and run new project for win32 ###
+
+    $ cocos run -p win32
+
+### Build and run new project for Windows 8.1/10.0 and Windows Phone 8.1/10.0 ###
+
+    $ cocos new MyGame -p com.your_company.mygame -l cpp -d projects
+
+* Visual Studio 2013 Update 4 or later is required for Windows 8.1 Universal Apps
+
+* Visual Studio 2015 (Release version) and Windows 10.0 (Release version) are required for Windows 10.0 Universal Windows Platform (UWP) Apps. RC versions of Visual Studio and Windows 10 are no longer supported.
+
+Starting with Cocos2d-x v3.3, you can create Windows 8.1 Universal Apps (Windows Store and Windows Phone 8.1).
+Starting with Cocos2d-x v3.8 you can create Windows 10.0 UWP Apps (Windows Store and Windows Phone 10.0).
+Starting with Cocos2d-x v3.6 there will no longer be support for Windows Phone 8.0.
+
+See more info on how to install and create games on Windows RT (Windows and Windows Phone 8.1) at http://msopentech.github.io/cocos2d-x/
+
+### Build and run new project for web ###
+
+Only JS project can be published to web platforms, so you will need to create a JS project first:
+
+    $ cocos new -l js WebGame
+
+Then you can run your game in a web browser:
+
+    $ cocos run -p web
+
+Or you can publish your game to `publish/html5/` folder:
+
+    $ cocos run -p web -m release [--advanced]
+
+Documentations and samples
+-------------
+* [All Docs in a single place!](http://cocos2d-x.org/docs/)
+* [Online API Reference](http://cocos2d-x.org/docs/api-ref/index.html) _Note that Cocos2d-x, Cocos2d-JS and Cocos Creator have different API set_
+* [Programmers Guide](http://cocos2d-x.org/docs/programmers-guide/2/index.html)
+* [Latest Release Note](https://github.com/cocos2d/cocos2d-x/blob/v3/docs/RELEASE_NOTES.md)
+* [Changelog](https://github.com/cocos2d/cocos2d-x/blob/v3/CHANGELOG)
+* [Cocos2d sample games](https://github.com/cocos2d/cocos2d-x-samples) _More samples will be added in v3.8_
+
+Main features
+-------------
+   * Scene management (workflow)
+   * Transitions between scenes
+   * Sprites and Sprite Sheets
+   * Effects: Lens, Ripple, Waves, Liquid, etc.
+   * Actions (behaviours):
+     * Transformation Actions: Move, Rotate, Scale, Fade, Tint, etc.
+     * Composable actions: Sequence, Spawn, Repeat, Reverse
+     * Ease Actions: Exp, Sin, Cubic, Elastic, etc.
+     * Misc actions: CallFunc, OrbitCamera, Follow, Tween
+   * Basic menus and buttons
+   * Integrated with physics engines: [Box2d][5] and [Chipmunk][6]
+   * Particle system
+   * Skeleton Animations: [Spine][7] and Armature support
+   * Fonts:
+     * Fast font rendering using Fixed and Variable width fonts
+     * Support for .ttf fonts
+   * Tile Map support: Orthogonal, Isometric and Hexagonal
+   * Parallax scrolling
+   * Motion Streak
+   * Render To Texture
+   * Touch/Accelerometer on mobile devices
+   * Touch/Mouse/Keyboard on desktop
+   * Sound Engine support (CocosDenshion library) based on OpenAL
+   * Integrated Slow motion/Fast forward
+   * Fast and compressed textures: PVR compressed and uncompressed textures, ETC1 compressed textures, and more
+   * Resolution Independent
+   * Language: C++, with Lua and JavaScript bindings
+   * Open Source Commercial Friendly(MIT): Compatible with open and closed source projects
+   * OpenGL ES 2.0 (mobile) / OpenGL 2.1 (desktop) based
+
+Build Requirements
+------------------
+
+* Mac OS X 10.7+, Xcode 7+
+* or Ubuntu 12.10+, CMake 2.6+
+* or Windows 7+, VS 2013+
+* Python 2.7.5
+* NDK r11+ is required to build Android games
+* Android Studio 2.3+ bo build Android games
+* Tizen SDK 2.3+ is required to build Tizen games
+* Windows Phone/Store 10.0 VS 2015
+* JRE or JDK 1.6+ is required for web publishing
+
+Runtime Requirements
+--------------------
+  * iOS 7.0+ for iPhone / iPad games
+  * Android 2.3.3+ for Android games
+  * Tizen 2.3+ or 2.4+ for Tizen games
+  * Windows 10.0 for Windows Phone/Store 10.0  games
+  * OS X v10.9+ for Mac games
+  * Windows 7+ for Win games
+  * Modern browsers and IE 9+ for web games
+
+Running Tests
+--------------------
+
+Select the test you want from Xcode Scheme chooser.
+
+* Cocos Console
+
+```
+// Enter cpp test folder
+cd tests/cpp-tests
+// Or enter js test folder
+cd tests/js-tests
+// Or enter lua test folder
+cd tests/lua-tests
+
+// Compile or run test case
+cocos compile -p ios|mac|android|win32|win8_1|metro|web -m debug|release
+cocos run -p ios|mac|android|win32|win8_1|metro|web -m debug|release
+```
+
+* For OS X / iOS
+
+```
+$ cd cocos2d-x/build
+$ open cocos2d_tests.xcodeproj
+```
+
+* For Linux
+
+```
+$ cd cocos2d-x/build
+$ ./install-deps-linux.sh
+$ cmake ..
+$ make
+```
+
+Run Samples
+
+```
+$ bin/cpp-empty-test/cpp-empty-test
+or
+$ bin/lua-empty-test/lua-empty-test
+```
+
+      You may meet building errors when building libGLFW.so. It is because libGL.so directs to an error target,
+      you should make it to direct to a correct one. `install-deps-linux.sh` only has to be run once.
+
+* For Windows
+
+Open the `cocos2d-x/build/cocos2d-win32.sln`
+
+* For Windows 8.1 Universal Apps (Phone and Store)
+
+Open the `cocos2d-x/build/cocos2d-win8.1-universal.sln`
+
+* For Windows 10.0 Universal Windows Platform (UWP) Apps (Phone and Store)
+
+Open the `cocos2d-x/build/cocos2d-win10.sln`
+
+* For Android
+
+```
+$ cd cocos2d-x/build
+$ python ./android-build.py cpp-empty-test -p 10
+$ adb install ../tests/cpp-empty-test/proj.android/bin/CppEmptyTest-debug.apk
+```
+
+Then click item on Android device to run tests. Available value of `-p` is the API level, cocos2d-x supports from level 10.
+
+* For Tizen
+
+Please refer to this [guide](http://cocos2d-x.org/docs/installation/Tizen/index.html ).
+
+Learning Resources
+--------------------------------
+
+* [Programmers Guide](http://cocos2d-x.org/docs/programmers-guide/2/index.html)
+* [Sonar Systems Videos](https://www.youtube.com/user/sonarsystemslimited/search?query=cocos2d-x)
+* [Android Fundamentals](https://developer.android.com/guide/components/fundamentals.html)
+* [Make School Tutorials](https://www.makeschool.com/tutorials/)
+* [Games From Scratch](http://www.gamefromscratch.com/page/Cocos2d-x-CPP-Game-Programming-Tutorial-Series.aspx)
+* [Cocos2d sample games](https://github.com/cocos2d/cocos2d-x-samples)
+
+Spreading the word!
+--------------------------------
+You can help us spread the word about cocos2d-x! We would surely appreciate it!
+
+* Talk about us on Facebook! Our [Facebook Page](https://www.facebook.com/cocos2dx/)
+* Tweet, Tweet! Our [Twitter](https://twitter.com/cocos2dx)
+* Read our [Blog](http://blog.cocos2d-x.org/) and promote it on your social media.
+* Become a [Regional Coordinator](http://discuss.cocos2d-x.org/t/we-need-regional-coordinators/24104)
+
+See what we are planning!
+--------------------------------
+You can see exactly what we are planning to do with the Cocos family of products.
+
+* [Cocos2d-x roadmap](https://trello.com/b/Np6obnuE/cocos2d-x-roadmap)
+
+Where to get help
+--------------------------------
+
+* [Forums](http://discuss.cocos2d-x.org)
+* [Bug Tracker](https://github.com/cocos2d/cocos2d-x/issues)
+* IRC. We are in [Freenode](https://webchat.freenode.net/) in the _#cocos2d_ channel
+* `cpp-tests` project. This project is our basis for testing. Use this project to
+learn how we implement the functionality of the engine. This project is located in
+__cocos2d-x_root/build.__
+* [API Reference](http://cocos2d-x.org/docs/api-ref/index.html).
+* [Latest Release Note](https://github.com/cocos2d/cocos2d-x/blob/v3/docs/RELEASE_NOTES.md)
+* [Changelog](https://github.com/cocos2d/cocos2d-x/blob/v3/CHANGELOG)
+
+Contributing to the Project
+--------------------------------
+
+Cocos2d-x is licensed under the [MIT License](https://opensource.org/licenses/MIT). We welcome participation!
+
+Did you find a bug? Do you have feature request? Do you want to merge a feature?
+
+  * [contributing to cocos2d-x][8]
+
+Contact us
+----------
+
+   * Forum: [http://discuss.cocos2d-x.org][9]
+   * Twitter: [http://www.twitter.com/cocos2dx][10]
+   * Weibo: [http://t.sina.com.cn/cocos2dx][11]
+   * IRC: [https://webchat.freenode.net/][12] (#cocos2d and #cocos2d-x channels)
+
+[1]: http://www.cocos2d-x.org "cocos2d-x"
+[2]: http://www.cocos2d-iphone.org "cocos2d for iPhone"
+[3]: http://www.cocos2d-x.org/projects/cocos2d-x/wiki/Download
+[4]: http://www.cocos2d-x.org/download/version#Cocos2d-x
+[5]: http://www.box2d.org "Box2D"
+[6]: http://www.chipmunk-physics.net "Chipmunk2D"
+[7]: http://esotericsoftware.com/ "http://esotericsoftware.com/"
+[8]: https://github.com/cocos2d/cocos2d-x/blob/v3/CONTRIBUTING.md
+[9]: http://discuss.cocos2d-x.org "http://discuss.cocos2d-x.org"
+[10]: http://www.twitter.com/cocos2dx "http://www.twitter.com/cocos2dx"
+[11]: http://t.sina.com.cn/cocos2dx "http://t.sina.com.cn/cocos2dx"
+[12]: https://webchat.freenode.net/ "https://webchat.freenode.net/"

+ 95 - 0
cocos2d/cmake/AndroidNdkGdb.cmake

@@ -0,0 +1,95 @@
+# Copyright (c) 2014, Pavel Rojtberg
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived from this
+# software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+# ------------------------------------------------------------------------------
+# Usage:
+# 1. place AndroidNdkGdb.cmake somewhere inside ${CMAKE_MODULE_PATH}
+# 2. inside your project add
+#
+#    include(AndroidNdkGdb)
+#    android_ndk_gdb_enable()
+#    # for each target
+#    add_library(MyLibrary ...)
+#    android_ndk_gdb_debuggable(MyLibrary)    
+
+
+# add gdbserver and general gdb configuration to project
+# also create a mininal NDK skeleton so ndk-gdb finds the paths
+#
+# the optional parameter defines the path to the android project.
+# uses PROJECT_BINARY_DIR by default.
+macro(android_ndk_gdb_enable)
+    if(ANDROID)
+        # create custom target that depends on the real target so it gets executed afterwards
+        add_custom_target(NDK_GDB ALL)
+        
+        if(${ARGC})
+            set(ANDROID_PROJECT_DIR ${ARGV0})
+        else()
+            set(ANDROID_PROJECT_DIR ${PROJECT_BINARY_DIR})
+        endif()
+
+        set(NDK_GDB_SOLIB_PATH ${ANDROID_PROJECT_DIR}/obj/local/${ANDROID_NDK_ABI_NAME}/)
+        file(MAKE_DIRECTORY ${NDK_GDB_SOLIB_PATH})
+        
+        # 1. generate essential Android Makefiles
+        file(MAKE_DIRECTORY ${ANDROID_PROJECT_DIR}/jni)
+        if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Android.mk)
+            file(WRITE ${ANDROID_PROJECT_DIR}/jni/Android.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n")
+        endif()
+        if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Application.mk)
+            file(WRITE ${ANDROID_PROJECT_DIR}/jni/Application.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n")
+        endif()
+    
+        # 2. generate gdb.setup
+        get_directory_property(PROJECT_INCLUDES DIRECTORY ${PROJECT_SOURCE_DIR} INCLUDE_DIRECTORIES)
+        string(REGEX REPLACE ";" " " PROJECT_INCLUDES "${PROJECT_INCLUDES}")
+        file(WRITE ${LIBRARY_OUTPUT_PATH}/gdb.setup "set solib-search-path ${NDK_GDB_SOLIB_PATH}\n")
+        file(APPEND ${LIBRARY_OUTPUT_PATH}/gdb.setup "directory ${PROJECT_INCLUDES}\n")
+    
+        # 3. copy gdbserver executable
+        file(COPY ${ANDROID_NDK}/prebuilt/android-${ANDROID_ARCH_NAME}/gdbserver/gdbserver DESTINATION ${LIBRARY_OUTPUT_PATH})
+        file(RENAME ${LIBRARY_OUTPUT_PATH}/gdbserver ${LIBRARY_OUTPUT_PATH}/gdbserver.so)
+    endif()
+endmacro()
+
+# register a target for remote debugging
+# copies the debug version to NDK_GDB_SOLIB_PATH then strips symbols of original
+macro(android_ndk_gdb_debuggable TARGET_NAME)
+    if(ANDROID)
+        # create custom target that depends on the real target so it gets executed afterwards
+        add_dependencies(NDK_GDB ${TARGET_NAME})
+    
+        # 4. copy lib to obj
+        add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:${TARGET_NAME}> ${NDK_GDB_SOLIB_PATH})
+    
+        # 5. strip symbols
+        add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_STRIP} $<TARGET_FILE:${TARGET_NAME}>)
+    endif()
+endmacro()

+ 58 - 0
cocos2d/cmake/AndroidNdkModules.cmake

@@ -0,0 +1,58 @@
+# Copyright (c) 2014, Pavel Rojtberg
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived from this
+# software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+macro(android_ndk_import_module_cpufeatures)
+    if(ANDROID)
+        include_directories(${ANDROID_NDK}/sources/android/cpufeatures)      
+        add_library(cpufeatures ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
+        target_link_libraries(cpufeatures dl)
+    endif()
+endmacro()
+
+macro(android_ndk_import_module_native_app_glue)
+    if(ANDROID)
+        include_directories(${ANDROID_NDK}/sources/android/native_app_glue)
+        add_library(native_app_glue ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
+        target_link_libraries(native_app_glue log)
+    endif()
+endmacro()
+
+macro(android_ndk_import_module_ndk_helper)
+    if(ANDROID)
+        android_ndk_import_module_cpufeatures()
+        android_ndk_import_module_native_app_glue()
+        
+        include_directories(${ANDROID_NDK}/sources/android/ndk_helper)
+        file(GLOB _NDK_HELPER_SRCS ${ANDROID_NDK}/sources/android/ndk_helper/*.cpp ${ANDROID_NDK}/sources/android/ndk_helper/gl3stub.c)
+        add_library(ndk_helper ${_NDK_HELPER_SRCS})
+        target_link_libraries(ndk_helper log android EGL GLESv2 cpufeatures native_app_glue)
+        
+        unset(_NDK_HELPER_SRCS)
+    endif()
+endmacro()

+ 2 - 0
cocos2d/cmake/BuildHelpers.CMakeLists.txt

@@ -0,0 +1,2 @@
+# For compatibility only, please use include(CocosBuildHelpers) in future projects
+include(CocosBuildHelpers)

+ 154 - 0
cocos2d/cmake/Modules/BuildModules.cmake

@@ -0,0 +1,154 @@
+macro (BuildModules)
+	# desktop platforms
+	if(LINUX OR MACOSX OR WINDOWS)
+	  cocos_find_package(OpenGL OPENGL REQUIRED)
+
+	  if(LINUX OR WINDOWS)
+	    cocos_find_package(GLEW GLEW REQUIRED)
+	    #TODO: implement correct schema for pass cocos2d specific requirements to projects
+	    include_directories(${GLEW_INCLUDE_DIRS})
+	  endif()
+
+	  cocos_find_package(GLFW3 GLFW3 REQUIRED)
+	  include_directories(${GLFW3_INCLUDE_DIRS})
+
+	  if(LINUX)
+	    set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
+	    find_package(Threads REQUIRED)
+	    set(THREADS_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
+
+	    cocos_find_package(SQLite3 SQLITE3 REQUIRED)
+	    cocos_find_package(FMOD FMOD REQUIRED)
+	    cocos_find_package(Fontconfig FONTCONFIG REQUIRED)
+	    cocos_find_package(GTK3 GTK3 REQUIRED)
+	  endif()
+
+	  if(WINDOWS)
+	    cocos_find_package(Vorbis VORBIS REQUIRED)
+	    cocos_find_package(MPG123 MPG123 REQUIRED)
+	    cocos_find_package(OpenAL OPENAL REQUIRED)
+	    # because FindOpenAL.cmake set include dir for '#include <al.h>' for portability (not for '#include <AL/al.h>'
+        set(OPENAL_DEFINITIONS "-DOPENAL_PLAIN_INCLUDES")
+	  endif()
+	endif(LINUX OR MACOSX OR WINDOWS)
+
+	# Freetype required on all platforms
+	cocos_find_package(Freetype FREETYPE REQUIRED)
+
+	# WebP required if used
+	if(USE_WEBP)
+	  cocos_find_package(WebP WEBP REQUIRED)
+	endif(USE_WEBP)
+
+	# Chipmunk
+	if(USE_CHIPMUNK)
+	  if(USE_PREBUILT_LIBS)
+	    cocos_find_package(Chipmunk CHIPMUNK REQUIRED)
+	  endif()
+	endif(USE_CHIPMUNK)
+
+	# Box2d (not prebuilded, exists as source)
+	if(USE_BOX2D)
+	  if(USE_PREBUILT_LIBS OR USE_SOURCES_EXTERNAL)
+	    add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/external/Box2D)
+	    set(Box2D_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/external/box2d/include)
+	    set(Box2D_LIBRARIES box2d)
+	  else()
+	    find_package(Box2D REQUIRED CONFIG)
+	    # actually Box2D in next line is not a library, it is target exported from Box2DConfig.cmake
+	    set(Box2D_LIBRARIES Box2D)
+	  endif()
+	  message(STATUS "Box2D include dirs: ${Box2D_INCLUDE_DIRS}")
+	elseif(BUILD_BOX2D)
+	  add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/external/Box2D)
+	endif(USE_BOX2D)
+
+	# Bullet (not prebuilded, exists as source)
+	if(USE_BULLET)
+	  if(USE_PREBUILT_LIBS OR USE_SOURCES_EXTERNAL)
+	    add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/external/bullet)
+	    set(BULLET_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/external/bullet)
+	    set(BULLET_LIBRARIES bullet)
+	  else()
+	    cocos_find_package(bullet BULLET REQUIRED)
+	    set(BULLET_LIBRARIES bullet)
+	  endif()
+	  message(STATUS "Bullet include dirs: ${BULLET_INCLUDE_DIRS}")
+	endif(USE_BULLET)
+
+	# Recast (not prebuilded, exists as source)
+	if(USE_RECAST)
+	  if(USE_PREBUILT_LIBS OR USE_SOURCES_EXTERNAL)
+	    add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/external/recast)
+	    set(RECAST_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/external/recast)
+	    set(RECAST_LIBRARIES recast)
+	  else()
+	    cocos_find_package(recast RECAST REQUIRED)
+	    set(RECAST_LIBRARIES recast)
+	  endif()
+	  message(STATUS "Recast include dirs: ${RECAST_INCLUDE_DIRS}")
+	endif(USE_RECAST)
+
+	# Tinyxml2 (not prebuilded, exists as source)
+	if(USE_PREBUILT_LIBS OR USE_SOURCES_EXTERNAL)
+	  add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/external/tinyxml2)
+	  set(TinyXML2_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/external/tinyxml2)
+	  set(TinyXML2_LIBRARIES tinyxml2)
+	else()
+	  cocos_find_package(TinyXML2 TinyXML2 REQUIRED)
+	endif()
+	message(STATUS "TinyXML2 include dirs: ${TinyXML2_INCLUDE_DIRS}")
+
+	# libjpeg
+	cocos_find_package(JPEG JPEG REQUIRED)
+	cocos_find_package(ZLIB ZLIB REQUIRED)
+
+	# minizip (we try to migrate to minizip from https://github.com/nmoinvaz/minizip)
+	# only msys2 currently provides package for this variant, all other
+	# dists have packages from zlib, thats very old for us.
+	# moreover our embedded version modified to quick provide
+	# functionality needed by cocos.
+	if(USE_PREBUILT_LIBS OR NOT MINGW)
+	  #TODO: hack! should be in external/unzip/CMakeLists.txt
+	  include_directories(${ZLIB_INCLUDE_DIRS})
+	  add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/external/unzip)
+	  set(MINIZIP_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/external/unzip ${ZLIB_INCLUDE_DIRS})
+	  set(MINIZIP_LIBRARIES unzip ${ZLIB_LIBRARIES})
+	  message(STATUS "MINIZIP include dirs: ${MINIZIP_INCLUDE_DIRS}")
+	else()
+	  cocos_find_package(MINIZIP MINIZIP REQUIRED)
+	  # double check that we have needed functions
+	  include(CheckLibraryExists)
+	  check_library_exists(${MINIZIP_LIBRARIES} "unzGoToFirstFile2" "" MINIZIP_HAS_GOTOFIRSTFILE2)
+	  if(NOT MINIZIP_HAS_GOTOFIRSTFILE2)
+	    message(FATAL_ERROR "Minizip library on you system very old. Please use recent version from https://github.com/nmoinvaz/minizip or enable USE_PREBUILT_LIBS")
+	    return()
+	  endif()
+	endif()
+
+	cocos_find_package(PNG PNG REQUIRED)
+	cocos_find_package(TIFF TIFF REQUIRED)
+	cocos_find_package(WEBSOCKETS WEBSOCKETS REQUIRED)
+	cocos_find_package(CURL CURL REQUIRED)
+
+	# flatbuffers
+	if(USE_PREBUILT_LIBS OR USE_SOURCES_EXTERNAL)
+	  add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/external/flatbuffers)
+	  set(FLATBUFFERS_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/external)
+	  message(STATUS "Flatbuffers include dirs: ${FLATBUFFERS_INCLUDE_DIRS}")
+	else()
+	  cocos_find_package(flatbuffers flatbuffers REQUIRED)
+	endif()
+
+	# xxhash
+	if(USE_PREBUILT_LIBS OR USE_SOURCES_EXTERNAL)
+	  add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/external/xxhash)
+	  set(XXHASH_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/external/xxhash)
+	  set(XXHASH_LIBRARIES xxhash)
+	else()
+	  cocos_find_package(xxhash xxhash REQUIRED)
+	endif()
+
+	# libcocos2d.a
+    add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/cocos)
+endmacro(BuildModules)

+ 160 - 0
cocos2d/cmake/Modules/CMakeParseArguments.cmake

@@ -0,0 +1,160 @@
+#.rst:
+# CMakeParseArguments
+# -------------------
+#
+#
+#
+# CMAKE_PARSE_ARGUMENTS(<prefix> <options> <one_value_keywords>
+# <multi_value_keywords> args...)
+#
+# CMAKE_PARSE_ARGUMENTS() is intended to be used in macros or functions
+# for parsing the arguments given to that macro or function.  It
+# processes the arguments and defines a set of variables which hold the
+# values of the respective options.
+#
+# The <options> argument contains all options for the respective macro,
+# i.e.  keywords which can be used when calling the macro without any
+# value following, like e.g.  the OPTIONAL keyword of the install()
+# command.
+#
+# The <one_value_keywords> argument contains all keywords for this macro
+# which are followed by one value, like e.g.  DESTINATION keyword of the
+# install() command.
+#
+# The <multi_value_keywords> argument contains all keywords for this
+# macro which can be followed by more than one value, like e.g.  the
+# TARGETS or FILES keywords of the install() command.
+#
+# When done, CMAKE_PARSE_ARGUMENTS() will have defined for each of the
+# keywords listed in <options>, <one_value_keywords> and
+# <multi_value_keywords> a variable composed of the given <prefix>
+# followed by "_" and the name of the respective keyword.  These
+# variables will then hold the respective value from the argument list.
+# For the <options> keywords this will be TRUE or FALSE.
+#
+# All remaining arguments are collected in a variable
+# <prefix>_UNPARSED_ARGUMENTS, this can be checked afterwards to see
+# whether your macro was called with unrecognized parameters.
+#
+# As an example here a my_install() macro, which takes similar arguments
+# as the real install() command:
+#
+# ::
+#
+#    function(MY_INSTALL)
+#      set(options OPTIONAL FAST)
+#      set(oneValueArgs DESTINATION RENAME)
+#      set(multiValueArgs TARGETS CONFIGURATIONS)
+#      cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
+#      ...
+#
+#
+#
+# Assume my_install() has been called like this:
+#
+# ::
+#
+#    my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub)
+#
+#
+#
+# After the cmake_parse_arguments() call the macro will have set the
+# following variables:
+#
+# ::
+#
+#    MY_INSTALL_OPTIONAL = TRUE
+#    MY_INSTALL_FAST = FALSE (this option was not used when calling my_install()
+#    MY_INSTALL_DESTINATION = "bin"
+#    MY_INSTALL_RENAME = "" (was not used)
+#    MY_INSTALL_TARGETS = "foo;bar"
+#    MY_INSTALL_CONFIGURATIONS = "" (was not used)
+#    MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (no value expected after "OPTIONAL"
+#
+#
+#
+# You can then continue and process these variables.
+#
+# Keywords terminate lists of values, e.g.  if directly after a
+# one_value_keyword another recognized keyword follows, this is
+# interpreted as the beginning of the new option.  E.g.
+# my_install(TARGETS foo DESTINATION OPTIONAL) would result in
+# MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION
+# would be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefor.
+
+#=============================================================================
+# Copyright 2010 Alexander Neundorf <neundorf@kde.org>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+
+if(__CMAKE_PARSE_ARGUMENTS_INCLUDED)
+  return()
+endif()
+set(__CMAKE_PARSE_ARGUMENTS_INCLUDED TRUE)
+
+
+function(CMAKE_PARSE_ARGUMENTS prefix _optionNames _singleArgNames _multiArgNames)
+  # first set all result variables to empty/FALSE
+  foreach(arg_name ${_singleArgNames} ${_multiArgNames})
+    set(${prefix}_${arg_name})
+  endforeach()
+
+  foreach(option ${_optionNames})
+    set(${prefix}_${option} FALSE)
+  endforeach()
+
+  set(${prefix}_UNPARSED_ARGUMENTS)
+
+  set(insideValues FALSE)
+  set(currentArgName)
+
+  # now iterate over all arguments and fill the result variables
+  foreach(currentArg ${ARGN})
+    list(FIND _optionNames "${currentArg}" optionIndex)  # ... then this marks the end of the arguments belonging to this keyword
+    list(FIND _singleArgNames "${currentArg}" singleArgIndex)  # ... then this marks the end of the arguments belonging to this keyword
+    list(FIND _multiArgNames "${currentArg}" multiArgIndex)  # ... then this marks the end of the arguments belonging to this keyword
+
+    if(${optionIndex} EQUAL -1  AND  ${singleArgIndex} EQUAL -1  AND  ${multiArgIndex} EQUAL -1)
+      if(insideValues)
+        if("${insideValues}" STREQUAL "SINGLE")
+          set(${prefix}_${currentArgName} ${currentArg})
+          set(insideValues FALSE)
+        elseif("${insideValues}" STREQUAL "MULTI")
+          list(APPEND ${prefix}_${currentArgName} ${currentArg})
+        endif()
+      else()
+        list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${currentArg})
+      endif()
+    else()
+      if(NOT ${optionIndex} EQUAL -1)
+        set(${prefix}_${currentArg} TRUE)
+        set(insideValues FALSE)
+      elseif(NOT ${singleArgIndex} EQUAL -1)
+        set(currentArgName ${currentArg})
+        set(${prefix}_${currentArgName})
+        set(insideValues "SINGLE")
+      elseif(NOT ${multiArgIndex} EQUAL -1)
+        set(currentArgName ${currentArg})
+        set(${prefix}_${currentArgName})
+        set(insideValues "MULTI")
+      endif()
+    endif()
+
+  endforeach()
+
+  # propagate the result variables to the caller:
+  foreach(arg_name ${_singleArgNames} ${_multiArgNames} ${_optionNames})
+    set(${prefix}_${arg_name}  ${${prefix}_${arg_name}} PARENT_SCOPE)
+  endforeach()
+  set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE)
+
+endfunction()

+ 163 - 0
cocos2d/cmake/Modules/CocosBuildHelpers.cmake

@@ -0,0 +1,163 @@
+include(CMakeParseArguments)
+
+macro(pre_build TARGET_NAME)
+  add_custom_target( ${TARGET_NAME}_PRE_BUILD ALL )
+
+  add_custom_command(
+    TARGET ${TARGET_NAME}_PRE_BUILD
+    ${ARGN}
+    PRE_BUILD
+    COMMENT "${TARGET_NAME}_PRE_BUILD ..."
+    )
+
+  add_custom_target(${TARGET_NAME}_CORE_PRE_BUILD)
+  add_dependencies(${TARGET_NAME}_PRE_BUILD ${TARGET_NAME}_CORE_PRE_BUILD)
+  add_dependencies(${TARGET_NAME} ${TARGET_NAME}_PRE_BUILD)
+endmacro()
+
+function(cocos_mark_resources)
+    set(oneValueArgs BASEDIR RESOURCEBASE)
+    set(multiValueArgs FILES)
+    cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+    if(NOT opt_RESOURCEBASE)
+        set(opt_RESOURCEBASE Resources)
+    endif()
+
+    get_filename_component(BASEDIR_ABS ${opt_BASEDIR} ABSOLUTE)
+    foreach(RES_FILE ${opt_FILES} ${opt_UNPARSED_ARGUMENTS})
+        get_filename_component(RES_FILE_ABS ${RES_FILE} ABSOLUTE)
+        file(RELATIVE_PATH RES ${BASEDIR_ABS} ${RES_FILE_ABS})
+        get_filename_component(RES_LOC ${RES} PATH)
+        set_source_files_properties(${RES_FILE} PROPERTIES
+            MACOSX_PACKAGE_LOCATION "${opt_RESOURCEBASE}/${RES_LOC}"
+            HEADER_FILE_ONLY 1
+            )
+    endforeach()
+endfunction()
+
+# cocos_find_package(pkg args...)
+# works same as find_package, but do additional care to properly find
+# prebuilt libs for cocos
+macro(cocos_find_package pkg_name pkg_prefix)
+  if(NOT USE_PREBUILT_LIBS OR NOT ${pkg_prefix}_FOUND)
+    find_package(${pkg_name} ${ARGN})
+  endif()
+  if(NOT ${pkg_prefix}_INCLUDE_DIRS AND ${pkg_prefix}_INCLUDE_DIR)
+    set(${pkg_prefix}_INCLUDE_DIRS ${${pkg_prefix}_INCLUDE_DIR})
+  endif()
+  if(NOT ${pkg_prefix}_LIBRARIES AND ${pkg_prefix}_LIBRARY)
+    set(${pkg_prefix}_LIBRARIES ${${pkg_prefix}_LIBRARY})
+  endif()
+
+  message(STATUS "${pkg_name} include dirs: ${${pkg_prefix}_INCLUDE_DIRS}")
+endmacro()
+
+# cocos_use_pkg(pkg) function.
+# This function applies standard package variables (after find_package(pkg) call) to current scope
+# Recognized variables: <pkg>_INCLUDE_DIRS, <pkg>_LIBRARIES, <pkg>_LIBRARY_DIRS
+# Also if BUILD_SHARED_LIBS variable off, it is try to use <pkg>_STATIC_* vars before
+function(cocos_use_pkg target pkg)
+  set(prefix ${pkg})
+  
+  set(_include_dirs)
+  if(NOT _include_dirs)
+    set(_include_dirs ${${prefix}_INCLUDE_DIRS})
+  endif()
+  if(NOT _include_dirs)
+    # backward compat with old package-find scripts
+    set(_include_dirs ${${prefix}_INCLUDE_DIR})
+  endif()
+  if(_include_dirs)
+    include_directories(${_include_dirs})
+    message(STATUS "${pkg} add to include_dirs: ${_include_dirs}")
+  endif()
+  
+  set(_library_dirs)
+  if(NOT _library_dirs)
+    set(_library_dirs ${${prefix}_LIBRARY_DIRS})
+  endif()
+  if(_library_dirs)
+    link_directories(${_library_dirs})
+    message(STATUS "${pkg} add to link_dirs: ${_library_dirs}")
+  endif()
+  
+  set(_libs)
+  if(NOT _libs)
+    set(_libs ${${prefix}_LIBRARIES})
+  endif()
+  if(NOT _libs)
+    set(_libs ${${prefix}_LIBRARY})
+  endif()
+  if(_libs)
+    target_link_libraries(${target} ${_libs})
+    message(STATUS "${pkg} libs added to '${target}': ${_libs}")
+  endif()
+  
+  set(_defs)
+  if(NOT _defs)
+    set(_defs ${${prefix}_DEFINITIONS})
+  endif()
+  if(_defs)
+    add_definitions(${_defs})
+    message(STATUS "${pkg} add definitions: ${_defs}")
+  endif()
+endfunction()
+
+#cmake has some strange defaults, this should help us a lot
+#Please use them everywhere
+
+#WINDOWS 	= 	Windows Desktop
+#WINRT 		= 	Windows RT
+#WP8 	  	= 	Windows Phone 8
+#ANDROID    =	Android
+#IOS		=	iOS
+#MACOSX		=	MacOS X
+#LINUX      =   Linux
+
+if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+  if(WINRT)
+    set(SYSTEM_STRING "Windows RT")
+  elseif(WP8)
+    set(SYSTEM_STRING "Windows Phone 8")
+  else()
+    set(WINDOWS TRUE)
+    set(SYSTEM_STRING "Windows Desktop")
+  endif()
+elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+  if(ANDROID)
+    set(SYSTEM_STRING "Android")
+  else()
+    set(LINUX TRUE)
+    set(SYSTEM_STRING "Linux")
+  endif()
+elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+  if(IOS)
+    set(SYSTEM_STRING "IOS")
+  else()
+    set(MACOSX TRUE)
+    set(APPLE TRUE)
+    set(SYSTEM_STRING "Mac OSX")
+  endif()
+endif()
+
+if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+  set(COMPILER_STRING ${CMAKE_CXX_COMPILER_ID})
+  set(CLANG TRUE)
+elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
+  if(MINGW)
+    set(COMPILER_STRING "Mingw GCC")
+  else()
+    set(COMPILER_STRING "GCC")
+  endif()
+elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
+  set(COMPILER_STRING "${CMAKE_CXX_COMPILER_ID} C++")
+elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+  set(COMPILER_STRING "Visual Studio C++")
+endif()
+
+if(CMAKE_CROSSCOMPILING)
+  set(BUILDING_STRING "It appears you are cross compiling for ${SYSTEM_STRING} with ${COMPILER_STRING}")
+else()
+  set(BUILDING_STRING "It appears you are building natively for ${SYSTEM_STRING} with ${COMPILER_STRING}")
+endif()

+ 220 - 0
cocos2d/cmake/Modules/CocosUsePrebuiltLibs.cmake

@@ -0,0 +1,220 @@
+# CocosUsePrebuiltLibs - sets external libs variables to link with
+
+# START CONFIG
+
+set(_chipmunk_inc chipmunk/chipmunk.h)
+set(_chipmunk_inc_paths include)
+if(WINDOWS)
+    if (${MSVC_VERSION} STREQUAL "1900")
+        set(_chipmunk_libs chipmunk libchipmunk-2015)
+    else()
+        set(_chipmunk_libs chipmunk libchipmunk)
+    endif(${MSVC_VERSION})
+else()
+    set(_chipmunk_libs chipmunk libchipmunk)
+endif(WINDOWS)
+
+set(_curl_inc curl/curl.h)
+# order: curl, ssl, crypto
+set(_curl_libs curl libcurl_imp libcurl ssl libeay32 ssleay32 crypto)
+
+set(_freetype2_prefix FREETYPE)
+set(_freetype2_inc ft2build.h freetype/freetype.h)
+set(_freetype2_inc_paths freetype2)
+set(_freetype2_libs freetype freetype250)
+
+set(_jpeg_inc jpeglib.h)
+if(WINDOWS)
+    if (${MSVC_VERSION} STREQUAL "1900")
+        set(_jpeg_libs jpeg libjpeg-2015)
+    else()
+        set(_jpeg_libs jpeg libjpeg)
+    endif(${MSVC_VERSION})
+else()
+    set(_jpeg_libs jpeg libjpeg)
+endif(WINDOWS)
+
+set(_png_inc png.h)
+if(WINDOWS)
+    if (${MSVC_VERSION} STREQUAL "1900")
+        set(_png_libs png libpng-2015)
+    else()
+        set(_png_libs png libpng)
+    endif(${MSVC_VERSION})
+else()
+    set(_png_libs png libpng)
+endif(WINDOWS)
+
+set(_tiff_inc tiff.h)
+if(WINDOWS)
+    if (${MSVC_VERSION} STREQUAL "1900")
+        set(_tiff_libs tiff libtiff-2015)
+    else()
+        set(_tiff_libs tiff libtiff)
+    endif(${MSVC_VERSION})
+else()
+    set(_tiff_libs tiff libtiff)
+endif(WINDOWS)
+
+set(_webp_inc decode.h)
+set(_webp_libs webp libwebp)
+
+set(_websockets_inc libwebsockets.h)
+set(_websockets_libs websockets libwebsockets)
+
+set(_openssl_inc openssl/ssl.h)
+set(_openssl_libs ssl crypto)
+
+set(_glfw3_inc glfw3.h)
+if(WINDOWS)
+    if (${MSVC_VERSION} STREQUAL "1900")
+        set(_glfw3_libs glfw3-2015 libglfw3)
+    else()
+        set(_glfw3_libs glfw3 libglfw3)
+    endif(${MSVC_VERSION})
+else()
+    set(_glfw3_libs glfw3 libglfw3)
+endif(WINDOWS)
+
+set(_sqlite3_inc sqlite3.h)
+set(_sqlite3_libs sqlite3)
+
+set(_gles_prefix GLEW)
+set(_gles_inc GL/glew.h)
+set(_gles_inc_paths OGLES)
+set(_gles_libs glew32)
+
+set(_icon_prefix ICONV)
+set(_icon_inc iconv.h)
+set(_icon_libs libiconv)
+
+set(_MP3Decoder_prefix MPG123)
+set(_MP3Decoder_inc mpg123.h)
+set(_MP3Decoder_libs libmpg123)
+
+set(_OggDecoder_prefix VORBIS)
+set(_OggDecoder_inc ogg/ogg.h)
+set(_OggDecoder_libs libogg libvorbis libvorbisfile)
+
+set(_OpenalSoft_prefix OPENAL)
+set(_OpenalSoft_inc al.h)
+set(_OpenalSoft_inc_paths AL)
+set(_OpenalSoft_libs OpenAL32)
+
+set(_zlib_inc zlib.h)
+set(_zlib_libs z libzlib libz)
+
+set(_fmod_prefix FMOD)
+set(_fmod_inc fmod.hpp)
+set(_fmod_libs fmod fmod64 fmod fmod64)
+
+set(all_prebuilt_libs
+  chipmunk
+  curl
+  freetype2
+  jpeg
+  png
+  tiff
+  webp
+  websockets
+  openssl
+)
+
+
+if(MACOSX)
+  list(APPEND all_prebuilt_libs glfw3 zlib)
+endif()
+
+# We use MSVC instead of WINDOWS because it can be mingw that can't use our prebuilt libs
+if(MSVC)
+  list(APPEND all_prebuilt_libs glfw3 sqlite3 gles icon MP3Decoder OggDecoder OpenalSoft zlib)
+endif()
+
+if(LINUX)
+  list(APPEND all_prebuilt_libs fmod)
+endif()
+
+if(ANDROID)
+  list(APPEND all_prebuilt_libs zlib)
+endif()
+
+
+# END CONFIG
+
+foreach(_lib ${all_prebuilt_libs})
+  if(_${_lib}_prefix)
+    set(_prefix ${_${_lib}_prefix})
+  else()
+    # auto-prefix is uppercased name
+    string(TOUPPER ${_lib} _prefix)
+  endif()
+
+  set(roots
+    ${COCOS_EXTERNAL_DIR}/${_lib}
+    ${COCOS_EXTERNAL_DIR}/${PLATFORM_FOLDER}-specific/${_lib}
+    )
+  foreach(_root ${roots})
+    if(EXISTS ${_root})
+      set(include_dir_candidates
+        ${_root}/include
+        ${_root}/include/${ARCH_DIR}
+        ${_root}/include/${PLATFORM_FOLDER}
+        ${_root}/include/${PLATFORM_FOLDER}/${ARCH_DIR}
+        )
+      set(include_dirs)
+      foreach(_dir ${include_dir_candidates})
+        if(EXISTS ${_dir})
+          # find all include paths
+          if(_${_lib}_inc_paths)
+            set(_suffixes ${_${_lib}_inc_paths})
+          else()
+            set(_suffixes include)
+          endif()
+          foreach(_inc_name ${_${_lib}_inc})
+            unset(_inc_tmp CACHE)
+            find_path(_inc_tmp ${_inc_name} PATH_SUFFIXES ${_suffixes} PATHS ${_dir} NO_DEFAULT_PATH)
+            if(_inc_tmp)
+              list(APPEND include_dirs ${_inc_tmp})
+            endif()
+          endforeach()
+        endif(EXISTS ${_dir})
+      endforeach()
+      if(include_dirs)
+        set(${_prefix}_INCLUDE_DIRS ${include_dirs} CACHE PATH "Path to includes for ${_prefix}" FORCE)
+      endif()
+      #message(STATUS "${_lib} ${_prefix}_INCLUDE_DIRS: ${${_prefix}_INCLUDE_DIRS}")
+
+      set(lib_dir_candidates
+        ${_root}/prebuilt/${PLATFORM_FOLDER}/${ANDROID_ABI}
+        ${_root}/prebuilt/${PLATFORM_FOLDER}/${ARCH_DIR}
+        ${_root}/prebuilt/${PLATFORM_FOLDER}
+        ${_root}/prebuilt/${PLATFORM_FOLDER}/release-lib
+        ${_root}/prebuilt/${ARCH_DIR}
+        ${_root}/libraries/${PLATFORM_FOLDER}
+        ${_root}/prebuilt
+        )
+      set(libs)
+      foreach(_dir ${lib_dir_candidates})
+        if(EXISTS ${_dir})
+          # find all libs
+          foreach(_lib_name ${_${_lib}_libs})
+            unset(_lib_tmp CACHE)
+            find_library(_lib_tmp ${_lib_name} PATHS ${_dir} NO_DEFAULT_PATH)
+            if(_lib_tmp)
+              list(APPEND libs ${_lib_tmp})
+            endif()
+          endforeach()
+        endif(EXISTS ${_dir})
+      endforeach()
+      if(libs)
+        set(${_prefix}_LIBRARIES ${libs} CACHE STRING "Libraries to link for ${_prefix}" FORCE)
+      endif()
+      #message(STATUS "${_lib} ${_prefix}_LIBRARIES: ${${_prefix}_LIBRARIES}")
+
+      if(${_prefix}_LIBRARIES AND ${_prefix}_INCLUDE_DIRS)
+        set(${_prefix}_FOUND YES)
+      endif()
+      
+    endif(EXISTS ${_root})
+  endforeach()
+endforeach()

+ 86 - 0
cocos2d/cmake/Modules/FindCURL.cmake

@@ -0,0 +1,86 @@
+#.rst:
+# FindCURL
+# --------
+#
+# Find curl
+#
+# Find the native CURL headers and libraries.
+#
+# ::
+#
+#   CURL_INCLUDE_DIRS   - where to find curl/curl.h, etc.
+#   CURL_LIBRARIES      - List of libraries when using curl.
+#   CURL_FOUND          - True if curl found.
+#   CURL_VERSION_STRING - the version of curl found (since CMake 2.8.8)
+
+#=============================================================================
+# Copyright 2006-2009 Kitware, Inc.
+# Copyright 2012 Rolf Eike Beer <eike@sf-mail.de>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+set(CURL_LIBRARY_NAMES
+  curl
+# Windows MSVC prebuilts:
+  curllib
+  libcurl_imp
+  curllib_static
+# Windows older "Win32 - MSVC" prebuilts (libcurl.lib, e.g. libcurl-7.15.5-win32-msvc.zip):
+  libcurl
+  )
+
+find_package(PkgConfig)
+if(PKG_CONFIG_FOUND)
+  pkg_search_module(CURL QUIET libcurl)
+endif()
+
+if(NOT CURL_FOUND)
+
+    # Look for the header file.
+    find_path(CURL_INCLUDE_DIR NAMES curl/curl.h)
+    mark_as_advanced(CURL_INCLUDE_DIR)
+
+    # Look for the library (sorted from most current/relevant entry to least).
+    find_library(CURL_LIBRARY NAMES
+        curl
+      # Windows MSVC prebuilts:
+        curllib
+        libcurl_imp
+        curllib_static
+      # Windows older "Win32 - MSVC" prebuilts (libcurl.lib, e.g. libcurl-7.15.5-win32-msvc.zip):
+        libcurl
+    )
+    mark_as_advanced(CURL_LIBRARY)
+
+    if(CURL_INCLUDE_DIR)
+      foreach(_curl_version_header curlver.h curl.h)
+        if(EXISTS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}")
+          file(STRINGS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}" curl_version_str REGEX "^#define[\t ]+LIBCURL_VERSION[\t ]+\".*\"")
+
+          string(REGEX REPLACE "^#define[\t ]+LIBCURL_VERSION[\t ]+\"([^\"]*)\".*" "\\1" CURL_VERSION_STRING "${curl_version_str}")
+          unset(curl_version_str)
+          break()
+        endif()
+      endforeach()
+    endif()
+
+    include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+    FIND_PACKAGE_HANDLE_STANDARD_ARGS(CURL
+                                      REQUIRED_VARS CURL_LIBRARY CURL_INCLUDE_DIR
+                                      VERSION_VAR CURL_VERSION_STRING)
+
+    if(CURL_FOUND)
+      set(CURL_LIBRARIES ${CURL_LIBRARY})
+      set(CURL_INCLUDE_DIRS ${CURL_INCLUDE_DIR})
+    endif()
+
+endif()
+

+ 79 - 0
cocos2d/cmake/Modules/FindChipmunk.cmake

@@ -0,0 +1,79 @@
+#.rst:
+# FindChipmunk
+# ------------
+#
+# Locate Chipmunk library
+#
+# This module defines
+#
+# ::
+#
+#   CHIPMUNK_LIBRARIES, the library to link against
+#   CHIPMUNK_FOUND, if false, do not try to link to Chipmunk 
+#   CHIPMUNK_INCLUDE_DIRS, where to find headers.
+#   This is the concatenation of the paths:
+#   CHIPMUNK_INCLUDE_DIR
+#
+#=============================================================================
+# Copyright 2014-2014 Martell Malone
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+FIND_PATH(CHIPMUNK_INCLUDE_DIR chipmunk/chipmunk.h
+  HINTS
+  ENV CHIPMUNK_DIR
+  PATH_SUFFIXES include
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw # Fink
+  /opt/local # DarwinPorts
+  /opt/csw # Blastwave
+  /opt
+)
+
+FIND_LIBRARY(CHIPMUNK_LIBRARY
+  NAMES chipmunk libchipmunk
+  HINTS
+  ENV CHIPMUNK_DIR
+  PATH_SUFFIXES lib
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw
+  /opt/local
+  /opt/csw
+  /opt
+)
+
+set(CHIPMUNK_INCLUDE_DIRS "${CHIPMUNK_INCLUDE_DIR}")
+
+IF(CHIPMUNK_LIBRARY)
+  # include the math library for Unix
+  IF(UNIX AND NOT APPLE)
+    FIND_LIBRARY(CHIPMUNK_MATH_LIBRARY m)
+    SET(CHIPMUNK_LIBRARIES "${CHIPMUNK_LIBRARY};${CHIPMUNK_MATH_LIBRARY}" CACHE STRING "Chipmunk Libraries")
+  # For Windows and Mac, don't need to explicitly include the math library
+  ELSE(UNIX AND NOT APPLE)
+    SET( CHIPMUNK_LIBRARIES "${CHIPMUNK_LIBRARY}" CACHE STRING "Chipmunk Libraries")
+  ENDIF(UNIX AND NOT APPLE)
+ENDIF(CHIPMUNK_LIBRARY)
+
+INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+# handle the QUIETLY and REQUIRED arguments and set CHIPMUNK_FOUND to TRUE if 
+# all listed variables are TRUE
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Chipmunk DEFAULT_MSG CHIPMUNK_LIBRARIES CHIPMUNK_INCLUDE_DIR)
+
+MARK_AS_ADVANCED(CHIPMUNK_INCLUDE_DIR CHIPMUNK_LIBRARIES CHIPMUNK_LIBRARY CHIPMUNK_MATH_LIBRARY)

+ 51 - 0
cocos2d/cmake/Modules/FindFMOD.cmake

@@ -0,0 +1,51 @@
+#.rst:
+# FindFMOD
+# ------------
+#
+# Locate FMOD Ex library
+#
+# This module defines
+#
+# ::
+#
+#   FMOD_LIBRARIES, the library to link against
+#   FMOD_FOUND, if false, do not try to link to fmodex
+#   FMOD_INCLUDE_DIRS, where to find headers.
+#
+
+find_path(FMOD_INCLUDE_DIR fmod.hpp
+  HINTS ENV FMOD_DIR
+  PATH_SUFFIXES include/fmod include
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw # Fink
+  /opt/local # DarwinPorts
+  /opt/csw # Blastwave
+  /opt
+  )
+
+find_library(FMOD_LIBRARY NAMES fmod fmod64
+  HINTS ENV FMOD_DIR
+  PATH_SUFFIXES lib
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw # Fink
+  /opt/local # DarwinPorts
+  /opt/csw # Blastwave
+  /opt
+  )
+
+set(FMOD_INCLUDE_DIRS "${FMOD_INCLUDE_DIR}")
+set(FMOD_LIBRARIES "${FMOD_LIBRARY}")
+
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args(FMOD DEFAULT_MSG FMOD_LIBRARIES FMOD_INCLUDE_DIRS)
+
+mark_as_advanced(FMOD_INCLUDE_DIR FMOD_LIBRARY FMOD_INCLUDE_DIRS FMOD_LIBRARIES)
+

+ 17 - 0
cocos2d/cmake/Modules/FindFontconfig.cmake

@@ -0,0 +1,17 @@
+# FindFontconfig
+# --------------
+#
+# Locate Fontconfig library
+#
+
+if(NOT FONTCONFIG_FOUND)
+  find_package(PkgConfig)
+  pkg_search_module(FONTCONFIG fontconfig)
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Fontconfig
+  REQUIRED_VARS FONTCONFIG_FOUND
+  VERSION_VAR FONTCONFIG_VERSION
+  )
+

+ 168 - 0
cocos2d/cmake/Modules/FindFreetype.cmake

@@ -0,0 +1,168 @@
+#.rst:
+# FindFreetype
+# ------------
+#
+# Locate FreeType library
+#
+# This module defines
+#
+# ::
+#
+#   FREETYPE_LIBRARIES, the library to link against
+#   FREETYPE_FOUND, if false, do not try to link to FREETYPE
+#   FREETYPE_INCLUDE_DIRS, where to find headers.
+#   FREETYPE_VERSION_STRING, the version of freetype found (since CMake 2.8.8)
+#   This is the concatenation of the paths:
+#   FREETYPE_INCLUDE_DIR_ft2build
+#   FREETYPE_INCLUDE_DIR_freetype2
+#
+#
+#
+# $FREETYPE_DIR is an environment variable that would correspond to the
+# ./configure --prefix=$FREETYPE_DIR used in building FREETYPE.
+
+#=============================================================================
+# Copyright 2007-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+# Created by Eric Wing.
+# Modifications by Alexander Neundorf.
+# This file has been renamed to "FindFreetype.cmake" instead of the correct
+# "FindFreeType.cmake" in order to be compatible with the one from KDE4, Alex.
+
+# Try find freetype for our arch in external folder
+#todo: fix location of freetype includes for linux android on cocos prebuilt repo
+#i.e we should not need to include an extra dir of /freetype2
+
+# Try pkg-config first (because it provided deps info)
+if(NOT FREETYPE_FOUND)
+  find_package(PkgConfig)
+  pkg_search_module(FREETYPE freetype2)
+endif()
+if(NOT FREETYPE_FOUND)
+
+# Ugh, FreeType seems to use some #include trickery which
+# makes this harder than it should be. It looks like they
+# put ft2build.h in a common/easier-to-find location which
+# then contains a #include to a more specific header in a
+# more specific location (#include <freetype/config/ftheader.h>).
+# Then from there, they need to set a bunch of #define's
+# so you can do something like:
+# #include FT_FREETYPE_H
+# Unfortunately, using CMake's mechanisms like include_directories()
+# wants explicit full paths and this trickery doesn't work too well.
+# I'm going to attempt to cut out the middleman and hope
+# everything still works.
+find_path(FREETYPE_INCLUDE_DIR_ft2build ft2build.h
+  HINTS
+    ENV FREETYPE_DIR
+  PATHS
+    ~/Library/Frameworks
+    /Library/Frameworks
+    /usr/local
+    /usr
+    /usr/X11R6
+    /usr/local/X11R6
+    /usr/local/X11
+    /usr/freeware
+    ENV GTKMM_BASEPATH
+    [HKEY_CURRENT_USER\\SOFTWARE\\gtkmm\\2.4;Path]
+    [HKEY_LOCAL_MACHINE\\SOFTWARE\\gtkmm\\2.4;Path]
+  PATH_SUFFIXES include/freetype2 include
+)
+
+find_path(FREETYPE_INCLUDE_DIR_freetype2
+  NAMES
+    freetype/config/ftheader.h
+    config/ftheader.h
+  HINTS
+    ENV FREETYPE_DIR
+  PATHS
+    ~/Library/Frameworks
+    /Library/Frameworks
+    /usr/local
+    /usr
+    /usr/X11R6
+    /usr/local/X11R6
+    /usr/local/X11
+    /usr/freeware
+    ENV GTKMM_BASEPATH
+    [HKEY_CURRENT_USER\\SOFTWARE\\gtkmm\\2.4;Path]
+    [HKEY_LOCAL_MACHINE\\SOFTWARE\\gtkmm\\2.4;Path]
+  PATH_SUFFIXES include/freetype2 include
+)
+
+find_library(FREETYPE_LIBRARY
+  NAMES freetype libfreetype freetype219
+  HINTS
+    ENV FREETYPE_DIR
+  PATH_SUFFIXES lib
+  PATHS
+    ~/Library/Frameworks
+    /Library/Frameworks
+    /usr/local
+    /usr
+    /usr/X11R6
+    /usr/local/X11R6
+    /usr/local/X11
+    /usr/freeware
+    ENV GTKMM_BASEPATH
+    [HKEY_CURRENT_USER\\SOFTWARE\\gtkmm\\2.4;Path]
+    [HKEY_LOCAL_MACHINE\\SOFTWARE\\gtkmm\\2.4;Path]
+)
+
+# set the user variables
+if(FREETYPE_INCLUDE_DIR_ft2build AND FREETYPE_INCLUDE_DIR_freetype2)
+  set(FREETYPE_INCLUDE_DIRS "${FREETYPE_INCLUDE_DIR_ft2build};${FREETYPE_INCLUDE_DIR_freetype2}")
+  list(REMOVE_DUPLICATES FREETYPE_INCLUDE_DIRS)
+endif()
+set(FREETYPE_LIBRARIES "${FREETYPE_LIBRARY}")
+
+if(EXISTS "${FREETYPE_INCLUDE_DIR_freetype2}/freetype/freetype.h")
+  set(FREETYPE_H "${FREETYPE_INCLUDE_DIR_freetype2}/freetype/freetype.h")
+elseif(EXISTS "${FREETYPE_INCLUDE_DIR_freetype2}/freetype.h")
+  set(FREETYPE_H "${FREETYPE_INCLUDE_DIR_freetype2}/freetype.h")
+endif()
+
+if(FREETYPE_INCLUDE_DIR_freetype2 AND FREETYPE_H)
+    file(STRINGS "${FREETYPE_H}" freetype_version_str
+         REGEX "^#[\t ]*define[\t ]+FREETYPE_(MAJOR|MINOR|PATCH)[\t ]+[0-9]+$")
+
+    unset(FREETYPE_VERSION_STRING)
+    foreach(VPART MAJOR MINOR PATCH)
+        foreach(VLINE ${freetype_version_str})
+            if(VLINE MATCHES "^#[\t ]*define[\t ]+FREETYPE_${VPART}")
+                string(REGEX REPLACE "^#[\t ]*define[\t ]+FREETYPE_${VPART}[\t ]+([0-9]+)$" "\\1"
+                       FREETYPE_VERSION_PART "${VLINE}")
+                if(FREETYPE_VERSION_STRING)
+                    set(FREETYPE_VERSION_STRING "${FREETYPE_VERSION_STRING}.${FREETYPE_VERSION_PART}")
+                else()
+                    set(FREETYPE_VERSION_STRING "${FREETYPE_VERSION_PART}")
+                endif()
+                unset(FREETYPE_VERSION_PART)
+            endif()
+        endforeach()
+    endforeach()
+endif()
+
+set(FREETYPE_LIBRARIES ${FREETYPE_LIBRARY})
+
+# handle the QUIETLY and REQUIRED arguments and set FREETYPE_FOUND to TRUE if
+# all listed variables are TRUE
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Freetype
+                                  REQUIRED_VARS FREETYPE_LIBRARIES FREETYPE_INCLUDE_DIRS
+                                  VERSION_VAR FREETYPE_VERSION_STRING)
+
+endif(NOT FREETYPE_FOUND)
+
+mark_as_advanced(FREETYPE_LIBRARY FREETYPE_INCLUDE_DIR_freetype2 FREETYPE_INCLUDE_DIR_ft2build)

+ 156 - 0
cocos2d/cmake/Modules/FindGLFW3.cmake

@@ -0,0 +1,156 @@
+#.rst:
+# FindGLFW3
+# ------------
+#
+# Locate glfw3 library
+#
+# This module defines
+#
+# ::
+#
+#   GLFW3_LIBRARIES, the library to link against
+#   GLFW3_FOUND, if false, do not try to link to FREETYPE
+#   GLFW3_INCLUDE_DIRS, where to find headers.
+#   This is the concatenation of the paths:
+#   GLFW3_INCLUDE_DIR
+#
+#=============================================================================
+# Copyright 2014-2014 Martell Malone
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+# glfw has special requirements for linking (from docs: http://www.glfw.org/docs/latest/build.html)
+# MINGW or MSVC + static "glfw3" -> link: opengl32, gdi32 (plus glu32 if use GLU)
+# MINGW or MSVC + dynamic "glfw3dll" (but this not true ;) -> -DGLFW_DLL link: no
+# UNIX + static -> pkg-config --static --libs
+# UNIX + dynamic -> pkg-config --libs
+# So... if we find dynamic version, no problems, but if we find static, we need to determine deps
+#  but cmake can't simply say to us what kind of library it found. So we try to find static version
+#  first, and then if nothing found, we repeat search for dynamic
+
+find_package(PkgConfig)
+if(PKG_CONFIG_FOUND)
+  message(STATUS "PkgConfig found")
+else()
+  message(STATUS "PkgConfig not found, if you have only static glfw library, you build can fail")
+endif()
+
+if(PKG_CONFIG_FOUND)
+  # Save some global stuff that we change, to revert after work has been done
+  set(_saved_PKG_CONFIG_PATH "$ENV{PKG_CONFIG_PATH}")
+  set(_saved_CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_FIND_LIBRARY_SUFFIXES}")
+
+  # add /usr/local/lib/pkgconfig to pkg-config search path (some linuxes do not do that, but glfw installs to taht prefix by default)
+  file(TO_CMAKE_PATH "$ENV{PKG_CONFIG_PATH}" PKG_CONFIG_PATH)
+  list(APPEND PKG_CONFIG_PATH "/usr/local/lib/pkgconfig")
+  file(TO_NATIVE_PATH "${PKG_CONFIG_PATH}" new_pkg_config_path)
+  set(ENV{PKG_CONFIG_PATH} "${new_pkg_config_path}")
+
+  # now try to find glfw with pkg-config
+  pkg_check_modules(PC_GLFW3 glfw3)
+  if(PC_GLFW3_FOUND)
+
+    # try to find static library
+    set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
+    find_library(GLFW3_STATIC_LIBRARY NAMES glfw3 libglfw3 PATHS ${PC_GLFW3_LIBRARY_DIRS} NO_DEFAULT_PATH)
+    find_library(GLFW3_STATIC_LIBRARY NAMES glfw3 libglfw3 PATHS ${PC_GLFW3_LIBRARY_DIRS})
+    # also we include glfw3.h header, not GLFW/glfw3.h :(
+    find_path(GLFW3_INCLUDE_DIRS glfw3.h PATH_SUFFIXES GLFW PATHS ${PC_GLFW3_INCLUDE_DIRS} NO_DEFAULT_PATH)
+    find_path(GLFW3_INCLUDE_DIRS glfw3.h PATH_SUFFIXES GLFW PATHS ${PC_GLFW3_INCLUDE_DIRS})
+
+    if(GLFW3_STATIC_LIBRARY)
+      # glfw3 is static
+      set(GLFW3_LIBRARIES ${PC_GLFW3_STATIC_LIBRARIES})
+      set(GLFW3_LIBRARY_DIRS ${PC_GLFW3_STATIC_LIBRARY_DIRS})
+
+      # We also need to add any other LDFLAGS, but with additional fixup for Apple frameworks :(
+      if(APPLE)
+        unset(_is_framework)
+        foreach(_arg ${PC_GLFW3_STATIC_LDFLAGS_OTHER})
+          if(_is_framework)
+            set(var FRAMEWORK_${_arg}_LIBRARY)
+            find_library(${var} ${_arg})
+            if(${var})
+              list(APPEND GLFW3_LIBRARIES ${${var}})
+            endif()
+            unset(var)
+            unset(_is_framework)
+          else()
+            if(_arg STREQUAL "-framework")
+              set(_is_framework 1)
+            else()
+              list(APPEND GLFW3_LIBRARIES ${_arg})
+            endif()
+          endif()
+        endforeach()
+      else(APPLE)
+        list(APPEND GLFW3_LIBRARIES ${PC_GLFW3_STATIC_LDFLAGS_OTHER})
+      endif(APPLE)
+
+    else()
+      # glfw3 is dynamic
+      set(GLFW3_DEFINITIONS -DGLFW_DLL)
+      set(GLFW3_LIBRARIES ${PC_GLFW3_LIBRARIES})
+      set(GLFW3_LIBRARY_DIRS ${PC_GLFW3_LIBRARY_DIRS})
+
+    endif()
+    set(GLFW3_FOUND 1)
+    
+  endif()
+
+  # Restore global stuff
+  set(CMAKE_FIND_LIBRARY_SUFFIXES "${_saved_CMAKE_FIND_LIBRARY_SUFFIXES}")
+  set(ENV{PKG_CONFIG_PATH} "${_saved_PKG_CONFIG_PATH}")
+endif(PKG_CONFIG_FOUND)
+
+# fallback if pkg-config method not work
+if(NOT GLFW3_FOUND)
+
+  find_path(GLFW3_INCLUDE_DIR glfw3.h
+    HINTS
+    ENV GLFW3_DIR
+    PATH_SUFFIXES include/GLFW include
+    PATHS
+    ~/Library/Frameworks
+    /Library/Frameworks
+    /usr/local
+    /usr
+    /sw # Fink
+    /opt/local # DarwinPorts
+    /opt/csw # Blastwave
+    /opt
+  )
+
+  find_library(GLFW3_LIBRARY 
+    NAMES glfw3 libglfw3 glfw
+    HINTS
+    ENV GLFW3_DIR
+    PATH_SUFFIXES lib
+    PATHS
+    ~/Library/Frameworks
+    /Library/Frameworks
+    /usr/local
+    /usr
+    /sw
+    /opt/local
+    /opt/csw
+    /opt
+  )
+
+  set(GLFW3_INCLUDE_DIRS "${GLFW3_INCLUDE_DIR}")
+  set(GLFW3_LIBRARIES "${GLFW3_LIBRARY}")
+
+  include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+  find_package_handle_standard_args(GLFW3 DEFAULT_MSG GLFW3_LIBRARIES GLFW3_INCLUDE_DIR)
+
+endif()
+
+mark_as_advanced(GLFW3_INCLUDE_DIR GLFW3_LIBRARIES GLFW3_LIBRARY)

+ 56 - 0
cocos2d/cmake/Modules/FindGTK3.cmake

@@ -0,0 +1,56 @@
+# - Try to find GTK3
+#
+# $Id: FindGTK3.cmake 39970 2011-11-21 15:39:25Z jmayer $
+#
+# Once done this will define
+#
+#  GTK3_FOUND - System has GTK3
+#  GTK3_INCLUDE_DIRS - The GTK3 include directory
+#  GTK3_LIBRARIES - The libraries needed to use GTK3
+#  GTK3_DEFINITIONS - Compiler switches required for using GTK3
+#=============================================================================
+# Copyright 2011 Duncan Mac-Vicar P. <duncan@kde.org>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file COPYING-CMAKE-SCRIPTS for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+# use pkg-config to get the directories and then use these values
+# in the FIND_PATH() and FIND_LIBRARY() calls
+find_package(PkgConfig)
+pkg_check_modules(PC_GTK3 gtk+-3.0 QUIET)
+
+# MESSAGE(STATUS "PC_GTK3_LIBRARIES: ${PC_GTK3_LIBRARIES}")
+# MESSAGE(STATUS "PC_GTK3_LIBRARY_DIRS: ${PC_GTK3_LIBRARY_DIRS}")
+# MESSAGE(STATUS "PC_GTK3_LDFLAGS: ${PC_GTK3_LDFLAGS}")
+# MESSAGE(STATUS "PC_GTK3_LDFLAGS_OTHER: ${PC_GTK3_LDFLAGS_OTHER}")
+
+set(GTK3_DEFINITIONS ${PC_GTK3_CFLAGS_OTHER})
+
+#FIND_PATH(GTK3_INCLUDE_DIR NAMES "gtk/gtk.h"
+#   HINTS
+#   ${PC_GTK3_INCLUDEDIR}
+#   ${PC_GTK3_INCLUDE_DIRS}
+#   PATH_SUFFIXES "gtk-3.0"
+#   )
+set(GTK3_INCLUDE_DIRS ${PC_GTK3_INCLUDE_DIRS})
+
+#FIND_LIBRARY(GTK3_LIBRARIES NAMES gtk-3 gtk3
+#   HINTS
+#   ${PC_GTK3_LIBDIR}
+#   ${PC_GTK3_LIBRARY_DIRS}
+#   )
+set(GTK3_LIBRARIES ${PC_GTK3_LIBRARIES})
+
+# handle the QUIETLY and REQUIRED arguments and set GTK3_FOUND to TRUE if
+# all listed variables are TRUE
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(GTK3 DEFAULT_MSG GTK3_LIBRARIES GTK3_INCLUDE_DIRS)
+
+mark_as_advanced(GTK3_INCLUDE_DIRS GTK3_LIBRARIES)

+ 49 - 0
cocos2d/cmake/Modules/FindJPEG.cmake

@@ -0,0 +1,49 @@
+#.rst:
+# FindJPEG
+# --------
+#
+# Find JPEG
+#
+# Find the native JPEG includes and library This module defines
+#
+# ::
+#
+#   JPEG_INCLUDE_DIRS, where to find jpeglib.h, etc.
+#   JPEG_LIBRARIES, the libraries needed to use JPEG.
+#   JPEG_FOUND, If false, do not try to use JPEG.
+#
+# also defined, but not for general use are
+#
+# ::
+#
+#   JPEG_LIBRARY, where to find the JPEG library.
+
+#=============================================================================
+# Copyright 2001-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+find_path(JPEG_INCLUDE_DIR jpeglib.h)
+
+set(JPEG_NAMES ${JPEG_NAMES} jpeg)
+find_library(JPEG_LIBRARY NAMES ${JPEG_NAMES} )
+
+# handle the QUIETLY and REQUIRED arguments and set JPEG_FOUND to TRUE if
+# all listed variables are TRUE
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(JPEG DEFAULT_MSG JPEG_LIBRARY JPEG_INCLUDE_DIR)
+
+if(JPEG_FOUND)
+  set(JPEG_INCLUDE_DIRS ${JPEG_INCLUDE_DIR})
+  set(JPEG_LIBRARIES ${JPEG_LIBRARY})
+endif()
+
+mark_as_advanced(JPEG_LIBRARY JPEG_INCLUDE_DIRS )

+ 60 - 0
cocos2d/cmake/Modules/FindMINIZIP.cmake

@@ -0,0 +1,60 @@
+#.rst:
+# FindMINIZIP
+# ------------
+#
+# Locate minizip library (from zlib package)
+#
+# This module defines
+#
+# ::
+#
+#   MINIZIP_LIBRARIES, the library to link against
+#   MINIZIP_FOUND, if false, do not try to link to fmodex
+#   MINIZIP_INCLUDE_DIRS, where to find headers.
+#
+
+# Try pkg-config first
+if(NOT MINIZIP_LIBRARY AND NOT MINIZIP_INCLUDE_DIR)
+  find_package(PkgConfig)
+  pkg_search_module(MINIZIP minizip)
+  if(MINIZIP_FOUND)
+    return()
+  endif()
+endif()
+
+find_path(MINIZIP_INCLUDE_DIR minizip/unzip.h
+  HINTS ENV MINIZIP_DIR
+  PATH_SUFFIXES include
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw # Fink
+  /opt/local # DarwinPorts
+  /opt/csw # Blastwave
+  /opt
+  )
+
+find_library(MINIZIP_LIBRARY NAMES minizip libminizip
+  HINTS ENV MINIZIP_DIR
+  PATH_SUFFIXES lib
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw # Fink
+  /opt/local # DarwinPorts
+  /opt/csw # Blastwave
+  /opt
+  )
+
+set(MINIZIP_INCLUDE_DIRS "${MINIZIP_INCLUDE_DIR}")
+set(MINIZIP_LIBRARIES "${MINIZIP_LIBRARY}")
+
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args(MINIZIP DEFAULT_MSG MINIZIP_LIBRARIES MINIZIP_INCLUDE_DIRS)
+
+mark_as_advanced(MINIZIP_INCLUDE_DIR MINIZIP_LIBRARY)
+

+ 17 - 0
cocos2d/cmake/Modules/FindMPG123.cmake

@@ -0,0 +1,17 @@
+# - Find mpg123
+# Find the native mpg123 includes and libraries
+#
+#  MPG123_INCLUDE_DIRS - where to find mpg123.h, etc.
+#  MPG123_LIBRARIES    - List of libraries when using mpg123.
+#  MPG123_FOUND        - True if mpg123 found.
+
+find_path(MPG123_INCLUDE_DIR mpg123.h)
+find_library(MPG123_LIBRARY NAMES mpg123 libmpg123)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(MPG123 DEFAULT_MSG MPG123_INCLUDE_DIR MPG123_LIBRARY)
+
+set(MPG123_INCLUDE_DIRS ${MPG123_INCLUDE_DIR})
+set(MPG123_LIBRARIES ${MPG123_LIBRARY})
+
+mark_as_advanced(MPG123_INCLUDE_DIR MPG123_LIBRARY)

+ 20 - 0
cocos2d/cmake/Modules/FindOgg.cmake

@@ -0,0 +1,20 @@
+# - Find ogg
+# Find the native ogg includes and libraries
+#
+#  OGG_INCLUDE_DIRS - where to find ogg.h, etc.
+#  OGG_LIBRARIES    - List of libraries when using ogg.
+#  OGG_FOUND        - True if ogg found.
+
+find_path(OGG_INCLUDE_DIR ogg/ogg.h)
+# MSVC built ogg may be named ogg_static.
+# The provided project files name the library with the lib prefix.
+find_library(OGG_LIBRARY NAMES ogg ogg_static libogg libogg_static)
+# Handle the QUIETLY and REQUIRED arguments and set OGG_FOUND
+# to TRUE if all listed variables are TRUE.
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(OGG DEFAULT_MSG OGG_INCLUDE_DIR OGG_LIBRARY)
+
+set(OGG_INCLUDE_DIRS ${OGG_INCLUDE_DIR})
+set(OGG_LIBRARIES ${OGG_LIBRARY})
+
+mark_as_advanced(OGG_INCLUDE_DIR OGG_LIBRARY)

+ 160 - 0
cocos2d/cmake/Modules/FindPNG.cmake

@@ -0,0 +1,160 @@
+#.rst:
+# FindPNG
+# -------
+#
+# Find the native PNG includes and library
+#
+#
+#
+# This module searches libpng, the library for working with PNG images.
+#
+# It defines the following variables
+#
+# ::
+#
+#   PNG_INCLUDE_DIRS, where to find png.h, etc.
+#   PNG_LIBRARIES, the libraries to link against to use PNG.
+#   PNG_DEFINITIONS - You should add_definitons(${PNG_DEFINITIONS}) before compiling code that includes png library files.
+#   PNG_FOUND, If false, do not try to use PNG.
+#   PNG_VERSION_STRING - the version of the PNG library found (since CMake 2.8.8)
+#
+# Also defined, but not for general use are
+#
+# ::
+#
+#   PNG_LIBRARY, where to find the PNG library.
+#
+# For backward compatiblity the variable PNG_INCLUDE_DIR is also set.
+# It has the same value as PNG_INCLUDE_DIRS.
+#
+# Since PNG depends on the ZLib compression library, none of the above
+# will be defined unless ZLib can be found.
+
+#=============================================================================
+# Copyright 2002-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+if(PNG_FIND_QUIETLY)
+  set(_FIND_ZLIB_ARG QUIET)
+endif()
+find_package(ZLIB ${_FIND_ZLIB_ARG})
+
+if(ZLIB_FOUND)
+  find_path(PNG_PNG_INCLUDE_DIR png.h
+    HINTS ENV PNG_DIR
+    PATH_SUFFIXES include/libpng include
+    PATHS
+    ~/Library/Frameworks
+    /Library/Frameworks
+    /usr/local
+    /usr
+    /sw # Fink
+    /opt/local # DarwinPorts
+    /opt/csw # Blastwave
+    /opt
+  )
+
+  list(APPEND PNG_NAMES png libpng)
+  unset(PNG_NAMES_DEBUG)
+  set(_PNG_VERSION_SUFFIXES 17 16 15 14 12)
+  if (PNG_FIND_VERSION MATCHES "^[0-9]+\\.[0-9]+(\\..*)?$")
+    string(REGEX REPLACE
+        "^([0-9]+)\\.([0-9]+).*" "\\1\\2"
+        _PNG_VERSION_SUFFIX_MIN "${PNG_FIND_VERSION}")
+    if (PNG_FIND_VERSION_EXACT)
+      set(_PNG_VERSION_SUFFIXES ${_PNG_VERSION_SUFFIX_MIN})
+    else ()
+      string(REGEX REPLACE
+          "${_PNG_VERSION_SUFFIX_MIN}.*" "${_PNG_VERSION_SUFFIX_MIN}"
+          _PNG_VERSION_SUFFIXES "${_PNG_VERSION_SUFFIXES}")
+    endif ()
+    unset(_PNG_VERSION_SUFFIX_MIN)
+  endif ()
+  foreach(v IN LISTS _PNG_VERSION_SUFFIXES)
+    list(APPEND PNG_NAMES png${v} libpng${v})
+    list(APPEND PNG_NAMES_DEBUG png${v}d libpng${v}d)
+  endforeach()
+  unset(_PNG_VERSION_SUFFIXES)
+  # For compatiblity with versions prior to this multi-config search, honor
+  # any PNG_LIBRARY that is already specified and skip the search.
+  if(NOT PNG_LIBRARY)
+    find_library(PNG_LIBRARY_RELEASE
+      NAMES ${PNG_NAMES}
+      HINTS ENV PNG_DIR
+      PATH_SUFFIXES lib
+      PATHS
+      ~/Library/Frameworks
+      /Library/Frameworks
+      /usr/local
+      /usr
+      /sw
+      /opt/local
+      /opt/csw
+      /opt
+      )
+    find_library(PNG_LIBRARY_DEBUG
+      NAMES ${PNG_NAMES_DEBUG}
+      HINTS ENV PNG_DIR
+      PATH_SUFFIXES lib
+      PATHS
+      ~/Library/Frameworks
+      /Library/Frameworks
+      /usr/local
+      /usr
+      /sw
+      /opt/local
+      /opt/csw
+      /opt
+      )
+    include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
+    select_library_configurations(PNG)
+    mark_as_advanced(PNG_LIBRARY_RELEASE PNG_LIBRARY_DEBUG)
+  endif()
+  unset(PNG_NAMES)
+  unset(PNG_NAMES_DEBUG)
+
+  # Set by select_library_configurations(), but we want the one from
+  # find_package_handle_standard_args() below.
+  unset(PNG_FOUND)
+
+  if (PNG_LIBRARY AND PNG_PNG_INCLUDE_DIR)
+      # png.h includes zlib.h. Sigh.
+      set(PNG_INCLUDE_DIRS ${PNG_PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} )
+      set(PNG_INCLUDE_DIR ${PNG_INCLUDE_DIRS} ) # for backward compatiblity
+      set(PNG_LIBRARIES ${PNG_LIBRARY} ${ZLIB_LIBRARY})
+
+      if (CYGWIN)
+        if(BUILD_SHARED_LIBS)
+           # No need to define PNG_USE_DLL here, because it's default for Cygwin.
+        else()
+          set (PNG_DEFINITIONS -DPNG_STATIC)
+        endif()
+      endif ()
+
+  endif ()
+
+  if (PNG_PNG_INCLUDE_DIR AND EXISTS "${PNG_PNG_INCLUDE_DIR}/png.h")
+      file(STRINGS "${PNG_PNG_INCLUDE_DIR}/png.h" png_version_str REGEX "^#define[ \t]+PNG_LIBPNG_VER_STRING[ \t]+\".+\"")
+
+      string(REGEX REPLACE "^#define[ \t]+PNG_LIBPNG_VER_STRING[ \t]+\"([^\"]+)\".*" "\\1" PNG_VERSION_STRING "${png_version_str}")
+      unset(png_version_str)
+  endif ()
+endif()
+
+# handle the QUIETLY and REQUIRED arguments and set PNG_FOUND to TRUE if
+# all listed variables are TRUE
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args(PNG
+                                  REQUIRED_VARS PNG_LIBRARY PNG_PNG_INCLUDE_DIR
+                                  VERSION_VAR PNG_VERSION_STRING)
+
+mark_as_advanced(PNG_PNG_INCLUDE_DIR PNG_LIBRARY )

+ 351 - 0
cocos2d/cmake/Modules/FindPackageHandleStandardArgs.cmake

@@ -0,0 +1,351 @@
+#.rst:
+# FindPackageHandleStandardArgs
+# -----------------------------
+#
+#
+#
+# FIND_PACKAGE_HANDLE_STANDARD_ARGS(<name> ...  )
+#
+# This function is intended to be used in FindXXX.cmake modules files.
+# It handles the REQUIRED, QUIET and version-related arguments to
+# find_package().  It also sets the <packagename>_FOUND variable.  The
+# package is considered found if all variables <var1>...  listed contain
+# valid results, e.g.  valid filepaths.
+#
+# There are two modes of this function.  The first argument in both
+# modes is the name of the Find-module where it is called (in original
+# casing).
+#
+# The first simple mode looks like this:
+#
+# ::
+#
+#     FIND_PACKAGE_HANDLE_STANDARD_ARGS(<name> (DEFAULT_MSG|"Custom failure message") <var1>...<varN> )
+#
+# If the variables <var1> to <varN> are all valid, then
+# <UPPERCASED_NAME>_FOUND will be set to TRUE.  If DEFAULT_MSG is given
+# as second argument, then the function will generate itself useful
+# success and error messages.  You can also supply a custom error
+# message for the failure case.  This is not recommended.
+#
+# The second mode is more powerful and also supports version checking:
+#
+# ::
+#
+#     FIND_PACKAGE_HANDLE_STANDARD_ARGS(NAME [FOUND_VAR <resultVar>]
+#                                            [REQUIRED_VARS <var1>...<varN>]
+#                                            [VERSION_VAR   <versionvar>]
+#                                            [HANDLE_COMPONENTS]
+#                                            [CONFIG_MODE]
+#                                            [FAIL_MESSAGE "Custom failure message"] )
+#
+#
+#
+# In this mode, the name of the result-variable can be set either to
+# either <UPPERCASED_NAME>_FOUND or <OriginalCase_Name>_FOUND using the
+# FOUND_VAR option.  Other names for the result-variable are not
+# allowed.  So for a Find-module named FindFooBar.cmake, the two
+# possible names are FooBar_FOUND and FOOBAR_FOUND.  It is recommended
+# to use the original case version.  If the FOUND_VAR option is not
+# used, the default is <UPPERCASED_NAME>_FOUND.
+#
+# As in the simple mode, if <var1> through <varN> are all valid,
+# <packagename>_FOUND will be set to TRUE.  After REQUIRED_VARS the
+# variables which are required for this package are listed.  Following
+# VERSION_VAR the name of the variable can be specified which holds the
+# version of the package which has been found.  If this is done, this
+# version will be checked against the (potentially) specified required
+# version used in the find_package() call.  The EXACT keyword is also
+# handled.  The default messages include information about the required
+# version and the version which has been actually found, both if the
+# version is ok or not.  If the package supports components, use the
+# HANDLE_COMPONENTS option to enable handling them.  In this case,
+# find_package_handle_standard_args() will report which components have
+# been found and which are missing, and the <packagename>_FOUND variable
+# will be set to FALSE if any of the required components (i.e.  not the
+# ones listed after OPTIONAL_COMPONENTS) are missing.  Use the option
+# CONFIG_MODE if your FindXXX.cmake module is a wrapper for a
+# find_package(...  NO_MODULE) call.  In this case VERSION_VAR will be
+# set to <NAME>_VERSION and the macro will automatically check whether
+# the Config module was found.  Via FAIL_MESSAGE a custom failure
+# message can be specified, if this is not used, the default message
+# will be displayed.
+#
+# Example for mode 1:
+#
+# ::
+#
+#     find_package_handle_standard_args(LibXml2  DEFAULT_MSG  LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR)
+#
+#
+#
+# LibXml2 is considered to be found, if both LIBXML2_LIBRARY and
+# LIBXML2_INCLUDE_DIR are valid.  Then also LIBXML2_FOUND is set to
+# TRUE.  If it is not found and REQUIRED was used, it fails with
+# FATAL_ERROR, independent whether QUIET was used or not.  If it is
+# found, success will be reported, including the content of <var1>.  On
+# repeated Cmake runs, the same message won't be printed again.
+#
+# Example for mode 2:
+#
+# ::
+#
+#     find_package_handle_standard_args(LibXslt FOUND_VAR LibXslt_FOUND
+#                                              REQUIRED_VARS LibXslt_LIBRARIES LibXslt_INCLUDE_DIRS
+#                                              VERSION_VAR LibXslt_VERSION_STRING)
+#
+# In this case, LibXslt is considered to be found if the variable(s)
+# listed after REQUIRED_VAR are all valid, i.e.  LibXslt_LIBRARIES and
+# LibXslt_INCLUDE_DIRS in this case.  The result will then be stored in
+# LibXslt_FOUND .  Also the version of LibXslt will be checked by using
+# the version contained in LibXslt_VERSION_STRING.  Since no
+# FAIL_MESSAGE is given, the default messages will be printed.
+#
+# Another example for mode 2:
+#
+# ::
+#
+#     find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4)
+#     find_package_handle_standard_args(Automoc4  CONFIG_MODE)
+#
+# In this case, FindAutmoc4.cmake wraps a call to find_package(Automoc4
+# NO_MODULE) and adds an additional search directory for automoc4.  Here
+# the result will be stored in AUTOMOC4_FOUND.  The following
+# FIND_PACKAGE_HANDLE_STANDARD_ARGS() call produces a proper
+# success/error message.
+
+#=============================================================================
+# Copyright 2007-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake)
+include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake)
+
+# internal helper macro
+macro(_FPHSA_FAILURE_MESSAGE _msg)
+  if (${_NAME}_FIND_REQUIRED)
+    message(FATAL_ERROR "${_msg}")
+  else ()
+    if (NOT ${_NAME}_FIND_QUIETLY)
+      message(STATUS "${_msg}")
+    endif ()
+  endif ()
+endmacro()
+
+
+# internal helper macro to generate the failure message when used in CONFIG_MODE:
+macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
+  # <name>_CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found:
+  if(${_NAME}_CONFIG)
+    _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing: ${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})")
+  else()
+    # If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version.
+    # List them all in the error message:
+    if(${_NAME}_CONSIDERED_CONFIGS)
+      set(configsText "")
+      list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount)
+      math(EXPR configsCount "${configsCount} - 1")
+      foreach(currentConfigIndex RANGE ${configsCount})
+        list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename)
+        list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
+        set(configsText "${configsText}    ${filename} (version ${version})\n")
+      endforeach()
+      if (${_NAME}_NOT_FOUND_MESSAGE)
+        set(configsText "${configsText}    Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n")
+      endif()
+      _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}")
+
+    else()
+      # Simple case: No Config-file was found at all:
+      _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}")
+    endif()
+  endif()
+endmacro()
+
+
+function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
+
+# set up the arguments for CMAKE_PARSE_ARGUMENTS and check whether we are in
+# new extended or in the "old" mode:
+  set(options  CONFIG_MODE  HANDLE_COMPONENTS)
+  set(oneValueArgs  FAIL_MESSAGE  VERSION_VAR  FOUND_VAR)
+  set(multiValueArgs REQUIRED_VARS)
+  set(_KEYWORDS_FOR_EXTENDED_MODE  ${options} ${oneValueArgs} ${multiValueArgs} )
+  list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX)
+
+  if(${INDEX} EQUAL -1)
+    set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG})
+    set(FPHSA_REQUIRED_VARS ${ARGN})
+    set(FPHSA_VERSION_VAR)
+  else()
+
+    CMAKE_PARSE_ARGUMENTS(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}"  ${_FIRST_ARG} ${ARGN})
+
+    if(FPHSA_UNPARSED_ARGUMENTS)
+      message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"")
+    endif()
+
+    if(NOT FPHSA_FAIL_MESSAGE)
+      set(FPHSA_FAIL_MESSAGE  "DEFAULT_MSG")
+    endif()
+  endif()
+
+# now that we collected all arguments, process them
+
+  if("${FPHSA_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG")
+    set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}")
+  endif()
+
+  # In config-mode, we rely on the variable <package>_CONFIG, which is set by find_package()
+  # when it successfully found the config-file, including version checking:
+  if(FPHSA_CONFIG_MODE)
+    list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG)
+    list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS)
+    set(FPHSA_VERSION_VAR ${_NAME}_VERSION)
+  endif()
+
+  if(NOT FPHSA_REQUIRED_VARS)
+    message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()")
+  endif()
+
+  list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR)
+
+  string(TOUPPER ${_NAME} _NAME_UPPER)
+  string(TOLOWER ${_NAME} _NAME_LOWER)
+
+  if(FPHSA_FOUND_VAR)
+    if(FPHSA_FOUND_VAR MATCHES "^${_NAME}_FOUND$"  OR  FPHSA_FOUND_VAR MATCHES "^${_NAME_UPPER}_FOUND$")
+      set(_FOUND_VAR ${FPHSA_FOUND_VAR})
+    else()
+      message(FATAL_ERROR "The argument for FOUND_VAR is \"${FPHSA_FOUND_VAR}\", but only \"${_NAME}_FOUND\" and \"${_NAME_UPPER}_FOUND\" are valid names.")
+    endif()
+  else()
+    set(_FOUND_VAR ${_NAME_UPPER}_FOUND)
+  endif()
+
+  # collect all variables which were not found, so they can be printed, so the
+  # user knows better what went wrong (#6375)
+  set(MISSING_VARS "")
+  set(DETAILS "")
+  # check if all passed variables are valid
+  unset(${_FOUND_VAR})
+  foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS})
+    if(NOT ${_CURRENT_VAR})
+      set(${_FOUND_VAR} FALSE)
+      set(MISSING_VARS "${MISSING_VARS} ${_CURRENT_VAR}")
+    else()
+      set(DETAILS "${DETAILS}[${${_CURRENT_VAR}}]")
+    endif()
+  endforeach()
+  if(NOT "${${_FOUND_VAR}}" STREQUAL "FALSE")
+    set(${_FOUND_VAR} TRUE)
+  endif()
+
+  # component handling
+  unset(FOUND_COMPONENTS_MSG)
+  unset(MISSING_COMPONENTS_MSG)
+
+  if(FPHSA_HANDLE_COMPONENTS)
+    foreach(comp ${${_NAME}_FIND_COMPONENTS})
+      if(${_NAME}_${comp}_FOUND)
+
+        if(NOT DEFINED FOUND_COMPONENTS_MSG)
+          set(FOUND_COMPONENTS_MSG "found components: ")
+        endif()
+        set(FOUND_COMPONENTS_MSG "${FOUND_COMPONENTS_MSG} ${comp}")
+
+      else()
+
+        if(NOT DEFINED MISSING_COMPONENTS_MSG)
+          set(MISSING_COMPONENTS_MSG "missing components: ")
+        endif()
+        set(MISSING_COMPONENTS_MSG "${MISSING_COMPONENTS_MSG} ${comp}")
+
+        if(${_NAME}_FIND_REQUIRED_${comp})
+          set(${_FOUND_VAR} FALSE)
+          set(MISSING_VARS "${MISSING_VARS} ${comp}")
+        endif()
+
+      endif()
+    endforeach()
+    set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}")
+    set(DETAILS "${DETAILS}[c${COMPONENT_MSG}]")
+  endif()
+
+  # version handling:
+  set(VERSION_MSG "")
+  set(VERSION_OK TRUE)
+  set(VERSION ${${FPHSA_VERSION_VAR}} )
+  if (${_NAME}_FIND_VERSION)
+
+    if(VERSION)
+
+      if(${_NAME}_FIND_VERSION_EXACT)       # exact version required
+        if (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}")
+          set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
+          set(VERSION_OK FALSE)
+        else ()
+          set(VERSION_MSG "(found suitable exact version \"${VERSION}\")")
+        endif ()
+
+      else()     # minimum version specified:
+        if ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}")
+          set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"")
+          set(VERSION_OK FALSE)
+        else ()
+          set(VERSION_MSG "(found suitable version \"${VERSION}\", minimum required is \"${${_NAME}_FIND_VERSION}\")")
+        endif ()
+      endif()
+
+    else()
+
+      # if the package was not found, but a version was given, add that to the output:
+      if(${_NAME}_FIND_VERSION_EXACT)
+         set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")")
+      else()
+         set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")")
+      endif()
+
+    endif()
+  else ()
+    if(VERSION)
+      set(VERSION_MSG "(found version \"${VERSION}\")")
+    endif()
+  endif ()
+
+  if(VERSION_OK)
+    set(DETAILS "${DETAILS}[v${VERSION}(${${_NAME}_FIND_VERSION})]")
+  else()
+    set(${_FOUND_VAR} FALSE)
+  endif()
+
+
+  # print the result:
+  if (${_FOUND_VAR})
+    FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}")
+  else ()
+
+    if(FPHSA_CONFIG_MODE)
+      _FPHSA_HANDLE_FAILURE_CONFIG_MODE()
+    else()
+      if(NOT VERSION_OK)
+        _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})")
+      else()
+        _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}")
+      endif()
+    endif()
+
+  endif ()
+
+  set(${_FOUND_VAR} ${${_FOUND_VAR}} PARENT_SCOPE)
+
+endfunction()

+ 57 - 0
cocos2d/cmake/Modules/FindPackageMessage.cmake

@@ -0,0 +1,57 @@
+#.rst:
+# FindPackageMessage
+# ------------------
+#
+#
+#
+# FIND_PACKAGE_MESSAGE(<name> "message for user" "find result details")
+#
+# This macro is intended to be used in FindXXX.cmake modules files.  It
+# will print a message once for each unique find result.  This is useful
+# for telling the user where a package was found.  The first argument
+# specifies the name (XXX) of the package.  The second argument
+# specifies the message to display.  The third argument lists details
+# about the find result so that if they change the message will be
+# displayed again.  The macro also obeys the QUIET argument to the
+# find_package command.
+#
+# Example:
+#
+# ::
+#
+#   if(X11_FOUND)
+#     FIND_PACKAGE_MESSAGE(X11 "Found X11: ${X11_X11_LIB}"
+#       "[${X11_X11_LIB}][${X11_INCLUDE_DIR}]")
+#   else()
+#    ...
+#   endif()
+
+#=============================================================================
+# Copyright 2008-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+function(FIND_PACKAGE_MESSAGE pkg msg details)
+  # Avoid printing a message repeatedly for the same find result.
+  if(NOT ${pkg}_FIND_QUIETLY)
+    string(REGEX REPLACE "[\n]" "" details "${details}")
+    set(DETAILS_VAR FIND_PACKAGE_MESSAGE_DETAILS_${pkg})
+    if(NOT "${details}" STREQUAL "${${DETAILS_VAR}}")
+      # The message has not yet been printed.
+      message(STATUS "${msg}")
+
+      # Save the find details in the cache to avoid printing the same
+      # message again.
+      set("${DETAILS_VAR}" "${details}"
+        CACHE INTERNAL "Details about finding ${pkg}")
+    endif()
+  endif()
+endfunction()

+ 435 - 0
cocos2d/cmake/Modules/FindPkgConfig.cmake

@@ -0,0 +1,435 @@
+#.rst:
+# FindPkgConfig
+# -------------
+#
+# a pkg-config module for CMake
+#
+#
+#
+# Usage:
+#
+# ::
+#
+#    pkg_check_modules(<PREFIX> [REQUIRED] [QUIET] <MODULE> [<MODULE>]*)
+#      checks for all the given modules
+#
+#
+#
+# ::
+#
+#    pkg_search_module(<PREFIX> [REQUIRED] [QUIET] <MODULE> [<MODULE>]*)
+#      checks for given modules and uses the first working one
+#
+#
+#
+# When the 'REQUIRED' argument was set, macros will fail with an error
+# when module(s) could not be found
+#
+# When the 'QUIET' argument is set, no status messages will be printed.
+#
+# It sets the following variables:
+#
+# ::
+#
+#    PKG_CONFIG_FOUND          ... if pkg-config executable was found
+#    PKG_CONFIG_EXECUTABLE     ... pathname of the pkg-config program
+#    PKG_CONFIG_VERSION_STRING ... the version of the pkg-config program found
+#                                  (since CMake 2.8.8)
+#
+#
+#
+# For the following variables two sets of values exist; first one is the
+# common one and has the given PREFIX.  The second set contains flags
+# which are given out when pkgconfig was called with the '--static'
+# option.
+#
+# ::
+#
+#    <XPREFIX>_FOUND          ... set to 1 if module(s) exist
+#    <XPREFIX>_LIBRARIES      ... only the libraries (w/o the '-l')
+#    <XPREFIX>_LIBRARY_DIRS   ... the paths of the libraries (w/o the '-L')
+#    <XPREFIX>_LDFLAGS        ... all required linker flags
+#    <XPREFIX>_LDFLAGS_OTHER  ... all other linker flags
+#    <XPREFIX>_INCLUDE_DIRS   ... the '-I' preprocessor flags (w/o the '-I')
+#    <XPREFIX>_CFLAGS         ... all required cflags
+#    <XPREFIX>_CFLAGS_OTHER   ... the other compiler flags
+#
+#
+#
+# ::
+#
+#    <XPREFIX> = <PREFIX>        for common case
+#    <XPREFIX> = <PREFIX>_STATIC for static linking
+#
+#
+#
+# There are some special variables whose prefix depends on the count of
+# given modules.  When there is only one module, <PREFIX> stays
+# unchanged.  When there are multiple modules, the prefix will be
+# changed to <PREFIX>_<MODNAME>:
+#
+# ::
+#
+#    <XPREFIX>_VERSION    ... version of the module
+#    <XPREFIX>_PREFIX     ... prefix-directory of the module
+#    <XPREFIX>_INCLUDEDIR ... include-dir of the module
+#    <XPREFIX>_LIBDIR     ... lib-dir of the module
+#
+#
+#
+# ::
+#
+#    <XPREFIX> = <PREFIX>  when |MODULES| == 1, else
+#    <XPREFIX> = <PREFIX>_<MODNAME>
+#
+#
+#
+# A <MODULE> parameter can have the following formats:
+#
+# ::
+#
+#    {MODNAME}            ... matches any version
+#    {MODNAME}>={VERSION} ... at least version <VERSION> is required
+#    {MODNAME}={VERSION}  ... exactly version <VERSION> is required
+#    {MODNAME}<={VERSION} ... modules must not be newer than <VERSION>
+#
+#
+#
+# Examples
+#
+# ::
+#
+#    pkg_check_modules (GLIB2   glib-2.0)
+#
+#
+#
+# ::
+#
+#    pkg_check_modules (GLIB2   glib-2.0>=2.10)
+#      requires at least version 2.10 of glib2 and defines e.g.
+#        GLIB2_VERSION=2.10.3
+#
+#
+#
+# ::
+#
+#    pkg_check_modules (FOO     glib-2.0>=2.10 gtk+-2.0)
+#      requires both glib2 and gtk2, and defines e.g.
+#        FOO_glib-2.0_VERSION=2.10.3
+#        FOO_gtk+-2.0_VERSION=2.8.20
+#
+#
+#
+# ::
+#
+#    pkg_check_modules (XRENDER REQUIRED xrender)
+#      defines e.g.:
+#        XRENDER_LIBRARIES=Xrender;X11
+#        XRENDER_STATIC_LIBRARIES=Xrender;X11;pthread;Xau;Xdmcp
+#
+#
+#
+# ::
+#
+#    pkg_search_module (BAR     libxml-2.0 libxml2 libxml>=2)
+
+#=============================================================================
+# Copyright 2006-2009 Kitware, Inc.
+# Copyright 2006 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+### Common stuff ####
+set(PKG_CONFIG_VERSION 1)
+
+find_program(PKG_CONFIG_EXECUTABLE NAMES pkg-config DOC "pkg-config executable")
+mark_as_advanced(PKG_CONFIG_EXECUTABLE)
+
+if (PKG_CONFIG_EXECUTABLE)
+  execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --version
+    OUTPUT_VARIABLE PKG_CONFIG_VERSION_STRING
+    ERROR_QUIET
+    OUTPUT_STRIP_TRAILING_WHITESPACE)
+endif ()
+
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args(PkgConfig
+                                  REQUIRED_VARS PKG_CONFIG_EXECUTABLE
+                                  VERSION_VAR PKG_CONFIG_VERSION_STRING)
+
+# This is needed because the module name is "PkgConfig" but the name of
+# this variable has always been PKG_CONFIG_FOUND so this isn't automatically
+# handled by FPHSA.
+set(PKG_CONFIG_FOUND "${PKGCONFIG_FOUND}")
+
+# Unsets the given variables
+macro(_pkgconfig_unset var)
+  set(${var} "" CACHE INTERNAL "")
+endmacro()
+
+macro(_pkgconfig_set var value)
+  set(${var} ${value} CACHE INTERNAL "")
+endmacro()
+
+# Invokes pkgconfig, cleans up the result and sets variables
+macro(_pkgconfig_invoke _pkglist _prefix _varname _regexp)
+  set(_pkgconfig_invoke_result)
+
+  execute_process(
+    COMMAND ${PKG_CONFIG_EXECUTABLE} ${ARGN} ${_pkglist}
+    OUTPUT_VARIABLE _pkgconfig_invoke_result
+    RESULT_VARIABLE _pkgconfig_failed)
+
+  if (_pkgconfig_failed)
+    set(_pkgconfig_${_varname} "")
+    _pkgconfig_unset(${_prefix}_${_varname})
+  else()
+    string(REGEX REPLACE "[\r\n]"                  " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}")
+    string(REGEX REPLACE " +$"                     ""  _pkgconfig_invoke_result "${_pkgconfig_invoke_result}")
+
+    if (NOT ${_regexp} STREQUAL "")
+      string(REGEX REPLACE "${_regexp}" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}")
+    endif()
+
+    separate_arguments(_pkgconfig_invoke_result)
+
+    #message(STATUS "  ${_varname} ... ${_pkgconfig_invoke_result}")
+    set(_pkgconfig_${_varname} ${_pkgconfig_invoke_result})
+    _pkgconfig_set(${_prefix}_${_varname} "${_pkgconfig_invoke_result}")
+  endif()
+endmacro()
+
+# Invokes pkgconfig two times; once without '--static' and once with
+# '--static'
+macro(_pkgconfig_invoke_dyn _pkglist _prefix _varname cleanup_regexp)
+  _pkgconfig_invoke("${_pkglist}" ${_prefix}        ${_varname} "${cleanup_regexp}" ${ARGN})
+  _pkgconfig_invoke("${_pkglist}" ${_prefix} STATIC_${_varname} "${cleanup_regexp}" --static  ${ARGN})
+endmacro()
+
+# Splits given arguments into options and a package list
+macro(_pkgconfig_parse_options _result _is_req _is_silent)
+  set(${_is_req} 0)
+  set(${_is_silent} 0)
+
+  foreach(_pkg ${ARGN})
+    if (_pkg STREQUAL "REQUIRED")
+      set(${_is_req} 1)
+    endif ()
+    if (_pkg STREQUAL "QUIET")
+      set(${_is_silent} 1)
+    endif ()
+  endforeach()
+
+  set(${_result} ${ARGN})
+  list(REMOVE_ITEM ${_result} "REQUIRED")
+  list(REMOVE_ITEM ${_result} "QUIET")
+endmacro()
+
+###
+macro(_pkg_check_modules_internal _is_required _is_silent _prefix)
+  _pkgconfig_unset(${_prefix}_FOUND)
+  _pkgconfig_unset(${_prefix}_VERSION)
+  _pkgconfig_unset(${_prefix}_PREFIX)
+  _pkgconfig_unset(${_prefix}_INCLUDEDIR)
+  _pkgconfig_unset(${_prefix}_LIBDIR)
+  _pkgconfig_unset(${_prefix}_LIBS)
+  _pkgconfig_unset(${_prefix}_LIBS_L)
+  _pkgconfig_unset(${_prefix}_LIBS_PATHS)
+  _pkgconfig_unset(${_prefix}_LIBS_OTHER)
+  _pkgconfig_unset(${_prefix}_CFLAGS)
+  _pkgconfig_unset(${_prefix}_CFLAGS_I)
+  _pkgconfig_unset(${_prefix}_CFLAGS_OTHER)
+  _pkgconfig_unset(${_prefix}_STATIC_LIBDIR)
+  _pkgconfig_unset(${_prefix}_STATIC_LIBS)
+  _pkgconfig_unset(${_prefix}_STATIC_LIBS_L)
+  _pkgconfig_unset(${_prefix}_STATIC_LIBS_PATHS)
+  _pkgconfig_unset(${_prefix}_STATIC_LIBS_OTHER)
+  _pkgconfig_unset(${_prefix}_STATIC_CFLAGS)
+  _pkgconfig_unset(${_prefix}_STATIC_CFLAGS_I)
+  _pkgconfig_unset(${_prefix}_STATIC_CFLAGS_OTHER)
+
+  # create a better addressable variable of the modules and calculate its size
+  set(_pkg_check_modules_list ${ARGN})
+  list(LENGTH _pkg_check_modules_list _pkg_check_modules_cnt)
+
+  if(PKG_CONFIG_EXECUTABLE)
+    # give out status message telling checked module
+    if (NOT ${_is_silent})
+      if (_pkg_check_modules_cnt EQUAL 1)
+        message(STATUS "checking for module '${_pkg_check_modules_list}'")
+      else()
+        message(STATUS "checking for modules '${_pkg_check_modules_list}'")
+      endif()
+    endif()
+
+    set(_pkg_check_modules_packages)
+    set(_pkg_check_modules_failed)
+
+    # iterate through module list and check whether they exist and match the required version
+    foreach (_pkg_check_modules_pkg ${_pkg_check_modules_list})
+      set(_pkg_check_modules_exist_query)
+
+      # check whether version is given
+      if (_pkg_check_modules_pkg MATCHES ".*(>=|=|<=).*")
+        string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\1" _pkg_check_modules_pkg_name "${_pkg_check_modules_pkg}")
+        string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\2" _pkg_check_modules_pkg_op   "${_pkg_check_modules_pkg}")
+        string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\3" _pkg_check_modules_pkg_ver  "${_pkg_check_modules_pkg}")
+      else()
+        set(_pkg_check_modules_pkg_name "${_pkg_check_modules_pkg}")
+        set(_pkg_check_modules_pkg_op)
+        set(_pkg_check_modules_pkg_ver)
+      endif()
+
+      # handle the operands
+      if (_pkg_check_modules_pkg_op STREQUAL ">=")
+        list(APPEND _pkg_check_modules_exist_query --atleast-version)
+      endif()
+
+      if (_pkg_check_modules_pkg_op STREQUAL "=")
+        list(APPEND _pkg_check_modules_exist_query --exact-version)
+      endif()
+
+      if (_pkg_check_modules_pkg_op STREQUAL "<=")
+        list(APPEND _pkg_check_modules_exist_query --max-version)
+      endif()
+
+      # create the final query which is of the format:
+      # * --atleast-version <version> <pkg-name>
+      # * --exact-version <version> <pkg-name>
+      # * --max-version <version> <pkg-name>
+      # * --exists <pkg-name>
+      if (_pkg_check_modules_pkg_op)
+        list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_ver}")
+      else()
+        list(APPEND _pkg_check_modules_exist_query --exists)
+      endif()
+
+      _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_VERSION)
+      _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_PREFIX)
+      _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_INCLUDEDIR)
+      _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_LIBDIR)
+
+      list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_name}")
+      list(APPEND _pkg_check_modules_packages    "${_pkg_check_modules_pkg_name}")
+
+      # execute the query
+      execute_process(
+        COMMAND ${PKG_CONFIG_EXECUTABLE} ${_pkg_check_modules_exist_query}
+        RESULT_VARIABLE _pkgconfig_retval)
+
+      # evaluate result and tell failures
+      if (_pkgconfig_retval)
+        if(NOT ${_is_silent})
+          message(STATUS "  package '${_pkg_check_modules_pkg}' not found")
+        endif()
+
+        set(_pkg_check_modules_failed 1)
+      endif()
+    endforeach()
+
+    if(_pkg_check_modules_failed)
+      # fail when requested
+      if (${_is_required})
+        message(SEND_ERROR "A required package was not found")
+      endif ()
+    else()
+      # when we are here, we checked whether requested modules
+      # exist. Now, go through them and set variables
+
+      _pkgconfig_set(${_prefix}_FOUND 1)
+      list(LENGTH _pkg_check_modules_packages pkg_count)
+
+      # iterate through all modules again and set individual variables
+      foreach (_pkg_check_modules_pkg ${_pkg_check_modules_packages})
+        # handle case when there is only one package required
+        if (pkg_count EQUAL 1)
+          set(_pkg_check_prefix "${_prefix}")
+        else()
+          set(_pkg_check_prefix "${_prefix}_${_pkg_check_modules_pkg}")
+        endif()
+
+        _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" VERSION    ""   --modversion )
+        _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" PREFIX     ""   --variable=prefix )
+        _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" INCLUDEDIR ""   --variable=includedir )
+        _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" LIBDIR     ""   --variable=libdir )
+
+        if (NOT ${_is_silent})
+          message(STATUS "  found ${_pkg_check_modules_pkg}, version ${_pkgconfig_VERSION}")
+        endif ()
+      endforeach()
+
+      # set variables which are combined for multiple modules
+      _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LIBRARIES           "(^| )-l" --libs-only-l )
+      _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LIBRARY_DIRS        "(^| )-L" --libs-only-L )
+      _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LDFLAGS             ""        --libs )
+      _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LDFLAGS_OTHER       ""        --libs-only-other )
+
+      _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" INCLUDE_DIRS        "(^| )-I" --cflags-only-I )
+      _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS              ""        --cflags )
+      _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS_OTHER        ""        --cflags-only-other )
+    endif()
+  else()
+    if (${_is_required})
+      message(SEND_ERROR "pkg-config tool not found")
+    endif ()
+  endif()
+endmacro()
+
+###
+### User visible macros start here
+###
+
+###
+macro(pkg_check_modules _prefix _module0)
+  # check cached value
+  if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND)
+    _pkgconfig_parse_options   (_pkg_modules _pkg_is_required _pkg_is_silent "${_module0}" ${ARGN})
+    _pkg_check_modules_internal("${_pkg_is_required}" "${_pkg_is_silent}" "${_prefix}" ${_pkg_modules})
+
+    _pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION})
+  endif()
+endmacro()
+
+###
+macro(pkg_search_module _prefix _module0)
+  # check cached value
+  if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND)
+    set(_pkg_modules_found 0)
+    _pkgconfig_parse_options(_pkg_modules_alt _pkg_is_required _pkg_is_silent "${_module0}" ${ARGN})
+
+    if (NOT ${_pkg_is_silent})
+      message(STATUS "checking for one of the modules '${_pkg_modules_alt}'")
+    endif ()
+
+    # iterate through all modules and stop at the first working one.
+    foreach(_pkg_alt ${_pkg_modules_alt})
+      if(NOT _pkg_modules_found)
+        _pkg_check_modules_internal(0 1 "${_prefix}" "${_pkg_alt}")
+      endif()
+
+      if (${_prefix}_FOUND)
+        set(_pkg_modules_found 1)
+      endif()
+    endforeach()
+
+    if (NOT ${_prefix}_FOUND)
+      if(${_pkg_is_required})
+        message(SEND_ERROR "None of the required '${_pkg_modules_alt}' found")
+      endif()
+    endif()
+
+    _pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION})
+  endif()
+endmacro()
+
+### Local Variables:
+### mode: cmake
+### End:

+ 32 - 0
cocos2d/cmake/Modules/FindRecast.cmake

@@ -0,0 +1,32 @@
+#.rst:
+# FindRecast
+# ------------
+#
+# Locate RECAST library
+#
+# This module defines
+#
+# ::
+#
+#   RECAST_LIBRARIES, the library to link against
+#   RECAST_FOUND, the libraries needed to use RECAST
+#   RECAST_INCLUDE_DIRS, where to find headers.
+#
+
+find_path(RECAST_INCLUDE_DIR
+	NAMES Recast/Recast.h
+	PATH_SUFFIXES include
+)
+
+find_library(RECAST_LIBRARY 
+	NAMES Recast
+	PATH_SUFFIXES lib
+)
+
+set(RECAST_INCLUDE_DIRS "${RECAST_INCLUDE_DIR}")
+set(RECAST_LIBRARIES "${RECAST_LIBRARY}")
+
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args(RECAST DEFAULT_MSG RECAST_LIBRARIES RECAST_INCLUDE_DIRS)
+
+mark_as_advanced(RECAST_INCLUDE_DIR RECAST_LIBRARY)

+ 48 - 0
cocos2d/cmake/Modules/FindSQLite3.cmake

@@ -0,0 +1,48 @@
+# Find SQLite3
+#
+#  SQLITE3_INCLUDE_DIRS - where to find sqlite3.h header.
+#  SQLITE3_LIBRARIES    - List of SQLite3 libraries.
+#  SQLITE3_FOUND        - True if SQLite3 found.
+
+
+set(SQLITE3_FOUND false)
+
+find_path(SQLITE3_INCLUDE_DIRS
+	NAMES
+		sqlite3.h
+	PATHS
+		/usr/include
+		/usr/local/include
+		/opt/local/include
+		/sw/include
+)
+
+find_library(SQLITE3_LIBRARIES
+	NAMES
+		sqlite3
+	PATH_SUFFIXES
+		lib64
+		lib
+	PATHS
+		/usr/lib
+		/usr/local/lib
+		/opt/local/lib
+		/sw/lib
+		/usr/lib/x86_64-linux-gnu
+)
+
+
+if (SQLITE3_INCLUDE_DIRS AND SQLITE3_LIBRARIES)
+	set(SQLITE3_FOUND TRUE)
+	#these next two are needed by the CocosBuildHelpers cocos_find_package macro
+	set(SQLITE3_INCLUDE_DIR ${SQLITE3_INCLUDE_DIRs})
+	set(SQLITE3_LIBRARY ${SQLITE3_LIBRARIES})
+endif (SQLITE3_INCLUDE_DIRS AND SQLITE3_LIBRARIES)
+
+if (NOT SQLITE3_FOUND)
+	message(FATAL_ERROR "Could not find Sqlite3")
+endif (NOT SQLITE3_FOUND)
+
+
+mark_as_advanced(SQLITE3_INCLUDE_DIRS SQLITE3_LIBRARIES)
+

+ 88 - 0
cocos2d/cmake/Modules/FindTIFF.cmake

@@ -0,0 +1,88 @@
+#.rst:
+# FindTIFF
+# --------
+#
+# Find TIFF library
+#
+# Find the native TIFF includes and library This module defines
+#
+# ::
+#
+#   TIFF_INCLUDE_DIR, where to find tiff.h, etc.
+#   TIFF_LIBRARIES, libraries to link against to use TIFF.
+#   TIFF_FOUND, If false, do not try to use TIFF.
+#
+# also defined, but not for general use are
+#
+# ::
+#
+#   TIFF_LIBRARY, where to find the TIFF library.
+
+#=============================================================================
+# Copyright 2002-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+set(TIFF_NAMES ${TIFF_NAMES} tiff libtiff tiff3 libtiff3)
+
+find_path(TIFF_INCLUDE_DIR tiff.h
+    HINTS ENV TIFF_DIR
+    PATH_SUFFIXES include/libtiff include
+    PATHS
+    ~/Library/Frameworks
+    /Library/Frameworks
+    /usr/local
+    /usr
+    /sw # Fink
+    /opt/local # DarwinPorts
+    /opt/csw # Blastwave
+    /opt
+  )
+
+find_library(TIFF_LIBRARY
+  NAMES ${TIFF_NAMES}
+  HINTS ENV TIFF_DIR
+  PATH_SUFFIXES lib
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw
+  /opt/local
+  /opt/csw
+  /opt
+  )
+
+if(TIFF_INCLUDE_DIR AND EXISTS "${TIFF_INCLUDE_DIR}/tiffvers.h")
+    file(STRINGS "${TIFF_INCLUDE_DIR}/tiffvers.h" tiff_version_str
+         REGEX "^#define[\t ]+TIFFLIB_VERSION_STR[\t ]+\"LIBTIFF, Version .*")
+
+    string(REGEX REPLACE "^#define[\t ]+TIFFLIB_VERSION_STR[\t ]+\"LIBTIFF, Version +([^ \\n]*).*"
+           "\\1" TIFF_VERSION_STRING "${tiff_version_str}")
+    unset(tiff_version_str)
+endif()
+
+set(TIFF_INCLUDE_DIRS ${TIFF_INCLUDE_DIR})
+
+# handle the QUIETLY and REQUIRED arguments and set TIFF_FOUND to TRUE if
+# all listed variables are TRUE
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(TIFF
+  REQUIRED_VARS TIFF_LIBRARY TIFF_INCLUDE_DIRS
+  VERSION_VAR TIFF_VERSION_STRING
+  )
+
+if(TIFF_FOUND)
+  set( TIFF_LIBRARIES ${TIFF_LIBRARY} )
+endif()
+
+mark_as_advanced(TIFF_INCLUDE_DIRS TIFF_LIBRARY)

+ 51 - 0
cocos2d/cmake/Modules/FindTinyXML2.cmake

@@ -0,0 +1,51 @@
+#.rst:
+# FindTinyXML2
+# ------------
+#
+# Locate tinyxml2 library
+#
+# This module defines
+#
+# ::
+#
+#   TINYXML2_LIBRARIES, the library to link against
+#   TINYXML2_FOUND, if false, do not try to link to tinyxml2
+#   TINYXML2_INCLUDE_DIRS, where to find headers.
+#
+
+find_path(TinyXML2_INCLUDE_DIR tinyxml2.h
+  HINTS ENV TinyXML2_DIR
+  PATH_SUFFIXES include/tinyxml2 include
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw # Fink
+  /opt/local # DarwinPorts
+  /opt/csw # Blastwave
+  /opt
+)
+
+find_library(TinyXML2_LIBRARY 
+  NAMES tinyxml2 libtinyxml2
+  HINTS ENV TinyXML2_DIR
+  PATH_SUFFIXES lib
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw
+  /opt/local
+  /opt/csw
+  /opt
+)
+
+set(TinyXML2_INCLUDE_DIRS "${TinyXML2_INCLUDE_DIR}")
+set(TinyXML2_LIBRARIES "${TinyXML2_LIBRARY}")
+
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args(TinyXML2 DEFAULT_MSG TinyXML2_LIBRARIES TinyXML2_INCLUDE_DIRS)
+
+mark_as_advanced(TinyXML2_INCLUDE_DIRS TinyXML2_LIBRARIES TinyXML2_LIBRARY)

+ 29 - 0
cocos2d/cmake/Modules/FindVorbis.cmake

@@ -0,0 +1,29 @@
+# - Find vorbis
+# Find the native vorbis includes and libraries
+#
+#  VORBIS_INCLUDE_DIRS - where to find vorbis.h, etc.
+#  VORBIS_LIBRARIES    - List of libraries when using vorbis(file).
+#  VORBIS_FOUND        - True if vorbis found.
+
+find_package(Ogg)
+if(OGG_FOUND)
+	find_path(VORBIS_INCLUDE_DIR vorbis/vorbisfile.h)
+	# MSVC built vorbis may be named vorbis_static
+	# The provided project files name the library with the lib prefix.
+	find_library(VORBIS_LIBRARY NAMES vorbis vorbis_static libvorbis libvorbis_static)
+	find_library(VORBISFILE_LIBRARY NAMES vorbisfile vorbisfile_static libvorbisfile libvorbisfile_static)
+	# Handle the QUIETLY and REQUIRED arguments and set VORBIS_FOUND
+	# to TRUE if all listed variables are TRUE.
+	include(FindPackageHandleStandardArgs)
+	find_package_handle_standard_args(VORBIS DEFAULT_MSG VORBIS_INCLUDE_DIR VORBIS_LIBRARY VORBISFILE_LIBRARY)
+endif(OGG_FOUND)
+
+if(VORBIS_FOUND)
+  set(VORBIS_INCLUDE_DIRS ${VORBIS_INCLUDE_DIR})
+  set(VORBIS_LIBRARIES ${VORBISFILE_LIBRARY} ${VORBIS_LIBRARY} ${OGG_LIBRARY})
+else(VORBIS_FOUND)
+  set(VORBIS_INCLUDE_DIRS)
+  set(VORBIS_LIBRARIES)
+endif(VORBIS_FOUND)
+
+mark_as_advanced(VORBIS_INCLUDE_DIR VORBIS_LIBRARY VORBISFILE_LIBRARY)

+ 48 - 0
cocos2d/cmake/Modules/FindWEBSOCKETS.cmake

@@ -0,0 +1,48 @@
+#.rst:
+# FindWEBSOCKETS
+# --------
+#
+# Find websockets library
+#
+# ::
+#
+#   WEBSOCKETS_INCLUDE_DIRS, where to find libwebsockets.h.
+#   WEBSOCKETS_LIBRARIES, the libraries needed to use WEBSOCKETS.
+#   WEBSOCKETS_FOUND, If false, do not try to use WEBSOCKETS.
+#
+
+find_path(WEBSOCKETS_INCLUDE_DIR libwebsockets.h
+  HINTS ENV WEBSOCKETS_DIR
+  PATH_SUFFIXES include/websockets include/libwebsockets include
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw # Fink
+  /opt/local # DarwinPorts
+  /opt/csw # Blastwave
+  /opt
+  )
+
+find_library(WEBSOCKETS_LIBRARY NAMES websockets libwebsockets
+  HINTS ENV WEBSOCKETS_DIR
+  PATH_SUFFIXES lib
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw
+  /opt/local
+  /opt/csw
+  /opt
+  )
+
+set(WEBSOCKETS_INCLUDE_DIRS ${WEBSOCKETS_INCLUDE_DIR})
+set(WEBSOCKETS_LIBRARIES ${WEBSOCKETS_LIBRARY})
+
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args(WEBSOCKETS DEFAULT_MSG WEBSOCKETS_LIBRARIES WEBSOCKETS_INCLUDE_DIRS)
+
+mark_as_advanced(WEBSOCKETS_LIBRARIES WEBSOCKETS_INCLUDE_DIRS)

+ 69 - 0
cocos2d/cmake/Modules/FindWebP.cmake

@@ -0,0 +1,69 @@
+#.rst:
+# FindWebP
+# ------------
+#
+# Locate webp library
+#
+# This module defines
+#
+# ::
+#
+#   WEBP_LIBRARIES, the library to link against
+#   WEBP_FOUND, if false, do not try to link to FREETYPE
+#   WEBP_INCLUDE_DIRS, where to find headers.
+#   This is the concatenation of the paths:
+#   WEBP_INCLUDE_DIR
+#
+#=============================================================================
+# Copyright 2014-2014 Martell Malone
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+FIND_PATH(WEBP_INCLUDE_DIR decode.h
+  HINTS
+  ENV WEBP_DIR
+  PATH_SUFFIXES include/webp include
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw # Fink
+  /opt/local # DarwinPorts
+  /opt/csw # Blastwave
+  /opt
+)
+
+FIND_LIBRARY(WEBP_LIBRARY 
+  NAMES webp libwebp
+  HINTS
+  ENV WEBP_DIR
+  PATH_SUFFIXES lib
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw
+  /opt/local
+  /opt/csw
+  /opt
+)
+
+set(WEBP_INCLUDE_DIRS "${WEBP_INCLUDE_DIR}")
+set(WEBP_LIBRARIES "${WEBP_LIBRARY}")
+
+INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+# handle the QUIETLY and REQUIRED arguments and set WEBP_FOUND to TRUE if 
+# all listed variables are TRUE
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(WebP DEFAULT_MSG WEBP_LIBRARIES WEBP_INCLUDE_DIR)
+
+MARK_AS_ADVANCED(WEBP_INCLUDE_DIR WEBP_LIBRARIES WEBP_LIBRARY)

+ 32 - 0
cocos2d/cmake/Modules/Findflatbuffers.cmake

@@ -0,0 +1,32 @@
+#.rst:
+# Findflatbuffers
+# ------------
+#
+# Locate flatbuffers library
+#
+# This module defines
+#
+# ::
+#
+#   FLATBUFFERS_LIBRARIES, the library to link against
+#   FLATBUFFERS_FOUND, the libraries needed to use flatbuffers
+#   FLATBUFFERS_INCLUDE_DIRS, where to find headers.
+#
+
+find_path(FLATBUFFERS_INCLUDE_DIR
+	NAMES flatbuffers.h
+	PATH_SUFFIXES include include/flatbuffers
+)
+
+find_library(FLATBUFFERS_LIBRARY 
+	NAMES flatbuffers
+	PATH_SUFFIXES lib
+)
+
+set(FLATBUFFERS_INCLUDE_DIRS "${FLATBUFFERS_INCLUDE_DIR}")
+set(FLATBUFFERS_LIBRARIES "${FLATBUFFERS_LIBRARY}")
+
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args(FLATBUFFERS DEFAULT_MSG FLATBUFFERS_LIBRARIES FLATBUFFERS_INCLUDE_DIRS)
+
+mark_as_advanced(FLATBUFFERS_INCLUDE_DIR FLATBUFFERS_LIBRARY)

+ 32 - 0
cocos2d/cmake/Modules/Findxxhash.cmake

@@ -0,0 +1,32 @@
+#.rst:
+# Findxxhash
+# ------------
+#
+# Locate xxhash library
+#
+# This module defines
+#
+# ::
+#
+#   XXHASH_LIBRARIES, the library to link against
+#   XXHASH_FOUND, the libraries needed to use flatbuffers
+#   XXHASH_INCLUDE_DIRS, where to find headers.
+#
+
+find_path(XXHASH_INCLUDE_DIR
+	NAMES xxhash.h xxhash.h
+	PATH_SUFFIXES include include/xxhash
+)
+
+find_library(XXHASH_LIBRARY 
+	NAMES xxhash
+	PATH_SUFFIXES lib
+)
+
+set(XXHASH_INCLUDE_DIRS "${XXHASH_INCLUDE_DIR}")
+set(XXHASH_LIBRARIES "${XXHASH_LIBRARY}")
+
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args(XXHASH DEFAULT_MSG XXHASH_LIBRARIES XXHASH_INCLUDE_DIRS)
+
+mark_as_advanced(XXHASH_INCLUDE_DIR XXHASH_LIBRARY)

+ 81 - 0
cocos2d/cmake/Modules/SelectLibraryConfigurations.cmake

@@ -0,0 +1,81 @@
+#.rst:
+# SelectLibraryConfigurations
+# ---------------------------
+#
+#
+#
+# select_library_configurations( basename )
+#
+# This macro takes a library base name as an argument, and will choose
+# good values for basename_LIBRARY, basename_LIBRARIES,
+# basename_LIBRARY_DEBUG, and basename_LIBRARY_RELEASE depending on what
+# has been found and set.  If only basename_LIBRARY_RELEASE is defined,
+# basename_LIBRARY will be set to the release value, and
+# basename_LIBRARY_DEBUG will be set to basename_LIBRARY_DEBUG-NOTFOUND.
+# If only basename_LIBRARY_DEBUG is defined, then basename_LIBRARY will
+# take the debug value, and basename_LIBRARY_RELEASE will be set to
+# basename_LIBRARY_RELEASE-NOTFOUND.
+#
+# If the generator supports configuration types, then basename_LIBRARY
+# and basename_LIBRARIES will be set with debug and optimized flags
+# specifying the library to be used for the given configuration.  If no
+# build type has been set or the generator in use does not support
+# configuration types, then basename_LIBRARY and basename_LIBRARIES will
+# take only the release value, or the debug value if the release one is
+# not set.
+
+#=============================================================================
+# Copyright 2009 Will Dicharry <wdicharry@stellarscience.com>
+# Copyright 2005-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+# This macro was adapted from the FindQt4 CMake module and is maintained by Will
+# Dicharry <wdicharry@stellarscience.com>.
+
+macro( select_library_configurations basename )
+    if(NOT ${basename}_LIBRARY_RELEASE)
+        set(${basename}_LIBRARY_RELEASE "${basename}_LIBRARY_RELEASE-NOTFOUND" CACHE FILEPATH "Path to a library.")
+    endif()
+    if(NOT ${basename}_LIBRARY_DEBUG)
+        set(${basename}_LIBRARY_DEBUG "${basename}_LIBRARY_DEBUG-NOTFOUND" CACHE FILEPATH "Path to a library.")
+    endif()
+
+    if( ${basename}_LIBRARY_DEBUG AND ${basename}_LIBRARY_RELEASE AND
+           NOT ${basename}_LIBRARY_DEBUG STREQUAL ${basename}_LIBRARY_RELEASE AND
+           ( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE ) )
+        # if the generator supports configuration types or CMAKE_BUILD_TYPE
+        # is set, then set optimized and debug options.
+        set( ${basename}_LIBRARY "" )
+        foreach( _libname IN LISTS ${basename}_LIBRARY_RELEASE )
+            list( APPEND ${basename}_LIBRARY optimized "${_libname}" )
+        endforeach()
+        foreach( _libname IN LISTS ${basename}_LIBRARY_DEBUG )
+            list( APPEND ${basename}_LIBRARY debug "${_libname}" )
+        endforeach()
+    elseif( ${basename}_LIBRARY_RELEASE )
+        set( ${basename}_LIBRARY ${${basename}_LIBRARY_RELEASE} )
+    elseif( ${basename}_LIBRARY_DEBUG )
+        set( ${basename}_LIBRARY ${${basename}_LIBRARY_DEBUG} )
+    else()
+        set( ${basename}_LIBRARY "${basename}_LIBRARY-NOTFOUND")
+    endif()
+
+    set( ${basename}_LIBRARIES "${${basename}_LIBRARY}" )
+
+    if( ${basename}_LIBRARY )
+        set( ${basename}_FOUND TRUE )
+    endif()
+
+    mark_as_advanced( ${basename}_LIBRARY_RELEASE
+        ${basename}_LIBRARY_DEBUG
+    )
+endmacro()

+ 54 - 0
cocos2d/cmake/Modules/SelectModule.cmake

@@ -0,0 +1,54 @@
+macro (SelectModule)
+  set(USE_WEBP_DEFAULT ON)
+  if(WINRT OR WP8)
+    set(USE_WEBP_DEFAULT OFF)
+  endif()
+
+  set(USE_PREBUILT_LIBS_DEFAULT ON)
+  if(MINGW)
+    set(USE_PREBUILT_LIBS_DEFAULT OFF)
+  endif()
+
+  set(BUILD_CPP_EMPTY_TEST_DEFAULT ON)
+  set(BUILD_CPP_TESTS_DEFAULT ON)
+  set(BUILD_LUA_LIBS_DEFAULT ON)
+  set(BUILD_LUA_TESTS_DEFAULT ON)
+  set(BUILD_JS_LIBS_DEFAULT ON)
+  set(BUILD_JS_TESTS_DEFAULT ON)
+  # TODO: fix test samples for MSVC
+  if(MSVC)
+    set(BUILD_CPP_EMPTY_TEST_DEFAULT OFF)
+    set(BUILD_CPP_TESTS_DEFAULT OFF)
+    set(BUILD_LUA_LIBS_DEFAULT OFF)
+    set(BUILD_LUA_TESTS_DEFAULT OFF)
+    set(BUILD_JS_LIBS_DEFAULT OFF)
+    set(BUILD_JS_TESTS_DEFAULT OFF)
+  endif()
+
+  option(USE_CHIPMUNK "Use chipmunk for physics library" ON)
+  option(USE_BOX2D "Use box2d for physics library" OFF)
+  option(USE_BULLET "Use bullet for physics3d library" ON)
+  option(USE_RECAST "Use Recast for navigation mesh" ON)
+  option(USE_WEBP "Use WebP codec" ${USE_WEBP_DEFAULT})
+  option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
+  option(DEBUG_MODE "Debug or release?" ON)
+  option(BUILD_EXTENSIONS "Build extension library" ON)
+  option(BUILD_EDITOR_SPINE "Build editor support for spine" ON)
+  option(BUILD_EDITOR_COCOSTUDIO "Build editor support for cocostudio" ON)
+  option(BUILD_EDITOR_COCOSBUILDER "Build editor support for cocosbuilder" ON)
+  option(BUILD_BOX2D "Build box2d external without using it for physics library" OFF)
+  option(BUILD_CPP_TESTS "Build TestCpp samples" ${BUILD_CPP_TESTS_DEFAULT})
+  option(BUILD_CPP_EMPTY_TEST "Build TestCpp samples" ${BUILD_CPP_EMPTY_TEST_DEFAULT})
+  option(BUILD_LUA_LIBS "Build lua libraries" ${BUILD_LUA_LIBS_DEFAULT})
+  option(BUILD_LUA_TESTS "Build TestLua samples" ${BUILD_LUA_TESTS_DEFAULT})
+  option(BUILD_JS_LIBS "Build js libraries" ${BUILD_JS_LIBS_DEFAULT})
+  option(BUILD_JS_TESTS "Build TestJS samples" ${BUILD_JS_TESTS_DEFAULT})
+  option(USE_PREBUILT_LIBS "Use prebuilt libraries in external directory" ${USE_PREBUILT_LIBS_DEFAULT})
+  option(USE_SOURCES_EXTERNAL "Use sources in external directory (automatically ON when USE_PREBUILT_LIBS is ON)" OFF)
+
+  if(USE_PREBUILT_LIBS AND MINGW)
+    message(FATAL_ERROR "Prebuilt windows libs can't be used with mingw, please use packages.")
+    return()
+  endif()
+
+endmacro(SelectModule)

+ 104 - 0
cocos2d/cmake/Modules/SetCompilerOptions.cmake

@@ -0,0 +1,104 @@
+macro (SetCompilerOptions)
+	set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DCOCOS2D_DEBUG=1")
+	set(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
+
+    # definitions for chipmunk
+	if (USE_CHIPMUNK)
+		add_definitions(-DCC_ENABLE_CHIPMUNK_INTEGRATION=1)
+		if (IOS OR MACOSX)
+			# without this chipmunk will try to use apple defined geometry types, that conflicts with cocos
+            add_definitions(-DCP_USE_CGPOINTS=0)
+		endif()
+	else()
+		add_definitions(-DCC_USE_PHYSICS=0)
+	endif()
+
+    # definitions for box2d
+	if (USE_BOX2D)
+		add_definitions(-DCC_ENABLE_BOX2D_INTEGRATION=1)
+	else()
+		add_definitions(-DCC_ENABLE_BOX2D_INTEGRATION=0)
+	endif()
+
+    # definitions for bullet
+	if (USE_BULLET)
+		add_definitions(-DCC_ENABLE_BULLET_INTEGRATION=1)
+        add_definitions(-DCC_USE_3D_PHYSICS=1)
+	else()
+		add_definitions(-DCC_ENABLE_BULLET_INTEGRATION=0)
+        add_definitions(-DCC_USE_3D_PHYSICS=0)
+	endif()
+
+    # definitions for recast
+	if (USE_RECAST)
+		add_definitions(-DCC_USE_NAVMESH=1)
+	else()
+		add_definitions(-DCC_USE_NAVMESH=0)
+	endif()
+
+	# Compiler options
+	if(MSVC)
+	  add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS
+	                  -wd4251 -wd4244 -wd4334 -wd4005 -wd4820 -wd4710
+	                  -wd4514 -wd4056 -wd4996 -wd4099)
+
+	  # Use inline debug info (/Z7) format. Or internal error may occur.
+	  # Errors looks like: "xmemory0(592): error C3130: Internal Compiler Error: failed to write injected code block to PDB"
+	  foreach(lang C CXX)
+	    string(REGEX REPLACE "/Z[iI7]" "" CMAKE_${lang}_FLAGS_DEBUG "${CMAKE_${lang}_FLAGS_DEBUG}")
+	    set(CMAKE_${lang}_FLAGS_DEBUG "${CMAKE_${lang}_FLAGS_DEBUG} /Z7")
+	  endforeach()
+
+	else()
+	  set(CMAKE_C_FLAGS_DEBUG "-g -Wall -Wextra")
+	  set(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
+	  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -fPIC")
+	  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-deprecated-declarations -Wno-reorder -Wno-invalid-offsetof -fPIC")
+	  if(CLANG)
+	    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
+	  endif()
+	endif(MSVC)
+
+	# Some macro definitions
+	if(WINDOWS)
+
+	  if(BUILD_SHARED_LIBS)
+	    add_definitions(-D_USRDLL -D_EXPORT_DLL_ -D_USEGUIDLL -D_USREXDLL -D_USRSTUDIODLL)
+	  else()
+	    add_definitions(-DCC_STATIC)
+	  endif()
+
+	  add_definitions(-DCOCOS2DXWIN32_EXPORTS -D_WINDOWS -DWIN32 -D_WIN32)
+	  set(PLATFORM_FOLDER win32)
+	elseif(MACOSX OR APPLE)
+	  add_definitions(-DCC_TARGET_OS_MAC)
+	  add_definitions(-DUSE_FILE32API)
+	  set(PLATFORM_FOLDER mac)
+	elseif(LINUX)
+	  add_definitions(-DLINUX)
+	  set(PLATFORM_FOLDER linux)
+	elseif(ANDROID)
+	  add_definitions(-DUSE_FILE32API)
+	  set(PLATFORM_FOLDER android)
+	  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexceptions")
+	  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsigned-char -latomic")
+	else()
+	  message( FATAL_ERROR "Unsupported platform, CMake will exit" )
+	  return()
+	endif()
+
+	if(MINGW)
+	  #add_definitions(-DGLEW_STATIC)
+	  add_definitions(-D__SSIZE_T)
+
+	  if(CLANG)
+	    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ")
+	    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ")
+	  endif()
+	endif()
+
+	if (MINGW AND NOT USE_PREBUILT_LIBS)
+		add_definitions(-DMINIZIP_FROM_SYSTEM)
+	endif()
+
+endmacro (SetCompilerOptions)

+ 1715 - 0
cocos2d/cmake/android.toolchain.cmake

@@ -0,0 +1,1715 @@
+# Copyright (c) 2010-2011, Ethan Rublee
+# Copyright (c) 2011-2014, Andrey Kamaev
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1.  Redistributions of source code must retain the above copyright notice,
+#     this list of conditions and the following disclaimer.
+#
+# 2.  Redistributions in binary form must reproduce the above copyright notice,
+#     this list of conditions and the following disclaimer in the documentation
+#     and/or other materials provided with the distribution.
+#
+# 3.  Neither the name of the copyright holder nor the names of its
+#     contributors may be used to endorse or promote products derived from this
+#     software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+# ------------------------------------------------------------------------------
+#  Android CMake toolchain file, for use with the Android NDK r5-r10d
+#  Requires cmake 2.6.3 or newer (2.8.9 or newer is recommended).
+#  See home page: https://github.com/taka-no-me/android-cmake
+#
+#  Usage Linux:
+#   $ export ANDROID_NDK=/absolute/path/to/the/android-ndk
+#   $ mkdir build && cd build
+#   $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake ..
+#   $ make -j8
+#
+#  Usage Windows:
+#     You need native port of make to build your project.
+#     Android NDK r7 (and newer) already has make.exe on board.
+#     For older NDK you have to install it separately.
+#     For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm
+#
+#   $ SET ANDROID_NDK=C:\absolute\path\to\the\android-ndk
+#   $ mkdir build && cd build
+#   $ cmake.exe -G"MinGW Makefiles"
+#       -DCMAKE_TOOLCHAIN_FILE=path\to\the\android.toolchain.cmake
+#       -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%\prebuilt\windows\bin\make.exe" ..
+#   $ cmake.exe --build .
+#
+#
+#  Options (can be set as cmake parameters: -D<option_name>=<value>):
+#    ANDROID_NDK=/opt/android-ndk - path to the NDK root.
+#      Can be set as environment variable. Can be set only at first cmake run.
+#
+#    ANDROID_ABI=armeabi-v7a - specifies the target Application Binary
+#      Interface (ABI). This option nearly matches to the APP_ABI variable
+#      used by ndk-build tool from Android NDK.
+#
+#      Possible targets are:
+#        "armeabi" - ARMv5TE based CPU with software floating point operations
+#        "armeabi-v7a" - ARMv7 based devices with hardware FPU instructions
+#            this ABI target is used by default
+#        "armeabi-v7a with NEON" - same as armeabi-v7a, but
+#            sets NEON as floating-point unit
+#        "armeabi-v7a with VFPV3" - same as armeabi-v7a, but
+#            sets VFPV3 as floating-point unit (has 32 registers instead of 16)
+#        "armeabi-v6 with VFP" - tuned for ARMv6 processors having VFP
+#        "x86" - IA-32 instruction set
+#        "mips" - MIPS32 instruction set
+#
+#      64-bit ABIs for NDK r10 and newer:
+#        "arm64-v8a" - ARMv8 AArch64 instruction set
+#        "x86_64" - Intel64 instruction set (r1)
+#        "mips64" - MIPS64 instruction set (r6)
+#
+#    ANDROID_NATIVE_API_LEVEL=android-8 - level of Android API compile for.
+#      Option is read-only when standalone toolchain is used.
+#      Note: building for "android-L" requires explicit configuration.
+#
+#    ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 - the name of compiler
+#      toolchain to be used. The list of possible values depends on the NDK
+#      version. For NDK r10c the possible values are:
+#
+#        * aarch64-linux-android-4.9
+#        * aarch64-linux-android-clang3.4
+#        * aarch64-linux-android-clang3.5
+#        * arm-linux-androideabi-4.6
+#        * arm-linux-androideabi-4.8
+#        * arm-linux-androideabi-4.9 (default)
+#        * arm-linux-androideabi-clang3.4
+#        * arm-linux-androideabi-clang3.5
+#        * mips64el-linux-android-4.9
+#        * mips64el-linux-android-clang3.4
+#        * mips64el-linux-android-clang3.5
+#        * mipsel-linux-android-4.6
+#        * mipsel-linux-android-4.8
+#        * mipsel-linux-android-4.9
+#        * mipsel-linux-android-clang3.4
+#        * mipsel-linux-android-clang3.5
+#        * x86-4.6
+#        * x86-4.8
+#        * x86-4.9
+#        * x86-clang3.4
+#        * x86-clang3.5
+#        * x86_64-4.9
+#        * x86_64-clang3.4
+#        * x86_64-clang3.5
+#
+#    ANDROID_FORCE_ARM_BUILD=OFF - set ON to generate 32-bit ARM instructions
+#      instead of Thumb. Is not available for "armeabi-v6 with VFP"
+#      (is forced to be ON) ABI.
+#
+#    ANDROID_NO_UNDEFINED=ON - set ON to show all undefined symbols as linker
+#      errors even if they are not used.
+#
+#    ANDROID_SO_UNDEFINED=OFF - set ON to allow undefined symbols in shared
+#      libraries. Automatically turned for NDK r5x and r6x due to GLESv2
+#      problems.
+#
+#    ANDROID_STL=gnustl_static - specify the runtime to use.
+#
+#      Possible values are:
+#        none           -> Do not configure the runtime.
+#        system         -> Use the default minimal system C++ runtime library.
+#                          Implies -fno-rtti -fno-exceptions.
+#                          Is not available for standalone toolchain.
+#        system_re      -> Use the default minimal system C++ runtime library.
+#                          Implies -frtti -fexceptions.
+#                          Is not available for standalone toolchain.
+#        gabi++_static  -> Use the GAbi++ runtime as a static library.
+#                          Implies -frtti -fno-exceptions.
+#                          Available for NDK r7 and newer.
+#                          Is not available for standalone toolchain.
+#        gabi++_shared  -> Use the GAbi++ runtime as a shared library.
+#                          Implies -frtti -fno-exceptions.
+#                          Available for NDK r7 and newer.
+#                          Is not available for standalone toolchain.
+#        stlport_static -> Use the STLport runtime as a static library.
+#                          Implies -fno-rtti -fno-exceptions for NDK before r7.
+#                          Implies -frtti -fno-exceptions for NDK r7 and newer.
+#                          Is not available for standalone toolchain.
+#        stlport_shared -> Use the STLport runtime as a shared library.
+#                          Implies -fno-rtti -fno-exceptions for NDK before r7.
+#                          Implies -frtti -fno-exceptions for NDK r7 and newer.
+#                          Is not available for standalone toolchain.
+#        gnustl_static  -> Use the GNU STL as a static library.
+#                          Implies -frtti -fexceptions.
+#        gnustl_shared  -> Use the GNU STL as a shared library.
+#                          Implies -frtti -fno-exceptions.
+#                          Available for NDK r7b and newer.
+#                          Silently degrades to gnustl_static if not available.
+#        c++_shared     -> Use the LLVM libc++ runtime as a shared library.
+#                          Implies -std=c++11.
+#                          Available for NDK r7b and newer.
+#                          Is not available for standalone toolchain.
+#
+#    ANDROID_STL_FORCE_FEATURES=ON - turn rtti and exceptions support based on
+#      chosen runtime. If disabled, then the user is responsible for settings
+#      these options.
+#
+#  What?:
+#    android-cmake toolchain searches for NDK/toolchain in the following order:
+#      ANDROID_NDK - cmake parameter
+#      ANDROID_NDK - environment variable
+#      ANDROID_STANDALONE_TOOLCHAIN - cmake parameter
+#      ANDROID_STANDALONE_TOOLCHAIN - environment variable
+#      ANDROID_NDK - default locations
+#      ANDROID_STANDALONE_TOOLCHAIN - default locations
+#
+#    Make sure to do the following in your scripts:
+#      SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}" )
+#      SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}" )
+#    The flags will be prepopulated with critical flags, so don't loose them.
+#    Also be aware that toolchain also sets configuration-specific compiler
+#    flags and linker flags.
+#
+#    ANDROID and BUILD_ANDROID will be set to true, you may test any of these
+#    variables to make necessary Android-specific configuration changes.
+#
+#    Also ARMEABI or ARMEABI_V7A or X86 or MIPS or ARM64_V8A or X86_64 or MIPS64
+#    will be set true, mutually exclusive. NEON option will be set true
+#    if VFP is set to NEON.
+#
+# ------------------------------------------------------------------------------
+
+cmake_minimum_required( VERSION 2.6.3 )
+
+if( DEFINED CMAKE_CROSSCOMPILING )
+ # subsequent toolchain loading is not really needed
+ return()
+endif()
+
+if( CMAKE_TOOLCHAIN_FILE )
+ # touch toolchain variable to suppress "unused variable" warning
+endif()
+
+# inherit settings in recursive loads
+get_property( _CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE )
+if( _CMAKE_IN_TRY_COMPILE )
+ include( "${CMAKE_CURRENT_SOURCE_DIR}/../android.toolchain.config.cmake" OPTIONAL )
+endif()
+
+# this one is important
+if( CMAKE_VERSION VERSION_GREATER "3.0.99" )
+ set( CMAKE_SYSTEM_NAME Android )
+else()
+ set( CMAKE_SYSTEM_NAME Linux )
+endif()
+
+# this one not so much
+set( CMAKE_SYSTEM_VERSION 1 )
+
+# rpath makes low sense for Android
+set( CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "" )
+set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." )
+
+# NDK search paths
+set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r10d -r10c -r10b -r10 -r9d -r9c -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" )
+if( NOT DEFINED ANDROID_NDK_SEARCH_PATHS )
+ if( CMAKE_HOST_WIN32 )
+  file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS )
+  set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}" "$ENV{SystemDrive}/NVPACK" )
+ else()
+  file( TO_CMAKE_PATH "$ENV{HOME}" ANDROID_NDK_SEARCH_PATHS )
+  set( ANDROID_NDK_SEARCH_PATHS /opt "${ANDROID_NDK_SEARCH_PATHS}/NVPACK" )
+ endif()
+endif()
+if( NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH )
+ set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain )
+endif()
+
+# known ABIs
+set( ANDROID_SUPPORTED_ABIS_arm "armeabi-v7a;armeabi;armeabi-v7a with NEON;armeabi-v7a with VFPV3;armeabi-v6 with VFP" )
+set( ANDROID_SUPPORTED_ABIS_arm64 "arm64-v8a" )
+set( ANDROID_SUPPORTED_ABIS_x86 "x86" )
+set( ANDROID_SUPPORTED_ABIS_x86_64 "x86_64" )
+set( ANDROID_SUPPORTED_ABIS_mips "mips" )
+set( ANDROID_SUPPORTED_ABIS_mips64 "mips64" )
+
+# API level defaults
+set( ANDROID_DEFAULT_NDK_API_LEVEL 9 )
+set( ANDROID_DEFAULT_NDK_API_LEVEL_arm64 21 )
+set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 9 )
+set( ANDROID_DEFAULT_NDK_API_LEVEL_x86_64 21 )
+set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 9 )
+set( ANDROID_DEFAULT_NDK_API_LEVEL_mips64 21 )
+
+
+macro( __LIST_FILTER listvar regex )
+  if( ${listvar} )
+    foreach( __val ${${listvar}} )
+      if( __val MATCHES "${regex}" )
+        list( REMOVE_ITEM ${listvar} "${__val}" )
+      endif()
+    endforeach()
+  endif()
+endmacro()
+
+macro( __INIT_VARIABLE var_name )
+  set( __test_path 0 )
+  foreach( __var ${ARGN} )
+    if( __var STREQUAL "PATH" )
+      set( __test_path 1 )
+      break()
+    endif()
+  endforeach()
+
+  if( __test_path AND NOT EXISTS "${${var_name}}" )
+    unset( ${var_name} CACHE )
+  endif()
+
+  if( " ${${var_name}}" STREQUAL " " )
+    set( __values 0 )
+    foreach( __var ${ARGN} )
+      if( __var STREQUAL "VALUES" )
+        set( __values 1 )
+      elseif( NOT __var STREQUAL "PATH" )
+        if( __var MATCHES "^ENV_.*$" )
+          string( REPLACE "ENV_" "" __var "${__var}" )
+          set( __value "$ENV{${__var}}" )
+        elseif( DEFINED ${__var} )
+          set( __value "${${__var}}" )
+        elseif( __values )
+          set( __value "${__var}" )
+        else()
+          set( __value "" )
+        endif()
+
+        if( NOT " ${__value}" STREQUAL " " AND (NOT __test_path OR EXISTS "${__value}") )
+          set( ${var_name} "${__value}" )
+          break()
+        endif()
+      endif()
+    endforeach()
+    unset( __value )
+    unset( __values )
+  endif()
+
+  if( __test_path )
+    file( TO_CMAKE_PATH "${${var_name}}" ${var_name} )
+  endif()
+  unset( __test_path )
+endmacro()
+
+macro( __DETECT_NATIVE_API_LEVEL _var _path )
+  set( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*.*$" )
+  file( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" )
+  if( NOT __apiFileContent )
+    message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." )
+  endif()
+  string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" )
+  unset( __apiFileContent )
+  unset( __ndkApiLevelRegex )
+endmacro()
+
+macro( __DETECT_TOOLCHAIN_MACHINE_NAME _var _root )
+ if( EXISTS "${_root}" )
+    file( GLOB __gccExePath RELATIVE "${_root}/bin/" "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" )
+    __LIST_FILTER( __gccExePath "^[.].*" )
+    list( LENGTH __gccExePath __gccExePathsCount )
+    if( NOT __gccExePathsCount EQUAL 1  AND NOT _CMAKE_IN_TRY_COMPILE )
+      message( WARNING "Could not determine machine name for compiler from ${_root}" )
+      set( ${_var} "" )
+    else()
+      get_filename_component( __gccExeName "${__gccExePath}" NAME_WE )
+      string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" )
+    endif()
+    unset( __gccExePath )
+    unset( __gccExePathsCount )
+    unset( __gccExeName )
+  else()
+    set( ${_var} "" )
+  endif()
+endmacro()
+
+
+# fight against cygwin
+set( ANDROID_FORBID_SYGWIN TRUE CACHE BOOL "Prevent cmake from working under cygwin and using cygwin tools")
+mark_as_advanced( ANDROID_FORBID_SYGWIN )
+if( ANDROID_FORBID_SYGWIN )
+ if( CYGWIN )
+  message( FATAL_ERROR "Android NDK and android-cmake toolchain are not welcome Cygwin. It is unlikely that this cmake toolchain will work under cygwin. But if you want to try then you can set cmake variable ANDROID_FORBID_SYGWIN to FALSE and rerun cmake." )
+ endif()
+
+ if( CMAKE_HOST_WIN32 )
+  # remove cygwin from PATH
+  set( __new_path "$ENV{PATH}")
+  __LIST_FILTER( __new_path "cygwin" )
+  set(ENV{PATH} "${__new_path}")
+  unset(__new_path)
+ endif()
+endif()
+
+
+# detect current host platform
+if( NOT DEFINED ANDROID_NDK_HOST_X64 AND (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64" OR CMAKE_HOST_APPLE) )
+ set( ANDROID_NDK_HOST_X64 1 CACHE BOOL "Try to use 64-bit compiler toolchain" )
+ mark_as_advanced( ANDROID_NDK_HOST_X64 )
+endif()
+
+set( TOOL_OS_SUFFIX "" )
+if( CMAKE_HOST_APPLE )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86_64" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME2 "darwin-x86" )
+elseif( CMAKE_HOST_WIN32 )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME "windows-x86_64" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME2 "windows" )
+ set( TOOL_OS_SUFFIX ".exe" )
+elseif( CMAKE_HOST_UNIX )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86_64" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME2 "linux-x86" )
+else()
+ message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" )
+endif()
+
+if( NOT ANDROID_NDK_HOST_X64 )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} )
+endif()
+
+# see if we have path to Android NDK
+if( NOT ANDROID_NDK AND NOT ANDROID_STANDALONE_TOOLCHAIN )
+  __INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK )
+endif()
+if( NOT ANDROID_NDK )
+ # see if we have path to Android standalone toolchain
+ __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN )
+
+ if( NOT ANDROID_STANDALONE_TOOLCHAIN )
+  #try to find Android NDK in one of the the default locations
+  set( __ndkSearchPaths )
+  foreach( __ndkSearchPath ${ANDROID_NDK_SEARCH_PATHS} )
+   foreach( suffix ${ANDROID_SUPPORTED_NDK_VERSIONS} )
+    list( APPEND __ndkSearchPaths "${__ndkSearchPath}/android-ndk${suffix}" )
+   endforeach()
+  endforeach()
+  __INIT_VARIABLE( ANDROID_NDK PATH VALUES ${__ndkSearchPaths} )
+  unset( __ndkSearchPaths )
+
+  if( ANDROID_NDK )
+   message( STATUS "Using default path for Android NDK: ${ANDROID_NDK}" )
+   message( STATUS "  If you prefer to use a different location, please define a cmake or environment variable: ANDROID_NDK" )
+  else()
+   #try to find Android standalone toolchain in one of the the default locations
+   __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH )
+
+   if( ANDROID_STANDALONE_TOOLCHAIN )
+    message( STATUS "Using default path for standalone toolchain ${ANDROID_STANDALONE_TOOLCHAIN}" )
+    message( STATUS "  If you prefer to use a different location, please define the variable: ANDROID_STANDALONE_TOOLCHAIN" )
+   endif( ANDROID_STANDALONE_TOOLCHAIN )
+  endif( ANDROID_NDK )
+ endif( NOT ANDROID_STANDALONE_TOOLCHAIN )
+endif( NOT ANDROID_NDK )
+
+# remember found paths
+if( ANDROID_NDK )
+ get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE )
+ set( ANDROID_NDK "${ANDROID_NDK}" CACHE INTERNAL "Path of the Android NDK" FORCE )
+ set( BUILD_WITH_ANDROID_NDK True )
+ if( EXISTS "${ANDROID_NDK}/RELEASE.TXT" )
+  file( STRINGS "${ANDROID_NDK}/RELEASE.TXT" ANDROID_NDK_RELEASE_FULL LIMIT_COUNT 1 REGEX "r[0-9]+[a-z]?" )
+  string( REGEX MATCH "r([0-9]+)([a-z]?)" ANDROID_NDK_RELEASE "${ANDROID_NDK_RELEASE_FULL}" )
+ else()
+  set( ANDROID_NDK_RELEASE "r1x" )
+  set( ANDROID_NDK_RELEASE_FULL "unreleased" )
+ endif()
+ string( REGEX REPLACE "r([0-9]+)([a-z]?)" "\\1*1000" ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE}" )
+ string( FIND " abcdefghijklmnopqastuvwxyz" "${CMAKE_MATCH_2}" __ndkReleaseLetterNum )
+ math( EXPR ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE_NUM}+${__ndkReleaseLetterNum}" )
+elseif( ANDROID_STANDALONE_TOOLCHAIN )
+ get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE )
+ # try to detect change
+ if( CMAKE_AR )
+  string( LENGTH "${ANDROID_STANDALONE_TOOLCHAIN}" __length )
+  string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidStandaloneToolchainPreviousPath )
+  if( NOT __androidStandaloneToolchainPreviousPath STREQUAL ANDROID_STANDALONE_TOOLCHAIN )
+   message( FATAL_ERROR "It is not possible to change path to the Android standalone toolchain on subsequent run." )
+  endif()
+  unset( __androidStandaloneToolchainPreviousPath )
+  unset( __length )
+ endif()
+ set( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" CACHE INTERNAL "Path of the Android standalone toolchain" FORCE )
+ set( BUILD_WITH_STANDALONE_TOOLCHAIN True )
+else()
+ list(GET ANDROID_NDK_SEARCH_PATHS 0 ANDROID_NDK_SEARCH_PATH)
+ message( FATAL_ERROR "Could not find neither Android NDK nor Android standalone toolchain.
+    You should either set an environment variable:
+      export ANDROID_NDK=~/my-android-ndk
+    or
+      export ANDROID_STANDALONE_TOOLCHAIN=~/my-android-toolchain
+    or put the toolchain or NDK in the default path:
+      sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH}/android-ndk
+      sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" )
+endif()
+
+# android NDK layout
+if( BUILD_WITH_ANDROID_NDK )
+ if( NOT DEFINED ANDROID_NDK_LAYOUT )
+  # try to automatically detect the layout
+  if( EXISTS "${ANDROID_NDK}/RELEASE.TXT")
+   set( ANDROID_NDK_LAYOUT "RELEASE" )
+  elseif( EXISTS "${ANDROID_NDK}/../../linux-x86/toolchain/" )
+   set( ANDROID_NDK_LAYOUT "LINARO" )
+  elseif( EXISTS "${ANDROID_NDK}/../../gcc/" )
+   set( ANDROID_NDK_LAYOUT "ANDROID" )
+  endif()
+ endif()
+ set( ANDROID_NDK_LAYOUT "${ANDROID_NDK_LAYOUT}" CACHE STRING "The inner layout of NDK" )
+ mark_as_advanced( ANDROID_NDK_LAYOUT )
+ if( ANDROID_NDK_LAYOUT STREQUAL "LINARO" )
+  set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment
+  set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../${ANDROID_NDK_HOST_SYSTEM_NAME}/toolchain" )
+  set( ANDROID_NDK_TOOLCHAINS_SUBPATH  "" )
+  set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" )
+ elseif( ANDROID_NDK_LAYOUT STREQUAL "ANDROID" )
+  set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment
+  set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../gcc/${ANDROID_NDK_HOST_SYSTEM_NAME}/arm" )
+  set( ANDROID_NDK_TOOLCHAINS_SUBPATH  "" )
+  set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" )
+ else() # ANDROID_NDK_LAYOUT STREQUAL "RELEASE"
+  set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/toolchains" )
+  set( ANDROID_NDK_TOOLCHAINS_SUBPATH  "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" )
+  set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME2}" )
+ endif()
+ get_filename_component( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK_TOOLCHAINS_PATH}" ABSOLUTE )
+
+ # try to detect change of NDK
+ if( CMAKE_AR )
+  string( LENGTH "${ANDROID_NDK_TOOLCHAINS_PATH}" __length )
+  string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath )
+  if( NOT __androidNdkPreviousPath STREQUAL ANDROID_NDK_TOOLCHAINS_PATH )
+   message( FATAL_ERROR "It is not possible to change the path to the NDK on subsequent CMake run. You must remove all generated files from your build folder first.
+   " )
+  endif()
+  unset( __androidNdkPreviousPath )
+  unset( __length )
+ endif()
+endif()
+
+
+# get all the details about standalone toolchain
+if( BUILD_WITH_STANDALONE_TOOLCHAIN )
+ __DETECT_NATIVE_API_LEVEL( ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" )
+ set( ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
+ set( __availableToolchains "standalone" )
+ __DETECT_TOOLCHAIN_MACHINE_NAME( __availableToolchainMachines "${ANDROID_STANDALONE_TOOLCHAIN}" )
+ if( NOT __availableToolchainMachines )
+  message( FATAL_ERROR "Could not determine machine name of your toolchain. Probably your Android standalone toolchain is broken." )
+ endif()
+ if( __availableToolchainMachines MATCHES x86_64 )
+  set( __availableToolchainArchs "x86_64" )
+ elseif( __availableToolchainMachines MATCHES i686 )
+  set( __availableToolchainArchs "x86" )
+ elseif( __availableToolchainMachines MATCHES aarch64 )
+  set( __availableToolchainArchs "arm64" )
+ elseif( __availableToolchainMachines MATCHES arm )
+  set( __availableToolchainArchs "arm" )
+ elseif( __availableToolchainMachines MATCHES mips64el )
+  set( __availableToolchainArchs "mips64" )
+ elseif( __availableToolchainMachines MATCHES mipsel )
+  set( __availableToolchainArchs "mips" )
+ endif()
+ execute_process( COMMAND "${ANDROID_STANDALONE_TOOLCHAIN}/bin/${__availableToolchainMachines}-gcc${TOOL_OS_SUFFIX}" -dumpversion
+                  OUTPUT_VARIABLE __availableToolchainCompilerVersions OUTPUT_STRIP_TRAILING_WHITESPACE )
+ string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9]+)?" __availableToolchainCompilerVersions "${__availableToolchainCompilerVersions}" )
+ if( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/bin/clang${TOOL_OS_SUFFIX}" )
+  list( APPEND __availableToolchains "standalone-clang" )
+  list( APPEND __availableToolchainMachines ${__availableToolchainMachines} )
+  list( APPEND __availableToolchainArchs ${__availableToolchainArchs} )
+  list( APPEND __availableToolchainCompilerVersions ${__availableToolchainCompilerVersions} )
+ endif()
+endif()
+
+macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath )
+ foreach( __toolchain ${${__availableToolchainsLst}} )
+  if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" )
+   SET( __toolchainVersionRegex "^TOOLCHAIN_VERSION[\t ]+:=[\t ]+(.*)$" )
+   FILE( STRINGS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}/setup.mk" __toolchainVersionStr REGEX "${__toolchainVersionRegex}" )
+   if( __toolchainVersionStr )
+    string( REGEX REPLACE "${__toolchainVersionRegex}" "\\1" __toolchainVersionStr "${__toolchainVersionStr}" )
+    string( REGEX REPLACE "-clang3[.][0-9]$" "-${__toolchainVersionStr}" __gcc_toolchain "${__toolchain}" )
+   else()
+    string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" )
+   endif()
+   unset( __toolchainVersionStr )
+   unset( __toolchainVersionRegex )
+  else()
+   set( __gcc_toolchain "${__toolchain}" )
+  endif()
+  __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK_TOOLCHAINS_PATH}/${__gcc_toolchain}${__toolchain_subpath}" )
+  if( __machine )
+   string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9x]+)?$" __version "${__gcc_toolchain}" )
+   if( __machine MATCHES x86_64 )
+    set( __arch "x86_64" )
+   elseif( __machine MATCHES i686 )
+    set( __arch "x86" )
+   elseif( __machine MATCHES aarch64 )
+    set( __arch "arm64" )
+   elseif( __machine MATCHES arm )
+    set( __arch "arm" )
+   elseif( __machine MATCHES mips64el )
+    set( __arch "mips64" )
+   elseif( __machine MATCHES mipsel )
+    set( __arch "mips" )
+   else()
+    set( __arch "" )
+   endif()
+   #message("machine: !${__machine}!\narch: !${__arch}!\nversion: !${__version}!\ntoolchain: !${__toolchain}!\n")
+   if (__arch)
+    list( APPEND __availableToolchainMachines "${__machine}" )
+    list( APPEND __availableToolchainArchs "${__arch}" )
+    list( APPEND __availableToolchainCompilerVersions "${__version}" )
+    list( APPEND ${__availableToolchainsVar} "${__toolchain}" )
+   endif()
+  endif()
+  unset( __gcc_toolchain )
+ endforeach()
+endmacro()
+
+# get all the details about NDK
+if( BUILD_WITH_ANDROID_NDK )
+ file( GLOB ANDROID_SUPPORTED_NATIVE_API_LEVELS RELATIVE "${ANDROID_NDK}/platforms" "${ANDROID_NDK}/platforms/android-*" )
+ string( REPLACE "android-" "" ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_SUPPORTED_NATIVE_API_LEVELS}" )
+ set( __availableToolchains "" )
+ set( __availableToolchainMachines "" )
+ set( __availableToolchainArchs "" )
+ set( __availableToolchainCompilerVersions "" )
+ if( ANDROID_TOOLCHAIN_NAME AND EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_TOOLCHAIN_NAME}/" )
+  # do not go through all toolchains if we know the name
+  set( __availableToolchainsLst "${ANDROID_TOOLCHAIN_NAME}" )
+  __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
+  if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 )
+   __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" )
+   if( __availableToolchains )
+    set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} )
+   endif()
+  endif()
+ endif()
+ if( NOT __availableToolchains )
+  file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" )
+  if( __availableToolchainsLst )
+   list(SORT __availableToolchainsLst) # we need clang to go after gcc
+  endif()
+  __LIST_FILTER( __availableToolchainsLst "^[.]" )
+  __LIST_FILTER( __availableToolchainsLst "llvm" )
+  __LIST_FILTER( __availableToolchainsLst "renderscript" )
+  __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
+  if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 )
+   __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" )
+   if( __availableToolchains )
+    set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} )
+   endif()
+  endif()
+ endif()
+ if( NOT __availableToolchains )
+  message( FATAL_ERROR "Could not find any working toolchain in the NDK. Probably your Android NDK is broken." )
+ endif()
+endif()
+
+# build list of available ABIs
+set( ANDROID_SUPPORTED_ABIS "" )
+set( __uniqToolchainArchNames ${__availableToolchainArchs} )
+list( REMOVE_DUPLICATES __uniqToolchainArchNames )
+list( SORT __uniqToolchainArchNames )
+foreach( __arch ${__uniqToolchainArchNames} )
+ list( APPEND ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${__arch}} )
+endforeach()
+unset( __uniqToolchainArchNames )
+if( NOT ANDROID_SUPPORTED_ABIS )
+ message( FATAL_ERROR "No one of known Android ABIs is supported by this cmake toolchain." )
+endif()
+
+# choose target ABI
+__INIT_VARIABLE( ANDROID_ABI VALUES ${ANDROID_SUPPORTED_ABIS} )
+# verify that target ABI is supported
+list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx )
+if( __androidAbiIdx EQUAL -1 )
+ string( REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ABIS  "${ANDROID_SUPPORTED_ABIS}" )
+ message( FATAL_ERROR "Specified ANDROID_ABI = \"${ANDROID_ABI}\" is not supported by this cmake toolchain or your NDK/toolchain.
+   Supported values are: \"${PRINTABLE_ANDROID_SUPPORTED_ABIS}\"
+   " )
+endif()
+unset( __androidAbiIdx )
+
+# set target ABI options
+if( ANDROID_ABI STREQUAL "x86" )
+ set( X86 true )
+ set( ANDROID_NDK_ABI_NAME "x86" )
+ set( ANDROID_ARCH_NAME "x86" )
+ set( ANDROID_LLVM_TRIPLE "i686-none-linux-android" )
+ set( CMAKE_SYSTEM_PROCESSOR "i686" )
+elseif( ANDROID_ABI STREQUAL "x86_64" )
+ set( X86 true )
+ set( X86_64 true )
+ set( ANDROID_NDK_ABI_NAME "x86_64" )
+ set( ANDROID_ARCH_NAME "x86_64" )
+ set( CMAKE_SYSTEM_PROCESSOR "x86_64" )
+ set( ANDROID_LLVM_TRIPLE "x86_64-none-linux-android" )
+elseif( ANDROID_ABI STREQUAL "mips64" )
+ set( MIPS64 true )
+ set( ANDROID_NDK_ABI_NAME "mips64" )
+ set( ANDROID_ARCH_NAME "mips64" )
+ set( ANDROID_LLVM_TRIPLE "mips64el-none-linux-android" )
+ set( CMAKE_SYSTEM_PROCESSOR "mips64" )
+elseif( ANDROID_ABI STREQUAL "mips" )
+ set( MIPS true )
+ set( ANDROID_NDK_ABI_NAME "mips" )
+ set( ANDROID_ARCH_NAME "mips" )
+ set( ANDROID_LLVM_TRIPLE "mipsel-none-linux-android" )
+ set( CMAKE_SYSTEM_PROCESSOR "mips" )
+elseif( ANDROID_ABI STREQUAL "arm64-v8a" )
+ set( ARM64_V8A true )
+ set( ANDROID_NDK_ABI_NAME "arm64-v8a" )
+ set( ANDROID_ARCH_NAME "arm64" )
+ set( ANDROID_LLVM_TRIPLE "aarch64-none-linux-android" )
+ set( CMAKE_SYSTEM_PROCESSOR "aarch64" )
+ set( VFPV3 true )
+ set( NEON true )
+elseif( ANDROID_ABI STREQUAL "armeabi" )
+ set( ARMEABI true )
+ set( ANDROID_NDK_ABI_NAME "armeabi" )
+ set( ANDROID_ARCH_NAME "arm" )
+ set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" )
+ set( CMAKE_SYSTEM_PROCESSOR "armv5te" )
+elseif( ANDROID_ABI STREQUAL "armeabi-v6 with VFP" )
+ set( ARMEABI_V6 true )
+ set( ANDROID_NDK_ABI_NAME "armeabi" )
+ set( ANDROID_ARCH_NAME "arm" )
+ set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" )
+ set( CMAKE_SYSTEM_PROCESSOR "armv6" )
+ # need always fallback to older platform
+ set( ARMEABI true )
+elseif( ANDROID_ABI STREQUAL "armeabi-v7a")
+ set( ARMEABI_V7A true )
+ set( ANDROID_NDK_ABI_NAME "armeabi-v7a" )
+ set( ANDROID_ARCH_NAME "arm" )
+ set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" )
+ set( CMAKE_SYSTEM_PROCESSOR "armv7-a" )
+elseif( ANDROID_ABI STREQUAL "armeabi-v7a with VFPV3" )
+ set( ARMEABI_V7A true )
+ set( ANDROID_NDK_ABI_NAME "armeabi-v7a" )
+ set( ANDROID_ARCH_NAME "arm" )
+ set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" )
+ set( CMAKE_SYSTEM_PROCESSOR "armv7-a" )
+ set( VFPV3 true )
+elseif( ANDROID_ABI STREQUAL "armeabi-v7a with NEON" )
+ set( ARMEABI_V7A true )
+ set( ANDROID_NDK_ABI_NAME "armeabi-v7a" )
+ set( ANDROID_ARCH_NAME "arm" )
+ set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" )
+ set( CMAKE_SYSTEM_PROCESSOR "armv7-a" )
+ set( VFPV3 true )
+ set( NEON true )
+else()
+ message( SEND_ERROR "Unknown ANDROID_ABI=\"${ANDROID_ABI}\" is specified." )
+endif()
+
+if( CMAKE_BINARY_DIR AND EXISTS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" )
+ # really dirty hack
+ # it is not possible to change CMAKE_SYSTEM_PROCESSOR after the first run...
+ file( APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" "SET(CMAKE_SYSTEM_PROCESSOR \"${CMAKE_SYSTEM_PROCESSOR}\")\n" )
+endif()
+
+if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 )
+ __INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD VALUES OFF )
+ set( ANDROID_FORCE_ARM_BUILD ${ANDROID_FORCE_ARM_BUILD} CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1" FORCE )
+ mark_as_advanced( ANDROID_FORCE_ARM_BUILD )
+else()
+ unset( ANDROID_FORCE_ARM_BUILD CACHE )
+endif()
+
+# choose toolchain
+if( ANDROID_TOOLCHAIN_NAME )
+ list( FIND __availableToolchains "${ANDROID_TOOLCHAIN_NAME}" __toolchainIdx )
+ if( __toolchainIdx EQUAL -1 )
+  list( SORT __availableToolchains )
+  string( REPLACE ";" "\n  * " toolchains_list "${__availableToolchains}" )
+  set( toolchains_list "  * ${toolchains_list}")
+  message( FATAL_ERROR "Specified toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is missing in your NDK or broken. Please verify that your NDK is working or select another compiler toolchain.
+To configure the toolchain set CMake variable ANDROID_TOOLCHAIN_NAME to one of the following values:\n${toolchains_list}\n" )
+ endif()
+ list( GET __availableToolchainArchs ${__toolchainIdx} __toolchainArch )
+ if( NOT __toolchainArch STREQUAL ANDROID_ARCH_NAME )
+  message( SEND_ERROR "Selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is not able to compile binaries for the \"${ANDROID_ARCH_NAME}\" platform." )
+ endif()
+else()
+ set( __toolchainIdx -1 )
+ set( __applicableToolchains "" )
+ set( __toolchainMaxVersion "0.0.0" )
+ list( LENGTH __availableToolchains __availableToolchainsCount )
+ math( EXPR __availableToolchainsCount "${__availableToolchainsCount}-1" )
+ foreach( __idx RANGE ${__availableToolchainsCount} )
+  list( GET __availableToolchainArchs ${__idx} __toolchainArch )
+  if( __toolchainArch STREQUAL ANDROID_ARCH_NAME )
+   list( GET __availableToolchainCompilerVersions ${__idx} __toolchainVersion )
+   string( REPLACE "x" "99" __toolchainVersion "${__toolchainVersion}")
+   if( __toolchainVersion VERSION_GREATER __toolchainMaxVersion )
+    set( __toolchainMaxVersion "${__toolchainVersion}" )
+    set( __toolchainIdx ${__idx} )
+   endif()
+  endif()
+ endforeach()
+ unset( __availableToolchainsCount )
+ unset( __toolchainMaxVersion )
+ unset( __toolchainVersion )
+endif()
+unset( __toolchainArch )
+if( __toolchainIdx EQUAL -1 )
+ message( FATAL_ERROR "No one of available compiler toolchains is able to compile for ${ANDROID_ARCH_NAME} platform." )
+endif()
+list( GET __availableToolchains ${__toolchainIdx} ANDROID_TOOLCHAIN_NAME )
+list( GET __availableToolchainMachines ${__toolchainIdx} ANDROID_TOOLCHAIN_MACHINE_NAME )
+list( GET __availableToolchainCompilerVersions ${__toolchainIdx} ANDROID_COMPILER_VERSION )
+
+unset( __toolchainIdx )
+unset( __availableToolchains )
+unset( __availableToolchainMachines )
+unset( __availableToolchainArchs )
+unset( __availableToolchainCompilerVersions )
+
+# choose native API level
+__INIT_VARIABLE( ANDROID_NATIVE_API_LEVEL ENV_ANDROID_NATIVE_API_LEVEL ANDROID_API_LEVEL ENV_ANDROID_API_LEVEL ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL )
+string( REPLACE "android-" "" ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" )
+string( STRIP "${ANDROID_NATIVE_API_LEVEL}" ANDROID_NATIVE_API_LEVEL )
+# adjust API level
+set( __real_api_level ${ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME}} )
+foreach( __level ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
+ if( (__level LESS ANDROID_NATIVE_API_LEVEL OR __level STREQUAL ANDROID_NATIVE_API_LEVEL) AND NOT __level LESS __real_api_level )
+  set( __real_api_level ${__level} )
+ endif()
+endforeach()
+if( __real_api_level AND NOT ANDROID_NATIVE_API_LEVEL STREQUAL __real_api_level )
+ message( STATUS "Adjusting Android API level 'android-${ANDROID_NATIVE_API_LEVEL}' to 'android-${__real_api_level}'")
+ set( ANDROID_NATIVE_API_LEVEL ${__real_api_level} )
+endif()
+unset(__real_api_level)
+# validate
+list( FIND ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_NATIVE_API_LEVEL}" __levelIdx )
+if( __levelIdx EQUAL -1 )
+ message( SEND_ERROR "Specified Android native API level 'android-${ANDROID_NATIVE_API_LEVEL}' is not supported by your NDK/toolchain." )
+else()
+ if( BUILD_WITH_ANDROID_NDK )
+  __DETECT_NATIVE_API_LEVEL( __realApiLevel "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}/usr/include/android/api-level.h" )
+  if( NOT __realApiLevel EQUAL ANDROID_NATIVE_API_LEVEL AND NOT __realApiLevel GREATER 9000 )
+   message( SEND_ERROR "Specified Android API level (${ANDROID_NATIVE_API_LEVEL}) does not match to the level found (${__realApiLevel}). Probably your copy of NDK is broken." )
+  endif()
+  unset( __realApiLevel )
+ endif()
+ set( ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android API level for native code" FORCE )
+ set( CMAKE_ANDROID_API ${ANDROID_NATIVE_API_LEVEL} )
+ if( CMAKE_VERSION VERSION_GREATER "2.8" )
+  list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS )
+  set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
+ endif()
+endif()
+unset( __levelIdx )
+
+
+# remember target ABI
+set( ANDROID_ABI "${ANDROID_ABI}" CACHE STRING "The target ABI for Android. If arm, then armeabi-v7a is recommended for hardware floating point." FORCE )
+if( CMAKE_VERSION VERSION_GREATER "2.8" )
+ list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME} )
+ set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME}} )
+endif()
+
+
+# runtime choice (STL, rtti, exceptions)
+if( NOT ANDROID_STL )
+  set( ANDROID_STL gnustl_static )
+endif()
+set( ANDROID_STL "${ANDROID_STL}" CACHE STRING "C++ runtime" )
+set( ANDROID_STL_FORCE_FEATURES ON CACHE BOOL "automatically configure rtti and exceptions support based on C++ runtime" )
+mark_as_advanced( ANDROID_STL ANDROID_STL_FORCE_FEATURES )
+
+if( BUILD_WITH_ANDROID_NDK )
+ if( NOT "${ANDROID_STL}" MATCHES "^(none|system|system_re|gabi\\+\\+_static|gabi\\+\\+_shared|stlport_static|stlport_shared|gnustl_static|gnustl_shared|c\\+\\+_shared)$")
+  message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\".
+The possible values are:
+  none           -> Do not configure the runtime.
+  system         -> Use the default minimal system C++ runtime library.
+  system_re      -> Same as system but with rtti and exceptions.
+  gabi++_static  -> Use the GAbi++ runtime as a static library.
+  gabi++_shared  -> Use the GAbi++ runtime as a shared library.
+  stlport_static -> Use the STLport runtime as a static library.
+  stlport_shared -> Use the STLport runtime as a shared library.
+  gnustl_static  -> (default) Use the GNU STL as a static library.
+  gnustl_shared  -> Use the GNU STL as a shared library.
+  c++_shared     -> Use the LLVM libc++ as a shared library.
+" )
+ endif()
+elseif( BUILD_WITH_STANDALONE_TOOLCHAIN )
+ if( NOT "${ANDROID_STL}" MATCHES "^(none|gnustl_static|gnustl_shared)$")
+  message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\".
+The possible values are:
+  none           -> Do not configure the runtime.
+  gnustl_static  -> (default) Use the GNU STL as a static library.
+  gnustl_shared  -> Use the GNU STL as a shared library.
+" )
+ endif()
+endif()
+
+unset( ANDROID_RTTI )
+unset( ANDROID_EXCEPTIONS )
+unset( ANDROID_STL_INCLUDE_DIRS )
+unset( __libstl )
+unset( __libsupcxx )
+
+if( NOT _CMAKE_IN_TRY_COMPILE AND ANDROID_NDK_RELEASE STREQUAL "r7b" AND ARMEABI_V7A AND NOT VFPV3 AND ANDROID_STL MATCHES "gnustl" )
+ message( WARNING  "The GNU STL armeabi-v7a binaries from NDK r7b can crash non-NEON devices. The files provided with NDK r7b were not configured properly, resulting in crashes on Tegra2-based devices and others when trying to use certain floating-point functions (e.g., cosf, sinf, expf).
+You are strongly recommended to switch to another NDK release.
+" )
+endif()
+
+if( NOT _CMAKE_IN_TRY_COMPILE AND X86 AND ANDROID_STL MATCHES "gnustl" AND ANDROID_NDK_RELEASE STREQUAL "r6" )
+  message( WARNING  "The x86 system header file from NDK r6 has incorrect definition for ptrdiff_t. You are recommended to upgrade to a newer NDK release or manually patch the header:
+See https://android.googlesource.com/platform/development.git f907f4f9d4e56ccc8093df6fee54454b8bcab6c2
+  diff --git a/ndk/platforms/android-9/arch-x86/include/machine/_types.h b/ndk/platforms/android-9/arch-x86/include/machine/_types.h
+  index 5e28c64..65892a1 100644
+  --- a/ndk/platforms/android-9/arch-x86/include/machine/_types.h
+  +++ b/ndk/platforms/android-9/arch-x86/include/machine/_types.h
+  @@ -51,7 +51,11 @@ typedef long int       ssize_t;
+   #endif
+   #ifndef _PTRDIFF_T
+   #define _PTRDIFF_T
+  -typedef long           ptrdiff_t;
+  +#  ifdef __ANDROID__
+  +     typedef int            ptrdiff_t;
+  +#  else
+  +     typedef long           ptrdiff_t;
+  +#  endif
+   #endif
+" )
+endif()
+
+# setup paths and STL for standalone toolchain
+if( BUILD_WITH_STANDALONE_TOOLCHAIN )
+ set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" )
+ set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" )
+ set( ANDROID_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot" )
+
+ if( NOT ANDROID_STL STREQUAL "none" )
+  set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/include/c++/${ANDROID_COMPILER_VERSION}" )
+  if( NOT EXISTS "${ANDROID_STL_INCLUDE_DIRS}" )
+   # old location ( pre r8c )
+   set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}" )
+  endif()
+  if( ARMEABI_V7A AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/bits" )
+   list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}" )
+  elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb/bits" )
+   list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb" )
+  else()
+   list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" )
+  endif()
+  # always search static GNU STL to get the location of libsupc++.a
+  if( ARMEABI_V7A AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" )
+   set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb" )
+  elseif( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" )
+   set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}" )
+  elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libstdc++.a" )
+   set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb" )
+  elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libstdc++.a" )
+   set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib" )
+  endif()
+  if( __libstl )
+   set( __libsupcxx "${__libstl}/libsupc++.a" )
+   set( __libstl    "${__libstl}/libstdc++.a" )
+  endif()
+  if( NOT EXISTS "${__libsupcxx}" )
+   message( FATAL_ERROR "The required libstdsupc++.a is missing in your standalone toolchain.
+ Usually it happens because of bug in make-standalone-toolchain.sh script from NDK r7, r7b and r7c.
+ You need to either upgrade to newer NDK or manually copy
+     $ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a
+ to
+     ${__libsupcxx}
+   " )
+  endif()
+  if( ANDROID_STL STREQUAL "gnustl_shared" )
+   if( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" )
+    set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" )
+   elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" )
+    set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" )
+   elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" )
+    set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" )
+   endif()
+  endif()
+ endif()
+endif()
+
+# clang
+if( "${ANDROID_TOOLCHAIN_NAME}" STREQUAL "standalone-clang" )
+ set( ANDROID_COMPILER_IS_CLANG 1 )
+ execute_process( COMMAND "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/clang${TOOL_OS_SUFFIX}" --version OUTPUT_VARIABLE ANDROID_CLANG_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE )
+ string( REGEX MATCH "[0-9]+[.][0-9]+" ANDROID_CLANG_VERSION "${ANDROID_CLANG_VERSION}")
+elseif( "${ANDROID_TOOLCHAIN_NAME}" MATCHES "-clang3[.][0-9]?$" )
+ string( REGEX MATCH "3[.][0-9]$" ANDROID_CLANG_VERSION "${ANDROID_TOOLCHAIN_NAME}")
+ string( REGEX REPLACE "-clang${ANDROID_CLANG_VERSION}$" "-${ANDROID_COMPILER_VERSION}" ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" )
+ if( NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}/bin/clang${TOOL_OS_SUFFIX}" )
+  message( FATAL_ERROR "Could not find the Clang compiler driver" )
+ endif()
+ set( ANDROID_COMPILER_IS_CLANG 1 )
+ set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
+else()
+ set( ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" )
+ unset( ANDROID_COMPILER_IS_CLANG CACHE )
+endif()
+
+string( REPLACE "." "" _clang_name "clang${ANDROID_CLANG_VERSION}" )
+if( NOT EXISTS "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" )
+ set( _clang_name "clang" )
+endif()
+
+
+# setup paths and STL for NDK
+if( BUILD_WITH_ANDROID_NDK )
+ set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
+ set( ANDROID_SYSROOT "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}" )
+
+ if( ANDROID_STL STREQUAL "none" )
+  # do nothing
+ elseif( ANDROID_STL STREQUAL "system" )
+  set( ANDROID_RTTI             OFF )
+  set( ANDROID_EXCEPTIONS       OFF )
+  set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" )
+ elseif( ANDROID_STL STREQUAL "system_re" )
+  set( ANDROID_RTTI             ON )
+  set( ANDROID_EXCEPTIONS       ON )
+  set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" )
+ elseif( ANDROID_STL MATCHES "gabi" )
+  if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7
+   message( FATAL_ERROR "gabi++ is not available in your NDK. You have to upgrade to NDK r7 or newer to use gabi++.")
+  endif()
+  set( ANDROID_RTTI             ON )
+  set( ANDROID_EXCEPTIONS       OFF )
+  set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/gabi++/include" )
+  set( __libstl                 "${ANDROID_NDK}/sources/cxx-stl/gabi++/libs/${ANDROID_NDK_ABI_NAME}/libgabi++_static.a" )
+ elseif( ANDROID_STL MATCHES "stlport" )
+  if( NOT ANDROID_NDK_RELEASE_NUM LESS 8004 ) # before r8d
+   set( ANDROID_EXCEPTIONS       ON )
+  else()
+   set( ANDROID_EXCEPTIONS       OFF )
+  endif()
+  if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7
+   set( ANDROID_RTTI            OFF )
+  else()
+   set( ANDROID_RTTI            ON )
+  endif()
+  set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/stlport/stlport" )
+  set( __libstl                 "${ANDROID_NDK}/sources/cxx-stl/stlport/libs/${ANDROID_NDK_ABI_NAME}/libstlport_static.a" )
+ elseif( ANDROID_STL MATCHES "gnustl" )
+  set( ANDROID_EXCEPTIONS       ON )
+  set( ANDROID_RTTI             ON )
+  if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" )
+   if( ARMEABI_V7A AND ANDROID_COMPILER_VERSION VERSION_EQUAL "4.7" AND ANDROID_NDK_RELEASE STREQUAL "r8d" )
+    # gnustl binary for 4.7 compiler is buggy :(
+    # TODO: look for right fix
+    set( __libstl                "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.6" )
+   else()
+    set( __libstl                "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" )
+   endif()
+  else()
+   set( __libstl                "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++" )
+  endif()
+  set( ANDROID_STL_INCLUDE_DIRS "${__libstl}/include" "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/include" "${__libstl}/include/backward" )
+  if( EXISTS "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" )
+   set( __libstl                "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" )
+  else()
+   set( __libstl                "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" )
+  endif()
+ elseif( ANDROID_STL MATCHES "c\\+\\+_shared" )
+    set( ANDROID_EXCEPTIONS       ON )
+    set( ANDROID_RTTI             ON )
+    set( ANDROID_CXX_ROOT     "${ANDROID_NDK}/sources/cxx-stl/" )
+    set( ANDROID_LLVM_ROOT    "${ANDROID_CXX_ROOT}/llvm-libc++" )
+    if( X86 ) 
+        set( ANDROID_ABI_INCLUDE_DIRS "${ANDROID_CXX_ROOT}/gabi++/include" )
+    else()
+        set( ANDROID_ABI_INCLUDE_DIRS "${ANDROID_CXX_ROOT}/llvm-libc++abi/libcxxabi/include" )
+    endif()
+    set( ANDROID_STL_INCLUDE_DIRS     "${ANDROID_NDK}/sources" "${ANDROID_LLVM_ROOT}/libcxx/include" "${ANDROID_ABI_INCLUDE_DIRS}" )
+    # android support files
+    include_directories ( SYSTEM ${ANDROID_NDK}/sources/android/support/include )
+    if( EXISTS "${ANDROID_LLVM_ROOT}/libs/${ANDROID_NDK_ABI_NAME}/libc++_shared.so" )
+        set( __libstl                           "${ANDROID_LLVM_ROOT}/libs/${ANDROID_NDK_ABI_NAME}/libc++_shared.so" )
+    else()
+        message( "c++ shared library doesn't exist" )
+    endif()
+ else()
+  message( FATAL_ERROR "Unknown runtime: ${ANDROID_STL}" )
+ endif()
+ # find libsupc++.a - rtti & exceptions
+ if( ANDROID_STL STREQUAL "system_re" OR ANDROID_STL MATCHES "gnustl" )
+  set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r8b or newer
+  if( NOT EXISTS "${__libsupcxx}" )
+   set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r7-r8
+  endif()
+  if( NOT EXISTS "${__libsupcxx}" ) # before r7
+   if( ARMEABI_V7A )
+    if( ANDROID_FORCE_ARM_BUILD )
+     set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" )
+    else()
+     set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" )
+    endif()
+   elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD )
+    set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" )
+   else()
+    set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" )
+   endif()
+  endif()
+  if( NOT EXISTS "${__libsupcxx}")
+   message( ERROR "Could not find libsupc++.a for a chosen platform. Either your NDK is not supported or is broken.")
+  endif()
+ endif()
+endif()
+
+
+# case of shared STL linkage
+if( ANDROID_STL MATCHES "shared" AND DEFINED __libstl )
+ string( REPLACE "_static.a" "_shared.so" __libstl "${__libstl}" )
+ # TODO: check if .so file exists before the renaming
+endif()
+
+
+# ccache support
+__INIT_VARIABLE( _ndk_ccache NDK_CCACHE ENV_NDK_CCACHE )
+if( _ndk_ccache )
+ if( DEFINED NDK_CCACHE AND NOT EXISTS NDK_CCACHE )
+  unset( NDK_CCACHE CACHE )
+ endif()
+ find_program( NDK_CCACHE "${_ndk_ccache}" DOC "The path to ccache binary")
+else()
+ unset( NDK_CCACHE CACHE )
+endif()
+unset( _ndk_ccache )
+
+
+# setup the cross-compiler
+if( NOT CMAKE_C_COMPILER )
+ if( NDK_CCACHE AND NOT ANDROID_SYSROOT MATCHES "[ ;\"]" )
+  set( CMAKE_C_COMPILER   "${NDK_CCACHE}" CACHE PATH "ccache as C compiler" )
+  set( CMAKE_CXX_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C++ compiler" )
+  if( ANDROID_COMPILER_IS_CLANG )
+   set( CMAKE_C_COMPILER_ARG1   "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}"   CACHE PATH "C compiler")
+   set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
+  else()
+   set( CMAKE_C_COMPILER_ARG1   "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler")
+   set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
+  endif()
+ else()
+  if( ANDROID_COMPILER_IS_CLANG )
+   set( CMAKE_C_COMPILER   "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}"   CACHE PATH "C compiler")
+   set( CMAKE_CXX_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
+  else()
+   set( CMAKE_C_COMPILER   "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}"    CACHE PATH "C compiler" )
+   set( CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}"    CACHE PATH "C++ compiler" )
+  endif()
+ endif()
+ set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}"     CACHE PATH "assembler" )
+ set( CMAKE_STRIP        "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}"   CACHE PATH "strip" )
+ if( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" )
+  # Use gcc-ar if we have it for better LTO support.
+  set( CMAKE_AR           "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}"      CACHE PATH "archive" )
+ else()
+  set( CMAKE_AR           "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}"      CACHE PATH "archive" )
+ endif()
+ set( CMAKE_LINKER       "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_OS_SUFFIX}"      CACHE PATH "linker" )
+ set( CMAKE_NM           "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_OS_SUFFIX}"      CACHE PATH "nm" )
+ set( CMAKE_OBJCOPY      "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" )
+ set( CMAKE_OBJDUMP      "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" )
+ set( CMAKE_RANLIB       "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ranlib${TOOL_OS_SUFFIX}"  CACHE PATH "ranlib" )
+endif()
+
+set( _CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_MACHINE_NAME}-" )
+if( CMAKE_VERSION VERSION_LESS 2.8.5 )
+ set( CMAKE_ASM_COMPILER_ARG1 "-c" )
+endif()
+if( APPLE )
+ find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool )
+ if( NOT CMAKE_INSTALL_NAME_TOOL )
+  message( FATAL_ERROR "Could not find install_name_tool, please check your installation." )
+ endif()
+ mark_as_advanced( CMAKE_INSTALL_NAME_TOOL )
+endif()
+
+# Force set compilers because standard identification works badly for us
+include( CMakeForceCompiler )
+CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU )
+if( ANDROID_COMPILER_IS_CLANG )
+ set( CMAKE_C_COMPILER_ID Clang )
+endif()
+set( CMAKE_C_PLATFORM_ID Linux )
+if( X86_64 OR MIPS64 OR ARM64_V8A )
+ set( CMAKE_C_SIZEOF_DATA_PTR 8 )
+else()
+ set( CMAKE_C_SIZEOF_DATA_PTR 4 )
+endif()
+set( CMAKE_C_HAS_ISYSROOT 1 )
+set( CMAKE_C_COMPILER_ABI ELF )
+CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU )
+if( ANDROID_COMPILER_IS_CLANG )
+ set( CMAKE_CXX_COMPILER_ID Clang)
+endif()
+set( CMAKE_CXX_PLATFORM_ID Linux )
+set( CMAKE_CXX_SIZEOF_DATA_PTR ${CMAKE_C_SIZEOF_DATA_PTR} )
+set( CMAKE_CXX_HAS_ISYSROOT 1 )
+set( CMAKE_CXX_COMPILER_ABI ELF )
+set( CMAKE_CXX_SOURCE_FILE_EXTENSIONS cc cp cxx cpp CPP c++ C )
+# force ASM compiler (required for CMake < 2.8.5)
+set( CMAKE_ASM_COMPILER_ID_RUN TRUE )
+set( CMAKE_ASM_COMPILER_ID GNU )
+set( CMAKE_ASM_COMPILER_WORKS TRUE )
+set( CMAKE_ASM_COMPILER_FORCED TRUE )
+set( CMAKE_COMPILER_IS_GNUASM 1)
+set( CMAKE_ASM_SOURCE_FILE_EXTENSIONS s S asm )
+
+foreach( lang C CXX ASM )
+ if( ANDROID_COMPILER_IS_CLANG )
+  set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_CLANG_VERSION} )
+ else()
+  set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_COMPILER_VERSION} )
+ endif()
+endforeach()
+
+# flags and definitions
+remove_definitions( -DANDROID )
+add_definitions( -DANDROID )
+
+if( ANDROID_SYSROOT MATCHES "[ ;\"]" )
+ if( CMAKE_HOST_WIN32 )
+  # try to convert path to 8.3 form
+  file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "@echo %~s1" )
+  execute_process( COMMAND "$ENV{ComSpec}" /c "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "${ANDROID_SYSROOT}"
+                   OUTPUT_VARIABLE __path OUTPUT_STRIP_TRAILING_WHITESPACE
+                   RESULT_VARIABLE __result ERROR_QUIET )
+  if( __result EQUAL 0 )
+   file( TO_CMAKE_PATH "${__path}" ANDROID_SYSROOT )
+   set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" )
+  else()
+   set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" )
+  endif()
+ else()
+  set( ANDROID_CXX_FLAGS "'--sysroot=${ANDROID_SYSROOT}'" )
+ endif()
+ if( NOT _CMAKE_IN_TRY_COMPILE )
+  # quotes can break try_compile and compiler identification
+  message(WARNING "Path to your Android NDK (or toolchain) has non-alphanumeric symbols.\nThe build might be broken.\n")
+ endif()
+else()
+ set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" )
+endif()
+
+# NDK flags
+if (ARM64_V8A )
+ set( ANDROID_CXX_FLAGS         "${ANDROID_CXX_FLAGS} -funwind-tables" )
+ set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" )
+ set( ANDROID_CXX_FLAGS_DEBUG   "-fno-omit-frame-pointer -fno-strict-aliasing" )
+ if( NOT ANDROID_COMPILER_IS_CLANG )
+  set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" )
+ endif()
+elseif( ARMEABI OR ARMEABI_V7A)
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" )
+ if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 )
+  set( ANDROID_CXX_FLAGS_RELEASE "-mthumb -fomit-frame-pointer -fno-strict-aliasing" )
+  set( ANDROID_CXX_FLAGS_DEBUG   "-marm -fno-omit-frame-pointer -fno-strict-aliasing" )
+  if( NOT ANDROID_COMPILER_IS_CLANG )
+   set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -finline-limit=64" )
+  endif()
+ else()
+  # always compile ARMEABI_V6 in arm mode; otherwise there is no difference from ARMEABI
+  set( ANDROID_CXX_FLAGS_RELEASE "-marm -fomit-frame-pointer -fstrict-aliasing" )
+  set( ANDROID_CXX_FLAGS_DEBUG   "-marm -fno-omit-frame-pointer -fno-strict-aliasing" )
+  if( NOT ANDROID_COMPILER_IS_CLANG )
+   set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" )
+  endif()
+ endif()
+elseif( X86 OR X86_64 )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" )
+ if( NOT ANDROID_COMPILER_IS_CLANG )
+  set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" )
+ endif()
+ set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" )
+ set( ANDROID_CXX_FLAGS_DEBUG   "-fno-omit-frame-pointer -fno-strict-aliasing" )
+elseif( MIPS OR MIPS64 )
+ set( ANDROID_CXX_FLAGS         "${ANDROID_CXX_FLAGS} -fno-strict-aliasing -finline-functions -funwind-tables -fmessage-length=0" )
+ set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer" )
+ set( ANDROID_CXX_FLAGS_DEBUG   "-fno-omit-frame-pointer" )
+ if( NOT ANDROID_COMPILER_IS_CLANG )
+  set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" )
+  set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" )
+ endif()
+elseif()
+ set( ANDROID_CXX_FLAGS_RELEASE "" )
+ set( ANDROID_CXX_FLAGS_DEBUG   "" )
+endif()
+
+set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) # good/necessary when porting desktop libraries
+
+if( NOT X86 AND NOT ANDROID_COMPILER_IS_CLANG )
+ set( ANDROID_CXX_FLAGS "-Wno-psabi ${ANDROID_CXX_FLAGS}" )
+endif()
+
+if( NOT ANDROID_COMPILER_VERSION VERSION_LESS "4.6" )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -no-canonical-prefixes" ) # see https://android-review.googlesource.com/#/c/47564/
+endif()
+
+# ABI-specific flags
+if( ARMEABI_V7A )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mfloat-abi=softfp" )
+ if( NEON )
+  set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=neon" )
+ elseif( VFPV3 )
+  set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3" )
+ else()
+  set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" )
+ endif()
+elseif( ARMEABI_V6 )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv6 -mfloat-abi=softfp -mfpu=vfp" ) # vfp == vfpv2
+elseif( ARMEABI )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv5te -mtune=xscale -msoft-float" )
+endif()
+
+if( ANDROID_STL MATCHES "gnustl" AND (EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}") )
+ set( CMAKE_CXX_CREATE_SHARED_LIBRARY "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+ set( CMAKE_CXX_CREATE_SHARED_MODULE  "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+ set( CMAKE_CXX_LINK_EXECUTABLE       "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" )
+else()
+ set( CMAKE_CXX_CREATE_SHARED_LIBRARY "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+ set( CMAKE_CXX_CREATE_SHARED_MODULE  "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+ set( CMAKE_CXX_LINK_EXECUTABLE       "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" )
+endif()
+
+# STL
+if( EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}" )
+ if( EXISTS "${__libstl}" )
+  set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libstl}\"" )
+  set( CMAKE_CXX_CREATE_SHARED_MODULE  "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libstl}\"" )
+  set( CMAKE_CXX_LINK_EXECUTABLE       "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libstl}\"" )
+ endif()
+ if( EXISTS "${__libsupcxx}" )
+  set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" )
+  set( CMAKE_CXX_CREATE_SHARED_MODULE  "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" )
+  set( CMAKE_CXX_LINK_EXECUTABLE       "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libsupcxx}\"" )
+  # C objects:
+  set( CMAKE_C_CREATE_SHARED_LIBRARY "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_C_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+  set( CMAKE_C_CREATE_SHARED_MODULE  "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_C_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+  set( CMAKE_C_LINK_EXECUTABLE       "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" )
+  set( CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" )
+  set( CMAKE_C_CREATE_SHARED_MODULE  "${CMAKE_C_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" )
+  set( CMAKE_C_LINK_EXECUTABLE       "${CMAKE_C_LINK_EXECUTABLE} \"${__libsupcxx}\"" )
+ endif()
+ if( ANDROID_STL MATCHES "gnustl" )
+  if( NOT EXISTS "${ANDROID_LIBM_PATH}" )
+   set( ANDROID_LIBM_PATH -lm )
+  endif()
+  set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} ${ANDROID_LIBM_PATH}" )
+  set( CMAKE_CXX_CREATE_SHARED_MODULE  "${CMAKE_CXX_CREATE_SHARED_MODULE} ${ANDROID_LIBM_PATH}" )
+  set( CMAKE_CXX_LINK_EXECUTABLE       "${CMAKE_CXX_LINK_EXECUTABLE} ${ANDROID_LIBM_PATH}" )
+ endif()
+endif()
+
+# variables controlling optional build flags
+if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7
+ # libGLESv2.so in NDK's prior to r7 refers to missing external symbols.
+ # So this flag option is required for all projects using OpenGL from native.
+ __INIT_VARIABLE( ANDROID_SO_UNDEFINED                      VALUES ON )
+else()
+ __INIT_VARIABLE( ANDROID_SO_UNDEFINED                      VALUES OFF )
+endif()
+__INIT_VARIABLE( ANDROID_NO_UNDEFINED                       VALUES ON )
+__INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING             VALUES ON )
+__INIT_VARIABLE( ANDROID_GOLD_LINKER                        VALUES ON )
+__INIT_VARIABLE( ANDROID_NOEXECSTACK                        VALUES ON )
+__INIT_VARIABLE( ANDROID_RELRO                              VALUES ON )
+
+set( ANDROID_NO_UNDEFINED           ${ANDROID_NO_UNDEFINED}           CACHE BOOL "Show all undefined symbols as linker errors" )
+set( ANDROID_SO_UNDEFINED           ${ANDROID_SO_UNDEFINED}           CACHE BOOL "Allows or disallows undefined symbols in shared libraries" )
+set( ANDROID_FUNCTION_LEVEL_LINKING ${ANDROID_FUNCTION_LEVEL_LINKING} CACHE BOOL "Put each function in separate section and enable garbage collection of unused input sections at link time" )
+set( ANDROID_GOLD_LINKER            ${ANDROID_GOLD_LINKER}            CACHE BOOL "Enables gold linker" )
+set( ANDROID_NOEXECSTACK            ${ANDROID_NOEXECSTACK}            CACHE BOOL "Allows or disallows undefined symbols in shared libraries" )
+set( ANDROID_RELRO                  ${ANDROID_RELRO}                  CACHE BOOL "Enables RELRO - a memory corruption mitigation technique" )
+mark_as_advanced( ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_FUNCTION_LEVEL_LINKING ANDROID_GOLD_LINKER ANDROID_NOEXECSTACK ANDROID_RELRO )
+
+# linker flags
+set( ANDROID_LINKER_FLAGS "" )
+
+if( ARMEABI_V7A )
+ # this is *required* to use the following linker flags that routes around
+ # a CPU bug in some Cortex-A8 implementations:
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--fix-cortex-a8" )
+endif()
+
+if( ANDROID_NO_UNDEFINED )
+ if( MIPS )
+  # there is some sysroot-related problem in mips linker...
+  if( NOT ANDROID_SYSROOT MATCHES "[ ;\"]" )
+   set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined -Wl,-rpath-link,${ANDROID_SYSROOT}/usr/lib" )
+  endif()
+ else()
+  set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined" )
+ endif()
+endif()
+
+if( ANDROID_SO_UNDEFINED )
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-allow-shlib-undefined" )
+endif()
+
+if( ANDROID_FUNCTION_LEVEL_LINKING )
+ set( ANDROID_CXX_FLAGS    "${ANDROID_CXX_FLAGS} -fdata-sections -ffunction-sections" )
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--gc-sections" )
+endif()
+
+if( ANDROID_COMPILER_VERSION VERSION_EQUAL "4.6" )
+ if( ANDROID_GOLD_LINKER AND (CMAKE_HOST_UNIX OR ANDROID_NDK_RELEASE_NUM GREATER 8002) AND (ARMEABI OR ARMEABI_V7A OR X86) )
+  set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=gold" )
+ elseif( ANDROID_NDK_RELEASE_NUM GREATER 8002 ) # after r8b
+  set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=bfd" )
+ elseif( ANDROID_NDK_RELEASE STREQUAL "r8b" AND ARMEABI AND NOT _CMAKE_IN_TRY_COMPILE )
+  message( WARNING "The default bfd linker from arm GCC 4.6 toolchain can fail with 'unresolvable R_ARM_THM_CALL relocation' error message. See https://code.google.com/p/android/issues/detail?id=35342
+  On Linux and OS X host platform you can workaround this problem using gold linker (default).
+  Rerun cmake with -DANDROID_GOLD_LINKER=ON option in case of problems.
+" )
+ endif()
+endif() # version 4.6
+
+if( ANDROID_NOEXECSTACK )
+ if( ANDROID_COMPILER_IS_CLANG )
+  set( ANDROID_CXX_FLAGS    "${ANDROID_CXX_FLAGS} -Xclang -mnoexecstack" )
+ else()
+  set( ANDROID_CXX_FLAGS    "${ANDROID_CXX_FLAGS} -Wa,--noexecstack" )
+ endif()
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,noexecstack" )
+endif()
+
+if( ANDROID_RELRO )
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now" )
+endif()
+
+if( ANDROID_COMPILER_IS_CLANG )
+ set( ANDROID_CXX_FLAGS "-target ${ANDROID_LLVM_TRIPLE} -Qunused-arguments ${ANDROID_CXX_FLAGS}" )
+ if( BUILD_WITH_ANDROID_NDK )
+  set( ANDROID_CXX_FLAGS "-gcc-toolchain ${ANDROID_TOOLCHAIN_ROOT} ${ANDROID_CXX_FLAGS}" )
+ endif()
+endif()
+
+# cache flags
+set( CMAKE_CXX_FLAGS           ""                        CACHE STRING "c++ flags" )
+set( CMAKE_C_FLAGS             ""                        CACHE STRING "c flags" )
+set( CMAKE_CXX_FLAGS_RELEASE   "-O3 -DNDEBUG"            CACHE STRING "c++ Release flags" )
+set( CMAKE_C_FLAGS_RELEASE     "-O3 -DNDEBUG"            CACHE STRING "c Release flags" )
+set( CMAKE_CXX_FLAGS_DEBUG     "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c++ Debug flags" )
+set( CMAKE_C_FLAGS_DEBUG       "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c Debug flags" )
+set( CMAKE_SHARED_LINKER_FLAGS ""                        CACHE STRING "shared linker flags" )
+set( CMAKE_MODULE_LINKER_FLAGS ""                        CACHE STRING "module linker flags" )
+set( CMAKE_EXE_LINKER_FLAGS    "-Wl,-z,nocopyreloc"      CACHE STRING "executable linker flags" )
+
+# put flags to cache (for debug purpose only)
+set( ANDROID_CXX_FLAGS         "${ANDROID_CXX_FLAGS}"         CACHE INTERNAL "Android specific c/c++ flags" )
+set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE}" CACHE INTERNAL "Android specific c/c++ Release flags" )
+set( ANDROID_CXX_FLAGS_DEBUG   "${ANDROID_CXX_FLAGS_DEBUG}"   CACHE INTERNAL "Android specific c/c++ Debug flags" )
+set( ANDROID_LINKER_FLAGS      "${ANDROID_LINKER_FLAGS}"      CACHE INTERNAL "Android specific c/c++ linker flags" )
+
+# finish flags
+set( CMAKE_CXX_FLAGS           "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" )
+set( CMAKE_C_FLAGS             "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" )
+set( CMAKE_CXX_FLAGS_RELEASE   "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELEASE}" )
+set( CMAKE_C_FLAGS_RELEASE     "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_C_FLAGS_RELEASE}" )
+set( CMAKE_CXX_FLAGS_DEBUG     "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_DEBUG}" )
+set( CMAKE_C_FLAGS_DEBUG       "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_C_FLAGS_DEBUG}" )
+set( CMAKE_SHARED_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" )
+set( CMAKE_MODULE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" )
+set( CMAKE_EXE_LINKER_FLAGS    "${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" )
+
+if( MIPS AND BUILD_WITH_ANDROID_NDK AND ANDROID_NDK_RELEASE STREQUAL "r8" )
+ set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_SHARED_LINKER_FLAGS}" )
+ set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_MODULE_LINKER_FLAGS}" )
+ set( CMAKE_EXE_LINKER_FLAGS    "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.x ${CMAKE_EXE_LINKER_FLAGS}" )
+endif()
+
+# pie/pic
+if( NOT (ANDROID_NATIVE_API_LEVEL LESS 16) AND (NOT DEFINED ANDROID_APP_PIE OR ANDROID_APP_PIE) AND (CMAKE_VERSION VERSION_GREATER 2.8.8) )
+ set( CMAKE_POSITION_INDEPENDENT_CODE TRUE )
+ set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie")
+else()
+ set( CMAKE_POSITION_INDEPENDENT_CODE FALSE )
+ set( CMAKE_CXX_FLAGS "-fpic ${CMAKE_CXX_FLAGS}" )
+ set( CMAKE_C_FLAGS   "-fpic ${CMAKE_C_FLAGS}" )
+endif()
+
+# configure rtti
+if( DEFINED ANDROID_RTTI AND ANDROID_STL_FORCE_FEATURES )
+ if( ANDROID_RTTI )
+  set( CMAKE_CXX_FLAGS "-frtti ${CMAKE_CXX_FLAGS}" )
+ else()
+  set( CMAKE_CXX_FLAGS "-fno-rtti ${CMAKE_CXX_FLAGS}" )
+ endif()
+endif()
+
+# configure exceptios
+if( DEFINED ANDROID_EXCEPTIONS AND ANDROID_STL_FORCE_FEATURES )
+ if( ANDROID_EXCEPTIONS )
+  set( CMAKE_CXX_FLAGS "-fexceptions ${CMAKE_CXX_FLAGS}" )
+  set( CMAKE_C_FLAGS "-fexceptions ${CMAKE_C_FLAGS}" )
+ else()
+  set( CMAKE_CXX_FLAGS "-fno-exceptions ${CMAKE_CXX_FLAGS}" )
+  set( CMAKE_C_FLAGS "-fno-exceptions ${CMAKE_C_FLAGS}" )
+ endif()
+endif()
+
+# global includes and link directories
+include_directories( SYSTEM "${ANDROID_SYSROOT}/usr/include" "${ANDROID_SYSROOT}/usr/include/machine" ${ANDROID_STL_INCLUDE_DIRS} )
+get_filename_component(__android_install_path "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" ABSOLUTE) # avoid CMP0015 policy warning
+link_directories( "${__android_install_path}" )
+
+# detect if need link crtbegin_so.o explicitly
+if( NOT DEFINED ANDROID_EXPLICIT_CRT_LINK )
+ set( __cmd "${CMAKE_CXX_CREATE_SHARED_LIBRARY}" )
+ string( REPLACE "<CMAKE_CXX_COMPILER>" "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" __cmd "${__cmd}" )
+ string( REPLACE "<CMAKE_C_COMPILER>"   "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}"   __cmd "${__cmd}" )
+ string( REPLACE "<CMAKE_SHARED_LIBRARY_CXX_FLAGS>" "${CMAKE_CXX_FLAGS}" __cmd "${__cmd}" )
+ string( REPLACE "<LANGUAGE_COMPILE_FLAGS>" "" __cmd "${__cmd}" )
+ string( REPLACE "<LINK_FLAGS>" "${CMAKE_SHARED_LINKER_FLAGS}" __cmd "${__cmd}" )
+ string( REPLACE "<CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS>" "-shared" __cmd "${__cmd}" )
+ string( REPLACE "<CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG>" "" __cmd "${__cmd}" )
+ string( REPLACE "<TARGET_SONAME>" "" __cmd "${__cmd}" )
+ string( REPLACE "<TARGET>" "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain_crtlink_test.so" __cmd "${__cmd}" )
+ string( REPLACE "<OBJECTS>" "\"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" __cmd "${__cmd}" )
+ string( REPLACE "<LINK_LIBRARIES>" "" __cmd "${__cmd}" )
+ separate_arguments( __cmd )
+ foreach( __var ANDROID_NDK ANDROID_NDK_TOOLCHAINS_PATH ANDROID_STANDALONE_TOOLCHAIN )
+  if( ${__var} )
+   set( __tmp "${${__var}}" )
+   separate_arguments( __tmp )
+   string( REPLACE "${__tmp}" "${${__var}}" __cmd "${__cmd}")
+  endif()
+ endforeach()
+ string( REPLACE "'" "" __cmd "${__cmd}" )
+ string( REPLACE "\"" "" __cmd "${__cmd}" )
+ execute_process( COMMAND ${__cmd} RESULT_VARIABLE __cmd_result OUTPUT_QUIET ERROR_QUIET )
+ if( __cmd_result EQUAL 0 )
+  set( ANDROID_EXPLICIT_CRT_LINK ON )
+ else()
+  set( ANDROID_EXPLICIT_CRT_LINK OFF )
+ endif()
+endif()
+
+if( ANDROID_EXPLICIT_CRT_LINK )
+ set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" )
+ set( CMAKE_CXX_CREATE_SHARED_MODULE  "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" )
+endif()
+
+# setup output directories
+set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" )
+
+if( DEFINED LIBRARY_OUTPUT_PATH_ROOT
+      OR EXISTS "${CMAKE_SOURCE_DIR}/AndroidManifest.xml"
+      OR (EXISTS "${CMAKE_SOURCE_DIR}/../AndroidManifest.xml" AND EXISTS "${CMAKE_SOURCE_DIR}/../jni/") )
+  set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "Root for binaries output, set this to change where Android libs are installed to" )
+  if( NOT _CMAKE_IN_TRY_COMPILE )
+    if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" )
+      set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" )
+    else()
+      set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" )
+    endif()
+    set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for Android libs" )
+  endif()
+endif()
+
+# copy shaed stl library to build directory
+if( NOT _CMAKE_IN_TRY_COMPILE AND __libstl MATCHES "[.]so$" AND DEFINED LIBRARY_OUTPUT_PATH )
+  get_filename_component( __libstlname "${__libstl}" NAME )
+  execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${__libstl}" "${LIBRARY_OUTPUT_PATH}/${__libstlname}" RESULT_VARIABLE __fileCopyProcess )
+  if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${LIBRARY_OUTPUT_PATH}/${__libstlname}")
+    message( SEND_ERROR "Failed copying of ${__libstl} to the ${LIBRARY_OUTPUT_PATH}/${__libstlname}" )
+  endif()
+  unset( __fileCopyProcess )
+  unset( __libstlname )
+endif()
+
+
+# set these global flags for cmake client scripts to change behavior
+set( ANDROID True )
+set( BUILD_ANDROID True )
+
+# where is the target environment
+set( CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/bin" "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" "${ANDROID_SYSROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" )
+
+# only search for libraries and includes in the ndk toolchain
+set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
+set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
+set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
+
+
+# macro to find packages on the host OS
+macro( find_host_package )
+ set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
+ set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER )
+ set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER )
+ if( CMAKE_HOST_WIN32 )
+  SET( WIN32 1 )
+  SET( UNIX )
+ elseif( CMAKE_HOST_APPLE )
+  SET( APPLE 1 )
+  SET( UNIX )
+ endif()
+ find_package( ${ARGN} )
+ SET( WIN32 )
+ SET( APPLE )
+ SET( UNIX 1 )
+ set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
+ set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
+ set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
+endmacro()
+
+
+# macro to find programs on the host OS
+macro( find_host_program )
+ set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
+ set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER )
+ set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER )
+ if( CMAKE_HOST_WIN32 )
+  SET( WIN32 1 )
+  SET( UNIX )
+ elseif( CMAKE_HOST_APPLE )
+  SET( APPLE 1 )
+  SET( UNIX )
+ endif()
+ find_program( ${ARGN} )
+ SET( WIN32 )
+ SET( APPLE )
+ SET( UNIX 1 )
+ set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
+ set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
+ set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
+endmacro()
+
+
+# export toolchain settings for the try_compile() command
+if( NOT _CMAKE_IN_TRY_COMPILE )
+ set( __toolchain_config "")
+ foreach( __var NDK_CCACHE  LIBRARY_OUTPUT_PATH_ROOT  ANDROID_FORBID_SYGWIN
+                ANDROID_NDK_HOST_X64
+                ANDROID_NDK
+                ANDROID_NDK_LAYOUT
+                ANDROID_STANDALONE_TOOLCHAIN
+                ANDROID_TOOLCHAIN_NAME
+                ANDROID_ABI
+                ANDROID_NATIVE_API_LEVEL
+                ANDROID_STL
+                ANDROID_STL_FORCE_FEATURES
+                ANDROID_FORCE_ARM_BUILD
+                ANDROID_NO_UNDEFINED
+                ANDROID_SO_UNDEFINED
+                ANDROID_FUNCTION_LEVEL_LINKING
+                ANDROID_GOLD_LINKER
+                ANDROID_NOEXECSTACK
+                ANDROID_RELRO
+                ANDROID_LIBM_PATH
+                ANDROID_EXPLICIT_CRT_LINK
+                ANDROID_APP_PIE
+                )
+  if( DEFINED ${__var} )
+   if( ${__var} MATCHES " ")
+    set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" CACHE INTERNAL \"\" )\n" )
+   else()
+    set( __toolchain_config "${__toolchain_config}set( ${__var} ${${__var}} CACHE INTERNAL \"\" )\n" )
+   endif()
+  endif()
+ endforeach()
+ file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android.toolchain.config.cmake" "${__toolchain_config}" )
+ unset( __toolchain_config )
+endif()
+
+
+# force cmake to produce / instead of \ in build commands for Ninja generator
+if( CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_HOST_WIN32 )
+ # it is a bad hack after all
+ # CMake generates Ninja makefiles with UNIX paths only if it thinks that we are going to build with MinGW
+ set( CMAKE_COMPILER_IS_MINGW TRUE ) # tell CMake that we are MinGW
+ set( CMAKE_CROSSCOMPILING TRUE )    # stop recursion
+ enable_language( C )
+ enable_language( CXX )
+ # unset( CMAKE_COMPILER_IS_MINGW ) # can't unset because CMake does not convert back-slashes in response files without it
+ unset( MINGW )
+endif()
+
+
+# Variables controlling behavior or set by cmake toolchain:
+#   ANDROID_ABI : "armeabi-v7a" (default), "armeabi", "armeabi-v7a with NEON", "armeabi-v7a with VFPV3", "armeabi-v6 with VFP", "x86", "mips", "arm64-v8a", "x86_64", "mips64"
+#   ANDROID_NATIVE_API_LEVEL : 3,4,5,8,9,14,15,16,17,18,19,21 (depends on NDK version)
+#   ANDROID_STL : c++_shared/gnustl_static/gnustl_shared/stlport_static/stlport_shared/gabi++_static/gabi++_shared/system_re/system/none
+#   ANDROID_FORBID_SYGWIN : ON/OFF
+#   ANDROID_NO_UNDEFINED : ON/OFF
+#   ANDROID_SO_UNDEFINED : OFF/ON  (default depends on NDK version)
+#   ANDROID_FUNCTION_LEVEL_LINKING : ON/OFF
+#   ANDROID_GOLD_LINKER : ON/OFF
+#   ANDROID_NOEXECSTACK : ON/OFF
+#   ANDROID_RELRO : ON/OFF
+#   ANDROID_FORCE_ARM_BUILD : ON/OFF
+#   ANDROID_STL_FORCE_FEATURES : ON/OFF
+#   ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product/<product_name>/obj/lib/libm.so) to workaround unresolved `sincos`
+# Can be set only at the first run:
+#   ANDROID_NDK : path to your NDK install
+#   NDK_CCACHE : path to your ccache executable
+#   ANDROID_TOOLCHAIN_NAME : the NDK name of compiler toolchain
+#   ANDROID_NDK_HOST_X64 : try to use x86_64 toolchain (default for x64 host systems)
+#   ANDROID_NDK_LAYOUT : the inner NDK structure (RELEASE, LINARO, ANDROID)
+#   LIBRARY_OUTPUT_PATH_ROOT : <any valid path>
+#   ANDROID_STANDALONE_TOOLCHAIN
+#
+# Primary read-only variables:
+#   ANDROID : always TRUE
+#   ARMEABI : TRUE for arm v6 and older devices
+#   ARMEABI_V6 : TRUE for arm v6
+#   ARMEABI_V7A : TRUE for arm v7a
+#   ARM64_V8A : TRUE for arm64-v8a
+#   NEON : TRUE if NEON unit is enabled
+#   VFPV3 : TRUE if VFP version 3 is enabled
+#   X86 : TRUE if configured for x86
+#   X86_64 : TRUE if configured for x86_64
+#   MIPS : TRUE if configured for mips
+#   MIPS64 : TRUE if configured for mips64
+#   BUILD_WITH_ANDROID_NDK : TRUE if NDK is used
+#   BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used
+#   ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform
+#   ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "x86", "mips", "arm64-v8a", "x86_64", "mips64" depending on ANDROID_ABI
+#   ANDROID_NDK_RELEASE : from r5 to r10d; set only for NDK
+#   ANDROID_NDK_RELEASE_NUM : numeric ANDROID_NDK_RELEASE version (1000*major+minor)
+#   ANDROID_ARCH_NAME : "arm", "x86", "mips", "arm64", "x86_64", "mips64" depending on ANDROID_ABI
+#   ANDROID_SYSROOT : path to the compiler sysroot
+#   TOOL_OS_SUFFIX : "" or ".exe" depending on host platform
+#   ANDROID_COMPILER_IS_CLANG : TRUE if clang compiler is used
+#
+# Secondary (less stable) read-only variables:
+#   ANDROID_COMPILER_VERSION : GCC version used (not Clang version)
+#   ANDROID_CLANG_VERSION : version of clang compiler if clang is used
+#   ANDROID_CXX_FLAGS : C/C++ compiler flags required by Android platform
+#   ANDROID_SUPPORTED_ABIS : list of currently allowed values for ANDROID_ABI
+#   ANDROID_TOOLCHAIN_MACHINE_NAME : "arm-linux-androideabi", "arm-eabi" or "i686-android-linux"
+#   ANDROID_TOOLCHAIN_ROOT : path to the top level of toolchain (standalone or placed inside NDK)
+#   ANDROID_CLANG_TOOLCHAIN_ROOT : path to clang tools
+#   ANDROID_SUPPORTED_NATIVE_API_LEVELS : list of native API levels found inside NDK
+#   ANDROID_STL_INCLUDE_DIRS : stl include paths
+#   ANDROID_RTTI : if rtti is enabled by the runtime
+#   ANDROID_EXCEPTIONS : if exceptions are enabled by the runtime
+#   ANDROID_GCC_TOOLCHAIN_NAME : read-only, differs from ANDROID_TOOLCHAIN_NAME only if clang is used
+#
+# Defaults:
+#   ANDROID_DEFAULT_NDK_API_LEVEL
+#   ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH}
+#   ANDROID_NDK_SEARCH_PATHS
+#   ANDROID_SUPPORTED_ABIS_${ARCH}
+#   ANDROID_SUPPORTED_NDK_VERSIONS

+ 193 - 0
cocos2d/cmake/ios.toolchain.cmake

@@ -0,0 +1,193 @@
+# This file is based off of the Platform/Darwin.cmake and Platform/UnixPaths.cmake
+# files which are included with CMake 2.8.4
+# It has been altered for iOS development
+
+# Options:
+#
+# IOS_PLATFORM = OS (default) or SIMULATOR
+#   This decides if SDKS will be selected from the iPhoneOS.platform or iPhoneSimulator.platform folders
+#   OS - the default, used to build for iPhone and iPad physical devices, which have an arm arch.
+#   SIMULATOR - used to build for the Simulator platforms, which have an x86 arch.
+#
+# CMAKE_IOS_DEVELOPER_ROOT = automatic(default) or /path/to/platform/Developer folder
+#   By default this location is automatcially chosen based on the IOS_PLATFORM value above.
+#   If set manually, it will override the default location and force the user of a particular Developer Platform
+#
+# CMAKE_IOS_SDK_ROOT = automatic(default) or /path/to/platform/Developer/SDKs/SDK folder
+#   By default this location is automatcially chosen based on the CMAKE_IOS_DEVELOPER_ROOT value.
+#   In this case it will always be the most up-to-date SDK found in the CMAKE_IOS_DEVELOPER_ROOT path.
+#   If set manually, this will force the use of a specific SDK version
+
+# Macros:
+#
+# set_xcode_property (TARGET XCODE_PROPERTY XCODE_VALUE)
+#  A convenience macro for setting xcode specific properties on targets
+#  example: set_xcode_property (myioslib IPHONEOS_DEPLOYMENT_TARGET "3.1")
+#
+# find_host_package (PROGRAM ARGS)
+#  A macro used to find executable programs on the host system, not within the iOS environment.
+#  Thanks to the android-cmake project for providing the command
+
+# Standard settings
+set (CMAKE_SYSTEM_NAME Darwin)
+set (CMAKE_SYSTEM_VERSION 1)
+set (UNIX True)
+set (APPLE True)
+set (IOS True)
+
+# Required as of cmake 2.8.10
+set (CMAKE_OSX_DEPLOYMENT_TARGET "" CACHE STRING "Force unset of the deployment target for iOS" FORCE)
+
+# Determine the cmake host system version so we know where to find the iOS SDKs
+find_program (CMAKE_UNAME uname /bin /usr/bin /usr/local/bin)
+if (CMAKE_UNAME)
+	exec_program(uname ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION)
+	string (REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_VERSION "${CMAKE_HOST_SYSTEM_VERSION}")
+endif (CMAKE_UNAME)
+
+# Force the compilers to gcc for iOS
+include (CMakeForceCompiler)
+CMAKE_FORCE_C_COMPILER (/usr/bin/clang Apple)
+CMAKE_FORCE_CXX_COMPILER (/usr/bin/clang++ Apple)
+set(CMAKE_AR ar CACHE FILEPATH "" FORCE)
+
+# Skip the platform compiler checks for cross compiling
+set (CMAKE_CXX_COMPILER_WORKS TRUE)
+set (CMAKE_C_COMPILER_WORKS TRUE)
+
+# All iOS/Darwin specific settings - some may be redundant
+set (CMAKE_SHARED_LIBRARY_PREFIX "lib")
+set (CMAKE_SHARED_LIBRARY_SUFFIX ".dylib")
+set (CMAKE_SHARED_MODULE_PREFIX "lib")
+set (CMAKE_SHARED_MODULE_SUFFIX ".so")
+set (CMAKE_MODULE_EXISTS 1)
+set (CMAKE_DL_LIBS "")
+
+set (CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ")
+set (CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ")
+set (CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}")
+set (CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}")
+
+# Hidden visibilty is required for cxx on iOS 
+set (CMAKE_C_FLAGS_INIT "")
+set (CMAKE_CXX_FLAGS_INIT "-fvisibility=hidden -fvisibility-inlines-hidden -isysroot ${CMAKE_OSX_SYSROOT}")
+
+set (CMAKE_C_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}")
+set (CMAKE_CXX_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}")
+
+set (CMAKE_PLATFORM_HAS_INSTALLNAME 1)
+set (CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -headerpad_max_install_names")
+set (CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -headerpad_max_install_names")
+set (CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,")
+set (CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,")
+set (CMAKE_FIND_LIBRARY_SUFFIXES ".dylib" ".so" ".a")
+
+# hack: if a new cmake (which uses CMAKE_INSTALL_NAME_TOOL) runs on an old build tree
+# (where install_name_tool was hardcoded) and where CMAKE_INSTALL_NAME_TOOL isn't in the cache
+# and still cmake didn't fail in CMakeFindBinUtils.cmake (because it isn't rerun)
+# hardcode CMAKE_INSTALL_NAME_TOOL here to install_name_tool, so it behaves as it did before, Alex
+if (NOT DEFINED CMAKE_INSTALL_NAME_TOOL)
+	find_program(CMAKE_INSTALL_NAME_TOOL install_name_tool)
+endif (NOT DEFINED CMAKE_INSTALL_NAME_TOOL)
+
+# Setup iOS platform unless specified manually with IOS_PLATFORM
+if (NOT DEFINED IOS_PLATFORM)
+	set (IOS_PLATFORM "OS")
+endif (NOT DEFINED IOS_PLATFORM)
+set (IOS_PLATFORM ${IOS_PLATFORM} CACHE STRING "Type of iOS Platform")
+
+# Check the platform selection and setup for developer root
+if (${IOS_PLATFORM} STREQUAL "OS")
+	set (IOS_PLATFORM_LOCATION "iPhoneOS.platform")
+
+	# This causes the installers to properly locate the output libraries
+	set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos")
+elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR")
+	set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform")
+
+	# This causes the installers to properly locate the output libraries
+	set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator")
+else (${IOS_PLATFORM} STREQUAL "OS")
+	message (FATAL_ERROR "Unsupported IOS_PLATFORM value selected. Please choose OS or SIMULATOR")
+endif (${IOS_PLATFORM} STREQUAL "OS")
+
+# Setup iOS developer location unless specified manually with CMAKE_IOS_DEVELOPER_ROOT
+# Note Xcode 4.3 changed the installation location, choose the most recent one available
+set (XCODE_POST_43_ROOT "/Applications/Xcode.app/Contents/Developer/Platforms/${IOS_PLATFORM_LOCATION}/Developer")
+set (XCODE_PRE_43_ROOT "/Developer/Platforms/${IOS_PLATFORM_LOCATION}/Developer")
+if (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT)
+	if (EXISTS ${XCODE_POST_43_ROOT})
+		set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_POST_43_ROOT})
+	elseif(EXISTS ${XCODE_PRE_43_ROOT})
+		set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_PRE_43_ROOT})
+	endif (EXISTS ${XCODE_POST_43_ROOT})
+endif (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT)
+set (CMAKE_IOS_DEVELOPER_ROOT ${CMAKE_IOS_DEVELOPER_ROOT} CACHE PATH "Location of iOS Platform")
+
+# Find and use the most recent iOS sdk unless specified manually with CMAKE_IOS_SDK_ROOT
+if (NOT DEFINED CMAKE_IOS_SDK_ROOT)
+	file (GLOB _CMAKE_IOS_SDKS "${CMAKE_IOS_DEVELOPER_ROOT}/SDKs/*")
+	if (_CMAKE_IOS_SDKS) 
+		list (SORT _CMAKE_IOS_SDKS)
+		list (REVERSE _CMAKE_IOS_SDKS)
+		list (GET _CMAKE_IOS_SDKS 0 CMAKE_IOS_SDK_ROOT)
+	else (_CMAKE_IOS_SDKS)
+		message (FATAL_ERROR "No iOS SDK's found in default search path ${CMAKE_IOS_DEVELOPER_ROOT}. Manually set CMAKE_IOS_SDK_ROOT or install the iOS SDK.")
+	endif (_CMAKE_IOS_SDKS)
+	message (STATUS "Toolchain using default iOS SDK: ${CMAKE_IOS_SDK_ROOT}")
+endif (NOT DEFINED CMAKE_IOS_SDK_ROOT)
+set (CMAKE_IOS_SDK_ROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Location of the selected iOS SDK")
+
+# Set the sysroot default to the most recent SDK
+set (CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS support")
+
+# set the architecture for iOS 
+# NOTE: Currently both ARCHS_STANDARD_32_BIT and ARCHS_UNIVERSAL_IPHONE_OS set armv7 only, so set both manually
+if (${IOS_PLATFORM} STREQUAL "OS")
+	set (IOS_ARCH armv6 armv7)
+else (${IOS_PLATFORM} STREQUAL "OS")
+	set (IOS_ARCH i386)
+endif (${IOS_PLATFORM} STREQUAL "OS")
+
+set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE string  "Build architecture for iOS")
+
+# Set the find root to the iOS developer roots and to user defined paths
+set (CMAKE_FIND_ROOT_PATH ${CMAKE_IOS_DEVELOPER_ROOT} ${CMAKE_IOS_SDK_ROOT} ${CMAKE_PREFIX_PATH} CACHE string  "iOS find search path root")
+
+# default to searching for frameworks first
+set (CMAKE_FIND_FRAMEWORK FIRST)
+
+# set up the default search directories for frameworks
+set (CMAKE_SYSTEM_FRAMEWORK_PATH
+	${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks
+	${CMAKE_IOS_SDK_ROOT}/System/Library/PrivateFrameworks
+	${CMAKE_IOS_SDK_ROOT}/Developer/Library/Frameworks
+)
+
+# only search the iOS sdks, not the remainder of the host filesystem
+set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
+set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+
+# This little macro lets you set any XCode specific property
+macro (set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE)
+	set_property (TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE})
+endmacro (set_xcode_property)
+
+
+# This macro lets you find executable programs on the host system
+macro (find_host_package)
+	set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+	set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER)
+	set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER)
+	set (IOS FALSE)
+
+	find_package(${ARGN})
+
+	set (IOS TRUE)
+	set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
+	set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+	set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+endmacro (find_host_package)
+

+ 318 - 0
cocos2d/cocos/2d/CCAction.cpp

@@ -0,0 +1,318 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCAction.h"
+#include "2d/CCActionInterval.h"
+#include "2d/CCNode.h"
+#include "base/CCDirector.h"
+#include "base/ccUTF8.h"
+
+NS_CC_BEGIN
+//
+// Action Base Class
+//
+
+Action::Action()
+:_originalTarget(nullptr)
+,_target(nullptr)
+,_tag(Action::INVALID_TAG)
+,_flags(0)
+{
+#if CC_ENABLE_SCRIPT_BINDING
+    ScriptEngineProtocol* engine = ScriptEngineManager::getInstance()->getScriptEngine();
+    _scriptType = engine != nullptr ? engine->getScriptType() : kScriptTypeNone;
+#endif
+}
+
+Action::~Action()
+{
+    CCLOGINFO("deallocing Action: %p - tag: %i", this, _tag);
+}
+
+std::string Action::description() const
+{
+    return StringUtils::format("<Action | Tag = %d", _tag);
+}
+
+void Action::startWithTarget(Node *aTarget)
+{
+    _originalTarget = _target = aTarget;
+}
+
+void Action::stop()
+{
+    _target = nullptr;
+}
+
+bool Action::isDone() const
+{
+    return true;
+}
+
+void Action::step(float /*dt*/)
+{
+    CCLOG("[Action step]. override me");
+}
+
+void Action::update(float /*time*/)
+{
+    CCLOG("[Action update]. override me");
+}
+
+//
+// Speed
+//
+Speed::Speed()
+: _speed(0.0)
+, _innerAction(nullptr)
+{
+}
+
+Speed::~Speed()
+{
+    CC_SAFE_RELEASE(_innerAction);
+}
+
+Speed* Speed::create(ActionInterval* action, float speed)
+{
+    Speed *ret = new (std::nothrow) Speed();
+    if (ret && ret->initWithAction(action, speed))
+    {
+        ret->autorelease();
+        return ret;
+    }
+    CC_SAFE_DELETE(ret);
+    return nullptr;
+}
+
+bool Speed::initWithAction(ActionInterval *action, float speed)
+{
+    CCASSERT(action != nullptr, "action must not be NULL");
+    if (action == nullptr)
+    {
+        log("Speed::initWithAction error: action is nullptr!");
+        return false;
+    }
+    
+    action->retain();
+    _innerAction = action;
+    _speed = speed;
+    return true;
+}
+
+Speed *Speed::clone() const
+{
+    // no copy constructor
+    if (_innerAction)
+        return Speed::create(_innerAction->clone(), _speed);
+    
+    return nullptr;
+}
+
+void Speed::startWithTarget(Node* target)
+{
+    if (target && _innerAction)
+    {
+        Action::startWithTarget(target);
+        _innerAction->startWithTarget(target);
+    }
+    else
+        log("Speed::startWithTarget error: target(%p) or _innerAction(%p) is nullptr!", target, _innerAction);
+}
+
+void Speed::stop()
+{
+    if (_innerAction)
+        _innerAction->stop();
+    
+    Action::stop();
+}
+
+void Speed::step(float dt)
+{
+    _innerAction->step(dt * _speed);
+}
+
+bool Speed::isDone() const
+{
+    return _innerAction->isDone();
+}
+
+Speed *Speed::reverse() const
+{
+    if (_innerAction)
+        return Speed::create(_innerAction->reverse(), _speed);
+    
+    return nullptr;
+}
+
+void Speed::setInnerAction(ActionInterval *action)
+{
+    if (_innerAction != action)
+    {
+        CC_SAFE_RELEASE(_innerAction);
+        _innerAction = action;
+        CC_SAFE_RETAIN(_innerAction);
+    }
+}
+
+//
+// Follow
+//
+Follow::~Follow()
+{
+    CC_SAFE_RELEASE(_followedNode);
+}
+
+Follow* Follow::create(Node *followedNode, const Rect& rect/* = Rect::ZERO*/)
+{
+    return createWithOffset(followedNode, 0.0, 0.0,rect);
+}
+
+Follow* Follow::createWithOffset(Node* followedNode,float xOffset,float yOffset,const Rect& rect/*= Rect::ZERO*/){
+    
+    
+    Follow *follow = new (std::nothrow) Follow();
+    
+    bool valid;
+    
+    valid = follow->initWithTargetAndOffset(followedNode, xOffset, yOffset,rect);
+
+    if (follow && valid)
+    {
+        follow->autorelease();
+        return follow;
+    }
+    
+    delete follow;
+    return nullptr;
+    
+}
+Follow* Follow::clone() const
+{
+    // no copy constructor
+    return Follow::createWithOffset(_followedNode, _offsetX,_offsetY,_worldRect);
+    
+}
+
+Follow* Follow::reverse() const
+{
+    return clone();
+}
+
+bool Follow::initWithTargetAndOffset(Node *followedNode, float xOffset,float yOffset,const Rect& rect)
+{
+    CCASSERT(followedNode != nullptr, "FollowedNode can't be NULL");
+    if(followedNode == nullptr)
+    {
+        log("Follow::initWithTarget error: followedNode is nullptr!");
+        return false;
+    }
+ 
+    followedNode->retain();
+    _followedNode = followedNode;
+    _worldRect = rect;
+    _boundarySet = !rect.equals(Rect::ZERO);
+    _boundaryFullyCovered = false;
+
+    Size winSize = Director::getInstance()->getWinSize();
+    _fullScreenSize.set(winSize.width, winSize.height);
+    _halfScreenSize = _fullScreenSize * 0.5f;
+    _offsetX=xOffset;
+    _offsetY=yOffset;
+    _halfScreenSize.x += _offsetX;
+    _halfScreenSize.y += _offsetY;
+    
+    if (_boundarySet)
+    {
+        _leftBoundary = -((rect.origin.x+rect.size.width) - _fullScreenSize.x);
+        _rightBoundary = -rect.origin.x ;
+        _topBoundary = -rect.origin.y;
+        _bottomBoundary = -((rect.origin.y+rect.size.height) - _fullScreenSize.y);
+
+        if(_rightBoundary < _leftBoundary)
+        {
+            // screen width is larger than world's boundary width
+            //set both in the middle of the world
+            _rightBoundary = _leftBoundary = (_leftBoundary + _rightBoundary) / 2;
+        }
+        if(_topBoundary < _bottomBoundary)
+        {
+            // screen width is larger than world's boundary width
+            //set both in the middle of the world
+            _topBoundary = _bottomBoundary = (_topBoundary + _bottomBoundary) / 2;
+        }
+
+        if( (_topBoundary == _bottomBoundary) && (_leftBoundary == _rightBoundary) )
+        {
+            _boundaryFullyCovered = true;
+        }
+    }
+    
+    return true;
+}
+
+bool Follow::initWithTarget(Node *followedNode, const Rect& rect /*= Rect::ZERO*/){
+    
+    return initWithTargetAndOffset(followedNode, 0.0, 0.0,rect);
+    
+}
+void Follow::step(float /*dt*/)
+{
+    if(_boundarySet)
+    {
+        // whole map fits inside a single screen, no need to modify the position - unless map boundaries are increased
+        if(_boundaryFullyCovered)
+        {
+            return;
+        }
+
+        Vec2 tempPos = _halfScreenSize - _followedNode->getPosition();
+
+        _target->setPosition(clampf(tempPos.x, _leftBoundary, _rightBoundary),
+                                   clampf(tempPos.y, _bottomBoundary, _topBoundary));
+    }
+    else
+    {
+        _target->setPosition(_halfScreenSize - _followedNode->getPosition());
+    }
+}
+
+bool Follow::isDone() const
+{
+    return ( !_followedNode->isRunning() );
+}
+
+void Follow::stop()
+{
+    _target = nullptr;
+    Action::stop();
+}
+
+NS_CC_END
+
+

+ 461 - 0
cocos2d/cocos/2d/CCAction.h

@@ -0,0 +1,461 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+
+#ifndef __ACTIONS_CCACTION_H__
+#define __ACTIONS_CCACTION_H__
+
+#include "base/CCRef.h"
+#include "math/CCGeometry.h"
+#include "base/CCScriptSupport.h"
+
+NS_CC_BEGIN
+
+class Node;
+
+enum {
+    kActionUpdate
+};
+
+/**
+ * @addtogroup actions
+ * @{
+ */
+
+/** 
+ * @brief Base class for Action objects.
+ */
+class CC_DLL Action : public Ref, public Clonable
+{
+public:
+    /** Default tag used for all the actions. */
+    static const int INVALID_TAG = -1;
+    /**
+     * @js NA
+     * @lua NA
+     */
+    virtual std::string description() const;
+
+    /** Returns a clone of action.
+     *
+     * @return A clone action.
+     */
+    virtual Action* clone() const
+    {
+        CC_ASSERT(0);
+        return nullptr;
+    }
+
+    /** Returns a new action that performs the exact reverse of the action. 
+     *
+     * @return A new action that performs the exact reverse of the action.
+     * @js NA
+     */
+    virtual Action* reverse() const
+    {
+        CC_ASSERT(0);
+        return nullptr;
+    }
+
+    /** Return true if the action has finished. 
+     * 
+     * @return Is true if the action has finished.
+     */
+    virtual bool isDone() const;
+
+    /** Called before the action start. It will also set the target. 
+     *
+     * @param target A certain target.
+     */
+    virtual void startWithTarget(Node *target);
+
+    /** 
+     * Called after the action has finished. It will set the 'target' to nil.
+     * IMPORTANT: You should never call "Action::stop()" manually. Instead, use: "target->stopAction(action);".
+     */
+    virtual void stop();
+
+    /** Called every frame with it's delta time, dt in seconds. DON'T override unless you know what you are doing. 
+     *
+     * @param dt In seconds.
+     */
+    virtual void step(float dt);
+
+    /** 
+     * Called once per frame. time a value between 0 and 1.
+
+     * For example:
+     * - 0 Means that the action just started.
+     * - 0.5 Means that the action is in the middle.
+     * - 1 Means that the action is over.
+     *
+     * @param time A value between 0 and 1.
+     */
+    virtual void update(float time);
+    /** Return certain target.
+     *
+     * @return A certain target.
+     */
+    Node* getTarget() const { return _target; }
+    /** The action will modify the target properties. 
+     *
+     * @param target A certain target.
+     */
+    void setTarget(Node *target) { _target = target; }
+    /** Return a original Target. 
+     *
+     * @return A original Target.
+     */
+    Node* getOriginalTarget() const { return _originalTarget; }
+    /** 
+     * Set the original target, since target can be nil.
+     * Is the target that were used to run the action. Unless you are doing something complex, like ActionManager, you should NOT call this method.
+     * The target is 'assigned', it is not 'retained'.
+     * @since v0.8.2
+     *
+     * @param originalTarget Is 'assigned', it is not 'retained'.
+     */
+    void setOriginalTarget(Node *originalTarget) { _originalTarget = originalTarget; }
+    /** Returns a tag that is used to identify the action easily. 
+     *
+     * @return A tag.
+     */
+    int getTag() const { return _tag; }
+    /** Changes the tag that is used to identify the action easily. 
+     *
+     * @param tag Used to identify the action easily.
+     */
+    void setTag(int tag) { _tag = tag; }
+    /** Returns a flag field that is used to group the actions easily.
+     *
+     * @return A tag.
+     */
+    unsigned int getFlags() const { return _flags; }
+    /** Changes the flag field that is used to group the actions easily.
+     *
+     * @param flags Used to group the actions easily.
+     */
+    void setFlags(unsigned int flags) { _flags = flags; }
+
+CC_CONSTRUCTOR_ACCESS:
+    Action();
+    virtual ~Action();
+
+protected:
+    Node    *_originalTarget;
+    /** 
+     * The "target".
+     * The target will be set with the 'startWithTarget' method.
+     * When the 'stop' method is called, target will be set to nil.
+     * The target is 'assigned', it is not 'retained'.
+     */
+    Node    *_target;
+    /** The action tag. An identifier of the action. */
+    int     _tag;
+    /** The action flag field. To categorize action into certain groups.*/
+    unsigned int _flags;
+
+#if CC_ENABLE_SCRIPT_BINDING
+    ccScriptType _scriptType;         ///< type of script binding, lua or javascript
+#endif
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Action);
+};
+
+/** @class FiniteTimeAction
+ * @brief
+ * Base class actions that do have a finite time duration.
+ * Possible actions:
+ * - An action with a duration of 0 seconds.
+ * - An action with a duration of 35.5 seconds.
+ * Infinite time actions are valid.
+ */
+class CC_DLL FiniteTimeAction : public Action
+{
+public:
+    /** Get duration in seconds of the action. 
+     *
+     * @return The duration in seconds of the action.
+     */
+    float getDuration() const { return _duration; }
+    /** Set duration in seconds of the action. 
+     *
+     * @param duration In seconds of the action.
+     */
+    void setDuration(float duration) { _duration = duration; }
+
+    //
+    // Overrides
+    //
+    virtual FiniteTimeAction* reverse() const override
+    {
+        CC_ASSERT(0);
+        return nullptr;
+    }
+    virtual FiniteTimeAction* clone() const override
+    {
+        CC_ASSERT(0);
+        return nullptr;
+    }
+
+CC_CONSTRUCTOR_ACCESS:
+    FiniteTimeAction()
+    : _duration(0)
+    {}
+    virtual ~FiniteTimeAction(){}
+
+protected:
+    //! Duration in seconds.
+    float _duration;
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(FiniteTimeAction);
+};
+
+class ActionInterval;
+class RepeatForever;
+
+/** @class Speed
+ * @brief Changes the speed of an action, making it take longer (speed>1)
+ * or shorter (speed<1) time.
+ * Useful to simulate 'slow motion' or 'fast forward' effect.
+ * @warning This action can't be Sequenceable because it is not an IntervalAction.
+ */
+class CC_DLL Speed : public Action
+{
+public:
+    /** Create the action and set the speed.
+     *
+     * @param action An action.
+     * @param speed The action speed.
+     */
+    static Speed* create(ActionInterval* action, float speed);
+    /** Return the speed.
+     *
+     * @return The action speed.
+     */
+    float getSpeed() const { return _speed; }
+    /** Alter the speed of the inner function in runtime. 
+     *
+     * @param speed Alter the speed of the inner function in runtime.
+     */
+    void setSpeed(float speed) { _speed = speed; }
+
+    /** Replace the interior action.
+     *
+     * @param action The new action, it will replace the running action.
+     */
+    void setInnerAction(ActionInterval *action);
+    /** Return the interior action.
+     *
+     * @return The interior action.
+     */
+    ActionInterval* getInnerAction() const { return _innerAction; }
+
+    //
+    // Override
+    //
+    virtual Speed* clone() const override;
+    virtual Speed* reverse() const override;
+    virtual void startWithTarget(Node* target) override;
+    virtual void stop() override;
+    /**
+     * @param dt in seconds.
+     */
+    virtual void step(float dt) override;
+    /** Return true if the action has finished.
+     *
+     * @return Is true if the action has finished.
+     */
+    virtual bool isDone() const  override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    Speed();
+    virtual ~Speed(void);
+    /** Initializes the action. */
+    bool initWithAction(ActionInterval *action, float speed);
+
+protected:
+    float _speed;
+    ActionInterval *_innerAction;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Speed);
+};
+
+/** @class Follow
+ * @brief Follow is an action that "follows" a node.
+ * Eg:
+ * @code
+ * layer->runAction(Follow::create(hero));
+ * @endcode
+ * Instead of using Camera as a "follower", use this action instead.
+ * @since v0.99.2
+ */
+class CC_DLL Follow : public Action
+{
+public:
+    /**
+     * Creates the action with a set boundary or with no boundary.
+     *
+     * @param followedNode  The node to be followed.
+     * @param rect  The boundary. If \p rect is equal to Rect::ZERO, it'll work
+     *              with no boundary.
+    */
+    
+    static Follow* create(Node *followedNode, const Rect& rect = Rect::ZERO);
+    
+    /**
+     * Creates the action with a set boundary or with no boundary with offsets.
+     *
+     * @param followedNode  The node to be followed.
+     * @param rect  The boundary. If \p rect is equal to Rect::ZERO, it'll work
+     *              with no boundary.
+     * @param xOffset The horizontal offset from the center of the screen from which the
+     *               node  is to be followed.It can be positive,negative or zero.If
+     *               set to zero the node will be horizontally centered followed.
+     *  @param yOffset The vertical offset from the center of the screen from which the
+     *                 node is to be followed.It can be positive,negative or zero.
+     *                 If set to zero the node will be vertically centered followed.
+     *   If both xOffset and yOffset are set to zero,then the node will be horizontally and vertically centered followed.
+     */
+
+    static Follow* createWithOffset(Node* followedNode,float xOffset,float yOffset,const Rect& rect = Rect::ZERO);
+    
+    /** Return boundarySet.
+     *
+     * @return Return boundarySet.
+     */
+    bool isBoundarySet() const { return _boundarySet; }
+    /** Alter behavior - turn on/off boundary. 
+     *
+     * @param value Turn on/off boundary.
+     */
+    void setBoundarySet(bool value) { _boundarySet = value; }
+    
+    /** @deprecated Alter behavior - turn on/off boundary. 
+     *
+     * @param value Turn on/off boundary.
+     */
+    CC_DEPRECATED_ATTRIBUTE void setBoudarySet(bool value) { setBoundarySet(value); }
+
+    //
+    // Override
+    //
+    virtual Follow* clone() const override;
+    virtual Follow* reverse() const override;
+    /**
+     * @param dt in seconds.
+     * @js NA
+     */
+    virtual void step(float dt) override;
+    virtual bool isDone() const override;
+    virtual void stop() override;
+
+CC_CONSTRUCTOR_ACCESS:
+    /**
+     * @js ctor
+     */
+    Follow()
+    : _followedNode(nullptr)
+    , _boundarySet(false)
+    , _boundaryFullyCovered(false)
+    , _leftBoundary(0.0)
+    , _rightBoundary(0.0)
+    , _topBoundary(0.0)
+    , _bottomBoundary(0.0)
+    , _offsetX(0.0)
+    , _offsetY(0.0)
+    , _worldRect(Rect::ZERO)
+    {}
+    /**
+     * @js NA
+     * @lua NA
+     */
+    virtual ~Follow();
+    
+    /**
+     * Initializes the action with a set boundary or with no boundary.
+     *
+     * @param followedNode  The node to be followed.
+     * @param rect  The boundary. If \p rect is equal to Rect::ZERO, it'll work
+     *              with no boundary.
+    */
+    bool initWithTarget(Node *followedNode, const Rect& rect = Rect::ZERO);
+    
+    
+    /**
+     * Initializes the action with a set boundary or with no boundary with offsets.
+     *
+     * @param followedNode  The node to be followed.
+     * @param rect  The boundary. If \p rect is equal to Rect::ZERO, it'll work
+     *              with no boundary.
+     * @param xOffset The horizontal offset from the center of the screen from which the
+     *                node  is to be followed.It can be positive,negative or zero.If
+     *                set to zero the node will be horizontally centered followed.
+     * @param yOffset The vertical offset from the center of the screen from which the
+     *                node is to be followed.It can be positive,negative or zero.
+     *                If set to zero the node will be vertically centered followed.
+     *   If both xOffset and yOffset are set to zero,then the node will be horizontally and vertically centered followed.
+
+     */
+    bool initWithTargetAndOffset(Node *followedNode,float xOffset,float yOffset,const Rect& rect = Rect::ZERO);
+
+protected:
+    /** Node to follow. */
+    Node *_followedNode;
+
+    /** Whether camera should be limited to certain area. */
+    bool _boundarySet;
+
+    /** If screen size is bigger than the boundary - update not needed. */
+    bool _boundaryFullyCovered;
+
+    /** Fast access to the screen dimensions. */
+    Vec2 _halfScreenSize;
+    Vec2 _fullScreenSize;
+
+    /** World boundaries. */
+    float _leftBoundary;
+    float _rightBoundary;
+    float _topBoundary;
+    float _bottomBoundary;
+    
+    /** Horizontal (x) and vertical (y) offset values. */
+    float _offsetX;
+    float _offsetY;
+    
+    Rect _worldRect;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Follow);
+};
+
+// end of actions group
+/// @}
+
+NS_CC_END
+
+#endif // __ACTIONS_CCACTION_H__

+ 246 - 0
cocos2d/cocos/2d/CCActionCamera.cpp

@@ -0,0 +1,246 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCActionCamera.h"
+#include "2d/CCNode.h"
+#include "platform/CCStdC.h"
+
+NS_CC_BEGIN
+//
+// CameraAction
+//
+ActionCamera::ActionCamera()
+: _center(0, 0, 0)
+, _eye(0, 0, FLT_EPSILON)
+, _up(0, 1, 0)
+{
+}
+void ActionCamera::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+}
+
+ActionCamera* ActionCamera::clone() const
+{
+    auto action = new (std::nothrow) ActionCamera();
+    if (action)
+    {
+        action->autorelease();
+        return action;
+    }
+    
+    delete action;
+    return nullptr;
+}
+
+ActionCamera * ActionCamera::reverse() const
+{
+    // FIXME: This conversion isn't safe.
+    return (ActionCamera*)ReverseTime::create(const_cast<ActionCamera*>(this));
+}
+
+void ActionCamera::restore()
+{
+    _center.setZero();
+    _eye.set(0.0f, 0.0f, FLT_EPSILON);
+    _up.set(0.0f, 1.0f, 0.0f);
+}
+
+void ActionCamera::setEye(const Vec3& eye)
+{
+    _eye = eye;
+    updateTransform();
+}
+
+void ActionCamera::setEye(float x, float y, float z)
+{
+    _eye.set(x, y, z);
+    updateTransform();
+}
+
+void ActionCamera::setCenter(const Vec3& center)
+{
+    _center = center;
+    updateTransform();
+}
+
+void ActionCamera::setUp(const Vec3& up)
+{
+    _up = up;
+    updateTransform();
+}
+
+void ActionCamera::updateTransform()
+{
+    Mat4 lookupMatrix;
+    Mat4::createLookAt(_eye.x, _eye.y, _eye.z, _center.x, _center.y, _center.z, _up.x, _up.y, _up.z, &lookupMatrix);
+
+    Vec2 anchorPoint = _target->getAnchorPointInPoints();
+
+    bool needsTranslation = !anchorPoint.isZero();
+
+    Mat4 mv = Mat4::IDENTITY;
+
+    if(needsTranslation)
+    {
+        Mat4 t;
+        Mat4::createTranslation(anchorPoint.x, anchorPoint.y, 0, &t);
+        mv = mv * t;
+    }
+    
+    mv = mv * lookupMatrix;
+
+    if(needsTranslation)
+    {
+        Mat4 t;
+        Mat4::createTranslation(-anchorPoint.x, -anchorPoint.y, 0, &t);
+        mv = mv * t;
+    }
+
+    // FIXME: Using the AdditionalTransform is a complete hack.
+    // This should be done by multiplying the lookup-Matrix with the Node's MV matrix
+    // And then setting the result as the new MV matrix
+    // But that operation needs to be done after all the 'updates'.
+    // So the Director should emit an 'director_after_update' event.
+    // And this object should listen to it
+    _target->setAdditionalTransform(&mv);
+}
+
+//
+// OrbitCamera
+//
+
+OrbitCamera::OrbitCamera()
+: _radius(0.0)
+, _deltaRadius(0.0)
+, _angleZ(0.0)
+, _deltaAngleZ(0.0)
+, _angleX(0.0)
+, _deltaAngleX(0.0)
+, _radZ(0.0)
+, _radDeltaZ(0.0)
+, _radX(0.0)
+, _radDeltaX(0.0)
+{
+}
+OrbitCamera::~OrbitCamera()
+{
+}
+
+OrbitCamera * OrbitCamera::create(float t, float radius, float deltaRadius, float angleZ, float deltaAngleZ, float angleX, float deltaAngleX)
+{
+    OrbitCamera * obitCamera = new (std::nothrow) OrbitCamera();
+    if(obitCamera && obitCamera->initWithDuration(t, radius, deltaRadius, angleZ, deltaAngleZ, angleX, deltaAngleX))
+    {
+        obitCamera->autorelease();
+        return obitCamera;
+    }
+    
+    delete obitCamera;
+    return nullptr;
+}
+
+OrbitCamera* OrbitCamera::clone() const
+{
+    // no copy constructor
+    return OrbitCamera::create(_duration, _radius, _deltaRadius, _angleZ, _deltaAngleZ, _angleX, _deltaAngleX);
+}
+
+bool OrbitCamera::initWithDuration(float t, float radius, float deltaRadius, float angleZ, float deltaAngleZ, float angleX, float deltaAngleX)
+{
+    if ( ActionInterval::initWithDuration(t) )
+    {
+        _radius = radius;
+        _deltaRadius = deltaRadius;
+        _angleZ = angleZ;
+        _deltaAngleZ = deltaAngleZ;
+        _angleX = angleX;
+        _deltaAngleX = deltaAngleX;
+
+        _radDeltaZ = (float)CC_DEGREES_TO_RADIANS(deltaAngleZ);
+        _radDeltaX = (float)CC_DEGREES_TO_RADIANS(deltaAngleX);
+        return true;
+    }
+    return false;
+}
+
+void OrbitCamera::startWithTarget(Node *target)
+{
+    ActionCamera::startWithTarget(target);
+
+    float r, zenith, azimuth;
+    this->sphericalRadius(&r, &zenith, &azimuth);
+    if( std::isnan(_radius) )
+        _radius = r;
+    if( std::isnan(_angleZ) )
+        _angleZ = (float)CC_RADIANS_TO_DEGREES(zenith);
+    if( std::isnan(_angleX) )
+        _angleX = (float)CC_RADIANS_TO_DEGREES(azimuth);
+
+    _radZ = (float)CC_DEGREES_TO_RADIANS(_angleZ);
+    _radX = (float)CC_DEGREES_TO_RADIANS(_angleX);
+}
+
+void OrbitCamera::update(float dt)
+{
+    float r = (_radius + _deltaRadius * dt) * FLT_EPSILON;
+    float za = _radZ + _radDeltaZ * dt;
+    float xa = _radX + _radDeltaX * dt;
+
+    float i = sinf(za) * cosf(xa) * r + _center.x;
+    float j = sinf(za) * sinf(xa) * r + _center.y;
+    float k = cosf(za) * r + _center.z;
+
+    setEye(i,j,k);
+}
+
+void OrbitCamera::sphericalRadius(float *newRadius, float *zenith, float *azimuth)
+{
+    float r; // radius
+    float s;
+
+    float x = _eye.x - _center.x;
+    float y = _eye.y - _center.y;
+    float z = _eye.z - _center.z;
+
+    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= (float)M_PI - asinf(y/s);
+    else
+        *azimuth = asinf(y/s);
+
+    *newRadius = r / FLT_EPSILON;
+}
+
+NS_CC_END

+ 182 - 0
cocos2d/cocos/2d/CCActionCamera.h

@@ -0,0 +1,182 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+
+#ifndef __CCCAMERA_ACTION_H__
+#define __CCCAMERA_ACTION_H__
+
+#include "2d/CCActionInterval.h"
+#include "math/CCMath.h"
+
+NS_CC_BEGIN
+
+class Camera;
+
+/**
+ * @addtogroup actions
+ * @{
+ */
+
+/**
+ *@brief Base class for Camera actions.
+ *@ingroup Actions
+ */
+class CC_DLL ActionCamera : public ActionInterval
+{
+public:
+    /**
+     * @js ctor
+     * @lua new
+     */
+    ActionCamera();
+    /**
+     * @js NA
+     * @lua NA
+     */
+    virtual ~ActionCamera(){};
+
+    // Overrides
+    virtual void startWithTarget(Node *target) override;
+    virtual ActionCamera * reverse() const override;
+    virtual ActionCamera *clone() const override;
+
+    /* Sets the Eye value of the Camera. 
+     * 
+     * @param eye The Eye value of the Camera.
+     * @js NA
+     */
+    void setEye(const Vec3 &eye);
+    void setEye(float x, float y, float z);
+    /* Returns the Eye value of the Camera. 
+     *
+     * @return The Eye value of the Camera.
+     * @js NA
+     */
+    const Vec3& getEye() const { return _eye; }
+    /* Sets the Center value of the Camera. 
+     *
+     * @param center The Center value of the Camera.
+     * @js NA
+     */
+    void setCenter(const Vec3 &center);
+    /* Returns the Center value of the Camera. 
+     *
+     * @return The Center value of the Camera.
+     * @js NA
+     */
+    const Vec3& getCenter() const { return _center; }
+    /* Sets the Up value of the Camera. 
+     *
+     * @param up The Up value of the Camera.
+     * @js NA
+     */
+    void setUp(const Vec3 &up);
+    /* Returns the Up value of the Camera. 
+     *
+     * @return The Up value of the Camera.
+     * @js NA
+     */
+    const Vec3& getUp() const { return _up; }
+
+protected:
+
+    void restore();
+    void updateTransform();
+
+    Vec3 _center;
+    Vec3 _eye;
+    Vec3 _up;
+};
+
+/** @class OrbitCamera
+ *
+ * @brief OrbitCamera action.
+ * Orbits the camera around the center of the screen using spherical coordinates.
+ * @ingroup Actions
+ */
+class CC_DLL OrbitCamera : public ActionCamera
+{
+public:
+    /** Creates a OrbitCamera action with radius, delta-radius,  z, deltaZ, x, deltaX. 
+     *
+     * @param t Duration in seconds.
+     * @param radius The start radius.
+     * @param deltaRadius The delta radius.
+     * @param angleZ The start angle in Z.
+     * @param deltaAngleZ The delta angle in Z.
+     * @param angleX The start angle in X.
+     * @param deltaAngleX The delta angle in X.
+     * @return An OrbitCamera.
+     */
+    static OrbitCamera* create(float t, float radius, float deltaRadius, float angleZ, float deltaAngleZ, float angleX, float deltaAngleX);
+    
+    /** Positions the camera according to spherical coordinates. 
+     *
+     * @param r The spherical radius.
+     * @param zenith The spherical zenith.
+     * @param azimuth The spherical azimuth.
+     */
+    void sphericalRadius(float *r, float *zenith, float *azimuth);
+
+    // Overrides
+    OrbitCamera *clone() const override;
+    virtual void startWithTarget(Node *target) override;
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    /**
+     * @js ctor
+     */
+    OrbitCamera();
+    /**
+     * @js NA
+     * @lua NA
+     */
+    virtual ~OrbitCamera();
+    
+    /** Initializes a OrbitCamera action with radius, delta-radius,  z, deltaZ, x, deltaX. */
+    bool initWithDuration(float t, float radius, float deltaRadius, float angleZ, float deltaAngleZ, float angleX, float deltaAngleX);
+
+protected:
+    float _radius;
+    float _deltaRadius;
+    float _angleZ;
+    float _deltaAngleZ;
+    float _angleX;
+    float _deltaAngleX;
+
+    float _radZ;
+    float _radDeltaZ;
+    float _radX;
+    float _radDeltaX;
+};
+
+// end of actions group
+/// @}
+
+NS_CC_END
+
+#endif //__CCCAMERA_ACTION_H__

+ 555 - 0
cocos2d/cocos/2d/CCActionCatmullRom.cpp

@@ -0,0 +1,555 @@
+/*
+ * Copyright (c) 2008 Radu Gruian
+ * Copyright (c) 2011 Vit Valentin
+ * Copyright (c) 2012 cocos2d-x.org
+ * Copyright (c) 2013-2017 Chukong Technologies Inc.
+ *
+ * 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.
+ *
+ *
+ * Original code by Radu Gruian: http://www.codeproject.com/Articles/30838/Overhauser-Catmull-Rom-Splines-for-Camera-Animatio.So
+ *
+ * Adapted to cocos2d-x by Vit Valentin
+ *
+ * Adapted from cocos2d-x to cocos2d-iphone by Ricardo Quesada
+ */
+#include "base/ccMacros.h"
+#include "2d/CCActionCatmullRom.h"
+#include "2d/CCNode.h"
+
+using namespace std;
+
+NS_CC_BEGIN;
+
+/*
+ *  Implementation of PointArray
+ */
+
+PointArray* PointArray::create(ssize_t capacity)
+{
+    PointArray* pointArray = new (std::nothrow) PointArray();
+    if (pointArray && pointArray->initWithCapacity(capacity))
+    {
+        pointArray->autorelease();
+        return pointArray;
+    }
+
+    delete pointArray;
+    return nullptr;
+}
+
+bool PointArray::initWithCapacity(ssize_t capacity)
+{
+    _controlPoints = new (std::nothrow) vector<Vec2*>();
+    if (capacity > 0) {
+        _controlPoints->reserve(capacity);
+    }
+    
+    return true;
+}
+
+PointArray* PointArray::clone() const
+{
+    vector<Vec2*> *newArray = new (std::nothrow) vector<Vec2*>();
+    for (auto& controlPoint : *_controlPoints)
+    {
+        newArray->push_back(new Vec2(controlPoint->x, controlPoint->y));
+    }
+    
+    PointArray *points = new (std::nothrow) PointArray();
+    points->initWithCapacity(10);
+    points->setControlPoints(newArray);
+
+    points->autorelease();
+    return points;
+}
+
+PointArray::~PointArray()
+{
+    CCLOGINFO("deallocing PointArray: %p", this);
+
+    for (auto& controlPoint : *_controlPoints)
+    {
+        delete controlPoint;
+    }
+    delete _controlPoints;
+}
+
+PointArray::PointArray() :_controlPoints(nullptr){}
+
+const std::vector<Vec2*>* PointArray::getControlPoints() const
+{
+    return _controlPoints;
+}
+
+void PointArray::setControlPoints(vector<Vec2*> *controlPoints)
+{
+    CCASSERT(controlPoints != nullptr, "control points should not be nullptr");
+    
+    // delete old points
+    vector<Vec2*>::iterator iter;
+    for (auto& controlPoint : *_controlPoints)
+    {
+        delete controlPoint;
+    }
+    delete _controlPoints;
+    
+    _controlPoints = controlPoints;
+}
+
+void PointArray::addControlPoint(const Vec2& controlPoint)
+{    
+    _controlPoints->push_back(new Vec2(controlPoint.x, controlPoint.y));
+}
+
+void PointArray::insertControlPoint(Vec2 &controlPoint, ssize_t index)
+{
+    Vec2 *temp = new (std::nothrow) Vec2(controlPoint.x, controlPoint.y);
+    _controlPoints->insert(_controlPoints->begin() + index, temp);
+}
+
+Vec2 PointArray::getControlPointAtIndex(ssize_t index)
+{
+    index = MIN(static_cast<ssize_t>(_controlPoints->size())-1, MAX(index, 0));
+    return *(_controlPoints->at(index));
+}
+
+void PointArray::replaceControlPoint(cocos2d::Vec2 &controlPoint, ssize_t index)
+{
+    Vec2 *temp = _controlPoints->at(index);
+    temp->x = controlPoint.x;
+    temp->y = controlPoint.y;
+}
+
+void PointArray::removeControlPointAtIndex(ssize_t index)
+{
+    vector<Vec2*>::iterator iter = _controlPoints->begin() + index;
+    Vec2* removedPoint = *iter;
+    _controlPoints->erase(iter);
+    delete removedPoint;
+}
+
+ssize_t PointArray::count() const
+{
+    return _controlPoints->size();
+}
+
+PointArray* PointArray::reverse() const
+{
+    vector<Vec2*> *newArray = new (std::nothrow) vector<Vec2*>();
+    Vec2 *point = nullptr;
+    for (auto iter = _controlPoints->rbegin(), iterRend = _controlPoints->rend(); iter != iterRend; ++iter)
+    {
+        point = *iter;
+        newArray->push_back(new Vec2(point->x, point->y));
+    }
+    PointArray *config = PointArray::create(0);
+    config->setControlPoints(newArray);
+    
+    return config;
+}
+
+void PointArray::reverseInline()
+{
+    size_t l = _controlPoints->size();
+    Vec2 *p1 = nullptr;
+    Vec2 *p2 = nullptr;
+    float x, y;
+    for (size_t i = 0; i < l/2; ++i)
+    {
+        p1 = _controlPoints->at(i);
+        p2 = _controlPoints->at(l-i-1);
+        
+        x = p1->x;
+        y = p1->y;
+        
+        p1->x = p2->x;
+        p1->y = p2->y;
+        
+        p2->x = x;
+        p2->y = y;
+    }
+}
+
+// CatmullRom Spline formula:
+Vec2 ccCardinalSplineAt(Vec2 &p0, Vec2 &p1, Vec2 &p2, Vec2 &p3, float tension, float t)
+{
+    float t2 = t * t;
+    float t3 = t2 * t;
+    
+    /*
+     * Formula: s(-ttt + 2tt - t)P1 + s(-ttt + tt)P2 + (2ttt - 3tt + 1)P2 + s(ttt - 2tt + t)P3 + (-2ttt + 3tt)P3 + s(ttt - tt)P4
+     */
+    float s = (1 - tension) / 2;
+
+    float b1 = s * ((-t3 + (2 * t2)) - t);                      // s(-t3 + 2 t2 - t)P1
+    float b2 = s * (-t3 + t2) + (2 * t3 - 3 * t2 + 1);          // s(-t3 + t2)P2 + (2 t3 - 3 t2 + 1)P2
+    float b3 = s * (t3 - 2 * t2 + t) + (-2 * t3 + 3 * t2);      // s(t3 - 2 t2 + t)P3 + (-2 t3 + 3 t2)P3
+    float b4 = s * (t3 - t2);                                   // s(t3 - t2)P4
+    
+    float x = (p0.x*b1 + p1.x*b2 + p2.x*b3 + p3.x*b4);
+    float y = (p0.y*b1 + p1.y*b2 + p2.y*b3 + p3.y*b4);
+
+    return Vec2(x,y);
+}
+
+/* Implementation of CardinalSplineTo
+ */
+
+CardinalSplineTo* CardinalSplineTo::create(float duration, cocos2d::PointArray *points, float tension)
+{
+    CardinalSplineTo *ret = new (std::nothrow) CardinalSplineTo();
+    if (ret)
+    {
+        if (ret->initWithDuration(duration, points, tension))
+        {
+            ret->autorelease();
+        }
+        else 
+        {
+            CC_SAFE_RELEASE_NULL(ret);
+        }
+    }
+
+    return ret;
+}
+
+bool CardinalSplineTo::initWithDuration(float duration, cocos2d::PointArray *points, float tension)
+{
+    CCASSERT(points->count() > 0, "Invalid configuration. It must at least have one control point");
+
+    if (ActionInterval::initWithDuration(duration))
+    {
+        this->setPoints(points);
+        this->_tension = tension;
+        
+        return true;
+    }
+    
+    return false;
+}
+
+CardinalSplineTo::~CardinalSplineTo()
+{
+    CC_SAFE_RELEASE_NULL(_points);
+}
+
+CardinalSplineTo::CardinalSplineTo()
+: _points(nullptr)
+, _deltaT(0.f)
+, _tension(0.f)
+{
+}
+
+void CardinalSplineTo::startWithTarget(cocos2d::Node *target)
+{
+    ActionInterval::startWithTarget(target);
+
+//    _deltaT = (float) 1 / _points->count();
+    
+    // Issue #1441
+    _deltaT = (float) 1 / (_points->count() - 1);
+
+    _previousPosition = target->getPosition();
+    _accumulatedDiff.setZero();
+}
+
+CardinalSplineTo* CardinalSplineTo::clone() const
+{
+    // no copy constructor
+    auto a = new (std::nothrow) CardinalSplineTo();
+    a->initWithDuration(this->_duration, this->_points->clone(), this->_tension);
+    a->autorelease();
+    return a;
+}
+
+void CardinalSplineTo::update(float time)
+{
+    ssize_t p;
+    float lt;
+
+    // eg.
+    // p..p..p..p..p..p..p
+    // 1..2..3..4..5..6..7
+    // want p to be 1, 2, 3, 4, 5, 6
+    if (time == 1)
+    {
+        p = _points->count() - 1;
+        lt = 1;
+    }
+    else 
+    {
+        p = time / _deltaT;
+        lt = (time - _deltaT * (float)p) / _deltaT;
+    }
+    
+    // Interpolate
+    Vec2 pp0 = _points->getControlPointAtIndex(p-1);
+    Vec2 pp1 = _points->getControlPointAtIndex(p+0);
+    Vec2 pp2 = _points->getControlPointAtIndex(p+1);
+    Vec2 pp3 = _points->getControlPointAtIndex(p+2);
+
+    Vec2 newPos = ccCardinalSplineAt(pp0, pp1, pp2, pp3, _tension, lt);
+
+#if CC_ENABLE_STACKABLE_ACTIONS
+    // Support for stacked actions
+    Node *node = _target;
+    Vec2 diff = node->getPosition() - _previousPosition;
+    if( diff.x !=0 || diff.y != 0 )
+    {
+        _accumulatedDiff = _accumulatedDiff + diff;
+        newPos = newPos + _accumulatedDiff;
+    }
+#endif
+    
+    this->updatePosition(newPos);
+}
+
+void CardinalSplineTo::updatePosition(cocos2d::Vec2 &newPos)
+{
+    _target->setPosition(newPos);
+    _previousPosition = newPos;
+}
+
+CardinalSplineTo* CardinalSplineTo::reverse() const
+{
+    PointArray *pReverse = _points->reverse();
+    
+    return CardinalSplineTo::create(_duration, pReverse, _tension);
+}
+
+/* CardinalSplineBy
+ */
+
+CardinalSplineBy* CardinalSplineBy::create(float duration, cocos2d::PointArray *points, float tension)
+{
+    CardinalSplineBy *ret = new (std::nothrow) CardinalSplineBy();
+    if (ret)
+    {
+        if (ret->initWithDuration(duration, points, tension))
+        {
+            ret->autorelease();
+        }
+        else 
+        {
+            CC_SAFE_RELEASE_NULL(ret);
+        }
+    }
+
+    return ret;
+}
+
+CardinalSplineBy::CardinalSplineBy() : _startPosition(0,0)
+{
+}
+
+void CardinalSplineBy::updatePosition(cocos2d::Vec2 &newPos)
+{
+    Vec2 p = newPos + _startPosition;
+    _target->setPosition(p);
+    _previousPosition = p;
+}
+
+CardinalSplineBy* CardinalSplineBy::reverse() const
+{
+    PointArray *copyConfig = _points->clone();
+
+    //
+    // convert "absolutes" to "diffs"
+    //
+    Vec2 p = copyConfig->getControlPointAtIndex(0);
+    for (ssize_t i = 1; i < copyConfig->count(); ++i)
+    {
+        Vec2 current = copyConfig->getControlPointAtIndex(i);
+        Vec2 diff = current - p;
+        copyConfig->replaceControlPoint(diff, i);
+        
+        p = current;
+    }
+
+    // convert to "diffs" to "reverse absolute"
+
+    PointArray *pReverse = copyConfig->reverse();
+
+    // 1st element (which should be 0,0) should be here too
+    
+    p = pReverse->getControlPointAtIndex(pReverse->count()-1);
+    pReverse->removeControlPointAtIndex(pReverse->count()-1);
+    
+    p = -p;
+    pReverse->insertControlPoint(p, 0);
+    
+    for (ssize_t i = 1; i < pReverse->count(); ++i)
+    {
+        Vec2 current = pReverse->getControlPointAtIndex(i);
+        current = -current;
+        Vec2 abs = current + p;
+        pReverse->replaceControlPoint(abs, i);
+        
+        p = abs;
+    }
+
+    return CardinalSplineBy::create(_duration, pReverse, _tension);
+}
+
+void CardinalSplineBy::startWithTarget(cocos2d::Node *target)
+{    
+    CardinalSplineTo::startWithTarget(target);
+    _startPosition = target->getPosition();
+}
+
+CardinalSplineBy* CardinalSplineBy::clone() const
+{
+    // no copy constructor
+    auto a = new (std::nothrow) CardinalSplineBy();
+    a->initWithDuration(this->_duration, this->_points->clone(), this->_tension);
+    a->autorelease();
+    return a;
+}
+
+/* CatmullRomTo
+ */
+
+CatmullRomTo* CatmullRomTo::create(float dt, cocos2d::PointArray *points)
+{
+    CatmullRomTo *ret = new (std::nothrow) CatmullRomTo();
+    if (ret)
+    {
+        if (ret->initWithDuration(dt, points))
+        {
+            ret->autorelease();
+        }
+        else 
+        {
+            CC_SAFE_RELEASE_NULL(ret);
+        }
+    }
+
+    return ret;
+}
+
+bool CatmullRomTo::initWithDuration(float dt, cocos2d::PointArray *points)
+{
+    if (CardinalSplineTo::initWithDuration(dt, points, 0.5f))
+    {
+        return true;
+    }
+    
+    return false;
+}
+
+CatmullRomTo* CatmullRomTo::clone() const
+{
+    // no copy constructor
+    auto a = new (std::nothrow) CatmullRomTo();
+    a->initWithDuration(this->_duration, this->_points->clone());
+    a->autorelease();
+    return a;
+}
+
+CatmullRomTo* CatmullRomTo::reverse() const
+{
+    PointArray *reverse = _points->reverse();
+    return CatmullRomTo::create(_duration, reverse);
+}
+
+
+/* CatmullRomBy
+ */
+
+CatmullRomBy* CatmullRomBy::create(float dt, cocos2d::PointArray *points)
+{
+    CatmullRomBy *ret = new (std::nothrow) CatmullRomBy();
+    if (ret)
+    {
+        if (ret->initWithDuration(dt, points))
+        {
+            ret->autorelease();
+        }
+        else 
+        {
+            CC_SAFE_RELEASE_NULL(ret);
+        }
+    }
+
+    return ret;
+}
+
+bool CatmullRomBy::initWithDuration(float dt, cocos2d::PointArray *points)
+{
+    if (CardinalSplineTo::initWithDuration(dt, points, 0.5f))
+    {
+        return true;
+    }
+    
+    return false;
+}
+
+CatmullRomBy* CatmullRomBy::clone() const
+{
+    // no copy constructor
+    auto a = new (std::nothrow) CatmullRomBy();
+    a->initWithDuration(this->_duration, this->_points->clone());
+    a->autorelease();
+    return a;
+}
+
+CatmullRomBy* CatmullRomBy::reverse() const
+{
+    PointArray *copyConfig = _points->clone();
+
+    //
+    // convert "absolutes" to "diffs"
+    //
+    Vec2 p = copyConfig->getControlPointAtIndex(0);
+    for (ssize_t i = 1; i < copyConfig->count(); ++i)
+    {
+        Vec2 current = copyConfig->getControlPointAtIndex(i);
+        Vec2 diff = current - p;
+        copyConfig->replaceControlPoint(diff, i);
+
+        p = current;
+    }
+
+    // convert to "diffs" to "reverse absolute"
+
+    PointArray *reverse = copyConfig->reverse();
+
+    // 1st element (which should be 0,0) should be here too
+
+    p = reverse->getControlPointAtIndex(reverse->count()-1);
+    reverse->removeControlPointAtIndex(reverse->count()-1);
+
+    p = -p;
+    reverse->insertControlPoint(p, 0);
+
+    for (ssize_t i = 1; i < reverse->count(); ++i)
+    {
+        Vec2 current = reverse->getControlPointAtIndex(i);
+        current = -current;
+        Vec2 abs = current + p;
+        reverse->replaceControlPoint(abs, i);
+
+        p = abs;
+    }
+
+    return CatmullRomBy::create(_duration, reverse);
+}
+
+NS_CC_END;

+ 347 - 0
cocos2d/cocos/2d/CCActionCatmullRom.h

@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2008 Radu Gruian
+ * Copyright (c) 2011 Vit Valentin
+ * Copyright (c) 2012 cocos2d-x.org
+ * Copyright (c) 2013-2017 Chukong Technologies Inc.
+ *
+ *
+ * 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.
+ *
+ *
+ * Original code by Radu Gruian: http://www.codeproject.com/Articles/30838/Overhauser-Catmull-Rom-Splines-for-Camera-Animatio.So
+ *
+ * Adapted to cocos2d-x by Vit Valentin
+ *
+ * Adapted from cocos2d-x to cocos2d-iphone by Ricardo Quesada
+ */
+
+
+#ifndef __CCACTION_CATMULLROM_H__
+#define __CCACTION_CATMULLROM_H__
+
+#include <vector>
+
+#include "2d/CCActionInterval.h"
+#include "math/CCGeometry.h"
+
+NS_CC_BEGIN;
+
+class Node;
+
+/**
+ * @addtogroup actions
+ * @{
+ */
+
+/** An Array that contain control points.
+ * Used by CardinalSplineTo and (By) and CatmullRomTo (and By) actions.
+ * @ingroup Actions
+ * @js NA
+ */
+class CC_DLL PointArray : public Ref, public Clonable
+{
+public:
+
+    /** Creates and initializes a Points array with capacity.
+     * @js NA
+     * @param capacity The size of the array.
+     */
+    static PointArray* create(ssize_t capacity);
+
+    /**
+     * @js NA
+     * @lua NA
+     */
+    virtual ~PointArray();
+    /**
+     * @js NA
+     * @lua NA
+     */
+    PointArray();
+
+    /** Initializes a Catmull Rom config with a capacity hint.
+     *
+     * @js NA
+     * @param capacity The size of the array.
+     * @return True.
+     */
+    bool initWithCapacity(ssize_t capacity);
+
+    /** Appends a control point.
+     *
+     * @js NA
+     * @param controlPoint A control point.
+     */
+    void addControlPoint(const Vec2& controlPoint);
+
+    /** Inserts a controlPoint at index.
+     *
+     * @js NA
+     * @param controlPoint A control point.
+     * @param index Insert the point to array in index.
+     */
+    void insertControlPoint(Vec2 &controlPoint, ssize_t index);
+
+    /** Replaces an existing controlPoint at index.
+     *
+     * @js NA
+     * @param controlPoint A control point.
+     * @param index Replace the point to array in index.
+     */
+    void replaceControlPoint(Vec2 &controlPoint, ssize_t index);
+
+    /** Get the value of a controlPoint at a given index.
+     *
+     * @js NA
+     * @param index Get the point in index.
+     * @return A Vec2.
+     */
+    Vec2 getControlPointAtIndex(ssize_t index);
+
+    /** Deletes a control point at a given index
+     *
+     * @js NA
+     * @param index Remove the point in index.
+     */
+    void removeControlPointAtIndex(ssize_t index);
+
+    /** Returns the number of objects of the control point array.
+     *
+     * @js NA
+     * @return The number of objects of the control point array.
+     */
+    ssize_t count() const;
+
+    /** Returns a new copy of the array reversed. User is responsible for releasing this copy.
+     *
+     * @js NA
+     * @return A new copy of the array reversed.
+     */
+    PointArray* reverse() const;
+
+    /** Reverse the current control point array inline, without generating a new one.
+     * @js NA
+     */
+    void reverseInline();
+    /**
+     * @js NA
+     * @lua NA
+     */
+    virtual PointArray* clone() const;
+    /**
+     * @js NA
+     */
+    const std::vector<Vec2*>* getControlPoints() const;
+    /**
+     * @js NA
+     */
+    void setControlPoints(std::vector<Vec2*> *controlPoints);
+private:
+    /** Array that contains the control points. */
+    std::vector<Vec2*> *_controlPoints;
+};
+
+/** @class CardinalSplineTo
+ * Cardinal Spline path.
+ * http://en.wikipedia.org/wiki/Cubic_Hermite_spline#Cardinal_spline
+ * @ingroup Actions
+ */
+class CC_DLL CardinalSplineTo : public ActionInterval
+{
+public:
+
+    /** Creates an action with a Cardinal Spline array of points and tension.
+     * @param duration In seconds.
+     * @param points An PointArray.
+     * @param tension Goodness of fit.
+     * @code
+     * When this function bound to js or lua,the input params are changed.
+     * In js: var create(var t,var table)
+     * In lua: local create(local t, local table)
+     * @endcode
+     */
+    static CardinalSplineTo* create(float duration, PointArray* points, float tension);
+    /**
+     * @js NA
+     * @lua NA
+     */
+    virtual ~CardinalSplineTo();
+    /**
+     * @js ctor
+     * @lua NA
+     */
+    CardinalSplineTo();
+
+    /** 
+     * Initializes the action with a duration and an array of points.
+     *
+     * @param duration In seconds.
+     * @param points An PointArray.
+     * @param tension Goodness of fit.
+     */
+    bool initWithDuration(float duration, PointArray* points, float tension);
+    /** It will update the target position and change the _previousPosition to newPos
+     *
+     * @param newPos The new position.
+     */
+    virtual void updatePosition(Vec2 &newPos);
+    /** Return a PointArray.
+     *
+     * @return A PointArray.
+     */
+    PointArray* getPoints() { return _points; }
+    /**
+     * @js NA
+     * @lua NA
+     */
+    void setPoints(PointArray* points)
+    {
+        CC_SAFE_RETAIN(points);
+        CC_SAFE_RELEASE(_points);
+        _points = points;
+    }
+
+    // Overrides
+    virtual CardinalSplineTo *clone() const override;
+    virtual CardinalSplineTo* reverse() const override;
+    virtual void startWithTarget(Node *target) override;
+    
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+
+protected:
+    /** Array of control points */
+    PointArray *_points;
+    float _deltaT;
+    float _tension;
+    Vec2 _previousPosition;
+    Vec2 _accumulatedDiff;
+};
+
+/** @class CardinalSplineBy
+ * Cardinal Spline path.
+ * http://en.wikipedia.org/wiki/Cubic_Hermite_spline#Cardinal_spline
+ * @ingroup Actions
+ */
+class CC_DLL CardinalSplineBy : public CardinalSplineTo
+{
+public:
+
+    /** Creates an action with a Cardinal Spline array of points and tension.
+     * @code
+     * When this function bound to js or lua,the input params are changed.
+     * In js: var create(var t,var table).
+     * In lua: local create(local t, local table).
+     * @param duration In seconds.
+     * @param point An PointArray.
+     * @param tension Goodness of fit.
+     * @endcode
+     */
+    static CardinalSplineBy* create(float duration, PointArray* points, float tension);
+
+    CardinalSplineBy();
+
+    // Overrides
+    virtual void startWithTarget(Node *target) override;
+    virtual void updatePosition(Vec2 &newPos) override;
+    virtual CardinalSplineBy *clone() const override;
+    virtual CardinalSplineBy* reverse() const override;
+
+protected:
+    Vec2 _startPosition;
+};
+
+/** @class CatmullRomTo
+ * An action that moves the target with a CatmullRom curve to a destination point.
+ * A Catmull Rom is a Cardinal Spline with a tension of 0.5.
+ * http://en.wikipedia.org/wiki/Cubic_Hermite_spline#Catmull.E2.80.93Rom_spline
+ * @ingroup Actions
+ */
+class CC_DLL CatmullRomTo : public CardinalSplineTo
+{
+public:
+
+    /** Creates an action with a Cardinal Spline array of points and tension.
+     * @param dt In seconds.
+     * @param points An PointArray.
+     * @code
+     * When this function bound to js or lua,the input params are changed.
+     * In js: var create(var dt,var table).
+     * In lua: local create(local dt, local table).
+     * @endcode
+     */
+    static CatmullRomTo* create(float dt, PointArray* points);
+
+    /** 
+     * Initializes the action with a duration and an array of points.
+     *
+     * @param dt In seconds.
+     * @param points An PointArray.
+     */
+    bool initWithDuration(float dt, PointArray* points);
+
+    // Override
+    virtual CatmullRomTo *clone() const override;
+    virtual CatmullRomTo *reverse() const override;
+};
+
+/** @class CatmullRomBy
+ * An action that moves the target with a CatmullRom curve by a certain distance.
+ * A Catmull Rom is a Cardinal Spline with a tension of 0.5.
+ * http://en.wikipedia.org/wiki/Cubic_Hermite_spline#Catmull.E2.80.93Rom_spline
+ * @ingroup Actions
+ */
+class CC_DLL CatmullRomBy : public CardinalSplineBy
+{
+public:
+    /** Creates an action with a Cardinal Spline array of points and tension.
+     * @param dt In seconds.
+     * @param points An PointArray.
+     * @code
+     * When this function bound to js or lua,the input params are changed.
+     * In js: var create(var dt,var table).
+     * In lua: local create(local dt, local table).
+     * @endcode
+     */
+    static CatmullRomBy* create(float dt, PointArray* points);
+
+    /** Initializes the action with a duration and an array of points.
+     *
+     * @param dt In seconds.
+     * @param points An PointArray.
+     */
+    bool initWithDuration(float dt, PointArray* points);
+
+    // Override
+    virtual CatmullRomBy *clone() const override;
+    virtual CatmullRomBy *reverse() const override;
+
+};
+
+/** Returns the Cardinal Spline position for a given set of control points, tension and time */
+extern CC_DLL Vec2 ccCardinalSplineAt(Vec2 &p0, Vec2 &p1, Vec2 &p2, Vec2 &p3, float tension, float t);
+
+// end of actions group
+/// @}
+
+NS_CC_END;
+
+#endif // __CCACTION_CATMULLROM_H__

+ 324 - 0
cocos2d/cocos/2d/CCActionEase.cpp

@@ -0,0 +1,324 @@
+/****************************************************************************
+Copyright (c) 2008-2009 Jason Booth
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+
+/*
+ * Elastic, Back and Bounce actions based on code from:
+ * http://github.com/NikhilK/silverlightfx/
+ *
+ * by http://github.com/NikhilK
+ */
+
+#include "2d/CCActionEase.h"
+#include "2d/CCTweenFunction.h"
+
+NS_CC_BEGIN
+
+#ifndef M_PI_X_2
+#define M_PI_X_2 (float)M_PI * 2.0f
+#endif
+
+//
+// EaseAction
+//
+
+bool ActionEase::initWithAction(ActionInterval *action)
+{
+    CCASSERT(action != nullptr, "action couldn't be nullptr!");
+    if (action == nullptr)
+    {
+        return false;
+    }
+
+    if (ActionInterval::initWithDuration(action->getDuration()))
+    {
+        _inner = action;
+        action->retain();
+
+        return true;
+    }
+
+    return false;
+}
+
+ActionEase::~ActionEase(void)
+{
+    CC_SAFE_RELEASE(_inner);
+}
+
+void ActionEase::startWithTarget(Node *target)
+{
+    if (target && _inner)
+    {
+        ActionInterval::startWithTarget(target);
+        _inner->startWithTarget(_target);
+    }
+    else
+    {
+        log("ActionEase::startWithTarget error: target or _inner is nullptr!");
+    }
+}
+
+void ActionEase::stop(void)
+{
+    if (_inner)
+        _inner->stop();
+    
+    ActionInterval::stop();
+}
+
+void ActionEase::update(float time)
+{
+    _inner->update(time);
+}
+
+ActionInterval* ActionEase::getInnerAction()
+{
+    return _inner;
+}
+
+//
+// EaseRateAction
+//
+
+EaseRateAction* EaseRateAction::create(ActionInterval* action, float rate)
+{
+    CCASSERT(action != nullptr, "action cannot be nullptr!");
+
+    EaseRateAction *easeRateAction = new (std::nothrow) EaseRateAction();
+    if (easeRateAction && easeRateAction->initWithAction(action, rate))
+    {
+        easeRateAction->autorelease();
+        return easeRateAction;
+    }
+
+    CC_SAFE_DELETE(easeRateAction);
+    return nullptr;
+}
+
+bool EaseRateAction::initWithAction(ActionInterval *action, float rate)
+{
+    if (ActionEase::initWithAction(action))
+    {
+        _rate = rate;
+        return true;
+    }
+
+    return false;
+}
+
+//
+// NOTE: Converting these macros into Templates is desirable, but please see
+// issue #16159 [https://github.com/cocos2d/cocos2d-x/pull/16159] for further info
+//
+#define EASE_TEMPLATE_IMPL(CLASSNAME, TWEEN_FUNC, REVERSE_CLASSNAME) \
+CLASSNAME* CLASSNAME::create(cocos2d::ActionInterval *action) \
+{ \
+    CLASSNAME *ease = new (std::nothrow) CLASSNAME(); \
+    if (ease) \
+    { \
+        if (ease->initWithAction(action)) \
+            ease->autorelease(); \
+        else \
+            CC_SAFE_RELEASE_NULL(ease); \
+    } \
+    return ease; \
+} \
+CLASSNAME* CLASSNAME::clone() const \
+{ \
+    if(_inner) return CLASSNAME::create(_inner->clone()); \
+    return nullptr; \
+} \
+void CLASSNAME::update(float time) { \
+    _inner->update(TWEEN_FUNC(time)); \
+} \
+ActionEase* CLASSNAME::reverse() const { \
+    return REVERSE_CLASSNAME::create(_inner->reverse()); \
+}
+
+EASE_TEMPLATE_IMPL(EaseExponentialIn, tweenfunc::expoEaseIn, EaseExponentialOut);
+EASE_TEMPLATE_IMPL(EaseExponentialOut, tweenfunc::expoEaseOut, EaseExponentialIn);
+EASE_TEMPLATE_IMPL(EaseExponentialInOut, tweenfunc::expoEaseInOut, EaseExponentialInOut);
+EASE_TEMPLATE_IMPL(EaseSineIn, tweenfunc::sineEaseIn, EaseSineOut);
+EASE_TEMPLATE_IMPL(EaseSineOut, tweenfunc::sineEaseOut, EaseSineIn);
+EASE_TEMPLATE_IMPL(EaseSineInOut, tweenfunc::sineEaseInOut, EaseSineInOut);
+EASE_TEMPLATE_IMPL(EaseBounceIn, tweenfunc::bounceEaseIn, EaseBounceOut);
+EASE_TEMPLATE_IMPL(EaseBounceOut, tweenfunc::bounceEaseOut, EaseBounceIn);
+EASE_TEMPLATE_IMPL(EaseBounceInOut, tweenfunc::bounceEaseInOut, EaseBounceInOut);
+EASE_TEMPLATE_IMPL(EaseBackIn, tweenfunc::backEaseIn, EaseBackOut);
+EASE_TEMPLATE_IMPL(EaseBackOut, tweenfunc::backEaseOut, EaseBackIn);
+EASE_TEMPLATE_IMPL(EaseBackInOut, tweenfunc::backEaseInOut, EaseBackInOut);
+EASE_TEMPLATE_IMPL(EaseQuadraticActionIn, tweenfunc::quadraticIn, EaseQuadraticActionIn);
+EASE_TEMPLATE_IMPL(EaseQuadraticActionOut, tweenfunc::quadraticOut, EaseQuadraticActionOut);
+EASE_TEMPLATE_IMPL(EaseQuadraticActionInOut, tweenfunc::quadraticInOut, EaseQuadraticActionInOut);
+EASE_TEMPLATE_IMPL(EaseQuarticActionIn, tweenfunc::quartEaseIn, EaseQuarticActionIn);
+EASE_TEMPLATE_IMPL(EaseQuarticActionOut, tweenfunc::quartEaseOut, EaseQuarticActionOut);
+EASE_TEMPLATE_IMPL(EaseQuarticActionInOut, tweenfunc::quartEaseInOut, EaseQuarticActionInOut);
+EASE_TEMPLATE_IMPL(EaseQuinticActionIn, tweenfunc::quintEaseIn, EaseQuinticActionIn);
+EASE_TEMPLATE_IMPL(EaseQuinticActionOut, tweenfunc::quintEaseOut, EaseQuinticActionOut);
+EASE_TEMPLATE_IMPL(EaseQuinticActionInOut, tweenfunc::quintEaseInOut, EaseQuinticActionInOut);
+EASE_TEMPLATE_IMPL(EaseCircleActionIn, tweenfunc::circEaseIn, EaseCircleActionIn);
+EASE_TEMPLATE_IMPL(EaseCircleActionOut, tweenfunc::circEaseOut, EaseCircleActionOut);
+EASE_TEMPLATE_IMPL(EaseCircleActionInOut, tweenfunc::circEaseInOut, EaseCircleActionInOut);
+EASE_TEMPLATE_IMPL(EaseCubicActionIn, tweenfunc::cubicEaseIn, EaseCubicActionIn);
+EASE_TEMPLATE_IMPL(EaseCubicActionOut, tweenfunc::cubicEaseOut, EaseCubicActionOut);
+EASE_TEMPLATE_IMPL(EaseCubicActionInOut, tweenfunc::cubicEaseInOut, EaseCubicActionInOut);
+
+//
+// NOTE: Converting these macros into Templates is desirable, but please see
+// issue #16159 [https://github.com/cocos2d/cocos2d-x/pull/16159] for further info
+//
+#define EASERATE_TEMPLATE_IMPL(CLASSNAME, TWEEN_FUNC) \
+CLASSNAME* CLASSNAME::create(cocos2d::ActionInterval *action, float rate) \
+{ \
+    CLASSNAME *ease = new (std::nothrow) CLASSNAME(); \
+    if (ease) \
+    { \
+        if (ease->initWithAction(action, rate)) \
+            ease->autorelease(); \
+        else \
+            CC_SAFE_RELEASE_NULL(ease); \
+    } \
+    return ease; \
+} \
+CLASSNAME* CLASSNAME::clone() const \
+{ \
+    if(_inner) return CLASSNAME::create(_inner->clone(), _rate); \
+    return nullptr; \
+} \
+void CLASSNAME::update(float time) { \
+    _inner->update(TWEEN_FUNC(time, _rate)); \
+} \
+EaseRateAction* CLASSNAME::reverse() const { \
+    return CLASSNAME::create(_inner->reverse(), 1.f / _rate); \
+}
+
+// NOTE: the original code used the same class for the `reverse()` method
+EASERATE_TEMPLATE_IMPL(EaseIn, tweenfunc::easeIn);
+EASERATE_TEMPLATE_IMPL(EaseOut, tweenfunc::easeOut);
+EASERATE_TEMPLATE_IMPL(EaseInOut, tweenfunc::easeInOut);
+
+//
+// EaseElastic
+//
+
+bool EaseElastic::initWithAction(ActionInterval *action, float period /* = 0.3f*/)
+{
+    if (ActionEase::initWithAction(action))
+    {
+        _period = period;
+        return true;
+    }
+
+    return false;
+}
+
+//
+// NOTE: Converting these macros into Templates is desirable, but please see
+// issue #16159 [https://github.com/cocos2d/cocos2d-x/pull/16159] for further info
+//
+#define EASEELASTIC_TEMPLATE_IMPL(CLASSNAME, TWEEN_FUNC, REVERSE_CLASSNAME) \
+CLASSNAME* CLASSNAME::create(cocos2d::ActionInterval *action, float period /* = 0.3f*/) \
+{ \
+    CLASSNAME *ease = new (std::nothrow) CLASSNAME(); \
+    if (ease) \
+    { \
+        if (ease->initWithAction(action, period)) \
+            ease->autorelease(); \
+        else \
+            CC_SAFE_RELEASE_NULL(ease); \
+    } \
+    return ease; \
+} \
+CLASSNAME* CLASSNAME::clone() const \
+{ \
+    if(_inner) return CLASSNAME::create(_inner->clone(), _period); \
+    return nullptr; \
+} \
+void CLASSNAME::update(float time) { \
+    _inner->update(TWEEN_FUNC(time, _period)); \
+} \
+EaseElastic* CLASSNAME::reverse() const { \
+    return REVERSE_CLASSNAME::create(_inner->reverse(), _period); \
+}
+
+EASEELASTIC_TEMPLATE_IMPL(EaseElasticIn, tweenfunc::elasticEaseIn, EaseElasticOut);
+EASEELASTIC_TEMPLATE_IMPL(EaseElasticOut, tweenfunc::elasticEaseOut, EaseElasticIn);
+EASEELASTIC_TEMPLATE_IMPL(EaseElasticInOut, tweenfunc::elasticEaseInOut, EaseElasticInOut);
+
+//
+// EaseBezierAction
+//
+
+EaseBezierAction* EaseBezierAction::create(cocos2d::ActionInterval* action)
+{
+    EaseBezierAction *ret = new (std::nothrow) EaseBezierAction();
+    if (ret && ret->initWithAction(action))
+    {
+        ret->autorelease();
+        return ret;
+    }
+
+    delete ret;
+    return nullptr;
+}
+
+void EaseBezierAction::setBezierParamer( float p0, float p1, float p2, float p3)
+{
+    _p0 = p0;
+    _p1 = p1;
+    _p2 = p2;
+    _p3 = p3;
+}
+
+EaseBezierAction* EaseBezierAction::clone() const
+{
+    // no copy constructor
+    if (_inner)
+    {
+        auto ret = EaseBezierAction::create(_inner->clone());
+        if (ret)
+        {
+            ret->setBezierParamer(_p0,_p1,_p2,_p3);
+        }
+        return ret;
+    }
+
+    return nullptr;
+}
+
+void EaseBezierAction::update(float time)
+{
+    _inner->update(tweenfunc::bezieratFunction(_p0,_p1,_p2,_p3,time));
+}
+
+EaseBezierAction* EaseBezierAction::reverse() const
+{
+    EaseBezierAction* reverseAction = EaseBezierAction::create(_inner->reverse());
+    reverseAction->setBezierParamer(_p3,_p2,_p1,_p0);
+    return reverseAction;
+}
+
+NS_CC_END

+ 557 - 0
cocos2d/cocos/2d/CCActionEase.h

@@ -0,0 +1,557 @@
+/****************************************************************************
+Copyright (c) 2008-2009 Jason Booth
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+
+#ifndef __ACTION_CCEASE_ACTION_H__
+#define __ACTION_CCEASE_ACTION_H__
+
+#include "2d/CCActionInterval.h"
+#include "2d/CCTweenFunction.h"
+
+NS_CC_BEGIN
+
+/**
+ * @addtogroup actions
+ * @{
+ */
+
+/**
+ @class ActionEase
+ @brief Base class for Easing actions.
+ @details Ease actions are created from other interval actions.
+ The ease action will change the timeline of the inner action.
+ @ingroup Actions
+ */
+class CC_DLL ActionEase : public ActionInterval
+{
+public:
+    /**
+     @brief Get the pointer of the inner action.
+     @return The pointer of the inner action.
+    */
+    virtual ActionInterval* getInnerAction();
+
+    //
+    // Overrides
+    //
+    virtual void startWithTarget(Node *target) override;
+    virtual void stop() override;
+    virtual void update(float time) override;
+
+CC_CONSTRUCTOR_ACCESS:
+    ActionEase()
+    : _inner(nullptr)
+    {}
+    
+    virtual ~ActionEase();
+    /**
+     @brief Initializes the action.
+     @return Return true when the initialization success, otherwise return false.
+    */
+    bool initWithAction(ActionInterval *action);
+
+protected:
+    /** The inner action */
+    ActionInterval *_inner;
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(ActionEase);
+};
+
+/**
+ @class EaseRateAction
+ @brief Base class for Easing actions with rate parameters
+ @details Ease the inner action with specified rate.
+ @ingroup Actions
+ */
+class CC_DLL EaseRateAction : public ActionEase
+{
+public:
+    static EaseRateAction* create(ActionInterval* action, float rate);
+    /**
+    @brief Set the rate value for the ease rate action.
+    @param rate The value will be set.
+    */
+    void setRate(float rate) { _rate = rate; }
+    /**
+    @brief Get the rate value of the ease rate action.
+    @return Return the rate value of the ease rate action.
+    */
+    float getRate() const { return _rate; }
+
+CC_CONSTRUCTOR_ACCESS:
+    EaseRateAction() {}
+    virtual ~EaseRateAction() {}
+    /**
+     @brief Initializes the action with the inner action and the rate parameter.
+     @param pAction The pointer of the inner action.
+     @param fRate The value of the rate parameter.
+     @return Return true when the initialization success, otherwise return false.
+    */
+    bool initWithAction(ActionInterval *pAction, float fRate);
+
+protected:
+    float _rate;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(EaseRateAction);
+};
+
+//
+// NOTE: Converting these macros into Templates is desirable, but please see
+// issue #16159 [https://github.com/cocos2d/cocos2d-x/pull/16159] for further info
+//
+#define EASE_TEMPLATE_DECL_CLASS(CLASSNAME) \
+class CC_DLL CLASSNAME : public ActionEase \
+{ \
+CC_CONSTRUCTOR_ACCESS: \
+    virtual ~CLASSNAME() { } \
+    CLASSNAME() { } \
+public: \
+    static CLASSNAME* create(ActionInterval* action); \
+    virtual CLASSNAME* clone() const override; \
+    virtual void update(float time) override; \
+    virtual ActionEase* reverse() const override; \
+private: \
+    CC_DISALLOW_COPY_AND_ASSIGN(CLASSNAME); \
+};
+
+/**
+ @class EaseExponentialIn
+ @brief Ease Exponential In action.
+ @details The timeline of inner action will be changed by:
+ \f${ 2 }^{ 10*(time-1) }-1*0.001\f$.
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseExponentialIn);
+
+/**
+ @class EaseExponentialOut
+ @brief Ease Exponential Out
+ @details The timeline of inner action will be changed by:
+ \f$1-{ 2 }^{ -10*(time-1) }\f$.
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseExponentialOut);
+
+/**
+ @class EaseExponentialInOut
+ @brief Ease Exponential InOut
+ @details If time * 2 < 1, the timeline of inner action will be changed by:
+ \f$0.5*{ 2 }^{ 10*(time-1) }\f$.
+ else, the timeline of inner action will be changed by:
+ \f$0.5*(2-{ 2 }^{ -10*(time-1) })\f$.
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseExponentialInOut);
+
+/**
+ @class EaseSineIn
+ @brief Ease Sine In
+ @details The timeline of inner action will be changed by:
+ \f$1-cos(time*\frac { \pi  }{ 2 } )\f$.
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseSineIn);
+
+/**
+ @class EaseSineOut
+ @brief Ease Sine Out
+ @details The timeline of inner action will be changed by:
+ \f$sin(time*\frac { \pi  }{ 2 } )\f$.
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseSineOut);
+
+/**
+ @class EaseSineInOut
+ @brief Ease Sine InOut
+ @details The timeline of inner action will be changed by:
+ \f$-0.5*(cos(\pi *time)-1)\f$.
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseSineInOut);
+
+/**
+ @class EaseBounce
+ @brief EaseBounce abstract class.
+ @since v0.8.2
+ @ingroup Actions
+ */
+class CC_DLL EaseBounce : public ActionEase {};
+
+/**
+ @class EaseBounceIn
+ @brief EaseBounceIn action.
+ @warning This action doesn't use a bijective function.
+ Actions like Sequence might have an unexpected result when used with this action.
+ @since v0.8.2
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseBounceIn);
+
+/**
+ @class EaseBounceOut
+ @brief EaseBounceOut action.
+ @warning This action doesn't use a bijective function.
+ Actions like Sequence might have an unexpected result when used with this action.
+ @since v0.8.2
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseBounceOut);
+
+/**
+ @class EaseBounceInOut
+ @brief EaseBounceInOut action.
+ @warning This action doesn't use a bijective function.
+ Actions like Sequence might have an unexpected result when used with this action.
+ @since v0.8.2
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseBounceInOut);
+
+/**
+ @class EaseBackIn
+ @brief EaseBackIn action.
+ @warning This action doesn't use a bijective function.
+ Actions like Sequence might have an unexpected result when used with this action.
+ @since v0.8.2
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseBackIn);
+
+/**
+ @class EaseBackOut
+ @brief EaseBackOut action.
+ @warning This action doesn't use a bijective function.
+ Actions like Sequence might have an unexpected result when used with this action.
+ @since v0.8.2
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseBackOut);
+
+/**
+ @class EaseBackInOut
+ @brief EaseBackInOut action.
+ @warning This action doesn't use a bijective function.
+ Actions like Sequence might have an unexpected result when used with this action.
+ @since v0.8.2
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseBackInOut);
+
+/**
+ @class EaseQuadraticActionIn
+ @brief Ease Quadratic In
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseQuadraticActionIn);
+
+/**
+ @class EaseQuadraticActionOut
+ @brief Ease Quadratic Out
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseQuadraticActionOut);
+
+/**
+ @class EaseQuadraticActionInOut
+ @brief Ease Quadratic InOut
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseQuadraticActionInOut);
+
+/**
+ @class EaseQuarticActionIn
+ @brief Ease Quartic In
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseQuarticActionIn);
+
+/**
+ @class EaseQuarticActionOut
+ @brief Ease Quartic Out
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseQuarticActionOut);
+
+/**
+ @class EaseQuarticActionInOut
+ @brief Ease Quartic InOut
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseQuarticActionInOut);
+
+/**
+ @class EaseQuinticActionIn
+ @brief Ease Quintic In
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseQuinticActionIn);
+
+/**
+ @class EaseQuinticActionOut
+ @brief Ease Quintic Out
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseQuinticActionOut);
+
+/**
+ @class EaseQuinticActionInOut
+ @brief Ease Quintic InOut
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseQuinticActionInOut);
+
+/**
+ @class EaseCircleActionIn
+ @brief Ease Circle In
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseCircleActionIn);
+
+/**
+ @class EaseCircleActionOut
+ @brief Ease Circle Out
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseCircleActionOut);
+
+/**
+ @class EaseCircleActionInOut
+ @brief Ease Circle InOut
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseCircleActionInOut);
+
+/**
+ @class EaseCubicActionIn
+ @brief Ease Cubic In
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseCubicActionIn);
+
+/**
+ @class EaseCubicActionOut
+ @brief Ease Cubic Out
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseCubicActionOut);
+
+/**
+ @class EaseCubicActionInOut
+ @brief Ease Cubic InOut
+ @ingroup Actions
+ */
+EASE_TEMPLATE_DECL_CLASS(EaseCubicActionInOut);
+
+//
+// NOTE: Converting these macros into Templates is desirable, but please see
+// issue #16159 [https://github.com/cocos2d/cocos2d-x/pull/16159] for further info
+//
+
+#define EASERATE_TEMPLATE_DECL_CLASS(CLASSNAME) \
+class CC_DLL CLASSNAME : public EaseRateAction \
+{ \
+CC_CONSTRUCTOR_ACCESS: \
+    virtual ~CLASSNAME() { } \
+    CLASSNAME() { } \
+public: \
+    static CLASSNAME* create(ActionInterval* action, float rate); \
+    virtual CLASSNAME* clone() const override; \
+    virtual void update(float time) override; \
+    virtual EaseRateAction* reverse() const override; \
+private: \
+    CC_DISALLOW_COPY_AND_ASSIGN(CLASSNAME); \
+};
+
+/**
+ @class EaseIn
+ @brief EaseIn action with a rate.
+ @details The timeline of inner action will be changed by:
+ \f${ time }^{ rate }\f$.
+ @ingroup Actions
+ */
+EASERATE_TEMPLATE_DECL_CLASS(EaseIn);
+
+/**
+ @class EaseOut
+ @brief EaseOut action with a rate.
+ @details The timeline of inner action will be changed by:
+ \f${ time }^ { (1/rate) }\f$.
+ @ingroup Actions
+ */
+EASERATE_TEMPLATE_DECL_CLASS(EaseOut);
+
+/**
+ @class EaseInOut
+ @brief EaseInOut action with a rate
+ @details If time * 2 < 1, the timeline of inner action will be changed by:
+ \f$0.5*{ time }^{ rate }\f$.
+ Else, the timeline of inner action will be changed by:
+ \f$1.0-0.5*{ 2-time }^{ rate }\f$.
+ @ingroup Actions
+ */
+EASERATE_TEMPLATE_DECL_CLASS(EaseInOut);
+
+/**
+ @class EaseElastic
+ @brief Ease Elastic abstract class
+ @since v0.8.2
+ @ingroup Actions
+ */
+class CC_DLL EaseElastic : public ActionEase
+{
+public:
+
+    /**
+     @brief Get period of the wave in radians. Default value is 0.3.
+     @return Return the period of the wave in radians.
+    */
+    float getPeriod() const { return _period; }
+    /**
+     @brief Set period of the wave in radians.
+     @param fPeriod The value will be set.
+    */
+    void setPeriod(float fPeriod) { _period = fPeriod; }
+
+CC_CONSTRUCTOR_ACCESS:
+    EaseElastic() {}
+    virtual ~EaseElastic() {}
+    /**
+     @brief Initializes the action with the inner action and the period in radians.
+     @param action The pointer of the inner action.
+     @param period Period of the wave in radians. Default is 0.3.
+     @return Return true when the initialization success, otherwise return false.
+    */
+    bool initWithAction(ActionInterval *action, float period = 0.3f);
+
+protected:
+    float _period;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(EaseElastic);
+};
+
+//
+// NOTE: Converting these macros into Templates is desirable, but please see
+// issue #16159 [https://github.com/cocos2d/cocos2d-x/pull/16159] for further info
+//
+#define EASEELASTIC_TEMPLATE_DECL_CLASS(CLASSNAME) \
+class CC_DLL CLASSNAME : public EaseElastic \
+{ \
+CC_CONSTRUCTOR_ACCESS: \
+    virtual ~CLASSNAME() { } \
+    CLASSNAME() { } \
+public: \
+    static CLASSNAME* create(ActionInterval* action, float rate = 0.3f); \
+    virtual CLASSNAME* clone() const override; \
+    virtual void update(float time) override; \
+    virtual EaseElastic* reverse() const override; \
+private: \
+    CC_DISALLOW_COPY_AND_ASSIGN(CLASSNAME); \
+};
+
+/**
+ @class EaseElasticIn
+ @brief Ease Elastic In action.
+ @details If time == 0 or time == 1, the timeline of inner action will not be changed.
+ Else, the timeline of inner action will be changed by:
+ \f$-{ 2 }^{ 10*(time-1) }*sin((time-1-\frac { period }{ 4 } )*\pi *2/period)\f$.
+
+ @warning This action doesn't use a bijective function.
+ Actions like Sequence might have an unexpected result when used with this action.
+ @since v0.8.2
+ @ingroup Actions
+ */
+EASEELASTIC_TEMPLATE_DECL_CLASS(EaseElasticIn);
+
+/**
+ @class EaseElasticOut
+ @brief Ease Elastic Out action.
+ @details If time == 0 or time == 1, the timeline of inner action will not be changed.
+ Else, the timeline of inner action will be changed by:
+ \f${ 2 }^{ -10*time }*sin((time-\frac { period }{ 4 } )*\pi *2/period)+1\f$.
+ @warning This action doesn't use a bijective function.
+ Actions like Sequence might have an unexpected result when used with this action.
+ @since v0.8.2
+ @ingroup Actions
+ */
+EASEELASTIC_TEMPLATE_DECL_CLASS(EaseElasticOut);
+
+/**
+ @class EaseElasticInOut
+ @brief Ease Elastic InOut action.
+ @warning This action doesn't use a bijective function.
+ Actions like Sequence might have an unexpected result when used with this action.
+ @since v0.8.2
+ @ingroup Actions
+ */
+EASEELASTIC_TEMPLATE_DECL_CLASS(EaseElasticInOut);
+
+
+/**
+ @class EaseBezierAction
+ @brief Ease Bezier
+ @ingroup Actions
+ */
+class CC_DLL EaseBezierAction : public cocos2d::ActionEase
+{
+public:
+    /**
+     @brief Create the action with the inner action.
+     @param action The pointer of the inner action.
+     @return A pointer of EaseBezierAction action. If creation failed, return nil.
+    */
+    static EaseBezierAction* create(cocos2d::ActionInterval* action);
+
+    virtual void update(float time) override;
+    virtual EaseBezierAction* clone() const override;
+    virtual EaseBezierAction* reverse() const override;
+
+    /**
+     @brief Set the bezier parameters.
+    */
+    virtual void setBezierParamer( float p0, float p1, float p2, float p3);
+
+CC_CONSTRUCTOR_ACCESS:
+    EaseBezierAction() {}
+    virtual ~EaseBezierAction() {}
+
+protected:
+    float _p0;
+    float _p1;
+    float _p2;
+    float _p3;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(EaseBezierAction);
+};
+
+// end of actions group
+/// @}
+
+NS_CC_END
+
+#endif // __ACTION_CCEASE_ACTION_H__

+ 442 - 0
cocos2d/cocos/2d/CCActionGrid.cpp

@@ -0,0 +1,442 @@
+/****************************************************************************
+Copyright (c) 2009      On-Core
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCActionGrid.h"
+
+#include "2d/CCGrid.h"
+#include "2d/CCNodeGrid.h"
+#include "base/CCDirector.h"
+
+NS_CC_BEGIN
+// implementation of GridAction
+
+bool GridAction::initWithDuration(float duration, const Size& gridSize)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _gridSize = gridSize;
+
+        return true;
+    }
+
+    return false;
+}
+
+void GridAction::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    cacheTargetAsGridNode();
+
+    GridBase *targetGrid = _gridNodeTarget->getGrid();
+
+    if (targetGrid && targetGrid->getReuseGrid() > 0)
+    {
+        if (targetGrid->isActive() && targetGrid->getGridSize().width == _gridSize.width
+            && targetGrid->getGridSize().height == _gridSize.height)
+        {
+            targetGrid->reuse();
+        }
+        else
+        {
+            CCASSERT(0, "Invalid grid parameters!");
+        }
+    }
+    else
+    {
+        if (targetGrid && targetGrid->isActive())
+        {
+            targetGrid->setActive(false);
+        }
+
+        auto newgrid = this->getGrid();
+        _gridNodeTarget->setGrid(newgrid);
+        _gridNodeTarget->getGrid()->setActive(true);
+    }
+}
+
+void GridAction::cacheTargetAsGridNode()
+{
+    _gridNodeTarget = dynamic_cast<NodeGrid*> (_target);
+    CCASSERT(_gridNodeTarget, "GridActions can only used on NodeGrid");
+}
+
+GridAction* GridAction::reverse() const
+{
+    // FIXME: This conversion isn't safe.
+    return (GridAction*)ReverseTime::create( this->clone() );
+}
+
+GridBase* GridAction::getGrid()
+{
+    // Abstract class needs implementation
+    CCASSERT(0, "Subclass should implement this method!");
+
+    return nullptr;
+}
+
+// implementation of Grid3DAction
+
+GridBase* Grid3DAction::getGrid()
+{
+    return Grid3D::create(_gridSize, _gridNodeTarget->getGridRect());
+}
+
+Vec3 Grid3DAction::getVertex(const Vec2& position) const
+{
+    Grid3D *g = (Grid3D*)_gridNodeTarget->getGrid();
+    return g->getVertex(position);
+}
+
+Vec3 Grid3DAction::getOriginalVertex(const Vec2& position) const
+{
+    Grid3D *g = (Grid3D*)_gridNodeTarget->getGrid();
+    return g->getOriginalVertex(position);
+}
+
+void Grid3DAction::setVertex(const Vec2& position, const Vec3& vertex)
+{
+    Grid3D *g = (Grid3D*)_gridNodeTarget->getGrid();
+    g->setVertex(position, vertex);
+}
+
+Rect Grid3DAction::getGridRect() const
+{
+    Grid3D *g = (Grid3D*)_gridNodeTarget->getGrid();
+    return g->getGridRect();
+}
+
+// implementation of TiledGrid3DAction
+
+GridBase* TiledGrid3DAction::getGrid(void)
+{
+    return TiledGrid3D::create(_gridSize, _gridNodeTarget->getGridRect());
+}
+
+Quad3 TiledGrid3DAction::getTile(const Vec2& pos) const
+{
+    TiledGrid3D *g = (TiledGrid3D*)_gridNodeTarget->getGrid();
+    return g->getTile(pos);
+}
+
+Quad3 TiledGrid3DAction::getOriginalTile(const Vec2& pos) const
+{
+    TiledGrid3D *g = (TiledGrid3D*)_gridNodeTarget->getGrid();
+    return g->getOriginalTile(pos);
+}
+
+void TiledGrid3DAction::setTile(const Vec2& pos, const Quad3& coords)
+{
+    TiledGrid3D *g = (TiledGrid3D*)_gridNodeTarget->getGrid();
+    return g->setTile(pos, coords);
+}
+
+// implementation AccelDeccelAmplitude
+
+AccelDeccelAmplitude* AccelDeccelAmplitude::create(Action *action, float duration)
+{
+    AccelDeccelAmplitude *ret = new (std::nothrow) AccelDeccelAmplitude();
+    if (ret && ret->initWithAction(action, duration))
+    {
+        ret->autorelease();
+        return ret;
+    }
+
+    delete ret;
+    return nullptr;
+}
+
+bool AccelDeccelAmplitude::initWithAction(Action *action, float duration)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _rate = 1.0f;
+        _other = (ActionInterval*)(action);
+        action->retain();
+
+        return true;
+    }
+
+    return false;
+}
+
+AccelDeccelAmplitude* AccelDeccelAmplitude::clone() const
+{
+    // no copy constructor
+    if (_other)
+        return AccelDeccelAmplitude::create(_other->clone(), _rate);
+    
+    return nullptr;
+}
+
+AccelDeccelAmplitude::~AccelDeccelAmplitude()
+{
+    CC_SAFE_RELEASE(_other);
+}
+
+void AccelDeccelAmplitude::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    _other->startWithTarget(target);
+}
+
+void AccelDeccelAmplitude::update(float time)
+{
+    float f = time * 2;
+
+    if (f > 1)
+    {
+        f -= 1;
+        f = 1 - f;
+    }
+
+    ((AccelDeccelAmplitude*)(_other))->setAmplitudeRate(powf(f, _rate));
+}
+
+AccelDeccelAmplitude* AccelDeccelAmplitude::reverse() const
+{
+    if (_other)
+        return AccelDeccelAmplitude::create(_other->reverse(), _duration);
+    
+    return nullptr;
+}
+
+// implementation of AccelAmplitude
+
+AccelAmplitude* AccelAmplitude::create(Action *action, float duration)
+{
+    AccelAmplitude *ret = new (std::nothrow) AccelAmplitude();
+    if (ret && ret->initWithAction(action, duration))
+    {
+        ret->autorelease();
+        return ret;
+    }
+
+    delete ret;
+    return nullptr;
+}
+
+bool AccelAmplitude::initWithAction(Action *action, float duration)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _rate = 1.0f;
+        _other = (ActionInterval*)(action);
+        action->retain();
+
+        return true;
+    }
+
+    return false;
+}
+
+AccelAmplitude* AccelAmplitude::clone() const
+{
+    // no copy constructor
+    if (_other)
+        return AccelAmplitude::create(_other->clone(), _duration);
+    
+    return nullptr;
+}
+
+AccelAmplitude::~AccelAmplitude()
+{
+    CC_SAFE_DELETE(_other);
+}
+
+void AccelAmplitude::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    _other->startWithTarget(target);
+}
+
+void AccelAmplitude::update(float time)
+{
+    ((AccelAmplitude*)(_other))->setAmplitudeRate(powf(time, _rate));
+    _other->update(time);
+}
+
+AccelAmplitude* AccelAmplitude::reverse() const
+{
+    if (_other)
+        return AccelAmplitude::create(_other->reverse(), _duration);
+    
+    return nullptr;
+}
+
+// DeccelAmplitude
+
+DeccelAmplitude* DeccelAmplitude::create(Action *action, float duration)
+{
+    DeccelAmplitude *ret = new (std::nothrow) DeccelAmplitude();
+    if (ret && ret->initWithAction(action, duration))
+    {
+        ret->autorelease();
+        return ret;
+    }
+
+    delete ret;
+    return nullptr;
+}
+
+bool DeccelAmplitude::initWithAction(Action *action, float duration)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _rate = 1.0f;
+        _other = (ActionInterval*)(action);
+        action->retain();
+
+        return true;
+    }
+
+    return false;
+}
+
+DeccelAmplitude::~DeccelAmplitude()
+{
+    CC_SAFE_RELEASE(_other);
+}
+
+void DeccelAmplitude::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    _other->startWithTarget(target);
+}
+
+void DeccelAmplitude::update(float time)
+{
+    ((DeccelAmplitude*)(_other))->setAmplitudeRate(powf((1 - time), _rate));
+    _other->update(time);
+}
+
+DeccelAmplitude* DeccelAmplitude::clone() const
+{
+    // no copy constructor
+    if (_other)
+        return DeccelAmplitude::create(_other->clone(), _duration);
+    
+    return nullptr;
+}
+
+DeccelAmplitude* DeccelAmplitude::reverse() const
+{
+    return DeccelAmplitude::create(_other->reverse(), _duration);
+}
+
+// implementation of StopGrid
+
+void StopGrid::startWithTarget(Node *target)
+{
+    ActionInstant::startWithTarget(target);
+    cacheTargetAsGridNode();
+    GridBase *grid = _gridNodeTarget->getGrid();
+    if (grid && grid->isActive())
+    {
+        grid->setActive(false);
+    }
+}
+
+void StopGrid::cacheTargetAsGridNode()
+{
+    _gridNodeTarget = dynamic_cast<NodeGrid*> (_target);
+    CCASSERT(_gridNodeTarget, "GridActions can only used on NodeGrid");
+}
+
+StopGrid* StopGrid::create()
+{
+    StopGrid* action = new (std::nothrow) StopGrid();
+    if (action)
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+StopGrid* StopGrid::clone() const
+{
+    return StopGrid::create();
+}
+
+StopGrid* StopGrid::reverse() const
+{
+    // no reverse, just clone it
+    return this->clone();
+}
+
+// implementation of ReuseGrid
+
+ReuseGrid* ReuseGrid::create(int times)
+{
+    ReuseGrid *action = new (std::nothrow) ReuseGrid();
+    if (action && action->initWithTimes(times))
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+bool ReuseGrid::initWithTimes(int times)
+{
+    _times = times;
+
+    return true;
+}
+
+void ReuseGrid::startWithTarget(Node *target)
+{
+    ActionInstant::startWithTarget(target);
+    cacheTargetAsGridNode();
+
+    if (_gridNodeTarget->getGrid() && _gridNodeTarget->getGrid()->isActive())
+    {
+        _gridNodeTarget->getGrid()->setReuseGrid(_gridNodeTarget->getGrid()->getReuseGrid() + _times);
+    }
+}
+
+void ReuseGrid::cacheTargetAsGridNode()
+{
+    _gridNodeTarget = dynamic_cast<NodeGrid*> (_target);
+    CCASSERT(_gridNodeTarget, "GridActions can only used on NodeGrid");
+}
+
+ReuseGrid* ReuseGrid::clone() const
+{
+    return ReuseGrid::create(_times);
+}
+
+ReuseGrid* ReuseGrid::reverse() const
+{
+    // no reverse, just clone it
+    return this->clone();
+}
+
+NS_CC_END

+ 445 - 0
cocos2d/cocos/2d/CCActionGrid.h

@@ -0,0 +1,445 @@
+/****************************************************************************
+Copyright (c) 2009      On-Core
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+#ifndef __ACTION_CCGRID_ACTION_H__
+#define __ACTION_CCGRID_ACTION_H__
+
+#include "2d/CCActionInterval.h"
+#include "2d/CCActionInstant.h"
+
+NS_CC_BEGIN
+
+class GridBase;
+class NodeGrid;
+
+/**
+ * @addtogroup actions
+ * @{
+ */
+
+/** 
+@class GridAction
+@brief Base class for Grid actions.
+@details Grid actions are the actions take effect on GridBase.
+*/
+class CC_DLL GridAction : public ActionInterval
+{
+public:
+
+    /** 
+    @brief Get the pointer of GridBase.
+    @return The pointer of GridBase.
+    */
+    virtual GridBase* getGrid();
+
+    // overrides
+    virtual GridAction * clone() const override
+    {
+        CC_ASSERT(0);
+        return nullptr;
+    }
+    virtual GridAction* reverse() const override;
+    virtual void startWithTarget(Node *target) override;
+
+CC_CONSTRUCTOR_ACCESS:
+    GridAction() {}
+    virtual ~GridAction() {}
+    /** 
+     * @brief Initializes the action with size and duration.
+     * @param duration The duration of the GridAction. It's a value in seconds.
+     * @param gridSize The size of the GridAction should be.
+     * @return Return true when the initialization success, otherwise return false.
+     */
+    bool initWithDuration(float duration, const Size& gridSize);
+
+protected:
+    Size _gridSize;
+    
+    NodeGrid* _gridNodeTarget;
+    
+    void cacheTargetAsGridNode();
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(GridAction);
+};
+
+/** 
+ @brief Base class for Grid3D actions.
+ @details Grid3D actions can modify a non-tiled grid.
+ */
+class CC_DLL Grid3DAction : public GridAction
+{
+public:
+
+
+    virtual GridBase* getGrid() override;
+    /**
+     * @brief Get the vertex that belongs to certain position in the grid.
+     * @param position The position of the grid.
+     * @return Return a pointer of vertex.
+     * @js vertex
+     * @lua NA
+     */
+    Vec3 getVertex(const Vec2& position) const;
+
+    /** @deprecated Use getVertex() instead 
+     * @js NA
+     * @lua NA
+     */
+    CC_DEPRECATED_ATTRIBUTE Vec3 vertex(const Vec2& position) { return getVertex(position); }
+
+    /** 
+     * @brief Get the non-transformed vertex that belongs to certain position in the grid.
+     * @param position The position of the grid.
+     * @return Return a pointer of vertex.
+     * @js originalVertex
+     * @lua NA
+     */
+    Vec3 getOriginalVertex(const Vec2& position) const;
+
+    /** @deprecated Use getOriginalVertex() instead 
+     * @js NA
+     * @lua NA
+     */
+    CC_DEPRECATED_ATTRIBUTE Vec3 originalVertex(const Vec2& position) { return getOriginalVertex(position); }
+
+    /** 
+     * @brief Set a new vertex to a certain position of the grid.
+     * @param position The position of the grid.
+     * @param vertex The vertex will be used on the certain position of grid.
+     * @js setVertex
+     * @lua NA
+     */
+    void setVertex(const Vec2& position, const Vec3& vertex);
+
+    // Overrides
+    virtual Grid3DAction * clone() const override
+    {
+        CC_ASSERT(0);
+        return nullptr;
+    }
+    
+    /**
+     * @brief Get the effect grid rect.
+     * @return Return the effect grid rect.
+     */
+    Rect getGridRect() const;
+};
+
+/**
+@brief Base class for TiledGrid3D actions.
+*/
+class CC_DLL TiledGrid3DAction : public GridAction
+{
+public:
+    /** 
+     * @brief Create the action with size and duration.
+     * @param duration The duration of the action. It's a value in seconds.
+     * @param gridSize Specify the grid size of the action.
+     * @return A pointer of TiledGrid3DAction. If creation failed, return nil.
+     * @lua NA
+     */
+    static TiledGrid3DAction* create(float duration, const Size& gridSize);
+
+    /** 
+     * @brief Get the tile that belongs to a certain position of the grid.
+     * @param position The position of the tile want to get.
+     * @return A quadrilateral of the tile. 
+     * @js tile
+     * @lua NA
+     */
+    Quad3 getTile(const Vec2& position) const;
+
+    /** @deprecated Use getTile() instead 
+     * @js NA
+     * @lua NA
+     */
+    CC_DEPRECATED_ATTRIBUTE Quad3 tile(const Vec2& position) { return getTile(position); }
+
+    /** 
+     * @brief Get the non-transformed tile that belongs to a certain position of the grid.
+     * @param position The position of the tile want to get.
+     * @return A quadrilateral of the tile. 
+     * @js originalTile
+     * @lua NA
+     */
+    Quad3 getOriginalTile(const Vec2& position) const;
+
+    /** @deprecated Use getOriginalTile() instead.
+     * @js NA
+     * @lua NA
+     */
+    CC_DEPRECATED_ATTRIBUTE Quad3 originalTile(const Vec2& position) { return getOriginalTile(position); }
+
+    /** 
+     * @brief Set a new tile to a certain position of the grid.
+     * @param position The position of the tile.
+     * @param coords The quadrilateral of the new tile.
+     * @lua NA
+     */
+    void setTile(const Vec2& position, const Quad3& coords);
+
+    /** returns the grid */
+    virtual GridBase* getGrid() override;
+
+    // Override
+    virtual TiledGrid3DAction * clone() const override
+    {
+        CC_ASSERT(0);
+        return nullptr;
+    }
+};
+
+/**
+@brief AccelDeccelAmplitude action.
+@js NA
+*/
+class CC_DLL AccelDeccelAmplitude : public ActionInterval
+{
+public:
+    /**
+    @brief Create the action with an inner action that has the amplitude property, and a duration time.
+    @param action A pointer of the inner action.
+    @param duration Specify the duration of the AccelDeccelAmplitude action.
+    @return Return a pointer of AccelDeccelAmplitude action. When the creation failed, return nil.
+    */
+    static AccelDeccelAmplitude* create(Action *action, float duration);
+
+    /** 
+    @brief Get the value of amplitude rate.
+    @return the value of amplitude rate.
+    */
+    float getRate() const { return _rate; }
+    /**
+    @brief Set the value of amplitude rate.
+    @param rate Specify the value of amplitude rate.
+    */
+    void setRate(float rate) { _rate = rate; }
+
+    // Overrides
+    virtual void startWithTarget(Node *target) override;
+    virtual void update(float time) override;
+    virtual AccelDeccelAmplitude* clone() const override;
+    virtual AccelDeccelAmplitude* reverse() const override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    AccelDeccelAmplitude() {}
+    virtual ~AccelDeccelAmplitude();
+    
+    /** 
+    @brief Initializes the action with an inner action that has the amplitude property, and a duration time.
+    @param action A pointer of the inner action.
+    @param duration Specify the duration of the AccelDeccelAmplitude action.
+    @return If the initialization success, return true; otherwise, return false.
+    */
+    bool initWithAction(Action *action, float duration);
+
+protected:
+    float _rate;
+    ActionInterval *_other;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(AccelDeccelAmplitude);
+};
+
+/**
+@brief AccelAmplitude action.
+@js NA
+*/
+class CC_DLL AccelAmplitude : public ActionInterval
+{
+public:
+    /** 
+    @brief Create the action with an inner action that has the amplitude property, and a duration time.
+    @param action A pointer of the inner action.
+    @param duration Specify the duration of the AccelAmplitude action.
+    @return Return a pointer of AccelAmplitude action. When the creation failed, return nil.
+     */
+    static AccelAmplitude* create(Action *action, float duration);
+
+    /** 
+    @brief Get the value of amplitude rate.
+    @return The value of amplitude rate.
+    */
+    float getRate() const { return _rate; }
+    /**
+    @brief Set the value of amplitude rate.
+    @param rate Specify the value of amplitude rate.
+    */
+    void setRate(float rate) { _rate = rate; }
+
+    // Overrides
+    virtual void startWithTarget(Node *target) override;
+    virtual void update(float time) override;
+    virtual AccelAmplitude* clone() const override;
+    virtual AccelAmplitude* reverse() const override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    AccelAmplitude() {}
+    virtual ~AccelAmplitude();
+
+    bool initWithAction(Action *action, float duration);
+
+protected:
+    float _rate;
+    ActionInterval *_other;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(AccelAmplitude);
+};
+
+/**
+@brief DeccelAmplitude action.
+@js NA
+*/
+class CC_DLL DeccelAmplitude : public ActionInterval
+{
+public:
+    /** 
+    @brief Creates the action with an inner action that has the amplitude property, and a duration time.
+    @param action A pointer of the inner action.
+    @param duration Specify the duration of the DeccelAmplitude action.
+    @return Return a pointer of DeccelAmplitude. When the creation failed, return nil.
+    */
+    static DeccelAmplitude* create(Action *action, float duration);
+
+    /** 
+    @brief Get the value of amplitude rate.
+    @return The value of amplitude rate.
+    */
+    float getRate() const { return _rate; }
+    /**
+    @brief Set the value of amplitude rate.
+    @param rate Specify the value.
+    */
+    void setRate(float rate) { _rate = rate; }
+
+    // overrides
+    virtual void startWithTarget(Node *target) override;
+    virtual void update(float time) override;
+    virtual DeccelAmplitude* clone() const override;
+    virtual DeccelAmplitude* reverse() const override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    DeccelAmplitude() {}
+    virtual ~DeccelAmplitude();
+
+    /** 
+    @brief Initializes the action with an inner action that has the amplitude property, and a duration time.
+    @param action The pointer of inner action.
+    @param duration The duration of the DeccelAmplitude action.
+    @return If the initialization success, return true; otherwise, return false.
+    */
+    bool initWithAction(Action *action, float duration);
+
+protected:
+    float _rate;
+    ActionInterval *_other;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(DeccelAmplitude);
+};
+
+/**
+ @brief StopGrid action.
+ @warning Don't call this action if another grid action is active.
+ Call if you want to remove the grid effect. Example:
+ @code
+ Sequence::create(Lens3D::create(...), StopGrid::create(), nullptr);
+ @endcode
+ */
+class CC_DLL StopGrid : public ActionInstant
+{
+public:
+    /** 
+    @brief Create a StopGrid Action.
+    @return Return a pointer of StopGrid. When the creation failed, return nil.
+    */
+    static StopGrid* create();
+
+    // Overrides
+    virtual void startWithTarget(Node *target) override;
+    virtual StopGrid* clone() const override;
+    virtual StopGrid* reverse() const override;
+
+CC_CONSTRUCTOR_ACCESS:
+    StopGrid() {}
+    virtual ~StopGrid() {}
+    
+protected:
+    NodeGrid* _gridNodeTarget;
+    
+    void cacheTargetAsGridNode();
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(StopGrid);
+};
+
+/** 
+@brief ReuseGrid action.
+*/
+class CC_DLL ReuseGrid : public ActionInstant
+{
+public:
+    /** 
+    @brief Create an action with the number of times that the current grid will be reused.
+    @param times Specify times the grid will be reused.
+    @return Return a pointer of ReuseGrid. When the creation failed, return nil.
+    */
+    static ReuseGrid* create(int times);
+
+    // Override
+    virtual void startWithTarget(Node *target) override;
+    virtual ReuseGrid* clone() const override;
+    virtual ReuseGrid* reverse() const override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    ReuseGrid() {}
+    virtual ~ReuseGrid() {}
+    
+    /** 
+    @brief Initializes an action with the number of times that the current grid will be reused.
+    @param times Specify times the grid will be reused.
+    @return If the initialization success, return true; otherwise, return false.
+    */
+    bool initWithTimes(int times);
+
+protected:
+    NodeGrid* _gridNodeTarget;
+    
+    void cacheTargetAsGridNode();
+    
+    int _times;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(ReuseGrid);
+};
+
+// end of actions group
+/// @}
+
+NS_CC_END
+
+#endif // __ACTION_CCGRID_ACTION_H__

+ 731 - 0
cocos2d/cocos/2d/CCActionGrid3D.cpp

@@ -0,0 +1,731 @@
+/****************************************************************************
+Copyright (c) 2009      On-Core
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCActionGrid3D.h"
+#include "base/CCDirector.h"
+
+NS_CC_BEGIN
+// implementation of Waves3D
+
+Waves3D* Waves3D::create(float duration, const Size& gridSize, unsigned int waves, float amplitude)
+{
+    Waves3D *action = new (std::nothrow) Waves3D();
+
+    if (action && action->initWithDuration(duration, gridSize, waves, amplitude))
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+bool Waves3D::initWithDuration(float duration, const Size& gridSize, unsigned int waves, float amplitude)
+{
+    if (Grid3DAction::initWithDuration(duration, gridSize))
+    {
+        _waves = waves;
+        _amplitude = amplitude;
+        _amplitudeRate = 1.0f;
+
+        return true;
+    }
+
+    return false;
+}
+
+Waves3D* Waves3D::clone() const
+{
+    // no copy constructor
+    return Waves3D::create(_duration, _gridSize, _waves, _amplitude);
+}
+
+void Waves3D::update(float time)
+{
+    int i, j;
+    for (i = 0; i < _gridSize.width + 1; ++i)
+    {
+        for (j = 0; j < _gridSize.height + 1; ++j)
+        {
+            Vec3 v = getOriginalVertex(Vec2(i ,j));
+            v.z += (sinf((float)M_PI * time * _waves * 2 + (v.y+v.x) * 0.01f) * _amplitude * _amplitudeRate);
+            //CCLOG("v.z offset is %f\n", (sinf((float)M_PI * time * _waves * 2 + (v.y+v.x) * .01f) * _amplitude * _amplitudeRate));
+            setVertex(Vec2(i, j), v);
+        }
+    }
+}
+
+// implementation of FlipX3D
+
+FlipX3D* FlipX3D::create(float duration)
+{
+    FlipX3D *action = new (std::nothrow) FlipX3D();
+
+    if (action && action->initWithDuration(duration))
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+bool FlipX3D::initWithDuration(float duration)
+{
+    return Grid3DAction::initWithDuration(duration, Size(1, 1));
+}
+
+bool FlipX3D::initWithSize(const Size& gridSize, float duration)
+{
+    if (gridSize.width != 1 || gridSize.height != 1)
+    {
+        // Grid size must be (1,1)
+        CCASSERT(0, "Grid size must be (1,1)");
+
+        return false;
+    }
+
+    return Grid3DAction::initWithDuration(duration, gridSize);
+}
+
+FlipX3D* FlipX3D::clone() const
+{
+    // no copy constructor    
+    auto a = new (std::nothrow) FlipX3D();
+    a->initWithSize(_gridSize, _duration);
+    a->autorelease();
+    return a;
+}
+
+void FlipX3D::update(float time)
+{
+    float angle = (float)M_PI * time; // 180 degrees
+    float mz = sinf(angle);
+    angle = angle / 2.0f; // x calculates degrees from 0 to 90
+    float mx = cosf(angle);
+
+    Vec3 v0, v1, v, diff;
+
+    v0 = getOriginalVertex(Vec2(1.0f, 1.0f));
+    v1 = getOriginalVertex(Vec2());
+
+    float    x0 = v0.x;
+    float    x1 = v1.x;
+    float    x;
+    Vec2    a, b, c, d;
+
+    if ( x0 > x1 )
+    {
+        // Normal Grid
+        a.setZero();
+        b.set(0.0f, 1.0f);
+        c.set(1.0f, 0.0f);
+        d.set(1.0f, 1.0f);
+        x = x0;
+    }
+    else
+    {
+        // Reversed Grid
+        c.setZero();
+        d.set(0.0f, 1.0f);
+        a.set(1.0f, 0.0f);
+        b.set(1.0f, 1.0f);
+        x = x1;
+    }
+    
+    diff.x = ( x - x * mx );
+    diff.z = fabsf( floorf( (x * mz) / 4.0f ) );
+
+    // bottom-left
+    v = getOriginalVertex(a);
+    v.x = diff.x;
+    v.z += diff.z;
+    setVertex(a, v);
+    
+    // upper-left
+    v = getOriginalVertex(b);
+    v.x = diff.x;
+    v.z += diff.z;
+    setVertex(b, v);
+    
+    // bottom-right
+    v = getOriginalVertex(c);
+    v.x -= diff.x;
+    v.z -= diff.z;
+    setVertex(c, v);
+    
+    // upper-right
+    v = getOriginalVertex(d);
+    v.x -= diff.x;
+    v.z -= diff.z;
+    setVertex(d, v);
+}
+
+// implementation of FlipY3D
+
+FlipY3D* FlipY3D::clone() const
+{
+    // no copy constructor
+    auto a = new (std::nothrow) FlipY3D();
+    a->initWithSize(_gridSize, _duration);
+    a->autorelease();
+    return a;
+}
+
+FlipY3D* FlipY3D::create(float duration)
+{
+    FlipY3D *action = new (std::nothrow) FlipY3D();
+
+    if (action)
+    {
+        if (action->initWithDuration(duration))
+        {
+            action->autorelease();
+        }
+        else
+        {
+            CC_SAFE_RELEASE_NULL(action);
+        }
+    }
+
+    return action;
+}
+
+void FlipY3D::update(float time)
+{
+    float angle = (float)M_PI * time; // 180 degrees
+    float mz = sinf( angle );
+    angle = angle / 2.0f;     // x calculates degrees from 0 to 90
+    float my = cosf(angle);
+    
+    Vec3    v0, v1, v, diff;
+    
+    v0 = getOriginalVertex(Vec2(1.0f, 1.0f));
+    v1 = getOriginalVertex(Vec2());
+    
+    float    y0 = v0.y;
+    float    y1 = v1.y;
+    float y;
+    Vec2    a, b, c, d;
+    
+    if (y0 > y1)
+    {
+        // Normal Grid
+        a.setZero();
+        b.set(0.0f, 1.0f);
+        c.set(1.0f, 0.0f);
+        d.set(1.0f, 1.0f);
+        y = y0;
+    }
+    else
+    {
+        // Reversed Grid
+        b.setZero();
+        a.set(0.0f, 1.0f);
+        d.set(1.0f, 0.0f);
+        c.set(1.0f, 1.0f);
+        y = y1;
+    }
+    
+    diff.y = y - y * my;
+    diff.z = fabsf(floorf((y * mz) / 4.0f));
+    
+    // bottom-left
+    v = getOriginalVertex(a);
+    v.y = diff.y;
+    v.z += diff.z;
+    setVertex(a, v);
+    
+    // upper-left
+    v = getOriginalVertex(b);
+    v.y -= diff.y;
+    v.z -= diff.z;
+    setVertex(b, v);
+    
+    // bottom-right
+    v = getOriginalVertex(c);
+    v.y = diff.y;
+    v.z += diff.z;
+    setVertex(c, v);
+    
+    // upper-right
+    v = getOriginalVertex(d);
+    v.y -= diff.y;
+    v.z -= diff.z;
+    setVertex(d, v);
+}
+
+
+// implementation of Lens3D
+
+Lens3D* Lens3D::create(float duration, const Size& gridSize, const Vec2& position, float radius)
+{
+    Lens3D *action = new (std::nothrow) Lens3D();
+
+    if (action)
+    {
+        if (action->initWithDuration(duration, gridSize, position, radius))
+        {
+            action->autorelease();
+        }
+        else
+        {
+            CC_SAFE_RELEASE_NULL(action);
+        }
+    }
+
+    return action;
+}
+
+bool Lens3D::initWithDuration(float duration, const Size& gridSize, const Vec2& position, float radius)
+{
+    if (Grid3DAction::initWithDuration(duration, gridSize))
+    {
+        _position.set(-1.0f, -1.0f);
+        setPosition(position);
+        _radius = radius;
+        _lensEffect = 0.7f;
+        _concave = false;
+        _dirty = true;
+
+        return true;
+    }
+
+    return false;
+}
+
+Lens3D* Lens3D::clone() const
+{
+    // no copy constructor
+    auto a = new (std::nothrow) Lens3D();
+    a->initWithDuration(_duration, _gridSize, _position, _radius);
+    a->autorelease();
+    return a;
+}
+
+void Lens3D::setPosition(const Vec2& pos)
+{
+    if( !pos.equals(_position))
+    {
+        _position = pos;
+        _dirty = true;
+    }
+}
+
+void Lens3D::update(float /*time*/)
+{
+    if (_dirty)
+    {
+        int i, j;
+        
+        for (i = 0; i < _gridSize.width + 1; ++i)
+        {
+            for (j = 0; j < _gridSize.height + 1; ++j)
+            {
+                Vec3 v = getOriginalVertex(Vec2(i, j));
+                Vec2 vect = _position - Vec2(v.x, v.y);
+                float r = vect.getLength();
+                
+                if (r < _radius)
+                {
+                    r = _radius - r;
+                    float pre_log = r / _radius;
+                    if ( pre_log == 0 ) 
+                    {
+                        pre_log = 0.001f;
+                    }
+
+                    float l = logf(pre_log) * _lensEffect;
+                    float new_r = expf( l ) * _radius;
+                    
+                    if (vect.getLength() > 0)
+                    {
+                        vect.normalize();
+                        Vec2 new_vect = vect * new_r;
+                        v.z += (_concave ? -1.0f : 1.0f) * new_vect.getLength() * _lensEffect;
+                    }
+                }
+                
+                setVertex(Vec2(i, j), v);
+            }
+        }
+        
+        _dirty = false;
+    }
+}
+
+// implementation of Ripple3D
+
+Ripple3D* Ripple3D::create(float duration, const Size& gridSize, const Vec2& position, float radius, unsigned int waves, float amplitude)
+{
+    Ripple3D *action = new (std::nothrow) Ripple3D();
+
+    if (action)
+    {
+        if (action->initWithDuration(duration, gridSize, position, radius, waves, amplitude))
+        {
+            action->autorelease();
+        }
+        else
+        {
+            CC_SAFE_RELEASE_NULL(action);
+        }
+    }
+
+    return action;
+}
+
+bool Ripple3D::initWithDuration(float duration, const Size& gridSize, const Vec2& position, float radius, unsigned int waves, float amplitude)
+{
+    if (Grid3DAction::initWithDuration(duration, gridSize))
+    {
+        setPosition(position);
+        _radius = radius;
+        _waves = waves;
+        _amplitude = amplitude;
+        _amplitudeRate = 1.0f;
+
+        return true;
+    }
+
+    return false;
+}
+
+void Ripple3D::setPosition(const Vec2& position)
+{
+    _position = position;
+}
+
+
+Ripple3D* Ripple3D::clone() const
+{
+    // no copy constructor
+    auto a = new (std::nothrow) Ripple3D();
+    a->initWithDuration(_duration, _gridSize, _position, _radius, _waves, _amplitude);
+    a->autorelease();
+    return a;
+}
+
+void Ripple3D::update(float time)
+{
+    int i, j;
+
+    for (i = 0; i < (_gridSize.width+1); ++i)
+    {
+        for (j = 0; j < (_gridSize.height+1); ++j)
+        {
+            Vec3 v = getOriginalVertex(Vec2(i, j));
+            Vec2 vect = _position - Vec2(v.x,v.y);
+            float r = vect.getLength();
+            
+            if (r < _radius)
+            {
+                r = _radius - r;
+                float rate = powf(r / _radius, 2);
+                v.z += (sinf( time*(float)M_PI * _waves * 2 + r * 0.1f) * _amplitude * _amplitudeRate * rate);
+            }
+            
+            setVertex(Vec2(i, j), v);
+        }
+    }
+}
+
+// implementation of Shaky3D
+
+Shaky3D* Shaky3D::create(float duration, const Size& gridSize, int range, bool shakeZ)
+{
+    Shaky3D *action = new (std::nothrow) Shaky3D();
+
+    if (action)
+    {
+        if (action->initWithDuration(duration, gridSize, range, shakeZ))
+        {
+            action->autorelease();
+        }
+        else
+        {
+            CC_SAFE_RELEASE_NULL(action);
+        }
+    }
+
+    return action;
+}
+
+bool Shaky3D::initWithDuration(float duration, const Size& gridSize, int range, bool shakeZ)
+{
+    if (Grid3DAction::initWithDuration(duration, gridSize))
+    {
+        _randrange = range;
+        _shakeZ = shakeZ;
+
+        return true;
+    }
+
+    return false;
+}
+
+Shaky3D* Shaky3D::clone() const
+{
+    // no copy constructor
+    auto a = new (std::nothrow) Shaky3D();
+    a->initWithDuration(_duration, _gridSize, _randrange, _shakeZ);
+    a->autorelease();
+    return a;
+}
+
+void Shaky3D::update(float /*time*/)
+{
+    int i, j;
+
+    for (i = 0; i < (_gridSize.width+1); ++i)
+    {
+        for (j = 0; j < (_gridSize.height+1); ++j)
+        {
+            Vec3 v = getOriginalVertex(Vec2(i ,j));
+            v.x += (rand() % (_randrange*2)) - _randrange;
+            v.y += (rand() % (_randrange*2)) - _randrange;
+            if (_shakeZ)
+            {
+                v.z += (rand() % (_randrange*2)) - _randrange;
+            }
+            
+            setVertex(Vec2(i, j), v);
+        }
+    }
+}
+
+// implementation of Liquid
+
+Liquid* Liquid::create(float duration, const Size& gridSize, unsigned int waves, float amplitude)
+{
+    Liquid *action = new (std::nothrow) Liquid();
+
+    if (action)
+    {
+        if (action->initWithDuration(duration, gridSize, waves, amplitude))
+        {
+            action->autorelease();
+        }
+        else
+        {
+            CC_SAFE_RELEASE_NULL(action);
+        }
+    }
+
+    return action;
+}
+
+bool Liquid::initWithDuration(float duration, const Size& gridSize, unsigned int waves, float amplitude)
+{
+    if (Grid3DAction::initWithDuration(duration, gridSize))
+    {
+        _waves = waves;
+        _amplitude = amplitude;
+        _amplitudeRate = 1.0f;
+
+        return true;
+    }
+
+    return false;
+}
+
+Liquid* Liquid::clone() const
+{
+    // no copy constructor
+    auto a = new (std::nothrow) Liquid();
+    a->initWithDuration(_duration, _gridSize, _waves, _amplitude);
+    a->autorelease();
+    return a;
+}
+
+void Liquid::update(float time)
+{
+    int i, j;
+
+    for (i = 1; i < _gridSize.width; ++i)
+    {
+        for (j = 1; j < _gridSize.height; ++j)
+        {
+            Vec3 v = getOriginalVertex(Vec2(i, j));
+            v.x = (v.x + (sinf(time * (float)M_PI * _waves * 2 + v.x * .01f) * _amplitude * _amplitudeRate));
+            v.y = (v.y + (sinf(time * (float)M_PI * _waves * 2 + v.y * .01f) * _amplitude * _amplitudeRate));
+            setVertex(Vec2(i, j), v);
+        }
+    }
+}
+
+// implementation of Waves
+
+Waves* Waves::create(float duration, const Size& gridSize, unsigned int waves, float amplitude, bool horizontal, bool vertical)
+{
+    Waves *action = new (std::nothrow) Waves();
+
+    if (action)
+    {
+        if (action->initWithDuration(duration, gridSize, waves, amplitude, horizontal, vertical))
+        {
+            action->autorelease();
+        }
+        else
+        {
+            CC_SAFE_RELEASE_NULL(action);
+        }
+    }
+
+    return action;
+}
+
+bool Waves::initWithDuration(float duration, const Size& gridSize, unsigned int waves, float amplitude, bool horizontal, bool vertical)
+{
+    if (Grid3DAction::initWithDuration(duration, gridSize))
+    {
+        _waves = waves;
+        _amplitude = amplitude;
+        _amplitudeRate = 1.0f;
+        _horizontal = horizontal;
+        _vertical = vertical;
+
+        return true;
+    }
+
+    return false;
+}
+
+Waves* Waves::clone() const
+{
+    // no copy constructor
+    auto a = new (std::nothrow) Waves();
+    a->initWithDuration(_duration, _gridSize, _waves, _amplitude, _horizontal, _vertical);
+    a->autorelease();
+    return a;
+}
+
+void Waves::update(float time)
+{
+    int i, j;
+
+    for (i = 0; i < _gridSize.width + 1; ++i)
+    {
+        for (j = 0; j < _gridSize.height + 1; ++j)
+        {
+            Vec3 v = getOriginalVertex(Vec2(i, j));
+
+            if (_vertical)
+            {
+                v.x = (v.x + (sinf(time * (float)M_PI * _waves * 2 + v.y * .01f) * _amplitude * _amplitudeRate));
+            }
+
+            if (_horizontal)
+            {
+                v.y = (v.y + (sinf(time * (float)M_PI * _waves * 2 + v.x * .01f) * _amplitude * _amplitudeRate));
+            }
+
+            setVertex(Vec2(i, j), v);
+        }
+    }
+}
+
+// implementation of Twirl
+
+Twirl* Twirl::create(float duration, const Size& gridSize, const Vec2& position, unsigned int twirls, float amplitude)
+{
+    Twirl *action = new (std::nothrow) Twirl();
+
+    if (action)
+    {
+        if (action->initWithDuration(duration, gridSize, position, twirls, amplitude))
+        {
+            action->autorelease();
+        }
+        else
+        {
+            CC_SAFE_RELEASE_NULL(action);
+        }
+    }
+
+    return action;
+}
+
+bool Twirl::initWithDuration(float duration, const Size& gridSize, const Vec2& position, unsigned int twirls, float amplitude)
+{
+    if (Grid3DAction::initWithDuration(duration, gridSize))
+    {
+        setPosition(position);
+        _twirls = twirls;
+        _amplitude = amplitude;
+        _amplitudeRate = 1.0f;
+
+        return true;
+    }
+
+    return false;
+}
+
+void Twirl::setPosition(const Vec2& position)
+{
+    _position = position;
+}
+
+Twirl *Twirl::clone() const
+{
+    // no copy constructor    
+    auto a = new (std::nothrow) Twirl();
+    a->initWithDuration(_duration, _gridSize, _position, _twirls, _amplitude);
+    a->autorelease();
+    return a;
+}
+
+void Twirl::update(float time)
+{
+    int i, j;
+    Vec2    c = _position;
+    
+    for (i = 0; i < (_gridSize.width+1); ++i)
+    {
+        for (j = 0; j < (_gridSize.height+1); ++j)
+        {
+            Vec3 v = getOriginalVertex(Vec2(i ,j));
+            
+            Vec2 avg(i-(_gridSize.width/2.0f), j-(_gridSize.height/2.0f));
+            float r = avg.getLength();
+            
+            float amp = 0.1f * _amplitude * _amplitudeRate;
+            float a = r * cosf( (float)M_PI/2.0f + time * (float)M_PI * _twirls * 2 ) * amp;
+            
+            Vec2 d(
+                sinf(a) * (v.y-c.y) + cosf(a) * (v.x-c.x),
+                cosf(a) * (v.y-c.y) - sinf(a) * (v.x-c.x));
+            
+            v.x = c.x + d.x;
+            v.y = c.y + d.y;
+
+            setVertex(Vec2(i ,j), v);
+        }
+    }
+}
+
+NS_CC_END

+ 619 - 0
cocos2d/cocos/2d/CCActionGrid3D.h

@@ -0,0 +1,619 @@
+/****************************************************************************
+Copyright (c) 2009      On-Core
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+#ifndef __ACTION_CCGRID3D_ACTION_H__
+#define __ACTION_CCGRID3D_ACTION_H__
+
+#include "2d/CCActionGrid.h"
+
+NS_CC_BEGIN
+
+/**
+ * @addtogroup actions
+ * @{
+ */
+
+/** 
+@brief Waves3D action.
+@details This action is used for take effect on the target node as 3D waves.
+        You can control the effect by these parameters:
+        duration, grid size, waves count, amplitude.
+*/
+class CC_DLL Waves3D : public Grid3DAction
+{
+public:
+    /**
+    @brief Create an action with duration, grid size, waves and amplitude.
+    @param duration Specify the duration of the Waves3D action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param waves Specify the waves count of the Waves3D action.
+    @param amplitude Specify the amplitude of the Waves3D action.
+    @return If the creation success, return a pointer of Waves3D action; otherwise, return nil.
+    */
+    static Waves3D* create(float duration, const Size& gridSize, unsigned int waves, float amplitude);
+
+    /**
+    @brief Get the amplitude of the effect.
+    @return Return the amplitude of the effect.
+    */
+    float getAmplitude() const { return _amplitude; }
+    /**
+    @brief Set the amplitude to the effect.
+    @param amplitude The value of amplitude will be set.
+    */
+    void setAmplitude(float amplitude) { _amplitude = amplitude; }
+
+    /**
+    @brief Get the amplitude rate of the effect.
+    @return Return the amplitude rate of the effect.
+    */
+    float getAmplitudeRate() const { return _amplitudeRate; }
+    /**
+    @brief Set the amplitude rate of the effect.
+    @param amplitudeRate The value of amplitude rate will be set.
+    */
+    void setAmplitudeRate(float amplitudeRate) { _amplitudeRate = amplitudeRate; }
+
+    // Overrides
+    virtual Waves3D* clone() const override;
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    Waves3D() {}
+    virtual ~Waves3D() {}
+
+    /** 
+    @brief Initializes an action with duration, grid size, waves and amplitude.
+    @param duration Specify the duration of the Waves3D action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param waves Specify the waves count of the Waves3D action.
+    @param amplitude Specify the amplitude of the Waves3D action.
+    @return If the initialization success, return true; otherwise, return false.
+    */
+    bool initWithDuration(float duration, const Size& gridSize, unsigned int waves, float amplitude);
+
+protected:
+    unsigned int _waves;
+    float _amplitude;
+    float _amplitudeRate;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Waves3D);
+};
+
+/**
+@brief FlipX3D action.
+@details This action is used for flipping the target node on the x axis.
+*/
+class CC_DLL FlipX3D : public Grid3DAction
+{
+public:
+    /**
+    @brief Create the action with duration.
+    @param duration Specify the duration of the FilpX3D action. It's a value in seconds.
+    @return If the creation success, return a pointer of FilpX3D action; otherwise, return nil.
+    */
+    static FlipX3D* create(float duration);
+
+    // Override
+    virtual FlipX3D* clone() const override;
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    FlipX3D() {}
+    virtual ~FlipX3D() {}
+
+    /** 
+    @brief Initializes an action with duration.
+    @param duration Specify the duration of the FlipX3D action. It's a value in seconds.
+    @return If the initialization success, return true; otherwise, return false.
+    */
+    bool initWithDuration(float duration);
+
+    /** 
+    @brief Initializes an action with duration and grid size.
+    @param gridSize Specify the grid size of the FlipX3D action.
+    @param duration Specify the duration of the FlipX3D action. It's a value in seconds.
+    @return If the initialization success, return true; otherwise, return false.
+    */
+    virtual bool initWithSize(const Size& gridSize, float duration);
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(FlipX3D);
+};
+
+/**
+@brief FlipY3D action.
+@details This action is used for flipping the target node on the y axis.
+*/
+class CC_DLL FlipY3D : public FlipX3D
+{
+public:
+    /**
+    @brief Create the action with duration.
+    @param duration Specify the duration of the FlipY3D action. It's a value in seconds.
+    @return If the creation success, return a pointer of FlipY3D action; otherwise, return nil.
+    */
+    static FlipY3D* create(float duration);
+
+    // Overrides
+    virtual void update(float time) override;
+    virtual FlipY3D* clone() const override;
+
+CC_CONSTRUCTOR_ACCESS:
+    FlipY3D() {}
+    virtual ~FlipY3D() {}
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(FlipY3D);
+};
+
+/**
+@brief Lens3D action.
+@details This action is used for take effect on the target node as lens.
+        You can create the action by these parameters:
+        duration, grid size, center position of lens, radius of lens.
+        Also you can change the lens effect value & whether effect is concave by the setter methods.
+*/
+class CC_DLL Lens3D : public Grid3DAction
+{
+public:
+    /**
+    @brief Create the action with center position, radius, a grid size and duration.
+    @param duration Specify the duration of the Lens3D action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param position Specify the center position of the lens.
+    @param radius Specify the radius of the lens.
+    @return If the creation success, return a pointer of Lens3D action; otherwise, return nil.
+    */
+    static Lens3D* create(float duration, const Size& gridSize, const Vec2& position, float radius);
+
+    /**
+    @brief Get the value of lens effect. Default value is 0.7.
+    @return The value of lens effect.
+    */
+    float getLensEffect() const { return _lensEffect; }
+
+    /**
+    @brief Set the value of lens effect.
+    @param lensEffect The value of lens effect will be set.
+    */
+    void setLensEffect(float lensEffect) { _lensEffect = lensEffect; }
+
+    /**
+    @brief Set whether lens is concave.
+    @param concave Whether lens is concave.
+    */
+    void setConcave(bool concave) { _concave = concave; }
+
+    /**
+    @brief Get the center position of lens effect.
+    @return The center position of lens effect.
+    */
+    const Vec2& getPosition() const { return _position; }
+
+    /**
+    @brief Set the center position of lens effect.
+    @param position The center position will be set.
+    */
+    void setPosition(const Vec2& position);
+
+    // Overrides
+    virtual Lens3D* clone() const override;
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    Lens3D() {}
+    virtual ~Lens3D() {}
+
+    /**
+    @brief Initializes the action with center position, radius, grid size and duration.
+    @param duration Specify the duration of the Lens3D action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param position Specify the center position of the lens effect.
+    @param radius Specify the radius of the lens effect.
+    @return If the initialization success, return true; otherwise, return false.
+    */
+    bool initWithDuration(float duration, const Size& gridSize, const Vec2& position, float radius);
+
+protected:
+    /* lens center position */
+    Vec2 _position;
+    float _radius;
+    /** lens effect. Defaults to 0.7 - 0 means no effect, 1 is very strong effect */
+    float _lensEffect;
+    /** lens is concave. (true = concave, false = convex) default is convex i.e. false */
+    bool _concave;
+
+    bool _dirty;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Lens3D);
+};
+
+/**
+@brief Ripple3D action.
+@details This action is used for take effect on the target node as ripple.
+        You can create the action by these parameters:
+        duration, grid size, center position of ripple,
+        radius of ripple, waves count, amplitude.
+*/
+class CC_DLL Ripple3D : public Grid3DAction
+{
+public:
+    /**
+    @brief Create the action with center position, radius, number of waves, amplitude, a grid size and duration.
+    @param duration Specify the duration of the Ripple3D action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param position Specify the center position of the ripple effect.
+    @param radius Specify the radius of the ripple effect.
+    @param waves Specify the waves count of the ripple effect.
+    @param amplitude Specify the amplitude of the ripple effect.
+    @return If the creation success, return a pointer of Ripple3D action; otherwise, return nil.
+    */
+    static Ripple3D* create(float duration, const Size& gridSize, const Vec2& position, float radius, unsigned int waves, float amplitude);
+
+    /**
+    @brief Get the center position of ripple effect.
+    @return The center position of ripple effect.
+    */
+    const Vec2& getPosition() const { return _position; }
+    /**
+    @brief Set the center position of ripple effect.
+    @param position The center position of ripple effect will be set.
+    */
+    void setPosition(const Vec2& position);
+
+    /**
+    @brief Get the amplitude of ripple effect.
+    @return The amplitude of ripple effect.
+    */
+    float getAmplitude() const { return _amplitude; }
+    /**
+    @brief Set the amplitude of ripple effect.
+    @param fAmplitude The amplitude of ripple effect.
+    */
+    void setAmplitude(float fAmplitude) { _amplitude = fAmplitude; }
+
+    /**
+    @brief Get the amplitude rate of ripple effect.
+    @return The amplitude rate of ripple effect.
+    */
+    float getAmplitudeRate() const { return _amplitudeRate; }
+    /**
+    @brief Set the amplitude rate of ripple effect.
+    @param fAmplitudeRate The amplitude rate of ripple effect.
+    */
+    void setAmplitudeRate(float fAmplitudeRate) { _amplitudeRate = fAmplitudeRate; }
+
+    // Override
+    virtual Ripple3D* clone() const override;
+    virtual void update(float time) override;
+
+CC_CONSTRUCTOR_ACCESS:
+    Ripple3D() {}
+    virtual ~Ripple3D() {}
+
+    /**
+    @brief Initializes the action with center position, radius, number of waves, amplitude, a grid size and duration.
+    @param duration Specify the duration of the Ripple3D action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param position Specify the center position of the ripple effect.
+    @param radius Specify the radius of the ripple effect.
+    @param waves Specify the waves count of the ripple effect.
+    @param amplitude Specify the amplitude of the ripple effect.
+    @return If the initialization success, return true; otherwise, return false.
+     */
+    bool initWithDuration(float duration, const Size& gridSize, const Vec2& position, float radius, unsigned int waves, float amplitude);
+
+protected:
+    /* center position */
+    Vec2 _position;
+    float _radius;
+    unsigned int _waves;
+    float _amplitude;
+    float _amplitudeRate;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Ripple3D);
+};
+
+/**
+@brief Shaky3D action.
+@details This action is used for take effect on the target node as shaky.
+        You can create the action by these parameters:
+        duration, grid size, range, whether shake on the z axis.
+*/
+class CC_DLL Shaky3D : public Grid3DAction
+{
+public:
+    /** 
+    @brief Create the action with a range, shake Z vertices, a grid and duration.
+    @param initWithDuration Specify the duration of the Shaky3D action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param range Specify the range of the shaky effect.
+    @param shakeZ Specify whether shake on the z axis.
+    @return If the creation success, return a pointer of Shaky3D action; otherwise, return nil.
+    */
+    static Shaky3D* create(float initWithDuration, const Size& gridSize, int range, bool shakeZ);
+
+    // Overrides
+    virtual Shaky3D* clone() const override;
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    Shaky3D() {}
+    virtual ~Shaky3D() {}
+    
+    /** 
+    @brief Initializes the action with a range, shake Z vertices, grid size and duration.
+    @param duration Specify the duration of the Shaky3D action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param range Specify the range of the shaky effect.
+    @param shakeZ Specify whether shake on the z axis.
+    @return If the Initialization success, return true; otherwise, return false.
+    */
+    bool initWithDuration(float duration, const Size& gridSize, int range, bool shakeZ);
+
+protected:
+    int _randrange;
+    bool _shakeZ;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Shaky3D);
+};
+
+/**
+@brief Liquid action.
+@details This action is used for take effect on the target node as liquid.
+        You can create the action by these parameters:
+        duration, grid size, waves count, amplitude of the liquid effect.
+*/
+class CC_DLL Liquid : public Grid3DAction
+{
+public:
+    /**
+    @brief Create the action with amplitude, grid size, waves count and duration.
+    @param duration Specify the duration of the Liquid action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param waves Specify the waves count of the Liquid action.
+    @param amplitude Specify the amplitude of the Liquid action.
+    @return If the creation success, return a pointer of Liquid action; otherwise, return nil.
+    */
+    static Liquid* create(float duration, const Size& gridSize, unsigned int waves, float amplitude);
+
+    /**
+    @brief Get the amplitude of the effect.
+    @return Return the amplitude of the effect.
+    */
+    float getAmplitude() const { return _amplitude; }
+    /**
+    @brief Set the amplitude to the effect.
+    @param amplitude The value of amplitude will be set.
+    */
+    void setAmplitude(float amplitude) { _amplitude = amplitude; }
+
+    /**
+    @brief Get the amplitude rate of the effect.
+    @return Return the amplitude rate of the effect.
+    */
+    float getAmplitudeRate() const { return _amplitudeRate; }
+    /**
+    @brief Set the amplitude rate of the effect.
+    @param amplitudeRate The value of amplitude rate will be set.
+    */
+    void setAmplitudeRate(float amplitudeRate) { _amplitudeRate = amplitudeRate; }
+
+    // Overrides
+    virtual Liquid* clone() const override;
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    Liquid() {}
+    virtual ~Liquid() {}
+    
+    /**
+    @brief Initializes the action with amplitude, grid size, waves count and duration.
+    @param duration Specify the duration of the Liquid action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param waves Specify the waves count of the Liquid action.
+    @param amplitude Specify the amplitude of the Liquid action.
+    @return If the initialization success, return true; otherwise, return false.
+    */
+    bool initWithDuration(float duration, const Size& gridSize, unsigned int waves, float amplitude);
+
+protected:
+    unsigned int _waves;
+    float _amplitude;
+    float _amplitudeRate;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Liquid);
+};
+
+/**
+@brief Waves action.
+@details This action is used for take effect on the target node as waves.
+        You can control the effect by these parameters:
+        duration, grid size, waves count, amplitude,
+        whether waves on horizontal and whether waves on vertical.
+*/
+class CC_DLL Waves : public Grid3DAction
+{
+public:
+    /**
+    @brief Create the action with amplitude, horizontal sin, vertical sin, grid size, waves count and duration.
+    @param duration Specify the duration of the Waves action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param waves Specify the waves count of the Waves action.
+    @param amplitude Specify the amplitude of the Waves action.
+    @param horizontal Specify whether waves on horizontal.
+    @param vertical Specify whether waves on vertical.
+    @return If the creation success, return a pointer of Waves action; otherwise, return nil.
+    */
+    static Waves* create(float duration, const Size& gridSize, unsigned int waves, float amplitude, bool horizontal, bool vertical);
+
+    /**
+    @brief Get the amplitude of the effect.
+    @return Return the amplitude of the effect.
+    */
+    float getAmplitude() const { return _amplitude; }
+    /**
+    @brief Set the amplitude to the effect.
+    @param amplitude The value of amplitude will be set.
+    */
+    void setAmplitude(float amplitude) { _amplitude = amplitude; }
+
+    /**
+    @brief Get the amplitude rate of the effect.
+    @return Return the amplitude rate of the effect.
+    */
+    float getAmplitudeRate() const { return _amplitudeRate; }
+    /**
+    @brief Set the amplitude rate of the effect.
+    @param amplitudeRate The value of amplitude rate will be set.
+    */
+    void setAmplitudeRate(float amplitudeRate) { _amplitudeRate = amplitudeRate; }
+
+    // Overrides
+    virtual Waves* clone() const override;
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    Waves() {}
+    virtual ~Waves() {}
+    
+    /**
+    @brief Initializes the action with amplitude, horizontal sin, vertical sin, grid size, waves count and duration.
+    @param duration Specify the duration of the Waves action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param waves Specify the waves count of the Waves action.
+    @param amplitude Specify the amplitude of the Waves action.
+    @param horizontal Specify whether waves on horizontal.
+    @param vertical Specify whether waves on vertical.
+    @return If the initialization success, return true; otherwise, return false.
+    */
+    bool initWithDuration(float duration, const Size& gridSize, unsigned int waves, float amplitude, bool horizontal, bool vertical);
+
+protected:
+    unsigned int _waves;
+    float _amplitude;
+    float _amplitudeRate;
+    bool _vertical;
+    bool _horizontal;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Waves);
+};
+
+/**
+@brief Twirl action.
+@details This action is used for take effect on the target node as twirl.
+        You can control the effect by these parameters:
+        duration, grid size, center position, twirls count, amplitude.
+*/
+class CC_DLL Twirl : public Grid3DAction
+{
+public:
+    /**
+    @brief Create the action with center position, number of twirls, amplitude, a grid size and duration.
+    @param duration Specify the duration of the Twirl action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param position Specify the center position of the twirl action.
+    @param twirls Specify the twirls count of the Twirl action.
+    @param amplitude Specify the amplitude of the Twirl action.
+    @return If the creation success, return a pointer of Twirl action; otherwise, return nil.
+    */
+    static Twirl* create(float duration, const Size& gridSize, const Vec2& position, unsigned int twirls, float amplitude);
+
+    /**
+    @brief Get the center position of twirl action.
+    @return The center position of twirl action.
+    */
+    const Vec2& getPosition() const { return _position; }
+    /**
+    @brief Set the center position of twirl action.
+    @param position The center position of twirl action will be set.
+    */
+    void setPosition(const Vec2& position);
+
+    /**
+    @brief Get the amplitude of the effect.
+    @return Return the amplitude of the effect.
+    */
+    float getAmplitude() const { return _amplitude; }
+    /**
+    @brief Set the amplitude to the effect.
+    @param amplitude The value of amplitude will be set.
+    */
+    void setAmplitude(float amplitude) { _amplitude = amplitude; }
+
+    /**
+    @brief Get the amplitude rate of the effect.
+    @return Return the amplitude rate of the effect.
+    */
+    float getAmplitudeRate() const { return _amplitudeRate; }
+    /**
+    @brief Set the amplitude rate of the effect.
+    @param amplitudeRate The value of amplitude rate will be set.
+    */
+    void setAmplitudeRate(float amplitudeRate) { _amplitudeRate = amplitudeRate; }
+
+
+    // Overrides
+    virtual Twirl* clone() const override;
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    Twirl() {}
+    virtual ~Twirl() {}
+
+    /**
+    @brief Initializes the action with center position, number of twirls, amplitude, a grid size and duration.
+    @param duration Specify the duration of the Twirl action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param position Specify the center position of the twirl action.
+    @param twirls Specify the twirls count of the Twirl action.
+    @param amplitude Specify the amplitude of the Twirl action.
+    @return If the initialization success, return true; otherwise, return false.
+    */
+    bool initWithDuration(float duration, const Size& gridSize, const Vec2& position, unsigned int twirls, float amplitude);
+
+protected:
+    /* twirl center */
+    Vec2 _position;
+    unsigned int _twirls;
+    float _amplitude;
+    float _amplitudeRate;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Twirl);
+};
+
+// end of actions group
+/// @}
+
+NS_CC_END
+
+#endif // __ACTION_CCGRID3D_ACTION_H__

+ 633 - 0
cocos2d/cocos/2d/CCActionInstant.cpp

@@ -0,0 +1,633 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2011      Zynga Inc.
+ Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCActionInstant.h"
+#include "2d/CCNode.h"
+#include "2d/CCSprite.h"
+
+#if defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#elif _MSC_VER >= 1400 //vs 2005 or higher
+#pragma warning (push)
+#pragma warning (disable: 4996)
+#endif
+
+NS_CC_BEGIN
+//
+// InstantAction
+//
+bool ActionInstant::isDone() const
+{
+    return true;
+}
+
+void ActionInstant::step(float /*dt*/)
+{
+    float updateDt = 1;
+#if CC_ENABLE_SCRIPT_BINDING
+    if (_scriptType == kScriptTypeJavascript)
+    {
+        if (ScriptEngineManager::sendActionEventToJS(this, kActionUpdate, (void *)&updateDt))
+            return;
+    }
+#endif
+    update(updateDt);
+}
+
+void ActionInstant::update(float /*time*/)
+{
+    // nothing
+}
+
+//
+// Show
+//
+
+Show* Show::create() 
+{
+    Show* ret = new (std::nothrow) Show();
+
+    if (ret)
+    {
+        ret->autorelease();
+    }
+
+    return ret;
+}
+
+void Show::update(float /*time*/)
+{
+    _target->setVisible(true);
+}
+
+ActionInstant* Show::reverse() const
+{
+    return Hide::create();
+}
+
+Show* Show::clone() const
+{
+    // no copy constructor
+    return Show::create();
+}
+
+//
+// Hide
+//
+Hide * Hide::create() 
+{
+    Hide *ret = new (std::nothrow) Hide();
+
+    if (ret)
+    {
+        ret->autorelease();
+    }
+
+    return ret;
+}
+
+void Hide::update(float /*time*/)
+{
+    _target->setVisible(false);
+}
+
+ActionInstant *Hide::reverse() const
+{
+    return Show::create();
+}
+
+Hide* Hide::clone() const
+{
+    // no copy constructor
+    return Hide::create();
+}
+
+//
+// ToggleVisibility
+//
+ToggleVisibility * ToggleVisibility::create()
+{
+    ToggleVisibility *ret = new (std::nothrow) ToggleVisibility();
+
+    if (ret)
+    {
+        ret->autorelease();
+    }
+
+    return ret;
+}
+
+void ToggleVisibility::update(float /*time*/)
+{
+    _target->setVisible(!_target->isVisible());
+}
+
+ToggleVisibility * ToggleVisibility::reverse() const
+{
+    return ToggleVisibility::create();
+}
+
+ToggleVisibility * ToggleVisibility::clone() const
+{
+    // no copy constructor
+    return ToggleVisibility::create();
+}
+
+//
+// Remove Self
+//
+RemoveSelf * RemoveSelf::create(bool isNeedCleanUp /*= true*/) 
+{
+    RemoveSelf *ret = new (std::nothrow) RemoveSelf();
+
+    if (ret && ret->init(isNeedCleanUp))
+    {
+        ret->autorelease();
+    }
+
+    return ret;
+}
+
+bool RemoveSelf::init(bool isNeedCleanUp)
+{
+    _isNeedCleanUp = isNeedCleanUp;
+    return true;
+}
+
+void RemoveSelf::update(float /*time*/)
+{
+    _target->removeFromParentAndCleanup(_isNeedCleanUp);
+}
+
+RemoveSelf *RemoveSelf::reverse() const
+{
+    return RemoveSelf::create(_isNeedCleanUp);
+}
+
+RemoveSelf * RemoveSelf::clone() const
+{
+    // no copy constructor
+    return RemoveSelf::create(_isNeedCleanUp);
+}
+
+//
+// FlipX
+//
+
+FlipX *FlipX::create(bool x)
+{
+    FlipX *ret = new (std::nothrow) FlipX();
+
+    if (ret && ret->initWithFlipX(x))
+    {
+        ret->autorelease();
+        return ret;
+    }
+
+    CC_SAFE_DELETE(ret);
+    return nullptr;
+}
+
+bool FlipX::initWithFlipX(bool x)
+{
+    _flipX = x;
+    return true;
+}
+
+void FlipX::update(float /*time*/)
+{
+    static_cast<Sprite*>(_target)->setFlippedX(_flipX);
+}
+
+FlipX* FlipX::reverse() const
+{
+    return FlipX::create(!_flipX);
+}
+
+FlipX * FlipX::clone() const
+{
+    // no copy constructor
+    return FlipX::create(_flipX);
+}
+//
+// FlipY
+//
+
+FlipY * FlipY::create(bool y)
+{
+    FlipY *ret = new (std::nothrow) FlipY();
+
+    if (ret && ret->initWithFlipY(y))
+    {
+        ret->autorelease();
+        return ret;
+    }
+
+    CC_SAFE_DELETE(ret);
+    return nullptr;
+}
+
+bool FlipY::initWithFlipY(bool y)
+{
+    _flipY = y;
+    return true;
+}
+
+void FlipY::update(float /*time*/)
+{
+    static_cast<Sprite*>(_target)->setFlippedY(_flipY);
+}
+
+FlipY* FlipY::reverse() const
+{
+    return FlipY::create(!_flipY);
+}
+
+FlipY * FlipY::clone() const
+{
+    // no copy constructor
+    return FlipY::create(_flipY);
+}
+
+//
+// Place
+//
+
+Place* Place::create(const Vec2& pos)
+{
+    Place *ret = new (std::nothrow) Place();
+
+    if (ret && ret->initWithPosition(pos))
+    {
+        ret->autorelease();
+        return ret;
+    }
+
+    delete ret;
+    return nullptr;
+}
+
+bool Place::initWithPosition(const Vec2& pos)
+{
+    _position = pos;
+    return true;
+}
+
+Place * Place::clone() const
+{
+    // no copy constructor
+    return Place::create(_position);
+}
+
+Place * Place::reverse() const
+{
+    // no reverse, just clone
+    return this->clone();
+}
+
+void Place::update(float /*time*/)
+{
+    _target->setPosition(_position);
+}
+
+//
+// CallFunc
+//
+
+CallFunc * CallFunc::create(const std::function<void()> &func)
+{
+    CallFunc *ret = new (std::nothrow) CallFunc();
+
+    if (ret && ret->initWithFunction(func) )
+    {
+        ret->autorelease();
+        return ret;
+    }
+
+    CC_SAFE_DELETE(ret);
+    return nullptr;
+}
+
+CallFunc * CallFunc::create(Ref* selectorTarget, SEL_CallFunc selector) 
+{
+    CallFunc *ret = new (std::nothrow) CallFunc();
+
+    if (ret && ret->initWithTarget(selectorTarget))
+    {
+        ret->_callFunc = selector;
+        ret->autorelease();
+        return ret;
+    }
+
+    CC_SAFE_DELETE(ret);
+    return nullptr;
+}
+
+bool CallFunc::initWithFunction(const std::function<void()> &func)
+{
+    _function = func;
+    return true;
+}
+
+bool CallFunc::initWithTarget(Ref* target)
+{
+    if (target)
+    {
+        target->retain();
+    }
+
+    if (_selectorTarget)
+    {
+        _selectorTarget->release();
+    }
+
+    _selectorTarget = target;
+    return true;
+}
+
+CallFunc::~CallFunc()
+{
+    CC_SAFE_RELEASE(_selectorTarget);
+}
+
+CallFunc * CallFunc::clone() const
+    {
+    // no copy constructor
+    auto a = new (std::nothrow) CallFunc();
+    if( _selectorTarget)
+    {
+        a->initWithTarget(_selectorTarget);
+        a->_callFunc = _callFunc;
+    }
+    else if( _function )
+    {
+        a->initWithFunction(_function);
+    }
+
+    a->autorelease();
+    return a;
+}
+
+CallFunc * CallFunc::reverse() const
+{
+    // no reverse here, just return a clone
+    return this->clone();
+}
+
+void CallFunc::update(float /*time*/)
+{
+    this->execute();
+}
+
+void CallFunc::execute()
+{
+    if (_callFunc)
+    {
+        (_selectorTarget->*_callFunc)();
+    } 
+    else if( _function )
+    {
+        _function();
+    }
+}
+
+//
+// CallFuncN
+//
+
+CallFuncN * CallFuncN::create(const std::function<void(Node*)> &func)
+{
+    auto ret = new (std::nothrow) CallFuncN();
+
+    if (ret && ret->initWithFunction(func) )
+    {
+        ret->autorelease();
+        return ret;
+    }
+
+    CC_SAFE_DELETE(ret);
+    return nullptr;
+}
+
+// FIXME: deprecated
+CallFuncN * CallFuncN::create(Ref* selectorTarget, SEL_CallFuncN selector)
+{
+    CallFuncN *ret = new (std::nothrow) CallFuncN();
+
+    if (ret && ret->initWithTarget(selectorTarget, selector))
+    {
+        ret->autorelease();
+        return ret;
+    }
+
+    CC_SAFE_DELETE(ret);
+    return nullptr;
+}
+
+void CallFuncN::execute()
+{
+    if (_callFuncN)
+    {
+        (_selectorTarget->*_callFuncN)(_target);
+    }
+    else if (_functionN)
+    {
+        _functionN(_target);
+    }
+}
+
+bool CallFuncN::initWithFunction(const std::function<void (Node *)> &func)
+{
+    _functionN = func;
+    return true;
+}
+
+bool CallFuncN::initWithTarget(Ref* selectorTarget, SEL_CallFuncN selector)
+{
+    if (CallFunc::initWithTarget(selectorTarget))
+    {
+        _callFuncN = selector;
+        return true;
+    }
+
+    return false;
+}
+
+CallFuncN * CallFuncN::clone() const
+{
+    // no copy constructor
+    auto a = new (std::nothrow) CallFuncN();
+
+    if( _selectorTarget)
+    {
+        a->initWithTarget(_selectorTarget, _callFuncN);
+    }
+    else if( _functionN ){
+        a->initWithFunction(_functionN);
+    }
+
+    a->autorelease();
+    return a;
+}
+
+//
+// CallFuncND
+//
+
+__CCCallFuncND * __CCCallFuncND::create(Ref* selectorTarget, SEL_CallFuncND selector, void* d)
+{
+    __CCCallFuncND* ret = new (std::nothrow) __CCCallFuncND();
+    
+    if (ret && ret->initWithTarget(selectorTarget, selector, d))
+    {
+        ret->autorelease();
+        return ret;
+    }
+    
+    CC_SAFE_DELETE(ret);
+    return nullptr;
+}
+
+bool __CCCallFuncND::initWithTarget(Ref* selectorTarget, SEL_CallFuncND selector, void* d)
+{
+    if (CallFunc::initWithTarget(selectorTarget))
+    {
+        _data = d;
+        _callFuncND = selector;
+        return true;
+    }
+    
+    return false;
+}
+
+void __CCCallFuncND::execute()
+{
+    if (_callFuncND)
+    {
+        (_selectorTarget->*_callFuncND)(_target, _data);
+    }
+}
+
+__CCCallFuncND * __CCCallFuncND::clone() const
+{
+    // no copy constructor
+    auto a = new (std::nothrow) __CCCallFuncND();
+    
+    if( _selectorTarget)
+    {
+        a->initWithTarget(_selectorTarget, _callFuncND, _data);
+    }
+    
+    a->autorelease();
+    return a;
+}
+
+//
+// CallFuncO
+//
+__CCCallFuncO::__CCCallFuncO() :
+_object(nullptr)
+{
+}
+
+__CCCallFuncO::~__CCCallFuncO()
+{
+    CC_SAFE_RELEASE(_object);
+}
+
+void __CCCallFuncO::execute()
+{
+    if (_callFuncO)
+    {
+        (_selectorTarget->*_callFuncO)(_object);
+    }
+}
+
+__CCCallFuncO * __CCCallFuncO::create(Ref* selectorTarget, SEL_CallFuncO selector, Ref* object)
+{
+    __CCCallFuncO *ret = new (std::nothrow) __CCCallFuncO();
+    
+    if (ret && ret->initWithTarget(selectorTarget, selector, object))
+    {
+        ret->autorelease();
+        return ret;
+    }
+    
+    CC_SAFE_DELETE(ret);
+    return nullptr;
+}
+
+bool __CCCallFuncO::initWithTarget(Ref* selectorTarget, SEL_CallFuncO selector, Ref* object)
+{
+    if (CallFunc::initWithTarget(selectorTarget))
+    {
+        _object = object;
+        CC_SAFE_RETAIN(_object);
+        
+        _callFuncO = selector;
+        return true;
+    }
+    
+    return false;
+}
+
+__CCCallFuncO * __CCCallFuncO::clone() const
+{
+    // no copy constructor
+    auto a = new (std::nothrow) __CCCallFuncO();
+    
+    if( _selectorTarget)
+    {
+        a->initWithTarget(_selectorTarget, _callFuncO, _object);
+    }
+    
+    a->autorelease();
+    return a;
+}
+
+Ref* __CCCallFuncO::getObject() const
+{
+    return _object;
+}
+    
+void __CCCallFuncO::setObject(Ref* obj)
+{
+    if (obj != _object)
+    {
+        CC_SAFE_RELEASE(_object);
+        _object = obj;
+        CC_SAFE_RETAIN(_object);
+    }
+}
+
+NS_CC_END
+
+#if defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
+#pragma GCC diagnostic warning "-Wdeprecated-declarations"
+#elif _MSC_VER >= 1400 //vs 2005 or higher
+#pragma warning (pop)
+#endif

+ 556 - 0
cocos2d/cocos/2d/CCActionInstant.h

@@ -0,0 +1,556 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2011      Zynga Inc.
+ Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+
+#ifndef __CCINSTANT_ACTION_H__
+#define __CCINSTANT_ACTION_H__
+
+#include <functional>
+#include "2d/CCAction.h"
+
+NS_CC_BEGIN
+
+/**
+ * @addtogroup actions
+ * @{
+ */
+
+/** @class ActionInstant
+* @brief Instant actions are immediate actions. They don't have a duration like the IntervalAction actions.
+**/
+class CC_DLL ActionInstant : public FiniteTimeAction
+{
+public:
+    //
+    // Overrides
+    //
+    virtual ActionInstant* clone() const override
+    {
+        CC_ASSERT(0);
+        return nullptr;
+    }
+    
+    virtual ActionInstant * reverse() const override
+    {
+        CC_ASSERT(0);
+        return nullptr;
+    }
+
+    virtual bool isDone() const override;
+    /**
+     * @param dt In seconds.
+     */
+    virtual void step(float dt) override;
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+};
+
+/** @class Show
+* @brief Show the node.
+**/
+class CC_DLL Show : public ActionInstant
+{
+public:
+    /** Allocates and initializes the action.
+     *
+     * @return  An autoreleased Show object.
+     */
+    static Show * create();
+
+    //
+    // Overrides
+    //
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    virtual ActionInstant* reverse() const override;
+    virtual Show* clone() const override;
+
+CC_CONSTRUCTOR_ACCESS:
+    Show(){}
+    virtual ~Show(){}
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Show);
+};
+
+/** @class Hide
+* @brief Hide the node.
+*/
+class CC_DLL Hide : public ActionInstant
+{
+public:
+    /** Allocates and initializes the action.
+     *
+     * @return An autoreleased Hide object.
+     */
+    static Hide * create();
+
+    //
+    // Overrides
+    //
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    virtual ActionInstant* reverse() const override;
+    virtual Hide* clone() const override;
+
+CC_CONSTRUCTOR_ACCESS:
+    Hide(){}
+    virtual ~Hide(){}
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Hide);
+};
+
+/** @class ToggleVisibility
+* @brief Toggles the visibility of a node.
+*/
+class CC_DLL ToggleVisibility : public ActionInstant
+{
+public:
+    /** Allocates and initializes the action.
+     *
+     * @return An autoreleased ToggleVisibility object.
+     */
+    static ToggleVisibility * create();
+
+    //
+    // Overrides
+    //
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    virtual ToggleVisibility* reverse() const override;
+    virtual ToggleVisibility* clone() const override;
+
+CC_CONSTRUCTOR_ACCESS:
+    ToggleVisibility(){}
+    virtual ~ToggleVisibility(){}
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(ToggleVisibility);
+};
+
+/** @class RemoveSelf
+* @brief Remove the node.
+*/
+class CC_DLL RemoveSelf : public ActionInstant
+{
+public:
+    /** Create the action.
+     *
+     * @param isNeedCleanUp Is need to clean up, the default value is true.
+     * @return An autoreleased RemoveSelf object.
+     */
+    static RemoveSelf * create(bool isNeedCleanUp = true);
+
+    //
+    // Override
+    //
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    virtual RemoveSelf* clone() const override;
+    virtual RemoveSelf* reverse() const override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    RemoveSelf() : _isNeedCleanUp(true){}
+    virtual ~RemoveSelf(){}
+
+    /** init the action */
+    bool init(bool isNeedCleanUp);
+
+protected:
+    bool _isNeedCleanUp;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(RemoveSelf);
+};
+
+/** @class FlipX
+* @brief Flips the sprite horizontally.
+* @since v0.99.0
+*/
+class CC_DLL FlipX : public ActionInstant
+{
+public:
+    /** Create the action.
+     *
+     * @param x Flips the sprite horizontally if true.
+     * @return  An autoreleased FlipX object.
+     */
+    static FlipX * create(bool x);
+
+    //
+    // Overrides
+    //
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    virtual FlipX* reverse() const override;
+    virtual FlipX* clone() const override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    FlipX() :_flipX(false) {}
+    virtual ~FlipX() {}
+
+    /** init the action */
+    bool initWithFlipX(bool x);
+
+protected:
+    bool    _flipX;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(FlipX);
+};
+
+/** @class FlipY
+* @brief Flips the sprite vertically.
+* @since v0.99.0
+*/
+class CC_DLL FlipY : public ActionInstant
+{
+public:
+    /** Create the action.
+     *
+     * @param y Flips the sprite vertically if true.
+     * @return An autoreleased FlipY object.
+     */
+    static FlipY * create(bool y);
+
+    //
+    // Overrides
+    //
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    virtual FlipY* reverse() const override;
+    virtual FlipY* clone() const override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    FlipY() :_flipY(false) {}
+    virtual ~FlipY() {}
+
+    /** init the action */
+    bool initWithFlipY(bool y);
+
+protected:
+    bool    _flipY;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(FlipY);
+};
+
+/** @class Place
+* @brief Places the node in a certain position.
+*/
+class CC_DLL Place : public ActionInstant
+{
+public:
+
+    /** Creates a Place action with a position.
+     *
+     * @param pos  A certain position.
+     * @return  An autoreleased Place object.
+     */
+    static Place * create(const Vec2& pos);
+
+    //
+    // Overrides
+    //
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    virtual Place* reverse() const override;
+    virtual Place* clone() const override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    Place(){}
+    virtual ~Place(){}
+
+    /** Initializes a Place action with a position */
+    bool initWithPosition(const Vec2& pos);
+
+protected:
+    Vec2 _position;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Place);
+};
+
+
+/** @class CallFunc
+* @brief Calls a 'callback'.
+*/
+class CC_DLL CallFunc : public ActionInstant
+{
+public:
+    /** Creates the action with the callback of type std::function<void()>.
+     This is the preferred way to create the callback.
+     * When this function bound in js or lua ,the input param will be changed.
+     * In js: var create(var func, var this, var [data]) or var create(var func).
+     * In lua:local create(local funcID).
+     *
+     * @param func  A callback function need to be executed.
+     * @return  An autoreleased CallFunc object.
+     */
+    static CallFunc * create(const std::function<void()>& func);
+
+    /** Creates the action with the callback
+
+     typedef void (Ref::*SEL_CallFunc)();
+     @deprecated Use the std::function API instead.
+     * @js NA
+     * @lua NA
+     */
+    CC_DEPRECATED_ATTRIBUTE static CallFunc * create(Ref* target, SEL_CallFunc selector);
+
+public:
+    /** Executes the callback.
+     */
+    virtual void execute();
+
+    /** Get the selector target.
+     *
+     * @return The selector target.
+     */
+    Ref* getTargetCallback()
+    {
+        return _selectorTarget;
+    }
+
+    /** Set the selector target.
+     *
+     * @param sel The selector target.
+     */
+    void setTargetCallback(Ref* sel)
+    {
+        if (sel != _selectorTarget)
+        {
+            CC_SAFE_RETAIN(sel);
+            CC_SAFE_RELEASE(_selectorTarget);
+            _selectorTarget = sel;
+        }
+    }
+    //
+    // Overrides
+    //
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    virtual CallFunc* reverse() const override;
+    virtual CallFunc* clone() const override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    CallFunc()
+    : _selectorTarget(nullptr)
+    , _callFunc(nullptr)
+    , _function(nullptr)
+    {
+    }
+    virtual ~CallFunc();
+
+    /** initializes the action with the callback
+     typedef void (Ref::*SEL_CallFunc)();
+     @deprecated Use the std::function API instead.
+     */
+    CC_DEPRECATED_ATTRIBUTE bool initWithTarget(Ref* target);
+    
+    /** initializes the action with the std::function<void()>
+     * @lua NA
+     */
+    bool initWithFunction(const std::function<void()>& func);
+
+protected:
+    /** Target that will be called */
+    Ref*   _selectorTarget;
+
+    union
+    {
+        SEL_CallFunc    _callFunc;
+        SEL_CallFuncN    _callFuncN;
+    };
+    
+    /** function that will be called */
+    std::function<void()> _function;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(CallFunc);
+};
+
+/** @class CallFuncN
+* @brief Calls a 'callback' with the node as the first argument. N means Node.
+* @js NA
+*/
+class CC_DLL CallFuncN : public CallFunc
+{
+public:
+    /** Creates the action with the callback of type std::function<void()>.
+     This is the preferred way to create the callback.
+     *
+     * @param func  A callback function need to be executed.
+     * @return  An autoreleased CallFuncN object.
+     */
+    static CallFuncN * create(const std::function<void(Node*)>& func);
+
+    /** Creates the action with the callback.
+
+    typedef void (Ref::*SEL_CallFuncN)(Node*);
+     @deprecated Use the std::function API instead.
+    */
+    CC_DEPRECATED_ATTRIBUTE static CallFuncN * create(Ref* target, SEL_CallFuncN selector);
+
+    //
+    // Overrides
+    //
+    virtual CallFuncN* clone() const override;
+    virtual void execute() override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    CallFuncN():_functionN(nullptr){}
+    virtual ~CallFuncN(){}
+
+    /** initializes the action with the std::function<void(Node*)> */
+    bool initWithFunction(const std::function<void(Node*)>& func);
+    
+    /** initializes the action with the callback
+     
+     typedef void (Ref::*SEL_CallFuncN)(Node*);
+     @deprecated Use the std::function API instead.
+     */
+    CC_DEPRECATED_ATTRIBUTE bool initWithTarget(Ref* target, SEL_CallFuncN selector);
+
+protected:
+    /** function that will be called with the "sender" as the 1st argument */
+    std::function<void(Node*)> _functionN;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(CallFuncN);
+};
+
+/** @class __CCCallFuncND
+ * @deprecated Please use CallFuncN instead.
+ * @brief Calls a 'callback' with the node as the first argument and the 2nd argument is data.
+ * ND means: Node and Data. Data is void *, so it could be anything.
+ * @js NA
+ */
+class CC_DLL  __CCCallFuncND : public CallFunc
+{
+public:
+    /** Creates the action with the callback and the data to pass as an argument.
+     *
+     * @param target    A certain target.
+     * @param selector  The callback need to be executed.
+     * @param d Data, is void* type.
+     * @return An autoreleased __CCCallFuncND object.
+     */
+    CC_DEPRECATED_ATTRIBUTE static __CCCallFuncND * create(Ref* target, SEL_CallFuncND selector, void* d);
+    
+    //
+    // Overrides
+    //
+    virtual __CCCallFuncND* clone() const override;
+    virtual void execute() override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    __CCCallFuncND() {}
+    virtual ~__CCCallFuncND() {}
+    
+    /** initializes the action with the callback and the data to pass as an argument */
+    bool initWithTarget(Ref* target, SEL_CallFuncND selector, void* d);
+
+protected:
+    SEL_CallFuncND _callFuncND;
+    void* _data;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(__CCCallFuncND);
+};
+
+
+/** @class __CCCallFuncO
+ @deprecated Please use CallFuncN instead.
+ @brief Calls a 'callback' with an object as the first argument. O means Object.
+ @since v0.99.5
+ @js NA
+ */
+
+class CC_DLL __CCCallFuncO : public CallFunc
+{
+public:
+    /** Creates the action with the callback.
+        typedef void (Ref::*SEL_CallFuncO)(Ref*);
+     *
+     * @param target    A certain target.
+     * @param selector  The callback need to be executed.
+     * @param object    An object as the callback's first argument.
+     * @return An autoreleased __CCCallFuncO object.
+     */
+    CC_DEPRECATED_ATTRIBUTE static __CCCallFuncO * create(Ref* target, SEL_CallFuncO selector, Ref* object);
+    //
+    // Overrides
+    //
+    virtual __CCCallFuncO* clone() const override;
+    virtual void execute() override;
+    
+    Ref* getObject() const;
+    void setObject(Ref* obj);
+    
+CC_CONSTRUCTOR_ACCESS:
+    __CCCallFuncO();
+    virtual ~__CCCallFuncO();
+    /** initializes the action with the callback
+
+     typedef void (Ref::*SEL_CallFuncO)(Ref*);
+     */
+    bool initWithTarget(Ref* target, SEL_CallFuncO selector, Ref* object);
+    
+protected:
+    /** object to be passed as argument */
+    Ref* _object;
+    SEL_CallFuncO _callFuncO;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(__CCCallFuncO);
+};
+
+// end of actions group
+/// @}
+
+NS_CC_END
+
+#endif //__CCINSTANT_ACTION_H__

+ 2852 - 0
cocos2d/cocos/2d/CCActionInterval.cpp

@@ -0,0 +1,2852 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCActionInterval.h"
+
+#include <stdarg.h>
+
+#include "2d/CCSprite.h"
+#include "2d/CCNode.h"
+#include "2d/CCSpriteFrame.h"
+#include "2d/CCActionInstant.h"
+#include "base/CCDirector.h"
+#include "base/CCEventCustom.h"
+#include "base/CCEventDispatcher.h"
+#include "platform/CCStdC.h"
+#include "base/CCScriptSupport.h"
+
+NS_CC_BEGIN
+
+// Extra action for making a Sequence or Spawn when only adding one action to it.
+class ExtraAction : public FiniteTimeAction
+{
+public:
+    static ExtraAction* create();
+    virtual ExtraAction* clone() const;
+    virtual ExtraAction* reverse(void) const;
+    virtual void update(float time);
+    virtual void step(float dt);
+};
+
+ExtraAction* ExtraAction::create()
+{
+    ExtraAction* ret = new (std::nothrow) ExtraAction();
+    if (ret)
+    {
+        ret->autorelease();
+    }
+    return ret;
+}
+
+ExtraAction* ExtraAction::clone() const
+{
+    // no copy constructor
+    return ExtraAction::create();
+}
+
+ExtraAction* ExtraAction::reverse() const
+{
+    return ExtraAction::create();
+}
+
+void ExtraAction::update(float /*time*/)
+{
+}
+
+void ExtraAction::step(float /*dt*/)
+{
+}
+
+//
+// IntervalAction
+//
+
+bool ActionInterval::initWithDuration(float d)
+{
+    _duration = d;
+
+    // prevent division by 0
+    // This comparison could be in step:, but it might decrease the performance
+    // by 3% in heavy based action games.
+    if (_duration <= FLT_EPSILON)
+    {
+        _duration = FLT_EPSILON;
+    }
+
+    _elapsed = 0;
+    _firstTick = true;
+
+    return true;
+}
+
+bool ActionInterval::sendUpdateEventToScript(float dt, Action *actionObject)
+{
+#if CC_ENABLE_SCRIPT_BINDING
+    if (_scriptType == kScriptTypeJavascript)
+    {
+        if (ScriptEngineManager::sendActionEventToJS(actionObject, kActionUpdate, (void *)&dt))
+            return true;
+    }
+#endif
+    return false;
+}
+
+bool ActionInterval::isDone() const
+{
+    // fix #14936 _duration is not 0, but _elapsed is 0.
+    return (_elapsed + FLT_EPSILON) >= _duration;
+}
+
+void ActionInterval::step(float dt)
+{
+    if (_firstTick)
+    {
+        _firstTick = false;
+        _elapsed = 0;
+    }
+    else
+    {
+        _elapsed += dt;
+    }
+    
+    
+    float updateDt = MAX (0,                                  // needed for rewind. elapsed could be negative
+                           MIN(1, _elapsed / _duration)
+                           );
+
+    if (sendUpdateEventToScript(updateDt, this)) return;
+    
+    this->update(updateDt);
+}
+
+void ActionInterval::setAmplitudeRate(float /*amp*/)
+{
+    // Abstract class needs implementation
+    CCASSERT(0, "Subclass should implement this method!");
+}
+
+float ActionInterval::getAmplitudeRate()
+{
+    // Abstract class needs implementation
+    CCASSERT(0, "Subclass should implement this method!");
+
+    return 0;
+}
+
+void ActionInterval::startWithTarget(Node *target)
+{
+    FiniteTimeAction::startWithTarget(target);
+    _elapsed = 0.0f;
+    _firstTick = true;
+}
+
+//
+// Sequence
+//
+
+Sequence* Sequence::createWithTwoActions(FiniteTimeAction *actionOne, FiniteTimeAction *actionTwo)
+{
+    Sequence *sequence = new (std::nothrow) Sequence();
+    if (sequence && sequence->initWithTwoActions(actionOne, actionTwo))
+    {
+        sequence->autorelease();
+        return sequence;
+    }
+    
+    delete sequence;
+    return nullptr;
+}
+
+#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
+Sequence* Sequence::variadicCreate(FiniteTimeAction *action1, ...)
+{
+    va_list params;
+    va_start(params, action1);
+
+    Sequence *ret = Sequence::createWithVariableList(action1, params);
+
+    va_end(params);
+    
+    return ret;
+}
+#else
+Sequence* Sequence::create(FiniteTimeAction *action1, ...)
+{
+    va_list params;
+    va_start(params, action1);
+
+    Sequence *ret = Sequence::createWithVariableList(action1, params);
+
+    va_end(params);
+    
+    return ret;
+}
+#endif
+
+Sequence* Sequence::createWithVariableList(FiniteTimeAction *action1, va_list args)
+{
+    FiniteTimeAction *now;
+    FiniteTimeAction *prev = action1;
+    bool bOneAction = true;
+
+    while (action1)
+    {
+        now = va_arg(args, FiniteTimeAction*);
+        if (now)
+        {
+            prev = createWithTwoActions(prev, now);
+            bOneAction = false;
+        }
+        else
+        {
+            // If only one action is added to Sequence, make up a Sequence by adding a simplest finite time action.
+            if (bOneAction)
+            {
+                prev = createWithTwoActions(prev, ExtraAction::create());
+            }
+            break;
+        }
+    }
+    
+    return ((Sequence*)prev);
+}
+
+Sequence* Sequence::create(const Vector<FiniteTimeAction*>& arrayOfActions)
+{
+    Sequence* seq = new (std::nothrow) Sequence;
+    
+    if (seq && seq->init(arrayOfActions))
+    {
+        seq->autorelease();
+        return seq;
+    }
+    
+    delete seq;
+    return nullptr;
+}
+
+bool Sequence::init(const Vector<FiniteTimeAction*>& arrayOfActions)
+{
+    auto count = arrayOfActions.size();
+    if (count == 0)
+        return false;
+
+    if (count == 1)
+        return initWithTwoActions(arrayOfActions.at(0), ExtraAction::create());
+
+    // else size > 1
+    auto prev = arrayOfActions.at(0);
+    for (int i = 1; i < count-1; ++i)
+    {
+        prev = createWithTwoActions(prev, arrayOfActions.at(i));
+    }
+
+    return initWithTwoActions(prev, arrayOfActions.at(count-1));
+}
+
+bool Sequence::initWithTwoActions(FiniteTimeAction *actionOne, FiniteTimeAction *actionTwo)
+{
+    CCASSERT(actionOne != nullptr, "actionOne can't be nullptr!");
+    CCASSERT(actionTwo != nullptr, "actionTwo can't be nullptr!");
+    if (actionOne == nullptr || actionTwo == nullptr)
+    {
+        log("Sequence::initWithTwoActions error: action is nullptr!!");
+        return false;
+    }
+
+    float d = actionOne->getDuration() + actionTwo->getDuration();
+    ActionInterval::initWithDuration(d);
+
+    _actions[0] = actionOne;
+    actionOne->retain();
+
+    _actions[1] = actionTwo;
+    actionTwo->retain();
+
+    return true;
+}
+
+Sequence* Sequence::clone() const
+{
+    // no copy constructor
+    if (_actions[0] && _actions[1])
+    {
+        return Sequence::create(_actions[0]->clone(), _actions[1]->clone(), nullptr);
+    } else {
+        return nullptr;
+    }
+}
+
+Sequence::Sequence()
+: _split(0)
+{
+    _actions[0] = nullptr;
+    _actions[1] = nullptr;
+}
+
+Sequence::~Sequence()
+{
+    CC_SAFE_RELEASE(_actions[0]);
+    CC_SAFE_RELEASE(_actions[1]);
+}
+
+void Sequence::startWithTarget(Node *target)
+{
+    if (target == nullptr)
+    {
+        log("Sequence::startWithTarget error: target is nullptr!");
+        return;
+    }
+    if (_actions[0] == nullptr || _actions[1] == nullptr)
+    {
+        log("Sequence::startWithTarget error: _actions[0] or _actions[1] is nullptr!");
+        return;
+    }
+    if (_duration > FLT_EPSILON)
+        // fix #14936 - FLT_EPSILON (instant action) / very fast duration (0.001) leads to worng split, that leads to call instant action few times
+        _split = _actions[0]->getDuration() > FLT_EPSILON ? _actions[0]->getDuration() / _duration : 0;
+    
+    ActionInterval::startWithTarget(target);
+    _last = -1;
+}
+
+void Sequence::stop(void)
+{
+    // Issue #1305
+    if( _last != - 1 && _actions[_last])
+    {
+        _actions[_last]->stop();
+    }
+
+    ActionInterval::stop();
+}
+
+void Sequence::update(float t)
+{
+    int found = 0;
+    float new_t = 0.0f;
+
+    if( t < _split )
+    {
+        // action[0]
+        found = 0;
+        if( _split != 0 )
+            new_t = t / _split;
+        else
+            new_t = 1;
+
+    }
+    else
+    {
+        // action[1]
+        found = 1;
+        if ( _split == 1 )
+            new_t = 1;
+        else
+            new_t = (t-_split) / (1 - _split );
+    }
+
+    if ( found==1 )
+    {
+        if( _last == -1 )
+        {
+            // action[0] was skipped, execute it.
+            _actions[0]->startWithTarget(_target);
+            if (!(sendUpdateEventToScript(1.0f, _actions[0])))
+                _actions[0]->update(1.0f);
+            _actions[0]->stop();
+        }
+        else if( _last == 0 )
+        {
+            // switching to action 1. stop action 0.
+            if (!(sendUpdateEventToScript(1.0f, _actions[0])))
+                _actions[0]->update(1.0f);
+            _actions[0]->stop();
+        }
+    }
+    else if(found==0 && _last==1 )
+    {
+        // Reverse mode ?
+        // FIXME: Bug. this case doesn't contemplate when _last==-1, found=0 and in "reverse mode"
+        // since it will require a hack to know if an action is on reverse mode or not.
+        // "step" should be overridden, and the "reverseMode" value propagated to inner Sequences.
+        if (!(sendUpdateEventToScript(0, _actions[1])))
+            _actions[1]->update(0);
+        _actions[1]->stop();
+    }
+    // Last action found and it is done.
+    if( found == _last && _actions[found]->isDone() )
+    {
+        return;
+    }
+
+    // Last action found and it is done
+    if( found != _last )
+    {
+        _actions[found]->startWithTarget(_target);
+    }
+    if (!(sendUpdateEventToScript(new_t, _actions[found])))
+        _actions[found]->update(new_t);
+    _last = found;
+}
+
+Sequence* Sequence::reverse() const
+{
+    if (_actions[0] && _actions[1])
+        return Sequence::createWithTwoActions(_actions[1]->reverse(), _actions[0]->reverse());
+    else
+        return nullptr;
+}
+
+//
+// Repeat
+//
+
+Repeat* Repeat::create(FiniteTimeAction *action, unsigned int times)
+{
+    Repeat* repeat = new (std::nothrow) Repeat();
+    if (repeat && repeat->initWithAction(action, times))
+    {
+        repeat->autorelease();
+        return repeat;
+    }
+
+    delete repeat;
+    return nullptr;
+}
+
+bool Repeat::initWithAction(FiniteTimeAction *action, unsigned int times)
+{
+    float d = action->getDuration() * times;
+
+    if (action && ActionInterval::initWithDuration(d))
+    {
+        _times = times;
+        _innerAction = action;
+        action->retain();
+
+        _actionInstant = dynamic_cast<ActionInstant*>(action) ? true : false;
+        //an instant action needs to be executed one time less in the update method since it uses startWithTarget to execute the action
+        // minggo: instant action doesn't execute action in Repeat::startWithTarget(), so comment it.
+//        if (_actionInstant) 
+//        {
+//            _times -=1;
+//        }
+        _total = 0;
+
+        return true;
+    }
+
+    return false;
+}
+
+Repeat* Repeat::clone(void) const
+{
+    // no copy constructor
+    return Repeat::create(_innerAction->clone(), _times);
+}
+
+Repeat::~Repeat(void)
+{
+    CC_SAFE_RELEASE(_innerAction);
+}
+
+void Repeat::startWithTarget(Node *target)
+{
+    _total = 0;
+    _nextDt = _innerAction->getDuration()/_duration;
+    ActionInterval::startWithTarget(target);
+    _innerAction->startWithTarget(target);
+}
+
+void Repeat::stop(void)
+{
+    _innerAction->stop();
+    ActionInterval::stop();
+}
+
+// issue #80. Instead of hooking step:, hook update: since it can be called by any 
+// container action like Repeat, Sequence, Ease, etc..
+void Repeat::update(float dt)
+{
+    if (dt >= _nextDt)
+    {
+        while (dt >= _nextDt && _total < _times)
+        {
+            if (!(sendUpdateEventToScript(1.0f, _innerAction)))
+                _innerAction->update(1.0f);
+            _total++;
+
+            _innerAction->stop();
+            _innerAction->startWithTarget(_target);
+            _nextDt = _innerAction->getDuration()/_duration * (_total+1);
+        }
+
+        // fix for issue #1288, incorrect end value of repeat
+        if (std::abs(dt - 1.0f) < FLT_EPSILON && _total < _times)
+        {
+            if (!(sendUpdateEventToScript(1.0f, _innerAction)))
+                _innerAction->update(1.0f);
+            
+            _total++;
+        }
+
+        // don't set an instant action back or update it, it has no use because it has no duration
+        if (!_actionInstant)
+        {
+            if (_total == _times)
+            {
+                // minggo: inner action update is invoked above, don't have to invoke it here
+//                if (!(sendUpdateEventToScript(1, _innerAction)))
+//                    _innerAction->update(1);
+                _innerAction->stop();
+            }
+            else
+            {
+                // issue #390 prevent jerk, use right update
+                if (!(sendUpdateEventToScript(dt - (_nextDt - _innerAction->getDuration()/_duration), _innerAction)))
+                    _innerAction->update(dt - (_nextDt - _innerAction->getDuration()/_duration));
+            }
+        }
+    }
+    else
+    {
+        if (!(sendUpdateEventToScript(fmodf(dt * _times,1.0f), _innerAction)))
+            _innerAction->update(fmodf(dt * _times,1.0f));
+    }
+}
+
+bool Repeat::isDone(void) const
+{
+    return _total == _times;
+}
+
+Repeat* Repeat::reverse() const
+{
+    return Repeat::create(_innerAction->reverse(), _times);
+}
+
+//
+// RepeatForever
+//
+RepeatForever::~RepeatForever()
+{
+    CC_SAFE_RELEASE(_innerAction);
+}
+
+RepeatForever *RepeatForever::create(ActionInterval *action)
+{
+    RepeatForever *ret = new (std::nothrow) RepeatForever();
+    if (ret && ret->initWithAction(action))
+    {
+        ret->autorelease();
+        return ret;
+    }
+    
+    delete ret;
+    return nullptr;
+}
+
+bool RepeatForever::initWithAction(ActionInterval *action)
+{
+    CCASSERT(action != nullptr, "action can't be nullptr!");
+    if (action == nullptr)
+    {
+        log("RepeatForever::initWithAction error:action is nullptr!");
+        return false;
+    }
+    
+    action->retain();
+    _innerAction = action;
+    
+    return true;
+}
+
+RepeatForever *RepeatForever::clone() const
+{
+    // no copy constructor
+    return RepeatForever::create(_innerAction->clone());
+}
+
+void RepeatForever::startWithTarget(Node* target)
+{
+    ActionInterval::startWithTarget(target);
+    _innerAction->startWithTarget(target);
+}
+
+void RepeatForever::step(float dt)
+{
+    _innerAction->step(dt);
+    if (_innerAction->isDone())
+    {
+        float diff = _innerAction->getElapsed() - _innerAction->getDuration();
+        if (diff > _innerAction->getDuration())
+            diff = fmodf(diff, _innerAction->getDuration());
+        _innerAction->startWithTarget(_target);
+        // to prevent jerk. issue #390, 1247
+        _innerAction->step(0.0f);
+        _innerAction->step(diff);
+    }
+}
+
+bool RepeatForever::isDone() const
+{
+    return false;
+}
+
+RepeatForever *RepeatForever::reverse() const
+{
+    return RepeatForever::create(_innerAction->reverse());
+}
+
+//
+// Spawn
+//
+
+#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
+Spawn* Spawn::variadicCreate(FiniteTimeAction *action1, ...)
+{
+    va_list params;
+    va_start(params, action1);
+
+    Spawn *ret = Spawn::createWithVariableList(action1, params);
+
+    va_end(params);
+    
+    return ret;
+}
+#else
+Spawn* Spawn::create(FiniteTimeAction *action1, ...)
+{
+    va_list params;
+    va_start(params, action1);
+
+    Spawn *ret = Spawn::createWithVariableList(action1, params);
+
+    va_end(params);
+    
+    return ret;
+}
+#endif
+
+Spawn* Spawn::createWithVariableList(FiniteTimeAction *action1, va_list args)
+{
+    FiniteTimeAction *now;
+    FiniteTimeAction *prev = action1;
+    bool oneAction = true;
+
+    while (action1)
+    {
+        now = va_arg(args, FiniteTimeAction*);
+        if (now)
+        {
+            prev = createWithTwoActions(prev, now);
+            oneAction = false;
+        }
+        else
+        {
+            // If only one action is added to Spawn, make up a Spawn by adding a simplest finite time action.
+            if (oneAction)
+            {
+                prev = createWithTwoActions(prev, ExtraAction::create());
+            }
+            break;
+        }
+    }
+
+    return ((Spawn*)prev);
+}
+
+Spawn* Spawn::create(const Vector<FiniteTimeAction*>& arrayOfActions)
+{
+    Spawn* ret = new (std::nothrow) Spawn;
+    
+    if (ret && ret->init(arrayOfActions))
+    {
+        ret->autorelease();
+        return ret;
+    }
+    
+    delete ret;
+    return nullptr;
+}
+
+Spawn* Spawn::createWithTwoActions(FiniteTimeAction *action1, FiniteTimeAction *action2)
+{
+    Spawn *spawn = new (std::nothrow) Spawn();
+    if (spawn && spawn->initWithTwoActions(action1, action2))
+    {
+        spawn->autorelease();
+        return spawn;
+    }
+    
+    delete spawn;
+    return nullptr;
+}
+
+bool Spawn::init(const Vector<FiniteTimeAction*>& arrayOfActions)
+{
+    auto count = arrayOfActions.size();
+    
+    if (count == 0)
+        return false;
+    
+    if (count == 1)
+        return initWithTwoActions(arrayOfActions.at(0), ExtraAction::create());
+    
+    // else count > 1
+    auto prev = arrayOfActions.at(0);
+    for (int i = 1; i < count-1; ++i)
+    {
+        prev = createWithTwoActions(prev, arrayOfActions.at(i));
+    }
+    
+    return initWithTwoActions(prev, arrayOfActions.at(count-1));
+}
+
+bool Spawn::initWithTwoActions(FiniteTimeAction *action1, FiniteTimeAction *action2)
+{
+    CCASSERT(action1 != nullptr, "action1 can't be nullptr!");
+    CCASSERT(action2 != nullptr, "action2 can't be nullptr!");
+    if (action1 == nullptr || action2 == nullptr)
+    {
+        log("Spawn::initWithTwoActions error: action is nullptr!");
+        return false;
+    }
+
+    bool ret = false;
+
+    float d1 = action1->getDuration();
+    float d2 = action2->getDuration();
+
+    if (ActionInterval::initWithDuration(MAX(d1, d2)))
+    {
+        _one = action1;
+        _two = action2;
+
+        if (d1 > d2)
+        {
+            _two = Sequence::createWithTwoActions(action2, DelayTime::create(d1 - d2));
+        } 
+        else if (d1 < d2)
+        {
+            _one = Sequence::createWithTwoActions(action1, DelayTime::create(d2 - d1));
+        }
+
+        _one->retain();
+        _two->retain();
+
+        ret = true;
+    }
+
+    return ret;
+}
+
+Spawn* Spawn::clone(void) const
+{
+    // no copy constructor
+    if (_one && _two)
+        return Spawn::createWithTwoActions(_one->clone(), _two->clone());
+    else
+        return nullptr;
+}
+
+Spawn::Spawn()
+: _one(nullptr)
+, _two(nullptr)
+{
+    
+}
+
+Spawn::~Spawn(void)
+{
+    CC_SAFE_RELEASE(_one);
+    CC_SAFE_RELEASE(_two);
+}
+
+void Spawn::startWithTarget(Node *target)
+{
+    if (target == nullptr)
+    {
+        log("Spawn::startWithTarget error: target is nullptr!");
+        return;
+    }
+    if (_one == nullptr || _two == nullptr)
+    {
+        log("Spawn::startWithTarget error: _one or _two is nullptr!");
+        return;
+    }
+    
+    ActionInterval::startWithTarget(target);
+    _one->startWithTarget(target);
+    _two->startWithTarget(target);
+}
+
+void Spawn::stop(void)
+{
+    if (_one)
+        _one->stop();
+
+    if (_two)
+        _two->stop();
+
+    ActionInterval::stop();
+}
+
+void Spawn::update(float time)
+{
+    if (_one)
+    {
+        if (!(sendUpdateEventToScript(time, _one)))
+            _one->update(time);
+    }
+    if (_two)
+    {
+        if (!(sendUpdateEventToScript(time, _two)))
+            _two->update(time);
+    }
+}
+
+Spawn* Spawn::reverse() const
+{
+    if (_one && _two)
+        return Spawn::createWithTwoActions(_one->reverse(), _two->reverse());
+    
+    return nullptr;
+}
+
+//
+// RotateTo
+//
+
+RotateTo* RotateTo::create(float duration, float dstAngle)
+{
+    RotateTo* rotateTo = new (std::nothrow) RotateTo();
+    if (rotateTo && rotateTo->initWithDuration(duration, dstAngle, dstAngle))
+    {
+        rotateTo->autorelease();
+        return rotateTo;
+    }
+    
+    delete rotateTo;
+    return nullptr;
+}
+
+RotateTo* RotateTo::create(float duration, float dstAngleX, float dstAngleY)
+{
+    RotateTo* rotateTo = new (std::nothrow) RotateTo();
+    if (rotateTo && rotateTo->initWithDuration(duration, dstAngleX, dstAngleY))
+    {
+        rotateTo->autorelease();
+        return rotateTo;
+    }
+    
+    delete rotateTo;
+    return nullptr;
+}
+
+RotateTo* RotateTo::create(float duration, const Vec3& dstAngle3D)
+{
+    RotateTo* rotateTo = new (std::nothrow) RotateTo();
+    if(rotateTo && rotateTo->initWithDuration(duration, dstAngle3D))
+    {
+        rotateTo->autorelease();
+        return rotateTo;
+    }
+
+    delete rotateTo;
+    return nullptr;
+}
+
+RotateTo::RotateTo()
+: _is3D(false)
+{
+}
+
+bool RotateTo::initWithDuration(float duration, float dstAngleX, float dstAngleY)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _dstAngle.x = dstAngleX;
+        _dstAngle.y = dstAngleY;
+        
+        return true;
+    }
+    
+    return false;
+}
+
+bool RotateTo::initWithDuration(float duration, const Vec3& dstAngle3D)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _dstAngle = dstAngle3D;
+        _is3D = true;
+        
+        return true;
+    }
+    
+    return false;
+}
+
+RotateTo* RotateTo::clone(void) const
+{
+    // no copy constructor
+    auto a = new (std::nothrow) RotateTo();
+    if(_is3D)
+       a->initWithDuration(_duration, _dstAngle);
+    else
+        a->initWithDuration(_duration, _dstAngle.x, _dstAngle.y);
+    a->autorelease();
+    return a;
+}
+
+void RotateTo::calculateAngles(float &startAngle, float &diffAngle, float dstAngle)
+{
+    if (startAngle > 0)
+    {
+        startAngle = fmodf(startAngle, 360.0f);
+    }
+    else
+    {
+        startAngle = fmodf(startAngle, -360.0f);
+    }
+
+    diffAngle = dstAngle - startAngle;
+    if (diffAngle > 180)
+    {
+        diffAngle -= 360;
+    }
+    if (diffAngle < -180)
+    {
+        diffAngle += 360;
+    }
+}
+
+void RotateTo::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    
+    if (_is3D)
+    {
+        _startAngle = _target->getRotation3D();
+    }
+    else
+    {
+        _startAngle.x = _target->getRotationSkewX();
+        _startAngle.y = _target->getRotationSkewY();
+    }
+
+    calculateAngles(_startAngle.x, _diffAngle.x, _dstAngle.x);
+    calculateAngles(_startAngle.y, _diffAngle.y, _dstAngle.y);
+    calculateAngles(_startAngle.z, _diffAngle.z, _dstAngle.z);
+}
+
+void RotateTo::update(float time)
+{
+    if (_target)
+    {
+        if(_is3D)
+        {
+            _target->setRotation3D(Vec3(
+                _startAngle.x + _diffAngle.x * time,
+                _startAngle.y + _diffAngle.y * time,
+                _startAngle.z + _diffAngle.z * time
+            ));
+        }
+        else
+        {
+#if CC_USE_PHYSICS
+            if (_startAngle.x == _startAngle.y && _diffAngle.x == _diffAngle.y)
+            {
+                _target->setRotation(_startAngle.x + _diffAngle.x * time);
+            }
+            else
+            {
+                _target->setRotationSkewX(_startAngle.x + _diffAngle.x * time);
+                _target->setRotationSkewY(_startAngle.y + _diffAngle.y * time);
+            }
+#else
+            _target->setRotationSkewX(_startAngle.x + _diffAngle.x * time);
+            _target->setRotationSkewY(_startAngle.y + _diffAngle.y * time);
+#endif // CC_USE_PHYSICS
+        }
+    }
+}
+
+RotateTo *RotateTo::reverse() const
+{
+    CCASSERT(false, "RotateTo doesn't support the 'reverse' method");
+    return nullptr;
+}
+
+//
+// RotateBy
+//
+
+RotateBy* RotateBy::create(float duration, float deltaAngle)
+{
+    RotateBy *rotateBy = new (std::nothrow) RotateBy();
+    if (rotateBy && rotateBy->initWithDuration(duration, deltaAngle))
+    {
+        rotateBy->autorelease();
+        return rotateBy;
+    }
+    
+    delete rotateBy;
+    return nullptr;
+}
+
+RotateBy* RotateBy::create(float duration, float deltaAngleX, float deltaAngleY)
+{
+    RotateBy *rotateBy = new (std::nothrow) RotateBy();
+    if (rotateBy && rotateBy->initWithDuration(duration, deltaAngleX, deltaAngleY))
+    {
+        rotateBy->autorelease();
+        return rotateBy;
+    }
+
+    delete rotateBy;
+    return nullptr;
+}
+
+RotateBy* RotateBy::create(float duration, const Vec3& deltaAngle3D)
+{
+    RotateBy *rotateBy = new (std::nothrow) RotateBy();
+    if(rotateBy && rotateBy->initWithDuration(duration, deltaAngle3D))
+    {
+        rotateBy->autorelease();
+        return rotateBy;
+    }
+
+    delete rotateBy;
+    return nullptr;
+}
+
+RotateBy::RotateBy()
+: _is3D(false)
+{
+}
+
+bool RotateBy::initWithDuration(float duration, float deltaAngle)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _deltaAngle.x = _deltaAngle.y = deltaAngle;
+        return true;
+    }
+
+    return false;
+}
+
+bool RotateBy::initWithDuration(float duration, float deltaAngleX, float deltaAngleY)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _deltaAngle.x = deltaAngleX;
+        _deltaAngle.y = deltaAngleY;
+        return true;
+    }
+    
+    return false;
+}
+
+bool RotateBy::initWithDuration(float duration, const Vec3& deltaAngle3D)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _deltaAngle = deltaAngle3D;
+        _is3D = true;
+        return true;
+    }
+
+    return false;
+}
+
+
+RotateBy* RotateBy::clone() const
+{
+    // no copy constructor
+    auto a = new (std::nothrow) RotateBy();
+    if(_is3D)
+        a->initWithDuration(_duration, _deltaAngle);
+    else
+        a->initWithDuration(_duration, _deltaAngle.x, _deltaAngle.y);
+    a->autorelease();
+    return a;
+}
+
+void RotateBy::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    if(_is3D)
+    {
+        _startAngle = target->getRotation3D();
+    }
+    else
+    {
+        _startAngle.x = target->getRotationSkewX();
+        _startAngle.y = target->getRotationSkewY();
+    }
+}
+
+void RotateBy::update(float time)
+{
+    // FIXME: shall I add % 360
+    if (_target)
+    {
+        if(_is3D)
+        {
+            Vec3 v;
+            v.x = _startAngle.x + _deltaAngle.x * time;
+            v.y = _startAngle.y + _deltaAngle.y * time;
+            v.z = _startAngle.z + _deltaAngle.z * time;
+            _target->setRotation3D(v);
+        }
+        else
+        {
+#if CC_USE_PHYSICS
+            if (_startAngle.x == _startAngle.y && _deltaAngle.x == _deltaAngle.y)
+            {
+                _target->setRotation(_startAngle.x + _deltaAngle.x * time);
+            }
+            else
+            {
+                _target->setRotationSkewX(_startAngle.x + _deltaAngle.x * time);
+                _target->setRotationSkewY(_startAngle.y + _deltaAngle.y * time);
+            }
+#else
+            _target->setRotationSkewX(_startAngle.x + _deltaAngle.x * time);
+            _target->setRotationSkewY(_startAngle.y + _deltaAngle.y * time);
+#endif // CC_USE_PHYSICS
+        }
+    }
+}
+
+RotateBy* RotateBy::reverse() const
+{
+    if(_is3D)
+    {
+        Vec3 v;
+        v.x = - _deltaAngle.x;
+        v.y = - _deltaAngle.y;
+        v.z = - _deltaAngle.z;
+        return RotateBy::create(_duration, v);
+    }
+    else
+    {
+        return RotateBy::create(_duration, -_deltaAngle.x, -_deltaAngle.y);
+    }
+}
+
+//
+// MoveBy
+//
+
+MoveBy* MoveBy::create(float duration, const Vec2& deltaPosition)
+{
+    return MoveBy::create(duration, Vec3(deltaPosition.x, deltaPosition.y, 0));
+}
+
+MoveBy* MoveBy::create(float duration, const Vec3 &deltaPosition)
+{
+    MoveBy *ret = new (std::nothrow) MoveBy();
+    
+    if (ret && ret->initWithDuration(duration, deltaPosition))
+    {
+        ret->autorelease();
+        return ret;
+    }
+    
+    delete ret;
+    return nullptr;
+}
+
+bool MoveBy::initWithDuration(float duration, const Vec2& deltaPosition)
+{
+    return MoveBy::initWithDuration(duration, Vec3(deltaPosition.x, deltaPosition.y, 0));
+}
+
+bool MoveBy::initWithDuration(float duration, const Vec3& deltaPosition)
+{
+    bool ret = false;
+    
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _positionDelta = deltaPosition;
+        _is3D = true;
+        ret = true;
+    }
+    
+    return ret;
+}
+
+MoveBy* MoveBy::clone() const
+{
+    // no copy constructor
+    return MoveBy::create(_duration, _positionDelta);
+}
+
+void MoveBy::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    _previousPosition = _startPosition = target->getPosition3D();
+}
+
+MoveBy* MoveBy::reverse() const
+{
+    return MoveBy::create(_duration, -_positionDelta);
+}
+
+void MoveBy::update(float t)
+{
+    if (_target)
+    {
+#if CC_ENABLE_STACKABLE_ACTIONS
+        Vec3 currentPos = _target->getPosition3D();
+        Vec3 diff = currentPos - _previousPosition;
+        _startPosition = _startPosition + diff;
+        Vec3 newPos =  _startPosition + (_positionDelta * t);
+        _target->setPosition3D(newPos);
+        _previousPosition = newPos;
+#else
+        _target->setPosition3D(_startPosition + _positionDelta * t);
+#endif // CC_ENABLE_STACKABLE_ACTIONS
+    }
+}
+
+//
+// MoveTo
+//
+
+MoveTo* MoveTo::create(float duration, const Vec2& position)
+{
+    return MoveTo::create(duration, Vec3(position.x, position.y, 0));
+}
+
+MoveTo* MoveTo::create(float duration, const Vec3& position)
+{
+    MoveTo *ret = new (std::nothrow) MoveTo();
+    
+    if (ret && ret->initWithDuration(duration, position))
+    {
+        ret->autorelease();
+        return ret;
+    }
+    
+    delete ret;
+    return nullptr;
+}
+
+bool MoveTo::initWithDuration(float duration, const Vec2& position)
+{
+    return initWithDuration(duration, Vec3(position.x, position.y, 0));
+}
+
+bool MoveTo::initWithDuration(float duration, const Vec3& position)
+{
+    bool ret = false;
+    
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _endPosition = position;
+        ret = true;
+    }
+    
+    return ret;
+}
+
+MoveTo* MoveTo::clone() const
+{
+    // no copy constructor
+    return MoveTo::create(_duration, _endPosition);
+}
+
+void MoveTo::startWithTarget(Node *target)
+{
+    MoveBy::startWithTarget(target);
+    _positionDelta = _endPosition - target->getPosition3D();
+}
+
+MoveTo* MoveTo::reverse() const
+{
+    CCASSERT(false, "reverse() not supported in MoveTo");
+    return nullptr;
+}
+
+//
+// SkewTo
+//
+SkewTo* SkewTo::create(float t, float sx, float sy)
+{
+    SkewTo *skewTo = new (std::nothrow) SkewTo();
+    if (skewTo && skewTo->initWithDuration(t, sx, sy))
+    {
+        skewTo->autorelease();
+        return skewTo;
+    }
+
+    delete skewTo;
+    return nullptr;
+}
+
+bool SkewTo::initWithDuration(float t, float sx, float sy)
+{
+    bool bRet = false;
+
+    if (ActionInterval::initWithDuration(t))
+    {
+        _endSkewX = sx;
+        _endSkewY = sy;
+
+        bRet = true;
+    }
+
+    return bRet;
+}
+
+SkewTo* SkewTo::clone() const
+{
+    // no copy constructor
+    return SkewTo::create(_duration, _endSkewX, _endSkewY);
+}
+
+SkewTo* SkewTo::reverse() const
+{
+    CCASSERT(false, "reverse() not supported in SkewTo");
+    return nullptr;
+}
+
+void SkewTo::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+
+    _startSkewX = target->getSkewX();
+
+    if (_startSkewX > 0)
+    {
+        _startSkewX = fmodf(_startSkewX, 180.f);
+    }
+    else
+    {
+        _startSkewX = fmodf(_startSkewX, -180.f);
+    }
+
+    _deltaX = _endSkewX - _startSkewX;
+
+    if (_deltaX > 180)
+    {
+        _deltaX -= 360;
+    }
+    if (_deltaX < -180)
+    {
+        _deltaX += 360;
+    }
+
+    _startSkewY = target->getSkewY();
+
+    if (_startSkewY > 0)
+    {
+        _startSkewY = fmodf(_startSkewY, 360.f);
+    }
+    else
+    {
+        _startSkewY = fmodf(_startSkewY, -360.f);
+    }
+
+    _deltaY = _endSkewY - _startSkewY;
+
+    if (_deltaY > 180)
+    {
+        _deltaY -= 360;
+    }
+    if (_deltaY < -180)
+    {
+        _deltaY += 360;
+    }
+}
+
+void SkewTo::update(float t)
+{
+    _target->setSkewX(_startSkewX + _deltaX * t);
+    _target->setSkewY(_startSkewY + _deltaY * t);
+}
+
+SkewTo::SkewTo()
+: _skewX(0.0)
+, _skewY(0.0)
+, _startSkewX(0.0)
+, _startSkewY(0.0)
+, _endSkewX(0.0)
+, _endSkewY(0.0)
+, _deltaX(0.0)
+, _deltaY(0.0)
+{
+}
+
+//
+// SkewBy
+//
+SkewBy* SkewBy::create(float t, float sx, float sy)
+{
+    SkewBy *skewBy = new (std::nothrow) SkewBy();
+    if (skewBy && skewBy->initWithDuration(t, sx, sy))
+    {
+        skewBy->autorelease();
+        return  skewBy;
+    }
+
+    delete skewBy;
+    return nullptr;
+}
+
+SkewBy * SkewBy::clone() const
+{
+    // no copy constructor
+    return SkewBy::create(_duration, _skewX, _skewY);
+}
+
+bool SkewBy::initWithDuration(float t, float deltaSkewX, float deltaSkewY)
+{
+    bool ret = false;
+
+    if (SkewTo::initWithDuration(t, deltaSkewX, deltaSkewY))
+    {
+        _skewX = deltaSkewX;
+        _skewY = deltaSkewY;
+
+        ret = true;
+    }
+
+    return ret;
+}
+
+void SkewBy::startWithTarget(Node *target)
+{
+    SkewTo::startWithTarget(target);
+    _deltaX = _skewX;
+    _deltaY = _skewY;
+    _endSkewX = _startSkewX + _deltaX;
+    _endSkewY = _startSkewY + _deltaY;
+}
+
+SkewBy* SkewBy::reverse() const
+{
+    return SkewBy::create(_duration, -_skewX, -_skewY);
+}
+
+ResizeTo* ResizeTo::create(float duration, const cocos2d::Size& final_size)
+{
+    ResizeTo *ret = new (std::nothrow) ResizeTo();
+    
+    if (ret)
+    {
+        if (ret->initWithDuration(duration, final_size))
+        {
+            ret->autorelease();
+        } 
+        else
+        {
+            delete ret;
+            ret = nullptr;
+        }
+    }
+    
+    return ret;
+}
+
+ResizeTo* ResizeTo::clone(void) const
+{
+    // no copy constructor
+    ResizeTo* a = new (std::nothrow) ResizeTo();
+    a->initWithDuration(_duration, _finalSize);
+    a->autorelease();
+
+    return a;
+}
+
+void ResizeTo::startWithTarget(cocos2d::Node* target)
+{
+    ActionInterval::startWithTarget(target);
+    _initialSize = target->getContentSize();
+    _sizeDelta = _finalSize - _initialSize;
+}
+
+void ResizeTo::update(float time)
+{
+    if (_target)
+    {
+        auto new_size = _initialSize + (_sizeDelta * time);
+        _target->setContentSize(new_size);
+    }
+}
+
+bool ResizeTo::initWithDuration(float duration, const cocos2d::Size& final_size)
+{
+    if (cocos2d::ActionInterval::initWithDuration(duration))
+    {
+        _finalSize = final_size;
+        return true;
+    }
+
+    return false;
+}
+
+//
+// ResizeBy
+//
+
+ResizeBy* ResizeBy::create(float duration, const cocos2d::Size& deltaSize)
+{
+    ResizeBy *ret = new (std::nothrow) ResizeBy();
+    
+    if (ret)
+    {
+        if (ret->initWithDuration(duration, deltaSize))
+        {
+            ret->autorelease();
+        } 
+        else
+        {
+              delete ret;
+              ret = nullptr;
+        }
+    }
+    
+    return ret;
+}
+
+ResizeBy* ResizeBy::clone() const
+{
+    // no copy constructor
+    auto a = new (std::nothrow) ResizeBy();
+    a->initWithDuration(_duration, _sizeDelta);
+    a->autorelease();
+    return a;
+}
+
+void ResizeBy::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    _previousSize = _startSize = target->getContentSize();
+}
+
+ResizeBy* ResizeBy::reverse() const
+{
+    cocos2d::Size newSize(-_sizeDelta.width, -_sizeDelta.height);
+    return ResizeBy::create(_duration, newSize);
+}
+
+void ResizeBy::update(float t)
+{
+    if (_target)
+    {
+        _target->setContentSize(_startSize + (_sizeDelta * t));
+    }
+}
+
+bool ResizeBy::initWithDuration(float duration, const cocos2d::Size& deltaSize)
+{
+    bool ret = false;
+    
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _sizeDelta = deltaSize;
+        ret = true;
+    }
+    
+    return ret;
+}
+
+//
+// JumpBy
+//
+
+JumpBy* JumpBy::create(float duration, const Vec2& position, float height, int jumps)
+{
+    JumpBy *jumpBy = new (std::nothrow) JumpBy();
+    if (jumpBy && jumpBy->initWithDuration(duration, position, height, jumps))
+    {
+        jumpBy->autorelease();
+        return jumpBy;
+    }
+    
+    delete jumpBy;
+    return nullptr;
+}
+
+bool JumpBy::initWithDuration(float duration, const Vec2& position, float height, int jumps)
+{
+    CCASSERT(jumps>=0, "Number of jumps must be >= 0");
+    if (jumps < 0)
+    {
+        log("JumpBy::initWithDuration error: Number of jumps must be >= 0");
+        return false;
+    }
+    
+    if (ActionInterval::initWithDuration(duration) && jumps>=0)
+    {
+        _delta = position;
+        _height = height;
+        _jumps = jumps;
+
+        return true;
+    }
+
+    return false;
+}
+
+JumpBy* JumpBy::clone() const
+{
+    // no copy constructor
+    return JumpBy::create(_duration, _delta, _height, _jumps);
+}
+
+void JumpBy::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    _previousPos = _startPosition = target->getPosition();
+}
+
+void JumpBy::update(float t)
+{
+    // parabolic jump (since v0.8.2)
+    if (_target)
+    {
+        float frac = fmodf( t * _jumps, 1.0f );
+        float y = _height * 4 * frac * (1 - frac);
+        y += _delta.y * t;
+
+        float x = _delta.x * t;
+#if CC_ENABLE_STACKABLE_ACTIONS
+        Vec2 currentPos = _target->getPosition();
+
+        Vec2 diff = currentPos - _previousPos;
+        _startPosition = diff + _startPosition;
+
+        Vec2 newPos = _startPosition + Vec2(x,y);
+        _target->setPosition(newPos);
+
+        _previousPos = newPos;
+#else
+        _target->setPosition(_startPosition + Vec2(x,y));
+#endif // !CC_ENABLE_STACKABLE_ACTIONS
+    }
+}
+
+JumpBy* JumpBy::reverse() const
+{
+    return JumpBy::create(_duration, Vec2(-_delta.x, -_delta.y),
+        _height, _jumps);
+}
+
+//
+// JumpTo
+//
+
+JumpTo* JumpTo::create(float duration, const Vec2& position, float height, int jumps)
+{
+    JumpTo *jumpTo = new (std::nothrow) JumpTo();
+    if (jumpTo && jumpTo->initWithDuration(duration, position, height, jumps))
+    {
+        jumpTo->autorelease();
+        return jumpTo;
+    }
+    
+    delete jumpTo;
+    return nullptr;
+}
+
+bool JumpTo::initWithDuration(float duration, const Vec2& position, float height, int jumps)
+{
+    CCASSERT(jumps>=0, "Number of jumps must be >= 0");
+    if (jumps < 0)
+    {
+        log("JumpTo::initWithDuration error:Number of jumps must be >= 0");
+        return false;
+    }
+
+    if (ActionInterval::initWithDuration(duration) && jumps>=0)
+    {
+        _endPosition = position;
+        _height = height;
+        _jumps = jumps;
+
+        return true;
+    }
+
+    return false;
+}
+
+JumpTo* JumpTo::clone() const
+{
+    // no copy constructor
+    return JumpTo::create(_duration, _endPosition, _height, _jumps);
+}
+
+JumpTo* JumpTo::reverse() const
+{
+    CCASSERT(false, "reverse() not supported in JumpTo");
+    return nullptr;
+}
+
+void JumpTo::startWithTarget(Node *target)
+{
+    JumpBy::startWithTarget(target);
+    _delta.set(_endPosition.x - _startPosition.x, _endPosition.y - _startPosition.y);
+}
+
+// Bezier cubic formula:
+//    ((1 - t) + t)3 = 1 
+// Expands to ...
+//   (1 - t)3 + 3t(1-t)2 + 3t2(1 - t) + t3 = 1 
+static inline float bezierat( float a, float b, float c, float d, float t )
+{
+    return (powf(1-t,3) * a + 
+            3*t*(powf(1-t,2))*b + 
+            3*powf(t,2)*(1-t)*c +
+            powf(t,3)*d );
+}
+
+//
+// BezierBy
+//
+
+BezierBy* BezierBy::create(float t, const ccBezierConfig& c)
+{
+    BezierBy *bezierBy = new (std::nothrow) BezierBy();
+    if (bezierBy && bezierBy->initWithDuration(t, c))
+    {
+        bezierBy->autorelease();
+        return bezierBy;
+    }
+    
+    delete bezierBy;
+    return nullptr;
+}
+
+bool BezierBy::initWithDuration(float t, const ccBezierConfig& c)
+{
+    if (ActionInterval::initWithDuration(t))
+    {
+        _config = c;
+        return true;
+    }
+
+    return false;
+}
+
+void BezierBy::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    _previousPosition = _startPosition = target->getPosition();
+}
+
+BezierBy* BezierBy::clone() const
+{
+    // no copy constructor
+    return BezierBy::create(_duration, _config);
+}
+
+void BezierBy::update(float time)
+{
+    if (_target)
+    {
+        float xa = 0;
+        float xb = _config.controlPoint_1.x;
+        float xc = _config.controlPoint_2.x;
+        float xd = _config.endPosition.x;
+
+        float ya = 0;
+        float yb = _config.controlPoint_1.y;
+        float yc = _config.controlPoint_2.y;
+        float yd = _config.endPosition.y;
+
+        float x = bezierat(xa, xb, xc, xd, time);
+        float y = bezierat(ya, yb, yc, yd, time);
+
+#if CC_ENABLE_STACKABLE_ACTIONS
+        Vec2 currentPos = _target->getPosition();
+        Vec2 diff = currentPos - _previousPosition;
+        _startPosition = _startPosition + diff;
+
+        Vec2 newPos = _startPosition + Vec2(x,y);
+        _target->setPosition(newPos);
+
+        _previousPosition = newPos;
+#else
+        _target->setPosition( _startPosition + Vec2(x,y));
+#endif // !CC_ENABLE_STACKABLE_ACTIONS
+    }
+}
+
+BezierBy* BezierBy::reverse() const
+{
+    ccBezierConfig r;
+
+    r.endPosition = -_config.endPosition;
+    r.controlPoint_1 = _config.controlPoint_2 + (-_config.endPosition);
+    r.controlPoint_2 = _config.controlPoint_1 + (-_config.endPosition);
+
+    BezierBy *action = BezierBy::create(_duration, r);
+    return action;
+}
+
+//
+// BezierTo
+//
+
+BezierTo* BezierTo::create(float t, const ccBezierConfig& c)
+{
+    BezierTo *bezierTo = new (std::nothrow) BezierTo();
+    if (bezierTo && bezierTo->initWithDuration(t, c))
+    {
+        bezierTo->autorelease();
+        return bezierTo;
+    }
+    
+    delete bezierTo;
+    return nullptr;
+}
+
+bool BezierTo::initWithDuration(float t, const ccBezierConfig &c)
+{
+    if (ActionInterval::initWithDuration(t))
+    {
+        _toConfig = c;
+        return true;
+    }
+    
+    return false;
+}
+
+BezierTo* BezierTo::clone() const
+{
+    // no copy constructor
+    return BezierTo::create(_duration, _toConfig);
+}
+
+void BezierTo::startWithTarget(Node *target)
+{
+    BezierBy::startWithTarget(target);
+    _config.controlPoint_1 = _toConfig.controlPoint_1 - _startPosition;
+    _config.controlPoint_2 = _toConfig.controlPoint_2 - _startPosition;
+    _config.endPosition = _toConfig.endPosition - _startPosition;
+}
+
+BezierTo* BezierTo::reverse() const
+{
+    CCASSERT(false, "CCBezierTo doesn't support the 'reverse' method");
+    return nullptr;
+}
+
+//
+// ScaleTo
+//
+ScaleTo* ScaleTo::create(float duration, float s)
+{
+    ScaleTo *scaleTo = new (std::nothrow) ScaleTo();
+    if (scaleTo && scaleTo->initWithDuration(duration, s))
+    {
+        scaleTo->autorelease();
+        return  scaleTo;
+    }
+    
+    delete scaleTo;
+    return nullptr;
+}
+
+ScaleTo* ScaleTo::create(float duration, float sx, float sy)
+{
+    ScaleTo *scaleTo = new (std::nothrow) ScaleTo();
+    if (scaleTo && scaleTo->initWithDuration(duration, sx, sy))
+    {
+        scaleTo->autorelease();
+        return scaleTo;
+    }
+    
+    delete scaleTo;
+    return nullptr;
+}
+
+ScaleTo* ScaleTo::create(float duration, float sx, float sy, float sz)
+{
+    ScaleTo *scaleTo = new (std::nothrow) ScaleTo();
+    if (scaleTo && scaleTo->initWithDuration(duration, sx, sy, sz))
+    {
+        scaleTo->autorelease();
+        return scaleTo;
+    }
+    
+    delete scaleTo;
+    return nullptr;
+}
+
+bool ScaleTo::initWithDuration(float duration, float s)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _endScaleX = s;
+        _endScaleY = s;
+        _endScaleZ = s;
+
+        return true;
+    }
+
+    return false;
+}
+
+bool ScaleTo::initWithDuration(float duration, float sx, float sy)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _endScaleX = sx;
+        _endScaleY = sy;
+        _endScaleZ = 1.f;
+
+        return true;
+    }
+
+    return false;
+}
+
+bool ScaleTo::initWithDuration(float duration, float sx, float sy, float sz)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _endScaleX = sx;
+        _endScaleY = sy;
+        _endScaleZ = sz;
+
+        return true;
+    }
+
+    return false;
+}
+
+ScaleTo* ScaleTo::clone() const
+{
+    // no copy constructor
+    return ScaleTo::create(_duration, _endScaleX, _endScaleY, _endScaleZ);
+}
+
+ScaleTo* ScaleTo::reverse() const
+{
+    CCASSERT(false, "reverse() not supported in ScaleTo");
+    return nullptr;
+}
+
+void ScaleTo::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    _startScaleX = target->getScaleX();
+    _startScaleY = target->getScaleY();
+    _startScaleZ = target->getScaleZ();
+    _deltaX = _endScaleX - _startScaleX;
+    _deltaY = _endScaleY - _startScaleY;
+    _deltaZ = _endScaleZ - _startScaleZ;
+}
+
+void ScaleTo::update(float time)
+{
+    if (_target)
+    {
+        _target->setScaleX(_startScaleX + _deltaX * time);
+        _target->setScaleY(_startScaleY + _deltaY * time);
+        _target->setScaleZ(_startScaleZ + _deltaZ * time);
+    }
+}
+
+//
+// ScaleBy
+//
+
+ScaleBy* ScaleBy::create(float duration, float s)
+{
+    ScaleBy *scaleBy = new (std::nothrow) ScaleBy();
+    if (scaleBy && scaleBy->initWithDuration(duration, s))
+    {
+        scaleBy->autorelease();
+        return scaleBy;
+    }
+    
+    delete scaleBy;
+    return nullptr;
+}
+
+ScaleBy* ScaleBy::create(float duration, float sx, float sy)
+{
+    ScaleBy *scaleBy = new (std::nothrow) ScaleBy();
+    if (scaleBy && scaleBy->initWithDuration(duration, sx, sy, 1.f))
+    {
+        scaleBy->autorelease();
+        return scaleBy;
+    }
+    
+    delete scaleBy;
+    return nullptr;
+}
+
+ScaleBy* ScaleBy::create(float duration, float sx, float sy, float sz)
+{
+    ScaleBy *scaleBy = new (std::nothrow) ScaleBy();
+    if (scaleBy && scaleBy->initWithDuration(duration, sx, sy, sz))
+    {
+        scaleBy->autorelease();
+        return scaleBy;
+    }
+    
+    delete scaleBy;
+    return nullptr;
+}
+
+ScaleBy* ScaleBy::clone() const
+{
+    // no copy constructor
+    return ScaleBy::create(_duration, _endScaleX, _endScaleY, _endScaleZ);
+}
+
+void ScaleBy::startWithTarget(Node *target)
+{
+    ScaleTo::startWithTarget(target);
+    _deltaX = _startScaleX * _endScaleX - _startScaleX;
+    _deltaY = _startScaleY * _endScaleY - _startScaleY;
+    _deltaZ = _startScaleZ * _endScaleZ - _startScaleZ;
+}
+
+ScaleBy* ScaleBy::reverse() const
+{
+    return ScaleBy::create(_duration, 1 / _endScaleX, 1 / _endScaleY, 1/ _endScaleZ);
+}
+
+//
+// Blink
+//
+
+Blink* Blink::create(float duration, int blinks)
+{
+    Blink *blink = new (std::nothrow) Blink();
+    if (blink && blink->initWithDuration(duration, blinks))
+    {
+        blink->autorelease();
+        return blink;
+    }
+
+    delete blink;
+    return nullptr;
+}
+
+bool Blink::initWithDuration(float duration, int blinks)
+{
+    CCASSERT(blinks>=0, "blinks should be >= 0");
+    if (blinks < 0)
+    {
+        log("Blink::initWithDuration error:blinks should be >= 0");
+        return false;
+    }
+    
+    if (ActionInterval::initWithDuration(duration) && blinks>=0)
+    {
+        _times = blinks;
+        return true;
+    }
+
+    return false;
+}
+
+void Blink::stop()
+{
+    if (nullptr != _target)
+        _target->setVisible(_originalState);
+    ActionInterval::stop();
+}
+
+void Blink::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    _originalState = target->isVisible();
+}
+
+Blink* Blink::clone(void) const
+{
+    // no copy constructor
+    return Blink::create(_duration, _times);
+}
+
+void Blink::update(float time)
+{
+    if (_target && ! isDone())
+    {
+        float slice = 1.0f / _times;
+        float m = fmodf(time, slice);
+        _target->setVisible(m > slice / 2 ? true : false);
+    }
+}
+
+Blink* Blink::reverse() const
+{
+    return Blink::create(_duration, _times);
+}
+
+//
+// FadeIn
+//
+
+FadeIn* FadeIn::create(float d)
+{
+    FadeIn* action = new (std::nothrow) FadeIn();
+    if (action && action->initWithDuration(d,255.0f))
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+FadeIn* FadeIn::clone() const
+{
+    // no copy constructor
+    return FadeIn::create(_duration);
+}
+
+void FadeIn::setReverseAction(cocos2d::FadeTo *ac)
+{
+    _reverseAction = ac;
+}
+
+
+FadeTo* FadeIn::reverse() const
+{
+    auto action = FadeOut::create(_duration);
+    action->setReverseAction(const_cast<FadeIn*>(this));
+    return action;
+    
+}
+
+void FadeIn::startWithTarget(cocos2d::Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    
+    if (nullptr != _reverseAction)
+        this->_toOpacity = this->_reverseAction->_fromOpacity;
+    else
+        _toOpacity = 255.0f;
+    
+    if (target)
+        _fromOpacity = target->getOpacity();
+}
+
+//
+// FadeOut
+//
+
+FadeOut* FadeOut::create(float d)
+{
+    FadeOut* action = new (std::nothrow) FadeOut();
+    if (action && action->initWithDuration(d,0.0f))
+    {
+        action->autorelease();
+        return action;
+    }
+    
+    delete action;
+    return nullptr;
+}
+
+FadeOut* FadeOut::clone() const
+{
+    // no copy constructor
+    return FadeOut::create(_duration);
+}
+
+void FadeOut::startWithTarget(cocos2d::Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    
+    if (nullptr != _reverseAction)
+        _toOpacity = _reverseAction->_fromOpacity;
+    else
+        _toOpacity = 0.0f;
+    
+    if (target)
+        _fromOpacity = target->getOpacity();
+}
+
+void FadeOut::setReverseAction(cocos2d::FadeTo *ac)
+{
+    _reverseAction = ac;
+}
+
+
+FadeTo* FadeOut::reverse() const
+{
+    auto action = FadeIn::create(_duration);
+    action->setReverseAction(const_cast<FadeOut*>(this));
+    return action;
+}
+
+//
+// FadeTo
+//
+
+FadeTo* FadeTo::create(float duration, GLubyte opacity)
+{
+    FadeTo *fadeTo = new (std::nothrow) FadeTo();
+    if (fadeTo && fadeTo->initWithDuration(duration, opacity))
+    {
+        fadeTo->autorelease();
+        return fadeTo;
+    }
+    
+    delete fadeTo;
+    return nullptr;
+}
+
+bool FadeTo::initWithDuration(float duration, GLubyte opacity)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _toOpacity = opacity;
+        return true;
+    }
+
+    return false;
+}
+
+FadeTo* FadeTo::clone() const
+{
+    // no copy constructor
+    return FadeTo::create(_duration, _toOpacity);
+}
+
+FadeTo* FadeTo::reverse() const
+{
+    CCASSERT(false, "reverse() not supported in FadeTo");
+    return nullptr;
+}
+
+void FadeTo::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+
+    if (target)
+    {
+        _fromOpacity = target->getOpacity();
+    }
+}
+
+void FadeTo::update(float time)
+{
+    if (_target)
+    {
+        _target->setOpacity((GLubyte)(_fromOpacity + (_toOpacity - _fromOpacity) * time));
+    }
+}
+
+//
+// TintTo
+//
+TintTo* TintTo::create(float duration, GLubyte red, GLubyte green, GLubyte blue)
+{
+    TintTo *tintTo = new (std::nothrow) TintTo();
+    if (tintTo && tintTo->initWithDuration(duration, red, green, blue))
+    {
+        tintTo->autorelease();
+        return tintTo;
+    }
+    
+    delete tintTo;
+    return nullptr;
+}
+
+TintTo* TintTo::create(float duration, const Color3B& color)
+{
+    return create(duration, color.r, color.g, color.b);
+}
+
+bool TintTo::initWithDuration(float duration, GLubyte red, GLubyte green, GLubyte blue)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _to = Color3B(red, green, blue);
+        return true;
+    }
+
+    return false;
+}
+
+TintTo* TintTo::clone() const
+{
+    // no copy constructor
+    return TintTo::create(_duration, _to.r, _to.g, _to.b);
+}
+
+TintTo* TintTo::reverse() const
+{
+    CCASSERT(false, "reverse() not supported in TintTo");
+    return nullptr;
+}
+
+void TintTo::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    if (_target)
+    {
+        _from = _target->getColor();
+    }
+}
+
+void TintTo::update(float time)
+{
+    if (_target)
+    {
+        _target->setColor(Color3B(GLubyte(_from.r + (_to.r - _from.r) * time),
+            (GLubyte)(_from.g + (_to.g - _from.g) * time),
+            (GLubyte)(_from.b + (_to.b - _from.b) * time)));
+    }
+}
+
+//
+// TintBy
+//
+
+TintBy* TintBy::create(float duration, GLshort deltaRed, GLshort deltaGreen, GLshort deltaBlue)
+{
+    TintBy *tintBy = new (std::nothrow) TintBy();
+    if (tintBy && tintBy->initWithDuration(duration, deltaRed, deltaGreen, deltaBlue))
+    {
+        tintBy->autorelease();
+        return tintBy;
+    }
+    
+    delete tintBy;
+    return nullptr;
+}
+
+bool TintBy::initWithDuration(float duration, GLshort deltaRed, GLshort deltaGreen, GLshort deltaBlue)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _deltaR = deltaRed;
+        _deltaG = deltaGreen;
+        _deltaB = deltaBlue;
+
+        return true;
+    }
+
+    return false;
+}
+
+TintBy* TintBy::clone() const
+{
+    // no copy constructor
+    return TintBy::create(_duration, _deltaR, _deltaG, _deltaB);
+}
+
+void TintBy::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+
+    if (target)
+    {
+        Color3B color = target->getColor();
+        _fromR = color.r;
+        _fromG = color.g;
+        _fromB = color.b;
+    }    
+}
+
+void TintBy::update(float time)
+{
+    if (_target)
+    {
+        _target->setColor(Color3B((GLubyte)(_fromR + _deltaR * time),
+            (GLubyte)(_fromG + _deltaG * time),
+            (GLubyte)(_fromB + _deltaB * time)));
+    }    
+}
+
+TintBy* TintBy::reverse() const
+{
+    return TintBy::create(_duration, -_deltaR, -_deltaG, -_deltaB);
+}
+
+//
+// DelayTime
+//
+DelayTime* DelayTime::create(float d)
+{
+    DelayTime* action = new (std::nothrow) DelayTime();
+    if (action && action->initWithDuration(d))
+    {
+        action->autorelease();
+        return action;
+    }
+    
+    delete action;
+    return nullptr;
+}
+
+DelayTime* DelayTime::clone() const
+{
+    // no copy constructor
+    return DelayTime::create(_duration);
+}
+
+void DelayTime::update(float /*time*/)
+{
+    return;
+}
+
+DelayTime* DelayTime::reverse() const
+{
+    return DelayTime::create(_duration);
+}
+
+//
+// ReverseTime
+//
+
+ReverseTime* ReverseTime::create(FiniteTimeAction *action)
+{
+    // casting to prevent warnings
+    ReverseTime *reverseTime = new (std::nothrow) ReverseTime();
+    if (reverseTime && reverseTime->initWithAction( action->clone() ))
+    {
+        reverseTime->autorelease();
+        return reverseTime;
+    }
+    
+    delete reverseTime;
+    return nullptr;
+}
+
+bool ReverseTime::initWithAction(FiniteTimeAction *action)
+{
+    CCASSERT(action != nullptr, "action can't be nullptr!");
+    CCASSERT(action != _other, "action doesn't equal to _other!");
+    if (action == nullptr || action == _other)
+    {
+        log("ReverseTime::initWithAction error: action is null or action equal to _other");
+        return false;
+    }
+
+    if (ActionInterval::initWithDuration(action->getDuration()))
+    {
+        // Don't leak if action is reused
+        CC_SAFE_RELEASE(_other);
+
+        _other = action;
+        action->retain();
+
+        return true;
+    }
+
+    return false;
+}
+
+ReverseTime* ReverseTime::clone() const
+{
+    // no copy constructor
+    return ReverseTime::create(_other->clone());
+}
+
+ReverseTime::ReverseTime() : _other(nullptr)
+{
+
+}
+
+ReverseTime::~ReverseTime()
+{
+    CC_SAFE_RELEASE(_other);
+}
+
+void ReverseTime::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    _other->startWithTarget(target);
+}
+
+void ReverseTime::stop(void)
+{
+    _other->stop();
+    ActionInterval::stop();
+}
+
+void ReverseTime::update(float time)
+{
+    if (_other)
+    {
+        if (!(sendUpdateEventToScript(1 - time, _other)))
+            _other->update(1 - time);
+    }
+}
+
+ReverseTime* ReverseTime::reverse() const
+{
+    // FIXME: This looks like a bug
+    return (ReverseTime*)_other->clone();
+}
+
+//
+// Animate
+//
+Animate* Animate::create(Animation *animation)
+{
+    Animate *animate = new (std::nothrow) Animate();
+    if (animate && animate->initWithAnimation(animation))
+    {
+        animate->autorelease();
+        return animate;
+    }
+    
+    delete animate;
+    return nullptr;
+}
+
+Animate::Animate()
+: _splitTimes(new std::vector<float>)
+, _nextFrame(0)
+, _origFrame(nullptr)
+, _executedLoops(0)
+, _animation(nullptr)
+, _frameDisplayedEvent(nullptr)
+, _currFrameIndex(0)
+{
+
+}
+
+Animate::~Animate()
+{
+    CC_SAFE_RELEASE(_animation);
+    CC_SAFE_RELEASE(_origFrame);
+    CC_SAFE_DELETE(_splitTimes);
+    CC_SAFE_RELEASE(_frameDisplayedEvent);
+}
+
+bool Animate::initWithAnimation(Animation* animation)
+{
+    CCASSERT( animation!=nullptr, "Animate: argument Animation must be non-nullptr");
+    if (animation == nullptr)
+    {
+        log("Animate::initWithAnimation: argument Animation must be non-nullptr");
+        return false;
+    }
+
+    float singleDuration = animation->getDuration();
+
+    if ( ActionInterval::initWithDuration(singleDuration * animation->getLoops() ) )
+    {
+        _nextFrame = 0;
+        setAnimation(animation);
+        _origFrame = nullptr;
+        _executedLoops = 0;
+
+        _splitTimes->reserve(animation->getFrames().size());
+
+        float accumUnitsOfTime = 0;
+        float newUnitOfTimeValue = singleDuration / animation->getTotalDelayUnits();
+
+        auto& frames = animation->getFrames();
+
+        for (auto& frame : frames)
+        {
+            float value = (accumUnitsOfTime * newUnitOfTimeValue) / singleDuration;
+            accumUnitsOfTime += frame->getDelayUnits();
+            _splitTimes->push_back(value);
+        }    
+        return true;
+    }
+    return false;
+}
+
+void Animate::setAnimation(cocos2d::Animation *animation)
+{
+    if (_animation != animation)
+    {
+        CC_SAFE_RETAIN(animation);
+        CC_SAFE_RELEASE(_animation);
+        _animation = animation;
+    }
+}
+
+Animate* Animate::clone() const
+{
+    // no copy constructor
+    return Animate::create(_animation->clone());
+}
+
+void Animate::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    Sprite *sprite = static_cast<Sprite*>(target);
+
+    CC_SAFE_RELEASE(_origFrame);
+
+    if (_animation->getRestoreOriginalFrame())
+    {
+        _origFrame = sprite->getSpriteFrame();
+        _origFrame->retain();
+    }
+    _nextFrame = 0;
+    _executedLoops = 0;
+}
+
+void Animate::stop()
+{
+    if (_animation->getRestoreOriginalFrame() && _target)
+    {
+        auto blend = static_cast<Sprite*>(_target)->getBlendFunc();
+        static_cast<Sprite*>(_target)->setSpriteFrame(_origFrame);
+        static_cast<Sprite*>(_target)->setBlendFunc(blend);
+    }
+
+    ActionInterval::stop();
+}
+
+void Animate::update(float t)
+{
+    // if t==1, ignore. Animation should finish with t==1
+    if( t < 1.0f )
+    {
+        t *= _animation->getLoops();
+
+        // new loop?  If so, reset frame counter
+        unsigned int loopNumber = (unsigned int)t;
+        if( loopNumber > _executedLoops )
+        {
+            _nextFrame = 0;
+            _executedLoops++;
+        }
+
+        // new t for animations
+        t = fmodf(t, 1.0f);
+    }
+
+    auto& frames = _animation->getFrames();
+    auto numberOfFrames = frames.size();
+    SpriteFrame *frameToDisplay = nullptr;
+
+    for( int i=_nextFrame; i < numberOfFrames; i++ )
+    {
+        float splitTime = _splitTimes->at(i);
+
+        if( splitTime <= t )
+        {
+            auto blend = static_cast<Sprite*>(_target)->getBlendFunc();
+            _currFrameIndex = i;
+            AnimationFrame* frame = frames.at(_currFrameIndex);
+            frameToDisplay = frame->getSpriteFrame();
+            static_cast<Sprite*>(_target)->setSpriteFrame(frameToDisplay);
+            static_cast<Sprite*>(_target)->setBlendFunc(blend);
+
+            const ValueMap& dict = frame->getUserInfo();
+            if ( !dict.empty() )
+            {
+                if (_frameDisplayedEvent == nullptr)
+                    _frameDisplayedEvent = new (std::nothrow) EventCustom(AnimationFrameDisplayedNotification);
+                
+                _frameDisplayedEventInfo.target = _target;
+                _frameDisplayedEventInfo.userInfo = &dict;
+                _frameDisplayedEvent->setUserData(&_frameDisplayedEventInfo);
+                Director::getInstance()->getEventDispatcher()->dispatchEvent(_frameDisplayedEvent);
+            }
+            _nextFrame = i+1;
+        }
+        // Issue 1438. Could be more than one frame per tick, due to low frame rate or frame delta < 1/FPS
+        else {
+            break;
+        }
+    }
+}
+
+Animate* Animate::reverse() const
+{
+    auto& oldArray = _animation->getFrames();
+    Vector<AnimationFrame*> newArray(oldArray.size());
+   
+    if (!oldArray.empty())
+    {
+        for (auto iter = oldArray.crbegin(), iterCrend = oldArray.crend(); iter != iterCrend; ++iter)
+        {
+            AnimationFrame* animFrame = *iter;
+            if (!animFrame)
+            {
+                break;
+            }
+
+            newArray.pushBack(animFrame->clone());
+        }
+    }
+
+    Animation *newAnim = Animation::create(newArray, _animation->getDelayPerUnit(), _animation->getLoops());
+    newAnim->setRestoreOriginalFrame(_animation->getRestoreOriginalFrame());
+    return Animate::create(newAnim);
+}
+
+// TargetedAction
+
+TargetedAction::TargetedAction()
+: _action(nullptr)
+, _forcedTarget(nullptr)
+{
+
+}
+
+TargetedAction::~TargetedAction()
+{
+    CC_SAFE_RELEASE(_forcedTarget);
+    CC_SAFE_RELEASE(_action);
+}
+
+TargetedAction* TargetedAction::create(Node* target, FiniteTimeAction* action)
+{
+    TargetedAction* p = new (std::nothrow) TargetedAction();
+    if (p && p->initWithTarget(target, action))
+    {
+        p->autorelease();
+        return p;
+    }
+    
+    delete p;
+    return nullptr;
+}
+
+
+bool TargetedAction::initWithTarget(Node* target, FiniteTimeAction* action)
+{
+    if(ActionInterval::initWithDuration(action->getDuration()))
+    {
+        CC_SAFE_RETAIN(target);
+        _forcedTarget = target;
+        CC_SAFE_RETAIN(action);
+        _action = action;
+        return true;
+    }
+    return false;
+}
+
+TargetedAction* TargetedAction::clone() const
+{
+    // no copy constructor
+    // win32 : use the _other's copy object.
+    return TargetedAction::create(_forcedTarget, _action->clone());
+}
+
+TargetedAction* TargetedAction::reverse() const
+{
+    // just reverse the internal action
+    auto a = new (std::nothrow) TargetedAction();
+    a->initWithTarget(_forcedTarget, _action->reverse());
+    a->autorelease();
+    return a;
+}
+
+void TargetedAction::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    _action->startWithTarget(_forcedTarget);
+}
+
+void TargetedAction::stop()
+{
+    _action->stop();
+}
+
+void TargetedAction::update(float time)
+{
+    if (!(sendUpdateEventToScript(time, _action)))
+        _action->update(time);
+}
+
+void TargetedAction::setForcedTarget(Node* forcedTarget)
+{
+    if( _forcedTarget != forcedTarget )
+    {
+        CC_SAFE_RETAIN(forcedTarget);
+        CC_SAFE_RELEASE(_forcedTarget);
+        _forcedTarget = forcedTarget;
+    }
+}
+
+// ActionFloat
+
+ActionFloat* ActionFloat::create(float duration, float from, float to, ActionFloatCallback callback)
+{
+    auto ref = new (std::nothrow) ActionFloat();
+    if (ref && ref->initWithDuration(duration, from, to, callback))
+    {
+        ref->autorelease();
+        return ref;
+    }
+    
+    delete ref;
+    return nullptr;
+}
+
+bool ActionFloat::initWithDuration(float duration, float from, float to, ActionFloatCallback callback)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _from = from;
+        _to = to;
+        _callback = callback;
+        return true;
+    }
+    return false;
+}
+
+ActionFloat* ActionFloat::clone() const
+{
+    return ActionFloat::create(_duration, _from, _to, _callback);
+}
+
+void ActionFloat::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    _delta = _to - _from;
+}
+
+void ActionFloat::update(float delta)
+{
+    float value = _to - _delta * (1 - delta);
+
+    if (_callback)
+    {
+        // report back value to caller
+        _callback(value);
+    }
+}
+
+ActionFloat* ActionFloat::reverse() const
+{
+    return ActionFloat::create(_duration, _to, _from, _callback);
+}
+
+NS_CC_END

+ 1685 - 0
cocos2d/cocos/2d/CCActionInterval.h

@@ -0,0 +1,1685 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+
+#ifndef __ACTION_CCINTERVAL_ACTION_H__
+#define __ACTION_CCINTERVAL_ACTION_H__
+
+#include <vector>
+
+#include "2d/CCAction.h"
+#include "2d/CCAnimation.h"
+#include "base/CCProtocols.h"
+#include "base/CCVector.h"
+
+NS_CC_BEGIN
+
+class Node;
+class SpriteFrame;
+class EventCustom;
+
+/**
+ * @addtogroup actions
+ * @{
+ */
+
+/** @class ActionInterval
+@brief An interval action is an action that takes place within a certain period of time.
+It has an start time, and a finish time. The finish time is the parameter
+duration plus the start time.
+
+These ActionInterval actions have some interesting properties, like:
+- They can run normally (default)
+- They can run reversed with the reverse method
+- They can run with the time altered with the Accelerate, AccelDeccel and Speed actions.
+
+For example, you can simulate a Ping Pong effect running the action normally and
+then running it again in Reverse mode.
+
+Example:
+
+@code
+auto action = MoveBy::create(1.0f, Vec2::ONE);
+auto pingPongAction = Sequence::create(action, action->reverse(), nullptr);
+@endcode
+*/
+class CC_DLL ActionInterval : public FiniteTimeAction
+{
+public:
+    /** How many seconds had elapsed since the actions started to run.
+     *
+     * @return The seconds had elapsed since the actions started to run.
+     */
+    float getElapsed() { return _elapsed; }
+
+    /** Sets the amplitude rate, extension in GridAction
+     *
+     * @param amp   The amplitude rate.
+     */
+    void setAmplitudeRate(float amp);
+    
+    /** Gets the amplitude rate, extension in GridAction
+     *
+     * @return  The amplitude rate.
+     */
+    float getAmplitudeRate(void);
+
+    //
+    // Overrides
+    //
+    virtual bool isDone(void) const override;
+    /**
+     * @param dt in seconds
+     */
+    virtual void step(float dt) override;
+    virtual void startWithTarget(Node *target) override;
+    virtual ActionInterval* reverse() const override
+    {
+        CC_ASSERT(0);
+        return nullptr;
+    }
+
+    virtual ActionInterval *clone() const override
+    {
+        CC_ASSERT(0);
+        return nullptr;
+    }
+
+CC_CONSTRUCTOR_ACCESS:
+    /** initializes the action */
+    bool initWithDuration(float d);
+
+protected:
+    float _elapsed;
+    bool   _firstTick;
+
+protected:
+    bool sendUpdateEventToScript(float dt, Action *actionObject);
+};
+
+/** @class Sequence
+ * @brief Runs actions sequentially, one after another.
+ */
+class CC_DLL Sequence : public ActionInterval
+{
+public:
+    /** Helper constructor to create an array of sequenceable actions.
+     *
+     * @return An autoreleased Sequence object.
+     */
+#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
+    // VS2013 does not support nullptr in variable args lists and variadic templates are also not supported
+    typedef FiniteTimeAction* M;
+    static Sequence* create(M m1, std::nullptr_t listEnd) { return variadicCreate(m1, NULL); }
+    static Sequence* create(M m1, M m2, std::nullptr_t listEnd) { return variadicCreate(m1, m2, NULL); }
+    static Sequence* create(M m1, M m2, M m3, std::nullptr_t listEnd) { return variadicCreate(m1, m2, m3, NULL); }
+    static Sequence* create(M m1, M m2, M m3, M m4, std::nullptr_t listEnd) { return variadicCreate(m1, m2, m3, m4, NULL); }
+    static Sequence* create(M m1, M m2, M m3, M m4, M m5, std::nullptr_t listEnd) { return variadicCreate(m1, m2, m3, m4, m5, NULL); }
+    static Sequence* create(M m1, M m2, M m3, M m4, M m5, M m6, std::nullptr_t listEnd) { return variadicCreate(m1, m2, m3, m4, m5, m6, NULL); }
+    static Sequence* create(M m1, M m2, M m3, M m4, M m5, M m6, M m7, std::nullptr_t listEnd) { return variadicCreate(m1, m2, m3, m4, m5, m6, m7, NULL); }
+    static Sequence* create(M m1, M m2, M m3, M m4, M m5, M m6, M m7, M m8, std::nullptr_t listEnd) { return variadicCreate(m1, m2, m3, m4, m5, m6, m7, m8, NULL); }
+    static Sequence* create(M m1, M m2, M m3, M m4, M m5, M m6, M m7, M m8, M m9, std::nullptr_t listEnd) { return variadicCreate(m1, m2, m3, m4, m5, m6, m7, m8, m9, NULL); }
+    static Sequence* create(M m1, M m2, M m3, M m4, M m5, M m6, M m7, M m8, M m9, M m10, std::nullptr_t listEnd) { return variadicCreate(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10,  NULL); }
+
+    // On WP8 for variable argument lists longer than 10 items, use the other create functions or variadicCreate with NULL as the last argument
+    static Sequence* variadicCreate(FiniteTimeAction* item, ...);
+#else
+    static Sequence* create(FiniteTimeAction *action1, ...) CC_REQUIRES_NULL_TERMINATION;
+#endif
+
+    /** Helper constructor to create an array of sequenceable actions given an array.
+     * @code
+     * When this function bound to the js or lua,the input params changed
+     * in js  :var   create(var   object1,var   object2, ...)
+     * in lua :local create(local object1,local object2, ...)
+     * @endcode
+     *
+     * @param arrayOfActions An array of sequenceable actions.
+     * @return An autoreleased Sequence object.
+     */
+    static Sequence* create(const Vector<FiniteTimeAction*>& arrayOfActions);
+    /** Helper constructor to create an array of sequence-able actions.
+     *
+     * @param action1 The first sequenceable action.
+     * @param args The va_list variable.
+     * @return An autoreleased Sequence object.
+     * @js NA
+     */
+    static Sequence* createWithVariableList(FiniteTimeAction *action1, va_list args);
+    /** Creates the action.
+     * @param actionOne The first sequenceable action.
+     * @param actionTwo The second sequenceable action.
+     * @return An autoreleased Sequence object.
+     * @js NA
+     */
+    static Sequence* createWithTwoActions(FiniteTimeAction *actionOne, FiniteTimeAction *actionTwo);
+
+    //
+    // Overrides
+    //
+    virtual Sequence* clone() const override;
+    virtual Sequence* reverse() const override;
+    virtual void startWithTarget(Node *target) override;
+    virtual void stop(void) override;
+    /**
+     * @param t In seconds.
+     */
+    virtual void update(float t) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    Sequence();
+    virtual ~Sequence();
+
+    /** initializes the action */
+    bool initWithTwoActions(FiniteTimeAction *pActionOne, FiniteTimeAction *pActionTwo);
+    bool init(const Vector<FiniteTimeAction*>& arrayOfActions);
+
+protected:
+    FiniteTimeAction *_actions[2];
+    float _split;
+    int _last;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Sequence);
+};
+
+/** @class Repeat
+ * @brief Repeats an action a number of times.
+ * To repeat an action forever use the RepeatForever action.
+ */
+class CC_DLL Repeat : public ActionInterval
+{
+public:
+    /** Creates a Repeat action. Times is an unsigned integer between 1 and pow(2,30).
+     *
+     * @param action The action needs to repeat.
+     * @param times The repeat times.
+     * @return An autoreleased Repeat object.
+     */
+    static Repeat* create(FiniteTimeAction *action, unsigned int times);
+
+    /** Sets the inner action.
+     *
+     * @param action The inner action.
+     */
+    void setInnerAction(FiniteTimeAction *action)
+    {
+        if (_innerAction != action)
+        {
+            CC_SAFE_RETAIN(action);
+            CC_SAFE_RELEASE(_innerAction);
+            _innerAction = action;
+        }
+    }
+
+    /** Gets the inner action.
+     *
+     * @return The inner action.
+     */
+    FiniteTimeAction* getInnerAction()
+    {
+        return _innerAction;
+    }
+
+    //
+    // Overrides
+    //
+    virtual Repeat* clone() const override;
+    virtual Repeat* reverse() const override;
+    virtual void startWithTarget(Node *target) override;
+    virtual void stop(void) override;
+    /**
+     * @param dt In seconds.
+     */
+    virtual void update(float dt) override;
+    virtual bool isDone(void) const override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    Repeat() {}
+    virtual ~Repeat();
+
+    /** initializes a Repeat action. Times is an unsigned integer between 1 and pow(2,30) */
+    bool initWithAction(FiniteTimeAction *pAction, unsigned int times);
+
+protected:
+    unsigned int _times;
+    unsigned int _total;
+    float _nextDt;
+    bool _actionInstant;
+    /** Inner action */
+    FiniteTimeAction *_innerAction;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Repeat);
+};
+
+/** @class RepeatForever
+ * @brief Repeats an action for ever.
+ To repeat the an action for a limited number of times use the Repeat action.
+ * @warning This action can't be Sequenceable because it is not an IntervalAction.
+ */
+class CC_DLL RepeatForever : public ActionInterval
+{
+public:
+    /** Creates the action.
+     *
+     * @param action The action need to repeat forever.
+     * @return An autoreleased RepeatForever object.
+     */
+    static RepeatForever* create(ActionInterval *action);
+
+    /** Sets the inner action.
+     *
+     * @param action The inner action.
+     */
+    void setInnerAction(ActionInterval *action)
+    {
+        if (_innerAction != action)
+        {
+            CC_SAFE_RELEASE(_innerAction);
+            _innerAction = action;
+            CC_SAFE_RETAIN(_innerAction);
+        }
+    }
+
+    /** Gets the inner action.
+     *
+     * @return The inner action.
+     */
+    ActionInterval* getInnerAction()
+    {
+        return _innerAction;
+    }
+
+    //
+    // Overrides
+    //
+    virtual RepeatForever* clone() const override;
+    virtual RepeatForever* reverse(void) const override;
+    virtual void startWithTarget(Node* target) override;
+    /**
+     * @param dt In seconds.
+     */
+    virtual void step(float dt) override;
+    virtual bool isDone(void) const override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    RepeatForever()
+    : _innerAction(nullptr)
+    {}
+    virtual ~RepeatForever();
+
+    /** initializes the action */
+    bool initWithAction(ActionInterval *action);
+
+protected:
+    /** Inner action */
+    ActionInterval *_innerAction;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(RepeatForever);
+};
+
+/** @class Spawn
+ * @brief Spawn a new action immediately
+ */
+class CC_DLL Spawn : public ActionInterval
+{
+public:
+    /** Helper constructor to create an array of spawned actions.
+     * @code
+     * When this function bound to the js or lua, the input params changed.
+     * in js  :var   create(var   object1,var   object2, ...)
+     * in lua :local create(local object1,local object2, ...)
+     * @endcode
+     *
+     * @return An autoreleased Spawn object.
+     */
+#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
+    // VS2013 does not support nullptr in variable args lists and variadic templates are also not supported.
+    typedef FiniteTimeAction* M;
+    static Spawn* create(M m1, std::nullptr_t listEnd) { return variadicCreate(m1, NULL); }
+    static Spawn* create(M m1, M m2, std::nullptr_t listEnd) { return variadicCreate(m1, m2, NULL); }
+    static Spawn* create(M m1, M m2, M m3, std::nullptr_t listEnd) { return variadicCreate(m1, m2, m3, NULL); }
+    static Spawn* create(M m1, M m2, M m3, M m4, std::nullptr_t listEnd) { return variadicCreate(m1, m2, m3, m4, NULL); }
+    static Spawn* create(M m1, M m2, M m3, M m4, M m5, std::nullptr_t listEnd) { return variadicCreate(m1, m2, m3, m4, m5, NULL); }
+    static Spawn* create(M m1, M m2, M m3, M m4, M m5, M m6, std::nullptr_t listEnd) { return variadicCreate(m1, m2, m3, m4, m5, m6, NULL); }
+    static Spawn* create(M m1, M m2, M m3, M m4, M m5, M m6, M m7, std::nullptr_t listEnd) { return variadicCreate(m1, m2, m3, m4, m5, m6, m7, NULL); }
+    static Spawn* create(M m1, M m2, M m3, M m4, M m5, M m6, M m7, M m8, std::nullptr_t listEnd) { return variadicCreate(m1, m2, m3, m4, m5, m6, m7, m8, NULL); }
+    static Spawn* create(M m1, M m2, M m3, M m4, M m5, M m6, M m7, M m8, M m9, std::nullptr_t listEnd) { return variadicCreate(m1, m2, m3, m4, m5, m6, m7, m8, m9, NULL); }
+    static Spawn* create(M m1, M m2, M m3, M m4, M m5, M m6, M m7, M m8, M m9, M m10, std::nullptr_t listEnd) { return variadicCreate(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10,  NULL); }
+
+    // On WP8 for variable argument lists longer than 10 items, use the other create functions or createSpawn with NULL as the last argument.
+    static Spawn* variadicCreate(FiniteTimeAction* item, ...);
+#else
+    static Spawn* create(FiniteTimeAction *action1, ...) CC_REQUIRES_NULL_TERMINATION;
+#endif
+
+    /** Helper constructor to create an array of spawned actions. 
+     *
+     * @param action1   The first sequenceable action.
+     * @param args  The va_list variable.
+     * @return  An autoreleased Spawn object.
+     * @js NA
+     */
+    static Spawn* createWithVariableList(FiniteTimeAction *action1, va_list args);
+
+    /** Helper constructor to create an array of spawned actions given an array.
+     *
+     * @param arrayOfActions    An array of spawned actions.
+     * @return  An autoreleased Spawn object.
+     */
+    static Spawn* create(const Vector<FiniteTimeAction*>& arrayOfActions);
+
+    /** Creates the Spawn action.
+     *
+     * @param action1   The first spawned action.
+     * @param action2   The second spawned action.
+     * @return An autoreleased Spawn object.
+     * @js NA
+     */
+    static Spawn* createWithTwoActions(FiniteTimeAction *action1, FiniteTimeAction *action2);
+
+    //
+    // Overrides
+    //
+    virtual Spawn* clone() const override;
+    virtual Spawn* reverse(void) const override;
+    virtual void startWithTarget(Node *target) override;
+    virtual void stop(void) override;
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    Spawn();
+    virtual ~Spawn();
+
+    /** initializes the Spawn action with the 2 actions to spawn */
+    bool initWithTwoActions(FiniteTimeAction *action1, FiniteTimeAction *action2);
+    bool init(const Vector<FiniteTimeAction*>& arrayOfActions);
+
+protected:
+    FiniteTimeAction *_one;
+    FiniteTimeAction *_two;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Spawn);
+};
+
+/** @class RotateTo
+ * @brief Rotates a Node object to a certain angle by modifying it's rotation attribute.
+ The direction will be decided by the shortest angle.
+*/ 
+class CC_DLL RotateTo : public ActionInterval
+{
+public:
+    /** 
+     * Creates the action with separate rotation angles.
+     *
+     * @param duration Duration time, in seconds.
+     * @param dstAngleX In degreesCW.
+     * @param dstAngleY In degreesCW.
+     * @return An autoreleased RotateTo object.
+     */
+    static RotateTo* create(float duration, float dstAngleX, float dstAngleY);
+
+    /** 
+     * Creates the action.
+     *
+     * @param duration Duration time, in seconds.
+     * @param dstAngle In degreesCW.
+     * @return An autoreleased RotateTo object.
+     */
+    static RotateTo* create(float duration, float dstAngle);
+
+    /** 
+     * Creates the action with 3D rotation angles.
+     * @param duration Duration time, in seconds.
+     * @param dstAngle3D A Vec3 angle.
+     * @return An autoreleased RotateTo object.
+     */
+    static RotateTo* create(float duration, const Vec3& dstAngle3D);
+
+    //
+    // Overrides
+    //
+    virtual RotateTo* clone() const override;
+    virtual RotateTo* reverse() const override;
+    virtual void startWithTarget(Node *target) override;
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    RotateTo();
+    virtual ~RotateTo() {}
+
+    /** 
+     * initializes the action
+     * @param duration in seconds
+     * @param dstAngleX in degreesCW
+     * @param dstAngleY in degreesCW
+     */
+    bool initWithDuration(float duration, float dstAngleX, float dstAngleY);
+    /**
+     * initializes the action
+     * @param duration in seconds
+     */
+    bool initWithDuration(float duration, const Vec3& dstAngle3D);
+
+    /** 
+     * calculates the start and diff angles
+     * @param dstAngle in degreesCW
+     */
+    void calculateAngles(float &startAngle, float &diffAngle, float dstAngle);
+    
+protected:
+    bool _is3D;
+    Vec3 _dstAngle;
+    Vec3 _startAngle;
+    Vec3 _diffAngle;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(RotateTo);
+};
+
+/** @class RotateBy
+ * @brief Rotates a Node object clockwise a number of degrees by modifying it's rotation attribute.
+*/
+class CC_DLL RotateBy : public ActionInterval
+{
+public:
+    /** 
+     * Creates the action.
+     *
+     * @param duration Duration time, in seconds.
+     * @param deltaAngle In degreesCW.
+     * @return An autoreleased RotateBy object.
+     */
+    static RotateBy* create(float duration, float deltaAngle);
+    /**
+     * Creates the action with separate rotation angles.
+     *
+     * @param duration Duration time, in seconds.
+     * @param deltaAngleZ_X In degreesCW.
+     * @param deltaAngleZ_Y In degreesCW.
+     * @return An autoreleased RotateBy object.
+     * @warning The physics body contained in Node doesn't support rotate with different x and y angle.
+     */
+    static RotateBy* create(float duration, float deltaAngleZ_X, float deltaAngleZ_Y);
+    /** Creates the action with 3D rotation angles.
+     *
+     * @param duration Duration time, in seconds.
+     * @param deltaAngle3D A Vec3 angle.
+     * @return An autoreleased RotateBy object.
+     */
+    static RotateBy* create(float duration, const Vec3& deltaAngle3D);
+
+    //
+    // Override
+    //
+    virtual RotateBy* clone() const override;
+    virtual RotateBy* reverse(void) const override;
+    virtual void startWithTarget(Node *target) override;
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    RotateBy();
+    virtual ~RotateBy() {}
+
+    /** initializes the action */
+    bool initWithDuration(float duration, float deltaAngle);
+    /** 
+     * @warning The physics body contained in Node doesn't support rotate with different x and y angle.
+     * @param deltaAngleZ_X in degreesCW
+     * @param deltaAngleZ_Y in degreesCW
+     */
+    bool initWithDuration(float duration, float deltaAngleZ_X, float deltaAngleZ_Y);
+    bool initWithDuration(float duration, const Vec3& deltaAngle3D);
+    
+protected:
+    bool _is3D;
+    Vec3 _deltaAngle;
+    Vec3 _startAngle;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(RotateBy);
+};
+
+/** @class MoveBy
+ * @brief Moves a Node object x,y pixels by modifying it's position attribute.
+ x and y are relative to the position of the object.
+ Several MoveBy actions can be concurrently called, and the resulting
+ movement will be the sum of individual movements.
+ @since v2.1beta2-custom
+ */
+class CC_DLL MoveBy : public ActionInterval
+{
+public:
+    /** 
+     * Creates the action.
+     *
+     * @param duration Duration time, in seconds.
+     * @param deltaPosition The delta distance in 2d, it's a Vec2 type.
+     * @return An autoreleased MoveBy object.
+     */
+    static MoveBy* create(float duration, const Vec2& deltaPosition);
+    /**
+     * Creates the action.
+     *
+     * @param duration Duration time, in seconds.
+     * @param deltaPosition The delta distance in 3d, it's a Vec3 type.
+     * @return An autoreleased MoveBy object.
+     */
+    static MoveBy* create(float duration, const Vec3& deltaPosition);
+
+    //
+    // Overrides
+    //
+    virtual MoveBy* clone() const override;
+    virtual MoveBy* reverse(void) const  override;
+    virtual void startWithTarget(Node *target) override;
+    /**
+     * @param time in seconds
+     */
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    MoveBy():_is3D(false) {}
+    virtual ~MoveBy() {}
+
+    /** initializes the action */
+    bool initWithDuration(float duration, const Vec2& deltaPosition);
+    bool initWithDuration(float duration, const Vec3& deltaPosition);
+
+protected:
+    bool _is3D;
+    Vec3 _positionDelta;
+    Vec3 _startPosition;
+    Vec3 _previousPosition;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(MoveBy);
+};
+
+/** @class MoveTo
+ * @brief Moves a Node object to the position x,y. x and y are absolute coordinates by modifying it's position attribute.
+ Several MoveTo actions can be concurrently called, and the resulting
+ movement will be the sum of individual movements.
+ @since v2.1beta2-custom
+ */
+class CC_DLL MoveTo : public MoveBy
+{
+public:
+    /** 
+     * Creates the action.
+     * @param duration Duration time, in seconds.
+     * @param position The destination position in 2d.
+     * @return An autoreleased MoveTo object.
+     */
+    static MoveTo* create(float duration, const Vec2& position);
+    /**
+     * Creates the action.
+     * @param duration Duration time, in seconds.
+     * @param position The destination position in 3d.
+     * @return An autoreleased MoveTo object.
+     */
+    static MoveTo* create(float duration, const Vec3& position);
+
+    //
+    // Overrides
+    //
+    virtual MoveTo* clone() const override;
+    virtual MoveTo* reverse() const  override;
+    virtual void startWithTarget(Node *target) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    MoveTo() {}
+    virtual ~MoveTo() {}
+
+    /** 
+     * initializes the action
+     * @param duration in seconds
+     */
+    bool initWithDuration(float duration, const Vec2& position);
+    /**
+     * initializes the action
+     * @param duration in seconds
+     */
+    bool initWithDuration(float duration, const Vec3& position);
+
+protected:
+    Vec3 _endPosition;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(MoveTo);
+};
+
+/** @class SkewTo
+ * @brief Skews a Node object to given angles by modifying it's skewX and skewY attributes
+@since v1.0
+*/
+class CC_DLL SkewTo : public ActionInterval
+{
+public:
+    /** 
+     * Creates the action.
+     * @param t Duration time, in seconds.
+     * @param sx Skew x angle.
+     * @param sy Skew y angle.
+     * @return An autoreleased SkewTo object.
+     */
+    static SkewTo* create(float t, float sx, float sy);
+
+    //
+    // Overrides
+    //
+    virtual SkewTo* clone() const override;
+    virtual SkewTo* reverse(void) const override;
+    virtual void startWithTarget(Node *target) override;
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    SkewTo();
+    virtual ~SkewTo() {}
+    /**
+     * @param t In seconds.
+     */
+    bool initWithDuration(float t, float sx, float sy);
+
+protected:
+    float _skewX;
+    float _skewY;
+    float _startSkewX;
+    float _startSkewY;
+    float _endSkewX;
+    float _endSkewY;
+    float _deltaX;
+    float _deltaY;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(SkewTo);
+};
+
+/** @class SkewBy
+* @brief Skews a Node object by skewX and skewY degrees.
+@since v1.0
+*/
+class CC_DLL SkewBy : public SkewTo
+{
+public:
+    /** 
+     * Creates the action.
+     * @param t Duration time, in seconds.
+     * @param deltaSkewX Skew x delta angle.
+     * @param deltaSkewY Skew y delta angle.
+     * @return An autoreleased SkewBy object.
+     */
+    static SkewBy* create(float t, float deltaSkewX, float deltaSkewY);
+
+    //
+    // Overrides
+    //
+    virtual void startWithTarget(Node *target) override;
+    virtual SkewBy* clone() const  override;
+    virtual SkewBy* reverse(void) const override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    SkewBy() {}
+    virtual ~SkewBy() {}
+    /**
+     * @param t In seconds.
+     */
+    bool initWithDuration(float t, float sx, float sy);
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(SkewBy);
+};
+
+/** @class ResizeTo
+* @brief Resize a Node object to the final size by modifying it's Size attribute.
+*/
+class  CC_DLL ResizeTo : public ActionInterval 
+{
+public:
+    /**
+    * Creates the action.
+    * @brief Resize a Node object to the final size by modifying it's Size attribute. Works on all nodes where setContentSize is effective. But it's mostly useful for nodes where 9-slice is enabled
+    * @param duration Duration time, in seconds.
+    * @param final_size The target size to reach
+    * @return An autoreleased RotateTo object.
+    */
+    static ResizeTo* create(float duration, const cocos2d::Size& final_size);
+
+    //
+    // Overrides
+    //
+    virtual ResizeTo* clone() const override;
+    void startWithTarget(cocos2d::Node* target) override;
+    void update(float time) override;
+
+CC_CONSTRUCTOR_ACCESS:
+    ResizeTo() {}
+    virtual ~ResizeTo() {}
+    
+    /**
+    * initializes the action
+    * @param duration in seconds
+    * @param final_size in Size type
+    */
+    bool initWithDuration(float duration, const cocos2d::Size& final_size);
+
+protected:
+    cocos2d::Size _initialSize;
+    cocos2d::Size _finalSize;
+    cocos2d::Size _sizeDelta;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(ResizeTo);
+};
+
+
+/** @class ResizeBy
+* @brief Resize a Node object by a Size. Works on all nodes where setContentSize is effective. But it's mostly useful for nodes where 9-slice is enabled
+*/
+class CC_DLL ResizeBy : public ActionInterval 
+{
+public:
+    /**
+    * Creates the action.
+    *
+    * @param duration Duration time, in seconds.
+    * @param deltaSize The delta size.
+    * @return An autoreleased ResizeBy object.
+    */
+    static ResizeBy* create(float duration, const cocos2d::Size& deltaSize);
+    
+    //
+    // Overrides
+    //
+    virtual ResizeBy* clone() const override;
+    virtual ResizeBy* reverse(void) const  override;
+    virtual void startWithTarget(Node *target) override;
+    /**
+    * @param time in seconds
+    */
+    virtual void update(float time) override;
+
+CC_CONSTRUCTOR_ACCESS:
+    ResizeBy() {}
+    virtual ~ResizeBy() {}
+    
+    /** initializes the action */
+    bool initWithDuration(float duration, const cocos2d::Size& deltaSize);
+
+protected:
+    cocos2d::Size _sizeDelta;
+    cocos2d::Size _startSize;
+    cocos2d::Size _previousSize;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(ResizeBy);
+};
+
+
+/** @class JumpBy
+ * @brief Moves a Node object simulating a parabolic jump movement by modifying it's position attribute.
+*/
+class CC_DLL JumpBy : public ActionInterval
+{
+public:
+    /** 
+     * Creates the action.
+     * @param duration Duration time, in seconds.
+     * @param position The jumping distance.
+     * @param height The jumping height.
+     * @param jumps The jumping times.
+     * @return An autoreleased JumpBy object.
+     */
+    static JumpBy* create(float duration, const Vec2& position, float height, int jumps);
+
+    //
+    // Overrides
+    //
+    virtual JumpBy* clone() const override;
+    virtual JumpBy* reverse(void) const override;
+    virtual void startWithTarget(Node *target) override;
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    JumpBy() {}
+    virtual ~JumpBy() {}
+
+    /** 
+     * initializes the action
+     * @param duration in seconds
+     */
+    bool initWithDuration(float duration, const Vec2& position, float height, int jumps);
+
+protected:
+    Vec2           _startPosition;
+    Vec2           _delta;
+    float           _height;
+    int             _jumps;
+    Vec2           _previousPos;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(JumpBy);
+};
+
+/** @class JumpTo
+ * @brief Moves a Node object to a parabolic position simulating a jump movement by modifying it's position attribute.
+*/ 
+class CC_DLL JumpTo : public JumpBy
+{
+public:
+    /** 
+     * Creates the action.
+     * @param duration Duration time, in seconds.
+     * @param position The jumping destination position.
+     * @param height The jumping height.
+     * @param jumps The jumping times.
+     * @return An autoreleased JumpTo object.
+     */
+    static JumpTo* create(float duration, const Vec2& position, float height, int jumps);
+
+    //
+    // Override
+    //
+    virtual void startWithTarget(Node *target) override;
+    virtual JumpTo* clone() const override;
+    virtual JumpTo* reverse(void) const override;
+
+CC_CONSTRUCTOR_ACCESS:
+    JumpTo() {}
+    virtual ~JumpTo() {}
+
+    /** 
+     * initializes the action
+     * @param duration In seconds.
+     */
+    bool initWithDuration(float duration, const Vec2& position, float height, int jumps);
+
+protected:
+    Vec2 _endPosition;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(JumpTo);
+};
+
+/** @struct Bezier configuration structure
+ */
+typedef struct _ccBezierConfig {
+    //! end position of the bezier
+    Vec2 endPosition;
+    //! Bezier control point 1
+    Vec2 controlPoint_1;
+    //! Bezier control point 2
+    Vec2 controlPoint_2;
+} ccBezierConfig;
+
+/** @class BezierBy
+ * @brief An action that moves the target with a cubic Bezier curve by a certain distance.
+ */
+class CC_DLL BezierBy : public ActionInterval
+{
+public:
+    /** Creates the action with a duration and a bezier configuration.
+     * @param t Duration time, in seconds.
+     * @param c Bezier config.
+     * @return An autoreleased BezierBy object.
+     * @code
+     * When this function bound to js or lua,the input params are changed.
+     * in js: var create(var t,var table)
+     * in lua: local create(local t, local table)
+     * @endcode
+     */
+    static BezierBy* create(float t, const ccBezierConfig& c);
+
+    //
+    // Overrides
+    //
+    virtual BezierBy* clone() const override;
+    virtual BezierBy* reverse(void) const override;
+    virtual void startWithTarget(Node *target) override;
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    BezierBy() {}
+    virtual ~BezierBy() {}
+
+    /** 
+     * initializes the action with a duration and a bezier configuration
+     * @param t in seconds
+     */
+    bool initWithDuration(float t, const ccBezierConfig& c);
+
+protected:
+    ccBezierConfig _config;
+    Vec2 _startPosition;
+    Vec2 _previousPosition;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(BezierBy);
+};
+
+/** @class BezierTo
+ * @brief An action that moves the target with a cubic Bezier curve to a destination point.
+ @since v0.8.2
+ */
+class CC_DLL BezierTo : public BezierBy
+{
+public:
+    /** Creates the action with a duration and a bezier configuration.
+     * @param t Duration time, in seconds.
+     * @param c Bezier config.
+     * @return An autoreleased BezierTo object.
+     * @code
+     * when this function bound to js or lua,the input params are changed
+     * in js: var create(var t,var table)
+     * in lua: local create(local t, local table)
+     * @endcode
+     */
+    static BezierTo* create(float t, const ccBezierConfig& c);
+
+    //
+    // Overrides
+    //
+    virtual void startWithTarget(Node *target) override;
+    virtual BezierTo* clone() const override;
+    virtual BezierTo* reverse(void) const override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    BezierTo() {}
+    virtual ~BezierTo() {}
+    /**
+     * @param t In seconds.
+     */
+    bool initWithDuration(float t, const ccBezierConfig &c);
+
+protected:
+    ccBezierConfig _toConfig;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(BezierTo);
+};
+
+/** @class ScaleTo
+ @brief Scales a Node object to a zoom factor by modifying it's scale attribute.
+ @warning This action doesn't support "reverse".
+ @warning The physics body contained in Node doesn't support this action.
+ */
+class CC_DLL ScaleTo : public ActionInterval
+{
+public:
+    /** 
+     * Creates the action with the same scale factor for X and Y.
+     * @param duration Duration time, in seconds.
+     * @param s Scale factor of x and y.
+     * @return An autoreleased ScaleTo object.
+     */
+    static ScaleTo* create(float duration, float s);
+
+    /** 
+     * Creates the action with and X factor and a Y factor.
+     * @param duration Duration time, in seconds.
+     * @param sx Scale factor of x.
+     * @param sy Scale factor of y.
+     * @return An autoreleased ScaleTo object.
+     */
+    static ScaleTo* create(float duration, float sx, float sy);
+
+    /** 
+     * Creates the action with X Y Z factor.
+     * @param duration Duration time, in seconds.
+     * @param sx Scale factor of x.
+     * @param sy Scale factor of y.
+     * @param sz Scale factor of z.
+     * @return An autoreleased ScaleTo object.
+     */
+    static ScaleTo* create(float duration, float sx, float sy, float sz);
+
+    //
+    // Overrides
+    //
+    virtual ScaleTo* clone() const override;
+    virtual ScaleTo* reverse(void) const override;
+    virtual void startWithTarget(Node *target) override;
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    ScaleTo() {}
+    virtual ~ScaleTo() {}
+
+    /** 
+     * initializes the action with the same scale factor for X and Y
+     * @param duration in seconds
+     */
+    bool initWithDuration(float duration, float s);
+    /** 
+     * initializes the action with and X factor and a Y factor 
+     * @param duration in seconds
+     */
+    bool initWithDuration(float duration, float sx, float sy);
+    /** 
+     * initializes the action with X Y Z factor 
+     * @param duration in seconds
+     */
+    bool initWithDuration(float duration, float sx, float sy, float sz);
+
+protected:
+    float _scaleX;
+    float _scaleY;
+    float _scaleZ;
+    float _startScaleX;
+    float _startScaleY;
+    float _startScaleZ;
+    float _endScaleX;
+    float _endScaleY;
+    float _endScaleZ;
+    float _deltaX;
+    float _deltaY;
+    float _deltaZ;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(ScaleTo);
+};
+
+/** @class ScaleBy
+ * @brief Scales a Node object a zoom factor by modifying it's scale attribute.
+ @warning The physics body contained in Node doesn't support this action.
+*/
+class CC_DLL ScaleBy : public ScaleTo
+{
+public:
+    /** 
+     * Creates the action with the same scale factor for X and Y.
+     * @param duration Duration time, in seconds.
+     * @param s Scale factor of x and y.
+     * @return An autoreleased ScaleBy object.
+     */
+    static ScaleBy* create(float duration, float s);
+
+    /** 
+     * Creates the action with and X factor and a Y factor.
+     * @param duration Duration time, in seconds.
+     * @param sx Scale factor of x.
+     * @param sy Scale factor of y.
+     * @return An autoreleased ScaleBy object.
+     */
+    static ScaleBy* create(float duration, float sx, float sy);
+
+    /** 
+     * Creates the action with X Y Z factor.
+     * @param duration Duration time, in seconds.
+     * @param sx Scale factor of x.
+     * @param sy Scale factor of y.
+     * @param sz Scale factor of z.
+     * @return An autoreleased ScaleBy object.
+     */
+    static ScaleBy* create(float duration, float sx, float sy, float sz);
+
+    //
+    // Overrides
+    //
+    virtual void startWithTarget(Node *target) override;
+    virtual ScaleBy* clone() const override;
+    virtual ScaleBy* reverse(void) const override;
+
+CC_CONSTRUCTOR_ACCESS:
+    ScaleBy() {}
+    virtual ~ScaleBy() {}
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(ScaleBy);
+};
+
+/** @class Blink
+ * @brief Blinks a Node object by modifying it's visible attribute.
+*/
+class CC_DLL Blink : public ActionInterval
+{
+public:
+    /** 
+     * Creates the action.
+     * @param duration Duration time, in seconds.
+     * @param blinks Blink times.
+     * @return An autoreleased Blink object.
+     */
+    static Blink* create(float duration, int blinks);
+
+    //
+    // Overrides
+    //
+    virtual Blink* clone() const override;
+    virtual Blink* reverse() const override;
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    virtual void startWithTarget(Node *target) override;
+    virtual void stop() override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    Blink() {}
+    virtual ~Blink() {}
+
+    /** 
+     * initializes the action 
+     * @param duration in seconds
+     */
+    bool initWithDuration(float duration, int blinks);
+    
+protected:
+    int _times;
+    bool _originalState;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Blink);
+};
+
+
+/** @class FadeTo
+ * @brief Fades an object that implements the RGBAProtocol protocol. It modifies the opacity from the current value to a custom one.
+ @warning This action doesn't support "reverse"
+ */
+class CC_DLL FadeTo : public ActionInterval
+{
+public:
+    /** 
+     * Creates an action with duration and opacity.
+     * @param duration Duration time, in seconds.
+     * @param opacity A certain opacity, the range is from 0 to 255.
+     * @return An autoreleased FadeTo object.
+     */
+    static FadeTo* create(float duration, GLubyte opacity);
+
+    //
+    // Overrides
+    //
+    virtual FadeTo* clone() const override;
+    virtual FadeTo* reverse(void) const override;
+    virtual void startWithTarget(Node *target) override;
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    FadeTo() {}
+    virtual ~FadeTo() {}
+
+    /** 
+     * initializes the action with duration and opacity 
+     * @param duration in seconds
+     */
+    bool initWithDuration(float duration, GLubyte opacity);
+
+protected:
+    GLubyte _toOpacity;
+    GLubyte _fromOpacity;
+    friend class FadeOut;
+    friend class FadeIn;
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(FadeTo);
+};
+
+/** @class FadeIn
+ * @brief Fades In an object that implements the RGBAProtocol protocol. It modifies the opacity from 0 to 255.
+ The "reverse" of this action is FadeOut
+ */
+class CC_DLL FadeIn : public FadeTo
+{
+public:
+    /** 
+     * Creates the action.
+     * @param d Duration time, in seconds.
+     * @return An autoreleased FadeIn object.
+     */
+    static FadeIn* create(float d);
+
+    //
+    // Overrides
+    //
+    virtual void startWithTarget(Node *target) override;
+    virtual FadeIn* clone() const override;
+    virtual FadeTo* reverse(void) const override;
+
+    /**
+     * @js NA
+     */
+    void setReverseAction(FadeTo* ac);
+
+CC_CONSTRUCTOR_ACCESS:
+    FadeIn():_reverseAction(nullptr) {}
+    virtual ~FadeIn() {}
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(FadeIn);
+    FadeTo* _reverseAction;
+};
+
+/** @class FadeOut
+ * @brief Fades Out an object that implements the RGBAProtocol protocol. It modifies the opacity from 255 to 0.
+ The "reverse" of this action is FadeIn
+*/
+class CC_DLL FadeOut : public FadeTo
+{
+public:
+    /** 
+     * Creates the action.
+     * @param d Duration time, in seconds.
+     */
+    static FadeOut* create(float d);
+
+    //
+    // Overrides
+    //
+    virtual void startWithTarget(Node *target) override;
+    virtual FadeOut* clone() const  override;
+    virtual FadeTo* reverse(void) const override;
+
+    /**
+     * @js NA
+     */
+    void setReverseAction(FadeTo* ac);
+
+CC_CONSTRUCTOR_ACCESS:
+    FadeOut():_reverseAction(nullptr) {}
+    virtual ~FadeOut() {}
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(FadeOut);
+    FadeTo* _reverseAction;
+};
+
+/** @class TintTo
+ * @brief Tints a Node that implements the NodeRGB protocol from current tint to a custom one.
+ @warning This action doesn't support "reverse"
+ @since v0.7.2
+*/
+class CC_DLL TintTo : public ActionInterval
+{
+public:
+    /** 
+     * Creates an action with duration and color.
+     * @param duration Duration time, in seconds.
+     * @param red Red Color, from 0 to 255.
+     * @param green Green Color, from 0 to 255.
+     * @param blue Blue Color, from 0 to 255.
+     * @return An autoreleased TintTo object.
+     */
+    static TintTo* create(float duration, GLubyte red, GLubyte green, GLubyte blue);
+    /**
+     * Creates an action with duration and color.
+     * @param duration Duration time, in seconds.
+     * @param color It's a Color3B type.
+     * @return An autoreleased TintTo object.
+     */
+    static TintTo* create(float duration, const Color3B& color);
+
+    //
+    // Overrides
+    //
+    virtual TintTo* clone() const override;
+    virtual TintTo* reverse(void) const override;
+    virtual void startWithTarget(Node *target) override;
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    TintTo() {}
+    virtual ~TintTo() {}
+
+    /** initializes the action with duration and color */
+    bool initWithDuration(float duration, GLubyte red, GLubyte green, GLubyte blue);
+
+protected:
+    Color3B _to;
+    Color3B _from;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(TintTo);
+};
+
+/** @class TintBy
+ @brief Tints a Node that implements the NodeRGB protocol from current tint to a custom one.
+ @since v0.7.2
+ */
+class CC_DLL TintBy : public ActionInterval
+{
+public:
+    /** 
+     * Creates an action with duration and color.
+     * @param duration Duration time, in seconds.
+     * @param deltaRed Delta red color.
+     * @param deltaGreen Delta green color.
+     * @param deltaBlue Delta blue color.
+     * @return An autoreleased TintBy object.
+     */
+    static TintBy* create(float duration, GLshort deltaRed, GLshort deltaGreen, GLshort deltaBlue);
+
+    //
+    // Overrides
+    //
+    virtual TintBy* clone() const override;
+    virtual TintBy* reverse() const override;
+    virtual void startWithTarget(Node *target) override;
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    TintBy() {}
+    virtual ~TintBy() {}
+
+    /** initializes the action with duration and color */
+    bool initWithDuration(float duration, GLshort deltaRed, GLshort deltaGreen, GLshort deltaBlue);
+
+protected:
+    GLshort _deltaR;
+    GLshort _deltaG;
+    GLshort _deltaB;
+
+    GLshort _fromR;
+    GLshort _fromG;
+    GLshort _fromB;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(TintBy);
+};
+
+/** @class DelayTime
+ * @brief Delays the action a certain amount of seconds.
+*/
+class CC_DLL DelayTime : public ActionInterval
+{
+public:
+    /** 
+     * Creates the action.
+     * @param d Duration time, in seconds.
+     * @return An autoreleased DelayTime object.
+     */
+    static DelayTime* create(float d);
+
+    //
+    // Overrides
+    //
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    virtual DelayTime* reverse() const override;
+    virtual DelayTime* clone() const override;
+
+CC_CONSTRUCTOR_ACCESS:
+    DelayTime() {}
+    virtual ~DelayTime() {}
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(DelayTime);
+};
+
+/** @class ReverseTime
+ * @brief Executes an action in reverse order, from time=duration to time=0
+ 
+ @warning Use this action carefully. This action is not
+ sequenceable. Use it as the default "reversed" method
+ of your own actions, but using it outside the "reversed"
+ scope is not recommended.
+*/
+class CC_DLL ReverseTime : public ActionInterval
+{
+public:
+    /** Creates the action.
+     *
+     * @param action a certain action.
+     * @return An autoreleased ReverseTime object.
+     */
+    static ReverseTime* create(FiniteTimeAction *action);
+
+    //
+    // Overrides
+    //
+    virtual ReverseTime* reverse() const override;
+    virtual ReverseTime* clone() const override;
+    virtual void startWithTarget(Node *target) override;
+    virtual void stop(void) override;
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    ReverseTime();
+    virtual ~ReverseTime(void);
+
+    /** initializes the action */
+    bool initWithAction(FiniteTimeAction *action);
+
+protected:
+    FiniteTimeAction *_other;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(ReverseTime);
+};
+
+class Texture2D;
+/** @class Animate
+ * @brief Animates a sprite given the name of an Animation.
+ */
+class CC_DLL Animate : public ActionInterval
+{
+public:
+    /** Creates the action with an Animation and will restore the original frame when the animation is over.
+     *
+     * @param animation A certain animation.
+     * @return An autoreleased Animate object.
+     */
+    static Animate* create(Animation *animation);
+
+    /** Sets the Animation object to be animated 
+     * 
+     * @param animation certain animation.
+     */
+    void setAnimation( Animation* animation );
+    /** returns the Animation object that is being animated 
+     *
+     * @return Gets the animation object that is being animated.
+     */
+    Animation* getAnimation() { return _animation; }
+    const Animation* getAnimation() const { return _animation; }
+
+    /**
+     * Gets the index of sprite frame currently displayed.
+     * @return int  the index of sprite frame currently displayed.
+     */
+    int getCurrentFrameIndex() { return _currFrameIndex; }
+    //
+    // Overrides
+    //
+    virtual Animate* clone() const override;
+    virtual Animate* reverse() const override;
+    virtual void startWithTarget(Node *target) override;
+    virtual void stop(void) override;
+    /**
+     * @param t In seconds.
+     */
+    virtual void update(float t) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    Animate();
+    virtual ~Animate();
+
+    /** initializes the action with an Animation and will restore the original frame when the animation is over */
+    bool initWithAnimation(Animation *animation);
+
+protected:
+    std::vector<float>* _splitTimes;
+    int             _nextFrame;
+    SpriteFrame*    _origFrame;
+    int _currFrameIndex;
+    unsigned int    _executedLoops;
+    Animation*      _animation;
+
+    EventCustom*    _frameDisplayedEvent;
+    AnimationFrame::DisplayedEventInfo _frameDisplayedEventInfo;
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Animate);
+};
+
+/** @class TargetedAction
+ * @brief Overrides the target of an action so that it always runs on the target
+ * specified at action creation rather than the one specified by runAction.
+ */
+class CC_DLL TargetedAction : public ActionInterval
+{
+public:
+    /** Create an action with the specified action and forced target.
+     * 
+     * @param target The target needs to override.
+     * @param action The action needs to override.
+     * @return An autoreleased TargetedAction object.
+     */
+    static TargetedAction* create(Node* target, FiniteTimeAction* action);
+
+    /** Sets the target that the action will be forced to run with.
+     *
+     * @param forcedTarget The target that the action will be forced to run with.
+     */
+    void setForcedTarget(Node* forcedTarget);
+    /** returns the target that the action is forced to run with. 
+     *
+     * @return The target that the action is forced to run with.
+     */
+    Node* getForcedTarget() { return _forcedTarget; }
+    const Node* getForcedTarget() const { return _forcedTarget; }
+
+    //
+    // Overrides
+    //
+    virtual TargetedAction* clone() const override;
+    virtual TargetedAction* reverse() const  override;
+    virtual void startWithTarget(Node *target) override;
+    virtual void stop(void) override;
+    /**
+     * @param time In seconds.
+     */
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    TargetedAction();
+    virtual ~TargetedAction();
+
+    /** Init an action with the specified action and forced target */
+    bool initWithTarget(Node* target, FiniteTimeAction* action);
+
+protected:
+    FiniteTimeAction* _action;
+    Node* _forcedTarget;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(TargetedAction);
+};
+
+/**
+ * @class ActionFloat
+ * @brief Action used to animate any value in range [from,to] over specified time interval
+ */
+class CC_DLL ActionFloat : public ActionInterval
+{
+public:
+    /**
+     *  Callback function used to report back result
+     */
+    typedef std::function<void(float value)> ActionFloatCallback;
+
+    /**
+     * Creates FloatAction with specified duration, from value, to value and callback to report back
+     * results
+     * @param duration of the action
+     * @param from value to start from
+     * @param to value to be at the end of the action
+     * @param callback to report back result
+     *
+     * @return An autoreleased ActionFloat object
+     */
+    static ActionFloat* create(float duration, float from, float to, ActionFloatCallback callback);
+
+    /**
+     * Overridden ActionInterval methods
+     */
+    void startWithTarget(Node* target) override;
+    void update(float delta) override;
+    ActionFloat* reverse() const override;
+    ActionFloat* clone() const override;
+
+CC_CONSTRUCTOR_ACCESS:
+    ActionFloat() {};
+    virtual ~ActionFloat() {};
+
+    bool initWithDuration(float duration, float from, float to, ActionFloatCallback callback);
+
+protected:
+    /* From value */
+    float _from;
+    /* To value */
+    float _to;
+    /* delta time */
+    float _delta;
+
+    /* Callback to report back results */
+    ActionFloatCallback _callback;
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(ActionFloat);
+};
+
+// end of actions group
+/// @}
+
+NS_CC_END
+
+#endif //__ACTION_CCINTERVAL_ACTION_H__

+ 503 - 0
cocos2d/cocos/2d/CCActionManager.cpp

@@ -0,0 +1,503 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2009      Valentin Milea
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCActionManager.h"
+#include "2d/CCNode.h"
+#include "2d/CCAction.h"
+#include "base/CCScheduler.h"
+#include "base/ccMacros.h"
+#include "base/ccCArray.h"
+#include "base/uthash.h"
+
+NS_CC_BEGIN
+//
+// singleton stuff
+//
+typedef struct _hashElement
+{
+    struct _ccArray     *actions;
+    Node                *target;
+    int                 actionIndex;
+    Action              *currentAction;
+    bool                currentActionSalvaged;
+    bool                paused;
+    UT_hash_handle      hh;
+} tHashElement;
+
+ActionManager::ActionManager()
+: _targets(nullptr),
+  _currentTarget(nullptr),
+  _currentTargetSalvaged(false)
+{
+
+}
+
+ActionManager::~ActionManager()
+{
+    CCLOGINFO("deallocing ActionManager: %p", this);
+
+    removeAllActions();
+}
+
+// private
+
+void ActionManager::deleteHashElement(tHashElement *element)
+{
+    ccArrayFree(element->actions);
+    HASH_DEL(_targets, element);
+    element->target->release();
+    free(element);
+}
+
+void ActionManager::actionAllocWithHashElement(tHashElement *element)
+{
+    // 4 actions per Node by default
+    if (element->actions == nullptr)
+    {
+        element->actions = ccArrayNew(4);
+    }else 
+    if (element->actions->num == element->actions->max)
+    {
+        ccArrayDoubleCapacity(element->actions);
+    }
+
+}
+
+void ActionManager::removeActionAtIndex(ssize_t index, tHashElement *element)
+{
+    Action *action = static_cast<Action*>(element->actions->arr[index]);
+
+    if (action == element->currentAction && (! element->currentActionSalvaged))
+    {
+        element->currentAction->retain();
+        element->currentActionSalvaged = true;
+    }
+
+    ccArrayRemoveObjectAtIndex(element->actions, index, true);
+
+    // update actionIndex in case we are in tick. looping over the actions
+    if (element->actionIndex >= index)
+    {
+        element->actionIndex--;
+    }
+
+    if (element->actions->num == 0)
+    {
+        if (_currentTarget == element)
+        {
+            _currentTargetSalvaged = true;
+        }
+        else
+        {
+            deleteHashElement(element);
+        }
+    }
+}
+
+// pause / resume
+
+void ActionManager::pauseTarget(Node *target)
+{
+    tHashElement *element = nullptr;
+    HASH_FIND_PTR(_targets, &target, element);
+    if (element)
+    {
+        element->paused = true;
+    }
+}
+
+void ActionManager::resumeTarget(Node *target)
+{
+    tHashElement *element = nullptr;
+    HASH_FIND_PTR(_targets, &target, element);
+    if (element)
+    {
+        element->paused = false;
+    }
+}
+
+Vector<Node*> ActionManager::pauseAllRunningActions()
+{
+    Vector<Node*> idsWithActions;
+    
+    for (tHashElement *element=_targets; element != nullptr; element = (tHashElement *)element->hh.next) 
+    {
+        if (! element->paused) 
+        {
+            element->paused = true;
+            idsWithActions.pushBack(element->target);
+        }
+    }    
+    
+    return idsWithActions;
+}
+
+void ActionManager::resumeTargets(const Vector<Node*>& targetsToResume)
+{
+    for(const auto &node : targetsToResume)
+    {
+        this->resumeTarget(node);
+    }
+}
+
+// run
+
+void ActionManager::addAction(Action *action, Node *target, bool paused)
+{
+    CCASSERT(action != nullptr, "action can't be nullptr!");
+    CCASSERT(target != nullptr, "target can't be nullptr!");
+    if(action == nullptr || target == nullptr)
+        return;
+
+    tHashElement *element = nullptr;
+    // we should convert it to Ref*, because we save it as Ref*
+    Ref *tmp = target;
+    HASH_FIND_PTR(_targets, &tmp, element);
+    if (! element)
+    {
+        element = (tHashElement*)calloc(sizeof(*element), 1);
+        element->paused = paused;
+        target->retain();
+        element->target = target;
+        HASH_ADD_PTR(_targets, target, element);
+    }
+
+     actionAllocWithHashElement(element);
+ 
+     CCASSERT(! ccArrayContainsObject(element->actions, action), "action already be added!");
+     ccArrayAppendObject(element->actions, action);
+ 
+     action->startWithTarget(target);
+}
+
+// remove
+
+void ActionManager::removeAllActions()
+{
+    for (tHashElement *element = _targets; element != nullptr; )
+    {
+        auto target = element->target;
+        element = (tHashElement*)element->hh.next;
+        removeAllActionsFromTarget(target);
+    }
+}
+
+void ActionManager::removeAllActionsFromTarget(Node *target)
+{
+    // explicit null handling
+    if (target == nullptr)
+    {
+        return;
+    }
+
+    tHashElement *element = nullptr;
+    HASH_FIND_PTR(_targets, &target, element);
+    if (element)
+    {
+        if (ccArrayContainsObject(element->actions, element->currentAction) && (! element->currentActionSalvaged))
+        {
+            element->currentAction->retain();
+            element->currentActionSalvaged = true;
+        }
+
+        ccArrayRemoveAllObjects(element->actions);
+        if (_currentTarget == element)
+        {
+            _currentTargetSalvaged = true;
+        }
+        else
+        {
+            deleteHashElement(element);
+        }
+    }
+}
+
+void ActionManager::removeAction(Action *action)
+{
+    // explicit null handling
+    if (action == nullptr)
+    {
+        return;
+    }
+
+    tHashElement *element = nullptr;
+    Ref *target = action->getOriginalTarget();
+    HASH_FIND_PTR(_targets, &target, element);
+    if (element)
+    {
+        auto i = ccArrayGetIndexOfObject(element->actions, action);
+        if (i != CC_INVALID_INDEX)
+        {
+            removeActionAtIndex(i, element);
+        }
+    }
+}
+
+void ActionManager::removeActionByTag(int tag, Node *target)
+{
+    CCASSERT(tag != Action::INVALID_TAG, "Invalid tag value!");
+    CCASSERT(target != nullptr, "target can't be nullptr!");
+    if (target == nullptr)
+    {
+        return;
+    }
+
+    tHashElement *element = nullptr;
+    HASH_FIND_PTR(_targets, &target, element);
+
+    if (element)
+    {
+        auto limit = element->actions->num;
+        for (int i = 0; i < limit; ++i)
+        {
+            Action *action = static_cast<Action*>(element->actions->arr[i]);
+
+            if (action->getTag() == (int)tag && action->getOriginalTarget() == target)
+            {
+                removeActionAtIndex(i, element);
+                break;
+            }
+        }
+    }
+}
+
+void ActionManager::removeAllActionsByTag(int tag, Node *target)
+{
+    CCASSERT(tag != Action::INVALID_TAG, "Invalid tag value!");
+    CCASSERT(target != nullptr, "target can't be nullptr!");
+    if (target == nullptr)
+    {
+        return;
+    }
+    
+    tHashElement *element = nullptr;
+    HASH_FIND_PTR(_targets, &target, element);
+    
+    if (element)
+    {
+        auto limit = element->actions->num;
+        for (int i = 0; i < limit;)
+        {
+            Action *action = static_cast<Action*>(element->actions->arr[i]);
+
+            if (action->getTag() == (int)tag && action->getOriginalTarget() == target)
+            {
+                removeActionAtIndex(i, element);
+                --limit;
+            }
+            else
+            {
+                ++i;
+            }
+        }
+    }
+}
+
+void ActionManager::removeActionsByFlags(unsigned int flags, Node *target)
+{
+    if (flags == 0)
+    {
+        return;
+    }
+    CCASSERT(target != nullptr, "target can't be nullptr!");
+    if (target == nullptr)
+    {
+        return;
+    }
+
+    tHashElement *element = nullptr;
+    HASH_FIND_PTR(_targets, &target, element);
+
+    if (element)
+    {
+        auto limit = element->actions->num;
+        for (int i = 0; i < limit;)
+        {
+            Action *action = static_cast<Action*>(element->actions->arr[i]);
+
+            if ((action->getFlags() & flags) != 0 && action->getOriginalTarget() == target)
+            {
+                removeActionAtIndex(i, element);
+                --limit;
+            }
+            else
+            {
+                ++i;
+            }
+        }
+    }
+}
+
+// get
+
+// FIXME: Passing "const O *" instead of "const O&" because HASH_FIND_IT requires the address of a pointer
+// and, it is not possible to get the address of a reference
+Action* ActionManager::getActionByTag(int tag, const Node *target) const
+{
+    CCASSERT(tag != Action::INVALID_TAG, "Invalid tag value!");
+
+    tHashElement *element = nullptr;
+    HASH_FIND_PTR(_targets, &target, element);
+
+    if (element)
+    {
+        if (element->actions != nullptr)
+        {
+            auto limit = element->actions->num;
+            for (int i = 0; i < limit; ++i)
+            {
+                Action *action = static_cast<Action*>(element->actions->arr[i]);
+
+                if (action->getTag() == (int)tag)
+                {
+                    return action;
+                }
+            }
+        }
+    }
+
+    return nullptr;
+}
+
+// FIXME: Passing "const O *" instead of "const O&" because HASH_FIND_IT requires the address of a pointer
+// and, it is not possible to get the address of a reference
+ssize_t ActionManager::getNumberOfRunningActionsInTarget(const Node *target) const
+{
+    tHashElement *element = nullptr;
+    HASH_FIND_PTR(_targets, &target, element);
+    if (element)
+    {
+        return element->actions ? element->actions->num : 0;
+    }
+
+    return 0;
+}
+
+// FIXME: Passing "const O *" instead of "const O&" because HASH_FIND_IT requires the address of a pointer
+// and, it is not possible to get the address of a reference
+size_t ActionManager::getNumberOfRunningActionsInTargetByTag(const Node *target,
+                                                             int tag)
+{
+    CCASSERT(tag != Action::INVALID_TAG, "Invalid tag value!");
+
+    tHashElement *element = nullptr;
+    HASH_FIND_PTR(_targets, &target, element);
+
+    if(!element || !element->actions)
+        return 0;
+
+    int count = 0;
+    auto limit = element->actions->num;
+    for(int i = 0; i < limit; ++i)
+    {
+        auto action = static_cast<Action*>(element->actions->arr[i]);
+        if(action->getTag() == tag)
+            ++count;
+    }
+
+    return count;
+}
+
+ssize_t ActionManager::getNumberOfRunningActions() const
+{
+    ssize_t count = 0;
+    struct _hashElement* element = nullptr;
+    struct _hashElement* tmp = nullptr;
+    HASH_ITER(hh, _targets, element, tmp)
+    {
+        count += (element->actions ? element->actions->num : 0);
+    }
+    return count;
+}
+
+// main loop
+void ActionManager::update(float dt)
+{
+    for (tHashElement *elt = _targets; elt != nullptr; )
+    {
+        _currentTarget = elt;
+        _currentTargetSalvaged = false;
+
+        if (! _currentTarget->paused)
+        {
+            // The 'actions' MutableArray may change while inside this loop.
+            for (_currentTarget->actionIndex = 0; _currentTarget->actionIndex < _currentTarget->actions->num;
+                _currentTarget->actionIndex++)
+            {
+                _currentTarget->currentAction = static_cast<Action*>(_currentTarget->actions->arr[_currentTarget->actionIndex]);
+                if (_currentTarget->currentAction == nullptr)
+                {
+                    continue;
+                }
+
+                _currentTarget->currentActionSalvaged = false;
+
+                _currentTarget->currentAction->step(dt);
+
+                if (_currentTarget->currentActionSalvaged)
+                {
+                    // The currentAction told the node to remove it. To prevent the action from
+                    // accidentally deallocating itself before finishing its step, we retained
+                    // it. Now that step is done, it's safe to release it.
+                    _currentTarget->currentAction->release();
+                } else
+                if (_currentTarget->currentAction->isDone())
+                {
+                    _currentTarget->currentAction->stop();
+
+                    Action *action = _currentTarget->currentAction;
+                    // Make currentAction nil to prevent removeAction from salvaging it.
+                    _currentTarget->currentAction = nullptr;
+                    removeAction(action);
+                }
+
+                _currentTarget->currentAction = nullptr;
+            }
+        }
+
+        // elt, at this moment, is still valid
+        // so it is safe to ask this here (issue #490)
+        elt = (tHashElement*)(elt->hh.next);
+
+        // only delete currentTarget if no actions were scheduled during the cycle (issue #481)
+        if (_currentTargetSalvaged && _currentTarget->actions->num == 0)
+        {
+            deleteHashElement(_currentTarget);
+        }
+        //if some node reference 'target', it's reference count >= 2 (issues #14050)
+        else if (_currentTarget->target->getReferenceCount() == 1)
+        {
+            deleteHashElement(_currentTarget);
+        }
+    }
+
+    // issue #635
+    _currentTarget = nullptr;
+}
+
+NS_CC_END

+ 223 - 0
cocos2d/cocos/2d/CCActionManager.h

@@ -0,0 +1,223 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2009      Valentin Milea
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+
+#ifndef __ACTION_CCACTION_MANAGER_H__
+#define __ACTION_CCACTION_MANAGER_H__
+
+#include "2d/CCAction.h"
+#include "base/CCVector.h"
+#include "base/CCRef.h"
+
+NS_CC_BEGIN
+
+class Action;
+
+struct _hashElement;
+
+/**
+ * @addtogroup actions
+ * @{
+ */
+
+/** @class ActionManager
+ @brief ActionManager is a singleton that manages all the actions.
+ Normally you won't need to use this singleton directly. 99% of the cases you will use the Node interface,
+ which uses this singleton.
+ But there are some cases where you might need to use this singleton.
+ Examples:
+    - When you want to run an action where the target is different from a Node. 
+    - When you want to pause / resume the actions.
+ 
+ @since v0.8
+ */
+class CC_DLL ActionManager : public Ref
+{
+public:
+    /**
+     * @js ctor
+     */
+    ActionManager(void);
+
+    /**
+     * @js NA
+     * @lua NA
+     */
+    ~ActionManager(void);
+
+    // actions
+    
+    /** Adds an action with a target. 
+     If the target is already present, then the action will be added to the existing target.
+     If the target is not present, a new instance of this target will be created either paused or not, and the action will be added to the newly created target.
+     When the target is paused, the queued actions won't be 'ticked'.
+     *
+     * @param action    A certain action.
+     * @param target    The target which need to be added an action.
+     * @param paused    Is the target paused or not.
+     */
+    void addAction(Action *action, Node *target, bool paused);
+
+    /** Removes all actions from all the targets.
+     */
+    void removeAllActions();
+
+    /** Removes all actions from a certain target.
+     All the actions that belongs to the target will be removed.
+     *
+     * @param target    A certain target.
+     */
+    void removeAllActionsFromTarget(Node *target);
+
+    /** Removes an action given an action reference.
+     *
+     * @param action    A certain target.
+     */
+    void removeAction(Action *action);
+
+    /** Removes an action given its tag and the target.
+     *
+     * @param tag       The action's tag.
+     * @param target    A certain target.
+     */
+    void removeActionByTag(int tag, Node *target);
+    
+    /** Removes all actions given its tag and the target.
+     *
+     * @param tag       The actions' tag.
+     * @param target    A certain target.
+     * @js NA
+     */
+    void removeAllActionsByTag(int tag, Node *target);
+
+    /** Removes all actions matching at least one bit in flags and the target.
+     *
+     * @param flags     The flag field to match the actions' flags based on bitwise AND.
+     * @param target    A certain target.
+     * @js NA
+     */
+    void removeActionsByFlags(unsigned int flags, Node *target);
+
+    /** Gets an action given its tag an a target.
+     *
+     * @param tag       The action's tag.
+     * @param target    A certain target.
+     * @return  The Action the with the given tag.
+     */
+    Action* getActionByTag(int tag, const Node *target) const;
+
+    /** Returns the numbers of actions that are running in a certain target. 
+     * Composable actions are counted as 1 action. Example:
+     * - If you are running 1 Sequence of 7 actions, it will return 1.
+     * - If you are running 7 Sequences of 2 actions, it will return 7.
+     *
+     * @param target    A certain target.
+     * @return  The numbers of actions that are running in a certain target.
+     * @js NA
+     */
+    ssize_t getNumberOfRunningActionsInTarget(const Node *target) const;
+    
+    /** Returns the numbers of actions that are running in all targets.
+     * Composable actions are counted as 1 action. Example:
+     * - If you are running 1 Sequence of 7 actions, it will return 1.
+     * - If you are running 7 Sequences of 2 actions, it will return 7.
+     *
+     * @return  The numbers of actions that are running in a certain target.
+     * @js NA
+     */
+    ssize_t getNumberOfRunningActions() const;
+
+    /** @deprecated Use getNumberOfRunningActionsInTarget() instead.
+     */
+    CC_DEPRECATED_ATTRIBUTE ssize_t numberOfRunningActionsInTarget(Node *target) const { return getNumberOfRunningActionsInTarget(target); }
+
+
+    /** Returns the numbers of actions that are running in a
+     *  certain target with a specific tag.
+     * Like getNumberOfRunningActionsInTarget Composable actions
+     * are counted as 1 action. Example:
+     * - If you are running 1 Sequence of 7 actions, it will return 1.
+     * - If you are running 7 Sequences of 2 actions, it will return 7.
+     *
+     * @param target    A certain target.
+     * @param tag       Tag that will be searched.
+     * @return  The numbers of actions that are running in a certain target
+     *          with a specific tag.
+     * @see getNumberOfRunningActionsInTarget
+     * @js NA
+     */
+    size_t getNumberOfRunningActionsInTargetByTag(const Node *target, int tag);
+
+
+    /** Pauses the target: all running actions and newly added actions will be paused.
+     *
+     * @param target    A certain target.
+     */
+    void pauseTarget(Node *target);
+
+    /** Resumes the target. All queued actions will be resumed.
+     *
+     * @param target    A certain target.
+     */
+    void resumeTarget(Node *target);
+    
+    /** Pauses all running actions, returning a list of targets whose actions were paused.
+     *
+     * @return  A list of targets whose actions were paused.
+     */
+    Vector<Node*> pauseAllRunningActions();
+    
+    /** Resume a set of targets (convenience function to reverse a pauseAllRunningActions call).
+     *
+     * @param targetsToResume   A set of targets need to be resumed.
+     */
+    void resumeTargets(const Vector<Node*>& targetsToResume);
+    
+    /** Main loop of ActionManager.
+     * @param dt    In seconds.
+     */
+    void update(float dt);
+    
+protected:
+    // declared in ActionManager.m
+
+    void removeActionAtIndex(ssize_t index, struct _hashElement *element);
+    void deleteHashElement(struct _hashElement *element);
+    void actionAllocWithHashElement(struct _hashElement *element);
+
+protected:
+    struct _hashElement    *_targets;
+    struct _hashElement    *_currentTarget;
+    bool            _currentTargetSalvaged;
+};
+
+// end of actions group
+/// @}
+
+NS_CC_END
+
+#endif // __ACTION_CCACTION_MANAGER_H__

+ 132 - 0
cocos2d/cocos/2d/CCActionPageTurn3D.cpp

@@ -0,0 +1,132 @@
+/****************************************************************************
+Copyright (c) 2009      Sindesso Pty Ltd http://www.sindesso.com/
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCActionPageTurn3D.h"
+#include "2d/CCGrid.h"
+#include "2d/CCNodeGrid.h"
+
+NS_CC_BEGIN
+
+PageTurn3D* PageTurn3D::create(float duration, const Size& gridSize)
+{
+    PageTurn3D *action = new (std::nothrow) PageTurn3D();
+
+    if (action && action->initWithDuration(duration, gridSize))
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+PageTurn3D *PageTurn3D::clone() const
+{
+    // no copy constructor
+    return PageTurn3D::create(_duration, _gridSize);
+}
+
+GridBase* PageTurn3D::getGrid()
+{
+    auto result = Grid3D::create(_gridSize, _gridNodeTarget->getGridRect());
+    if (result)
+    {
+        result->setNeedDepthTestForBlit(true);
+    }
+    
+    return result;
+}
+
+/*
+ * Update each tick
+ * Time is the percentage of the way through the duration
+ */
+void PageTurn3D::update(float time)
+{
+    float tt = MAX(0, time - 0.25f);
+    float deltaAy = (tt * tt * 500);
+    float ay = -100 - deltaAy;
+    
+    float deltaTheta = sqrtf(time);
+    float theta = deltaTheta > 0.5f ? (float)M_PI_2*deltaTheta : (float)M_PI_2*(1-deltaTheta);
+    
+    float rotateByYAxis = (2-time)* M_PI;
+    
+    float sinTheta = sinf(theta);
+    float cosTheta = cosf(theta);
+    
+    for (int i = 0; i <= _gridSize.width; ++i)
+    {
+        for (int j = 0; j <= _gridSize.height; ++j)
+        {
+            // Get original vertex
+            Vec3 p = getOriginalVertex(Vec2(i ,j));
+            
+            p.x -= getGridRect().origin.x;
+            float R = sqrtf((p.x * p.x) + ((p.y - ay) * (p.y - ay)));
+            float r = R * sinTheta;
+            float alpha = asinf( p.x / R );
+            float beta = alpha / sinTheta;
+            float cosBeta = cosf( beta );
+            
+            // If beta > PI then we've wrapped around the cone
+            // Reduce the radius to stop these points interfering with others
+            if (beta <= M_PI)
+            {
+                p.x = ( r * sinf(beta));
+            }
+            else
+            {
+                // Force X = 0 to stop wrapped
+                // points
+                p.x = 0;
+            }
+
+            p.y = ( R + ay - ( r * (1 - cosBeta) * sinTheta));
+
+            // We scale z here to avoid the animation being
+            // too much bigger than the screen due to perspective transform
+
+            p.z = (r * ( 1 - cosBeta ) * cosTheta);// "100" didn't work for
+            p.x = p.z * sinf(rotateByYAxis) + p.x * cosf(rotateByYAxis);
+            p.z = p.z * cosf(rotateByYAxis) - p.x * sinf(rotateByYAxis);
+            p.z/=7;
+            //    Stop z coord from dropping beneath underlying page in a transition
+            // issue #751
+            if( p.z < 0.5f )
+            {
+                p.z = 0.5f;
+            }
+            
+            // Set new coords
+            p.x += getGridRect().origin.x;
+            setVertex(Vec2(i, j), p);
+            
+        }
+    }
+}
+
+NS_CC_END

+ 73 - 0
cocos2d/cocos/2d/CCActionPageTurn3D.h

@@ -0,0 +1,73 @@
+/****************************************************************************
+Copyright (c) 2009      Sindesso Pty Ltd http://www.sindesso.com/
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+#ifndef __ACTION_CCPAGETURN3D_ACTION_H__
+#define __ACTION_CCPAGETURN3D_ACTION_H__
+
+#include "2d/CCActionGrid3D.h"
+
+NS_CC_BEGIN
+
+/**
+ * @addtogroup actions
+ * @{
+ */
+
+/**
+ @brief This action simulates a page turn from the bottom right hand corner of the screen.
+ 
+ @details It's not much use by itself but is used by the PageTurnTransition.
+         Based on an original paper by L Hong et al.
+         http://www.parc.com/publication/1638/turning-pages-of-3d-electronic-books.html
+  
+ @since v0.8.2
+ */
+class CC_DLL PageTurn3D : public Grid3DAction
+{
+public:
+    /**
+     * @js NA 
+     */
+    virtual GridBase* getGrid() override;
+
+    /**
+    @brief Create an action with duration, grid size.
+    @param duration Specify the duration of the PageTurn3D action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @return If the creation success, return a pointer of PageTurn3D action; otherwise, return nil.
+    */
+    static PageTurn3D* create(float duration, const Size& gridSize);
+
+    // Overrides
+    virtual PageTurn3D* clone() const override;
+    virtual void update(float time) override;
+};
+
+// end of actions group
+/// @}
+
+NS_CC_END
+
+#endif // __ACTION_CCPAGETURN3D_ACTION_H__

+ 132 - 0
cocos2d/cocos/2d/CCActionProgressTimer.cpp

@@ -0,0 +1,132 @@
+/****************************************************************************
+Copyright (C) 2010      Lam Pham
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCActionProgressTimer.h"
+#include "2d/CCProgressTimer.h"
+
+NS_CC_BEGIN
+
+#define kProgressTimerCast ProgressTimer*
+
+// implementation of ProgressTo
+
+ProgressTo* ProgressTo::create(float duration, float percent)
+{
+    ProgressTo *progressTo = new (std::nothrow) ProgressTo();
+    if (progressTo && progressTo->initWithDuration(duration, percent))
+    {
+        progressTo->autorelease();
+        return progressTo;
+    }
+    
+    delete progressTo;
+    return nullptr;
+}
+
+bool ProgressTo::initWithDuration(float duration, float percent)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _to = percent;
+
+        return true;
+    }
+
+    return false;
+}
+
+ProgressTo* ProgressTo::clone() const
+{
+    // no copy constructor
+    return ProgressTo::create(_duration, _to);
+}
+
+ProgressTo* ProgressTo::reverse() const
+{
+    CCASSERT(false, "reverse() not supported in ProgressTo");
+    return nullptr;
+}
+
+void ProgressTo::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+    _from = ((kProgressTimerCast)(target))->getPercentage();
+}
+
+void ProgressTo::update(float time)
+{
+    ((kProgressTimerCast)(_target))->setPercentage(_from + (_to - _from) * time);
+}
+
+// implementation of ProgressFromTo
+
+ProgressFromTo* ProgressFromTo::create(float duration, float fromPercentage, float toPercentage)
+{
+    ProgressFromTo *progressFromTo = new (std::nothrow) ProgressFromTo();
+    if (progressFromTo && progressFromTo->initWithDuration(duration, fromPercentage, toPercentage)) {
+        progressFromTo->autorelease();
+        return progressFromTo;
+    }
+    
+    delete progressFromTo;
+    return nullptr;
+}
+
+bool ProgressFromTo::initWithDuration(float duration, float fromPercentage, float toPercentage)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _to = toPercentage;
+        _from = fromPercentage;
+
+        return true;
+    }
+
+    return false;
+}
+
+ProgressFromTo* ProgressFromTo::clone() const
+{
+    // no copy constructor
+    return ProgressFromTo::create(_duration, _from, _to);
+}
+
+
+ProgressFromTo* ProgressFromTo::reverse() const
+{
+    return ProgressFromTo::create(_duration, _to, _from);
+}
+
+void ProgressFromTo::startWithTarget(Node *target)
+{
+    ActionInterval::startWithTarget(target);
+}
+
+void ProgressFromTo::update(float time)
+{
+    ((kProgressTimerCast)(_target))->setPercentage(_from + (_to - _from) * time);
+}
+
+NS_CC_END

+ 133 - 0
cocos2d/cocos/2d/CCActionProgressTimer.h

@@ -0,0 +1,133 @@
+/****************************************************************************
+Copyright (C) 2010      Lam Pham
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+#ifndef __ACTION_CCPROGRESS_TIMER_H__
+#define __ACTION_CCPROGRESS_TIMER_H__
+
+#include "2d/CCActionInterval.h"
+
+NS_CC_BEGIN
+
+/**
+ * @addtogroup actions
+ * @{
+ */
+
+/**
+@brief Progress to percentage.
+@details This action show the target node from current percentage to the specified percentage.
+        You should specify the destination percentage when creating the action.
+@since v0.99.1
+*/
+class CC_DLL ProgressTo : public ActionInterval
+{
+public:
+    /** 
+     * @brief Create and initializes with a duration and a destination percentage.
+     * @param duration Specify the duration of the ProgressTo action. It's a value in seconds.
+     * @param percent Specify the destination percentage.
+     * @return If the creation success, return a pointer of ProgressTo action; otherwise, return nil.
+     */
+    static ProgressTo* create(float duration, float percent);
+
+    //
+    // Overrides
+    //
+    virtual ProgressTo* clone() const override;
+    virtual ProgressTo* reverse() const override;
+    virtual void startWithTarget(Node *target) override;
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    ProgressTo() {}
+    virtual ~ProgressTo() {}
+
+    /** 
+     * @brief Initializes with a duration and destination percentage. 
+     * @param duration Specify the duration of the ProgressTo action. It's a value in seconds.
+     * @param percent Specify the destination percentage.
+     * @return If the creation success, return true; otherwise, return false.
+     */
+    bool initWithDuration(float duration, float percent);
+
+protected:
+    float _to;
+    float _from;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(ProgressTo);
+};
+
+/**
+@brief Progress from a percentage to another percentage.
+@since v0.99.1
+*/
+class CC_DLL ProgressFromTo : public ActionInterval
+{
+public:
+    /** 
+     * @brief Create and initializes the action with a duration, a "from" percentage and a "to" percentage.
+     * @param duration Specify the duration of the ProgressFromTo action. It's a value in seconds.
+     * @param fromPercentage Specify the source percentage.
+     * @param toPercentage Specify the destination percentage.
+     * @return If the creation success, return a pointer of ProgressFromTo action; otherwise, return nil.
+     */
+    static ProgressFromTo* create(float duration, float fromPercentage, float toPercentage);
+
+    //
+    // Overrides
+    //
+    virtual ProgressFromTo* clone() const override;
+    virtual ProgressFromTo* reverse() const override;
+    virtual void startWithTarget(Node *target) override;
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    ProgressFromTo() {}
+    virtual ~ProgressFromTo() {}
+
+    /**
+     * @brief Initializes the action with a duration, a "from" percentage and a "to" percentage.
+     * @param duration Specify the duration of the ProgressFromTo action. It's a value in seconds.
+     * @param fromPercentage Specify the source percentage.
+     * @param toPercentage Specify the destination percentage.
+     * @return If the creation success, return true; otherwise, return false.
+     */
+    bool initWithDuration(float duration, float fromPercentage, float toPercentage);
+
+protected:
+    float _to;
+    float _from;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(ProgressFromTo);
+};
+
+// end of actions group
+/// @}
+
+NS_CC_END
+
+#endif // __ACTION_CCPROGRESS_TIMER_H__

+ 871 - 0
cocos2d/cocos/2d/CCActionTiledGrid.cpp

@@ -0,0 +1,871 @@
+/****************************************************************************
+Copyright (c) 2009      On-Core
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCActionTiledGrid.h"
+#include "2d/CCGrid.h"
+#include "2d/CCNodeGrid.h"
+#include "base/CCDirector.h"
+#include "base/ccMacros.h"
+
+NS_CC_BEGIN
+
+struct Tile
+{
+    Vec2    position;
+    Vec2    startPosition;
+    Size    delta;
+};
+
+// implementation of ShakyTiles3D
+
+ShakyTiles3D* ShakyTiles3D::create(float duration, const Size& gridSize, int range, bool shakeZ)
+{
+    ShakyTiles3D *action = new (std::nothrow) ShakyTiles3D();
+
+    if (action && action->initWithDuration(duration, gridSize, range, shakeZ))
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+bool ShakyTiles3D::initWithDuration(float duration, const Size& gridSize, int range, bool shakeZ)
+{
+    if (TiledGrid3DAction::initWithDuration(duration, gridSize))
+    {
+        _randrange = range;
+        _shakeZ = shakeZ;
+
+        return true;
+    }
+
+    return false;
+}
+
+ShakyTiles3D* ShakyTiles3D::clone() const
+{
+    // no copy constructor
+    return ShakyTiles3D::create(_duration, _gridSize, _randrange, _shakeZ);
+}
+
+void ShakyTiles3D::update(float /*time*/)
+{
+    int i, j;
+
+    for (i = 0; i < _gridSize.width; ++i)
+    {
+        for (j = 0; j < _gridSize.height; ++j)
+        {
+            Quad3 coords = getOriginalTile(Vec2(i, j));
+
+            // X
+            coords.bl.x += ( rand() % (_randrange*2) ) - _randrange;
+            coords.br.x += ( rand() % (_randrange*2) ) - _randrange;
+            coords.tl.x += ( rand() % (_randrange*2) ) - _randrange;
+            coords.tr.x += ( rand() % (_randrange*2) ) - _randrange;
+
+            // Y
+            coords.bl.y += ( rand() % (_randrange*2) ) - _randrange;
+            coords.br.y += ( rand() % (_randrange*2) ) - _randrange;
+            coords.tl.y += ( rand() % (_randrange*2) ) - _randrange;
+            coords.tr.y += ( rand() % (_randrange*2) ) - _randrange;
+
+            if (_shakeZ)
+            {
+                coords.bl.z += ( rand() % (_randrange*2) ) - _randrange;
+                coords.br.z += ( rand() % (_randrange*2) ) - _randrange;
+                coords.tl.z += ( rand() % (_randrange*2) ) - _randrange;
+                coords.tr.z += ( rand() % (_randrange*2) ) - _randrange;
+            }
+                        
+            setTile(Vec2(i, j), coords);
+        }
+    }
+}
+
+// implementation of ShatteredTiles3D
+
+ShatteredTiles3D* ShatteredTiles3D::create(float duration, const Size& gridSize, int range, bool shatterZ)
+{
+    ShatteredTiles3D *action = new (std::nothrow) ShatteredTiles3D();
+
+    if (action && action->initWithDuration(duration, gridSize, range, shatterZ))
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+bool ShatteredTiles3D::initWithDuration(float duration, const Size& gridSize, int range, bool shatterZ)
+{
+    if (TiledGrid3DAction::initWithDuration(duration, gridSize))
+    {
+        _once = false;
+        _randrange = range;
+        _shatterZ = shatterZ;
+
+        return true;
+    }
+
+    return false;
+}
+
+ShatteredTiles3D* ShatteredTiles3D::clone() const
+{
+    // no copy constructor
+    return ShatteredTiles3D::create(_duration, _gridSize, _randrange, _shatterZ);
+}
+
+void ShatteredTiles3D::update(float /*time*/)
+{
+    int i, j;
+
+    if (_once == false)
+    {
+        for (i = 0; i < _gridSize.width; ++i)
+        {
+            for (j = 0; j < _gridSize.height; ++j)
+            {
+                Quad3 coords = getOriginalTile(Vec2(i ,j));
+                
+                // X
+                coords.bl.x += ( rand() % (_randrange*2) ) - _randrange;
+                coords.br.x += ( rand() % (_randrange*2) ) - _randrange;
+                coords.tl.x += ( rand() % (_randrange*2) ) - _randrange;
+                coords.tr.x += ( rand() % (_randrange*2) ) - _randrange;
+                
+                // Y
+                coords.bl.y += ( rand() % (_randrange*2) ) - _randrange;
+                coords.br.y += ( rand() % (_randrange*2) ) - _randrange;
+                coords.tl.y += ( rand() % (_randrange*2) ) - _randrange;
+                coords.tr.y += ( rand() % (_randrange*2) ) - _randrange;
+
+                if (_shatterZ) 
+                {
+                    coords.bl.z += ( rand() % (_randrange*2) ) - _randrange;
+                    coords.br.z += ( rand() % (_randrange*2) ) - _randrange;                
+                    coords.tl.z += ( rand() % (_randrange*2) ) - _randrange;
+                    coords.tr.z += ( rand() % (_randrange*2) ) - _randrange;
+                }
+                
+                setTile(Vec2(i, j), coords);
+            }
+        }
+        
+        _once = true;
+    }
+}
+
+// implementation of ShuffleTiles
+
+ShuffleTiles* ShuffleTiles::create(float duration, const Size& gridSize, unsigned int seed)
+{
+    ShuffleTiles *action = new (std::nothrow) ShuffleTiles();
+
+    if (action && action->initWithDuration(duration, gridSize, seed))
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+bool ShuffleTiles::initWithDuration(float duration, const Size& gridSize, unsigned int seed)
+{
+    if (TiledGrid3DAction::initWithDuration(duration, gridSize))
+    {
+        _seed = seed;
+        _tilesOrder = nullptr;
+        _tiles = nullptr;
+
+        return true;
+    }
+
+    return false;
+}
+
+ShuffleTiles* ShuffleTiles::clone() const
+{
+    // no copy constructor
+    return ShuffleTiles::create(_duration, _gridSize, _seed);
+}
+
+ShuffleTiles::~ShuffleTiles()
+{
+    CC_SAFE_DELETE_ARRAY(_tilesOrder);
+    CC_SAFE_DELETE_ARRAY(_tiles);
+}
+
+void ShuffleTiles::shuffle(unsigned int *array, unsigned int len)
+{
+    for (int i = len - 1; i >= 0; i-- )
+    {
+        unsigned int j = rand() % (i+1);
+        unsigned int v = array[i];
+        array[i] = array[j];
+        array[j] = v;
+    }
+}
+
+Size ShuffleTiles::getDelta(const Size& pos) const
+{
+    Vec2    pos2;
+
+    unsigned int idx = pos.width * _gridSize.height + pos.height;
+
+    pos2.x = (float)(_tilesOrder[idx] / (int)_gridSize.height);
+    pos2.y = (float)(_tilesOrder[idx] % (int)_gridSize.height);
+
+    return Size((int)(pos2.x - pos.width), (int)(pos2.y - pos.height));
+}
+
+void ShuffleTiles::placeTile(const Vec2& pos, Tile *t)
+{
+    Quad3 coords = getOriginalTile(pos);
+
+    Vec2 step = _gridNodeTarget->getGrid()->getStep();
+    coords.bl.x += (int)(t->position.x * step.x);
+    coords.bl.y += (int)(t->position.y * step.y);
+
+    coords.br.x += (int)(t->position.x * step.x);
+    coords.br.y += (int)(t->position.y * step.y);
+
+    coords.tl.x += (int)(t->position.x * step.x);
+    coords.tl.y += (int)(t->position.y * step.y);
+
+    coords.tr.x += (int)(t->position.x * step.x);
+    coords.tr.y += (int)(t->position.y * step.y);
+
+    setTile(pos, coords);
+}
+
+void ShuffleTiles::startWithTarget(Node *target)
+{
+    TiledGrid3DAction::startWithTarget(target);
+
+    if (_seed != (unsigned int)-1)
+    {
+        std::srand(_seed);
+    }
+
+    _tilesCount = _gridSize.width * _gridSize.height;
+    _tilesOrder = new unsigned int[_tilesCount];
+
+    /**
+     * Use k to loop. Because _tilesCount is unsigned int,
+     * and i is used later for int.
+     */
+    for (unsigned int k = 0; k < _tilesCount; ++k)
+    {
+        _tilesOrder[k] = k;
+    }
+
+    shuffle(_tilesOrder, _tilesCount);
+
+    _tiles = (struct Tile *)new Tile[_tilesCount];
+    Tile *tileArray = (Tile*) _tiles;
+
+    for (int i = 0; i < _gridSize.width; ++i)
+    {
+        for ( int j = 0; j < _gridSize.height; ++j)
+        {
+            tileArray->position.set((float)i, (float)j);
+            tileArray->startPosition.set((float)i, (float)j);
+            tileArray->delta = getDelta(Size(i, j));
+            ++tileArray;
+        }
+    }
+}
+
+void ShuffleTiles::update(float time)
+{
+    Tile *tileArray = (Tile*)_tiles;
+
+    for (int i = 0; i < _gridSize.width; ++i)
+    {
+        for (int j = 0; j < _gridSize.height; ++j)
+        {
+            tileArray->position = Vec2((float)tileArray->delta.width, (float)tileArray->delta.height) * time;
+            placeTile(Vec2(i, j), tileArray);
+            ++tileArray;
+        }
+    }
+}
+
+// implementation of FadeOutTRTiles
+
+FadeOutTRTiles* FadeOutTRTiles::create(float duration, const Size& gridSize)
+{
+    FadeOutTRTiles *action = new (std::nothrow) FadeOutTRTiles();
+
+    if (action && action->initWithDuration(duration, gridSize))
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+FadeOutTRTiles* FadeOutTRTiles::clone() const
+{
+    // no copy constructor
+    return FadeOutTRTiles::create(_duration, _gridSize);
+}
+
+float FadeOutTRTiles::testFunc(const Size& pos, float time)
+{
+    Vec2 n = Vec2((float)_gridSize.width, (float)_gridSize.height) * time;
+    if ((n.x + n.y) == 0.0f)
+    {
+        return 1.0f;
+    }
+
+    return powf((pos.width + pos.height) / (n.x + n.y), 6);
+}
+
+void FadeOutTRTiles::turnOnTile(const Vec2& pos)
+{
+    setTile(pos, getOriginalTile(pos));
+}
+
+void FadeOutTRTiles::turnOffTile(const Vec2& pos)
+{
+    Quad3 coords;
+    memset(&coords, 0, sizeof(Quad3));
+    setTile(pos, coords);
+}
+
+void FadeOutTRTiles::transformTile(const Vec2& pos, float distance)
+{
+    Quad3 coords = getOriginalTile(pos);
+    Vec2 step = _gridNodeTarget->getGrid()->getStep();
+
+    coords.bl.x += (step.x / 2) * (1.0f - distance);
+    coords.bl.y += (step.y / 2) * (1.0f - distance);
+
+    coords.br.x -= (step.x / 2) * (1.0f - distance);
+    coords.br.y += (step.y / 2) * (1.0f - distance);
+
+    coords.tl.x += (step.x / 2) * (1.0f - distance);
+    coords.tl.y -= (step.y / 2) * (1.0f - distance);
+
+    coords.tr.x -= (step.x / 2) * (1.0f - distance);
+    coords.tr.y -= (step.y / 2) * (1.0f - distance);
+
+    setTile(pos, coords);
+}
+
+void FadeOutTRTiles::update(float time)
+{
+    for (int i = 0; i < _gridSize.width; ++i)
+    {
+        for (int j = 0; j < _gridSize.height; ++j)
+        {
+            float distance = testFunc(Size(i, j), time);
+            if ( distance == 0 )
+            {
+                turnOffTile(Vec2(i, j));
+            } else 
+            if (distance < 1)
+            {
+                transformTile(Vec2(i, j), distance);
+            }
+            else
+            {
+                turnOnTile(Vec2(i, j));
+            }
+        }
+    }
+}
+
+// implementation of FadeOutBLTiles
+
+FadeOutBLTiles* FadeOutBLTiles::create(float duration, const Size& gridSize)
+{
+    FadeOutBLTiles *action = new (std::nothrow) FadeOutBLTiles();
+
+    if (action && action->initWithDuration(duration, gridSize))
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+FadeOutBLTiles* FadeOutBLTiles::clone() const
+{
+    // no copy constructor
+    return FadeOutBLTiles::create(_duration, _gridSize);
+}
+
+float FadeOutBLTiles::testFunc(const Size& pos, float time)
+{
+    Vec2 n = Vec2((float)_gridSize.width, (float)_gridSize.height) * (1.0f - time);
+    if ((pos.width + pos.height) == 0)
+    {
+        return 1.0f;
+    }
+
+    return powf((n.x + n.y) / (pos.width + pos.height), 6);
+}
+
+// implementation of FadeOutUpTiles
+
+FadeOutUpTiles* FadeOutUpTiles::create(float duration, const Size& gridSize)
+{
+    FadeOutUpTiles *action = new (std::nothrow) FadeOutUpTiles();
+
+    if (action && action->initWithDuration(duration, gridSize))
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+FadeOutUpTiles* FadeOutUpTiles::clone() const
+{
+    // no copy constructor
+    return FadeOutUpTiles::create(_duration, _gridSize);
+}
+
+float FadeOutUpTiles::testFunc(const Size& pos, float time)
+{
+    Vec2 n = Vec2((float)_gridSize.width, (float)_gridSize.height) * time;
+    if (n.y == 0.0f)
+    {
+        return 1.0f;
+    }
+
+    return powf(pos.height / n.y, 6);
+}
+
+void FadeOutUpTiles::transformTile(const Vec2& pos, float distance)
+{
+    Quad3 coords = getOriginalTile(pos);
+    Vec2 step = _gridNodeTarget->getGrid()->getStep();
+
+    coords.bl.y += (step.y / 2) * (1.0f - distance);
+    coords.br.y += (step.y / 2) * (1.0f - distance);
+    coords.tl.y -= (step.y / 2) * (1.0f - distance);
+    coords.tr.y -= (step.y / 2) * (1.0f - distance);
+
+    setTile(pos, coords);
+}
+
+// implementation of FadeOutDownTiles
+
+FadeOutDownTiles* FadeOutDownTiles::create(float duration, const Size& gridSize)
+{
+    FadeOutDownTiles *action = new (std::nothrow) FadeOutDownTiles();
+
+    if (action && action->initWithDuration(duration, gridSize))
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+FadeOutDownTiles* FadeOutDownTiles::clone() const
+{
+    // no copy constructor
+    return FadeOutDownTiles::create(_duration, _gridSize);
+}
+
+float FadeOutDownTiles::testFunc(const Size& pos, float time)
+{
+    Vec2 n = Vec2((float)_gridSize.width, (float)_gridSize.height) * (1.0f - time);
+    return powf(n.y / (pos.height > 0.0f ? pos.height : 0.1f), 6);
+}
+
+// implementation of TurnOffTiles
+
+TurnOffTiles* TurnOffTiles::create(float duration, const Size& gridSize)
+{
+    TurnOffTiles* action = new (std::nothrow) TurnOffTiles();
+    if (action && action->initWithDuration(duration, gridSize, 0))
+    {
+        action->autorelease();
+        return action;
+    }
+    
+    delete action;
+    return nullptr;
+}
+
+TurnOffTiles* TurnOffTiles::create(float duration, const Size& gridSize, unsigned int seed)
+{
+    TurnOffTiles *action = new (std::nothrow) TurnOffTiles();
+
+    if (action && action->initWithDuration(duration, gridSize, seed))
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+bool TurnOffTiles::initWithDuration(float duration, const Size& gridSize, unsigned int seed)
+{
+    if (TiledGrid3DAction::initWithDuration(duration, gridSize))
+    {
+        _seed = seed;
+        _tilesOrder = nullptr;
+
+        return true;
+    }
+
+    return false;
+}
+
+TurnOffTiles* TurnOffTiles::clone() const
+{
+    // no copy constructor
+    return TurnOffTiles::create(_duration, _gridSize, _seed);
+}
+
+TurnOffTiles::~TurnOffTiles(void)
+{
+    CC_SAFE_DELETE_ARRAY(_tilesOrder);
+}
+
+void TurnOffTiles::shuffle(unsigned int *array, unsigned int len)
+{
+    for (int i = len - 1; i >= 0; i--)
+    {
+        unsigned int j = rand() % (i+1);
+        unsigned int v = array[i];
+        array[i] = array[j];
+        array[j] = v;
+    }
+}
+
+void TurnOffTiles::turnOnTile(const Vec2& pos)
+{
+    setTile(pos, getOriginalTile(pos));
+}
+
+void TurnOffTiles::turnOffTile(const Vec2& pos)
+{
+    Quad3 coords;
+
+    memset(&coords, 0, sizeof(Quad3));
+    setTile(pos, coords);
+}
+
+void TurnOffTiles::startWithTarget(Node *target)
+{
+    TiledGrid3DAction::startWithTarget(target);
+
+    if (_seed != (unsigned int)-1)
+    {
+        std::srand(_seed);
+    }
+
+    _tilesCount = _gridSize.width * _gridSize.height;
+    _tilesOrder = new unsigned int[_tilesCount];
+
+    for (unsigned int i = 0; i < _tilesCount; ++i)
+    {
+        _tilesOrder[i] = i;
+    }
+
+    shuffle(_tilesOrder, _tilesCount);
+}
+
+void TurnOffTiles::update(float time)
+{
+    unsigned int l = (unsigned int)(time * (float)_tilesCount);
+
+    unsigned int t = 0;
+    for (unsigned int i = 0; i < _tilesCount; i++ )
+    {
+        t = _tilesOrder[i];
+        Vec2 tilePos( (unsigned int)(t / _gridSize.height), t % (unsigned int)_gridSize.height );
+
+        if ( i < l )
+        {
+            turnOffTile(tilePos);
+        }
+        else
+        {
+            turnOnTile(tilePos);
+        }
+    }
+}
+
+// implementation of WavesTiles3D
+
+WavesTiles3D* WavesTiles3D::create(float duration, const Size& gridSize, unsigned int waves, float amplitude)
+{
+    WavesTiles3D *action = new (std::nothrow) WavesTiles3D();
+
+    if (action && action->initWithDuration(duration, gridSize, waves, amplitude))
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+bool WavesTiles3D::initWithDuration(float duration, const Size& gridSize, unsigned int waves, float amplitude)
+{
+    if (TiledGrid3DAction::initWithDuration(duration, gridSize))
+    {
+        _waves = waves;
+        _amplitude = amplitude;
+        _amplitudeRate = 1.0f;
+
+        return true;
+    }
+
+    return false;
+}
+
+WavesTiles3D* WavesTiles3D::clone() const
+{
+    // no copy constructor
+    return WavesTiles3D::create(_duration, _gridSize, _waves, _amplitude);
+}
+
+void WavesTiles3D::update(float time)
+{
+    for (int i = 0; i < _gridSize.width; i++ )
+    {
+        for (int j = 0; j < _gridSize.height; j++ )
+        {
+            Quad3 coords = getOriginalTile(Vec2(i, j));
+
+            coords.bl.z = (sinf(time * (float)M_PI  *_waves * 2 + 
+                (coords.bl.y+coords.bl.x) * .01f) * _amplitude * _amplitudeRate );
+            coords.br.z    = coords.bl.z;
+            coords.tl.z = coords.bl.z;
+            coords.tr.z = coords.bl.z;
+
+            setTile(Vec2(i, j), coords);
+        }
+    }
+}
+
+// implementation of JumpTiles3D
+
+JumpTiles3D* JumpTiles3D::create(float duration, const Size& gridSize, unsigned int numberOfJumps, float amplitude)
+{
+    JumpTiles3D *action = new (std::nothrow) JumpTiles3D();
+
+    if (action && action->initWithDuration(duration, gridSize, numberOfJumps, amplitude))
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+bool JumpTiles3D::initWithDuration(float duration, const Size& gridSize, unsigned int numberOfJumps, float amplitude)
+{
+    if (TiledGrid3DAction::initWithDuration(duration, gridSize))
+    {
+        _jumps = numberOfJumps;
+        _amplitude = amplitude;
+        _amplitudeRate = 1.0f;
+
+        return true;
+    }
+
+    return false;
+}
+
+JumpTiles3D* JumpTiles3D::clone() const
+{
+    // no copy constructor
+    return JumpTiles3D::create(_duration, _gridSize, _jumps, _amplitude);
+}
+
+void JumpTiles3D::update(float time)
+{
+    float sinz =  (sinf((float)M_PI * time * _jumps * 2) * _amplitude * _amplitudeRate );
+    float sinz2 = (sinf((float)M_PI * (time * _jumps * 2 + 1)) * _amplitude * _amplitudeRate );
+
+    for (int i = 0; i < _gridSize.width; i++ )
+    {
+        for (int j = 0; j < _gridSize.height; j++ )
+        {
+            Quad3 coords = getOriginalTile(Vec2(i, j));
+
+            if ( ((i+j) % 2) == 0 )
+            {
+                coords.bl.z += sinz;
+                coords.br.z += sinz;
+                coords.tl.z += sinz;
+                coords.tr.z += sinz;
+            }
+            else
+            {
+                coords.bl.z += sinz2;
+                coords.br.z += sinz2;
+                coords.tl.z += sinz2;
+                coords.tr.z += sinz2;
+            }
+
+            setTile(Vec2(i, j), coords);
+        }
+    }
+}
+
+// implementation of SplitRows
+
+SplitRows* SplitRows::create(float duration, unsigned int nRows)
+{
+    SplitRows *action = new (std::nothrow) SplitRows();
+
+    if (action && action->initWithDuration(duration, nRows))
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+bool SplitRows::initWithDuration(float duration, unsigned int rows)
+{
+    _rows = rows;
+
+    return TiledGrid3DAction::initWithDuration(duration, Size(1, rows));
+}
+
+SplitRows* SplitRows::clone() const
+{
+    // no copy constructor
+    return SplitRows::create(_duration, _rows);
+}
+
+void SplitRows::startWithTarget(Node *target)
+{
+    TiledGrid3DAction::startWithTarget(target);
+    _winSize = Director::getInstance()->getWinSizeInPixels();
+}
+
+void SplitRows::update(float time)
+{
+    for (unsigned int j = 0; j < _gridSize.height; ++j)
+    {
+        Quad3 coords = getOriginalTile(Vec2(0, j));
+        float    direction = 1;
+
+        if ( (j % 2 ) == 0 )
+        {
+            direction = -1;
+        }
+
+        coords.bl.x += direction * _winSize.width * time;
+        coords.br.x += direction * _winSize.width * time;
+        coords.tl.x += direction * _winSize.width * time;
+        coords.tr.x += direction * _winSize.width * time;
+
+        setTile(Vec2(0, j), coords);
+    }
+}
+
+// implementation of SplitCols
+
+SplitCols* SplitCols::create(float duration, unsigned int cols)
+{
+    SplitCols *action = new (std::nothrow) SplitCols();
+
+    if (action && action->initWithDuration(duration, cols))
+    {
+        action->autorelease();
+        return action;
+    }
+
+    delete action;
+    return nullptr;
+}
+
+bool SplitCols::initWithDuration(float duration, unsigned int cols)
+{
+    _cols = cols;
+    return TiledGrid3DAction::initWithDuration(duration, Size(cols, 1));
+}
+
+SplitCols* SplitCols::clone() const
+{
+    // no copy constructor
+    return SplitCols::create(_duration, _cols);
+}
+
+void SplitCols::startWithTarget(Node *target)
+{
+    TiledGrid3DAction::startWithTarget(target);
+    _winSize = Director::getInstance()->getWinSizeInPixels();
+}
+
+void SplitCols::update(float time)
+{
+    for (unsigned int i = 0; i < _gridSize.width; ++i)
+    {
+        Quad3 coords = getOriginalTile(Vec2(i, 0));
+        float    direction = 1;
+
+        if ( (i % 2 ) == 0 )
+        {
+            direction = -1;
+        }
+
+        coords.bl.y += direction * _winSize.height * time;
+        coords.br.y += direction * _winSize.height * time;
+        coords.tl.y += direction * _winSize.height * time;
+        coords.tr.y += direction * _winSize.height * time;
+
+        setTile(Vec2(i, 0), coords);
+    }
+}
+
+NS_CC_END

+ 609 - 0
cocos2d/cocos/2d/CCActionTiledGrid.h

@@ -0,0 +1,609 @@
+/****************************************************************************
+Copyright (c) 2009      On-Core
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+#ifndef __ACTION_CCTILEDGRID_ACTION_H__
+#define __ACTION_CCTILEDGRID_ACTION_H__
+
+#include "2d/CCActionGrid.h"
+
+NS_CC_BEGIN
+
+/**
+ * @addtogroup actions
+ * @{
+ */
+
+/**
+@brief ShakyTiles3D action.
+@details This action is make the target node shake with many tiles.
+        You can create the action by these parameters:
+        duration, grid size, range, whether shake on the z axis.
+ */
+class CC_DLL ShakyTiles3D : public TiledGrid3DAction
+{
+public:
+    /** 
+    @brief Create the action with a range, shake Z vertices, a grid and duration.
+    @param duration Specify the duration of the ShakyTiles3D action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param range Specify the range of the shaky effect.
+    @param shakeZ Specify whether shake on the z axis.
+    @return If the creation success, return a pointer of ShakyTiles3D action; otherwise, return nil.
+    */
+    static ShakyTiles3D* create(float duration, const Size& gridSize, int range, bool shakeZ);
+
+    // Override
+    virtual ShakyTiles3D* clone() const override;
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    ShakyTiles3D() {}
+    virtual ~ShakyTiles3D() {}
+
+    /** 
+    @brief Initializes the action with a range, shake Z vertices, grid size and duration.
+    @param duration Specify the duration of the ShakyTiles3D action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param range Specify the range of the shaky effect.
+    @param shakeZ Specify whether shake on the z axis.
+    @return If the Initialization success, return true; otherwise, return false.
+    */
+    bool initWithDuration(float duration, const Size& gridSize, int range, bool shakeZ);
+
+protected:
+    int _randrange;
+    bool _shakeZ;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(ShakyTiles3D);
+};
+
+/**
+@brief ShatteredTiles3D action.
+@details This action make the target node shattered with many tiles.
+        You can create the action by these parameters:
+        duration, grid size, range, whether shatter on the z axis.
+*/
+class CC_DLL ShatteredTiles3D : public TiledGrid3DAction
+{
+public:
+    /** 
+     * @brief Create the action with a range, whether of not to shatter Z vertices, grid size and duration.
+     * @param duration Specify the duration of the ShatteredTiles3D action. It's a value in seconds.
+     * @param gridSize Specify the size of the grid.
+     * @param range Specify the range of the shatter effect.
+     * @param shatterZ Specify whether shatter on the z axis.
+     * @return If the creation success, return a pointer of ShatteredTiles3D action; otherwise, return nil.
+     */
+    static ShatteredTiles3D* create(float duration, const Size& gridSize, int range, bool shatterZ);
+
+    // Override
+    virtual ShatteredTiles3D* clone() const override;
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    ShatteredTiles3D() {}
+    virtual ~ShatteredTiles3D() {}
+
+    /** 
+    @brief Initializes the action with a range, shatter Z vertices, grid size and duration.
+    @param duration Specify the duration of the ShatteredTiles3D action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param range Specify the range of the shatter effect.
+    @param shatterZ Specify whether shake on the z axis.
+    @return If the Initialization success, return true; otherwise, return false.
+    */
+    bool initWithDuration(float duration, const Size& gridSize, int range, bool shatterZ);
+
+protected:
+    int _randrange;
+    bool _once;
+    bool _shatterZ;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(ShatteredTiles3D);
+};
+
+struct Tile;
+/**
+@brief ShuffleTiles action.
+@details This action make the target node shuffle with many tiles in random order.
+        You can create the action by these parameters:
+        duration, grid size, the random seed.
+*/
+class CC_DLL ShuffleTiles : public TiledGrid3DAction
+{
+public:
+    /** 
+    * @brief Create the action with grid size, random seed and duration.
+    * @param duration Specify the duration of the ShuffleTiles action. It's a value in seconds.
+    * @param gridSize Specify the size of the grid.
+    * @param seed Specify the random seed.
+    * @return If the creation success, return a pointer of ShuffleTiles action; otherwise, return nil.
+    */
+    static ShuffleTiles* create(float duration, const Size& gridSize, unsigned int seed);
+
+    void shuffle(unsigned int *array, unsigned int len);
+    Size getDelta(const Size& pos) const;
+    void placeTile(const Vec2& pos, Tile *t);
+
+    // Overrides
+    virtual void startWithTarget(Node *target) override;
+    virtual void update(float time) override;
+    virtual ShuffleTiles* clone() const override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    ShuffleTiles() {}
+    virtual ~ShuffleTiles();
+
+    /** 
+    * @brief Initializes the action with grid size, random seed and duration.
+    * @param duration Specify the duration of the ShuffleTiles action. It's a value in seconds.
+    * @param gridSize Specify the size of the grid.
+    * @param seed Specify the random seed.
+    * @return If the Initialization success, return true; otherwise, return false.
+    */
+    bool initWithDuration(float duration, const Size& gridSize, unsigned int seed);
+
+protected:
+    unsigned int _seed;
+    unsigned int _tilesCount;
+    unsigned int* _tilesOrder;
+    Tile* _tiles;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(ShuffleTiles);
+};
+
+/**
+@brief FadeOutTRTiles action.
+@details Fades out the target node with many tiles from Bottom-Left to Top-Right.
+ */
+class CC_DLL FadeOutTRTiles : public TiledGrid3DAction
+{
+public:
+    /** 
+    * @brief Create the action with the grid size and the duration.
+    * @param duration Specify the duration of the FadeOutTRTiles action. It's a value in seconds.
+    * @param gridSize Specify the size of the grid.
+    * @return If the creation success, return a pointer of FadeOutTRTiles action; otherwise, return nil.
+    */
+    static FadeOutTRTiles* create(float duration, const Size& gridSize);
+
+    /**
+    @brief Calculate the percentage a tile should be shown.
+    @param pos The position index of the tile.
+    @param time The current percentage of the action.
+    @return Return the percentage the tile should be shown.
+    */
+    virtual float testFunc(const Size& pos, float time);
+
+    /**
+    @brief Show the tile at specified position.
+    @param pos The position index of the tile should be shown.
+    */
+    void turnOnTile(const Vec2& pos);
+
+    /**
+    @brief Hide the tile at specified position.
+    @param pos The position index of the tile should be hide.
+    */
+    void turnOffTile(const Vec2& pos);
+
+    /**
+    @brief Show part of the tile.
+    @param pos The position index of the tile should be shown.
+    @param distance The percentage that the tile should be shown.
+    */
+    virtual void transformTile(const Vec2& pos, float distance);
+
+    // Overrides
+    virtual void update(float time) override;
+    virtual FadeOutTRTiles* clone() const override;
+
+CC_CONSTRUCTOR_ACCESS:
+    FadeOutTRTiles() {}
+    virtual ~FadeOutTRTiles() {}
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(FadeOutTRTiles);
+};
+
+/**
+@brief FadeOutBLTiles action.
+@details Fades out the target node with many tiles from Top-Right to Bottom-Left.
+ */
+class CC_DLL FadeOutBLTiles : public FadeOutTRTiles
+{
+public:
+    /** 
+    * @brief Create the action with the grid size and the duration.
+    * @param duration Specify the duration of the FadeOutBLTiles action. It's a value in seconds.
+    * @param gridSize Specify the size of the grid.
+    * @return If the creation success, return a pointer of FadeOutBLTiles action; otherwise, return nil.
+    */
+    static FadeOutBLTiles* create(float duration, const Size& gridSize);
+
+    // Overrides
+    virtual float testFunc(const Size& pos, float time) override;
+    virtual FadeOutBLTiles* clone() const override;
+
+CC_CONSTRUCTOR_ACCESS:
+    FadeOutBLTiles() {}
+    virtual ~FadeOutBLTiles() {}
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(FadeOutBLTiles);
+};
+
+/**
+@brief FadeOutUpTiles action.
+@details Fades out the target node with many tiles from bottom to top.
+ */
+class CC_DLL FadeOutUpTiles : public FadeOutTRTiles
+{
+public:
+    /** 
+    * @brief Create the action with the grid size and the duration.
+    * @param duration Specify the duration of the FadeOutUpTiles action. It's a value in seconds.
+    * @param gridSize Specify the size of the grid.
+    * @return If the creation success, return a pointer of FadeOutUpTiles action; otherwise, return nil.
+    */
+    static FadeOutUpTiles* create(float duration, const Size& gridSize);
+
+    virtual void transformTile(const Vec2& pos, float distance) override;
+
+    // Overrides
+    virtual FadeOutUpTiles* clone() const override;
+    virtual float testFunc(const Size& pos, float time) override;
+
+CC_CONSTRUCTOR_ACCESS:
+    FadeOutUpTiles() {}
+    virtual ~FadeOutUpTiles() {}
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(FadeOutUpTiles);
+};
+
+/**
+@brief FadeOutDownTiles action.
+@details Fades out the target node with many tiles from top to bottom.
+ */
+class CC_DLL FadeOutDownTiles : public FadeOutUpTiles
+{
+public:
+    /** 
+    * @brief Create the action with the grid size and the duration.
+    * @param duration Specify the duration of the FadeOutDownTiles action. It's a value in seconds.
+    * @param gridSize Specify the size of the grid.
+    * @return If the creation success, return a pointer of FadeOutDownTiles action; otherwise, return nil.
+    */
+    static FadeOutDownTiles* create(float duration, const Size& gridSize);
+
+    // Overrides
+    virtual FadeOutDownTiles* clone() const override;
+    virtual float testFunc(const Size& pos, float time) override;
+
+CC_CONSTRUCTOR_ACCESS:
+    FadeOutDownTiles() {}
+    virtual ~FadeOutDownTiles() {}
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(FadeOutDownTiles);
+};
+
+/**
+@brief TurnOffTiles action.
+@details Turn off the target node with many tiles in random order.
+ */
+class CC_DLL TurnOffTiles : public TiledGrid3DAction
+{
+public:
+    /** 
+    * @brief Create the action with the grid size and the duration.
+    * @param duration Specify the duration of the TurnOffTiles action. It's a value in seconds.
+    * @param gridSize Specify the size of the grid.
+    * @return If the creation success, return a pointer of TurnOffTiles action; otherwise, return nil.
+    */
+    static TurnOffTiles* create(float duration, const Size& gridSize);
+    /** 
+    * @brief Create the action with the grid size and the duration.
+    * @param duration Specify the duration of the TurnOffTiles action. It's a value in seconds.
+    * @param gridSize Specify the size of the grid.
+    * @param seed Specify the random seed.
+    * @return If the creation success, return a pointer of TurnOffTiles action; otherwise, return nil.
+    */
+    static TurnOffTiles* create(float duration, const Size& gridSize, unsigned int seed);
+
+    /**
+    @brief Shuffle the array specified.
+    @param array The array will be shuffled.
+    @param len The size of the array.
+    */
+    void shuffle(unsigned int *array, unsigned int len);
+
+    /**
+    @brief Show the tile at specified position.
+    @param pos The position index of the tile should be shown.
+    */
+    void turnOnTile(const Vec2& pos);
+
+    /**
+    @brief Hide the tile at specified position.
+    @param pos The position index of the tile should be hide.
+    */
+    void turnOffTile(const Vec2& pos);
+
+    // Overrides
+	virtual TurnOffTiles* clone() const override;
+    virtual void startWithTarget(Node *target) override;
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    TurnOffTiles() {}
+    virtual ~TurnOffTiles();
+
+    /** 
+    * @brief Initializes the action with grid size, random seed and duration.
+    * @param duration Specify the duration of the TurnOffTiles action. It's a value in seconds.
+    * @param gridSize Specify the size of the grid.
+    * @param seed Specify the random seed.
+    * @return If the Initialization success, return true; otherwise, return false.
+    */
+    bool initWithDuration(float duration, const Size& gridSize, unsigned int seed);
+
+protected:
+    unsigned int    _seed;
+    unsigned int    _tilesCount;
+    unsigned int*   _tilesOrder;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(TurnOffTiles);
+};
+
+/**
+@brief WavesTiles3D action.
+@details This action wave the target node with many tiles.
+*/
+class CC_DLL WavesTiles3D : public TiledGrid3DAction
+{
+public:
+    /** 
+     * @brief Create the action with a number of waves, the waves amplitude, the grid size and the duration.
+     * @param duration Specify the duration of the WavesTiles3D action. It's a value in seconds.
+     * @param gridSize Specify the size of the grid.
+     * @param waves Specify the waves count of the WavesTiles3D action.
+     * @param amplitude Specify the amplitude of the WavesTiles3D action.
+     * @return If the creation success, return a pointer of WavesTiles3D action; otherwise, return nil.
+     */
+    static WavesTiles3D* create(float duration, const Size& gridSize, unsigned int waves, float amplitude);
+
+    /**
+    @brief Get the amplitude of the effect.
+    @return Return the amplitude of the effect.
+    */
+    float getAmplitude() const { return _amplitude; }
+    /**
+    @brief Set the amplitude to the effect.
+    @param amplitude The value of amplitude will be set.
+    */
+    void setAmplitude(float amplitude) { _amplitude = amplitude; }
+
+    /**
+    @brief Get the amplitude rate of the effect.
+    @return Return the amplitude rate of the effect.
+    */
+    float getAmplitudeRate() const { return _amplitudeRate; }
+    /**
+    @brief Set the amplitude rate of the effect.
+    @param amplitudeRate The value of amplitude rate will be set.
+    */
+    void setAmplitudeRate(float amplitudeRate) { _amplitudeRate = amplitudeRate; }
+
+    // Override
+    virtual WavesTiles3D* clone() const override;
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    WavesTiles3D() {}
+    virtual ~WavesTiles3D() {}
+
+    /** 
+    @brief Initializes an action with duration, grid size, waves count and amplitude.
+    @param duration Specify the duration of the WavesTiles3D action. It's a value in seconds.
+    @param gridSize Specify the size of the grid.
+    @param waves Specify the waves count of the WavesTiles3D action.
+    @param amplitude Specify the amplitude of the WavesTiles3D action.
+    @return If the initialization success, return true; otherwise, return false.
+    */
+    bool initWithDuration(float duration, const Size& gridSize, unsigned int waves, float amplitude);
+
+protected:
+    unsigned int _waves;
+    float _amplitude;
+    float _amplitudeRate;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(WavesTiles3D);
+};
+
+/**
+@brief JumpTiles3D action.
+@details Move the tiles of a target node across the Z axis.
+*/
+class CC_DLL JumpTiles3D : public TiledGrid3DAction
+{
+public:
+    /** 
+     * @brief Create the action with the number of jumps, the sin amplitude, the grid size and the duration.
+     * @param duration Specify the duration of the JumpTiles3D action. It's a value in seconds.
+     * @param gridSize Specify the size of the grid.
+     * @param numberOfJumps Specify the jump tiles count.
+     * @param amplitude Specify the amplitude of the JumpTiles3D action.
+     * @return If the creation success, return a pointer of JumpTiles3D action; otherwise, return nil.
+     */
+    static JumpTiles3D* create(float duration, const Size& gridSize, unsigned int numberOfJumps, float amplitude);
+
+    /**
+    @brief Get the amplitude of the effect.
+    @return Return the amplitude of the effect.
+    */
+    float getAmplitude() const { return _amplitude; }
+    /**
+    @brief Set the amplitude to the effect.
+    @param amplitude The value of amplitude will be set.
+    */
+    void setAmplitude(float amplitude) { _amplitude = amplitude; }
+
+    /**
+    @brief Get the amplitude rate of the effect.
+    @return Return the amplitude rate of the effect.
+    */
+    float getAmplitudeRate() const { return _amplitudeRate; }
+    /**
+    @brief Set the amplitude rate of the effect.
+    @param amplitudeRate The value of amplitude rate will be set.
+    */
+    void setAmplitudeRate(float amplitudeRate) { _amplitudeRate = amplitudeRate; }
+
+    // Override
+    virtual JumpTiles3D* clone() const override;
+    virtual void update(float time) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    JumpTiles3D() {}
+    virtual ~JumpTiles3D() {}
+
+    /** 
+     * @brief Initializes the action with the number of jumps, the sin amplitude, the grid size and the duration.
+     * @param duration Specify the duration of the JumpTiles3D action. It's a value in seconds.
+     * @param gridSize Specify the size of the grid.
+     * @param numberOfJumps Specify the jump tiles count.
+     * @param amplitude Specify the amplitude of the JumpTiles3D action.
+     * @return If the initialization success, return true; otherwise, return false.
+     */
+    bool initWithDuration(float duration, const Size& gridSize, unsigned int numberOfJumps, float amplitude);
+
+protected:
+    unsigned int _jumps;
+    float _amplitude;
+    float _amplitudeRate;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(JumpTiles3D);
+};
+
+/**
+@brief SplitRows action.
+@details Split the target node in many rows.
+        Then move out some rows from left, move out the other rows from right.
+*/
+class CC_DLL SplitRows : public TiledGrid3DAction
+{
+public :
+    /** 
+     * @brief Create the action with the number of rows and the duration.
+     * @param duration Specify the duration of the SplitRows action. It's a value in seconds.
+     * @param rows Specify the rows count should be split.
+     * @return If the creation success, return a pointer of SplitRows action; otherwise, return nil.
+     */
+    static SplitRows* create(float duration, unsigned int rows);
+
+    // Overrides
+    virtual SplitRows* clone() const override;
+    virtual void update(float time) override;
+    virtual void startWithTarget(Node *target) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    SplitRows() {}
+    virtual ~SplitRows() {}
+
+    /** 
+     * @brief Initializes the action with the number rows and the duration.
+     * @param duration Specify the duration of the SplitRows action. It's a value in seconds.
+     * @param rows Specify the rows count should be split.
+     * @return If the creation success, return true; otherwise, return false.
+     */
+    bool initWithDuration(float duration, unsigned int rows);
+
+protected:
+    unsigned int _rows;
+    Size _winSize;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(SplitRows);
+};
+
+/**
+@brief SplitCols action.
+@details Split the target node in many columns.
+        Then move out some columns from top, move out the other columns from bottom.
+*/
+class CC_DLL SplitCols : public TiledGrid3DAction
+{
+public:
+    
+    /** 
+     * @brief Create the action with the number of columns and the duration.
+     * @param duration Specify the duration of the SplitCols action. It's a value in seconds.
+     * @param cols Specify the columns count should be split.
+     * @return If the creation success, return a pointer of SplitCols action; otherwise, return nil.
+     */
+    static SplitCols* create(float duration, unsigned int cols);
+
+    // Overrides
+    virtual SplitCols* clone() const override;
+    /**
+     * @param time in seconds
+     */
+    virtual void update(float time) override;
+    virtual void startWithTarget(Node *target) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    SplitCols() {}
+    virtual ~SplitCols() {}
+
+    /** 
+     * @brief Initializes the action with the number columns and the duration.
+     * @param duration Specify the duration of the SplitCols action. It's a value in seconds.
+     * @param cols Specify the columns count should be split.
+     * @return If the creation success, return true; otherwise, return false.
+     */
+    bool initWithDuration(float duration, unsigned int cols);
+
+protected:
+    unsigned int _cols;
+    Size _winSize;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(SplitCols);
+};
+
+// end of actions group
+/// @}
+
+NS_CC_END
+
+#endif // __ACTION_CCTILEDGRID_ACTION_H__

+ 80 - 0
cocos2d/cocos/2d/CCActionTween.cpp

@@ -0,0 +1,80 @@
+/****************************************************************************
+Copyright (c) 2009      lhunath (Maarten Billemont)
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCActionTween.h"
+
+NS_CC_BEGIN
+
+ActionTween* ActionTween::create(float duration, const std::string& key, float from, float to)
+{
+    ActionTween* ret = new (std::nothrow) ActionTween();
+    if (ret && ret->initWithDuration(duration, key, from, to))
+    {
+        ret->autorelease();
+        return ret;
+    }
+    
+    delete ret;
+    return nullptr;
+}
+
+bool ActionTween::initWithDuration(float duration, const std::string& key, float from, float to)
+{
+    if (ActionInterval::initWithDuration(duration))
+    {
+        _key    = key;
+        _to       = to;
+        _from     = from;
+        return true;
+    }
+
+    return false;
+}
+
+ActionTween *ActionTween::clone() const
+{
+    return ActionTween::create(_duration, _key, _from, _to);
+}
+
+void ActionTween::startWithTarget(Node *target)
+{
+    CCASSERT(dynamic_cast<ActionTweenDelegate*>(target), "target must implement ActionTweenDelegate");
+    ActionInterval::startWithTarget(target);
+    _delta = _to - _from;
+}
+
+void ActionTween::update(float dt)
+{
+    dynamic_cast<ActionTweenDelegate*>(_target)->updateTweenAction(_to  - _delta * (1 - dt), _key);
+}
+
+ActionTween* ActionTween::reverse() const
+{
+    return ActionTween::create(_duration, _key, _to, _from);
+}
+
+
+NS_CC_END

+ 127 - 0
cocos2d/cocos/2d/CCActionTween.h

@@ -0,0 +1,127 @@
+/****************************************************************************
+Copyright (c) 2009      lhunath (Maarten Billemont)
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+#ifndef __CCACTIONTWEEN_H__
+#define __CCACTIONTWEEN_H__
+
+#include "2d/CCActionInterval.h"
+
+NS_CC_BEGIN
+
+/**
+ * @addtogroup actions
+ * @{
+ */
+
+/**
+@brief The delegate class for ActionTween.
+@details If you want to use ActionTween on a node.
+        You should implement the node follow these steps:
+        1. The node should be inherit from ActionTweenDelegate.
+        2. Override the virtual method updateTweenAction in the node.
+
+        Then once you running ActionTween on the node, the method updateTweenAction will be invoked.
+*/
+class CC_DLL ActionTweenDelegate
+{
+public:
+    /**
+     * @js NA
+     * @lua NA
+     */
+    virtual ~ActionTweenDelegate() {}
+
+    /**
+    @brief The callback function when ActionTween is running.
+    @param value The new value of the specified key.
+    @param key The key of property which should be updated.
+    */
+    virtual void updateTweenAction(float value, const std::string& key) = 0;
+};
+
+/** ActionTween
+
+ ActionTween is an action that lets you update any property of an object.
+ For example, if you want to modify the "width" property of a target from 200 to 300 in 2 seconds, then:
+
+ @code
+     auto modifyWidth = ActionTween::create(2, "width", 200, 300);
+     target->runAction(modifyWidth);
+ @endcode
+
+ Another example: ScaleTo action could be rewritten using PropertyAction:
+
+ @code
+     // scaleA and scaleB are equivalents
+     auto scaleA = ScaleTo::create(2, 3);                 // (duration, to)
+     auto scaleB = ActionTween::create(2, "scale", 1, 3); // (duration, key, from, to)
+ @endcode
+
+ @since v0.99.2
+ */
+class CC_DLL ActionTween : public ActionInterval
+{
+public:
+    /** 
+     * @brief Create and initializes the action with the property name (key), and the from and to parameters.
+     * @param duration The duration of the ActionTween. It's a value in seconds.
+     * @param key The key of property which should be updated.
+     * @param from The value of the specified property when the action begin.
+     * @param to The value of the specified property when the action end.
+     * @return If the creation success, return a pointer of ActionTween; otherwise, return nil.
+     */
+    static ActionTween* create(float duration, const std::string& key, float from, float to);
+
+    // Overrides
+    void startWithTarget(Node *target) override;
+    void update(float dt) override;
+    ActionTween* reverse() const override;
+    ActionTween *clone() const override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    /** 
+     * @brief Initializes the action with the property name (key), and the from and to parameters.
+     * @param duration The duration of the ActionTween. It's a value in seconds.
+     * @param key The key of property which should be updated.
+     * @param from The value of the specified property when the action begin.
+     * @param to The value of the specified property when the action end.
+     * @return If the initialization success, return true; otherwise, return false.
+     */
+    bool initWithDuration(float duration, const std::string& key, float from, float to);
+
+protected:
+    std::string       _key;
+    float            _from, _to;
+    float            _delta;
+};
+
+// end of actions group
+/// @}
+
+NS_CC_END
+
+#endif /* __CCACTIONTWEEN_H__ */
+
+

+ 202 - 0
cocos2d/cocos/2d/CCAnimation.cpp

@@ -0,0 +1,202 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCAnimation.h"
+#include "renderer/CCTextureCache.h"
+#include "renderer/CCTexture2D.h"
+#include "base/CCDirector.h"
+
+NS_CC_BEGIN
+
+AnimationFrame* AnimationFrame::create(SpriteFrame* spriteFrame, float delayUnits, const ValueMap& userInfo)
+{
+    auto ret = new (std::nothrow) AnimationFrame();
+    if (ret && ret->initWithSpriteFrame(spriteFrame, delayUnits, userInfo))
+    {
+        ret->autorelease();
+    }
+    else
+    {
+        CC_SAFE_DELETE(ret);
+    }
+    return ret;
+}
+
+AnimationFrame::AnimationFrame()
+: _spriteFrame(nullptr)
+, _delayUnits(0.0f)
+{
+
+}
+
+bool AnimationFrame::initWithSpriteFrame(SpriteFrame* spriteFrame, float delayUnits, const ValueMap& userInfo)
+{
+    setSpriteFrame(spriteFrame);
+    setDelayUnits(delayUnits);
+    setUserInfo(userInfo);
+
+    return true;
+}
+
+AnimationFrame::~AnimationFrame()
+{    
+    CCLOGINFO( "deallocing AnimationFrame: %p", this);
+
+    CC_SAFE_RELEASE(_spriteFrame);
+}
+
+AnimationFrame* AnimationFrame::clone() const
+{
+    // no copy constructor
+    auto frame = new (std::nothrow) AnimationFrame();
+    frame->initWithSpriteFrame(_spriteFrame->clone(),
+                               _delayUnits,
+                               _userInfo);
+
+    frame->autorelease();
+    return frame;
+}
+
+// implementation of Animation
+
+Animation* Animation::create()
+{
+    Animation *animation = new (std::nothrow) Animation();
+    animation->init();
+    animation->autorelease();
+
+    return animation;
+} 
+
+Animation* Animation::createWithSpriteFrames(const Vector<SpriteFrame*>& frames, float delay/* = 0.0f*/, unsigned int loops/* = 1*/)
+{
+    Animation *animation = new (std::nothrow) Animation();
+    animation->initWithSpriteFrames(frames, delay, loops);
+    animation->autorelease();
+
+    return animation;
+}
+
+Animation* Animation::create(const Vector<AnimationFrame*>& arrayOfAnimationFrameNames, float delayPerUnit, unsigned int loops /* = 1 */)
+{
+    Animation *animation = new (std::nothrow) Animation();
+    animation->initWithAnimationFrames(arrayOfAnimationFrameNames, delayPerUnit, loops);
+    animation->autorelease();
+    return animation;
+}
+
+bool Animation::init()
+{
+    _loops = 1;
+    _delayPerUnit = 0.0f;
+    
+    return true;
+}
+
+bool Animation::initWithSpriteFrames(const Vector<SpriteFrame*>& frames, float delay/* = 0.0f*/, unsigned int loops/* = 1*/)
+{
+    _delayPerUnit = delay;
+    _loops = loops;
+
+    for (auto& spriteFrame : frames)
+    {
+        auto animFrame = AnimationFrame::create(spriteFrame, 1, ValueMap());
+        _frames.pushBack(animFrame);
+        _totalDelayUnits++;
+    }
+
+    return true;
+}
+
+bool Animation::initWithAnimationFrames(const Vector<AnimationFrame*>& arrayOfAnimationFrames, float delayPerUnit, unsigned int loops)
+{
+    _delayPerUnit = delayPerUnit;
+    _loops = loops;
+
+    setFrames(arrayOfAnimationFrames);
+
+    for (auto& animFrame : _frames)
+    {
+        _totalDelayUnits += animFrame->getDelayUnits();
+    }
+    return true;
+}
+
+Animation::Animation()
+: _totalDelayUnits(0.0f)
+, _delayPerUnit(0.0f)
+, _duration(0.0f)
+, _restoreOriginalFrame(false)
+, _loops(0)
+{
+
+}
+
+Animation::~Animation(void)
+{
+    CCLOGINFO("deallocing Animation: %p", this);
+}
+
+void Animation::addSpriteFrame(SpriteFrame* spriteFrame)
+{
+    AnimationFrame *animFrame = AnimationFrame::create(spriteFrame, 1.0f, ValueMap());
+    _frames.pushBack(animFrame);
+
+    // update duration
+    _totalDelayUnits++;
+}
+
+void Animation::addSpriteFrameWithFile(const std::string& filename)
+{
+    Texture2D *texture = Director::getInstance()->getTextureCache()->addImage(filename);
+    Rect rect = Rect::ZERO;
+    rect.size = texture->getContentSize();
+    SpriteFrame *frame = SpriteFrame::createWithTexture(texture, rect);
+    addSpriteFrame(frame);
+}
+
+void Animation::addSpriteFrameWithTexture(Texture2D *pobTexture, const Rect& rect)
+{
+    SpriteFrame *frame = SpriteFrame::createWithTexture(pobTexture, rect);
+    addSpriteFrame(frame);
+}
+
+float Animation::getDuration(void) const
+{
+    return _totalDelayUnits * _delayPerUnit;
+}
+
+Animation* Animation::clone() const
+{
+    // no copy constructor    
+    auto a = new (std::nothrow) Animation();
+    a->initWithAnimationFrames(_frames, _delayPerUnit, _loops);
+    a->setRestoreOriginalFrame(_restoreOriginalFrame);
+    a->autorelease();
+    return a;
+}
+
+NS_CC_END

+ 329 - 0
cocos2d/cocos/2d/CCAnimation.h

@@ -0,0 +1,329 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+#ifndef __CC_ANIMATION_H__
+#define __CC_ANIMATION_H__
+
+#include "platform/CCPlatformConfig.h"
+#include "base/CCRef.h"
+#include "base/CCValue.h"
+#include "base/CCVector.h"
+#include "2d/CCSpriteFrame.h"
+
+#include <string>
+
+NS_CC_BEGIN
+
+class Texture2D;
+class SpriteFrame;
+
+/**
+ * @addtogroup _2d
+ * @{
+ */
+
+/** @class AnimationFrame
+ *
+ * A frame of the animation. It contains information like:
+ * - sprite frame name.
+ * - # of delay units.
+ * - offset
+ 
+ @since v2.0
+ */
+class CC_DLL AnimationFrame : public Ref, public Clonable
+{
+public:
+    /** @struct DisplayedEventInfo
+     * When the animation display,Dispatches the event of UserData.
+     */
+    struct DisplayedEventInfo
+    {
+        Node* target;
+        const ValueMap* userInfo;
+    };
+    
+    /**
+     * Creates the animation frame with a spriteframe, number of delay units and a notification user info.
+     *
+     * @param spriteFrame The animation frame with a spriteframe.
+     * @param delayUnits Number of delay units.
+     * @param userInfo A notification user info.
+     * @since 3.0
+     */
+    static AnimationFrame* create(SpriteFrame* spriteFrame, float delayUnits, const ValueMap& userInfo);
+    /** Return a SpriteFrameName to be used.
+     *
+     * @return a SpriteFrameName to be used.
+     */
+    SpriteFrame* getSpriteFrame() const { return _spriteFrame; };
+    /** Set the SpriteFrame.
+     *
+     * @param frame A SpriteFrame will be used.
+     */
+    void setSpriteFrame(SpriteFrame* frame)
+    {
+        CC_SAFE_RETAIN(frame);
+        CC_SAFE_RELEASE(_spriteFrame);
+        _spriteFrame = frame;
+    }
+
+    /** Gets the units of time the frame takes.
+     *
+     * @return The units of time the frame takes.
+     */
+    float getDelayUnits() const { return _delayUnits; };
+    
+    /** Sets the units of time the frame takes.
+     *
+     * @param delayUnits The units of time the frame takes.
+     */
+    void setDelayUnits(float delayUnits) { _delayUnits = delayUnits; };
+    
+    /** @brief Gets user information
+     * A AnimationFrameDisplayedNotification notification will be broadcast when the frame is displayed with this dictionary as UserInfo. 
+     * If UserInfo is nil, then no notification will be broadcast.
+     *
+     * @return A dictionary as UserInfo
+     */
+    const ValueMap& getUserInfo() const { return _userInfo; };
+    ValueMap& getUserInfo() { return _userInfo; };
+    
+    /** Sets user information.
+     * @param userInfo A dictionary as UserInfo.
+     */
+    void setUserInfo(const ValueMap& userInfo)
+    {
+        _userInfo = userInfo;
+    }
+    
+    // Overrides
+    virtual AnimationFrame *clone() const override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    /**
+     * @js ctor
+     */
+    AnimationFrame();
+    /**
+     * @js NA
+     * @lua NA
+     */
+    virtual ~AnimationFrame();
+    
+    /** initializes the animation frame with a spriteframe, number of delay units and a notification user info */
+    bool initWithSpriteFrame(SpriteFrame* spriteFrame, float delayUnits, const ValueMap& userInfo);
+
+protected:
+    
+    /** SpriteFrameName to be used */
+    SpriteFrame* _spriteFrame;
+
+    /**  how many units of time the frame takes */
+    float _delayUnits;
+
+    /**  A AnimationFrameDisplayedNotification notification will be broadcast when the frame is displayed with this dictionary as UserInfo. If UserInfo is nil, then no notification will be broadcast. */
+    ValueMap _userInfo;
+    
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(AnimationFrame);
+};
+
+
+
+
+/** @class Animation
+ * A Animation object is used to perform animations on the Sprite objects.
+ * The Animation object contains AnimationFrame objects, and a possible delay between the frames.
+ * You can animate a Animation object by using the Animate action. Example:
+ * @code
+ * sprite->runAction(Animate::create(animation));
+ * @endcode
+*/
+class CC_DLL Animation : public Ref, public Clonable
+{
+public:
+    /** Creates an animation.
+     * @since v0.99.5
+     */
+    static Animation* create(void);
+
+    /* Creates an animation with an array of SpriteFrame and a delay between frames in seconds.
+     * The frames will be added with one "delay unit".
+     * @since v0.99.5
+     * @param arrayOfSpriteFrameNames An array of SpriteFrame.
+     * @param delay A delay between frames in seconds.
+     * @param loops The times the animation is going to loop.
+     */
+    static Animation* createWithSpriteFrames(const Vector<SpriteFrame*>& arrayOfSpriteFrameNames, float delay = 0.0f, unsigned int loops = 1);
+
+    /* Creates an animation with an array of AnimationFrame, the delay per units in seconds and how many times it should be executed.
+     * @since v2.0
+     * @param arrayOfAnimationFrameNames An animation with an array of AnimationFrame.
+     * @param delayPerUnit The delay per units in seconds and how many times it should be executed.
+     * @param loops The times the animation is going to loop.
+     */
+    static Animation* create(const Vector<AnimationFrame*>& arrayOfAnimationFrameNames, float delayPerUnit, unsigned int loops = 1);
+
+    /** Adds a SpriteFrame to a Animation.
+     *
+     * @param frame The frame will be added with one "delay unit".
+     */
+    void addSpriteFrame(SpriteFrame *frame);
+
+    /** Adds a frame with an image filename. Internally it will create a SpriteFrame and it will add it.
+     * The frame will be added with one "delay unit".
+     * Added to facilitate the migration from v0.8 to v0.9.
+     * @param filename The path of SpriteFrame.
+     */
+    void addSpriteFrameWithFile(const std::string& filename);
+    /**
+     * @deprecated. Use addSpriteFrameWithFile() instead.
+     @js NA
+     */
+    CC_DEPRECATED_ATTRIBUTE void addSpriteFrameWithFileName(const std::string& filename){ addSpriteFrameWithFile(filename);}
+
+    /** Adds a frame with a texture and a rect. Internally it will create a SpriteFrame and it will add it.
+     * The frame will be added with one "delay unit".
+     * Added to facilitate the migration from v0.8 to v0.9.
+     * @param pobTexture A frame with a texture.
+     * @param rect The Texture of rect.
+     */
+    void addSpriteFrameWithTexture(Texture2D* pobTexture, const Rect& rect);
+
+    /** Gets the total Delay units of the Animation. 
+     *
+     * @return The total Delay units of the Animation.
+     */
+    float getTotalDelayUnits() const { return _totalDelayUnits; };
+    
+    /** Sets the delay in seconds of the "delay unit".
+     *
+     * @param delayPerUnit The delay in seconds of the "delay unit".
+     */
+    void setDelayPerUnit(float delayPerUnit) { _delayPerUnit = delayPerUnit; };
+    
+    /** Gets the delay in seconds of the "delay unit".
+     * 
+     * @return The delay in seconds of the "delay unit".
+     */
+    float getDelayPerUnit() const { return _delayPerUnit; };
+
+    
+    /** Gets the duration in seconds of the whole animation. It is the result of totalDelayUnits * delayPerUnit.
+     *
+     * @return Result of totalDelayUnits * delayPerUnit.
+     */
+    float getDuration() const;
+    
+    /** Gets the array of AnimationFrames.
+     * 
+     * @return The array of AnimationFrames.
+     */
+    const Vector<AnimationFrame*>& getFrames() const { return _frames; };
+    
+    /** Sets the array of AnimationFrames. 
+     *
+     * @param frames The array of AnimationFrames.
+     */
+    void setFrames(const Vector<AnimationFrame*>& frames)
+    {
+        _frames = frames;
+    }
+    
+    /** Checks whether to restore the original frame when animation finishes. 
+     *
+     * @return Restore the original frame when animation finishes.
+     */
+    bool getRestoreOriginalFrame() const { return _restoreOriginalFrame; };
+    
+    /** Sets whether to restore the original frame when animation finishes. 
+     *
+     * @param restoreOriginalFrame Whether to restore the original frame when animation finishes.
+     */
+    void setRestoreOriginalFrame(bool restoreOriginalFrame) { _restoreOriginalFrame = restoreOriginalFrame; };
+    
+    /** Gets the times the animation is going to loop. 0 means animation is not animated. 1, animation is executed one time, ... 
+     *
+     * @return The times the animation is going to loop.
+     */
+    unsigned int getLoops() const { return _loops; };
+    
+    /** Sets the times the animation is going to loop. 0 means animation is not animated. 1, animation is executed one time, ... 
+     *
+     * @param loops The times the animation is going to loop.
+     */
+    void setLoops(unsigned int loops) { _loops = loops; };
+    
+    // overrides
+    virtual Animation *clone() const override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    Animation();
+    virtual ~Animation(void);
+    
+    /** Initializes a Animation. */
+    bool init();
+    
+    /** Initializes a Animation with frames and a delay between frames.
+     * @since v0.99.5
+     */
+    bool initWithSpriteFrames(const Vector<SpriteFrame*>& arrayOfSpriteFrameNames, float delay = 0.0f, unsigned int loops = 1);
+    
+    /** Initializes a Animation with AnimationFrame.
+     * @since v2.0
+     */
+    bool initWithAnimationFrames(const Vector<AnimationFrame*>& arrayOfAnimationFrameNames, float delayPerUnit, unsigned int loops);
+
+protected:
+    /** total Delay units of the Animation. */
+    float _totalDelayUnits;
+
+    /** Delay in seconds of the "delay unit". */
+    float _delayPerUnit;
+
+    /** duration in seconds of the whole animation. It is the result of totalDelayUnits * delayPerUnit. */
+    float _duration;
+
+    /** array of AnimationFrames. */
+    Vector<AnimationFrame*> _frames;
+
+    /** whether or not it shall restore the original frame when the animation finishes. */
+    bool _restoreOriginalFrame;
+
+    /** how many times the animation is going to loop. 0 means animation is not animated. 1, animation is executed one time, ... */
+    unsigned int _loops;
+    
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(Animation);
+};
+
+// end of sprite_nodes group
+/// @}
+
+NS_CC_END
+
+#endif // __CC_ANIMATION_H__

+ 242 - 0
cocos2d/cocos/2d/CCAnimationCache.cpp

@@ -0,0 +1,242 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCAnimationCache.h"
+#include "2d/CCSpriteFrameCache.h"
+#include "platform/CCFileUtils.h"
+
+using namespace std;
+
+NS_CC_BEGIN
+
+AnimationCache* AnimationCache::s_sharedAnimationCache = nullptr;
+
+AnimationCache* AnimationCache::getInstance()
+{
+    if (! s_sharedAnimationCache)
+    {
+        s_sharedAnimationCache = new (std::nothrow) AnimationCache();
+        s_sharedAnimationCache->init();
+    }
+
+    return s_sharedAnimationCache;
+}
+
+void AnimationCache::destroyInstance()
+{
+    CC_SAFE_RELEASE_NULL(s_sharedAnimationCache);
+}
+
+bool AnimationCache::init()
+{
+    return true;
+}
+
+AnimationCache::AnimationCache()
+{
+}
+
+AnimationCache::~AnimationCache()
+{
+    CCLOGINFO("deallocing AnimationCache: %p", this);
+}
+
+void AnimationCache::addAnimation(Animation *animation, const std::string& name)
+{
+    _animations.insert(name, animation);
+}
+
+void AnimationCache::removeAnimation(const std::string& name)
+{
+    if (name.empty())
+        return;
+
+    _animations.erase(name);
+}
+
+Animation* AnimationCache::getAnimation(const std::string& name)
+{
+    return _animations.at(name);
+}
+
+void AnimationCache::parseVersion1(const ValueMap& animations)
+{
+    SpriteFrameCache *frameCache = SpriteFrameCache::getInstance();
+
+    for (const auto& anim : animations)
+    {
+        const ValueMap& animationDict = anim.second.asValueMap();
+        const ValueVector& frameNames = animationDict.at("frames").asValueVector();
+        float delay = animationDict.at("delay").asFloat();
+        Animation* animation = nullptr;
+
+        if ( frameNames.empty() )
+        {
+            CCLOG("cocos2d: AnimationCache: Animation '%s' found in dictionary without any frames - cannot add to animation cache.", anim.first.c_str());
+            continue;
+        }
+
+        ssize_t frameNameSize = frameNames.size();
+        Vector<AnimationFrame*> frames(frameNameSize);
+
+        for (auto& frameName : frameNames)
+        {
+            SpriteFrame* spriteFrame = frameCache->getSpriteFrameByName(frameName.asString());
+
+            if ( ! spriteFrame ) {
+                CCLOG("cocos2d: AnimationCache: Animation '%s' refers to frame '%s' which is not currently in the SpriteFrameCache. This frame will not be added to the animation.", anim.first.c_str(), frameName.asString().c_str());
+
+                continue;
+            }
+
+            AnimationFrame* animFrame = AnimationFrame::create(spriteFrame, 1, ValueMap());
+            frames.pushBack(animFrame);
+        }
+
+        if ( frames.empty() )
+        {
+            CCLOG("cocos2d: AnimationCache: None of the frames for animation '%s' were found in the SpriteFrameCache. Animation is not being added to the Animation Cache.", anim.first.c_str());
+            continue;
+        }
+        else if ( frames.size() != frameNameSize )
+        {
+            CCLOG("cocos2d: AnimationCache: An animation in your dictionary refers to a frame which is not in the SpriteFrameCache. Some or all of the frames for the animation '%s' may be missing.", anim.first.c_str());
+        }
+
+        animation = Animation::create(frames, delay, 1);
+
+        AnimationCache::getInstance()->addAnimation(animation, anim.first);
+    }
+}
+
+void AnimationCache::parseVersion2(const ValueMap& animations)
+{
+    SpriteFrameCache *frameCache = SpriteFrameCache::getInstance();
+
+    for (const auto& anim : animations)
+    {
+        std::string name = anim.first;
+        ValueMap& animationDict = const_cast<ValueMap&>(anim.second.asValueMap());
+
+        const Value& loops = animationDict["loops"];
+        bool restoreOriginalFrame = animationDict["restoreOriginalFrame"].asBool();
+
+        ValueVector& frameArray = animationDict["frames"].asValueVector();
+
+        if ( frameArray.empty() )
+        {
+            CCLOG("cocos2d: AnimationCache: Animation '%s' found in dictionary without any frames - cannot add to animation cache.", name.c_str());
+            continue;
+        }
+
+        // Array of AnimationFrames
+        Vector<AnimationFrame*> array(static_cast<int>(frameArray.size()));
+
+        for (auto& obj : frameArray)
+        {
+            ValueMap& entry = obj.asValueMap();
+            std::string spriteFrameName = entry["spriteframe"].asString();
+            SpriteFrame *spriteFrame = frameCache->getSpriteFrameByName(spriteFrameName);
+
+            if( ! spriteFrame ) {
+                CCLOG("cocos2d: AnimationCache: Animation '%s' refers to frame '%s' which is not currently in the SpriteFrameCache. This frame will not be added to the animation.", name.c_str(), spriteFrameName.c_str());
+
+                continue;
+            }
+
+            float delayUnits = entry["delayUnits"].asFloat();
+            Value& userInfo = entry["notification"];
+
+            AnimationFrame *animFrame = AnimationFrame::create(spriteFrame, delayUnits, userInfo.getType() == Value::Type::MAP ? userInfo.asValueMap() : ValueMapNull);
+
+            array.pushBack(animFrame);
+        }
+
+        float delayPerUnit = animationDict["delayPerUnit"].asFloat();
+        Animation *animation = Animation::create(array, delayPerUnit, loops.getType() != Value::Type::NONE ? loops.asInt() : 1);
+
+        animation->setRestoreOriginalFrame(restoreOriginalFrame);
+
+        AnimationCache::getInstance()->addAnimation(animation, name);
+    }
+}
+
+void AnimationCache::addAnimationsWithDictionary(const ValueMap& dictionary,const std::string& plist)
+{
+    if ( dictionary.find("animations") == dictionary.end() )
+    {
+        CCLOG("cocos2d: AnimationCache: No animations were found in provided dictionary.");
+        return;
+    }
+    
+    const Value& animations = dictionary.at("animations");
+    unsigned int version = 1;
+
+    if( dictionary.find("properties") != dictionary.end() )
+    {
+        const ValueMap& properties = dictionary.at("properties").asValueMap();
+        version = properties.at("format").asInt();
+        const ValueVector& spritesheets = properties.at("spritesheets").asValueVector();
+
+        for(const auto &value : spritesheets) {
+            std::string path = FileUtils::getInstance()->fullPathFromRelativeFile(value.asString(),plist);
+            SpriteFrameCache::getInstance()->addSpriteFramesWithFile(path);
+        }
+    }
+
+    switch (version) {
+        case 1:
+            parseVersion1(animations.asValueMap());
+            break;
+        case 2:
+            parseVersion2(animations.asValueMap());
+            break;
+        default:
+            CCASSERT(false, "Invalid animation format");
+    }
+}
+
+/** Read an NSDictionary from a plist file and parse it automatically for animations */
+void AnimationCache::addAnimationsWithFile(const std::string& plist)
+{
+    CCASSERT(!plist.empty(), "Invalid texture file name");
+    if (plist.empty()) {
+        log("%s error:file name is empty!", __FUNCTION__);
+        return;
+    }
+    
+    ValueMap dict = FileUtils::getInstance()->getValueMapFromFile(plist);
+
+    CCASSERT( !dict.empty(), "CCAnimationCache: File could not be found");
+    if (dict.empty()) {
+        log("AnimationCache::addAnimationsWithFile error:%s not exist!", plist.c_str());
+    }
+
+    addAnimationsWithDictionary(dict,plist);
+}
+
+
+NS_CC_END

+ 149 - 0
cocos2d/cocos/2d/CCAnimationCache.h

@@ -0,0 +1,149 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+#ifndef __CC_ANIMATION_CACHE_H__
+#define __CC_ANIMATION_CACHE_H__
+
+#include "base/CCRef.h"
+#include "base/CCMap.h"
+#include "base/CCValue.h"
+#include "2d/CCAnimation.h"
+
+#include <string>
+
+NS_CC_BEGIN
+
+
+class Animation;
+
+/**
+ * @addtogroup _2d
+ * @{
+ */
+
+/** Singleton that manages the Animations.
+It saves in a cache the animations. You should use this class if you want to save your animations in a cache.
+
+Before v0.99.5, the recommend way was to save them on the Sprite. Since v0.99.5, you should use this class instead.
+
+@since v0.99.5
+@js cc.animationCache
+*/
+class CC_DLL AnimationCache : public Ref
+{
+public:
+    /**
+     * @js ctor
+     */
+    AnimationCache();
+    /**
+     * @js NA
+     * @lua NA
+     */
+    ~AnimationCache();
+    /** Returns the shared instance of the Animation cache 
+	 @js NA
+	*/
+    static AnimationCache* getInstance();
+
+    /** Purges the cache. It releases all the Animation objects and the shared instance.
+		@js NA
+     */
+    static void destroyInstance();
+
+    /** @deprecated Use getInstance() instead. */
+    CC_DEPRECATED_ATTRIBUTE static AnimationCache* sharedAnimationCache() { return AnimationCache::getInstance(); }
+
+    /** @deprecated Use destroyInstance() instead. */
+    CC_DEPRECATED_ATTRIBUTE static void purgeSharedAnimationCache() { return AnimationCache::destroyInstance(); }
+
+    bool init(void);
+
+    /** Adds a Animation with a name.
+     *
+     * @param animation An animation.
+     * @param name The name of animation.
+     */
+    void addAnimation(Animation *animation, const std::string& name);
+
+    /** Deletes a Animation from the cache.
+     *
+     * @param name The name of animation.
+     */
+    void removeAnimation(const std::string& name);
+    /** @deprecated. Use removeAnimation() instead
+     * @js NA
+     * @lua NA
+     */
+    CC_DEPRECATED_ATTRIBUTE void removeAnimationByName(const std::string& name){ removeAnimation(name);}
+
+    /** Returns a Animation that was previously added.
+     * If the name is not found it will return nil.
+     * You should retain the returned copy if you are going to use it.
+     *
+     * @return A Animation that was previously added. If the name is not found it will return nil.
+     */
+    Animation* getAnimation(const std::string& name);
+    /**
+     * @deprecated. Use getAnimation() instead
+     * @js NA
+     * @lua NA
+     */
+    CC_DEPRECATED_ATTRIBUTE Animation* animationByName(const std::string& name){ return getAnimation(name); }
+
+    /** Adds an animation from an NSDictionary.
+     * Make sure that the frames were previously loaded in the SpriteFrameCache.
+     * @param dictionary An NSDictionary.
+     * @param plist The path of the relative file,it use to find the plist path for load SpriteFrames.
+     * @since v1.1
+	 @js NA
+     */
+    void addAnimationsWithDictionary(const ValueMap& dictionary,const std::string& plist);
+
+    /** Adds an animation from a plist file.
+     * Make sure that the frames were previously loaded in the SpriteFrameCache.
+     * @since v1.1
+     * @js addAnimations
+     * @lua addAnimations
+     * @param plist An animation from a plist file.
+     */
+    void addAnimationsWithFile(const std::string& plist);
+
+private:
+    void parseVersion1(const ValueMap& animations);
+    void parseVersion2(const ValueMap& animations);
+
+private:
+    Map<std::string, Animation*> _animations;
+    static AnimationCache* s_sharedAnimationCache;
+};
+
+// end of sprite_nodes group
+/// @}
+
+NS_CC_END
+
+#endif // __CC_ANIMATION_CACHE_H__

+ 257 - 0
cocos2d/cocos/2d/CCAtlasNode.cpp

@@ -0,0 +1,257 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCAtlasNode.h"
+#include "renderer/CCTextureAtlas.h"
+#include "base/CCDirector.h"
+#include "renderer/CCTextureCache.h"
+#include "renderer/CCRenderer.h"
+#include "renderer/CCGLProgram.h"
+
+NS_CC_BEGIN
+
+// implementation AtlasNode
+
+// AtlasNode - Creation & Init
+
+AtlasNode::AtlasNode()
+: _itemsPerRow(0)
+, _itemsPerColumn(0)
+, _itemWidth(0)
+, _itemHeight(0)
+, _textureAtlas(nullptr)
+, _isOpacityModifyRGB(false)
+, _quadsToDraw(0)
+, _uniformColor(0)
+, _ignoreContentScaleFactor(false)
+{
+}
+
+AtlasNode::~AtlasNode()
+{
+    CC_SAFE_RELEASE(_textureAtlas);
+}
+
+AtlasNode * AtlasNode::create(const std::string& tile, int tileWidth, int tileHeight, int itemsToRender)
+{
+    AtlasNode * ret = new (std::nothrow) AtlasNode();
+    if (ret->initWithTileFile(tile, tileWidth, tileHeight, itemsToRender))
+    {
+        ret->autorelease();
+        return ret;
+    }
+    CC_SAFE_DELETE(ret);
+    return nullptr;
+}
+
+bool AtlasNode::initWithTileFile(const std::string& tile, int tileWidth, int tileHeight, int itemsToRender)
+{
+    CCASSERT(tile.size() > 0, "file size should not be empty");
+    Texture2D *texture = Director::getInstance()->getTextureCache()->addImage(tile);
+    return initWithTexture(texture, tileWidth, tileHeight, itemsToRender);
+}
+
+bool AtlasNode::initWithTexture(Texture2D* texture, int tileWidth, int tileHeight, int itemsToRender)
+{
+    _itemWidth  = tileWidth;
+    _itemHeight = tileHeight;
+
+    _colorUnmodified = Color3B::WHITE;
+    _isOpacityModifyRGB = true;
+
+    _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;
+
+    _textureAtlas = new (std::nothrow) TextureAtlas();
+    _textureAtlas->initWithTexture(texture, itemsToRender);
+
+    if (! _textureAtlas)
+    {
+        CCLOG("cocos2d: Could not initialize AtlasNode. Invalid Texture.");
+        return false;
+    }
+
+    this->updateBlendFunc();
+    this->updateOpacityModifyRGB();
+
+    this->calculateMaxItems();
+
+    _quadsToDraw = itemsToRender;
+
+    // shader stuff
+    setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP, texture));
+
+    return true;
+}
+
+
+// AtlasNode - Atlas generation
+
+void AtlasNode::calculateMaxItems()
+{
+    Size s = _textureAtlas->getTexture()->getContentSize();
+    
+    if (_ignoreContentScaleFactor)
+    {
+        s = _textureAtlas->getTexture()->getContentSizeInPixels();
+    }
+    
+    _itemsPerColumn = (int)(s.height / _itemHeight);
+    _itemsPerRow = (int)(s.width / _itemWidth);
+}
+
+void AtlasNode::updateAtlasValues()
+{
+    CCASSERT(false, "CCAtlasNode:Abstract updateAtlasValue not overridden");
+}
+
+// AtlasNode - draw
+void AtlasNode::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
+{
+    // ETC1 ALPHA supports.
+    _quadCommand.init(_globalZOrder, _textureAtlas->getTexture(), getGLProgramState(), _blendFunc, _textureAtlas->getQuads(), _quadsToDraw, transform, flags);
+    
+    renderer->addCommand(&_quadCommand);
+
+}
+
+// AtlasNode - RGBA protocol
+
+const Color3B& AtlasNode::getColor() const
+{
+    if(_isOpacityModifyRGB)
+    {
+        return _colorUnmodified;
+    }
+    return Node::getColor();
+}
+
+void AtlasNode::setColor(const Color3B& color3)
+{
+    Color3B tmp = color3;
+    _colorUnmodified = color3;
+
+    if( _isOpacityModifyRGB )
+    {
+        tmp.r = tmp.r * _displayedOpacity/255;
+        tmp.g = tmp.g * _displayedOpacity/255;
+        tmp.b = tmp.b * _displayedOpacity/255;
+    }
+    Node::setColor(tmp);
+}
+
+void AtlasNode::setOpacity(GLubyte opacity)
+{
+    Node::setOpacity(opacity);
+
+    // special opacity for premultiplied textures
+    if( _isOpacityModifyRGB )
+        this->setColor(_colorUnmodified);
+}
+
+void AtlasNode::setOpacityModifyRGB(bool value)
+{
+    Color3B oldColor = this->getColor();
+    _isOpacityModifyRGB = value;
+    this->setColor(oldColor);
+}
+
+bool AtlasNode::isOpacityModifyRGB() const
+{
+    return _isOpacityModifyRGB;
+}
+
+void AtlasNode::updateOpacityModifyRGB()
+{
+    _isOpacityModifyRGB = _textureAtlas->getTexture()->hasPremultipliedAlpha();
+}
+
+void AtlasNode::setIgnoreContentScaleFactor(bool ignoreContentScaleFactor)
+{
+    _ignoreContentScaleFactor = ignoreContentScaleFactor;
+}
+
+// AtlasNode - CocosNodeTexture protocol
+
+const BlendFunc& AtlasNode::getBlendFunc() const
+{
+    return _blendFunc;
+}
+
+void AtlasNode::setBlendFunc(const BlendFunc &blendFunc)
+{
+    _blendFunc = blendFunc;
+}
+
+void AtlasNode::updateBlendFunc()
+{
+    if( ! _textureAtlas->getTexture()->hasPremultipliedAlpha() )
+    {
+        _blendFunc = BlendFunc::ALPHA_NON_PREMULTIPLIED;
+        setOpacityModifyRGB(false);
+    }
+    else
+    {
+        _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;
+        setOpacityModifyRGB(true);
+    }
+}
+
+void AtlasNode::setTexture(Texture2D *texture)
+{
+    _textureAtlas->setTexture(texture);
+    this->updateBlendFunc();
+    this->updateOpacityModifyRGB();
+}
+
+Texture2D * AtlasNode::getTexture() const
+{
+    return _textureAtlas->getTexture();
+}
+
+void AtlasNode::setTextureAtlas(TextureAtlas* textureAtlas)
+{
+    CC_SAFE_RETAIN(textureAtlas);
+    CC_SAFE_RELEASE(_textureAtlas);
+    _textureAtlas = textureAtlas;
+}
+
+TextureAtlas * AtlasNode::getTextureAtlas() const
+{
+    return _textureAtlas;
+}
+
+ssize_t AtlasNode::getQuadsToDraw() const
+{
+    return _quadsToDraw;
+}
+
+void AtlasNode::setQuadsToDraw(ssize_t quadsToDraw)
+{
+    _quadsToDraw = quadsToDraw;
+}
+
+NS_CC_END

+ 159 - 0
cocos2d/cocos/2d/CCAtlasNode.h

@@ -0,0 +1,159 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+
+#ifndef __CCATLAS_NODE_H__
+#define __CCATLAS_NODE_H__
+
+#include "2d/CCNode.h"
+#include "base/CCProtocols.h"
+#include "base/ccTypes.h"
+#include "renderer/CCQuadCommand.h"
+
+NS_CC_BEGIN
+
+/**
+ * @addtogroup _2d
+ * @{
+ */
+
+class TextureAtlas;
+
+/** @brief AtlasNode is a subclass of Node that implements the RGBAProtocol and TextureProtocol protocol.
+ * It knows how to render a TextureAtlas object.
+ * If you are going to render a TextureAtlas consider subclassing AtlasNode (or a subclass of AtlasNode).
+ * All features from Node are valid, plus the following features:
+ * - opacity and RGB colors.
+ */
+class CC_DLL AtlasNode : public Node, public TextureProtocol
+{    
+public:
+	/** creates a AtlasNode  with an Atlas file the width and height of each item and the quantity of items to render.
+     *
+     * @param filename The path of Atlas file.
+     * @param tileWidth The width of the item.
+     * @param tileHeight The height of the item.
+     * @param itemsToRender The quantity of items to render.
+     */
+	static AtlasNode * create(const std::string& filename, int tileWidth, int tileHeight, int itemsToRender);
+
+    /** updates the Atlas (indexed vertex array).
+    * Shall be overridden in subclasses.
+    */
+    virtual void updateAtlasValues();
+    
+    /** Set an buffer manager of the texture vertex. */
+    void setTextureAtlas(TextureAtlas* textureAtlas);
+    
+    /** Return the buffer manager of the texture vertex. 
+     *
+     * @return Return A TextureAtlas.
+     */
+    TextureAtlas* getTextureAtlas() const;
+    
+    void setQuadsToDraw(ssize_t quadsToDraw);
+    ssize_t getQuadsToDraw() const;
+
+    
+    // Overrides
+    virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override;
+    virtual Texture2D* getTexture() const override;
+    virtual void setTexture(Texture2D *texture) override;
+    virtual bool isOpacityModifyRGB() const override;
+    virtual void setOpacityModifyRGB(bool isOpacityModifyRGB) override;
+    virtual const Color3B& getColor(void) const override;
+    virtual void setColor(const Color3B& color) override;
+    virtual void setOpacity(GLubyte opacity) override;
+    /**
+    * @code
+    * When this function bound into js or lua,the parameter will be changed
+    * In js: var setBlendFunc(var src, var dst)
+    * @endcode
+    * @lua NA
+    */
+    virtual void setBlendFunc(const BlendFunc& blendFunc) override;
+    /**
+    * @lua NA
+    */
+    virtual const BlendFunc& getBlendFunc() const override;
+
+CC_CONSTRUCTOR_ACCESS:
+    AtlasNode();
+    virtual ~AtlasNode();
+
+    /** Initializes an AtlasNode  with an Atlas file the width and height of each item and the quantity of items to render*/
+    bool initWithTileFile(const std::string& tile, int tileWidth, int tileHeight, int itemsToRender);
+    
+    /** Initializes an AtlasNode  with a texture the width and height of each item measured in points and the quantity of items to render*/
+    bool initWithTexture(Texture2D* texture, int tileWidth, int tileHeight, int itemsToRender);
+
+protected:
+    void calculateMaxItems();
+    void updateBlendFunc();
+    void updateOpacityModifyRGB();
+
+    friend class Director;
+    void setIgnoreContentScaleFactor(bool bIgnoreContentScaleFactor);
+
+    /** Chars per row. */
+    int    _itemsPerRow;
+    /** Chars per column. */
+    int    _itemsPerColumn;
+
+    /** Width of each char. */
+    int    _itemWidth;
+    /** Height of each char. */
+    int    _itemHeight;
+    
+    Color3B    _colorUnmodified;
+    
+    TextureAtlas* _textureAtlas;
+    /** Protocol variables. */
+    bool _isOpacityModifyRGB;
+    BlendFunc _blendFunc;
+
+    /** Quads to draw. */
+    ssize_t _quadsToDraw;
+    /** Color uniform. */
+    GLint    _uniformColor;
+    /** This variable is only used for LabelAtlas FPS display. So plz don't modify its value. */
+    bool _ignoreContentScaleFactor;
+    /** Quad command. */
+    QuadCommand _quadCommand;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(AtlasNode);
+
+};
+
+// end of base_node group
+/// @}
+
+NS_CC_END
+
+#endif // __CCATLAS_NODE_H__
+
+

+ 725 - 0
cocos2d/cocos/2d/CCAutoPolygon.cpp

@@ -0,0 +1,725 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCAutoPolygon.h"
+#include "poly2tri/poly2tri.h"
+#include "base/CCDirector.h"
+#include "renderer/CCTextureCache.h"
+#include "clipper/clipper.hpp"
+#include <algorithm>
+#include <math.h>
+
+USING_NS_CC;
+
+static unsigned short quadIndices9[]={
+    0+4*0,1+4*0,2+4*0, 3+4*0,2+4*0,1+4*0,
+    0+4*1,1+4*1,2+4*1, 3+4*1,2+4*1,1+4*1,
+    0+4*2,1+4*2,2+4*2, 3+4*2,2+4*2,1+4*2,
+    0+4*3,1+4*3,2+4*3, 3+4*3,2+4*3,1+4*3,
+    0+4*4,1+4*4,2+4*4, 3+4*4,2+4*4,1+4*4,
+    0+4*5,1+4*5,2+4*5, 3+4*5,2+4*5,1+4*5,
+    0+4*6,1+4*6,2+4*6, 3+4*6,2+4*6,1+4*6,
+    0+4*7,1+4*7,2+4*7, 3+4*7,2+4*7,1+4*7,
+    0+4*8,1+4*8,2+4*8, 3+4*8,2+4*8,1+4*8,
+};
+
+const static float PRECISION = 10.0f;
+
+PolygonInfo::PolygonInfo()
+: _rect(Rect::ZERO)
+, _filename("")
+, _isVertsOwner(true)
+{
+    triangles.verts = nullptr;
+    triangles.indices = nullptr;
+    triangles.vertCount = 0;
+    triangles.indexCount = 0;
+};
+
+PolygonInfo::PolygonInfo(const PolygonInfo& other)
+: triangles()
+, _rect()
+, _isVertsOwner(true)
+{
+    _filename = other._filename;
+    _isVertsOwner = true;
+    _rect = other._rect;
+    triangles.verts = new (std::nothrow) V3F_C4B_T2F[other.triangles.vertCount];
+    triangles.indices = new (std::nothrow) unsigned short[other.triangles.indexCount];
+    CCASSERT(triangles.verts && triangles.indices, "not enough memory");
+    triangles.vertCount = other.triangles.vertCount;
+    triangles.indexCount = other.triangles.indexCount;
+    memcpy(triangles.verts, other.triangles.verts, other.triangles.vertCount * sizeof(other.triangles.verts[0]));
+    memcpy(triangles.indices, other.triangles.indices, other.triangles.indexCount * sizeof(other.triangles.indices[0]));
+};
+
+PolygonInfo& PolygonInfo::operator= (const PolygonInfo& other)
+{
+    if(this != &other)
+    {
+        releaseVertsAndIndices();
+        _filename = other._filename;
+        _isVertsOwner = true;
+        _rect = other._rect;
+        triangles.verts = new (std::nothrow) V3F_C4B_T2F[other.triangles.vertCount];
+        triangles.indices = new (std::nothrow) unsigned short[other.triangles.indexCount];
+        CCASSERT(triangles.verts && triangles.indices, "not enough memory");
+        triangles.vertCount = other.triangles.vertCount;
+        triangles.indexCount = other.triangles.indexCount;
+        memcpy(triangles.verts, other.triangles.verts, other.triangles.vertCount * sizeof(other.triangles.verts[0]));
+        memcpy(triangles.indices, other.triangles.indices, other.triangles.indexCount * sizeof(other.triangles.indices[0]));
+    }
+    return *this;
+}
+
+PolygonInfo::~PolygonInfo()
+{
+    releaseVertsAndIndices();
+}
+
+void PolygonInfo::setQuad(V3F_C4B_T2F_Quad *quad)
+{
+    releaseVertsAndIndices();
+    _isVertsOwner = false;
+    triangles.indices = quadIndices9;
+    triangles.vertCount = 4;
+    triangles.indexCount = 6;
+    triangles.verts = (V3F_C4B_T2F*)quad;
+}
+
+void PolygonInfo::setQuads(V3F_C4B_T2F_Quad *quad, int numberOfQuads)
+{
+    CCASSERT(numberOfQuads >= 1 && numberOfQuads <= 9, "Invalid number of Quads");
+
+    releaseVertsAndIndices();
+    _isVertsOwner = false;
+    triangles.indices = quadIndices9;
+    triangles.vertCount = 4 * numberOfQuads;
+    triangles.indexCount = 6 * numberOfQuads;
+    triangles.verts = (V3F_C4B_T2F*)quad;
+}
+
+void PolygonInfo::setTriangles(const TrianglesCommand::Triangles& other)
+{
+    this->releaseVertsAndIndices();
+    _isVertsOwner = false;
+    
+    this->triangles.vertCount = other.vertCount;
+    this->triangles.indexCount = other.indexCount;
+    this->triangles.verts = other.verts;
+    this->triangles.indices = other.indices;
+}
+
+void PolygonInfo::releaseVertsAndIndices()
+{
+    if(_isVertsOwner)
+    {
+        if(nullptr != triangles.verts)
+        {
+            CC_SAFE_DELETE_ARRAY(triangles.verts);
+        }
+        
+        if(nullptr != triangles.indices)
+        {
+            CC_SAFE_DELETE_ARRAY(triangles.indices);
+        }
+    }
+}
+
+unsigned int PolygonInfo::getVertCount() const
+{
+    return (unsigned int)triangles.vertCount;
+}
+
+unsigned int PolygonInfo::getTrianglesCount() const
+{
+    return (unsigned int)triangles.indexCount/3;
+}
+
+unsigned int PolygonInfo::getTriaglesCount() const
+{
+    return getTrianglesCount();
+}
+
+float PolygonInfo::getArea() const
+{
+    float area = 0;
+    V3F_C4B_T2F *verts = triangles.verts;
+    unsigned short *indices = triangles.indices;
+    for(int i = 0; i < triangles.indexCount; i+=3)
+    {
+        auto A = verts[indices[i]].vertices;
+        auto B = verts[indices[i+1]].vertices;
+        auto C = verts[indices[i+2]].vertices;
+        area += (A.x*(B.y-C.y) + B.x*(C.y-A.y) + C.x*(A.y - B.y))/2;
+    }
+    return area;
+}
+
+AutoPolygon::AutoPolygon(const std::string &filename)
+:_image(nullptr)
+,_data(nullptr)
+,_filename("")
+,_width(0)
+,_height(0)
+,_scaleFactor(0)
+{
+    _filename = filename;
+    _image = new (std::nothrow) Image();
+    _image->initWithImageFile(filename);
+    CCASSERT(_image->getRenderFormat()==Texture2D::PixelFormat::RGBA8888, "unsupported format, currently only supports rgba8888");
+    _data = _image->getData();
+    _width = _image->getWidth();
+    _height = _image->getHeight();
+    _scaleFactor = Director::getInstance()->getContentScaleFactor();
+}
+
+AutoPolygon::~AutoPolygon()
+{
+    CC_SAFE_DELETE(_image);
+}
+
+std::vector<Vec2> AutoPolygon::trace(const Rect& rect, float threshold)
+{
+    Vec2 first = findFirstNoneTransparentPixel(rect, threshold);
+    return marchSquare(rect, first, threshold);
+}
+
+Vec2 AutoPolygon::findFirstNoneTransparentPixel(const Rect& rect, float threshold)
+{
+	bool found = false;
+    Vec2 i;
+    for(i.y = rect.origin.y; i.y < rect.origin.y+rect.size.height; i.y++)
+    {
+        if(found)break;
+        for(i.x = rect.origin.x; i.x < rect.origin.x+rect.size.width; i.x++)
+        {
+            auto alpha = getAlphaByPos(i);
+            if(alpha>threshold)
+            {
+                found = true;
+                break;
+            }
+        }
+    }
+    CCASSERT(found, "image is all transparent!");
+    return i;
+}
+
+unsigned char AutoPolygon::getAlphaByIndex(unsigned int i)
+{
+    return *(_data+i*4+3);
+}
+unsigned char AutoPolygon::getAlphaByPos(const Vec2& pos)
+{
+    return *(_data+((int)pos.y*_width+(int)pos.x)*4+3);
+}
+
+unsigned int AutoPolygon::getSquareValue(unsigned int x, unsigned int y, const Rect& rect, float threshold)
+{
+    /*
+     checking the 2x2 pixel grid, assigning these values to each pixel, if not transparent
+     +---+---+
+     | 1 | 2 |
+     +---+---+
+     | 4 | 8 | <- current pixel (curx,cury)
+     +---+---+
+     */
+    unsigned int sv = 0;
+    //NOTE: due to the way we pick points from texture, rect needs to be smaller, otherwise it goes outside 1 pixel
+    auto fixedRect = Rect(rect.origin, rect.size-Size(2,2));
+    
+    Vec2 tl = Vec2(x-1, y-1);
+    sv += (fixedRect.containsPoint(tl) && getAlphaByPos(tl) > threshold)? 1 : 0;
+    Vec2 tr = Vec2(x, y-1);
+    sv += (fixedRect.containsPoint(tr) && getAlphaByPos(tr) > threshold)? 2 : 0;
+    Vec2 bl = Vec2(x-1, y);
+    sv += (fixedRect.containsPoint(bl) && getAlphaByPos(bl) > threshold)? 4 : 0;
+    Vec2 br = Vec2(x, y);
+    sv += (fixedRect.containsPoint(br) && getAlphaByPos(br) > threshold)? 8 : 0;
+    CCASSERT(sv != 0 && sv != 15, "square value should not be 0, or 15");
+    return sv;
+}
+
+std::vector<cocos2d::Vec2> AutoPolygon::marchSquare(const Rect& rect, const Vec2& start, float threshold)
+{
+    int stepx = 0;
+    int stepy = 0;
+    int prevx = 0;
+    int prevy = 0;
+    int startx = start.x;
+    int starty = start.y;
+    int curx = startx;
+    int cury = starty;
+    unsigned int count = 0;
+    std::vector<int> case9s;
+    std::vector<int> case6s;
+    int i;
+    std::vector<int>::iterator it;
+    std::vector<cocos2d::Vec2> _points;
+    do{
+        int sv = getSquareValue(curx, cury, rect, threshold);
+        switch(sv){
+
+            case 1:
+            case 5:
+            case 13:
+                /* going UP with these cases:
+                 1          5           13
+                 +---+---+  +---+---+  +---+---+ 
+                 | 1 |   |  | 1 |   |  | 1 |   | 
+                 +---+---+  +---+---+  +---+---+ 
+                 |   |   |  | 4 |   |  | 4 | 8 | 
+                 +---+---+  +---+---+  +---+---+
+                 */
+                stepx = 0;
+                stepy = -1;
+                break;
+
+                
+            case 8:
+            case 10:
+            case 11:
+                /* going DOWN with these cases:
+                 8          10          11
+                 +---+---+  +---+---+   +---+---+
+                 |   |   |  |   | 2 |   | 1 | 2 |
+                 +---+---+  +---+---+   +---+---+
+                 |   | 8 |  |   | 8 |   |   | 8 |
+                 +---+---+  +---+---+  	+---+---+
+                 */
+                stepx = 0;
+                stepy = 1;
+                break;
+
+                
+            case 4:
+            case 12:
+            case 14:
+                /* going LEFT with these cases:
+                 4          12          14
+                 +---+---+  +---+---+   +---+---+
+                 |   |   |  |   |   |   |   | 2 |
+                 +---+---+  +---+---+   +---+---+
+                 | 4 |   |  | 4 | 8 |   | 4 | 8 |
+                 +---+---+  +---+---+  	+---+---+
+                 */
+                stepx = -1;
+                stepy = 0;
+                break;
+                
+                
+            case 2 :
+            case 3 :
+            case 7 :
+                /* going RIGHT with these cases:
+                 2          3           7        
+                 +---+---+  +---+---+   +---+---+
+                 |   | 2 |  | 1 | 2 |   | 1 | 2 |
+                 +---+---+  +---+---+   +---+---+
+                 |   |   |  |   |   |   | 4 |   |
+                 +---+---+  +---+---+  	+---+---+
+                 */
+                stepx=1;
+                stepy=0;
+                break;
+            case 9 :
+                /*
+                 +---+---+
+                 | 1 |   |
+                 +---+---+
+                 |   | 8 |
+                 +---+---+
+                 this should normally go UP, but if we already been here, we go down
+                */
+                //find index from xy;
+                i = getIndexFromPos(curx, cury);
+                it = find (case9s.begin(), case9s.end(), i);
+                if (it != case9s.end())
+                {
+                    //found, so we go down, and delete from case9s;
+                    stepx = 0;
+                    stepy = 1;
+                    case9s.erase(it);
+                }
+                else
+                {
+                    //not found, we go up, and add to case9s;
+                    stepx = 0;
+                    stepy = -1;
+                    case9s.push_back(i);
+                }
+                break;
+            case 6 :
+                /*
+                 6
+                 +---+---+
+                 |   | 2 |
+                 +---+---+
+                 | 4 |   |
+                 +---+---+
+                 this normally go RIGHT, but if its coming from UP, it should go LEFT
+                 */
+                i = getIndexFromPos(curx, cury);
+                it = find (case6s.begin(), case6s.end(), i);
+                if (it != case6s.end())
+                {
+                    //found, so we go down, and delete from case9s;
+                    stepx = -1;
+                    stepy = 0;
+                    case6s.erase(it);
+                }
+                else{
+                    //not found, we go up, and add to case9s;
+                    stepx = 1;
+                    stepy = 0;
+                    case6s.push_back(i);
+                }
+                break;
+            default:
+                CCLOG("this shouldn't happen.");
+        }
+        //little optimization
+        // if previous direction is same as current direction,
+        // then we should modify the last vec to current
+        curx += stepx;
+        cury += stepy;
+        if(stepx == prevx && stepy == prevy)
+        {
+            _points.back().x = (float)(curx-rect.origin.x) / _scaleFactor;
+            _points.back().y = (float)(rect.size.height - cury + rect.origin.y) / _scaleFactor;
+        }
+        else
+        {
+            _points.push_back(Vec2((float)(curx - rect.origin.x) / _scaleFactor, (float)(rect.size.height - cury + rect.origin.y) / _scaleFactor));
+        }
+
+        count++;
+        prevx = stepx;
+        prevy = stepy;
+
+#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
+        const auto totalPixel = _width * _height;
+        CCASSERT(count <= totalPixel, "oh no, marching square cannot find starting position");
+#endif
+    } while(curx != startx || cury != starty);
+    return _points;
+}
+
+float AutoPolygon::perpendicularDistance(const cocos2d::Vec2& i, const cocos2d::Vec2& start, const cocos2d::Vec2& end)
+{
+    float res;
+    float slope;
+    float intercept;
+    
+    if(start.x == end.x)
+    {
+        res = fabsf(i.x- end.x);
+    }
+    else if (start.y == end.y)
+    {
+        res = fabsf(i.y - end.y);
+    }
+    else{
+        slope = (end.y - start.y) / (end.x - start.x);
+        intercept = start.y - (slope*start.x);
+        res = fabsf(slope * i.x - i.y + intercept) / sqrtf(powf(slope, 2)+1);
+    }
+    return res;
+}
+std::vector<cocos2d::Vec2> AutoPolygon::rdp(const std::vector<cocos2d::Vec2>& v, float optimization)
+{
+    if(v.size() < 3)
+        return v;
+    
+    int index = -1;
+    float dist = 0;
+    //not looping first and last point
+    for(size_t i = 1, size = v.size(); i < size-1; ++i)
+    {
+        float cdist = perpendicularDistance(v[i], v.front(), v.back());
+        if(cdist > dist)
+        {
+            dist = cdist;
+            index = static_cast<int>(i);
+        }
+    }
+    if (dist>optimization)
+    {
+        std::vector<Vec2>::const_iterator begin = v.begin();
+        std::vector<Vec2>::const_iterator end   = v.end();
+        std::vector<Vec2> l1(begin, begin+index+1);
+        std::vector<Vec2> l2(begin+index, end);
+        
+        std::vector<Vec2> r1 = rdp(l1, optimization);
+        std::vector<Vec2> r2 = rdp(l2, optimization);
+        
+        r1.insert(r1.end(), r2.begin()+1, r2.end());
+        return r1;
+    }
+    else {
+        std::vector<Vec2> ret;
+        ret.push_back(v.front());
+        ret.push_back(v.back());
+        return ret;
+    }
+}
+std::vector<Vec2> AutoPolygon::reduce(const std::vector<Vec2>& points, const Rect& rect, float epsilon)
+{
+    auto size = points.size();
+    // if there are less than 3 points, then we have nothing
+    if(size<3)
+    {
+        log("AUTOPOLYGON: cannot reduce points for %s that has less than 3 points in input, e: %f", _filename.c_str(), epsilon);
+        return std::vector<Vec2>();
+    }
+    // if there are less than 9 points (but more than 3), then we don't need to reduce it
+    else if (size < 9)
+    {
+        log("AUTOPOLYGON: cannot reduce points for %s e: %f",_filename.c_str(), epsilon);
+        return points;
+    }
+    float maxEp = MIN(rect.size.width, rect.size.height);
+    float ep = clampf(epsilon, 0.0, maxEp/_scaleFactor/2);
+    std::vector<Vec2> result = rdp(points, ep);
+    
+    auto last = result.back();
+    if (last.y > result.front().y && last.getDistance(result.front()) < ep * 0.5f)
+    {
+        result.front().y = last.y;
+        result.pop_back();
+    }
+    return result;
+}
+
+std::vector<Vec2> AutoPolygon::expand(const std::vector<Vec2>& points, const cocos2d::Rect &rect, float epsilon)
+{
+    auto size = points.size();
+    // if there are less than 3 points, then we have nothing
+    if(size<3)
+    {
+        log("AUTOPOLYGON: cannot expand points for %s with less than 3 points, e: %f", _filename.c_str(), epsilon);
+        return std::vector<Vec2>();
+    }
+    ClipperLib::Path subj;
+    ClipperLib::PolyTree solution;
+    ClipperLib::PolyTree out;
+    for(const auto& pt : points)
+    {
+        subj << ClipperLib::IntPoint(pt.x* PRECISION, pt.y * PRECISION);
+    }
+    ClipperLib::ClipperOffset co;
+    co.AddPath(subj, ClipperLib::jtMiter, ClipperLib::etClosedPolygon);
+    co.Execute(solution, epsilon * PRECISION);
+    
+    ClipperLib::PolyNode* p = solution.GetFirst();
+    if(!p)
+    {
+        log("AUTOPOLYGON: Clipper failed to expand the points");
+        return points;
+    }
+    while(p->IsHole()){
+        p = p->GetNext();
+    }
+
+    //turn the result into simply polygon (AKA, fix overlap)
+    
+    //clamp into the specified rect
+    ClipperLib::Clipper cl;
+    cl.StrictlySimple(true);
+    cl.AddPath(p->Contour, ClipperLib::ptSubject, true);
+    //create the clipping rect
+    ClipperLib::Path clamp;
+    clamp.push_back(ClipperLib::IntPoint(0, 0));
+    clamp.push_back(ClipperLib::IntPoint(rect.size.width/_scaleFactor * PRECISION, 0));
+    clamp.push_back(ClipperLib::IntPoint(rect.size.width/_scaleFactor * PRECISION, rect.size.height/_scaleFactor * PRECISION));
+    clamp.push_back(ClipperLib::IntPoint(0, rect.size.height/_scaleFactor * PRECISION));
+    cl.AddPath(clamp, ClipperLib::ptClip, true);
+    cl.Execute(ClipperLib::ctIntersection, out);
+    
+    std::vector<Vec2> outPoints;
+    ClipperLib::PolyNode* p2 = out.GetFirst();
+    while(p2->IsHole()){
+        p2 = p2->GetNext();
+    }
+    for(const auto& pt : p2->Contour)
+    {
+        outPoints.push_back(Vec2(pt.X/PRECISION, pt.Y/PRECISION));
+    }
+    return outPoints;
+}
+
+TrianglesCommand::Triangles AutoPolygon::triangulate(const std::vector<Vec2>& points)
+{
+    // if there are less than 3 points, then we can't triangulate
+    if(points.size()<3)
+    {
+        log("AUTOPOLYGON: cannot triangulate %s with less than 3 points", _filename.c_str());
+        return TrianglesCommand::Triangles();
+    }
+    std::vector<p2t::Point*> p2points;
+    for(const auto& pt : points)
+    {
+        p2t::Point * p = new (std::nothrow) p2t::Point(pt.x, pt.y);
+        p2points.push_back(p);
+    }
+    p2t::CDT cdt(p2points);
+    cdt.Triangulate();
+    std::vector<p2t::Triangle*> tris = cdt.GetTriangles();
+    
+    // we won't know the size of verts and indices until we process all of the triangles!
+    std::vector<V3F_C4B_T2F> verts;
+    std::vector<unsigned short> indices;
+
+    unsigned short idx = 0;
+    unsigned short vdx = 0;
+
+    for(const auto& ite : tris)
+    {
+        for(int i = 0; i < 3; ++i)
+        {
+            auto p = ite->GetPoint(i);
+            auto v3 = Vec3(p->x, p->y, 0);
+            bool found = false;
+            size_t j;
+            size_t length = vdx;
+            for(j = 0; j < length; j++)
+            {
+                if(verts[j].vertices == v3)
+                {
+                    found = true;
+                    break;
+                }
+            }
+            if(found)
+            {
+                //if we found the same vertex, don't add to verts, but use the same vertex with indices
+                indices.push_back(j);
+                idx++;
+            }
+            else
+            {
+                //vert does not exist yet, so we need to create a new one,
+                auto c4b = Color4B::WHITE;
+                auto t2f = Tex2F(0,0); // don't worry about tex coords now, we calculate that later
+                V3F_C4B_T2F vert = {v3,c4b,t2f};
+                verts.push_back(vert);
+                indices.push_back(vdx);
+                idx++;
+                vdx++;
+            }
+        }
+    }
+    for(auto j : p2points)
+    {
+        delete j;
+    };
+
+    // now that we know the size of verts and indices we can create the buffers
+    V3F_C4B_T2F* vertsBuf = new (std::nothrow) V3F_C4B_T2F[verts.size()];
+    memcpy(vertsBuf, verts.data(), verts.size() * sizeof(V3F_C4B_T2F));
+
+    unsigned short* indicesBuf = new (std::nothrow) unsigned short[indices.size()];
+    memcpy(indicesBuf, indices.data(), indices.size() * sizeof(short));
+
+    // Triangles should really use std::vector and not arrays for verts and indices. 
+    // Then the above memcpy would not be necessary
+    TrianglesCommand::Triangles triangles = { vertsBuf, indicesBuf, static_cast<int>(verts.size()), static_cast<int>(indices.size()) };
+    return triangles;
+}
+
+void AutoPolygon::calculateUV(const Rect& rect, V3F_C4B_T2F* verts, ssize_t count)
+{
+    /*
+     whole texture UV coordination
+     0,0                  1,0
+     +---------------------+
+     |                     |0.1
+     |                     |0.2
+     |     +--------+      |0.3
+     |     |texRect |      |0.4
+     |     |        |      |0.5
+     |     |        |      |0.6
+     |     +--------+      |0.7
+     |                     |0.8
+     |                     |0.9
+     +---------------------+
+     0,1                  1,1
+     */
+    
+    CCASSERT(_width && _height, "please specify width and height for this AutoPolygon instance");
+    float texWidth  = _width;
+    float texHeight = _height;
+
+    auto end = &verts[count];
+    for(auto i = verts; i != end; ++i)
+    {
+        // for every point, offset with the center point
+        float u = (i->vertices.x*_scaleFactor + rect.origin.x) / texWidth;
+        float v = (rect.origin.y+rect.size.height - i->vertices.y*_scaleFactor) / texHeight;
+        i->texCoords.u = u;
+        i->texCoords.v = v;
+    }
+}
+
+Rect AutoPolygon::getRealRect(const Rect& rect)
+{
+    Rect realRect = rect;
+    //check rect to see if its zero
+    if(realRect.equals(Rect::ZERO))
+    {
+        //if the instance doesn't have width and height, then the whole operation is kaput
+        CCASSERT(_height && _width, "Please specify a width and height for this instance before using its functions");
+        realRect = Rect(0,0, _width, _height);
+    }
+    else{
+        //rect is specified, so convert to real rect
+        realRect = CC_RECT_POINTS_TO_PIXELS(rect);
+    }
+    return realRect;
+}
+
+PolygonInfo AutoPolygon::generateTriangles(const Rect& rect, float epsilon, float threshold)
+{
+    Rect realRect = getRealRect(rect);
+    auto p = trace(realRect, threshold);
+    p = reduce(p, realRect, epsilon);
+    p = expand(p, realRect, epsilon);
+    auto tri = triangulate(p);
+    calculateUV(realRect, tri.verts, tri.vertCount);
+    PolygonInfo ret;
+    ret.triangles = tri;
+    ret.setFilename(_filename);
+    ret.setRect(realRect);
+    return ret;
+}
+
+PolygonInfo AutoPolygon::generatePolygon(const std::string& filename, const Rect& rect, float epsilon, float threshold)
+{
+    AutoPolygon ap(filename);
+    return ap.generateTriangles(rect, epsilon, threshold);
+}

+ 287 - 0
cocos2d/cocos/2d/CCAutoPolygon.h

@@ -0,0 +1,287 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+
+#ifndef COCOS_2D_CCAUTOPOLYGON_H__
+#define COCOS_2D_CCAUTOPOLYGON_H__
+
+#include <string>
+#include <vector>
+#include "platform/CCImage.h"
+#include "renderer/CCTrianglesCommand.h"
+
+NS_CC_BEGIN
+
+/**
+ * @addtogroup _2d
+ * @{
+ */
+
+/**
+ * PolygonInfo is an object holding the required data to display Sprites.
+ * It can be a simple as a triangle, or as complex as a whole 3D mesh
+ */
+class CC_DLL PolygonInfo
+{
+public:
+    /// @name Creators
+    /// @{
+    /**
+     * Creates an empty Polygon info
+     * @memberof PolygonInfo
+     * @return PolygonInfo object
+     */
+    PolygonInfo();
+
+    /**
+     * Create an polygoninfo from the data of another Polygoninfo
+     * @param other     another PolygonInfo to be copied
+     * @return duplicate of the other PolygonInfo
+     */
+    PolygonInfo(const PolygonInfo& other);
+    //  end of creators group
+    /// @}
+    
+    /**
+     * Copy the member of the other PolygonInfo
+     * @param other     another PolygonInfo to be copied
+     */
+    PolygonInfo& operator= (const PolygonInfo &other);
+    ~PolygonInfo();
+    
+    /**
+     * set the data to be a pointer to a quad
+     * the member verts will not be released when this PolygonInfo destructs
+     * as the verts memory are managed by other objects
+     * @param quad  a pointer to the V3F_C4B_T2F_Quad object
+     */
+    void setQuad(V3F_C4B_T2F_Quad *quad);
+
+    /**
+     * set the data to be a pointer to a number of Quads
+     * the member verts will not be released when this PolygonInfo destructs
+     * as the verts memory are managed by other objects
+     * @param quad  a pointer to the V3F_C4B_T2F_Quad quads
+     */
+    void setQuads(V3F_C4B_T2F_Quad *quads, int numberOfQuads);
+
+
+    /**
+     * set the data to be a pointer to a triangles
+     * the member verts will not be released when this PolygonInfo destructs
+     * as the verts memory are managed by other objects
+     * @param triangles  a pointer to the TrianglesCommand::Triangles object
+     */
+    void setTriangles(const TrianglesCommand::Triangles& triangles);
+
+    /**
+     * get vertex count
+     * @return number of vertices
+     */
+    unsigned int getVertCount() const;
+    
+    /**
+     * get triangles count
+     * @return number of triangles
+     */
+    unsigned int getTrianglesCount() const;
+
+    /** @deprecated Use method getTrianglesCount() instead */
+    CC_DEPRECATED_ATTRIBUTE unsigned int getTriaglesCount() const;
+    
+    /**
+     * get sum of all triangle area size
+     * @return sum of all triangle area size
+     */
+    float getArea() const;
+
+    const Rect& getRect() const { return _rect; }
+    void setRect(const Rect& rect) { _rect = rect; }
+    const std::string& getFilename() const { return _filename; }
+    void setFilename(const std::string& filename ) { _filename = filename; }
+
+    // FIXME: this should be a property, not a public ivar
+    TrianglesCommand::Triangles triangles;
+
+protected:
+    bool _isVertsOwner;
+    Rect _rect;
+    std::string _filename;
+
+private:
+    void releaseVertsAndIndices();
+};
+
+
+/**
+ * AutoPolygon is a helper Object
+ * AutoPolygon's purpose is to process an image into 2d polygon mesh in runtime
+ * It has functions for each step in the process, from tracing all the points, to triangulation
+ * the result can be then passed to Sprite::create() to create a Polygon Sprite
+ */
+class CC_DLL AutoPolygon
+{
+public:
+    /**
+     * create an AutoPolygon and initialize it with an image file
+     * the image must be a 32bit PNG for current version 3.7
+     * @param   filename    a path to image file, e.g., "scene1/monster.png".
+     * @return  an AutoPolygon object;
+     */
+    AutoPolygon(const std::string &filename);
+    
+    /**
+     * Destructor of AutoPolygon.
+     */
+    ~AutoPolygon();
+    
+    /**
+     * trace all the points along the outline of the image, 
+     * @warning must create AutoPolygon with filename to use this function
+     * @param   rect    a texture rect for specify an area of the image
+     * @param   threshold   the value when alpha is greater than this value will be counted as opaque, default to 0.0
+     * @return  a vector of vec2 of all the points found in clockwise order
+     * @code
+     * auto ap = AutoPolygon("grossini.png");
+     * auto rect = Rect(100, 100, 200, 200);
+     * std::vector<Vec2> points = ap.trace(rect);//default threshold is 0.0
+     * @endcode
+     */
+     std::vector<Vec2> trace(const cocos2d::Rect& rect, float threshold = 0.0f);
+    
+    /**
+     * reduce the amount of points so its faster for GPU to process and draw
+     * based on Ramer-Douglas-Peucker algorithm
+     * @param   points  a vector of Vec2 points as input
+     * @param   rect    a texture rect for specify an area of the image to avoid over reduction
+     * @param   epsilon the perpendicular distance where points smaller than this value will be discarded
+     * @return  a vector of Vec2 of the remaining points in clockwise order
+     * @code
+     * auto ap = AutoPolygon();
+     * std::vector<Vec2> reduced = ap.reduce(inputPoints, rect);//default epsilon is 2
+     * @endcode
+     */
+    std::vector<Vec2> reduce(const std::vector<Vec2>& points, const Rect& rect, float epsilon = 2.0f);
+    
+    /**
+     * expand the points along their edge, useful after you reduce the points that cuts into the sprite
+     * using ClipperLib
+     * @param   points  a vector of Vec2 points as input
+     * @param   rect    a texture rect for specify an area of the image, the expanded points will be clamped in this rect, ultimately resulting in a quad if the expansion is too great
+     * @param   epsilon the distance which the edges will expand
+     * @return  a vector of Vec2 as the result of the expansion
+     * @code
+     * auto ap = AutoPolygon();
+     * std::vector<Vec2> expanded = ap.expand(inputPoints, rect, 2.0);
+     * @endcode
+     */
+    std::vector<Vec2> expand(const std::vector<Vec2>& points, const Rect& rect, float epsilon);
+    
+    /**
+     * Triangulate the input points into triangles for rendering
+     * using poly2tri
+     * @warning points must be closed loop, cannot have 2 points sharing the same position and cannot intersect itself
+     * @param   points  a vector of vec2 points as input
+     * @return  a Triangles object with points and indices
+     * @code
+     * auto ap = AutoPolygon();
+     * TrianglesCommand::Triangles myPolygons = ap.triangulate(myPoints);
+     * @endcode
+     */
+    TrianglesCommand::Triangles triangulate(const std::vector<Vec2>& points);
+    
+    /**
+     * calculate the UV coordinates for each points based on a texture rect
+     * @warning This method requires the AutoPolygon object to know the texture file dimension
+     * @param   rect    a texture rect to specify where to map the UV
+     * @param   verts   a pointer to the verts array, served both as input and output verts
+     * @param   count   the count for the verts array
+     * @code
+     * auto ap = AutoPolygon("grossini.png");
+     * TrianglesCommand::Triangles myPolygons = ap.triangulate(myPoints);
+     * ap.calculateUV(rect, myPolygons.verts, 20);
+     * @endcode
+     */
+    void calculateUV(const Rect& rect, V3F_C4B_T2F* verts, ssize_t count);
+    
+    /**
+     * a helper function, packing trace, reduce, expand, triangulate and calculate uv in one function
+     * @param   rect    texture rect, use Rect::ZERO for the size of the texture, default is Rect::ZERO
+     * @param   epsilon the value used to reduce and expand, default to 2.0
+     * @param   threshold   the value where bigger than the threshold will be counted as opaque, used in trace
+     * @return  a PolygonInfo, to use with sprite
+     * @code
+     * auto ap = AutoPolygon("grossini.png");
+     * PolygonInfo myInfo = ap.generateTriangles();//use all default values
+     * auto sp1 = Sprite::create(myInfo);
+     * polygonInfo myInfo2 = ap.generateTriangles(Rect::ZERO, 5.0, 0.1);//ap can be reused to generate another set of PolygonInfo with different settings
+     * auto sp2 = Sprite::create(myInfo2);
+     * @endcode
+     */
+    PolygonInfo generateTriangles(const Rect& rect = Rect::ZERO, float epsilon = 2.0f, float threshold = 0.05f);
+    
+    /**
+     * a helper function, packing autoPolygon creation, trace, reduce, expand, triangulate and calculate uv in one function
+     * @warning if you want to repetitively generate polygons, consider create an AutoPolygon object, and use generateTriangles function, as it only reads the file once
+     * @param   filename     A path to image file, e.g., "scene1/monster.png".
+     * @param   rect    texture rect, use Rect::ZERO for the size of the texture, default is Rect::ZERO
+     * @param   epsilon the value used to reduce and expand, default to 2.0
+     * @param   threshold   the value where bigger than the threshold will be counted as opaque, used in trace
+     * @return  a PolygonInfo, to use with sprite
+     * @code
+     * auto sp = Sprite::create(AutoPolygon::generatePolygon("grossini.png"));
+     * @endcode
+     */
+    static PolygonInfo generatePolygon(const std::string& filename, const Rect& rect = Rect::ZERO, float epsilon = 2.0f, float threshold = 0.05f);
+protected:
+    Vec2 findFirstNoneTransparentPixel(const Rect& rect, float threshold);
+    std::vector<cocos2d::Vec2> marchSquare(const Rect& rect, const Vec2& first, float threshold);
+    unsigned int getSquareValue(unsigned int x, unsigned int y, const Rect& rect, float threshold);
+
+    unsigned char getAlphaByIndex(unsigned int i);
+    unsigned char getAlphaByPos(const Vec2& pos);
+
+    int getIndexFromPos(unsigned int x, unsigned int y) { return y*_width+x; }
+    cocos2d::Vec2 getPosFromIndex(unsigned int i) { return cocos2d::Vec2(static_cast<float>(i%_width), static_cast<float>(i/_width)); }
+
+    std::vector<cocos2d::Vec2> rdp(const std::vector<cocos2d::Vec2>& v, float optimization);
+    float perpendicularDistance(const cocos2d::Vec2& i, const cocos2d::Vec2& start, const cocos2d::Vec2& end);
+
+    //real rect is the size that is in scale with the texture file
+    Rect getRealRect(const Rect& rect);
+    
+    Image* _image;
+    unsigned char * _data;
+    std::string _filename;
+    unsigned int _width;
+    unsigned int _height;
+    float _scaleFactor;
+    unsigned int _threshold;
+};
+
+NS_CC_END
+
+#endif // #ifndef COCOS_2D_CCAUTOPOLYGON_H__

+ 542 - 0
cocos2d/cocos/2d/CCCamera.cpp

@@ -0,0 +1,542 @@
+/****************************************************************************
+ Copyright (c) 2014-2017 Chukong Technologies 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.
+
+ Code based GamePlay3D's Camera: http://gameplay3d.org
+
+ ****************************************************************************/
+#include "2d/CCCamera.h"
+#include "2d/CCCameraBackgroundBrush.h"
+#include "base/CCDirector.h"
+#include "platform/CCGLView.h"
+#include "2d/CCScene.h"
+#include "renderer/CCRenderer.h"
+#include "renderer/CCQuadCommand.h"
+#include "renderer/CCGLProgramCache.h"
+#include "renderer/ccGLStateCache.h"
+#include "renderer/CCFrameBuffer.h"
+#include "renderer/CCRenderState.h"
+
+NS_CC_BEGIN
+
+Camera* Camera::_visitingCamera = nullptr;
+experimental::Viewport Camera::_defaultViewport;
+
+// start static methods
+
+Camera* Camera::create()
+{
+    Camera* camera = new (std::nothrow) Camera();
+    camera->initDefault();
+    camera->autorelease();
+    camera->setDepth(0.f);
+    
+    return camera;
+}
+
+Camera* Camera::createPerspective(float fieldOfView, float aspectRatio, float nearPlane, float farPlane)
+{
+    auto ret = new (std::nothrow) Camera();
+    if (ret)
+    {
+        ret->initPerspective(fieldOfView, aspectRatio, nearPlane, farPlane);
+        ret->autorelease();
+        return ret;
+    }
+    CC_SAFE_DELETE(ret);
+    return nullptr;
+}
+
+Camera* Camera::createOrthographic(float zoomX, float zoomY, float nearPlane, float farPlane)
+{
+    auto ret = new (std::nothrow) Camera();
+    if (ret)
+    {
+        ret->initOrthographic(zoomX, zoomY, nearPlane, farPlane);
+        ret->autorelease();
+        return ret;
+    }
+    CC_SAFE_DELETE(ret);
+    return nullptr;
+}
+
+Camera* Camera::getDefaultCamera()
+{
+    auto scene = Director::getInstance()->getRunningScene();
+    if(scene)
+    {
+        return scene->getDefaultCamera();
+    }
+
+    return nullptr;
+}
+
+const experimental::Viewport& Camera::getDefaultViewport()
+{
+    return _defaultViewport;
+}
+void Camera::setDefaultViewport(const experimental::Viewport& vp)
+{
+    _defaultViewport = vp;
+}
+
+const Camera* Camera::getVisitingCamera()
+{
+    return _visitingCamera;
+}
+
+// end static methods
+
+Camera::Camera()
+: _scene(nullptr)
+, _viewProjectionDirty(true)
+, _cameraFlag(1)
+, _frustumDirty(true)
+, _viewProjectionUpdated(false)
+, _depth(-1)
+, _fbo(nullptr)
+{
+    _frustum.setClipZ(true);
+    _clearBrush = CameraBackgroundBrush::createDepthBrush(1.f);
+    _clearBrush->retain();
+}
+
+Camera::~Camera()
+{
+    CC_SAFE_RELEASE_NULL(_fbo);
+    CC_SAFE_RELEASE(_clearBrush);
+}
+
+const Mat4& Camera::getProjectionMatrix() const
+{
+    return _projection;
+}
+const Mat4& Camera::getViewMatrix() const
+{
+    Mat4 viewInv(getNodeToWorldTransform());
+    static int count = sizeof(float) * 16;
+    if (memcmp(viewInv.m, _viewInv.m, count) != 0)
+    {
+        _viewProjectionDirty = true;
+        _frustumDirty = true;
+        _viewInv = viewInv;
+        _view = viewInv.getInversed();
+    }
+    return _view;
+}
+void Camera::lookAt(const Vec3& lookAtPos, const Vec3& up)
+{
+    Vec3 upv = up;
+    upv.normalize();
+    Vec3 zaxis;
+    Vec3::subtract(this->getPosition3D(), lookAtPos, &zaxis);
+    zaxis.normalize();
+    
+    Vec3 xaxis;
+    Vec3::cross(upv, zaxis, &xaxis);
+    xaxis.normalize();
+    
+    Vec3 yaxis;
+    Vec3::cross(zaxis, xaxis, &yaxis);
+    yaxis.normalize();
+    Mat4  rotation;
+    rotation.m[0] = xaxis.x;
+    rotation.m[1] = xaxis.y;
+    rotation.m[2] = xaxis.z;
+    rotation.m[3] = 0;
+    
+    rotation.m[4] = yaxis.x;
+    rotation.m[5] = yaxis.y;
+    rotation.m[6] = yaxis.z;
+    rotation.m[7] = 0;
+    rotation.m[8] = zaxis.x;
+    rotation.m[9] = zaxis.y;
+    rotation.m[10] = zaxis.z;
+    rotation.m[11] = 0;
+    
+    Quaternion  quaternion;
+    Quaternion::createFromRotationMatrix(rotation,&quaternion);
+    quaternion.normalize();
+    setRotationQuat(quaternion);
+}
+
+const Mat4& Camera::getViewProjectionMatrix() const
+{
+    getViewMatrix();
+    if (_viewProjectionDirty)
+    {
+        _viewProjectionDirty = false;
+        Mat4::multiply(_projection, _view, &_viewProjection);
+    }
+    
+    return _viewProjection;
+}
+
+void Camera::setAdditionalProjection(const Mat4& mat)
+{
+    _projection = mat * _projection;
+    getViewProjectionMatrix();
+}
+
+bool Camera::initDefault()
+{
+    auto size = Director::getInstance()->getWinSize();
+    //create default camera
+    auto projection = Director::getInstance()->getProjection();
+    switch (projection)
+    {
+        case Director::Projection::_2D:
+        {
+            initOrthographic(size.width, size.height, -1024, 1024);
+            setPosition3D(Vec3(0.0f, 0.0f, 0.0f));
+            setRotation3D(Vec3(0.f, 0.f, 0.f));
+            break;
+        }
+        case Director::Projection::_3D:
+        {
+            float zeye = Director::getInstance()->getZEye();
+            initPerspective(60, (GLfloat)size.width / size.height, 10, zeye + size.height / 2.0f);
+            Vec3 eye(size.width/2, size.height/2.0f, zeye), center(size.width/2, size.height/2, 0.0f), up(0.0f, 1.0f, 0.0f);
+            setPosition3D(eye);
+            lookAt(center, up);
+            break;
+        }
+        default:
+            CCLOG("unrecognized projection");
+            break;
+    }
+    return true;
+}
+
+bool Camera::initPerspective(float fieldOfView, float aspectRatio, float nearPlane, float farPlane)
+{
+    _fieldOfView = fieldOfView;
+    _aspectRatio = aspectRatio;
+    _nearPlane = nearPlane;
+    _farPlane = farPlane;
+    Mat4::createPerspective(_fieldOfView, _aspectRatio, _nearPlane, _farPlane, &_projection);
+    _viewProjectionDirty = true;
+    _frustumDirty = true;
+    
+    return true;
+}
+
+bool Camera::initOrthographic(float zoomX, float zoomY, float nearPlane, float farPlane)
+{
+    _zoom[0] = zoomX;
+    _zoom[1] = zoomY;
+    _nearPlane = nearPlane;
+    _farPlane = farPlane;
+    Mat4::createOrthographicOffCenter(0, _zoom[0], 0, _zoom[1], _nearPlane, _farPlane, &_projection);
+    _viewProjectionDirty = true;
+    _frustumDirty = true;
+    
+    return true;
+}
+
+Vec2 Camera::project(const Vec3& src) const
+{
+    Vec2 screenPos;
+    
+    auto viewport = Director::getInstance()->getWinSize();
+    Vec4 clipPos;
+    getViewProjectionMatrix().transformVector(Vec4(src.x, src.y, src.z, 1.0f), &clipPos);
+    
+    CCASSERT(clipPos.w != 0.0f, "clipPos.w can't be 0.0f!");
+    float ndcX = clipPos.x / clipPos.w;
+    float ndcY = clipPos.y / clipPos.w;
+    
+    screenPos.x = (ndcX + 1.0f) * 0.5f * viewport.width;
+    screenPos.y = (1.0f - (ndcY + 1.0f) * 0.5f) * viewport.height;
+    return screenPos;
+}
+
+Vec2 Camera::projectGL(const Vec3& src) const
+{
+    Vec2 screenPos;
+    
+    auto viewport = Director::getInstance()->getWinSize();
+    Vec4 clipPos;
+    getViewProjectionMatrix().transformVector(Vec4(src.x, src.y, src.z, 1.0f), &clipPos);
+    
+    CCASSERT(clipPos.w != 0.0f, "clipPos.w can't be 0.0f!");
+    float ndcX = clipPos.x / clipPos.w;
+    float ndcY = clipPos.y / clipPos.w;
+    
+    screenPos.x = (ndcX + 1.0f) * 0.5f * viewport.width;
+    screenPos.y = (ndcY + 1.0f) * 0.5f * viewport.height;
+    return screenPos;
+}
+
+Vec3 Camera::unproject(const Vec3& src) const
+{
+    Vec3 dst;
+    unproject(Director::getInstance()->getWinSize(), &src, &dst);
+    return dst;
+}
+
+Vec3 Camera::unprojectGL(const Vec3& src) const
+{
+    Vec3 dst;
+    unprojectGL(Director::getInstance()->getWinSize(), &src, &dst);
+    return dst;
+}
+
+void Camera::unproject(const Size& viewport, const Vec3* src, Vec3* dst) const
+{
+    CCASSERT(src && dst, "vec3 can not be null");
+    
+    Vec4 screen(src->x / viewport.width, ((viewport.height - src->y)) / viewport.height, src->z, 1.0f);
+    screen.x = screen.x * 2.0f - 1.0f;
+    screen.y = screen.y * 2.0f - 1.0f;
+    screen.z = screen.z * 2.0f - 1.0f;
+    
+    getViewProjectionMatrix().getInversed().transformVector(screen, &screen);
+    if (screen.w != 0.0f)
+    {
+        screen.x /= screen.w;
+        screen.y /= screen.w;
+        screen.z /= screen.w;
+    }
+    
+    dst->set(screen.x, screen.y, screen.z);
+}
+
+void Camera::unprojectGL(const Size& viewport, const Vec3* src, Vec3* dst) const
+{
+    CCASSERT(src && dst, "vec3 can not be null");
+    
+    Vec4 screen(src->x / viewport.width, src->y / viewport.height, src->z, 1.0f);
+    screen.x = screen.x * 2.0f - 1.0f;
+    screen.y = screen.y * 2.0f - 1.0f;
+    screen.z = screen.z * 2.0f - 1.0f;
+    
+    getViewProjectionMatrix().getInversed().transformVector(screen, &screen);
+    if (screen.w != 0.0f)
+    {
+        screen.x /= screen.w;
+        screen.y /= screen.w;
+        screen.z /= screen.w;
+    }
+    
+    dst->set(screen.x, screen.y, screen.z);
+}
+
+bool Camera::isVisibleInFrustum(const AABB* aabb) const
+{
+    if (_frustumDirty)
+    {
+        _frustum.initFrustum(this);
+        _frustumDirty = false;
+    }
+    return !_frustum.isOutOfFrustum(*aabb);
+}
+
+float Camera::getDepthInView(const Mat4& transform) const
+{
+    Mat4 camWorldMat = getNodeToWorldTransform();
+    const Mat4 &viewMat = camWorldMat.getInversed();
+    float depth = -(viewMat.m[2] * transform.m[12] + viewMat.m[6] * transform.m[13] + viewMat.m[10] * transform.m[14] + viewMat.m[14]);
+    return depth;
+}
+
+void Camera::setDepth(int8_t depth)
+{
+    if (_depth != depth)
+    {
+        _depth = depth;
+        if (_scene)
+        {
+            //notify scene that the camera order is dirty
+            _scene->setCameraOrderDirty();
+        }
+    }
+}
+
+void Camera::onEnter()
+{
+    if (_scene == nullptr)
+    {
+        auto scene = getScene();
+        if (scene)
+        {
+            setScene(scene);
+        }
+    }
+    Node::onEnter();
+}
+
+void Camera::onExit()
+{
+    // remove this camera from scene
+    setScene(nullptr);
+    Node::onExit();
+}
+
+void Camera::setScene(Scene* scene)
+{
+    if (_scene != scene)
+    {
+        //remove old scene
+        if (_scene)
+        {
+            auto& cameras = _scene->_cameras;
+            auto it = std::find(cameras.begin(), cameras.end(), this);
+            if (it != cameras.end())
+                cameras.erase(it);
+            _scene = nullptr;
+        }
+        //set new scene
+        if (scene)
+        {
+            _scene = scene;
+            auto& cameras = _scene->_cameras;
+            auto it = std::find(cameras.begin(), cameras.end(), this);
+            if (it == cameras.end())
+            {
+                _scene->_cameras.push_back(this);
+                //notify scene that the camera order is dirty
+                _scene->setCameraOrderDirty();
+            }
+        }
+    }
+}
+
+void Camera::clearBackground()
+{
+    if (_clearBrush)
+    {
+        _clearBrush->drawBackground(this);
+    }
+}
+
+void Camera::setFrameBufferObject(experimental::FrameBuffer *fbo)
+{
+    CC_SAFE_RETAIN(fbo);
+    CC_SAFE_RELEASE_NULL(_fbo);
+    _fbo = fbo;
+    if(_scene)
+    {
+        _scene->setCameraOrderDirty();
+    }
+}
+
+void Camera::apply()
+{
+    _viewProjectionUpdated = _transformUpdated;
+    applyFrameBufferObject();
+    applyViewport();
+}
+
+void Camera::applyFrameBufferObject()
+{
+    if(nullptr == _fbo)
+    {
+        // inherit from context if it doesn't have a FBO
+        // don't call apply the default one
+//        experimental::FrameBuffer::applyDefaultFBO();
+    }
+    else
+    {
+        _fbo->applyFBO();
+    }
+}
+
+void Camera::applyViewport()
+{
+    glGetIntegerv(GL_VIEWPORT, _oldViewport);
+
+    if(nullptr == _fbo)
+    {
+        glViewport(getDefaultViewport()._left, getDefaultViewport()._bottom, getDefaultViewport()._width, getDefaultViewport()._height);
+    }
+    else
+    {
+        glViewport(_viewport._left * _fbo->getWidth(), _viewport._bottom * _fbo->getHeight(),
+                   _viewport._width * _fbo->getWidth(), _viewport._height * _fbo->getHeight());
+    }
+}
+
+void Camera::setViewport(const experimental::Viewport& vp)
+{
+    _viewport = vp;
+}
+
+void Camera::restore()
+{
+    restoreFrameBufferObject();
+    restoreViewport();
+}
+
+void Camera::restoreFrameBufferObject()
+{
+    if(nullptr == _fbo)
+    {
+        // it was inherited from context if it doesn't have a FBO
+        // don't call restore the default one... just keep using the previous one
+//        experimental::FrameBuffer::applyDefaultFBO();
+    }
+    else
+    {
+        _fbo->restoreFBO();
+    }
+}
+
+void Camera::restoreViewport()
+{
+    glViewport(_oldViewport[0], _oldViewport[1], _oldViewport[2], _oldViewport[3]);
+}
+
+int Camera::getRenderOrder() const
+{
+    int result(0);
+    if(_fbo)
+    {
+        result = _fbo->getFID()<<8;
+    }
+    else
+    {
+        result = 127 <<8;
+    }
+    result += _depth;
+    return result;
+}
+
+void Camera::visit(Renderer* renderer, const Mat4 &parentTransform, uint32_t parentFlags)
+{
+    _viewProjectionUpdated = _transformUpdated;
+    return Node::visit(renderer, parentTransform, parentFlags);
+}
+
+void Camera::setBackgroundBrush(CameraBackgroundBrush* clearBrush)
+{
+    CC_SAFE_RETAIN(clearBrush);
+    CC_SAFE_RELEASE(_clearBrush);
+    _clearBrush = clearBrush;
+}
+
+bool Camera::isBrushValid()
+{
+    return _clearBrush != nullptr && _clearBrush->isValid();
+}
+
+NS_CC_END

+ 340 - 0
cocos2d/cocos/2d/CCCamera.h

@@ -0,0 +1,340 @@
+/****************************************************************************
+Copyright (c) 2014-2017 Chukong Technologies 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.
+
+ Code based GamePlay3D's Camera: http://gameplay3d.org
+
+ ****************************************************************************/
+#ifndef _CCCAMERA_H__
+#define _CCCAMERA_H__
+
+#include "2d/CCNode.h"
+#include "3d/CCFrustum.h"
+#include "renderer/CCQuadCommand.h"
+#include "renderer/CCCustomCommand.h"
+#include "renderer/CCFrameBuffer.h"
+
+NS_CC_BEGIN
+
+class Scene;
+class CameraBackgroundBrush;
+
+/**
+ * Note: 
+ * Scene creates a default camera. And the default camera mask of Node is 1, therefore it can be seen by the default camera.
+ * During rendering the scene, it draws the objects seen by each camera in the added order except default camera. The default camera is the last one being drawn with.
+ * It's usually a good idea to render 3D objects in a separate camera.
+ * And set the 3d camera flag to CameraFlag::USER1 or anything else except DEFAULT. Dedicate The DEFAULT camera for UI, because it is rendered at last.
+ * You can change the camera order to get different result when depth test is not enabled.
+ * For each camera, transparent 3d sprite is rendered after opaque 3d sprite and other 2d objects.
+ */
+enum class CameraFlag
+{
+    DEFAULT = 1,
+    USER1 = 1 << 1,
+    USER2 = 1 << 2,
+    USER3 = 1 << 3,
+    USER4 = 1 << 4,
+    USER5 = 1 << 5,
+    USER6 = 1 << 6,
+    USER7 = 1 << 7,
+    USER8 = 1 << 8,
+};
+/**
+ * Defines a camera .
+ */
+class CC_DLL Camera :public Node
+{
+    friend class Scene;
+    friend class Director;
+    friend class EventDispatcher;
+public:
+    /**
+    * The type of camera.
+    */
+    enum class Type
+    {
+        PERSPECTIVE = 1,
+        ORTHOGRAPHIC = 2
+    };
+public:
+    /**
+    * Creates a perspective camera.
+    *
+    * @param fieldOfView The field of view for the perspective camera (normally in the range of 40-60 degrees).
+    * @param aspectRatio The aspect ratio of the camera (normally the width of the viewport divided by the height of the viewport).
+    * @param nearPlane The near plane distance.
+    * @param farPlane The far plane distance.
+    */
+    static Camera* createPerspective(float fieldOfView, float aspectRatio, float nearPlane, float farPlane);
+    /**
+    * Creates an orthographic camera.
+    *
+    * @param zoomX The zoom factor along the X-axis of the orthographic projection (the width of the ortho projection).
+    * @param zoomY The zoom factor along the Y-axis of the orthographic projection (the height of the ortho projection).
+    * @param nearPlane The near plane distance.
+    * @param farPlane The far plane distance.
+    */
+    static Camera* createOrthographic(float zoomX, float zoomY, float nearPlane, float farPlane);
+
+    /** create default camera, the camera type depends on Director::getProjection, the depth of the default camera is 0 */
+    static Camera* create();
+
+    /**
+     * Get the visiting camera , the visiting camera shall be set on Scene::render
+     */
+    static const Camera* getVisitingCamera();
+
+    static const experimental::Viewport& getDefaultViewport();
+    static void setDefaultViewport(const experimental::Viewport& vp);
+
+    /**
+     * Get the default camera of the current running scene.
+     */
+    static Camera* getDefaultCamera();
+
+    /**
+    * Gets the type of camera.
+    *
+    * @return The camera type.
+    */
+    Camera::Type getType() const { return _type; }
+
+    /**get & set Camera flag*/
+    CameraFlag getCameraFlag() const { return (CameraFlag)_cameraFlag; }
+    void setCameraFlag(CameraFlag flag) { _cameraFlag = (unsigned short)flag; }
+
+    /**
+    * Make Camera looks at target
+    *
+    * @param target The target camera is point at
+    * @param up The up vector, usually it's Y axis
+    */
+    virtual void lookAt(const Vec3& target, const Vec3& up = Vec3::UNIT_Y);
+
+    /**
+    * Gets the camera's projection matrix.
+    *
+    * @return The camera projection matrix.
+    */
+    const Mat4& getProjectionMatrix() const;
+    /**
+    * Gets the camera's view matrix.
+    *
+    * @return The camera view matrix.
+    */
+    const Mat4& getViewMatrix() const;
+
+    /**get view projection matrix*/
+    const Mat4& getViewProjectionMatrix() const;
+    
+    /* convert the specified point in 3D world-space coordinates into the screen-space coordinates.
+     *
+     * Origin point at left top corner in screen-space.
+     * @param src The world-space position.
+     * @return The screen-space position.
+     */
+    Vec2 project(const Vec3& src) const;
+    
+    /* convert the specified point in 3D world-space coordinates into the GL-screen-space coordinates.
+     *
+     * Origin point at left bottom corner in GL-screen-space.
+     * @param src The 3D world-space position.
+     * @return The GL-screen-space position.
+     */
+    Vec2 projectGL(const Vec3& src) const;
+    
+    /**
+     * Convert the specified point of screen-space coordinate into the 3D world-space coordinate.
+     *
+     * Origin point at left top corner in screen-space.
+     * @param src The screen-space position.
+     * @return The 3D world-space position.
+     */
+    Vec3 unproject(const Vec3& src) const;
+    
+    /**
+     * Convert the specified point of GL-screen-space coordinate into the 3D world-space coordinate.
+     *
+     * Origin point at left bottom corner in GL-screen-space.
+     * @param src The GL-screen-space position.
+     * @return The 3D world-space position.
+     */
+    Vec3 unprojectGL(const Vec3& src) const;
+    
+    /**
+     * Convert the specified point of screen-space coordinate into the 3D world-space coordinate.
+     *
+     * Origin point at left top corner in screen-space.
+     * @param size The window size to use.
+     * @param src  The screen-space position.
+     * @param dst  The 3D world-space position.
+     */
+    void unproject(const Size& size, const Vec3* src, Vec3* dst) const;
+    
+    /**
+     * Convert the specified point of GL-screen-space coordinate into the 3D world-space coordinate.
+     *
+     * Origin point at left bottom corner in GL-screen-space.
+     * @param size The window size to use.
+     * @param src  The GL-screen-space position.
+     * @param dst  The 3D world-space position.
+     */
+    void unprojectGL(const Size& size, const Vec3* src, Vec3* dst) const;
+
+    /**
+     * Is this aabb visible in frustum
+     */
+    bool isVisibleInFrustum(const AABB* aabb) const;
+    
+    /**
+     * Get object depth towards camera
+     */
+    float getDepthInView(const Mat4& transform) const;
+    
+    /**
+     * set depth, camera with larger depth is drawn on top of camera with smaller depth, the depth of camera with CameraFlag::DEFAULT is 0, user defined camera is -1 by default
+     */
+    void setDepth(int8_t depth);
+    
+    /**
+     * get depth, camera with larger depth is drawn on top of camera with smaller depth, the depth of camera with CameraFlag::DEFAULT is 0, user defined camera is -1 by default
+     */
+    int8_t getDepth() const { return _depth; }
+    
+    /**
+     get rendered order
+     */
+    int getRenderOrder() const;
+    
+    /**
+     * Get the frustum's far plane.
+     */
+    float getFarPlane() const { return _farPlane; }
+
+    /**
+     * Get the frustum's near plane.
+     */
+    float getNearPlane() const { return _nearPlane; }
+    
+    //override
+    virtual void onEnter() override;
+    virtual void onExit() override;
+
+    /**
+     Before rendering scene with this camera, the background need to be cleared. It clears the depth buffer with max depth by default. Use setBackgroundBrush to modify the default behavior
+     */
+    void clearBackground();
+    /**
+     Apply the FBO, RenderTargets and viewport.
+     */
+    void apply();
+    /**
+     Restore the FBO, RenderTargets and viewport.
+     */
+    void restore();
+
+    /**
+     Set FBO, which will attach several render target for the rendered result.
+     */
+    void setFrameBufferObject(experimental::FrameBuffer* fbo);
+    /**
+     Set Viewport for camera.
+     */
+    void setViewport(const experimental::Viewport& vp);
+
+    /**
+     * Whether or not the viewprojection matrix was updated since the last frame.
+     * @return True if the viewprojection matrix was updated since the last frame.
+     */
+    bool isViewProjectionUpdated() const {return _viewProjectionUpdated;}
+
+    /**
+     * set the background brush. See CameraBackgroundBrush for more information.
+     * @param clearBrush Brush used to clear the background
+     */
+    void setBackgroundBrush(CameraBackgroundBrush* clearBrush);
+
+    /**
+     * Get clear brush
+     */
+    CameraBackgroundBrush* getBackgroundBrush() const { return _clearBrush; }
+
+    virtual void visit(Renderer* renderer, const Mat4 &parentTransform, uint32_t parentFlags) override;
+
+    bool isBrushValid();
+
+CC_CONSTRUCTOR_ACCESS:
+    Camera();
+    ~Camera();
+
+    /**
+     * Set the scene,this method shall not be invoke manually
+     */
+    void setScene(Scene* scene);
+
+    /**set additional matrix for the projection matrix, it multiplies mat to projection matrix when called, used by WP8*/
+    void setAdditionalProjection(const Mat4& mat);
+
+    /** init camera */
+    bool initDefault();
+    bool initPerspective(float fieldOfView, float aspectRatio, float nearPlane, float farPlane);
+    bool initOrthographic(float zoomX, float zoomY, float nearPlane, float farPlane);
+    void applyFrameBufferObject();
+    void applyViewport();
+    void restoreFrameBufferObject();
+    void restoreViewport();
+
+protected:
+    static Camera* _visitingCamera;
+    static experimental::Viewport _defaultViewport;
+
+    Scene* _scene; //Scene camera belongs to
+    Mat4 _projection;
+    mutable Mat4 _view;
+    mutable Mat4 _viewInv;
+    mutable Mat4 _viewProjection;
+
+    Vec3 _up;
+    Camera::Type _type;
+    float _fieldOfView;
+    float _zoom[2];
+    float _aspectRatio;
+    float _nearPlane;
+    float _farPlane;
+    mutable bool  _viewProjectionDirty;
+    bool _viewProjectionUpdated; //Whether or not the viewprojection matrix was updated since the last frame.
+    unsigned short _cameraFlag; // camera flag
+    mutable Frustum _frustum;   // camera frustum
+    mutable bool _frustumDirty;
+    int8_t  _depth;                 //camera depth, the depth of camera with CameraFlag::DEFAULT flag is 0 by default, a camera with larger depth is drawn on top of camera with smaller depth
+
+    CameraBackgroundBrush* _clearBrush; //brush used to clear the back ground
+
+    experimental::Viewport _viewport;
+    experimental::FrameBuffer* _fbo;
+    GLint _oldViewport[4];
+};
+
+NS_CC_END
+
+#endif// __CCCAMERA_H_

+ 498 - 0
cocos2d/cocos/2d/CCCameraBackgroundBrush.cpp

@@ -0,0 +1,498 @@
+/****************************************************************************
+ Copyright (c) 2015-2017 Chukong Technologies 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 "2d/CCCameraBackgroundBrush.h"
+#include "2d/CCCamera.h"
+#include "base/ccMacros.h"
+#include "base/CCConfiguration.h"
+#include "base/CCDirector.h"
+#include "renderer/ccGLStateCache.h"
+#include "renderer/CCGLProgram.h"
+#include "renderer/CCGLProgramCache.h"
+#include "renderer/CCGLProgramState.h"
+#include "renderer/CCRenderer.h"
+#include "renderer/CCRenderState.h"
+#include "renderer/CCTextureCube.h"
+
+#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
+#include "base/CCEventCustom.h"
+#include "base/CCEventListenerCustom.h"
+#include "base/CCEventType.h"
+#include "base/CCEventDispatcher.h"
+#endif
+
+NS_CC_BEGIN
+
+CameraBackgroundBrush::CameraBackgroundBrush()
+: _glProgramState(nullptr)
+{
+    
+}
+
+CameraBackgroundBrush::~CameraBackgroundBrush()
+{
+    CC_SAFE_RELEASE(_glProgramState);
+}
+
+CameraBackgroundBrush* CameraBackgroundBrush::createNoneBrush()
+{
+    auto ret = new (std::nothrow) CameraBackgroundBrush();
+    ret->init();
+    
+    ret->autorelease();
+    return ret;
+}
+
+CameraBackgroundColorBrush* CameraBackgroundBrush::createColorBrush(const Color4F& color, float depth)
+{
+    return CameraBackgroundColorBrush::create(color, depth);
+}
+
+CameraBackgroundDepthBrush* CameraBackgroundBrush::createDepthBrush(float depth)
+{
+    return CameraBackgroundDepthBrush::create(depth);
+}
+
+CameraBackgroundSkyBoxBrush* CameraBackgroundBrush::createSkyboxBrush(const std::string& positive_x, const std::string& negative_x, const std::string& positive_y, const std::string& negative_y, const std::string& positive_z, const std::string& negative_z)
+{
+    return CameraBackgroundSkyBoxBrush::create(positive_x, negative_x, positive_y, negative_y, positive_z, negative_z);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+CameraBackgroundDepthBrush::CameraBackgroundDepthBrush()
+: _depth(0.f)
+, _clearColor(GL_FALSE)
+{
+    
+}
+CameraBackgroundDepthBrush::~CameraBackgroundDepthBrush()
+{
+    
+}
+
+CameraBackgroundDepthBrush* CameraBackgroundDepthBrush::create(float depth)
+{
+    auto ret = new (std::nothrow) CameraBackgroundDepthBrush();
+    
+    if (nullptr != ret && ret->init())
+    {
+        ret->_depth = depth;
+        ret->autorelease();
+    }
+    else
+    {
+        CC_SAFE_DELETE(ret);
+    }
+
+    return ret;
+}
+
+bool CameraBackgroundDepthBrush::init()
+{
+    auto shader = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_CAMERA_CLEAR);
+    _glProgramState = GLProgramState::getOrCreateWithGLProgram(shader);
+    _glProgramState->retain();
+    
+    _quad.bl.vertices = Vec3(-1,-1,0);
+    _quad.br.vertices = Vec3(1,-1,0);
+    _quad.tl.vertices = Vec3(-1,1,0);
+    _quad.tr.vertices = Vec3(1,1,0);
+    
+    _quad.bl.colors = _quad.br.colors = _quad.tl.colors = _quad.tr.colors = Color4B(0,0,0,1);
+    
+    _quad.bl.texCoords = Tex2F(0,0);
+    _quad.br.texCoords = Tex2F(1,0);
+    _quad.tl.texCoords = Tex2F(0,1);
+    _quad.tr.texCoords = Tex2F(1,1);
+    return true;
+}
+
+void CameraBackgroundDepthBrush::drawBackground(Camera* /*camera*/)
+{
+    GLboolean oldDepthTest;
+    GLint oldDepthFunc;
+    GLboolean oldDepthMask;
+    {
+        glColorMask(_clearColor, _clearColor, _clearColor, _clearColor);
+        glStencilMask(0);
+        
+        oldDepthTest = glIsEnabled(GL_DEPTH_TEST);
+        glGetIntegerv(GL_DEPTH_FUNC, &oldDepthFunc);
+        glGetBooleanv(GL_DEPTH_WRITEMASK, &oldDepthMask);
+        
+        glDepthMask(GL_TRUE);
+        glEnable(GL_DEPTH_TEST);
+        glDepthFunc(GL_ALWAYS);
+    }
+    
+    //draw
+    
+    _glProgramState->setUniformFloat("depth", _depth);
+    _glProgramState->apply(Mat4::IDENTITY);
+    GLshort indices[6] = {0, 1, 2, 3, 2, 1};
+    
+    {
+        GL::bindVAO(0);
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
+        
+        GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);
+        
+        // vertices
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), &_quad.tl.vertices);
+        
+        // colors
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V3F_C4B_T2F), &_quad.tl.colors);
+        
+        // tex coords
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), &_quad.tl.texCoords);
+        
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+    }
+    
+    
+    {
+        if(GL_FALSE == oldDepthTest)
+        {
+            glDisable(GL_DEPTH_TEST);
+        }
+        glDepthFunc(oldDepthFunc);
+        
+        if(GL_FALSE == oldDepthMask)
+        {
+            glDepthMask(GL_FALSE);
+        }
+        
+        /* IMPORTANT: We only need to update the states that are not restored.
+         Since we don't know what was the previous value of the mask, we update the RenderState
+         after setting it.
+         The other values don't need to be updated since they were restored to their original values
+         */
+        glStencilMask(0xFFFFF);
+        //        RenderState::StateBlock::_defaultState->setStencilWrite(0xFFFFF);
+        
+        /* BUG: RenderState does not support glColorMask yet. */
+        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+CameraBackgroundColorBrush::CameraBackgroundColorBrush()
+: _color(0.f, 0.f, 0.f, 0.f)
+{
+    
+}
+
+CameraBackgroundColorBrush::~CameraBackgroundColorBrush()
+{
+    
+}
+
+bool CameraBackgroundColorBrush::init()
+{
+    CameraBackgroundDepthBrush::init();
+    this->_clearColor = GL_TRUE;
+    return true;
+}
+
+void CameraBackgroundColorBrush::setColor(const Color4F& color)
+{
+    _quad.bl.colors = _quad.br.colors = _quad.tl.colors = _quad.tr.colors = Color4B(color);
+}
+
+CameraBackgroundColorBrush* CameraBackgroundColorBrush::create(const Color4F& color, float depth)
+{
+    auto ret = new (std::nothrow) CameraBackgroundColorBrush();
+
+    if (nullptr != ret && ret->init())
+    {
+        ret->setColor(color);
+        ret->setDepth(depth);
+        ret->autorelease();
+    }
+    else
+    {
+        CC_SAFE_DELETE(ret);
+    }
+
+    return ret;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+CameraBackgroundSkyBoxBrush::CameraBackgroundSkyBoxBrush()
+: _vao(0)
+, _vertexBuffer(0)
+, _indexBuffer(0)
+, _texture(nullptr)
+, _actived(true)
+, _textureValid(true)
+{
+#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
+    _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED,
+                                                            [this](EventCustom*)
+                                                            {
+                                                                initBuffer();
+                                                            }
+                                                            );
+    Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1);
+#endif
+}
+
+CameraBackgroundSkyBoxBrush::~CameraBackgroundSkyBoxBrush()
+{
+    CC_SAFE_RELEASE(_texture);
+    
+    glDeleteBuffers(1, &_vertexBuffer);
+    glDeleteBuffers(1, &_indexBuffer);
+    
+    _vertexBuffer = 0;
+    _indexBuffer = 0;
+    
+    if (Configuration::getInstance()->supportsShareableVAO())
+    {
+        glDeleteVertexArrays(1, &_vao);
+        GL::bindVAO(0);
+        _vao = 0;
+    }
+}
+
+CameraBackgroundSkyBoxBrush* CameraBackgroundSkyBoxBrush::create(
+    const std::string& positive_x,
+    const std::string& negative_x,
+    const std::string& positive_y,
+    const std::string& negative_y,
+    const std::string& positive_z,
+    const std::string& negative_z
+    )
+{
+    CameraBackgroundSkyBoxBrush* ret = nullptr;
+
+    auto texture = TextureCube::create(positive_x,
+                                       negative_x,
+                                       positive_y,
+                                       negative_y,
+                                       positive_z,
+                                       negative_z);
+
+    if (texture != nullptr)
+    {
+
+        Texture2D::TexParams tRepeatParams;
+        tRepeatParams.magFilter = GL_LINEAR;
+        tRepeatParams.minFilter = GL_LINEAR;
+        tRepeatParams.wrapS = GL_CLAMP_TO_EDGE;
+        tRepeatParams.wrapT = GL_CLAMP_TO_EDGE;
+        texture->setTexParameters(tRepeatParams);
+
+        ret = new (std::nothrow) CameraBackgroundSkyBoxBrush;
+
+        if (nullptr != ret && ret->init())
+        {
+            ret->setTexture(texture);
+            ret->autorelease();
+        }
+        else
+        {
+            CC_SAFE_DELETE(texture);
+            CC_SAFE_DELETE(ret);
+        }
+    }
+
+    return ret;
+}
+
+CameraBackgroundSkyBoxBrush* CameraBackgroundSkyBoxBrush::create()
+{
+    auto ret = new (std::nothrow) CameraBackgroundSkyBoxBrush();
+    
+    if (nullptr != ret && ret->init())
+    {
+        ret->autorelease();
+    }
+    else
+    {
+        CC_SAFE_DELETE(ret);
+    }
+
+    return ret;
+}
+
+void CameraBackgroundSkyBoxBrush::drawBackground(Camera* camera)
+{
+    if (!_actived)
+        return;
+
+    Mat4 cameraModelMat = camera->getNodeToWorldTransform();
+    
+    Vec4 color(1.f, 1.f, 1.f, 1.f);
+    _glProgramState->setUniformVec4("u_color", color);
+    cameraModelMat.m[12] = cameraModelMat.m[13] = cameraModelMat.m[14] = 0;
+    _glProgramState->setUniformMat4("u_cameraRot", cameraModelMat);
+    
+    _glProgramState->apply(Mat4::IDENTITY);
+    
+    glEnable(GL_DEPTH_TEST);
+    RenderState::StateBlock::_defaultState->setDepthTest(true);
+    
+    glDepthMask(GL_TRUE);
+    RenderState::StateBlock::_defaultState->setDepthWrite(true);
+    
+    glDepthFunc(GL_ALWAYS);
+    RenderState::StateBlock::_defaultState->setDepthFunction(RenderState::DEPTH_ALWAYS);
+    
+    glEnable(GL_CULL_FACE);
+    RenderState::StateBlock::_defaultState->setCullFace(true);
+    
+    glCullFace(GL_BACK);
+    RenderState::StateBlock::_defaultState->setCullFaceSide(RenderState::CULL_FACE_SIDE_BACK);
+    
+    glDisable(GL_BLEND);
+    RenderState::StateBlock::_defaultState->setBlend(false);
+    
+    if (Configuration::getInstance()->supportsShareableVAO())
+    {
+        GL::bindVAO(_vao);
+    }
+    else
+    {
+        GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION);
+        
+        glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), nullptr);
+        
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
+    }
+    
+    glDrawElements(GL_TRIANGLES, (GLsizei)36, GL_UNSIGNED_BYTE, nullptr);
+    
+    if (Configuration::getInstance()->supportsShareableVAO())
+    {
+        GL::bindVAO(0);
+    }
+    else
+    {
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    }
+    
+    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 8);
+    
+    CHECK_GL_ERROR_DEBUG();
+}
+
+bool CameraBackgroundSkyBoxBrush::init()
+{
+    auto shader = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_SKYBOX);
+    _glProgramState = GLProgramState::create(shader);
+    _glProgramState->setVertexAttribPointer(GLProgram::ATTRIBUTE_NAME_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), nullptr);
+    _glProgramState->retain();
+    
+    initBuffer();
+    
+    return true;
+}
+
+void CameraBackgroundSkyBoxBrush::initBuffer()
+{
+    if (_vertexBuffer)
+        glDeleteBuffers(1, &_vertexBuffer);
+    if (_indexBuffer)
+        glDeleteBuffers(1, &_indexBuffer);
+    
+    if (Configuration::getInstance()->supportsShareableVAO() && _vao)
+    {
+        glDeleteVertexArrays(1, &_vao);
+        GL::bindVAO(0);
+        _vao = 0;
+    }
+    
+    if (Configuration::getInstance()->supportsShareableVAO())
+    {
+        glGenVertexArrays(1, &_vao);
+        GL::bindVAO(_vao);
+    }
+    
+    // init vertex buffer object
+    Vec3 vexBuf[] =
+    {
+        Vec3(1, -1, 1),  Vec3(1, 1, 1),  Vec3(-1, 1, 1),  Vec3(-1, -1, 1),
+        Vec3(1, -1, -1), Vec3(1, 1, -1), Vec3(-1, 1, -1), Vec3(-1, -1, -1)
+    };
+    
+    glGenBuffers(1, &_vertexBuffer);
+    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(vexBuf), vexBuf, GL_STATIC_DRAW);
+    
+    // init index buffer object
+    const unsigned char idxBuf[] = {  2, 1, 0, 3, 2, 0, // font
+        1, 5, 4, 1, 4, 0, // right
+        4, 5, 6, 4, 6, 7, // back
+        7, 6, 2, 7, 2, 3, // left
+        2, 6, 5, 2, 5, 1, // up
+        3, 0, 4, 3, 4, 7  // down
+    };
+    
+    glGenBuffers(1, &_indexBuffer);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(idxBuf), idxBuf, GL_STATIC_DRAW);
+    
+    if (Configuration::getInstance()->supportsShareableVAO())
+    {
+        glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
+        _glProgramState->applyAttributes(false);
+        
+        GL::bindVAO(0);
+    }
+}
+
+void CameraBackgroundSkyBoxBrush::setTexture(TextureCube*  texture)
+{
+    CC_SAFE_RETAIN(texture);
+    CC_SAFE_RELEASE(_texture);
+    _texture = texture;
+    _glProgramState->setUniformTexture("u_Env", _texture);
+}
+
+bool CameraBackgroundSkyBoxBrush::isActived() const
+{
+    return _actived;
+}
+void CameraBackgroundSkyBoxBrush::setActived(bool actived)
+{
+    _actived = actived;
+}
+
+void CameraBackgroundSkyBoxBrush::setTextureValid(bool valid)
+{
+    _textureValid = valid;
+}
+
+bool CameraBackgroundSkyBoxBrush::isValid()
+{
+    return _actived;
+}
+
+NS_CC_END

+ 276 - 0
cocos2d/cocos/2d/CCCameraBackgroundBrush.h

@@ -0,0 +1,276 @@
+/****************************************************************************
+ Copyright (c) 2015-2017 Chukong Technologies 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.
+ 
+ ****************************************************************************/
+#ifndef _CCCAMERA_BACKGROUND_BRUSH_H__
+#define _CCCAMERA_BACKGROUND_BRUSH_H__
+
+#include "base/ccTypes.h"
+#include "base/CCRef.h"
+#include "3d/CCFrustum.h"
+#include "renderer/CCQuadCommand.h"
+#include "renderer/CCCustomCommand.h"
+#include "renderer/CCFrameBuffer.h"
+
+NS_CC_BEGIN
+
+class CameraBackgroundColorBrush;
+class CameraBackgroundDepthBrush;
+class CameraBackgroundSkyBoxBrush;
+
+class GLProgramState;
+class Camera;
+
+/**
+ * Defines a brush to clear the background of camera.
+ * There are 4 types of brush. None brush do nothing, Depth brush clear background with given depth, Color brush clear background with given color and depth, Skybox brush clear the background with a skybox. Camera uses depth brush by default.
+ */
+class CC_DLL CameraBackgroundBrush : public Ref
+{
+public:
+    /**
+     * Brush types. There are 4 types of brush. See CameraBackgroundDepthBrush, CameraBackgroundColorBrush, CameraBackgroundSkyBoxBrush for more information.
+     */
+    enum class BrushType
+    {
+        NONE, //none brush
+        DEPTH, // depth brush. See CameraBackgroundDepthBrush
+        COLOR, // color brush. See CameraBackgroundColorBrush
+        SKYBOX, // skybox brush. See CameraBackgroundSkyBoxBrush
+    };
+    
+    /**
+     * get brush type
+     * @return BrushType
+     */
+    virtual BrushType getBrushType() const { return BrushType::NONE; }
+    
+    /**
+     * Creates a none brush, it does nothing when clear the background
+     * @return Created brush.
+     */
+    static CameraBackgroundBrush* createNoneBrush();
+    
+    /**
+     * Creates a depth brush, which clears depth buffer with a given depth.
+     * @param depth Depth used to clear depth buffer
+     * @return Created brush
+     */
+    static CameraBackgroundDepthBrush* createDepthBrush(float depth = 1.f);
+    
+    /**
+     * Creates a color brush
+     * @param color Color of brush
+     * @param depth Depth used to clear depth buffer
+     * @return Created brush
+     */
+    static CameraBackgroundColorBrush* createColorBrush(const Color4F& color, float depth);
+    
+    
+    /** Creates a Skybox brush with 6 textures.
+     @param positive_x texture for the right side of the texture cube face.
+     @param negative_x texture for the up side of the texture cube face.
+     @param positive_y texture for the top side of the texture cube face
+     @param negative_y texture for the bottom side of the texture cube face
+     @param positive_z texture for the forward side of the texture cube face.
+     @param negative_z texture for the rear side of the texture cube face.
+     @return  A new brush inited with given parameters.
+     */
+    static CameraBackgroundSkyBoxBrush* createSkyboxBrush(const std::string& positive_x, const std::string& negative_x,
+                                                          const std::string& positive_y, const std::string& negative_y,
+                                                          const std::string& positive_z, const std::string& negative_z);
+    /**
+     * draw the background
+     */
+    virtual void drawBackground(Camera* /*camera*/) {}
+
+    virtual bool isValid() { return true; }
+
+CC_CONSTRUCTOR_ACCESS :
+    CameraBackgroundBrush();
+    virtual ~CameraBackgroundBrush();
+
+    virtual bool init() { return true; }
+    
+protected:
+    GLProgramState* _glProgramState;
+};
+
+/**
+ * Depth brush clear depth buffer with given depth
+ */
+class CC_DLL CameraBackgroundDepthBrush : public CameraBackgroundBrush
+{
+public:
+    /**
+     * Create a depth brush
+     * @param depth Depth used to clear the depth buffer
+     * @return Created brush
+     */
+    static CameraBackgroundDepthBrush* create(float depth);
+    
+    /**
+     * Get brush type. Should be BrushType::DEPTH
+     * @return brush type
+     */
+    virtual BrushType getBrushType() const override { return BrushType::DEPTH; }
+    
+    /**
+     * Draw background
+     */
+    virtual void drawBackground(Camera* camera) override;
+    
+    /**
+     * Set depth
+     * @param depth Depth used to clear depth buffer
+     */
+    void setDepth(float depth) { _depth = depth; }
+    
+CC_CONSTRUCTOR_ACCESS:
+    CameraBackgroundDepthBrush();
+    virtual ~CameraBackgroundDepthBrush();
+
+    virtual bool init() override;
+    
+protected:
+    float _depth;
+    
+    GLboolean _clearColor;
+    
+    V3F_C4B_T2F_Quad _quad;
+};
+
+/**
+ * Color brush clear buffer with given depth and color
+ */
+class CC_DLL CameraBackgroundColorBrush : public CameraBackgroundDepthBrush
+{
+public:
+    /**
+     * Get brush type. Should be BrushType::COLOR
+     * @return brush type
+     */
+    virtual BrushType getBrushType() const override { return BrushType::COLOR; }
+    
+    /**
+     * Create a color brush
+     * @param color Color used to clear the color buffer
+     * @param depth Depth used to clear the depth buffer
+     * @return Created brush
+     */
+    static CameraBackgroundColorBrush* create(const Color4F& color, float depth);
+    
+    /**
+     * Set clear color
+     * @param color Color used to clear the color buffer
+     */
+    void setColor(const Color4F& color);
+    
+CC_CONSTRUCTOR_ACCESS:
+    CameraBackgroundColorBrush();
+    virtual ~CameraBackgroundColorBrush();
+
+    virtual bool init() override;
+    
+protected:
+    Color4F _color;
+};
+
+class TextureCube;
+class GLProgramState;
+class EventListenerCustom;
+
+/**
+ * Skybox brush clear buffer with a skybox
+ */
+class CC_DLL CameraBackgroundSkyBoxBrush : public CameraBackgroundBrush
+{
+public:
+    /**
+     * Get brush type. Should be BrushType::SKYBOX
+     * @return brush type
+     */
+    virtual BrushType getBrushType() const override { return BrushType::SKYBOX; }
+    
+    /** Creates a Skybox brush with 6 textures.
+     @param positive_x texture for the right side of the texture cube face.
+     @param negative_x texture for the up side of the texture cube face.
+     @param positive_y texture for the top side of the texture cube face
+     @param negative_y texture for the bottom side of the texture cube face
+     @param positive_z texture for the forward side of the texture cube face.
+     @param negative_z texture for the rear side of the texture cube face.
+     @return  A new brush inited with given parameters.
+     */
+    static CameraBackgroundSkyBoxBrush* create(const std::string& positive_x, const std::string& negative_x,
+                                        const std::string& positive_y, const std::string& negative_y,
+                                        const std::string& positive_z, const std::string& negative_z);
+    
+    /** Creates a Skybox brush with 6 textures.
+     */
+    static CameraBackgroundSkyBoxBrush* create();
+    /**
+     * Set skybox texture 
+     * @param texture Skybox texture
+     */
+    void setTexture(TextureCube*  texture);
+    
+    /**
+     * Draw background
+     */
+    virtual void drawBackground(Camera* camera) override;
+
+    bool isActived() const;
+    void setActived(bool actived);
+    virtual void setTextureValid(bool valid);
+    virtual bool isValid()override;
+
+CC_CONSTRUCTOR_ACCESS :
+    CameraBackgroundSkyBoxBrush();
+    virtual ~CameraBackgroundSkyBoxBrush();
+    
+    /**
+     * init Skybox.
+     */
+    virtual bool init() override;
+    
+protected:
+    void initBuffer();
+    
+    GLuint      _vao;
+    GLuint      _vertexBuffer;
+    GLuint      _indexBuffer;
+    
+    TextureCube*  _texture;
+    
+#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
+    EventListenerCustom* _backToForegroundListener;
+#endif
+
+private:
+    bool _actived;
+    bool _textureValid;
+};
+
+NS_CC_END
+
+#endif// _CCCAMERA_BACKGROUND_BRUSH_H__

+ 367 - 0
cocos2d/cocos/2d/CCClippingNode.cpp

@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2012      Pierre-David Bélanger
+ * Copyright (c) 2012      cocos2d-x.org
+ * Copyright (c) 2013-2017 Chukong Technologies Inc.
+ *
+ * cocos2d-x: 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 "2d/CCClippingNode.h"
+#include "2d/CCDrawingPrimitives.h"
+#include "renderer/CCGLProgramCache.h"
+#include "renderer/ccGLStateCache.h"
+#include "renderer/CCRenderer.h"
+#include "renderer/CCRenderState.h"
+#include "base/CCDirector.h"
+#include "base/CCStencilStateManager.h"
+
+#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
+#define CC_CLIPPING_NODE_OPENGLES 0
+#else
+#define CC_CLIPPING_NODE_OPENGLES 1
+#endif
+
+NS_CC_BEGIN
+
+#if CC_CLIPPING_NODE_OPENGLES
+static void setProgram(Node *n, GLProgram *p)
+{
+    n->setGLProgram(p);
+    
+    auto& children = n->getChildren();
+    for(const auto &child : children) {
+        setProgram(child, p);
+    }
+}
+#endif
+
+ClippingNode::ClippingNode()
+: _stencil(nullptr)
+, _stencilStateManager(new StencilStateManager())
+, _originStencilProgram(nullptr)
+{
+}
+
+ClippingNode::~ClippingNode()
+{
+    if (_stencil)
+    {
+        _stencil->stopAllActions();
+        _stencil->release();
+    }
+    CC_SAFE_DELETE(_stencilStateManager);
+}
+
+ClippingNode* ClippingNode::create()
+{
+    ClippingNode *ret = new (std::nothrow) ClippingNode();
+    if (ret && ret->init())
+    {
+        ret->autorelease();
+    }
+    else
+    {
+        CC_SAFE_DELETE(ret);
+    }
+    
+    return ret;
+}
+
+ClippingNode* ClippingNode::create(Node *pStencil)
+{
+    ClippingNode *ret = new (std::nothrow) ClippingNode();
+    if (ret && ret->init(pStencil))
+    {
+        ret->autorelease();
+    }
+    else
+    {
+        CC_SAFE_DELETE(ret);
+    }
+    
+    return ret;
+}
+
+bool ClippingNode::init()
+{
+    return init(nullptr);
+}
+
+bool ClippingNode::init(Node *stencil)
+{
+    setStencil(stencil);
+    return true;
+}
+
+void ClippingNode::onEnter()
+{
+#if CC_ENABLE_SCRIPT_BINDING
+    if (_scriptType == kScriptTypeJavascript)
+    {
+        if (ScriptEngineManager::sendNodeEventToJSExtended(this, kNodeOnEnter))
+            return;
+    }
+#endif
+    
+    Node::onEnter();
+    
+    if (_stencil != nullptr)
+    {
+        _stencil->onEnter();
+    }
+    else
+    {
+        CCLOG("ClippingNode warning: _stencil is nil.");
+    }
+}
+
+void ClippingNode::onEnterTransitionDidFinish()
+{
+#if CC_ENABLE_SCRIPT_BINDING
+    if (_scriptType == kScriptTypeJavascript)
+    {
+        if (ScriptEngineManager::sendNodeEventToJSExtended(this, kNodeOnEnterTransitionDidFinish))
+            return;
+    }
+#endif
+    
+    Node::onEnterTransitionDidFinish();
+    
+    if (_stencil != nullptr)
+    {
+        _stencil->onEnterTransitionDidFinish();
+    }
+}
+
+void ClippingNode::onExitTransitionDidStart()
+{
+#if CC_ENABLE_SCRIPT_BINDING
+    if (_scriptType == kScriptTypeJavascript)
+    {
+        if (ScriptEngineManager::sendNodeEventToJSExtended(this, kNodeOnExitTransitionDidStart))
+            return;
+    }
+#endif
+    
+    if (_stencil != nullptr)
+    {
+        _stencil->onExitTransitionDidStart();
+    }
+   
+    Node::onExitTransitionDidStart();
+}
+
+void ClippingNode::onExit()
+{
+#if CC_ENABLE_SCRIPT_BINDING
+    if (_scriptType == kScriptTypeJavascript)
+    {
+        if (ScriptEngineManager::sendNodeEventToJSExtended(this, kNodeOnExit))
+            return;
+    }
+#endif
+    
+    if (_stencil != nullptr)
+    {
+        _stencil->onExit();
+    }
+    
+    Node::onExit();
+}
+
+
+void ClippingNode::visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t parentFlags)
+{
+    if (!_visible || !hasContent())
+        return;
+    
+    uint32_t flags = processParentFlags(parentTransform, parentFlags);
+
+    // IMPORTANT:
+    // To ease the migration to v3.0, we still support the Mat4 stack,
+    // but it is deprecated and your code should not rely on it
+    Director* director = Director::getInstance();
+    CCASSERT(nullptr != director, "Director is null when setting matrix stack");
+    director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
+    director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
+
+    //Add group command
+        
+    _groupCommand.init(_globalZOrder);
+    renderer->addCommand(&_groupCommand);
+
+    renderer->pushGroup(_groupCommand.getRenderQueueID());
+
+    _beforeVisitCmd.init(_globalZOrder);
+    _beforeVisitCmd.func = CC_CALLBACK_0(StencilStateManager::onBeforeVisit, _stencilStateManager);
+    renderer->addCommand(&_beforeVisitCmd);
+    
+    auto alphaThreshold = this->getAlphaThreshold();
+    if (alphaThreshold < 1)
+    {
+#if CC_CLIPPING_NODE_OPENGLES
+        // since glAlphaTest do not exists in OES, use a shader that writes
+        // pixel only if greater than an alpha threshold
+        GLProgram *program = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_ALPHA_TEST_NO_MV);
+        GLint alphaValueLocation = glGetUniformLocation(program->getProgram(), GLProgram::UNIFORM_NAME_ALPHA_TEST_VALUE);
+        // set our alphaThreshold
+        program->use();
+        program->setUniformLocationWith1f(alphaValueLocation, alphaThreshold);
+        // we need to recursively apply this shader to all the nodes in the stencil node
+        // FIXME: we should have a way to apply shader to all nodes without having to do this
+        setProgram(_stencil, program);
+#endif
+
+    }
+    _stencil->visit(renderer, _modelViewTransform, flags);
+
+    _afterDrawStencilCmd.init(_globalZOrder);
+    _afterDrawStencilCmd.func = CC_CALLBACK_0(StencilStateManager::onAfterDrawStencil, _stencilStateManager);
+    renderer->addCommand(&_afterDrawStencilCmd);
+
+    int i = 0;
+    bool visibleByCamera = isVisitableByVisitingCamera();
+    
+    if(!_children.empty())
+    {
+        sortAllChildren();
+        // draw children zOrder < 0
+        for(auto size = _children.size(); i < size; ++i)
+        {
+            auto node = _children.at(i);
+            
+            if ( node && node->getLocalZOrder() < 0 )
+                node->visit(renderer, _modelViewTransform, flags);
+            else
+                break;
+        }
+        // self draw
+        if (visibleByCamera)
+            this->draw(renderer, _modelViewTransform, flags);
+
+        for(auto it=_children.cbegin()+i, itCend = _children.cend(); it != itCend; ++it)
+            (*it)->visit(renderer, _modelViewTransform, flags);
+    }
+    else if (visibleByCamera)
+    {
+        this->draw(renderer, _modelViewTransform, flags);
+    }
+
+    _afterVisitCmd.init(_globalZOrder);
+    _afterVisitCmd.func = CC_CALLBACK_0(StencilStateManager::onAfterVisit, _stencilStateManager);
+    renderer->addCommand(&_afterVisitCmd);
+
+    renderer->popGroup();
+    
+    director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
+}
+
+void ClippingNode::setCameraMask(unsigned short mask, bool applyChildren)
+{
+    Node::setCameraMask(mask, applyChildren);
+    
+    if (_stencil)
+        _stencil->setCameraMask(mask, applyChildren);
+}
+
+Node* ClippingNode::getStencil() const
+{
+    return _stencil;
+}
+
+void ClippingNode::setStencil(Node *stencil)
+{
+    //early out if the stencil is already set
+    if (_stencil == stencil)
+        return;
+    
+#if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
+    auto sEngine = ScriptEngineManager::getInstance()->getScriptEngine();
+    if (sEngine)
+    {
+        if (_stencil)
+            sEngine->releaseScriptObject(this, _stencil);
+        if (stencil)
+            sEngine->retainScriptObject(this, stencil);
+    }
+#endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
+    
+    //cleanup current stencil
+    if(_stencil != nullptr && _stencil->isRunning())
+    {
+        _stencil->onExitTransitionDidStart();
+        _stencil->onExit();
+    }
+    CC_SAFE_RELEASE_NULL(_stencil);
+    
+    //initialise new stencil
+    _stencil = stencil;
+    CC_SAFE_RETAIN(_stencil);
+    if(_stencil != nullptr && this->isRunning())
+    {
+        _stencil->onEnter();
+        if(this->_isTransitionFinished)
+        {
+            _stencil->onEnterTransitionDidFinish();
+        }
+    }
+    
+    if (_stencil != nullptr)
+        _originStencilProgram = _stencil->getGLProgram();
+}
+
+bool ClippingNode::hasContent() const
+{
+    return _children.size() > 0;
+}
+
+GLfloat ClippingNode::getAlphaThreshold() const
+{
+    return _stencilStateManager->getAlphaThreshold();
+}
+
+void ClippingNode::setAlphaThreshold(GLfloat alphaThreshold)
+{
+#if CC_CLIPPING_NODE_OPENGLES
+    if (alphaThreshold == 1 && alphaThreshold != _stencilStateManager->getAlphaThreshold())
+    {
+        // should reset program used by _stencil
+        if (_stencil)
+            setProgram(_stencil, _originStencilProgram);
+    }
+#endif
+    
+    _stencilStateManager->setAlphaThreshold(alphaThreshold);
+}
+
+bool ClippingNode::isInverted() const
+{
+    return _stencilStateManager->isInverted();
+}
+
+void ClippingNode::setInverted(bool inverted)
+{
+    _stencilStateManager->setInverted(inverted);
+}
+
+
+NS_CC_END

+ 174 - 0
cocos2d/cocos/2d/CCClippingNode.h

@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2012      Pierre-David Bélanger
+ * Copyright (c) 2012      cocos2d-x.org
+ * Copyright (c) 2013-2017 Chukong Technologies 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.
+ *
+ */
+
+#ifndef __MISCNODE_CCCLIPPING_NODE_H__
+#define __MISCNODE_CCCLIPPING_NODE_H__
+
+#include "2d/CCNode.h"
+#include "platform/CCGL.h"
+#include "renderer/CCGroupCommand.h"
+#include "renderer/CCCustomCommand.h"
+
+NS_CC_BEGIN
+
+class StencilStateManager;
+/**
+ *  @addtogroup _2d
+ *  @{
+ */
+/** ClippingNode is a subclass of Node.
+ * It draws its content (children) clipped using a stencil.
+ * The stencil is an other Node that will not be drawn.
+ * The clipping is done using the alpha part of the stencil (adjusted with an alphaThreshold).
+ */
+class CC_DLL ClippingNode : public Node
+{
+public:
+    /** Creates and initializes a clipping node without a stencil.
+     *
+     * @return An autorelease ClippingNode.
+     */
+    static ClippingNode* create();
+    
+    /** Creates and initializes a clipping node with an other node as its stencil.
+     * The stencil node will be retained.
+     * @param stencil The stencil node.
+     */
+    static ClippingNode* create(Node *stencil);
+
+    /** The Node to use as a stencil to do the clipping.
+     * The stencil node will be retained.
+     * This default to nil.
+     *
+     * @return The stencil node.
+     */
+    Node* getStencil() const;
+    
+    /** Set the Node to use as a stencil to do the clipping.
+     *
+     * @param stencil The Node to use as a stencil to do the clipping.
+     */
+    void setStencil(Node *stencil);
+
+    /** If stencil has no children it will not be drawn.
+     * If you have custom stencil-based node with stencil drawing mechanics other then children-based,
+     * then this method should return true every time you wish stencil to be visited.
+     * By default returns true if has any children attached.
+     *
+     * @return If you have custom stencil-based node with stencil drawing mechanics other then children-based,
+     *         then this method should return true every time you wish stencil to be visited.
+     *         By default returns true if has any children attached.
+     * @js NA
+     */
+    virtual bool hasContent() const;
+
+    /** The alpha threshold.
+     * The content is drawn only where the stencil have pixel with alpha greater than the alphaThreshold.
+     * Should be a float between 0 and 1.
+     * This default to 1 (so alpha test is disabled).
+     *
+     * @return The alpha threshold value,Should be a float between 0 and 1.
+     */
+    GLfloat getAlphaThreshold() const;
+    
+    /** Set the alpha threshold. 
+     * 
+     * @param alphaThreshold The alpha threshold.
+     */
+    void setAlphaThreshold(GLfloat alphaThreshold);
+    
+    /** Inverted. If this is set to true,
+     * the stencil is inverted, so the content is drawn where the stencil is NOT drawn.
+     * This default to false.
+     *
+     * @return If the clippingNode is Inverted, it will be return true.
+     */
+    bool isInverted() const;
+    
+    /** Set the ClippingNode whether or not invert.
+     *
+     * @param inverted A bool Type,to set the ClippingNode whether or not invert.
+     */
+    void setInverted(bool inverted);
+
+    // Overrides
+    /**
+     * @lua NA
+     */
+    virtual void onEnter() override;
+    /**
+     * @lua NA
+     */
+    virtual void onEnterTransitionDidFinish() override;
+    /**
+     * @lua NA
+     */
+    virtual void onExitTransitionDidStart() override;
+    /**
+     * @lua NA
+     */
+    virtual void onExit() override;
+    virtual void visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t parentFlags) override;
+    
+    virtual void setCameraMask(unsigned short mask, bool applyChildren = true) override;
+    
+CC_CONSTRUCTOR_ACCESS:
+    ClippingNode();
+    
+    /**
+     * @js NA
+     * @lua NA
+     */
+    virtual ~ClippingNode();
+
+    /** Initializes a clipping node without a stencil.
+     */
+    virtual bool init() override;
+    
+    /** Initializes a clipping node with an other node as its stencil.
+     The stencil node will be retained, and its parent will be set to this clipping node.
+     */
+    virtual bool init(Node *stencil);
+
+protected:
+    Node* _stencil;
+    GLProgram* _originStencilProgram;
+   
+    StencilStateManager* _stencilStateManager;
+    
+    GroupCommand _groupCommand;
+    CustomCommand _beforeVisitCmd;
+    CustomCommand _afterDrawStencilCmd;
+    CustomCommand _afterVisitCmd;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(ClippingNode);
+};
+/** @} */
+NS_CC_END
+
+#endif // __MISCNODE_CCCLIPPING_NODE_H__

+ 84 - 0
cocos2d/cocos/2d/CCClippingRectangleNode.cpp

@@ -0,0 +1,84 @@
+
+#include "2d/CCClippingRectangleNode.h"
+#include "base/CCDirector.h"
+#include "renderer/CCRenderer.h"
+#include "math/Vec2.h"
+#include "platform/CCGLView.h"
+
+NS_CC_BEGIN
+
+ClippingRectangleNode* ClippingRectangleNode::create(const Rect& clippingRegion)
+{
+    ClippingRectangleNode* node = new (std::nothrow) ClippingRectangleNode();
+    if (node && node->init()) {
+        node->setClippingRegion(clippingRegion);
+        node->autorelease();
+    } else {
+        CC_SAFE_DELETE(node);
+    }
+    
+    return node;
+}
+
+ClippingRectangleNode* ClippingRectangleNode::create()
+{
+    ClippingRectangleNode* node = new (std::nothrow) ClippingRectangleNode();
+    if (node && node->init()) {
+        node->autorelease();
+    } else {
+        CC_SAFE_DELETE(node);
+    }
+    
+    return node;
+}
+
+void ClippingRectangleNode::setClippingRegion(const Rect &clippingRegion)
+{
+    _clippingRegion = clippingRegion;
+}
+
+void ClippingRectangleNode::onBeforeVisitScissor()
+{
+    if (_clippingEnabled) {
+        glEnable(GL_SCISSOR_TEST);
+
+        float scaleX = _scaleX;
+        float scaleY = _scaleY;
+        Node *parent = this->getParent();
+        while (parent) {
+            scaleX *= parent->getScaleX();
+            scaleY *= parent->getScaleY();
+            parent = parent->getParent();
+        }
+        
+        const Point pos = convertToWorldSpace(Point(_clippingRegion.origin.x, _clippingRegion.origin.y));
+        GLView* glView = Director::getInstance()->getOpenGLView();
+        glView->setScissorInPoints(pos.x,
+                                   pos.y,
+                                   _clippingRegion.size.width * scaleX,
+                                   _clippingRegion.size.height * scaleY);
+    }
+}
+
+void ClippingRectangleNode::onAfterVisitScissor()
+{
+    if (_clippingEnabled)
+    {
+        glDisable(GL_SCISSOR_TEST);
+    }
+}
+
+void ClippingRectangleNode::visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t parentFlags)
+{
+    _beforeVisitCmdScissor.init(_globalZOrder);
+    _beforeVisitCmdScissor.func = CC_CALLBACK_0(ClippingRectangleNode::onBeforeVisitScissor, this);
+    renderer->addCommand(&_beforeVisitCmdScissor);
+    
+    Node::visit(renderer, parentTransform, parentFlags);
+    
+    _afterVisitCmdScissor.init(_globalZOrder);
+    _afterVisitCmdScissor.func = CC_CALLBACK_0(ClippingRectangleNode::onAfterVisitScissor, this);
+    renderer->addCommand(&_afterVisitCmdScissor);
+}
+
+NS_CC_END

+ 117 - 0
cocos2d/cocos/2d/CCClippingRectangleNode.h

@@ -0,0 +1,117 @@
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ * cocos2d-x: http://www.cocos2d-x.org
+ *
+ * Copyright (c) 2012 Pierre-David Bélanger
+ * Copyright (c) 2012 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 __MISCNODE_CCCLIPPING_RECTANGLE_NODE_H__
+#define __MISCNODE_CCCLIPPING_RECTANGLE_NODE_H__
+
+#include "2d/CCNode.h"
+#include "renderer/CCCustomCommand.h"
+#include "platform/CCGL.h"
+
+NS_CC_BEGIN
+
+/**
+ * @addtogroup _2d
+ * @{
+ */
+
+/**
+@brief Clipping Rectangle Node.
+@details A node that clipped with specified rectangle.
+ The region of ClippingRectangleNode doesn't support any transform except scale.
+@js NA
+*/
+class CC_DLL ClippingRectangleNode : public Node
+{    
+public:
+    /**
+    @brief Create node with specified clipping region.
+    @param clippingRegion Specify the clipping rectangle.
+    @return If the creation success, return a pointer of ClippingRectangleNode; otherwise return nil.
+    */
+    static ClippingRectangleNode* create(const Rect& clippingRegion);
+    /**
+    @brief Create a clipping rectangle node.
+    @return If the creation success, return a pointer of ClippingRectangleNode; otherwise return nil.
+    */
+    static ClippingRectangleNode* create();
+    
+    /**
+    @brief Get the clipping rectangle.
+    @return The clipping rectangle.
+    */
+    const Rect& getClippingRegion() const {
+        return _clippingRegion;
+    }
+    /**
+    @brief Set the clipping rectangle.
+    @param clippingRegion Specify the clipping rectangle.
+    */
+    void setClippingRegion(const Rect& clippingRegion);
+    
+    /**
+    @brief Get whether the clipping is enabled or not.
+    @return Whether the clipping is enabled or not. Default is true.
+    */
+    bool isClippingEnabled() const {
+        return _clippingEnabled;
+    }
+
+    /**
+    @brief Enable/Disable the clipping.
+    @param enabled Pass true to enable clipping. Pass false to disable clipping.
+    */
+    void setClippingEnabled(bool enabled) {
+        _clippingEnabled = enabled;
+    }
+
+    //virtual void draw(Renderer* renderer, const Mat4 &transform, uint32_t flags) override;
+    virtual void visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t parentFlags) override;
+
+protected:
+    ClippingRectangleNode()
+    : _clippingEnabled(true)
+    {
+    }
+    
+    void onBeforeVisitScissor();
+    void onAfterVisitScissor();
+    
+    Rect _clippingRegion;
+    bool _clippingEnabled;
+    
+    CustomCommand _beforeVisitCmdScissor;
+    CustomCommand _afterVisitCmdScissor;
+};
+
+// end of _2d group
+/// @}
+
+NS_CC_END
+
+#endif
+

+ 152 - 0
cocos2d/cocos/2d/CCComponent.cpp

@@ -0,0 +1,152 @@
+/****************************************************************************
+Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCComponent.h"
+
+NS_CC_BEGIN
+
+Component::Component()
+: _owner(nullptr)
+, _enabled(true)
+{
+#if CC_ENABLE_SCRIPT_BINDING
+    ScriptEngineProtocol* engine = ScriptEngineManager::getInstance()->getScriptEngine();
+    _scriptType = engine != nullptr ? engine->getScriptType() : kScriptTypeNone;
+#endif
+}
+
+Component::~Component()
+{
+}
+
+bool Component::init()
+{
+    return true;
+}
+
+#if CC_ENABLE_SCRIPT_BINDING
+
+static bool sendComponentEventToJS(Component* node, int action)
+{
+    auto scriptEngine = ScriptEngineManager::getInstance()->getScriptEngine();
+    
+    if (scriptEngine->isCalledFromScript())
+    {
+        scriptEngine->setCalledFromScript(false);
+    }
+    else
+    {
+        BasicScriptData data(node,(void*)&action);
+        ScriptEvent scriptEvent(kComponentEvent,(void*)&data);
+        if (scriptEngine->sendEvent(&scriptEvent))
+            return true;
+    }
+    
+    return false;
+}
+
+#endif
+
+void Component::onEnter()
+{
+#if CC_ENABLE_SCRIPT_BINDING
+    if (_scriptType == kScriptTypeJavascript)
+    {
+        sendComponentEventToJS(this, kComponentOnEnter);
+    }
+#endif
+}
+
+void Component::onExit()
+{
+#if CC_ENABLE_SCRIPT_BINDING
+    if (_scriptType == kScriptTypeJavascript)
+    {
+        sendComponentEventToJS(this, kComponentOnExit);
+    }
+#endif
+}
+
+void Component::onAdd()
+{
+#if CC_ENABLE_SCRIPT_BINDING
+    if (_scriptType == kScriptTypeJavascript)
+    {
+        sendComponentEventToJS(this, kComponentOnAdd);
+    }
+#endif
+}
+
+void Component::onRemove()
+{
+#if CC_ENABLE_SCRIPT_BINDING
+    if (_scriptType == kScriptTypeJavascript)
+    {
+        sendComponentEventToJS(this, kComponentOnRemove);
+    }
+#endif
+}
+
+void Component::update(float /*delta*/)
+{
+#if CC_ENABLE_SCRIPT_BINDING
+    if (_scriptType == kScriptTypeJavascript)
+    {
+        sendComponentEventToJS(this, kComponentOnUpdate);
+    }
+#endif
+}
+
+bool Component::serialize(void* /*ar*/)
+{
+    return true;
+}
+
+Component* Component::create()
+{
+    Component * ret = new (std::nothrow) Component();
+
+    if (ret && ret->init())
+    {
+        ret->autorelease();
+    }
+    else
+    {
+        CC_SAFE_DELETE(ret);
+    }
+
+    return ret;
+}
+
+void Component::setOwner(Node *owner)
+{
+    _owner = owner;
+}
+
+void Component::setEnabled(bool enabled)
+{
+    _enabled = enabled;
+}
+
+NS_CC_END

+ 94 - 0
cocos2d/cocos/2d/CCComponent.h

@@ -0,0 +1,94 @@
+/****************************************************************************
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+
+#ifndef __CC_FRAMEWORK_COMPONENT_H__
+#define __CC_FRAMEWORK_COMPONENT_H__
+
+/// @cond DO_NOT_SHOW
+#include <string>
+#include "base/CCRef.h"
+#include "base/CCScriptSupport.h"
+
+NS_CC_BEGIN
+
+class Node;
+
+enum {
+    kComponentOnEnter,
+    kComponentOnExit,
+    kComponentOnAdd,
+    kComponentOnRemove,
+    kComponentOnUpdate
+};
+
+class CC_DLL Component : public Ref
+{
+public:
+    static Component* create();
+
+    /**
+     * @js NA
+     * @lua NA
+     */
+    virtual ~Component();
+
+    virtual bool init();
+
+    bool isEnabled() const { return _enabled; }
+    virtual void setEnabled(bool enabled);
+    
+    const std::string& getName() const { return _name; }
+    virtual void setName(const std::string& name) { _name = name; }
+    
+    Node* getOwner() const { return _owner; }
+    virtual void setOwner(Node *owner);
+
+    virtual void update(float delta);
+    virtual bool serialize(void* r);
+
+    virtual void onEnter();
+    virtual void onExit();
+    virtual void onAdd();
+    virtual void onRemove();
+
+CC_CONSTRUCTOR_ACCESS:
+    /**
+    * @js ctor
+    */
+    Component();
+
+protected:
+    Node* _owner;
+    std::string _name;
+    bool _enabled;
+    
+#if CC_ENABLE_SCRIPT_BINDING
+    ccScriptType _scriptType;         ///< type of script binding, lua or javascript
+#endif
+};
+
+NS_CC_END
+
+/// @endcond
+#endif  // __CC_FRAMEWORK_COMPONENT_H__

+ 149 - 0
cocos2d/cocos/2d/CCComponentContainer.cpp

@@ -0,0 +1,149 @@
+/****************************************************************************
+Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCComponentContainer.h"
+#include "2d/CCComponent.h"
+#include "2d/CCNode.h"
+
+NS_CC_BEGIN
+
+ComponentContainer::ComponentContainer(Node* node)
+: _owner(node)
+{
+}
+
+ComponentContainer::~ComponentContainer()
+{  
+}
+
+Component* ComponentContainer::get(const std::string& name) const
+{
+    Component* ret = nullptr;
+
+    auto it = _componentMap.find(name);
+    if (it != _componentMap.end())
+    {
+        ret = it->second;
+    }
+
+    return ret;
+}
+
+bool ComponentContainer::add(Component *com)
+{
+    bool ret = false;
+    CCASSERT(com != nullptr, "Component must be non-nil");
+    CCASSERT(com->getOwner() == nullptr, "Component already added. It can't be added again");
+    do
+    {
+        auto componentName = com->getName();
+
+        if (_componentMap.find(componentName) != _componentMap.end())
+        {
+            CCASSERT(false, "ComponentContainer already have this kind of component");
+            break;
+        }
+        _componentMap[componentName] = com;
+        com->retain();
+        com->setOwner(_owner);
+        com->onAdd();
+
+        ret = true;
+    } while(0);
+    return ret;
+}
+
+bool ComponentContainer::remove(const std::string& componentName)
+{
+    bool ret = false;
+    do 
+    {        
+        auto iter = _componentMap.find(componentName);
+        CC_BREAK_IF(iter == _componentMap.end());
+
+        auto component = iter->second;
+        _componentMap.erase(componentName);
+
+        component->onRemove();
+        component->setOwner(nullptr);
+        component->release();
+
+        ret = true;
+    } while(0);
+
+    return ret;
+ }
+
+bool ComponentContainer::remove(Component *com)
+{
+    return remove(com->getName());
+}
+
+void ComponentContainer::removeAll()
+{
+    if (!_componentMap.empty())
+    {
+        for (auto& iter : _componentMap)
+        {
+            iter.second->onRemove();
+            iter.second->setOwner(nullptr);
+            iter.second->release();
+        }
+        
+        _componentMap.clear();
+        _owner->unscheduleUpdate();
+    }
+}
+
+void ComponentContainer::visit(float delta)
+{
+    if (!_componentMap.empty())
+    {
+        CC_SAFE_RETAIN(_owner);
+        for (auto& iter : _componentMap)
+        {
+            iter.second->update(delta);
+        }
+        CC_SAFE_RELEASE(_owner);
+    }
+}
+
+void ComponentContainer::onEnter()
+{
+    for (auto& iter : _componentMap)
+    {
+        iter.second->onEnter();
+    }
+}
+
+void ComponentContainer::onExit()
+{
+    for (auto& iter : _componentMap)
+    {
+        iter.second->onExit();
+    }
+}
+
+NS_CC_END

+ 78 - 0
cocos2d/cocos/2d/CCComponentContainer.h

@@ -0,0 +1,78 @@
+/****************************************************************************
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+
+#ifndef __CC_FRAMEWORK_COMCONTAINER_H__
+#define __CC_FRAMEWORK_COMCONTAINER_H__
+
+/// @cond DO_NOT_SHOW
+
+#include "base/CCMap.h"
+#include <string>
+
+NS_CC_BEGIN
+
+class Component;
+class Node;
+
+class CC_DLL ComponentContainer
+{
+protected:
+    /**
+     * @js ctor
+     */
+    ComponentContainer(Node* node);
+    
+public:
+    /**
+     * @js NA
+     * @lua NA
+     */
+    ~ComponentContainer();
+    
+	/**
+     * @js getComponent
+     */
+	Component* get(const std::string& name) const;
+
+    bool add(Component *com);
+    bool remove(const std::string& name);
+    bool remove(Component *com);
+    void removeAll();
+    void visit(float delta);
+    
+    void onEnter();
+    void onExit();
+    
+    bool isEmpty() const { return _componentMap.empty(); } 
+private:
+    std::unordered_map<std::string, Component*> _componentMap;
+    Node *_owner;
+    
+    friend class Node;
+};
+
+NS_CC_END
+
+/// @endcond
+#endif  // __CC_FRAMEWORK_COMCONTAINER_H__

+ 951 - 0
cocos2d/cocos/2d/CCDrawNode.cpp

@@ -0,0 +1,951 @@
+/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software
+ * Copyright (c) 2012 cocos2d-x.org
+ * Copyright (c) 2013-2017 Chukong Technologies Inc.
+ *
+ * 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 "2d/CCDrawNode.h"
+#include "base/CCEventType.h"
+#include "base/CCConfiguration.h"
+#include "renderer/CCRenderer.h"
+#include "renderer/ccGLStateCache.h"
+#include "renderer/CCGLProgramState.h"
+#include "renderer/CCGLProgramCache.h"
+#include "base/CCDirector.h"
+#include "base/CCEventListenerCustom.h"
+#include "base/CCEventDispatcher.h"
+#include "2d/CCActionCatmullRom.h"
+#include "platform/CCGL.h"
+
+NS_CC_BEGIN
+
+// Vec2 == CGPoint in 32-bits, but not in 64-bits (OS X)
+// that's why the "v2f" functions are needed
+static Vec2 v2fzero(0.0f,0.0f);
+
+static inline Vec2 v2f(float x, float y)
+{
+    Vec2 ret(x, y);
+    return ret;
+}
+
+static inline Vec2 v2fadd(const Vec2 &v0, const Vec2 &v1)
+{
+    return v2f(v0.x+v1.x, v0.y+v1.y);
+}
+
+static inline Vec2 v2fsub(const Vec2 &v0, const Vec2 &v1)
+{
+    return v2f(v0.x-v1.x, v0.y-v1.y);
+}
+
+static inline Vec2 v2fmult(const Vec2 &v, float s)
+{
+    return v2f(v.x * s, v.y * s);
+}
+
+static inline Vec2 v2fperp(const Vec2 &p0)
+{
+    return v2f(-p0.y, p0.x);
+}
+
+static inline Vec2 v2fneg(const Vec2 &p0)
+{
+    return v2f(-p0.x, - p0.y);
+}
+
+static inline float v2fdot(const Vec2 &p0, const Vec2 &p1)
+{
+    return  p0.x * p1.x + p0.y * p1.y;
+}
+
+static inline Vec2 v2fnormalize(const Vec2 &p)
+{
+    Vec2 r(p.x, p.y);
+    r.normalize();
+    return v2f(r.x, r.y);
+}
+
+static inline Vec2 __v2f(const Vec2 &v)
+{
+//#ifdef __LP64__
+    return v2f(v.x, v.y);
+// #else
+//     return * ((Vec2*) &v);
+// #endif
+}
+
+static inline Tex2F __t(const Vec2 &v)
+{
+    return *(Tex2F*)&v;
+}
+
+// implementation of DrawNode
+
+DrawNode::DrawNode(GLfloat lineWidth)
+: _vao(0)
+, _vbo(0)
+, _vaoGLPoint(0)
+, _vboGLPoint(0)
+, _vaoGLLine(0)
+, _vboGLLine(0)
+, _bufferCapacity(0)
+, _bufferCount(0)
+, _buffer(nullptr)
+, _bufferCapacityGLPoint(0)
+, _bufferCountGLPoint(0)
+, _bufferGLPoint(nullptr)
+, _bufferCapacityGLLine(0)
+, _bufferCountGLLine(0)
+, _bufferGLLine(nullptr)
+, _dirty(false)
+, _dirtyGLPoint(false)
+, _dirtyGLLine(false)
+, _lineWidth(lineWidth)
+, _defaultLineWidth(lineWidth)
+{
+    _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;
+}
+
+DrawNode::~DrawNode()
+{
+    free(_buffer);
+    _buffer = nullptr;
+    free(_bufferGLPoint);
+    _bufferGLPoint = nullptr;
+    free(_bufferGLLine);
+    _bufferGLLine = nullptr;
+    
+    glDeleteBuffers(1, &_vbo);
+    glDeleteBuffers(1, &_vboGLLine);
+    glDeleteBuffers(1, &_vboGLPoint);
+    _vbo = 0;
+    _vboGLPoint = 0;
+    _vboGLLine = 0;
+    
+    if (Configuration::getInstance()->supportsShareableVAO())
+    {
+        GL::bindVAO(0);
+        glDeleteVertexArrays(1, &_vao);
+        glDeleteVertexArrays(1, &_vaoGLLine);
+        glDeleteVertexArrays(1, &_vaoGLPoint);
+        _vao = _vaoGLLine = _vaoGLPoint = 0;
+    }
+}
+
+DrawNode* DrawNode::create(GLfloat defaultLineWidth)
+{
+    DrawNode* ret = new (std::nothrow) DrawNode(defaultLineWidth);
+    if (ret && ret->init())
+    {
+        ret->autorelease();
+    }
+    else
+    {
+        CC_SAFE_DELETE(ret);
+    }
+    
+    return ret;
+}
+
+void DrawNode::ensureCapacity(int count)
+{
+    CCASSERT(count>=0, "capacity must be >= 0");
+    
+    if(_bufferCount + count > _bufferCapacity)
+    {
+        _bufferCapacity += MAX(_bufferCapacity, count);
+        _buffer = (V2F_C4B_T2F*)realloc(_buffer, _bufferCapacity*sizeof(V2F_C4B_T2F));
+    }
+}
+
+void DrawNode::ensureCapacityGLPoint(int count)
+{
+    CCASSERT(count>=0, "capacity must be >= 0");
+    
+    if(_bufferCountGLPoint + count > _bufferCapacityGLPoint)
+    {
+        _bufferCapacityGLPoint += MAX(_bufferCapacityGLPoint, count);
+        _bufferGLPoint = (V2F_C4B_T2F*)realloc(_bufferGLPoint, _bufferCapacityGLPoint*sizeof(V2F_C4B_T2F));
+    }
+}
+
+void DrawNode::ensureCapacityGLLine(int count)
+{
+    CCASSERT(count>=0, "capacity must be >= 0");
+    
+    if(_bufferCountGLLine + count > _bufferCapacityGLLine)
+    {
+        _bufferCapacityGLLine += MAX(_bufferCapacityGLLine, count);
+        _bufferGLLine = (V2F_C4B_T2F*)realloc(_bufferGLLine, _bufferCapacityGLLine*sizeof(V2F_C4B_T2F));
+    }
+}
+
+bool DrawNode::init()
+{
+    _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;
+
+    setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_LENGTH_TEXTURE_COLOR));
+    
+    ensureCapacity(512);
+    ensureCapacityGLPoint(64);
+    ensureCapacityGLLine(256);
+    
+    if (Configuration::getInstance()->supportsShareableVAO())
+    {
+        glGenVertexArrays(1, &_vao);
+        GL::bindVAO(_vao);
+        glGenBuffers(1, &_vbo);
+        glBindBuffer(GL_ARRAY_BUFFER, _vbo);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)* _bufferCapacity, _buffer, GL_STREAM_DRAW);
+        // vertex
+        glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, vertices));
+        // color
+        glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_COLOR);
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, colors));
+        // texcoord
+        glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_TEX_COORD);
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, texCoords));
+        
+        glGenVertexArrays(1, &_vaoGLLine);
+        GL::bindVAO(_vaoGLLine);
+        glGenBuffers(1, &_vboGLLine);
+        glBindBuffer(GL_ARRAY_BUFFER, _vboGLLine);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacityGLLine, _bufferGLLine, GL_STREAM_DRAW);
+        // vertex
+        glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, vertices));
+        // color
+        glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_COLOR);
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, colors));
+        // texcoord
+        glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_TEX_COORD);
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, texCoords));
+        
+        glGenVertexArrays(1, &_vaoGLPoint);
+        GL::bindVAO(_vaoGLPoint);
+        glGenBuffers(1, &_vboGLPoint);
+        glBindBuffer(GL_ARRAY_BUFFER, _vboGLPoint);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacityGLPoint, _bufferGLPoint, GL_STREAM_DRAW);
+        // vertex
+        glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, vertices));
+        // color
+        glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_COLOR);
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, colors));
+        // Texture coord as pointsize
+        glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_TEX_COORD);
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, texCoords));
+        
+        GL::bindVAO(0);
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
+        
+    }
+    else
+    {
+        glGenBuffers(1, &_vbo);
+        glBindBuffer(GL_ARRAY_BUFFER, _vbo);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)* _bufferCapacity, _buffer, GL_STREAM_DRAW);
+        
+        glGenBuffers(1, &_vboGLLine);
+        glBindBuffer(GL_ARRAY_BUFFER, _vboGLLine);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacityGLLine, _bufferGLLine, GL_STREAM_DRAW);
+        
+        glGenBuffers(1, &_vboGLPoint);
+        glBindBuffer(GL_ARRAY_BUFFER, _vboGLPoint);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacityGLPoint, _bufferGLPoint, GL_STREAM_DRAW);
+
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
+    }
+    
+    CHECK_GL_ERROR_DEBUG();
+    
+    _dirty = true;
+    _dirtyGLLine = true;
+    _dirtyGLPoint = true;
+    
+#if CC_ENABLE_CACHE_TEXTURE_DATA
+    // Need to listen the event only when not use batchnode, because it will use VBO
+    auto listener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom* event){
+   /** listen the event that renderer was recreated on Android/WP8 */
+        this->init();
+    });
+
+    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
+#endif
+    
+    return true;
+}
+
+void DrawNode::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
+{
+    if(_bufferCount)
+    {
+        _customCommand.init(_globalZOrder, transform, flags);
+        _customCommand.func = CC_CALLBACK_0(DrawNode::onDraw, this, transform, flags);
+        renderer->addCommand(&_customCommand);
+    }
+    
+    if(_bufferCountGLPoint)
+    {
+        _customCommandGLPoint.init(_globalZOrder, transform, flags);
+        _customCommandGLPoint.func = CC_CALLBACK_0(DrawNode::onDrawGLPoint, this, transform, flags);
+        renderer->addCommand(&_customCommandGLPoint);
+    }
+    
+    if(_bufferCountGLLine)
+    {
+        _customCommandGLLine.init(_globalZOrder, transform, flags);
+        _customCommandGLLine.func = CC_CALLBACK_0(DrawNode::onDrawGLLine, this, transform, flags);
+        renderer->addCommand(&_customCommandGLLine);
+    }
+}
+
+void DrawNode::onDraw(const Mat4 &transform, uint32_t /*flags*/)
+{
+    getGLProgramState()->apply(transform);
+    auto glProgram = this->getGLProgram();
+    glProgram->setUniformLocationWith1f(glProgram->getUniformLocation("u_alpha"), _displayedOpacity / 255.0);
+    GL::blendFunc(_blendFunc.src, _blendFunc.dst);
+
+    if (_dirty)
+    {
+        glBindBuffer(GL_ARRAY_BUFFER, _vbo);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacity, _buffer, GL_STREAM_DRAW);
+        
+        _dirty = false;
+    }
+    if (Configuration::getInstance()->supportsShareableVAO())
+    {
+        GL::bindVAO(_vao);
+    }
+    else
+    {
+        GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);
+
+        glBindBuffer(GL_ARRAY_BUFFER, _vbo);
+        // vertex
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, vertices));
+        // color
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, colors));
+        // texcoord
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, texCoords));
+    }
+
+    glDrawArrays(GL_TRIANGLES, 0, _bufferCount);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    
+    if (Configuration::getInstance()->supportsShareableVAO())
+    {
+        GL::bindVAO(0);
+    }
+    
+    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _bufferCount);
+    CHECK_GL_ERROR_DEBUG();
+}
+
+void DrawNode::onDrawGLLine(const Mat4 &transform, uint32_t /*flags*/)
+{
+    auto glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_LENGTH_TEXTURE_COLOR);
+    glProgram->use();
+    glProgram->setUniformsForBuiltins(transform);
+    glProgram->setUniformLocationWith1f(glProgram->getUniformLocation("u_alpha"), _displayedOpacity / 255.0);
+
+    GL::blendFunc(_blendFunc.src, _blendFunc.dst);
+
+    if (_dirtyGLLine)
+    {
+        glBindBuffer(GL_ARRAY_BUFFER, _vboGLLine);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacityGLLine, _bufferGLLine, GL_STREAM_DRAW);
+        _dirtyGLLine = false;
+    }
+    if (Configuration::getInstance()->supportsShareableVAO())
+    {
+        GL::bindVAO(_vaoGLLine);
+    }
+    else
+    {
+        glBindBuffer(GL_ARRAY_BUFFER, _vboGLLine);
+        GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);
+        // vertex
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, vertices));
+        // color
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, colors));
+        // texcoord
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, texCoords));
+    }
+
+    glLineWidth(_lineWidth);
+    glDrawArrays(GL_LINES, 0, _bufferCountGLLine);
+    
+    if (Configuration::getInstance()->supportsShareableVAO())
+    {
+        GL::bindVAO(0);
+    }
+    
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,_bufferCountGLLine);
+
+    CHECK_GL_ERROR_DEBUG();
+}
+
+void DrawNode::onDrawGLPoint(const Mat4 &transform, uint32_t /*flags*/)
+{
+    auto glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_COLOR_TEXASPOINTSIZE);
+    glProgram->use();
+    glProgram->setUniformsForBuiltins(transform);
+    glProgram->setUniformLocationWith1f(glProgram->getUniformLocation("u_alpha"), _displayedOpacity / 255.0);
+
+    GL::blendFunc(_blendFunc.src, _blendFunc.dst);
+
+    if (_dirtyGLPoint)
+    {
+        glBindBuffer(GL_ARRAY_BUFFER, _vboGLPoint);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacityGLPoint, _bufferGLPoint, GL_STREAM_DRAW);
+        
+        _dirtyGLPoint = false;
+    }
+    
+    if (Configuration::getInstance()->supportsShareableVAO())
+    {
+        GL::bindVAO(_vaoGLPoint);
+    }
+    else
+    {
+        glBindBuffer(GL_ARRAY_BUFFER, _vboGLPoint);
+        GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, vertices));
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, colors));
+        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, texCoords));
+    }
+    
+    glDrawArrays(GL_POINTS, 0, _bufferCountGLPoint);
+    
+    if (Configuration::getInstance()->supportsShareableVAO())
+    {
+        GL::bindVAO(0);
+    }
+    
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    
+    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,_bufferCountGLPoint);
+    CHECK_GL_ERROR_DEBUG();
+}
+
+void DrawNode::drawPoint(const Vec2& position, const float pointSize, const Color4F &color)
+{
+    ensureCapacityGLPoint(1);
+    
+    V2F_C4B_T2F *point = (V2F_C4B_T2F*)(_bufferGLPoint + _bufferCountGLPoint);
+    V2F_C4B_T2F a = {position, Color4B(color), Tex2F(pointSize,0)};
+    *point = a;
+    
+    _bufferCountGLPoint += 1;
+    _dirtyGLPoint = true;
+}
+
+void DrawNode::drawPoints(const Vec2 *position, unsigned int numberOfPoints, const Color4F &color)
+{
+    drawPoints(position, numberOfPoints, 1.0, color);
+}
+
+void DrawNode::drawPoints(const Vec2 *position, unsigned int numberOfPoints, const float pointSize, const Color4F &color)
+{
+    ensureCapacityGLPoint(numberOfPoints);
+    
+    V2F_C4B_T2F *point = (V2F_C4B_T2F*)(_bufferGLPoint + _bufferCountGLPoint);
+    
+    for(unsigned int i=0; i < numberOfPoints; i++,point++)
+    {
+        V2F_C4B_T2F a = {position[i], Color4B(color), Tex2F(pointSize,0)};
+        *point = a;
+    }
+    
+    _bufferCountGLPoint += numberOfPoints;
+    _dirtyGLPoint = true;
+}
+
+void DrawNode::drawLine(const Vec2 &origin, const Vec2 &destination, const Color4F &color)
+{
+    ensureCapacityGLLine(2);
+    
+    V2F_C4B_T2F *point = (V2F_C4B_T2F*)(_bufferGLLine + _bufferCountGLLine);
+    
+    V2F_C4B_T2F a = {origin, Color4B(color), Tex2F(0.0, 0.0)};
+    V2F_C4B_T2F b = {destination, Color4B(color), Tex2F(0.0, 0.0)};
+    
+    *point = a;
+    *(point+1) = b;
+    
+    _bufferCountGLLine += 2;
+    _dirtyGLLine = true;
+}
+
+void DrawNode::drawRect(const Vec2 &origin, const Vec2 &destination, const Color4F &color)
+{
+    drawLine(Vec2(origin.x, origin.y), Vec2(destination.x, origin.y), color);
+    drawLine(Vec2(destination.x, origin.y), Vec2(destination.x, destination.y), color);
+    drawLine(Vec2(destination.x, destination.y), Vec2(origin.x, destination.y), color);
+    drawLine(Vec2(origin.x, destination.y), Vec2(origin.x, origin.y), color);
+}
+
+void DrawNode::drawPoly(const Vec2 *poli, unsigned int numberOfPoints, bool closePolygon, const Color4F &color)
+{
+    unsigned int vertex_count;
+    if(closePolygon)
+    {
+        vertex_count = 2 * numberOfPoints;
+        ensureCapacityGLLine(vertex_count);
+    }
+    else
+    {
+        vertex_count = 2 * (numberOfPoints - 1);
+        ensureCapacityGLLine(vertex_count);
+    }
+    
+    V2F_C4B_T2F *point = (V2F_C4B_T2F*)(_bufferGLLine + _bufferCountGLLine);
+ 
+    unsigned int i = 0;
+    for(; i<numberOfPoints-1; i++)
+    {
+        V2F_C4B_T2F a = {poli[i], Color4B(color), Tex2F(0.0, 0.0)};
+        V2F_C4B_T2F b = {poli[i+1], Color4B(color), Tex2F(0.0, 0.0)};
+        
+        *point = a;
+        *(point+1) = b;
+        point += 2;
+    }
+    if(closePolygon)
+    {
+        V2F_C4B_T2F a = {poli[i], Color4B(color), Tex2F(0.0, 0.0)};
+        V2F_C4B_T2F b = {poli[0], Color4B(color), Tex2F(0.0, 0.0)};
+        *point = a;
+        *(point+1) = b;
+    }
+    
+    _bufferCountGLLine += vertex_count;
+}
+
+void DrawNode::drawCircle(const Vec2& center, float radius, float angle, unsigned int segments, bool drawLineToCenter, float scaleX, float scaleY, const Color4F &color)
+{
+    const float coef = 2.0f * (float)M_PI/segments;
+    
+    Vec2 *vertices = new (std::nothrow) Vec2[segments+2];
+    if( ! vertices )
+        return;
+    
+    for(unsigned int i = 0;i <= segments; i++) {
+        float rads = i*coef;
+        GLfloat j = radius * cosf(rads + angle) * scaleX + center.x;
+        GLfloat k = radius * sinf(rads + angle) * scaleY + center.y;
+        
+        vertices[i].x = j;
+        vertices[i].y = k;
+    }
+    if(drawLineToCenter)
+    {
+        vertices[segments+1].x = center.x;
+        vertices[segments+1].y = center.y;
+        drawPoly(vertices, segments+2, true, color);
+    }
+    else
+        drawPoly(vertices, segments+1, true, color);
+    
+    CC_SAFE_DELETE_ARRAY(vertices);
+}
+
+void DrawNode::drawCircle(const Vec2 &center, float radius, float angle, unsigned int segments, bool drawLineToCenter, const Color4F &color)
+{
+    drawCircle(center, radius, angle, segments, drawLineToCenter, 1.0f, 1.0f, color);
+}
+
+void DrawNode::drawQuadBezier(const Vec2 &origin, const Vec2 &control, const Vec2 &destination, unsigned int segments, const Color4F &color)
+{
+    Vec2* vertices = new (std::nothrow) Vec2[segments + 1];
+    if( ! vertices )
+        return;
+    
+    float t = 0.0f;
+    for(unsigned int i = 0; i < segments; i++)
+    {
+        vertices[i].x = powf(1 - t, 2) * origin.x + 2.0f * (1 - t) * t * control.x + t * t * destination.x;
+        vertices[i].y = powf(1 - t, 2) * origin.y + 2.0f * (1 - t) * t * control.y + t * t * destination.y;
+        t += 1.0f / segments;
+    }
+    vertices[segments].x = destination.x;
+    vertices[segments].y = destination.y;
+    
+    drawPoly(vertices, segments+1, false, color);
+
+    CC_SAFE_DELETE_ARRAY(vertices);
+}
+
+void DrawNode::drawCubicBezier(const Vec2 &origin, const Vec2 &control1, const Vec2 &control2, const Vec2 &destination, unsigned int segments, const Color4F &color)
+{
+    Vec2* vertices = new (std::nothrow) Vec2[segments + 1];
+    if( ! vertices )
+        return;
+    
+    float t = 0;
+    for (unsigned int i = 0; i < segments; i++)
+    {
+        vertices[i].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;
+        vertices[i].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;
+        t += 1.0f / segments;
+    }
+    vertices[segments].x = destination.x;
+    vertices[segments].y = destination.y;
+    
+    drawPoly(vertices, segments+1, false, color);
+
+    CC_SAFE_DELETE_ARRAY(vertices);
+}
+
+void DrawNode::drawCardinalSpline(PointArray *config, float tension,  unsigned int segments, const Color4F &color)
+{
+    Vec2* vertices = new (std::nothrow) Vec2[segments + 1];
+    if( ! vertices )
+        return;
+    
+    ssize_t p;
+    float lt;
+    float deltaT = 1.0f / config->count();
+    
+    for( unsigned int i=0; i < segments+1;i++) {
+        
+        float dt = (float)i / segments;
+        
+        // border
+        if( dt == 1 ) {
+            p = config->count() - 1;
+            lt = 1;
+        } else {
+            p = dt / deltaT;
+            lt = (dt - deltaT * (float)p) / deltaT;
+        }
+        
+        // Interpolate
+        Vec2 pp0 = config->getControlPointAtIndex(p-1);
+        Vec2 pp1 = config->getControlPointAtIndex(p+0);
+        Vec2 pp2 = config->getControlPointAtIndex(p+1);
+        Vec2 pp3 = config->getControlPointAtIndex(p+2);
+        
+        Vec2 newPos = ccCardinalSplineAt( pp0, pp1, pp2, pp3, tension, lt);
+        vertices[i].x = newPos.x;
+        vertices[i].y = newPos.y;
+    }
+    
+    drawPoly(vertices, segments+1, false, color);
+    
+    CC_SAFE_DELETE_ARRAY(vertices);
+}
+
+void DrawNode::drawCatmullRom(PointArray *points, unsigned int segments, const Color4F &color)
+{
+    drawCardinalSpline( points, 0.5f, segments, color);
+}
+
+void DrawNode::drawDot(const Vec2 &pos, float radius, const Color4F &color)
+{
+    unsigned int vertex_count = 2*3;
+    ensureCapacity(vertex_count);
+    
+    V2F_C4B_T2F a = {Vec2(pos.x - radius, pos.y - radius), Color4B(color), Tex2F(-1.0, -1.0) };
+    V2F_C4B_T2F b = {Vec2(pos.x - radius, pos.y + radius), Color4B(color), Tex2F(-1.0,  1.0) };
+    V2F_C4B_T2F c = {Vec2(pos.x + radius, pos.y + radius), Color4B(color), Tex2F( 1.0,  1.0) };
+    V2F_C4B_T2F d = {Vec2(pos.x + radius, pos.y - radius), Color4B(color), Tex2F( 1.0, -1.0) };
+    
+    V2F_C4B_T2F_Triangle *triangles = (V2F_C4B_T2F_Triangle *)(_buffer + _bufferCount);
+    V2F_C4B_T2F_Triangle triangle0 = {a, b, c};
+    V2F_C4B_T2F_Triangle triangle1 = {a, c, d};
+    triangles[0] = triangle0;
+    triangles[1] = triangle1;
+    
+    _bufferCount += vertex_count;
+    
+    _dirty = true;
+}
+
+void DrawNode::drawRect(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3, const Vec2& p4, const Color4F &color)
+{
+    drawLine(Vec2(p1.x, p1.y), Vec2(p2.x, p2.y), color);
+    drawLine(Vec2(p2.x, p2.y), Vec2(p3.x, p3.y), color);
+    drawLine(Vec2(p3.x, p3.y), Vec2(p4.x, p4.y), color);
+    drawLine(Vec2(p4.x, p4.y), Vec2(p1.x, p1.y), color);
+}
+
+void DrawNode::drawSegment(const Vec2 &from, const Vec2 &to, float radius, const Color4F &color)
+{
+    unsigned int vertex_count = 6*3;
+    ensureCapacity(vertex_count);
+    
+    Vec2 a = __v2f(from);
+    Vec2 b = __v2f(to);
+    
+    
+    Vec2 n = v2fnormalize(v2fperp(v2fsub(b, a)));
+    Vec2 t = v2fperp(n);
+    
+    Vec2 nw = v2fmult(n, radius);
+    Vec2 tw = v2fmult(t, radius);
+    Vec2 v0 = v2fsub(b, v2fadd(nw, tw));
+    Vec2 v1 = v2fadd(b, v2fsub(nw, tw));
+    Vec2 v2 = v2fsub(b, nw);
+    Vec2 v3 = v2fadd(b, nw);
+    Vec2 v4 = v2fsub(a, nw);
+    Vec2 v5 = v2fadd(a, nw);
+    Vec2 v6 = v2fsub(a, v2fsub(nw, tw));
+    Vec2 v7 = v2fadd(a, v2fadd(nw, tw));
+    
+    
+    V2F_C4B_T2F_Triangle *triangles = (V2F_C4B_T2F_Triangle *)(_buffer + _bufferCount);
+    
+    V2F_C4B_T2F_Triangle triangles0 = {
+        {v0, Color4B(color), __t(v2fneg(v2fadd(n, t)))},
+        {v1, Color4B(color), __t(v2fsub(n, t))},
+        {v2, Color4B(color), __t(v2fneg(n))},
+    };
+    triangles[0] = triangles0;
+    
+    V2F_C4B_T2F_Triangle triangles1 = {
+        {v3, Color4B(color), __t(n)},
+        {v1, Color4B(color), __t(v2fsub(n, t))},
+        {v2, Color4B(color), __t(v2fneg(n))},
+    };
+    triangles[1] = triangles1;
+    
+    V2F_C4B_T2F_Triangle triangles2 = {
+        {v3, Color4B(color), __t(n)},
+        {v4, Color4B(color), __t(v2fneg(n))},
+        {v2, Color4B(color), __t(v2fneg(n))},
+    };
+    triangles[2] = triangles2;
+
+    V2F_C4B_T2F_Triangle triangles3 = {
+        {v3, Color4B(color), __t(n)},
+        {v4, Color4B(color), __t(v2fneg(n))},
+        {v5, Color4B(color), __t(n) },
+    };
+    triangles[3] = triangles3;
+
+    V2F_C4B_T2F_Triangle triangles4 = {
+        {v6, Color4B(color), __t(v2fsub(t, n))},
+        {v4, Color4B(color), __t(v2fneg(n)) },
+        {v5, Color4B(color), __t(n)},
+    };
+    triangles[4] = triangles4;
+
+    V2F_C4B_T2F_Triangle triangles5 = {
+        {v6, Color4B(color), __t(v2fsub(t, n))},
+        {v7, Color4B(color), __t(v2fadd(n, t))},
+        {v5, Color4B(color), __t(n)},
+    };
+    triangles[5] = triangles5;
+    
+    _bufferCount += vertex_count;
+    
+    _dirty = true;
+}
+
+void DrawNode::drawPolygon(const Vec2 *verts, int count, const Color4F &fillColor, float borderWidth, const Color4F &borderColor)
+{
+    CCASSERT(count >= 0, "invalid count value");
+    
+    bool outline = (borderColor.a > 0.0f && borderWidth > 0.0f);
+    
+    auto  triangle_count = outline ? (3*count - 2) : (count - 2);
+    auto vertex_count = 3*triangle_count;
+    ensureCapacity(vertex_count);
+    
+    V2F_C4B_T2F_Triangle *triangles = (V2F_C4B_T2F_Triangle *)(_buffer + _bufferCount);
+    V2F_C4B_T2F_Triangle *cursor = triangles;
+    
+    for (int i = 0; i < count-2; i++)
+    {
+        V2F_C4B_T2F_Triangle tmp = {
+            {verts[0], Color4B(fillColor), __t(v2fzero)},
+            {verts[i+1], Color4B(fillColor), __t(v2fzero)},
+            {verts[i+2], Color4B(fillColor), __t(v2fzero)},
+        };
+        
+        *cursor++ = tmp;
+    }
+    
+    if(outline)
+    {
+        struct ExtrudeVerts {Vec2 offset, n;};
+        struct ExtrudeVerts* extrude = (struct ExtrudeVerts*)malloc(sizeof(struct ExtrudeVerts)*count);
+        memset(extrude, 0, sizeof(struct ExtrudeVerts)*count);
+        
+        for (int i = 0; i < count; i++)
+        {
+            Vec2 v0 = __v2f(verts[(i-1+count)%count]);
+            Vec2 v1 = __v2f(verts[i]);
+            Vec2 v2 = __v2f(verts[(i+1)%count]);
+            
+            Vec2 n1 = v2fnormalize(v2fperp(v2fsub(v1, v0)));
+            Vec2 n2 = v2fnormalize(v2fperp(v2fsub(v2, v1)));
+            
+            Vec2 offset = v2fmult(v2fadd(n1, n2), 1.0f / (v2fdot(n1, n2) + 1.0f));
+            struct ExtrudeVerts tmp = {offset, n2};
+            extrude[i] = tmp;
+        }
+        
+        for(int i = 0; i < count; i++)
+        {
+            int j = (i+1)%count;
+            Vec2 v0 = __v2f(verts[i]);
+            Vec2 v1 = __v2f(verts[j]);
+            
+            Vec2 n0 = extrude[i].n;
+            
+            Vec2 offset0 = extrude[i].offset;
+            Vec2 offset1 = extrude[j].offset;
+            
+            Vec2 inner0 = v2fsub(v0, v2fmult(offset0, borderWidth));
+            Vec2 inner1 = v2fsub(v1, v2fmult(offset1, borderWidth));
+            Vec2 outer0 = v2fadd(v0, v2fmult(offset0, borderWidth));
+            Vec2 outer1 = v2fadd(v1, v2fmult(offset1, borderWidth));
+            
+            V2F_C4B_T2F_Triangle tmp1 = {
+                {inner0, Color4B(borderColor), __t(v2fneg(n0))},
+                {inner1, Color4B(borderColor), __t(v2fneg(n0))},
+                {outer1, Color4B(borderColor), __t(n0)}
+            };
+            *cursor++ = tmp1;
+            
+            V2F_C4B_T2F_Triangle tmp2 = {
+                {inner0, Color4B(borderColor), __t(v2fneg(n0))},
+                {outer0, Color4B(borderColor), __t(n0)},
+                {outer1, Color4B(borderColor), __t(n0)}
+            };
+            *cursor++ = tmp2;
+        }
+        
+        free(extrude);
+    }
+    
+    _bufferCount += vertex_count;
+    
+    _dirty = true;
+}
+
+void DrawNode::drawSolidRect(const Vec2 &origin, const Vec2 &destination, const Color4F &color)
+{
+    Vec2 vertices[] = {
+        origin,
+        Vec2(destination.x, origin.y),
+        destination,
+        Vec2(origin.x, destination.y)
+    };
+    
+    drawSolidPoly(vertices, 4, color );
+}
+
+void DrawNode::drawSolidPoly(const Vec2 *poli, unsigned int numberOfPoints, const Color4F &color)
+{
+    drawPolygon(poli, numberOfPoints, color, 0.0, Color4F(0.0, 0.0, 0.0, 0.0));
+}
+
+void DrawNode::drawSolidCircle(const Vec2& center, float radius, float angle, unsigned int segments, float scaleX, float scaleY, const Color4F &color)
+{
+    const float coef = 2.0f * (float)M_PI/segments;
+    
+    Vec2 *vertices = new (std::nothrow) Vec2[segments];
+    if( ! vertices )
+        return;
+    
+    for(unsigned int i = 0;i < segments; i++)
+    {
+        float rads = i*coef;
+        GLfloat j = radius * cosf(rads + angle) * scaleX + center.x;
+        GLfloat k = radius * sinf(rads + angle) * scaleY + center.y;
+        
+        vertices[i].x = j;
+        vertices[i].y = k;
+    }
+    
+    drawSolidPoly(vertices, segments, color);
+    
+    CC_SAFE_DELETE_ARRAY(vertices);
+}
+
+void DrawNode::drawSolidCircle( const Vec2& center, float radius, float angle, unsigned int segments, const Color4F& color)
+{
+    drawSolidCircle(center, radius, angle, segments, 1.0f, 1.0f, color);
+}
+
+void DrawNode::drawTriangle(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3, const Color4F &color)
+{
+    unsigned int vertex_count = 3;
+    ensureCapacity(vertex_count);
+
+    Color4B col = Color4B(color);
+    V2F_C4B_T2F a = {Vec2(p1.x, p1.y), col, Tex2F(0.0, 0.0) };
+    V2F_C4B_T2F b = {Vec2(p2.x, p2.y), col, Tex2F(0.0,  0.0) };
+    V2F_C4B_T2F c = {Vec2(p3.x, p3.y), col, Tex2F(0.0,  0.0) };
+
+    V2F_C4B_T2F_Triangle *triangles = (V2F_C4B_T2F_Triangle *)(_buffer + _bufferCount);
+    V2F_C4B_T2F_Triangle triangle = {a, b, c};
+    triangles[0] = triangle;
+
+    _bufferCount += vertex_count;
+    _dirty = true;
+}
+
+void DrawNode::drawQuadraticBezier(const Vec2& from, const Vec2& control, const Vec2& to, unsigned int segments, const Color4F &color)
+{
+    drawQuadBezier(from, control, to, segments, color);
+}
+
+void DrawNode::clear()
+{
+    _bufferCount = 0;
+    _dirty = true;
+    _bufferCountGLLine = 0;
+    _dirtyGLLine = true;
+    _bufferCountGLPoint = 0;
+    _dirtyGLPoint = true;
+    _lineWidth = _defaultLineWidth;
+}
+
+const BlendFunc& DrawNode::getBlendFunc() const
+{
+    return _blendFunc;
+}
+
+void DrawNode::setBlendFunc(const BlendFunc &blendFunc)
+{
+    _blendFunc = blendFunc;
+}
+
+void DrawNode::setLineWidth(GLfloat lineWidth)
+{
+    _lineWidth = lineWidth;
+}
+
+GLfloat DrawNode::getLineWidth()
+{
+    return this->_lineWidth;
+}
+
+
+NS_CC_END

+ 370 - 0
cocos2d/cocos/2d/CCDrawNode.h

@@ -0,0 +1,370 @@
+/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software
+ * Copyright (c) 2012 cocos2d-x.org
+ * Copyright (c) 2013-2017 Chukong Technologies Inc.
+ *
+ * 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.
+ */
+
+/*
+ * Code copied & pasted from SpacePatrol game https://github.com/slembcke/SpacePatrol
+ *
+ * Renamed and added some changes for cocos2d
+ *
+ */
+
+#ifndef __CCDRAWNODES_CCDRAW_NODE_H__
+#define __CCDRAWNODES_CCDRAW_NODE_H__
+
+#include "2d/CCNode.h"
+#include "base/ccTypes.h"
+#include "renderer/CCCustomCommand.h"
+#include "math/CCMath.h"
+
+NS_CC_BEGIN
+
+static const int DEFAULT_LINE_WIDTH = 2;
+
+class PointArray;
+/**
+ * @addtogroup _2d
+ * @{
+ */
+
+/** @class DrawNode
+ * @brief Node that draws dots, segments and polygons.
+ * Faster than the "drawing primitives" since they draws everything in one single batch.
+ * @since v2.1
+ */
+class CC_DLL DrawNode : public Node
+{
+public:
+    /** creates and initialize a DrawNode node.
+     *
+     * @return Return an autorelease object.
+     */
+    static DrawNode* create(GLfloat defaultLineWidth = DEFAULT_LINE_WIDTH);
+    
+    /** Draw a point.
+     *
+     * @param point A Vec2 used to point.
+     * @param pointSize The point size.
+     * @param color The point color.
+     * @js NA
+     */
+    void drawPoint(const Vec2& point, const float pointSize, const Color4F &color);
+    
+    /** Draw a group point.
+     *
+     * @param position A Vec2 pointer.
+     * @param numberOfPoints The number of points.
+     * @param color The point color.
+     * @js NA
+     */
+    void drawPoints(const Vec2 *position, unsigned int numberOfPoints, const Color4F &color);
+    
+    /** Draw a group point.
+     *
+     * @param position A Vec2 pointer.
+     * @param numberOfPoints The number of points.
+     * @param pointSize The point size.
+     * @param color The point color.
+     * @js NA
+     */
+    void drawPoints(const Vec2 *position, unsigned int numberOfPoints, const float pointSize, const Color4F &color);
+    
+    /** Draw an line from origin to destination with color. 
+     * 
+     * @param origin The line origin.
+     * @param destination The line destination.
+     * @param color The line color.
+     * @js NA
+     */
+    void drawLine(const Vec2 &origin, const Vec2 &destination, const Color4F &color);
+    
+    /** Draws a rectangle given the origin and destination point measured in points.
+     * The origin and the destination can not have the same x and y coordinate.
+     *
+     * @param origin The rectangle origin.
+     * @param destination The rectangle destination.
+     * @param color The rectangle color.
+     */
+    void drawRect(const Vec2 &origin, const Vec2 &destination, const Color4F &color);
+    
+    /** Draws a polygon given a pointer to point coordinates and the number of vertices measured in points.
+     * The polygon can be closed or open.
+     *
+     * @param poli A pointer to point coordinates.
+     * @param numberOfPoints The number of vertices measured in points.
+     * @param closePolygon The polygon can be closed or open.
+     * @param color The polygon color.
+     */
+    void drawPoly(const Vec2 *poli, unsigned int numberOfPoints, bool closePolygon, const Color4F &color);
+    
+    /** Draws a circle given the center, radius and number of segments.
+     *
+     * @param center The circle center point.
+     * @param radius The circle rotate of radius.
+     * @param angle  The circle angle.
+     * @param segments The number of segments.
+     * @param drawLineToCenter Whether or not draw the line from the origin to center.
+     * @param scaleX The scale value in x.
+     * @param scaleY The scale value in y.
+     * @param color Set the circle color.
+     */
+    void drawCircle( const Vec2& center, float radius, float angle, unsigned int segments, bool drawLineToCenter, float scaleX, float scaleY, const Color4F &color);
+    
+    /** Draws a circle given the center, radius and number of segments.
+     *
+     * @param center The circle center point.
+     * @param radius The circle rotate of radius.
+     * @param angle  The circle angle.
+     * @param segments The number of segments.
+     * @param drawLineToCenter Whether or not draw the line from the origin to center.
+     * @param color Set the circle color.
+     */
+    void drawCircle(const Vec2 &center, float radius, float angle, unsigned int segments, bool drawLineToCenter, const Color4F &color);
+    
+    /** Draws a quad bezier path.
+     *
+     * @param origin The origin of the bezier path.
+     * @param control The control of the bezier path.
+     * @param destination The destination of the bezier path.
+     * @param segments The number of segments.
+     * @param color Set the quad bezier color.
+     */
+    void drawQuadBezier(const Vec2 &origin, const Vec2 &control, const Vec2 &destination, unsigned int segments, const Color4F &color);
+
+    /** Draw a cubic bezier curve with color and number of segments
+     *
+     * @param origin The origin of the bezier path.
+     * @param control1 The first control of the bezier path.
+     * @param control2 The second control of the bezier path.
+     * @param destination The destination of the bezier path.
+     * @param segments The number of segments.
+     * @param color Set the cubic bezier color.
+     */
+    void drawCubicBezier(const Vec2 &origin, const Vec2 &control1, const Vec2 &control2, const Vec2 &destination, unsigned int segments, const Color4F &color);
+    
+    /** Draws a Cardinal Spline path.
+     *
+     * @param config A array point.
+     * @param tension The tension of the spline.
+     * @param segments The number of segments.
+     * @param color Set the Spline color.
+     */
+    void drawCardinalSpline(PointArray *config, float tension,  unsigned int segments, const Color4F &color);
+    
+    /** Draws a Catmull Rom path.
+     *
+     * @param points A point array  of control point.
+     * @param segments The number of segments.
+     * @param color The Catmull Rom color.
+     */
+    void drawCatmullRom(PointArray *points, unsigned int segments, const Color4F &color);
+    
+    /** draw a dot at a position, with a given radius and color. 
+     *
+     * @param pos The dot center.
+     * @param radius The dot radius.
+     * @param color The dot color.
+     */
+    void drawDot(const Vec2 &pos, float radius, const Color4F &color);
+    
+    /** Draws a rectangle with 4 points.
+     *
+     * @param p1 The rectangle vertex point.
+     * @param p2 The rectangle vertex point.
+     * @param p3 The rectangle vertex point.
+     * @param p4 The rectangle vertex point.
+     * @param color The rectangle color.
+     */
+    void drawRect(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3, const Vec2& p4, const Color4F &color);
+    
+    /** Draws a solid rectangle given the origin and destination point measured in points.
+     * The origin and the destination can not have the same x and y coordinate.
+     *
+     * @param origin The rectangle origin.
+     * @param destination The rectangle destination.
+     * @param color The rectangle color.
+     * @js NA
+     */
+    void drawSolidRect(const Vec2 &origin, const Vec2 &destination, const Color4F &color);
+    
+    /** Draws a solid polygon given a pointer to CGPoint coordinates, the number of vertices measured in points, and a color.
+     *
+     * @param poli A solid polygon given a pointer to CGPoint coordinates.
+     * @param numberOfPoints The number of vertices measured in points.
+     * @param color The solid polygon color.
+     * @js NA
+     */
+    void drawSolidPoly(const Vec2 *poli, unsigned int numberOfPoints, const Color4F &color);
+    
+    /** Draws a solid circle given the center, radius and number of segments.
+     * @param center The circle center point.
+     * @param radius The circle rotate of radius.
+     * @param angle  The circle angle.
+     * @param segments The number of segments.
+     * @param scaleX The scale value in x.
+     * @param scaleY The scale value in y.
+     * @param color The solid circle color.
+     * @js NA
+     */
+    void drawSolidCircle(const Vec2& center, float radius, float angle, unsigned int segments, float scaleX, float scaleY, const Color4F &color);
+    
+    /** Draws a solid circle given the center, radius and number of segments.
+     * @param center The circle center point.
+     * @param radius The circle rotate of radius.
+     * @param angle  The circle angle.
+     * @param segments The number of segments.
+     * @param color The solid circle color.
+     * @js NA
+     */
+    void drawSolidCircle(const Vec2& center, float radius, float angle, unsigned int segments, const Color4F& color);
+    
+    /** draw a segment with a radius and color. 
+     *
+     * @param from The segment origin.
+     * @param to The segment destination.
+     * @param radius The segment radius.
+     * @param color The segment color.
+     */
+    void drawSegment(const Vec2 &from, const Vec2 &to, float radius, const Color4F &color);
+    
+    /** draw a polygon with a fill color and line color
+    * @code
+    * When this function bound into js or lua,the parameter will be changed
+    * In js: var drawPolygon(var Arrayofpoints, var fillColor, var width, var borderColor)
+    * In lua:local drawPolygon(local pointTable,local tableCount,local fillColor,local width,local borderColor)
+    * @endcode
+    * @param verts A pointer to point coordinates.
+    * @param count The number of verts measured in points.
+    * @param fillColor The color will fill in polygon.
+    * @param borderWidth The border of line width.
+    * @param borderColor The border of line color.
+    * @js NA
+    */
+    void drawPolygon(const Vec2 *verts, int count, const Color4F &fillColor, float borderWidth, const Color4F &borderColor);
+	
+    /** draw a triangle with color. 
+     *
+     * @param p1 The triangle vertex point.
+     * @param p2 The triangle vertex point.
+     * @param p3 The triangle vertex point.
+     * @param color The triangle color.
+     * @js NA
+     */
+    void drawTriangle(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3, const Color4F &color);
+
+    /** draw a quadratic bezier curve with color and number of segments, use drawQuadBezier instead.
+     *
+     * @param from The origin of the bezier path.
+     * @param control The control of the bezier path.
+     * @param to The destination of the bezier path.
+     * @param segments The number of segments.
+     * @param color The quadratic bezier color.
+     * @js NA
+     */
+    CC_DEPRECATED_ATTRIBUTE void drawQuadraticBezier(const Vec2& from, const Vec2& control, const Vec2& to, unsigned int segments, const Color4F &color);
+    
+    /** Clear the geometry in the node's buffer. */
+    void clear();
+    /** Get the color mixed mode.
+    * @lua NA
+    */
+    const BlendFunc& getBlendFunc() const;
+    /** Set the color mixed mode.
+    * @code
+    * When this function bound into js or lua,the parameter will be changed
+    * In js: var setBlendFunc(var src, var dst)
+    * @endcode
+    * @lua NA
+    */
+    void setBlendFunc(const BlendFunc &blendFunc);
+
+    /**
+     * @js NA
+     */
+    virtual void onDraw(const Mat4 &transform, uint32_t flags);
+    /**
+     * @js NA
+     */
+    virtual void onDrawGLLine(const Mat4 &transform, uint32_t flags);
+    /**
+     * @js NA
+     */
+    virtual void onDrawGLPoint(const Mat4 &transform, uint32_t flags);
+    
+    // Overrides
+    virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override;
+    
+    void setLineWidth(GLfloat lineWidth);
+
+    // Get CocosStudio guide lines width.
+    GLfloat getLineWidth();
+
+CC_CONSTRUCTOR_ACCESS:
+    DrawNode(GLfloat lineWidth = DEFAULT_LINE_WIDTH);
+    virtual ~DrawNode();
+    virtual bool init() override;
+
+protected:
+    void ensureCapacity(int count);
+    void ensureCapacityGLPoint(int count);
+    void ensureCapacityGLLine(int count);
+
+    GLuint      _vao;
+    GLuint      _vbo;
+    GLuint      _vaoGLPoint;
+    GLuint      _vboGLPoint;
+    GLuint      _vaoGLLine;
+    GLuint      _vboGLLine;
+
+    int         _bufferCapacity;
+    GLsizei     _bufferCount;
+    V2F_C4B_T2F *_buffer;
+    
+    int         _bufferCapacityGLPoint;
+    GLsizei     _bufferCountGLPoint;
+    V2F_C4B_T2F *_bufferGLPoint;
+    Color4F     _pointColor;
+    int         _pointSize;
+    
+    int         _bufferCapacityGLLine;
+    GLsizei     _bufferCountGLLine;
+    V2F_C4B_T2F *_bufferGLLine;
+
+    BlendFunc   _blendFunc;
+    CustomCommand _customCommand;
+    CustomCommand _customCommandGLPoint;
+    CustomCommand _customCommandGLLine;
+
+    bool        _dirty;
+    bool        _dirtyGLPoint;
+    bool        _dirtyGLLine;
+    
+    GLfloat         _lineWidth;
+
+    GLfloat  _defaultLineWidth;
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(DrawNode);
+};
+/** @} */
+NS_CC_END
+
+#endif // __CCDRAWNODES_CCDRAW_NODE_H__

+ 447 - 0
cocos2d/cocos/2d/CCDrawingPrimitives.cpp

@@ -0,0 +1,447 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2010-2013 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+
+/*
+ *
+ * IMPORTANT       IMPORTANT        IMPORTANT        IMPORTANT
+ *
+ *
+ * LEGACY FUNCTIONS
+ *
+ * USE DrawNode instead
+ *
+ */
+
+#include "2d/CCDrawingPrimitives.h"
+
+#include <string.h>
+#include <cmath>
+
+#include "2d/CCActionCatmullRom.h"
+#include "base/CCDirector.h"
+#include "renderer/ccGLStateCache.h"
+#include "renderer/CCGLProgramCache.h"
+#include "renderer/CCRenderer.h"
+#include "platform/CCGL.h"
+
+NS_CC_BEGIN
+
+#if defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#elif _MSC_VER >= 1400 //vs 2005 or higher
+#pragma warning (push)
+#pragma warning (disable: 4996)
+#endif
+
+#ifndef M_PI
+    #define M_PI       3.14159265358979323846
+#endif
+
+namespace DrawPrimitives {
+
+static bool s_initialized = false;
+static GLProgram* s_shader = nullptr;
+static int s_colorLocation = -1;
+static Color4F s_color(1.0f,1.0f,1.0f,1.0f);
+static int s_pointSizeLocation = -1;
+static GLfloat s_pointSize = 1.0f;
+
+
+static void lazy_init()
+{
+    if( ! s_initialized ) {
+
+        //
+        // Position and 1 color passed as a uniform (to simulate glColor4ub )
+        //
+        s_shader = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_U_COLOR);
+        s_shader->retain();
+        
+        s_colorLocation = s_shader->getUniformLocation("u_color");
+        CHECK_GL_ERROR_DEBUG();
+        s_pointSizeLocation = s_shader->getUniformLocation("u_pointSize");
+        CHECK_GL_ERROR_DEBUG();
+
+        s_initialized = true;
+    }
+}
+
+// When switching from background to foreground on android, we want the parameters to be initialized again
+void init()
+{
+    lazy_init();
+}
+
+void free()
+{
+    CC_SAFE_RELEASE_NULL(s_shader);
+    s_initialized = false;
+}
+
+void drawPoint(const Vec2& point)
+{
+    lazy_init();
+
+    Vec2 p;
+    p.x = point.x;
+    p.y = point.y;
+
+    GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION );
+    s_shader->use();
+    s_shader->setUniformsForBuiltins();
+
+    s_shader->setUniformLocationWith4fv(s_colorLocation, (GLfloat*) &s_color.r, 1);
+    s_shader->setUniformLocationWith1f(s_pointSizeLocation, s_pointSize);
+
+    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, &p);
+
+    glDrawArrays(GL_POINTS, 0, 1);
+
+    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,1);
+}
+
+void drawPoints( const Vec2 *points, unsigned int numberOfPoints )
+{
+    lazy_init();
+
+    GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION );
+    s_shader->use();
+    s_shader->setUniformsForBuiltins();
+    s_shader->setUniformLocationWith4fv(s_colorLocation, (GLfloat*) &s_color.r, 1);
+    s_shader->setUniformLocationWith1f(s_pointSizeLocation, s_pointSize);
+
+    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, points);
+    glDrawArrays(GL_POINTS, 0, (GLsizei) numberOfPoints);
+
+    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, numberOfPoints);
+}
+
+
+void drawLine(const Vec2& origin, const Vec2& destination)
+{
+    lazy_init();
+
+    Vec2 vertices[2] = {
+        Vec2(origin.x, origin.y),
+        Vec2(destination.x, destination.y)
+    };
+
+    s_shader->use();
+    s_shader->setUniformsForBuiltins();
+    s_shader->setUniformLocationWith4fv(s_colorLocation, (GLfloat*) &s_color.r, 1);
+
+    GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION );
+    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
+    glDrawArrays(GL_LINES, 0, 2);
+
+    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,2);
+}
+
+void drawRect( Vec2 origin, Vec2 destination )
+{
+    drawLine(Vec2(origin.x, origin.y), Vec2(destination.x, origin.y));
+    drawLine(Vec2(destination.x, origin.y), Vec2(destination.x, destination.y));
+    drawLine(Vec2(destination.x, destination.y), Vec2(origin.x, destination.y));
+    drawLine(Vec2(origin.x, destination.y), Vec2(origin.x, origin.y));
+}
+
+void drawSolidRect(Vec2 origin, Vec2 destination, Color4F color)
+{
+    Vec2 vertices[] = {
+        origin,
+        Vec2(destination.x, origin.y),
+        destination,
+        Vec2(origin.x, destination.y)
+    };
+
+    drawSolidPoly(vertices, 4, color );
+}
+
+void drawPoly(const Vec2 *poli, unsigned int numberOfPoints, bool closePolygon)
+{
+    lazy_init();
+
+    s_shader->use();
+    s_shader->setUniformsForBuiltins();
+    s_shader->setUniformLocationWith4fv(s_colorLocation, (GLfloat*) &s_color.r, 1);
+
+    GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION );
+
+    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, poli);
+
+    if( closePolygon )
+        glDrawArrays(GL_LINE_LOOP, 0, (GLsizei) numberOfPoints);
+    else
+        glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) numberOfPoints);
+
+    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, numberOfPoints);
+}
+
+void drawSolidPoly(const Vec2 *poli, unsigned int numberOfPoints, Color4F color)
+{
+    lazy_init();
+
+    s_shader->use();
+    s_shader->setUniformsForBuiltins();
+    s_shader->setUniformLocationWith4fv(s_colorLocation, (GLfloat*) &color.r, 1);
+
+    GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION );
+
+    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, poli);
+    glDrawArrays(GL_TRIANGLE_FAN, 0, (GLsizei) numberOfPoints);
+
+    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, numberOfPoints);
+}
+
+void drawCircle( const Vec2& center, float radius, float angle, unsigned int segments, bool drawLineToCenter, float scaleX, float scaleY)
+{
+    lazy_init();
+
+    int additionalSegment = 1;
+    if (drawLineToCenter)
+        additionalSegment++;
+
+    const float coef = 2.0f * (float)M_PI/segments;
+
+    GLfloat *vertices = (GLfloat*)calloc( sizeof(GLfloat)*2*(segments+2), 1);
+    if( ! vertices )
+        return;
+
+    for(unsigned int i = 0;i <= segments; i++) {
+        float rads = i*coef;
+        GLfloat j = radius * cosf(rads + angle) * scaleX + center.x;
+        GLfloat k = radius * sinf(rads + angle) * scaleY + center.y;
+
+        vertices[i*2] = j;
+        vertices[i*2+1] = k;
+    }
+    vertices[(segments+1)*2] = center.x;
+    vertices[(segments+1)*2+1] = center.y;
+
+    s_shader->use();
+    s_shader->setUniformsForBuiltins();
+    s_shader->setUniformLocationWith4fv(s_colorLocation, (GLfloat*) &s_color.r, 1);
+
+    GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION );
+
+    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
+    glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) segments+additionalSegment);
+
+    ::free( vertices );
+
+    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,segments+additionalSegment);
+}
+
+void drawCircle( const Vec2& center, float radius, float angle, unsigned int segments, bool drawLineToCenter)
+{
+    drawCircle(center, radius, angle, segments, drawLineToCenter, 1.0f, 1.0f);
+}
+
+void drawSolidCircle( const Vec2& center, float radius, float angle, unsigned int segments, float scaleX, float scaleY)
+{
+    lazy_init();
+    
+    const float coef = 2.0f * (float)M_PI/segments;
+    
+    GLfloat *vertices = (GLfloat*)calloc( sizeof(GLfloat)*2*(segments+2), 1);
+    if( ! vertices )
+        return;
+    
+    for(unsigned int i = 0;i <= segments; i++) {
+        float rads = i*coef;
+        GLfloat j = radius * cosf(rads + angle) * scaleX + center.x;
+        GLfloat k = radius * sinf(rads + angle) * scaleY + center.y;
+        
+        vertices[i*2] = j;
+        vertices[i*2+1] = k;
+    }
+    vertices[(segments+1)*2] = center.x;
+    vertices[(segments+1)*2+1] = center.y;
+    
+    s_shader->use();
+    s_shader->setUniformsForBuiltins();
+    s_shader->setUniformLocationWith4fv(s_colorLocation, (GLfloat*) &s_color.r, 1);
+    
+    GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION );
+    
+    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
+
+    glDrawArrays(GL_TRIANGLE_FAN, 0, (GLsizei) segments+1);
+    
+    ::free( vertices );
+    
+    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,segments+1);
+}
+
+void drawSolidCircle( const Vec2& center, float radius, float angle, unsigned int segments)
+{
+    drawSolidCircle(center, radius, angle, segments, 1.0f, 1.0f);
+}
+
+void drawQuadBezier(const Vec2& origin, const Vec2& control, const Vec2& destination, unsigned int segments)
+{
+    lazy_init();
+
+    Vec2* vertices = new (std::nothrow) Vec2[segments + 1];
+
+    float t = 0.0f;
+    for(unsigned int i = 0; i < segments; i++)
+    {
+        vertices[i].x = powf(1 - t, 2) * origin.x + 2.0f * (1 - t) * t * control.x + t * t * destination.x;
+        vertices[i].y = powf(1 - t, 2) * origin.y + 2.0f * (1 - t) * t * control.y + t * t * destination.y;
+        t += 1.0f / segments;
+    }
+    vertices[segments].x = destination.x;
+    vertices[segments].y = destination.y;
+
+    s_shader->use();
+    s_shader->setUniformsForBuiltins();
+    s_shader->setUniformLocationWith4fv(s_colorLocation, (GLfloat*) &s_color.r, 1);
+
+    GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION );
+
+    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
+    glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) segments + 1);
+    CC_SAFE_DELETE_ARRAY(vertices);
+
+    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,segments+1);
+}
+
+void drawCatmullRom( PointArray *points, unsigned int segments )
+{
+    drawCardinalSpline( points, 0.5f, segments );
+}
+
+void drawCardinalSpline( PointArray *config, float tension,  unsigned int segments )
+{
+    lazy_init();
+
+    Vec2* vertices = new (std::nothrow) Vec2[segments + 1];
+
+    ssize_t p;
+    float lt;
+    float deltaT = 1.0f / config->count();
+
+    for( unsigned int i=0; i < segments+1;i++) {
+
+        float dt = (float)i / segments;
+
+        // border
+        if( dt == 1 ) {
+            p = config->count() - 1;
+            lt = 1;
+        } else {
+            p = dt / deltaT;
+            lt = (dt - deltaT * (float)p) / deltaT;
+        }
+
+        // Interpolate
+        Vec2 pp0 = config->getControlPointAtIndex(p-1);
+        Vec2 pp1 = config->getControlPointAtIndex(p+0);
+        Vec2 pp2 = config->getControlPointAtIndex(p+1);
+        Vec2 pp3 = config->getControlPointAtIndex(p+2);
+
+        Vec2 newPos = ccCardinalSplineAt( pp0, pp1, pp2, pp3, tension, lt);
+        vertices[i].x = newPos.x;
+        vertices[i].y = newPos.y;
+    }
+
+    s_shader->use();
+    s_shader->setUniformsForBuiltins();
+    s_shader->setUniformLocationWith4fv(s_colorLocation, (GLfloat*)&s_color.r, 1);
+
+    GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION );
+
+    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
+    glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) segments + 1);
+
+    CC_SAFE_DELETE_ARRAY(vertices);
+    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,segments+1);
+}
+
+void drawCubicBezier(const Vec2& origin, const Vec2& control1, const Vec2& control2, const Vec2& destination, unsigned int segments)
+{
+    lazy_init();
+
+    Vec2* vertices = new (std::nothrow) Vec2[segments + 1];
+
+    float t = 0;
+    for (unsigned int i = 0; i < segments; i++)
+    {
+        vertices[i].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;
+        vertices[i].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;
+        t += 1.0f / segments;
+    }
+    vertices[segments].x = destination.x;
+    vertices[segments].y = destination.y;
+
+    s_shader->use();
+    s_shader->setUniformsForBuiltins();
+    s_shader->setUniformLocationWith4fv(s_colorLocation, (GLfloat*) &s_color.r, 1);
+
+    GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION );
+
+    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
+    glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) segments + 1);
+    CC_SAFE_DELETE_ARRAY(vertices);
+
+    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,segments+1);
+}
+
+void setDrawColor4F( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
+{
+    s_color.r = r;
+    s_color.g = g;
+    s_color.b = b;
+    s_color.a = a;
+}
+
+void setPointSize( GLfloat pointSize )
+{
+    s_pointSize = pointSize * CC_CONTENT_SCALE_FACTOR();
+
+    // TODO: glPointSize( pointSize );
+
+}
+
+void setDrawColor4B( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+    s_color.r = r/255.0f;
+    s_color.g = g/255.0f;
+    s_color.b = b/255.0f;
+    s_color.a = a/255.0f;
+}
+
+} // DrawPrimitives namespace
+
+#if defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
+#pragma GCC diagnostic warning "-Wdeprecated-declarations"
+#elif _MSC_VER >= 1400 //vs 2005 or higher
+#pragma warning (pop)
+#endif
+
+NS_CC_END

+ 272 - 0
cocos2d/cocos/2d/CCDrawingPrimitives.h

@@ -0,0 +1,272 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2010-2013 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+
+/*
+ *
+ * IMPORTANT       IMPORTANT        IMPORTANT        IMPORTANT
+ *
+ *
+ * LEGACY FUNCTIONS
+ *
+ * USE DrawNode instead
+ *
+ */
+
+
+#ifndef __CCDRAWING_PRIMITIVES__
+#define __CCDRAWING_PRIMITIVES__
+    
+
+#include "base/ccTypes.h"
+#include "base/ccMacros.h"
+#include "math/CCMath.h"
+
+/**
+ @file
+ Drawing OpenGL ES primitives.
+ - drawPoint, drawPoints
+ - drawLine
+ - drawRect, drawSolidRect
+ - drawPoly, drawSolidPoly
+ - drawCircle
+ - drawQuadBezier
+ - drawCubicBezier
+ - drawCatmullRom
+ - drawCardinalSpline
+ 
+ You can change the color, point size, width by calling:
+ - drawColor4B(), drawColor4F()
+ - ccPointSize()
+ - glLineWidth()
+ 
+ @warning These functions draws the Line, Vec2, Polygon, immediately. They aren't batched. If you are going to make a game that depends on these primitives, I suggest creating a batch. Instead you should use DrawNode
+ 
+ */
+
+NS_CC_BEGIN
+
+/**
+ * @addtogroup _2d
+ * @{
+ */
+
+class PointArray;
+
+/**
+* @js cc.DrawingPrimitiveCanvas/cc.DrawingPrimitiveWebGL
+*/
+namespace DrawPrimitives
+{
+    /**
+     * Initializes the drawing primitives.
+     * @js NA
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL init();
+
+    /**
+     * Frees allocated resources by the drawing primitives.
+     * @js NA
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL free();
+
+    /** Draws a point given x and y coordinate measured in points
+     *
+     * @param point A Vec2 with a point given x and y coordinate.
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL drawPoint(const Vec2& point);
+
+    /** Draws an array of points.
+     *
+     * @param points A point coordinates.
+     * @param numberOfPoints The number of points.
+     * @since v0.7.2
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL drawPoints(const Vec2 *points, unsigned int numberOfPoints);
+
+    /** Draws a line given the origin and destination point measured in points
+     *
+     * @param origin A Vec2 Type point used to the line origin.
+     * @param destination A Vec2 Type point used to the line destination.
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL drawLine(const Vec2& origin, const Vec2& destination);
+
+    /** Draws a rectangle given the origin and destination point measured in points.
+     * The origin and the destination can not have the same x and y coordinate.
+     *
+     * @param origin The rectangle origin.
+     * @param destination The rectangle destination.
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL drawRect(Vec2 origin, Vec2 destination);
+
+    /** Draws a solid rectangle given the origin and destination point measured in points.
+     * The origin and the destination can not have the same x and y coordinate.
+     *
+     * @param origin The rectangle origin.
+     * @param destination The rectangle destination.
+     * @param color The rectangle color.
+     * @since 1.1
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL drawSolidRect(Vec2 origin, Vec2 destination, Color4F color);
+
+    /** Draws a polygon given a pointer to point coordinates and the number of vertices measured in points.
+     * The polygon can be closed or open.
+     *
+     * @param vertices A pointer to point coordinates.
+     * @param numOfVertices The number of vertices measured in points.
+     * @param closePolygon The polygon can be closed or open.
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL drawPoly(const Vec2 *vertices, unsigned int numOfVertices, bool closePolygon);
+
+    /** Draws a solid polygon given a pointer to CGPoint coordinates, the number of vertices measured in points, and a color.
+     *
+     * @param poli A solid polygon given a pointer to CGPoint coordinates.
+     * @param numberOfPoints The number of vertices measured in points.
+     * @param color The solid polygon color.
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL drawSolidPoly(const Vec2 *poli, unsigned int numberOfPoints, Color4F color);
+
+    /** Draws a circle given the center, radius and number of segments. 
+     *
+     * @param center The circle center point.
+     * @param radius The circle rotate of radius.
+     * @param angle  The circle angle.
+     * @param segments The number of segments.
+     * @param drawLineToCenter Whether or not draw the line from the origin to center.
+     * @param scaleX The scale value in x.
+     * @param scaleY The scale value in y.
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL drawCircle(const Vec2& center, float radius, float angle, unsigned int segments, bool drawLineToCenter, float scaleX, float scaleY);
+    
+    /** Draws a circle given the center, radius and number of segments.
+     *
+     * @param center The circle center point.
+     * @param radius The circle rotate of radius.
+     * @param angle  The circle angle.
+     * @param segments The number of segments.
+     * @param drawLineToCenter Whether or not draw the line from the origin to center.
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL drawCircle(const Vec2& center, float radius, float angle, unsigned int segments, bool drawLineToCenter);
+
+    /** Draws a solid circle given the center, radius and number of segments.
+     * @param center The circle center point.
+     * @param radius The circle rotate of radius.
+     * @param angle  The circle angle.
+     * @param segments The number of segments.
+     * @param scaleX The scale value in x.
+     * @param scaleY The scale value in y.
+     * @js NA
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL drawSolidCircle(const Vec2& center, float radius, float angle, unsigned int segments, float scaleX, float scaleY);
+    
+    /** Draws a solid circle given the center, radius and number of segments.
+     * @param center The circle center point.
+     * @param radius The circle rotate of radius.
+     * @param angle  The circle angle.
+     * @param segments The number of segments.
+     * @js NA
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL drawSolidCircle(const Vec2& center, float radius, float angle, unsigned int segments);
+
+    /** Draws a quad bezier path.
+     *
+     * @param origin The origin of the bezier path.
+     * @param control The control of the bezier path.
+     * @param destination The destination of the bezier path.
+     * @param segments The number of segments.
+     * @warning This function could be pretty slow. Use it only for debugging purposes.
+     * @since v0.8
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL drawQuadBezier(const Vec2& origin, const Vec2& control, const Vec2& destination, unsigned int segments);
+
+    /** Draws a cubic bezier path.
+     *
+     * @param origin The origin of the bezier path.
+     * @param control1 The first control of the bezier path.
+     * @param control2 The second control of the bezier path.
+     * @param destination The destination of the bezier path.
+     * @param segments The number of segments.
+     * @warning This function could be pretty slow. Use it only for debugging purposes.
+     * @since v0.8
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL drawCubicBezier(const Vec2& origin, const Vec2& control1, const Vec2& control2, const Vec2& destination, unsigned int segments);
+
+    /** Draws a Catmull Rom path.
+     *
+     * @param arrayOfControlPoints A point array  of control point.
+     * @param segments The number of segments.
+     * @warning This function could be pretty slow. Use it only for debugging purposes.
+     * @since v2.0
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL drawCatmullRom(PointArray *arrayOfControlPoints, unsigned int segments);
+
+    /** Draws a Cardinal Spline path.
+     *
+     * @param config A array point.
+     * @param tension The tension of the spline.
+     * @param segments The number of segments.
+     * @warning This function could be pretty slow. Use it only for debugging purposes.
+     * @since v2.0
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL drawCardinalSpline(PointArray *config, float tension,  unsigned int segments);
+
+    /** Set the drawing color with 4 unsigned bytes.
+     *
+     * @param r The red color with a unsigned bytes.
+     * @param g The green color with a unsigned bytes.
+     * @param b The blue color with a unsigned bytes.
+     * @param a Alpha with a unsigned bytes.
+     * @since v2.0
+     * @js setDrawColor
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL setDrawColor4B(GLubyte r, GLubyte g, GLubyte b, GLubyte a);
+
+    /** Set the drawing color with 4 floats.
+     *
+     * @param r The red color with an floats.
+     * @param g The green color with an floats.
+     * @param b The blue color with an floats.
+     * @param a Alpha with an floats.
+     * @since v2.0
+     * @js setDrawColor
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL setDrawColor4F(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
+
+    /** Set the point size in points. Default 1.
+     *
+     * @param pointSize The point size with an float.
+     * @since v2.0
+     */
+    CC_DEPRECATED_ATTRIBUTE void CC_DLL setPointSize(GLfloat pointSize);
+
+};
+
+// end of global group
+/** @} */
+
+NS_CC_END
+
+#endif // __CCDRAWING_PRIMITIVES__

+ 898 - 0
cocos2d/cocos/2d/CCFastTMXLayer.cpp

@@ -0,0 +1,898 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies Inc.
+
+Copyright (c) 2011 HKASoftware
+
+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.
+****************************************************************************/
+
+/*
+ Original rewrite of TMXLayer was based on HKTMXTiledMap by HKASoftware http://hkasoftware.com
+ Further info: http://www.cocos2d-iphone.org/forums/topic/hktmxtiledmap/
+
+ It was rewritten again, and only a small part of the original HK ideas/code remains in this implementation
+
+ */
+#include "2d/CCFastTMXLayer.h"
+#include "2d/CCFastTMXTiledMap.h"
+#include "2d/CCSprite.h"
+#include "2d/CCCamera.h"
+#include "renderer/CCTextureCache.h"
+#include "renderer/CCGLProgramCache.h"
+#include "renderer/ccGLStateCache.h"
+#include "renderer/CCRenderer.h"
+#include "renderer/CCVertexIndexBuffer.h"
+#include "base/CCDirector.h"
+#include "base/ccUTF8.h"
+
+NS_CC_BEGIN
+namespace experimental {
+
+const int TMXLayer::FAST_TMX_ORIENTATION_ORTHO = 0;
+const int TMXLayer::FAST_TMX_ORIENTATION_HEX = 1;
+const int TMXLayer::FAST_TMX_ORIENTATION_ISO = 2;
+
+// FastTMXLayer - init & alloc & dealloc
+TMXLayer * TMXLayer::create(TMXTilesetInfo *tilesetInfo, TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo)
+{
+    TMXLayer *ret = new (std::nothrow) TMXLayer();
+    if (ret->initWithTilesetInfo(tilesetInfo, layerInfo, mapInfo))
+    {
+        ret->autorelease();
+        return ret;
+    }
+    CC_SAFE_DELETE(ret);
+    return nullptr;
+}
+
+bool TMXLayer::initWithTilesetInfo(TMXTilesetInfo *tilesetInfo, TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo)
+{    
+
+    if( tilesetInfo )
+    {
+        _texture = Director::getInstance()->getTextureCache()->addImage(tilesetInfo->_sourceImage);
+        _texture->retain();
+    }
+
+    // layerInfo
+    _layerName = layerInfo->_name;
+    _layerSize = layerInfo->_layerSize;
+    _tiles = layerInfo->_tiles;
+    _quadsDirty = true;
+    setOpacity( layerInfo->_opacity );
+    setProperties(layerInfo->getProperties());
+
+    // tilesetInfo
+    _tileSet = tilesetInfo;
+    CC_SAFE_RETAIN(_tileSet);
+
+    // mapInfo
+    _mapTileSize = mapInfo->getTileSize();
+    _layerOrientation = mapInfo->getOrientation();
+
+    // offset (after layer orientation is set);
+    Vec2 offset = this->calculateLayerOffset(layerInfo->_offset);
+    this->setPosition(CC_POINT_PIXELS_TO_POINTS(offset));
+
+    this->setContentSize(CC_SIZE_PIXELS_TO_POINTS(Size(_layerSize.width * _mapTileSize.width, _layerSize.height * _mapTileSize.height)));
+    
+    this->tileToNodeTransform();
+
+    // shader, and other stuff
+    setGLProgram(GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR));
+    
+    _useAutomaticVertexZ = false;
+    _vertexZvalue = 0;
+
+    return true;
+}
+
+TMXLayer::TMXLayer()
+: _layerName("")
+, _layerSize(Size::ZERO)
+, _mapTileSize(Size::ZERO)
+, _tiles(nullptr)
+, _tileSet(nullptr)
+, _layerOrientation(FAST_TMX_ORIENTATION_ORTHO)
+, _texture(nullptr)
+, _vertexZvalue(0)
+, _useAutomaticVertexZ(false)
+, _quadsDirty(true)
+, _dirty(true)
+, _vertexBuffer(nullptr)
+, _vData(nullptr)
+, _indexBuffer(nullptr)
+{
+}
+
+TMXLayer::~TMXLayer()
+{
+    CC_SAFE_RELEASE(_tileSet);
+    CC_SAFE_RELEASE(_texture);
+    CC_SAFE_FREE(_tiles);
+    CC_SAFE_RELEASE(_vData);
+    CC_SAFE_RELEASE(_vertexBuffer);
+    CC_SAFE_RELEASE(_indexBuffer);
+    
+}
+
+void TMXLayer::draw(Renderer *renderer, const Mat4& transform, uint32_t flags)
+{
+    updateTotalQuads();
+
+    bool isViewProjectionUpdated = true;
+    auto visitingCamera = Camera::getVisitingCamera();
+    auto defaultCamera = Camera::getDefaultCamera();
+    if (visitingCamera == defaultCamera) {
+        isViewProjectionUpdated = visitingCamera->isViewProjectionUpdated();
+    }
+    
+    if( flags != 0 || _dirty || _quadsDirty || isViewProjectionUpdated)
+    {
+        Size s = Director::getInstance()->getVisibleSize();
+        auto rect = Rect(Camera::getVisitingCamera()->getPositionX() - s.width * 0.5f,
+                     Camera::getVisitingCamera()->getPositionY() - s.height * 0.5f,
+                     s.width,
+                     s.height);
+        
+        Mat4 inv = transform;
+        inv.inverse();
+        rect = RectApplyTransform(rect, inv);
+        
+        updateTiles(rect);
+        updateIndexBuffer();
+        updatePrimitives();
+        _dirty = false;
+    }
+    
+    if(_renderCommands.size() < static_cast<size_t>(_primitives.size()))
+    {
+        _renderCommands.resize(_primitives.size());
+    }
+    
+    int index = 0;
+    for(const auto& iter : _primitives)
+    {
+        if(iter.second->getCount() > 0)
+        {
+            auto& cmd = _renderCommands[index++];
+            auto blendfunc = _texture->hasPremultipliedAlpha() ? BlendFunc::ALPHA_PREMULTIPLIED : BlendFunc::ALPHA_NON_PREMULTIPLIED;
+            cmd.init(iter.first, _texture->getName(), getGLProgramState(), blendfunc, iter.second, _modelViewTransform, flags);
+            renderer->addCommand(&cmd);
+        }
+    }
+}
+
+void TMXLayer::onDraw(Primitive *primitive)
+{
+    GL::bindTexture2D(_texture->getName());
+    getGLProgramState()->apply(_modelViewTransform);
+    
+    GL::bindVAO(0);
+    primitive->draw();
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, primitive->getCount() * 4);
+}
+
+void TMXLayer::updateTiles(const Rect& culledRect)
+{
+    Rect visibleTiles = Rect(culledRect.origin, culledRect.size * Director::getInstance()->getContentScaleFactor());
+    Size mapTileSize = CC_SIZE_PIXELS_TO_POINTS(_mapTileSize);
+    Size tileSize = CC_SIZE_PIXELS_TO_POINTS(_tileSet->_tileSize);
+    Mat4 nodeToTileTransform = _tileToNodeTransform.getInversed();
+    //transform to tile
+    visibleTiles = RectApplyTransform(visibleTiles, nodeToTileTransform);
+    // tile coordinate is upside-down, so we need to make the tile coordinate use top-left for the start point.
+    visibleTiles.origin.y += 1;
+    
+    // if x=0.7, width=9.5, we need to draw number 0~10 of tiles, and so is height.
+    visibleTiles.size.width = ceil(visibleTiles.origin.x + visibleTiles.size.width)  - floor(visibleTiles.origin.x);
+    visibleTiles.size.height = ceil(visibleTiles.origin.y + visibleTiles.size.height) - floor(visibleTiles.origin.y);
+    visibleTiles.origin.x = floor(visibleTiles.origin.x);
+    visibleTiles.origin.y = floor(visibleTiles.origin.y);
+
+    // for the bigger tiles.
+    int tilesOverX = 0;
+    int tilesOverY = 0;
+    // for diagonal orientation tiles
+    float tileSizeMax = std::max(tileSize.width, tileSize.height);
+    if (_layerOrientation == FAST_TMX_ORIENTATION_ORTHO)
+    {
+        tilesOverX = ceil(tileSizeMax / mapTileSize.width) - 1;
+        tilesOverY = ceil(tileSizeMax / mapTileSize.height) - 1;
+        
+        if (tilesOverX < 0) tilesOverX = 0;
+        if (tilesOverY < 0) tilesOverY = 0;
+    }
+    else if(_layerOrientation == FAST_TMX_ORIENTATION_ISO)
+    {
+        Rect overTileRect(0, 0, tileSizeMax - mapTileSize.width, tileSizeMax - mapTileSize.height);
+        if (overTileRect.size.width < 0) overTileRect.size.width = 0;
+        if (overTileRect.size.height < 0) overTileRect.size.height = 0;
+        overTileRect = RectApplyTransform(overTileRect, nodeToTileTransform);
+        
+        tilesOverX = ceil(overTileRect.origin.x + overTileRect.size.width) - floor(overTileRect.origin.x);
+        tilesOverY = ceil(overTileRect.origin.y + overTileRect.size.height) - floor(overTileRect.origin.y);
+    }
+    else
+    {
+        //do nothing, do not support
+        //CCASSERT(0, "TMX invalid value");
+    }
+    
+    _indicesVertexZNumber.clear();
+    
+    for(const auto& iter : _indicesVertexZOffsets)
+    {
+        _indicesVertexZNumber[iter.first] = iter.second;
+    }
+    
+    int yBegin = std::max(0.f,visibleTiles.origin.y - tilesOverY);
+    int yEnd = std::min(_layerSize.height,visibleTiles.origin.y + visibleTiles.size.height + tilesOverY);
+    int xBegin = std::max(0.f,visibleTiles.origin.x - tilesOverX);
+    int xEnd = std::min(_layerSize.width,visibleTiles.origin.x + visibleTiles.size.width + tilesOverX);
+    
+    for (int y =  yBegin; y < yEnd; ++y)
+    {
+        for (int x = xBegin; x < xEnd; ++x)
+        {
+            int tileIndex = getTileIndexByPos(x, y);
+            if(_tiles[tileIndex] == 0) continue;
+            
+            int vertexZ = getVertexZForPos(Vec2(x,y));
+            auto iter = _indicesVertexZNumber.find(vertexZ);
+            int offset = iter->second;
+            iter->second++;
+            
+            int quadIndex = _tileToQuadIndex[tileIndex];
+            CC_ASSERT(-1 != quadIndex);
+            _indices[6 * offset + 0] = quadIndex * 4 + 0;
+            _indices[6 * offset + 1] = quadIndex * 4 + 1;
+            _indices[6 * offset + 2] = quadIndex * 4 + 2;
+            _indices[6 * offset + 3] = quadIndex * 4 + 3;
+            _indices[6 * offset + 4] = quadIndex * 4 + 2;
+            _indices[6 * offset + 5] = quadIndex * 4 + 1;
+            
+        } // for x
+    } // for y
+    
+    for(const auto& iter : _indicesVertexZOffsets)
+    {
+        _indicesVertexZNumber[iter.first] -= iter.second;
+        if(_indicesVertexZNumber[iter.first] == 0)
+        {
+            _indicesVertexZNumber.erase(iter.first);
+        }
+    }
+    
+}
+
+void TMXLayer::updateVertexBuffer()
+{
+    GL::bindVAO(0);
+    if(nullptr == _vData)
+    {
+        _vertexBuffer = VertexBuffer::create(sizeof(V3F_C4B_T2F), (int)_totalQuads.size() * 4);
+        _vData = VertexData::create();
+        _vData->setStream(_vertexBuffer, VertexStreamAttribute(0, GLProgram::VERTEX_ATTRIB_POSITION, GL_FLOAT, 3));
+        _vData->setStream(_vertexBuffer, VertexStreamAttribute(offsetof(V3F_C4B_T2F, colors), GLProgram::VERTEX_ATTRIB_COLOR, GL_UNSIGNED_BYTE, 4, true));
+        _vData->setStream(_vertexBuffer, VertexStreamAttribute(offsetof(V3F_C4B_T2F, texCoords), GLProgram::VERTEX_ATTRIB_TEX_COORD, GL_FLOAT, 2));
+        CC_SAFE_RETAIN(_vData);
+        CC_SAFE_RETAIN(_vertexBuffer);
+    }
+    if(_vertexBuffer)
+    {
+        _vertexBuffer->updateVertices((void*)&_totalQuads[0], (int)_totalQuads.size() * 4, 0);
+    }
+    
+}
+
+void TMXLayer::updateIndexBuffer()
+{
+    if(nullptr == _indexBuffer)
+    {
+#ifdef CC_FAST_TILEMAP_32_BIT_INDICES
+        _indexBuffer = IndexBuffer::create(IndexBuffer::IndexType::INDEX_TYPE_UINT_32, (int)_indices.size());
+#else
+        _indexBuffer = IndexBuffer::create(IndexBuffer::IndexType::INDEX_TYPE_SHORT_16, (int)_indices.size());
+#endif
+        CC_SAFE_RETAIN(_indexBuffer);
+    }
+    _indexBuffer->updateIndices(&_indices[0], (int)_indices.size(), 0);
+    
+}
+
+// FastTMXLayer - setup Tiles
+void TMXLayer::setupTiles()
+{    
+    // Optimization: quick hack that sets the image size on the tileset
+    _tileSet->_imageSize = _texture->getContentSizeInPixels();
+
+    // By default all the tiles are aliased
+    // pros: easier to render
+    // cons: difficult to scale / rotate / etc.
+    _texture->setAliasTexParameters();
+
+    //CFByteOrder o = CFByteOrderGetCurrent();
+
+    // Parse cocos2d properties
+    this->parseInternalProperties();
+
+    Size screenSize = Director::getInstance()->getWinSize();
+
+    switch (_layerOrientation)
+    {
+        case FAST_TMX_ORIENTATION_ORTHO:
+            _screenGridSize.width = ceil(screenSize.width / _mapTileSize.width) + 1;
+            _screenGridSize.height = ceil(screenSize.height / _mapTileSize.height) + 1;
+
+            // tiles could be bigger than the grid, add additional rows if needed
+            _screenGridSize.height += _tileSet->_tileSize.height / _mapTileSize.height;
+            break;
+        case FAST_TMX_ORIENTATION_ISO:
+            _screenGridSize.width = ceil(screenSize.width / _mapTileSize.width) + 2;
+            _screenGridSize.height = ceil(screenSize.height / (_mapTileSize.height/2)) + 4;
+            break;
+        case FAST_TMX_ORIENTATION_HEX:
+        default:
+            CCLOGERROR("FastTMX does not support type %d", _layerOrientation);
+            break;
+    }
+
+    _screenTileCount = _screenGridSize.width * _screenGridSize.height;
+
+}
+
+Mat4 TMXLayer::tileToNodeTransform()
+{
+    float w = _mapTileSize.width / CC_CONTENT_SCALE_FACTOR();
+    float h = _mapTileSize.height / CC_CONTENT_SCALE_FACTOR();
+    float offY = (_layerSize.height - 1) * h;
+    
+    switch(_layerOrientation)
+    {
+        case FAST_TMX_ORIENTATION_ORTHO:
+        {
+            _tileToNodeTransform = Mat4
+            (
+                w, 0.0f, 0.0f, 0.0f,
+                0.0f, -h, 0.0f, offY,
+                0.0f, 0.0f, 1.0f, 0.0f,
+                0.0f, 0.0, 0.0f, 1.0f
+            );
+            
+            return _tileToNodeTransform;
+        }
+        case FAST_TMX_ORIENTATION_ISO:
+        {
+            float offX = (_layerSize.width - 1) * w / 2;
+            _tileToNodeTransform = Mat4
+            (
+                w/2, -w/2, 0.0f, offX,
+                -h/2, -h/2, 0.0f, offY,
+                0.0f, 0.0f, 1.0f, 0.0f,
+                0.0f, 0.0f, 0.0f, 1.0f
+            );
+            return _tileToNodeTransform;
+        }
+        case FAST_TMX_ORIENTATION_HEX:
+        {
+            _tileToNodeTransform = Mat4
+            (
+                h * sqrtf(0.75),    0,   0, 0,
+                -h/2,      -h,      0,   offY,
+                0,               0,     1,  0,
+                0,               0,     0,  1
+            );
+            return _tileToNodeTransform;
+        }
+        default:
+        {
+            _tileToNodeTransform = Mat4::IDENTITY;
+            return _tileToNodeTransform;
+        }
+    }
+    
+}
+
+void TMXLayer::updatePrimitives()
+{
+    for(const auto& iter : _indicesVertexZNumber)
+    {
+        int start = _indicesVertexZOffsets.at(iter.first);
+        
+        auto primitiveIter= _primitives.find(iter.first);
+        if(primitiveIter == _primitives.end())
+        {
+            auto primitive = Primitive::create(_vData, _indexBuffer, GL_TRIANGLES);
+            primitive->setCount(iter.second * 6);
+            primitive->setStart(start * 6);
+            
+            _primitives.insert(iter.first, primitive);
+        }
+        else
+        {
+            primitiveIter->second->setCount(iter.second * 6);
+            primitiveIter->second->setStart(start * 6);
+        }
+    }
+}
+
+void TMXLayer::updateTotalQuads()
+{
+    if(_quadsDirty)
+    {
+        Size tileSize = CC_SIZE_PIXELS_TO_POINTS(_tileSet->_tileSize);
+        Size texSize = _tileSet->_imageSize;
+        _tileToQuadIndex.clear();
+        _totalQuads.resize(int(_layerSize.width * _layerSize.height));
+        _indices.resize(6 * int(_layerSize.width * _layerSize.height));
+        _tileToQuadIndex.resize(int(_layerSize.width * _layerSize.height),-1);
+        _indicesVertexZOffsets.clear();
+        
+        int quadIndex = 0;
+        for(int y = 0; y < _layerSize.height; ++y)
+        {
+            for(int x =0; x < _layerSize.width; ++x)
+            {
+                int tileIndex = getTileIndexByPos(x, y);
+                int tileGID = _tiles[tileIndex];
+                
+                if(tileGID == 0) continue;
+                
+                _tileToQuadIndex[tileIndex] = quadIndex;
+                
+                auto& quad = _totalQuads[quadIndex];
+                
+                Vec3 nodePos(float(x), float(y), 0);
+                _tileToNodeTransform.transformPoint(&nodePos);
+                
+                float left, right, top, bottom, z;
+                
+                z = getVertexZForPos(Vec2(x, y));
+                auto iter = _indicesVertexZOffsets.find(z);
+                if(iter == _indicesVertexZOffsets.end())
+                {
+                    _indicesVertexZOffsets[z] = 1;
+                }
+                else
+                {
+                    iter->second++;
+                }
+                // vertices
+                if (tileGID & kTMXTileDiagonalFlag)
+                {
+                    left = nodePos.x;
+                    right = nodePos.x + tileSize.height;
+                    bottom = nodePos.y + tileSize.width;
+                    top = nodePos.y;
+                }
+                else
+                {
+                    left = nodePos.x;
+                    right = nodePos.x + tileSize.width;
+                    bottom = nodePos.y + tileSize.height;
+                    top = nodePos.y;
+                }
+                
+                if(tileGID & kTMXTileVerticalFlag)
+                    std::swap(top, bottom);
+                if(tileGID & kTMXTileHorizontalFlag)
+                    std::swap(left, right);
+                
+                if(tileGID & kTMXTileDiagonalFlag)
+                {
+                    // FIXME: not working correctly
+                    quad.bl.vertices.x = left;
+                    quad.bl.vertices.y = bottom;
+                    quad.bl.vertices.z = z;
+                    quad.br.vertices.x = left;
+                    quad.br.vertices.y = top;
+                    quad.br.vertices.z = z;
+                    quad.tl.vertices.x = right;
+                    quad.tl.vertices.y = bottom;
+                    quad.tl.vertices.z = z;
+                    quad.tr.vertices.x = right;
+                    quad.tr.vertices.y = top;
+                    quad.tr.vertices.z = z;
+                }
+                else
+                {
+                    quad.bl.vertices.x = left;
+                    quad.bl.vertices.y = bottom;
+                    quad.bl.vertices.z = z;
+                    quad.br.vertices.x = right;
+                    quad.br.vertices.y = bottom;
+                    quad.br.vertices.z = z;
+                    quad.tl.vertices.x = left;
+                    quad.tl.vertices.y = top;
+                    quad.tl.vertices.z = z;
+                    quad.tr.vertices.x = right;
+                    quad.tr.vertices.y = top;
+                    quad.tr.vertices.z = z;
+                }
+                
+                // texcoords
+                Rect tileTexture = _tileSet->getRectForGID(tileGID);
+                left   = (tileTexture.origin.x / texSize.width);
+                right  = left + (tileTexture.size.width / texSize.width);
+                bottom = (tileTexture.origin.y / texSize.height);
+                top    = bottom + (tileTexture.size.height / texSize.height);
+                
+                quad.bl.texCoords.u = left;
+                quad.bl.texCoords.v = bottom;
+                quad.br.texCoords.u = right;
+                quad.br.texCoords.v = bottom;
+                quad.tl.texCoords.u = left;
+                quad.tl.texCoords.v = top;
+                quad.tr.texCoords.u = right;
+                quad.tr.texCoords.v = top;
+                
+                quad.bl.colors = Color4B::WHITE;
+                quad.br.colors = Color4B::WHITE;
+                quad.tl.colors = Color4B::WHITE;
+                quad.tr.colors = Color4B::WHITE;
+                
+                ++quadIndex;
+            }
+        }
+        
+        int offset = 0;
+        for(auto& vertexZOffset : _indicesVertexZOffsets)
+        {
+            std::swap(offset, vertexZOffset.second);
+            offset += vertexZOffset.second;
+        }
+        updateVertexBuffer();
+        
+        _quadsDirty = false;
+    }
+}
+
+// removing / getting tiles
+Sprite* TMXLayer::getTileAt(const Vec2& tileCoordinate)
+{
+    CCASSERT( tileCoordinate.x < _layerSize.width && tileCoordinate.y < _layerSize.height && tileCoordinate.x >=0 && tileCoordinate.y >=0, "TMXLayer: invalid position");
+    CCASSERT( _tiles, "TMXLayer: the tiles map has been released");
+    
+    Sprite *tile = nullptr;
+    int gid = this->getTileGIDAt(tileCoordinate);
+    
+    // if GID == 0, then no tile is present
+    if( gid ) {
+        int index = (int) tileCoordinate.x + (int) tileCoordinate.y * _layerSize.width;
+        
+        auto it = _spriteContainer.find(index);
+        if (it != _spriteContainer.end())
+        {
+            tile = it->second.first;
+        }
+        else
+        {
+            // tile not created yet. create it
+            Rect rect = _tileSet->getRectForGID(gid);
+            rect = CC_RECT_PIXELS_TO_POINTS(rect);
+            tile = Sprite::createWithTexture(_texture, rect);
+            
+            Vec2 p = this->getPositionAt(tileCoordinate);
+            tile->setAnchorPoint(Vec2::ZERO);
+            tile->setPosition(p);
+            tile->setPositionZ((float)getVertexZForPos(tileCoordinate));
+            tile->setOpacity(this->getOpacity());
+            tile->setTag(index);
+            this->addChild(tile, index);
+            _spriteContainer.insert(std::pair<int, std::pair<Sprite*, int> >(index, std::pair<Sprite*, int>(tile, gid)));
+            
+            // tile is converted to sprite.
+            setFlaggedTileGIDByIndex(index, 0);
+        }
+    }
+    return tile;
+}
+
+int TMXLayer::getTileGIDAt(const Vec2& tileCoordinate, TMXTileFlags* flags/* = nullptr*/)
+{
+    CCASSERT(tileCoordinate.x < _layerSize.width && tileCoordinate.y < _layerSize.height && tileCoordinate.x >=0 && tileCoordinate.y >=0, "TMXLayer: invalid position");
+    CCASSERT(_tiles, "TMXLayer: the tiles map has been released");
+    
+    int idx = static_cast<int>(((int) tileCoordinate.x + (int) tileCoordinate.y * _layerSize.width));
+    
+    // Bits on the far end of the 32-bit global tile ID are used for tile flags
+    int tile = _tiles[idx];
+    auto it = _spriteContainer.find(idx);
+    
+    // converted to sprite.
+    if (tile == 0 && it != _spriteContainer.end())
+    {
+        tile = it->second.second;
+    }
+    
+    // issue1264, flipped tiles can be changed dynamically
+    if (flags)
+    {
+        *flags = (TMXTileFlags)(tile & kTMXFlipedAll);
+    }
+    
+    return (tile & kTMXFlippedMask);
+}
+
+Vec2 TMXLayer::getPositionAt(const Vec2& pos)
+{
+    return PointApplyTransform(pos, _tileToNodeTransform);
+}
+
+int TMXLayer::getVertexZForPos(const Vec2& pos)
+{
+    int ret = 0;
+    int maxVal = 0;
+    if (_useAutomaticVertexZ)
+    {
+        switch (_layerOrientation)
+        {
+            case FAST_TMX_ORIENTATION_ISO:
+                maxVal = static_cast<int>(_layerSize.width + _layerSize.height);
+                ret = static_cast<int>(-(maxVal - (pos.x + pos.y)));
+                break;
+            case FAST_TMX_ORIENTATION_ORTHO:
+                ret = static_cast<int>(-(_layerSize.height-pos.y));
+                break;
+            case FAST_TMX_ORIENTATION_HEX:
+                CCASSERT(0, "TMX Hexa vertexZ not supported");
+                break;
+            default:
+                CCASSERT(0, "TMX invalid value");
+                break;
+        }
+    }
+    else
+    {
+        ret = _vertexZvalue;
+    }
+    
+    return ret;
+}
+
+void TMXLayer::removeTileAt(const Vec2& tileCoordinate)
+{
+    
+    CCASSERT( tileCoordinate.x < _layerSize.width && tileCoordinate.y < _layerSize.height && tileCoordinate.x >=0 && tileCoordinate.y >=0, "TMXLayer: invalid position");
+    
+    int gid = this->getTileGIDAt(tileCoordinate);
+    
+    if( gid ) {
+        
+        int z = (int) tileCoordinate.x + (int) tileCoordinate.y * _layerSize.width;
+        
+        // remove tile from GID map
+        setFlaggedTileGIDByIndex(z, 0);
+        
+        // remove it from sprites
+        auto it = _spriteContainer.find(z);
+        if (it != _spriteContainer.end())
+        {
+            this->removeChild(it->second.first);
+        }
+    }
+}
+
+void TMXLayer::setFlaggedTileGIDByIndex(int index, uint32_t gid)
+{
+    if(gid == _tiles[index]) return;
+    _tiles[index] = gid;
+    _quadsDirty = true;
+    _dirty = true;
+}
+
+void TMXLayer::removeChild(Node* node, bool cleanup)
+{
+    int tag = node->getTag();
+    auto it = _spriteContainer.find(tag);
+    if (it != _spriteContainer.end() && it->second.first == node)
+    {
+        _spriteContainer.erase(it);
+    }
+    Node::removeChild(node, cleanup);
+}
+
+// TMXLayer - Properties
+Value TMXLayer::getProperty(const std::string& propertyName) const
+{
+    if (_properties.find(propertyName) != _properties.end())
+        return _properties.at(propertyName);
+    
+    return Value();
+}
+
+void TMXLayer::parseInternalProperties()
+{
+    auto vertexz = getProperty("cc_vertexz");
+    if (vertexz.isNull()) return;
+    
+    std::string vertexZStr = vertexz.asString();
+    // If "automatic" is on, then parse the "cc_alpha_func" too
+    if (vertexZStr == "automatic")
+    {
+        _useAutomaticVertexZ = true;
+        auto alphaFuncVal = getProperty("cc_alpha_func");
+        float alphaFuncValue = alphaFuncVal.asFloat();
+        setGLProgram(GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_ALPHA_TEST));
+        
+        GLint alphaValueLocation = glGetUniformLocation(getGLProgram()->getProgram(), GLProgram::UNIFORM_NAME_ALPHA_TEST_VALUE);
+        
+        // NOTE: alpha test shader is hard-coded to use the equivalent of a glAlphaFunc(GL_GREATER) comparison
+        
+        // use shader program to set uniform
+        getGLProgram()->use();
+        getGLProgram()->setUniformLocationWith1f(alphaValueLocation, alphaFuncValue);
+        CHECK_GL_ERROR_DEBUG();
+    }
+    else
+    {
+        _vertexZvalue = vertexz.asInt();
+    }
+}
+
+//CCTMXLayer2 - obtaining positions, offset
+Vec2 TMXLayer::calculateLayerOffset(const Vec2& pos)
+{
+    Vec2 ret;
+    switch (_layerOrientation) 
+    {
+    case FAST_TMX_ORIENTATION_ORTHO:
+        ret.set( pos.x * _mapTileSize.width, -pos.y *_mapTileSize.height);
+        break;
+    case FAST_TMX_ORIENTATION_ISO:
+        ret.set((_mapTileSize.width /2) * (pos.x - pos.y),
+                  (_mapTileSize.height /2 ) * (-pos.x - pos.y));
+        break;
+    case FAST_TMX_ORIENTATION_HEX:
+    default:
+        CCASSERT(pos.isZero(), "offset for this map not implemented yet");
+        break;
+    }
+    return ret;    
+}
+
+// TMXLayer - adding / remove tiles
+void TMXLayer::setTileGID(int gid, const Vec2& tileCoordinate)
+{
+    setTileGID(gid, tileCoordinate, (TMXTileFlags)0);
+}
+
+void TMXLayer::setTileGID(int gid, const Vec2& tileCoordinate, TMXTileFlags flags)
+{
+    CCASSERT(tileCoordinate.x < _layerSize.width && tileCoordinate.y < _layerSize.height && tileCoordinate.x >=0 && tileCoordinate.y >=0, "TMXLayer: invalid position");
+    CCASSERT(_tiles, "TMXLayer: the tiles map has been released");
+    CCASSERT(gid == 0 || gid >= _tileSet->_firstGid, "TMXLayer: invalid gid" );
+    
+    TMXTileFlags currentFlags;
+    int currentGID = getTileGIDAt(tileCoordinate, &currentFlags);
+    
+    if (currentGID == gid && currentFlags == flags) return;
+    
+    uint32_t gidAndFlags = gid | flags;
+    
+    // setting gid=0 is equal to remove the tile
+    if (gid == 0)
+    {
+        removeTileAt(tileCoordinate);
+    }
+    // empty tile. create a new one
+    else if (currentGID == 0)
+    {
+        int z = (int) tileCoordinate.x + (int) tileCoordinate.y * _layerSize.width;
+        setFlaggedTileGIDByIndex(z, gidAndFlags);
+    }
+    // modifying an existing tile with a non-empty tile
+    else
+    {
+        int z = (int) tileCoordinate.x + (int) tileCoordinate.y * _layerSize.width;
+        auto it = _spriteContainer.find(z);
+        if (it != _spriteContainer.end())
+        {
+            Sprite *sprite = it->second.first;
+            Rect rect = _tileSet->getRectForGID(gid);
+            rect = CC_RECT_PIXELS_TO_POINTS(rect);
+            
+            sprite->setTextureRect(rect, false, rect.size);
+            this->reorderChild(sprite, z);
+            if (flags)
+            {
+                setupTileSprite(sprite, sprite->getPosition(), gidAndFlags);
+            }
+            
+            it->second.second = gidAndFlags;
+        }
+        else
+        {
+            setFlaggedTileGIDByIndex(z, gidAndFlags);
+        }
+    }
+}
+
+void TMXLayer::setupTileSprite(Sprite* sprite, const Vec2& pos, uint32_t gid)
+{
+    sprite->setPosition(getPositionAt(pos));
+    sprite->setPositionZ((float)getVertexZForPos(pos));
+    sprite->setAnchorPoint(Vec2::ZERO);
+    sprite->setOpacity(this->getOpacity());
+    
+    //issue 1264, flip can be undone as well
+    sprite->setFlippedX(false);
+    sprite->setFlippedY(false);
+    sprite->setRotation(0.0f);
+    
+    // Rotation in tiled is achieved using 3 flipped states, flipping across the horizontal, vertical, and diagonal axes of the tiles.
+    if (gid & kTMXTileDiagonalFlag)
+    {
+        // put the anchor in the middle for ease of rotation.
+        sprite->setAnchorPoint(Vec2(0.5f,0.5f));
+        sprite->setPosition(getPositionAt(pos).x + sprite->getContentSize().height/2,
+                                  getPositionAt(pos).y + sprite->getContentSize().width/2 );
+        
+        uint32_t flag = gid & (kTMXTileHorizontalFlag | kTMXTileVerticalFlag );
+        
+        // handle the 4 diagonally flipped states.
+        if (flag == kTMXTileHorizontalFlag)
+        {
+            sprite->setRotation(90.0f);
+        }
+        else if (flag == kTMXTileVerticalFlag)
+        {
+            sprite->setRotation(270.0f);
+        }
+        else if (flag == (kTMXTileVerticalFlag | kTMXTileHorizontalFlag) )
+        {
+            sprite->setRotation(90.0f);
+            sprite->setFlippedX(true);
+        }
+        else
+        {
+            sprite->setRotation(270.0f);
+            sprite->setFlippedX(true);
+        }
+    }
+    else
+    {
+        if (gid & kTMXTileHorizontalFlag)
+        {
+            sprite->setFlippedX(true);
+        }
+        
+        if (gid & kTMXTileVerticalFlag)
+        {
+            sprite->setFlippedY(true);
+        }
+    }
+}
+
+std::string TMXLayer::getDescription() const
+{
+    return StringUtils::format("<FastTMXLayer | tag = %d, size = %d,%d>", _tag, (int)_mapTileSize.width, (int)_mapTileSize.height);
+}
+
+} //end of namespace experimental
+
+NS_CC_END

+ 367 - 0
cocos2d/cocos/2d/CCFastTMXLayer.h

@@ -0,0 +1,367 @@
+/****************************************************************************
+Copyright (c) 2008-2010 Ricardo Quesada
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+#ifndef __CC_FAST_TMX_LAYER_H__
+#define __CC_FAST_TMX_LAYER_H__
+
+#include <map>
+#include <unordered_map>
+#include "2d/CCNode.h"
+#include "2d/CCTMXXMLParser.h"
+#include "renderer/CCPrimitiveCommand.h"
+#include "base/CCMap.h"
+
+NS_CC_BEGIN
+
+class TMXMapInfo;
+class TMXLayerInfo;
+class TMXTilesetInfo;
+class Texture2D;
+class Sprite;
+struct _ccCArray;
+
+namespace experimental{
+
+/**
+ * @addtogroup _2d
+ * @{
+ */
+
+/** @brief FastTMXLayer represents the TMX layer.
+
+ * It is a subclass of SpriteBatchNode. By default the tiles are rendered using a TextureAtlas.
+ * If you modify a tile on runtime, then, that tile will become a Sprite, otherwise no Sprite objects are created.
+ * The benefits of using Sprite objects as tiles are:
+ * - tiles (Sprite) can be rotated/scaled/moved with a nice API.
+
+ * If the layer contains a property named "cc_vertexz" with an integer (in can be positive or negative),
+ * then all the tiles belonging to the layer will use that value as their OpenGL vertex Z for depth.
+
+ * On the other hand, if the "cc_vertexz" property has the "automatic" value, then the tiles will use an automatic vertex Z value.
+ * Also before drawing the tiles, GL_ALPHA_TEST will be enabled, and disabled after drawing them. The used alpha func will be:
+
+ * glAlphaFunc( GL_GREATER, value ).
+
+ * "value" by default is 0, but you can change it from Tiled by adding the "cc_alpha_func" property to the layer.
+ * The value 0 should work for most cases, but if you have tiles that are semi-transparent, then you might want to use a different
+ * value, like 0.5.
+ 
+ * For further information, please see the programming guide:
+ * http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:tiled_maps
+ 
+ * @since v3.2
+ * @js NA
+ */
+
+class CC_DLL TMXLayer : public Node
+{
+public:
+    /** Creates a FastTMXLayer with an tileset info, a layer info and a map info.
+     *
+     * @param tilesetInfo An tileset info.
+     * @param layerInfo A layer info.
+     * @param mapInfo A map info.
+     * @return Return an autorelease object.
+     */
+    static TMXLayer * create(TMXTilesetInfo *tilesetInfo, TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo);
+    /**
+     * @js ctor
+     */
+    TMXLayer();
+    /**
+     * @js NA
+     * @lua NA
+     */
+    virtual ~TMXLayer();
+
+    /** Returns the tile gid at a given tile coordinate. It also returns the tile flags.
+     * 
+     * @param tileCoordinate The tile coordinate.
+     * @param flags A TMXTileFlags.
+     * @return The tile gid at a given tile coordinate. It also returns the tile flags.
+     */
+    int getTileGIDAt(const Vec2& tileCoordinate, TMXTileFlags* flags = nullptr);
+
+    /** Sets the tile gid (gid = tile global id) at a given tile coordinate.
+     * The Tile GID can be obtained by using the method "tileGIDAt" or by using the TMX editor -> Tileset Mgr +1.
+     * If a tile is already placed at that position, then it will be removed.
+     * @param gid The gid value.
+     * @param tileCoordinate The tile coordinate.
+     */
+    void setTileGID(int gid, const Vec2& tileCoordinate);
+
+    /** Sets the tile gid (gid = tile global id) at a given tile coordinate.
+     * The Tile GID can be obtained by using the method "tileGIDAt" or by using the TMX editor -> Tileset Mgr +1.
+     * If a tile is already placed at that position, then it will be removed.
+     * Use withFlags if the tile flags need to be changed as well.
+     *
+     * @param gid A integer value,it will be sets the tile gid.
+     * @param tileCoordinate The tile coordinate.
+     * @param flags A TMXTileFlags.
+     */
+    void setTileGID(int gid, const Vec2& tileCoordinate, TMXTileFlags flags);
+
+    /** Removes a tile at given tile coordinate.
+     *
+     * @param tileCoordinate The tile Coordinate.
+     */
+    void removeTileAt(const Vec2& tileCoordinate);
+
+    /** Returns the position in points of a given tile coordinate.
+     *
+     * @param tileCoordinate The tile Coordinate.
+     * @return The position in points of a given tile coordinate.
+     */
+    Vec2 getPositionAt(const Vec2& tileCoordinate);
+
+    /** Return the value for the specific property name.
+     *
+     * @param propertyName The value for the specific property name.
+     * @return The value for the specific property name.
+     */
+    Value getProperty(const std::string& propertyName) const;
+
+    /** Creates the tiles. */
+    void setupTiles();
+    
+    /** Get the tile layer name.
+     *
+     * @return The tile layer name.
+     */
+    const std::string& getLayerName() { return _layerName; }
+    
+    /** Set the tile layer name.
+     *
+     * @param layerName The new layer name.
+     */
+    void setLayerName(const std::string& layerName) { _layerName = layerName; }
+
+    /** Size of the layer in tiles.
+     *
+     * @return Size of the layer in tiles.
+     */
+    const Size& getLayerSize() const { return _layerSize; }
+    
+    /** Set the size of the layer in tiles. 
+     *
+     * @param size The new size of the layer in tiles.
+     */
+    void setLayerSize(const Size& size) { _layerSize = size; }
+    
+    /** Size of the map's tile (could be different from the tile's size).
+     *
+     * @return Size of the map's tile (could be different from the tile's size).
+     */
+    const Size& getMapTileSize() const { return _mapTileSize; }
+    
+    /** Set the size of the map's tile. 
+     *
+     * @param size The new size of the map's tile.
+     */
+    void setMapTileSize(const Size& size) { _mapTileSize = size; }
+    
+    /** Pointer to the map of tiles.
+     * @js NA
+     * @lua NA
+     * @return The pointer to the map of tiles.
+     */
+    const uint32_t* getTiles() const { return _tiles; };
+    
+    /** Set the pointer to the map of tiles.
+     *
+     * @param tiles The pointer to the map of tiles.
+     */
+    void setTiles(uint32_t* tiles) { _tiles = tiles; _quadsDirty = true;};
+    
+    /** Tileset information for the layer.
+     *
+     * @return Tileset information for the layer.
+     */
+    TMXTilesetInfo* getTileSet() const { return _tileSet; }
+    
+    /** Set the tileset information for the layer. 
+     *
+     * @param info The new tileset information for the layer.
+     */
+    void setTileSet(TMXTilesetInfo* info) {
+        CC_SAFE_RETAIN(info);
+        CC_SAFE_RELEASE(_tileSet);
+        _tileSet = info;
+    }
+    
+    /** Layer orientation, which is the same as the map orientation.
+     *
+     * @return Layer orientation, which is the same as the map orientation.
+     */
+    int getLayerOrientation() const { return _layerOrientation; }
+    
+    /** Set Layer orientation, which is the same as the map orientation. 
+     *
+     * @param orientation Layer orientation, which is the same as the map orientation.
+     */
+    void setLayerOrientation(int orientation) { _layerOrientation = orientation; }
+    
+    /** Properties from the layer. They can be added using Tiled. 
+     *
+     * @return Properties from the layer. They can be added using Tiled.
+     */
+    const ValueMap& getProperties() const { return _properties; }
+    
+    /** Properties from the layer. They can be added using Tiled.
+     *
+     * @return Properties from the layer. They can be added using Tiled.
+     */
+    ValueMap& getProperties() { return _properties; }
+    
+    /** Set the properties to the layer.
+     *
+     * @param properties The properties to the layer.
+     */
+    void setProperties(const ValueMap& properties)
+    {
+        _properties = properties;
+    }
+
+    /** Returns the tile (Sprite) at a given a tile coordinate.
+     * The returned Sprite will be already added to the TMXLayer. Don't add it again.
+     * The Sprite can be treated like any other Sprite: rotated, scaled, translated, opacity, color, etc.
+     * You can remove either by calling:
+     * - layer->removeChild(sprite, cleanup);
+     *
+     * @return Returns the tile (Sprite) at a given a tile coordinate.
+     */
+    Sprite* getTileAt(const Vec2& tileCoordinate);
+    
+    /** Set an sprite to the tile,with the tile coordinate and gid.
+     *
+     * @param sprite A Sprite.
+     * @param pos The tile coordinate.
+     * @param gid The tile gid.
+     */
+    void setupTileSprite(Sprite* sprite, const Vec2& pos, uint32_t gid);
+
+    //
+    // Override
+    //
+    virtual std::string getDescription() const override;
+    virtual void draw(Renderer *renderer, const Mat4& transform, uint32_t flags) override;
+    void removeChild(Node* child, bool cleanup = true) override;
+
+protected:
+
+    bool initWithTilesetInfo(TMXTilesetInfo *tilesetInfo, TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo);
+    void updateTiles(const Rect& culledRect);
+    Vec2 calculateLayerOffset(const Vec2& offset);
+
+    /* The layer recognizes some special properties, like cc_vertexz */
+    void parseInternalProperties();
+    
+    Mat4 tileToNodeTransform();
+    Rect tileBoundsForClipTransform(const Mat4 &tileToClip);
+    
+    int getVertexZForPos(const Vec2& pos);
+    
+    //Flip flags is packed into gid
+    void setFlaggedTileGIDByIndex(int index, uint32_t gid);
+    
+    //
+    void updateTotalQuads();
+    
+    void onDraw(Primitive* primitive);
+    int getTileIndexByPos(int x, int y) const { return x + y * (int) _layerSize.width; }
+    
+    void updateVertexBuffer();
+    void updateIndexBuffer();
+    void updatePrimitives();
+protected:
+    
+    //! name of the layer
+    std::string _layerName;
+
+    /** size of the layer in tiles */
+    Size _layerSize;
+    /** size of the map's tile (could be different from the tile's size) */
+    Size _mapTileSize;
+    /** pointer to the map of tiles */
+    uint32_t* _tiles;
+    /** Tileset information for the layer */
+    TMXTilesetInfo* _tileSet;
+    /** Layer orientation, which is the same as the map orientation */
+    int _layerOrientation;
+    /** properties from the layer. They can be added using Tiled */
+    ValueMap _properties;
+
+    Texture2D *_texture;
+    
+    /** container for sprite children. map<index, pair<sprite, gid> > */
+    std::map<int, std::pair<Sprite*, int> > _spriteContainer;
+
+    //GLuint _buffersVBO; //0: vertex, 1: indices
+
+    Size _screenGridSize;
+    Rect _screenGridRect;
+    int _screenTileCount;
+    
+    int _vertexZvalue;
+    bool _useAutomaticVertexZ;
+    
+    /** tile coordinate to node coordinate transform */
+    Mat4 _tileToNodeTransform;
+    /** data for rendering */
+    bool _quadsDirty;
+    std::vector<int> _tileToQuadIndex;
+    std::vector<V3F_C4B_T2F_Quad> _totalQuads;
+#ifdef CC_FAST_TILEMAP_32_BIT_INDICES
+    std::vector<GLuint> _indices;
+#else
+    std::vector<GLushort> _indices;
+#endif
+    std::map<int/*vertexZ*/, int/*offset to _indices by quads*/> _indicesVertexZOffsets;
+    std::unordered_map<int/*vertexZ*/, int/*number to quads*/> _indicesVertexZNumber;
+    std::vector<PrimitiveCommand> _renderCommands;
+    bool _dirty;
+    
+    VertexBuffer* _vertexBuffer;
+    
+    VertexData* _vData;
+    
+    IndexBuffer* _indexBuffer;
+    
+    Map<int , Primitive*> _primitives;
+    
+public:
+    /** Possible orientations of the TMX map */
+    static const int FAST_TMX_ORIENTATION_ORTHO;
+    static const int FAST_TMX_ORIENTATION_HEX;
+    static const int FAST_TMX_ORIENTATION_ISO;
+};
+
+// end of tilemap_parallax_nodes group
+/// @}
+} //end of namespace experimental
+NS_CC_END
+
+#endif //__CCTMX_LAYER2_H__

+ 261 - 0
cocos2d/cocos/2d/CCFastTMXTiledMap.cpp

@@ -0,0 +1,261 @@
+/****************************************************************************
+Copyright (c) 2009-2010 Ricardo Quesada
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCFastTMXTiledMap.h"
+#include "2d/CCFastTMXLayer.h"
+#include "base/ccUTF8.h"
+
+NS_CC_BEGIN
+namespace experimental {
+
+// implementation FastTMXTiledMap
+
+TMXTiledMap * TMXTiledMap::create(const std::string& tmxFile)
+{
+    TMXTiledMap *ret = new (std::nothrow) TMXTiledMap();
+    if (ret->initWithTMXFile(tmxFile))
+    {
+        ret->autorelease();
+        return ret;
+    }
+    CC_SAFE_DELETE(ret);
+    return nullptr;
+}
+
+TMXTiledMap* TMXTiledMap::createWithXML(const std::string& tmxString, const std::string& resourcePath)
+{
+    TMXTiledMap *ret = new (std::nothrow) TMXTiledMap();
+    if (ret->initWithXML(tmxString, resourcePath))
+    {
+        ret->autorelease();
+        return ret;
+    }
+    CC_SAFE_DELETE(ret);
+    return nullptr;
+}
+
+bool TMXTiledMap::initWithTMXFile(const std::string& tmxFile)
+{
+    CCASSERT(tmxFile.size()>0, "FastTMXTiledMap: tmx file should not be empty");
+    
+    setContentSize(Size::ZERO);
+
+    TMXMapInfo *mapInfo = TMXMapInfo::create(tmxFile);
+
+    if (! mapInfo)
+    {
+        return false;
+    }
+    CCASSERT( !mapInfo->getTilesets().empty(), "FastTMXTiledMap: Map not found. Please check the filename.");
+    buildWithMapInfo(mapInfo);
+
+    return true;
+}
+
+bool TMXTiledMap::initWithXML(const std::string& tmxString, const std::string& resourcePath)
+{
+    setContentSize(Size::ZERO);
+
+    TMXMapInfo *mapInfo = TMXMapInfo::createWithXML(tmxString, resourcePath);
+
+    CCASSERT( !mapInfo->getTilesets().empty(), "FastTMXTiledMap: Map not found. Please check the filename.");
+    buildWithMapInfo(mapInfo);
+
+    return true;
+}
+
+TMXTiledMap::TMXTiledMap()
+    :_mapSize(Size::ZERO)
+    ,_tileSize(Size::ZERO)        
+{
+}
+
+TMXTiledMap::~TMXTiledMap()
+{
+}
+
+// private
+TMXLayer * TMXTiledMap::parseLayer(TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo)
+{
+    TMXTilesetInfo *tileset = tilesetForLayer(layerInfo, mapInfo);
+    if (tileset == nullptr)
+        return nullptr;
+    
+    TMXLayer *layer = TMXLayer::create(tileset, layerInfo, mapInfo);
+
+    // tell the layerinfo to release the ownership of the tiles map.
+    layerInfo->_ownTiles = false;
+    layer->setupTiles();
+
+    return layer;
+}
+
+TMXTilesetInfo * TMXTiledMap::tilesetForLayer(TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo)
+{
+    Size size = layerInfo->_layerSize;
+    auto& tilesets = mapInfo->getTilesets();
+
+    for (auto iter = tilesets.crbegin(), iterCrend = tilesets.crend(); iter != iterCrend; ++iter)
+    {
+        TMXTilesetInfo* tilesetInfo = *iter;
+        if (tilesetInfo)
+        {
+            for( int y=0; y < size.height; y++ )
+            {
+                for( int x=0; x < size.width; x++ )
+                {
+                    uint32_t pos = static_cast<uint32_t>(x + size.width * y);
+                    uint32_t gid = layerInfo->_tiles[ pos ];
+                    
+                    // gid are stored in little endian.
+                    // if host is big endian, then swap
+                    //if( o == CFByteOrderBigEndian )
+                    //    gid = CFSwapInt32( gid );
+                    /* We support little endian.*/
+                    
+                    // FIXME: gid == 0 --> empty tile
+                    if( gid != 0 )
+                    {
+                        // Optimization: quick return
+                        // if the layer is invalid (more than 1 tileset per layer) an CCAssert will be thrown later
+                        if( (gid & kTMXFlippedMask)
+                            >= static_cast<uint32_t>(tilesetInfo->_firstGid))
+                        {
+                            return tilesetInfo;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    // If all the tiles are 0, return empty tileset
+    CCLOG("cocos2d: Warning: TMX Layer '%s' has no tiles", layerInfo->_name.c_str());
+    return nullptr;
+}
+
+void TMXTiledMap::buildWithMapInfo(TMXMapInfo* mapInfo)
+{
+    _mapSize = mapInfo->getMapSize();
+    _tileSize = mapInfo->getTileSize();
+    _mapOrientation = mapInfo->getOrientation();
+
+    _objectGroups = mapInfo->getObjectGroups();
+
+    _properties = mapInfo->getProperties();
+
+    _tileProperties = mapInfo->getTileProperties();
+
+    int idx=0;
+
+    auto& layers = mapInfo->getLayers();
+    for(const auto &layerInfo : layers) {
+        if (layerInfo->_visible)
+        {
+            TMXLayer *child = parseLayer(layerInfo, mapInfo);
+            if (child == nullptr) {
+                idx++;
+                continue;
+            }
+            addChild(child, idx, idx);
+            
+            // update content size with the max size
+            const Size& childSize = child->getContentSize();
+            Size currentSize = this->getContentSize();
+            currentSize.width = std::max( currentSize.width, childSize.width );
+            currentSize.height = std::max( currentSize.height, childSize.height );
+            this->setContentSize(currentSize);
+            
+            idx++;
+        }
+    }
+}
+
+// public
+TMXLayer * TMXTiledMap::getLayer(const std::string& layerName) const
+{
+    CCASSERT(layerName.size() > 0, "Invalid layer name!");
+    
+    for (auto& child : _children)
+    {
+        TMXLayer* layer = dynamic_cast<TMXLayer*>(child);
+        if(layer)
+        {
+            if(layerName.compare( layer->getLayerName()) == 0)
+            {
+                return layer;
+            }
+        }
+    }
+
+    // layer not found
+    return nullptr;
+}
+
+TMXObjectGroup * TMXTiledMap::getObjectGroup(const std::string& groupName) const
+{
+    CCASSERT(groupName.size() > 0, "Invalid group name!");
+
+    if (_objectGroups.size()>0)
+    {
+        for (const auto& objectGroup : _objectGroups)
+        {
+            if (objectGroup && objectGroup->getGroupName() == groupName)
+            {
+                return objectGroup;
+            }
+        }
+    }
+
+    // objectGroup not found
+    return nullptr;
+}
+
+Value TMXTiledMap::getProperty(const std::string& propertyName) const
+{
+    if (_properties.find(propertyName) != _properties.end())
+        return _properties.at(propertyName);
+    
+    return Value();
+}
+
+Value TMXTiledMap::getPropertiesForGID(int GID) const
+{
+    if (_tileProperties.find(GID) != _tileProperties.end())
+        return _tileProperties.at(GID);
+    
+    return Value();
+}
+
+std::string TMXTiledMap::getDescription() const
+{
+    return StringUtils::format("<FastTMXTiledMap | Tag = %d, Layers = %d", _tag, static_cast<int>(_children.size()));
+}
+
+} //end of namespace experimental
+
+NS_CC_END
+

+ 256 - 0
cocos2d/cocos/2d/CCFastTMXTiledMap.h

@@ -0,0 +1,256 @@
+/****************************************************************************
+Copyright (c) 2009-2010 Ricardo Quesada
+Copyright (c) 2010-2012 cocos2d-x.org
+Copyright (c) 2011      Zynga Inc.
+Copyright (c) 2013-2017 Chukong Technologies 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.
+****************************************************************************/
+#ifndef __CC_FAST_TMX_TILEMAP_H__
+#define __CC_FAST_TMX_TILEMAP_H__
+
+#include "2d/CCNode.h"
+#include "2d/CCTMXObjectGroup.h"
+
+NS_CC_BEGIN
+
+class TMXLayerInfo;
+class TMXTilesetInfo;
+class TMXMapInfo;
+
+namespace experimental {
+    
+class TMXLayer;
+/**
+ * @addtogroup _2d
+ * @{
+ */
+    
+/** @brief FastTMXTiledMap knows how to parse and render a TMX map.
+
+ * It adds support for the TMX tiled map format used by http://www.mapeditor.org.
+ * It supports isometric, hexagonal and orthogonal tiles.
+ * It also supports object groups, objects, and properties.
+
+ * Features:
+ * - Each tile will be treated as an Sprite.
+ * - The sprites are created on demand. They will be created only when you call "layer->tileAt(position)".
+ * - Each tile can be rotated / moved / scaled / tinted / "opaqued", since each tile is a Sprite.
+ * - Tiles can be added/removed in runtime.
+ * - The z-order of the tiles can be modified in runtime.
+ * - Each tile has an anchorPoint of (0,0).
+ * - The anchorPoint of the TMXTileMap is (0,0).
+ * - The TMX layers will be added as a child.
+ * - The TMX layers will be aliased by default.
+ * - The tileset image will be loaded using the TextureCache.
+ * - Each tile will have a unique tag.
+ * - Each tile will have a unique z value. top-left: z=1, bottom-right: z=max z.
+ * - Each object group will be treated as an MutableArray.
+ * - Object class which will contain all the properties in a dictionary.
+ * - Properties can be assigned to the Map, Layer, Object Group, and Object.
+
+ * Limitations:
+ * - It only supports one tileset per layer.
+ * - Embedded images are not supported.
+ * - It only supports the XML format (the JSON format is not supported).
+
+ * Technical description:
+ * Each layer is created using an FastTMXLayer (subclass of SpriteBatchNode). If you have 5 layers, then 5 FastTMXLayer will be created,
+ * unless the layer visibility is off. In that case, the layer won't be created at all.
+ * You can obtain the layers (FastTMXLayer objects) at runtime by:
+ * - map->getChildByTag(tag_number);  // 0=1st layer, 1=2nd layer, 2=3rd layer, etc...
+ * - map->getLayer(name_of_the_layer);
+
+ * Each object group is created using a TMXObjectGroup which is a subclass of MutableArray.
+ * You can obtain the object groups at runtime by:
+ * - map->getObjectGroup(name_of_the_object_group);
+
+ * Each object is a TMXObject.
+
+ * Each property is stored as a key-value pair in an MutableDictionary.
+ * You can obtain the properties at runtime by:
+
+ * map->getProperty(name_of_the_property);
+ * layer->getProperty(name_of_the_property);
+ * objectGroup->getProperty(name_of_the_property);
+ * object->getProperty(name_of_the_property);
+
+ * @since v3.2
+ * @js NA
+ */
+class CC_DLL TMXTiledMap : public Node
+{
+public:
+    /** Creates a TMX Tiled Map with a TMX file.
+     *
+     * @return An autorelease object.
+     */
+    static TMXTiledMap* create(const std::string& tmxFile);
+
+    /** Initializes a TMX Tiled Map with a TMX formatted XML string and a path to TMX resources. 
+     *
+     * @param tmxString A TMX formatted XML string.
+     * @param resourcePath A path to TMX resources.
+     * @return An autorelease object.
+     */
+    static TMXTiledMap* createWithXML(const std::string& tmxString, const std::string& resourcePath);
+
+    /** Return the FastTMXLayer for the specific layer. 
+     * 
+     * @return Return the FastTMXLayer for the specific layer.
+     */
+    TMXLayer* getLayer(const std::string& layerName) const;
+
+    /** Return the TMXObjectGroup for the specific group. 
+     * 
+     * @return Return the TMXObjectGroup for the specific group.
+     */
+    TMXObjectGroup* getObjectGroup(const std::string& groupName) const;
+
+    /** Return the value for the specific property name.
+     *
+     * @return Return the value for the specific property name.
+     */
+    Value getProperty(const std::string& propertyName) const;
+
+    /** Return properties dictionary for tile GID.
+     *
+     * @return Return properties dictionary for tile GID.
+     */
+    Value getPropertiesForGID(int GID) const;
+
+    /** The map's size property measured in tiles. 
+     *
+     * @return The map's size property measured in tiles.
+     */
+    const Size& getMapSize() const { return _mapSize; }
+    
+    /** Set the map's size property measured in tiles.
+     *
+     * @param mapSize The map's size property measured in tiles.
+     */
+    void setMapSize(const Size& mapSize) { _mapSize = mapSize; }
+
+    /** The tiles's size property measured in pixels.
+     *
+     * @return The tiles's size property measured in pixels.
+     */
+    const Size& getTileSize() const { return _tileSize; }
+    
+    /** Set the tiles's size property measured in pixels. 
+     *
+     * @param tileSize The tiles's size property measured in pixels.
+     */
+    void setTileSize(const Size& tileSize) { _tileSize = tileSize; }
+
+    /** Get map orientation. 
+     *
+     * @return The map orientation.
+     */
+    int getMapOrientation() const { return _mapOrientation; }
+    
+    /** Set map orientation. 
+     *
+     * @param mapOrientation The map orientation.
+     */
+    void setMapOrientation(int mapOrientation) { _mapOrientation = mapOrientation; }
+
+    /** Get object groups. 
+     *
+     * @return Object groups.
+     */
+    const Vector<TMXObjectGroup*>& getObjectGroups() const { return _objectGroups; }
+    Vector<TMXObjectGroup*>& getObjectGroups() { return _objectGroups; }
+    
+    /** Set object groups. 
+     *
+     * @param groups An object groups.
+     */
+    void setObjectGroups(const Vector<TMXObjectGroup*>& groups) {
+        _objectGroups = groups;
+    }
+    
+    /** Get properties.
+     *
+     * @return Properties.
+     */
+    const ValueMap& getProperties() const { return _properties; }
+    
+    /** Set properties. 
+     *
+     * @param properties An ValueMap Properties.
+     */
+    void setProperties(const ValueMap& properties) {
+        _properties = properties;
+    }
+
+    virtual std::string getDescription() const override;
+
+protected:
+    /**
+     * @js ctor
+     */
+    TMXTiledMap();
+    /**
+     * @js NA
+     * @lua NA
+     */
+    virtual ~TMXTiledMap();
+
+    /** initializes a TMX Tiled Map with a TMX file */
+    bool initWithTMXFile(const std::string& tmxFile);
+
+    /** initializes a TMX Tiled Map with a TMX formatted XML string and a path to TMX resources */
+    bool initWithXML(const std::string& tmxString, const std::string& resourcePath);
+    
+    TMXLayer * parseLayer(TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo);
+    TMXTilesetInfo * tilesetForLayer(TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo);
+    void buildWithMapInfo(TMXMapInfo* mapInfo);
+
+    /** the map's size property measured in tiles */
+    Size _mapSize;
+    /** the tiles's size property measured in pixels */
+    Size _tileSize;
+    /** map orientation */
+    int _mapOrientation;
+    /** object groups */
+    Vector<TMXObjectGroup*> _objectGroups;
+    /** properties */
+    ValueMap _properties;
+    
+    //! tile properties
+    ValueMapIntKey _tileProperties;
+
+private:
+    CC_DISALLOW_COPY_AND_ASSIGN(TMXTiledMap);
+
+};
+
+// end of tilemap_parallax_nodes group
+/** @} */
+    
+} //end of namespace experimental
+
+NS_CC_END
+
+#endif //__CCTMX_TILE_MAP2_H__
+
+

+ 0 - 0
cocos2d/cocos/2d/CCFont.cpp


+ 59 - 0
cocos2d/cocos/2d/CCFont.h

@@ -0,0 +1,59 @@
+/****************************************************************************
+ Copyright (c) 2013      Zynga Inc.
+ Copyright (c) 2013-2017 Chukong Technologies 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.
+ ****************************************************************************/
+
+#ifndef _CCFont_h_
+#define _CCFont_h_
+
+/// @cond DO_NOT_SHOW
+
+#include <string>
+#include "base/ccTypes.h"
+#include "base/ccUTF8.h"
+
+NS_CC_BEGIN
+
+class FontAtlas;
+
+class CC_DLL Font : public Ref
+{
+public:
+    virtual FontAtlas* createFontAtlas() = 0;
+
+    virtual int* getHorizontalKerningForTextUTF32(const std::u32string& text, int &outNumLetters) const = 0;
+    
+    CC_DEPRECATED_ATTRIBUTE inline int* getHorizontalKerningForTextUTF16(const std::u16string& text, int &outNumLetters) const
+    {
+        std::u32string utf32;
+        StringUtils::UTF16ToUTF32(text, utf32);
+        return getHorizontalKerningForTextUTF32(utf32, outNumLetters);
+    }
+    
+    virtual int getFontMaxHeight() const { return 0; }
+};
+
+NS_CC_END
+
+/// @endcond
+#endif

+ 490 - 0
cocos2d/cocos/2d/CCFontAtlas.cpp

@@ -0,0 +1,490 @@
+/****************************************************************************
+ Copyright (c) 2013      Zynga Inc.
+ Copyright (c) 2013-2017 Chukong Technologies 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 "2d/CCFontAtlas.h"
+#if CC_TARGET_PLATFORM != CC_PLATFORM_WIN32 && CC_TARGET_PLATFORM != CC_PLATFORM_WINRT && CC_TARGET_PLATFORM != CC_PLATFORM_ANDROID
+#include <iconv.h>
+#elif CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
+#include "platform/android/jni/Java_org_cocos2dx_lib_Cocos2dxHelper.h"
+#endif
+#include "2d/CCFontFreeType.h"
+#include "base/ccUTF8.h"
+#include "base/CCDirector.h"
+#include "base/CCEventListenerCustom.h"
+#include "base/CCEventDispatcher.h"
+#include "base/CCEventType.h"
+
+NS_CC_BEGIN
+
+const int FontAtlas::CacheTextureWidth = 512;
+const int FontAtlas::CacheTextureHeight = 512;
+const char* FontAtlas::CMD_PURGE_FONTATLAS = "__cc_PURGE_FONTATLAS";
+const char* FontAtlas::CMD_RESET_FONTATLAS = "__cc_RESET_FONTATLAS";
+
+FontAtlas::FontAtlas(Font &theFont) 
+: _font(&theFont)
+, _fontFreeType(nullptr)
+, _iconv(nullptr)
+, _currentPageData(nullptr)
+, _fontAscender(0)
+, _rendererRecreatedListener(nullptr)
+, _antialiasEnabled(true)
+, _currLineHeight(0)
+{
+    _font->retain();
+
+    _fontFreeType = dynamic_cast<FontFreeType*>(_font);
+    if (_fontFreeType)
+    {
+        _lineHeight = _font->getFontMaxHeight();
+        _fontAscender = _fontFreeType->getFontAscender();
+        auto texture = new (std::nothrow) Texture2D;
+        _currentPage = 0;
+        _currentPageOrigX = 0;
+        _currentPageOrigY = 0;
+        _letterEdgeExtend = 2;
+        _letterPadding = 0;
+
+        if (_fontFreeType->isDistanceFieldEnabled())
+        {
+            _letterPadding += 2 * FontFreeType::DistanceMapSpread;    
+        }
+        _currentPageDataSize = CacheTextureWidth * CacheTextureHeight;
+        auto outlineSize = _fontFreeType->getOutlineSize();
+        if(outlineSize > 0)
+        {
+            _lineHeight += 2 * outlineSize;
+            _currentPageDataSize *= 2;
+        }
+
+        _currentPageData = new (std::nothrow) unsigned char[_currentPageDataSize];
+        memset(_currentPageData, 0, _currentPageDataSize);
+
+        auto  pixelFormat = outlineSize > 0 ? Texture2D::PixelFormat::AI88 : Texture2D::PixelFormat::A8; 
+        texture->initWithData(_currentPageData, _currentPageDataSize, 
+            pixelFormat, CacheTextureWidth, CacheTextureHeight, Size(CacheTextureWidth,CacheTextureHeight) );
+
+        addTexture(texture,0);
+        texture->release();
+
+#if CC_ENABLE_CACHE_TEXTURE_DATA
+        auto eventDispatcher = Director::getInstance()->getEventDispatcher();
+
+        _rendererRecreatedListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, CC_CALLBACK_1(FontAtlas::listenRendererRecreated, this));
+        eventDispatcher->addEventListenerWithFixedPriority(_rendererRecreatedListener, 1);
+#endif
+    }
+}
+
+FontAtlas::~FontAtlas()
+{
+#if CC_ENABLE_CACHE_TEXTURE_DATA
+    if (_fontFreeType && _rendererRecreatedListener)
+    {
+        auto eventDispatcher = Director::getInstance()->getEventDispatcher();
+        eventDispatcher->removeEventListener(_rendererRecreatedListener);
+        _rendererRecreatedListener = nullptr;
+    }
+#endif
+
+    _font->release();
+    releaseTextures();
+
+    delete []_currentPageData;
+
+#if CC_TARGET_PLATFORM != CC_PLATFORM_WIN32 && CC_TARGET_PLATFORM != CC_PLATFORM_WINRT && CC_TARGET_PLATFORM != CC_PLATFORM_ANDROID
+    if (_iconv)
+    {
+        iconv_close(_iconv);
+        _iconv = nullptr;
+    }
+#endif
+}
+
+void FontAtlas::reset()
+{
+    releaseTextures();
+    
+    _currLineHeight = 0;
+    _currentPage = 0;
+    _currentPageOrigX = 0;
+    _currentPageOrigY = 0;
+    _letterDefinitions.clear();
+}
+
+void FontAtlas::releaseTextures()
+{
+    for( auto &item: _atlasTextures)
+    {
+        item.second->release();
+    }
+    _atlasTextures.clear();
+}
+
+void FontAtlas::purgeTexturesAtlas()
+{
+    if (_fontFreeType)
+    {
+        reset();
+        auto eventDispatcher = Director::getInstance()->getEventDispatcher();
+        eventDispatcher->dispatchCustomEvent(CMD_PURGE_FONTATLAS,this);
+        eventDispatcher->dispatchCustomEvent(CMD_RESET_FONTATLAS,this);
+    }
+}
+
+void FontAtlas::listenRendererRecreated(EventCustom * /*event*/)
+{
+    purgeTexturesAtlas();
+}
+
+void FontAtlas::addLetterDefinition(char32_t utf32Char, const FontLetterDefinition &letterDefinition)
+{
+    _letterDefinitions[utf32Char] = letterDefinition;
+}
+
+void FontAtlas::scaleFontLetterDefinition(float scaleFactor)
+{
+    for (auto&& fontDefinition : _letterDefinitions) {
+        auto& letterDefinition = fontDefinition.second;
+        letterDefinition.width *= scaleFactor;
+        letterDefinition.height *= scaleFactor;
+        letterDefinition.offsetX *= scaleFactor;
+        letterDefinition.offsetY *= scaleFactor;
+        letterDefinition.xAdvance *= scaleFactor;
+    }
+}
+
+bool FontAtlas::getLetterDefinitionForChar(char32_t utf32Char, FontLetterDefinition &letterDefinition)
+{
+    auto outIterator = _letterDefinitions.find(utf32Char);
+
+    if (outIterator != _letterDefinitions.end())
+    {
+        letterDefinition = (*outIterator).second;
+        return letterDefinition.validDefinition;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+void FontAtlas::conversionU32TOGB2312(const std::u32string& u32Text, std::unordered_map<unsigned int, unsigned int>& charCodeMap)
+{
+    size_t strLen = u32Text.length();
+    auto gb2312StrSize = strLen * 2;
+    auto gb2312Text = new (std::nothrow) char[gb2312StrSize];
+    memset(gb2312Text, 0, gb2312StrSize);
+
+    switch (_fontFreeType->getEncoding())
+    {
+    case FT_ENCODING_GB2312:
+    {
+#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT
+        std::u16string u16Text;
+        cocos2d::StringUtils::UTF32ToUTF16(u32Text, u16Text);
+        WideCharToMultiByte(936, NULL, (LPCWCH)u16Text.c_str(), strLen, (LPSTR)gb2312Text, gb2312StrSize, NULL, NULL);
+#elif CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
+        conversionEncodingJNI((char*)u32Text.c_str(), gb2312StrSize, "UTF-32LE", gb2312Text, "GB2312");
+#else
+        if (_iconv == nullptr)
+        {
+            _iconv = iconv_open("GBK//TRANSLIT", "UTF-32LE");
+        }
+
+        if (_iconv == (iconv_t)-1)
+        {
+            CCLOG("conversion from utf32 to gb2312 not available");
+        }
+        else
+        {
+            char* pin = (char*)u32Text.c_str();
+            char* pout = gb2312Text;
+            size_t inLen = strLen * 2;
+            size_t outLen = gb2312StrSize;
+
+            iconv(_iconv, (char**)&pin, &inLen, &pout, &outLen);
+        }
+#endif
+    }
+    break;
+    default:
+        CCLOG("Unsupported encoding:%d", _fontFreeType->getEncoding());
+        break;
+    }
+
+    unsigned short gb2312Code = 0;
+    unsigned char* dst = (unsigned char*)&gb2312Code;
+    char32_t u32Code;
+    for (size_t index = 0, gbIndex = 0; index < strLen; ++index)
+    {
+        u32Code = u32Text[index];
+        if (u32Code < 256)
+        {
+            charCodeMap[u32Code] = u32Code;
+            gbIndex += 1;
+        }
+        else
+        {
+            dst[0] = gb2312Text[gbIndex + 1];
+            dst[1] = gb2312Text[gbIndex];
+            charCodeMap[u32Code] = gb2312Code;
+
+            gbIndex += 2;
+        }
+    }
+
+    delete[] gb2312Text;
+}
+
+void FontAtlas::findNewCharacters(const std::u32string& u32Text, std::unordered_map<unsigned int, unsigned int>& charCodeMap)
+{
+    std::u32string newChars;
+    FT_Encoding charEncoding = _fontFreeType->getEncoding();
+
+    //find new characters
+    if (_letterDefinitions.empty())
+    {
+        // fixed #16169: new android project crash in android 5.0.2 device (Nexus 7) when use 3.12.
+        // While using clang compiler with gnustl_static on android, the copy assignment operator of `std::u32string`
+        // will affect the memory validity, it means after `newChars` is destroyed, the memory of `u32Text` holds
+        // will be a dead region. `u32text` represents the variable in `Label::_utf32Text`, when somewhere
+        // allocates memory by `malloc, realloc, new, new[]`, the generated memory address may be the same
+        // as `Label::_utf32Text` holds. If doing a `memset` or other memory operations, the orignal `Label::_utf32Text`
+        // will be in an unknown state. Meanwhile, a bunch lots of logic which depends on `Label::_utf32Text`
+        // will be broken.
+        
+        // newChars = u32Text;
+        
+        // Using `append` method is a workaround for this issue. So please be carefuly while using the assignment operator
+        // of `std::u32string`.
+        newChars.append(u32Text);
+    }
+    else
+    {
+        auto length = u32Text.length();
+        newChars.reserve(length);
+        for (size_t i = 0; i < length; ++i)
+        {
+            auto outIterator = _letterDefinitions.find(u32Text[i]);
+            if (outIterator == _letterDefinitions.end())
+            {
+                newChars.push_back(u32Text[i]);
+            }
+        }
+    }
+
+    if (!newChars.empty())
+    {
+        switch (charEncoding)
+        {
+        case FT_ENCODING_UNICODE:
+        {
+            for (auto u32Code : newChars)
+            {
+                charCodeMap[u32Code] = u32Code;
+            }
+            break;
+        }
+        case FT_ENCODING_GB2312:
+        {
+            conversionU32TOGB2312(newChars, charCodeMap);
+            break;
+        }
+        default:
+            CCLOG("FontAtlas::findNewCharacters: Unsupported encoding:%d", charEncoding);
+            break;
+        }
+    }
+}
+
+bool FontAtlas::prepareLetterDefinitions(const std::u32string& utf32Text)
+{
+    if (_fontFreeType == nullptr)
+    {
+        return false;
+    } 
+    
+    std::unordered_map<unsigned int, unsigned int> codeMapOfNewChar;
+    findNewCharacters(utf32Text, codeMapOfNewChar);
+    if (codeMapOfNewChar.empty())
+    {
+        return false;
+    }
+
+    int adjustForDistanceMap = _letterPadding / 2;
+    int adjustForExtend = _letterEdgeExtend / 2;
+    long bitmapWidth;
+    long bitmapHeight;
+    int glyphHeight;
+    Rect tempRect;
+    FontLetterDefinition tempDef;
+
+    auto scaleFactor = CC_CONTENT_SCALE_FACTOR();
+    auto  pixelFormat = _fontFreeType->getOutlineSize() > 0 ? Texture2D::PixelFormat::AI88 : Texture2D::PixelFormat::A8;
+
+    float startY = _currentPageOrigY;
+
+    for (auto&& it : codeMapOfNewChar)
+    {
+        auto bitmap = _fontFreeType->getGlyphBitmap(it.second, bitmapWidth, bitmapHeight, tempRect, tempDef.xAdvance);
+        if (bitmap && bitmapWidth > 0 && bitmapHeight > 0)
+        {
+            tempDef.validDefinition = true;
+            tempDef.width = tempRect.size.width + _letterPadding + _letterEdgeExtend;
+            tempDef.height = tempRect.size.height + _letterPadding + _letterEdgeExtend;
+            tempDef.offsetX = tempRect.origin.x - adjustForDistanceMap - adjustForExtend;
+            tempDef.offsetY = _fontAscender + tempRect.origin.y - adjustForDistanceMap - adjustForExtend;
+
+            if (_currentPageOrigX + tempDef.width > CacheTextureWidth)
+            {
+                _currentPageOrigY += _currLineHeight;
+                _currLineHeight = 0;
+                _currentPageOrigX = 0;
+                if (_currentPageOrigY + _lineHeight + _letterPadding + _letterEdgeExtend >= CacheTextureHeight)
+                {
+                    unsigned char *data = nullptr;
+                    if (pixelFormat == Texture2D::PixelFormat::AI88)
+                    {
+                        data = _currentPageData + CacheTextureWidth * (int)startY * 2;
+                    }
+                    else
+                    {
+                        data = _currentPageData + CacheTextureWidth * (int)startY;
+                    }
+                    _atlasTextures[_currentPage]->updateWithData(data, 0, startY,
+                        CacheTextureWidth, CacheTextureHeight - startY);
+
+                    startY = 0.0f;
+
+                    _currentPageOrigY = 0;
+                    memset(_currentPageData, 0, _currentPageDataSize);
+                    _currentPage++;
+                    auto tex = new (std::nothrow) Texture2D;
+                    if (_antialiasEnabled)
+                    {
+                        tex->setAntiAliasTexParameters();
+                    }
+                    else
+                    {
+                        tex->setAliasTexParameters();
+                    }
+                    tex->initWithData(_currentPageData, _currentPageDataSize,
+                        pixelFormat, CacheTextureWidth, CacheTextureHeight, Size(CacheTextureWidth, CacheTextureHeight));
+                    addTexture(tex, _currentPage);
+                    tex->release();
+                }
+            }
+            glyphHeight = static_cast<int>(bitmapHeight) + _letterPadding + _letterEdgeExtend;
+            if (glyphHeight > _currLineHeight)
+            {
+                _currLineHeight = glyphHeight;
+            }
+            _fontFreeType->renderCharAt(_currentPageData, _currentPageOrigX + adjustForExtend, _currentPageOrigY + adjustForExtend, bitmap, bitmapWidth, bitmapHeight);
+
+            tempDef.U = _currentPageOrigX;
+            tempDef.V = _currentPageOrigY;
+            tempDef.textureID = _currentPage;
+            _currentPageOrigX += tempDef.width + 1;
+            // take from pixels to points
+            tempDef.width = tempDef.width / scaleFactor;
+            tempDef.height = tempDef.height / scaleFactor;
+            tempDef.U = tempDef.U / scaleFactor;
+            tempDef.V = tempDef.V / scaleFactor;
+        }
+        else{
+            if (tempDef.xAdvance)
+                tempDef.validDefinition = true;
+            else
+                tempDef.validDefinition = false;
+
+            tempDef.width = 0;
+            tempDef.height = 0;
+            tempDef.U = 0;
+            tempDef.V = 0;
+            tempDef.offsetX = 0;
+            tempDef.offsetY = 0;
+            tempDef.textureID = 0;
+            _currentPageOrigX += 1;
+        }
+
+        _letterDefinitions[it.first] = tempDef;
+    }
+
+    unsigned char *data = nullptr;
+    if (pixelFormat == Texture2D::PixelFormat::AI88)
+    {
+        data = _currentPageData + CacheTextureWidth * (int)startY * 2;
+    }
+    else
+    {
+        data = _currentPageData + CacheTextureWidth * (int)startY;
+    }
+    _atlasTextures[_currentPage]->updateWithData(data, 0, startY, CacheTextureWidth, _currentPageOrigY - startY + _currLineHeight);
+
+    return true;
+}
+
+void FontAtlas::addTexture(Texture2D *texture, int slot)
+{
+    texture->retain();
+    _atlasTextures[slot] = texture;
+}
+
+Texture2D* FontAtlas::getTexture(int slot)
+{
+    return _atlasTextures[slot];
+}
+
+void  FontAtlas::setLineHeight(float newHeight)
+{
+    _lineHeight = newHeight;
+}
+
+void FontAtlas::setAliasTexParameters()
+{
+    if (_antialiasEnabled)
+    {
+        _antialiasEnabled = false;
+        for (const auto & tex : _atlasTextures)
+        {
+            tex.second->setAliasTexParameters();
+        }
+    }
+}
+
+void FontAtlas::setAntiAliasTexParameters()
+{
+    if (! _antialiasEnabled)
+    {
+        _antialiasEnabled = true;
+        for (const auto & tex : _atlasTextures)
+        {
+            tex.second->setAntiAliasTexParameters();
+        }
+    }
+}
+
+NS_CC_END

Some files were not shown because too many files changed in this diff