From 1b05afc7bed0e2ac55f61a6b6bfae65856aeee75 Mon Sep 17 00:00:00 2001 From: chsieh Date: Thu, 23 Dec 2010 11:10:02 -0800 Subject: [PATCH] Interim code. Integrating cocos2d. --- Classes/Foundation/Common/GlobalDefines.h | 4 +- .../GraphicsServices/Geometry/BasicPrimitives.h | 27 + .../GraphicsServices/Geometry/BasicPrimitives.mm | 26 + .../Foundation/GraphicsServices/OpenGLServices.h | 4 +- .../Foundation/GraphicsServices/OpenGLServices.mm | 13 +- Classes/Foundation/Math/MathTypes.h | 162 ++-- Classes/Foundation/Math/Matrix.h | 614 +++++----- Classes/Foundation/Math/Quaternion.h | 22 +- Classes/Foundation/Math/Vector.h | 592 +++++----- Classes/cocos2d/CCAction.h | 188 +++ Classes/cocos2d/CCAction.m | 360 ++++++ Classes/cocos2d/CCActionCamera.h | 72 ++ Classes/cocos2d/CCActionCamera.m | 146 +++ Classes/cocos2d/CCActionEase.h | 159 +++ Classes/cocos2d/CCActionEase.m | 534 +++++++++ Classes/cocos2d/CCActionGrid.h | 165 +++ Classes/cocos2d/CCActionGrid.m | 386 +++++++ Classes/cocos2d/CCActionGrid3D.h | 208 ++++ Classes/cocos2d/CCActionGrid3D.m | 659 +++++++++++ Classes/cocos2d/CCActionInstant.h | 197 ++++ Classes/cocos2d/CCActionInstant.m | 472 ++++++++ Classes/cocos2d/CCActionInterval.h | 384 +++++++ Classes/cocos2d/CCActionInterval.m | 1213 ++++++++++++++++++++ Classes/cocos2d/CCActionManager.h | 118 ++ Classes/cocos2d/CCActionManager.m | 356 ++++++ Classes/cocos2d/CCActionPageTurn3D.h | 42 + Classes/cocos2d/CCActionPageTurn3D.m | 86 ++ Classes/cocos2d/CCActionProgressTimer.h | 59 + Classes/cocos2d/CCActionProgressTimer.m | 103 ++ Classes/cocos2d/CCActionTiledGrid.h | 211 ++++ Classes/cocos2d/CCActionTiledGrid.m | 768 +++++++++++++ Classes/cocos2d/CCActionTween.h | 62 + Classes/cocos2d/CCActionTween.m | 72 ++ Classes/cocos2d/CCAnimation.h | 132 +++ Classes/cocos2d/CCAnimation.m | 152 +++ Classes/cocos2d/CCAnimationCache.h | 63 + Classes/cocos2d/CCAnimationCache.m | 100 ++ Classes/cocos2d/CCAtlasNode.h | 86 ++ Classes/cocos2d/CCAtlasNode.m | 205 ++++ Classes/cocos2d/CCBlockSupport.h | 51 + Classes/cocos2d/CCBlockSupport.m | 46 + Classes/cocos2d/CCCamera.h | 94 ++ Classes/cocos2d/CCCamera.m | 130 +++ Classes/cocos2d/CCCompatibility.h | 224 ++++ Classes/cocos2d/CCCompatibility.m | 596 ++++++++++ Classes/cocos2d/CCConfiguration.h | 110 ++ Classes/cocos2d/CCConfiguration.m | 192 +++ Classes/cocos2d/CCDirector.h | 304 +++++ Classes/cocos2d/CCDirector.m | 557 +++++++++ Classes/cocos2d/CCDrawingPrimitives.h | 91 ++ Classes/cocos2d/CCDrawingPrimitives.m | 271 +++++ Classes/cocos2d/CCGrabber.h | 43 + Classes/cocos2d/CCGrabber.m | 95 ++ Classes/cocos2d/CCGrid.h | 121 ++ Classes/cocos2d/CCGrid.m | 571 +++++++++ Classes/cocos2d/CCLabelAtlas.h | 61 + Classes/cocos2d/CCLabelAtlas.m | 189 +++ Classes/cocos2d/CCLabelBMFont.h | 189 +++ Classes/cocos2d/CCLabelBMFont.m | 669 +++++++++++ Classes/cocos2d/CCLabelTTF.h | 62 + Classes/cocos2d/CCLabelTTF.m | 125 ++ Classes/cocos2d/CCLayer.h | 261 +++++ Classes/cocos2d/CCLayer.m | 562 +++++++++ Classes/cocos2d/CCMenu.h | 89 ++ Classes/cocos2d/CCMenu.m | 516 +++++++++ Classes/cocos2d/CCMenuItem.h | 341 ++++++ Classes/cocos2d/CCMenuItem.m | 752 ++++++++++++ Classes/cocos2d/CCMotionStreak.h | 67 ++ Classes/cocos2d/CCMotionStreak.m | 104 ++ Classes/cocos2d/CCNode.h | 510 ++++++++ Classes/cocos2d/CCNode.m | 883 ++++++++++++++ Classes/cocos2d/CCParallaxNode.h | 49 + Classes/cocos2d/CCParallaxNode.m | 160 +++ Classes/cocos2d/CCParticleExamples.h | 110 ++ Classes/cocos2d/CCParticleExamples.m | 925 +++++++++++++++ Classes/cocos2d/CCParticleSystem.h | 444 +++++++ Classes/cocos2d/CCParticleSystem.m | 795 +++++++++++++ Classes/cocos2d/CCParticleSystemPoint.h | 64 + Classes/cocos2d/CCParticleSystemPoint.m | 207 ++++ Classes/cocos2d/CCParticleSystemQuad.h | 74 ++ Classes/cocos2d/CCParticleSystemQuad.m | 314 +++++ Classes/cocos2d/CCProgressTimer.h | 83 ++ Classes/cocos2d/CCProgressTimer.m | 494 ++++++++ Classes/cocos2d/CCProtocols.h | 124 ++ Classes/cocos2d/CCRenderTexture.h | 108 ++ Classes/cocos2d/CCRenderTexture.m | 308 +++++ Classes/cocos2d/CCRibbon.h | 117 ++ Classes/cocos2d/CCRibbon.m | 381 ++++++ Classes/cocos2d/CCScene.h | 42 + Classes/cocos2d/CCScene.m | 44 + Classes/cocos2d/CCScheduler.h | 212 ++++ Classes/cocos2d/CCScheduler.m | 597 ++++++++++ Classes/cocos2d/CCSprite.h | 367 ++++++ Classes/cocos2d/CCSprite.m | 1004 ++++++++++++++++ Classes/cocos2d/CCSpriteBatchNode.h | 143 +++ Classes/cocos2d/CCSpriteBatchNode.m | 499 ++++++++ Classes/cocos2d/CCSpriteFrame.h | 89 ++ Classes/cocos2d/CCSpriteFrame.m | 87 ++ Classes/cocos2d/CCSpriteFrameCache.h | 133 +++ Classes/cocos2d/CCSpriteFrameCache.m | 344 ++++++ Classes/cocos2d/CCSpriteSheet.h | 61 + Classes/cocos2d/CCSpriteSheet.m | 37 + Classes/cocos2d/CCTMXLayer.h | 153 +++ Classes/cocos2d/CCTMXLayer.m | 668 +++++++++++ Classes/cocos2d/CCTMXObjectGroup.h | 65 ++ Classes/cocos2d/CCTMXObjectGroup.m | 83 ++ Classes/cocos2d/CCTMXTiledMap.h | 144 +++ Classes/cocos2d/CCTMXTiledMap.m | 202 ++++ Classes/cocos2d/CCTMXXMLParser.h | 200 ++++ Classes/cocos2d/CCTMXXMLParser.m | 444 +++++++ Classes/cocos2d/CCTexture2D.h | 308 +++++ Classes/cocos2d/CCTexture2D.m | 754 ++++++++++++ Classes/cocos2d/CCTextureAtlas.h | 138 +++ Classes/cocos2d/CCTextureAtlas.m | 343 ++++++ Classes/cocos2d/CCTextureCache.h | 139 +++ Classes/cocos2d/CCTextureCache.m | 466 ++++++++ Classes/cocos2d/CCTexturePVR.h | 118 ++ Classes/cocos2d/CCTexturePVR.m | 407 +++++++ Classes/cocos2d/CCTileMapAtlas.h | 82 ++ Classes/cocos2d/CCTileMapAtlas.m | 233 ++++ Classes/cocos2d/CCTransition.h | 295 +++++ Classes/cocos2d/CCTransition.m | 1057 +++++++++++++++++ Classes/cocos2d/CCTransitionPageTurn.h | 60 + Classes/cocos2d/CCTransitionPageTurn.m | 117 ++ Classes/cocos2d/CCTransitionRadial.h | 40 + Classes/cocos2d/CCTransitionRadial.m | 115 ++ Classes/cocos2d/Platforms/CCGL.h | 82 ++ Classes/cocos2d/Platforms/CCNS.h | 62 + Classes/cocos2d/Platforms/Mac/CCDirectorMac.h | 99 ++ Classes/cocos2d/Platforms/Mac/CCDirectorMac.m | 471 ++++++++ Classes/cocos2d/Platforms/Mac/CCEventDispatcher.h | 233 ++++ Classes/cocos2d/Platforms/Mac/CCEventDispatcher.m | 578 ++++++++++ Classes/cocos2d/Platforms/Mac/MacGLView.h | 88 ++ Classes/cocos2d/Platforms/Mac/MacGLView.m | 241 ++++ Classes/cocos2d/Platforms/iOS/CCDirectorIOS.h | 342 ++++++ Classes/cocos2d/Platforms/iOS/CCDirectorIOS.m | 897 +++++++++++++++ .../Platforms/iOS/CCTouchDelegateProtocol.h | 75 ++ Classes/cocos2d/Platforms/iOS/CCTouchDispatcher.h | 122 ++ Classes/cocos2d/Platforms/iOS/CCTouchDispatcher.m | 326 ++++++ Classes/cocos2d/Platforms/iOS/CCTouchHandler.h | 93 ++ Classes/cocos2d/Platforms/iOS/CCTouchHandler.m | 135 +++ Classes/cocos2d/Platforms/iOS/EAGLView.h | 155 +++ Classes/cocos2d/Platforms/iOS/EAGLView.m | 342 ++++++ Classes/cocos2d/Platforms/iOS/ES1Renderer.h | 71 ++ Classes/cocos2d/Platforms/iOS/ES1Renderer.m | 252 ++++ Classes/cocos2d/Platforms/iOS/ESRenderer.h | 53 + Classes/cocos2d/Platforms/iOS/glu.c | 113 ++ Classes/cocos2d/Platforms/iOS/glu.h | 29 + Classes/cocos2d/Support/CCArray.h | 92 ++ Classes/cocos2d/Support/CCArray.m | 245 ++++ Classes/cocos2d/Support/CCFileUtils.h | 61 + Classes/cocos2d/Support/CCFileUtils.m | 168 +++ Classes/cocos2d/Support/CCProfiling.h | 53 + Classes/cocos2d/Support/CCProfiling.m | 117 ++ Classes/cocos2d/Support/CGPointExtension.h | 321 ++++++ Classes/cocos2d/Support/CGPointExtension.m | 167 +++ Classes/cocos2d/Support/OpenGL_Internal.h | 80 ++ Classes/cocos2d/Support/TGAlib.h | 55 + Classes/cocos2d/Support/TGAlib.m | 272 +++++ Classes/cocos2d/Support/TransformUtils.h | 37 + Classes/cocos2d/Support/TransformUtils.m | 46 + Classes/cocos2d/Support/ZipUtils.h | 78 ++ Classes/cocos2d/Support/ZipUtils.m | 246 ++++ Classes/cocos2d/Support/base64.c | 89 ++ Classes/cocos2d/Support/base64.h | 33 + Classes/cocos2d/Support/ccCArray.h | 406 +++++++ Classes/cocos2d/Support/ccUtils.c | 20 + Classes/cocos2d/Support/ccUtils.h | 29 + Classes/cocos2d/Support/uthash.h | 956 +++++++++++++++ Classes/cocos2d/Support/utlist.h | 493 ++++++++ Classes/cocos2d/ccConfig.h | 291 +++++ Classes/cocos2d/ccMacros.h | 227 ++++ Classes/cocos2d/ccTypes.h | 262 +++++ Classes/cocos2d/cocos2d.h | 165 +++ Classes/cocos2d/cocos2d.m | 33 + Littlest.xcodeproj/project.pbxproj | 14 + 176 files changed, 42357 insertions(+), 703 deletions(-) create mode 100644 Classes/Foundation/GraphicsServices/Geometry/BasicPrimitives.h create mode 100644 Classes/Foundation/GraphicsServices/Geometry/BasicPrimitives.mm create mode 100644 Classes/cocos2d/CCAction.h create mode 100644 Classes/cocos2d/CCAction.m create mode 100644 Classes/cocos2d/CCActionCamera.h create mode 100644 Classes/cocos2d/CCActionCamera.m create mode 100644 Classes/cocos2d/CCActionEase.h create mode 100644 Classes/cocos2d/CCActionEase.m create mode 100644 Classes/cocos2d/CCActionGrid.h create mode 100644 Classes/cocos2d/CCActionGrid.m create mode 100644 Classes/cocos2d/CCActionGrid3D.h create mode 100644 Classes/cocos2d/CCActionGrid3D.m create mode 100644 Classes/cocos2d/CCActionInstant.h create mode 100644 Classes/cocos2d/CCActionInstant.m create mode 100644 Classes/cocos2d/CCActionInterval.h create mode 100644 Classes/cocos2d/CCActionInterval.m create mode 100644 Classes/cocos2d/CCActionManager.h create mode 100644 Classes/cocos2d/CCActionManager.m create mode 100644 Classes/cocos2d/CCActionPageTurn3D.h create mode 100644 Classes/cocos2d/CCActionPageTurn3D.m create mode 100644 Classes/cocos2d/CCActionProgressTimer.h create mode 100644 Classes/cocos2d/CCActionProgressTimer.m create mode 100644 Classes/cocos2d/CCActionTiledGrid.h create mode 100644 Classes/cocos2d/CCActionTiledGrid.m create mode 100644 Classes/cocos2d/CCActionTween.h create mode 100644 Classes/cocos2d/CCActionTween.m create mode 100644 Classes/cocos2d/CCAnimation.h create mode 100644 Classes/cocos2d/CCAnimation.m create mode 100644 Classes/cocos2d/CCAnimationCache.h create mode 100644 Classes/cocos2d/CCAnimationCache.m create mode 100644 Classes/cocos2d/CCAtlasNode.h create mode 100644 Classes/cocos2d/CCAtlasNode.m create mode 100644 Classes/cocos2d/CCBlockSupport.h create mode 100644 Classes/cocos2d/CCBlockSupport.m create mode 100644 Classes/cocos2d/CCCamera.h create mode 100644 Classes/cocos2d/CCCamera.m create mode 100644 Classes/cocos2d/CCCompatibility.h create mode 100644 Classes/cocos2d/CCCompatibility.m create mode 100644 Classes/cocos2d/CCConfiguration.h create mode 100644 Classes/cocos2d/CCConfiguration.m create mode 100644 Classes/cocos2d/CCDirector.h create mode 100644 Classes/cocos2d/CCDirector.m create mode 100644 Classes/cocos2d/CCDrawingPrimitives.h create mode 100644 Classes/cocos2d/CCDrawingPrimitives.m create mode 100644 Classes/cocos2d/CCGrabber.h create mode 100644 Classes/cocos2d/CCGrabber.m create mode 100644 Classes/cocos2d/CCGrid.h create mode 100644 Classes/cocos2d/CCGrid.m create mode 100644 Classes/cocos2d/CCLabelAtlas.h create mode 100644 Classes/cocos2d/CCLabelAtlas.m create mode 100644 Classes/cocos2d/CCLabelBMFont.h create mode 100644 Classes/cocos2d/CCLabelBMFont.m create mode 100644 Classes/cocos2d/CCLabelTTF.h create mode 100644 Classes/cocos2d/CCLabelTTF.m create mode 100644 Classes/cocos2d/CCLayer.h create mode 100644 Classes/cocos2d/CCLayer.m create mode 100644 Classes/cocos2d/CCMenu.h create mode 100644 Classes/cocos2d/CCMenu.m create mode 100644 Classes/cocos2d/CCMenuItem.h create mode 100644 Classes/cocos2d/CCMenuItem.m create mode 100644 Classes/cocos2d/CCMotionStreak.h create mode 100644 Classes/cocos2d/CCMotionStreak.m create mode 100644 Classes/cocos2d/CCNode.h create mode 100644 Classes/cocos2d/CCNode.m create mode 100644 Classes/cocos2d/CCParallaxNode.h create mode 100644 Classes/cocos2d/CCParallaxNode.m create mode 100644 Classes/cocos2d/CCParticleExamples.h create mode 100644 Classes/cocos2d/CCParticleExamples.m create mode 100644 Classes/cocos2d/CCParticleSystem.h create mode 100644 Classes/cocos2d/CCParticleSystem.m create mode 100644 Classes/cocos2d/CCParticleSystemPoint.h create mode 100644 Classes/cocos2d/CCParticleSystemPoint.m create mode 100644 Classes/cocos2d/CCParticleSystemQuad.h create mode 100644 Classes/cocos2d/CCParticleSystemQuad.m create mode 100644 Classes/cocos2d/CCProgressTimer.h create mode 100644 Classes/cocos2d/CCProgressTimer.m create mode 100644 Classes/cocos2d/CCProtocols.h create mode 100755 Classes/cocos2d/CCRenderTexture.h create mode 100755 Classes/cocos2d/CCRenderTexture.m create mode 100644 Classes/cocos2d/CCRibbon.h create mode 100644 Classes/cocos2d/CCRibbon.m create mode 100644 Classes/cocos2d/CCScene.h create mode 100644 Classes/cocos2d/CCScene.m create mode 100644 Classes/cocos2d/CCScheduler.h create mode 100644 Classes/cocos2d/CCScheduler.m create mode 100644 Classes/cocos2d/CCSprite.h create mode 100644 Classes/cocos2d/CCSprite.m create mode 100644 Classes/cocos2d/CCSpriteBatchNode.h create mode 100644 Classes/cocos2d/CCSpriteBatchNode.m create mode 100644 Classes/cocos2d/CCSpriteFrame.h create mode 100644 Classes/cocos2d/CCSpriteFrame.m create mode 100644 Classes/cocos2d/CCSpriteFrameCache.h create mode 100644 Classes/cocos2d/CCSpriteFrameCache.m create mode 100644 Classes/cocos2d/CCSpriteSheet.h create mode 100644 Classes/cocos2d/CCSpriteSheet.m create mode 100644 Classes/cocos2d/CCTMXLayer.h create mode 100644 Classes/cocos2d/CCTMXLayer.m create mode 100644 Classes/cocos2d/CCTMXObjectGroup.h create mode 100644 Classes/cocos2d/CCTMXObjectGroup.m create mode 100644 Classes/cocos2d/CCTMXTiledMap.h create mode 100644 Classes/cocos2d/CCTMXTiledMap.m create mode 100644 Classes/cocos2d/CCTMXXMLParser.h create mode 100644 Classes/cocos2d/CCTMXXMLParser.m create mode 100644 Classes/cocos2d/CCTexture2D.h create mode 100644 Classes/cocos2d/CCTexture2D.m create mode 100644 Classes/cocos2d/CCTextureAtlas.h create mode 100644 Classes/cocos2d/CCTextureAtlas.m create mode 100644 Classes/cocos2d/CCTextureCache.h create mode 100644 Classes/cocos2d/CCTextureCache.m create mode 100644 Classes/cocos2d/CCTexturePVR.h create mode 100644 Classes/cocos2d/CCTexturePVR.m create mode 100644 Classes/cocos2d/CCTileMapAtlas.h create mode 100644 Classes/cocos2d/CCTileMapAtlas.m create mode 100644 Classes/cocos2d/CCTransition.h create mode 100644 Classes/cocos2d/CCTransition.m create mode 100644 Classes/cocos2d/CCTransitionPageTurn.h create mode 100644 Classes/cocos2d/CCTransitionPageTurn.m create mode 100644 Classes/cocos2d/CCTransitionRadial.h create mode 100644 Classes/cocos2d/CCTransitionRadial.m create mode 100644 Classes/cocos2d/Platforms/CCGL.h create mode 100644 Classes/cocos2d/Platforms/CCNS.h create mode 100644 Classes/cocos2d/Platforms/Mac/CCDirectorMac.h create mode 100644 Classes/cocos2d/Platforms/Mac/CCDirectorMac.m create mode 100644 Classes/cocos2d/Platforms/Mac/CCEventDispatcher.h create mode 100644 Classes/cocos2d/Platforms/Mac/CCEventDispatcher.m create mode 100644 Classes/cocos2d/Platforms/Mac/MacGLView.h create mode 100644 Classes/cocos2d/Platforms/Mac/MacGLView.m create mode 100755 Classes/cocos2d/Platforms/iOS/CCDirectorIOS.h create mode 100755 Classes/cocos2d/Platforms/iOS/CCDirectorIOS.m create mode 100644 Classes/cocos2d/Platforms/iOS/CCTouchDelegateProtocol.h create mode 100644 Classes/cocos2d/Platforms/iOS/CCTouchDispatcher.h create mode 100644 Classes/cocos2d/Platforms/iOS/CCTouchDispatcher.m create mode 100644 Classes/cocos2d/Platforms/iOS/CCTouchHandler.h create mode 100644 Classes/cocos2d/Platforms/iOS/CCTouchHandler.m create mode 100755 Classes/cocos2d/Platforms/iOS/EAGLView.h create mode 100755 Classes/cocos2d/Platforms/iOS/EAGLView.m create mode 100755 Classes/cocos2d/Platforms/iOS/ES1Renderer.h create mode 100755 Classes/cocos2d/Platforms/iOS/ES1Renderer.m create mode 100755 Classes/cocos2d/Platforms/iOS/ESRenderer.h create mode 100755 Classes/cocos2d/Platforms/iOS/glu.c create mode 100644 Classes/cocos2d/Platforms/iOS/glu.h create mode 100644 Classes/cocos2d/Support/CCArray.h create mode 100644 Classes/cocos2d/Support/CCArray.m create mode 100644 Classes/cocos2d/Support/CCFileUtils.h create mode 100644 Classes/cocos2d/Support/CCFileUtils.m create mode 100644 Classes/cocos2d/Support/CCProfiling.h create mode 100644 Classes/cocos2d/Support/CCProfiling.m create mode 100644 Classes/cocos2d/Support/CGPointExtension.h create mode 100644 Classes/cocos2d/Support/CGPointExtension.m create mode 100644 Classes/cocos2d/Support/OpenGL_Internal.h create mode 100644 Classes/cocos2d/Support/TGAlib.h create mode 100644 Classes/cocos2d/Support/TGAlib.m create mode 100644 Classes/cocos2d/Support/TransformUtils.h create mode 100644 Classes/cocos2d/Support/TransformUtils.m create mode 100644 Classes/cocos2d/Support/ZipUtils.h create mode 100644 Classes/cocos2d/Support/ZipUtils.m create mode 100644 Classes/cocos2d/Support/base64.c create mode 100644 Classes/cocos2d/Support/base64.h create mode 100644 Classes/cocos2d/Support/ccCArray.h create mode 100644 Classes/cocos2d/Support/ccUtils.c create mode 100644 Classes/cocos2d/Support/ccUtils.h create mode 100644 Classes/cocos2d/Support/uthash.h create mode 100644 Classes/cocos2d/Support/utlist.h create mode 100644 Classes/cocos2d/ccConfig.h create mode 100644 Classes/cocos2d/ccMacros.h create mode 100644 Classes/cocos2d/ccTypes.h create mode 100644 Classes/cocos2d/cocos2d.h create mode 100644 Classes/cocos2d/cocos2d.m diff --git a/Classes/Foundation/Common/GlobalDefines.h b/Classes/Foundation/Common/GlobalDefines.h index 7dde617..14712b2 100755 --- a/Classes/Foundation/Common/GlobalDefines.h +++ b/Classes/Foundation/Common/GlobalDefines.h @@ -70,9 +70,9 @@ //---------------------------------------------------------------------------------------- // alignment macros #if defined(__WINDOWS__) -#define ALIGN(N) __declspec(align(N)) +#define MEM_ALIGN(N) __declspec(align(N)) #elif defined(__iOS__) -#define ALIGN(N) __attribute__((aligned (N))) +#define MEM_ALIGN(N) __attribute__((aligned (N))) #endif #define IS_POWER_OF_TWO(x) ( ((x) & -(x)) == (x) ) diff --git a/Classes/Foundation/GraphicsServices/Geometry/BasicPrimitives.h b/Classes/Foundation/GraphicsServices/Geometry/BasicPrimitives.h new file mode 100644 index 0000000..ba50ba9 --- /dev/null +++ b/Classes/Foundation/GraphicsServices/Geometry/BasicPrimitives.h @@ -0,0 +1,27 @@ +#pragma once + +#include "Foundation/Common/GlobalInclude.h" +#include "Foundation/Math/MathInclude.h" + +//#include +#include + +//---------------------------------------------------------------------------------------- +struct Basic2DPrimitive +{ +protected: + Basic2DPrimitive(); // Only the children classes can call this. + ~Basic2DPrimitive(); + + GLuint mVertexBuffer; + uint16_t mX, mY; +}; + +//---------------------------------------------------------------------------------------- +struct Rectangle : public Basic2DPrimitive +{ +public: + GLuint mWidth, mHeight; + + Rectangle( uint16_t width, uint16_t height, uint16_t anchorX, uint16_t anchorY ); +}; diff --git a/Classes/Foundation/GraphicsServices/Geometry/BasicPrimitives.mm b/Classes/Foundation/GraphicsServices/Geometry/BasicPrimitives.mm new file mode 100644 index 0000000..4cc9da1 --- /dev/null +++ b/Classes/Foundation/GraphicsServices/Geometry/BasicPrimitives.mm @@ -0,0 +1,26 @@ +#include "BasicPrimitives.h" + +//---------------------------------------------------------------------------------------- +Basic2DPrimitive::Basic2DPrimitive() : mVertexBuffer(0), mX(0), mY(0) +{ + glGenBuffers( 1, &mVertexBuffer ); +} + +//---------------------------------------------------------------------------------------- +Basic2DPrimitive::~Basic2DPrimitive() +{ + glDeleteBuffers( 1, &mVertexBuffer ); +} + +//---------------------------------------------------------------------------------------- +Rectangle::Rectangle( uint16_t width, uint16_t height, uint16_t anchorX, uint16_t anchorY ) : Basic2DPrimitive() +{ + Assert( mVertexBuffer ); + glBindBuffer( GL_ARRAY_BUFFER, mVertexBuffer ); + + mWidth = width; + mHeight = height; + + uint16_t values[4 * 2] = {-anchorX, height + anchorY, -anchorX, }; + glBufferData( GL_ARRAY_BUFFER, 4 * 2 * sizeof(uint16_t), values, GL_STATIC_DRAW ); +} diff --git a/Classes/Foundation/GraphicsServices/OpenGLServices.h b/Classes/Foundation/GraphicsServices/OpenGLServices.h index 819ba12..deadd57 100644 --- a/Classes/Foundation/GraphicsServices/OpenGLServices.h +++ b/Classes/Foundation/GraphicsServices/OpenGLServices.h @@ -10,8 +10,8 @@ * we should never need to set context other than during startup or shutdown. *****************************************************************************************/ -#include -#include +//#include +//#include #include #include diff --git a/Classes/Foundation/GraphicsServices/OpenGLServices.mm b/Classes/Foundation/GraphicsServices/OpenGLServices.mm index 236059e..9c1f7a2 100644 --- a/Classes/Foundation/GraphicsServices/OpenGLServices.mm +++ b/Classes/Foundation/GraphicsServices/OpenGLServices.mm @@ -22,16 +22,21 @@ bool OpenGLServices::init( EAGLContext* mainContext ) initScratchMem(); - // Enable some common states. + // Enable some common states and set their parameters. glEnable( GL_TEXTURE_2D ); - glEnable( GL_BLEND ); - // We will premultiply alpha into the color channels of all textures (so no alpha animation). // This is basically the A over B alpha scheme. glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ); - glEnable( GL_DEPTH_TEST ); + glDepthFunc( GL_LEQUAL ); + glFrontFace( GL_CCW ); + glCullFace( GL_BACK ); + + // Disable unused stuff. + glDisable( GL_STENCIL_TEST ); + glDisable( GL_SCISSOR_TEST ); + glDisable( GL_DITHER ); return true; } diff --git a/Classes/Foundation/Math/MathTypes.h b/Classes/Foundation/Math/MathTypes.h index c16a44e..379bf16 100755 --- a/Classes/Foundation/Math/MathTypes.h +++ b/Classes/Foundation/Math/MathTypes.h @@ -4,16 +4,16 @@ #include "Foundation/Math/MathOperations.h" //---------------------------------------------------------------------------------------- -struct Vector2 +struct Vec2 { float x; float y; - slInline explicit Vector2() {} - slInline explicit Vector2(const float xy) {x = xy; y = xy;} - slInline explicit Vector2(const float ix, const float iy) {x = ix; y = iy;} + slInline explicit Vec2() {} + slInline explicit Vec2(const float xy) {x = xy; y = xy;} + slInline explicit Vec2(const float ix, const float iy) {x = ix; y = iy;} - slInline Vector2(const Vector2& v) {x = v.x; y = v.y;} // copy constructor + slInline Vec2(const Vec2& v) {x = v.x; y = v.y;} // copy constructor slInline float* AsFloatArray() {return &x;} slInline const float* AsFloatArray() const {return &x;} @@ -23,21 +23,21 @@ struct Vector2 //---------------------------------------------------------------------------------------- -struct Vector3 +struct Vec3 { float x; float y; float z; - slInline explicit Vector3() {} - slInline explicit Vector3(const float xyz) {x = xyz; y = xyz; z = xyz;} - slInline explicit Vector3(const float ix, const float iy, const float iz) {x = ix; y = iy; z = iz;} + slInline explicit Vec3() {} + slInline explicit Vec3(const float xyz) {x = xyz; y = xyz; z = xyz;} + slInline explicit Vec3(const float ix, const float iy, const float iz) {x = ix; y = iy; z = iz;} - slInline explicit Vector3(const Vector2& v, const float iz) {x = v.x; y = v.y; z = iz;} + slInline explicit Vec3(const Vec2& v, const float iz) {x = v.x; y = v.y; z = iz;} - slInline Vector3(const Vector3& v) {x = v.x; y = v.y; z = v.z;} // copy constructor + slInline Vec3(const Vec3& v) {x = v.x; y = v.y; z = v.z;} // copy constructor - slInline Vector2 AsVector2() const {return Vector2(x, y);} + slInline Vec2 AsVec2() const {return Vec2(x, y);} slInline float* AsFloatArray() {return &x;} slInline const float* AsFloatArray() const {return &x;} @@ -47,27 +47,27 @@ struct Vector3 //---------------------------------------------------------------------------------------- -struct Vector4 +struct Vec4 { float x; float y; float z; float w; - slInline explicit Vector4() {} - slInline explicit Vector4(const float xyzw) {x = xyzw; y = xyzw; z = xyzw; w = xyzw;} - slInline explicit Vector4(const float xyz, const float iw) {x = xyz; y = xyz; z = xyz; w = iw;} - slInline explicit Vector4(const float ix, const float iy, const float iz, const float iw) {x = ix; y = iy; z = iz; w = iw;} + slInline explicit Vec4() {} + slInline explicit Vec4(const float xyzw) {x = xyzw; y = xyzw; z = xyzw; w = xyzw;} + slInline explicit Vec4(const float xyz, const float iw) {x = xyz; y = xyz; z = xyz; w = iw;} + slInline explicit Vec4(const float ix, const float iy, const float iz, const float iw) {x = ix; y = iy; z = iz; w = iw;} - slInline explicit Vector4(const Vector2& u, const Vector2& v) {x = u.x; y = u.y; z = v.x; w = v.y;} - slInline explicit Vector4(const Vector2& v, const float iz, const float iw) {x = v.x; y = v.y; z = iz; w = iw;} + slInline explicit Vec4(const Vec2& u, const Vec2& v) {x = u.x; y = u.y; z = v.x; w = v.y;} + slInline explicit Vec4(const Vec2& v, const float iz, const float iw) {x = v.x; y = v.y; z = iz; w = iw;} - slInline explicit Vector4(const Vector3& v, const float iw) {x = v.x; y = v.y; z = v.z; w = iw;} + slInline explicit Vec4(const Vec3& v, const float iw) {x = v.x; y = v.y; z = v.z; w = iw;} - slInline Vector4(const Vector4& v) {x = v.x; y = v.y; z = v.z; w = v.w;} // copy constructor + slInline Vec4(const Vec4& v) {x = v.x; y = v.y; z = v.z; w = v.w;} // copy constructor - slInline Vector2 AsVector2() const {return Vector2(x, y);} - slInline Vector3 AsVector3() const {return Vector3(x, y, z);} + slInline Vec2 AsVec2() const {return Vec2(x, y);} + slInline Vec3 AsVec3() const {return Vec3(x, y, z);} slInline float* AsFloatArray() {return &x;} slInline const float* AsFloatArray() const {return &x;} @@ -85,43 +85,43 @@ struct Quaternion float s; slInline explicit Quaternion() {} - explicit Quaternion(const float angle, const Vector3& normalized_axis); + explicit Quaternion(const float angle, const Vec3& normalized_axis); explicit Quaternion(const float angle, const float x, const float y, const float z); slInline Quaternion(const Quaternion& q) {i = q.i; j = q.j; k = q.k; s = q.s;} - Vector4 AsVector4(); + Vec4 AsVec4(); slInline float* AsFloatArray() {return &i;} - Vector3 GetImaginary(); + Vec3 GetImaginary(); slInline float GetReal() {return s;} }; -slInline Quaternion::Quaternion(const float angle, const Vector3& normalized_axis) +slInline Quaternion::Quaternion(const float angle, const Vec3& normalized_axis) { - Assert( EpsilonEquals(LengthVector3(normalized_axis), 1.0f, kEpsilon) ); + Assert( EpsilonEquals(normalized_axis.x * normalized_axis.x + normalized_axis.y * normalized_axis.y + normalized_axis.z * normalized_axis.z, 1.0f, kSqrtEpsilon) ); float half_angle = angle * 0.5f; - float sin_half_angle = Sinf(half_angle); + float sin_half_angle = (float)Sinf(half_angle); i = normalized_axis.x * sin_half_angle; j = normalized_axis.y * sin_half_angle; k = normalized_axis.z * sin_half_angle; - s = Cosf(half_angle); + s = (float)Cosf(half_angle); } slInline Quaternion::Quaternion(const float angle, const float x, const float y, const float z) { Assert( EpsilonEquals(x * x + y * y + z * z, 1.0f, kSqrtEpsilon) ); float half_angle = angle * 0.5f; - float sin_half_angle = Sinf(half_angle); + float sin_half_angle = (float)Sinf(half_angle); i = x * sin_half_angle; j = y * sin_half_angle; k = z * sin_half_angle; - s = Cosf(half_angle); + s = (float)Cosf(half_angle); } -Vector4 Quaternion::AsVector4() +Vec4 Quaternion::AsVec4() { - Vector4 r; + Vec4 r; r.x = i; r.y = j; r.z = k; @@ -129,9 +129,9 @@ Vector4 Quaternion::AsVector4() return r; } -Vector3 Quaternion::GetImaginary() +Vec3 Quaternion::GetImaginary() { - Vector3 r; + Vec3 r; r.x = i; r.y = j; r.z = k; @@ -140,35 +140,35 @@ Vector3 Quaternion::GetImaginary() //---------------------------------------------------------------------------------------- -struct Matrix3 +struct Mat3 { - Vector3 v[3]; + Vec3 v[3]; - slInline explicit Matrix3() {} - explicit Matrix3(const Vector3& v0, const Vector3& v1, const Vector3& v2); - explicit Matrix3(const float v00, const float v01, const float v02, - const float v10, const float v11, const float v12, - const float v20, const float v21, const float v22); - Matrix3(Matrix3& m); // copy constructor + slInline explicit Mat3() {} + explicit Mat3(const Vec3& v0, const Vec3& v1, const Vec3& v2); + explicit Mat3(const float v00, const float v01, const float v02, + const float v10, const float v11, const float v12, + const float v20, const float v21, const float v22); + Mat3(const Mat3& m); // copy constructor float* AsFloatArray() {return &v[0].x;} }; -slInline Matrix3::Matrix3(const Vector3& v0, const Vector3& v1, const Vector3& v2) +slInline Mat3::Mat3(const Vec3& v0, const Vec3& v1, const Vec3& v2) { v[0] = v0; v[1] = v1; v[2] = v2; } -slInline Matrix3::Matrix3(const float v00, const float v01, const float v02, const float v10, const float v11, const float v12, const float v20, const float v21, const float v22) +slInline Mat3::Mat3(const float v00, const float v01, const float v02, const float v10, const float v11, const float v12, const float v20, const float v21, const float v22) { v[0].x = v00; v[0].y = v01; v[0].z = v02; v[1].x = v10; v[1].y = v11; v[1].z = v12; v[2].x = v20; v[2].y = v21; v[2].z = v22; } -slInline Matrix3::Matrix3(Matrix3& m) +slInline Mat3::Mat3(const Mat3& m) { v[0] = m.v[0]; v[1] = m.v[1]; @@ -177,23 +177,23 @@ slInline Matrix3::Matrix3(Matrix3& m) //---------------------------------------------------------------------------------------- -struct Matrix4 +struct Mat4 { - Vector4 v[4]; + Vec4 v[4]; - slInline explicit Matrix4() {} - explicit Matrix4(const Vector4& v0, const Vector4& v1, const Vector4& v2, const Vector4& v3); - explicit Matrix4(const float v00, const float v01, const float v02, const float v03, - const float v10, const float v11, const float v12, const float v13, - const float v20, const float v21, const float v22, const float v23, - const float v30, const float v31, const float v32, const float v33); - explicit Matrix4(const Matrix3& m); - Matrix4(const Matrix4& m); // copy constructor + slInline explicit Mat4() {} + explicit Mat4(const Vec4& v0, const Vec4& v1, const Vec4& v2, const Vec4& v3); + explicit Mat4(const float v00, const float v01, const float v02, const float v03, + const float v10, const float v11, const float v12, const float v13, + const float v20, const float v21, const float v22, const float v23, + const float v30, const float v31, const float v32, const float v33); + explicit Mat4(const Mat3& m); + Mat4(const Mat4& m); // copy constructor float* AsFloatArray() {return &v[0].x;} }; -slInline Matrix4::Matrix4(const Vector4& v0, const Vector4& v1, const Vector4& v2, const Vector4& v3) +slInline Mat4::Mat4(const Vec4& v0, const Vec4& v1, const Vec4& v2, const Vec4& v3) { v[0] = v0; v[1] = v1; @@ -201,7 +201,7 @@ slInline Matrix4::Matrix4(const Vector4& v0, const Vector4& v1, const Vector4& v v[3] = v3; } -slInline Matrix4::Matrix4(const float v00, const float v01, const float v02, const float v03, const float v10, const float v11, const float v12, const float v13, const float v20, const float v21, const float v22, const float v23, const float v30, const float v31, const float v32, const float v33) +slInline Mat4::Mat4(const float v00, const float v01, const float v02, const float v03, const float v10, const float v11, const float v12, const float v13, const float v20, const float v21, const float v22, const float v23, const float v30, const float v31, const float v32, const float v33) { v[0].x = v00; v[0].y = v01; v[0].z = v02; v[0].w = v03; v[1].x = v10; v[1].y = v11; v[1].z = v12; v[1].w = v13; @@ -209,7 +209,7 @@ slInline Matrix4::Matrix4(const float v00, const float v01, const float v02, con v[3].x = v30; v[3].y = v31; v[3].z = v32; v[3].w = v33; } -slInline Matrix4::Matrix4(const Matrix3& m) +slInline Mat4::Mat4(const Mat3& m) { v[0].x = m.v[0].x; v[0].y = m.v[0].y; v[0].z = m.v[0].z; v[0].w = 0.0f; v[1].x = m.v[1].x; v[1].y = m.v[1].y; v[1].z = m.v[1].z; v[1].w = 0.0f; @@ -217,7 +217,7 @@ slInline Matrix4::Matrix4(const Matrix3& m) v[3].x = 0.0f; v[3].y = 0.0f; v[3].z = 0.0f; v[3].w = 1.0f; } -slInline Matrix4::Matrix4(const Matrix4& m) +slInline Mat4::Mat4(const Mat4& m) { v[0] = m.v[0]; v[1] = m.v[1]; @@ -227,18 +227,18 @@ slInline Matrix4::Matrix4(const Matrix4& m) //---------------------------------------------------------------------------------------- -typedef ALIGN(8) Vector2 AlignedVector2; -typedef ALIGN(16) Vector3 AlignedVector3; -typedef ALIGN(16) Vector4 AlignedVector4; +typedef MEM_ALIGN(8) Vec2 AlignedVec2; +typedef MEM_ALIGN(16) Vec3 AlignedVec3; +typedef MEM_ALIGN(16) Vec4 AlignedVec4; -typedef ALIGN(64) Matrix3 AlignedMatrix3; -typedef ALIGN(64) Matrix4 AlignedMatrix4; +typedef MEM_ALIGN(64) Mat3 AlignedMat3; +typedef MEM_ALIGN(64) Mat4 AlignedMat4; //---------------------------------------------------------------------------------------- // SIMD Structures //---------------------------------------------------------------------------------------- -struct Vector2SOA +struct Vec2SOA { uint32_t m_Count; uint32_t m_MaxCount; @@ -246,13 +246,13 @@ struct Vector2SOA float* m_X; float* m_Y; - slInline explicit Vector2SOA() {m_Count = 0; m_MaxCount = 0; m_X = NULL; m_Y = NULL;} - bool InitVector2SOA(float* buffer, uint32_t buffer_size); + slInline explicit Vec2SOA() {m_Count = 0; m_MaxCount = 0; m_X = NULL; m_Y = NULL;} + bool InitVec2SOA(float* buffer, uint32_t buffer_size); - void GetVector2AtIndex(Vector2& v, uint32_t index) {Assert(index < m_Count); v.x = m_X[index]; v.y = m_Y[index];} + void GetVec2AtIndex(Vec2& v, uint32_t index) {Assert(index < m_Count); v.x = m_X[index]; v.y = m_Y[index];} }; -slInline bool Vector2SOA::InitVector2SOA(float* buffer, uint32_t max_count) +slInline bool Vec2SOA::InitVec2SOA(float* buffer, uint32_t max_count) { m_Count = 0; @@ -280,17 +280,17 @@ slInline bool Vector2SOA::InitVector2SOA(float* buffer, uint32_t max_count) //---------------------------------------------------------------------------------------- -struct Vector3SOA : public Vector2SOA +struct Vec3SOA : public Vec2SOA { float* m_Z; - slInline explicit Vector3SOA() {m_Count = 0; m_MaxCount = 0; m_X = NULL; m_Y = NULL; m_Z = NULL;} - bool InitVector3SOA(float* buffer, uint32_t buffer_size); + slInline explicit Vec3SOA() {m_Count = 0; m_MaxCount = 0; m_X = NULL; m_Y = NULL; m_Z = NULL;} + bool InitVec3SOA(float* buffer, uint32_t buffer_size); - void GetVector3AtIndex(Vector3& v, uint32_t index) {Assert(index < m_Count); v.x = m_X[index]; v.y = m_Y[index]; v.z = m_Z[index];} + void GetVec3AtIndex(Vec3& v, uint32_t index) {Assert(index < m_Count); v.x = m_X[index]; v.y = m_Y[index]; v.z = m_Z[index];} }; -slInline bool Vector3SOA::InitVector3SOA(float* buffer, uint32_t max_count) +slInline bool Vec3SOA::InitVec3SOA(float* buffer, uint32_t max_count) { m_Count = 0; @@ -321,17 +321,17 @@ slInline bool Vector3SOA::InitVector3SOA(float* buffer, uint32_t max_count) //---------------------------------------------------------------------------------------- -struct Vector4SOA : public Vector3SOA +struct Vec4SOA : public Vec3SOA { float* m_W; - slInline explicit Vector4SOA() {m_Count = 0; m_MaxCount = 0; m_X = NULL; m_Y = NULL; m_Z = NULL; m_W = NULL;} - bool InitVector4SOA(float* buffer, uint32_t buffer_size); + slInline explicit Vec4SOA() {m_Count = 0; m_MaxCount = 0; m_X = NULL; m_Y = NULL; m_Z = NULL; m_W = NULL;} + bool InitVec4SOA(float* buffer, uint32_t buffer_size); - void GetVector4AtIndex(Vector4& v, uint32_t index) {Assert(index < m_Count); v.x = m_X[index]; v.y = m_Y[index]; v.z = m_Z[index]; v.w = m_W[index];} + void GetVec4AtIndex(Vec4& v, uint32_t index) {Assert(index < m_Count); v.x = m_X[index]; v.y = m_Y[index]; v.z = m_Z[index]; v.w = m_W[index];} }; -slInline bool Vector4SOA::InitVector4SOA(float* buffer, uint32_t max_count) +slInline bool Vec4SOA::InitVec4SOA(float* buffer, uint32_t max_count) { m_Count = 0; diff --git a/Classes/Foundation/Math/Matrix.h b/Classes/Foundation/Math/Matrix.h index 37e5362..40e2a70 100755 --- a/Classes/Foundation/Math/Matrix.h +++ b/Classes/Foundation/Math/Matrix.h @@ -21,36 +21,36 @@ //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- -// Matrix3 +// Mat3 //---------------------------------------------------------------------------------------- -void SetMatrix3(Matrix3& r, const Matrix3& a); -void SetMatrix3(Matrix3& r, const Vector3& v0, const Vector3& v1, const Vector3& v2); +void SetMat3(Mat3& r, const Mat3& a); +void SetMat3(Mat3& r, const Vec3& v0, const Vec3& v1, const Vec3& v2); -void ScaleMatrix3(Matrix3& r, const float s, const Matrix3& a); -Matrix3 ScaleMatrix3(const float s, const Matrix3& a); +void ScaleMat3(Mat3& r, const float s, const Mat3& a); +Mat3 ScaleMat3(const float s, const Mat3& a); -float DeterminantOfMatrix3(const Matrix3& a); +float DeterminantOfMat3(const Mat3& a); -void TransposeMatrix3(Matrix3& r, const Matrix3& a); -Matrix3 TransposeMatrix3(const Matrix3& a); +void TransposeMat3(Mat3& r, const Mat3& a); +Mat3 TransposeMat3(const Mat3& a); -void InvertAffineMatrix3(Matrix3& r, const Matrix3& a); -Matrix3 InvertAffineMatrix3(const Matrix3& a); +void InvertAffineMat3(Mat3& r, const Mat3& a); +Mat3 InvertAffineMat3(const Mat3& a); -void InvertGeneralMatrix3(Matrix3& r, const Matrix3& a); -Matrix3 InvertGeneralMatrix3(const Matrix3& a); +void InvertGeneralMat3(Mat3& r, const Mat3& a); +Mat3 InvertGeneralMat3(const Mat3& a); -void MulMatrix3(Matrix3& r, const Matrix3& a, const Matrix3& b); -Matrix3 MulMatrix3(const Matrix3& a, const Matrix3& b); +void MulMat3(Mat3& r, const Mat3& a, const Mat3& b); +Mat3 MulMat3(const Mat3& a, const Mat3& b); -void MulMatrix3ByTransposedMatrix3(Matrix3& r, const Matrix3& a, const Matrix3& b); -Matrix3 MulMatrix3ByTransposedMatrix3(const Matrix3& a, const Matrix3& b); +void MulMat3ByTransposedMat3(Mat3& r, const Mat3& a, const Mat3& b); +Mat3 MulMat3ByTransposedMat3(const Mat3& a, const Mat3& b); -void MulVector3ByMatrix3(Vector3& r, const Vector3& v, const Matrix3& a); -Vector3 MulVector3ByMatrix3(const Vector3& v, const Matrix3& a); +void MulVec3ByMat3(Vec3& r, const Vec3& v, const Mat3& a); +Vec3 MulVec3ByMat3(const Vec3& v, const Mat3& a); //---------------------------------------------------------------------------------------- -slInline void SetMatrix3(Matrix3& r, const Matrix3& a) +slInline void SetMat3(Mat3& r, const Mat3& a) { r.v[0] = a.v[0]; r.v[1] = a.v[1]; @@ -58,7 +58,7 @@ slInline void SetMatrix3(Matrix3& r, const Matrix3& a) } //---------------------------------------------------------------------------------------- -slInline void SetMatrix3(Matrix3& r, const Vector3& v0, const Vector3& v1, const Vector3& v2) +slInline void SetMat3(Mat3& r, const Vec3& v0, const Vec3& v1, const Vec3& v2) { r.v[0] = v0; r.v[1] = v1; @@ -66,25 +66,25 @@ slInline void SetMatrix3(Matrix3& r, const Vector3& v0, const Vector3& v1, const } //---------------------------------------------------------------------------------------- -slInline void ScaleMatrix3(Matrix3& r, const float s, const Matrix3& a) +slInline void ScaleMat3(Mat3& r, const float s, const Mat3& a) { - ScaleVector3(r.v[0], s, a.v[0]); - ScaleVector3(r.v[1], s, a.v[1]); - ScaleVector3(r.v[2], s, a.v[2]); + ScaleVec3(r.v[0], s, a.v[0]); + ScaleVec3(r.v[1], s, a.v[1]); + ScaleVec3(r.v[2], s, a.v[2]); } //---------------------------------------------------------------------------------------- -slInline Matrix3 ScaleMatrix3(const float s, const Matrix3& a) +slInline Mat3 ScaleMat3(const float s, const Mat3& a) { - Matrix3 r; - ScaleVector3(r.v[0], s, a.v[0]); - ScaleVector3(r.v[1], s, a.v[1]); - ScaleVector3(r.v[2], s, a.v[2]); + Mat3 r; + ScaleVec3(r.v[0], s, a.v[0]); + ScaleVec3(r.v[1], s, a.v[1]); + ScaleVec3(r.v[2], s, a.v[2]); return r; } //---------------------------------------------------------------------------------------- -slInline float DeterminantOfMatrix3(const Matrix3& a) +slInline float DeterminantOfMat3(const Mat3& a) { return a.v[0].x * (a.v[1].y * a.v[2].z - a.v[1].z * a.v[2].y) + a.v[0].y * (a.v[1].z * a.v[2].x - a.v[1].x * a.v[2].z) @@ -92,7 +92,7 @@ slInline float DeterminantOfMatrix3(const Matrix3& a) } //---------------------------------------------------------------------------------------- -slInline void TransposeMatrix3(Matrix3& r, const Matrix3& a) +slInline void TransposeMat3(Mat3& r, const Mat3& a) { // a might be the same as r r.v[0].x = a.v[0].x; @@ -114,9 +114,9 @@ slInline void TransposeMatrix3(Matrix3& r, const Matrix3& a) } //---------------------------------------------------------------------------------------- -slInline Matrix3 TransposeMatrix3(const Matrix3& a) +slInline Mat3 TransposeMat3(const Mat3& a) { - Matrix3 r; + Mat3 r; r.v[0].x = a.v[0].x; r.v[0].y = a.v[1].x; r.v[0].z = a.v[2].x; r.v[1].x = a.v[0].y; r.v[1].y = a.v[1].y; r.v[1].z = a.v[2].y; r.v[2].x = a.v[0].z; r.v[2].y = a.v[1].z; r.v[2].z = a.v[2].z; @@ -124,139 +124,139 @@ slInline Matrix3 TransposeMatrix3(const Matrix3& a) } //---------------------------------------------------------------------------------------- -slInline void InvertAffineMatrix3(Matrix3& r, const Matrix3& a) +slInline void InvertAffineMat3(Mat3& r, const Mat3& a) { - TransposeMatrix3(r, a); + TransposeMat3(r, a); } //---------------------------------------------------------------------------------------- -slInline Matrix3 InvertAffineMatrix3(const Matrix3& a) +slInline Mat3 InvertAffineMat3(const Mat3& a) { - return TransposeMatrix3(a); + return TransposeMat3(a); } //---------------------------------------------------------------------------------------- -slInline void InvertGeneralMatrix3(Matrix3& r, const Matrix3& a) +slInline void InvertGeneralMat3(Mat3& r, const Mat3& a) { - float inv_determinant = 1.0f / DeterminantOfMatrix3(a); + float inv_determinant = 1.0f / DeterminantOfMat3(a); - Matrix3 a_T; - TransposeMatrix3(a_T, a); - CrossVector3(r.v[0], a_T.v[1], a_T.v[2]); - CrossVector3(r.v[1], a_T.v[2], a_T.v[0]); - CrossVector3(r.v[2], a_T.v[0], a_T.v[1]); + Mat3 a_T; + TransposeMat3(a_T, a); + CrossVec3(r.v[0], a_T.v[1], a_T.v[2]); + CrossVec3(r.v[1], a_T.v[2], a_T.v[0]); + CrossVec3(r.v[2], a_T.v[0], a_T.v[1]); - ScaleMatrix3(r, inv_determinant, r); + ScaleMat3(r, inv_determinant, r); } //---------------------------------------------------------------------------------------- -slInline Matrix3 InvertGeneralMatrix3(const Matrix3& a) +slInline Mat3 InvertGeneralMat3(const Mat3& a) { - float inv_determinant = 1.0f / DeterminantOfMatrix3(a); + float inv_determinant = 1.0f / DeterminantOfMat3(a); - Matrix3 r; - Matrix3 a_T = TransposeMatrix3(a); - CrossVector3(r.v[0], a_T.v[1], a_T.v[2]); - CrossVector3(r.v[1], a_T.v[2], a_T.v[0]); - CrossVector3(r.v[2], a_T.v[0], a_T.v[1]); + Mat3 r; + Mat3 a_T = TransposeMat3(a); + CrossVec3(r.v[0], a_T.v[1], a_T.v[2]); + CrossVec3(r.v[1], a_T.v[2], a_T.v[0]); + CrossVec3(r.v[2], a_T.v[0], a_T.v[1]); - return ScaleMatrix3(inv_determinant, r); + return ScaleMat3(inv_determinant, r); } //---------------------------------------------------------------------------------------- -slInline void MulMatrix3(Matrix3& r, const Matrix3& a, const Matrix3& b) +slInline void MulMat3(Mat3& r, const Mat3& a, const Mat3& b) { - Matrix3 temp; + Mat3 temp; - temp.v[0].x = DotVector3(a.v[0], b.v[0].x, b.v[1].x, b.v[2].x); - temp.v[0].y = DotVector3(a.v[0], b.v[0].y, b.v[1].y, b.v[2].y); - temp.v[0].z = DotVector3(a.v[0], b.v[0].z, b.v[1].z, b.v[2].z); + temp.v[0].x = DotVec3(a.v[0], b.v[0].x, b.v[1].x, b.v[2].x); + temp.v[0].y = DotVec3(a.v[0], b.v[0].y, b.v[1].y, b.v[2].y); + temp.v[0].z = DotVec3(a.v[0], b.v[0].z, b.v[1].z, b.v[2].z); - temp.v[1].x = DotVector3(a.v[1], b.v[0].x, b.v[1].x, b.v[2].x); - temp.v[1].y = DotVector3(a.v[1], b.v[0].y, b.v[1].y, b.v[2].y); - temp.v[1].z = DotVector3(a.v[1], b.v[0].z, b.v[1].z, b.v[2].z); + temp.v[1].x = DotVec3(a.v[1], b.v[0].x, b.v[1].x, b.v[2].x); + temp.v[1].y = DotVec3(a.v[1], b.v[0].y, b.v[1].y, b.v[2].y); + temp.v[1].z = DotVec3(a.v[1], b.v[0].z, b.v[1].z, b.v[2].z); - temp.v[2].x = DotVector3(a.v[2], b.v[0].x, b.v[1].x, b.v[2].x); - temp.v[2].y = DotVector3(a.v[2], b.v[0].y, b.v[1].y, b.v[2].y); - temp.v[2].z = DotVector3(a.v[2], b.v[0].z, b.v[1].z, b.v[2].z); + temp.v[2].x = DotVec3(a.v[2], b.v[0].x, b.v[1].x, b.v[2].x); + temp.v[2].y = DotVec3(a.v[2], b.v[0].y, b.v[1].y, b.v[2].y); + temp.v[2].z = DotVec3(a.v[2], b.v[0].z, b.v[1].z, b.v[2].z); - SetMatrix3(r, temp); + SetMat3(r, temp); } //---------------------------------------------------------------------------------------- -slInline Matrix3 MulMatrix3(const Matrix3& a, const Matrix3& b) +slInline Mat3 MulMat3(const Mat3& a, const Mat3& b) { - Matrix3 r; + Mat3 r; - r.v[0].x = DotVector3(a.v[0], b.v[0].x, b.v[1].x, b.v[2].x); - r.v[0].y = DotVector3(a.v[0], b.v[0].y, b.v[1].y, b.v[2].y); - r.v[0].z = DotVector3(a.v[0], b.v[0].z, b.v[1].z, b.v[2].z); + r.v[0].x = DotVec3(a.v[0], b.v[0].x, b.v[1].x, b.v[2].x); + r.v[0].y = DotVec3(a.v[0], b.v[0].y, b.v[1].y, b.v[2].y); + r.v[0].z = DotVec3(a.v[0], b.v[0].z, b.v[1].z, b.v[2].z); - r.v[1].x = DotVector3(a.v[1], b.v[0].x, b.v[1].x, b.v[2].x); - r.v[1].y = DotVector3(a.v[1], b.v[0].y, b.v[1].y, b.v[2].y); - r.v[1].z = DotVector3(a.v[1], b.v[0].z, b.v[1].z, b.v[2].z); + r.v[1].x = DotVec3(a.v[1], b.v[0].x, b.v[1].x, b.v[2].x); + r.v[1].y = DotVec3(a.v[1], b.v[0].y, b.v[1].y, b.v[2].y); + r.v[1].z = DotVec3(a.v[1], b.v[0].z, b.v[1].z, b.v[2].z); - r.v[2].x = DotVector3(a.v[2], b.v[0].x, b.v[1].x, b.v[2].x); - r.v[2].y = DotVector3(a.v[2], b.v[0].y, b.v[1].y, b.v[2].y); - r.v[2].z = DotVector3(a.v[2], b.v[0].z, b.v[1].z, b.v[2].z); + r.v[2].x = DotVec3(a.v[2], b.v[0].x, b.v[1].x, b.v[2].x); + r.v[2].y = DotVec3(a.v[2], b.v[0].y, b.v[1].y, b.v[2].y); + r.v[2].z = DotVec3(a.v[2], b.v[0].z, b.v[1].z, b.v[2].z); return r; } //---------------------------------------------------------------------------------------- -slInline void MulMatrix3ByTransposedMatrix3(Matrix3& r, const Matrix3& a, const Matrix3& b) +slInline void MulMat3ByTransposedMat3(Mat3& r, const Mat3& a, const Mat3& b) { - Matrix3 temp; + Mat3 temp; - temp.v[0].x = DotVector3(a.v[0], b.v[0]); - temp.v[0].y = DotVector3(a.v[0], b.v[1]); - temp.v[0].z = DotVector3(a.v[0], b.v[2]); + temp.v[0].x = DotVec3(a.v[0], b.v[0]); + temp.v[0].y = DotVec3(a.v[0], b.v[1]); + temp.v[0].z = DotVec3(a.v[0], b.v[2]); - temp.v[1].x = DotVector3(a.v[1], b.v[0]); - temp.v[1].y = DotVector3(a.v[1], b.v[1]); - temp.v[1].z = DotVector3(a.v[1], b.v[2]); + temp.v[1].x = DotVec3(a.v[1], b.v[0]); + temp.v[1].y = DotVec3(a.v[1], b.v[1]); + temp.v[1].z = DotVec3(a.v[1], b.v[2]); - temp.v[2].x = DotVector3(a.v[2], b.v[0]); - temp.v[2].y = DotVector3(a.v[2], b.v[1]); - temp.v[2].z = DotVector3(a.v[2], b.v[2]); + temp.v[2].x = DotVec3(a.v[2], b.v[0]); + temp.v[2].y = DotVec3(a.v[2], b.v[1]); + temp.v[2].z = DotVec3(a.v[2], b.v[2]); - SetMatrix3(r, temp); + SetMat3(r, temp); } //---------------------------------------------------------------------------------------- -slInline Matrix3 MulMatrix3ByTransposedMatrix3(const Matrix3& a, const Matrix3& b) +slInline Mat3 MulMat3ByTransposedMat3(const Mat3& a, const Mat3& b) { - Matrix3 r; + Mat3 r; - r.v[0].x = DotVector3(a.v[0], b.v[0]); - r.v[0].y = DotVector3(a.v[0], b.v[1]); - r.v[0].z = DotVector3(a.v[0], b.v[2]); + r.v[0].x = DotVec3(a.v[0], b.v[0]); + r.v[0].y = DotVec3(a.v[0], b.v[1]); + r.v[0].z = DotVec3(a.v[0], b.v[2]); - r.v[1].x = DotVector3(a.v[1], b.v[0]); - r.v[1].y = DotVector3(a.v[1], b.v[1]); - r.v[1].z = DotVector3(a.v[1], b.v[2]); + r.v[1].x = DotVec3(a.v[1], b.v[0]); + r.v[1].y = DotVec3(a.v[1], b.v[1]); + r.v[1].z = DotVec3(a.v[1], b.v[2]); - r.v[2].x = DotVector3(a.v[2], b.v[0]); - r.v[2].y = DotVector3(a.v[2], b.v[1]); - r.v[2].z = DotVector3(a.v[2], b.v[2]); + r.v[2].x = DotVec3(a.v[2], b.v[0]); + r.v[2].y = DotVec3(a.v[2], b.v[1]); + r.v[2].z = DotVec3(a.v[2], b.v[2]); return r; } //---------------------------------------------------------------------------------------- // do NOT pass in components of a as the r vector -slInline void MulVector3ByMatrix3(Vector3& r, const Vector3& v, const Matrix3& a) +slInline void MulVec3ByMat3(Vec3& r, const Vec3& v, const Mat3& a) { float x = v.x * a.v[0].x + v.y * a.v[1].x + v.z * a.v[2].x; float y = v.x * a.v[0].y + v.y * a.v[1].y + v.z * a.v[2].y; float z = v.x * a.v[0].z + v.y * a.v[1].z + v.z * a.v[2].z; - SetVector3(r, x, y, z); + SetVec3(r, x, y, z); } //---------------------------------------------------------------------------------------- -slInline Vector3 MulVector3ByMatrix3(const Vector3& v, const Matrix3& a) +slInline Vec3 MulVec3ByMat3(const Vec3& v, const Mat3& a) { - Vector3 r; + Vec3 r; r.x = v.x * a.v[0].x + v.y * a.v[1].x + v.z * a.v[2].x; r.y = v.x * a.v[0].y + v.y * a.v[1].y + v.z * a.v[2].y; r.z = v.x * a.v[0].z + v.y * a.v[1].z + v.z * a.v[2].z; @@ -266,46 +266,46 @@ slInline Vector3 MulVector3ByMatrix3(const Vector3& v, const Matrix3& a) //---------------------------------------------------------------------------------------- -// Matrix4 +// Mat4 //---------------------------------------------------------------------------------------- -void SetMatrix4(Matrix4& r, const Matrix4& a); -void SetMatrix4(Matrix4& r, const Matrix3& a); -void SetMatrix4(Matrix4& r, const Matrix3& a, const Vector3& position); +void SetMat4(Mat4& r, const Mat4& a); +void SetMat4(Mat4& r, const Mat3& a); +void SetMat4(Mat4& r, const Mat3& a, const Vec3& position); -void ScaleMatrix4(Matrix4& r, const float s, const Matrix4& a); -Matrix4 ScaleMatrix4(const float s, const Matrix4& a); +void ScaleMat4(Mat4& r, const float s, const Mat4& a); +Mat4 ScaleMat4(const float s, const Mat4& a); -float DeterminantOfMatrix4(const Matrix4& a); +float DeterminantOfMat4(const Mat4& a); -void TransposeMatrix4(Matrix4& r, const Matrix4& a); -Matrix4 TransposeMatrix4(const Matrix4& a); +void TransposeMat4(Mat4& r, const Mat4& a); +Mat4 TransposeMat4(const Mat4& a); -void InvertAffineMatrix4(Matrix4& r, const Matrix4& a); -Matrix4 InvertAffineMatrix4(const Matrix4& a); +void InvertAffineMat4(Mat4& r, const Mat4& a); +Mat4 InvertAffineMat4(const Mat4& a); -void InvertGeneralMatrix4(Matrix4& r, const Matrix4& a); -Matrix4 InvertGeneralMatrix4(const Matrix4& a); +void InvertGeneralMat4(Mat4& r, const Mat4& a); +Mat4 InvertGeneralMat4(const Mat4& a); -void MulMatrix4(Matrix4& r, const Matrix4& a, const Matrix4& b); -Matrix4 MulMatrix4(const Matrix4& a, const Matrix4& b); +void MulMat4(Mat4& r, const Mat4& a, const Mat4& b); +Mat4 MulMat4(const Mat4& a, const Mat4& b); -void MulMatrix4ByTransposedMatrix4(Matrix4& r, const Matrix4& a, const Matrix4& t); -Matrix4 MulMatrix4ByTransposedMatrix4(const Matrix4& a, Matrix4& t); +void MulMat4ByTransposedMat4(Mat4& r, const Mat4& a, const Mat4& t); +Mat4 MulMat4ByTransposedMat4(const Mat4& a, Mat4& t); -void MulVector4ByMatrix4(Vector4& r, const Vector4& v, const Matrix4& a); -Vector4 MulVector4ByMatrix4(const Vector4& v, const Matrix4& a); +void MulVec4ByMat4(Vec4& r, const Vec4& v, const Mat4& a); +Vec4 MulVec4ByMat4(const Vec4& v, const Mat4& a); -void MulVector3ByMatrix4(Vector4& r, const Vector3& v, const float w, const Matrix4& a); -Vector4 MulVector3ByMatrix4(const Vector3& v, const float w, const Matrix4& a); +void MulVec3ByMat4(Vec4& r, const Vec3& v, const float w, const Mat4& a); +Vec4 MulVec3ByMat4(const Vec3& v, const float w, const Mat4& a); -void MulVector4ByTransposedMatrix4(Vector4& r, const Vector4& v, const Matrix4& t); -Vector4 MulVector4ByTransposedMatrix4(const Vector4& v, const Matrix4& t); +void MulVec4ByTransposedMat4(Vec4& r, const Vec4& v, const Mat4& t); +Vec4 MulVec4ByTransposedMat4(const Vec4& v, const Mat4& t); -void MulVector3ByTransposedMatrix4(Vector4& r, const Vector3& v, const float w, const Matrix4& t); -Vector4 MulVector3ByTransposedMatrix4(const Vector3& v, const float w, const Matrix4& t); +void MulVec3ByTransposedMat4(Vec4& r, const Vec3& v, const float w, const Mat4& t); +Vec4 MulVec3ByTransposedMat4(const Vec3& v, const float w, const Mat4& t); //---------------------------------------------------------------------------------------- -slInline void SetMatrix4(Matrix4& r, const Matrix4& a) +slInline void SetMat4(Mat4& r, const Mat4& a) { r.v[0] = a.v[0]; r.v[1] = a.v[1]; @@ -314,54 +314,54 @@ slInline void SetMatrix4(Matrix4& r, const Matrix4& a) } //---------------------------------------------------------------------------------------- -slInline void SetMatrix4(Matrix4& r, const Matrix3& a) +slInline void SetMat4(Mat4& r, const Mat3& a) { - SetVector4(r.v[0], a.v[0], 0.0f); - SetVector4(r.v[1], a.v[1], 0.0f); - SetVector4(r.v[2], a.v[2], 0.0f); - SetVector4(r.v[3], 0.0f, 0.0f, 0.0f, 1.0f); + SetVec4(r.v[0], a.v[0], 0.0f); + SetVec4(r.v[1], a.v[1], 0.0f); + SetVec4(r.v[2], a.v[2], 0.0f); + SetVec4(r.v[3], 0.0f, 0.0f, 0.0f, 1.0f); } //---------------------------------------------------------------------------------------- -slInline void SetMatrix4(Matrix4& r, const Matrix3& a, const Vector3& position) +slInline void SetMat4(Mat4& r, const Mat3& a, const Vec3& position) { - SetVector4(r.v[0], a.v[0], 0.0f); - SetVector4(r.v[1], a.v[1], 0.0f); - SetVector4(r.v[2], a.v[2], 0.0f); - SetVector4(r.v[3], position, 1.0f); + SetVec4(r.v[0], a.v[0], 0.0f); + SetVec4(r.v[1], a.v[1], 0.0f); + SetVec4(r.v[2], a.v[2], 0.0f); + SetVec4(r.v[3], position, 1.0f); } //---------------------------------------------------------------------------------------- -slInline void ScaleMatrix4(Matrix4& r, const float s, const Matrix4& a) +slInline void ScaleMat4(Mat4& r, const float s, const Mat4& a) { - ScaleVector4(r.v[0], s, a.v[0]); - ScaleVector4(r.v[1], s, a.v[1]); - ScaleVector4(r.v[2], s, a.v[2]); - ScaleVector4(r.v[3], s, a.v[3]); + ScaleVec4(r.v[0], s, a.v[0]); + ScaleVec4(r.v[1], s, a.v[1]); + ScaleVec4(r.v[2], s, a.v[2]); + ScaleVec4(r.v[3], s, a.v[3]); } //---------------------------------------------------------------------------------------- -slInline Matrix4 ScaleMatrix4(const float s, const Matrix4& a) +slInline Mat4 ScaleMat4(const float s, const Mat4& a) { - Matrix4 r; - ScaleVector4(r.v[0], s, a.v[0]); - ScaleVector4(r.v[1], s, a.v[1]); - ScaleVector4(r.v[2], s, a.v[2]); - ScaleVector4(r.v[3], s, a.v[3]); + Mat4 r; + ScaleVec4(r.v[0], s, a.v[0]); + ScaleVec4(r.v[1], s, a.v[1]); + ScaleVec4(r.v[2], s, a.v[2]); + ScaleVec4(r.v[3], s, a.v[3]); return r; } //---------------------------------------------------------------------------------------- -slInline float DeterminantOfMatrix4(const Matrix4& a) +slInline float DeterminantOfMat4(const Mat4& a) { // is this correct? - Vector4 cross_product; - CrossVector4(cross_product, a.v[1], a.v[2], a.v[3]); - return DotVector4(a.v[0], cross_product); + Vec4 cross_product; + CrossVec4(cross_product, a.v[1], a.v[2], a.v[3]); + return DotVec4(a.v[0], cross_product); } //---------------------------------------------------------------------------------------- -slInline void TransposeMatrix4(Matrix4& r, const Matrix4& a) +slInline void TransposeMat4(Mat4& r, const Mat4& a) { // a might be the same as r r.v[0].x = a.v[0].x; @@ -396,9 +396,9 @@ slInline void TransposeMatrix4(Matrix4& r, const Matrix4& a) } //---------------------------------------------------------------------------------------- -slInline Matrix4 TransposeMatrix4(const Matrix4& a) +slInline Mat4 TransposeMat4(const Mat4& a) { - Matrix4 r; + Mat4 r; r.v[0].x = a.v[0].x; r.v[0].y = a.v[1].x; r.v[0].z = a.v[2].x; r.v[0].w = a.v[3].x; r.v[1].x = a.v[0].y; r.v[1].y = a.v[1].y; r.v[1].z = a.v[2].y; r.v[1].w = a.v[3].y; r.v[2].x = a.v[0].z; r.v[2].y = a.v[1].z; r.v[2].z = a.v[2].z; r.v[2].w = a.v[3].z; @@ -407,254 +407,254 @@ slInline Matrix4 TransposeMatrix4(const Matrix4& a) } //---------------------------------------------------------------------------------------- -slInline void InvertAffineMatrix4(Matrix4& r, const Matrix4& a) +slInline void InvertAffineMat4(Mat4& r, const Mat4& a) { // this may not be correct... - Matrix3 a3_T(a.v[0].AsVector3(), a.v[1].AsVector3(), a.v[2].AsVector3()); - InvertAffineMatrix3(a3_T, a3_T); + Mat3 a3_T(a.v[0].AsVec3(), a.v[1].AsVec3(), a.v[2].AsVec3()); + InvertAffineMat3(a3_T, a3_T); - Vector3 transpose; - MulVector3ByMatrix3(transpose, a.v[3].AsVector3(), a3_T); + Vec3 transpose; + MulVec3ByMat3(transpose, a.v[3].AsVec3(), a3_T); - SetMatrix4(r, a3_T, transpose); + SetMat4(r, a3_T, transpose); } //---------------------------------------------------------------------------------------- -slInline Matrix4 InvertAffineMatrix4(const Matrix4& a) +slInline Mat4 InvertAffineMat4(const Mat4& a) { - Matrix4 r; + Mat4 r; // this may not be correct... - Matrix3 a3_T(a.v[0].AsVector3(), a.v[1].AsVector3(), a.v[2].AsVector3()); - InvertAffineMatrix3(a3_T, a3_T); + Mat3 a3_T(a.v[0].AsVec3(), a.v[1].AsVec3(), a.v[2].AsVec3()); + InvertAffineMat3(a3_T, a3_T); - Vector3 transpose; - MulVector3ByMatrix3(transpose, a.v[3].AsVector3(), a3_T); + Vec3 transpose; + MulVec3ByMat3(transpose, a.v[3].AsVec3(), a3_T); - SetMatrix4(r, a3_T, transpose); + SetMat4(r, a3_T, transpose); return r; } //---------------------------------------------------------------------------------------- -slInline void InvertGeneralMatrix4(Matrix4& r, const Matrix4& a) +slInline void InvertGeneralMat4(Mat4& r, const Mat4& a) { // does this work? - float inv_determinant = 1.0f / DeterminantOfMatrix4(a); + float inv_determinant = 1.0f / DeterminantOfMat4(a); - Matrix4 a_T; - TransposeMatrix4(a_T, a); - CrossVector4(r.v[0], a_T.v[1], a_T.v[2], a_T.v[3]); - CrossVector4(r.v[1], a_T.v[2], a_T.v[3], a_T.v[0]); - CrossVector4(r.v[2], a_T.v[3], a_T.v[0], a_T.v[1]); - CrossVector4(r.v[3], a_T.v[0], a_T.v[1], a_T.v[2]); + Mat4 a_T; + TransposeMat4(a_T, a); + CrossVec4(r.v[0], a_T.v[1], a_T.v[2], a_T.v[3]); + CrossVec4(r.v[1], a_T.v[2], a_T.v[3], a_T.v[0]); + CrossVec4(r.v[2], a_T.v[3], a_T.v[0], a_T.v[1]); + CrossVec4(r.v[3], a_T.v[0], a_T.v[1], a_T.v[2]); - ScaleMatrix4(r, inv_determinant, r); + ScaleMat4(r, inv_determinant, r); } //---------------------------------------------------------------------------------------- -slInline Matrix4 InvertGeneralMatrix4(const Matrix4& a) +slInline Mat4 InvertGeneralMat4(const Mat4& a) { // does this work? - Matrix4 r; - float inv_determinant = 1.0f / DeterminantOfMatrix4(a); + Mat4 r; + float inv_determinant = 1.0f / DeterminantOfMat4(a); - Matrix4 a_T; - TransposeMatrix4(a_T, a); - r.v[0] = CrossVector4(a_T.v[1], a_T.v[2], a_T.v[3]); - r.v[1] = CrossVector4(a_T.v[2], a_T.v[3], a_T.v[0]); - r.v[2] = CrossVector4(a_T.v[3], a_T.v[0], a_T.v[1]); - r.v[3] = CrossVector4(a_T.v[0], a_T.v[1], a_T.v[2]); + Mat4 a_T; + TransposeMat4(a_T, a); + r.v[0] = CrossVec4(a_T.v[1], a_T.v[2], a_T.v[3]); + r.v[1] = CrossVec4(a_T.v[2], a_T.v[3], a_T.v[0]); + r.v[2] = CrossVec4(a_T.v[3], a_T.v[0], a_T.v[1]); + r.v[3] = CrossVec4(a_T.v[0], a_T.v[1], a_T.v[2]); - return ScaleMatrix4(inv_determinant, r); + return ScaleMat4(inv_determinant, r); } //---------------------------------------------------------------------------------------- -slInline void MulMatrix4(Matrix4& r, const Matrix4& a, const Matrix4& b) +slInline void MulMat4(Mat4& r, const Mat4& a, const Mat4& b) { - Matrix4 temp; + Mat4 temp; - temp.v[0].x = DotVector4(a.v[0], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x); - temp.v[0].y = DotVector4(a.v[0], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y); - temp.v[0].z = DotVector4(a.v[0], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z); - temp.v[0].w = DotVector4(a.v[0], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w); + temp.v[0].x = DotVec4(a.v[0], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x); + temp.v[0].y = DotVec4(a.v[0], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y); + temp.v[0].z = DotVec4(a.v[0], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z); + temp.v[0].w = DotVec4(a.v[0], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w); - temp.v[1].x = DotVector4(a.v[1], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x); - temp.v[1].y = DotVector4(a.v[1], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y); - temp.v[1].z = DotVector4(a.v[1], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z); - temp.v[1].w = DotVector4(a.v[1], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w); + temp.v[1].x = DotVec4(a.v[1], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x); + temp.v[1].y = DotVec4(a.v[1], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y); + temp.v[1].z = DotVec4(a.v[1], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z); + temp.v[1].w = DotVec4(a.v[1], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w); - temp.v[2].x = DotVector4(a.v[2], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x); - temp.v[2].y = DotVector4(a.v[2], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y); - temp.v[2].z = DotVector4(a.v[2], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z); - temp.v[2].w = DotVector4(a.v[2], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w); + temp.v[2].x = DotVec4(a.v[2], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x); + temp.v[2].y = DotVec4(a.v[2], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y); + temp.v[2].z = DotVec4(a.v[2], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z); + temp.v[2].w = DotVec4(a.v[2], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w); - temp.v[3].x = DotVector4(a.v[3], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x); - temp.v[3].y = DotVector4(a.v[3], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y); - temp.v[3].z = DotVector4(a.v[3], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z); - temp.v[3].w = DotVector4(a.v[3], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w); + temp.v[3].x = DotVec4(a.v[3], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x); + temp.v[3].y = DotVec4(a.v[3], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y); + temp.v[3].z = DotVec4(a.v[3], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z); + temp.v[3].w = DotVec4(a.v[3], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w); - SetMatrix4(r, temp); + SetMat4(r, temp); } //---------------------------------------------------------------------------------------- -slInline Matrix4 MulMatrix4(const Matrix4& a, const Matrix4& b) +slInline Mat4 MulMat4(const Mat4& a, const Mat4& b) { - Matrix4 r; + Mat4 r; - r.v[0].x = DotVector4(a.v[0], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x); - r.v[0].y = DotVector4(a.v[0], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y); - r.v[0].z = DotVector4(a.v[0], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z); - r.v[0].w = DotVector4(a.v[0], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w); + r.v[0].x = DotVec4(a.v[0], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x); + r.v[0].y = DotVec4(a.v[0], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y); + r.v[0].z = DotVec4(a.v[0], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z); + r.v[0].w = DotVec4(a.v[0], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w); - r.v[1].x = DotVector4(a.v[1], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x); - r.v[1].y = DotVector4(a.v[1], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y); - r.v[1].z = DotVector4(a.v[1], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z); - r.v[1].w = DotVector4(a.v[1], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w); + r.v[1].x = DotVec4(a.v[1], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x); + r.v[1].y = DotVec4(a.v[1], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y); + r.v[1].z = DotVec4(a.v[1], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z); + r.v[1].w = DotVec4(a.v[1], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w); - r.v[2].x = DotVector4(a.v[2], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x); - r.v[2].y = DotVector4(a.v[2], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y); - r.v[2].z = DotVector4(a.v[2], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z); - r.v[2].w = DotVector4(a.v[2], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w); + r.v[2].x = DotVec4(a.v[2], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x); + r.v[2].y = DotVec4(a.v[2], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y); + r.v[2].z = DotVec4(a.v[2], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z); + r.v[2].w = DotVec4(a.v[2], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w); - r.v[3].x = DotVector4(a.v[3], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x); - r.v[3].y = DotVector4(a.v[3], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y); - r.v[3].z = DotVector4(a.v[3], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z); - r.v[3].w = DotVector4(a.v[3], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w); + r.v[3].x = DotVec4(a.v[3], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x); + r.v[3].y = DotVec4(a.v[3], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y); + r.v[3].z = DotVec4(a.v[3], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z); + r.v[3].w = DotVec4(a.v[3], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w); return r; } //---------------------------------------------------------------------------------------- -slInline void MulMatrix4ByTransposedMatrix4(Matrix4& r, const Matrix4& a, const Matrix4& t) +slInline void MulMat4ByTransposedMat4(Mat4& r, const Mat4& a, const Mat4& t) { - Matrix4 temp; + Mat4 temp; - temp.v[0].x = DotVector4(a.v[0], b.v[0]); - temp.v[0].y = DotVector4(a.v[0], b.v[1]); - temp.v[0].z = DotVector4(a.v[0], b.v[2]); - temp.v[0].w = DotVector4(a.v[0], b.v[3]); + temp.v[0].x = DotVec4(a.v[0], t.v[0]); + temp.v[0].y = DotVec4(a.v[0], t.v[1]); + temp.v[0].z = DotVec4(a.v[0], t.v[2]); + temp.v[0].w = DotVec4(a.v[0], t.v[3]); - temp.v[1].x = DotVector4(a.v[1], b.v[0]); - temp.v[1].y = DotVector4(a.v[1], b.v[1]); - temp.v[1].z = DotVector4(a.v[1], b.v[2]); - temp.v[1].w = DotVector4(a.v[1], b.v[3]); + temp.v[1].x = DotVec4(a.v[1], t.v[0]); + temp.v[1].y = DotVec4(a.v[1], t.v[1]); + temp.v[1].z = DotVec4(a.v[1], t.v[2]); + temp.v[1].w = DotVec4(a.v[1], t.v[3]); - temp.v[2].x = DotVector4(a.v[2], b.v[0]); - temp.v[2].y = DotVector4(a.v[2], b.v[1]); - temp.v[2].z = DotVector4(a.v[2], b.v[2]); - temp.v[2].w = DotVector4(a.v[2], b.v[3]); + temp.v[2].x = DotVec4(a.v[2], t.v[0]); + temp.v[2].y = DotVec4(a.v[2], t.v[1]); + temp.v[2].z = DotVec4(a.v[2], t.v[2]); + temp.v[2].w = DotVec4(a.v[2], t.v[3]); - temp.v[3].x = DotVector4(a.v[3], b.v[0]); - temp.v[3].y = DotVector4(a.v[3], b.v[1]); - temp.v[3].z = DotVector4(a.v[3], b.v[2]); - temp.v[3].w = DotVector4(a.v[3], b.v[3]); + temp.v[3].x = DotVec4(a.v[3], t.v[0]); + temp.v[3].y = DotVec4(a.v[3], t.v[1]); + temp.v[3].z = DotVec4(a.v[3], t.v[2]); + temp.v[3].w = DotVec4(a.v[3], t.v[3]); - SetMatrix4(r, temp); + SetMat4(r, temp); } //---------------------------------------------------------------------------------------- -slInline Matrix4 MulMatrix4ByTransposedMatrix4(const Matrix4& a, const Matrix4& t) +slInline Mat4 MulMat4ByTransposedMat4(const Mat4& a, const Mat4& t) { - Matrix4 r; + Mat4 r; - r.v[0].x = DotVector4(a.v[0], b.v[0]); - r.v[0].y = DotVector4(a.v[0], b.v[1]); - r.v[0].z = DotVector4(a.v[0], b.v[2]); - r.v[0].w = DotVector4(a.v[0], b.v[3]); + r.v[0].x = DotVec4(a.v[0], t.v[0]); + r.v[0].y = DotVec4(a.v[0], t.v[1]); + r.v[0].z = DotVec4(a.v[0], t.v[2]); + r.v[0].w = DotVec4(a.v[0], t.v[3]); - r.v[1].x = DotVector4(a.v[1], b.v[0]); - r.v[1].y = DotVector4(a.v[1], b.v[1]); - r.v[1].z = DotVector4(a.v[1], b.v[2]); - r.v[1].w = DotVector4(a.v[1], b.v[3]); + r.v[1].x = DotVec4(a.v[1], t.v[0]); + r.v[1].y = DotVec4(a.v[1], t.v[1]); + r.v[1].z = DotVec4(a.v[1], t.v[2]); + r.v[1].w = DotVec4(a.v[1], t.v[3]); - r.v[2].x = DotVector4(a.v[2], b.v[0]); - r.v[2].y = DotVector4(a.v[2], b.v[1]); - r.v[2].z = DotVector4(a.v[2], b.v[2]); - r.v[2].w = DotVector4(a.v[2], b.v[3]); + r.v[2].x = DotVec4(a.v[2], t.v[0]); + r.v[2].y = DotVec4(a.v[2], t.v[1]); + r.v[2].z = DotVec4(a.v[2], t.v[2]); + r.v[2].w = DotVec4(a.v[2], t.v[3]); - r.v[3].x = DotVector4(a.v[3], b.v[0]); - r.v[3].y = DotVector4(a.v[3], b.v[1]); - r.v[3].z = DotVector4(a.v[3], b.v[2]); - r.v[3].w = DotVector4(a.v[3], b.v[3]); + r.v[3].x = DotVec4(a.v[3], t.v[0]); + r.v[3].y = DotVec4(a.v[3], t.v[1]); + r.v[3].z = DotVec4(a.v[3], t.v[2]); + r.v[3].w = DotVec4(a.v[3], t.v[3]); return r; } //---------------------------------------------------------------------------------------- -slInline void MulVector4ByMatrix4(Vector4& r, const Vector4& v, const Matrix4& a) +slInline void MulVec4ByMat4(Vec4& r, const Vec4& v, const Mat4& a) { - Vector4 result; - ScaleVector4(result, v.x, a.v[0]); - ScaleAddVector4(result, v.y, a.v[1], result); - ScaleAddVector4(result, v.z, a.v[2], result); - ScaleAddVector4(result, v.w, a.v[3], result); - SetVector4(r, result); + Vec4 result; + ScaleVec4(result, v.x, a.v[0]); + ScaleAddVec4(result, v.y, a.v[1], result); + ScaleAddVec4(result, v.z, a.v[2], result); + ScaleAddVec4(result, v.w, a.v[3], result); + SetVec4(r, result); } //---------------------------------------------------------------------------------------- -slInline Vector4 MulVector4ByMatrix4(const Vector4& v, const Matrix4& a) +slInline Vec4 MulVec4ByMat4(const Vec4& v, const Mat4& a) { - Vector4 r; - ScaleVector4(r, v.x, a.v[0]); - ScaleAddVector4(r, v.y, a.v[1], r); - ScaleAddVector4(r, v.z, a.v[2], r); - ScaleAddVector4(r, v.w, a.v[3], r); + Vec4 r; + ScaleVec4(r, v.x, a.v[0]); + ScaleAddVec4(r, v.y, a.v[1], r); + ScaleAddVec4(r, v.z, a.v[2], r); + ScaleAddVec4(r, v.w, a.v[3], r); return r; } //---------------------------------------------------------------------------------------- -slInline void MulVector3ByMatrix4(Vector4& r, const Vector3& v, const float iw, const Matrix4& a) +slInline void MulVec3ByMat4(Vec4& r, const Vec3& v, const float iw, const Mat4& a) { - Vector4 result; - ScaleVector4(result, v.x, a.v[0]); - ScaleAddVector4(result, v.y, a.v[1], result); - ScaleAddVector4(result, v.z, a.v[2], result); - ScaleAddVector4(result, iw, a.v[3], result); - SetVector4(r, result); + Vec4 result; + ScaleVec4(result, v.x, a.v[0]); + ScaleAddVec4(result, v.y, a.v[1], result); + ScaleAddVec4(result, v.z, a.v[2], result); + ScaleAddVec4(result, iw, a.v[3], result); + SetVec4(r, result); } //---------------------------------------------------------------------------------------- -slInline Vector4 MulVector3ByMatrix4(const Vector3& v, const float iw, const Matrix4& a) +slInline Vec4 MulVec3ByMat4(const Vec3& v, const float iw, const Mat4& a) { - Vector4 r; - ScaleVector4(r, v.x, a.v[0]); - ScaleAddVector4(r, v.y, a.v[1], r); - ScaleAddVector4(r, v.z, a.v[2], r); - ScaleAddVector4(r, iw, a.v[3], r); + Vec4 r; + ScaleVec4(r, v.x, a.v[0]); + ScaleAddVec4(r, v.y, a.v[1], r); + ScaleAddVec4(r, v.z, a.v[2], r); + ScaleAddVec4(r, iw, a.v[3], r); return r; } //---------------------------------------------------------------------------------------- -slInline void MulVector4ByTransposedMatrix4(Vector4& r, const Vector4& v, const Matrix4& t) +slInline void MulVec4ByTransposedMat4(Vec4& r, const Vec4& v, const Mat4& t) { - float x = DotVector4(v, t.v[0]); - float y = DotVector4(v, t.v[1]); - float z = DotVector4(v, t.v[2]); - float w = DotVector4(v, t.v[3]); - SetVector4(r, x, y, z, w); + float x = DotVec4(v, t.v[0]); + float y = DotVec4(v, t.v[1]); + float z = DotVec4(v, t.v[2]); + float w = DotVec4(v, t.v[3]); + SetVec4(r, x, y, z, w); } //---------------------------------------------------------------------------------------- -slInline Vector4 MulVector4ByTransposedMatrix4(const Vector4& v, const Matrix4& t) +slInline Vec4 MulVec4ByTransposedMat4(const Vec4& v, const Mat4& t) { - Vector4 r; - r.x = DotVector4(v, t.v[0]); - r.y = DotVector4(v, t.v[1]); - r.z = DotVector4(v, t.v[2]); - r.w = DotVector4(v, t.v[3]); + Vec4 r; + r.x = DotVec4(v, t.v[0]); + r.y = DotVec4(v, t.v[1]); + r.z = DotVec4(v, t.v[2]); + r.w = DotVec4(v, t.v[3]); return r; } //---------------------------------------------------------------------------------------- -slInline void MulVector3ByTransposedMatrix4(Vector4& r, const Vector3& v, const float w, const Matrix4& t) +slInline void MulVec3ByTransposedMat4(Vec4& r, const Vec3& v, const float w, const Mat4& t) { - Vector4 v_new(v, w); - MulVector4ByTransposedMatrix4(r, v_new, a); + Vec4 v_new(v, w); + MulVec4ByTransposedMat4(r, v_new, t); } //---------------------------------------------------------------------------------------- -slInline Vector4 MulVector3ByTransposedMatrix4(const Vector3& v, const float w, const Matrix4& t) +slInline Vec4 MulVec3ByTransposedMat4(const Vec3& v, const float w, const Mat4& t) { - Vector4 v_as_v4(v, w); - return MulVector4ByTransposedMatrix4(v_as_v4, t); + Vec4 v_as_v4(v, w); + return MulVec4ByTransposedMat4(v_as_v4, t); } diff --git a/Classes/Foundation/Math/Quaternion.h b/Classes/Foundation/Math/Quaternion.h index 8a303db..d9cce5d 100755 --- a/Classes/Foundation/Math/Quaternion.h +++ b/Classes/Foundation/Math/Quaternion.h @@ -1,14 +1,14 @@ #pragma once #include "Foundation/Common/GlobalInclude.h" -#include "Foundation/Common/MathTypes.h" +#include "Foundation/Math/MathTypes.h" #include "Foundation/Math/Vector.h" //---------------------------------------------------------------------------------------- // Quaternion //---------------------------------------------------------------------------------------- void SetQuaternion(Quaternion& r, const float angle, const float x, const float y, const float z); -void SetQuaternion(Quaternion& r, const float angle, const Vector3& rotation_axis); +void SetQuaternion(Quaternion& r, const float angle, const Vec3& rotation_axis); void ScaleQuaternion(Quaternion& r, const float s, const Quaternion& q); void MulQuaternion(Quaternion& r, const Quaternion& p, const Quaternion& q); void ConjugateOfQuaternion(Quaternion& r, const Quaternion& q); @@ -20,29 +20,29 @@ void InverseQuaterion(Quaternion& r, const Quaternion& q); //---------------------------------------------------------------------------------------- void SetQuaternion(Quaternion& r, const float angle, const float x, const float y, const float z) { - Assert( EpsilonEquals(LengthVector3(rotation_axis), 0.0f, kEpsilon) ); + Assert( EpsilonEquals(x*x + y*y + z*z, 0.0f, kSqrtEpsilon) ); float half_angle = angle * 0.5f; - float sin_half_angle = Sinf(half_angle); + float sin_half_angle = (float)Sinf(half_angle); r.i = x * sin_half_angle; r.j = y * sin_half_angle; r.k = z * sin_half_angle; - r.s = Cosf(half_angle); + r.s = (float)Cosf(half_angle); } //---------------------------------------------------------------------------------------- -void SetQuaternion(Quaternion& r, const float angle, const Vector3& rotation_axis) +void SetQuaternion(Quaternion& r, const float angle, const Vec3& rotation_axis) { - Assert( EpsilonEquals(LengthVector3(rotation_axis), 0.0f, kEpsilon) ); + Assert( EpsilonEquals(rotation_axis.x * rotation_axis.x + rotation_axis.y * rotation_axis.y + rotation_axis.z * rotation_axis.z, 0.0f, kSqrtEpsilon) ); float half_angle = angle * 0.5f; - float sin_half_angle = Sinf(half_angle); + float sin_half_angle = (float)Sinf(half_angle); r.i = rotation_axis.x * sin_half_angle; r.j = rotation_axis.y * sin_half_angle; r.k = rotation_axis.z * sin_half_angle; - r.s = Cosf(half_angle); + r.s = (float)Cosf(half_angle); } //---------------------------------------------------------------------------------------- @@ -75,7 +75,7 @@ void ConjugateOfQuaternion(Quaternion& r, const Quaternion& q) //---------------------------------------------------------------------------------------- float NormOfQuaternion(const Quaternion& q) { - return Sqrtf( q.i * q.i + q.j * q.j + q.k * q.k + q.s * q.s); + return (float)Sqrtf( q.i * q.i + q.j * q.j + q.k * q.k + q.s * q.s); } //---------------------------------------------------------------------------------------- @@ -87,7 +87,7 @@ float NormSquaredOfQuaternion(const Quaternion& q) //---------------------------------------------------------------------------------------- void NormalizeQuaternion(Quaternion& r, Quaternion& q) { - float norm_scale = 1.0f / NormQuaternion( q ); + float norm_scale = 1.0f / NormOfQuaternion( q ); ScaleQuaternion( r, norm_scale, q ); } diff --git a/Classes/Foundation/Math/Vector.h b/Classes/Foundation/Math/Vector.h index 3e5e524..91cc817 100755 --- a/Classes/Foundation/Math/Vector.h +++ b/Classes/Foundation/Math/Vector.h @@ -5,407 +5,407 @@ #include "Foundation/Math/MathOperations.h" //---------------------------------------------------------------------------------------- -// Vector2 +// Vec2 //---------------------------------------------------------------------------------------- -void SetVector2(Vector2& r, const Vector2& v); -void SetVector2(Vector2& r, const float x, const float y); -void SetVector2(Vector2& r, const float xy); -void AbsVector2(Vector2& r, const Vector2& v); -float MinComponentVector2(const Vector2& v); -float MaxComponentVector2(const Vector2& v); -uint32_t MinIndexVector2(const Vector2& v); -uint32_t MaxIndexVector2(const Vector2& v); -float DotVector2(const Vector2& a, const Vector2& b); -float DotVector2(const Vector2& a, const float x, const float y); +void SetVec2(Vec2& r, const Vec2& v); +void SetVec2(Vec2& r, const float x, const float y); +void SetVec2(Vec2& r, const float xy); +void AbsVec2(Vec2& r, const Vec2& v); +float MinComponentVec2(const Vec2& v); +float MaxComponentVec2(const Vec2& v); +uint32_t MinIndexVec2(const Vec2& v); +uint32_t MaxIndexVec2(const Vec2& v); +float DotVec2(const Vec2& a, const Vec2& b); +float DotVec2(const Vec2& a, const float x, const float y); -void PerpendicularVector2(Vector2& r, const Vector2& v); -Vector2 PerpendicularVector2(const Vector2& v); +void PerpendicularVec2(Vec2& r, const Vec2& v); +Vec2 PerpendicularVec2(const Vec2& v); -void AddVector2ByScalar(Vector2& r, const float s, const Vector2& v); -Vector2 AddVector2ByScalar(const float s, const Vector2& v); +void AddVec2ByScalar(Vec2& r, const float s, const Vec2& v); +Vec2 AddVec2ByScalar(const float s, const Vec2& v); -void AddVector2(Vector2& r, const Vector2& a, const Vector2& b); -Vector2 AddVector2(const Vector2& a, const Vector2& b); +void AddVec2(Vec2& r, const Vec2& a, const Vec2& b); +Vec2 AddVec2(const Vec2& a, const Vec2& b); -void AddVector2(Vector2& r, const Vector2& a, const float x, const float y); -Vector2 AddVector2(const Vector2& a, const float x, const float y); +void AddVec2(Vec2& r, const Vec2& a, const float x, const float y); +Vec2 AddVec2(const Vec2& a, const float x, const float y); -void SubVector2(Vector2& r, const Vector2& a, const Vector2& b); -Vector2 SubVector2(const Vector2& a, const Vector2& b); +void SubVec2(Vec2& r, const Vec2& a, const Vec2& b); +Vec2 SubVec2(const Vec2& a, const Vec2& b); -void SubVector2(Vector2& r, const Vector2& a, const float x, const float y); -Vector2 SubVector2(const Vector2& a, const float x, const float y); +void SubVec2(Vec2& r, const Vec2& a, const float x, const float y); +Vec2 SubVec2(const Vec2& a, const float x, const float y); -void ScaleVector2(Vector2& r, const float s, const Vector2& v); -Vector2 ScaleVector2(const float s, const Vector2& v); +void ScaleVec2(Vec2& r, const float s, const Vec2& v); +Vec2 ScaleVec2(const float s, const Vec2& v); -void MulVector2(Vector2& r, const Vector2& a, const Vector2& b); -Vector2 MulVector2(const Vector2& a, const Vector2& b); +void MulVec2(Vec2& r, const Vec2& a, const Vec2& b); +Vec2 MulVec2(const Vec2& a, const Vec2& b); -void MulVector2(Vector2& r, const Vector2& a, const float x, const float y); -Vector2 MulVector2(const Vector2& a, const float x, const float y); +void MulVec2(Vec2& r, const Vec2& a, const float x, const float y); +Vec2 MulVec2(const Vec2& a, const float x, const float y); -void DivVector2(Vector2& r, const Vector2& a, const Vector2& b); -Vector2 DivVector2(const Vector2& a, const Vector2& b); +void DivVec2(Vec2& r, const Vec2& a, const Vec2& b); +Vec2 DivVec2(const Vec2& a, const Vec2& b); -void DivVector2(Vector2& r, const Vector2& a, const float x, const float y); -Vector2 DivVector2(const Vector2& a, const float x, const float y); +void DivVec2(Vec2& r, const Vec2& a, const float x, const float y); +Vec2 DivVec2(const Vec2& a, const float x, const float y); -void ScaleAddVector2(Vector2& r, const float s, const Vector2& v_scale, const Vector2& v_add); -Vector2 ScaleAddVector2(const float s, const Vector2& v_scale, const Vector2& v_add); +void ScaleAddVec2(Vec2& r, const float s, const Vec2& v_scale, const Vec2& v_add); +Vec2 ScaleAddVec2(const float s, const Vec2& v_scale, const Vec2& v_add); -void NormalizeVector2(Vector2& r, const Vector2& a); -Vector2 NormalizeVector2(const Vector2& a); +void NormalizeVec2(Vec2& r, const Vec2& a); +Vec2 NormalizeVec2(const Vec2& a); -float LengthOfVector2(const Vector2& a); -float LengthSquaredOfVector2(const Vector2& a); +float LengthOfVec2(const Vec2& a); +float LengthSquaredOfVec2(const Vec2& a); //---------------------------------------------------------------------------------------- -slInline void SetVector2(Vector2& r, const Vector2& v) +slInline void SetVec2(Vec2& r, const Vec2& v) { r.x = v.x; r.y = v.y; } //---------------------------------------------------------------------------------------- -slInline void SetVector2(Vector2& r, const float x, const float y) +slInline void SetVec2(Vec2& r, const float x, const float y) { r.x = x; r.y = y; } //---------------------------------------------------------------------------------------- -slInline void SetVector2(Vector2& r, const float xy) +slInline void SetVec2(Vec2& r, const float xy) { r.x = xy; r.y = xy; } //---------------------------------------------------------------------------------------- -void AbsVector2(Vector2& r, const Vector2& v) +void AbsVec2(Vec2& r, const Vec2& v) { r.x = Absf(v.x); r.y = Absf(v.y); } //---------------------------------------------------------------------------------------- -float MinComponentVector2(const Vector2& v) +float MinComponentVec2(const Vec2& v) { return v.x <= v.y ? v.x : v.y; } //---------------------------------------------------------------------------------------- -float MaxComponentVector2(const Vector2& v) +float MaxComponentVec2(const Vec2& v) { return v.x >= v.y ? v.x : v.y; } //---------------------------------------------------------------------------------------- -uint32_t MinIndexVector2(const Vector2& v) +uint32_t MinIndexVec2(const Vec2& v) { return v.x <= v.y ? 0 : 1; } //---------------------------------------------------------------------------------------- -uint32_t MaxIndexVector2(const Vector2& v) +uint32_t MaxIndexVec2(const Vec2& v) { return v.x >= v.y ? 0 : 1; } //---------------------------------------------------------------------------------------- -slInline float DotVector2(const Vector2& a, const Vector2& b) +slInline float DotVec2(const Vec2& a, const Vec2& b) { return a.x * b.x + a.y * b.y; } //---------------------------------------------------------------------------------------- -slInline float DotVector2(const Vector2& a, const float x, const float y) +slInline float DotVec2(const Vec2& a, const float x, const float y) { return a.x * x + a.y * y; } //---------------------------------------------------------------------------------------- -slInline void PerpendicularVector2(Vector2& r, const Vector2& v) +slInline void PerpendicularVec2(Vec2& r, const Vec2& v) { r.x = -v.y; r.y = v.x; } //---------------------------------------------------------------------------------------- -slInline Vector2 PerpendicularVector2(const Vector2& v) +slInline Vec2 PerpendicularVec2(const Vec2& v) { - Vector2 r; + Vec2 r; r.x = -v.y; r.y = v.x; return r; } //---------------------------------------------------------------------------------------- -slInline void AddVector2ByScalar(Vector2& r, const float s, Vector2& v) +slInline void AddVec2ByScalar(Vec2& r, const float s, Vec2& v) { r.x = s + v.x; r.y = s + v.y; } //---------------------------------------------------------------------------------------- -slInline Vector2 AddVector2ByScalar(const float s, const Vector2& v) +slInline Vec2 AddVec2ByScalar(const float s, const Vec2& v) { - Vector2 r; + Vec2 r; r.x = s + v.x; r.y = s + v.y; return r; } //---------------------------------------------------------------------------------------- -slInline void AddVector2(Vector2& r, const Vector2& a, const Vector2& b) +slInline void AddVec2(Vec2& r, const Vec2& a, const Vec2& b) { r.x = a.x + b.x; r.y = a.y + b.y; } //---------------------------------------------------------------------------------------- -slInline Vector2 AddVector2(const Vector2& a, const Vector2& b) +slInline Vec2 AddVec2(const Vec2& a, const Vec2& b) { - Vector2 r; + Vec2 r; r.x = a.x + b.x; r.y = a.y + b.y; return r; } //---------------------------------------------------------------------------------------- -slInline void AddVector2(Vector2& r, const Vector2& a, const float x, const float y) +slInline void AddVec2(Vec2& r, const Vec2& a, const float x, const float y) { r.x = a.x + x; r.y = a.y + y; } //---------------------------------------------------------------------------------------- -slInline Vector2 AddVector2(const Vector2& a, const float x, const float y) +slInline Vec2 AddVec2(const Vec2& a, const float x, const float y) { - Vector2 r; + Vec2 r; r.x = a.x + x; r.y = a.y + y; return r; } //---------------------------------------------------------------------------------------- -slInline void SubVector2(Vector2& r, const Vector2& a, const Vector2& b) +slInline void SubVec2(Vec2& r, const Vec2& a, const Vec2& b) { r.x = a.x - b.x; r.y = a.y - b.y; } //---------------------------------------------------------------------------------------- -slInline Vector2 SubVector2(const Vector2& a, const Vector2& b) +slInline Vec2 SubVec2(const Vec2& a, const Vec2& b) { - Vector2 r; + Vec2 r; r.x = a.x - b.x; r.y = a.y - b.y; return r; } //---------------------------------------------------------------------------------------- -slInline void SubVector2(Vector2& r, const Vector2& a, const float x, const float y) +slInline void SubVec2(Vec2& r, const Vec2& a, const float x, const float y) { r.x = a.x - x; r.y = a.y - y; } //---------------------------------------------------------------------------------------- -slInline Vector2 SubVector2(const Vector2& a, const float x, const float y) +slInline Vec2 SubVec2(const Vec2& a, const float x, const float y) { - Vector2 r; + Vec2 r; r.x = a.x - x; r.y = a.y - y; return r; } //---------------------------------------------------------------------------------------- -slInline void ScaleVector2(Vector2& r, const float s, const Vector2& v) +slInline void ScaleVec2(Vec2& r, const float s, const Vec2& v) { r.x = s * v.x; r.y = s * v.y; } //---------------------------------------------------------------------------------------- -slInline Vector2 ScaleVector2(const float s, const Vector2& v) +slInline Vec2 ScaleVec2(const float s, const Vec2& v) { - Vector2 r; + Vec2 r; r.x = s * v.x; r.y = s * v.y; return r; } //---------------------------------------------------------------------------------------- -slInline void MulVector2(Vector2& r, const Vector2& a, const Vector2& b) +slInline void MulVec2(Vec2& r, const Vec2& a, const Vec2& b) { r.x = a.x * b.x; r.y = a.y * b.y; } //---------------------------------------------------------------------------------------- -slInline Vector2 MulVector2(const Vector2& a, const Vector2& b) +slInline Vec2 MulVec2(const Vec2& a, const Vec2& b) { - Vector2 r; + Vec2 r; r.x = a.x * b.x; r.y = a.y * b.y; return r; } //---------------------------------------------------------------------------------------- -slInline void MulVector2(Vector2& r, const Vector2& a, const float x, const float y) +slInline void MulVec2(Vec2& r, const Vec2& a, const float x, const float y) { r.x = a.x * x; r.y = a.y * y; } //---------------------------------------------------------------------------------------- -slInline Vector2 MulVector2(const Vector2& a, const float x, const float y) +slInline Vec2 MulVec2(const Vec2& a, const float x, const float y) { - Vector2 r; + Vec2 r; r.x = a.x * x; r.y = a.y * y; return r; } //---------------------------------------------------------------------------------------- -slInline void DivVector2(Vector2& r, const Vector2& a, const Vector2& b) +slInline void DivVec2(Vec2& r, const Vec2& a, const Vec2& b) { r.x = a.x / b.x; r.y = a.y / b.y; } //---------------------------------------------------------------------------------------- -slInline Vector2 DivVector2(const Vector2& a, const Vector2& b) +slInline Vec2 DivVec2(const Vec2& a, const Vec2& b) { - Vector2 r; + Vec2 r; r.x = a.x / b.x; r.y = a.y / b.y; return r; } //---------------------------------------------------------------------------------------- -slInline void DivVector2(Vector2& r, const Vector2& a, const float x, const float y) +slInline void DivVec2(Vec2& r, const Vec2& a, const float x, const float y) { r.x = a.x / x; r.y = a.y / y; } //---------------------------------------------------------------------------------------- -slInline Vector2 DivVector2(const Vector2& a, const float x, const float y) +slInline Vec2 DivVec2(const Vec2& a, const float x, const float y) { - Vector2 r; + Vec2 r; r.x = a.x / x; r.y = a.y / y; return r; } //---------------------------------------------------------------------------------------- -slInline void ScaleAddVector2(Vector2& r, const float s, const Vector2& v_scale, const Vector2& v_add) +slInline void ScaleAddVec2(Vec2& r, const float s, const Vec2& v_scale, const Vec2& v_add) { r.x = v_scale.x * s + v_add.x; r.y = v_scale.y * s + v_add.y; } //---------------------------------------------------------------------------------------- -slInline Vector2 ScaleAddVector2(const float s, const Vector2& v_scale, const Vector2& v_add) +slInline Vec2 ScaleAddVec2(const float s, const Vec2& v_scale, const Vec2& v_add) { - Vector2 r; + Vec2 r; r.x = v_scale.x * s + v_add.x; r.y = v_scale.y * s + v_add.y; return r; } //---------------------------------------------------------------------------------------- -slInline void NormalizeVector2(Vector2& r, const Vector2& a) +slInline void NormalizeVec2(Vec2& r, const Vec2& a) { - float scale = 1.0f / LengthOfVector2(a); - ScaleVector2( r, scale, a ); + float scale = 1.0f / LengthOfVec2(a); + ScaleVec2( r, scale, a ); } //---------------------------------------------------------------------------------------- -slInline Vector2 NormalizeVector2(const Vector2& a) +slInline Vec2 NormalizeVec2(const Vec2& a) { - float scale = 1.0f / LengthOfVector2(a); - return ScaleVector2( scale, a ); + float scale = 1.0f / LengthOfVec2(a); + return ScaleVec2( scale, a ); } //---------------------------------------------------------------------------------------- -slInline float LengthOfVector2(const Vector2& a) +slInline float LengthOfVec2(const Vec2& a) { - return Sqrtf( DotVector2(a, a) ); + return (float)Sqrtf( DotVec2(a, a) ); } //---------------------------------------------------------------------------------------- -slInline float LengthSquaredOfVector2(const Vector2& a) +slInline float LengthSquaredOfVec2(const Vec2& a) { - return DotVector2(a, a); + return DotVec2(a, a); } //---------------------------------------------------------------------------------------- -// Vector3 +// Vec3 //---------------------------------------------------------------------------------------- -void SetVector3(Vector3& r, const Vector3& v); -void SetVector3(Vector3& r, const Vector2& v, const float z); -void SetVector3(Vector3& r, const float xyz); -void SetVector3(Vector3& r, const float x, const float y, const float z); +void SetVec3(Vec3& r, const Vec3& v); +void SetVec3(Vec3& r, const Vec2& v, const float z); +void SetVec3(Vec3& r, const float xyz); +void SetVec3(Vec3& r, const float x, const float y, const float z); -void AbsVector3(Vector3& r, const Vector3& v); -Vector3 AbsVector3(const Vector3& v); +void AbsVec3(Vec3& r, const Vec3& v); +Vec3 AbsVec3(const Vec3& v); -float MinComponentVector3(const Vector3& v); -float MaxComponentVector3(const Vector3& v); -uint32_t MinIndexVector3(const Vector3& v); -uint32_t MaxIndexVector3(const Vector3& v); -float DotVector3(const Vector3& a, const Vector3& b); -float DotVector3(const Vector3& a, const float x, const float y, const float z); +float MinComponentVec3(const Vec3& v); +float MaxComponentVec3(const Vec3& v); +uint32_t MinIndexVec3(const Vec3& v); +uint32_t MaxIndexVec3(const Vec3& v); +float DotVec3(const Vec3& a, const Vec3& b); +float DotVec3(const Vec3& a, const float x, const float y, const float z); -void CrossVector3(Vector3& r, const Vector3& a, const Vector3& b); -Vector3 CrossVector3(const Vector3& a, const Vector3& b); +void CrossVec3(Vec3& r, const Vec3& a, const Vec3& b); +Vec3 CrossVec3(const Vec3& a, const Vec3& b); -void AddVector3ByScalar(Vector3& r, const float s, Vector3& v); -Vector3 AddVector3ByScalar(const float s, Vector3& v); +void AddVec3ByScalar(Vec3& r, const float s, Vec3& v); +Vec3 AddVec3ByScalar(const float s, Vec3& v); -void AddVector3(Vector3& r, const Vector3& a, const Vector3& b); -Vector3 AddVector3(const Vector3& a, const Vector3& b); +void AddVec3(Vec3& r, const Vec3& a, const Vec3& b); +Vec3 AddVec3(const Vec3& a, const Vec3& b); -void AddVector3(Vector3& r, const Vector3& a, const float x, const float y, const float z); -Vector3 AddVector3(const Vector3& a, const float x, const float y, const float z); +void AddVec3(Vec3& r, const Vec3& a, const float x, const float y, const float z); +Vec3 AddVec3(const Vec3& a, const float x, const float y, const float z); -void SubVector3(Vector3& r, const Vector3& a, const Vector3& b); -Vector3 SubVector3(const Vector3& a, const Vector3& b); +void SubVec3(Vec3& r, const Vec3& a, const Vec3& b); +Vec3 SubVec3(const Vec3& a, const Vec3& b); -void SubVector3(Vector3& r, const Vector3& a, const float x, const float y, const float z); -Vector3 SubVector3(const Vector3& a, const float x, const float y, const float z); +void SubVec3(Vec3& r, const Vec3& a, const float x, const float y, const float z); +Vec3 SubVec3(const Vec3& a, const float x, const float y, const float z); -void ScaleVector3(Vector3& r, const float s, const Vector3& v); -Vector3 ScaleVector3(const float s, const Vector3& v); +void ScaleVec3(Vec3& r, const float s, const Vec3& v); +Vec3 ScaleVec3(const float s, const Vec3& v); -void MulVector3(Vector3& r, const Vector3& a, const Vector3& b); -Vector3 MulVector3(const Vector3& a, const Vector3& b); +void MulVec3(Vec3& r, const Vec3& a, const Vec3& b); +Vec3 MulVec3(const Vec3& a, const Vec3& b); -void MulVector3(Vector3& r, const Vector3& a, const float x, const float y, const float z); -Vector3 MulVector3(const Vector3& a, const float x, const float y, const float z); +void MulVec3(Vec3& r, const Vec3& a, const float x, const float y, const float z); +Vec3 MulVec3(const Vec3& a, const float x, const float y, const float z); -void DivVector3(Vector3& r, const Vector3& a, const Vector3& b); -Vector3 DivVector3(const Vector3& a, const Vector3& b); +void DivVec3(Vec3& r, const Vec3& a, const Vec3& b); +Vec3 DivVec3(const Vec3& a, const Vec3& b); -void DivVector3(Vector3& r, const Vector3& a, const float x, const float y, const float z); -Vector3 DivVector3(const Vector3& a, const float x, const float y, const float z); +void DivVec3(Vec3& r, const Vec3& a, const float x, const float y, const float z); +Vec3 DivVec3(const Vec3& a, const float x, const float y, const float z); -void ScaleAddVector3(Vector3& r, const float s, const Vector3& v_scale, const Vector3& v_add); -Vector3 ScaleAddVector3(const float s, const Vector3& v_scale, const Vector3& v_add); +void ScaleAddVec3(Vec3& r, const float s, const Vec3& v_scale, const Vec3& v_add); +Vec3 ScaleAddVec3(const float s, const Vec3& v_scale, const Vec3& v_add); -void NormalizeVector3(Vector3& r, const Vector3& a); -Vector3 NormalizeVector3(const Vector3& a); +void NormalizeVec3(Vec3& r, const Vec3& a); +Vec3 NormalizeVec3(const Vec3& a); -float LengthVector3(const Vector3& a); -float LengthSquaredVector3(const Vector3& a); +float LengthOfVec3(const Vec3& a); +float LengthSquaredVec3(const Vec3& a); //---------------------------------------------------------------------------------------- -slInline void SetVector3(Vector3& r, const Vector3& v) +slInline void SetVec3(Vec3& r, const Vec3& v) { r.x = v.x; r.y = v.y; @@ -413,7 +413,7 @@ slInline void SetVector3(Vector3& r, const Vector3& v) } //---------------------------------------------------------------------------------------- -slInline void SetVector3(Vector3& r, const Vector2& v, const float z) +slInline void SetVec3(Vec3& r, const Vec2& v, const float z) { r.x = v.x; r.y = v.y; @@ -421,7 +421,7 @@ slInline void SetVector3(Vector3& r, const Vector2& v, const float z) } //---------------------------------------------------------------------------------------- -slInline void SetVector3(Vector3& r, const float xyz) +slInline void SetVec3(Vec3& r, const float xyz) { r.x = xyz; r.y = xyz; @@ -429,7 +429,7 @@ slInline void SetVector3(Vector3& r, const float xyz) } //---------------------------------------------------------------------------------------- -slInline void SetVector3(Vector3& r, const float x, const float y, const float z) +slInline void SetVec3(Vec3& r, const float x, const float y, const float z) { r.x = x; r.y = y; @@ -437,7 +437,7 @@ slInline void SetVector3(Vector3& r, const float x, const float y, const float z } //---------------------------------------------------------------------------------------- -slInline void AbsVector3(Vector3& r, const Vector3& v) +slInline void AbsVec3(Vec3& r, const Vec3& v) { r.x = Absf(v.x); r.y = Absf(v.y); @@ -445,9 +445,9 @@ slInline void AbsVector3(Vector3& r, const Vector3& v) } //---------------------------------------------------------------------------------------- -slInline Vector3 AbsVector3(const Vector3& v) +slInline Vec3 AbsVec3(const Vec3& v) { - Vector3 r; + Vec3 r; r.x = Absf(v.x); r.y = Absf(v.y); r.z = Absf(v.z); @@ -455,21 +455,21 @@ slInline Vector3 AbsVector3(const Vector3& v) } //---------------------------------------------------------------------------------------- -slInline float MinComponentVector3(const Vector3& v) +slInline float MinComponentVec3(const Vec3& v) { float xy = v.x <= v.y ? v.x : v.y; return xy <= v.z ? xy : v.z; } //---------------------------------------------------------------------------------------- -slInline float MaxComponentVector3(const Vector3& v) +slInline float MaxComponentVec3(const Vec3& v) { float xy = v.x >= v.y ? v.x : v.y; return xy >= v.z ? xy : v.z; } //---------------------------------------------------------------------------------------- -slInline uint32_t MinIndexVector3(const Vector3& v) +slInline uint32_t MinIndexVec3(const Vec3& v) { const float* v_array = &v.x; uint32_t xy = v.x <= v.y ? 0 : 1; @@ -477,7 +477,7 @@ slInline uint32_t MinIndexVector3(const Vector3& v) } //---------------------------------------------------------------------------------------- -slInline uint32_t MaxIndexVector3(const Vector3& v) +slInline uint32_t MaxIndexVec3(const Vec3& v) { const float* v_array = &v.x; uint32_t xy = v.x >= v.y ? 0 : 1; @@ -485,19 +485,19 @@ slInline uint32_t MaxIndexVector3(const Vector3& v) } //---------------------------------------------------------------------------------------- -slInline float DotVector3(const Vector3& a, const Vector3& b) +slInline float DotVec3(const Vec3& a, const Vec3& b) { return a.x * b.x + a.y * b.y + a.z * b.z; } //---------------------------------------------------------------------------------------- -slInline float DotVector3(const Vector3& a, const float x, const float y, const float z) +slInline float DotVec3(const Vec3& a, const float x, const float y, const float z) { return a.x * x + a.y * y + a.z * z; } //---------------------------------------------------------------------------------------- -slInline void CrossVector3(Vector3& r, const Vector3& a, const Vector3& b) +slInline void CrossVec3(Vec3& r, const Vec3& a, const Vec3& b) { float x = a.y * b.z - b.y * a.z; float y = a.z * b.x - b.z * a.x; @@ -508,9 +508,9 @@ slInline void CrossVector3(Vector3& r, const Vector3& a, const Vector3& b) } //---------------------------------------------------------------------------------------- -slInline Vector3 CrossVector3(const Vector3& a, const Vector3& b) +slInline Vec3 CrossVec3(const Vec3& a, const Vec3& b) { - Vector3 r; + Vec3 r; r.x = a.y * b.z - b.y * a.z; r.y = a.z * b.x - b.z * a.x; r.z = a.x * b.y - b.x * a.y; @@ -518,7 +518,7 @@ slInline Vector3 CrossVector3(const Vector3& a, const Vector3& b) } //---------------------------------------------------------------------------------------- -slInline void AddVector3ByScalar(Vector3& r, const float s, Vector3& v) +slInline void AddVec3ByScalar(Vec3& r, const float s, Vec3& v) { r.x = s + v.x; r.y = s + v.y; @@ -526,9 +526,9 @@ slInline void AddVector3ByScalar(Vector3& r, const float s, Vector3& v) } //---------------------------------------------------------------------------------------- -slInline Vector3 AddVector3ByScalar(const float s, Vector3& v) +slInline Vec3 AddVec3ByScalar(const float s, Vec3& v) { - Vector3 r; + Vec3 r; r.x = s + v.x; r.y = s + v.y; r.z = s + v.z; @@ -536,7 +536,7 @@ slInline Vector3 AddVector3ByScalar(const float s, Vector3& v) } //---------------------------------------------------------------------------------------- -slInline void AddVector3(Vector3& r, const Vector3& a, const Vector3& b) +slInline void AddVec3(Vec3& r, const Vec3& a, const Vec3& b) { r.x = a.x + b.x; r.y = a.y + b.y; @@ -544,9 +544,9 @@ slInline void AddVector3(Vector3& r, const Vector3& a, const Vector3& b) } //---------------------------------------------------------------------------------------- -slInline Vector3 AddVector3(const Vector3& a, const Vector3& b) +slInline Vec3 AddVec3(const Vec3& a, const Vec3& b) { - Vector3 r; + Vec3 r; r.x = a.x + b.x; r.y = a.y + b.y; r.z = a.z + b.z; @@ -554,7 +554,7 @@ slInline Vector3 AddVector3(const Vector3& a, const Vector3& b) } //---------------------------------------------------------------------------------------- -slInline void AddVector3(Vector3& r, const Vector3& a, const float x, const float y, const float z) +slInline void AddVec3(Vec3& r, const Vec3& a, const float x, const float y, const float z) { r.x = a.x + x; r.y = a.y + y; @@ -562,9 +562,9 @@ slInline void AddVector3(Vector3& r, const Vector3& a, const float x, const floa } //---------------------------------------------------------------------------------------- -slInline Vector3 AddVector3(const Vector3& a, const float x, const float y, const float z) +slInline Vec3 AddVec3(const Vec3& a, const float x, const float y, const float z) { - Vector3 r; + Vec3 r; r.x = a.x + x; r.y = a.y + y; r.z = a.z + z; @@ -572,7 +572,7 @@ slInline Vector3 AddVector3(const Vector3& a, const float x, const float y, cons } //---------------------------------------------------------------------------------------- -slInline void SubVector3(Vector3& r, const Vector3& a, const Vector3& b) +slInline void SubVec3(Vec3& r, const Vec3& a, const Vec3& b) { r.x = a.x - b.x; r.y = a.y - b.y; @@ -580,9 +580,9 @@ slInline void SubVector3(Vector3& r, const Vector3& a, const Vector3& b) } //---------------------------------------------------------------------------------------- -slInline Vector3 SubVector3(const Vector3& a, const Vector3& b) +slInline Vec3 SubVec3(const Vec3& a, const Vec3& b) { - Vector3 r; + Vec3 r; r.x = a.x - b.x; r.y = a.y - b.y; r.z = a.z - b.z; @@ -590,9 +590,9 @@ slInline Vector3 SubVector3(const Vector3& a, const Vector3& b) } //---------------------------------------------------------------------------------------- -slInline Vector3 SubVector3(const Vector3& a, const float x, const float y, const float z) +slInline Vec3 SubVec3(const Vec3& a, const float x, const float y, const float z) { - Vector3 r; + Vec3 r; r.x = a.x - x; r.y = a.y - y; r.z = a.z - z; @@ -600,7 +600,7 @@ slInline Vector3 SubVector3(const Vector3& a, const float x, const float y, cons } //---------------------------------------------------------------------------------------- -slInline void ScaleVector3(Vector3& r, const float s, const Vector3& v) +slInline void ScaleVec3(Vec3& r, const float s, const Vec3& v) { r.x = s * v.x; r.y = s * v.y; @@ -608,9 +608,9 @@ slInline void ScaleVector3(Vector3& r, const float s, const Vector3& v) } //---------------------------------------------------------------------------------------- -slInline Vector3 ScaleVector3(const float s, const Vector3& v) +slInline Vec3 ScaleVec3(const float s, const Vec3& v) { - Vector3 r; + Vec3 r; r.x = s * v.x; r.y = s * v.y; r.z = s * v.z; @@ -618,7 +618,7 @@ slInline Vector3 ScaleVector3(const float s, const Vector3& v) } //---------------------------------------------------------------------------------------- -slInline void MulVector3(Vector3& r, const Vector3& a, const Vector3& b) +slInline void MulVec3(Vec3& r, const Vec3& a, const Vec3& b) { r.x = a.x * b.x; r.y = a.y * b.y; @@ -626,9 +626,9 @@ slInline void MulVector3(Vector3& r, const Vector3& a, const Vector3& b) } //---------------------------------------------------------------------------------------- -slInline Vector3 MulVector3(const Vector3& a, const Vector3& b) +slInline Vec3 MulVec3(const Vec3& a, const Vec3& b) { - Vector3 r; + Vec3 r; r.x = a.x * b.x; r.y = a.y * b.y; r.z = a.z * b.z; @@ -636,7 +636,7 @@ slInline Vector3 MulVector3(const Vector3& a, const Vector3& b) } //---------------------------------------------------------------------------------------- -slInline void MulVector3(Vector3& r, const Vector3& a, const float x, const float y, const float z) +slInline void MulVec3(Vec3& r, const Vec3& a, const float x, const float y, const float z) { r.x = a.x * x; r.y = a.y * y; @@ -644,9 +644,9 @@ slInline void MulVector3(Vector3& r, const Vector3& a, const float x, const floa } //---------------------------------------------------------------------------------------- -slInline Vector3 MulVector3(const Vector3& a, const float x, const float y, const float z) +slInline Vec3 MulVec3(const Vec3& a, const float x, const float y, const float z) { - Vector3 r; + Vec3 r; r.x = a.x * x; r.y = a.y * y; r.z = a.z * z; @@ -654,7 +654,7 @@ slInline Vector3 MulVector3(const Vector3& a, const float x, const float y, cons } //---------------------------------------------------------------------------------------- -slInline void DivVector3(Vector3& r, const Vector3& a, const Vector3& b) +slInline void DivVec3(Vec3& r, const Vec3& a, const Vec3& b) { r.x = a.x / b.x; r.y = a.y / b.y; @@ -662,9 +662,9 @@ slInline void DivVector3(Vector3& r, const Vector3& a, const Vector3& b) } //---------------------------------------------------------------------------------------- -slInline Vector3 DivVector3(const Vector3& a, const Vector3& b) +slInline Vec3 DivVec3(const Vec3& a, const Vec3& b) { - Vector3 r; + Vec3 r; r.x = a.x / b.x; r.y = a.y / b.y; r.z = a.z / b.z; @@ -672,7 +672,7 @@ slInline Vector3 DivVector3(const Vector3& a, const Vector3& b) } //---------------------------------------------------------------------------------------- -slInline void DivVector3(Vector3& r, const Vector3& a, const float x, const float y, const float z) +slInline void DivVec3(Vec3& r, const Vec3& a, const float x, const float y, const float z) { r.x = a.x / x; r.y = a.y / y; @@ -680,9 +680,9 @@ slInline void DivVector3(Vector3& r, const Vector3& a, const float x, const floa } //---------------------------------------------------------------------------------------- -slInline Vector3 DivVector3(const Vector3& a, const float x, const float y, const float z) +slInline Vec3 DivVec3(const Vec3& a, const float x, const float y, const float z) { - Vector3 r; + Vec3 r; r.x = a.x / x; r.y = a.y / y; r.z = a.z / z; @@ -690,7 +690,7 @@ slInline Vector3 DivVector3(const Vector3& a, const float x, const float y, cons } //---------------------------------------------------------------------------------------- -slInline void ScaleAddVector3(Vector3& r, const float s, const Vector3& v_scale, const Vector3& v_add) +slInline void ScaleAddVec3(Vec3& r, const float s, const Vec3& v_scale, const Vec3& v_add) { r.x = s * v_scale.x + v_add.x; r.y = s * v_scale.y + v_add.y; @@ -698,9 +698,9 @@ slInline void ScaleAddVector3(Vector3& r, const float s, const Vector3& v_scale, } //---------------------------------------------------------------------------------------- -slInline Vector3 ScaleAddVector3(const float s, const Vector3& v_scale, const Vector3& v_add) +slInline Vec3 ScaleAddVec3(const float s, const Vec3& v_scale, const Vec3& v_add) { - Vector3 r; + Vec3 r; r.x = s * v_scale.x + v_add.x; r.y = s * v_scale.y + v_add.y; r.z = s * v_scale.z + v_add.z; @@ -708,96 +708,96 @@ slInline Vector3 ScaleAddVector3(const float s, const Vector3& v_scale, const Ve } //---------------------------------------------------------------------------------------- -slInline void NormalizeVector3(Vector3& r, const Vector3& a) +slInline void NormalizeVec3(Vec3& r, const Vec3& a) { - float scale = 1.0f / LengthOfVector3( a ); - ScaleVector3( r, scale, a ); + float scale = 1.0f / LengthOfVec3( a ); + ScaleVec3( r, scale, a ); } //---------------------------------------------------------------------------------------- -slInline Vector3 NormalizeVector3(const Vector3& a) +slInline Vec3 NormalizeVec3(const Vec3& a) { - float scale = 1.0f / LengthOfVector3( a ); - return ScaleVector3( scale, a ); + float scale = 1.0f / LengthOfVec3( a ); + return ScaleVec3( scale, a ); } //---------------------------------------------------------------------------------------- -slInline float LengthOfVector3(const Vector3& a) +slInline float LengthOfVec3(const Vec3& a) { - return Sqrtf( DotVector3(a, a) ); + return (float)Sqrtf( DotVec3(a, a) ); } //---------------------------------------------------------------------------------------- -slInline float LengthSquaredOfVector3(const Vector3& a) +slInline float LengthSquaredOfVec3(const Vec3& a) { - return DotVector3( a, a ); + return DotVec3( a, a ); } //---------------------------------------------------------------------------------------- -// Vector4 +// Vec4 //---------------------------------------------------------------------------------------- -void SetVector4(Vector4& r, const Vector4& v); -void SetVector4(Vector4& r, const Vector2& a, const Vector2& b); -void SetVector4(Vector4& r, const Vector3& v, const float w); -void SetVector4(Vector4& r, const float xyzw); -void SetVector4(Vector4& r, const float x, const float y, const float z, const float w); +void SetVec4(Vec4& r, const Vec4& v); +void SetVec4(Vec4& r, const Vec2& a, const Vec2& b); +void SetVec4(Vec4& r, const Vec3& v, const float w); +void SetVec4(Vec4& r, const float xyzw); +void SetVec4(Vec4& r, const float x, const float y, const float z, const float w); -void AbsVector4(Vector4& r, const Vector4& v); -Vector4 AbsVector4(const Vector4& v); +void AbsVec4(Vec4& r, const Vec4& v); +Vec4 AbsVec4(const Vec4& v); -float MinComponentVector4(const Vector4& v); -float MaxComponentVector4(const Vector4& v); -uint32_t MinIndexVector4(const Vector4& v); -uint32_t MaxIndexVector4(const Vector4& v); -float DotVector4(const Vector4& a, const Vector4& b); -float DotVector4(const Vector4& a, const float x, const float y, const float z, const float w); +float MinComponentVec4(const Vec4& v); +float MaxComponentVec4(const Vec4& v); +uint32_t MinIndexVec4(const Vec4& v); +uint32_t MaxIndexVec4(const Vec4& v); +float DotVec4(const Vec4& a, const Vec4& b); +float DotVec4(const Vec4& a, const float x, const float y, const float z, const float w); -void CrossVector4(Vector4& r, const Vector4& a, const Vector4& b, const Vector4& c); -Vector4 CrossVector4(const Vector4& a, const Vector4& b, const Vector4& c); +void CrossVec4(Vec4& r, const Vec4& a, const Vec4& b, const Vec4& c); +Vec4 CrossVec4(const Vec4& a, const Vec4& b, const Vec4& c); -void AddVector4ByScalar(Vector4& r, const float s, Vector4& v); -Vector4 AddVector4ByScalar(const float s, Vector4& v); +void AddVec4ByScalar(Vec4& r, const float s, Vec4& v); +Vec4 AddVec4ByScalar(const float s, Vec4& v); -void AddVector4(Vector4& r, const Vector4& a, const Vector4& b); -Vector4 AddVector4(const Vector4& a, const Vector4& b); +void AddVec4(Vec4& r, const Vec4& a, const Vec4& b); +Vec4 AddVec4(const Vec4& a, const Vec4& b); -void AddVector4(Vector4& r, const Vector4& a, const float x, const float y, const float z, const float w); -Vector4 AddVector4(const Vector4& a, const float x, const float y, const float z, const float w); +void AddVec4(Vec4& r, const Vec4& a, const float x, const float y, const float z, const float w); +Vec4 AddVec4(const Vec4& a, const float x, const float y, const float z, const float w); -void SubVector4(Vector4& r, const Vector4& a, const Vector4& b); -Vector4 SubVector4(const Vector4& a, const Vector4& b); +void SubVec4(Vec4& r, const Vec4& a, const Vec4& b); +Vec4 SubVec4(const Vec4& a, const Vec4& b); -void SubVector4(Vector4& r, const Vector4& a, const float x, const float y, const float z, const float w); -Vector4 SubVector4(const Vector4& a, const float x, const float y, const float z, const float w); +void SubVec4(Vec4& r, const Vec4& a, const float x, const float y, const float z, const float w); +Vec4 SubVec4(const Vec4& a, const float x, const float y, const float z, const float w); -void ScaleVector4(Vector4& r, const float s, const Vector4& v); -Vector4 ScaleVector4(const float s, const Vector4& v); +void ScaleVec4(Vec4& r, const float s, const Vec4& v); +Vec4 ScaleVec4(const float s, const Vec4& v); -void MulVector4(Vector4& r, const Vector4& a, const Vector4& b); -Vector4 MulVector4(const Vector4& a, const Vector4& b); +void MulVec4(Vec4& r, const Vec4& a, const Vec4& b); +Vec4 MulVec4(const Vec4& a, const Vec4& b); -void MulVector4(Vector4& r, const Vector4& a, const float x, const float y, const float z, const float w); -Vector4 MulVector4(const Vector4& a, const float x, const float y, const float z, const float w); +void MulVec4(Vec4& r, const Vec4& a, const float x, const float y, const float z, const float w); +Vec4 MulVec4(const Vec4& a, const float x, const float y, const float z, const float w); -void DivVector4(Vector4& r, const Vector4& a, const Vector4& b); -Vector4 DivVector4(const Vector4& a, const Vector4& b); +void DivVec4(Vec4& r, const Vec4& a, const Vec4& b); +Vec4 DivVec4(const Vec4& a, const Vec4& b); -void DivVector4(Vector4& r, const Vector4& a, const float x, const float y, const float z, const float w); -Vector4 DivVector4(const Vector4& a, const float x, const float y, const float z, const float w); +void DivVec4(Vec4& r, const Vec4& a, const float x, const float y, const float z, const float w); +Vec4 DivVec4(const Vec4& a, const float x, const float y, const float z, const float w); -void ScaleAddVector4(Vector4& r, const float s, const Vector4& v_scale, const Vector4& v_add); -Vector4 ScaleAddVector4(const float s, const Vector4& v_scale, const Vector4& v_add); +void ScaleAddVec4(Vec4& r, const float s, const Vec4& v_scale, const Vec4& v_add); +Vec4 ScaleAddVec4(const float s, const Vec4& v_scale, const Vec4& v_add); -void NormalizeVector4(Vector4& r, const Vector4& a); -Vector4 NormalizeVector4(const Vector4& a); +void NormalizeVec4(Vec4& r, const Vec4& a); +Vec4 NormalizeVec4(const Vec4& a); -float LengthVector4(const Vector4& a); -float LengthSquaredVector4(const Vector4& a); +float LengthOfVec4(const Vec4& a); +float LengthSquaredVec4(const Vec4& a); //---------------------------------------------------------------------------------------- -slInline void SetVector4(Vector4& r, const Vector4& v) +slInline void SetVec4(Vec4& r, const Vec4& v) { r.x = v.x; r.y = v.y; @@ -806,7 +806,7 @@ slInline void SetVector4(Vector4& r, const Vector4& v) } //---------------------------------------------------------------------------------------- -slInline void SetVector4(Vector4& r, const Vector2& a, const Vector2& b) +slInline void SetVec4(Vec4& r, const Vec2& a, const Vec2& b) { r.x = a.x; r.y = a.y; @@ -815,7 +815,7 @@ slInline void SetVector4(Vector4& r, const Vector2& a, const Vector2& b) } //---------------------------------------------------------------------------------------- -slInline void SetVector4(Vector4& r, const Vector3& v, const float w) +slInline void SetVec4(Vec4& r, const Vec3& v, const float w) { r.x = v.x; r.y = v.y; @@ -824,7 +824,7 @@ slInline void SetVector4(Vector4& r, const Vector3& v, const float w) } //---------------------------------------------------------------------------------------- -slInline void SetVector4(Vector4& r, const float xyzw) +slInline void SetVec4(Vec4& r, const float xyzw) { r.x = xyzw; r.y = xyzw; @@ -833,7 +833,7 @@ slInline void SetVector4(Vector4& r, const float xyzw) } //---------------------------------------------------------------------------------------- -slInline void SetVector4(Vector4& r, const float x, const float y, const float z, const float w) +slInline void SetVec4(Vec4& r, const float x, const float y, const float z, const float w) { r.x = x; r.y = y; @@ -842,7 +842,7 @@ slInline void SetVector4(Vector4& r, const float x, const float y, const float z } //---------------------------------------------------------------------------------------- -slInline void AbsVector4(Vector4& r, const Vector4& v) +slInline void AbsVec4(Vec4& r, const Vec4& v) { r.x = Absf(v.x); r.y = Absf(v.y); @@ -851,9 +851,9 @@ slInline void AbsVector4(Vector4& r, const Vector4& v) } //---------------------------------------------------------------------------------------- -slInline Vector4 AbsVector4(const Vector4& v) +slInline Vec4 AbsVec4(const Vec4& v) { - Vector4 r; + Vec4 r; r.x = Absf(v.x); r.y = Absf(v.y); r.z = Absf(v.z); @@ -862,7 +862,7 @@ slInline Vector4 AbsVector4(const Vector4& v) } //---------------------------------------------------------------------------------------- -slInline float MinComponentVector4(const Vector4& v) +slInline float MinComponentVec4(const Vec4& v) { float xy = v.x <= v.y ? v.x : v.y; float zw = v.z <= v.w ? v.z : v.w; @@ -870,7 +870,7 @@ slInline float MinComponentVector4(const Vector4& v) } //---------------------------------------------------------------------------------------- -slInline float MaxComponentVector4(const Vector4& v) +slInline float MaxComponentVec4(const Vec4& v) { float xy = v.x >= v.y ? v.x : v.y; float zw = v.z >= v.w ? v.z : v.w; @@ -878,7 +878,7 @@ slInline float MaxComponentVector4(const Vector4& v) } //---------------------------------------------------------------------------------------- -slInline uint32_t MinIndexVector4(const Vector4& v) +slInline uint32_t MinIndexVec4(const Vec4& v) { const float* v_array = &v.x; uint32_t xy = v.x <= v.y ? 0 : 1; @@ -887,7 +887,7 @@ slInline uint32_t MinIndexVector4(const Vector4& v) } //---------------------------------------------------------------------------------------- -slInline uint32_t MaxIndexVector4(const Vector4& v) +slInline uint32_t MaxIndexVec4(const Vec4& v) { const float* v_array = &v.x; uint32_t xy = v.x >= v.y ? 0 : 1; @@ -896,19 +896,19 @@ slInline uint32_t MaxIndexVector4(const Vector4& v) } //---------------------------------------------------------------------------------------- -slInline float DotVector4(const Vector4& a, const Vector4& b) +slInline float DotVec4(const Vec4& a, const Vec4& b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; } //---------------------------------------------------------------------------------------- -slInline float DotVector4(const Vector4& a, const float x, const float y, const float z, const float w) +slInline float DotVec4(const Vec4& a, const float x, const float y, const float z, const float w) { return a.x * x + a.y * y + a.z * z + a.w * w; } //---------------------------------------------------------------------------------------- -slInline void CrossVector4(Vector4& r, const Vector4& a, const Vector4& b, const Vector4& c) +slInline void CrossVec4(Vec4& r, const Vec4& a, const Vec4& b, const Vec4& c) { // is this right? r.x = a.y * (b.z * c.w - b.w * c.z) - a.z * (b.y * c.w - c.y * b.w) + a.w * (b.y * c.z - b.z * c.y); @@ -918,9 +918,9 @@ slInline void CrossVector4(Vector4& r, const Vector4& a, const Vector4& b, const } //---------------------------------------------------------------------------------------- -slInline Vector4 CrossVector4(const Vector4& a, const Vector4& b, const Vector4& c) +slInline Vec4 CrossVec4(const Vec4& a, const Vec4& b, const Vec4& c) { - Vector4 r; + Vec4 r; // is this right? r.x = a.y * (b.z * c.w - b.w * c.z) - a.z * (b.y * c.w - c.y * b.w) + a.w * (b.y * c.z - b.z * c.y); r.y = -a.x * (b.z * c.w - b.w * c.z) + a.z * (b.x * c.w - c.x * b.w) - a.w * (b.x * c.z - b.z * c.x); @@ -930,7 +930,7 @@ slInline Vector4 CrossVector4(const Vector4& a, const Vector4& b, const Vector4& } //---------------------------------------------------------------------------------------- -slInline void AddVector4ByScalar(Vector4& r, const float s, Vector4& v) +slInline void AddVec4ByScalar(Vec4& r, const float s, Vec4& v) { r.x = s * v.x; r.y = s * v.y; @@ -939,9 +939,9 @@ slInline void AddVector4ByScalar(Vector4& r, const float s, Vector4& v) } //---------------------------------------------------------------------------------------- -slInline Vector4 AddVector4ByScalar(const float s, Vector4& v) +slInline Vec4 AddVec4ByScalar(const float s, Vec4& v) { - Vector4 r; + Vec4 r; r.x = s * v.x; r.y = s * v.y; r.z = s * v.z; @@ -950,7 +950,7 @@ slInline Vector4 AddVector4ByScalar(const float s, Vector4& v) } //---------------------------------------------------------------------------------------- -slInline void AddVector4(Vector4& r, const Vector4& a, const Vector4& b) +slInline void AddVec4(Vec4& r, const Vec4& a, const Vec4& b) { r.x = a.x + b.x; r.y = a.y + b.y; @@ -959,9 +959,9 @@ slInline void AddVector4(Vector4& r, const Vector4& a, const Vector4& b) } //---------------------------------------------------------------------------------------- -slInline Vector4 AddVector4(const Vector4& a, const Vector4& b) +slInline Vec4 AddVec4(const Vec4& a, const Vec4& b) { - Vector4 r; + Vec4 r; r.x = a.x + b.x; r.y = a.y + b.y; r.z = a.z + b.z; @@ -970,7 +970,7 @@ slInline Vector4 AddVector4(const Vector4& a, const Vector4& b) } //---------------------------------------------------------------------------------------- -slInline void AddVector4(Vector4& r, const Vector4& a, const float x, const float y, const float z, const float w) +slInline void AddVec4(Vec4& r, const Vec4& a, const float x, const float y, const float z, const float w) { r.x = a.x + x; r.y = a.y + y; @@ -979,9 +979,9 @@ slInline void AddVector4(Vector4& r, const Vector4& a, const float x, const floa } //---------------------------------------------------------------------------------------- -slInline Vector4 AddVector4(const Vector4& a, const float x, const float y, const float z, const float w) +slInline Vec4 AddVec4(const Vec4& a, const float x, const float y, const float z, const float w) { - Vector4 r; + Vec4 r; r.x = a.x + x; r.y = a.y + y; r.z = a.z + z; @@ -990,7 +990,7 @@ slInline Vector4 AddVector4(const Vector4& a, const float x, const float y, cons } //---------------------------------------------------------------------------------------- -slInline void SubVector4(Vector4& r, const Vector4& a, const Vector4& b) +slInline void SubVec4(Vec4& r, const Vec4& a, const Vec4& b) { r.x = a.x - b.x; r.y = a.y - b.y; @@ -999,9 +999,9 @@ slInline void SubVector4(Vector4& r, const Vector4& a, const Vector4& b) } //---------------------------------------------------------------------------------------- -slInline Vector4 SubVector4(const Vector4& a, const Vector4& b) +slInline Vec4 SubVec4(const Vec4& a, const Vec4& b) { - Vector4 r; + Vec4 r; r.x = a.x - b.x; r.y = a.y - b.y; r.z = a.z - b.z; @@ -1010,7 +1010,7 @@ slInline Vector4 SubVector4(const Vector4& a, const Vector4& b) } //---------------------------------------------------------------------------------------- -slInline void SubVector4(Vector4& r, const Vector4& a, const float x, const float y, const float z, const float w) +slInline void SubVec4(Vec4& r, const Vec4& a, const float x, const float y, const float z, const float w) { r.x = a.x - x; r.y = a.y - y; @@ -1019,9 +1019,9 @@ slInline void SubVector4(Vector4& r, const Vector4& a, const float x, const floa } //---------------------------------------------------------------------------------------- -slInline Vector4 SubVector4(const Vector4& a, const float x, const float y, const float z, const float w) +slInline Vec4 SubVec4(const Vec4& a, const float x, const float y, const float z, const float w) { - Vector4 r; + Vec4 r; r.x = a.x - x; r.y = a.y - y; r.z = a.z - z; @@ -1030,7 +1030,7 @@ slInline Vector4 SubVector4(const Vector4& a, const float x, const float y, cons } //---------------------------------------------------------------------------------------- -slInline void ScaleVector4(Vector4& r, const float s, const Vector4& v) +slInline void ScaleVec4(Vec4& r, const float s, const Vec4& v) { r.x = s * v.x; r.y = s * v.y; @@ -1039,9 +1039,9 @@ slInline void ScaleVector4(Vector4& r, const float s, const Vector4& v) } //---------------------------------------------------------------------------------------- -slInline Vector4 ScaleVector4(const float s, const Vector4& v) +slInline Vec4 ScaleVec4(const float s, const Vec4& v) { - Vector4 r; + Vec4 r; r.x = s * v.x; r.y = s * v.y; r.z = s * v.z; @@ -1050,7 +1050,7 @@ slInline Vector4 ScaleVector4(const float s, const Vector4& v) } //---------------------------------------------------------------------------------------- -slInline void MulVector4(Vector4& r, const Vector4& a, const Vector4& b) +slInline void MulVec4(Vec4& r, const Vec4& a, const Vec4& b) { r.x = a.x * b.x; r.y = a.y * b.y; @@ -1059,9 +1059,9 @@ slInline void MulVector4(Vector4& r, const Vector4& a, const Vector4& b) } //---------------------------------------------------------------------------------------- -slInline Vector4 MulVector4(const Vector4& a, const Vector4& b) +slInline Vec4 MulVec4(const Vec4& a, const Vec4& b) { - Vector4 r; + Vec4 r; r.x = a.x * b.x; r.y = a.y * b.y; r.z = a.z * b.z; @@ -1070,7 +1070,7 @@ slInline Vector4 MulVector4(const Vector4& a, const Vector4& b) } //---------------------------------------------------------------------------------------- -slInline void MulVector4(Vector4& r, const Vector4& a, const float x, const float y, const float z, const float w) +slInline void MulVec4(Vec4& r, const Vec4& a, const float x, const float y, const float z, const float w) { r.x = a.x * x; r.y = a.y * y; @@ -1079,9 +1079,9 @@ slInline void MulVector4(Vector4& r, const Vector4& a, const float x, const floa } //---------------------------------------------------------------------------------------- -slInline Vector4 MulVector4(const Vector4& a, const float x, const float y, const float z, const float w) +slInline Vec4 MulVec4(const Vec4& a, const float x, const float y, const float z, const float w) { - Vector4 r; + Vec4 r; r.x = a.x * x; r.y = a.y * y; r.z = a.z * z; @@ -1090,7 +1090,7 @@ slInline Vector4 MulVector4(const Vector4& a, const float x, const float y, cons } //---------------------------------------------------------------------------------------- -slInline void DivVector4(Vector4& r, const Vector4& a, const Vector4& b) +slInline void DivVec4(Vec4& r, const Vec4& a, const Vec4& b) { r.x = a.x / b.x; r.y = a.y / b.y; @@ -1099,9 +1099,9 @@ slInline void DivVector4(Vector4& r, const Vector4& a, const Vector4& b) } //---------------------------------------------------------------------------------------- -slInline Vector4 DivVector4(const Vector4& a, const Vector4& b) +slInline Vec4 DivVec4(const Vec4& a, const Vec4& b) { - Vector4 r; + Vec4 r; r.x = a.x / b.x; r.y = a.y / b.y; r.z = a.z / b.z; @@ -1110,7 +1110,7 @@ slInline Vector4 DivVector4(const Vector4& a, const Vector4& b) } //---------------------------------------------------------------------------------------- -slInline void DivVector4(Vector4& r, const Vector4& a, const float x, const float y, const float z, const float w) +slInline void DivVec4(Vec4& r, const Vec4& a, const float x, const float y, const float z, const float w) { r.x = a.x / x; r.y = a.y / y; @@ -1119,9 +1119,9 @@ slInline void DivVector4(Vector4& r, const Vector4& a, const float x, const floa } //---------------------------------------------------------------------------------------- -slInline Vector4 DivVector4(const Vector4& a, const float x, const float y, const float z, const float w) +slInline Vec4 DivVec4(const Vec4& a, const float x, const float y, const float z, const float w) { - Vector4 r; + Vec4 r; r.x = a.x / x; r.y = a.y / y; r.z = a.z / z; @@ -1130,7 +1130,7 @@ slInline Vector4 DivVector4(const Vector4& a, const float x, const float y, cons } //---------------------------------------------------------------------------------------- -slInline void ScaleAddVector4(Vector4& r, const float s, const Vector4& v_scale, const Vector4& v_add) +slInline void ScaleAddVec4(Vec4& r, const float s, const Vec4& v_scale, const Vec4& v_add) { r.x = s * v_scale.x + v_add.x; r.y = s * v_scale.y + v_add.y; @@ -1139,9 +1139,9 @@ slInline void ScaleAddVector4(Vector4& r, const float s, const Vector4& v_scale, } //---------------------------------------------------------------------------------------- -slInline Vector4 ScaleAddVector4(const float s, const Vector4& v_scale, const Vector4& v_add) +slInline Vec4 ScaleAddVec4(const float s, const Vec4& v_scale, const Vec4& v_add) { - Vector4 r; + Vec4 r; r.x = s * v_scale.x + v_add.x; r.y = s * v_scale.y + v_add.y; r.z = s * v_scale.z + v_add.z; @@ -1150,27 +1150,27 @@ slInline Vector4 ScaleAddVector4(const float s, const Vector4& v_scale, const Ve } //---------------------------------------------------------------------------------------- -slInline void NormalizeVector4(Vector4& r, const Vector4& a) +slInline void NormalizeVec4(Vec4& r, const Vec4& a) { - float scale = 1.0f / LengthOfVector4( a ); - ScaleVector4( r, scale, a ); + float scale = 1.0f / LengthOfVec4( a ); + ScaleVec4( r, scale, a ); } //---------------------------------------------------------------------------------------- -slInline Vector4 NormalizeVector4(const Vector4& a) +slInline Vec4 NormalizeVec4(const Vec4& a) { - float scale = 1.0f / LengthOfVector4( a ); - return ScaleVector4( scale, a ); + float scale = 1.0f / LengthOfVec4( a ); + return ScaleVec4( scale, a ); } //---------------------------------------------------------------------------------------- -slInline float LengthOfVector4(const Vector4& a) +slInline float LengthOfVec4(const Vec4& a) { - return Sqrtf( DotVector4(a, a) ); + return (float)Sqrtf( DotVec4(a, a) ); } //---------------------------------------------------------------------------------------- -slInline float LengthSquaredOfVector4(const Vector4& a) +slInline float LengthSquaredOfVec4(const Vec4& a) { - return DotVector4( a, a ); + return DotVec4( a, a ); } diff --git a/Classes/cocos2d/CCAction.h b/Classes/cocos2d/CCAction.h new file mode 100644 index 0000000..327a251 --- /dev/null +++ b/Classes/cocos2d/CCAction.h @@ -0,0 +1,188 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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 +#import + +#import "ccTypes.h" + +enum { + //! Default tag + kCCActionTagInvalid = -1, +}; + +/** Base class for CCAction objects. + */ +@interface CCAction : NSObject +{ + id originalTarget_; + id target_; + NSInteger tag_; +} + +/** The "target". The action will modify the target properties. + 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'. + */ +@property (nonatomic,readonly,assign) id target; + +/** 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. + @since v0.8.2 +*/ +@property (nonatomic,readonly,assign) id originalTarget; + + +/** The action tag. An identifier of the action */ +@property (nonatomic,readwrite,assign) NSInteger tag; + +/** Allocates and initializes the action */ ++(id) action; + +/** Initializes the action */ +-(id) init; + +-(id) copyWithZone: (NSZone*) zone; + +//! return YES if the action has finished +-(BOOL) isDone; +//! called before the action start. It will also set the target. +-(void) startWithTarget:(id)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];" +-(void) stop; +//! called every frame with it's delta time. DON'T override unless you know what you are doing. +-(void) step: (ccTime) 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 +-(void) update: (ccTime) time; + +@end + +/** 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 + Infitite time actions are valid + */ +@interface CCFiniteTimeAction : CCAction +{ + //! duration in seconds + ccTime duration_; +} +//! duration in seconds of the action +@property (nonatomic,readwrite) ccTime duration; + +/** returns a reversed action */ +- (CCFiniteTimeAction*) reverse; +@end + + +@class CCActionInterval; +/** 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 + */ +@interface CCRepeatForever : CCAction +{ + CCActionInterval *other; +} +/** creates the action */ ++(id) actionWithAction: (CCActionInterval*) action; +/** initializes the action */ +-(id) initWithAction: (CCActionInterval*) action; +@end + +/** Changes the speed of an action, making it take longer (speed>1) + or less (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 + */ +@interface CCSpeed : CCAction +{ + CCActionInterval *other; + float speed; +} +/** alter the speed of the inner function in runtime */ +@property (nonatomic,readwrite) float speed; +/** creates the action */ ++(id) actionWithAction: (CCActionInterval*) action speed:(float)rate; +/** initializes the action */ +-(id) initWithAction: (CCActionInterval*) action speed:(float)rate; +@end + +@class CCNode; +/** CCFollow is an action that "follows" a node. + + Eg: + [layer runAction: [CCFollow actionWithTarget:hero]]; + + Instead of using CCCamera as a "follower", use this action instead. + @since v0.99.2 + */ +@interface CCFollow : CCAction +{ + /* node to follow */ + CCNode *followedNode_; + + /* whether camera should be limited to certain area */ + BOOL boundarySet; + + /* if screensize is bigger than the boundary - update not needed */ + BOOL boundaryFullyCovered; + + /* fast access to the screen dimensions */ + CGPoint halfScreenSize; + CGPoint fullScreenSize; + + /* world boundaries */ + float leftBoundary; + float rightBoundary; + float topBoundary; + float bottomBoundary; +} + +/** alter behavior - turn on/off boundary */ +@property (nonatomic,readwrite) BOOL boundarySet; + +/** creates the action with no boundary set */ ++(id) actionWithTarget:(CCNode *)followedNode; + +/** creates the action with a set boundary */ ++(id) actionWithTarget:(CCNode *)followedNode worldBoundary:(CGRect)rect; + +/** initializes the action */ +-(id) initWithTarget:(CCNode *)followedNode; + +/** initializes the action with a set boundary */ +-(id) initWithTarget:(CCNode *)followedNode worldBoundary:(CGRect)rect; + +@end + diff --git a/Classes/cocos2d/CCAction.m b/Classes/cocos2d/CCAction.m new file mode 100644 index 0000000..8fc3b4c --- /dev/null +++ b/Classes/cocos2d/CCAction.m @@ -0,0 +1,360 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + + +#import +#import "CCDirector.h" +#import "ccMacros.h" +#import "CCAction.h" +#import "CCActionInterval.h" +#import "Support/CGPointExtension.h" + +// +// Action Base Class +// +#pragma mark - +#pragma mark Action +@implementation CCAction + +@synthesize tag = tag_, target = target_, originalTarget = originalTarget_; + ++(id) action +{ + return [[[self alloc] init] autorelease]; +} + +-(id) init +{ + if( (self=[super init]) ) { + originalTarget_ = target_ = nil; + tag_ = kCCActionTagInvalid; + } + return self; +} + +-(void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + [super dealloc]; +} + +-(NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %08X | Tag = %i>", [self class], self, tag_]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] init]; + copy.tag = tag_; + return copy; +} + +-(void) startWithTarget:(id)aTarget +{ + originalTarget_ = target_ = aTarget; +} + +-(void) stop +{ + target_ = nil; +} + +-(BOOL) isDone +{ + return YES; +} + +-(void) step: (ccTime) dt +{ + NSLog(@"[Action step]. override me"); +} + +-(void) update: (ccTime) time +{ + NSLog(@"[Action update]. override me"); +} +@end + +// +// FiniteTimeAction +// +#pragma mark - +#pragma mark FiniteTimeAction +@implementation CCFiniteTimeAction +@synthesize duration = duration_; + +- (CCFiniteTimeAction*) reverse +{ + CCLOG(@"cocos2d: FiniteTimeAction#reverse: Implement me"); + return nil; +} +@end + + +// +// RepeatForever +// +#pragma mark - +#pragma mark RepeatForever +@implementation CCRepeatForever ++(id) actionWithAction: (CCActionInterval*) action +{ + return [[[self alloc] initWithAction: action] autorelease]; +} + +-(id) initWithAction: (CCActionInterval*) action +{ + if( (self=[super init]) ) + other = [action retain]; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithAction:[[other copy] autorelease] ]; + return copy; +} + +-(void) dealloc +{ + [other release]; + [super dealloc]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [other startWithTarget:target_]; +} + +-(void) step:(ccTime) dt +{ + [other step: dt]; + if( [other isDone] ) { + ccTime diff = dt + other.duration - other.elapsed; + [other startWithTarget:target_]; + + // to prevent jerk. issue #390 + [other step: diff]; + } +} + + +-(BOOL) isDone +{ + return NO; +} + +- (CCActionInterval *) reverse +{ + return [CCRepeatForever actionWithAction:[other reverse]]; +} + +@end + +// +// Speed +// +#pragma mark - +#pragma mark Speed +@implementation CCSpeed +@synthesize speed; + ++(id) actionWithAction: (CCActionInterval*) action speed:(float)r +{ + return [[[self alloc] initWithAction: action speed:r] autorelease]; +} + +-(id) initWithAction: (CCActionInterval*) action speed:(float)r +{ + if( (self=[super init]) ) { + other = [action retain]; + speed = r; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithAction:[[other copy] autorelease] speed:speed]; + return copy; +} + +-(void) dealloc +{ + [other release]; + [super dealloc]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [other startWithTarget:target_]; +} + +-(void) stop +{ + [other stop]; + [super stop]; +} + +-(void) step:(ccTime) dt +{ + [other step: dt * speed]; +} + +-(BOOL) isDone +{ + return [other isDone]; +} + +- (CCActionInterval *) reverse +{ + return [CCSpeed actionWithAction:[other reverse] speed:speed]; +} +@end + +// +// Follow +// +#pragma mark - +#pragma mark Follow +@implementation CCFollow + +@synthesize boundarySet; + ++(id) actionWithTarget:(CCNode *) fNode +{ + return [[[self alloc] initWithTarget:fNode] autorelease]; +} + ++(id) actionWithTarget:(CCNode *) fNode worldBoundary:(CGRect)rect +{ + return [[[self alloc] initWithTarget:fNode worldBoundary:rect] autorelease]; +} + +-(id) initWithTarget:(CCNode *)fNode +{ + if( (self=[super init]) ) { + + followedNode_ = [fNode retain]; + boundarySet = FALSE; + boundaryFullyCovered = FALSE; + + CGSize s = [[CCDirector sharedDirector] winSize]; + fullScreenSize = CGPointMake(s.width, s.height); + halfScreenSize = ccpMult(fullScreenSize, .5f); + } + + return self; +} + +-(id) initWithTarget:(CCNode *)fNode worldBoundary:(CGRect)rect +{ + if( (self=[super init]) ) { + + followedNode_ = [fNode retain]; + boundarySet = TRUE; + boundaryFullyCovered = FALSE; + + CGSize winSize = [[CCDirector sharedDirector] winSize]; + fullScreenSize = CGPointMake(winSize.width, winSize.height); + halfScreenSize = ccpMult(fullScreenSize, .5f); + + 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 self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] init]; + copy.tag = tag_; + return copy; +} + +-(void) step:(ccTime) dt +{ +#define CLAMP(x,y,z) MIN(MAX(x,y),z) + + if(boundarySet) + { + // whole map fits inside a single screen, no need to modify the position - unless map boundaries are increased + if(boundaryFullyCovered) + return; + + CGPoint tempPos = ccpSub( halfScreenSize, followedNode_.position); + [target_ setPosition:ccp(CLAMP(tempPos.x,leftBoundary,rightBoundary), CLAMP(tempPos.y,bottomBoundary,topBoundary))]; + } + else + [target_ setPosition:ccpSub( halfScreenSize, followedNode_.position )]; + +#undef CLAMP +} + + +-(BOOL) isDone +{ + return !followedNode_.isRunning; +} + +-(void) stop +{ + target_ = nil; + [super stop]; +} + +-(void) dealloc +{ + [followedNode_ release]; + [super dealloc]; +} + +@end + + diff --git a/Classes/cocos2d/CCActionCamera.h b/Classes/cocos2d/CCActionCamera.h new file mode 100644 index 0000000..131c084 --- /dev/null +++ b/Classes/cocos2d/CCActionCamera.h @@ -0,0 +1,72 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + +#import "CCActionInterval.h" + +@class CCCamera; + +/** Base class for CCCamera actions + */ +@interface CCActionCamera : CCActionInterval +{ + float centerXOrig_; + float centerYOrig_; + float centerZOrig_; + + float eyeXOrig_; + float eyeYOrig_; + float eyeZOrig_; + + float upXOrig_; + float upYOrig_; + float upZOrig_; +} +@end + +/** CCOrbitCamera action + Orbits the camera around the center of the screen using spherical coordinates + */ +@interface CCOrbitCamera : CCActionCamera +{ + float radius_; + float deltaRadius_; + float angleZ_; + float deltaAngleZ_; + float angleX_; + float deltaAngleX_; + + float radZ_; + float radDeltaZ_; + float radX_; + float radDeltaX_; + +} +/** creates a CCOrbitCamera action with radius, delta-radius, z, deltaZ, x, deltaX */ ++(id) actionWithDuration:(float) t radius:(float)r deltaRadius:(float) dr angleZ:(float)z deltaAngleZ:(float)dz angleX:(float)x deltaAngleX:(float)dx; +/** initializes a CCOrbitCamera action with radius, delta-radius, z, deltaZ, x, deltaX */ +-(id) initWithDuration:(float) t radius:(float)r deltaRadius:(float) dr angleZ:(float)z deltaAngleZ:(float)dz angleX:(float)x deltaAngleX:(float)dx; +/** positions the camera according to spherical coordinates */ +-(void) sphericalRadius:(float*) r zenith:(float*) zenith azimuth:(float*) azimuth; +@end diff --git a/Classes/cocos2d/CCActionCamera.m b/Classes/cocos2d/CCActionCamera.m new file mode 100644 index 0000000..5134c6f --- /dev/null +++ b/Classes/cocos2d/CCActionCamera.m @@ -0,0 +1,146 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + + +#import "CCActionCamera.h" +#import "CCNode.h" +#import "CCCamera.h" +#import "ccMacros.h" + +// +// CameraAction +// +@implementation CCActionCamera +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + CCCamera *camera = [target_ camera]; + [camera centerX:¢erXOrig_ centerY:¢erYOrig_ centerZ:¢erZOrig_]; + [camera eyeX:&eyeXOrig_ eyeY:&eyeYOrig_ eyeZ:&eyeZOrig_]; + [camera upX:&upXOrig_ upY:&upYOrig_ upZ: &upZOrig_]; +} + +-(id) reverse +{ + return [CCReverseTime actionWithAction:self]; +} +@end + +@implementation CCOrbitCamera ++(id) actionWithDuration:(float)t radius:(float)r deltaRadius:(float) dr angleZ:(float)z deltaAngleZ:(float)dz angleX:(float)x deltaAngleX:(float)dx +{ + return [[[self alloc] initWithDuration:t radius:r deltaRadius:dr angleZ:z deltaAngleZ:dz angleX:x deltaAngleX:dx] autorelease]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone: zone] initWithDuration:duration_ radius:radius_ deltaRadius:deltaRadius_ angleZ:angleZ_ deltaAngleZ:deltaAngleZ_ angleX:angleX_ deltaAngleX:deltaAngleX_]; +} + + +-(id) initWithDuration:(float)t radius:(float)r deltaRadius:(float) dr angleZ:(float)z deltaAngleZ:(float)dz angleX:(float)x deltaAngleX:(float)dx +{ + if((self=[super initWithDuration:t]) ) { + + radius_ = r; + deltaRadius_ = dr; + angleZ_ = z; + deltaAngleZ_ = dz; + angleX_ = x; + deltaAngleX_ = dx; + + radDeltaZ_ = (CGFloat)CC_DEGREES_TO_RADIANS(dz); + radDeltaX_ = (CGFloat)CC_DEGREES_TO_RADIANS(dx); + } + + return self; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + float r, zenith, azimuth; + + [self sphericalRadius: &r zenith:&zenith azimuth:&azimuth]; + +#if 0 // isnan() is not supported on the simulator, and isnan() always returns false. + if( isnan(radius_) ) + radius_ = r; + + if( isnan( angleZ_) ) + angleZ_ = (CGFloat)CC_RADIANS_TO_DEGREES(zenith); + + if( isnan( angleX_ ) ) + angleX_ = (CGFloat)CC_RADIANS_TO_DEGREES(azimuth); +#endif + + radZ_ = (CGFloat)CC_DEGREES_TO_RADIANS(angleZ_); + radX_ = (CGFloat)CC_DEGREES_TO_RADIANS(angleX_); +} + +-(void) update: (ccTime) dt +{ + float r = (radius_ + deltaRadius_ * dt) *[CCCamera getZEye]; + float za = radZ_ + radDeltaZ_ * dt; + float xa = radX_ + radDeltaX_ * dt; + + float i = sinf(za) * cosf(xa) * r + centerXOrig_; + float j = sinf(za) * sinf(xa) * r + centerYOrig_; + float k = cosf(za) * r + centerZOrig_; + + [[target_ camera] setEyeX:i eyeY:j eyeZ:k]; +} + +-(void) sphericalRadius:(float*) newRadius zenith:(float*) zenith azimuth:(float*) azimuth +{ + float ex, ey, ez, cx, cy, cz, x, y, z; + float r; // radius + float s; + + CCCamera *camera = [target_ camera]; + [camera eyeX:&ex eyeY:&ey eyeZ:&ez]; + [camera centerX:&cx centerY:&cy centerZ:&cz]; + + x = ex-cx; + y = ey-cy; + z = ez-cz; + + r = sqrtf( x*x + y*y + z*z); + s = sqrtf( x*x + y*y); + 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 / [CCCamera getZEye]; +} +@end diff --git a/Classes/cocos2d/CCActionEase.h b/Classes/cocos2d/CCActionEase.h new file mode 100644 index 0000000..fced701 --- /dev/null +++ b/Classes/cocos2d/CCActionEase.h @@ -0,0 +1,159 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2009 Jason Booth + * + * 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. + * + */ + + +#import "CCActionInterval.h" + +/** Base class for Easing actions + */ +@interface CCActionEase : CCActionInterval +{ + CCActionInterval * other; +} +/** creates the action */ ++(id) actionWithAction: (CCActionInterval*) action; +/** initializes the action */ +-(id) initWithAction: (CCActionInterval*) action; +@end + +/** Base class for Easing actions with rate parameters + */ +@interface CCEaseRateAction : CCActionEase +{ + float rate; +} +/** rate value for the actions */ +@property (nonatomic,readwrite,assign) float rate; +/** Creates the action with the inner action and the rate parameter */ ++(id) actionWithAction: (CCActionInterval*) action rate:(float)rate; +/** Initializes the action with the inner action and the rate parameter */ +-(id) initWithAction: (CCActionInterval*) action rate:(float)rate; +@end + +/** CCEaseIn action with a rate + */ +@interface CCEaseIn : CCEaseRateAction {} @end + +/** CCEaseOut action with a rate + */ +@interface CCEaseOut : CCEaseRateAction {} @end + +/** CCEaseInOut action with a rate + */ +@interface CCEaseInOut : CCEaseRateAction {} @end + +/** CCEase Exponential In + */ +@interface CCEaseExponentialIn : CCActionEase {} @end +/** Ease Exponential Out + */ +@interface CCEaseExponentialOut : CCActionEase {} @end +/** Ease Exponential InOut + */ +@interface CCEaseExponentialInOut : CCActionEase {} @end +/** Ease Sine In + */ +@interface CCEaseSineIn : CCActionEase {} @end +/** Ease Sine Out + */ +@interface CCEaseSineOut : CCActionEase {} @end +/** Ease Sine InOut + */ +@interface CCEaseSineInOut : CCActionEase {} @end + +/** Ease Elastic abstract class + @since v0.8.2 + */ +@interface CCEaseElastic : CCActionEase +{ + float period_; +} + +/** period of the wave in radians. default is 0.3 */ +@property (nonatomic,readwrite) float period; + +/** Creates the action with the inner action and the period in radians (default is 0.3) */ ++(id) actionWithAction: (CCActionInterval*) action period:(float)period; +/** Initializes the action with the inner action and the period in radians (default is 0.3) */ +-(id) initWithAction: (CCActionInterval*) action period:(float)period; +@end + +/** Ease Elastic In action. + @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 + */ +@interface CCEaseElasticIn : CCEaseElastic {} @end +/** Ease Elastic Out action. + @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 + */ +@interface CCEaseElasticOut : CCEaseElastic {} @end +/** Ease Elastic InOut action. + @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 + */ +@interface CCEaseElasticInOut : CCEaseElastic {} @end + +/** CCEaseBounce abstract class. + @since v0.8.2 +*/ +@interface CCEaseBounce : CCActionEase {} @end + +/** CCEaseBounceIn action. + @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 +*/ +@interface CCEaseBounceIn : CCEaseBounce {} @end + +/** EaseBounceOut action. + @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 + */ +@interface CCEaseBounceOut : CCEaseBounce {} @end + +/** CCEaseBounceInOut action. + @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 + */ +@interface CCEaseBounceInOut : CCEaseBounce {} @end + +/** CCEaseBackIn action. + @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 + */ +@interface CCEaseBackIn : CCActionEase {} @end + +/** CCEaseBackOut action. + @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 + */ +@interface CCEaseBackOut : CCActionEase {} @end + +/** CCEaseBackInOut action. + @warning This action doesn't use a bijective fucntion. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 + */ +@interface CCEaseBackInOut : CCActionEase {} @end + diff --git a/Classes/cocos2d/CCActionEase.m b/Classes/cocos2d/CCActionEase.m new file mode 100644 index 0000000..f28be11 --- /dev/null +++ b/Classes/cocos2d/CCActionEase.m @@ -0,0 +1,534 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2009 Jason Booth + * + * 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 + */ + +#import "CCActionEase.h" + +#ifndef M_PI_X_2 +#define M_PI_X_2 (float)M_PI * 2.0f +#endif + +#pragma mark EaseAction + +// +// EaseAction +// +@implementation CCActionEase + ++(id) actionWithAction: (CCActionInterval*) action +{ + return [[[self alloc] initWithAction: action] autorelease ]; +} + +-(id) initWithAction: (CCActionInterval*) action +{ + NSAssert( action!=nil, @"Ease: arguments must be non-nil"); + + if( (self=[super initWithDuration: action.duration]) ) + other = [action retain]; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[other copy] autorelease]]; + return copy; +} + +-(void) dealloc +{ + [other release]; + [super dealloc]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [other startWithTarget:target_]; +} + +-(void) stop +{ + [other stop]; + [super stop]; +} + +-(void) update: (ccTime) t +{ + [other update: t]; +} + +-(CCActionInterval*) reverse +{ + return [[self class] actionWithAction: [other reverse]]; +} +@end + + +#pragma mark - +#pragma mark EaseRate + +// +// EaseRateAction +// +@implementation CCEaseRateAction +@synthesize rate; ++(id) actionWithAction: (CCActionInterval*) action rate:(float)aRate +{ + return [[[self alloc] initWithAction: action rate:aRate] autorelease ]; +} + +-(id) initWithAction: (CCActionInterval*) action rate:(float)aRate +{ + if( (self=[super initWithAction:action ]) ) + self.rate = aRate; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[other copy] autorelease] rate:rate]; + return copy; +} + +-(void) dealloc +{ + [super dealloc]; +} + +-(CCActionInterval*) reverse +{ + return [[self class] actionWithAction: [other reverse] rate:1/rate]; +} +@end + +// +// EeseIn +// +@implementation CCEaseIn +-(void) update: (ccTime) t +{ + [other update: powf(t,rate)]; +} +@end + +// +// EaseOut +// +@implementation CCEaseOut +-(void) update: (ccTime) t +{ + [other update: powf(t,1/rate)]; +} +@end + +// +// EaseInOut +// +@implementation CCEaseInOut +-(void) update: (ccTime) t +{ + int sign =1; + int r = (int) rate; + if (r % 2 == 0) + sign = -1; + t *= 2; + if (t < 1) + [other update: 0.5f * powf (t, rate)]; + else + [other update: sign*0.5f * (powf (t-2, rate) + sign*2)]; +} + +// InOut and OutIn are symmetrical +-(CCActionInterval*) reverse +{ + return [[self class] actionWithAction: [other reverse] rate:rate]; +} + +@end + +#pragma mark - +#pragma mark EaseExponential + +// +// EaseExponentialIn +// +@implementation CCEaseExponentialIn +-(void) update: (ccTime) t +{ + [other update: (t==0) ? 0 : powf(2, 10 * (t/1 - 1)) - 1 * 0.001f]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseExponentialOut actionWithAction: [other reverse]]; +} +@end + +// +// EaseExponentialOut +// +@implementation CCEaseExponentialOut +-(void) update: (ccTime) t +{ + [other update: (t==1) ? 1 : (-powf(2, -10 * t/1) + 1)]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseExponentialIn actionWithAction: [other reverse]]; +} +@end + +// +// EaseExponentialInOut +// +@implementation CCEaseExponentialInOut +-(void) update: (ccTime) t +{ + t /= 0.5f; + if (t < 1) + t = 0.5f * powf(2, 10 * (t - 1)); + else + t = 0.5f * (-powf(2, -10 * (t -1) ) + 2); + + [other update:t]; +} +@end + + +#pragma mark - +#pragma mark EaseSin actions + +// +// EaseSineIn +// +@implementation CCEaseSineIn +-(void) update: (ccTime) t +{ + [other update:-1*cosf(t * (float)M_PI_2) +1]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseSineOut actionWithAction: [other reverse]]; +} +@end + +// +// EaseSineOut +// +@implementation CCEaseSineOut +-(void) update: (ccTime) t +{ + [other update:sinf(t * (float)M_PI_2)]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseSineIn actionWithAction: [other reverse]]; +} +@end + +// +// EaseSineInOut +// +@implementation CCEaseSineInOut +-(void) update: (ccTime) t +{ + [other update:-0.5f*(cosf( (float)M_PI*t) - 1)]; +} +@end + +#pragma mark - +#pragma mark EaseElastic actions + +// +// EaseElastic +// +@implementation CCEaseElastic + +@synthesize period = period_; + ++(id) actionWithAction: (CCActionInterval*) action +{ + return [[[self alloc] initWithAction:action period:0.3f] autorelease]; +} + ++(id) actionWithAction: (CCActionInterval*) action period:(float)period +{ + return [[[self alloc] initWithAction:action period:period] autorelease]; +} + +-(id) initWithAction: (CCActionInterval*) action +{ + return [self initWithAction:action period:0.3f]; +} + +-(id) initWithAction: (CCActionInterval*) action period:(float)period +{ + if( (self=[super initWithAction:action]) ) + period_ = period; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[other copy] autorelease] period:period_]; + return copy; +} + +-(CCActionInterval*) reverse +{ + NSAssert(NO,@"Override me"); + return nil; +} + +@end + +// +// EaseElasticIn +// + +@implementation CCEaseElasticIn +-(void) update: (ccTime) t +{ + ccTime newT = 0; + if (t == 0 || t == 1) + newT = t; + + else { + float s = period_ / 4; + t = t - 1; + newT = -powf(2, 10 * t) * sinf( (t-s) *M_PI_X_2 / period_); + } + [other update:newT]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseElasticOut actionWithAction: [other reverse] period:period_]; +} + +@end + +// +// EaseElasticOut +// +@implementation CCEaseElasticOut + +-(void) update: (ccTime) t +{ + ccTime newT = 0; + if (t == 0 || t == 1) { + newT = t; + + } else { + float s = period_ / 4; + newT = powf(2, -10 * t) * sinf( (t-s) *M_PI_X_2 / period_) + 1; + } + [other update:newT]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseElasticIn actionWithAction: [other reverse] period:period_]; +} + +@end + +// +// EaseElasticInOut +// +@implementation CCEaseElasticInOut +-(void) update: (ccTime) t +{ + ccTime newT = 0; + + if( t == 0 || t == 1 ) + newT = t; + else { + t = t * 2; + if(! period_ ) + period_ = 0.3f * 1.5f; + ccTime s = period_ / 4; + + t = t -1; + if( t < 0 ) + newT = -0.5f * powf(2, 10 * t) * sinf((t - s) * M_PI_X_2 / period_); + else + newT = powf(2, -10 * t) * sinf((t - s) * M_PI_X_2 / period_) * 0.5f + 1; + } + [other update:newT]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseElasticInOut actionWithAction: [other reverse] period:period_]; +} + +@end + +#pragma mark - +#pragma mark EaseBounce actions + +// +// EaseBounce +// +@implementation CCEaseBounce +-(ccTime) bounceTime:(ccTime) t +{ + if (t < 1 / 2.75) { + return 7.5625f * t * t; + } + else if (t < 2 / 2.75) { + t -= 1.5f / 2.75f; + return 7.5625f * t * t + 0.75f; + } + else if (t < 2.5 / 2.75) { + t -= 2.25f / 2.75f; + return 7.5625f * t * t + 0.9375f; + } + + t -= 2.625f / 2.75f; + return 7.5625f * t * t + 0.984375f; +} +@end + +// +// EaseBounceIn +// + +@implementation CCEaseBounceIn + +-(void) update: (ccTime) t +{ + ccTime newT = 1 - [self bounceTime:1-t]; + [other update:newT]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseBounceOut actionWithAction: [other reverse]]; +} + +@end + +@implementation CCEaseBounceOut + +-(void) update: (ccTime) t +{ + ccTime newT = [self bounceTime:t]; + [other update:newT]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseBounceIn actionWithAction: [other reverse]]; +} + +@end + +@implementation CCEaseBounceInOut + +-(void) update: (ccTime) t +{ + ccTime newT = 0; + if (t < 0.5) { + t = t * 2; + newT = (1 - [self bounceTime:1-t] ) * 0.5f; + } else + newT = [self bounceTime:t * 2 - 1] * 0.5f + 0.5f; + + [other update:newT]; +} +@end + +#pragma mark - +#pragma mark Ease Back actions + +// +// EaseBackIn +// +@implementation CCEaseBackIn + +-(void) update: (ccTime) t +{ + ccTime overshoot = 1.70158f; + [other update: t * t * ((overshoot + 1) * t - overshoot)]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseBackOut actionWithAction: [other reverse]]; +} +@end + +// +// EaseBackOut +// +@implementation CCEaseBackOut +-(void) update: (ccTime) t +{ + ccTime overshoot = 1.70158f; + + t = t - 1; + [other update: t * t * ((overshoot + 1) * t + overshoot) + 1]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseBackIn actionWithAction: [other reverse]]; +} +@end + +// +// EaseBackInOut +// +@implementation CCEaseBackInOut + +-(void) update: (ccTime) t +{ + ccTime overshoot = 1.70158f * 1.525f; + + t = t * 2; + if (t < 1) + [other update: (t * t * ((overshoot + 1) * t - overshoot)) / 2]; + else { + t = t - 2; + [other update: (t * t * ((overshoot + 1) * t + overshoot)) / 2 + 1]; + } +} +@end diff --git a/Classes/cocos2d/CCActionGrid.h b/Classes/cocos2d/CCActionGrid.h new file mode 100644 index 0000000..13b6bc7 --- /dev/null +++ b/Classes/cocos2d/CCActionGrid.h @@ -0,0 +1,165 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * 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. + * + */ + + +#import "CCActionInterval.h" +#import "CCActionInstant.h" +#import "CCGrid.h" + +@class CCGridBase; + +/** Base class for Grid actions */ +@interface CCGridAction : CCActionInterval +{ + ccGridSize gridSize_; +} + +/** size of the grid */ +@property (nonatomic,readwrite) ccGridSize gridSize; + +/** creates the action with size and duration */ ++(id) actionWithSize:(ccGridSize)size duration:(ccTime)d; +/** initializes the action with size and duration */ +-(id) initWithSize:(ccGridSize)gridSize duration:(ccTime)d; +/** returns the grid */ +-(CCGridBase *)grid; + +@end + +//////////////////////////////////////////////////////////// + +/** Base class for CCGrid3D actions. + Grid3D actions can modify a non-tiled grid. + */ +@interface CCGrid3DAction : CCGridAction +{ +} + +/** returns the vertex than belongs to certain position in the grid */ +-(ccVertex3F)vertex:(ccGridSize)pos; +/** returns the non-transformed vertex than belongs to certain position in the grid */ +-(ccVertex3F)originalVertex:(ccGridSize)pos; +/** sets a new vertex to a certain position of the grid */ +-(void)setVertex:(ccGridSize)pos vertex:(ccVertex3F)vertex; + +@end + +//////////////////////////////////////////////////////////// + +/** Base class for CCTiledGrid3D actions */ +@interface CCTiledGrid3DAction : CCGridAction +{ +} + +/** returns the tile that belongs to a certain position of the grid */ +-(ccQuad3)tile:(ccGridSize)pos; +/** returns the non-transformed tile that belongs to a certain position of the grid */ +-(ccQuad3)originalTile:(ccGridSize)pos; +/** sets a new tile to a certain position of the grid */ +-(void)setTile:(ccGridSize)pos coords:(ccQuad3)coords; + +@end + +//////////////////////////////////////////////////////////// + +/** CCAccelDeccelAmplitude action */ +@interface CCAccelDeccelAmplitude : CCActionInterval +{ + float rate; + CCActionInterval *other; +} + +/** amplitude rate */ +@property (nonatomic,readwrite) float rate; + +/** creates the action with an inner action that has the amplitude property, and a duration time */ ++(id)actionWithAction:(CCAction*)action duration:(ccTime)d; +/** initializes the action with an inner action that has the amplitude property, and a duration time */ +-(id)initWithAction:(CCAction*)action duration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCAccelAmplitude action */ +@interface CCAccelAmplitude : CCActionInterval +{ + float rate; + CCActionInterval *other; +} + +/** amplitude rate */ +@property (nonatomic,readwrite) float rate; + +/** creates the action with an inner action that has the amplitude property, and a duration time */ ++(id)actionWithAction:(CCAction*)action duration:(ccTime)d; +/** initializes the action with an inner action that has the amplitude property, and a duration time */ +-(id)initWithAction:(CCAction*)action duration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCDeccelAmplitude action */ +@interface CCDeccelAmplitude : CCActionInterval +{ + float rate; + CCActionInterval *other; +} + +/** amplitude rate */ +@property (nonatomic,readwrite) float rate; + +/** creates the action with an inner action that has the amplitude property, and a duration time */ ++(id)actionWithAction:(CCAction*)action duration:(ccTime)d; +/** initializes the action with an inner action that has the amplitude property, and a duration time */ +-(id)initWithAction:(CCAction*)action duration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCStopGrid action. + Don't call this action if another grid action is active. + Call if you want to remove the the grid effect. Example: + [Sequence actions:[Lens ...], [StopGrid action], nil]; + */ +@interface CCStopGrid : CCActionInstant +{ +} +@end + +//////////////////////////////////////////////////////////// + +/** CCReuseGrid action */ +@interface CCReuseGrid : CCActionInstant +{ + int t; +} +/** creates an action with the number of times that the current grid will be reused */ ++(id) actionWithTimes: (int) times; +/** initializes an action with the number of times that the current grid will be reused */ +-(id) initWithTimes: (int) times; +@end diff --git a/Classes/cocos2d/CCActionGrid.m b/Classes/cocos2d/CCActionGrid.m new file mode 100644 index 0000000..b2d8f98 --- /dev/null +++ b/Classes/cocos2d/CCActionGrid.m @@ -0,0 +1,386 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * 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. + * + */ + + +#import "CCActionGrid.h" +#import "CCDirector.h" + +#pragma mark - +#pragma mark GridAction + +@implementation CCGridAction + +@synthesize gridSize = gridSize_; + ++(id) actionWithSize:(ccGridSize)size duration:(ccTime)d +{ + return [[[self alloc] initWithSize:size duration:d ] autorelease]; +} + +-(id) initWithSize:(ccGridSize)gSize duration:(ccTime)d +{ + if ( (self = [super initWithDuration:d]) ) + { + gridSize_ = gSize; + } + + return self; +} + +-(void)startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + + CCGridBase *newgrid = [self grid]; + + CCNode *t = (CCNode*) target_; + CCGridBase *targetGrid = [t grid]; + + if ( targetGrid && targetGrid.reuseGrid > 0 ) + { + if ( targetGrid.active && targetGrid.gridSize.x == gridSize_.x && targetGrid.gridSize.y == gridSize_.y && [targetGrid isKindOfClass:[newgrid class]] ) + [targetGrid reuse]; + else + [NSException raise:@"GridBase" format:@"Cannot reuse grid"]; + } + else + { + if ( targetGrid && targetGrid.active ) + targetGrid.active = NO; + + t.grid = newgrid; + t.grid.active = YES; + } +} + +-(CCGridBase *)grid +{ + [NSException raise:@"GridBase" format:@"Abstract class needs implementation"]; + return nil; +} + +- (CCActionInterval*) reverse +{ + return [CCReverseTime actionWithAction:self]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithSize:gridSize_ duration:duration_]; + return copy; +} +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark Grid3DAction + +@implementation CCGrid3DAction + +-(CCGridBase *)grid +{ + return [CCGrid3D gridWithSize:gridSize_]; +} + +-(ccVertex3F)vertex:(ccGridSize)pos +{ + CCGrid3D *g = (CCGrid3D *)[target_ grid]; + return [g vertex:pos]; +} + +-(ccVertex3F)originalVertex:(ccGridSize)pos +{ + CCGrid3D *g = (CCGrid3D *)[target_ grid]; + return [g originalVertex:pos]; +} + +-(void)setVertex:(ccGridSize)pos vertex:(ccVertex3F)vertex +{ + CCGrid3D *g = (CCGrid3D *)[target_ grid]; + return [g setVertex:pos vertex:vertex]; +} +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark TiledGrid3DAction + +@implementation CCTiledGrid3DAction + +-(CCGridBase *)grid +{ + return [CCTiledGrid3D gridWithSize:gridSize_]; +} + +-(ccQuad3)tile:(ccGridSize)pos +{ + CCTiledGrid3D *g = (CCTiledGrid3D *)[target_ grid]; + return [g tile:pos]; +} + +-(ccQuad3)originalTile:(ccGridSize)pos +{ + CCTiledGrid3D *g = (CCTiledGrid3D *)[target_ grid]; + return [g originalTile:pos]; +} + +-(void)setTile:(ccGridSize)pos coords:(ccQuad3)coords +{ + CCTiledGrid3D *g = (CCTiledGrid3D *)[target_ grid]; + [g setTile:pos coords:coords]; +} + +@end + +//////////////////////////////////////////////////////////// + +@interface CCActionInterval (Amplitude) +-(void)setAmplitudeRate:(CGFloat)amp; +-(CGFloat)getAmplitudeRate; +@end + +@implementation CCActionInterval (Amplitude) +-(void)setAmplitudeRate:(CGFloat)amp +{ + [NSException raise:@"IntervalAction (Amplitude)" format:@"Abstract class needs implementation"]; +} + +-(CGFloat)getAmplitudeRate +{ + [NSException raise:@"IntervalAction (Amplitude)" format:@"Abstract class needs implementation"]; + return 0; +} +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark AccelDeccelAmplitude + +@implementation CCAccelDeccelAmplitude + +@synthesize rate; + ++(id)actionWithAction:(CCAction*)action duration:(ccTime)d +{ + return [[[self alloc] initWithAction:action duration:d ] autorelease]; +} + +-(id)initWithAction:(CCAction *)action duration:(ccTime)d +{ + if ( (self = [super initWithDuration:d]) ) + { + rate = 1.0f; + other = [action retain]; + } + + return self; +} + +-(void)dealloc +{ + [other release]; + [super dealloc]; +} + +-(void)startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [other startWithTarget:target_]; +} + +-(void) update: (ccTime) time +{ + float f = time*2; + + if (f > 1) + { + f -= 1; + f = 1 - f; + } + + [other setAmplitudeRate:powf(f, rate)]; + [other update:time]; +} + +- (CCActionInterval*) reverse +{ + return [CCAccelDeccelAmplitude actionWithAction:[other reverse] duration:duration_]; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark AccelAmplitude + +@implementation CCAccelAmplitude + +@synthesize rate; + ++(id)actionWithAction:(CCAction*)action duration:(ccTime)d +{ + return [[[self alloc] initWithAction:action duration:d ] autorelease]; +} + +-(id)initWithAction:(CCAction *)action duration:(ccTime)d +{ + if ( (self = [super initWithDuration:d]) ) + { + rate = 1.0f; + other = [action retain]; + } + + return self; +} + +-(void)dealloc +{ + [other release]; + [super dealloc]; +} + +-(void)startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [other startWithTarget:target_]; +} + +-(void) update: (ccTime) time +{ + [other setAmplitudeRate:powf(time, rate)]; + [other update:time]; +} + +- (CCActionInterval*) reverse +{ + return [CCAccelAmplitude actionWithAction:[other reverse] duration:self.duration]; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark DeccelAmplitude + +@implementation CCDeccelAmplitude + +@synthesize rate; + ++(id)actionWithAction:(CCAction*)action duration:(ccTime)d +{ + return [[[self alloc] initWithAction:action duration:d ] autorelease]; +} + +-(id)initWithAction:(CCAction *)action duration:(ccTime)d +{ + if ( (self = [super initWithDuration:d]) ) + { + rate = 1.0f; + other = [action retain]; + } + + return self; +} + +-(void)dealloc +{ + [other release]; + [super dealloc]; +} + +-(void)startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [other startWithTarget:target_]; +} + +-(void) update: (ccTime) time +{ + [other setAmplitudeRate:powf((1-time), rate)]; + [other update:time]; +} + +- (CCActionInterval*) reverse +{ + return [CCDeccelAmplitude actionWithAction:[other reverse] duration:self.duration]; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark StopGrid + +@implementation CCStopGrid + +-(void)startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + + if ( [[self target] grid] && [[[self target] grid] active] ) { + [[[self target] grid] setActive: NO]; + +// [[self target] setGrid: nil]; + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark ReuseGrid + +@implementation CCReuseGrid + ++(id)actionWithTimes:(int)times +{ + return [[[self alloc] initWithTimes:times ] autorelease]; +} + +-(id)initWithTimes:(int)times +{ + if ( (self = [super init]) ) + t = times; + + return self; +} + +-(void)startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + + CCNode *myTarget = (CCNode*) [self target]; + if ( myTarget.grid && myTarget.grid.active ) + myTarget.grid.reuseGrid += t; +} + +@end diff --git a/Classes/cocos2d/CCActionGrid3D.h b/Classes/cocos2d/CCActionGrid3D.h new file mode 100644 index 0000000..a8003f4 --- /dev/null +++ b/Classes/cocos2d/CCActionGrid3D.h @@ -0,0 +1,208 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * 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. + * + */ + + +#import "CCActionGrid.h" + +/** CCWaves3D action */ +@interface CCWaves3D : CCGrid3DAction +{ + int waves; + float amplitude; + float amplitudeRate; +} + +/** amplitude of the wave */ +@property (nonatomic,readwrite) float amplitude; +/** amplitude rate of the wave */ +@property (nonatomic,readwrite) float amplitudeRate; + ++(id)actionWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d; +-(id)initWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCFlipX3D action */ +@interface CCFlipX3D : CCGrid3DAction +{ +} + +/** creates the action with duration */ ++(id) actionWithDuration:(ccTime)d; +/** initizlies the action with duration */ +-(id) initWithDuration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCFlipY3D action */ +@interface CCFlipY3D : CCFlipX3D +{ +} + +@end + +//////////////////////////////////////////////////////////// + +/** CCLens3D action */ +@interface CCLens3D : CCGrid3DAction +{ + CGPoint position_; + CGPoint positionInPixels_; + float radius_; + float lensEffect_; + BOOL dirty_; +} + +/** lens effect. Defaults to 0.7 - 0 means no effect, 1 is very strong effect */ +@property (nonatomic,readwrite) float lensEffect; +/** lens center position in Points */ +@property (nonatomic,readwrite) CGPoint position; + +/** creates the action with center position in Points, radius, a grid size and duration */ ++(id)actionWithPosition:(CGPoint)pos radius:(float)r grid:(ccGridSize)gridSize duration:(ccTime)d; +/** initializes the action with center position in Points, radius, a grid size and duration */ +-(id)initWithPosition:(CGPoint)pos radius:(float)r grid:(ccGridSize)gridSize duration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCRipple3D action */ +@interface CCRipple3D : CCGrid3DAction +{ + CGPoint position_; + CGPoint positionInPixels_; + float radius_; + int waves_; + float amplitude_; + float amplitudeRate_; +} + +/** center position in Points */ +@property (nonatomic,readwrite) CGPoint position; +/** amplitude */ +@property (nonatomic,readwrite) float amplitude; +/** amplitude rate */ +@property (nonatomic,readwrite) float amplitudeRate; + +/** creates the action with a position in points, radius, number of waves, amplitude, a grid size and duration */ ++(id)actionWithPosition:(CGPoint)pos radius:(float)r waves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d; +/** initializes the action with a position in points, radius, number of waves, amplitude, a grid size and duration */ +-(id)initWithPosition:(CGPoint)pos radius:(float)r waves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCShaky3D action */ +@interface CCShaky3D : CCGrid3DAction +{ + int randrange; + BOOL shakeZ; +} + +/** creates the action with a range, shake Z vertices, a grid and duration */ ++(id)actionWithRange:(int)range shakeZ:(BOOL)shakeZ grid:(ccGridSize)gridSize duration:(ccTime)d; +/** initializes the action with a range, shake Z vertices, a grid and duration */ +-(id)initWithRange:(int)range shakeZ:(BOOL)shakeZ grid:(ccGridSize)gridSize duration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCLiquid action */ +@interface CCLiquid : CCGrid3DAction +{ + int waves; + float amplitude; + float amplitudeRate; + +} + +/** amplitude */ +@property (nonatomic,readwrite) float amplitude; +/** amplitude rate */ +@property (nonatomic,readwrite) float amplitudeRate; + +/** creates the action with amplitude, a grid and duration */ ++(id)actionWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d; +/** initializes the action with amplitude, a grid and duration */ +-(id)initWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCWaves action */ +@interface CCWaves : CCGrid3DAction +{ + int waves; + float amplitude; + float amplitudeRate; + BOOL vertical; + BOOL horizontal; +} + +/** amplitude */ +@property (nonatomic,readwrite) float amplitude; +/** amplitude rate */ +@property (nonatomic,readwrite) float amplitudeRate; + +/** initializes the action with amplitude, horizontal sin, vertical sin, a grid and duration */ ++(id)actionWithWaves:(int)wav amplitude:(float)amp horizontal:(BOOL)h vertical:(BOOL)v grid:(ccGridSize)gridSize duration:(ccTime)d; +/** creates the action with amplitude, horizontal sin, vertical sin, a grid and duration */ +-(id)initWithWaves:(int)wav amplitude:(float)amp horizontal:(BOOL)h vertical:(BOOL)v grid:(ccGridSize)gridSize duration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCTwirl action */ +@interface CCTwirl : CCGrid3DAction +{ + CGPoint position_; + CGPoint positionInPixels_; + int twirls_; + float amplitude_; + float amplitudeRate_; +} + +/** twirl center */ +@property (nonatomic,readwrite) CGPoint position; +/** amplitude */ +@property (nonatomic,readwrite) float amplitude; +/** amplitude rate */ +@property (nonatomic,readwrite) float amplitudeRate; + +/** creates the action with center position, number of twirls, amplitude, a grid size and duration */ ++(id)actionWithPosition:(CGPoint)pos twirls:(int)t amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d; +/** initializes the action with center position, number of twirls, amplitude, a grid size and duration */ +-(id)initWithPosition:(CGPoint)pos twirls:(int)t amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d; + +@end diff --git a/Classes/cocos2d/CCActionGrid3D.m b/Classes/cocos2d/CCActionGrid3D.m new file mode 100644 index 0000000..1d4a783 --- /dev/null +++ b/Classes/cocos2d/CCActionGrid3D.m @@ -0,0 +1,659 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * 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. + * + */ + + +#import "CCActionGrid3D.h" +#import "ccMacros.h" +#import "Support/CGPointExtension.h" + +#pragma mark - +#pragma mark Waves3D + +@implementation CCWaves3D + +@synthesize amplitude; +@synthesize amplitudeRate; + ++(id)actionWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d +{ + return [[[self alloc] initWithWaves:wav amplitude:amp grid:gridSize duration:d] autorelease]; +} + +-(id)initWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gSize duration:(ccTime)d +{ + if ( (self = [super initWithSize:gSize duration:d]) ) + { + waves = wav; + amplitude = amp; + amplitudeRate = 1.0f; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithWaves:waves amplitude:amplitude grid:gridSize_ duration:duration_]; + return copy; +} + + +-(void)update:(ccTime)time +{ + int i, j; + + for( i = 0; i < (gridSize_.x+1); i++ ) + { + for( j = 0; j < (gridSize_.y+1); j++ ) + { + ccVertex3F v = [self originalVertex:ccg(i,j)]; + v.z += (sinf((CGFloat)M_PI*time*waves*2 + (v.y+v.x) * .01f) * amplitude * amplitudeRate); + [self setVertex:ccg(i,j) vertex:v]; + } + } +} +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark FlipX3D + +@implementation CCFlipX3D + ++(id) actionWithDuration:(ccTime)d +{ + return [[[self alloc] initWithSize:ccg(1,1) duration:d] autorelease]; +} + +-(id) initWithDuration:(ccTime)d +{ + return [super initWithSize:ccg(1,1) duration:d]; +} + +-(id)initWithSize:(ccGridSize)gSize duration:(ccTime)d +{ + if ( gSize.x != 1 || gSize.y != 1 ) + { + [NSException raise:@"FlipX3D" format:@"Grid size must be (1,1)"]; + } + + return [super initWithSize:gSize duration:d]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithSize:gridSize_ duration:duration_]; + return copy; +} + + +-(void)update:(ccTime)time +{ + CGFloat angle = (CGFloat)M_PI * time; // 180 degrees + CGFloat mz = sinf( angle ); + angle = angle / 2.0f; // x calculates degrees from 0 to 90 + CGFloat mx = cosf( angle ); + + ccVertex3F v0, v1, v, diff; + + v0 = [self originalVertex:ccg(1,1)]; + v1 = [self originalVertex:ccg(0,0)]; + + CGFloat x0 = v0.x; + CGFloat x1 = v1.x; + CGFloat x; + ccGridSize a, b, c, d; + + if ( x0 > x1 ) + { + // Normal Grid + a = ccg(0,0); + b = ccg(0,1); + c = ccg(1,0); + d = ccg(1,1); + x = x0; + } + else + { + // Reversed Grid + c = ccg(0,0); + d = ccg(0,1); + a = ccg(1,0); + b = ccg(1,1); + x = x1; + } + + diff.x = ( x - x * mx ); + diff.z = fabsf( floorf( (x * mz) / 4.0f ) ); + +// bottom-left + v = [self originalVertex:a]; + v.x = diff.x; + v.z += diff.z; + [self setVertex:a vertex:v]; + +// upper-left + v = [self originalVertex:b]; + v.x = diff.x; + v.z += diff.z; + [self setVertex:b vertex:v]; + +// bottom-right + v = [self originalVertex:c]; + v.x -= diff.x; + v.z -= diff.z; + [self setVertex:c vertex:v]; + +// upper-right + v = [self originalVertex:d]; + v.x -= diff.x; + v.z -= diff.z; + [self setVertex:d vertex:v]; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark FlipY3D + +@implementation CCFlipY3D + +-(void)update:(ccTime)time +{ + CGFloat angle = (CGFloat)M_PI * time; // 180 degrees + CGFloat mz = sinf( angle ); + angle = angle / 2.0f; // x calculates degrees from 0 to 90 + CGFloat my = cosf( angle ); + + ccVertex3F v0, v1, v, diff; + + v0 = [self originalVertex:ccg(1,1)]; + v1 = [self originalVertex:ccg(0,0)]; + + CGFloat y0 = v0.y; + CGFloat y1 = v1.y; + CGFloat y; + ccGridSize a, b, c, d; + + if ( y0 > y1 ) + { + // Normal Grid + a = ccg(0,0); + b = ccg(0,1); + c = ccg(1,0); + d = ccg(1,1); + y = y0; + } + else + { + // Reversed Grid + b = ccg(0,0); + a = ccg(0,1); + d = ccg(1,0); + c = ccg(1,1); + y = y1; + } + + diff.y = y - y * my; + diff.z = fabsf( floorf( (y * mz) / 4.0f ) ); + + // bottom-left + v = [self originalVertex:a]; + v.y = diff.y; + v.z += diff.z; + [self setVertex:a vertex:v]; + + // upper-left + v = [self originalVertex:b]; + v.y -= diff.y; + v.z -= diff.z; + [self setVertex:b vertex:v]; + + // bottom-right + v = [self originalVertex:c]; + v.y = diff.y; + v.z += diff.z; + [self setVertex:c vertex:v]; + + // upper-right + v = [self originalVertex:d]; + v.y -= diff.y; + v.z -= diff.z; + [self setVertex:d vertex:v]; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark Lens3D + +@implementation CCLens3D + +@synthesize lensEffect=lensEffect_; + ++(id)actionWithPosition:(CGPoint)pos radius:(float)r grid:(ccGridSize)gridSize duration:(ccTime)d +{ + return [[[self alloc] initWithPosition:pos radius:r grid:gridSize duration:d] autorelease]; +} + +-(id)initWithPosition:(CGPoint)pos radius:(float)r grid:(ccGridSize)gSize duration:(ccTime)d +{ + if ( (self = [super initWithSize:gSize duration:d]) ) + { + position_ = ccp(-1,-1); + self.position = pos; + radius_ = r; + lensEffect_ = 0.7f; + dirty_ = YES; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithPosition:position_ radius:radius_ grid:gridSize_ duration:duration_]; + return copy; +} + +-(void) setPosition:(CGPoint)pos +{ + if( ! CGPointEqualToPoint(pos, position_) ) { + position_ = pos; + positionInPixels_.x = pos.x * CC_CONTENT_SCALE_FACTOR(); + positionInPixels_.y = pos.y * CC_CONTENT_SCALE_FACTOR(); + + dirty_ = YES; + } +} + +-(CGPoint) position +{ + return position_; +} + +-(void)update:(ccTime)time +{ + if ( dirty_ ) + { + int i, j; + + for( i = 0; i < gridSize_.x+1; i++ ) + { + for( j = 0; j < gridSize_.y+1; j++ ) + { + ccVertex3F v = [self originalVertex:ccg(i,j)]; + CGPoint vect = ccpSub(positionInPixels_, ccp(v.x,v.y)); + CGFloat r = ccpLength(vect); + + if ( r < radius_ ) + { + r = radius_ - r; + CGFloat 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 ( ccpLength(vect) > 0 ) + { + vect = ccpNormalize(vect); + CGPoint new_vect = ccpMult(vect, new_r); + v.z += ccpLength(new_vect) * lensEffect_; + } + } + + [self setVertex:ccg(i,j) vertex:v]; + } + } + + dirty_ = NO; + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark Ripple3D + +@implementation CCRipple3D + +@synthesize amplitude = amplitude_; +@synthesize amplitudeRate = amplitudeRate_; + ++(id)actionWithPosition:(CGPoint)pos radius:(float)r waves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d +{ + return [[[self alloc] initWithPosition:pos radius:r waves:wav amplitude:amp grid:gridSize duration:d] autorelease]; +} + +-(id)initWithPosition:(CGPoint)pos radius:(float)r waves:(int)wav amplitude:(float)amp grid:(ccGridSize)gSize duration:(ccTime)d +{ + if ( (self = [super initWithSize:gSize duration:d]) ) + { + self.position = pos; + radius_ = r; + waves_ = wav; + amplitude_ = amp; + amplitudeRate_ = 1.0f; + } + + return self; +} + +-(CGPoint) position +{ + return position_; +} + +-(void) setPosition:(CGPoint)pos +{ + position_ = pos; + positionInPixels_.x = pos.x * CC_CONTENT_SCALE_FACTOR(); + positionInPixels_.y = pos.y * CC_CONTENT_SCALE_FACTOR(); +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithPosition:position_ radius:radius_ waves:waves_ amplitude:amplitude_ grid:gridSize_ duration:duration_]; + return copy; +} + + +-(void)update:(ccTime)time +{ + int i, j; + + for( i = 0; i < (gridSize_.x+1); i++ ) + { + for( j = 0; j < (gridSize_.y+1); j++ ) + { + ccVertex3F v = [self originalVertex:ccg(i,j)]; + CGPoint vect = ccpSub(positionInPixels_, ccp(v.x,v.y)); + CGFloat r = ccpLength(vect); + + if ( r < radius_ ) + { + r = radius_ - r; + CGFloat rate = powf( r / radius_, 2); + v.z += (sinf( time*(CGFloat)M_PI*waves_*2 + r * 0.1f) * amplitude_ * amplitudeRate_ * rate ); + } + + [self setVertex:ccg(i,j) vertex:v]; + } + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark Shaky3D + +@implementation CCShaky3D + ++(id)actionWithRange:(int)range shakeZ:(BOOL)sz grid:(ccGridSize)gridSize duration:(ccTime)d +{ + return [[[self alloc] initWithRange:range shakeZ:sz grid:gridSize duration:d] autorelease]; +} + +-(id)initWithRange:(int)range shakeZ:(BOOL)sz grid:(ccGridSize)gSize duration:(ccTime)d +{ + if ( (self = [super initWithSize:gSize duration:d]) ) + { + randrange = range; + shakeZ = sz; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithRange:randrange shakeZ:shakeZ grid:gridSize_ duration:duration_]; + return copy; +} + +-(void)update:(ccTime)time +{ + int i, j; + + for( i = 0; i < (gridSize_.x+1); i++ ) + { + for( j = 0; j < (gridSize_.y+1); j++ ) + { + ccVertex3F v = [self originalVertex:ccg(i,j)]; + v.x += ( rand() % (randrange*2) ) - randrange; + v.y += ( rand() % (randrange*2) ) - randrange; + if( shakeZ ) + v.z += ( rand() % (randrange*2) ) - randrange; + + [self setVertex:ccg(i,j) vertex:v]; + } + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark Liquid + +@implementation CCLiquid + +@synthesize amplitude; +@synthesize amplitudeRate; + ++(id)actionWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d +{ + return [[[self alloc] initWithWaves:wav amplitude:amp grid:gridSize duration:d] autorelease]; +} + +-(id)initWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gSize duration:(ccTime)d +{ + if ( (self = [super initWithSize:gSize duration:d]) ) + { + waves = wav; + amplitude = amp; + amplitudeRate = 1.0f; + } + + return self; +} + +-(void)update:(ccTime)time +{ + int i, j; + + for( i = 1; i < gridSize_.x; i++ ) + { + for( j = 1; j < gridSize_.y; j++ ) + { + ccVertex3F v = [self originalVertex:ccg(i,j)]; + v.x = (v.x + (sinf(time*(CGFloat)M_PI*waves*2 + v.x * .01f) * amplitude * amplitudeRate)); + v.y = (v.y + (sinf(time*(CGFloat)M_PI*waves*2 + v.y * .01f) * amplitude * amplitudeRate)); + [self setVertex:ccg(i,j) vertex:v]; + } + } +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithWaves:waves amplitude:amplitude grid:gridSize_ duration:duration_]; + return copy; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark Waves + +@implementation CCWaves + +@synthesize amplitude; +@synthesize amplitudeRate; + ++(id)actionWithWaves:(int)wav amplitude:(float)amp horizontal:(BOOL)h vertical:(BOOL)v grid:(ccGridSize)gridSize duration:(ccTime)d +{ + return [[[self alloc] initWithWaves:wav amplitude:amp horizontal:h vertical:v grid:gridSize duration:d] autorelease]; +} + +-(id)initWithWaves:(int)wav amplitude:(float)amp horizontal:(BOOL)h vertical:(BOOL)v grid:(ccGridSize)gSize duration:(ccTime)d +{ + if ( (self = [super initWithSize:gSize duration:d]) ) + { + waves = wav; + amplitude = amp; + amplitudeRate = 1.0f; + horizontal = h; + vertical = v; + } + + return self; +} + +-(void)update:(ccTime)time +{ + int i, j; + + for( i = 0; i < (gridSize_.x+1); i++ ) + { + for( j = 0; j < (gridSize_.y+1); j++ ) + { + ccVertex3F v = [self originalVertex:ccg(i,j)]; + + if ( vertical ) + v.x = (v.x + (sinf(time*(CGFloat)M_PI*waves*2 + v.y * .01f) * amplitude * amplitudeRate)); + + if ( horizontal ) + v.y = (v.y + (sinf(time*(CGFloat)M_PI*waves*2 + v.x * .01f) * amplitude * amplitudeRate)); + + [self setVertex:ccg(i,j) vertex:v]; + } + } +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithWaves:waves amplitude:amplitude horizontal:horizontal vertical:vertical grid:gridSize_ duration:duration_]; + return copy; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark Twirl + +@implementation CCTwirl + +@synthesize amplitude = amplitude_; +@synthesize amplitudeRate = amplitudeRate_; + ++(id)actionWithPosition:(CGPoint)pos twirls:(int)t amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d +{ + return [[[self alloc] initWithPosition:pos twirls:t amplitude:amp grid:gridSize duration:d] autorelease]; +} + +-(id)initWithPosition:(CGPoint)pos twirls:(int)t amplitude:(float)amp grid:(ccGridSize)gSize duration:(ccTime)d +{ + if ( (self = [super initWithSize:gSize duration:d]) ) + { + self.position = pos; + twirls_ = t; + amplitude_ = amp; + amplitudeRate_ = 1.0f; + } + + return self; +} + +-(void) setPosition:(CGPoint)pos +{ + position_ = pos; + positionInPixels_.x = pos.x * CC_CONTENT_SCALE_FACTOR(); + positionInPixels_.y = pos.y * CC_CONTENT_SCALE_FACTOR(); +} + +-(CGPoint) position +{ + return position_; +} + +-(void)update:(ccTime)time +{ + int i, j; + CGPoint c = positionInPixels_; + + for( i = 0; i < (gridSize_.x+1); i++ ) + { + for( j = 0; j < (gridSize_.y+1); j++ ) + { + ccVertex3F v = [self originalVertex:ccg(i,j)]; + + CGPoint avg = ccp(i-(gridSize_.x/2.0f), j-(gridSize_.y/2.0f)); + CGFloat r = ccpLength( avg ); + + CGFloat amp = 0.1f * amplitude_ * amplitudeRate_; + CGFloat a = r * cosf( (CGFloat)M_PI/2.0f + time * (CGFloat)M_PI * twirls_ * 2 ) * amp; + + float cosA = cosf(a); + float sinA = sinf(a); + + CGPoint d = { + sinA * (v.y-c.y) + cosA * (v.x-c.x), + cosA * (v.y-c.y) - sinA * (v.x-c.x) + }; + + v.x = c.x + d.x; + v.y = c.y + d.y; + + [self setVertex:ccg(i,j) vertex:v]; + } + } +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithPosition:position_ + twirls:twirls_ + amplitude:amplitude_ + grid:gridSize_ + duration:duration_]; + return copy; +} + + +@end diff --git a/Classes/cocos2d/CCActionInstant.h b/Classes/cocos2d/CCActionInstant.h new file mode 100644 index 0000000..40eb15f --- /dev/null +++ b/Classes/cocos2d/CCActionInstant.h @@ -0,0 +1,197 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + +#import "CCAction.h" + +/** Instant actions are immediate actions. They don't have a duration like + the CCIntervalAction actions. +*/ +@interface CCActionInstant : CCFiniteTimeAction +{ +} +@end + +/** Show the node + */ + @interface CCShow : CCActionInstant +{ +} +@end + +/** Hide the node + */ +@interface CCHide : CCActionInstant +{ +} +@end + +/** Toggles the visibility of a node + */ +@interface CCToggleVisibility : CCActionInstant +{ +} +@end + +/** Flips the sprite horizontally + @since v0.99.0 + */ +@interface CCFlipX : CCActionInstant +{ + BOOL flipX; +} ++(id) actionWithFlipX:(BOOL)x; +-(id) initWithFlipX:(BOOL)x; +@end + +/** Flips the sprite vertically + @since v0.99.0 + */ +@interface CCFlipY : CCActionInstant +{ + BOOL flipY; +} ++(id) actionWithFlipY:(BOOL)y; +-(id) initWithFlipY:(BOOL)y; +@end + +/** Places the node in a certain position + */ +@interface CCPlace : CCActionInstant +{ + CGPoint position; +} +/** creates a Place action with a position */ ++(id) actionWithPosition: (CGPoint) pos; +/** Initializes a Place action with a position */ +-(id) initWithPosition: (CGPoint) pos; +@end + +/** Calls a 'callback' + */ +@interface CCCallFunc : CCActionInstant +{ + id targetCallback_; + SEL selector_; +} +/** creates the action with the callback */ ++(id) actionWithTarget: (id) t selector:(SEL) s; +/** initializes the action with the callback */ +-(id) initWithTarget: (id) t selector:(SEL) s; +/** exeuctes the callback */ +-(void) execute; +@end + +/** Calls a 'callback' with the node as the first argument. + N means Node + */ +@interface CCCallFuncN : CCCallFunc +{ +} +@end + +typedef void (*CC_CALLBACK_ND)(id, SEL, id, void *); +/** 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. + */ +@interface CCCallFuncND : CCCallFuncN +{ + void *data_; + CC_CALLBACK_ND callbackMethod_; +} + +/** Invocation object that has the target#selector and the parameters */ +@property (nonatomic,readwrite) CC_CALLBACK_ND callbackMethod; + +/** creates the action with the callback and the data to pass as an argument */ ++(id) actionWithTarget: (id) t selector:(SEL) s data:(void*)d; +/** initializes the action with the callback and the data to pass as an argument */ +-(id) initWithTarget:(id) t selector:(SEL) s data:(void*) d; +@end + +/** Calls a 'callback' with an object as the first argument. + O means Object. + @since v0.99.5 + */ +@interface CCCallFuncO : CCCallFunc +{ + id object_; +} +/** creates the action with the callback and the object to pass as an argument */ ++(id) actionWithTarget: (id) t selector:(SEL) s object:(id)object; +/** initializes the action with the callback and the object to pass as an argument */ +-(id) initWithTarget:(id) t selector:(SEL) s object:(id)object; + +@end + +#pragma mark Blocks Support + +#if NS_BLOCKS_AVAILABLE + +/** Executes a callback using a block. + */ +@interface CCCallBlock : CCActionInstant +{ + void (^block_)(); +} + +/** creates the action with the specified block, to be used as a callback. + The block will be "copied". + */ ++(id) actionWithBlock:(void(^)())block; + +/** initialized the action with the specified block, to be used as a callback. + The block will be "copied". + */ +-(id) initWithBlock:(void(^)())block; + +/** executes the callback */ +-(void) execute; +@end + +@class CCNode; + +/** Executes a callback using a block with a single CCNode parameter. + */ +@interface CCCallBlockN : CCActionInstant +{ + void (^block_)(CCNode *); +} + +/** creates the action with the specified block, to be used as a callback. + The block will be "copied". + */ ++(id) actionWithBlock:(void(^)(CCNode *node))block; + +/** initialized the action with the specified block, to be used as a callback. + The block will be "copied". + */ +-(id) initWithBlock:(void(^)(CCNode *node))block; + +/** executes the callback */ +-(void) execute; +@end + +#endif diff --git a/Classes/cocos2d/CCActionInstant.m b/Classes/cocos2d/CCActionInstant.m new file mode 100644 index 0000000..2b9072c --- /dev/null +++ b/Classes/cocos2d/CCActionInstant.m @@ -0,0 +1,472 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + +#import "CCBlockSupport.h" +#import "CCActionInstant.h" +#import "CCNode.h" +#import "CCSprite.h" + + +// +// InstantAction +// +#pragma mark CCActionInstant + +@implementation CCActionInstant + +-(id) init +{ + if( (self=[super init]) ) + duration_ = 0; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] init]; + return copy; +} + +- (BOOL) isDone +{ + return YES; +} + +-(void) step: (ccTime) dt +{ + [self update: 1]; +} + +-(void) update: (ccTime) t +{ + // ignore +} + +-(CCFiniteTimeAction*) reverse +{ + return [[self copy] autorelease]; +} +@end + +// +// Show +// +#pragma mark CCShow + +@implementation CCShow +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + ((CCNode *)target_).visible = YES; +} + +-(CCFiniteTimeAction*) reverse +{ + return [CCHide action]; +} +@end + +// +// Hide +// +#pragma mark CCHide + +@implementation CCHide +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + ((CCNode *)target_).visible = NO; +} + +-(CCFiniteTimeAction*) reverse +{ + return [CCShow action]; +} +@end + +// +// ToggleVisibility +// +#pragma mark CCToggleVisibility + +@implementation CCToggleVisibility +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + ((CCNode *)target_).visible = !((CCNode *)target_).visible; +} +@end + +// +// FlipX +// +#pragma mark CCFlipX + +@implementation CCFlipX ++(id) actionWithFlipX:(BOOL)x +{ + return [[[self alloc] initWithFlipX:x] autorelease]; +} + +-(id) initWithFlipX:(BOOL)x +{ + if(( self=[super init])) + flipX = x; + + return self; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [(CCSprite*)aTarget setFlipX:flipX]; +} + +-(CCFiniteTimeAction*) reverse +{ + return [CCFlipX actionWithFlipX:!flipX]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithFlipX:flipX]; + return copy; +} +@end + +// +// FlipY +// +#pragma mark CCFlipY + +@implementation CCFlipY ++(id) actionWithFlipY:(BOOL)y +{ + return [[[self alloc] initWithFlipY:y] autorelease]; +} + +-(id) initWithFlipY:(BOOL)y +{ + if(( self=[super init])) + flipY = y; + + return self; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [(CCSprite*)aTarget setFlipY:flipY]; +} + +-(CCFiniteTimeAction*) reverse +{ + return [CCFlipY actionWithFlipY:!flipY]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithFlipY:flipY]; + return copy; +} +@end + + +// +// Place +// +#pragma mark CCPlace + +@implementation CCPlace ++(id) actionWithPosition: (CGPoint) pos +{ + return [[[self alloc]initWithPosition:pos]autorelease]; +} + +-(id) initWithPosition: (CGPoint) pos +{ + if( (self=[super init]) ) + position = pos; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithPosition: position]; + return copy; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + ((CCNode *)target_).position = position; +} + +@end + +// +// CallFunc +// +#pragma mark CCCallFunc + +@implementation CCCallFunc ++(id) actionWithTarget: (id) t selector:(SEL) s +{ + return [[[self alloc] initWithTarget: t selector: s] autorelease]; +} + +-(id) initWithTarget: (id) t selector:(SEL) s +{ + if( (self=[super init]) ) { + targetCallback_ = [t retain]; + selector_ = s; + } + return self; +} + +-(NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %08X | Tag = %i | target = %@ | selector = %@>", + [self class], + self, + tag_, + [targetCallback_ class], + NSStringFromSelector(selector_) + ]; +} + +-(void) dealloc +{ + [targetCallback_ release]; + [super dealloc]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithTarget:targetCallback_ selector:selector_]; + return copy; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [self execute]; +} + +-(void) execute +{ + [targetCallback_ performSelector:selector_]; +} +@end + +// +// CallFuncN +// +#pragma mark CCCallFuncN + +@implementation CCCallFuncN + +-(void) execute +{ + [targetCallback_ performSelector:selector_ withObject:target_]; +} +@end + +// +// CallFuncND +// +#pragma mark CCCallFuncND + +@implementation CCCallFuncND + +@synthesize callbackMethod = callbackMethod_; + ++(id) actionWithTarget:(id)t selector:(SEL)s data:(void*)d +{ + return [[[self alloc] initWithTarget:t selector:s data:d] autorelease]; +} + +-(id) initWithTarget:(id)t selector:(SEL)s data:(void*)d +{ + if( (self=[super initWithTarget:t selector:s]) ) { + data_ = d; + +#if COCOS2D_DEBUG + NSMethodSignature * sig = [t methodSignatureForSelector:s]; // added + NSAssert(sig !=0 , @"Signature not found for selector - does it have the following form? -(void)name:(id)sender data:(void*)data"); +#endif + callbackMethod_ = (CC_CALLBACK_ND) [t methodForSelector:s]; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithTarget:targetCallback_ selector:selector_ data:data_]; + return copy; +} + +-(void) dealloc +{ + // nothing to dealloc really. Everything is dealloc on super (CCCallFuncN) + [super dealloc]; +} + +-(void) execute +{ + callbackMethod_(targetCallback_,selector_,target_, data_); +} +@end + +@implementation CCCallFuncO + ++(id) actionWithTarget: (id) t selector:(SEL) s object:(id)object +{ + return [[[self alloc] initWithTarget:t selector:s object:object] autorelease]; +} + +-(id) initWithTarget:(id) t selector:(SEL) s object:(id)object +{ + if( (self=[super initWithTarget:t selector:s] ) ) + object_ = [object retain]; + + return self; +} + +- (void) dealloc +{ + [object_ release]; + [super dealloc]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithTarget:targetCallback_ selector:selector_ object:object_]; + return copy; +} + + +-(void) execute +{ + [targetCallback_ performSelector:selector_ withObject:object_]; +} + +@end + + +#pragma mark - +#pragma mark Blocks + +#if NS_BLOCKS_AVAILABLE + +#pragma mark CCCallBlock + +@implementation CCCallBlock + ++(id) actionWithBlock:(void(^)())block +{ + return [[[self alloc] initWithBlock:block] autorelease]; +} + +-(id) initWithBlock:(void(^)())block +{ + if ((self = [super init])) + block_ = [block copy]; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithBlock:block_]; + return copy; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [self execute]; +} + +-(void) execute +{ + block_(); +} + +-(void) dealloc +{ + [block_ release]; + [super dealloc]; +} + +@end + +#pragma mark CCCallBlockN + +@implementation CCCallBlockN + ++(id) actionWithBlock:(void(^)(CCNode *node))block +{ + return [[[self alloc] initWithBlock:block] autorelease]; +} + +-(id) initWithBlock:(void(^)(CCNode *node))block +{ + if ((self = [super init])) + block_ = [block copy]; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithBlock:block_]; + return copy; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [self execute]; +} + +-(void) execute +{ + block_(target_); +} + +-(void) dealloc +{ + [block_ release]; + [super dealloc]; +} + +@end + + +#endif // NS_BLOCKS_AVAILABLE diff --git a/Classes/cocos2d/CCActionInterval.h b/Classes/cocos2d/CCActionInterval.h new file mode 100644 index 0000000..035bd50 --- /dev/null +++ b/Classes/cocos2d/CCActionInterval.h @@ -0,0 +1,384 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + +#import "CCNode.h" +#import "CCAction.h" +#import "CCProtocols.h" + +#include + +/** 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 CCActionInterval 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: + + CCAction * pingPongAction = [CCSequence actions: action, [action reverse], nil]; +*/ +@interface CCActionInterval: CCFiniteTimeAction +{ + ccTime elapsed_; + BOOL firstTick_; +} + +/** how many seconds had elapsed since the actions started to run. */ +@property (nonatomic,readonly) ccTime elapsed; + +/** creates the action */ ++(id) actionWithDuration: (ccTime) d; +/** initializes the action */ +-(id) initWithDuration: (ccTime) d; +/** returns YES if the action has finished */ +-(BOOL) isDone; +/** returns a reversed action */ +- (CCActionInterval*) reverse; +@end + +/** Runs actions sequentially, one after another + */ +@interface CCSequence : CCActionInterval +{ + CCFiniteTimeAction *actions[2]; + ccTime split; + int last; +} +/** helper contructor to create an array of sequenceable actions */ ++(id) actions: (CCFiniteTimeAction*) action1, ... NS_REQUIRES_NIL_TERMINATION; +/** creates the action */ ++(id) actionOne:(CCFiniteTimeAction*)actionOne two:(CCFiniteTimeAction*)actionTwo; +/** initializes the action */ +-(id) initOne:(CCFiniteTimeAction*)actionOne two:(CCFiniteTimeAction*)actionTwo; +@end + + +/** Repeats an action a number of times. + * To repeat an action forever use the CCRepeatForever action. + */ +@interface CCRepeat : CCActionInterval +{ + unsigned int times_; + unsigned int total_; + CCFiniteTimeAction *other_; +} +/** creates a CCRepeat action. Times is an unsigned integer between 1 and pow(2,30) */ ++(id) actionWithAction:(CCFiniteTimeAction*)action times: (unsigned int)times; +/** initializes a CCRepeat action. Times is an unsigned integer between 1 and pow(2,30) */ +-(id) initWithAction:(CCFiniteTimeAction*)action times: (unsigned int)times; +@end + +/** Spawn a new action immediately + */ +@interface CCSpawn : CCActionInterval +{ + CCFiniteTimeAction *one; + CCFiniteTimeAction *two; +} +/** helper constructor to create an array of spawned actions */ ++(id) actions: (CCFiniteTimeAction*) action1, ... NS_REQUIRES_NIL_TERMINATION; +/** creates the Spawn action */ ++(id) actionOne: (CCFiniteTimeAction*) one two:(CCFiniteTimeAction*) two; +/** initializes the Spawn action with the 2 actions to spawn */ +-(id) initOne: (CCFiniteTimeAction*) one two:(CCFiniteTimeAction*) two; +@end + +/** Rotates a CCNode object to a certain angle by modifying it's + rotation attribute. + The direction will be decided by the shortest angle. +*/ +@interface CCRotateTo : CCActionInterval +{ + float dstAngle; + float startAngle; + float diffAngle; +} +/** creates the action */ ++(id) actionWithDuration:(ccTime)duration angle:(float)angle; +/** initializes the action */ +-(id) initWithDuration:(ccTime)duration angle:(float)angle; +@end + +/** Rotates a CCNode object clockwise a number of degrees by modiying it's rotation attribute. +*/ +@interface CCRotateBy : CCActionInterval +{ + float angle; + float startAngle; +} +/** creates the action */ ++(id) actionWithDuration:(ccTime)duration angle:(float)deltaAngle; +/** initializes the action */ +-(id) initWithDuration:(ccTime)duration angle:(float)deltaAngle; +@end + +/** Moves a CCNode object to the position x,y. x and y are absolute coordinates by modifying it's position attribute. +*/ +@interface CCMoveTo : CCActionInterval +{ + CGPoint endPosition; + CGPoint startPosition; + CGPoint delta; +} +/** creates the action */ ++(id) actionWithDuration:(ccTime)duration position:(CGPoint)position; +/** initializes the action */ +-(id) initWithDuration:(ccTime)duration position:(CGPoint)position; +@end + +/** Moves a CCNode object x,y pixels by modifying it's position attribute. + x and y are relative to the position of the object. + Duration is is seconds. +*/ +@interface CCMoveBy : CCMoveTo +{ +} +/** creates the action */ ++(id) actionWithDuration: (ccTime)duration position:(CGPoint)deltaPosition; +/** initializes the action */ +-(id) initWithDuration: (ccTime)duration position:(CGPoint)deltaPosition; +@end + +/** Moves a CCNode object simulating a parabolic jump movement by modifying it's position attribute. +*/ + @interface CCJumpBy : CCActionInterval +{ + CGPoint startPosition; + CGPoint delta; + ccTime height; + int jumps; +} +/** creates the action */ ++(id) actionWithDuration: (ccTime)duration position:(CGPoint)position height:(ccTime)height jumps:(int)jumps; +/** initializes the action */ +-(id) initWithDuration: (ccTime)duration position:(CGPoint)position height:(ccTime)height jumps:(int)jumps; +@end + +/** Moves a CCNode object to a parabolic position simulating a jump movement by modifying it's position attribute. +*/ + @interface CCJumpTo : CCJumpBy +{ +} +@end + +/** bezier configuration structure + */ +typedef struct _ccBezierConfig { + //! end position of the bezier + CGPoint endPosition; + //! Bezier control point 1 + CGPoint controlPoint_1; + //! Bezier control point 2 + CGPoint controlPoint_2; +} ccBezierConfig; + +/** An action that moves the target with a cubic Bezier curve by a certain distance. + */ +@interface CCBezierBy : CCActionInterval +{ + ccBezierConfig config; + CGPoint startPosition; +} + +/** creates the action with a duration and a bezier configuration */ ++(id) actionWithDuration: (ccTime) t bezier:(ccBezierConfig) c; + +/** initializes the action with a duration and a bezier configuration */ +-(id) initWithDuration: (ccTime) t bezier:(ccBezierConfig) c; +@end + +/** An action that moves the target with a cubic Bezier curve to a destination point. + @since v0.8.2 + */ +@interface CCBezierTo : CCBezierBy +{ +} +@end + +/** Scales a CCNode object to a zoom factor by modifying it's scale attribute. + @warning This action doesn't support "reverse" + */ +@interface CCScaleTo : CCActionInterval +{ + float scaleX; + float scaleY; + float startScaleX; + float startScaleY; + float endScaleX; + float endScaleY; + float deltaX; + float deltaY; +} +/** creates the action with the same scale factor for X and Y */ ++(id) actionWithDuration: (ccTime)duration scale:(float) s; +/** initializes the action with the same scale factor for X and Y */ +-(id) initWithDuration: (ccTime)duration scale:(float) s; +/** creates the action with and X factor and a Y factor */ ++(id) actionWithDuration: (ccTime)duration scaleX:(float) sx scaleY:(float)sy; +/** initializes the action with and X factor and a Y factor */ +-(id) initWithDuration: (ccTime)duration scaleX:(float) sx scaleY:(float)sy; +@end + +/** Scales a CCNode object a zoom factor by modifying it's scale attribute. +*/ +@interface CCScaleBy : CCScaleTo +{ +} +@end + +/** Blinks a CCNode object by modifying it's visible attribute +*/ +@interface CCBlink : CCActionInterval +{ + int times; +} +/** creates the action */ ++(id) actionWithDuration: (ccTime)duration blinks:(unsigned int)blinks; +/** initilizes the action */ +-(id) initWithDuration: (ccTime)duration blinks:(unsigned int)blinks; +@end + +/** Fades In an object that implements the CCRGBAProtocol protocol. It modifies the opacity from 0 to 255. + The "reverse" of this action is FadeOut + */ +@interface CCFadeIn : CCActionInterval +{ +} +@end + +/** Fades Out an object that implements the CCRGBAProtocol protocol. It modifies the opacity from 255 to 0. + The "reverse" of this action is FadeIn +*/ +@interface CCFadeOut : CCActionInterval +{ +} +@end + +/** Fades an object that implements the CCRGBAProtocol protocol. It modifies the opacity from the current value to a custom one. + @warning This action doesn't support "reverse" + */ +@interface CCFadeTo : CCActionInterval +{ + GLubyte toOpacity; + GLubyte fromOpacity; +} +/** creates an action with duration and opactiy */ ++(id) actionWithDuration:(ccTime)duration opacity:(GLubyte)opactiy; +/** initializes the action with duration and opacity */ +-(id) initWithDuration:(ccTime)duration opacity:(GLubyte)opacity; +@end + +/** Tints a CCNode that implements the CCNodeRGB protocol from current tint to a custom one. + @warning This action doesn't support "reverse" + @since v0.7.2 +*/ +@interface CCTintTo : CCActionInterval +{ + ccColor3B to; + ccColor3B from; +} +/** creates an action with duration and color */ ++(id) actionWithDuration:(ccTime)duration red:(GLubyte)red green:(GLubyte)green blue:(GLubyte)blue; +/** initializes the action with duration and color */ +-(id) initWithDuration:(ccTime)duration red:(GLubyte)red green:(GLubyte)green blue:(GLubyte)blue; +@end + +/** Tints a CCNode that implements the CCNodeRGB protocol from current tint to a custom one. + @since v0.7.2 + */ +@interface CCTintBy : CCActionInterval +{ + GLshort deltaR, deltaG, deltaB; + GLshort fromR, fromG, fromB; +} +/** creates an action with duration and color */ ++(id) actionWithDuration:(ccTime)duration red:(GLshort)deltaRed green:(GLshort)deltaGreen blue:(GLshort)deltaBlue; +/** initializes the action with duration and color */ +-(id) initWithDuration:(ccTime)duration red:(GLshort)deltaRed green:(GLshort)deltaGreen blue:(GLshort)deltaBlue; +@end + +/** Delays the action a certain amount of seconds +*/ +@interface CCDelayTime : CCActionInterval +{ +} +@end + +/** 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. +*/ +@interface CCReverseTime : CCActionInterval +{ + CCFiniteTimeAction * other; +} +/** creates the action */ ++(id) actionWithAction: (CCFiniteTimeAction*) action; +/** initializes the action */ +-(id) initWithAction: (CCFiniteTimeAction*) action; +@end + + +@class CCAnimation; +@class CCTexture2D; +/** Animates a sprite given the name of an Animation */ +@interface CCAnimate : CCActionInterval +{ + CCAnimation *animation_; + id origFrame; + BOOL restoreOriginalFrame; +} +/** animation used for the animage */ +@property (readwrite,nonatomic,retain) CCAnimation * animation; + +/** creates the action with an Animation and will restore the original frame when the animation is over */ ++(id) actionWithAnimation:(CCAnimation*) a; +/** initializes the action with an Animation and will restore the original frame when the animtion is over */ +-(id) initWithAnimation:(CCAnimation*) a; +/** creates the action with an Animation */ ++(id) actionWithAnimation:(CCAnimation*) a restoreOriginalFrame:(BOOL)b; +/** initializes the action with an Animation */ +-(id) initWithAnimation:(CCAnimation*) a restoreOriginalFrame:(BOOL)b; +/** creates an action with a duration, animation and depending of the restoreOriginalFrame, it will restore the original frame or not. + The 'delay' parameter of the animation will be overrided by the duration parameter. + @since v0.99.0 + */ ++(id) actionWithDuration:(ccTime)duration animation:(CCAnimation*)animation restoreOriginalFrame:(BOOL)b; +/** initializes an action with a duration, animation and depending of the restoreOriginalFrame, it will restore the original frame or not. + The 'delay' parameter of the animation will be overrided by the duration parameter. + @since v0.99.0 + */ +-(id) initWithDuration:(ccTime)duration animation:(CCAnimation*)animation restoreOriginalFrame:(BOOL)b; +@end \ No newline at end of file diff --git a/Classes/cocos2d/CCActionInterval.m b/Classes/cocos2d/CCActionInterval.m new file mode 100644 index 0000000..148bb0a --- /dev/null +++ b/Classes/cocos2d/CCActionInterval.m @@ -0,0 +1,1213 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + + +#import "CCActionInterval.h" +#import "CCSprite.h" +#import "CCSpriteFrame.h" +#import "CCAnimation.h" +#import "CCNode.h" +#import "Support/CGPointExtension.h" + +// +// IntervalAction +// +#pragma mark - +#pragma mark IntervalAction +@implementation CCActionInterval + +@synthesize elapsed = elapsed_; + +-(id) init +{ + NSAssert(NO, @"IntervalActionInit: Init not supported. Use InitWithDuration"); + [self release]; + return nil; +} + ++(id) actionWithDuration: (ccTime) d +{ + return [[[self alloc] initWithDuration:d ] autorelease]; +} + +-(id) initWithDuration: (ccTime) d +{ + if( (self=[super init]) ) { + 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_ == 0 ) + duration_ = FLT_EPSILON; + elapsed_ = 0; + firstTick_ = YES; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] ]; + return copy; +} + +- (BOOL) isDone +{ + return (elapsed_ >= duration_); +} + +-(void) step: (ccTime) dt +{ + if( firstTick_ ) { + firstTick_ = NO; + elapsed_ = 0; + } else + elapsed_ += dt; + + [self update: MIN(1, elapsed_/duration_)]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + elapsed_ = 0.0f; + firstTick_ = YES; +} + +- (CCActionInterval*) reverse +{ + NSAssert(NO, @"CCIntervalAction: reverse not implemented."); + return nil; +} +@end + +// +// Sequence +// +#pragma mark - +#pragma mark Sequence +@implementation CCSequence ++(id) actionOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two +{ + return [[[self alloc] initOne:one two:two ] autorelease]; +} + ++(id) actions: (CCFiniteTimeAction*) action1, ... +{ + va_list params; + va_start(params,action1); + + CCFiniteTimeAction *now; + CCFiniteTimeAction *prev = action1; + + while( action1 ) { + now = va_arg(params,CCFiniteTimeAction*); + if ( now ) + prev = [self actionOne: prev two: now]; + else + break; + } + va_end(params); + return prev; +} + +-(id) initOne: (CCFiniteTimeAction*) one_ two: (CCFiniteTimeAction*) two_ +{ + NSAssert( one_!=nil, @"Sequence: argument one must be non-nil"); + NSAssert( two_!=nil, @"Sequence: argument two must be non-nil"); + + CCFiniteTimeAction *one = one_; + CCFiniteTimeAction *two = two_; + + ccTime d = [one duration] + [two duration]; + [super initWithDuration: d]; + + actions[0] = [one retain]; + actions[1] = [two retain]; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone:zone] initOne:[[actions[0] copy] autorelease] two:[[actions[1] copy] autorelease] ]; + return copy; +} + +-(void) dealloc +{ + [actions[0] release]; + [actions[1] release]; + [super dealloc]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + split = [actions[0] duration] / duration_; + last = -1; +} + +-(void) stop +{ + [actions[0] stop]; + [actions[1] stop]; + [super stop]; +} + +-(void) update: (ccTime) t +{ + int found = 0; + ccTime new_t = 0.0f; + + if( t >= split ) { + found = 1; + if ( split == 1 ) + new_t = 1; + else + new_t = (t-split) / (1 - split ); + } else { + found = 0; + if( split != 0 ) + new_t = t / split; + else + new_t = 1; + } + + if (last == -1 && found==1) { + [actions[0] startWithTarget:target_]; + [actions[0] update:1.0f]; + [actions[0] stop]; + } + + if (last != found ) { + if( last != -1 ) { + [actions[last] update: 1.0f]; + [actions[last] stop]; + } + [actions[found] startWithTarget:target_]; + } + [actions[found] update: new_t]; + last = found; +} + +- (CCActionInterval *) reverse +{ + return [[self class] actionOne: [actions[1] reverse] two: [actions[0] reverse ] ]; +} +@end + +// +// Repeat +// +#pragma mark - +#pragma mark CCRepeat +@implementation CCRepeat ++(id) actionWithAction:(CCFiniteTimeAction*)action times:(unsigned int)times +{ + return [[[self alloc] initWithAction:action times:times] autorelease]; +} + +-(id) initWithAction:(CCFiniteTimeAction*)action times:(unsigned int)times +{ + ccTime d = [action duration] * times; + + if( (self=[super initWithDuration: d ]) ) { + times_ = times; + other_ = [action retain]; + + total_ = 0; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[other_ copy] autorelease] times:times_]; + return copy; +} + +-(void) dealloc +{ + [other_ release]; + [super dealloc]; +} + +-(void) startWithTarget:(id)aTarget +{ + total_ = 0; + [super startWithTarget:aTarget]; + [other_ startWithTarget:aTarget]; +} + +-(void) stop +{ + [other_ stop]; + [super stop]; +} + + +// issue #80. Instead of hooking step:, hook update: since it can be called by any +// container action like Repeat, Sequence, AccelDeccel, etc.. +-(void) update:(ccTime) dt +{ + ccTime t = dt * times_; + if( t > total_+1 ) { + [other_ update:1.0f]; + total_++; + [other_ stop]; + [other_ startWithTarget:target_]; + + // repeat is over ? + if( total_== times_ ) + // so, set it in the original position + [other_ update:0]; + else { + // no ? start next repeat with the right update + // to prevent jerk (issue #390) + [other_ update: t-total_]; + } + + } else { + + float r = fmodf(t, 1.0f); + + // fix last repeat position + // else it could be 0. + if( dt== 1.0f) { + r = 1.0f; + total_++; // this is the added line + } + [other_ update: MIN(r,1)]; + } +} + +-(BOOL) isDone +{ + return ( total_ == times_ ); +} + +- (CCActionInterval *) reverse +{ + return [[self class] actionWithAction:[other_ reverse] times:times_]; +} +@end + +// +// Spawn +// +#pragma mark - +#pragma mark Spawn + +@implementation CCSpawn ++(id) actions: (CCFiniteTimeAction*) action1, ... +{ + va_list params; + va_start(params,action1); + + CCFiniteTimeAction *now; + CCFiniteTimeAction *prev = action1; + + while( action1 ) { + now = va_arg(params,CCFiniteTimeAction*); + if ( now ) + prev = [self actionOne: prev two: now]; + else + break; + } + va_end(params); + return prev; +} + ++(id) actionOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two +{ + return [[[self alloc] initOne:one two:two ] autorelease]; +} + +-(id) initOne: (CCFiniteTimeAction*) one_ two: (CCFiniteTimeAction*) two_ +{ + NSAssert( one_!=nil, @"Spawn: argument one must be non-nil"); + NSAssert( two_!=nil, @"Spawn: argument two must be non-nil"); + + ccTime d1 = [one_ duration]; + ccTime d2 = [two_ duration]; + + [super initWithDuration: fmaxf(d1,d2)]; + + one = one_; + two = two_; + + if( d1 > d2 ) + two = [CCSequence actionOne: two_ two:[CCDelayTime actionWithDuration: (d1-d2)] ]; + else if( d1 < d2) + one = [CCSequence actionOne: one_ two: [CCDelayTime actionWithDuration: (d2-d1)] ]; + + [one retain]; + [two retain]; + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initOne: [[one copy] autorelease] two: [[two copy] autorelease] ]; + return copy; +} + +-(void) dealloc +{ + [one release]; + [two release]; + [super dealloc]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [one startWithTarget:target_]; + [two startWithTarget:target_]; +} + +-(void) stop +{ + [one stop]; + [two stop]; + [super stop]; +} + +-(void) update: (ccTime) t +{ + [one update:t]; + [two update:t]; +} + +- (CCActionInterval *) reverse +{ + return [[self class] actionOne: [one reverse] two: [two reverse ] ]; +} +@end + +// +// RotateTo +// +#pragma mark - +#pragma mark RotateTo + +@implementation CCRotateTo ++(id) actionWithDuration: (ccTime) t angle:(float) a +{ + return [[[self alloc] initWithDuration:t angle:a ] autorelease]; +} + +-(id) initWithDuration: (ccTime) t angle:(float) a +{ + if( (self=[super initWithDuration: t]) ) + dstAngle = a; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] angle: dstAngle]; + return copy; +} + +-(void) startWithTarget:(CCNode *)aTarget +{ + [super startWithTarget:aTarget]; + + startAngle = [target_ rotation]; + 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) update: (ccTime) t +{ + [target_ setRotation: startAngle + diffAngle * t]; +} +@end + + +// +// RotateBy +// +#pragma mark - +#pragma mark RotateBy + +@implementation CCRotateBy ++(id) actionWithDuration: (ccTime) t angle:(float) a +{ + return [[[self alloc] initWithDuration:t angle:a ] autorelease]; +} + +-(id) initWithDuration: (ccTime) t angle:(float) a +{ + if( (self=[super initWithDuration: t]) ) + angle = a; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] angle: angle]; + return copy; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + startAngle = [target_ rotation]; +} + +-(void) update: (ccTime) t +{ + // XXX: shall I add % 360 + [target_ setRotation: (startAngle + angle * t )]; +} + +-(CCActionInterval*) reverse +{ + return [[self class] actionWithDuration:duration_ angle:-angle]; +} + +@end + +// +// MoveTo +// +#pragma mark - +#pragma mark MoveTo + +@implementation CCMoveTo ++(id) actionWithDuration: (ccTime) t position: (CGPoint) p +{ + return [[[self alloc] initWithDuration:t position:p ] autorelease]; +} + +-(id) initWithDuration: (ccTime) t position: (CGPoint) p +{ + if( (self=[super initWithDuration: t]) ) + endPosition = p; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] position: endPosition]; + return copy; +} + +-(void) startWithTarget:(CCNode *)aTarget +{ + [super startWithTarget:aTarget]; + startPosition = [(CCNode*)target_ position]; + delta = ccpSub( endPosition, startPosition ); +} + +-(void) update: (ccTime) t +{ + [target_ setPosition: ccp( (startPosition.x + delta.x * t ), (startPosition.y + delta.y * t ) )]; +} +@end + +// +// MoveBy +// +#pragma mark - +#pragma mark MoveBy + +@implementation CCMoveBy ++(id) actionWithDuration: (ccTime) t position: (CGPoint) p +{ + return [[[self alloc] initWithDuration:t position:p ] autorelease]; +} + +-(id) initWithDuration: (ccTime) t position: (CGPoint) p +{ + if( (self=[super initWithDuration: t]) ) + delta = p; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] position: delta]; + return copy; +} + +-(void) startWithTarget:(CCNode *)aTarget +{ + CGPoint dTmp = delta; + [super startWithTarget:aTarget]; + delta = dTmp; +} + +-(CCActionInterval*) reverse +{ + return [[self class] actionWithDuration:duration_ position:ccp( -delta.x, -delta.y)]; +} +@end + +// +// JumpBy +// +#pragma mark - +#pragma mark JumpBy + +@implementation CCJumpBy ++(id) actionWithDuration: (ccTime) t position: (CGPoint) pos height: (ccTime) h jumps:(int)j +{ + return [[[self alloc] initWithDuration: t position: pos height: h jumps:j] autorelease]; +} + +-(id) initWithDuration: (ccTime) t position: (CGPoint) pos height: (ccTime) h jumps:(int)j +{ + if( (self=[super initWithDuration:t]) ) { + delta = pos; + height = h; + jumps = j; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] position: delta height:height jumps:jumps]; + return copy; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + startPosition = [(CCNode*)target_ position]; +} + +-(void) update: (ccTime) t +{ + // Sin jump. Less realistic +// ccTime y = height * fabsf( sinf(t * (CGFloat)M_PI * jumps ) ); +// y += delta.y * t; +// ccTime x = delta.x * t; +// [target setPosition: ccp( startPosition.x + x, startPosition.y + y )]; + + // parabolic jump (since v0.8.2) + ccTime frac = fmodf( t * jumps, 1.0f ); + ccTime y = height * 4 * frac * (1 - frac); + y += delta.y * t; + ccTime x = delta.x * t; + [target_ setPosition: ccp( startPosition.x + x, startPosition.y + y )]; + +} + +-(CCActionInterval*) reverse +{ + return [[self class] actionWithDuration:duration_ position: ccp(-delta.x,-delta.y) height: height jumps:jumps]; +} +@end + +// +// JumpTo +// +#pragma mark - +#pragma mark JumpTo + +@implementation CCJumpTo +-(void) startWithTarget:(CCNode *)aTarget +{ + [super startWithTarget:aTarget]; + delta = ccp( delta.x - startPosition.x, delta.y - startPosition.y ); +} +@end + + +#pragma mark - +#pragma mark BezierBy + +// 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, ccTime 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 +// +@implementation CCBezierBy ++(id) actionWithDuration: (ccTime) t bezier:(ccBezierConfig) c +{ + return [[[self alloc] initWithDuration:t bezier:c ] autorelease]; +} + +-(id) initWithDuration: (ccTime) t bezier:(ccBezierConfig) c +{ + if( (self=[super initWithDuration: t]) ) { + config = c; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] bezier: config]; + return copy; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + startPosition = [(CCNode*)target_ position]; +} + +-(void) update: (ccTime) t +{ + 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, t); + float y = bezierat(ya, yb, yc, yd, t); + [target_ setPosition: ccpAdd( startPosition, ccp(x,y))]; +} + +- (CCActionInterval*) reverse +{ + ccBezierConfig r; + + r.endPosition = ccpNeg(config.endPosition); + r.controlPoint_1 = ccpAdd(config.controlPoint_2, ccpNeg(config.endPosition)); + r.controlPoint_2 = ccpAdd(config.controlPoint_1, ccpNeg(config.endPosition)); + + CCBezierBy *action = [[self class] actionWithDuration:[self duration] bezier:r]; + return action; +} +@end + +// +// BezierTo +// +#pragma mark - +#pragma mark BezierTo +@implementation CCBezierTo +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + config.controlPoint_1 = ccpSub(config.controlPoint_1, startPosition); + config.controlPoint_2 = ccpSub(config.controlPoint_2, startPosition); + config.endPosition = ccpSub(config.endPosition, startPosition); +} +@end + + +// +// ScaleTo +// +#pragma mark - +#pragma mark ScaleTo +@implementation CCScaleTo ++(id) actionWithDuration: (ccTime) t scale:(float) s +{ + return [[[self alloc] initWithDuration: t scale:s] autorelease]; +} + +-(id) initWithDuration: (ccTime) t scale:(float) s +{ + if( (self=[super initWithDuration: t]) ) { + endScaleX = s; + endScaleY = s; + } + return self; +} + ++(id) actionWithDuration: (ccTime) t scaleX:(float)sx scaleY:(float)sy +{ + return [[[self alloc] initWithDuration: t scaleX:sx scaleY:sy] autorelease]; +} + +-(id) initWithDuration: (ccTime) t scaleX:(float)sx scaleY:(float)sy +{ + if( (self=[super initWithDuration: t]) ) { + endScaleX = sx; + endScaleY = sy; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] scaleX:endScaleX scaleY:endScaleY]; + return copy; +} + +-(void) startWithTarget:(CCNode *)aTarget +{ + [super startWithTarget:aTarget]; + startScaleX = [target_ scaleX]; + startScaleY = [target_ scaleY]; + deltaX = endScaleX - startScaleX; + deltaY = endScaleY - startScaleY; +} + +-(void) update: (ccTime) t +{ + [target_ setScaleX: (startScaleX + deltaX * t ) ]; + [target_ setScaleY: (startScaleY + deltaY * t ) ]; +} +@end + +// +// ScaleBy +// +#pragma mark - +#pragma mark ScaleBy +@implementation CCScaleBy +-(void) startWithTarget:(CCNode *)aTarget +{ + [super startWithTarget:aTarget]; + deltaX = startScaleX * endScaleX - startScaleX; + deltaY = startScaleY * endScaleY - startScaleY; +} + +-(CCActionInterval*) reverse +{ + return [[self class] actionWithDuration:duration_ scaleX: 1/endScaleX scaleY:1/endScaleY]; +} +@end + +// +// Blink +// +#pragma mark - +#pragma mark Blink +@implementation CCBlink ++(id) actionWithDuration: (ccTime) t blinks: (unsigned int) b +{ + return [[[ self alloc] initWithDuration: t blinks: b] autorelease]; +} + +-(id) initWithDuration: (ccTime) t blinks: (unsigned int) b +{ + if( (self=[super initWithDuration: t] ) ) + times = b; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] blinks: times]; + return copy; +} + +-(void) update: (ccTime) t +{ + if( ! [self isDone] ) { + ccTime slice = 1.0f / times; + ccTime m = fmodf(t, slice); + [target_ setVisible: (m > slice/2) ? YES : NO]; + } +} + +-(CCActionInterval*) reverse +{ + // return 'self' + return [[self class] actionWithDuration:duration_ blinks: times]; +} +@end + +// +// FadeIn +// +#pragma mark - +#pragma mark FadeIn +@implementation CCFadeIn +-(void) update: (ccTime) t +{ + [(id) target_ setOpacity: 255 *t]; +} + +-(CCActionInterval*) reverse +{ + return [CCFadeOut actionWithDuration:duration_]; +} +@end + +// +// FadeOut +// +#pragma mark - +#pragma mark FadeOut +@implementation CCFadeOut +-(void) update: (ccTime) t +{ + [(id) target_ setOpacity: 255 *(1-t)]; +} + +-(CCActionInterval*) reverse +{ + return [CCFadeIn actionWithDuration:duration_]; +} +@end + +// +// FadeTo +// +#pragma mark - +#pragma mark FadeTo +@implementation CCFadeTo ++(id) actionWithDuration: (ccTime) t opacity: (GLubyte) o +{ + return [[[ self alloc] initWithDuration: t opacity: o] autorelease]; +} + +-(id) initWithDuration: (ccTime) t opacity: (GLubyte) o +{ + if( (self=[super initWithDuration: t] ) ) + toOpacity = o; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] opacity: toOpacity]; + return copy; +} + +-(void) startWithTarget:(CCNode *)aTarget +{ + [super startWithTarget:aTarget]; + fromOpacity = [(id)target_ opacity]; +} + +-(void) update: (ccTime) t +{ + [(id)target_ setOpacity: fromOpacity + ( toOpacity - fromOpacity ) * t]; +} +@end + +// +// TintTo +// +#pragma mark - +#pragma mark TintTo +@implementation CCTintTo ++(id) actionWithDuration:(ccTime)t red:(GLubyte)r green:(GLubyte)g blue:(GLubyte)b +{ + return [[(CCTintTo*)[ self alloc] initWithDuration:t red:r green:g blue:b] autorelease]; +} + +-(id) initWithDuration: (ccTime) t red:(GLubyte)r green:(GLubyte)g blue:(GLubyte)b +{ + if( (self=[super initWithDuration: t] ) ) + to = ccc3(r,g,b); + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [(CCTintTo*)[[self class] allocWithZone: zone] initWithDuration: [self duration] red:to.r green:to.g blue:to.b]; + return copy; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + + id tn = (id) target_; + from = [tn color]; +} + +-(void) update: (ccTime) t +{ + id tn = (id) target_; + [tn setColor:ccc3(from.r + (to.r - from.r) * t, from.g + (to.g - from.g) * t, from.b + (to.b - from.b) * t)]; +} +@end + +// +// TintBy +// +#pragma mark - +#pragma mark TintBy +@implementation CCTintBy ++(id) actionWithDuration:(ccTime)t red:(GLshort)r green:(GLshort)g blue:(GLshort)b +{ + return [[(CCTintBy*)[ self alloc] initWithDuration:t red:r green:g blue:b] autorelease]; +} + +-(id) initWithDuration:(ccTime)t red:(GLshort)r green:(GLshort)g blue:(GLshort)b +{ + if( (self=[super initWithDuration: t] ) ) { + deltaR = r; + deltaG = g; + deltaB = b; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + return[(CCTintBy*)[[self class] allocWithZone: zone] initWithDuration: [self duration] red:deltaR green:deltaG blue:deltaB]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + + id tn = (id) target_; + ccColor3B color = [tn color]; + fromR = color.r; + fromG = color.g; + fromB = color.b; +} + +-(void) update: (ccTime) t +{ + id tn = (id) target_; + [tn setColor:ccc3( fromR + deltaR * t, fromG + deltaG * t, fromB + deltaB * t)]; +} + +- (CCActionInterval*) reverse +{ + return [CCTintBy actionWithDuration:duration_ red:-deltaR green:-deltaG blue:-deltaB]; +} +@end + +// +// DelayTime +// +#pragma mark - +#pragma mark DelayTime +@implementation CCDelayTime +-(void) update: (ccTime) t +{ + return; +} + +-(id)reverse +{ + return [[self class] actionWithDuration:duration_]; +} +@end + +// +// ReverseTime +// +#pragma mark - +#pragma mark ReverseTime +@implementation CCReverseTime ++(id) actionWithAction: (CCFiniteTimeAction*) action +{ + // casting to prevent warnings + CCReverseTime *a = [super alloc]; + return [[a initWithAction:action] autorelease]; +} + +-(id) initWithAction: (CCFiniteTimeAction*) action +{ + if( (self=[super initWithDuration: [action duration]]) ) + other = [action retain]; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone: zone] initWithAction:[[other copy] autorelease] ]; +} + +-(void) dealloc +{ + [other release]; + [super dealloc]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [other startWithTarget:target_]; +} + +-(void) stop +{ + [other stop]; + [super stop]; +} + +-(void) update:(ccTime)t +{ + [other update:1-t]; +} + +-(CCActionInterval*) reverse +{ + return [[other copy] autorelease]; +} +@end + +// +// Animate +// + +#pragma mark - +#pragma mark Animate +@implementation CCAnimate + +@synthesize animation = animation_; + ++(id) actionWithAnimation: (CCAnimation*)anim +{ + return [[[self alloc] initWithAnimation:anim restoreOriginalFrame:YES] autorelease]; +} + ++(id) actionWithAnimation: (CCAnimation*)anim restoreOriginalFrame:(BOOL)b +{ + return [[[self alloc] initWithAnimation:anim restoreOriginalFrame:b] autorelease]; +} + ++(id) actionWithDuration:(ccTime)duration animation: (CCAnimation*)anim restoreOriginalFrame:(BOOL)b +{ + return [[[self alloc] initWithDuration:duration animation:anim restoreOriginalFrame:b] autorelease]; +} + +-(id) initWithAnimation: (CCAnimation*)anim +{ + NSAssert( anim!=nil, @"Animate: argument Animation must be non-nil"); + return [self initWithAnimation:anim restoreOriginalFrame:YES]; +} + +-(id) initWithAnimation: (CCAnimation*)anim restoreOriginalFrame:(BOOL) b +{ + NSAssert( anim!=nil, @"Animate: argument Animation must be non-nil"); + + if( (self=[super initWithDuration: [[anim frames] count] * [anim delay]]) ) { + + restoreOriginalFrame = b; + self.animation = anim; + origFrame = nil; + } + return self; +} + +-(id) initWithDuration:(ccTime)aDuration animation: (CCAnimation*)anim restoreOriginalFrame:(BOOL) b +{ + NSAssert( anim!=nil, @"Animate: argument Animation must be non-nil"); + + if( (self=[super initWithDuration:aDuration] ) ) { + + restoreOriginalFrame = b; + self.animation = anim; + origFrame = nil; + } + return self; +} + + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone: zone] initWithDuration:duration_ animation:animation_ restoreOriginalFrame:restoreOriginalFrame]; +} + +-(void) dealloc +{ + [animation_ release]; + [origFrame release]; + [super dealloc]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + CCSprite *sprite = target_; + + [origFrame release]; + + if( restoreOriginalFrame ) + origFrame = [[sprite displayedFrame] retain]; +} + +-(void) stop +{ + if( restoreOriginalFrame ) { + CCSprite *sprite = target_; + [sprite setDisplayFrame:origFrame]; + } + + [super stop]; +} + +-(void) update: (ccTime) t +{ + NSArray *frames = [animation_ frames]; + NSUInteger numberOfFrames = [frames count]; + + NSUInteger idx = t * numberOfFrames; + + if( idx >= numberOfFrames ) + idx = numberOfFrames -1; + + CCSprite *sprite = target_; + if (! [sprite isFrameDisplayed: [frames objectAtIndex: idx]] ) + [sprite setDisplayFrame: [frames objectAtIndex:idx]]; +} + +- (CCActionInterval *) reverse +{ + NSArray *oldArray = [animation_ frames]; + NSMutableArray *newArray = [NSMutableArray arrayWithCapacity:[oldArray count]]; + NSEnumerator *enumerator = [oldArray reverseObjectEnumerator]; + for (id element in enumerator) + [newArray addObject:[[element copy] autorelease]]; + + CCAnimation *newAnim = [CCAnimation animationWithFrames:newArray delay:animation_.delay]; + return [[self class] actionWithDuration:duration_ animation:newAnim restoreOriginalFrame:restoreOriginalFrame]; +} + +@end diff --git a/Classes/cocos2d/CCActionManager.h b/Classes/cocos2d/CCActionManager.h new file mode 100644 index 0000000..476390b --- /dev/null +++ b/Classes/cocos2d/CCActionManager.h @@ -0,0 +1,118 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2009 Valentin Milea + * + * 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. + * + */ + + +#import "CCAction.h" +#import "Support/ccCArray.h" +#import "Support/uthash.h" + +typedef struct _hashElement +{ + struct ccArray *actions; + id target; + unsigned int actionIndex; + CCAction *currentAction; + BOOL currentActionSalvaged; + BOOL paused; + UT_hash_handle hh; +} tHashElement; + + +/** CCActionManager 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 CCNode 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 CCNode. + - When you want to pause / resume the actions + + @since v0.8 + */ +@interface CCActionManager : NSObject +{ + tHashElement *targets; + tHashElement *currentTarget; + BOOL currentTargetSalvaged; +} + +/** returns a shared instance of the CCActionManager */ ++ (CCActionManager *)sharedManager; + +/** purges the shared action manager. It releases the retained instance. + @since v0.99.0 + */ ++(void)purgeSharedManager; + +// 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 paused, and the action will be added to the newly created target. + When the target is paused, the queued actions won't be 'ticked'. + */ +-(void) addAction: (CCAction*) action target:(id)target paused:(BOOL)paused; +/** Removes all actions from all the targers. + */ +-(void) removeAllActions; + +/** Removes all actions from a certain target. + All the actions that belongs to the target will be removed. + */ +-(void) removeAllActionsFromTarget:(id)target; +/** Removes an action given an action reference. + */ +-(void) removeAction: (CCAction*) action; +/** Removes an action given its tag and the target */ +-(void) removeActionByTag:(int)tag target:(id)target; +/** Gets an action given its tag an a target + @return the Action the with the given tag + */ +-(CCAction*) getActionByTag:(int) tag target:(id)target; +/** 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. + */ +-(int) numberOfRunningActionsInTarget:(id)target; + +/** Pauses the target: all running actions and newly added actions will be paused. + */ +-(void) pauseTarget:(id)target; +/** Resumes the target. All queued actions will be resumed. + */ +-(void) resumeTarget:(id)target; + +/** Resumes the target. All queued actions will be resumed. + @deprecated Use resumeTarget: instead. Will be removed in v1.0. + */ +-(void) resumeAllActionsForTarget:(id)target DEPRECATED_ATTRIBUTE; +/** Pauses the target: all running actions and newly added actions will be paused. + */ +-(void) pauseAllActionsForTarget:(id)target DEPRECATED_ATTRIBUTE; + + +@end + diff --git a/Classes/cocos2d/CCActionManager.m b/Classes/cocos2d/CCActionManager.m new file mode 100644 index 0000000..9a6376f --- /dev/null +++ b/Classes/cocos2d/CCActionManager.m @@ -0,0 +1,356 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2009 Valentin Milea + * + * 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. + * + */ + + +#import "CCActionManager.h" +#import "CCScheduler.h" +#import "ccMacros.h" + + +// +// singleton stuff +// +static CCActionManager *sharedManager_ = nil; + +@interface CCActionManager (Private) +-(void) removeActionAtIndex:(NSUInteger)index hashElement:(tHashElement*)element; +-(void) deleteHashElement:(tHashElement*)element; +-(void) actionAllocWithHashElement:(tHashElement*)element; +@end + + +@implementation CCActionManager + +#pragma mark ActionManager - init ++ (CCActionManager *)sharedManager +{ + if (!sharedManager_) + sharedManager_ = [[self alloc] init]; + + return sharedManager_; +} + ++(id)alloc +{ + NSAssert(sharedManager_ == nil, @"Attempted to allocate a second instance of a singleton."); + return [super alloc]; +} + ++(void)purgeSharedManager +{ + [[CCScheduler sharedScheduler] unscheduleUpdateForTarget:self]; + [sharedManager_ release]; + sharedManager_ = nil; +} + +-(id) init +{ + if ((self=[super init]) ) { + [[CCScheduler sharedScheduler] scheduleUpdateForTarget:self priority:0 paused:NO]; + targets = NULL; + } + + return self; +} + +- (void) dealloc +{ + CCLOGINFO( @"cocos2d: deallocing %@", self); + + [self removeAllActions]; + + sharedManager_ = nil; + + [super dealloc]; +} + +#pragma mark ActionManager - Private + +-(void) deleteHashElement:(tHashElement*)element +{ + ccArrayFree(element->actions); + HASH_DEL(targets, element); +// CCLOG(@"cocos2d: ---- buckets: %d/%d - %@", targets->entries, targets->size, element->target); + [element->target release]; + free(element); +} + +-(void) actionAllocWithHashElement:(tHashElement*)element +{ + // 4 actions per Node by default + if( element->actions == nil ) + element->actions = ccArrayNew(4); + else if( element->actions->num == element->actions->max ) + ccArrayDoubleCapacity(element->actions); +} + +-(void) removeActionAtIndex:(NSUInteger)index hashElement:(tHashElement*)element +{ + id action = element->actions->arr[index]; + + if( action == element->currentAction && !element->currentActionSalvaged ) { + [element->currentAction retain]; + element->currentActionSalvaged = YES; + } + + ccArrayRemoveObjectAtIndex(element->actions, index); + + // 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 = YES; + else + [self deleteHashElement: element]; + } +} + +#pragma mark ActionManager - Pause / Resume + +// XXX DEPRECATED. REMOVE IN 1.0 +-(void) pauseAllActionsForTarget:(id)target +{ + [self pauseTarget:target]; +} + +-(void) pauseTarget:(id)target +{ + tHashElement *element = NULL; + HASH_FIND_INT(targets, &target, element); + if( element ) + element->paused = YES; +// else +// CCLOG(@"cocos2d: pauseAllActions: Target not found"); +} + +// XXX DEPRECATED. REMOVE IN 1.0 +-(void) resumeAllActionsForTarget:(id)target +{ + [self resumeTarget:target]; +} + +-(void) resumeTarget:(id)target +{ + tHashElement *element = NULL; + HASH_FIND_INT(targets, &target, element); + if( element ) + element->paused = NO; +// else +// CCLOG(@"cocos2d: resumeAllActions: Target not found"); +} + +#pragma mark ActionManager - run + +-(void) addAction:(CCAction*)action target:(id)target paused:(BOOL)paused +{ + NSAssert( action != nil, @"Argument action must be non-nil"); + NSAssert( target != nil, @"Argument target must be non-nil"); + + tHashElement *element = NULL; + HASH_FIND_INT(targets, &target, element); + if( ! element ) { + element = calloc( sizeof( *element ), 1 ); + element->paused = paused; + element->target = [target retain]; + HASH_ADD_INT(targets, target, element); +// CCLOG(@"cocos2d: ---- buckets: %d/%d - %@", targets->entries, targets->size, element->target); + + } + + [self actionAllocWithHashElement:element]; + + NSAssert( !ccArrayContainsObject(element->actions, action), @"runAction: Action already running"); + ccArrayAppendObject(element->actions, action); + + [action startWithTarget:target]; +} + +#pragma mark ActionManager - remove + +-(void) removeAllActions +{ + for(tHashElement *element=targets; element != NULL; ) { + id target = element->target; + element = element->hh.next; + [self removeAllActionsFromTarget:target]; + } +} +-(void) removeAllActionsFromTarget:(id)target +{ + // explicit nil handling + if( target == nil ) + return; + + tHashElement *element = NULL; + HASH_FIND_INT(targets, &target, element); + if( element ) { + if( ccArrayContainsObject(element->actions, element->currentAction) && !element->currentActionSalvaged ) { + [element->currentAction retain]; + element->currentActionSalvaged = YES; + } + ccArrayRemoveAllObjects(element->actions); + if( currentTarget == element ) + currentTargetSalvaged = YES; + else + [self deleteHashElement:element]; + } +// else { +// CCLOG(@"cocos2d: removeAllActionsFromTarget: Target not found"); +// } +} + +-(void) removeAction: (CCAction*) action +{ + // explicit nil handling + if (action == nil) + return; + + tHashElement *element = NULL; + id target = [action originalTarget]; + HASH_FIND_INT(targets, &target, element ); + if( element ) { + NSUInteger i = ccArrayGetIndexOfObject(element->actions, action); + if( i != NSNotFound ) + [self removeActionAtIndex:i hashElement:element]; + } +// else { +// CCLOG(@"cocos2d: removeAction: Target not found"); +// } +} + +-(void) removeActionByTag:(int) aTag target:(id)target +{ + NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag"); + NSAssert( target != nil, @"Target should be ! nil"); + + tHashElement *element = NULL; + HASH_FIND_INT(targets, &target, element); + + if( element ) { + NSUInteger limit = element->actions->num; + for( NSUInteger i = 0; i < limit; i++) { + CCAction *a = element->actions->arr[i]; + + if( a.tag == aTag && [a originalTarget]==target) + return [self removeActionAtIndex:i hashElement:element]; + } +// CCLOG(@"cocos2d: removeActionByTag: Action not found!"); + } +// else { +// CCLOG(@"cocos2d: removeActionByTag: Target not found!"); +// } +} + +#pragma mark ActionManager - get + +-(CCAction*) getActionByTag:(int)aTag target:(id)target +{ + NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag"); + + tHashElement *element = NULL; + HASH_FIND_INT(targets, &target, element); + + if( element ) { + if( element->actions != nil ) { + NSUInteger limit = element->actions->num; + for( NSUInteger i = 0; i < limit; i++) { + CCAction *a = element->actions->arr[i]; + + if( a.tag == aTag ) + return a; + } + } +// CCLOG(@"cocos2d: getActionByTag: Action not found"); + } +// else { +// CCLOG(@"cocos2d: getActionByTag: Target not found"); +// } + return nil; +} + +-(int) numberOfRunningActionsInTarget:(id) target +{ + tHashElement *element = NULL; + HASH_FIND_INT(targets, &target, element); + if( element ) + return element->actions ? element->actions->num : 0; + +// CCLOG(@"cocos2d: numberOfRunningActionsInTarget: Target not found"); + return 0; +} + +#pragma mark ActionManager - main loop + +-(void) update: (ccTime) dt +{ + for(tHashElement *elt = targets; elt != NULL; ) { + + currentTarget = elt; + currentTargetSalvaged = NO; + + if( ! currentTarget->paused ) { + + // The 'actions' ccArray may change while inside this loop. + for( currentTarget->actionIndex = 0; currentTarget->actionIndex < currentTarget->actions->num; currentTarget->actionIndex++) { + currentTarget->currentAction = currentTarget->actions->arr[currentTarget->actionIndex]; + currentTarget->currentActionSalvaged = NO; + + [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]; + + CCAction *a = currentTarget->currentAction; + // Make currentAction nil to prevent removeAction from salvaging it. + currentTarget->currentAction = nil; + [self removeAction:a]; + } + + currentTarget->currentAction = nil; + } + } + + // elt, at this moment, is still valid + // so it is safe to ask this here (issue #490) + elt = elt->hh.next; + + // only delete currentTarget if no actions were scheduled during the cycle (issue #481) + if( currentTargetSalvaged && currentTarget->actions->num == 0 ) + [self deleteHashElement:currentTarget]; + } + + // issue #635 + currentTarget = nil; +} +@end diff --git a/Classes/cocos2d/CCActionPageTurn3D.h b/Classes/cocos2d/CCActionPageTurn3D.h new file mode 100644 index 0000000..39eb31d --- /dev/null +++ b/Classes/cocos2d/CCActionPageTurn3D.h @@ -0,0 +1,42 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Sindesso Pty Ltd http://www.sindesso.com/ + * + * 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. + * + */ + + +#import "CCActionGrid3D.h" + +/** + * This action simulates a page turn from the bottom right hand corner of the screen + * 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 + */ +@interface CCPageTurn3D : CCGrid3DAction +{ +} + +@end diff --git a/Classes/cocos2d/CCActionPageTurn3D.m b/Classes/cocos2d/CCActionPageTurn3D.m new file mode 100644 index 0000000..ee59500 --- /dev/null +++ b/Classes/cocos2d/CCActionPageTurn3D.m @@ -0,0 +1,86 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Sindesso Pty Ltd http://www.sindesso.com/ + * + * 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. + * + */ + +#import "CCActionPageTurn3D.h" + +@implementation CCPageTurn3D + +/* + * Update each tick + * Time is the percentage of the way through the duration + */ +-(void)update:(ccTime)time +{ + float tt = MAX( 0, time - 0.25f ); + float deltaAy = ( tt * tt * 500); + float ay = -100 - deltaAy; + + float deltaTheta = - (float) M_PI_2 * sqrtf( time) ; + float theta = /*0.01f*/ + (float) M_PI_2 +deltaTheta; + + float sinTheta = sinf(theta); + float cosTheta = cosf(theta); + + for( int i = 0; i <=gridSize_.x; i++ ) + { + for( int j = 0; j <= gridSize_.y; j++ ) + { + // Get original vertex + ccVertex3F p = [self originalVertex:ccg(i,j)]; + + 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 perspectve transform + p.z = (r * ( 1 - cosBeta ) * cosTheta) / 7; // "100" didn't work for + + // 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 + [self setVertex:ccg(i,j) vertex:p]; + } + } +} +@end diff --git a/Classes/cocos2d/CCActionProgressTimer.h b/Classes/cocos2d/CCActionProgressTimer.h new file mode 100644 index 0000000..500631b --- /dev/null +++ b/Classes/cocos2d/CCActionProgressTimer.h @@ -0,0 +1,59 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (C) 2010 Lam Pham + * + * 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. + * + */ + + +#import +#import "CCProgressTimer.h" +#import "CCActionInterval.h" + +/** + Progress to percentage +@since v0.99.1 +*/ +@interface CCProgressTo : CCActionInterval +{ + float to_; + float from_; +} +/** Creates and initializes with a duration and a percent */ ++(id) actionWithDuration:(ccTime)duration percent:(float)percent; +/** Initializes with a duration and a percent */ +-(id) initWithDuration:(ccTime)duration percent:(float)percent; +@end + +/** + Progress from a percentage to another percentage + @since v0.99.1 + */ +@interface CCProgressFromTo : CCActionInterval +{ + float to_; + float from_; +} +/** Creates and initializes the action with a duration, a "from" percentage and a "to" percentage */ ++(id) actionWithDuration:(ccTime)duration from:(float)fromPercentage to:(float) toPercentage; +/** Initializes the action with a duration, a "from" percentage and a "to" percentage */ +-(id) initWithDuration:(ccTime)duration from:(float)fromPercentage to:(float) toPercentage; +@end diff --git a/Classes/cocos2d/CCActionProgressTimer.m b/Classes/cocos2d/CCActionProgressTimer.m new file mode 100644 index 0000000..c242570 --- /dev/null +++ b/Classes/cocos2d/CCActionProgressTimer.m @@ -0,0 +1,103 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (C) 2010 Lam Pham + * + * 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. + * + */ + + +#import "CCActionProgressTimer.h" + +#define kProgressTimerCast CCProgressTimer* + +@implementation CCProgressTo ++(id) actionWithDuration: (ccTime) t percent: (float) v +{ + return [[[ self alloc] initWithDuration: t percent: v] autorelease]; +} + +-(id) initWithDuration: (ccTime) t percent: (float) v +{ + if( (self=[super initWithDuration: t] ) ) + to_ = v; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:duration_ percent:to_]; + return copy; +} + +-(void) startWithTarget:(id) aTarget; +{ + [super startWithTarget:aTarget]; + from_ = [(kProgressTimerCast)target_ percentage]; + + // XXX: Is this correct ? + // Adding it to support CCRepeat + if( from_ == 100) + from_ = 0; +} + +-(void) update: (ccTime) t +{ + [(kProgressTimerCast)target_ setPercentage: from_ + ( to_ - from_ ) * t]; +} +@end + +@implementation CCProgressFromTo ++(id) actionWithDuration: (ccTime) t from:(float)fromPercentage to:(float) toPercentage +{ + return [[[self alloc] initWithDuration: t from: fromPercentage to: toPercentage] autorelease]; +} + +-(id) initWithDuration: (ccTime) t from:(float)fromPercentage to:(float) toPercentage +{ + if( (self=[super initWithDuration: t] ) ){ + to_ = toPercentage; + from_ = fromPercentage; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:duration_ from:from_ to:to_]; + return copy; +} + +- (CCActionInterval *) reverse +{ + return [[self class] actionWithDuration:duration_ from:to_ to:from_]; +} + +-(void) startWithTarget:(id) aTarget; +{ + [super startWithTarget:aTarget]; +} + +-(void) update: (ccTime) t +{ + [(kProgressTimerCast)target_ setPercentage: from_ + ( to_ - from_ ) * t]; +} +@end diff --git a/Classes/cocos2d/CCActionTiledGrid.h b/Classes/cocos2d/CCActionTiledGrid.h new file mode 100644 index 0000000..5d88b16 --- /dev/null +++ b/Classes/cocos2d/CCActionTiledGrid.h @@ -0,0 +1,211 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * 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. + * + */ + +#import "CCActionGrid.h" + +/** CCShakyTiles3D action */ +@interface CCShakyTiles3D : CCTiledGrid3DAction +{ + int randrange; + BOOL shakeZ; +} + +/** creates the action with a range, whether or not to shake Z vertices, a grid size, and duration */ ++(id)actionWithRange:(int)range shakeZ:(BOOL)shakeZ grid:(ccGridSize)gridSize duration:(ccTime)d; +/** initializes the action with a range, whether or not to shake Z vertices, a grid size, and duration */ +-(id)initWithRange:(int)range shakeZ:(BOOL)shakeZ grid:(ccGridSize)gridSize duration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCShatteredTiles3D action */ +@interface CCShatteredTiles3D : CCTiledGrid3DAction +{ + int randrange; + BOOL once; + BOOL shatterZ; +} + +/** creates the action with a range, whether of not to shatter Z vertices, a grid size and duration */ ++(id)actionWithRange:(int)range shatterZ:(BOOL)shatterZ grid:(ccGridSize)gridSize duration:(ccTime)d; +/** initializes the action with a range, whether or not to shatter Z vertices, a grid size and duration */ +-(id)initWithRange:(int)range shatterZ:(BOOL)shatterZ grid:(ccGridSize)gridSize duration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCShuffleTiles action + Shuffle the tiles in random order + */ +@interface CCShuffleTiles : CCTiledGrid3DAction +{ + int seed; + int tilesCount; + int *tilesOrder; + void *tiles; +} + +/** creates the action with a random seed, the grid size and the duration */ ++(id)actionWithSeed:(int)s grid:(ccGridSize)gridSize duration:(ccTime)d; +/** initializes the action with a random seed, the grid size and the duration */ +-(id)initWithSeed:(int)s grid:(ccGridSize)gridSize duration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCFadeOutTRTiles action + Fades out the tiles in a Top-Right direction + */ +@interface CCFadeOutTRTiles : CCTiledGrid3DAction +{ +} +@end + +//////////////////////////////////////////////////////////// + +/** CCFadeOutBLTiles action. + Fades out the tiles in a Bottom-Left direction + */ +@interface CCFadeOutBLTiles : CCFadeOutTRTiles +{ +} +@end + +//////////////////////////////////////////////////////////// + +/** CCFadeOutUpTiles action. + Fades out the tiles in upwards direction + */ +@interface CCFadeOutUpTiles : CCFadeOutTRTiles +{ +} +@end + +//////////////////////////////////////////////////////////// + +/** CCFadeOutDownTiles action. + Fades out the tiles in downwards direction + */ +@interface CCFadeOutDownTiles : CCFadeOutUpTiles +{ +} +@end + +//////////////////////////////////////////////////////////// + +/** CCTurnOffTiles action. + Turn off the files in random order + */ +@interface CCTurnOffTiles : CCTiledGrid3DAction +{ + int seed; + int tilesCount; + int *tilesOrder; +} + +/** creates the action with a random seed, the grid size and the duration */ ++(id)actionWithSeed:(int)s grid:(ccGridSize)gridSize duration:(ccTime)d; +/** initializes the action with a random seed, the grid size and the duration */ +-(id)initWithSeed:(int)s grid:(ccGridSize)gridSize duration:(ccTime)d; +@end + +//////////////////////////////////////////////////////////// + +/** CCWavesTiles3D action. */ +@interface CCWavesTiles3D : CCTiledGrid3DAction +{ + int waves; + float amplitude; + float amplitudeRate; +} + +/** waves amplitude */ +@property (nonatomic,readwrite) float amplitude; +/** waves amplitude rate */ +@property (nonatomic,readwrite) float amplitudeRate; + +/** creates the action with a number of waves, the waves amplitude, the grid size and the duration */ ++(id)actionWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d; +/** initializes the action with a number of waves, the waves amplitude, the grid size and the duration */ +-(id)initWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCJumpTiles3D action. + A sin function is executed to move the tiles across the Z axis + */ +@interface CCJumpTiles3D : CCTiledGrid3DAction +{ + int jumps; + float amplitude; + float amplitudeRate; +} + +/** amplitude of the sin*/ +@property (nonatomic,readwrite) float amplitude; +/** amplitude rate */ +@property (nonatomic,readwrite) float amplitudeRate; + +/** creates the action with the number of jumps, the sin amplitude, the grid size and the duration */ ++(id)actionWithJumps:(int)j amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d; +/** initializes the action with the number of jumps, the sin amplitude, the grid size and the duration */ +-(id)initWithJumps:(int)j amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCSplitRows action */ +@interface CCSplitRows : CCTiledGrid3DAction +{ + int rows; + CGSize winSize; +} +/** creates the action with the number of rows to split and the duration */ ++(id)actionWithRows:(int)rows duration:(ccTime)duration; +/** initializes the action with the number of rows to split and the duration */ +-(id)initWithRows:(int)rows duration:(ccTime)duration; + +@end + +//////////////////////////////////////////////////////////// + +/** CCSplitCols action */ +@interface CCSplitCols : CCTiledGrid3DAction +{ + int cols; + CGSize winSize; +} +/** creates the action with the number of columns to split and the duration */ ++(id)actionWithCols:(int)cols duration:(ccTime)duration; +/** initializes the action with the number of columns to split and the duration */ +-(id)initWithCols:(int)cols duration:(ccTime)duration; + +@end diff --git a/Classes/cocos2d/CCActionTiledGrid.m b/Classes/cocos2d/CCActionTiledGrid.m new file mode 100644 index 0000000..4513866 --- /dev/null +++ b/Classes/cocos2d/CCActionTiledGrid.m @@ -0,0 +1,768 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * 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. + * + */ + + +#import "CCActionTiledGrid.h" +#import "CCDirector.h" +#import "ccMacros.h" +#import "Support/CGPointExtension.h" + +typedef struct +{ + CGPoint position; + CGPoint startPosition; + ccGridSize delta; +} Tile; + +#pragma mark - +#pragma mark ShakyTiles3D + +@implementation CCShakyTiles3D + ++(id)actionWithRange:(int)range shakeZ:(BOOL)shakeZ grid:(ccGridSize)gridSize duration:(ccTime)d +{ + return [[[self alloc] initWithRange:range shakeZ:shakeZ grid:gridSize duration:d] autorelease]; +} + +-(id)initWithRange:(int)range shakeZ:(BOOL)sz grid:(ccGridSize)gSize duration:(ccTime)d +{ + if ( (self = [super initWithSize:gSize duration:d]) ) + { + randrange = range; + shakeZ = sz; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithRange:randrange shakeZ:shakeZ grid:gridSize_ duration:duration_]; + return copy; +} + + +-(void)update:(ccTime)time +{ + int i, j; + + for( i = 0; i < gridSize_.x; i++ ) + { + for( j = 0; j < gridSize_.y; j++ ) + { + ccQuad3 coords = [self originalTile:ccg(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; + } + + [self setTile:ccg(i,j) coords:coords]; + } + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCShatteredTiles3D + +@implementation CCShatteredTiles3D + ++(id)actionWithRange:(int)range shatterZ:(BOOL)sz grid:(ccGridSize)gridSize duration:(ccTime)d +{ + return [[[self alloc] initWithRange:range shatterZ:sz grid:gridSize duration:d] autorelease]; +} + +-(id)initWithRange:(int)range shatterZ:(BOOL)sz grid:(ccGridSize)gSize duration:(ccTime)d +{ + if ( (self = [super initWithSize:gSize duration:d]) ) + { + once = NO; + randrange = range; + shatterZ = sz; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithRange:randrange shatterZ:shatterZ grid:gridSize_ duration:duration_]; + return copy; +} + + +-(void)update:(ccTime)time +{ + int i, j; + + if ( once == NO ) + { + for( i = 0; i < gridSize_.x; i++ ) + { + for( j = 0; j < gridSize_.y; j++ ) + { + ccQuad3 coords = [self originalTile:ccg(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; + } + + [self setTile:ccg(i,j) coords:coords]; + } + } + + once = YES; + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCShuffleTiles + +@implementation CCShuffleTiles + ++(id)actionWithSeed:(int)s grid:(ccGridSize)gridSize duration:(ccTime)d +{ + return [[[self alloc] initWithSeed:s grid:gridSize duration:d] autorelease]; +} + +-(id)initWithSeed:(int)s grid:(ccGridSize)gSize duration:(ccTime)d +{ + if ( (self = [super initWithSize:gSize duration:d]) ) + { + seed = s; + tilesOrder = nil; + tiles = nil; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithSeed:seed grid:gridSize_ duration:duration_]; + return copy; +} + + +-(void)dealloc +{ + if ( tilesOrder ) free(tilesOrder); + if ( tiles ) free(tiles); + [super dealloc]; +} + +-(void)shuffle:(int*)array count:(int)len +{ + int i; + for( i = len - 1; i >= 0; i-- ) + { + int j = rand() % (i+1); + int v = array[i]; + array[i] = array[j]; + array[j] = v; + } +} + +-(ccGridSize)getDelta:(ccGridSize)pos +{ + CGPoint pos2; + + int idx = pos.x * gridSize_.y + pos.y; + + pos2.x = tilesOrder[idx] / (int)gridSize_.y; + pos2.y = tilesOrder[idx] % (int)gridSize_.y; + + return ccg(pos2.x - pos.x, pos2.y - pos.y); +} + +-(void)placeTile:(ccGridSize)pos tile:(Tile)t +{ + ccQuad3 coords = [self originalTile:pos]; + + CGPoint step = [[target_ grid] step]; + 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); + + [self setTile:pos coords:coords]; +} + +-(void)startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + + if ( seed != -1 ) + srand(seed); + + tilesCount = gridSize_.x * gridSize_.y; + tilesOrder = (int*)malloc(tilesCount*sizeof(int)); + int i, j; + + for( i = 0; i < tilesCount; i++ ) + tilesOrder[i] = i; + + [self shuffle:tilesOrder count:tilesCount]; + + tiles = malloc(tilesCount*sizeof(Tile)); + Tile *tileArray = (Tile*)tiles; + + for( i = 0; i < gridSize_.x; i++ ) + { + for( j = 0; j < gridSize_.y; j++ ) + { + tileArray->position = ccp(i,j); + tileArray->startPosition = ccp(i,j); + tileArray->delta = [self getDelta:ccg(i,j)]; + tileArray++; + } + } +} + +-(void)update:(ccTime)time +{ + int i, j; + + Tile *tileArray = (Tile*)tiles; + + for( i = 0; i < gridSize_.x; i++ ) + { + for( j = 0; j < gridSize_.y; j++ ) + { + tileArray->position = ccpMult( ccp(tileArray->delta.x, tileArray->delta.y), time); + [self placeTile:ccg(i,j) tile:*tileArray]; + tileArray++; + } + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCFadeOutTRTiles + +@implementation CCFadeOutTRTiles + +-(float)testFunc:(ccGridSize)pos time:(ccTime)time +{ + CGPoint n = ccpMult( ccp(gridSize_.x,gridSize_.y), time); + if ( (n.x+n.y) == 0.0f ) + return 1.0f; + + return powf( (pos.x+pos.y) / (n.x+n.y), 6 ); +} + +-(void)turnOnTile:(ccGridSize)pos +{ + [self setTile:pos coords:[self originalTile:pos]]; +} + +-(void)turnOffTile:(ccGridSize)pos +{ + ccQuad3 coords; + bzero(&coords, sizeof(ccQuad3)); + [self setTile:pos coords:coords]; +} + +-(void)transformTile:(ccGridSize)pos distance:(float)distance +{ + ccQuad3 coords = [self originalTile:pos]; + CGPoint step = [[target_ grid] step]; + + 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); + + [self setTile:pos coords:coords]; +} + +-(void)update:(ccTime)time +{ + int i, j; + + for( i = 0; i < gridSize_.x; i++ ) + { + for( j = 0; j < gridSize_.y; j++ ) + { + float distance = [self testFunc:ccg(i,j) time:time]; + if ( distance == 0 ) + [self turnOffTile:ccg(i,j)]; + else if ( distance < 1 ) + [self transformTile:ccg(i,j) distance:distance]; + else + [self turnOnTile:ccg(i,j)]; + } + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCFadeOutBLTiles + +@implementation CCFadeOutBLTiles + +-(float)testFunc:(ccGridSize)pos time:(ccTime)time +{ + CGPoint n = ccpMult(ccp(gridSize_.x, gridSize_.y), (1.0f-time)); + if ( (pos.x+pos.y) == 0 ) + return 1.0f; + + return powf( (n.x+n.y) / (pos.x+pos.y), 6 ); +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCFadeOutUpTiles + +@implementation CCFadeOutUpTiles + +-(float)testFunc:(ccGridSize)pos time:(ccTime)time +{ + CGPoint n = ccpMult(ccp(gridSize_.x, gridSize_.y), time); + if ( n.y == 0 ) + return 1.0f; + + return powf( pos.y / n.y, 6 ); +} + +-(void)transformTile:(ccGridSize)pos distance:(float)distance +{ + ccQuad3 coords = [self originalTile:pos]; + CGPoint step = [[target_ grid] step]; + + 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); + + [self setTile:pos coords:coords]; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCFadeOutDownTiles + +@implementation CCFadeOutDownTiles + +-(float)testFunc:(ccGridSize)pos time:(ccTime)time +{ + CGPoint n = ccpMult(ccp(gridSize_.x,gridSize_.y), (1.0f - time)); + if ( pos.y == 0 ) + return 1.0f; + + return powf( n.y / pos.y, 6 ); +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark TurnOffTiles + +@implementation CCTurnOffTiles + ++(id)actionWithSeed:(int)s grid:(ccGridSize)gridSize duration:(ccTime)d +{ + return [[[self alloc] initWithSeed:s grid:gridSize duration:d] autorelease]; +} + +-(id)initWithSeed:(int)s grid:(ccGridSize)gSize duration:(ccTime)d +{ + if ( (self = [super initWithSize:gSize duration:d]) ) + { + seed = s; + tilesOrder = nil; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithSeed:seed grid:gridSize_ duration:duration_]; + return copy; +} + +-(void)dealloc +{ + if ( tilesOrder ) free(tilesOrder); + [super dealloc]; +} + +-(void)shuffle:(int*)array count:(int)len +{ + int i; + for( i = len - 1; i >= 0; i-- ) + { + int j = rand() % (i+1); + int v = array[i]; + array[i] = array[j]; + array[j] = v; + } +} + +-(void)turnOnTile:(ccGridSize)pos +{ + [self setTile:pos coords:[self originalTile:pos]]; +} + +-(void)turnOffTile:(ccGridSize)pos +{ + ccQuad3 coords; + + bzero(&coords, sizeof(ccQuad3)); + [self setTile:pos coords:coords]; +} + +-(void)startWithTarget:(id)aTarget +{ + int i; + + [super startWithTarget:aTarget]; + + if ( seed != -1 ) + srand(seed); + + tilesCount = gridSize_.x * gridSize_.y; + tilesOrder = (int*)malloc(tilesCount*sizeof(int)); + + for( i = 0; i < tilesCount; i++ ) + tilesOrder[i] = i; + + [self shuffle:tilesOrder count:tilesCount]; +} + +-(void)update:(ccTime)time +{ + int i, l, t; + + l = (int)(time * (float)tilesCount); + + for( i = 0; i < tilesCount; i++ ) + { + t = tilesOrder[i]; + ccGridSize tilePos = ccg( t / gridSize_.y, t % gridSize_.y ); + + if ( i < l ) + [self turnOffTile:tilePos]; + else + [self turnOnTile:tilePos]; + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCWavesTiles3D + +@implementation CCWavesTiles3D + +@synthesize amplitude; +@synthesize amplitudeRate; + ++(id)actionWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d +{ + return [[[self alloc] initWithWaves:wav amplitude:amp grid:gridSize duration:d] autorelease]; +} + +-(id)initWithWaves:(int)wav amplitude:(float)amp grid:(ccGridSize)gSize duration:(ccTime)d +{ + if ( (self = [super initWithSize:gSize duration:d]) ) + { + waves = wav; + amplitude = amp; + amplitudeRate = 1.0f; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithWaves:waves amplitude:amplitude grid:gridSize_ duration:duration_]; + return copy; +} + + +-(void)update:(ccTime)time +{ + int i, j; + + for( i = 0; i < gridSize_.x; i++ ) + { + for( j = 0; j < gridSize_.y; j++ ) + { + ccQuad3 coords = [self originalTile:ccg(i,j)]; + + coords.bl.z = (sinf(time*(CGFloat)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; + + [self setTile:ccg(i,j) coords:coords]; + } + } +} +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCJumpTiles3D + +@implementation CCJumpTiles3D + +@synthesize amplitude; +@synthesize amplitudeRate; + ++(id)actionWithJumps:(int)j amplitude:(float)amp grid:(ccGridSize)gridSize duration:(ccTime)d +{ + return [[[self alloc] initWithJumps:j amplitude:amp grid:gridSize duration:d] autorelease]; +} + +-(id)initWithJumps:(int)j amplitude:(float)amp grid:(ccGridSize)gSize duration:(ccTime)d +{ + if ( (self = [super initWithSize:gSize duration:d]) ) + { + jumps = j; + amplitude = amp; + amplitudeRate = 1.0f; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithJumps:jumps amplitude:amplitude grid:gridSize_ duration:duration_]; + return copy; +} + + +-(void)update:(ccTime)time +{ + int i, j; + + float sinz = (sinf((CGFloat)M_PI*time*jumps*2) * amplitude * amplitudeRate ); + float sinz2 = (sinf((CGFloat)M_PI*(time*jumps*2 + 1)) * amplitude * amplitudeRate ); + + for( i = 0; i < gridSize_.x; i++ ) + { + for( j = 0; j < gridSize_.y; j++ ) + { + ccQuad3 coords = [self originalTile:ccg(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; + } + + [self setTile:ccg(i,j) coords:coords]; + } + } +} +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark SplitRows + +@implementation CCSplitRows + ++(id)actionWithRows:(int)r duration:(ccTime)d +{ + return [[[self alloc] initWithRows:r duration:d] autorelease]; +} + +-(id)initWithRows:(int)r duration:(ccTime)d +{ + rows = r; + return [super initWithSize:ccg(1,r) duration:d]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithRows:rows duration:duration_]; + return copy; +} + +-(void)startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + winSize = [[CCDirector sharedDirector] winSizeInPixels]; +} + +-(void)update:(ccTime)time +{ + int j; + + for( j = 0; j < gridSize_.y; j++ ) + { + ccQuad3 coords = [self originalTile:ccg(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; + + [self setTile:ccg(0,j) coords:coords]; + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCSplitCols + +@implementation CCSplitCols + ++(id)actionWithCols:(int)c duration:(ccTime)d +{ + return [[[self alloc] initWithCols:c duration:d] autorelease]; +} + +-(id)initWithCols:(int)c duration:(ccTime)d +{ + cols = c; + return [super initWithSize:ccg(c,1) duration:d]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithCols:cols duration:duration_]; + return copy; +} + +-(void)startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + winSize = [[CCDirector sharedDirector] winSizeInPixels]; +} + +-(void)update:(ccTime)time +{ + int i; + + for( i = 0; i < gridSize_.x; i++ ) + { + ccQuad3 coords = [self originalTile:ccg(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; + + [self setTile:ccg(i,0) coords:coords]; + } +} + +@end diff --git a/Classes/cocos2d/CCActionTween.h b/Classes/cocos2d/CCActionTween.h new file mode 100644 index 0000000..69fdea5 --- /dev/null +++ b/Classes/cocos2d/CCActionTween.h @@ -0,0 +1,62 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright 2009 lhunath (Maarten Billemont) + * + * 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. + * + */ + + +#import +#import "CCActionInterval.h" + +/** CCActionTween + + CCActionTween 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 senconds, then: + + id modifyWidth = [CCActionTween actionWithDuration:2 key:@"width" from:200 to:300]; + [target runAction:modifyWidth]; + + + Another example: CCScaleTo action could be rewriten using CCPropertyAction: + + // scaleA and scaleB are equivalents + id scaleA = [CCScaleTo actionWithDuration:2 scale:3]; + id scaleB = [CCActionTween actionWithDuration:2 key:@"scale" from:1 to:3]; + + + @since v0.99.2 + */ +@interface CCActionTween : CCActionInterval +{ + NSString *key_; + + float from_, to_; + float delta_; +} + +/** creates an initializes the action with the property name (key), and the from and to parameters. */ ++ (id)actionWithDuration:(ccTime)aDuration key:(NSString *)key from:(float)from to:(float)to; + +/** initializes the action with the property name (key), and the from and to parameters. */ +- (id)initWithDuration:(ccTime)aDuration key:(NSString *)key from:(float)from to:(float)to; + +@end diff --git a/Classes/cocos2d/CCActionTween.m b/Classes/cocos2d/CCActionTween.m new file mode 100644 index 0000000..95ae572 --- /dev/null +++ b/Classes/cocos2d/CCActionTween.m @@ -0,0 +1,72 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright 2009 lhunath (Maarten Billemont) + * + * 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. + * + */ + +#import "CCActionTween.h" + + +@implementation CCActionTween + ++ (id)actionWithDuration:(ccTime)aDuration key:(NSString *)aKey from:(float)aFrom to:(float)aTo { + + return [[[[self class] alloc] initWithDuration:aDuration key:aKey from:aFrom to:aTo] autorelease]; +} + +- (id)initWithDuration:(ccTime)aDuration key:(NSString *)key from:(float)from to:(float)to { + + if ((self = [super initWithDuration:aDuration])) { + + key_ = [key copy]; + to_ = to; + from_ = from; + + } + + return self; +} + +- (void) dealloc +{ + [key_ release]; + [super dealloc]; +} + +- (void)startWithTarget:aTarget +{ + [super startWithTarget:aTarget]; + delta_ = to_ - from_; +} + +- (void) update:(ccTime) dt +{ + [target_ setValue:[NSNumber numberWithFloat:to_ - delta_ * (1 - dt)] forKey:key_]; +} + +- (CCActionInterval *) reverse +{ + return [[self class] actionWithDuration:duration_ key:key_ from:to_ to:from_]; +} + + +@end diff --git a/Classes/cocos2d/CCAnimation.h b/Classes/cocos2d/CCAnimation.h new file mode 100644 index 0000000..86c089c --- /dev/null +++ b/Classes/cocos2d/CCAnimation.h @@ -0,0 +1,132 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + +#import + +@class CCSpriteFrame; +@class CCTexture2D; + +/** A CCAnimation object is used to perform animations on the CCSprite objects. + + The CCAnimation object contains CCSpriteFrame objects, and a possible delay between the frames. + You can animate a CCAnimation object by using the CCAnimate action. Example: + + [sprite runAction:[CCAnimate actionWithAnimation:animation]]; + + */ +@interface CCAnimation : NSObject +{ + NSString *name_; + float delay_; + NSMutableArray *frames_; +} + +/** name of the animation */ +@property (nonatomic,readwrite,retain) NSString *name; +/** delay between frames in seconds. */ +@property (nonatomic,readwrite,assign) float delay; +/** array of frames */ +@property (nonatomic,readwrite,retain) NSMutableArray *frames; + +/** Creates an animation + @since v0.99.5 + */ ++(id) animation; + +/** Creates an animation with frames. + @since v0.99.5 + */ ++(id) animationWithFrames:(NSArray*)frames; + +/* Creates an animation with frames and a delay between frames. + @since v0.99.5 + */ ++(id) animationWithFrames:(NSArray*)frames delay:(float)delay; + +/** Creates a CCAnimation with a name + @since v0.99.3 + @deprecated Will be removed in 1.0.1. Use "animation" instead. + */ ++(id) animationWithName:(NSString*)name DEPRECATED_ATTRIBUTE; + +/** Creates a CCAnimation with a name and frames + @since v0.99.3 + @deprecated Will be removed in 1.0.1. Use "animationWithFrames" instead. + */ ++(id) animationWithName:(NSString*)name frames:(NSArray*)frames DEPRECATED_ATTRIBUTE; + +/** Creates a CCAnimation with a name and delay between frames. */ ++(id) animationWithName:(NSString*)name delay:(float)delay DEPRECATED_ATTRIBUTE; + +/** Creates a CCAnimation with a name, delay and an array of CCSpriteFrames. */ ++(id) animationWithName:(NSString*)name delay:(float)delay frames:(NSArray*)frames DEPRECATED_ATTRIBUTE; + + +/** Initializes a CCAnimation with frames. + @since v0.99.5 +*/ +-(id) initWithFrames:(NSArray*)frames; + +/** Initializes a CCAnimation with frames and a delay between frames + @since v0.99.5 + */ +-(id) initWithFrames:(NSArray *)frames delay:(float)delay; + +/** Initializes a CCAnimation with a name + @since v0.99.3 + @deprecated Will be removed in 1.0.1. Use "init" instead. + */ +-(id) initWithName:(NSString*)name DEPRECATED_ATTRIBUTE; + +/** Initializes a CCAnimation with a name and frames + @since v0.99.3 + @deprecated Will be removed in 1.0.1. Use "initWithFrames" instead. + */ +-(id) initWithName:(NSString*)name frames:(NSArray*)frames DEPRECATED_ATTRIBUTE; + +/** Initializes a CCAnimation with a name and delay between frames. + @deprecated Will be removed in 1.0.1. Use "initWithFrames:nil delay:delay" instead. +*/ +-(id) initWithName:(NSString*)name delay:(float)delay DEPRECATED_ATTRIBUTE; + +/** Initializes a CCAnimation with a name, delay and an array of CCSpriteFrames. + @deprecated Will be removed in 1.0.1. Use "initWithFrames:frames delay:delay" instead. +*/ +-(id) initWithName:(NSString*)name delay:(float)delay frames:(NSArray*)frames DEPRECATED_ATTRIBUTE; + +/** Adds a frame to a CCAnimation. */ +-(void) addFrame:(CCSpriteFrame*)frame; + +/** Adds a frame with an image filename. Internally it will create a CCSpriteFrame and it will add it. + Added to facilitate the migration from v0.8 to v0.9. + */ +-(void) addFrameWithFilename:(NSString*)filename; + +/** Adds a frame with a texture and a rect. Internally it will create a CCSpriteFrame and it will add it. + Added to facilitate the migration from v0.8 to v0.9. + */ +-(void) addFrameWithTexture:(CCTexture2D*)texture rect:(CGRect)rect; + +@end diff --git a/Classes/cocos2d/CCAnimation.m b/Classes/cocos2d/CCAnimation.m new file mode 100644 index 0000000..bb8480c --- /dev/null +++ b/Classes/cocos2d/CCAnimation.m @@ -0,0 +1,152 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + +#import "ccMacros.h" +#import "CCAnimation.h" +#import "CCSpriteFrame.h" +#import "CCTexture2D.h" +#import "CCTextureCache.h" + +@implementation CCAnimation +@synthesize name = name_, delay = delay_, frames = frames_; + ++(id) animation +{ + return [[[self alloc] init] autorelease]; +} + ++(id) animationWithFrames:(NSArray*)frames +{ + return [[[self alloc] initWithFrames:frames] autorelease]; +} + ++(id) animationWithFrames:(NSArray*)frames delay:(float)delay +{ + return [[[self alloc] initWithFrames:frames delay:delay] autorelease]; +} + ++(id) animationWithName:(NSString*)name +{ + return [[[self alloc] initWithName:name] autorelease]; +} + ++(id) animationWithName:(NSString*)name frames:(NSArray*)frames +{ + return [[[self alloc] initWithName:name frames:frames] autorelease]; +} + ++(id) animationWithName:(NSString*)aname delay:(float)d frames:(NSArray*)array +{ + return [[[self alloc] initWithName:aname delay:d frames:array] autorelease]; +} + ++(id) animationWithName:(NSString*)aname delay:(float)d +{ + return [[[self alloc] initWithName:aname delay:d] autorelease]; +} + +-(id) init +{ + return [self initWithFrames:nil delay:0]; +} + +-(id) initWithFrames:(NSArray*)frames +{ + return [self initWithFrames:frames delay:0]; +} + +-(id) initWithFrames:(NSArray*)array delay:(float)delay +{ + if( (self=[super init]) ) { + + delay_ = delay; + self.frames = [NSMutableArray arrayWithArray:array]; + } + return self; +} + +-(id) initWithName:(NSString*)name +{ + return [self initWithName:name delay:0 frames:nil]; +} + +-(id) initWithName:(NSString*)name frames:(NSArray*)frames +{ + return [self initWithName:name delay:0 frames:frames]; +} + +-(id) initWithName:(NSString*)t delay:(float)d +{ + return [self initWithName:t delay:d frames:nil]; +} + +-(id) initWithName:(NSString*)name delay:(float)delay frames:(NSArray*)array +{ + if( (self=[super init]) ) { + + delay_ = delay; + self.name = name; + self.frames = [NSMutableArray arrayWithArray:array]; + } + return self; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %08X | frames=%d, delay:%f>", [self class], self, + [frames_ count], + delay_ + ]; +} + +-(void) dealloc +{ + CCLOGINFO( @"cocos2d: deallocing %@",self); + [name_ release]; + [frames_ release]; + [super dealloc]; +} + +-(void) addFrame:(CCSpriteFrame*)frame +{ + [frames_ addObject:frame]; +} + +-(void) addFrameWithFilename:(NSString*)filename +{ + CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:filename]; + CGRect rect = CGRectZero; + rect.size = texture.contentSize; + CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:texture rect:rect]; + [frames_ addObject:frame]; +} + +-(void) addFrameWithTexture:(CCTexture2D*)texture rect:(CGRect)rect +{ + CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:texture rect:rect]; + [frames_ addObject:frame]; +} + +@end diff --git a/Classes/cocos2d/CCAnimationCache.h b/Classes/cocos2d/CCAnimationCache.h new file mode 100644 index 0000000..3a9b8ae --- /dev/null +++ b/Classes/cocos2d/CCAnimationCache.h @@ -0,0 +1,63 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * + * 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. + * + */ + +#import + +@class CCAnimation; + +/** 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 CCSprite. Since v0.99.5, you should use this class instead. + + @since v0.99.5 + */ +@interface CCAnimationCache : NSObject +{ + NSMutableDictionary *animations_; +} + +/** Retruns ths shared instance of the Animation cache */ ++ (CCAnimationCache *) sharedAnimationCache; + +/** Purges the cache. It releases all the CCAnimation objects and the shared instance. + */ ++(void)purgeSharedAnimationCache; + +/** Adds a CCAnimation with a name. + */ +-(void) addAnimation:(CCAnimation*)animation name:(NSString*)name; + +/** Deletes a CCAnimation from the cache. + */ +-(void) removeAnimationByName:(NSString*)name; + +/** Returns a CCAnimation 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. + */ +-(CCAnimation*) animationByName:(NSString*)name; + +@end diff --git a/Classes/cocos2d/CCAnimationCache.m b/Classes/cocos2d/CCAnimationCache.m new file mode 100644 index 0000000..003bc63 --- /dev/null +++ b/Classes/cocos2d/CCAnimationCache.m @@ -0,0 +1,100 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * + * 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. + * + */ + +#import "ccMacros.h" +#import "CCAnimationCache.h" +#import "CCAnimation.h" +#import "CCSprite.h" + + +@implementation CCAnimationCache + +#pragma mark CCAnimationCache - Alloc, Init & Dealloc + +static CCAnimationCache *sharedAnimationCache_=nil; + ++ (CCAnimationCache *)sharedAnimationCache +{ + if (!sharedAnimationCache_) + sharedAnimationCache_ = [[CCAnimationCache alloc] init]; + + return sharedAnimationCache_; +} + ++(id)alloc +{ + NSAssert(sharedAnimationCache_ == nil, @"Attempted to allocate a second instance of a singleton."); + return [super alloc]; +} + ++(void)purgeSharedAnimationCache +{ + [sharedAnimationCache_ release]; + sharedAnimationCache_ = nil; +} + +-(id) init +{ + if( (self=[super init]) ) { + animations_ = [[NSMutableDictionary alloc] initWithCapacity: 20]; + } + + return self; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %08X | num of animations = %i>", [self class], self, [animations_ count]]; +} + +-(void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + + [animations_ release]; + [super dealloc]; +} + +#pragma mark CCAnimationCache - load/get/del + +-(void) addAnimation:(CCAnimation*)animation name:(NSString*)name +{ + [animations_ setObject:animation forKey:name]; +} + +-(void) removeAnimationByName:(NSString*)name +{ + if( ! name ) + return; + + [animations_ removeObjectForKey:name]; +} + +-(CCAnimation*) animationByName:(NSString*)name +{ + return [animations_ objectForKey:name]; +} + +@end diff --git a/Classes/cocos2d/CCAtlasNode.h b/Classes/cocos2d/CCAtlasNode.h new file mode 100644 index 0000000..145586f --- /dev/null +++ b/Classes/cocos2d/CCAtlasNode.h @@ -0,0 +1,86 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + */ + + +#import "CCTextureAtlas.h" +#import "CCNode.h" +#import "CCProtocols.h" + +/** CCAtlasNode is a subclass of CCNode that implements the CCRGBAProtocol and + CCTextureProtocol protocol + + It knows how to render a TextureAtlas object. + If you are going to render a TextureAtlas consider subclassing CCAtlasNode (or a subclass of CCAtlasNode) + + All features from CCNode are valid, plus the following features: + - opacity and RGB colors + */ +@interface CCAtlasNode : CCNode +{ + // texture atlas + CCTextureAtlas *textureAtlas_; + + // chars per row + int itemsPerRow_; + // chars per column + int itemsPerColumn_; + + // width of each char + int itemWidth_; + // height of each char + int itemHeight_; + + // blend function + ccBlendFunc blendFunc_; + + // texture RGBA. + GLubyte opacity_; + ccColor3B color_; + ccColor3B colorUnmodified_; + BOOL opacityModifyRGB_; +} + +/** conforms to CCTextureProtocol protocol */ +@property (nonatomic,readwrite,retain) CCTextureAtlas *textureAtlas; + +/** conforms to CCTextureProtocol protocol */ +@property (nonatomic,readwrite) ccBlendFunc blendFunc; + +/** conforms to CCRGBAProtocol protocol */ +@property (nonatomic,readwrite) GLubyte opacity; +/** conforms to CCRGBAProtocol protocol */ +@property (nonatomic,readwrite) ccColor3B color; + + +/** creates a CCAtlasNode with an Atlas file the width and height of each item measured in points and the quantity of items to render*/ ++(id) atlasWithTileFile:(NSString*)tile tileWidth:(int)w tileHeight:(int)h itemsToRender: (int) c; + +/** initializes an CCAtlasNode with an Atlas file the width and height of each item measured in points and the quantity of items to render*/ +-(id) initWithTileFile:(NSString*)tile tileWidth:(int)w tileHeight:(int)h itemsToRender: (int) c; + +/** updates the Atlas (indexed vertex array). + * Shall be overriden in subclasses + */ +-(void) updateAtlasValues; +@end diff --git a/Classes/cocos2d/CCAtlasNode.m b/Classes/cocos2d/CCAtlasNode.m new file mode 100644 index 0000000..840fead --- /dev/null +++ b/Classes/cocos2d/CCAtlasNode.m @@ -0,0 +1,205 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + */ + + +#import "CCAtlasNode.h" +#import "ccMacros.h" + + +@interface CCAtlasNode () +-(void) calculateMaxItems; +-(void) updateBlendFunc; +-(void) updateOpacityModifyRGB; +@end + +@implementation CCAtlasNode + +@synthesize textureAtlas = textureAtlas_; +@synthesize blendFunc = blendFunc_; + +#pragma mark CCAtlasNode - Creation & Init ++(id) atlasWithTileFile:(NSString*)tile tileWidth:(int)w tileHeight:(int)h itemsToRender: (int) c +{ + return [[[self alloc] initWithTileFile:tile tileWidth:w tileHeight:h itemsToRender:c] autorelease]; +} + +-(id) initWithTileFile:(NSString*)tile tileWidth:(int)w tileHeight:(int)h itemsToRender: (int) c +{ + if( (self=[super init]) ) { + + itemWidth_ = w * CC_CONTENT_SCALE_FACTOR(); + itemHeight_ = h * CC_CONTENT_SCALE_FACTOR(); + + opacity_ = 255; + color_ = colorUnmodified_ = ccWHITE; + opacityModifyRGB_ = YES; + + blendFunc_.src = CC_BLEND_SRC; + blendFunc_.dst = CC_BLEND_DST; + + // double retain to avoid the autorelease pool + // also, using: self.textureAtlas supports re-initialization without leaking + self.textureAtlas = [[CCTextureAtlas alloc] initWithFile:tile capacity:c]; + [textureAtlas_ release]; + + if( ! textureAtlas_ ) { + CCLOG(@"cocos2d: Could not initialize CCAtlasNode. Invalid Texture"); + [self release]; + return nil; + } + + [self updateBlendFunc]; + [self updateOpacityModifyRGB]; + + [self calculateMaxItems]; + + } + return self; +} + +-(void) dealloc +{ + [textureAtlas_ release]; + + [super dealloc]; +} + +#pragma mark CCAtlasNode - Atlas generation + +-(void) calculateMaxItems +{ + CGSize s = [[textureAtlas_ texture] contentSizeInPixels]; + itemsPerColumn_ = s.height / itemHeight_; + itemsPerRow_ = s.width / itemWidth_; +} + +-(void) updateAtlasValues +{ + [NSException raise:@"CCAtlasNode:Abstract" format:@"updateAtlasValue not overriden"]; +} + +#pragma mark CCAtlasNode - draw +- (void) draw +{ + // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY + // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY + // Unneeded states: GL_COLOR_ARRAY + glDisableClientState(GL_COLOR_ARRAY); + + glColor4ub( color_.r, color_.g, color_.b, opacity_); + + BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST; + if( newBlend ) + glBlendFunc( blendFunc_.src, blendFunc_.dst ); + + [textureAtlas_ drawQuads]; + + if( newBlend ) + glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST); + + // is this chepear than saving/restoring color state ? + // XXX: There is no need to restore the color to (255,255,255,255). Objects should use the color + // XXX: that they need +// glColor4ub( 255, 255, 255, 255); + + // restore default GL state + glEnableClientState(GL_COLOR_ARRAY); + +} + +#pragma mark CCAtlasNode - RGBA protocol + +- (ccColor3B) color +{ + if(opacityModifyRGB_) + return colorUnmodified_; + + return color_; +} + +-(void) setColor:(ccColor3B)color3 +{ + color_ = colorUnmodified_ = color3; + + if( opacityModifyRGB_ ){ + color_.r = color3.r * opacity_/255; + color_.g = color3.g * opacity_/255; + color_.b = color3.b * opacity_/255; + } +} + +-(GLubyte) opacity +{ + return opacity_; +} + +-(void) setOpacity:(GLubyte) anOpacity +{ + opacity_ = anOpacity; + + // special opacity for premultiplied textures + if( opacityModifyRGB_ ) + [self setColor: colorUnmodified_]; +} + +-(void) setOpacityModifyRGB:(BOOL)modify +{ + ccColor3B oldColor = self.color; + opacityModifyRGB_ = modify; + self.color = oldColor; +} + +-(BOOL) doesOpacityModifyRGB +{ + return opacityModifyRGB_; +} + +-(void) updateOpacityModifyRGB +{ + opacityModifyRGB_ = [textureAtlas_.texture hasPremultipliedAlpha]; +} + +#pragma mark CCAtlasNode - CocosNodeTexture protocol + +-(void) updateBlendFunc +{ + if( ! [textureAtlas_.texture hasPremultipliedAlpha] ) { + blendFunc_.src = GL_SRC_ALPHA; + blendFunc_.dst = GL_ONE_MINUS_SRC_ALPHA; + } +} + +-(void) setTexture:(CCTexture2D*)texture +{ + textureAtlas_.texture = texture; + [self updateBlendFunc]; + [self updateOpacityModifyRGB]; +} + +-(CCTexture2D*) texture +{ + return textureAtlas_.texture; +} + +@end diff --git a/Classes/cocos2d/CCBlockSupport.h b/Classes/cocos2d/CCBlockSupport.h new file mode 100644 index 0000000..339d5aa --- /dev/null +++ b/Classes/cocos2d/CCBlockSupport.h @@ -0,0 +1,51 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Stuart Carnie + * + * 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. + * + */ + + +#import + +/** @file + cocos2d blocks support + */ + +// To comply with Apple Objective C runtime (this is defined in NSObjCRuntime.h) +#if !defined(NS_BLOCKS_AVAILABLE) + #if __BLOCKS__ + #define NS_BLOCKS_AVAILABLE 1 + #else + #define NS_BLOCKS_AVAILABLE 0 + #endif +#endif + +#if NS_BLOCKS_AVAILABLE + +@interface NSObject(CCBlocksAdditions) + +- (void)ccCallbackBlock; +- (void)ccCallbackBlockWithSender:(id)sender; + +@end + +#endif // NS_BLOCKS_AVAILABLE diff --git a/Classes/cocos2d/CCBlockSupport.m b/Classes/cocos2d/CCBlockSupport.m new file mode 100644 index 0000000..9ac99b3 --- /dev/null +++ b/Classes/cocos2d/CCBlockSupport.m @@ -0,0 +1,46 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Stuart Carnie + * + * 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. + * + */ + + +#import "CCBlockSupport.h" + +#if NS_BLOCKS_AVAILABLE + +@implementation NSObject(CCBlocksAdditions) + +- (void)ccCallbackBlock { + void (^block)(void) = (id)self; + block(); +} + +- (void)ccCallbackBlockWithSender:(id)sender { + void (^block)(id) = (id)self; + block(sender); +} + + +@end + +#endif diff --git a/Classes/cocos2d/CCCamera.h b/Classes/cocos2d/CCCamera.h new file mode 100644 index 0000000..387c854 --- /dev/null +++ b/Classes/cocos2d/CCCamera.h @@ -0,0 +1,94 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + */ + + + +#import "CCNode.h" + +/** + A CCCamera is used in every CCNode. + Useful to look at the object from different views. + The OpenGL gluLookAt() function is used to locate the + camera. + + If the object is transformed by any of the scale, rotation or + position attributes, then they will override the camera. + + IMPORTANT: Either your use the camera or the rotation/scale/position properties. You can't use both. + World coordinates won't work if you use the camera. + + Limitations: + + - Some nodes, like CCParallaxNode, CCParticle uses world node coordinates, and they won't work properly if you move them (or any of their ancestors) + using the camera. + + - It doesn't work on batched nodes like CCSprite objects when they are parented to a CCSpriteBatchNode object. + + - It is recommended to use it ONLY if you are going to create 3D effects. For 2D effecs, use the action CCFollow or position/scale/rotate. + +*/ + +@interface CCCamera : NSObject +{ + float eyeX_; + float eyeY_; + float eyeZ_; + + float centerX_; + float centerY_; + float centerZ_; + + float upX_; + float upY_; + float upZ_; + + BOOL dirty_; +} + +/** whether of not the camera is dirty */ +@property (nonatomic,readwrite) BOOL dirty; + +/** returns the Z eye */ ++(float) getZEye; + +/** sets the camera in the defaul position */ +-(void) restore; +/** Sets the camera using gluLookAt using its eye, center and up_vector */ +-(void) locate; +/** sets the eye values in points */ +-(void) setEyeX: (float)x eyeY:(float)y eyeZ:(float)z; +/** sets the center values in points */ +-(void) setCenterX: (float)x centerY:(float)y centerZ:(float)z; +/** sets the up values */ +-(void) setUpX: (float)x upY:(float)y upZ:(float)z; + +/** get the eye vector values in points */ +-(void) eyeX:(float*)x eyeY:(float*)y eyeZ:(float*)z; +/** get the center vector values in points */ +-(void) centerX:(float*)x centerY:(float*)y centerZ:(float*)z; +/** get the up vector values */ +-(void) upX:(float*)x upY:(float*)y upZ:(float*)z; + + +@end diff --git a/Classes/cocos2d/CCCamera.m b/Classes/cocos2d/CCCamera.m new file mode 100644 index 0000000..3841ab3 --- /dev/null +++ b/Classes/cocos2d/CCCamera.m @@ -0,0 +1,130 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + */ + + +#import "Platforms/CCGL.h" +#import "CCCamera.h" +#import "ccMacros.h" +#import "CCDrawingPrimitives.h" + +@implementation CCCamera + +@synthesize dirty = dirty_; + +-(id) init +{ + if( (self=[super init]) ) + [self restore]; + + return self; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %08X | center = (%.2f,%.2f,%.2f)>", [self class], self, centerX_, centerY_, centerZ_]; +} + + +- (void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + [super dealloc]; +} + +-(void) restore +{ + eyeX_ = eyeY_ = 0; + eyeZ_ = [CCCamera getZEye]; + + centerX_ = centerY_ = centerZ_ = 0; + + upX_ = 0.0f; + upY_ = 1.0f; + upZ_ = 0.0f; + + dirty_ = NO; +} + +-(void) locate +{ + if( dirty_ ) + gluLookAt( eyeX_, eyeY_, eyeZ_, + centerX_, centerY_, centerZ_, + upX_, upY_, upZ_ + ); +} + ++(float) getZEye +{ + return FLT_EPSILON; +// CGSize s = [[CCDirector sharedDirector] displaySize]; +// return ( s.height / 1.1566f ); +} + +-(void) setEyeX: (float)x eyeY:(float)y eyeZ:(float)z +{ + eyeX_ = x * CC_CONTENT_SCALE_FACTOR(); + eyeY_ = y * CC_CONTENT_SCALE_FACTOR(); + eyeZ_ = z * CC_CONTENT_SCALE_FACTOR(); + dirty_ = YES; +} + +-(void) setCenterX: (float)x centerY:(float)y centerZ:(float)z +{ + centerX_ = x * CC_CONTENT_SCALE_FACTOR(); + centerY_ = y * CC_CONTENT_SCALE_FACTOR(); + centerZ_ = z * CC_CONTENT_SCALE_FACTOR(); + dirty_ = YES; +} + +-(void) setUpX: (float)x upY:(float)y upZ:(float)z +{ + upX_ = x; + upY_ = y; + upZ_ = z; + dirty_ = YES; +} + +-(void) eyeX: (float*)x eyeY:(float*)y eyeZ:(float*)z +{ + *x = eyeX_ / CC_CONTENT_SCALE_FACTOR(); + *y = eyeY_ / CC_CONTENT_SCALE_FACTOR(); + *z = eyeZ_ / CC_CONTENT_SCALE_FACTOR(); +} + +-(void) centerX: (float*)x centerY:(float*)y centerZ:(float*)z +{ + *x = centerX_ / CC_CONTENT_SCALE_FACTOR(); + *y = centerY_ / CC_CONTENT_SCALE_FACTOR(); + *z = centerZ_ / CC_CONTENT_SCALE_FACTOR(); +} + +-(void) upX: (float*)x upY:(float*)y upZ:(float*)z +{ + *x = upX_; + *y = upY_; + *z = upZ_; +} + +@end diff --git a/Classes/cocos2d/CCCompatibility.h b/Classes/cocos2d/CCCompatibility.h new file mode 100644 index 0000000..b1b578e --- /dev/null +++ b/Classes/cocos2d/CCCompatibility.h @@ -0,0 +1,224 @@ + +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + +// AUTOMATICALLY GENERATED. DO NOT EDIT + + +#import +#import "cocos2d.h" + +#if CC_COMPATIBILITY_WITH_0_8 + +DEPRECATED_ATTRIBUTE @interface AccelAmplitude : CCAccelAmplitude {} @end +DEPRECATED_ATTRIBUTE @interface AccelDeccelAmplitude : CCAccelDeccelAmplitude {} @end +DEPRECATED_ATTRIBUTE @interface Action : CCAction {} @end +DEPRECATED_ATTRIBUTE @interface ActionManager : CCActionManager {} @end +DEPRECATED_ATTRIBUTE @interface Animate : CCAnimate {} @end +DEPRECATED_ATTRIBUTE @interface Animation : CCAnimation {} @end +DEPRECATED_ATTRIBUTE @interface AtlasAnimation : CCAnimation {} @end +DEPRECATED_ATTRIBUTE @interface AtlasNode : CCAtlasNode {} @end +DEPRECATED_ATTRIBUTE @interface AtlasSprite : CCSprite {} @end +DEPRECATED_ATTRIBUTE @interface AtlasSpriteFrame : CCSpriteFrame {} @end +DEPRECATED_ATTRIBUTE @interface AtlasSpriteManager : CCSpriteSheet {} @end +DEPRECATED_ATTRIBUTE @interface BezierBy : CCBezierBy {} @end +DEPRECATED_ATTRIBUTE @interface BezierTo : CCBezierTo {} @end +DEPRECATED_ATTRIBUTE @interface BitmapFontAtlas : CCBitmapFontAtlas {} @end +DEPRECATED_ATTRIBUTE @interface BitmapFontConfiguration : CCBitmapFontConfiguration {} @end +DEPRECATED_ATTRIBUTE @interface Blink : CCBlink {} @end +DEPRECATED_ATTRIBUTE @interface CallFunc : CCCallFunc {} @end +DEPRECATED_ATTRIBUTE @interface CallFuncN : CCCallFuncN {} @end +DEPRECATED_ATTRIBUTE @interface CallFuncND : CCCallFuncND {} @end +DEPRECATED_ATTRIBUTE @interface Camera : CCCamera {} @end +DEPRECATED_ATTRIBUTE @interface CameraAction : CCCameraAction {} @end +DEPRECATED_ATTRIBUTE @interface CocosNode : CCNode {} @end +DEPRECATED_ATTRIBUTE @interface ColorLayer : CCColorLayer {} @end +DEPRECATED_ATTRIBUTE @interface DeccelAmplitude : CCDeccelAmplitude {} @end +DEPRECATED_ATTRIBUTE @interface DelayTime : CCDelayTime {} @end +DEPRECATED_ATTRIBUTE @interface Director : CCDirector {} @end +DEPRECATED_ATTRIBUTE @interface DisplayLinkDirector : CCDisplayLinkDirector {} @end +DEPRECATED_ATTRIBUTE @interface EaseAction : CCEaseAction {} @end +DEPRECATED_ATTRIBUTE @interface EaseBackIn : CCEaseBackIn {} @end +DEPRECATED_ATTRIBUTE @interface EaseBackInOut : CCEaseBackInOut {} @end +DEPRECATED_ATTRIBUTE @interface EaseBackOut : CCEaseBackOut {} @end +DEPRECATED_ATTRIBUTE @interface EaseBounce : CCEaseBounce {} @end +DEPRECATED_ATTRIBUTE @interface EaseBounceIn : CCEaseBounceIn {} @end +DEPRECATED_ATTRIBUTE @interface EaseBounceInOut : CCEaseBounceInOut {} @end +DEPRECATED_ATTRIBUTE @interface EaseBounceOut : CCEaseBounceOut {} @end +DEPRECATED_ATTRIBUTE @interface EaseElastic : CCEaseElastic {} @end +DEPRECATED_ATTRIBUTE @interface EaseElasticIn : CCEaseElasticIn {} @end +DEPRECATED_ATTRIBUTE @interface EaseElasticInOut : CCEaseElasticInOut {} @end +DEPRECATED_ATTRIBUTE @interface EaseElasticOut : CCEaseElasticOut {} @end +DEPRECATED_ATTRIBUTE @interface EaseExponentialIn : CCEaseExponentialIn {} @end +DEPRECATED_ATTRIBUTE @interface EaseExponentialInOut : CCEaseExponentialInOut {} @end +DEPRECATED_ATTRIBUTE @interface EaseExponentialOut : CCEaseExponentialOut {} @end +DEPRECATED_ATTRIBUTE @interface EaseIn : CCEaseIn {} @end +DEPRECATED_ATTRIBUTE @interface EaseInOut : CCEaseInOut {} @end +DEPRECATED_ATTRIBUTE @interface EaseOut : CCEaseOut {} @end +DEPRECATED_ATTRIBUTE @interface EaseRateAction : CCEaseRateAction {} @end +DEPRECATED_ATTRIBUTE @interface EaseSineIn : CCEaseSineIn {} @end +DEPRECATED_ATTRIBUTE @interface EaseSineInOut : CCEaseSineInOut {} @end +DEPRECATED_ATTRIBUTE @interface EaseSineOut : CCEaseSineOut {} @end +DEPRECATED_ATTRIBUTE @interface FadeBLTransition : CCTransitionFadeBL {} @end +DEPRECATED_ATTRIBUTE @interface FadeDownTransition : CCTransitionFadeDown {} @end +DEPRECATED_ATTRIBUTE @interface FadeIn : CCFadeIn {} @end +DEPRECATED_ATTRIBUTE @interface FadeOut : CCFadeOut {} @end +DEPRECATED_ATTRIBUTE @interface FadeOutBLTiles : CCFadeOutBLTiles {} @end +DEPRECATED_ATTRIBUTE @interface FadeOutDownTiles : CCFadeOutDownTiles {} @end +DEPRECATED_ATTRIBUTE @interface FadeOutTRTiles : CCFadeOutTRTiles {} @end +DEPRECATED_ATTRIBUTE @interface FadeOutUpTiles : CCFadeOutUpTiles {} @end +DEPRECATED_ATTRIBUTE @interface FadeTRTransition : CCTransitionFadeTR {} @end +DEPRECATED_ATTRIBUTE @interface FadeTo : CCFadeTo {} @end +DEPRECATED_ATTRIBUTE @interface FadeTransition : CCTransitionFade {} @end +DEPRECATED_ATTRIBUTE @interface FadeUpTransition : CCTransitionFadeUp {} @end +DEPRECATED_ATTRIBUTE @interface FastDirector : CCFastDirector {} @end +DEPRECATED_ATTRIBUTE @interface FiniteTimeAction : CCFiniteTimeAction {} @end +DEPRECATED_ATTRIBUTE @interface FlipAngularTransition : CCTransitionFlipAngular {} @end +DEPRECATED_ATTRIBUTE @interface FlipX3D : CCFlipX3D {} @end +DEPRECATED_ATTRIBUTE @interface FlipXTransition : CCTransitionFlipX {} @end +DEPRECATED_ATTRIBUTE @interface FlipY3D : CCFlipY3D {} @end +DEPRECATED_ATTRIBUTE @interface FlipYTransition : CCTransitionFlipY {} @end +DEPRECATED_ATTRIBUTE @interface Grabber : CCGrabber {} @end +DEPRECATED_ATTRIBUTE @interface Grid3D : CCGrid3D {} @end +DEPRECATED_ATTRIBUTE @interface Grid3DAction : CCGrid3DAction {} @end +DEPRECATED_ATTRIBUTE @interface GridAction : CCGridAction {} @end +DEPRECATED_ATTRIBUTE @interface GridBase : CCGridBase {} @end +DEPRECATED_ATTRIBUTE @interface Hide : CCHide {} @end +DEPRECATED_ATTRIBUTE @interface InstantAction : CCInstantAction {} @end +DEPRECATED_ATTRIBUTE @interface IntervalAction : CCIntervalAction {} @end +DEPRECATED_ATTRIBUTE @interface JumpBy : CCJumpBy {} @end +DEPRECATED_ATTRIBUTE @interface JumpTiles3D : CCJumpTiles3D {} @end +DEPRECATED_ATTRIBUTE @interface JumpTo : CCJumpTo {} @end +DEPRECATED_ATTRIBUTE @interface JumpZoomTransition : CCTransitionJumpZoom {} @end +DEPRECATED_ATTRIBUTE @interface Label : CCLabel {} @end +DEPRECATED_ATTRIBUTE @interface LabelAtlas : CCLabelAtlas {} @end +DEPRECATED_ATTRIBUTE @interface Layer : CCLayer {} @end +DEPRECATED_ATTRIBUTE @interface Lens3D : CCLens3D {} @end +DEPRECATED_ATTRIBUTE @interface Liquid : CCLiquid {} @end +DEPRECATED_ATTRIBUTE @interface Menu : CCMenu {} @end +DEPRECATED_ATTRIBUTE @interface MenuItem : CCMenuItem {} @end +DEPRECATED_ATTRIBUTE @interface MenuItemAtlasFont : CCMenuItemAtlasFont {} @end +DEPRECATED_ATTRIBUTE @interface MenuItemFont : CCMenuItemFont {} @end +DEPRECATED_ATTRIBUTE @interface MenuItemImage : CCMenuItemImage {} @end +DEPRECATED_ATTRIBUTE @interface MenuItemLabel : CCMenuItemLabel {} @end +DEPRECATED_ATTRIBUTE @interface MenuItemSprite : CCMenuItemSprite {} @end +DEPRECATED_ATTRIBUTE @interface MenuItemToggle : CCMenuItemToggle {} @end +DEPRECATED_ATTRIBUTE @interface MotionStreak : CCMotionStreak {} @end +DEPRECATED_ATTRIBUTE @interface MoveBy : CCMoveBy {} @end +DEPRECATED_ATTRIBUTE @interface MoveInBTransition : CCTransitionMoveInB {} @end +DEPRECATED_ATTRIBUTE @interface MoveInLTransition : CCTransitionMoveInL {} @end +DEPRECATED_ATTRIBUTE @interface MoveInRTransition : CCTransitionMoveInR {} @end +DEPRECATED_ATTRIBUTE @interface MoveInTTransition : CCTransitionMoveInT {} @end +DEPRECATED_ATTRIBUTE @interface MoveTo : CCMoveTo {} @end +DEPRECATED_ATTRIBUTE @interface MultiplexLayer : CCMultiplexLayer {} @end +DEPRECATED_ATTRIBUTE @interface OrbitCamera : CCOrbitCamera {} @end +DEPRECATED_ATTRIBUTE @interface OrientedTransitionScene : CCTransitionSceneOriented {} @end +DEPRECATED_ATTRIBUTE @interface PVRTexture : CCPVRTexture {} @end +DEPRECATED_ATTRIBUTE @interface PageTurn3D : CCPageTurn3D {} @end +DEPRECATED_ATTRIBUTE @interface PageTurnTransition : CCPageTurnTransition {} @end +DEPRECATED_ATTRIBUTE @interface ParallaxNode : CCParallaxNode {} @end +DEPRECATED_ATTRIBUTE @interface ParticleExplosion : CCParticleExplosion {} @end +DEPRECATED_ATTRIBUTE @interface ParticleFire : CCParticleFire {} @end +DEPRECATED_ATTRIBUTE @interface ParticleFireworks : CCParticleFireworks {} @end +DEPRECATED_ATTRIBUTE @interface ParticleFlower : CCParticleFlower {} @end +DEPRECATED_ATTRIBUTE @interface ParticleGalaxy : CCParticleGalaxy {} @end +DEPRECATED_ATTRIBUTE @interface ParticleMeteor : CCParticleMeteor {} @end +DEPRECATED_ATTRIBUTE @interface ParticleRain : CCParticleRain {} @end +DEPRECATED_ATTRIBUTE @interface ParticleSmoke : CCParticleSmoke {} @end +DEPRECATED_ATTRIBUTE @interface ParticleSnow : CCParticleSnow {} @end +DEPRECATED_ATTRIBUTE @interface ParticleSpiral : CCParticleSpiral {} @end +DEPRECATED_ATTRIBUTE @interface ParticleSun : CCParticleSun {} @end +DEPRECATED_ATTRIBUTE @interface ParticleSystem : CCParticleSystem {} @end +DEPRECATED_ATTRIBUTE @interface Place : CCPlace {} @end +DEPRECATED_ATTRIBUTE @interface PointParticleSystem : CCPointParticleSystem {} @end +DEPRECATED_ATTRIBUTE @interface QuadParticleSystem : CCQuadParticleSystem {} @end +DEPRECATED_ATTRIBUTE @interface RenderTexture : CCRenderTexture {} @end +DEPRECATED_ATTRIBUTE @interface Repeat : CCRepeat {} @end +DEPRECATED_ATTRIBUTE @interface RepeatForever : CCRepeatForever {} @end +DEPRECATED_ATTRIBUTE @interface ReuseGrid : CCReuseGrid {} @end +DEPRECATED_ATTRIBUTE @interface ReverseTime : CCReverseTime {} @end +DEPRECATED_ATTRIBUTE @interface Ribbon : CCRibbon {} @end +DEPRECATED_ATTRIBUTE @interface RibbonSegment : CCRibbonSegment {} @end +DEPRECATED_ATTRIBUTE @interface Ripple3D : CCRipple3D {} @end +DEPRECATED_ATTRIBUTE @interface RotateBy : CCRotateBy {} @end +DEPRECATED_ATTRIBUTE @interface RotateTo : CCRotateTo {} @end +DEPRECATED_ATTRIBUTE @interface RotoZoomTransition : CCTransitionRotoZoom {} @end +DEPRECATED_ATTRIBUTE @interface ScaleBy : CCScaleBy {} @end +DEPRECATED_ATTRIBUTE @interface ScaleTo : CCScaleTo {} @end +DEPRECATED_ATTRIBUTE @interface Scene : CCScene {} @end +DEPRECATED_ATTRIBUTE @interface Scheduler : CCScheduler {} @end +DEPRECATED_ATTRIBUTE @interface Sequence : CCSequence {} @end +DEPRECATED_ATTRIBUTE @interface Shaky3D : CCShaky3D {} @end +DEPRECATED_ATTRIBUTE @interface ShakyTiles3D : CCShakyTiles3D {} @end +DEPRECATED_ATTRIBUTE @interface ShatteredTiles3D : CCShatteredTiles3D {} @end +DEPRECATED_ATTRIBUTE @interface Show : CCShow {} @end +DEPRECATED_ATTRIBUTE @interface ShrinkGrowTransition : CCTransitionShrinkGrow {} @end +DEPRECATED_ATTRIBUTE @interface ShuffleTiles : CCShuffleTiles {} @end +DEPRECATED_ATTRIBUTE @interface SlideInBTransition : CCTransitionSlideInB {} @end +DEPRECATED_ATTRIBUTE @interface SlideInLTransition : CCTransitionSlideInL {} @end +DEPRECATED_ATTRIBUTE @interface SlideInRTransition : CCTransitionSlideInR {} @end +DEPRECATED_ATTRIBUTE @interface SlideInTTransition : CCTransitionSlideInT {} @end +DEPRECATED_ATTRIBUTE @interface Spawn : CCSpawn {} @end +DEPRECATED_ATTRIBUTE @interface Speed : CCSpeed {} @end +DEPRECATED_ATTRIBUTE @interface SplitCols : CCSplitCols {} @end +DEPRECATED_ATTRIBUTE @interface SplitColsTransition : CCTransitionSplitCols {} @end +DEPRECATED_ATTRIBUTE @interface SplitRows : CCSplitRows {} @end +DEPRECATED_ATTRIBUTE @interface SplitRowsTransition : CCTransitionSplitRows {} @end +DEPRECATED_ATTRIBUTE @interface Sprite : CCSprite {} @end +DEPRECATED_ATTRIBUTE @interface StandardTouchHandler : CCStandardTouchHandler {} @end +DEPRECATED_ATTRIBUTE @interface StopGrid : CCStopGrid {} @end +DEPRECATED_ATTRIBUTE @interface TMXLayer : CCTMXLayer {} @end +DEPRECATED_ATTRIBUTE @interface TMXLayerInfo : CCTMXLayerInfo {} @end +DEPRECATED_ATTRIBUTE @interface TMXMapInfo : CCTMXMapInfo {} @end +DEPRECATED_ATTRIBUTE @interface TMXTiledMap : CCTMXTiledMap {} @end +DEPRECATED_ATTRIBUTE @interface TMXTilesetInfo : CCTMXTilesetInfo {} @end +DEPRECATED_ATTRIBUTE @interface TargetedTouchHandler : CCTargetedTouchHandler {} @end +DEPRECATED_ATTRIBUTE @interface Texture2D : CCTexture2D {} @end +DEPRECATED_ATTRIBUTE @interface TextureAtlas : CCTextureAtlas {} @end +DEPRECATED_ATTRIBUTE @interface TextureMgr : CCTextureCache {} @end +DEPRECATED_ATTRIBUTE @interface TextureNode : CCSprite {} @end +DEPRECATED_ATTRIBUTE @interface ThreadedFastDirector : CCThreadedFastDirector {} @end +DEPRECATED_ATTRIBUTE @interface TileMapAtlas : CCTileMapAtlas {} @end +DEPRECATED_ATTRIBUTE @interface TiledGrid3D : CCTiledGrid3D {} @end +DEPRECATED_ATTRIBUTE @interface TiledGrid3DAction : CCTiledGrid3DAction {} @end +DEPRECATED_ATTRIBUTE @interface Timer : CCTimer {} @end +DEPRECATED_ATTRIBUTE @interface TimerDirector : CCTimerDirector {} @end +DEPRECATED_ATTRIBUTE @interface TintBy : CCTintBy {} @end +DEPRECATED_ATTRIBUTE @interface TintTo : CCTintTo {} @end +DEPRECATED_ATTRIBUTE @interface ToggleVisibility : CCToggleVisibility {} @end +DEPRECATED_ATTRIBUTE @interface TouchDispatcher : CCTouchDispatcher {} @end +DEPRECATED_ATTRIBUTE @interface TouchHandler : CCTouchHandler {} @end +DEPRECATED_ATTRIBUTE @interface TransitionScene : CCTransitionScene {} @end +DEPRECATED_ATTRIBUTE @interface TurnOffTiles : CCTurnOffTiles {} @end +DEPRECATED_ATTRIBUTE @interface TurnOffTilesTransition : CCTransitionTurnOffTiles {} @end +DEPRECATED_ATTRIBUTE @interface Twirl : CCTwirl {} @end +DEPRECATED_ATTRIBUTE @interface Waves : CCWaves {} @end +DEPRECATED_ATTRIBUTE @interface Waves3D : CCWaves3D {} @end +DEPRECATED_ATTRIBUTE @interface WavesTiles3D : CCWavesTiles3D {} @end +DEPRECATED_ATTRIBUTE @interface ZoomFlipAngularTransition : CCTransitionZoomFlipAngular {} @end +DEPRECATED_ATTRIBUTE @interface ZoomFlipXTransition : CCTransitionZoomFlipX {} @end +DEPRECATED_ATTRIBUTE @interface ZoomFlipYTransition : CCTransitionZoomFlipY {} @end + +#endif // CC_COMPATIBILITY_WITH_0_8 diff --git a/Classes/cocos2d/CCCompatibility.m b/Classes/cocos2d/CCCompatibility.m new file mode 100644 index 0000000..93d0e53 --- /dev/null +++ b/Classes/cocos2d/CCCompatibility.m @@ -0,0 +1,596 @@ + +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + +// AUTOMATICALLY GENERATED. DO NOT EDIT + +#include "CCCompatibility.h" +#if CC_COMPATIBILITY_WITH_0_8 +@implementation AccelAmplitude +@end + +@implementation AccelDeccelAmplitude +@end + +@implementation Action +@end + +@implementation ActionManager +@end + +@implementation Animate +@end + +@implementation Animation +@end + +@implementation AtlasAnimation +@end + +@implementation AtlasNode +@end + +@implementation AtlasSprite +@end + +@implementation AtlasSpriteFrame +@end + +@implementation AtlasSpriteManager +@end + +@implementation BezierBy +@end + +@implementation BezierTo +@end + +@implementation BitmapFontAtlas +@end + +@implementation BitmapFontConfiguration +@end + +@implementation Blink +@end + +@implementation CallFunc +@end + +@implementation CallFuncN +@end + +@implementation CallFuncND +@end + +@implementation Camera +@end + +@implementation CameraAction +@end + +@implementation CocosNode +@end + +@implementation ColorLayer +@end + +@implementation DeccelAmplitude +@end + +@implementation DelayTime +@end + +@implementation Director +@end + +@implementation DisplayLinkDirector +@end + +@implementation EaseAction +@end + +@implementation EaseBackIn +@end + +@implementation EaseBackInOut +@end + +@implementation EaseBackOut +@end + +@implementation EaseBounce +@end + +@implementation EaseBounceIn +@end + +@implementation EaseBounceInOut +@end + +@implementation EaseBounceOut +@end + +@implementation EaseElastic +@end + +@implementation EaseElasticIn +@end + +@implementation EaseElasticInOut +@end + +@implementation EaseElasticOut +@end + +@implementation EaseExponentialIn +@end + +@implementation EaseExponentialInOut +@end + +@implementation EaseExponentialOut +@end + +@implementation EaseIn +@end + +@implementation EaseInOut +@end + +@implementation EaseOut +@end + +@implementation EaseRateAction +@end + +@implementation EaseSineIn +@end + +@implementation EaseSineInOut +@end + +@implementation EaseSineOut +@end + +@implementation FadeBLTransition +@end + +@implementation FadeDownTransition +@end + +@implementation FadeIn +@end + +@implementation FadeOut +@end + +@implementation FadeOutBLTiles +@end + +@implementation FadeOutDownTiles +@end + +@implementation FadeOutTRTiles +@end + +@implementation FadeOutUpTiles +@end + +@implementation FadeTRTransition +@end + +@implementation FadeTo +@end + +@implementation FadeTransition +@end + +@implementation FadeUpTransition +@end + +@implementation FastDirector +@end + +@implementation FiniteTimeAction +@end + +@implementation FlipAngularTransition +@end + +@implementation FlipX3D +@end + +@implementation FlipXTransition +@end + +@implementation FlipY3D +@end + +@implementation FlipYTransition +@end + +@implementation Grabber +@end + +@implementation Grid3D +@end + +@implementation Grid3DAction +@end + +@implementation GridAction +@end + +@implementation GridBase +@end + +@implementation Hide +@end + +@implementation InstantAction +@end + +@implementation IntervalAction +@end + +@implementation JumpBy +@end + +@implementation JumpTiles3D +@end + +@implementation JumpTo +@end + +@implementation JumpZoomTransition +@end + +@implementation Label +@end + +@implementation LabelAtlas +@end + +@implementation Layer +@end + +@implementation Lens3D +@end + +@implementation Liquid +@end + +@implementation Menu +@end + +@implementation MenuItem +@end + +@implementation MenuItemAtlasFont +@end + +@implementation MenuItemFont +@end + +@implementation MenuItemImage +@end + +@implementation MenuItemLabel +@end + +@implementation MenuItemSprite +@end + +@implementation MenuItemToggle +@end + +@implementation MotionStreak +@end + +@implementation MoveBy +@end + +@implementation MoveInBTransition +@end + +@implementation MoveInLTransition +@end + +@implementation MoveInRTransition +@end + +@implementation MoveInTTransition +@end + +@implementation MoveTo +@end + +@implementation MultiplexLayer +@end + +@implementation OrbitCamera +@end + +@implementation OrientedTransitionScene +@end + +@implementation PVRTexture +@end + +@implementation PageTurn3D +@end + +@implementation PageTurnTransition +@end + +@implementation ParallaxNode +@end + +@implementation ParticleExplosion +@end + +@implementation ParticleFire +@end + +@implementation ParticleFireworks +@end + +@implementation ParticleFlower +@end + +@implementation ParticleGalaxy +@end + +@implementation ParticleMeteor +@end + +@implementation ParticleRain +@end + +@implementation ParticleSmoke +@end + +@implementation ParticleSnow +@end + +@implementation ParticleSpiral +@end + +@implementation ParticleSun +@end + +@implementation ParticleSystem +@end + +@implementation Place +@end + +@implementation PointParticleSystem +@end + +@implementation QuadParticleSystem +@end + +@implementation RenderTexture +@end + +@implementation Repeat +@end + +@implementation RepeatForever +@end + +@implementation ReuseGrid +@end + +@implementation ReverseTime +@end + +@implementation Ribbon +@end + +@implementation RibbonSegment +@end + +@implementation Ripple3D +@end + +@implementation RotateBy +@end + +@implementation RotateTo +@end + +@implementation RotoZoomTransition +@end + +@implementation ScaleBy +@end + +@implementation ScaleTo +@end + +@implementation Scene +@end + +@implementation Scheduler +@end + +@implementation Sequence +@end + +@implementation Shaky3D +@end + +@implementation ShakyTiles3D +@end + +@implementation ShatteredTiles3D +@end + +@implementation Show +@end + +@implementation ShrinkGrowTransition +@end + +@implementation ShuffleTiles +@end + +@implementation SlideInBTransition +@end + +@implementation SlideInLTransition +@end + +@implementation SlideInRTransition +@end + +@implementation SlideInTTransition +@end + +@implementation Spawn +@end + +@implementation Speed +@end + +@implementation SplitCols +@end + +@implementation SplitColsTransition +@end + +@implementation SplitRows +@end + +@implementation SplitRowsTransition +@end + +@implementation Sprite +@end + +@implementation StandardTouchHandler +@end + +@implementation StopGrid +@end + +@implementation TMXLayer +@end + +@implementation TMXLayerInfo +@end + +@implementation TMXMapInfo +@end + +@implementation TMXTiledMap +@end + +@implementation TMXTilesetInfo +@end + +@implementation TargetedTouchHandler +@end + +@implementation Texture2D +@end + +@implementation TextureAtlas +@end + +@implementation TextureMgr +@end + +@implementation TextureNode +@end + +@implementation ThreadedFastDirector +@end + +@implementation TileMapAtlas +@end + +@implementation TiledGrid3D +@end + +@implementation TiledGrid3DAction +@end + +@implementation Timer +@end + +@implementation TimerDirector +@end + +@implementation TintBy +@end + +@implementation TintTo +@end + +@implementation ToggleVisibility +@end + +@implementation TouchDispatcher +@end + +@implementation TouchHandler +@end + +@implementation TransitionScene +@end + +@implementation TurnOffTiles +@end + +@implementation TurnOffTilesTransition +@end + +@implementation Twirl +@end + +@implementation Waves +@end + +@implementation Waves3D +@end + +@implementation WavesTiles3D +@end + +@implementation ZoomFlipAngularTransition +@end + +@implementation ZoomFlipXTransition +@end + +@implementation ZoomFlipYTransition +@end + + +#endif // CC_COMPATIBILITY_WITH_0_8 diff --git a/Classes/cocos2d/CCConfiguration.h b/Classes/cocos2d/CCConfiguration.h new file mode 100644 index 0000000..11bd120 --- /dev/null +++ b/Classes/cocos2d/CCConfiguration.h @@ -0,0 +1,110 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * + * 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. + */ + +#import + +#import "Platforms/CCGL.h" + +/** OS version definitions. Includes both iOS and Mac OS versions + */ +enum { + kCCiOSVersion_3_0 = 0x03000000, + kCCiOSVersion_3_1 = 0x03010000, + kCCiOSVersion_3_1_1 = 0x03010100, + kCCiOSVersion_3_1_2 = 0x03010200, + kCCiOSVersion_3_1_3 = 0x03010300, + kCCiOSVersion_3_2 = 0x03020000, + kCCiOSVersion_3_2_1 = 0x03020100, + kCCiOSVersion_4_0 = 0x04000000, + kCCiOSVersion_4_0_1 = 0x04000100, + kCCiOSVersion_4_1 = 0x04010000, + + kCCMacVersion_10_5 = 0x0a050000, + kCCMacVersion_10_6 = 0x0a060000, + kCCMacVersion_10_7 = 0x0a070000, +}; + +/** + CCConfiguration contains some openGL variables + @since v0.99.0 + */ +@interface CCConfiguration : NSObject { + + GLint maxTextureSize_; + GLint maxModelviewStackDepth_; + BOOL supportsPVRTC_; + BOOL supportsNPOT_; + BOOL supportsBGRA8888_; + BOOL supportsDiscardFramebuffer_; + unsigned int OSVersion_; + GLint maxSamplesAllowed_; +} + +/** OpenGL Max texture size. */ +@property (nonatomic, readonly) GLint maxTextureSize; + +/** OpenGL Max Modelview Stack Depth. */ +@property (nonatomic, readonly) GLint maxModelviewStackDepth; + +/** Whether or not the GPU supports NPOT (Non Power Of Two) textures. + NPOT textures have the following limitations: + - They can't have mipmaps + - They only accept GL_CLAMP_TO_EDGE in GL_TEXTURE_WRAP_{S,T} + + @since v0.99.2 + */ +@property (nonatomic, readonly) BOOL supportsNPOT; + +/** Whether or not PVR Texture Compressed is supported */ +@property (nonatomic, readonly) BOOL supportsPVRTC; + +/** Whether or not BGRA8888 textures are supported. + + @since v0.99.2 + */ +@property (nonatomic, readonly) BOOL supportsBGRA8888; + +/** Whether or not glDiscardFramebufferEXT is supported + + @since v0.99.2 + */ +@property (nonatomic, readonly) BOOL supportsDiscardFramebuffer; + +/** returns the OS version. + - On iOS devices it returns the firmware version. + - On Mac returns the OS version + + @since v0.99.5 + */ +@property (nonatomic, readonly) unsigned int OSVersion; + +/** returns a shared instance of the CCConfiguration */ ++(CCConfiguration *) sharedConfiguration; + +/** returns whether or not an OpenGL is supported */ +- (BOOL) checkForGLExtension:(NSString *)searchName; + + + +@end diff --git a/Classes/cocos2d/CCConfiguration.m b/Classes/cocos2d/CCConfiguration.m new file mode 100644 index 0000000..e70bed1 --- /dev/null +++ b/Classes/cocos2d/CCConfiguration.m @@ -0,0 +1,192 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * + * 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. + */ + +#import + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +#import // Needed for UIDevice +#endif + +#import "Platforms/CCGL.h" +#import "CCBlockSupport.h" +#import "CCConfiguration.h" +#import "ccMacros.h" +#import "ccConfig.h" +#import "Support/OpenGL_Internal.h" + +@implementation CCConfiguration + +@synthesize maxTextureSize = maxTextureSize_; +@synthesize supportsPVRTC = supportsPVRTC_; +@synthesize maxModelviewStackDepth = maxModelviewStackDepth_; +@synthesize supportsNPOT = supportsNPOT_; +@synthesize supportsBGRA8888 = supportsBGRA8888_; +@synthesize supportsDiscardFramebuffer = supportsDiscardFramebuffer_; +@synthesize OSVersion = OSVersion_; + +// +// singleton stuff +// +static CCConfiguration *_sharedConfiguration = nil; + +static char * glExtensions; + ++ (CCConfiguration *)sharedConfiguration +{ + if (!_sharedConfiguration) + _sharedConfiguration = [[self alloc] init]; + + return _sharedConfiguration; +} + ++(id)alloc +{ + NSAssert(_sharedConfiguration == nil, @"Attempted to allocate a second instance of a singleton."); + return [super alloc]; +} + + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) +- (NSString*)getMacVersion +{ + SInt32 versionMajor, versionMinor, versionBugFix; + Gestalt(gestaltSystemVersionMajor, &versionMajor); + Gestalt(gestaltSystemVersionMinor, &versionMinor); + Gestalt(gestaltSystemVersionBugFix, &versionBugFix); + + return [NSString stringWithFormat:@"%d.%d.%d", versionMajor, versionMinor, versionBugFix]; +} +#endif // __MAC_OS_X_VERSION_MAX_ALLOWED + +-(id) init +{ + if( (self=[super init])) { + + // Obtain iOS version + OSVersion_ = 0; +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + NSString *OSVer = [[UIDevice currentDevice] systemVersion]; +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + NSString *OSVer = [self getMacVersion]; +#endif + NSArray *arr = [OSVer componentsSeparatedByString:@"."]; + int idx=0x01000000; + for( NSString *str in arr ) { + int value = [str intValue]; + OSVersion_ += value * idx; + idx = idx >> 8; + } + CCLOG(@"cocos2d: OS version: %@ (0x%08x)", OSVer, OSVersion_); + + CCLOG(@"cocos2d: GL_VENDOR: %s", glGetString(GL_VENDOR) ); + CCLOG(@"cocos2d: GL_RENDERER: %s", glGetString ( GL_RENDERER ) ); + CCLOG(@"cocos2d: GL_VERSION: %s", glGetString ( GL_VERSION ) ); + + glExtensions = (char*) glGetString(GL_EXTENSIONS); + + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize_); + glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, &maxModelviewStackDepth_); +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + if( OSVersion_ >= kCCiOSVersion_4_0 ) + glGetIntegerv(GL_MAX_SAMPLES_APPLE, &maxSamplesAllowed_); + else + maxSamplesAllowed_ = 0; +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + glGetIntegerv(GL_MAX_SAMPLES, &maxSamplesAllowed_); +#endif + + supportsPVRTC_ = [self checkForGLExtension:@"GL_IMG_texture_compression_pvrtc"]; +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + supportsNPOT_ = [self checkForGLExtension:@"GL_APPLE_texture_2D_limited_npot"]; +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + supportsNPOT_ = [self checkForGLExtension:@"GL_ARB_texture_non_power_of_two"]; +#endif + // It seems that somewhere between firmware iOS 3.0 and 4.2 Apple renamed + // GL_IMG_... to GL_APPLE.... So we should check both names + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + BOOL bgra8a = [self checkForGLExtension:@"GL_IMG_texture_format_BGRA8888"]; + BOOL bgra8b = [self checkForGLExtension:@"GL_APPLE_texture_format_BGRA8888"]; + supportsBGRA8888_ = bgra8a | bgra8b; +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + supportsBGRA8888_ = [self checkForGLExtension:@"GL_EXT_bgra"]; +#endif + + supportsDiscardFramebuffer_ = [self checkForGLExtension:@"GL_EXT_discard_framebuffer"]; + + CCLOG(@"cocos2d: GL_MAX_TEXTURE_SIZE: %d", maxTextureSize_); + CCLOG(@"cocos2d: GL_MAX_MODELVIEW_STACK_DEPTH: %d",maxModelviewStackDepth_); + CCLOG(@"cocos2d: GL_MAX_SAMPLES: %d", maxSamplesAllowed_); + CCLOG(@"cocos2d: GL supports PVRTC: %s", (supportsPVRTC_ ? "YES" : "NO") ); + CCLOG(@"cocos2d: GL supports BGRA8888 textures: %s", (supportsBGRA8888_ ? "YES" : "NO") ); + CCLOG(@"cocos2d: GL supports NPOT textures: %s", (supportsNPOT_ ? "YES" : "NO") ); + CCLOG(@"cocos2d: GL supports discard_framebuffer: %s", (supportsDiscardFramebuffer_ ? "YES" : "NO") ); + CCLOG(@"cocos2d: compiled with NPOT support: %s", +#if CC_TEXTURE_NPOT_SUPPORT + "YES" +#else + "NO" +#endif + ); + CCLOG(@"cocos2d: compiled with VBO support in TextureAtlas : %s", +#if CC_USES_VBO + "YES" +#else + "NO" +#endif + ); + + CCLOG(@"cocos2d: compiled with Affine Matrix transformation in CCNode : %s", +#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX + "YES" +#else + "NO" +#endif + ); + + CCLOG(@"cocos2d: compiled with Profiling Support: %s", +#if CC_ENABLE_PROFILERS + + "YES - *** Disable it when you finish profiling ***" +#else + "NO" +#endif + ); + + CHECK_GL_ERROR(); + } + + return self; +} + +- (BOOL) checkForGLExtension:(NSString *)searchName +{ + // For best results, extensionsNames should be stored in your renderer so that it does not + // need to be recreated on each invocation. + NSString *extensionsString = [NSString stringWithCString:glExtensions encoding: NSASCIIStringEncoding]; + NSArray *extensionsNames = [extensionsString componentsSeparatedByString:@" "]; + return [extensionsNames containsObject: searchName]; +} +@end diff --git a/Classes/cocos2d/CCDirector.h b/Classes/cocos2d/CCDirector.h new file mode 100644 index 0000000..fd36364 --- /dev/null +++ b/Classes/cocos2d/CCDirector.h @@ -0,0 +1,304 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + */ + + +#import "ccConfig.h" +#import "ccTypes.h" + +// OpenGL related +#import "Platforms/CCGL.h" +#import "CCProtocols.h" + +/** @typedef ccDirectorProjection + Possible OpenGL projections used by director + */ +typedef enum { + /// sets a 2D projection (orthogonal projection). + kCCDirectorProjection2D, + + /// sets a 3D projection with a fovy=60, znear=0.5f and zfar=1500. + kCCDirectorProjection3D, + + /// it calls "updateProjection" on the projection delegate. + kCCDirectorProjectionCustom, + + /// Detault projection is 3D projection + kCCDirectorProjectionDefault = kCCDirectorProjection3D, + + // backward compatibility stuff + CCDirectorProjection2D = kCCDirectorProjection2D, + CCDirectorProjection3D = kCCDirectorProjection3D, + CCDirectorProjectionCustom = kCCDirectorProjectionCustom, + +} ccDirectorProjection; + + +@class CCLabelAtlas; +@class CCScene; + +/**Class that creates and handle the main Window and manages how +and when to execute the Scenes. + + The CCDirector is also resposible for: + - initializing the OpenGL ES context + - setting the OpenGL pixel format (default on is RGB565) + - setting the OpenGL buffer depth (default one is 0-bit) + - setting the projection (default one is 3D) + - setting the orientation (default one is Protrait) + + Since the CCDirector is a singleton, the standard way to use it is by calling: + - [[CCDirector sharedDirector] methodName]; + + The CCDirector also sets the default OpenGL context: + - GL_TEXTURE_2D is enabled + - GL_VERTEX_ARRAY is enabled + - GL_COLOR_ARRAY is enabled + - GL_TEXTURE_COORD_ARRAY is enabled +*/ +@interface CCDirector : NSObject +{ + CC_GLVIEW *openGLView_; + + // internal timer + NSTimeInterval animationInterval_; + NSTimeInterval oldAnimationInterval_; + + /* display FPS ? */ + BOOL displayFPS_; + + NSUInteger frames_; + ccTime accumDt_; + ccTime frameRate_; +#if CC_DIRECTOR_FAST_FPS + CCLabelAtlas *FPSLabel_; +#endif + + /* is the running scene paused */ + BOOL isPaused_; + + /* The running scene */ + CCScene *runningScene_; + + /* This object will be visited after the scene. Useful to hook a notification node */ + id notificationNode_; + + /* will be the next 'runningScene' in the next frame + nextScene is a weak reference. */ + CCScene *nextScene_; + + /* If YES, then "old" scene will receive the cleanup message */ + BOOL sendCleanupToScene_; + + /* scheduled scenes */ + NSMutableArray *scenesStack_; + + /* last time the main loop was updated */ + struct timeval lastUpdate_; + /* delta time since last tick to main loop */ + ccTime dt; + /* whether or not the next delta time will be zero */ + BOOL nextDeltaTimeZero_; + + /* projection used */ + ccDirectorProjection projection_; + + /* Projection protocol delegate */ + id projectionDelegate_; + + /* window size in points */ + CGSize winSizeInPoints_; + + /* window size in pixels */ + CGSize winSizeInPixels_; + + /* the cocos2d running thread */ + NSThread *runningThread_; + + // profiler +#if CC_ENABLE_PROFILERS + ccTime accumDtForProfiler_; +#endif +} + +/** returns the cocos2d thread. + If you want to run any cocos2d task, run it in this thread. + On iOS usually it is the main thread. + @since v0.99.5 + */ +@property (readonly, nonatomic ) NSThread *runningThread; +/** The current running Scene. Director can only run one Scene at the time */ +@property (nonatomic,readonly) CCScene* runningScene; +/** The FPS value */ +@property (nonatomic,readwrite, assign) NSTimeInterval animationInterval; +/** Whether or not to display the FPS on the bottom-left corner */ +@property (nonatomic,readwrite, assign) BOOL displayFPS; +/** The OpenGLView, where everything is rendered */ +@property (nonatomic,readwrite,retain) CC_GLVIEW *openGLView; +/** whether or not the next delta time will be zero */ +@property (nonatomic,readwrite,assign) BOOL nextDeltaTimeZero; +/** Whether or not the Director is paused */ +@property (nonatomic,readonly) BOOL isPaused; +/** Sets an OpenGL projection + @since v0.8.2 + */ +@property (nonatomic,readwrite) ccDirectorProjection projection; + +/** Whether or not the replaced scene will receive the cleanup message. + If the new scene is pushed, then the old scene won't receive the "cleanup" message. + If the new scene replaces the old one, the it will receive the "cleanup" message. + @since v0.99.0 + */ +@property (nonatomic, readonly) BOOL sendCleanupToScene; + +/** This object will be visited after the main scene is visited. + This object MUST implement the "visit" selector. + Useful to hook a notification object, like CCNotifications (http://github.com/manucorporat/CCNotifications) + @since v0.99.5 + */ +@property (nonatomic, readwrite, retain) id notificationNode; + +/** This object will be called when the OpenGL projection is udpated and only when the kCCDirectorProjectionCustom projection is used. + @since v0.99.5 + */ +@property (nonatomic, readwrite, retain) id projectionDelegate; + +/** returns a shared instance of the director */ ++(CCDirector *)sharedDirector; + + + +// Window size + +/** returns the size of the OpenGL view in points. + It takes into account any possible rotation (device orientation) of the window + */ +- (CGSize) winSize; + +/** returns the size of the OpenGL view in pixels. + It takes into account any possible rotation (device orientation) of the window. + On Mac winSize and winSizeInPixels return the same value. + */ +- (CGSize) winSizeInPixels; +/** returns the display size of the OpenGL view in pixels. + It doesn't take into account any possible rotation of the window. + */ +-(CGSize) displaySizeInPixels; +/** changes the projection size */ +-(void) reshapeProjection:(CGSize)newWindowSize; + +/** converts a UIKit coordinate to an OpenGL coordinate + Useful to convert (multi) touchs coordinates to the current layout (portrait or landscape) + */ +-(CGPoint) convertToGL: (CGPoint) p; +/** converts an OpenGL coordinate to a UIKit coordinate + Useful to convert node points to window points for calls such as glScissor + */ +-(CGPoint) convertToUI:(CGPoint)p; + +/// XXX: missing description +-(float) getZEye; + +// Scene Management + +/**Enters the Director's main loop with the given Scene. + * Call it to run only your FIRST scene. + * Don't call it if there is already a running scene. + */ +- (void) runWithScene:(CCScene*) scene; + +/**Suspends the execution of the running scene, pushing it on the stack of suspended scenes. + * The new scene will be executed. + * Try to avoid big stacks of pushed scenes to reduce memory allocation. + * ONLY call it if there is a running scene. + */ +- (void) pushScene:(CCScene*) scene; + +/**Pops out a scene from the queue. + * This scene will replace the running one. + * The running scene will be deleted. If there are no more scenes in the stack the execution is terminated. + * ONLY call it if there is a running scene. + */ +- (void) popScene; + +/** Replaces the running scene with a new one. The running scene is terminated. + * ONLY call it if there is a running scene. + */ +-(void) replaceScene: (CCScene*) scene; + +/** Ends the execution, releases the running scene. + It doesn't remove the OpenGL view from its parent. You have to do it manually. + */ +-(void) end; + +/** Pauses the running scene. + The running scene will be _drawed_ but all scheduled timers will be paused + While paused, the draw rate will be 4 FPS to reduce CPU consuption + */ +-(void) pause; + +/** Resumes the paused scene + The scheduled timers will be activated again. + The "delta time" will be 0 (as if the game wasn't paused) + */ +-(void) resume; + +/** Stops the animation. Nothing will be drawn. The main loop won't be triggered anymore. + If you wan't to pause your animation call [pause] instead. + */ +-(void) stopAnimation; + +/** The main loop is triggered again. + Call this function only if [stopAnimation] was called earlier + @warning Dont' call this function to start the main loop. To run the main loop call runWithScene + */ +-(void) startAnimation; + +/** Draw the scene. + This method is called every frame. Don't call it manually. + */ +-(void) drawScene; + +// Memory Helper + +/** Removes all the cocos2d data that was cached automatically. + It will purge the CCTextureCache, CCBitmapFont cache. + IMPORTANT: The CCSpriteFrameCache won't be purged. If you want to purge it, you have to purge it manually. + @since v0.99.3 + */ +-(void) purgeCachedData; + +// OpenGL Helper + +/** sets the OpenGL default values */ +-(void) setGLDefaultValues; + +/** enables/disables OpenGL alpha blending */ +- (void) setAlphaBlending: (BOOL) on; +/** enables/disables OpenGL depth test */ +- (void) setDepthTest: (BOOL) on; + +// Profiler +-(void) showProfilers; + +@end diff --git a/Classes/cocos2d/CCDirector.m b/Classes/cocos2d/CCDirector.m new file mode 100644 index 0000000..35425fe --- /dev/null +++ b/Classes/cocos2d/CCDirector.m @@ -0,0 +1,557 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + */ + + +/* Idea of decoupling Window from Director taken from OC3D project: http://code.google.com/p/oc3d/ + */ + +#import +#import + +// cocos2d imports +#import "CCDirector.h" +#import "CCScheduler.h" +#import "CCActionManager.h" +#import "CCTextureCache.h" +#import "CCAnimationCache.h" +#import "CCLabelAtlas.h" +#import "ccMacros.h" +#import "CCTransition.h" +#import "CCScene.h" +#import "CCSpriteFrameCache.h" +#import "CCTexture2D.h" +#import "CCLabelBMFont.h" +#import "CCLayer.h" + +// support imports +#import "Platforms/CCGL.h" +#import "Platforms/CCNS.h" + +#import "Support/OpenGL_Internal.h" +#import "Support/CGPointExtension.h" + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +#import "Platforms/iOS/CCDirectorIOS.h" +#define CC_DIRECTOR_DEFAULT CCDirectorTimer +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) +#import "Platforms/Mac/CCDirectorMac.h" +#define CC_DIRECTOR_DEFAULT CCDirectorDisplayLink +#endif + +#import "Support/CCProfiling.h" + +#define kDefaultFPS 60.0 // 60 frames per second + +extern NSString * cocos2dVersion(void); + + +@interface CCDirector (Private) +-(void) setNextScene; +// shows the FPS in the screen +-(void) showFPS; +// calculates delta time since last time it was called +-(void) calculateDeltaTime; +@end + +@implementation CCDirector + +@synthesize animationInterval = animationInterval_; +@synthesize runningScene = runningScene_; +@synthesize displayFPS = displayFPS_; +@synthesize nextDeltaTimeZero = nextDeltaTimeZero_; +@synthesize isPaused = isPaused_; +@synthesize sendCleanupToScene = sendCleanupToScene_; +@synthesize runningThread = runningThread_; +@synthesize notificationNode = notificationNode_; +@synthesize projectionDelegate = projectionDelegate_; +// +// singleton stuff +// +static CCDirector *_sharedDirector = nil; + ++ (CCDirector *)sharedDirector +{ + if (!_sharedDirector) { + + // + // Default Director is TimerDirector + // + if( [ [CCDirector class] isEqual:[self class]] ) + _sharedDirector = [[CC_DIRECTOR_DEFAULT alloc] init]; + else + _sharedDirector = [[self alloc] init]; + } + + return _sharedDirector; +} + ++(id)alloc +{ + NSAssert(_sharedDirector == nil, @"Attempted to allocate a second instance of a singleton."); + return [super alloc]; +} + +- (id) init +{ + CCLOG(@"cocos2d: %@", cocos2dVersion() ); + + if( (self=[super init]) ) { + + CCLOG(@"cocos2d: Using Director Type:%@", [self class]); + + // scenes + runningScene_ = nil; + nextScene_ = nil; + + notificationNode_ = nil; + + oldAnimationInterval_ = animationInterval_ = 1.0 / kDefaultFPS; + scenesStack_ = [[NSMutableArray alloc] initWithCapacity:10]; + + // Set default projection (3D) + projection_ = kCCDirectorProjectionDefault; + + // projection delegate if "Custom" projection is used + projectionDelegate_ = nil; + + // FPS + displayFPS_ = NO; + frames_ = 0; + + // paused ? + isPaused_ = NO; + + // running thread + runningThread_ = nil; + + winSizeInPixels_ = winSizeInPoints_ = CGSizeZero; + } + + return self; +} + +- (void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + +#if CC_DIRECTOR_FAST_FPS + [FPSLabel_ release]; +#endif + [runningScene_ release]; + [notificationNode_ release]; + [scenesStack_ release]; + + [projectionDelegate_ release]; + + _sharedDirector = nil; + + [super dealloc]; +} + +-(void) setGLDefaultValues +{ + // This method SHOULD be called only after openGLView_ was initialized + NSAssert( openGLView_, @"openGLView_ must be initialized"); + + [self setAlphaBlending: YES]; + [self setDepthTest: YES]; + [self setProjection: projection_]; + + // set other opengl default values + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + +#if CC_DIRECTOR_FAST_FPS + if (!FPSLabel_) { + CCTexture2DPixelFormat currentFormat = [CCTexture2D defaultAlphaPixelFormat]; + [CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA4444]; + FPSLabel_ = [[CCLabelAtlas labelWithString:@"00.0" charMapFile:@"fps_images.png" itemWidth:16 itemHeight:24 startCharMap:'.'] retain]; + [CCTexture2D setDefaultAlphaPixelFormat:currentFormat]; + } +#endif // CC_DIRECTOR_FAST_FPS +} + +// +// Draw the Scene +// +- (void) drawScene +{ + // Override me +} + +-(void) calculateDeltaTime +{ + struct timeval now; + + if( gettimeofday( &now, NULL) != 0 ) { + CCLOG(@"cocos2d: error in gettimeofday"); + dt = 0; + return; + } + + // new delta time + if( nextDeltaTimeZero_ ) { + dt = 0; + nextDeltaTimeZero_ = NO; + } else { + dt = (now.tv_sec - lastUpdate_.tv_sec) + (now.tv_usec - lastUpdate_.tv_usec) / 1000000.0f; + dt = MAX(0,dt); + } + + lastUpdate_ = now; +} + +#pragma mark Director - Memory Helper + +-(void) purgeCachedData +{ + [CCLabelBMFont purgeCachedData]; + [CCTextureCache purgeSharedTextureCache]; +} + +#pragma mark Director - Scene OpenGL Helper + +-(ccDirectorProjection) projection +{ + return projection_; +} + +-(float) getZEye +{ + return ( winSizeInPixels_.height / 1.1566f ); +} + +-(void) setProjection:(ccDirectorProjection)projection +{ + CCLOG(@"cocos2d: override me"); +} + +- (void) setAlphaBlending: (BOOL) on +{ + if (on) { + glEnable(GL_BLEND); + glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST); + + } else + glDisable(GL_BLEND); +} + +- (void) setDepthTest: (BOOL) on +{ + if (on) { + ccglClearDepth(1.0f); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + } else + glDisable( GL_DEPTH_TEST ); +} + +#pragma mark Director Integration with a UIKit view + +-(CC_GLVIEW*) openGLView +{ + return openGLView_; +} + +-(void) setOpenGLView:(CC_GLVIEW *)view +{ + NSAssert( view, @"OpenGLView must be non-nil"); + + if( view != openGLView_ ) { + [openGLView_ release]; + openGLView_ = [view retain]; + + // set size + winSizeInPixels_ = winSizeInPoints_ = CCNSSizeToCGSize( [view bounds].size ); + + [self setGLDefaultValues]; + } +} + +#pragma mark Director Scene Landscape + +-(CGPoint)convertToGL:(CGPoint)uiPoint +{ + CCLOG(@"CCDirector#convertToGL: OVERRIDE ME."); + return CGPointZero; +} + +-(CGPoint)convertToUI:(CGPoint)glPoint +{ + CCLOG(@"CCDirector#convertToUI: OVERRIDE ME."); + return CGPointZero; +} + +-(CGSize)winSize +{ + return winSizeInPoints_; +} + +-(CGSize)winSizeInPixels +{ + return winSizeInPixels_; +} + +-(CGSize)displaySizeInPixels +{ + return winSizeInPixels_; +} + +-(void) reshapeProjection:(CGSize)newWindowSize +{ + winSizeInPixels_ = winSizeInPoints_ = newWindowSize; + [self setProjection:projection_]; +} + +#pragma mark Director Scene Management + +- (void)runWithScene:(CCScene*) scene +{ + NSAssert( scene != nil, @"Argument must be non-nil"); + NSAssert( runningScene_ == nil, @"You can't run an scene if another Scene is running. Use replaceScene or pushScene instead"); + + [self pushScene:scene]; + [self startAnimation]; +} + +-(void) replaceScene: (CCScene*) scene +{ + NSAssert( scene != nil, @"Argument must be non-nil"); + + NSUInteger index = [scenesStack_ count]; + + sendCleanupToScene_ = YES; + [scenesStack_ replaceObjectAtIndex:index-1 withObject:scene]; + nextScene_ = scene; // nextScene_ is a weak ref +} + +- (void) pushScene: (CCScene*) scene +{ + NSAssert( scene != nil, @"Argument must be non-nil"); + + sendCleanupToScene_ = NO; + + [scenesStack_ addObject: scene]; + nextScene_ = scene; // nextScene_ is a weak ref +} + +-(void) popScene +{ + NSAssert( runningScene_ != nil, @"A running Scene is needed"); + + [scenesStack_ removeLastObject]; + NSUInteger c = [scenesStack_ count]; + + if( c == 0 ) + [self end]; + else { + sendCleanupToScene_ = YES; + nextScene_ = [scenesStack_ objectAtIndex:c-1]; + } +} + +-(void) end +{ + [runningScene_ onExit]; + [runningScene_ cleanup]; + [runningScene_ release]; + + runningScene_ = nil; + nextScene_ = nil; + + // remove all objects, but don't release it. + // runWithScene might be executed after 'end'. + [scenesStack_ removeAllObjects]; + + [self stopAnimation]; + +#if CC_DIRECTOR_FAST_FPS + [FPSLabel_ release]; + FPSLabel_ = nil; +#endif + + [projectionDelegate_ release]; + projectionDelegate_ = nil; + + // Purge bitmap cache + [CCLabelBMFont purgeCachedData]; + + // Purge all managers + [CCAnimationCache purgeSharedAnimationCache]; + [CCSpriteFrameCache purgeSharedSpriteFrameCache]; + [CCScheduler purgeSharedScheduler]; + [CCActionManager purgeSharedManager]; + [CCTextureCache purgeSharedTextureCache]; + + + // OpenGL view + + // Since the director doesn't attach the openglview to the window + // it shouldn't remove it from the window too. +// [openGLView_ removeFromSuperview]; + + [openGLView_ release]; + openGLView_ = nil; +} + +-(void) setNextScene +{ + Class transClass = [CCTransitionScene class]; + BOOL runningIsTransition = [runningScene_ isKindOfClass:transClass]; + BOOL newIsTransition = [nextScene_ isKindOfClass:transClass]; + + // If it is not a transition, call onExit/cleanup + if( ! newIsTransition ) { + [runningScene_ onExit]; + + // issue #709. the root node (scene) should receive the cleanup message too + // otherwise it might be leaked. + if( sendCleanupToScene_) + [runningScene_ cleanup]; + } + + [runningScene_ release]; + + runningScene_ = [nextScene_ retain]; + nextScene_ = nil; + + if( ! runningIsTransition ) { + [runningScene_ onEnter]; + [runningScene_ onEnterTransitionDidFinish]; + } +} + +-(void) pause +{ + if( isPaused_ ) + return; + + oldAnimationInterval_ = animationInterval_; + + // when paused, don't consume CPU + [self setAnimationInterval:1/4.0]; + isPaused_ = YES; +} + +-(void) resume +{ + if( ! isPaused_ ) + return; + + [self setAnimationInterval: oldAnimationInterval_]; + + if( gettimeofday( &lastUpdate_, NULL) != 0 ) { + CCLOG(@"cocos2d: Director: Error in gettimeofday"); + } + + isPaused_ = NO; + dt = 0; +} + +- (void)startAnimation +{ + CCLOG(@"cocos2d: Director#startAnimation. Override me"); +} + +- (void)stopAnimation +{ + CCLOG(@"cocos2d: Director#stopAnimation. Override me"); +} + +- (void)setAnimationInterval:(NSTimeInterval)interval +{ + CCLOG(@"cocos2d: Director#setAnimationInterval. Override me"); +} + +#if CC_DIRECTOR_FAST_FPS + +// display the FPS using a LabelAtlas +// updates the FPS every frame +-(void) showFPS +{ + frames_++; + accumDt_ += dt; + + if ( accumDt_ > CC_DIRECTOR_FPS_INTERVAL) { + frameRate_ = frames_/accumDt_; + frames_ = 0; + accumDt_ = 0; + +// sprintf(format,"%.1f",frameRate); +// [FPSLabel setCString:format]; + + NSString *str = [[NSString alloc] initWithFormat:@"%.1f", frameRate_]; + [FPSLabel_ setString:str]; + [str release]; + } + + [FPSLabel_ draw]; +} +#else +// display the FPS using a manually generated Texture (very slow) +// updates the FPS 3 times per second aprox. +-(void) showFPS +{ + frames_++; + accumDt_ += dt; + + if ( accumDt_ > CC_DIRECTOR_FPS_INTERVAL) { + frameRate_ = frames_/accumDt_; + frames_ = 0; + accumDt_ = 0; + } + + NSString *str = [NSString stringWithFormat:@"%.2f",frameRate_]; + CCTexture2D *texture = [[CCTexture2D alloc] initWithString:str dimensions:CGSizeMake(100,30) alignment:UITextAlignmentLeft fontName:@"Arial" fontSize:24]; + + // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY + // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY + // Unneeded states: GL_COLOR_ARRAY + glDisableClientState(GL_COLOR_ARRAY); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glColor4ub(224,224,244,200); + [texture drawAtPoint: ccp(5,2)]; + [texture release]; + + glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST); + + // restore default GL state + glEnableClientState(GL_COLOR_ARRAY); +} +#endif + +- (void) showProfilers { +#if CC_ENABLE_PROFILERS + accumDtForProfiler_ += dt; + if (accumDtForProfiler_ > 1.0f) { + accumDtForProfiler_ = 0; + [[CCProfiler sharedProfiler] displayTimers]; + } +#endif // CC_ENABLE_PROFILERS +} + +@end + diff --git a/Classes/cocos2d/CCDrawingPrimitives.h b/Classes/cocos2d/CCDrawingPrimitives.h new file mode 100644 index 0000000..1dbd9a5 --- /dev/null +++ b/Classes/cocos2d/CCDrawingPrimitives.h @@ -0,0 +1,91 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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_DRAWING_PRIMITIVES_H +#define __CC_DRAWING_PRIMITIVES_H + +#import +#import + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +#import // for CGPoint +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + @file + Drawing OpenGL ES primitives. + - ccDrawPoint + - ccDrawLine + - ccDrawPoly + - ccDrawCircle + - ccDrawQuadBezier + - ccDrawCubicBezier + + You can change the color, width and other property by calling the + glColor4ub(), glLineWitdh(), glPointSize(). + + @warning These functions draws the Line, Point, Polygon, immediately. They aren't batched. If you are going to make a game that depends on these primitives, I suggest creating a batch. + */ + + +/** draws a point given x and y coordinate measured in points. */ +void ccDrawPoint( CGPoint point ); + +/** draws an array of points. + @since v0.7.2 + */ +void ccDrawPoints( const CGPoint *points, NSUInteger numberOfPoints ); + +/** draws a line given the origin and destination point measured in points. */ +void ccDrawLine( CGPoint origin, CGPoint destination ); + +/** draws a poligon given a pointer to CGPoint coordiantes and the number of vertices measured in points. + The polygon can be closed or open + */ +void ccDrawPoly( const CGPoint *vertices, NSUInteger numOfVertices, BOOL closePolygon ); + +/** draws a circle given the center, radius and number of segments measured in points */ +void ccDrawCircle( CGPoint center, float radius, float angle, NSUInteger segments, BOOL drawLineToCenter); + +/** draws a quad bezier path measured in points. + @since v0.8 + */ +void ccDrawQuadBezier(CGPoint origin, CGPoint control, CGPoint destination, NSUInteger segments); + +/** draws a cubic bezier path measured in points. + @since v0.8 + */ +void ccDrawCubicBezier(CGPoint origin, CGPoint control1, CGPoint control2, CGPoint destination, NSUInteger segments); + +#ifdef __cplusplus +} +#endif + +#endif // __CC_DRAWING_PRIMITIVES_H diff --git a/Classes/cocos2d/CCDrawingPrimitives.m b/Classes/cocos2d/CCDrawingPrimitives.m new file mode 100644 index 0000000..1e26a6f --- /dev/null +++ b/Classes/cocos2d/CCDrawingPrimitives.m @@ -0,0 +1,271 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + */ + +#import +#import +#import + +#import "CCDrawingPrimitives.h" +#import "ccTypes.h" +#import "ccMacros.h" +#import "Platforms/CCGL.h" + +void ccDrawPoint( CGPoint point ) +{ + ccVertex2F p = (ccVertex2F) {point.x * CC_CONTENT_SCALE_FACTOR(), point.y * CC_CONTENT_SCALE_FACTOR() }; + + // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY + // Needed states: GL_VERTEX_ARRAY, + // Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY + glDisable(GL_TEXTURE_2D); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + glVertexPointer(2, GL_FLOAT, 0, &p); + glDrawArrays(GL_POINTS, 0, 1); + + // restore default state + glEnableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnable(GL_TEXTURE_2D); +} + +void ccDrawPoints( const CGPoint *points, NSUInteger numberOfPoints ) +{ + // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY + // Needed states: GL_VERTEX_ARRAY, + // Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY + glDisable(GL_TEXTURE_2D); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + ccVertex2F newPoints[numberOfPoints]; + + // iPhone and 32-bit machines optimization + if( sizeof(CGPoint) == sizeof(ccVertex2F) ) { + + // points ? + if( CC_CONTENT_SCALE_FACTOR() != 1 ) { + for( NSUInteger i=0; i + +@class CCTexture2D; + +/** FBO class that grabs the the contents of the screen */ +@interface CCGrabber : NSObject +{ + GLuint fbo; + GLint oldFBO; +} + +-(void)grab:(CCTexture2D*)texture; +-(void)beforeRender:(CCTexture2D*)texture; +-(void)afterRender:(CCTexture2D*)texture; + +@end diff --git a/Classes/cocos2d/CCGrabber.m b/Classes/cocos2d/CCGrabber.m new file mode 100644 index 0000000..a259091 --- /dev/null +++ b/Classes/cocos2d/CCGrabber.m @@ -0,0 +1,95 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * 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. + * + */ + + +#import "Platforms/CCGL.h" +#import "CCGrabber.h" +#import "ccMacros.h" +#import "CCTexture2D.h" +#import "Support/OpenGL_Internal.h" + +@implementation CCGrabber + +-(id) init +{ + if(( self = [super init] )) { + // generate FBO + ccglGenFramebuffers(1, &fbo); + } + return self; +} + +-(void)grab:(CCTexture2D*)texture +{ + glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &oldFBO); + + // bind + ccglBindFramebuffer(CC_GL_FRAMEBUFFER, fbo); + + // associate texture with FBO + ccglFramebufferTexture2D(CC_GL_FRAMEBUFFER, CC_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.name, 0); + + // check if it worked (probably worth doing :) ) + GLuint status = ccglCheckFramebufferStatus(CC_GL_FRAMEBUFFER); + if (status != CC_GL_FRAMEBUFFER_COMPLETE) + [NSException raise:@"Frame Grabber" format:@"Could not attach texture to framebuffer"]; + + ccglBindFramebuffer(CC_GL_FRAMEBUFFER, oldFBO); +} + +-(void)beforeRender:(CCTexture2D*)texture +{ + glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &oldFBO); + ccglBindFramebuffer(CC_GL_FRAMEBUFFER, fbo); + + // BUG XXX: doesn't work with RGB565. + + + glClearColor(0,0,0,0); + + // BUG #631: To fix #631, uncomment the lines with #631 + // Warning: But it CCGrabber won't work with 2 effects at the same time +// glClearColor(0.0f,0.0f,0.0f,1.0f); // #631 + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + +// glColorMask(TRUE, TRUE, TRUE, FALSE); // #631 + +} + +-(void)afterRender:(CCTexture2D*)texture +{ + ccglBindFramebuffer(CC_GL_FRAMEBUFFER, oldFBO); +// glColorMask(TRUE, TRUE, TRUE, TRUE); // #631 +} + +- (void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + ccglDeleteFramebuffers(1, &fbo); + [super dealloc]; +} + +@end diff --git a/Classes/cocos2d/CCGrid.h b/Classes/cocos2d/CCGrid.h new file mode 100644 index 0000000..e5e77e8 --- /dev/null +++ b/Classes/cocos2d/CCGrid.h @@ -0,0 +1,121 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * 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. + * + */ + + +#import + +#import "CCNode.h" +#import "CCCamera.h" +#import "ccTypes.h" + +@class CCTexture2D; +@class CCGrabber; + +/** Base class for other + */ +@interface CCGridBase : NSObject +{ + BOOL active_; + int reuseGrid_; + ccGridSize gridSize_; + CCTexture2D *texture_; + CGPoint step_; + CCGrabber *grabber_; + BOOL isTextureFlipped_; +} + +/** wheter or not the grid is active */ +@property (nonatomic,readwrite) BOOL active; +/** number of times that the grid will be reused */ +@property (nonatomic,readwrite) int reuseGrid; +/** size of the grid */ +@property (nonatomic,readonly) ccGridSize gridSize; +/** pixels between the grids */ +@property (nonatomic,readwrite) CGPoint step; +/** texture used */ +@property (nonatomic, retain) CCTexture2D *texture; +/** grabber used */ +@property (nonatomic, retain) CCGrabber *grabber; +/** is texture flipped */ +@property (nonatomic, readwrite) BOOL isTextureFlipped; + ++(id) gridWithSize:(ccGridSize)gridSize texture:(CCTexture2D*)texture flippedTexture:(BOOL)flipped; ++(id) gridWithSize:(ccGridSize)gridSize; + +-(id) initWithSize:(ccGridSize)gridSize texture:(CCTexture2D*)texture flippedTexture:(BOOL)flipped; +-(id)initWithSize:(ccGridSize)gridSize; +-(void)beforeDraw; +-(void)afterDraw:(CCNode*)target; +-(void)blit; +-(void)reuse; + +-(void)calculateVertexPoints; + +@end + +//////////////////////////////////////////////////////////// + +/** + CCGrid3D is a 3D grid implementation. Each vertex has 3 dimensions: x,y,z + */ +@interface CCGrid3D : CCGridBase +{ + GLvoid *texCoordinates; + GLvoid *vertices; + GLvoid *originalVertices; + GLushort *indices; +} + +/** returns the vertex at a given position */ +-(ccVertex3F)vertex:(ccGridSize)pos; +/** returns the original (non-transformed) vertex at a given position */ +-(ccVertex3F)originalVertex:(ccGridSize)pos; +/** sets a new vertex at a given position */ +-(void)setVertex:(ccGridSize)pos vertex:(ccVertex3F)vertex; + +@end + +//////////////////////////////////////////////////////////// + +/** + CCTiledGrid3D is a 3D grid implementation. It differs from Grid3D in that + the tiles can be separated from the grid. +*/ +@interface CCTiledGrid3D : CCGridBase +{ + GLvoid *texCoordinates; + GLvoid *vertices; + GLvoid *originalVertices; + GLushort *indices; +} + +/** returns the tile at the given position */ +-(ccQuad3)tile:(ccGridSize)pos; +/** returns the original tile (untransformed) at the given position */ +-(ccQuad3)originalTile:(ccGridSize)pos; +/** sets a new tile */ +-(void)setTile:(ccGridSize)pos coords:(ccQuad3)coords; + +@end diff --git a/Classes/cocos2d/CCGrid.m b/Classes/cocos2d/CCGrid.m new file mode 100644 index 0000000..b63fbb8 --- /dev/null +++ b/Classes/cocos2d/CCGrid.m @@ -0,0 +1,571 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * 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. + * + */ + + +#import + +#import "ccMacros.h" +#import "CCGrid.h" +#import "CCTexture2D.h" +#import "CCDirector.h" +#import "CCGrabber.h" + +#import "Platforms/CCGL.h" +#import "Support/CGPointExtension.h" +#import "Support/ccUtils.h" + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +#import "Platforms/iOS/CCDirectorIOS.h" +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED + +#pragma mark - +#pragma mark CCGridBase + +@implementation CCGridBase + +@synthesize reuseGrid = reuseGrid_; +@synthesize texture = texture_; +@synthesize grabber = grabber_; +@synthesize gridSize = gridSize_; +@synthesize step = step_; + ++(id) gridWithSize:(ccGridSize)gridSize texture:(CCTexture2D*)texture flippedTexture:(BOOL)flipped +{ + return [[[self alloc] initWithSize:gridSize texture:texture flippedTexture:flipped] autorelease]; +} + ++(id) gridWithSize:(ccGridSize)gridSize +{ + return [[(CCGridBase*)[self alloc] initWithSize:gridSize] autorelease]; +} + +-(id) initWithSize:(ccGridSize)gridSize texture:(CCTexture2D*)texture flippedTexture:(BOOL)flipped +{ + if( (self=[super init]) ) { + + active_ = NO; + reuseGrid_ = 0; + gridSize_ = gridSize; + + self.texture = texture; + isTextureFlipped_ = flipped; + + CGSize texSize = [texture_ contentSizeInPixels]; + step_.x = texSize.width / gridSize_.x; + step_.y = texSize.height / gridSize_.y; + + grabber_ = [[CCGrabber alloc] init]; + [grabber_ grab:texture_]; + + [self calculateVertexPoints]; + } + return self; +} + +-(id)initWithSize:(ccGridSize)gSize +{ + CCDirector *director = [CCDirector sharedDirector]; + CGSize s = [director winSizeInPixels]; + + unsigned int POTWide = ccNextPOT(s.width); + unsigned int POTHigh = ccNextPOT(s.height); + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + EAGLView *glview = [[CCDirector sharedDirector] openGLView]; + NSString *pixelFormat = [glview pixelFormat]; + + CCTexture2DPixelFormat format = [pixelFormat isEqualToString: kEAGLColorFormatRGB565] ? kCCTexture2DPixelFormat_RGB565 : kCCTexture2DPixelFormat_RGBA8888; +#else + CCTexture2DPixelFormat format = kCCTexture2DPixelFormat_RGBA8888; +#endif + + void *data = calloc((int)(POTWide * POTHigh * 4), 1); + if( ! data ) { + CCLOG(@"cocos2d: CCGrid: not enough memory"); + [self release]; + return nil; + } + + CCTexture2D *texture = [[CCTexture2D alloc] initWithData:data pixelFormat:format pixelsWide:POTWide pixelsHigh:POTHigh contentSize:s]; + free( data ); + + if( ! texture ) { + CCLOG(@"cocos2d: CCGrid: error creating texture"); + [self release]; + return nil; + } + + self = [self initWithSize:gSize texture:texture flippedTexture:NO]; + + [texture release]; + + return self; +} +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %08X | Dimensions = %ix%i>", [self class], self, gridSize_.x, gridSize_.y]; +} + +- (void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + + [self setActive: NO]; + + [texture_ release]; + [grabber_ release]; + [super dealloc]; +} + +// properties +-(BOOL) active +{ + return active_; +} + +-(void) setActive:(BOOL)active +{ + active_ = active; + if( ! active ) { + CCDirector *director = [CCDirector sharedDirector]; + ccDirectorProjection proj = [director projection]; + [director setProjection:proj]; + } +} + +-(BOOL) isTextureFlipped +{ + return isTextureFlipped_; +} + +-(void) setIsTextureFlipped:(BOOL)flipped +{ + if( isTextureFlipped_ != flipped ) { + isTextureFlipped_ = flipped; + [self calculateVertexPoints]; + } +} + +// This routine can be merged with Director +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +-(void)applyLandscape +{ + CCDirector *director = [CCDirector sharedDirector]; + + CGSize winSize = [director displaySizeInPixels]; + float w = winSize.width / 2; + float h = winSize.height / 2; + + ccDeviceOrientation orientation = [director deviceOrientation]; + + switch (orientation) { + case CCDeviceOrientationLandscapeLeft: + glTranslatef(w,h,0); + glRotatef(-90,0,0,1); + glTranslatef(-h,-w,0); + break; + case CCDeviceOrientationLandscapeRight: + glTranslatef(w,h,0); + glRotatef(90,0,0,1); + glTranslatef(-h,-w,0); + break; + case CCDeviceOrientationPortraitUpsideDown: + glTranslatef(w,h,0); + glRotatef(180,0,0,1); + glTranslatef(-w,-h,0); + break; + default: + break; + } +} +#endif + +-(void)set2DProjection +{ + CGSize winSize = [[CCDirector sharedDirector] winSizeInPixels]; + + glLoadIdentity(); + glViewport(0, 0, winSize.width, winSize.height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + ccglOrtho(0, winSize.width, 0, winSize.height, -1024, 1024); + glMatrixMode(GL_MODELVIEW); +} + +// This routine can be merged with Director +-(void)set3DProjection +{ + CCDirector *director = [CCDirector sharedDirector]; + + CGSize winSize = [director displaySizeInPixels]; + + glViewport(0, 0, winSize.width, winSize.height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(60, (GLfloat)winSize.width/winSize.height, 0.5f, 1500.0f); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( winSize.width/2, winSize.height/2, [director getZEye], + winSize.width/2, winSize.height/2, 0, + 0.0f, 1.0f, 0.0f + ); +} + +-(void)beforeDraw +{ + [self set2DProjection]; + [grabber_ beforeRender:texture_]; +} + +-(void)afterDraw:(CCNode *)target +{ + [grabber_ afterRender:texture_]; + + [self set3DProjection]; +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + [self applyLandscape]; +#endif + + if( target.camera.dirty ) { + + CGPoint offset = [target anchorPointInPixels]; + + // + // XXX: Camera should be applied in the AnchorPoint + // + ccglTranslate(offset.x, offset.y, 0); + [target.camera locate]; + ccglTranslate(-offset.x, -offset.y, 0); + } + + glBindTexture(GL_TEXTURE_2D, texture_.name); + + [self blit]; +} + +-(void)blit +{ + [NSException raise:@"GridBase" format:@"Abstract class needs implementation"]; +} + +-(void)reuse +{ + [NSException raise:@"GridBase" format:@"Abstract class needs implementation"]; +} + +-(void)calculateVertexPoints +{ + [NSException raise:@"GridBase" format:@"Abstract class needs implementation"]; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCGrid3D +@implementation CCGrid3D + +-(void)dealloc +{ + free(texCoordinates); + free(vertices); + free(indices); + free(originalVertices); + [super dealloc]; +} + +-(void)blit +{ + int n = gridSize_.x * gridSize_.y; + + // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY + // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY + // Unneeded states: GL_COLOR_ARRAY + glDisableClientState(GL_COLOR_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, vertices); + glTexCoordPointer(2, GL_FLOAT, 0, texCoordinates); + glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, indices); + + // restore GL default state + glEnableClientState(GL_COLOR_ARRAY); +} + +-(void)calculateVertexPoints +{ + float width = (float)texture_.pixelsWide; + float height = (float)texture_.pixelsHigh; + float imageH = texture_.contentSizeInPixels.height; + + int x, y, i; + + vertices = malloc((gridSize_.x+1)*(gridSize_.y+1)*sizeof(ccVertex3F)); + originalVertices = malloc((gridSize_.x+1)*(gridSize_.y+1)*sizeof(ccVertex3F)); + texCoordinates = malloc((gridSize_.x+1)*(gridSize_.y+1)*sizeof(CGPoint)); + indices = malloc(gridSize_.x*gridSize_.y*sizeof(GLushort)*6); + + float *vertArray = (float*)vertices; + float *texArray = (float*)texCoordinates; + GLushort *idxArray = (GLushort *)indices; + + for( x = 0; x < gridSize_.x; x++ ) + { + for( y = 0; y < gridSize_.y; y++ ) + { + int idx = (y * gridSize_.x) + x; + + float x1 = x * step_.x; + float x2 = x1 + step_.x; + float y1 = y * step_.y; + float y2 = y1 + step_.y; + + GLushort a = x * (gridSize_.y+1) + y; + GLushort b = (x+1) * (gridSize_.y+1) + y; + GLushort c = (x+1) * (gridSize_.y+1) + (y+1); + GLushort d = x * (gridSize_.y+1) + (y+1); + + GLushort tempidx[6] = { a, b, d, b, c, d }; + + memcpy(&idxArray[6*idx], tempidx, 6*sizeof(GLushort)); + + int l1[4] = { a*3, b*3, c*3, d*3 }; + ccVertex3F e = {x1,y1,0}; + ccVertex3F f = {x2,y1,0}; + ccVertex3F g = {x2,y2,0}; + ccVertex3F h = {x1,y2,0}; + + ccVertex3F l2[4] = { e, f, g, h }; + + int tex1[4] = { a*2, b*2, c*2, d*2 }; + CGPoint tex2[4] = { ccp(x1, y1), ccp(x2, y1), ccp(x2, y2), ccp(x1, y2) }; + + for( i = 0; i < 4; i++ ) + { + vertArray[ l1[i] ] = l2[i].x; + vertArray[ l1[i] + 1 ] = l2[i].y; + vertArray[ l1[i] + 2 ] = l2[i].z; + + texArray[ tex1[i] ] = tex2[i].x / width; + if( isTextureFlipped_ ) + texArray[ tex1[i] + 1 ] = (imageH - tex2[i].y) / height; + else + texArray[ tex1[i] + 1 ] = tex2[i].y / height; + } + } + } + + memcpy(originalVertices, vertices, (gridSize_.x+1)*(gridSize_.y+1)*sizeof(ccVertex3F)); +} + +-(ccVertex3F)vertex:(ccGridSize)pos +{ + int index = (pos.x * (gridSize_.y+1) + pos.y) * 3; + float *vertArray = (float *)vertices; + + ccVertex3F vert = { vertArray[index], vertArray[index+1], vertArray[index+2] }; + + return vert; +} + +-(ccVertex3F)originalVertex:(ccGridSize)pos +{ + int index = (pos.x * (gridSize_.y+1) + pos.y) * 3; + float *vertArray = (float *)originalVertices; + + ccVertex3F vert = { vertArray[index], vertArray[index+1], vertArray[index+2] }; + + return vert; +} + +-(void)setVertex:(ccGridSize)pos vertex:(ccVertex3F)vertex +{ + int index = (pos.x * (gridSize_.y+1) + pos.y) * 3; + float *vertArray = (float *)vertices; + vertArray[index] = vertex.x; + vertArray[index+1] = vertex.y; + vertArray[index+2] = vertex.z; +} + +-(void)reuse +{ + if ( reuseGrid_ > 0 ) + { + memcpy(originalVertices, vertices, (gridSize_.x+1)*(gridSize_.y+1)*sizeof(ccVertex3F)); + reuseGrid_--; + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCTiledGrid3D + +@implementation CCTiledGrid3D + +-(void)dealloc +{ + free(texCoordinates); + free(vertices); + free(indices); + free(originalVertices); + [super dealloc]; +} + +-(void)blit +{ + int n = gridSize_.x * gridSize_.y; + + // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY + // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY + // Unneeded states: GL_COLOR_ARRAY + glDisableClientState(GL_COLOR_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, vertices); + glTexCoordPointer(2, GL_FLOAT, 0, texCoordinates); + glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, indices); + + // restore default GL state + glEnableClientState(GL_COLOR_ARRAY); +} + +-(void)calculateVertexPoints +{ + float width = (float)texture_.pixelsWide; + float height = (float)texture_.pixelsHigh; + float imageH = texture_.contentSizeInPixels.height; + + int numQuads = gridSize_.x * gridSize_.y; + + vertices = malloc(numQuads*12*sizeof(GLfloat)); + originalVertices = malloc(numQuads*12*sizeof(GLfloat)); + texCoordinates = malloc(numQuads*8*sizeof(GLfloat)); + indices = malloc(numQuads*6*sizeof(GLushort)); + + float *vertArray = (float*)vertices; + float *texArray = (float*)texCoordinates; + GLushort *idxArray = (GLushort *)indices; + + int x, y; + + for( x = 0; x < gridSize_.x; x++ ) + { + for( y = 0; y < gridSize_.y; y++ ) + { + float x1 = x * step_.x; + float x2 = x1 + step_.x; + float y1 = y * step_.y; + float y2 = y1 + step_.y; + + *vertArray++ = x1; + *vertArray++ = y1; + *vertArray++ = 0; + *vertArray++ = x2; + *vertArray++ = y1; + *vertArray++ = 0; + *vertArray++ = x1; + *vertArray++ = y2; + *vertArray++ = 0; + *vertArray++ = x2; + *vertArray++ = y2; + *vertArray++ = 0; + + float newY1 = y1; + float newY2 = y2; + + if( isTextureFlipped_ ) { + newY1 = imageH - y1; + newY2 = imageH - y2; + } + + *texArray++ = x1 / width; + *texArray++ = newY1 / height; + *texArray++ = x2 / width; + *texArray++ = newY1 / height; + *texArray++ = x1 / width; + *texArray++ = newY2 / height; + *texArray++ = x2 / width; + *texArray++ = newY2 / height; + } + } + + for( x = 0; x < numQuads; x++) + { + idxArray[x*6+0] = x*4+0; + idxArray[x*6+1] = x*4+1; + idxArray[x*6+2] = x*4+2; + + idxArray[x*6+3] = x*4+1; + idxArray[x*6+4] = x*4+2; + idxArray[x*6+5] = x*4+3; + } + + memcpy(originalVertices, vertices, numQuads*12*sizeof(GLfloat)); +} + +-(void)setTile:(ccGridSize)pos coords:(ccQuad3)coords +{ + int idx = (gridSize_.y * pos.x + pos.y) * 4 * 3; + float *vertArray = (float*)vertices; + memcpy(&vertArray[idx], &coords, sizeof(ccQuad3)); +} + +-(ccQuad3)originalTile:(ccGridSize)pos +{ + int idx = (gridSize_.y * pos.x + pos.y) * 4 * 3; + float *vertArray = (float*)originalVertices; + + ccQuad3 ret; + memcpy(&ret, &vertArray[idx], sizeof(ccQuad3)); + + return ret; +} + +-(ccQuad3)tile:(ccGridSize)pos +{ + int idx = (gridSize_.y * pos.x + pos.y) * 4 * 3; + float *vertArray = (float*)vertices; + + ccQuad3 ret; + memcpy(&ret, &vertArray[idx], sizeof(ccQuad3)); + + return ret; +} + +-(void)reuse +{ + if ( reuseGrid_ > 0 ) + { + int numQuads = gridSize_.x * gridSize_.y; + + memcpy(originalVertices, vertices, numQuads*12*sizeof(GLfloat)); + reuseGrid_--; + } +} + +@end diff --git a/Classes/cocos2d/CCLabelAtlas.h b/Classes/cocos2d/CCLabelAtlas.h new file mode 100644 index 0000000..d30fb38 --- /dev/null +++ b/Classes/cocos2d/CCLabelAtlas.h @@ -0,0 +1,61 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + +#import "CCAtlasNode.h" +#import "CCTextureAtlas.h" + +/** CCLabelAtlas is a subclass of CCAtlasNode. + + It can be as a replacement of CCLabel since it is MUCH faster. + + CCLabelAtlas versus CCLabel: + - CCLabelAtlas is MUCH faster than CCLabel + - CCLabelAtlas "characters" have a fixed height and width + - CCLabelAtlas "characters" can be anything you want since they are taken from an image file + + A more flexible class is CCBitmapFontAtlas. It supports variable width characters and it also has a nice editor. + */ +@interface CCLabelAtlas : CCAtlasNode +{ + // string to render + NSString *string_; + + // the first char in the charmap + char mapStartChar; +} + + +/** creates the CCLabelAtlas with a string, a char map file(the atlas), the width and height of each element in points and the starting char of the atlas */ ++(id) labelWithString:(NSString*) string charMapFile: (NSString*) charmapfile itemWidth:(int)w itemHeight:(int)h startCharMap:(char)c; + +/** creates the CCLabelAtlas with a string, a char map file(the atlas), the width and height of each element in points and the starting char of the atlas. + @deprecated Will be removed in 1.0.1. Use "labelWithString:" instead + */ ++(id) labelAtlasWithString:(NSString*) string charMapFile: (NSString*) charmapfile itemWidth:(int)w itemHeight:(int)h startCharMap:(char)c DEPRECATED_ATTRIBUTE; + +/** initializes the CCLabelAtlas with a string, a char map file(the atlas), the width and height in points of each element and the starting char of the atlas */ +-(id) initWithString:(NSString*) string charMapFile: (NSString*) charmapfile itemWidth:(int)w itemHeight:(int)h startCharMap:(char)c; +@end diff --git a/Classes/cocos2d/CCLabelAtlas.m b/Classes/cocos2d/CCLabelAtlas.m new file mode 100644 index 0000000..98ba04e --- /dev/null +++ b/Classes/cocos2d/CCLabelAtlas.m @@ -0,0 +1,189 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + +#import "ccConfig.h" +#import "ccMacros.h" +#import "CCDrawingPrimitives.h" +#import "CCLabelAtlas.h" +#import "Support/CGPointExtension.h" + + + +@implementation CCLabelAtlas + +#pragma mark CCLabelAtlas - Creation & Init ++(id) labelWithString:(NSString*)string charMapFile:(NSString*)charmapfile itemWidth:(int)w itemHeight:(int)h startCharMap:(char)c +{ + return [[[self alloc] initWithString:string charMapFile:charmapfile itemWidth:w itemHeight:h startCharMap:c] autorelease]; +} + +// XXX DEPRECATED. Remove it in 1.0.1 ++(id) labelAtlasWithString:(NSString*) string charMapFile: (NSString*) charmapfile itemWidth:(int)w itemHeight:(int)h startCharMap:(char)c +{ + return [self labelWithString:string charMapFile:charmapfile itemWidth:w itemHeight:h startCharMap:c]; +} + + +-(id) initWithString:(NSString*) theString charMapFile: (NSString*) charmapfile itemWidth:(int)w itemHeight:(int)h startCharMap:(char)c +{ + + if ((self=[super initWithTileFile:charmapfile tileWidth:w tileHeight:h itemsToRender:[theString length] ]) ) { + + mapStartChar = c; + [self setString: theString]; + } + + return self; +} + +-(void) dealloc +{ + [string_ release]; + + [super dealloc]; +} + +#pragma mark CCLabelAtlas - Atlas generation + +-(void) updateAtlasValues +{ + int n = [string_ length]; + + ccV3F_C4B_T2F_Quad quad; + + const char *s = [string_ UTF8String]; + + CCTexture2D *texture = [textureAtlas_ texture]; + float textureWide = [texture pixelsWide]; + float textureHigh = [texture pixelsHigh]; + + for( NSUInteger i=0; i textureAtlas_.totalQuads ) + [textureAtlas_ resizeCapacity: newString.length]; + + [string_ release]; + string_ = [newString copy]; + [self updateAtlasValues]; + + CGSize s; + s.width = [string_ length] * itemWidth_; + s.height = itemHeight_; + [self setContentSizeInPixels:s]; +} + +-(NSString*) string +{ + return string_; +} + +#pragma mark CCLabelAtlas - draw + +// XXX: overriding draw from AtlasNode +- (void) draw +{ + // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY + // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY + // Unneeded states: GL_COLOR_ARRAY + glDisableClientState(GL_COLOR_ARRAY); + + glColor4ub( color_.r, color_.g, color_.b, opacity_); + + BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST; + if( newBlend ) + glBlendFunc( blendFunc_.src, blendFunc_.dst ); + + [textureAtlas_ drawNumberOfQuads: string_.length]; + + if( newBlend ) + glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST); + + // is this chepear than saving/restoring color state ? + // XXX: There is no need to restore the color to (255,255,255,255). Objects should use the color + // XXX: that they need +// glColor4ub( 255, 255, 255, 255); + + // Restore Default GL state. Enable GL_COLOR_ARRAY + glEnableClientState(GL_COLOR_ARRAY); + + +#if CC_LABELATLAS_DEBUG_DRAW + CGSize s = [self contentSize]; + CGPoint vertices[4]={ + ccp(0,0),ccp(s.width,0), + ccp(s.width,s.height),ccp(0,s.height), + }; + ccDrawPoly(vertices, 4, YES); +#endif // CC_LABELATLAS_DEBUG_DRAW + +} +@end diff --git a/Classes/cocos2d/CCLabelBMFont.h b/Classes/cocos2d/CCLabelBMFont.h new file mode 100644 index 0000000..38b32dc --- /dev/null +++ b/Classes/cocos2d/CCLabelBMFont.h @@ -0,0 +1,189 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + * Portions of this code are based and inspired on: + * http://www.71squared.co.uk/2009/04/iphone-game-programming-tutorial-4-bitmap-font-class + * by Michael Daley + + * Use any of these editors to generate bitmap font atlas: + * http://www.n4te.com/hiero/hiero.jnlp + * http://slick.cokeandcode.com/demos/hiero.jnlp + * http://www.angelcode.com/products/bmfont/ + * + */ + +#import "CCSpriteBatchNode.h" +#import "Support/uthash.h" + +struct _KerningHashElement; + +/** @struct ccBMFontDef + BMFont definition + */ +typedef struct _BMFontDef { + //! ID of the character + unsigned int charID; + //! origin and size of the font + CGRect rect; + //! The X amount the image should be offset when drawing the image (in pixels) + int xOffset; + //! The Y amount the image should be offset when drawing the image (in pixels) + int yOffset; + //! The amount to move the current position after drawing the character (in pixels) + int xAdvance; +} ccBMFontDef; + +/** @struct ccBMFontPadding + BMFont padding + @since v0.8.2 + */ +typedef struct _BMFontPadding { + /// padding left + int left; + /// padding top + int top; + /// padding right + int right; + /// padding bottom + int bottom; +} ccBMFontPadding; + +enum { + // how many characters are supported + kCCBMFontMaxChars = 2048, //256, +}; + +/** CCBMFontConfiguration has parsed configuration of the the .fnt file + @since v0.8 + */ +@interface CCBMFontConfiguration : NSObject +{ +// XXX: Creating a public interface so that the bitmapFontArray[] is accesible +@public + // The characters building up the font + ccBMFontDef BMFontArray_[kCCBMFontMaxChars]; + + // FNTConfig: Common Height + NSUInteger commonHeight_; + + // Padding + ccBMFontPadding padding_; + + // atlas name + NSString *atlasName_; + + // values for kerning + struct _KerningHashElement *kerningDictionary_; +} + +/** allocates a CCBMFontConfiguration with a FNT file */ ++(id) configurationWithFNTFile:(NSString*)FNTfile; +/** initializes a CCBMFontConfiguration with a FNT file */ +-(id) initWithFNTfile:(NSString*)FNTfile; +@end + + +/** CCLabelBMFont is a subclass of CCSpriteBatchNode + + Features: + - Treats each character like a CCSprite. This means that each individual character can be: + - rotated + - scaled + - translated + - tinted + - chage the opacity + - It can be used as part of a menu item. + - anchorPoint can be used to align the "label" + - Supports AngelCode text format + + Limitations: + - All inner characters are using an anchorPoint of (0.5f, 0.5f) and it is not recommend to change it + because it might affect the rendering + + CCLabelBMFont implements the protocol CCLabelProtocol, like CCLabel and CCLabelAtlas. + CCLabelBMFont has the flexibility of CCLabel, the speed of CCLabelAtlas and all the features of CCSprite. + If in doubt, use CCLabelBMFont instead of CCLabelAtlas / CCLabel. + + Supported editors: + - http://www.n4te.com/hiero/hiero.jnlp + - http://slick.cokeandcode.com/demos/hiero.jnlp + - http://www.angelcode.com/products/bmfont/ + + @since v0.8 + */ + +@interface CCLabelBMFont : CCSpriteBatchNode +{ + // string to render + NSString *string_; + + CCBMFontConfiguration *configuration_; + + // texture RGBA + GLubyte opacity_; + ccColor3B color_; + BOOL opacityModifyRGB_; +} + +/** Purges the cached data. + Removes from memory the cached configurations and the atlas name dictionary. + @since v0.99.3 + */ ++(void) purgeCachedData; + +/** conforms to CCRGBAProtocol protocol */ +@property (nonatomic,readwrite) GLubyte opacity; +/** conforms to CCRGBAProtocol protocol */ +@property (nonatomic,readwrite) ccColor3B color; + + +/** creates a BMFont label with an initial string and the FNT file */ ++(id) labelWithString:(NSString*)string fntFile:(NSString*)fntFile; + +/** creates a BMFont label with an initial string and the FNT file + @deprecated Will be removed in 1.0.1. Use "labelWithString" instead. + */ ++(id) bitmapFontAtlasWithString:(NSString*)string fntFile:(NSString*)fntFile DEPRECATED_ATTRIBUTE; + +/** init a BMFont label with an initial string and the FNT file */ +-(id) initWithString:(NSString*)string fntFile:(NSString*)fntFile; + +/** updates the font chars based on the string to render */ +-(void) createFontChars; +@end + +/** Free function that parses a FNT file a place it on the cache +*/ +CCBMFontConfiguration * FNTConfigLoadFile( NSString *file ); +/** Purges the FNT config cache + */ +void FNTConfigRemoveCache( void ); + + + +/** CCBitmapFontAtlas + @deprecated Use CCLabelBMFont instead. Will be removed 1.0.1 + */ +DEPRECATED_ATTRIBUTE @interface CCBitmapFontAtlas : CCLabelBMFont +@end + diff --git a/Classes/cocos2d/CCLabelBMFont.m b/Classes/cocos2d/CCLabelBMFont.m new file mode 100644 index 0000000..67e168e --- /dev/null +++ b/Classes/cocos2d/CCLabelBMFont.m @@ -0,0 +1,669 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + * Portions of this code are based and inspired on: + * http://www.71squared.co.uk/2009/04/iphone-game-programming-tutorial-4-bitmap-font-class + * by Michael Daley + * + * + * Use any of these editors to generate bitmap font atlas: + * http://www.n4te.com/hiero/hiero.jnlp + * http://slick.cokeandcode.com/demos/hiero.jnlp + * http://www.angelcode.com/products/bmfont/ + */ + +#import "ccConfig.h" +#import "CCLabelBMFont.h" +#import "CCSprite.h" +#import "CCDrawingPrimitives.h" +#import "CCConfiguration.h" +#import "Support/CCFileUtils.h" +#import "Support/CGPointExtension.h" +#import "Support/uthash.h" + +#pragma mark - +#pragma mark FNTConfig Cache - free functions + +NSMutableDictionary *configurations = nil; +CCBMFontConfiguration* FNTConfigLoadFile( NSString *fntFile) +{ + CCBMFontConfiguration *ret = nil; + + if( configurations == nil ) + configurations = [[NSMutableDictionary dictionaryWithCapacity:3] retain]; + + ret = [configurations objectForKey:fntFile]; + if( ret == nil ) { + ret = [CCBMFontConfiguration configurationWithFNTFile:fntFile]; + [configurations setObject:ret forKey:fntFile]; + } + + return ret; +} + +void FNTConfigRemoveCache( void ) +{ + [configurations removeAllObjects]; +} + +#pragma mark - Hash Element + +// Equal function for targetSet. +typedef struct _KerningHashElement +{ + int key; // key for the hash. 16-bit for 1st element, 16-bit for 2nd element + int amount; + UT_hash_handle hh; +} tKerningHashElement; + +#pragma mark - +#pragma mark BitmapFontConfiguration + + +@interface CCBMFontConfiguration (Private) +-(void) parseConfigFile:(NSString*)controlFile; +-(void) parseCharacterDefinition:(NSString*)line charDef:(ccBMFontDef*)characterDefinition; +-(void) parseInfoArguments:(NSString*)line; +-(void) parseCommonArguments:(NSString*)line; +-(void) parseImageFileName:(NSString*)line fntFile:(NSString*)fntFile; +-(void) parseKerningCapacity:(NSString*)line; +-(void) parseKerningEntry:(NSString*)line; +-(void) purgeKerningDictionary; +@end + +@implementation CCBMFontConfiguration + ++(id) configurationWithFNTFile:(NSString*)FNTfile +{ + return [[[self alloc] initWithFNTfile:FNTfile] autorelease]; +} + +-(id) initWithFNTfile:(NSString*)fntFile +{ + if((self=[super init])) { + + kerningDictionary_ = NULL; + + [self parseConfigFile:fntFile]; + } + return self; +} + +- (void) dealloc +{ + CCLOGINFO( @"cocos2d: deallocing %@", self); + [self purgeKerningDictionary]; + [atlasName_ release]; + [super dealloc]; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %08X | Kernings:%d | Image = %@>", [self class], self, + HASH_COUNT(kerningDictionary_), + atlasName_]; +} + + +-(void) purgeKerningDictionary +{ + tKerningHashElement *current; + + while(kerningDictionary_) { + current = kerningDictionary_; + HASH_DEL(kerningDictionary_,current); + free(current); + } +} + +- (void)parseConfigFile:(NSString*)fntFile +{ + NSString *fullpath = [CCFileUtils fullPathFromRelativePath:fntFile]; + NSString *contents = [NSString stringWithContentsOfFile:fullpath encoding:NSUTF8StringEncoding error:nil]; + + + // Move all lines in the string, which are denoted by \n, into an array + NSArray *lines = [[NSArray alloc] initWithArray:[contents componentsSeparatedByString:@"\n"]]; + + // Create an enumerator which we can use to move through the lines read from the control file + NSEnumerator *nse = [lines objectEnumerator]; + + // Create a holder for each line we are going to work with + NSString *line; + + // Loop through all the lines in the lines array processing each one + while( (line = [nse nextObject]) ) { + // parse spacing / padding + if([line hasPrefix:@"info face"]) { + // XXX: info parsing is incomplete + // Not needed for the Hiero editors, but needed for the AngelCode editor +// [self parseInfoArguments:line]; + } + // Check to see if the start of the line is something we are interested in + else if([line hasPrefix:@"common lineHeight"]) { + [self parseCommonArguments:line]; + } + else if([line hasPrefix:@"page id"]) { + [self parseImageFileName:line fntFile:fntFile]; + } + else if([line hasPrefix:@"chars c"]) { + // Ignore this line + } + else if([line hasPrefix:@"char"]) { + // Parse the current line and create a new CharDef + ccBMFontDef characterDefinition; + [self parseCharacterDefinition:line charDef:&characterDefinition]; + + // Add the CharDef returned to the charArray + BMFontArray_[ characterDefinition.charID ] = characterDefinition; + } + else if([line hasPrefix:@"kernings count"]) { + [self parseKerningCapacity:line]; + } + else if([line hasPrefix:@"kerning first"]) { + [self parseKerningEntry:line]; + } + } + // Finished with lines so release it + [lines release]; +} + +-(void) parseImageFileName:(NSString*)line fntFile:(NSString*)fntFile +{ + NSString *propertyValue = nil; + + // Break the values for this line up using = + NSArray *values = [line componentsSeparatedByString:@"="]; + + // Get the enumerator for the array of components which has been created + NSEnumerator *nse = [values objectEnumerator]; + + // We need to move past the first entry in the array before we start assigning values + [nse nextObject]; + + // page ID. Sanity check + propertyValue = [nse nextObject]; + NSAssert( [propertyValue intValue] == 0, @"XXX: BitmapFontAtlas only supports 1 page"); + + // file + propertyValue = [nse nextObject]; + NSArray *array = [propertyValue componentsSeparatedByString:@"\""]; + propertyValue = [array objectAtIndex:1]; + NSAssert(propertyValue,@"BitmapFontAtlas file could not be found"); + + // Supports subdirectories + NSString *dir = [fntFile stringByDeletingLastPathComponent]; + atlasName_ = [dir stringByAppendingPathComponent:propertyValue]; + + [atlasName_ retain]; +} + +-(void) parseInfoArguments:(NSString*)line +{ + // + // possible lines to parse: + // info face="Script" size=32 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=1,4,3,2 spacing=0,0 outline=0 + // info face="Cracked" size=36 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 + // + NSArray *values = [line componentsSeparatedByString:@"="]; + NSEnumerator *nse = [values objectEnumerator]; + NSString *propertyValue = nil; + + // We need to move past the first entry in the array before we start assigning values + [nse nextObject]; + + // face (ignore) + [nse nextObject]; + + // size (ignore) + [nse nextObject]; + + // bold (ignore) + [nse nextObject]; + + // italic (ignore) + [nse nextObject]; + + // charset (ignore) + [nse nextObject]; + + // unicode (ignore) + [nse nextObject]; + + // strechH (ignore) + [nse nextObject]; + + // smooth (ignore) + [nse nextObject]; + + // aa (ignore) + [nse nextObject]; + + // padding (ignore) + propertyValue = [nse nextObject]; + { + + NSArray *paddingValues = [propertyValue componentsSeparatedByString:@","]; + NSEnumerator *paddingEnum = [paddingValues objectEnumerator]; + // padding top + propertyValue = [paddingEnum nextObject]; + padding_.top = [propertyValue intValue]; + + // padding right + propertyValue = [paddingEnum nextObject]; + padding_.right = [propertyValue intValue]; + + // padding bottom + propertyValue = [paddingEnum nextObject]; + padding_.bottom = [propertyValue intValue]; + + // padding left + propertyValue = [paddingEnum nextObject]; + padding_.left = [propertyValue intValue]; + + CCLOG(@"cocos2d: padding: %d,%d,%d,%d", padding_.left, padding_.top, padding_.right, padding_.bottom); + } + + // spacing (ignore) + [nse nextObject]; +} + +-(void) parseCommonArguments:(NSString*)line +{ + // + // line to parse: + // common lineHeight=104 base=26 scaleW=1024 scaleH=512 pages=1 packed=0 + // + NSArray *values = [line componentsSeparatedByString:@"="]; + NSEnumerator *nse = [values objectEnumerator]; + NSString *propertyValue = nil; + + // We need to move past the first entry in the array before we start assigning values + [nse nextObject]; + + // Character ID + propertyValue = [nse nextObject]; + commonHeight_ = [propertyValue intValue]; + + // base (ignore) + [nse nextObject]; + + + // scaleW. sanity check + propertyValue = [nse nextObject]; + NSAssert( [propertyValue intValue] <= [[CCConfiguration sharedConfiguration] maxTextureSize], @"CCLabelBMFont: page can't be larger than supported"); + + // scaleH. sanity check + propertyValue = [nse nextObject]; + NSAssert( [propertyValue intValue] <= [[CCConfiguration sharedConfiguration] maxTextureSize], @"CCLabelBMFont: page can't be larger than supported"); + + // pages. sanity check + propertyValue = [nse nextObject]; + NSAssert( [propertyValue intValue] == 1, @"CCBitfontAtlas: only supports 1 page"); + + // packed (ignore) What does this mean ?? +} +- (void)parseCharacterDefinition:(NSString*)line charDef:(ccBMFontDef*)characterDefinition +{ + // Break the values for this line up using = + NSArray *values = [line componentsSeparatedByString:@"="]; + NSEnumerator *nse = [values objectEnumerator]; + NSString *propertyValue; + + // We need to move past the first entry in the array before we start assigning values + [nse nextObject]; + + // Character ID + propertyValue = [nse nextObject]; + propertyValue = [propertyValue substringToIndex: [propertyValue rangeOfString: @" "].location]; + characterDefinition->charID = [propertyValue intValue]; + NSAssert(characterDefinition->charID < kCCBMFontMaxChars, @"BitmpaFontAtlas: CharID bigger than supported"); + + // Character x + propertyValue = [nse nextObject]; + characterDefinition->rect.origin.x = [propertyValue intValue]; + // Character y + propertyValue = [nse nextObject]; + characterDefinition->rect.origin.y = [propertyValue intValue]; + // Character width + propertyValue = [nse nextObject]; + characterDefinition->rect.size.width = [propertyValue intValue]; + // Character height + propertyValue = [nse nextObject]; + characterDefinition->rect.size.height = [propertyValue intValue]; + // Character xoffset + propertyValue = [nse nextObject]; + characterDefinition->xOffset = [propertyValue intValue]; + // Character yoffset + propertyValue = [nse nextObject]; + characterDefinition->yOffset = [propertyValue intValue]; + // Character xadvance + propertyValue = [nse nextObject]; + characterDefinition->xAdvance = [propertyValue intValue]; +} + +-(void) parseKerningCapacity:(NSString*) line +{ + // When using uthash there is not need to parse the capacity. + +// NSAssert(!kerningDictionary, @"dictionary already initialized"); +// +// // Break the values for this line up using = +// NSArray *values = [line componentsSeparatedByString:@"="]; +// NSEnumerator *nse = [values objectEnumerator]; +// NSString *propertyValue; +// +// // We need to move past the first entry in the array before we start assigning values +// [nse nextObject]; +// +// // count +// propertyValue = [nse nextObject]; +// int capacity = [propertyValue intValue]; +// +// if( capacity != -1 ) +// kerningDictionary = ccHashSetNew(capacity, targetSetEql); +} + +-(void) parseKerningEntry:(NSString*) line +{ + NSArray *values = [line componentsSeparatedByString:@"="]; + NSEnumerator *nse = [values objectEnumerator]; + NSString *propertyValue; + + // We need to move past the first entry in the array before we start assigning values + [nse nextObject]; + + // first + propertyValue = [nse nextObject]; + int first = [propertyValue intValue]; + + // second + propertyValue = [nse nextObject]; + int second = [propertyValue intValue]; + + // second + propertyValue = [nse nextObject]; + int amount = [propertyValue intValue]; + + tKerningHashElement *element = calloc( sizeof( *element ), 1 ); + element->amount = amount; + element->key = (first<<16) | (second&0xffff); + HASH_ADD_INT(kerningDictionary_,key, element); +} + +@end + +#pragma mark - +#pragma mark CCLabelBMFont + +@interface CCLabelBMFont (Private) +-(NSString*) atlasNameFromFntFile:(NSString*)fntFile; + +-(int) kerningAmountForFirst:(unichar)first second:(unichar)second; + +@end + +@implementation CCLabelBMFont + +@synthesize opacity = opacity_, color = color_; + +#pragma mark BitmapFontAtlas - Purge Cache ++(void) purgeCachedData +{ + FNTConfigRemoveCache(); +} + +#pragma mark BitmapFontAtlas - Creation & Init + ++(id) labelWithString:(NSString *)string fntFile:(NSString *)fntFile +{ + return [[[self alloc] initWithString:string fntFile:fntFile] autorelease]; +} + +// XXX - deprecated - Will be removed in 1.0.1 ++(id) bitmapFontAtlasWithString:(NSString*)string fntFile:(NSString*)fntFile +{ + return [self labelWithString:string fntFile:fntFile]; +} + +-(id) initWithString:(NSString*)theString fntFile:(NSString*)fntFile +{ + + [configuration_ release]; // allow re-init + + configuration_ = FNTConfigLoadFile(fntFile); + [configuration_ retain]; + + NSAssert( configuration_, @"Error creating config for BitmapFontAtlas"); + + + if ((self=[super initWithFile:configuration_->atlasName_ capacity:[theString length]])) { + + opacity_ = 255; + color_ = ccWHITE; + + contentSize_ = CGSizeZero; + + opacityModifyRGB_ = [[textureAtlas_ texture] hasPremultipliedAlpha]; + + anchorPoint_ = ccp(0.5f, 0.5f); + + [self setString:theString]; + } + + return self; +} + +-(void) dealloc +{ + [string_ release]; + [configuration_ release]; + [super dealloc]; +} + +#pragma mark BitmapFontAtlas - Atlas generation + +-(int) kerningAmountForFirst:(unichar)first second:(unichar)second +{ + int ret = 0; + unsigned int key = (first<<16) | (second & 0xffff); + + if( configuration_->kerningDictionary_ ) { + tKerningHashElement *element = NULL; + HASH_FIND_INT(configuration_->kerningDictionary_, &key, element); + if(element) + ret = element->amount; + } + + return ret; +} + +-(void) createFontChars +{ + int nextFontPositionX = 0; + int nextFontPositionY = 0; + unichar prev = -1; + int kerningAmount = 0; + + CGSize tmpSize = CGSizeZero; + + int longestLine = 0; + int totalHeight = 0; + + int quantityOfLines = 1; + + NSUInteger stringLen = [string_ length]; + if( ! stringLen ) + return; + + // quantity of lines NEEDS to be calculated before parsing the lines, + // since the Y position needs to be calcualted before hand + for(NSUInteger i=0; i < stringLen-1;i++) { + unichar c = [string_ characterAtIndex:i]; + if( c=='\n') + quantityOfLines++; + } + + totalHeight = configuration_->commonHeight_ * quantityOfLines; + nextFontPositionY = -(configuration_->commonHeight_ - configuration_->commonHeight_*quantityOfLines); + + for(NSUInteger i=0; icommonHeight_; + continue; + } + + kerningAmount = [self kerningAmountForFirst:prev second:c]; + + ccBMFontDef fontDef = configuration_->BMFontArray_[c]; + + CGRect rect = fontDef.rect; + + CCSprite *fontChar; + + fontChar = (CCSprite*) [self getChildByTag:i]; + if( ! fontChar ) { + fontChar = [[CCSprite alloc] initWithBatchNode:self rectInPixels:rect]; + [self addChild:fontChar z:0 tag:i]; + [fontChar release]; + } + else { + // reusing fonts + [fontChar setTextureRectInPixels:rect rotated:NO untrimmedSize:rect.size]; + + // restore to default in case they were modified + fontChar.visible = YES; + fontChar.opacity = 255; + } + + float yOffset = configuration_->commonHeight_ - fontDef.yOffset; + fontChar.positionInPixels = ccp( (float)nextFontPositionX + fontDef.xOffset + fontDef.rect.size.width*0.5f + kerningAmount, + (float)nextFontPositionY + yOffset - rect.size.height*0.5f ); + + // update kerning + nextFontPositionX += configuration_->BMFontArray_[c].xAdvance + kerningAmount; + prev = c; + + // Apply label properties + [fontChar setOpacityModifyRGB:opacityModifyRGB_]; + // Color MUST be set before opacity, since opacity might change color if OpacityModifyRGB is on + [fontChar setColor:color_]; + + // only apply opacity if it is different than 255 ) + // to prevent modifying the color too (issue #610) + if( opacity_ != 255 ) + [fontChar setOpacity: opacity_]; + + if (longestLine < nextFontPositionX) + longestLine = nextFontPositionX; + } + + tmpSize.width = longestLine; + tmpSize.height = totalHeight; + + [self setContentSizeInPixels:tmpSize]; +} + +#pragma mark BitmapFontAtlas - CCLabelProtocol protocol +- (void) setString:(NSString*) newString +{ + [string_ release]; + string_ = [newString copy]; + + CCNode *child; + CCARRAY_FOREACH(children_, child) + child.visible = NO; + + [self createFontChars]; +} + +-(NSString*) string +{ + return string_; +} + +-(void) setCString:(char*)label +{ + [self setString:[NSString stringWithUTF8String:label]]; +} + +#pragma mark BitmapFontAtlas - CCRGBAProtocol protocol + +-(void) setColor:(ccColor3B)color +{ + color_ = color; + + CCSprite *child; + CCARRAY_FOREACH(children_, child) + [child setColor:color_]; +} + +-(void) setOpacity:(GLubyte)opacity +{ + opacity_ = opacity; + + id child; + CCARRAY_FOREACH(children_, child) + [child setOpacity:opacity_]; +} +-(void) setOpacityModifyRGB:(BOOL)modify +{ + opacityModifyRGB_ = modify; + + id child; + CCARRAY_FOREACH(children_, child) + [child setOpacityModifyRGB:modify]; +} + +-(BOOL) doesOpacityModifyRGB +{ + return opacityModifyRGB_; +} + +#pragma mark BitmapFontAtlas - AnchorPoint +-(void) setAnchorPoint:(CGPoint)point +{ + if( ! CGPointEqualToPoint(point, anchorPoint_) ) { + [super setAnchorPoint:point]; + [self createFontChars]; + } +} + +#pragma mark BitmapFontAtlas - Debug draw +#if CC_BITMAPFONTATLAS_DEBUG_DRAW +-(void) draw +{ + [super draw]; + CGSize s = [self contentSize]; + CGPoint vertices[4]={ + ccp(0,0),ccp(s.width,0), + ccp(s.width,s.height),ccp(0,s.height), + }; + ccDrawPoly(vertices, 4, YES); +} +#endif // CC_BITMAPFONTATLAS_DEBUG_DRAW +@end diff --git a/Classes/cocos2d/CCLabelTTF.h b/Classes/cocos2d/CCLabelTTF.h new file mode 100644 index 0000000..66cdda7 --- /dev/null +++ b/Classes/cocos2d/CCLabelTTF.h @@ -0,0 +1,62 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + +#import "CCTexture2D.h" +#import "CCSprite.h" +#import "Platforms/CCNS.h" + + +/** CCLabel is a subclass of CCTextureNode that knows how to render text labels + * + * All features from CCTextureNode are valid in CCLabel + * + * CCLabel objects are slow. Consider using CCLabelAtlas or CCBitmapFontAtlas instead. + */ + +@interface CCLabelTTF : CCSprite +{ + CGSize dimensions_; + CCTextAlignment alignment_; + NSString * fontName_; + CGFloat fontSize_; + NSString *string_; +} + +/** creates a CCLabel from a fontname, alignment, dimension in points and font size in points*/ ++ (id) labelWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size; +/** creates a CCLabel from a fontname and font size in points*/ ++ (id) labelWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size; +/** initializes the CCLabel with a font name, alignment, dimension in points and font size in points */ +- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size; +/** initializes the CCLabel with a font name and font size in points */ +- (id) initWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size; + +/** changes the string to render + * @warning Changing the string is as expensive as creating a new CCLabel. To obtain better performance use CCLabelAtlas + */ +- (void) setString:(NSString*)str; + +@end diff --git a/Classes/cocos2d/CCLabelTTF.m b/Classes/cocos2d/CCLabelTTF.m new file mode 100644 index 0000000..5760a20 --- /dev/null +++ b/Classes/cocos2d/CCLabelTTF.m @@ -0,0 +1,125 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + +#import + +#import "CCLabelTTF.h" +#import "Support/CGPointExtension.h" +#import "ccMacros.h" + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +#import "Platforms/iOS/CCDirectorIOS.h" +#endif + +@implementation CCLabelTTF + +- (id) init +{ + NSAssert(NO, @"CCLabelTTF: Init not supported. Use initWithString"); + [self release]; + return nil; +} + ++ (id) labelWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size +{ + return [[[self alloc] initWithString: string dimensions:dimensions alignment:alignment fontName:name fontSize:size]autorelease]; +} + ++ (id) labelWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size +{ + return [[[self alloc] initWithString: string fontName:name fontSize:size]autorelease]; +} + + +- (id) initWithString:(NSString*)str dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size +{ + if( (self=[super init]) ) { + + dimensions_ = CGSizeMake( dimensions.width * CC_CONTENT_SCALE_FACTOR(), dimensions.height * CC_CONTENT_SCALE_FACTOR() ); + alignment_ = alignment; + fontName_ = [name retain]; + fontSize_ = size * CC_CONTENT_SCALE_FACTOR(); + + [self setString:str]; + } + return self; +} + +- (id) initWithString:(NSString*)str fontName:(NSString*)name fontSize:(CGFloat)size +{ + if( (self=[super init]) ) { + + dimensions_ = CGSizeZero; + fontName_ = [name retain]; + fontSize_ = size * CC_CONTENT_SCALE_FACTOR(); + + [self setString:str]; + } + return self; +} + +- (void) setString:(NSString*)str +{ + [string_ release]; + string_ = [str copy]; + + CCTexture2D *tex; + if( CGSizeEqualToSize( dimensions_, CGSizeZero ) ) + tex = [[CCTexture2D alloc] initWithString:str + fontName:fontName_ + fontSize:fontSize_]; + else + tex = [[CCTexture2D alloc] initWithString:str + dimensions:dimensions_ + alignment:alignment_ + fontName:fontName_ + fontSize:fontSize_]; + + [self setTexture:tex]; + [tex release]; + + CGRect rect = CGRectZero; + rect.size = [texture_ contentSize]; + [self setTextureRect: rect]; +} + +-(NSString*) string +{ + return string_; +} + +- (void) dealloc +{ + [string_ release]; + [fontName_ release]; + [super dealloc]; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %08X | FontName = %@, FontSize = %.1f>", [self class], self, fontName_, fontSize_]; +} +@end diff --git a/Classes/cocos2d/CCLayer.h b/Classes/cocos2d/CCLayer.h new file mode 100644 index 0000000..9c02f37 --- /dev/null +++ b/Classes/cocos2d/CCLayer.h @@ -0,0 +1,261 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + + +#import +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +#import // Needed for UIAccelerometerDelegate +#import "Platforms/iOS/CCTouchDelegateProtocol.h" // Touches only supported on iOS +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) +#import "Platforms/Mac/CCEventDispatcher.h" +#endif + +#import "CCProtocols.h" +#import "CCNode.h" + +// +// CCLayer +// +/** CCLayer is a subclass of CCNode that implements the TouchEventsDelegate protocol. + + All features from CCNode are valid, plus the following new features: + - It can receive iPhone Touches + - It can receive Accelerometer input +*/ +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +@interface CCLayer : CCNode +{ + BOOL isTouchEnabled_; + BOOL isAccelerometerEnabled_; +} +/** If isTouchEnabled, this method is called onEnter. Override it to change the + way CCLayer receives touch events. + ( Default: [[TouchDispatcher sharedDispatcher] addStandardDelegate:self priority:0] ) + Example: + -(void) registerWithTouchDispatcher + { + [[TouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:INT_MIN+1 swallowsTouches:YES]; + } + + Valid only on iOS. Not valid on Mac. + + @since v0.8.0 + */ +-(void) registerWithTouchDispatcher; + +/** whether or not it will receive Touch events. + You can enable / disable touch events with this property. + Only the touches of this node will be affected. This "method" is not propagated to it's children. + + Valid only on iOS. Not valid on Mac. + + @since v0.8.1 + */ +@property(nonatomic,assign) BOOL isTouchEnabled; +/** whether or not it will receive Accelerometer events + You can enable / disable accelerometer events with this property. + + Valid only on iOS. Not valid on Mac. + + @since v0.8.1 + */ +@property(nonatomic,assign) BOOL isAccelerometerEnabled; + +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + + +@interface CCLayer : CCNode +{ + BOOL isMouseEnabled_; + BOOL isKeyboardEnabled_; +} + +/** whether or not it will receive mouse events. + + Valind only Mac. Not valid on iOS + */ +@property (nonatomic, readwrite) BOOL isMouseEnabled; + +/** whether or not it will receive keyboard events. + + Valind only Mac. Not valid on iOS + */ +@property (nonatomic, readwrite) BOOL isKeyboardEnabled; + +/** priority of the mouse event delegate. + Default 0. + Override this method to set another priority. + + Valind only Mac. Not valid on iOS + */ +-(NSInteger) mouseDelegatePriority; + +/** priority of the keyboard event delegate. + Default 0. + Override this method to set another priority. + + Valind only Mac. Not valid on iOS + */ +-(NSInteger) keyboardDelegatePriority; + +#endif // mac + + +@end + +// +// CCLayerColor +// +/** CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol. + + All features from CCLayer are valid, plus the following new features: + - opacity + - RGB colors + */ +@interface CCLayerColor : CCLayer +{ + GLubyte opacity_; + ccColor3B color_; + GLfloat squareVertices[4 * 2]; + GLubyte squareColors[4 * 4]; + + ccBlendFunc blendFunc_; +} + +/** creates a CCLayer with color, width and height in Points*/ ++ (id) layerWithColor: (ccColor4B)color width:(GLfloat)w height:(GLfloat)h; +/** creates a CCLayer with color. Width and height are the window size. */ ++ (id) layerWithColor: (ccColor4B)color; + +/** initializes a CCLayer with color, width and height in Points */ +- (id) initWithColor:(ccColor4B)color width:(GLfloat)w height:(GLfloat)h; +/** initializes a CCLayer with color. Width and height are the window size. */ +- (id) initWithColor:(ccColor4B)color; + +/** change width in Points */ +-(void) changeWidth: (GLfloat)w; +/** change height in Points */ +-(void) changeHeight: (GLfloat)h; +/** change width and height in Points + @since v0.8 + */ +-(void) changeWidth:(GLfloat)w height:(GLfloat)h; + +/** Opacity: conforms to CCRGBAProtocol protocol */ +@property (nonatomic,readonly) GLubyte opacity; +/** Opacity: conforms to CCRGBAProtocol protocol */ +@property (nonatomic,readonly) ccColor3B color; +/** BlendFunction. Conforms to CCBlendProtocol protocol */ +@property (nonatomic,readwrite) ccBlendFunc blendFunc; +@end + +/** CCColorLayer + It is the same as CCLayerColor. + + @deprecated Use CCLayerColor instead. This class will be removed in v1.0.1 + */ +DEPRECATED_ATTRIBUTE @interface CCColorLayer : CCLayerColor +@end + + +// +// CCLayerGradient +// +/** CCLayerGradient is a subclass of CCLayerColor that draws gradients across +the background. + + All features from CCLayerColor are valid, plus the following new features: + - direction + - final color + + Color is interpolated between the startColor and endColor along the given + vector (starting at the origin, ending at the terminus). If no vector is + supplied, it defaults to (0, -1) -- a fade from top to bottom. + + Given the nature of + the interpolation, you will not see either the start or end color for + non-cardinal vectors; a smooth gradient implying both end points will be still + be drawn, however. + + @since v0.99.5 + */ +@interface CCLayerGradient : CCLayerColor +{ + ccColor3B endColor_; + GLubyte startOpacity_; + GLubyte endOpacity_; + CGPoint vector_; +} + +/** Creates a full-screen CCLayer with a gradient between start and end. */ ++ (id) layerWithColor: (ccColor4B) start fadingTo: (ccColor4B) end; +/** Creates a full-screen CCLayer with a gradient between start and end in the direction of v. */ ++ (id) layerWithColor: (ccColor4B) start fadingTo: (ccColor4B) end alongVector: (CGPoint) v; + +/** Initializes the CCLayer with a gradient between start and end. */ +- (id) initWithColor: (ccColor4B) start fadingTo: (ccColor4B) end; +/** Initializes the CCLayer with a gradient between start and end in the direction of v. */ +- (id) initWithColor: (ccColor4B) start fadingTo: (ccColor4B) end alongVector: (CGPoint) v; + +/** The starting color. */ +- (ccColor3B) startColor; +- (void) setStartColor:(ccColor3B)colors; + +/** The ending color. */ +@property (nonatomic, readwrite) ccColor3B endColor; +/** The starting opacity. */ +@property (nonatomic, readwrite) GLubyte startOpacity; +/** The ending color. */ +@property (nonatomic, readwrite) GLubyte endOpacity; +/** The vector along which to fade color. */ +@property (nonatomic, readwrite) CGPoint vector; + +@end + +/** CCMultipleLayer is a CCLayer with the ability to multiplex it's children. + Features: + - It supports one or more children + - Only one children will be active a time + */ +@interface CCMultiplexLayer : CCLayer +{ + unsigned int enabledLayer; + NSMutableArray *layers; +} + +/** creates a CCMultiplexLayer with one or more layers using a variable argument list. */ ++(id) layerWithLayers: (CCLayer*) layer, ... NS_REQUIRES_NIL_TERMINATION; +/** initializes a MultiplexLayer with one or more layers using a variable argument list. */ +-(id) initWithLayers: (CCLayer*) layer vaList:(va_list) params; +/** switches to a certain layer indexed by n. + The current (old) layer will be removed from it's parent with 'cleanup:YES'. + */ +-(void) switchTo: (unsigned int) n; +/** release the current layer and switches to another layer indexed by n. + The current (old) layer will be removed from it's parent with 'cleanup:YES'. + */ +-(void) switchToAndReleaseMe: (unsigned int) n; +@end diff --git a/Classes/cocos2d/CCLayer.m b/Classes/cocos2d/CCLayer.m new file mode 100644 index 0000000..6604bb8 --- /dev/null +++ b/Classes/cocos2d/CCLayer.m @@ -0,0 +1,562 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + +#import + +#import "Platforms/CCGL.h" + +#import "CCLayer.h" +#import "CCDirector.h" +#import "ccMacros.h" +#import "Support/CGPointExtension.h" + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +#import "Platforms/iOS/CCTouchDispatcher.h" +#import "Platforms/iOS/CCDirectorIOS.h" +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) +#import "Platforms/Mac/CCEventDispatcher.h" +#endif + +#pragma mark - +#pragma mark Layer + +@implementation CCLayer + +#pragma mark Layer - Init +-(id) init +{ + if( (self=[super init]) ) { + + CGSize s = [[CCDirector sharedDirector] winSize]; + anchorPoint_ = ccp(0.5f, 0.5f); + [self setContentSize:s]; + self.isRelativeAnchorPoint = NO; + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + isTouchEnabled_ = NO; + isAccelerometerEnabled_ = NO; +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + isMouseEnabled_ = NO; + isKeyboardEnabled_ = NO; +#endif + } + + return self; +} + +#pragma mark Layer - Touch and Accelerometer related + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +-(void) registerWithTouchDispatcher +{ + [[CCTouchDispatcher sharedDispatcher] addStandardDelegate:self priority:0]; +} + +-(BOOL) isAccelerometerEnabled +{ + return isAccelerometerEnabled_; +} + +-(void) setIsAccelerometerEnabled:(BOOL)enabled +{ + if( enabled != isAccelerometerEnabled_ ) { + isAccelerometerEnabled_ = enabled; + if( isRunning_ ) { + if( enabled ) + [[UIAccelerometer sharedAccelerometer] setDelegate:self]; + else + [[UIAccelerometer sharedAccelerometer] setDelegate:nil]; + } + } +} + +-(BOOL) isTouchEnabled +{ + return isTouchEnabled_; +} + +-(void) setIsTouchEnabled:(BOOL)enabled +{ + if( isTouchEnabled_ != enabled ) { + isTouchEnabled_ = enabled; + if( isRunning_ ) { + if( enabled ) + [self registerWithTouchDispatcher]; + else + [[CCTouchDispatcher sharedDispatcher] removeDelegate:self]; + } + } +} + +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + +#pragma mark CCLayer - Mouse & Keyboard events + +-(NSInteger) mouseDelegatePriority +{ + return 0; +} + +-(BOOL) isMouseEnabled +{ + return isMouseEnabled_; +} + +-(void) setIsMouseEnabled:(BOOL)enabled +{ + if( isMouseEnabled_ != enabled ) { + isMouseEnabled_ = enabled; + + if( isRunning_ ) { + if( enabled ) + [[CCEventDispatcher sharedDispatcher] addMouseDelegate:self priority:[self mouseDelegatePriority]]; + else + [[CCEventDispatcher sharedDispatcher] removeMouseDelegate:self]; + } + } +} + +-(NSInteger) keyboardDelegatePriority +{ + return 0; +} + +-(BOOL) isKeyboardEnabled +{ + return isKeyboardEnabled_; +} + +-(void) setIsKeyboardEnabled:(BOOL)enabled +{ + if( isKeyboardEnabled_ != enabled ) { + isKeyboardEnabled_ = enabled; + + if( isRunning_ ) { + if( enabled ) + [[CCEventDispatcher sharedDispatcher] addKeyboardDelegate:self priority:[self keyboardDelegatePriority] ]; + else + [[CCEventDispatcher sharedDispatcher] removeKeyboardDelegate:self]; + } + } +} + + +#endif // Mac + + +#pragma mark Layer - Callbacks +-(void) onEnter +{ +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + // register 'parent' nodes first + // since events are propagated in reverse order + if (isTouchEnabled_) + [self registerWithTouchDispatcher]; + +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + if( isMouseEnabled_ ) + [[CCEventDispatcher sharedDispatcher] addMouseDelegate:self priority:[self mouseDelegatePriority]]; + + if( isKeyboardEnabled_) + [[CCEventDispatcher sharedDispatcher] addKeyboardDelegate:self priority:[self keyboardDelegatePriority]]; +#endif + + // then iterate over all the children + [super onEnter]; +} + +// issue #624. +// Can't register mouse, touches here because of #issue #1018, and #1021 +-(void) onEnterTransitionDidFinish +{ +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + if( isAccelerometerEnabled_ ) + [[UIAccelerometer sharedAccelerometer] setDelegate:self]; +#endif + + [super onEnterTransitionDidFinish]; +} + + +-(void) onExit +{ +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + if( isTouchEnabled_ ) + [[CCTouchDispatcher sharedDispatcher] removeDelegate:self]; + + if( isAccelerometerEnabled_ ) + [[UIAccelerometer sharedAccelerometer] setDelegate:nil]; + +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + if( isMouseEnabled_ ) + [[CCEventDispatcher sharedDispatcher] removeMouseDelegate:self]; + + if( isKeyboardEnabled_ ) + [[CCEventDispatcher sharedDispatcher] removeKeyboardDelegate:self]; +#endif + + [super onExit]; +} + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event +{ + NSAssert(NO, @"Layer#ccTouchBegan override me"); + return YES; +} +#endif +@end + +#pragma mark - +#pragma mark LayerColor + +@interface CCLayerColor (Private) +-(void) updateColor; +@end + +@implementation CCLayerColor + +// Opacity and RGB color protocol +@synthesize opacity = opacity_, color = color_; +@synthesize blendFunc = blendFunc_; + + ++ (id) layerWithColor:(ccColor4B)color width:(GLfloat)w height:(GLfloat) h +{ + return [[[self alloc] initWithColor:color width:w height:h] autorelease]; +} + ++ (id) layerWithColor:(ccColor4B)color +{ + return [[(CCLayerColor*)[self alloc] initWithColor:color] autorelease]; +} + +- (id) initWithColor:(ccColor4B)color width:(GLfloat)w height:(GLfloat) h +{ + if( (self=[super init]) ) { + + // default blend function + blendFunc_ = (ccBlendFunc) { CC_BLEND_SRC, CC_BLEND_DST }; + + color_.r = color.r; + color_.g = color.g; + color_.b = color.b; + opacity_ = color.a; + + for (NSUInteger i = 0; i +{ + tCCMenuState state_; + CCMenuItem *selectedItem_; + GLubyte opacity_; + ccColor3B color_; +} + +/** creates a CCMenu with it's items */ ++ (id) menuWithItems: (CCMenuItem*) item, ... NS_REQUIRES_NIL_TERMINATION; + +/** initializes a CCMenu with it's items */ +- (id) initWithItems: (CCMenuItem*) item vaList: (va_list) args; + +/** align items vertically */ +-(void) alignItemsVertically; +/** align items vertically with padding + @since v0.7.2 + */ +-(void) alignItemsVerticallyWithPadding:(float) padding; + +/** align items horizontally */ +-(void) alignItemsHorizontally; +/** align items horizontally with padding + @since v0.7.2 + */ +-(void) alignItemsHorizontallyWithPadding: (float) padding; + + +/** align items in rows of columns */ +-(void) alignItemsInColumns: (NSNumber *) columns, ... NS_REQUIRES_NIL_TERMINATION; +-(void) alignItemsInColumns: (NSNumber *) columns vaList: (va_list) args; + +/** align items in columns of rows */ +-(void) alignItemsInRows: (NSNumber *) rows, ... NS_REQUIRES_NIL_TERMINATION; +-(void) alignItemsInRows: (NSNumber *) rows vaList: (va_list) args; + + +/** conforms to CCRGBAProtocol protocol */ +@property (nonatomic,readonly) GLubyte opacity; +/** conforms to CCRGBAProtocol protocol */ +@property (nonatomic,readonly) ccColor3B color; + +@end diff --git a/Classes/cocos2d/CCMenu.m b/Classes/cocos2d/CCMenu.m new file mode 100644 index 0000000..59e0218 --- /dev/null +++ b/Classes/cocos2d/CCMenu.m @@ -0,0 +1,516 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + + +#import "CCMenu.h" +#import "CCDirector.h" +#import "Support/CGPointExtension.h" +#import "ccMacros.h" + +#import +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +#import "Platforms/iOS/CCDirectorIOS.h" +#import "Platforms/iOS/CCTouchDispatcher.h" +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) +#import "Platforms/Mac/MacGLView.h" +#import "Platforms/Mac/CCDirectorMac.h" +#endif + +enum { + kDefaultPadding = 5, +}; + +@implementation CCMenu + +@synthesize opacity = opacity_, color = color_; + +- (id) init +{ + NSAssert(NO, @"CCMenu: Init not supported."); + [self release]; + return nil; +} + ++(id) menuWithItems: (CCMenuItem*) item, ... +{ + va_list args; + va_start(args,item); + + id s = [[[self alloc] initWithItems: item vaList:args] autorelease]; + + va_end(args); + return s; +} + +-(id) initWithItems: (CCMenuItem*) item vaList: (va_list) args +{ + if( (self=[super init]) ) { + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + self.isTouchEnabled = YES; +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + self.isMouseEnabled = YES; +#endif + + // menu in the center of the screen + CGSize s = [[CCDirector sharedDirector] winSize]; + + self.isRelativeAnchorPoint = NO; + anchorPoint_ = ccp(0.5f, 0.5f); + [self setContentSize:s]; + + // XXX: in v0.7, winSize should return the visible size + // XXX: so the bar calculation should be done there +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + CGRect r = [[UIApplication sharedApplication] statusBarFrame]; + ccDeviceOrientation orientation = [[CCDirector sharedDirector] deviceOrientation]; + if( orientation == CCDeviceOrientationLandscapeLeft || orientation == CCDeviceOrientationLandscapeRight ) + s.height -= r.size.width; + else + s.height -= r.size.height; +#endif + self.position = ccp(s.width/2, s.height/2); + + int z=0; + + if (item) { + [self addChild: item z:z]; + CCMenuItem *i = va_arg(args, CCMenuItem*); + while(i) { + z++; + [self addChild: i z:z]; + i = va_arg(args, CCMenuItem*); + } + } + // [self alignItemsVertically]; + + selectedItem_ = nil; + state_ = kCCMenuStateWaiting; + } + + return self; +} + +-(void) dealloc +{ + [super dealloc]; +} + +/* + * override add: + */ +-(void) addChild:(CCMenuItem*)child z:(int)z tag:(int) aTag +{ + NSAssert( [child isKindOfClass:[CCMenuItem class]], @"Menu only supports MenuItem objects as children"); + [super addChild:child z:z tag:aTag]; +} + +- (void) onExit +{ + if(state_ == kCCMenuStateTrackingTouch) + { + [selectedItem_ unselected]; + state_ = kCCMenuStateWaiting; + selectedItem_ = nil; + } + [super onExit]; +} + +#pragma mark Menu - Touches + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +-(void) registerWithTouchDispatcher +{ + [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:kCCMenuTouchPriority swallowsTouches:YES]; +} + +-(CCMenuItem *) itemForTouch: (UITouch *) touch +{ + CGPoint touchLocation = [touch locationInView: [touch view]]; + touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation]; + + CCMenuItem* item; + CCARRAY_FOREACH(children_, item){ + // ignore invisible and disabled items: issue #779, #866 + if ( [item visible] && [item isEnabled] ) { + + CGPoint local = [item convertToNodeSpace:touchLocation]; + CGRect r = [item rect]; + r.origin = CGPointZero; + + if( CGRectContainsPoint( r, local ) ) + return item; + } + } + return nil; +} + +-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event +{ + if( state_ != kCCMenuStateWaiting || !visible_ ) + return NO; + + selectedItem_ = [self itemForTouch:touch]; + [selectedItem_ selected]; + + if( selectedItem_ ) { + state_ = kCCMenuStateTrackingTouch; + return YES; + } + return NO; +} + +-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event +{ + NSAssert(state_ == kCCMenuStateTrackingTouch, @"[Menu ccTouchEnded] -- invalid state"); + + [selectedItem_ unselected]; + [selectedItem_ activate]; + + state_ = kCCMenuStateWaiting; +} + +-(void) ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event +{ + NSAssert(state_ == kCCMenuStateTrackingTouch, @"[Menu ccTouchCancelled] -- invalid state"); + + [selectedItem_ unselected]; + + state_ = kCCMenuStateWaiting; +} + +-(void) ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event +{ + NSAssert(state_ == kCCMenuStateTrackingTouch, @"[Menu ccTouchMoved] -- invalid state"); + + CCMenuItem *currentItem = [self itemForTouch:touch]; + + if (currentItem != selectedItem_) { + [selectedItem_ unselected]; + selectedItem_ = currentItem; + [selectedItem_ selected]; + } +} + +#pragma mark Menu - Mouse + +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + +-(NSInteger) mouseDelegatePriority +{ + return NSIntegerMin+1; +} + +-(CCMenuItem *) itemForMouseEvent: (NSEvent *) event +{ + CGPoint location = [(CCDirectorMac*)[CCDirector sharedDirector] convertEventToGL:event]; + + CCMenuItem* item; + CCARRAY_FOREACH(children_, item){ + // ignore invisible and disabled items: issue #779, #866 + if ( [item visible] && [item isEnabled] ) { + + CGPoint local = [item convertToNodeSpace:location]; + + CGRect r = [item rect]; + r.origin = CGPointZero; + + if( CGRectContainsPoint( r, local ) ) + return item; + } + } + return nil; +} + +-(BOOL) ccMouseUp:(NSEvent *)event +{ + if( selectedItem_ ) { + [selectedItem_ unselected]; + [selectedItem_ activate]; + + state_ = kCCMenuStateWaiting; + + return YES; + } + + return NO; +} + +-(BOOL) ccMouseDown:(NSEvent *)event +{ + if( ! visible_ ) + return NO; + + selectedItem_ = [self itemForMouseEvent:event]; + [selectedItem_ selected]; + + if( selectedItem_ ) { + state_ = kCCMenuStateTrackingTouch; + return YES; + } + + return NO; +} + +-(BOOL) ccMouseDragged:(NSEvent *)event +{ + CCMenuItem *currentItem = [self itemForMouseEvent:event]; + + if (currentItem != selectedItem_) { + [selectedItem_ unselected]; + selectedItem_ = currentItem; + [selectedItem_ selected]; + } + + // swallows event ? + if( currentItem && state_ == kCCMenuStateTrackingTouch ) + return YES; + return NO; +} + +#endif // Mac Mouse support + +#pragma mark Menu - Alignment +-(void) alignItemsVertically +{ + return [self alignItemsVerticallyWithPadding:kDefaultPadding]; +} +-(void) alignItemsVerticallyWithPadding:(float)padding +{ + float height = -padding; + + CCMenuItem *item; + CCARRAY_FOREACH(children_, item) + height += item.contentSize.height * item.scaleY + padding; + + float y = height / 2.0f; + + CCARRAY_FOREACH(children_, item) { + CGSize itemSize = item.contentSize; + [item setPosition:ccp(0, y - itemSize.height * item.scaleY / 2.0f)]; + y -= itemSize.height * item.scaleY + padding; + } +} + +-(void) alignItemsHorizontally +{ + return [self alignItemsHorizontallyWithPadding:kDefaultPadding]; +} + +-(void) alignItemsHorizontallyWithPadding:(float)padding +{ + + float width = -padding; + CCMenuItem *item; + CCARRAY_FOREACH(children_, item) + width += item.contentSize.width * item.scaleX + padding; + + float x = -width / 2.0f; + + CCARRAY_FOREACH(children_, item){ + CGSize itemSize = item.contentSize; + [item setPosition:ccp(x + itemSize.width * item.scaleX / 2.0f, 0)]; + x += itemSize.width * item.scaleX + padding; + } +} + +-(void) alignItemsInColumns: (NSNumber *) columns, ... +{ + va_list args; + va_start(args, columns); + + [self alignItemsInColumns:columns vaList:args]; + + va_end(args); +} + +-(void) alignItemsInColumns: (NSNumber *) columns vaList: (va_list) args +{ + NSMutableArray *rows = [[NSMutableArray alloc] initWithObjects:columns, nil]; + columns = va_arg(args, NSNumber*); + while(columns) { + [rows addObject:columns]; + columns = va_arg(args, NSNumber*); + } + + int height = -5; + NSUInteger row = 0, rowHeight = 0, columnsOccupied = 0, rowColumns; + CCMenuItem *item; + CCARRAY_FOREACH(children_, item){ + NSAssert( row < [rows count], @"Too many menu items for the amount of rows/columns."); + + rowColumns = [(NSNumber *) [rows objectAtIndex:row] unsignedIntegerValue]; + NSAssert( rowColumns, @"Can't have zero columns on a row"); + + rowHeight = fmaxf(rowHeight, item.contentSize.height); + ++columnsOccupied; + + if(columnsOccupied >= rowColumns) { + height += rowHeight + 5; + + columnsOccupied = 0; + rowHeight = 0; + ++row; + } + } + NSAssert( !columnsOccupied, @"Too many rows/columns for available menu items." ); + + CGSize winSize = [[CCDirector sharedDirector] winSize]; + + row = 0; rowHeight = 0; rowColumns = 0; + float w, x, y = height / 2; + CCARRAY_FOREACH(children_, item) { + if(rowColumns == 0) { + rowColumns = [(NSNumber *) [rows objectAtIndex:row] unsignedIntegerValue]; + w = winSize.width / (1 + rowColumns); + x = w; + } + + CGSize itemSize = item.contentSize; + rowHeight = fmaxf(rowHeight, itemSize.height); + [item setPosition:ccp(x - winSize.width / 2, + y - itemSize.height / 2)]; + + x += w + 10; + ++columnsOccupied; + + if(columnsOccupied >= rowColumns) { + y -= rowHeight + 5; + + columnsOccupied = 0; + rowColumns = 0; + rowHeight = 0; + ++row; + } + } + + [rows release]; +} + +-(void) alignItemsInRows: (NSNumber *) rows, ... +{ + va_list args; + va_start(args, rows); + + [self alignItemsInRows:rows vaList:args]; + + va_end(args); +} + +-(void) alignItemsInRows: (NSNumber *) rows vaList: (va_list) args +{ + NSMutableArray *columns = [[NSMutableArray alloc] initWithObjects:rows, nil]; + rows = va_arg(args, NSNumber*); + while(rows) { + [columns addObject:rows]; + rows = va_arg(args, NSNumber*); + } + + NSMutableArray *columnWidths = [[NSMutableArray alloc] init]; + NSMutableArray *columnHeights = [[NSMutableArray alloc] init]; + + int width = -10, columnHeight = -5; + NSUInteger column = 0, columnWidth = 0, rowsOccupied = 0, columnRows; + CCMenuItem *item; + CCARRAY_FOREACH(children_, item){ + NSAssert( column < [columns count], @"Too many menu items for the amount of rows/columns."); + + columnRows = [(NSNumber *) [columns objectAtIndex:column] unsignedIntegerValue]; + NSAssert( columnRows, @"Can't have zero rows on a column"); + + CGSize itemSize = item.contentSize; + columnWidth = fmaxf(columnWidth, itemSize.width); + columnHeight += itemSize.height + 5; + ++rowsOccupied; + + if(rowsOccupied >= columnRows) { + [columnWidths addObject:[NSNumber numberWithUnsignedInteger:columnWidth]]; + [columnHeights addObject:[NSNumber numberWithUnsignedInteger:columnHeight]]; + width += columnWidth + 10; + + rowsOccupied = 0; + columnWidth = 0; + columnHeight = -5; + ++column; + } + } + NSAssert( !rowsOccupied, @"Too many rows/columns for available menu items."); + + CGSize winSize = [[CCDirector sharedDirector] winSize]; + + column = 0; columnWidth = 0; columnRows = 0; + float x = -width / 2, y; + + CCARRAY_FOREACH(children_, item){ + if(columnRows == 0) { + columnRows = [(NSNumber *) [columns objectAtIndex:column] unsignedIntegerValue]; + y = ([(NSNumber *) [columnHeights objectAtIndex:column] intValue] + winSize.height) / 2; + } + + CGSize itemSize = item.contentSize; + columnWidth = fmaxf(columnWidth, itemSize.width); + [item setPosition:ccp(x + [(NSNumber *) [columnWidths objectAtIndex:column] unsignedIntegerValue] / 2, + y - winSize.height / 2)]; + + y -= itemSize.height + 10; + ++rowsOccupied; + + if(rowsOccupied >= columnRows) { + x += columnWidth + 5; + + rowsOccupied = 0; + columnRows = 0; + columnWidth = 0; + ++column; + } + } + + [columns release]; + [columnWidths release]; + [columnHeights release]; +} + +#pragma mark Menu - Opacity Protocol + +/** Override synthesized setOpacity to recurse items */ +- (void) setOpacity:(GLubyte)newOpacity +{ + opacity_ = newOpacity; + + id item; + CCARRAY_FOREACH(children_, item) + [item setOpacity:opacity_]; +} + +-(void) setColor:(ccColor3B)color +{ + color_ = color; + + id item; + CCARRAY_FOREACH(children_, item) + [item setColor:color_]; +} +@end diff --git a/Classes/cocos2d/CCMenuItem.h b/Classes/cocos2d/CCMenuItem.h new file mode 100644 index 0000000..ca07b5e --- /dev/null +++ b/Classes/cocos2d/CCMenuItem.h @@ -0,0 +1,341 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + +#import "CCBlockSupport.h" + +#import "CCNode.h" +#import "CCProtocols.h" + +@class CCSprite; + +#define kItemSize 32 + +/** CCMenuItem base class + * + * Subclass CCMenuItem (or any subclass) to create your custom CCMenuItem objects. + */ +@interface CCMenuItem : CCNode +{ + NSInvocation *invocation; +#if NS_BLOCKS_AVAILABLE + // used for menu items using a block + void (^block_)(id sender); +#endif + + BOOL isEnabled_; + BOOL isSelected_; +} + +/** returns whether or not the item is selected +@since v0.8.2 +*/ +@property (nonatomic,readonly) BOOL isSelected; + +/** Creates a CCMenuItem with a target/selector */ ++(id) itemWithTarget:(id)target selector:(SEL)selector; + +/** Initializes a CCMenuItem with a target/selector */ +-(id) initWithTarget:(id)target selector:(SEL)selector; + +#if NS_BLOCKS_AVAILABLE +/** Creates a CCMenuItem with the specified block. + The block will be "copied". + */ ++(id) itemWithBlock:(void(^)(id sender))block; + +/** Initializes a CCMenuItem with the specified block. + The block will be "copied". +*/ +-(id) initWithBlock:(void(^)(id sender))block; +#endif + +/** Returns the outside box in points */ +-(CGRect) rect; + +/** Activate the item */ +-(void) activate; + +/** The item was selected (not activated), similar to "mouse-over" */ +-(void) selected; + +/** The item was unselected */ +-(void) unselected; + +/** Enable or disabled the CCMenuItem */ +-(void) setIsEnabled:(BOOL)enabled; +/** Returns whether or not the CCMenuItem is enabled */ +-(BOOL) isEnabled; +@end + +/** An abstract class for "label" CCMenuItemLabel items + Any CCNode that supports the CCLabelProtocol protocol can be added. + Supported nodes: + - CCLabelBMFont + - CCLabelAtlas + - CCLabelTTF + */ +@interface CCMenuItemLabel : CCMenuItem +{ + CCNode *label_; + ccColor3B colorBackup; + ccColor3B disabledColor_; + float originalScale_; +} + +/** the color that will be used to disable the item */ +@property (nonatomic,readwrite) ccColor3B disabledColor; + +/** Label that is rendered. It can be any CCNode that implements the CCLabelProtocol */ +@property (nonatomic,readwrite,assign) CCNode* label; + +/** creates a CCMenuItemLabel with a Label, target and selector */ ++(id) itemWithLabel:(CCNode*)label target:(id)target selector:(SEL)selector; + +/** initializes a CCMenuItemLabel with a Label, target and selector */ +-(id) initWithLabel:(CCNode*)label target:(id)target selector:(SEL)selector; + +#if NS_BLOCKS_AVAILABLE +/** creates a CCMenuItemLabel with a Label and a block to execute. + The block will be "copied". + */ ++(id) itemWithLabel:(CCNode*)label block:(void(^)(id sender))block; + +/** initializes a CCMenuItemLabel with a Label and a block to execute. + The block will be "copied". + */ +-(id) initWithLabel:(CCNode*)label block:(void(^)(id sender))block; +#endif + +/** sets a new string to the inner label */ +-(void) setString:(NSString*)label; + +/** Enable or disabled the CCMenuItemFont + @warning setIsEnabled changes the RGB color of the font + */ +-(void) setIsEnabled: (BOOL)enabled; +@end + +/** A CCMenuItemAtlasFont + Helper class that creates a MenuItemLabel class with a LabelAtlas + */ +@interface CCMenuItemAtlasFont : CCMenuItemLabel +{ +} + +/** creates a menu item from a string and atlas with a target/selector */ ++(id) itemFromString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap; + +/** creates a menu item from a string and atlas. Use it with MenuItemToggle */ ++(id) itemFromString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap target:(id) rec selector:(SEL) cb; + +/** initializes a menu item from a string and atlas with a target/selector */ +-(id) initFromString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap target:(id) rec selector:(SEL) cb; + +#if NS_BLOCKS_AVAILABLE +/** creates a menu item from a string and atlas. Use it with MenuItemToggle. + The block will be "copied". + */ ++(id) itemFromString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap block:(void(^)(id sender))block; + +/** initializes a menu item from a string and atlas with a block. + The block will be "copied". + */ +-(id) initFromString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap block:(void(^)(id sender))block; +#endif + +@end + +/** A CCMenuItemFont + Helper class that creates a CCMenuItemLabel class with a Label + */ +@interface CCMenuItemFont : CCMenuItemLabel +{ +} +/** set font size */ ++(void) setFontSize: (int) s; + +/** get font size */ ++(int) fontSize; + +/** set the font name */ ++(void) setFontName: (NSString*) n; + +/** get the font name */ ++(NSString*) fontName; + +/** creates a menu item from a string without target/selector. To be used with CCMenuItemToggle */ ++(id) itemFromString: (NSString*) value; + +/** creates a menu item from a string with a target/selector */ ++(id) itemFromString: (NSString*) value target:(id) r selector:(SEL) s; + +/** initializes a menu item from a string with a target/selector */ +-(id) initFromString: (NSString*) value target:(id) r selector:(SEL) s; + +#if NS_BLOCKS_AVAILABLE +/** creates a menu item from a string with the specified block. + The block will be "copied". + */ ++(id) itemFromString: (NSString*) value block:(void(^)(id sender))block; + +/** initializes a menu item from a string with the specified block. + The block will be "copied". + */ +-(id) initFromString: (NSString*) value block:(void(^)(id sender))block; +#endif +@end + +/** CCMenuItemSprite accepts CCNode objects as items. + The images has 3 different states: + - unselected image + - selected image + - disabled image + + @since v0.8.0 + */ +@interface CCMenuItemSprite : CCMenuItem +{ + CCNode *normalImage_, *selectedImage_, *disabledImage_; +} + +// weak references + +/** the image used when the item is not selected */ +@property (nonatomic,readwrite,assign) CCNode *normalImage; +/** the image used when the item is selected */ +@property (nonatomic,readwrite,assign) CCNode *selectedImage; +/** the image used when the item is disabled */ +@property (nonatomic,readwrite,assign) CCNode *disabledImage; + +/** creates a menu item with a normal and selected image*/ ++(id) itemFromNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite; +/** creates a menu item with a normal and selected image with target/selector */ ++(id) itemFromNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite target:(id)target selector:(SEL)selector; +/** creates a menu item with a normal,selected and disabled image with target/selector */ ++(id) itemFromNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite disabledSprite:(CCNode*)disabledSprite target:(id)target selector:(SEL)selector; +/** initializes a menu item with a normal, selected and disabled image with target/selector */ +-(id) initFromNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite disabledSprite:(CCNode*)disabledSprite target:(id)target selector:(SEL)selector; + +#if NS_BLOCKS_AVAILABLE +/** creates a menu item with a normal and selected image with a block. + The block will be "copied". + */ ++(id) itemFromNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite block:(void(^)(id sender))block; +/** creates a menu item with a normal,selected and disabled image with a block. + The block will be "copied". + */ ++(id) itemFromNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite disabledSprite:(CCNode*)disabledSprite block:(void(^)(id sender))block; +/** initializes a menu item with a normal, selected and disabled image with a block. + The block will be "copied". + */ +-(id) initFromNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite disabledSprite:(CCNode*)disabledSprite block:(void(^)(id sender))block; +#endif + +@end + +/** CCMenuItemImage accepts images as items. + The images has 3 different states: + - unselected image + - selected image + - disabled image + + For best results try that all images are of the same size + */ +@interface CCMenuItemImage : CCMenuItemSprite +{ +} + +/** creates a menu item with a normal and selected image*/ ++(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2; +/** creates a menu item with a normal and selected image with target/selector */ ++(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 target:(id) r selector:(SEL) s; +/** creates a menu item with a normal,selected and disabled image with target/selector */ ++(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 disabledImage:(NSString*) value3 target:(id) r selector:(SEL) s; +/** initializes a menu item with a normal, selected and disabled image with target/selector */ +-(id) initFromNormalImage: (NSString*) value selectedImage:(NSString*)value2 disabledImage:(NSString*) value3 target:(id) r selector:(SEL) s; +#if NS_BLOCKS_AVAILABLE +/** creates a menu item with a normal and selected image with a block. + The block will be "copied". + */ ++(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 block:(void(^)(id sender))block; +/** creates a menu item with a normal,selected and disabled image with a block. + The block will be "copied". +*/ ++(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 disabledImage:(NSString*) value3 block:(void(^)(id sender))block; +/** initializes a menu item with a normal, selected and disabled image with a block. + The block will be "copied". +*/ +-(id) initFromNormalImage: (NSString*) value selectedImage:(NSString*)value2 disabledImage:(NSString*) value3 block:(void(^)(id sender))block; +#endif +@end + + + +/** A CCMenuItemToggle + A simple container class that "toggles" it's inner items + The inner itmes can be any MenuItem + */ +@interface CCMenuItemToggle : CCMenuItem +{ + NSUInteger selectedIndex_; + NSMutableArray* subItems_; + GLubyte opacity_; + ccColor3B color_; +} + +/** conforms with CCRGBAProtocol protocol */ +@property (nonatomic,readonly) GLubyte opacity; +/** conforms with CCRGBAProtocol protocol */ +@property (nonatomic,readonly) ccColor3B color; + +/** returns the selected item */ +@property (nonatomic,readwrite) NSUInteger selectedIndex; +/** NSMutableArray that contains the subitems. You can add/remove items in runtime, and you can replace the array with a new one. + @since v0.7.2 + */ +@property (nonatomic,readwrite,retain) NSMutableArray *subItems; + +/** creates a menu item from a list of items with a target/selector */ ++(id) itemWithTarget:(id)t selector:(SEL)s items:(CCMenuItem*) item, ... NS_REQUIRES_NIL_TERMINATION; + +/** initializes a menu item from a list of items with a target selector */ +-(id) initWithTarget:(id)t selector:(SEL)s items:(CCMenuItem*) item vaList:(va_list) args; + +#if NS_BLOCKS_AVAILABLE +/** creates a menu item from a list of items and executes the given block when the item is selected. + The block will be "copied". + */ ++(id) itemWithBlock:(void(^)(id sender))block items:(CCMenuItem*)item, ... NS_REQUIRES_NIL_TERMINATION; + +/** initializes a menu item from a list of items with a block. + The block will be "copied". + */ +-(id) initWithBlock:(void (^)(id))block items:(CCMenuItem*)item vaList:(va_list)args; +#endif + +/** return the selected item */ +-(CCMenuItem*) selectedItem; +@end + diff --git a/Classes/cocos2d/CCMenuItem.m b/Classes/cocos2d/CCMenuItem.m new file mode 100644 index 0000000..304702e --- /dev/null +++ b/Classes/cocos2d/CCMenuItem.m @@ -0,0 +1,752 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + +#import "CCMenuItem.h" +#import "CCLabelTTF.h" +#import "CCLabelAtlas.h" +#import "CCActionInterval.h" +#import "CCSprite.h" +#import "Support/CGPointExtension.h" + +static int _fontSize = kItemSize; +static NSString *_fontName = @"Marker Felt"; +static BOOL _fontNameRelease = NO; + +enum { + kCurrentItem = 0xc0c05001, +}; + +enum { + kZoomActionTag = 0xc0c05002, +}; + + + +#pragma mark - +#pragma mark CCMenuItem + +@implementation CCMenuItem + +@synthesize isSelected=isSelected_; +-(id) init +{ + NSAssert(NO, @"MenuItemInit: Init not supported."); + [self release]; + return nil; +} + ++(id) itemWithTarget:(id) r selector:(SEL) s +{ + return [[[self alloc] initWithTarget:r selector:s] autorelease]; +} + +-(id) initWithTarget:(id) rec selector:(SEL) cb +{ + if((self=[super init]) ) { + + anchorPoint_ = ccp(0.5f, 0.5f); + NSMethodSignature * sig = nil; + + if( rec && cb ) { + sig = [rec methodSignatureForSelector:cb]; + + invocation = nil; + invocation = [NSInvocation invocationWithMethodSignature:sig]; + [invocation setTarget:rec]; + [invocation setSelector:cb]; +#if NS_BLOCKS_AVAILABLE + if ([sig numberOfArguments] == 3) +#endif + [invocation setArgument:&self atIndex:2]; + + [invocation retain]; + } + + isEnabled_ = YES; + isSelected_ = NO; + } + + return self; +} + +#if NS_BLOCKS_AVAILABLE + ++(id) itemWithBlock:(void(^)(id sender))block { + return [[[self alloc] initWithBlock:block] autorelease]; +} + +-(id) initWithBlock:(void(^)(id sender))block { + block_ = [block copy]; + return [self initWithTarget:block_ selector:@selector(ccCallbackBlockWithSender:)]; +} + +#endif // NS_BLOCKS_AVAILABLE + +-(void) dealloc +{ + [invocation release]; + +#if NS_BLOCKS_AVAILABLE + [block_ release]; +#endif + + [super dealloc]; +} + +-(void) selected +{ + isSelected_ = YES; +} + +-(void) unselected +{ + isSelected_ = NO; +} + +-(void) activate +{ + if(isEnabled_) + [invocation invoke]; +} + +-(void) setIsEnabled: (BOOL)enabled +{ + isEnabled_ = enabled; +} + +-(BOOL) isEnabled +{ + return isEnabled_; +} + +-(CGRect) rect +{ + return CGRectMake( position_.x - contentSize_.width*anchorPoint_.x, + position_.y - contentSize_.height*anchorPoint_.y, + contentSize_.width, contentSize_.height); +} + +@end + + +#pragma mark - +#pragma mark CCMenuItemLabel + +@implementation CCMenuItemLabel + +@synthesize disabledColor = disabledColor_; + ++(id) itemWithLabel:(CCNode*)label target:(id)target selector:(SEL)selector +{ + return [[[self alloc] initWithLabel:label target:target selector:selector] autorelease]; +} + +-(id) initWithLabel:(CCNode*)label target:(id)target selector:(SEL)selector +{ + if( (self=[super initWithTarget:target selector:selector]) ) { + originalScale_ = 1; + colorBackup = ccWHITE; + disabledColor_ = ccc3( 126,126,126); + self.label = label; + + } + return self; +} + +#if NS_BLOCKS_AVAILABLE + ++(id) itemWithLabel:(CCNode*)label block:(void(^)(id sender))block { + return [[[self alloc] initWithLabel:label block:block] autorelease]; +} + +-(id) initWithLabel:(CCNode*)label block:(void(^)(id sender))block { + block_ = [block copy]; + return [self initWithLabel:label target:block_ selector:@selector(ccCallbackBlockWithSender:)]; +} + +#endif // NS_BLOCKS_AVAILABLE + +-(CCNode*) label +{ + return label_; +} +-(void) setLabel:(CCNode*) label +{ + if( label != label_ ) { + [self removeChild:label_ cleanup:YES]; + [self addChild:label]; + + label_ = label; + label_.anchorPoint = ccp(0,0); + + [self setContentSize:[label_ contentSize]]; + } +} + +-(void) setString:(NSString *)string +{ + [label_ setString:string]; + [self setContentSize: [label_ contentSize]]; +} + +-(void) activate { + if(isEnabled_) { + [self stopAllActions]; + + self.scale = originalScale_; + + [super activate]; + } +} + +-(void) selected +{ + // subclass to change the default action + if(isEnabled_) { + [super selected]; + [self stopActionByTag:kZoomActionTag]; + originalScale_ = self.scale; + CCAction *zoomAction = [CCScaleTo actionWithDuration:0.1f scale:originalScale_ * 1.2f]; + zoomAction.tag = kZoomActionTag; + [self runAction:zoomAction]; + } +} + +-(void) unselected +{ + // subclass to change the default action + if(isEnabled_) { + [super unselected]; + [self stopActionByTag:kZoomActionTag]; + CCAction *zoomAction = [CCScaleTo actionWithDuration:0.1f scale:originalScale_]; + zoomAction.tag = kZoomActionTag; + [self runAction:zoomAction]; + } +} + +-(void) setIsEnabled: (BOOL)enabled +{ + if( isEnabled_ != enabled ) { + if(enabled == NO) { + colorBackup = [label_ color]; + [label_ setColor: disabledColor_]; + } + else + [label_ setColor:colorBackup]; + } + + [super setIsEnabled:enabled]; +} + +- (void) setOpacity: (GLubyte)opacity +{ + [label_ setOpacity:opacity]; +} +-(GLubyte) opacity +{ + return [label_ opacity]; +} +-(void) setColor:(ccColor3B)color +{ + [label_ setColor:color]; +} +-(ccColor3B) color +{ + return [label_ color]; +} +@end + +#pragma mark - +#pragma mark CCMenuItemAtlasFont + +@implementation CCMenuItemAtlasFont + ++(id) itemFromString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap +{ + return [CCMenuItemAtlasFont itemFromString:value charMapFile:charMapFile itemWidth:itemWidth itemHeight:itemHeight startCharMap:startCharMap target:nil selector:nil]; +} + ++(id) itemFromString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap target:(id) rec selector:(SEL) cb +{ + return [[[self alloc] initFromString:value charMapFile:charMapFile itemWidth:itemWidth itemHeight:itemHeight startCharMap:startCharMap target:rec selector:cb] autorelease]; +} + +-(id) initFromString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap target:(id) rec selector:(SEL) cb +{ + NSAssert( [value length] != 0, @"value length must be greater than 0"); + + CCLabelAtlas *label = [[CCLabelAtlas alloc] initWithString:value charMapFile:charMapFile itemWidth:itemWidth itemHeight:itemHeight startCharMap:startCharMap]; + [label autorelease]; + + if((self=[super initWithLabel:label target:rec selector:cb]) ) { + // do something ? + } + + return self; +} + +#if NS_BLOCKS_AVAILABLE ++(id) itemFromString:(NSString*)value charMapFile:(NSString*)charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap block:(void(^)(id sender))block { + return [[[self alloc] initFromString:value charMapFile:charMapFile itemWidth:itemWidth itemHeight:itemHeight startCharMap:startCharMap block:block] autorelease]; +} + +-(id) initFromString:(NSString*)value charMapFile:(NSString*)charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap block:(void(^)(id sender))block { + block_ = [block copy]; + return [self initFromString:value charMapFile:charMapFile itemWidth:itemWidth itemHeight:itemHeight startCharMap:startCharMap target:block_ selector:@selector(ccCallbackBlockWithSender:)]; +} +#endif // NS_BLOCKS_AVAILABLE + +-(void) dealloc +{ + [super dealloc]; +} +@end + + +#pragma mark - +#pragma mark CCMenuItemFont + +@implementation CCMenuItemFont + ++(void) setFontSize: (int) s +{ + _fontSize = s; +} + ++(int) fontSize +{ + return _fontSize; +} + ++(void) setFontName: (NSString*) n +{ + if( _fontNameRelease ) + [_fontName release]; + + _fontName = [n retain]; + _fontNameRelease = YES; +} + ++(NSString*) fontName +{ + return _fontName; +} + ++(id) itemFromString: (NSString*) value target:(id) r selector:(SEL) s +{ + return [[[self alloc] initFromString: value target:r selector:s] autorelease]; +} + ++(id) itemFromString: (NSString*) value +{ + return [[[self alloc] initFromString: value target:nil selector:nil] autorelease]; +} + +-(id) initFromString: (NSString*) value target:(id) rec selector:(SEL) cb +{ + NSAssert( [value length] != 0, @"Value length must be greater than 0"); + + CCLabelTTF *label = [CCLabelTTF labelWithString:value fontName:_fontName fontSize:_fontSize]; + + if((self=[super initWithLabel:label target:rec selector:cb]) ) { + // do something ? + } + + return self; +} + +#if NS_BLOCKS_AVAILABLE ++(id) itemFromString: (NSString*) value block:(void(^)(id sender))block { + return [[[self alloc] initFromString:value block:block] autorelease]; +} + +-(id) initFromString: (NSString*) value block:(void(^)(id sender))block { + block_ = [block copy]; + return [self initFromString:value target:block_ selector:@selector(ccCallbackBlockWithSender:)]; +} +#endif // NS_BLOCKS_AVAILABLE + +@end + +#pragma mark - +#pragma mark CCMenuItemSprite +@implementation CCMenuItemSprite + +@synthesize normalImage=normalImage_, selectedImage=selectedImage_, disabledImage=disabledImage_; + ++(id) itemFromNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite +{ + return [self itemFromNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:nil target:nil selector:nil]; +} ++(id) itemFromNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite target:(id)target selector:(SEL)selector +{ + return [self itemFromNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:nil target:target selector:selector]; +} ++(id) itemFromNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite disabledSprite:(CCNode*)disabledSprite target:(id)target selector:(SEL)selector +{ + return [[[self alloc] initFromNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:disabledSprite target:target selector:selector] autorelease]; +} +-(id) initFromNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite disabledSprite:(CCNode*)disabledSprite target:(id)target selector:(SEL)selector +{ + if( (self=[super initWithTarget:target selector:selector]) ) { + + self.normalImage = normalSprite; + self.selectedImage = selectedSprite; + self.disabledImage = disabledSprite; + + [self setContentSize: [normalImage_ contentSize]]; + } + return self; +} + +#if NS_BLOCKS_AVAILABLE ++(id) itemFromNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite block:(void(^)(id sender))block { + return [self itemFromNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:nil block:block]; +} + ++(id) itemFromNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite disabledSprite:(CCNode*)disabledSprite block:(void(^)(id sender))block { + return [[[self alloc] initFromNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:disabledSprite block:block] autorelease]; +} + +-(id) initFromNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite disabledSprite:(CCNode*)disabledSprite block:(void(^)(id sender))block { + block_ = [block copy]; + return [self initFromNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:disabledSprite target:block_ selector:@selector(ccCallbackBlockWithSender:)]; +} +#endif // NS_BLOCKS_AVAILABLE + + +-(void) setNormalImage:(CCNode *)image +{ + if( image != normalImage_ ) { + image.anchorPoint = ccp(0,0); + image.visible = YES; + + [self removeChild:normalImage_ cleanup:YES]; + [self addChild:image]; + + normalImage_ = image; + } +} + +-(void) setSelectedImage:(CCNode *)image +{ + if( image != selectedImage_ ) { + image.anchorPoint = ccp(0,0); + image.visible = NO; + + [self removeChild:selectedImage_ cleanup:YES]; + [self addChild:image]; + + selectedImage_ = image; + } +} + +-(void) setDisabledImage:(CCNode *)image +{ + if( image != disabledImage_ ) { + image.anchorPoint = ccp(0,0); + image.visible = NO; + + [self removeChild:disabledImage_ cleanup:YES]; + [self addChild:image]; + + disabledImage_ = image; + } +} + +#pragma mark CCMenuItemImage - CCRGBAProtocol protocol +- (void) setOpacity: (GLubyte)opacity +{ + [normalImage_ setOpacity:opacity]; + [selectedImage_ setOpacity:opacity]; + [disabledImage_ setOpacity:opacity]; +} + +-(void) setColor:(ccColor3B)color +{ + [normalImage_ setColor:color]; + [selectedImage_ setColor:color]; + [disabledImage_ setColor:color]; +} + +-(GLubyte) opacity +{ + return [normalImage_ opacity]; +} + +-(ccColor3B) color +{ + return [normalImage_ color]; +} + +-(void) selected +{ + [super selected]; + + if( selectedImage_ ) { + [normalImage_ setVisible:NO]; + [selectedImage_ setVisible:YES]; + [disabledImage_ setVisible:NO]; + + } else { // there is not selected image + + [normalImage_ setVisible:YES]; + [selectedImage_ setVisible:NO]; + [disabledImage_ setVisible:NO]; + } +} + +-(void) unselected +{ + [super unselected]; + [normalImage_ setVisible:YES]; + [selectedImage_ setVisible:NO]; + [disabledImage_ setVisible:NO]; +} + +-(void) setIsEnabled:(BOOL)enabled +{ + [super setIsEnabled:enabled]; + + if( enabled ) { + [normalImage_ setVisible:YES]; + [selectedImage_ setVisible:NO]; + [disabledImage_ setVisible:NO]; + + } else { + if( disabledImage_ ) { + [normalImage_ setVisible:NO]; + [selectedImage_ setVisible:NO]; + [disabledImage_ setVisible:YES]; + } else { + [normalImage_ setVisible:YES]; + [selectedImage_ setVisible:NO]; + [disabledImage_ setVisible:NO]; + } + } +} + +@end + +#pragma mark - +#pragma mark CCMenuItemImage + +@implementation CCMenuItemImage + ++(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 +{ + return [self itemFromNormalImage:value selectedImage:value2 disabledImage: nil target:nil selector:nil]; +} + ++(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 target:(id) t selector:(SEL) s +{ + return [self itemFromNormalImage:value selectedImage:value2 disabledImage: nil target:t selector:s]; +} + ++(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 disabledImage: (NSString*) value3 +{ + return [[[self alloc] initFromNormalImage:value selectedImage:value2 disabledImage:value3 target:nil selector:nil] autorelease]; +} + ++(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 disabledImage: (NSString*) value3 target:(id) t selector:(SEL) s +{ + return [[[self alloc] initFromNormalImage:value selectedImage:value2 disabledImage:value3 target:t selector:s] autorelease]; +} + +-(id) initFromNormalImage: (NSString*) normalI selectedImage:(NSString*)selectedI disabledImage: (NSString*) disabledI target:(id)t selector:(SEL)sel +{ + CCNode *normalImage = [CCSprite spriteWithFile:normalI]; + CCNode *selectedImage = nil; + CCNode *disabledImage = nil; + + if( selectedI ) + selectedImage = [CCSprite spriteWithFile:selectedI]; + if(disabledI) + disabledImage = [CCSprite spriteWithFile:disabledI]; + + return [self initFromNormalSprite:normalImage selectedSprite:selectedImage disabledSprite:disabledImage target:t selector:sel]; +} + +#if NS_BLOCKS_AVAILABLE + ++(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 block:(void(^)(id sender))block { + return [self itemFromNormalImage:value selectedImage:value2 disabledImage:nil block:block]; +} + ++(id) itemFromNormalImage: (NSString*)value selectedImage:(NSString*) value2 disabledImage:(NSString*) value3 block:(void(^)(id sender))block { + return [[[self alloc] initFromNormalImage:value selectedImage:value2 disabledImage:value3 block:block] autorelease]; +} + +-(id) initFromNormalImage: (NSString*) value selectedImage:(NSString*)value2 disabledImage:(NSString*) value3 block:(void(^)(id sender))block { + block_ = [block copy]; + return [self initFromNormalImage:value selectedImage:value2 disabledImage:value3 target:block_ selector:@selector(ccCallbackBlockWithSender:)]; +} + +#endif // NS_BLOCKS_AVAILABLE + +@end + +#pragma mark - +#pragma mark CCMenuItemToggle + +// +// MenuItemToggle +// +@implementation CCMenuItemToggle + +@synthesize subItems = subItems_; +@synthesize opacity = opacity_, color = color_; + ++(id) itemWithTarget: (id)t selector: (SEL)sel items: (CCMenuItem*) item, ... +{ + va_list args; + va_start(args, item); + + id s = [[[self alloc] initWithTarget: t selector:sel items: item vaList:args] autorelease]; + + va_end(args); + return s; +} + +-(id) initWithTarget: (id)t selector: (SEL)sel items:(CCMenuItem*) item vaList: (va_list) args +{ + if( (self=[super initWithTarget:t selector:sel]) ) { + + self.subItems = [NSMutableArray arrayWithCapacity:2]; + + int z = 0; + CCMenuItem *i = item; + while(i) { + z++; + [subItems_ addObject:i]; + i = va_arg(args, CCMenuItem*); + } + + selectedIndex_ = NSUIntegerMax; + [self setSelectedIndex:0]; + } + + return self; +} + +#if NS_BLOCKS_AVAILABLE + ++(id) itemWithBlock:(void(^)(id sender))block items:(CCMenuItem*)item, ... { + va_list args; + va_start(args, item); + + id s = [[[self alloc] initWithBlock:block items:item vaList:args] autorelease]; + + va_end(args); + return s; +} + +-(id) initWithBlock:(void (^)(id))block items:(CCMenuItem*)item vaList:(va_list)args { + block_ = [block copy]; + return [self initWithTarget:block_ selector:@selector(ccCallbackBlockWithSender:) items:item vaList:args]; +} + +#endif // NS_BLOCKS_AVAILABLE + +-(void) dealloc +{ + [subItems_ release]; + [super dealloc]; +} + +-(void)setSelectedIndex:(NSUInteger)index +{ + if( index != selectedIndex_ ) { + selectedIndex_=index; + [self removeChildByTag:kCurrentItem cleanup:NO]; + + CCMenuItem *item = [subItems_ objectAtIndex:selectedIndex_]; + [self addChild:item z:0 tag:kCurrentItem]; + + CGSize s = [item contentSize]; + [self setContentSize: s]; + item.position = ccp( s.width/2, s.height/2 ); + } +} + +-(NSUInteger) selectedIndex +{ + return selectedIndex_; +} + + +-(void) selected +{ + [super selected]; + [[subItems_ objectAtIndex:selectedIndex_] selected]; +} + +-(void) unselected +{ + [super unselected]; + [[subItems_ objectAtIndex:selectedIndex_] unselected]; +} + +-(void) activate +{ + // update index + if( isEnabled_ ) { + NSUInteger newIndex = (selectedIndex_ + 1) % [subItems_ count]; + [self setSelectedIndex:newIndex]; + + } + + [super activate]; +} + +-(void) setIsEnabled: (BOOL)enabled +{ + [super setIsEnabled:enabled]; + for(CCMenuItem* item in subItems_) + [item setIsEnabled:enabled]; +} + +-(CCMenuItem*) selectedItem +{ + return [subItems_ objectAtIndex:selectedIndex_]; +} + +#pragma mark CCMenuItemToggle - CCRGBAProtocol protocol + +- (void) setOpacity: (GLubyte)opacity +{ + opacity_ = opacity; + for(CCMenuItem* item in subItems_) + [item setOpacity:opacity]; +} + +- (void) setColor:(ccColor3B)color +{ + color_ = color; + for(CCMenuItem* item in subItems_) + [item setColor:color]; +} + +@end diff --git a/Classes/cocos2d/CCMotionStreak.h b/Classes/cocos2d/CCMotionStreak.h new file mode 100644 index 0000000..e017124 --- /dev/null +++ b/Classes/cocos2d/CCMotionStreak.h @@ -0,0 +1,67 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008, 2009 Jason Booth + * + * 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. + * + */ + +#import +#import "CCNode.h" +#import "CCRibbon.h" + +/** + * CCMotionStreak manages a Ribbon based on it's motion in absolute space. + * You construct it with a fadeTime, minimum segment size, texture path, texture + * length and color. The fadeTime controls how long it takes each vertex in + * the streak to fade out, the minimum segment size it how many pixels the + * streak will move before adding a new ribbon segement, and the texture + * length is the how many pixels the texture is stretched across. The texture + * is vertically aligned along the streak segemnts. + * + * Limitations: + * CCMotionStreak, by default, will use the GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA blending function. + * This blending function might not be the correct one for certain textures. + * But you can change it by using: + * [obj setBlendFunc: (ccBlendfunc) {new_src_blend_func, new_dst_blend_func}]; + * + * @since v0.8.1 + */ +@interface CCMotionStreak : CCNode +{ + CCRibbon* ribbon_; + float segThreshold_; + float width_; + CGPoint lastLocation_; +} + +/** Ribbon used by MotionStreak (weak reference) */ +@property (nonatomic,readonly) CCRibbon *ribbon; + +/** creates the a MotionStreak. The image will be loaded using the TextureMgr. */ ++(id)streakWithFade:(float)fade minSeg:(float)seg image:(NSString*)path width:(float)width length:(float)length color:(ccColor4B)color; + +/** initializes a MotionStreak. The file will be loaded using the TextureMgr. */ +-(id)initWithFade:(float)fade minSeg:(float)seg image:(NSString*)path width:(float)width length:(float)length color:(ccColor4B)color; + +/** polling function */ +-(void)update:(ccTime)delta; + +@end diff --git a/Classes/cocos2d/CCMotionStreak.m b/Classes/cocos2d/CCMotionStreak.m new file mode 100644 index 0000000..698cc59 --- /dev/null +++ b/Classes/cocos2d/CCMotionStreak.m @@ -0,0 +1,104 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008, 2009 Jason Booth + * + * 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. + * + * + ********************************************************* + * + * Motion Streak manages a Ribbon based on it's motion in absolute space. + * You construct it with a fadeTime, minimum segment size, texture path, texture + * length and color. The fadeTime controls how long it takes each vertex in + * the streak to fade out, the minimum segment size it how many pixels the + * streak will move before adding a new ribbon segement, and the texture + * length is the how many pixels the texture is stretched across. The texture + * is vertically aligned along the streak segemnts. + */ + +#import "CCMotionStreak.h" +#import "Support/CGPointExtension.h" + +@implementation CCMotionStreak + +@synthesize ribbon = ribbon_; + ++(id)streakWithFade:(float)fade minSeg:(float)seg image:(NSString*)path width:(float)width length:(float)length color:(ccColor4B)color +{ + return [[[self alloc] initWithFade:(float)fade minSeg:seg image:path width:width length:length color:color] autorelease]; +} + +-(id)initWithFade:(float)fade minSeg:(float)seg image:(NSString*)path width:(float)width length:(float)length color:(ccColor4B)color +{ + if( (self=[super init])) { + segThreshold_ = seg; + width_ = width; + lastLocation_ = CGPointZero; + ribbon_ = [CCRibbon ribbonWithWidth:width_ image:path length:length color:color fade:fade]; + [self addChild:ribbon_]; + + // update ribbon position + [self scheduleUpdate]; + } + return self; +} + +-(void)update:(ccTime)delta +{ + CGPoint location = [self convertToWorldSpace:CGPointZero]; + [ribbon_ setPosition:ccp(-1*location.x, -1*location.y)]; + float len = ccpLength(ccpSub(lastLocation_, location)); + if (len > segThreshold_) + { + [ribbon_ addPointAt:location width:width_]; + lastLocation_ = location; + } + [ribbon_ update:delta]; +} + + +-(void)dealloc +{ + [super dealloc]; +} + +#pragma mark MotionStreak - CocosNodeTexture protocol + +-(void) setTexture:(CCTexture2D*) texture +{ + [ribbon_ setTexture: texture]; +} + +-(CCTexture2D*) texture +{ + return [ribbon_ texture]; +} + +-(ccBlendFunc) blendFunc +{ + return [ribbon_ blendFunc]; +} + +-(void) setBlendFunc:(ccBlendFunc)blendFunc +{ + [ribbon_ setBlendFunc:blendFunc]; +} + +@end diff --git a/Classes/cocos2d/CCNode.h b/Classes/cocos2d/CCNode.h new file mode 100644 index 0000000..d6faaf5 --- /dev/null +++ b/Classes/cocos2d/CCNode.h @@ -0,0 +1,510 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2009 Valentin Milea + * + * 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. + */ + +#import + +#import "Platforms/CCGL.h" +#import "CCAction.h" +#import "ccTypes.h" +#import "CCTexture2D.h" +#import "CCProtocols.h" +#import "ccConfig.h" +#import "Support/CCArray.h" + +enum { + kCCNodeTagInvalid = -1, +}; + +@class CCCamera; +@class CCGridBase; + +/** CCNode is the main element. Anything thats gets drawn or contains things that get drawn is a CCNode. + The most popular CCNodes are: CCScene, CCLayer, CCSprite, CCMenu. + + The main features of a CCNode are: + - They can contain other CCNode nodes (addChild, getChildByTag, removeChild, etc) + - They can schedule periodic callback (schedule, unschedule, etc) + - They can execute actions (runAction, stopAction, etc) + + Some CCNode nodes provide extra functionality for them or their children. + + Subclassing a CCNode usually means (one/all) of: + - overriding init to initialize resources and schedule callbacks + - create callbacks to handle the advancement of time + - overriding draw to render the node + + Features of CCNode: + - position + - scale (x, y) + - rotation (in degrees, clockwise) + - CCCamera (an interface to gluLookAt ) + - CCGridBase (to do mesh transformations) + - anchor point + - size + - visible + - z-order + - openGL z position + + Default values: + - rotation: 0 + - position: (x=0,y=0) + - scale: (x=1,y=1) + - contentSize: (x=0,y=0) + - anchorPoint: (x=0,y=0) + + Limitations: + - A CCNode is a "void" object. It doesn't have a texture + + Order in transformations with grid disabled + -# The node will be translated (position) + -# The node will be rotated (rotation) + -# The node will be scaled (scale) + -# The node will be moved according to the camera values (camera) + + Order in transformations with grid enabled + -# The node will be translated (position) + -# The node will be rotated (rotation) + -# The node will be scaled (scale) + -# The grid will capture the screen + -# The node will be moved according to the camera values (camera) + -# The grid will render the captured screen + + Camera: + - Each node has a camera. By default it points to the center of the CCNode. + */ +@interface CCNode : NSObject +{ + // rotation angle + float rotation_; + + // scaling factors + float scaleX_, scaleY_; + + // position of the node + CGPoint position_; + CGPoint positionInPixels_; + + // is visible + BOOL visible_; + + // anchor point in pixels + CGPoint anchorPointInPixels_; + // anchor point normalized + CGPoint anchorPoint_; + // If YES the transformtions will be relative to (-transform.x, -transform.y). + // Sprites, Labels and any other "small" object uses it. + // Scenes, Layers and other "whole screen" object don't use it. + BOOL isRelativeAnchorPoint_; + + // untransformed size of the node + CGSize contentSize_; + CGSize contentSizeInPixels_; + + // transform + CGAffineTransform transform_, inverse_; +#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX + GLfloat transformGL_[16]; +#endif + + // openGL real Z vertex + float vertexZ_; + + // a Camera + CCCamera *camera_; + + // a Grid + CCGridBase *grid_; + + // z-order value + NSInteger zOrder_; + + // array of children + CCArray *children_; + + // weakref to parent + CCNode *parent_; + + // a tag. any number you want to assign to the node + NSInteger tag_; + + // user data field + void *userData_; + + // Is running + BOOL isRunning_; + + // To reduce memory, place BOOLs that are not properties here: + BOOL isTransformDirty_:1; + BOOL isInverseDirty_:1; +#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX + BOOL isTransformGLDirty_:1; +#endif +} + +/** The z order of the node relative to it's "brothers": children of the same parent */ +@property(nonatomic,readonly) NSInteger zOrder; +/** The real openGL Z vertex. + Differences between openGL Z vertex and cocos2d Z order: + - OpenGL Z modifies the Z vertex, and not the Z order in the relation between parent-children + - OpenGL Z might require to set 2D projection + - cocos2d Z order works OK if all the nodes uses the same openGL Z vertex. eg: vertexZ = 0 + @warning: Use it at your own risk since it might break the cocos2d parent-children z order + @since v0.8 + */ +@property (nonatomic,readwrite) float vertexZ; +/** The rotation (angle) of the node in degrees. 0 is the default rotation angle. Positive values rotate node CW. */ +@property(nonatomic,readwrite,assign) float rotation; +/** The scale factor of the node. 1.0 is the default scale factor. It modifies the X and Y scale at the same time. */ +@property(nonatomic,readwrite,assign) float scale; +/** The scale factor of the node. 1.0 is the default scale factor. It only modifies the X scale factor. */ +@property(nonatomic,readwrite,assign) float scaleX; +/** The scale factor of the node. 1.0 is the default scale factor. It only modifies the Y scale factor. */ +@property(nonatomic,readwrite,assign) float scaleY; +/** Position (x,y) of the node in points. (0,0) is the left-bottom corner. */ +@property(nonatomic,readwrite,assign) CGPoint position; +/** Position (x,y) of the node in points. (0,0) is the left-bottom corner. */ +@property(nonatomic,readwrite,assign) CGPoint positionInPixels; +/** A CCCamera object that lets you move the node using a gluLookAt +*/ +@property(nonatomic,readonly) CCCamera* camera; +/** Array of children */ +@property(nonatomic,readonly) CCArray *children; +/** A CCGrid object that is used when applying effects */ +@property(nonatomic,readwrite,retain) CCGridBase* grid; +/** Whether of not the node is visible. Default is YES */ +@property(nonatomic,readwrite,assign) BOOL visible; +/** anchorPoint is the point around which all transformations and positioning manipulations take place. + It's like a pin in the node where it is "attached" to its parent. + The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner. + But you can use values higher than (1,1) and lower than (0,0) too. + The default anchorPoint is (0,0). It starts in the bottom-left corner. CCSprite and other subclasses have a different default anchorPoint. + @since v0.8 + */ +@property(nonatomic,readwrite) CGPoint anchorPoint; +/** The anchorPoint in absolute pixels. + Since v0.8 you can only read it. If you wish to modify it, use anchorPoint instead + */ +@property(nonatomic,readonly) CGPoint anchorPointInPixels; + +/** The untransformed size of the node in Points + The contentSize remains the same no matter the node is scaled or rotated. + All nodes has a size. Layer and Scene has the same size of the screen. + @since v0.8 + */ +@property (nonatomic,readwrite) CGSize contentSize; + +/** The untransformed size of the node in Pixels + The contentSize remains the same no matter the node is scaled or rotated. + All nodes has a size. Layer and Scene has the same size of the screen. + @since v0.8 + */ +@property (nonatomic,readwrite) CGSize contentSizeInPixels; + +/** whether or not the node is running */ +@property(nonatomic,readonly) BOOL isRunning; +/** A weak reference to the parent */ +@property(nonatomic,readwrite,assign) CCNode* parent; +/** If YES the transformtions will be relative to it's anchor point. + * Sprites, Labels and any other sizeble object use it have it enabled by default. + * Scenes, Layers and other "whole screen" object don't use it, have it disabled by default. + */ +@property(nonatomic,readwrite,assign) BOOL isRelativeAnchorPoint; +/** A tag used to identify the node easily */ +@property(nonatomic,readwrite,assign) NSInteger tag; +/** A custom user data pointer */ +@property(nonatomic,readwrite,assign) void *userData; + +// initializators +/** allocates and initializes a node. + The node will be created as "autorelease". + */ ++(id) node; +/** initializes the node */ +-(id) init; + + +// scene managment + +/** callback that is called every time the CCNode enters the 'stage'. + If the CCNode enters the 'stage' with a transition, this callback is called when the transition starts. + During onEnter you can't a "sister/brother" node. + */ +-(void) onEnter; +/** callback that is called when the CCNode enters in the 'stage'. + If the CCNode enters the 'stage' with a transition, this callback is called when the transition finishes. + @since v0.8 + */ +-(void) onEnterTransitionDidFinish; +/** callback that is called every time the CCNode leaves the 'stage'. + If the CCNode leaves the 'stage' with a transition, this callback is called when the transition finishes. + During onExit you can't a "sister/brother" node. + */ +-(void) onExit; + + +// composition: ADD + +/** Adds a child to the container with z-order as 0. + If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately. + @since v0.7.1 + */ +-(void) addChild: (CCNode*)node; + +/** Adds a child to the container with a z-order. + If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately. + @since v0.7.1 + */ +-(void) addChild: (CCNode*)node z:(int)z; + +/** Adds a child to the container with z order and tag. + If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately. + @since v0.7.1 + */ +-(void) addChild: (CCNode*)node z:(int)z tag:(int)tag; + +// composition: REMOVE + +/** Remove itself from its parent node. If cleanup is YES, then also remove all actions and callbacks. + If the node orphan, then nothing happens. + @since v0.99.3 + */ +-(void) removeFromParentAndCleanup:(BOOL)cleanup; + +/** Removes a child from the container. It will also cleanup all running actions depending on the cleanup parameter. + @since v0.7.1 + */ +-(void) removeChild: (CCNode*)node cleanup:(BOOL)cleanup; + +/** Removes a child from the container by tag value. It will also cleanup all running actions depending on the cleanup parameter + @since v0.7.1 + */ +-(void) removeChildByTag:(int) tag cleanup:(BOOL)cleanup; + +/** Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter. + @since v0.7.1 + */ +-(void) removeAllChildrenWithCleanup:(BOOL)cleanup; + +// composition: GET +/** Gets a child from the container given its tag + @return returns a CCNode object + @since v0.7.1 + */ +-(CCNode*) getChildByTag:(int) tag; + +/** Reorders a child according to a new z value. + * The child MUST be already added. + */ +-(void) reorderChild:(CCNode*)child z:(int)zOrder; + +/** Stops all running actions and schedulers + @since v0.8 + */ +-(void) cleanup; + +// draw + +/** Override this method to draw your own node. + The following GL states will be enabled by default: + - glEnableClientState(GL_VERTEX_ARRAY); + - glEnableClientState(GL_COLOR_ARRAY); + - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + - glEnable(GL_TEXTURE_2D); + + AND YOU SHOULD NOT DISABLE THEM AFTER DRAWING YOUR NODE + + But if you enable any other GL state, you should disable it after drawing your node. + */ +-(void) draw; +/** recursive method that visit its children and draw them */ +-(void) visit; + +// transformations + +/** performs OpenGL view-matrix transformation based on position, scale, rotation and other attributes. */ +-(void) transform; + +/** performs OpenGL view-matrix transformation of it's ancestors. + Generally the ancestors are already transformed, but in certain cases (eg: attaching a FBO) + it's necessary to transform the ancestors again. + @since v0.7.2 + */ +-(void) transformAncestors; + +/** returns a "local" axis aligned bounding box of the node in points. + The returned box is relative only to its parent. + The returned box is in Points. + + @since v0.8.2 + */ +- (CGRect) boundingBox; + +/** returns a "local" axis aligned bounding box of the node in pixels. + The returned box is relative only to its parent. + The returned box is in Points. + + @since v0.99.5 + */ +- (CGRect) boundingBoxInPixels; + + +// actions + +/** Executes an action, and returns the action that is executed. + The node becomes the action's target. + @warning Starting from v0.8 actions don't retain their target anymore. + @since v0.7.1 + @return An Action pointer + */ +-(CCAction*) runAction: (CCAction*) action; +/** Removes all actions from the running action list */ +-(void) stopAllActions; +/** Removes an action from the running action list */ +-(void) stopAction: (CCAction*) action; +/** Removes an action from the running action list given its tag + @since v0.7.1 +*/ +-(void) stopActionByTag:(int) tag; +/** Gets an action from the running action list given its tag + @since v0.7.1 + @return the Action the with the given tag + */ +-(CCAction*) getActionByTag:(int) tag; +/** Returns the numbers of actions that are running plus the ones that are schedule to run (actions in actionsToAdd and actions arrays). + * 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. + */ +-(int) numberOfRunningActions; + +// timers + +/** check whether a selector is scheduled. */ +//-(BOOL) isScheduled: (SEL) selector; + +/** schedules the "update" method. It will use the order number 0. This method will be called every frame. + Scheduled methods with a lower order value will be called before the ones that have a higher order value. + Only one "udpate" method could be scheduled per node. + + @since v0.99.3 + */ +-(void) scheduleUpdate; + +/** schedules the "update" selector with a custom priority. This selector will be called every frame. + Scheduled selectors with a lower priority will be called before the ones that have a higher value. + Only one "udpate" selector could be scheduled per node (You can't have 2 'update' selectors). + + @since v0.99.3 + */ +-(void) scheduleUpdateWithPriority:(int)priority; + +/* unschedules the "update" method. + + @since v0.99.3 + */ +-(void) unscheduleUpdate; + + +/** schedules a selector. + The scheduled selector will be ticked every frame + */ +-(void) schedule: (SEL) s; +/** schedules a custom selector with an interval time in seconds. + If time is 0 it will be ticked every frame. + If time is 0, it is recommended to use 'scheduleUpdate' instead. + + If the selector is already scheduled, then the interval parameter will be updated without scheduling it again. + */ +-(void) schedule: (SEL) s interval:(ccTime)seconds; +/** unschedules a custom selector.*/ +-(void) unschedule: (SEL) s; + +/** unschedule all scheduled selectors: custom selectors, and the 'update' selector. + Actions are not affected by this method. +@since v0.99.3 + */ +-(void) unscheduleAllSelectors; + +/** resumes all scheduled selectors and actions. + Called internally by onEnter + */ +-(void) resumeSchedulerAndActions; +/** pauses all scheduled selectors and actions. + Called internally by onExit + */ +-(void) pauseSchedulerAndActions; + + +// transformation methods + +/** Returns the matrix that transform the node's (local) space coordinates into the parent's space coordinates. + The matrix is in Pixels. + @since v0.7.1 + */ +- (CGAffineTransform)nodeToParentTransform; +/** Returns the matrix that transform parent's space coordinates to the node's (local) space coordinates. + The matrix is in Pixels. + @since v0.7.1 + */ +- (CGAffineTransform)parentToNodeTransform; +/** Retrusn the world affine transform matrix. The matrix is in Pixels. + @since v0.7.1 + */ +- (CGAffineTransform)nodeToWorldTransform; +/** Returns the inverse world affine transform matrix. The matrix is in Pixels. + @since v0.7.1 + */ +- (CGAffineTransform)worldToNodeTransform; +/** Converts a Point to node (local) space coordinates. The result is in Points. + @since v0.7.1 + */ +- (CGPoint)convertToNodeSpace:(CGPoint)worldPoint; +/** Converts a Point to world space coordinates. The result is in Points. + @since v0.7.1 + */ +- (CGPoint)convertToWorldSpace:(CGPoint)nodePoint; +/** Converts a Point to node (local) space coordinates. The result is in Points. + treating the returned/received node point as anchor relative. + @since v0.7.1 + */ +- (CGPoint)convertToNodeSpaceAR:(CGPoint)worldPoint; +/** Converts a local Point to world space coordinates.The result is in Points. + treating the returned/received node point as anchor relative. + @since v0.7.1 + */ +- (CGPoint)convertToWorldSpaceAR:(CGPoint)nodePoint; + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +/** Converts a UITouch to node (local) space coordinates. The result is in Points. + @since v0.7.1 + */ +- (CGPoint)convertTouchToNodeSpace:(UITouch *)touch; +/** Converts a UITouch to node (local) space coordinates. The result is in Points. + This method is AR (Anchor Relative).. + @since v0.7.1 + */ +- (CGPoint)convertTouchToNodeSpaceAR:(UITouch *)touch; +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED +@end diff --git a/Classes/cocos2d/CCNode.m b/Classes/cocos2d/CCNode.m new file mode 100644 index 0000000..5392905 --- /dev/null +++ b/Classes/cocos2d/CCNode.m @@ -0,0 +1,883 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2009 Valentin Milea + * + * 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. + */ + +#import "CCNode.h" +#import "CCGrid.h" +#import "CCDirector.h" +#import "CCActionManager.h" +#import "CCCamera.h" +#import "CCScheduler.h" +#import "ccConfig.h" +#import "ccMacros.h" +#import "Support/CGPointExtension.h" +#import "Support/ccCArray.h" +#import "Support/TransformUtils.h" +#import "ccMacros.h" + +#import +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +#import "Platforms/iOS/CCDirectorIOS.h" +#endif + + +#if CC_COCOSNODE_RENDER_SUBPIXEL +#define RENDER_IN_SUBPIXEL +#else +#define RENDER_IN_SUBPIXEL (NSInteger) +#endif + +@interface CCNode () +// lazy allocs +-(void) childrenAlloc; +// helper that reorder a child +-(void) insertChild:(CCNode*)child z:(int)z; +// used internally to alter the zOrder variable. DON'T call this method manually +-(void) _setZOrder:(int) z; +-(void) detachChild:(CCNode *)child cleanup:(BOOL)doCleanup; +@end + +@implementation CCNode + +@synthesize children = children_; +@synthesize visible = visible_; +@synthesize parent = parent_; +@synthesize grid = grid_; +@synthesize zOrder = zOrder_; +@synthesize tag = tag_; +@synthesize vertexZ = vertexZ_; +@synthesize isRunning = isRunning_; +@synthesize userData = userData_; + +#pragma mark CCNode - Transform related properties + +@synthesize rotation = rotation_, scaleX = scaleX_, scaleY = scaleY_; +@synthesize position = position_, positionInPixels = positionInPixels_; +@synthesize anchorPoint = anchorPoint_, anchorPointInPixels = anchorPointInPixels_; +@synthesize contentSize = contentSize_, contentSizeInPixels = contentSizeInPixels_; +@synthesize isRelativeAnchorPoint = isRelativeAnchorPoint_; + +// getters synthesized, setters explicit +-(void) setRotation: (float)newRotation +{ + rotation_ = newRotation; + isTransformDirty_ = isInverseDirty_ = YES; +#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX + isTransformGLDirty_ = YES; +#endif +} + +-(void) setScaleX: (float)newScaleX +{ + scaleX_ = newScaleX; + isTransformDirty_ = isInverseDirty_ = YES; +#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX + isTransformGLDirty_ = YES; +#endif +} + +-(void) setScaleY: (float)newScaleY +{ + scaleY_ = newScaleY; + isTransformDirty_ = isInverseDirty_ = YES; +#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX + isTransformGLDirty_ = YES; +#endif +} + +-(void) setPosition: (CGPoint)newPosition +{ + position_ = newPosition; + if( CC_CONTENT_SCALE_FACTOR() == 1 ) + positionInPixels_ = position_; + else + positionInPixels_ = ccpMult( newPosition, CC_CONTENT_SCALE_FACTOR() ); + + isTransformDirty_ = isInverseDirty_ = YES; +#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX + isTransformGLDirty_ = YES; +#endif +} + +-(void) setPositionInPixels:(CGPoint)newPosition +{ + positionInPixels_ = newPosition; + + if( CC_CONTENT_SCALE_FACTOR() == 1 ) + position_ = positionInPixels_; + else + position_ = ccpMult( newPosition, 1/CC_CONTENT_SCALE_FACTOR() ); + + isTransformDirty_ = isInverseDirty_ = YES; +#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX + isTransformGLDirty_ = YES; +#endif +} + +-(void) setIsRelativeAnchorPoint: (BOOL)newValue +{ + isRelativeAnchorPoint_ = newValue; + isTransformDirty_ = isInverseDirty_ = YES; +#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX + isTransformGLDirty_ = YES; +#endif +} + +-(void) setAnchorPoint:(CGPoint)point +{ + if( ! CGPointEqualToPoint(point, anchorPoint_) ) { + anchorPoint_ = point; + anchorPointInPixels_ = ccp( contentSizeInPixels_.width * anchorPoint_.x, contentSizeInPixels_.height * anchorPoint_.y ); + isTransformDirty_ = isInverseDirty_ = YES; +#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX + isTransformGLDirty_ = YES; +#endif + } +} + +-(void) setContentSize:(CGSize)size +{ + if( ! CGSizeEqualToSize(size, contentSize_) ) { + contentSize_ = size; + + if( CC_CONTENT_SCALE_FACTOR() == 1 ) + contentSizeInPixels_ = contentSize_; + else + contentSizeInPixels_ = CGSizeMake( size.width * CC_CONTENT_SCALE_FACTOR(), size.height * CC_CONTENT_SCALE_FACTOR() ); + + anchorPointInPixels_ = ccp( contentSizeInPixels_.width * anchorPoint_.x, contentSizeInPixels_.height * anchorPoint_.y ); + isTransformDirty_ = isInverseDirty_ = YES; +#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX + isTransformGLDirty_ = YES; +#endif + } +} + +-(void) setContentSizeInPixels:(CGSize)size +{ + if( ! CGSizeEqualToSize(size, contentSizeInPixels_) ) { + contentSizeInPixels_ = size; + + if( CC_CONTENT_SCALE_FACTOR() == 1 ) + contentSize_ = contentSizeInPixels_; + else + contentSize_ = CGSizeMake( size.width / CC_CONTENT_SCALE_FACTOR(), size.height / CC_CONTENT_SCALE_FACTOR() ); + + anchorPointInPixels_ = ccp( contentSizeInPixels_.width * anchorPoint_.x, contentSizeInPixels_.height * anchorPoint_.y ); + isTransformDirty_ = isInverseDirty_ = YES; +#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX + isTransformGLDirty_ = YES; +#endif + } +} + +- (CGRect) boundingBox +{ + CGRect ret = [self boundingBoxInPixels]; + return CC_RECT_PIXELS_TO_POINTS( ret ); +} + +- (CGRect) boundingBoxInPixels +{ + CGRect rect = CGRectMake(0, 0, contentSizeInPixels_.width, contentSizeInPixels_.height); + return CGRectApplyAffineTransform(rect, [self nodeToParentTransform]); +} + +-(void) setVertexZ:(float)vertexZ +{ + vertexZ_ = vertexZ * CC_CONTENT_SCALE_FACTOR(); +} + +-(float) scale +{ + NSAssert( scaleX_ == scaleY_, @"CCNode#scale. ScaleX != ScaleY. Don't know which one to return"); + return scaleX_; +} + +-(void) setScale:(float) s +{ + scaleX_ = scaleY_ = s; + isTransformDirty_ = isInverseDirty_ = YES; +#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX + isTransformGLDirty_ = YES; +#endif +} + +#pragma mark CCNode - Init & cleanup + ++(id) node +{ + return [[[self alloc] init] autorelease]; +} + +-(id) init +{ + if ((self=[super init]) ) { + + isRunning_ = NO; + + rotation_ = 0.0f; + scaleX_ = scaleY_ = 1.0f; + positionInPixels_ = position_ = CGPointZero; + anchorPointInPixels_ = anchorPoint_ = CGPointZero; + contentSizeInPixels_ = contentSize_ = CGSizeZero; + + + // "whole screen" objects. like Scenes and Layers, should set isRelativeAnchorPoint to NO + isRelativeAnchorPoint_ = YES; + + isTransformDirty_ = isInverseDirty_ = YES; +#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX + isTransformGLDirty_ = YES; +#endif + + vertexZ_ = 0; + + grid_ = nil; + + visible_ = YES; + + tag_ = kCCNodeTagInvalid; + + zOrder_ = 0; + + // lazy alloc + camera_ = nil; + + // children (lazy allocs) + children_ = nil; + + // userData is always inited as nil + userData_ = nil; + + //initialize parent to nil + parent_ = nil; + } + + return self; +} + +- (void)cleanup +{ + // actions + [self stopAllActions]; + [self unscheduleAllSelectors]; + + // timers + [children_ makeObjectsPerformSelector:@selector(cleanup)]; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %08X | Tag = %i>", [self class], self, tag_]; +} + +- (void) dealloc +{ + CCLOGINFO( @"cocos2d: deallocing %@", self); + + // attributes + [camera_ release]; + + [grid_ release]; + + // children + CCNode *child; + CCARRAY_FOREACH(children_, child) + child.parent = nil; + + [children_ release]; + + [super dealloc]; +} + +#pragma mark CCNode Composition + +-(void) childrenAlloc +{ + children_ = [[CCArray alloc] initWithCapacity:4]; +} + +// camera: lazy alloc +-(CCCamera*) camera +{ + if( ! camera_ ) { + camera_ = [[CCCamera alloc] init]; + + // by default, center camera at the Sprite's anchor point + // [camera_ setCenterX:anchorPointInPixels_.x centerY:anchorPointInPixels_.y centerZ:0]; + // [camera_ setEyeX:anchorPointInPixels_.x eyeY:anchorPointInPixels_.y eyeZ:1]; + + // [camera_ setCenterX:0 centerY:0 centerZ:0]; + // [camera_ setEyeX:0 eyeY:0 eyeZ:1]; + + } + + return camera_; +} + +-(CCNode*) getChildByTag:(int) aTag +{ + NSAssert( aTag != kCCNodeTagInvalid, @"Invalid tag"); + + CCNode *node; + CCARRAY_FOREACH(children_, node){ + if( node.tag == aTag ) + return node; + } + // not found + return nil; +} + +/* "add" logic MUST only be on this method + * If a class want's to extend the 'addChild' behaviour it only needs + * to override this method + */ +-(void) addChild: (CCNode*) child z:(int)z tag:(int) aTag +{ + NSAssert( child != nil, @"Argument must be non-nil"); + NSAssert( child.parent == nil, @"child already added. It can't be added again"); + + if( ! children_ ) + [self childrenAlloc]; + + [self insertChild:child z:z]; + + child.tag = aTag; + + [child setParent: self]; + + if( isRunning_ ) { + [child onEnter]; + [child onEnterTransitionDidFinish]; + } +} + +-(void) addChild: (CCNode*) child z:(int)z +{ + NSAssert( child != nil, @"Argument must be non-nil"); + [self addChild:child z:z tag:child.tag]; +} + +-(void) addChild: (CCNode*) child +{ + NSAssert( child != nil, @"Argument must be non-nil"); + [self addChild:child z:child.zOrder tag:child.tag]; +} + +-(void) removeFromParentAndCleanup:(BOOL)cleanup +{ + [parent_ removeChild:self cleanup:cleanup]; +} + +/* "remove" logic MUST only be on this method + * If a class want's to extend the 'removeChild' behavior it only needs + * to override this method + */ +-(void) removeChild: (CCNode*)child cleanup:(BOOL)cleanup +{ + // explicit nil handling + if (child == nil) + return; + + if ( [children_ containsObject:child] ) + [self detachChild:child cleanup:cleanup]; +} + +-(void) removeChildByTag:(int)aTag cleanup:(BOOL)cleanup +{ + NSAssert( aTag != kCCNodeTagInvalid, @"Invalid tag"); + + CCNode *child = [self getChildByTag:aTag]; + + if (child == nil) + CCLOG(@"cocos2d: removeChildByTag: child not found!"); + else + [self removeChild:child cleanup:cleanup]; +} + +-(void) removeAllChildrenWithCleanup:(BOOL)cleanup +{ + // not using detachChild improves speed here + CCNode *c; + CCARRAY_FOREACH(children_, c) + { + // IMPORTANT: + // -1st do onExit + // -2nd cleanup + if (isRunning_) + [c onExit]; + + if (cleanup) + [c cleanup]; + + // set parent nil at the end (issue #476) + [c setParent:nil]; + } + + [children_ removeAllObjects]; +} + +-(void) detachChild:(CCNode *)child cleanup:(BOOL)doCleanup +{ + // IMPORTANT: + // -1st do onExit + // -2nd cleanup + if (isRunning_) + [child onExit]; + + // If you don't do cleanup, the child's actions will not get removed and the + // its scheduledSelectors_ dict will not get released! + if (doCleanup) + [child cleanup]; + + // set parent nil at the end (issue #476) + [child setParent:nil]; + + [children_ removeObject:child]; +} + +// used internally to alter the zOrder variable. DON'T call this method manually +-(void) _setZOrder:(int) z +{ + zOrder_ = z; +} + +// helper used by reorderChild & add +-(void) insertChild:(CCNode*)child z:(int)z +{ + NSUInteger index=0; + CCNode *a = [children_ lastObject]; + + // quick comparison to improve performance + if (!a || a.zOrder <= z) + [children_ addObject:child]; + + else + { + CCARRAY_FOREACH(children_, a) { + if ( a.zOrder > z ) { + [children_ insertObject:child atIndex:index]; + break; + } + index++; + } + } + + [child _setZOrder:z]; +} + +-(void) reorderChild:(CCNode*) child z:(int)z +{ + NSAssert( child != nil, @"Child must be non-nil"); + + [child retain]; + [children_ removeObject:child]; + + [self insertChild:child z:z]; + + [child release]; +} + +#pragma mark CCNode Draw + +-(void) draw +{ + // override me + // Only use this function to draw your staff. + // DON'T draw your stuff outside this method +} + +-(void) visit +{ + // quick return if not visible + if (!visible_) + return; + + glPushMatrix(); + + if ( grid_ && grid_.active) { + [grid_ beforeDraw]; + [self transformAncestors]; + } + + [self transform]; + + if(children_) { + ccArray *arrayData = children_->data; + NSUInteger i = 0; + + // draw children zOrder < 0 + for( ; i < arrayData->num; i++ ) { + CCNode *child = arrayData->arr[i]; + if ( [child zOrder] < 0 ) + [child visit]; + else + break; + } + + // self draw + [self draw]; + + // draw children zOrder >= 0 + for( ; i < arrayData->num; i++ ) { + CCNode *child = arrayData->arr[i]; + [child visit]; + } + + } else + [self draw]; + + if ( grid_ && grid_.active) + [grid_ afterDraw:self]; + + glPopMatrix(); +} + +#pragma mark CCNode - Transformations + +-(void) transformAncestors +{ + if( parent_ ) { + [parent_ transformAncestors]; + [parent_ transform]; + } +} + +-(void) transform +{ + // transformations + +#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX + // BEGIN alternative -- using cached transform + // + if( isTransformGLDirty_ ) { + CGAffineTransform t = [self nodeToParentTransform]; + CGAffineToGL(&t, transformGL_); + isTransformGLDirty_ = NO; + } + + glMultMatrixf(transformGL_); + if( vertexZ_ ) + glTranslatef(0, 0, vertexZ_); + + // XXX: Expensive calls. Camera should be integrated into the cached affine matrix + if ( camera_ && !(grid_ && grid_.active) ) + { + BOOL translate = (anchorPointInPixels_.x != 0.0f || anchorPointInPixels_.y != 0.0f); + + if( translate ) + ccglTranslate(RENDER_IN_SUBPIXEL(anchorPointInPixels_.x), RENDER_IN_SUBPIXEL(anchorPointInPixels_.y), 0); + + [camera_ locate]; + + if( translate ) + ccglTranslate(RENDER_IN_SUBPIXEL(-anchorPointInPixels_.x), RENDER_IN_SUBPIXEL(-anchorPointInPixels_.y), 0); + } + + + // END alternative + +#else + // BEGIN original implementation + // + // translate + if ( isRelativeAnchorPoint_ && (anchorPointInPixels_.x != 0 || anchorPointInPixels_.y != 0 ) ) + glTranslatef( RENDER_IN_SUBPIXEL(-anchorPointInPixels_.x), RENDER_IN_SUBPIXEL(-anchorPointInPixels_.y), 0); + + if (anchorPointInPixels_.x != 0 || anchorPointInPixels_.y != 0) + glTranslatef( RENDER_IN_SUBPIXEL(positionInPixels_.x + anchorPointInPixels_.x), RENDER_IN_SUBPIXEL(positionInPixels_.y + anchorPointInPixels_.y), vertexZ_); + else if ( positionInPixels_.x !=0 || positionInPixels_.y !=0 || vertexZ_ != 0) + glTranslatef( RENDER_IN_SUBPIXEL(positionInPixels_.x), RENDER_IN_SUBPIXEL(positionInPixels_.y), vertexZ_ ); + + // rotate + if (rotation_ != 0.0f ) + glRotatef( -rotation_, 0.0f, 0.0f, 1.0f ); + + // scale + if (scaleX_ != 1.0f || scaleY_ != 1.0f) + glScalef( scaleX_, scaleY_, 1.0f ); + + if ( camera_ && !(grid_ && grid_.active) ) + [camera_ locate]; + + // restore and re-position point + if (anchorPointInPixels_.x != 0.0f || anchorPointInPixels_.y != 0.0f) + glTranslatef(RENDER_IN_SUBPIXEL(-anchorPointInPixels_.x), RENDER_IN_SUBPIXEL(-anchorPointInPixels_.y), 0); + + // + // END original implementation +#endif + +} + +#pragma mark CCNode SceneManagement + +-(void) onEnter +{ + [children_ makeObjectsPerformSelector:@selector(onEnter)]; + [self resumeSchedulerAndActions]; + + isRunning_ = YES; +} + +-(void) onEnterTransitionDidFinish +{ + [children_ makeObjectsPerformSelector:@selector(onEnterTransitionDidFinish)]; +} + +-(void) onExit +{ + [self pauseSchedulerAndActions]; + isRunning_ = NO; + + [children_ makeObjectsPerformSelector:@selector(onExit)]; +} + +#pragma mark CCNode Actions + +-(CCAction*) runAction:(CCAction*) action +{ + NSAssert( action != nil, @"Argument must be non-nil"); + + [[CCActionManager sharedManager] addAction:action target:self paused:!isRunning_]; + return action; +} + +-(void) stopAllActions +{ + [[CCActionManager sharedManager] removeAllActionsFromTarget:self]; +} + +-(void) stopAction: (CCAction*) action +{ + [[CCActionManager sharedManager] removeAction:action]; +} + +-(void) stopActionByTag:(int)aTag +{ + NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag"); + [[CCActionManager sharedManager] removeActionByTag:aTag target:self]; +} + +-(CCAction*) getActionByTag:(int) aTag +{ + NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag"); + return [[CCActionManager sharedManager] getActionByTag:aTag target:self]; +} + +-(int) numberOfRunningActions +{ + return [[CCActionManager sharedManager] numberOfRunningActionsInTarget:self]; +} + +#pragma mark CCNode - Scheduler + +-(void) scheduleUpdate +{ + [self scheduleUpdateWithPriority:0]; +} + +-(void) scheduleUpdateWithPriority:(int)priority +{ + [[CCScheduler sharedScheduler] scheduleUpdateForTarget:self priority:priority paused:!isRunning_]; +} + +-(void) unscheduleUpdate +{ + [[CCScheduler sharedScheduler] unscheduleUpdateForTarget:self]; +} + +-(void) schedule:(SEL)selector +{ + [self schedule:selector interval:0]; +} + +-(void) schedule:(SEL)selector interval:(ccTime)interval +{ + NSAssert( selector != nil, @"Argument must be non-nil"); + NSAssert( interval >=0, @"Arguemnt must be positive"); + + [[CCScheduler sharedScheduler] scheduleSelector:selector forTarget:self interval:interval paused:!isRunning_]; +} + +-(void) unschedule:(SEL)selector +{ + // explicit nil handling + if (selector == nil) + return; + + [[CCScheduler sharedScheduler] unscheduleSelector:selector forTarget:self]; +} + +-(void) unscheduleAllSelectors +{ + [[CCScheduler sharedScheduler] unscheduleAllSelectorsForTarget:self]; +} +- (void) resumeSchedulerAndActions +{ + [[CCScheduler sharedScheduler] resumeTarget:self]; + [[CCActionManager sharedManager] resumeTarget:self]; +} + +- (void) pauseSchedulerAndActions +{ + [[CCScheduler sharedScheduler] pauseTarget:self]; + [[CCActionManager sharedManager] pauseTarget:self]; +} + +#pragma mark CCNode Transform + +- (CGAffineTransform)nodeToParentTransform +{ + if ( isTransformDirty_ ) { + + transform_ = CGAffineTransformIdentity; + + if ( !isRelativeAnchorPoint_ && !CGPointEqualToPoint(anchorPointInPixels_, CGPointZero) ) + transform_ = CGAffineTransformTranslate(transform_, anchorPointInPixels_.x, anchorPointInPixels_.y); + + if( ! CGPointEqualToPoint(positionInPixels_, CGPointZero) ) + transform_ = CGAffineTransformTranslate(transform_, positionInPixels_.x, positionInPixels_.y); + + if( rotation_ != 0 ) + transform_ = CGAffineTransformRotate(transform_, -CC_DEGREES_TO_RADIANS(rotation_)); + + if( ! (scaleX_ == 1 && scaleY_ == 1) ) + transform_ = CGAffineTransformScale(transform_, scaleX_, scaleY_); + + if( ! CGPointEqualToPoint(anchorPointInPixels_, CGPointZero) ) + transform_ = CGAffineTransformTranslate(transform_, -anchorPointInPixels_.x, -anchorPointInPixels_.y); + + isTransformDirty_ = NO; + } + + return transform_; +} + +- (CGAffineTransform)parentToNodeTransform +{ + if ( isInverseDirty_ ) { + inverse_ = CGAffineTransformInvert([self nodeToParentTransform]); + isInverseDirty_ = NO; + } + + return inverse_; +} + +- (CGAffineTransform)nodeToWorldTransform +{ + CGAffineTransform t = [self nodeToParentTransform]; + + for (CCNode *p = parent_; p != nil; p = p.parent) + t = CGAffineTransformConcat(t, [p nodeToParentTransform]); + + return t; +} + +- (CGAffineTransform)worldToNodeTransform +{ + return CGAffineTransformInvert([self nodeToWorldTransform]); +} + +- (CGPoint)convertToNodeSpace:(CGPoint)worldPoint +{ + CGPoint ret; + if( CC_CONTENT_SCALE_FACTOR() == 1 ) + ret = CGPointApplyAffineTransform(worldPoint, [self worldToNodeTransform]); + else { + ret = ccpMult( worldPoint, CC_CONTENT_SCALE_FACTOR() ); + ret = CGPointApplyAffineTransform(ret, [self worldToNodeTransform]); + ret = ccpMult( ret, 1/CC_CONTENT_SCALE_FACTOR() ); + } + + return ret; +} + +- (CGPoint)convertToWorldSpace:(CGPoint)nodePoint +{ + CGPoint ret; + if( CC_CONTENT_SCALE_FACTOR() == 1 ) + ret = CGPointApplyAffineTransform(nodePoint, [self nodeToWorldTransform]); + else { + ret = ccpMult( nodePoint, CC_CONTENT_SCALE_FACTOR() ); + ret = CGPointApplyAffineTransform(ret, [self nodeToWorldTransform]); + ret = ccpMult( ret, 1/CC_CONTENT_SCALE_FACTOR() ); + } + + return ret; +} + +- (CGPoint)convertToNodeSpaceAR:(CGPoint)worldPoint +{ + CGPoint nodePoint = [self convertToNodeSpace:worldPoint]; + CGPoint anchorInPoints; + if( CC_CONTENT_SCALE_FACTOR() == 1 ) + anchorInPoints = anchorPointInPixels_; + else + anchorInPoints = ccpMult( anchorPointInPixels_, 1/CC_CONTENT_SCALE_FACTOR() ); + + return ccpSub(nodePoint, anchorInPoints); +} + +- (CGPoint)convertToWorldSpaceAR:(CGPoint)nodePoint +{ + CGPoint anchorInPoints; + if( CC_CONTENT_SCALE_FACTOR() == 1 ) + anchorInPoints = anchorPointInPixels_; + else + anchorInPoints = ccpMult( anchorPointInPixels_, 1/CC_CONTENT_SCALE_FACTOR() ); + + nodePoint = ccpAdd(nodePoint, anchorInPoints); + return [self convertToWorldSpace:nodePoint]; +} + +- (CGPoint)convertToWindowSpace:(CGPoint)nodePoint +{ + CGPoint worldPoint = [self convertToWorldSpace:nodePoint]; + return [[CCDirector sharedDirector] convertToUI:worldPoint]; +} + +// convenience methods which take a UITouch instead of CGPoint + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + +- (CGPoint)convertTouchToNodeSpace:(UITouch *)touch +{ + CGPoint point = [touch locationInView: [touch view]]; + point = [[CCDirector sharedDirector] convertToGL: point]; + return [self convertToNodeSpace:point]; +} + +- (CGPoint)convertTouchToNodeSpaceAR:(UITouch *)touch +{ + CGPoint point = [touch locationInView: [touch view]]; + point = [[CCDirector sharedDirector] convertToGL: point]; + return [self convertToNodeSpaceAR:point]; +} + +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED + + +@end diff --git a/Classes/cocos2d/CCParallaxNode.h b/Classes/cocos2d/CCParallaxNode.h new file mode 100644 index 0000000..c41b304 --- /dev/null +++ b/Classes/cocos2d/CCParallaxNode.h @@ -0,0 +1,49 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009-2010 Ricardo Quesada + * + * 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. + * + */ + +#import "CCNode.h" +#import "Support/ccCArray.h" + +/** CCParallaxNode: A node that simulates a parallax scroller + + The children will be moved faster / slower than the parent according the the parallax ratio. + + */ +@interface CCParallaxNode : CCNode +{ + ccArray *parallaxArray_; + CGPoint lastPosition; +} + +/** array that holds the offset / ratio of the children */ +@property (nonatomic,readwrite) ccArray * parallaxArray; + +/** Adds a child to the container with a z-order, a parallax ratio and a position offset + It returns self, so you can chain several addChilds. + @since v0.8 + */ +-(void) addChild: (CCNode*)node z:(int)z parallaxRatio:(CGPoint)c positionOffset:(CGPoint)positionOffset; + +@end diff --git a/Classes/cocos2d/CCParallaxNode.m b/Classes/cocos2d/CCParallaxNode.m new file mode 100644 index 0000000..20f573c --- /dev/null +++ b/Classes/cocos2d/CCParallaxNode.m @@ -0,0 +1,160 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009-2010 Ricardo Quesada + * + * 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. + * + */ + +#import "CCParallaxNode.h" +#import "Support/CGPointExtension.h" +#import "Support/ccCArray.h" + +@interface CGPointObject : NSObject +{ + CGPoint ratio_; + CGPoint offset_; + CCNode *child_; // weak ref +} +@property (readwrite) CGPoint ratio; +@property (readwrite) CGPoint offset; +@property (readwrite,assign) CCNode *child; ++(id) pointWithCGPoint:(CGPoint)point offset:(CGPoint)offset; +-(id) initWithCGPoint:(CGPoint)point offset:(CGPoint)offset; +@end +@implementation CGPointObject +@synthesize ratio = ratio_; +@synthesize offset = offset_; +@synthesize child=child_; + ++(id) pointWithCGPoint:(CGPoint)ratio offset:(CGPoint)offset +{ + return [[[self alloc] initWithCGPoint:ratio offset:offset] autorelease]; +} +-(id) initWithCGPoint:(CGPoint)ratio offset:(CGPoint)offset +{ + if( (self=[super init])) { + ratio_ = ratio; + offset_ = offset; + } + return self; +} +@end + +@implementation CCParallaxNode + +@synthesize parallaxArray = parallaxArray_; + +-(id) init +{ + if( (self=[super init]) ) { + parallaxArray_ = ccArrayNew(5); + lastPosition = CGPointMake(-100,-100); + } + return self; +} + +- (void) dealloc +{ + if( parallaxArray_ ) { + ccArrayFree(parallaxArray_); + parallaxArray_ = nil; + } + [super dealloc]; +} + +-(void) addChild:(CCNode*)child z:(int)z tag:(int)tag +{ + NSAssert(NO,@"ParallaxNode: use addChild:z:parallaxRatio:positionOffset instead"); +} + +-(void) addChild: (CCNode*) child z:(int)z parallaxRatio:(CGPoint)ratio positionOffset:(CGPoint)offset +{ + NSAssert( child != nil, @"Argument must be non-nil"); + CGPointObject *obj = [CGPointObject pointWithCGPoint:ratio offset:offset]; + obj.child = child; + ccArrayAppendObjectWithResize(parallaxArray_, obj); + + CGPoint pos = self.position; + pos.x = pos.x * ratio.x + offset.x; + pos.y = pos.y * ratio.y + offset.y; + child.position = pos; + + [super addChild: child z:z tag:child.tag]; +} + +-(void) removeChild:(CCNode*)node cleanup:(BOOL)cleanup +{ + for( unsigned int i=0;i < parallaxArray_->num;i++) { + CGPointObject *point = parallaxArray_->arr[i]; + if( [point.child isEqual:node] ) { + ccArrayRemoveObjectAtIndex(parallaxArray_, i); + break; + } + } + [super removeChild:node cleanup:cleanup]; +} + +-(void) removeAllChildrenWithCleanup:(BOOL)cleanup +{ + ccArrayRemoveAllObjects(parallaxArray_); + [super removeAllChildrenWithCleanup:cleanup]; +} + +-(CGPoint) absolutePosition_ +{ + CGPoint ret = position_; + + CCNode *cn = self; + + while (cn.parent != nil) { + cn = cn.parent; + ret = ccpAdd( ret, cn.position ); + } + + return ret; +} + +/* + The positions are updated at visit because: + - using a timer is not guaranteed that it will called after all the positions were updated + - overriding "draw" will only precise if the children have a z > 0 +*/ +-(void) visit +{ +// CGPoint pos = position_; +// CGPoint pos = [self convertToWorldSpace:CGPointZero]; + CGPoint pos = [self absolutePosition_]; + if( ! CGPointEqualToPoint(pos, lastPosition) ) { + + for(unsigned int i=0; i < parallaxArray_->num; i++ ) { + + CGPointObject *point = parallaxArray_->arr[i]; + float x = -pos.x + pos.x * point.ratio.x + point.offset.x; + float y = -pos.y + pos.y * point.ratio.y + point.offset.y; + point.child.position = ccp(x,y); + } + + lastPosition = pos; + } + + [super visit]; +} +@end diff --git a/Classes/cocos2d/CCParticleExamples.h b/Classes/cocos2d/CCParticleExamples.h new file mode 100644 index 0000000..b28fca9 --- /dev/null +++ b/Classes/cocos2d/CCParticleExamples.h @@ -0,0 +1,110 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + +#import + +#import "CCParticleSystemPoint.h" +#import "CCParticleSystemQuad.h" + +// build each architecture with the optimal particle system + +// ARMv7, Mac or Simulator use "Quad" particle +#if defined(__ARM_NEON__) || defined(__MAC_OS_X_VERSION_MAX_ALLOWED) || TARGET_IPHONE_SIMULATOR + #define ARCH_OPTIMAL_PARTICLE_SYSTEM CCParticleSystemQuad + +// ARMv6 use "Point" particle +#elif __arm__ + #define ARCH_OPTIMAL_PARTICLE_SYSTEM CCParticleSystemPoint +#else + #error(unknown architecture) +#endif + + +//! A fire particle system +@interface CCParticleFire: ARCH_OPTIMAL_PARTICLE_SYSTEM +{ +} +@end + +//! A fireworks particle system +@interface CCParticleFireworks : ARCH_OPTIMAL_PARTICLE_SYSTEM +{ +} +@end + +//! A sun particle system +@interface CCParticleSun : ARCH_OPTIMAL_PARTICLE_SYSTEM +{ +} +@end + +//! A galaxy particle system +@interface CCParticleGalaxy : ARCH_OPTIMAL_PARTICLE_SYSTEM +{ +} +@end + +//! A flower particle system +@interface CCParticleFlower : ARCH_OPTIMAL_PARTICLE_SYSTEM +{ +} +@end + +//! A meteor particle system +@interface CCParticleMeteor : ARCH_OPTIMAL_PARTICLE_SYSTEM +{ +} +@end + +//! An spiral particle system +@interface CCParticleSpiral : ARCH_OPTIMAL_PARTICLE_SYSTEM +{ +} +@end + +//! An explosion particle system +@interface CCParticleExplosion : ARCH_OPTIMAL_PARTICLE_SYSTEM +{ +} +@end + +//! An smoke particle system +@interface CCParticleSmoke : ARCH_OPTIMAL_PARTICLE_SYSTEM +{ +} +@end + +//! An snow particle system +@interface CCParticleSnow : ARCH_OPTIMAL_PARTICLE_SYSTEM +{ +} +@end + +//! A rain particle system +@interface CCParticleRain : ARCH_OPTIMAL_PARTICLE_SYSTEM +{ +} +@end diff --git a/Classes/cocos2d/CCParticleExamples.m b/Classes/cocos2d/CCParticleExamples.m new file mode 100644 index 0000000..c3b8f8f --- /dev/null +++ b/Classes/cocos2d/CCParticleExamples.m @@ -0,0 +1,925 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + +// cocos2d +#import "CCParticleExamples.h" +#import "CCTextureCache.h" +#import "CCDirector.h" +#import "Support/CGPointExtension.h" + +// +// ParticleFireworks +// +@implementation CCParticleFireworks +-(id) init +{ + return [self initWithTotalParticles:1500]; +} + +-(id) initWithTotalParticles:(int)p +{ + if( (self=[super initWithTotalParticles:p]) ) { + // duration + duration = kCCParticleDurationInfinity; + + // Gravity Mode + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,-90); + + // Gravity Mode: radial + self.radialAccel = 0; + self.radialAccelVar = 0; + + // Gravity Mode: speed of particles + self.speed = 180; + self.speedVar = 50; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, winSize.height/2); + + // angle + angle = 90; + angleVar = 20; + + // life of particles + life = 3.5f; + lifeVar = 1; + + // emits per frame + emissionRate = totalParticles/life; + + // color of particles + startColor.r = 0.5f; + startColor.g = 0.5f; + startColor.b = 0.5f; + startColor.a = 1.0f; + startColorVar.r = 0.5f; + startColorVar.g = 0.5f; + startColorVar.b = 0.5f; + startColorVar.a = 0.1f; + endColor.r = 0.1f; + endColor.g = 0.1f; + endColor.b = 0.1f; + endColor.a = 0.2f; + endColorVar.r = 0.1f; + endColorVar.g = 0.1f; + endColorVar.b = 0.1f; + endColorVar.a = 0.2f; + + // size, in pixels + startSize = 8.0f; + startSizeVar = 2.0f; + endSize = kCCParticleStartSizeEqualToEndSize; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = NO; + } + + return self; +} +@end + +// +// ParticleFire +// +@implementation CCParticleFire +-(id) init +{ + return [self initWithTotalParticles:250]; +} + +-(id) initWithTotalParticles:(int) p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // duration + duration = kCCParticleDurationInfinity; + + // Gravity Mode + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,0); + + // Gravity Mode: radial acceleration + self.radialAccel = 0; + self.radialAccelVar = 0; + + // Gravity Mode: speed of particles + self.speed = 60; + self.speedVar = 20; + + // starting angle + angle = 90; + angleVar = 10; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, 60); + posVar = ccp(40, 20); + + // life of particles + life = 3; + lifeVar = 0.25f; + + + // size, in pixels + startSize = 54.0f; + startSizeVar = 10.0f; + endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per frame + emissionRate = totalParticles/life; + + // color of particles + startColor.r = 0.76f; + startColor.g = 0.25f; + startColor.b = 0.12f; + startColor.a = 1.0f; + startColorVar.r = 0.0f; + startColorVar.g = 0.0f; + startColorVar.b = 0.0f; + startColorVar.a = 0.0f; + endColor.r = 0.0f; + endColor.g = 0.0f; + endColor.b = 0.0f; + endColor.a = 1.0f; + endColorVar.r = 0.0f; + endColorVar.g = 0.0f; + endColorVar.b = 0.0f; + endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = YES; + } + + return self; +} +@end + +// +// ParticleSun +// +@implementation CCParticleSun +-(id) init +{ + return [self initWithTotalParticles:350]; +} + +-(id) initWithTotalParticles:(int) p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // additive + self.blendAdditive = YES; + + // duration + duration = kCCParticleDurationInfinity; + + // Gravity Mode + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,0); + + // Gravity mode: radial acceleration + self.radialAccel = 0; + self.radialAccelVar = 0; + + // Gravity mode: speed of particles + self.speed = 20; + self.speedVar = 5; + + + // angle + angle = 90; + angleVar = 360; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, winSize.height/2); + posVar = CGPointZero; + + // life of particles + life = 1; + lifeVar = 0.5f; + + // size, in pixels + startSize = 30.0f; + startSizeVar = 10.0f; + endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per seconds + emissionRate = totalParticles/life; + + // color of particles + startColor.r = 0.76f; + startColor.g = 0.25f; + startColor.b = 0.12f; + startColor.a = 1.0f; + startColorVar.r = 0.0f; + startColorVar.g = 0.0f; + startColorVar.b = 0.0f; + startColorVar.a = 0.0f; + endColor.r = 0.0f; + endColor.g = 0.0f; + endColor.b = 0.0f; + endColor.a = 1.0f; + endColorVar.r = 0.0f; + endColorVar.g = 0.0f; + endColorVar.b = 0.0f; + endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + } + + return self; +} +@end + +// +// ParticleGalaxy +// +@implementation CCParticleGalaxy +-(id) init +{ + return [self initWithTotalParticles:200]; +} + +-(id) initWithTotalParticles:(int)p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // duration + duration = kCCParticleDurationInfinity; + + // Gravity Mode + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,0); + + // Gravity Mode: speed of particles + self.speed = 60; + self.speedVar = 10; + + // Gravity Mode: radial + self.radialAccel = -80; + self.radialAccelVar = 0; + + // Gravity Mode: tagential + self.tangentialAccel = 80; + self.tangentialAccelVar = 0; + + // angle + angle = 90; + angleVar = 360; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, winSize.height/2); + posVar = CGPointZero; + + // life of particles + life = 4; + lifeVar = 1; + + // size, in pixels + startSize = 37.0f; + startSizeVar = 10.0f; + endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per second + emissionRate = totalParticles/life; + + // color of particles + startColor.r = 0.12f; + startColor.g = 0.25f; + startColor.b = 0.76f; + startColor.a = 1.0f; + startColorVar.r = 0.0f; + startColorVar.g = 0.0f; + startColorVar.b = 0.0f; + startColorVar.a = 0.0f; + endColor.r = 0.0f; + endColor.g = 0.0f; + endColor.b = 0.0f; + endColor.a = 1.0f; + endColorVar.r = 0.0f; + endColorVar.g = 0.0f; + endColorVar.b = 0.0f; + endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = YES; + } + + return self; +} +@end + +// +// ParticleFlower +// +@implementation CCParticleFlower +-(id) init +{ + return [self initWithTotalParticles:250]; +} + +-(id) initWithTotalParticles:(int) p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // duration + duration = kCCParticleDurationInfinity; + + // Gravity Mode + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,0); + + // Gravity Mode: speed of particles + self.speed = 80; + self.speedVar = 10; + + // Gravity Mode: radial + self.radialAccel = -60; + self.radialAccelVar = 0; + + // Gravity Mode: tagential + self.tangentialAccel = 15; + self.tangentialAccelVar = 0; + + // angle + angle = 90; + angleVar = 360; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, winSize.height/2); + posVar = CGPointZero; + + // life of particles + life = 4; + lifeVar = 1; + + // size, in pixels + startSize = 30.0f; + startSizeVar = 10.0f; + endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per second + emissionRate = totalParticles/life; + + // color of particles + startColor.r = 0.50f; + startColor.g = 0.50f; + startColor.b = 0.50f; + startColor.a = 1.0f; + startColorVar.r = 0.5f; + startColorVar.g = 0.5f; + startColorVar.b = 0.5f; + startColorVar.a = 0.5f; + endColor.r = 0.0f; + endColor.g = 0.0f; + endColor.b = 0.0f; + endColor.a = 1.0f; + endColorVar.r = 0.0f; + endColorVar.g = 0.0f; + endColorVar.b = 0.0f; + endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = YES; + } + + return self; +} +@end + +// +// ParticleMeteor +// +@implementation CCParticleMeteor +-(id) init +{ + return [self initWithTotalParticles:150]; +} + +-(id) initWithTotalParticles:(int) p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // duration + duration = kCCParticleDurationInfinity; + + // Gravity Mode + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(-200,200); + + // Gravity Mode: speed of particles + self.speed = 15; + self.speedVar = 5; + + // Gravity Mode: radial + self.radialAccel = 0; + self.radialAccelVar = 0; + + // Gravity Mode: tagential + self.tangentialAccel = 0; + self.tangentialAccelVar = 0; + + // angle + angle = 90; + angleVar = 360; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, winSize.height/2); + posVar = CGPointZero; + + // life of particles + life = 2; + lifeVar = 1; + + // size, in pixels + startSize = 60.0f; + startSizeVar = 10.0f; + endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per second + emissionRate = totalParticles/life; + + // color of particles + startColor.r = 0.2f; + startColor.g = 0.4f; + startColor.b = 0.7f; + startColor.a = 1.0f; + startColorVar.r = 0.0f; + startColorVar.g = 0.0f; + startColorVar.b = 0.2f; + startColorVar.a = 0.1f; + endColor.r = 0.0f; + endColor.g = 0.0f; + endColor.b = 0.0f; + endColor.a = 1.0f; + endColorVar.r = 0.0f; + endColorVar.g = 0.0f; + endColorVar.b = 0.0f; + endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = YES; + } + + return self; +} +@end + +// +// ParticleSpiral +// +@implementation CCParticleSpiral +-(id) init +{ + return [self initWithTotalParticles:500]; +} + +-(id) initWithTotalParticles:(int) p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // duration + duration = kCCParticleDurationInfinity; + + // Gravity Mode + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,0); + + // Gravity Mode: speed of particles + self.speed = 150; + self.speedVar = 0; + + // Gravity Mode: radial + self.radialAccel = -380; + self.radialAccelVar = 0; + + // Gravity Mode: tagential + self.tangentialAccel = 45; + self.tangentialAccelVar = 0; + + // angle + angle = 90; + angleVar = 0; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, winSize.height/2); + posVar = CGPointZero; + + // life of particles + life = 12; + lifeVar = 0; + + // size, in pixels + startSize = 20.0f; + startSizeVar = 0.0f; + endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per second + emissionRate = totalParticles/life; + + // color of particles + startColor.r = 0.5f; + startColor.g = 0.5f; + startColor.b = 0.5f; + startColor.a = 1.0f; + startColorVar.r = 0.5f; + startColorVar.g = 0.5f; + startColorVar.b = 0.5f; + startColorVar.a = 0.0f; + endColor.r = 0.5f; + endColor.g = 0.5f; + endColor.b = 0.5f; + endColor.a = 1.0f; + endColorVar.r = 0.5f; + endColorVar.g = 0.5f; + endColorVar.b = 0.5f; + endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = NO; + } + + return self; +} +@end + +// +// ParticleExplosion +// +@implementation CCParticleExplosion +-(id) init +{ + return [self initWithTotalParticles:700]; +} + +-(id) initWithTotalParticles:(int)p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // duration + duration = 0.1f; + + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,0); + + // Gravity Mode: speed of particles + self.speed = 70; + self.speedVar = 40; + + // Gravity Mode: radial + self.radialAccel = 0; + self.radialAccelVar = 0; + + // Gravity Mode: tagential + self.tangentialAccel = 0; + self.tangentialAccelVar = 0; + + // angle + angle = 90; + angleVar = 360; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, winSize.height/2); + posVar = CGPointZero; + + // life of particles + life = 5.0f; + lifeVar = 2; + + // size, in pixels + startSize = 15.0f; + startSizeVar = 10.0f; + endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per second + emissionRate = totalParticles/duration; + + // color of particles + startColor.r = 0.7f; + startColor.g = 0.1f; + startColor.b = 0.2f; + startColor.a = 1.0f; + startColorVar.r = 0.5f; + startColorVar.g = 0.5f; + startColorVar.b = 0.5f; + startColorVar.a = 0.0f; + endColor.r = 0.5f; + endColor.g = 0.5f; + endColor.b = 0.5f; + endColor.a = 0.0f; + endColorVar.r = 0.5f; + endColorVar.g = 0.5f; + endColorVar.b = 0.5f; + endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = NO; + } + + return self; +} +@end + +// +// ParticleSmoke +// +@implementation CCParticleSmoke +-(id) init +{ + return [self initWithTotalParticles:200]; +} + +-(id) initWithTotalParticles:(int) p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // duration + duration = kCCParticleDurationInfinity; + + // Emitter mode: Gravity Mode + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,0); + + // Gravity Mode: radial acceleration + self.radialAccel = 0; + self.radialAccelVar = 0; + + // Gravity Mode: speed of particles + self.speed = 25; + self.speedVar = 10; + + // angle + angle = 90; + angleVar = 5; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, 0); + posVar = ccp(20, 0); + + // life of particles + life = 4; + lifeVar = 1; + + // size, in pixels + startSize = 60.0f; + startSizeVar = 10.0f; + endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per frame + emissionRate = totalParticles/life; + + // color of particles + startColor.r = 0.8f; + startColor.g = 0.8f; + startColor.b = 0.8f; + startColor.a = 1.0f; + startColorVar.r = 0.02f; + startColorVar.g = 0.02f; + startColorVar.b = 0.02f; + startColorVar.a = 0.0f; + endColor.r = 0.0f; + endColor.g = 0.0f; + endColor.b = 0.0f; + endColor.a = 1.0f; + endColorVar.r = 0.0f; + endColorVar.g = 0.0f; + endColorVar.b = 0.0f; + endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = NO; + } + + return self; +} +@end + +@implementation CCParticleSnow +-(id) init +{ + return [self initWithTotalParticles:700]; +} + +-(id) initWithTotalParticles:(int)p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // duration + duration = kCCParticleDurationInfinity; + + // set gravity mode. + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,-1); + + // Gravity Mode: speed of particles + self.speed = 5; + self.speedVar = 1; + + // Gravity Mode: radial + self.radialAccel = 0; + self.radialAccelVar = 1; + + // Gravity mode: tagential + self.tangentialAccel = 0; + self.tangentialAccelVar = 1; + + // emitter position + self.position = (CGPoint) { + [[CCDirector sharedDirector] winSize].width / 2, + [[CCDirector sharedDirector] winSize].height + 10 + }; + posVar = ccp( [[CCDirector sharedDirector] winSize].width / 2, 0 ); + + // angle + angle = -90; + angleVar = 5; + + // life of particles + life = 45; + lifeVar = 15; + + // size, in pixels + startSize = 10.0f; + startSizeVar = 5.0f; + endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per second + emissionRate = 10; + + // color of particles + startColor.r = 1.0f; + startColor.g = 1.0f; + startColor.b = 1.0f; + startColor.a = 1.0f; + startColorVar.r = 0.0f; + startColorVar.g = 0.0f; + startColorVar.b = 0.0f; + startColorVar.a = 0.0f; + endColor.r = 1.0f; + endColor.g = 1.0f; + endColor.b = 1.0f; + endColor.a = 0.0f; + endColorVar.r = 0.0f; + endColorVar.g = 0.0f; + endColorVar.b = 0.0f; + endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = NO; + } + + return self; +} +@end + +@implementation CCParticleRain +-(id) init +{ + return [self initWithTotalParticles:1000]; +} + +-(id) initWithTotalParticles:(int)p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // duration + duration = kCCParticleDurationInfinity; + + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(10,-10); + + // Gravity Mode: radial + self.radialAccel = 0; + self.radialAccelVar = 1; + + // Gravity Mode: tagential + self.tangentialAccel = 0; + self.tangentialAccelVar = 1; + + // Gravity Mode: speed of particles + self.speed = 130; + self.speedVar = 30; + + // angle + angle = -90; + angleVar = 5; + + + // emitter position + self.position = (CGPoint) { + [[CCDirector sharedDirector] winSize].width / 2, + [[CCDirector sharedDirector] winSize].height + }; + posVar = ccp( [[CCDirector sharedDirector] winSize].width / 2, 0 ); + + // life of particles + life = 4.5f; + lifeVar = 0; + + // size, in pixels + startSize = 4.0f; + startSizeVar = 2.0f; + endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per second + emissionRate = 20; + + // color of particles + startColor.r = 0.7f; + startColor.g = 0.8f; + startColor.b = 1.0f; + startColor.a = 1.0f; + startColorVar.r = 0.0f; + startColorVar.g = 0.0f; + startColorVar.b = 0.0f; + startColorVar.a = 0.0f; + endColor.r = 0.7f; + endColor.g = 0.8f; + endColor.b = 1.0f; + endColor.a = 0.5f; + endColorVar.r = 0.0f; + endColorVar.g = 0.0f; + endColorVar.b = 0.0f; + endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = NO; + } + + return self; +} +@end diff --git a/Classes/cocos2d/CCParticleSystem.h b/Classes/cocos2d/CCParticleSystem.h new file mode 100644 index 0000000..e87961d --- /dev/null +++ b/Classes/cocos2d/CCParticleSystem.h @@ -0,0 +1,444 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + +#import "CCProtocols.h" +#import "CCNode.h" +#import "ccTypes.h" +#import "ccConfig.h" + +#if CC_ENABLE_PROFILERS +@class CCProfilingTimer; +#endif + +//* @enum +enum { + /** The Particle emitter lives forever */ + kCCParticleDurationInfinity = -1, + + /** The starting size of the particle is equal to the ending size */ + kCCParticleStartSizeEqualToEndSize = -1, + + /** The starting radius of the particle is equal to the ending radius */ + kCCParticleStartRadiusEqualToEndRadius = -1, + + // backward compatible + kParticleStartSizeEqualToEndSize = kCCParticleStartSizeEqualToEndSize, + kParticleDurationInfinity = kCCParticleDurationInfinity, +}; + +//* @enum +enum { + /** Gravity mode (A mode) */ + kCCParticleModeGravity, + + /** Radius mode (B mode) */ + kCCParticleModeRadius, +}; + + +/** @typedef tCCPositionType + possible types of particle positions + */ +typedef enum { + /** Living particles are attached to the world and are unaffected by emitter repositioning. */ + kCCPositionTypeFree, + + /** Living particles are attached to the world but will follow the emitter repositioning. + Use case: Attach an emitter to an sprite, and you want that the emitter follows the sprite. + */ + kCCPositionTypeRelative, + + /** Living particles are attached to the emitter and are translated along with it. */ + kCCPositionTypeGrouped, +}tCCPositionType; + +// backward compatible +enum { + kPositionTypeFree = kCCPositionTypeFree, + kPositionTypeGrouped = kCCPositionTypeGrouped, +}; + +/** @struct tCCParticle + Structure that contains the values of each particle + */ +typedef struct sCCParticle { + CGPoint pos; + CGPoint startPos; + + ccColor4F color; + ccColor4F deltaColor; + + float size; + float deltaSize; + + float rotation; + float deltaRotation; + + ccTime timeToLive; + + union { + // Mode A: gravity, direction, radial accel, tangential accel + struct { + CGPoint dir; + float radialAccel; + float tangentialAccel; + } A; + + // Mode B: radius mode + struct { + float angle; + float degreesPerSecond; + float radius; + float deltaRadius; + } B; + } mode; + +}tCCParticle; + +typedef void (*CC_UPDATE_PARTICLE_IMP)(id, SEL, tCCParticle*, CGPoint); + +@class CCTexture2D; + +/** Particle System base class + Attributes of a Particle System: + - emmision rate of the particles + - Gravity Mode (Mode A): + - gravity + - direction + - speed +- variance + - tangential acceleration +- variance + - radial acceleration +- variance + - Radius Mode (Mode B): + - startRadius +- variance + - endRadius +- variance + - rotate +- variance + - Properties common to all modes: + - life +- life variance + - start spin +- variance + - end spin +- variance + - start size +- variance + - end size +- variance + - start color +- variance + - end color +- variance + - life +- variance + - blending function + - texture + + cocos2d also supports particles generated by Particle Designer (http://particledesigner.71squared.com/). + 'Radius Mode' in Particle Designer uses a fixed emit rate of 30 hz. Since that can't be guarateed in cocos2d, + cocos2d uses a another approach, but the results are almost identical. + + cocos2d supports all the variables used by Particle Designer plus a bit more: + - spinning particles (supported when using CCParticleSystemQuad) + - tangential acceleration (Gravity mode) + - radial acceleration (Gravity mode) + - radius direction (Radius mode) (Particle Designer supports outwards to inwards direction only) + + It is possible to customize any of the above mentioned properties in runtime. Example: + + @code + emitter.radialAccel = 15; + emitter.startSpin = 0; + @endcode + + */ +@interface CCParticleSystem : CCNode +{ + // is the particle system active ? + BOOL active; + // duration in seconds of the system. -1 is infinity + float duration; + // time elapsed since the start of the system (in seconds) + float elapsed; + + // position is from "superclass" CocosNode + CGPoint sourcePosition; + // Position variance + CGPoint posVar; + + // The angle (direction) of the particles measured in degrees + float angle; + // Angle variance measured in degrees; + float angleVar; + + // Different modes + + NSInteger emitterMode_; + union { + // Mode A:Gravity + Tangential Accel + Radial Accel + struct { + // gravity of the particles + CGPoint gravity; + + // The speed the particles will have. + float speed; + // The speed variance + float speedVar; + + // Tangential acceleration + float tangentialAccel; + // Tangential acceleration variance + float tangentialAccelVar; + + // Radial acceleration + float radialAccel; + // Radial acceleration variance + float radialAccelVar; + } A; + + // Mode B: circular movement (gravity, radial accel and tangential accel don't are not used in this mode) + struct { + + // The starting radius of the particles + float startRadius; + // The starting radius variance of the particles + float startRadiusVar; + // The ending radius of the particles + float endRadius; + // The ending radius variance of the particles + float endRadiusVar; + // Number of degress to rotate a particle around the source pos per second + float rotatePerSecond; + // Variance in degrees for rotatePerSecond + float rotatePerSecondVar; + } B; + } mode; + + // start ize of the particles + float startSize; + // start Size variance + float startSizeVar; + // End size of the particle + float endSize; + // end size of variance + float endSizeVar; + + // How many seconds will the particle live + float life; + // Life variance + float lifeVar; + + // Start color of the particles + ccColor4F startColor; + // Start color variance + ccColor4F startColorVar; + // End color of the particles + ccColor4F endColor; + // End color variance + ccColor4F endColorVar; + + // start angle of the particles + float startSpin; + // start angle variance + float startSpinVar; + // End angle of the particle + float endSpin; + // end angle ariance + float endSpinVar; + + + // Array of particles + tCCParticle *particles; + // Maximum particles + NSUInteger totalParticles; + // Count of active particles + NSUInteger particleCount; + + // color modulate +// BOOL colorModulate; + + // How many particles can be emitted per second + float emissionRate; + float emitCounter; + + // Texture of the particles + CCTexture2D *texture_; + // blend function + ccBlendFunc blendFunc_; + + // movment type: free or grouped + tCCPositionType positionType_; + + // Whether or not the node will be auto-removed when there are not particles + BOOL autoRemoveOnFinish_; + + // particle idx + NSUInteger particleIdx; + + // Optimization + CC_UPDATE_PARTICLE_IMP updateParticleImp; + SEL updateParticleSel; + +// profiling +#if CC_ENABLE_PROFILERS + CCProfilingTimer* _profilingTimer; +#endif +} + +/** Is the emitter active */ +@property (nonatomic,readonly) BOOL active; +/** Quantity of particles that are being simulated at the moment */ +@property (nonatomic,readonly) NSUInteger particleCount; +/** How many seconds the emitter wil run. -1 means 'forever' */ +@property (nonatomic,readwrite,assign) float duration; +/** sourcePosition of the emitter */ +@property (nonatomic,readwrite,assign) CGPoint sourcePosition; +/** Position variance of the emitter */ +@property (nonatomic,readwrite,assign) CGPoint posVar; +/** life, and life variation of each particle */ +@property (nonatomic,readwrite,assign) float life; +/** life variance of each particle */ +@property (nonatomic,readwrite,assign) float lifeVar; +/** angle and angle variation of each particle */ +@property (nonatomic,readwrite,assign) float angle; +/** angle variance of each particle */ +@property (nonatomic,readwrite,assign) float angleVar; + +/** Gravity value. Only available in 'Gravity' mode. */ +@property (nonatomic,readwrite,assign) CGPoint gravity; +/** speed of each particle. Only available in 'Gravity' mode. */ +@property (nonatomic,readwrite,assign) float speed; +/** speed variance of each particle. Only available in 'Gravity' mode. */ +@property (nonatomic,readwrite,assign) float speedVar; +/** tangential acceleration of each particle. Only available in 'Gravity' mode. */ +@property (nonatomic,readwrite,assign) float tangentialAccel; +/** tangential acceleration variance of each particle. Only available in 'Gravity' mode. */ +@property (nonatomic,readwrite,assign) float tangentialAccelVar; +/** radial acceleration of each particle. Only available in 'Gravity' mode. */ +@property (nonatomic,readwrite,assign) float radialAccel; +/** radial acceleration variance of each particle. Only available in 'Gravity' mode. */ +@property (nonatomic,readwrite,assign) float radialAccelVar; + +/** The starting radius of the particles. Only available in 'Radius' mode. */ +@property (nonatomic,readwrite,assign) float startRadius; +/** The starting radius variance of the particles. Only available in 'Radius' mode. */ +@property (nonatomic,readwrite,assign) float startRadiusVar; +/** The ending radius of the particles. Only available in 'Radius' mode. */ +@property (nonatomic,readwrite,assign) float endRadius; +/** The ending radius variance of the particles. Only available in 'Radius' mode. */ +@property (nonatomic,readwrite,assign) float endRadiusVar; +/** Number of degress to rotate a particle around the source pos per second. Only available in 'Radius' mode. */ +@property (nonatomic,readwrite,assign) float rotatePerSecond; +/** Variance in degrees for rotatePerSecond. Only available in 'Radius' mode. */ +@property (nonatomic,readwrite,assign) float rotatePerSecondVar; + +/** start size in pixels of each particle */ +@property (nonatomic,readwrite,assign) float startSize; +/** size variance in pixels of each particle */ +@property (nonatomic,readwrite,assign) float startSizeVar; +/** end size in pixels of each particle */ +@property (nonatomic,readwrite,assign) float endSize; +/** end size variance in pixels of each particle */ +@property (nonatomic,readwrite,assign) float endSizeVar; +/** start color of each particle */ +@property (nonatomic,readwrite,assign) ccColor4F startColor; +/** start color variance of each particle */ +@property (nonatomic,readwrite,assign) ccColor4F startColorVar; +/** end color and end color variation of each particle */ +@property (nonatomic,readwrite,assign) ccColor4F endColor; +/** end color variance of each particle */ +@property (nonatomic,readwrite,assign) ccColor4F endColorVar; +//* initial angle of each particle +@property (nonatomic,readwrite,assign) float startSpin; +//* initial angle of each particle +@property (nonatomic,readwrite,assign) float startSpinVar; +//* initial angle of each particle +@property (nonatomic,readwrite,assign) float endSpin; +//* initial angle of each particle +@property (nonatomic,readwrite,assign) float endSpinVar; +/** emission rate of the particles */ +@property (nonatomic,readwrite,assign) float emissionRate; +/** maximum particles of the system */ +@property (nonatomic,readwrite,assign) NSUInteger totalParticles; +/** conforms to CocosNodeTexture protocol */ +@property (nonatomic,readwrite, retain) CCTexture2D * texture; +/** conforms to CocosNodeTexture protocol */ +@property (nonatomic,readwrite) ccBlendFunc blendFunc; +/** whether or not the particles are using blend additive. + If enabled, the following blending function will be used. + @code + source blend function = GL_SRC_ALPHA; + dest blend function = GL_ONE; + @endcode + */ +@property (nonatomic,readwrite) BOOL blendAdditive; +/** particles movement type: Free or Grouped + @since v0.8 + */ +@property (nonatomic,readwrite) tCCPositionType positionType; +/** whether or not the node will be auto-removed when it has no particles left. + By default it is NO. + @since v0.8 + */ +@property (nonatomic,readwrite) BOOL autoRemoveOnFinish; +/** Switch between different kind of emitter modes: + - kCCParticleModeGravity: uses gravity, speed, radial and tangential acceleration + - kCCParticleModeRadius: uses radius movement + rotation + */ +@property (nonatomic,readwrite) NSInteger emitterMode; + +/** creates an initializes a CCParticleSystem from a plist file. + This plist files can be creted manually or with Particle Designer: + http://particledesigner.71squared.com/ + @since v0.99.3 + */ ++(id) particleWithFile:(NSString*)plistFile; + +/** initializes a CCParticleSystem from a plist file. + This plist files can be creted manually or with Particle Designer: + http://particledesigner.71squared.com/ + @since v0.99.3 + */ +-(id) initWithFile:(NSString*) plistFile; + +/** initializes a CCQuadParticleSystem from a NSDictionary. + @since v0.99.3 + */ +-(id) initWithDictionary:(NSDictionary*)dictionary; + +//! Initializes a system with a fixed number of particles +-(id) initWithTotalParticles:(int) numberOfParticles; +//! Add a particle to the emitter +-(BOOL) addParticle; +//! Initializes a particle +-(void) initParticle: (tCCParticle*) particle; +//! stop emitting particles. Running particles will continue to run until they die +-(void) stopSystem; +//! Kill all living particles. +-(void) resetSystem; +//! whether or not the system is full +-(BOOL) isFull; + +//! should be overriden by subclasses +-(void) updateQuadWithParticle:(tCCParticle*)particle newPosition:(CGPoint)pos; +//! should be overriden by subclasses +-(void) postStep; + +//! called in every loop. +-(void) update: (ccTime) dt; + +@end + diff --git a/Classes/cocos2d/CCParticleSystem.m b/Classes/cocos2d/CCParticleSystem.m new file mode 100644 index 0000000..1ee46da --- /dev/null +++ b/Classes/cocos2d/CCParticleSystem.m @@ -0,0 +1,795 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + +// ideas taken from: +// . The ocean spray in your face [Jeff Lander] +// http://www.double.co.nz/dust/col0798.pdf +// . Building an Advanced Particle System [John van der Burg] +// http://www.gamasutra.com/features/20000623/vanderburg_01.htm +// . LOVE game engine +// http://love2d.org/ +// +// +// Radius mode support, from 71 squared +// http://particledesigner.71squared.com/ +// +// IMPORTANT: Particle Designer is supported by cocos2d, but +// 'Radius Mode' in Particle Designer uses a fixed emit rate of 30 hz. Since that can't be guarateed in cocos2d, +// cocos2d uses a another approach, but the results are almost identical. +// + +// opengl +#import "Platforms/CCGL.h" + +// cocos2d +#import "ccConfig.h" +#if CC_ENABLE_PROFILERS +#import "Support/CCProfiling.h" +#endif +#import "CCParticleSystem.h" +#import "CCTextureCache.h" +#import "ccMacros.h" + +// support +#import "Support/OpenGL_Internal.h" +#import "Support/CGPointExtension.h" +#import "Support/base64.h" +#import "Support/ZipUtils.h" +#import "Support/CCFileUtils.h" + +@implementation CCParticleSystem +@synthesize active, duration; +@synthesize sourcePosition, posVar; +@synthesize particleCount; +@synthesize life, lifeVar; +@synthesize angle, angleVar; +@synthesize startColor, startColorVar, endColor, endColorVar; +@synthesize startSpin, startSpinVar, endSpin, endSpinVar; +@synthesize emissionRate; +@synthesize totalParticles; +@synthesize startSize, startSizeVar; +@synthesize endSize, endSizeVar; +@synthesize blendFunc = blendFunc_; +@synthesize positionType = positionType_; +@synthesize autoRemoveOnFinish = autoRemoveOnFinish_; +@synthesize emitterMode = emitterMode_; + + ++(id) particleWithFile:(NSString*) plistFile +{ + return [[[self alloc] initWithFile:plistFile] autorelease]; +} + +-(id) init { + NSAssert(NO, @"CCParticleSystem: Init not supported."); + [self release]; + return nil; +} + +-(id) initWithFile:(NSString *)plistFile +{ + NSString *path = [CCFileUtils fullPathFromRelativePath:plistFile]; + NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; + + NSAssert( dict != nil, @"Particles: file not found"); + return [self initWithDictionary:dict]; +} + +-(id) initWithDictionary:(NSDictionary *)dictionary +{ + NSUInteger maxParticles = [[dictionary valueForKey:@"maxParticles"] intValue]; + // self, not super + if ((self=[self initWithTotalParticles:maxParticles] ) ) { + + // angle + angle = [[dictionary valueForKey:@"angle"] floatValue]; + angleVar = [[dictionary valueForKey:@"angleVariance"] floatValue]; + + // duration + duration = [[dictionary valueForKey:@"duration"] floatValue]; + + // blend function + blendFunc_.src = [[dictionary valueForKey:@"blendFuncSource"] intValue]; + blendFunc_.dst = [[dictionary valueForKey:@"blendFuncDestination"] intValue]; + + // color + float r,g,b,a; + + r = [[dictionary valueForKey:@"startColorRed"] floatValue]; + g = [[dictionary valueForKey:@"startColorGreen"] floatValue]; + b = [[dictionary valueForKey:@"startColorBlue"] floatValue]; + a = [[dictionary valueForKey:@"startColorAlpha"] floatValue]; + startColor = (ccColor4F) {r,g,b,a}; + + r = [[dictionary valueForKey:@"startColorVarianceRed"] floatValue]; + g = [[dictionary valueForKey:@"startColorVarianceGreen"] floatValue]; + b = [[dictionary valueForKey:@"startColorVarianceBlue"] floatValue]; + a = [[dictionary valueForKey:@"startColorVarianceAlpha"] floatValue]; + startColorVar = (ccColor4F) {r,g,b,a}; + + r = [[dictionary valueForKey:@"finishColorRed"] floatValue]; + g = [[dictionary valueForKey:@"finishColorGreen"] floatValue]; + b = [[dictionary valueForKey:@"finishColorBlue"] floatValue]; + a = [[dictionary valueForKey:@"finishColorAlpha"] floatValue]; + endColor = (ccColor4F) {r,g,b,a}; + + r = [[dictionary valueForKey:@"finishColorVarianceRed"] floatValue]; + g = [[dictionary valueForKey:@"finishColorVarianceGreen"] floatValue]; + b = [[dictionary valueForKey:@"finishColorVarianceBlue"] floatValue]; + a = [[dictionary valueForKey:@"finishColorVarianceAlpha"] floatValue]; + endColorVar = (ccColor4F) {r,g,b,a}; + + // particle size + startSize = [[dictionary valueForKey:@"startParticleSize"] floatValue]; + startSizeVar = [[dictionary valueForKey:@"startParticleSizeVariance"] floatValue]; + endSize = [[dictionary valueForKey:@"finishParticleSize"] floatValue]; + endSizeVar = [[dictionary valueForKey:@"finishParticleSizeVariance"] floatValue]; + + + // position + float x = [[dictionary valueForKey:@"sourcePositionx"] floatValue]; + float y = [[dictionary valueForKey:@"sourcePositiony"] floatValue]; + self.position = ccp(x,y); + posVar.x = [[dictionary valueForKey:@"sourcePositionVariancex"] floatValue]; + posVar.y = [[dictionary valueForKey:@"sourcePositionVariancey"] floatValue]; + + + emitterMode_ = [[dictionary valueForKey:@"emitterType"] intValue]; + + // Mode A: Gravity + tangential accel + radial accel + if( emitterMode_ == kCCParticleModeGravity ) { + // gravity + mode.A.gravity.x = [[dictionary valueForKey:@"gravityx"] floatValue]; + mode.A.gravity.y = [[dictionary valueForKey:@"gravityy"] floatValue]; + + // + // speed + mode.A.speed = [[dictionary valueForKey:@"speed"] floatValue]; + mode.A.speedVar = [[dictionary valueForKey:@"speedVariance"] floatValue]; + + // radial acceleration + NSString *tmp = [dictionary valueForKey:@"radialAcceleration"]; + mode.A.radialAccel = tmp ? [tmp floatValue] : 0; + + tmp = [dictionary valueForKey:@"radialAccelVariance"]; + mode.A.radialAccelVar = tmp ? [tmp floatValue] : 0; + + // tangential acceleration + tmp = [dictionary valueForKey:@"tangentialAcceleration"]; + mode.A.tangentialAccel = tmp ? [tmp floatValue] : 0; + + tmp = [dictionary valueForKey:@"tangentialAccelVariance"]; + mode.A.tangentialAccelVar = tmp ? [tmp floatValue] : 0; + } + + + // or Mode B: radius movement + else if( emitterMode_ == kCCParticleModeRadius ) { + float maxRadius = [[dictionary valueForKey:@"maxRadius"] floatValue]; + float maxRadiusVar = [[dictionary valueForKey:@"maxRadiusVariance"] floatValue]; + float minRadius = [[dictionary valueForKey:@"minRadius"] floatValue]; + + mode.B.startRadius = maxRadius; + mode.B.startRadiusVar = maxRadiusVar; + mode.B.endRadius = minRadius; + mode.B.endRadiusVar = 0; + mode.B.rotatePerSecond = [[dictionary valueForKey:@"rotatePerSecond"] floatValue]; + mode.B.rotatePerSecondVar = [[dictionary valueForKey:@"rotatePerSecondVariance"] floatValue]; + + } else { + NSAssert( NO, @"Invalid emitterType in config file"); + } + + // life span + life = [[dictionary valueForKey:@"particleLifespan"] floatValue]; + lifeVar = [[dictionary valueForKey:@"particleLifespanVariance"] floatValue]; + + // emission Rate + emissionRate = totalParticles/life; + + // texture + // Try to get the texture from the cache + NSString *textureName = [dictionary valueForKey:@"textureFileName"]; + + self.texture = [[CCTextureCache sharedTextureCache] addImage:textureName]; + + NSString *textureData = [dictionary valueForKey:@"textureImageData"]; + + if ( ! texture_ && textureData) { + + // if it fails, try to get it from the base64-gzipped data + unsigned char *buffer = NULL; + NSUInteger len = base64Decode((unsigned char*)[textureData UTF8String], [textureData length], &buffer); + NSAssert( buffer != NULL, @"CCParticleSystem: error decoding textureImageData"); + + unsigned char *deflated = NULL; + NSUInteger deflatedLen = ccInflateMemory(buffer, len, &deflated); + free( buffer ); + + NSAssert( deflated != NULL, @"CCParticleSystem: error ungzipping textureImageData"); + NSData *data = [[NSData alloc] initWithBytes:deflated length:deflatedLen]; + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + UIImage *image = [[UIImage alloc] initWithData:data]; +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + NSBitmapImageRep *image = [[NSBitmapImageRep alloc] initWithData:data]; +#endif + + free(deflated); deflated = NULL; + + self.texture = [[CCTextureCache sharedTextureCache] addCGImage:[image CGImage] forKey:textureName]; + [data release]; + [image release]; + } + + NSAssert( [self texture] != NULL, @"CCParticleSystem: error loading the texture"); + + } + + return self; +} + +-(id) initWithTotalParticles:(int) numberOfParticles +{ + if( (self=[super init]) ) { + + totalParticles = numberOfParticles; + + particles = calloc( totalParticles, sizeof(tCCParticle) ); + + if( ! particles ) { + NSLog(@"Particle system: not enough memory"); + [self release]; + return nil; + } + + // default, active + active = YES; + + // default blend function + blendFunc_ = (ccBlendFunc) { CC_BLEND_SRC, CC_BLEND_DST }; + + // default movement type; + positionType_ = kCCPositionTypeFree; + + // by default be in mode A: + emitterMode_ = kCCParticleModeGravity; + + // default: modulate + // XXX: not used + // colorModulate = YES; + + autoRemoveOnFinish_ = NO; + + // profiling +#if CC_ENABLE_PROFILERS + _profilingTimer = [[CCProfiler timerWithName:@"particle system" andInstance:self] retain]; +#endif + + // Optimization: compile udpateParticle method + updateParticleSel = @selector(updateQuadWithParticle:newPosition:); + updateParticleImp = (CC_UPDATE_PARTICLE_IMP) [self methodForSelector:updateParticleSel]; + + // udpate after action in run! + [self scheduleUpdateWithPriority:1]; + + } + + return self; +} + +-(void) dealloc +{ + free( particles ); + + [texture_ release]; + // profiling +#if CC_ENABLE_PROFILERS + [CCProfiler releaseTimer:_profilingTimer]; +#endif + + [super dealloc]; +} + +-(BOOL) addParticle +{ + if( [self isFull] ) + return NO; + + tCCParticle * particle = &particles[ particleCount ]; + + [self initParticle: particle]; + particleCount++; + + return YES; +} + +-(void) initParticle: (tCCParticle*) particle +{ + + // timeToLive + // no negative life. prevent division by 0 + particle->timeToLive = MAX(0, life + lifeVar * CCRANDOM_MINUS1_1() ); + + // position + particle->pos.x = sourcePosition.x + posVar.x * CCRANDOM_MINUS1_1(); + particle->pos.x *= CC_CONTENT_SCALE_FACTOR(); + particle->pos.y = sourcePosition.y + posVar.y * CCRANDOM_MINUS1_1(); + particle->pos.y *= CC_CONTENT_SCALE_FACTOR(); + + // Color + ccColor4F start; + start.r = MIN(1, MAX(0, startColor.r + startColorVar.r * CCRANDOM_MINUS1_1() ) ); + start.g = MIN(1, MAX(0, startColor.g + startColorVar.g * CCRANDOM_MINUS1_1() ) ); + start.b = MIN(1, MAX(0, startColor.b + startColorVar.b * CCRANDOM_MINUS1_1() ) ); + start.a = MIN(1, MAX(0, startColor.a + startColorVar.a * CCRANDOM_MINUS1_1() ) ); + + ccColor4F end; + end.r = MIN(1, MAX(0, endColor.r + endColorVar.r * CCRANDOM_MINUS1_1() ) ); + end.g = MIN(1, MAX(0, endColor.g + endColorVar.g * CCRANDOM_MINUS1_1() ) ); + end.b = MIN(1, MAX(0, endColor.b + endColorVar.b * CCRANDOM_MINUS1_1() ) ); + end.a = MIN(1, MAX(0, endColor.a + endColorVar.a * CCRANDOM_MINUS1_1() ) ); + + particle->color = start; + particle->deltaColor.r = (end.r - start.r) / particle->timeToLive; + particle->deltaColor.g = (end.g - start.g) / particle->timeToLive; + particle->deltaColor.b = (end.b - start.b) / particle->timeToLive; + particle->deltaColor.a = (end.a - start.a) / particle->timeToLive; + + // size + float startS = MAX(0, startSize + startSizeVar * CCRANDOM_MINUS1_1() ); // no negative size + startS *= CC_CONTENT_SCALE_FACTOR(); + + particle->size = startS; + if( endSize == kCCParticleStartSizeEqualToEndSize ) + particle->deltaSize = 0; + else { + float endS = endSize + endSizeVar * CCRANDOM_MINUS1_1(); + endS = MAX(0, endS); + endS *= CC_CONTENT_SCALE_FACTOR(); + particle->deltaSize = (endS - startS) / particle->timeToLive; + } + + // rotation + float startA = startSpin + startSpinVar * CCRANDOM_MINUS1_1(); + float endA = endSpin + endSpinVar * CCRANDOM_MINUS1_1(); + particle->rotation = startA; + particle->deltaRotation = (endA - startA) / particle->timeToLive; + + // position + if( positionType_ == kCCPositionTypeFree ) { + CGPoint p = [self convertToWorldSpace:CGPointZero]; + particle->startPos = ccpMult( p, CC_CONTENT_SCALE_FACTOR() ); + } + else if( positionType_ == kCCPositionTypeRelative ) { + particle->startPos = ccpMult( position_, CC_CONTENT_SCALE_FACTOR() ); + } + + // direction + float a = CC_DEGREES_TO_RADIANS( angle + angleVar * CCRANDOM_MINUS1_1() ); + + // Mode Gravity: A + if( emitterMode_ == kCCParticleModeGravity ) { + + CGPoint v = {cosf( a ), sinf( a )}; + float s = mode.A.speed + mode.A.speedVar * CCRANDOM_MINUS1_1(); + s *= CC_CONTENT_SCALE_FACTOR(); + + // direction + particle->mode.A.dir = ccpMult( v, s ); + + // radial accel + particle->mode.A.radialAccel = mode.A.radialAccel + mode.A.radialAccelVar * CCRANDOM_MINUS1_1(); + particle->mode.A.radialAccel *= CC_CONTENT_SCALE_FACTOR(); + + // tangential accel + particle->mode.A.tangentialAccel = mode.A.tangentialAccel + mode.A.tangentialAccelVar * CCRANDOM_MINUS1_1(); + particle->mode.A.tangentialAccel *= CC_CONTENT_SCALE_FACTOR(); + + } + + // Mode Radius: B + else { + // Set the default diameter of the particle from the source position + float startRadius = mode.B.startRadius + mode.B.startRadiusVar * CCRANDOM_MINUS1_1(); + float endRadius = mode.B.endRadius + mode.B.endRadiusVar * CCRANDOM_MINUS1_1(); + + startRadius *= CC_CONTENT_SCALE_FACTOR(); + endRadius *= CC_CONTENT_SCALE_FACTOR(); + + particle->mode.B.radius = startRadius; + + if( mode.B.endRadius == kCCParticleStartRadiusEqualToEndRadius ) + particle->mode.B.deltaRadius = 0; + else + particle->mode.B.deltaRadius = (endRadius - startRadius) / particle->timeToLive; + + particle->mode.B.angle = a; + particle->mode.B.degreesPerSecond = CC_DEGREES_TO_RADIANS(mode.B.rotatePerSecond + mode.B.rotatePerSecondVar * CCRANDOM_MINUS1_1()); + } +} + +-(void) stopSystem +{ + active = NO; + elapsed = duration; + emitCounter = 0; +} + +-(void) resetSystem +{ + active = YES; + elapsed = 0; + for(particleIdx = 0; particleIdx < particleCount; ++particleIdx) { + tCCParticle *p = &particles[particleIdx]; + p->timeToLive = 0; + } +} + +-(BOOL) isFull +{ + return (particleCount == totalParticles); +} + +#pragma mark ParticleSystem - MainLoop +-(void) update: (ccTime) dt +{ + if( active && emissionRate ) { + float rate = 1.0f / emissionRate; + emitCounter += dt; + while( particleCount < totalParticles && emitCounter > rate ) { + [self addParticle]; + emitCounter -= rate; + } + + elapsed += dt; + if(duration != -1 && duration < elapsed) + [self stopSystem]; + } + + particleIdx = 0; + + +#if CC_ENABLE_PROFILERS + CCProfilingBeginTimingBlock(_profilingTimer); +#endif + + + CGPoint currentPosition = CGPointZero; + if( positionType_ == kCCPositionTypeFree ) { + currentPosition = [self convertToWorldSpace:CGPointZero]; + currentPosition.x *= CC_CONTENT_SCALE_FACTOR(); + currentPosition.y *= CC_CONTENT_SCALE_FACTOR(); + } + else if( positionType_ == kCCPositionTypeRelative ) { + currentPosition = position_; + currentPosition.x *= CC_CONTENT_SCALE_FACTOR(); + currentPosition.y *= CC_CONTENT_SCALE_FACTOR(); + } + + while( particleIdx < particleCount ) + { + tCCParticle *p = &particles[particleIdx]; + + // life + p->timeToLive -= dt; + + if( p->timeToLive > 0 ) { + + // Mode A: gravity, direction, tangential accel & radial accel + if( emitterMode_ == kCCParticleModeGravity ) { + CGPoint tmp, radial, tangential; + + radial = CGPointZero; + // radial acceleration + if(p->pos.x || p->pos.y) + radial = ccpNormalize(p->pos); + + tangential = radial; + radial = ccpMult(radial, p->mode.A.radialAccel); + + // tangential acceleration + float newy = tangential.x; + tangential.x = -tangential.y; + tangential.y = newy; + tangential = ccpMult(tangential, p->mode.A.tangentialAccel); + + // (gravity + radial + tangential) * dt + tmp = ccpAdd( ccpAdd( radial, tangential), mode.A.gravity); + tmp = ccpMult( tmp, dt); + p->mode.A.dir = ccpAdd( p->mode.A.dir, tmp); + tmp = ccpMult(p->mode.A.dir, dt); + p->pos = ccpAdd( p->pos, tmp ); + } + + // Mode B: radius movement + else { + // Update the angle and radius of the particle. + p->mode.B.angle += p->mode.B.degreesPerSecond * dt; + p->mode.B.radius += p->mode.B.deltaRadius * dt; + + p->pos.x = - cosf(p->mode.B.angle) * p->mode.B.radius; + p->pos.y = - sinf(p->mode.B.angle) * p->mode.B.radius; + } + + // color + p->color.r += (p->deltaColor.r * dt); + p->color.g += (p->deltaColor.g * dt); + p->color.b += (p->deltaColor.b * dt); + p->color.a += (p->deltaColor.a * dt); + + // size + p->size += (p->deltaSize * dt); + p->size = MAX( 0, p->size ); + + // angle + p->rotation += (p->deltaRotation * dt); + + // + // update values in quad + // + + CGPoint newPos; + + if( positionType_ == kCCPositionTypeFree || positionType_ == kCCPositionTypeRelative ) { + CGPoint diff = ccpSub( currentPosition, p->startPos ); + newPos = ccpSub(p->pos, diff); + + } else + newPos = p->pos; + + + updateParticleImp(self, updateParticleSel, p, newPos); + + // update particle counter + particleIdx++; + + } else { + // life < 0 + if( particleIdx != particleCount-1 ) + particles[particleIdx] = particles[particleCount-1]; + particleCount--; + + if( particleCount == 0 && autoRemoveOnFinish_ ) { + [self unscheduleUpdate]; + [parent_ removeChild:self cleanup:YES]; + return; + } + } + } + +#if CC_ENABLE_PROFILERS + CCProfilingEndTimingBlock(_profilingTimer); +#endif + +#ifdef CC_USES_VBO + [self postStep]; +#endif +} + +-(void) updateQuadWithParticle:(tCCParticle*)particle newPosition:(CGPoint)pos; +{ + // should be overriden +} + +-(void) postStep +{ + // should be overriden +} + +#pragma mark ParticleSystem - CCTexture protocol + +-(void) setTexture:(CCTexture2D*) texture +{ + [texture_ release]; + texture_ = [texture retain]; + + // If the new texture has No premultiplied alpha, AND the blendFunc hasn't been changed, then update it + if( texture_ && ! [texture hasPremultipliedAlpha] && + ( blendFunc_.src == CC_BLEND_SRC && blendFunc_.dst == CC_BLEND_DST ) ) { + + blendFunc_.src = GL_SRC_ALPHA; + blendFunc_.dst = GL_ONE_MINUS_SRC_ALPHA; + } +} + +-(CCTexture2D*) texture +{ + return texture_; +} + +#pragma mark ParticleSystem - Additive Blending +-(void) setBlendAdditive:(BOOL)additive +{ + if( additive ) { + blendFunc_.src = GL_SRC_ALPHA; + blendFunc_.dst = GL_ONE; + + } else { + + if( texture_ && ! [texture_ hasPremultipliedAlpha] ) { + blendFunc_.src = GL_SRC_ALPHA; + blendFunc_.dst = GL_ONE_MINUS_SRC_ALPHA; + } else { + blendFunc_.src = CC_BLEND_SRC; + blendFunc_.dst = CC_BLEND_DST; + } + } +} + +-(BOOL) blendAdditive +{ + return( blendFunc_.src == GL_SRC_ALPHA && blendFunc_.dst == GL_ONE); +} + +#pragma mark ParticleSystem - Properties of Gravity Mode +-(void) setTangentialAccel:(float)t +{ + NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + mode.A.tangentialAccel = t; +} +-(float) tangentialAccel +{ + NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + return mode.A.tangentialAccel; +} + +-(void) setTangentialAccelVar:(float)t +{ + NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + mode.A.tangentialAccelVar = t; +} +-(float) tangentialAccelVar +{ + NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + return mode.A.tangentialAccelVar; +} + +-(void) setRadialAccel:(float)t +{ + NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + mode.A.radialAccel = t; +} +-(float) radialAccel +{ + NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + return mode.A.radialAccel; +} + +-(void) setRadialAccelVar:(float)t +{ + NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + mode.A.radialAccelVar = t; +} +-(float) radialAccelVar +{ + NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + return mode.A.radialAccelVar; +} + +-(void) setGravity:(CGPoint)g +{ + NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + mode.A.gravity = g; +} +-(CGPoint) gravity +{ + NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + return mode.A.gravity; +} + +-(void) setSpeed:(float)speed +{ + NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + mode.A.speed = speed; +} +-(float) speed +{ + NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + return mode.A.speed; +} + +-(void) setSpeedVar:(float)speedVar +{ + NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + mode.A.speedVar = speedVar; +} +-(float) speedVar +{ + NSAssert( emitterMode_ == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + return mode.A.speedVar; +} + +#pragma mark ParticleSystem - Properties of Radius Mode + +-(void) setStartRadius:(float)startRadius +{ + NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius"); + mode.B.startRadius = startRadius; +} +-(float) startRadius +{ + NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius"); + return mode.B.startRadius; +} + +-(void) setStartRadiusVar:(float)startRadiusVar +{ + NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius"); + mode.B.startRadiusVar = startRadiusVar; +} +-(float) startRadiusVar +{ + NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius"); + return mode.B.startRadiusVar; +} + +-(void) setEndRadius:(float)endRadius +{ + NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius"); + mode.B.endRadius = endRadius; +} +-(float) endRadius +{ + NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius"); + return mode.B.endRadius; +} + +-(void) setEndRadiusVar:(float)endRadiusVar +{ + NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius"); + mode.B.endRadiusVar = endRadiusVar; +} +-(float) endRadiusVar +{ + NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius"); + return mode.B.endRadiusVar; +} + +-(void) setRotatePerSecond:(float)degrees +{ + NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius"); + mode.B.rotatePerSecond = degrees; +} +-(float) rotatePerSecond +{ + NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius"); + return mode.B.rotatePerSecond; +} + +-(void) setRotatePerSecondVar:(float)degrees +{ + NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius"); + mode.B.rotatePerSecondVar = degrees; +} +-(float) rotatePerSecondVar +{ + NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius"); + return mode.B.rotatePerSecondVar; +} +@end + + diff --git a/Classes/cocos2d/CCParticleSystemPoint.h b/Classes/cocos2d/CCParticleSystemPoint.h new file mode 100644 index 0000000..029ad41 --- /dev/null +++ b/Classes/cocos2d/CCParticleSystemPoint.h @@ -0,0 +1,64 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + + +#import +#import "CCParticleSystem.h" + +#define CC_MAX_PARTICLE_SIZE 64 + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + +/** CCParticleSystemPoint is a subclass of CCParticleSystem + Attributes of a Particle System: + * All the attributes of Particle System + + Features: + * consumes small memory: uses 1 vertex (x,y) per particle, no need to assign tex coordinates + * size can't be bigger than 64 + * the system can't be scaled since the particles are rendered using GL_POINT_SPRITE + + Limitations: + * On 3rd gen iPhone devices and iPads, this node performs MUCH slower than CCParticleSystemQuad. + */ +@interface CCParticleSystemPoint : CCParticleSystem +{ + // Array of (x,y,size) + ccPointSprite *vertices; + // vertices buffer id +#if CC_USES_VBO + GLuint verticesID; +#endif +} +@end + +#elif __MAC_OS_X_VERSION_MAX_ALLOWED + +#import "CCParticleSystemQuad.h" + +@interface CCParticleSystemPoint : CCParticleSystemQuad +@end + +#endif diff --git a/Classes/cocos2d/CCParticleSystemPoint.m b/Classes/cocos2d/CCParticleSystemPoint.m new file mode 100644 index 0000000..f789f04 --- /dev/null +++ b/Classes/cocos2d/CCParticleSystemPoint.m @@ -0,0 +1,207 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + * + */ + +#import +#import "CCParticleSystemPoint.h" + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + +// opengl +#import "Platforms/CCGL.h" + +// cocos2d +#import "CCTextureCache.h" +#import "ccMacros.h" + +// support +#import "Support/OpenGL_Internal.h" +#import "Support/CGPointExtension.h" + +@implementation CCParticleSystemPoint + +-(id) initWithTotalParticles:(int) numberOfParticles +{ + if( (self=[super initWithTotalParticles:numberOfParticles]) ) { + + vertices = malloc( sizeof(ccPointSprite) * totalParticles ); + + if( ! vertices ) { + NSLog(@"cocos2d: Particle system: not enough memory"); + [self release]; + return nil; + } + +#if CC_USES_VBO + glGenBuffers(1, &verticesID); + + // initial binding + glBindBuffer(GL_ARRAY_BUFFER, verticesID); + glBufferData(GL_ARRAY_BUFFER, sizeof(ccPointSprite)*totalParticles, vertices, GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); +#endif + } + + return self; +} + +-(void) dealloc +{ + free(vertices); +#if CC_USES_VBO + glDeleteBuffers(1, &verticesID); +#endif + + [super dealloc]; +} + +-(void) updateQuadWithParticle:(tCCParticle*)p newPosition:(CGPoint)newPos +{ + // place vertices and colos in array + vertices[particleIdx].pos = (ccVertex2F) {newPos.x, newPos.y}; + vertices[particleIdx].size = p->size; + vertices[particleIdx].colors = p->color; +} + +-(void) postStep +{ +#if CC_USES_VBO + glBindBuffer(GL_ARRAY_BUFFER, verticesID); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(ccPointSprite)*particleCount, vertices); + glBindBuffer(GL_ARRAY_BUFFER, 0); +#endif +} + +-(void) draw +{ + if (particleIdx==0) + return; + + // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY + // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY + // Unneeded states: GL_TEXTURE_COORD_ARRAY + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + glBindTexture(GL_TEXTURE_2D, texture_.name); + + glEnable(GL_POINT_SPRITE_OES); + glTexEnvi( GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE ); + +#define kPointSize sizeof(vertices[0]) + +#if CC_USES_VBO + glBindBuffer(GL_ARRAY_BUFFER, verticesID); + + glVertexPointer(2,GL_FLOAT, kPointSize, 0); + + glColorPointer(4, GL_FLOAT, kPointSize, (GLvoid*) offsetof(ccPointSprite, colors) ); + + glEnableClientState(GL_POINT_SIZE_ARRAY_OES); + glPointSizePointerOES(GL_FLOAT, kPointSize, (GLvoid*) offsetof(ccPointSprite, size) ); +#else // Uses Vertex Array List + int offset = (int)vertices; + glVertexPointer(2,GL_FLOAT, kPointSize, (GLvoid*) offset); + + int diff = offsetof(ccPointSprite, colors); + glColorPointer(4, GL_FLOAT, kPointSize, (GLvoid*) (offset+diff)); + + glEnableClientState(GL_POINT_SIZE_ARRAY_OES); + diff = offsetof(ccPointSprite, size); + glPointSizePointerOES(GL_FLOAT, kPointSize, (GLvoid*) (offset+diff)); +#endif + + BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST; + if( newBlend ) + glBlendFunc( blendFunc_.src, blendFunc_.dst ); + + + glDrawArrays(GL_POINTS, 0, particleIdx); + + // restore blend state + if( newBlend ) + glBlendFunc( CC_BLEND_SRC, CC_BLEND_DST); + + +#if CC_USES_VBO + // unbind VBO buffer + glBindBuffer(GL_ARRAY_BUFFER, 0); +#endif + + glDisableClientState(GL_POINT_SIZE_ARRAY_OES); + glDisable(GL_POINT_SPRITE_OES); + + // restore GL default state + glEnableClientState(GL_TEXTURE_COORD_ARRAY); +} + +#pragma mark Non supported properties + +// +// SPIN IS NOT SUPPORTED +// +-(void) setStartSpin:(float)a +{ + NSAssert(a == 0, @"PointParticleSystem doesn't support spinning"); + [super setStartSpin:a]; +} +-(void) setStartSpinVar:(float)a +{ + NSAssert(a == 0, @"PointParticleSystem doesn't support spinning"); + [super setStartSpin:a]; +} +-(void) setEndSpin:(float)a +{ + NSAssert(a == 0, @"PointParticleSystem doesn't support spinning"); + [super setStartSpin:a]; +} +-(void) setEndSpinVar:(float)a +{ + NSAssert(a == 0, @"PointParticleSystem doesn't support spinning"); + [super setStartSpin:a]; +} + +// +// SIZE > 64 IS NOT SUPPORTED +// +-(void) setStartSize:(float)size +{ + NSAssert(size >= 0 && size <= CC_MAX_PARTICLE_SIZE, @"PointParticleSystem only supports 0 <= size <= 64"); + [super setStartSize:size]; +} + +-(void) setEndSize:(float)size +{ + NSAssert( (size == kCCParticleStartSizeEqualToEndSize) || + ( size >= 0 && size <= CC_MAX_PARTICLE_SIZE), @"PointParticleSystem only supports 0 <= size <= 64"); + [super setEndSize:size]; +} +@end + +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) +@implementation CCParticleSystemPoint +@end + +#endif // __MAC_OS_X_VERSION_MAX_ALLOWED + + diff --git a/Classes/cocos2d/CCParticleSystemQuad.h b/Classes/cocos2d/CCParticleSystemQuad.h new file mode 100644 index 0000000..eea9edd --- /dev/null +++ b/Classes/cocos2d/CCParticleSystemQuad.h @@ -0,0 +1,74 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2009 Leonardo Kasperavičius + * + * 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. + * + */ + + +#import "CCParticleSystem.h" +#import "ccConfig.h" + +@class CCSpriteFrame; + +/** CCParticleSystemQuad is a subclass of CCParticleSystem + + It includes all the features of ParticleSystem. + + Special features and Limitations: + - Particle size can be any float number. + - The system can be scaled + - The particles can be rotated + - On 1st and 2nd gen iPhones: It is only a bit slower that CCParticleSystemPoint + - On 3rd gen iPhone and iPads: It is MUCH faster than CCParticleSystemPoint + - It consumes more RAM and more GPU memory than CCParticleSystemPoint + - It supports subrects + @since v0.8 + */ +@interface CCParticleSystemQuad : CCParticleSystem +{ + ccV2F_C4F_T2F_Quad *quads_; // quads to be rendered + GLushort *indices_; // indices +#if CC_USES_VBO + GLuint quadsID_; // VBO id +#endif +} + +/** initialices the indices for the vertices */ +-(void) initIndices; + +/** initilizes the texture with a rectangle measured Points */ +-(void) initTexCoordsWithRect:(CGRect)rect; + +/** Sets a new CCSpriteFrame as particle. + WARNING: this method is experimental. Use setTexture:withRect instead. + @since v0.99.4 + */ +-(void)setDisplayFrame:(CCSpriteFrame*)spriteFrame; + +/** Sets a new texture with a rect. The rect is in Points. + @since v0.99.4 + */ +-(void) setTexture:(CCTexture2D *)texture withRect:(CGRect)rect; + +@end + diff --git a/Classes/cocos2d/CCParticleSystemQuad.m b/Classes/cocos2d/CCParticleSystemQuad.m new file mode 100644 index 0000000..219f2cc --- /dev/null +++ b/Classes/cocos2d/CCParticleSystemQuad.m @@ -0,0 +1,314 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2009 Leonardo Kasperavičius + * + * 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. + * + */ + + +// opengl +#import "Platforms/CCGL.h" + +// cocos2d +#import "ccConfig.h" +#import "CCParticleSystemQuad.h" +#import "CCTextureCache.h" +#import "ccMacros.h" +#import "CCSpriteFrame.h" + +// support +#import "Support/OpenGL_Internal.h" +#import "Support/CGPointExtension.h" + +@implementation CCParticleSystemQuad + + +// overriding the init method +-(id) initWithTotalParticles:(int) numberOfParticles +{ + // base initialization + if( (self=[super initWithTotalParticles:numberOfParticles]) ) { + + // allocating data space + quads_ = calloc( sizeof(quads_[0]) * totalParticles, 1 ); + indices_ = calloc( sizeof(indices_[0]) * totalParticles * 6, 1 ); + + if( !quads_ || !indices_) { + NSLog(@"cocos2d: Particle system: not enough memory"); + if( quads_ ) + free( quads_ ); + if(indices_) + free(indices_); + + [self release]; + return nil; + } + + // initialize only once the texCoords and the indices + [self initTexCoordsWithRect:CGRectMake(0, 0, [texture_ pixelsWide], [texture_ pixelsHigh])]; + [self initIndices]; + +#if CC_USES_VBO + // create the VBO buffer + glGenBuffers(1, &quadsID_); + + // initial binding + glBindBuffer(GL_ARRAY_BUFFER, quadsID_); + glBufferData(GL_ARRAY_BUFFER, sizeof(quads_[0])*totalParticles, quads_,GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); +#endif + } + + return self; +} + +-(void) dealloc +{ + free(quads_); + free(indices_); +#if CC_USES_VBO + glDeleteBuffers(1, &quadsID_); +#endif + + [super dealloc]; +} + +// rect is in Points coordinates. +-(void) initTexCoordsWithRect:(CGRect)pointRect +{ + // convert to Tex coords + + CGRect rect = CGRectMake( + pointRect.origin.x * CC_CONTENT_SCALE_FACTOR(), + pointRect.origin.y * CC_CONTENT_SCALE_FACTOR(), + pointRect.size.width * CC_CONTENT_SCALE_FACTOR(), + pointRect.size.height * CC_CONTENT_SCALE_FACTOR() ); + + GLfloat wide = [texture_ pixelsWide]; + GLfloat high = [texture_ pixelsHigh]; + +#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL + GLfloat left = (rect.origin.x*2+1) / (wide*2); + GLfloat bottom = (rect.origin.y*2+1) / (high*2); + GLfloat right = left + (rect.size.width*2-2) / (wide*2); + GLfloat top = bottom + (rect.size.height*2-2) / (high*2); +#else + GLfloat left = rect.origin.x / wide; + GLfloat bottom = rect.origin.y / high; + GLfloat right = left + rect.size.width / wide; + GLfloat top = bottom + rect.size.height / high; +#endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL + + // Important. Texture in cocos2d are inverted, so the Y component should be inverted + CC_SWAP( top, bottom); + + for(NSUInteger i=0; ibl.colors = p->color; + quad->br.colors = p->color; + quad->tl.colors = p->color; + quad->tr.colors = p->color; + + // vertices + GLfloat size_2 = p->size/2; + if( p->rotation ) { + GLfloat x1 = -size_2; + GLfloat y1 = -size_2; + + GLfloat x2 = size_2; + GLfloat y2 = size_2; + GLfloat x = newPos.x; + GLfloat y = newPos.y; + + GLfloat r = (GLfloat)-CC_DEGREES_TO_RADIANS(p->rotation); + GLfloat cr = cosf(r); + GLfloat sr = sinf(r); + GLfloat ax = x1 * cr - y1 * sr + x; + GLfloat ay = x1 * sr + y1 * cr + y; + GLfloat bx = x2 * cr - y1 * sr + x; + GLfloat by = x2 * sr + y1 * cr + y; + GLfloat cx = x2 * cr - y2 * sr + x; + GLfloat cy = x2 * sr + y2 * cr + y; + GLfloat dx = x1 * cr - y2 * sr + x; + GLfloat dy = x1 * sr + y2 * cr + y; + + // bottom-left + quad->bl.vertices.x = ax; + quad->bl.vertices.y = ay; + + // bottom-right vertex: + quad->br.vertices.x = bx; + quad->br.vertices.y = by; + + // top-left vertex: + quad->tl.vertices.x = dx; + quad->tl.vertices.y = dy; + + // top-right vertex: + quad->tr.vertices.x = cx; + quad->tr.vertices.y = cy; + } else { + // bottom-left vertex: + quad->bl.vertices.x = newPos.x - size_2; + quad->bl.vertices.y = newPos.y - size_2; + + // bottom-right vertex: + quad->br.vertices.x = newPos.x + size_2; + quad->br.vertices.y = newPos.y - size_2; + + // top-left vertex: + quad->tl.vertices.x = newPos.x - size_2; + quad->tl.vertices.y = newPos.y + size_2; + + // top-right vertex: + quad->tr.vertices.x = newPos.x + size_2; + quad->tr.vertices.y = newPos.y + size_2; + } +} + +-(void) postStep +{ +#if CC_USES_VBO + glBindBuffer(GL_ARRAY_BUFFER, quadsID_); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(quads_[0])*particleCount, quads_); + glBindBuffer(GL_ARRAY_BUFFER, 0); +#endif +} + +// overriding draw method +-(void) draw +{ + // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY + // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY + // Unneeded states: - + + glBindTexture(GL_TEXTURE_2D, [texture_ name]); + +#define kQuadSize sizeof(quads_[0].bl) + +#if CC_USES_VBO + glBindBuffer(GL_ARRAY_BUFFER, quadsID_); + + glVertexPointer(2,GL_FLOAT, kQuadSize, 0); + + glColorPointer(4, GL_FLOAT, kQuadSize, (GLvoid*) offsetof(ccV2F_C4F_T2F,colors) ); + + glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*) offsetof(ccV2F_C4F_T2F,texCoords) ); +#else // vertex array list + + NSUInteger offset = (NSUInteger) quads_; + + // vertex + NSUInteger diff = offsetof( ccV2F_C4F_T2F, vertices); + glVertexPointer(2,GL_FLOAT, kQuadSize, (GLvoid*) (offset+diff) ); + + // color + diff = offsetof( ccV2F_C4F_T2F, colors); + glColorPointer(4, GL_FLOAT, kQuadSize, (GLvoid*)(offset + diff)); + + // tex coords + diff = offsetof( ccV2F_C4F_T2F, texCoords); + glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*)(offset + diff)); + +#endif // ! CC_USES_VBO + + BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST; + if( newBlend ) + glBlendFunc( blendFunc_.src, blendFunc_.dst ); + + NSAssert( particleIdx == particleCount, @"Abnormal error in particle quad"); + glDrawElements(GL_TRIANGLES, particleIdx*6, GL_UNSIGNED_SHORT, indices_); + + // restore blend state + if( newBlend ) + glBlendFunc( CC_BLEND_SRC, CC_BLEND_DST ); + +#if CC_USES_VBO + glBindBuffer(GL_ARRAY_BUFFER, 0); +#endif + + // restore GL default state + // - +} + +@end + + diff --git a/Classes/cocos2d/CCProgressTimer.h b/Classes/cocos2d/CCProgressTimer.h new file mode 100644 index 0000000..6661a6f --- /dev/null +++ b/Classes/cocos2d/CCProgressTimer.h @@ -0,0 +1,83 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Lam Pham + * + * 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. + * + */ + +#import +#import "CCSprite.h" + +/** Types of progress + @since v0.99.1 + */ +typedef enum { + /// Radial Counter-Clockwise + kCCProgressTimerTypeRadialCCW, + /// Radial ClockWise + kCCProgressTimerTypeRadialCW, + /// Horizontal Left-Right + kCCProgressTimerTypeHorizontalBarLR, + /// Horizontal Right-Left + kCCProgressTimerTypeHorizontalBarRL, + /// Vertical Bottom-top + kCCProgressTimerTypeVerticalBarBT, + /// Vertical Top-Bottom + kCCProgressTimerTypeVerticalBarTB, +} CCProgressTimerType; + +/** + CCProgresstimer is a subclass of CCNode. + It renders the inner sprite according to the percentage. + The progress can be Radial, Horizontal or vertical. + @since v0.99.1 + */ +@interface CCProgressTimer : CCNode +{ + CCProgressTimerType type_; + float percentage_; + CCSprite *sprite_; + + int vertexDataCount_; + ccV2F_C4F_T2F *vertexData_; +} + +/** Change the percentage to change progress. */ +@property (nonatomic, readwrite) CCProgressTimerType type; + +/** Percentages are from 0 to 100 */ +@property (nonatomic, readwrite) float percentage; + +/** The image to show the progress percentage */ +@property (nonatomic, readwrite, retain) CCSprite *sprite; + + +/** Creates a progress timer with an image filename as the shape the timer goes through */ ++ (id) progressWithFile:(NSString*) filename; +/** Initializes a progress timer with an image filename as the shape the timer goes through */ +- (id) initWithFile:(NSString*) filename; + +/** Creates a progress timer with the texture as the shape the timer goes through */ ++ (id) progressWithTexture:(CCTexture2D*) texture; +/** Creates a progress timer with the texture as the shape the timer goes through */ +- (id) initWithTexture:(CCTexture2D*) texture; + +@end diff --git a/Classes/cocos2d/CCProgressTimer.m b/Classes/cocos2d/CCProgressTimer.m new file mode 100644 index 0000000..20c66c6 --- /dev/null +++ b/Classes/cocos2d/CCProgressTimer.m @@ -0,0 +1,494 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Lam Pham + * + * 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. + * + */ + +#import "CCProgressTimer.h" + +#import "ccMacros.h" +#import "CCTextureCache.h" +#import "Support/CGPointExtension.h" + + + +#define kProgressTextureCoordsCount 4 +// kProgressTextureCoords holds points {0,0} {0,1} {1,1} {1,0} we can represent it as bits +const char kProgressTextureCoords = 0x1e; + +@interface CCProgressTimer (Internal) + +-(void)updateProgress; +-(void)updateBar; +-(void)updateRadial; +-(void)updateColor; +-(CGPoint)boundaryTexCoord:(char)index; +@end + + +@implementation CCProgressTimer +@synthesize percentage = percentage_; +@synthesize sprite = sprite_; +@synthesize type = type_; + ++(id)progressWithFile:(NSString*) filename +{ + return [[[self alloc]initWithFile:filename] autorelease]; +} +-(id)initWithFile:(NSString*) filename +{ + return [self initWithTexture:[[CCTextureCache sharedTextureCache] addImage: filename]]; +} + ++(id)progressWithTexture:(CCTexture2D*) texture +{ + return [[[self alloc]initWithTexture:texture] autorelease]; +} +-(id)initWithTexture:(CCTexture2D*) texture +{ + if(( self = [super init] )){ + self.sprite = [CCSprite spriteWithTexture:texture]; + percentage_ = 0.f; + vertexData_ = NULL; + vertexDataCount_ = 0; + self.anchorPoint = ccp(.5f,.5f); + self.contentSize = sprite_.contentSize; + self.type = kCCProgressTimerTypeRadialCCW; + } + return self; +} +-(void)dealloc +{ + if(vertexData_) + free(vertexData_); + + [sprite_ release]; + [super dealloc]; +} + +-(void)setPercentage:(float) percentage +{ + if(percentage_ != percentage){ + if(percentage_ < 0.f) + percentage_ = 0.f; + else if(percentage > 100.0f) + percentage_ = 100.f; + else + percentage_ = percentage; + + [self updateProgress]; + } +} +-(void)setSprite:(CCSprite *)newSprite +{ + if(sprite_ != newSprite){ + [sprite_ release]; + sprite_ = [newSprite retain]; + + // Everytime we set a new sprite, we free the current vertex data + if(vertexData_){ + free(vertexData_); + vertexData_ = NULL; + vertexDataCount_ = 0; + } + } +} +-(void)setType:(CCProgressTimerType)newType +{ + if (newType != type_) { + + // release all previous information + if(vertexData_){ + free(vertexData_); + vertexData_ = NULL; + vertexDataCount_ = 0; + } + type_ = newType; + } +} +@end + +@implementation CCProgressTimer(Internal) + +/// +// @returns the vertex position from the texture coordinate +/// +-(ccVertex2F)vertexFromTexCoord:(CGPoint) texCoord +{ + CGPoint tmp; + ccVertex2F ret; + if (sprite_.texture) { + CCTexture2D *texture = [sprite_ texture]; + CGSize texSize = [texture contentSizeInPixels]; + tmp = ccp(texSize.width * texCoord.x/texture.maxS, + texSize.height * (1 - (texCoord.y/texture.maxT))); + } else + tmp = CGPointZero; + + ret.x = tmp.x; + ret.y = tmp.y; + return ret; +} +-(void)updateColor { + ccColor4F color = ccc4FFromccc3B(sprite_.color); + if([sprite_.texture hasPremultipliedAlpha]){ + float op = sprite_.opacity/255.f; + color.r *= op; + color.g *= op; + color.b *= op; + color.a = op; + } else + color.a = sprite_.opacity/255.f; + + if(vertexData_){ + for (int i=0; i < vertexDataCount_; ++i) { + vertexData_[i].colors = color; + } + } +} + +-(void)updateProgress +{ + switch (type_) { + case kCCProgressTimerTypeRadialCW: + case kCCProgressTimerTypeRadialCCW: + [self updateRadial]; + break; + case kCCProgressTimerTypeHorizontalBarLR: + case kCCProgressTimerTypeHorizontalBarRL: + case kCCProgressTimerTypeVerticalBarBT: + case kCCProgressTimerTypeVerticalBarTB: + [self updateBar]; + break; + default: + break; + } +} + +/// +// Update does the work of mapping the texture onto the triangles +// It now doesn't occur the cost of free/alloc data every update cycle. +// It also only changes the percentage point but no other points if they have not +// been modified. +// +// It now deals with flipped texture. If you run into this problem, just use the +// sprite property and enable the methods flipX, flipY. +/// +-(void)updateRadial +{ + // Texture Max is the actual max coordinates to deal with non-power of 2 textures + CGPoint tMax = ccp(sprite_.texture.maxS,sprite_.texture.maxT); + + // Grab the midpoint + CGPoint midpoint = ccpCompMult(self.anchorPoint, tMax); + + float alpha = percentage_ / 100.f; + + // Otherwise we can get the angle from the alpha + float angle = 2.f*((float)M_PI) * ( type_ == kCCProgressTimerTypeRadialCW? alpha : 1.f - alpha); + + // We find the vector to do a hit detection based on the percentage + // We know the first vector is the one @ 12 o'clock (top,mid) so we rotate + // from that by the progress angle around the midpoint pivot + CGPoint topMid = ccp(midpoint.x, 0.f); + CGPoint percentagePt = ccpRotateByAngle(topMid, midpoint, angle); + + + int index = 0; + CGPoint hit = CGPointZero; + + if (alpha == 0.f) { + // More efficient since we don't always need to check intersection + // If the alpha is zero then the hit point is top mid and the index is 0. + hit = topMid; + index = 0; + } else if (alpha == 1.f) { + // More efficient since we don't always need to check intersection + // If the alpha is one then the hit point is top mid and the index is 4. + hit = topMid; + index = 4; + } else { + // We run a for loop checking the edges of the texture to find the + // intersection point + // We loop through five points since the top is split in half + + float min_t = FLT_MAX; + + for (int i = 0; i <= kProgressTextureCoordsCount; ++i) { + int pIndex = (i + (kProgressTextureCoordsCount - 1))%kProgressTextureCoordsCount; + + CGPoint edgePtA = ccpCompMult([self boundaryTexCoord:i % kProgressTextureCoordsCount],tMax); + CGPoint edgePtB = ccpCompMult([self boundaryTexCoord:pIndex],tMax); + + // Remember that the top edge is split in half for the 12 o'clock position + // Let's deal with that here by finding the correct endpoints + if(i == 0){ + edgePtB = ccpLerp(edgePtA,edgePtB,.5f); + } else if(i == 4){ + edgePtA = ccpLerp(edgePtA,edgePtB,.5f); + } + + // s and t are returned by ccpLineIntersect + float s = 0, t = 0; + if(ccpLineIntersect(edgePtA, edgePtB, midpoint, percentagePt, &s, &t)) + { + + // Since our hit test is on rays we have to deal with the top edge + // being in split in half so we have to test as a segment + if ((i == 0 || i == 4)) { + // s represents the point between edgePtA--edgePtB + if (!(0.f <= s && s <= 1.f)) { + continue; + } + } + // As long as our t isn't negative we are at least finding a + // correct hitpoint from midpoint to percentagePt. + if (t >= 0.f) { + // Because the percentage line and all the texture edges are + // rays we should only account for the shortest intersection + if (t < min_t) { + min_t = t; + index = i; + } + } + } + } + + // Now that we have the minimum magnitude we can use that to find our intersection + hit = ccpAdd(midpoint, ccpMult(ccpSub(percentagePt, midpoint),min_t)); + + } + + + // The size of the vertex data is the index from the hitpoint + // the 3 is for the midpoint, 12 o'clock point and hitpoint position. + + BOOL sameIndexCount = YES; + if(vertexDataCount_ != index + 3){ + sameIndexCount = NO; + if(vertexData_){ + free(vertexData_); + vertexData_ = NULL; + vertexDataCount_ = 0; + } + } + + + if(!vertexData_) { + vertexDataCount_ = index + 3; + vertexData_ = malloc(vertexDataCount_ * sizeof(ccV2F_C4F_T2F)); + NSAssert( vertexData_, @"CCProgressTimer. Not enough memory"); + + [self updateColor]; + } + + if (!sameIndexCount) { + + // First we populate the array with the midpoint, then all + // vertices/texcoords/colors of the 12 'o clock start and edges and the hitpoint + vertexData_[0].texCoords = (ccTex2F){midpoint.x, midpoint.y}; + vertexData_[0].vertices = [self vertexFromTexCoord:midpoint]; + + vertexData_[1].texCoords = (ccTex2F){midpoint.x, 0.f}; + vertexData_[1].vertices = [self vertexFromTexCoord:ccp(midpoint.x, 0.f)]; + + for(int i = 0; i < index; ++i){ + CGPoint texCoords = ccpCompMult([self boundaryTexCoord:i], tMax); + + vertexData_[i+2].texCoords = (ccTex2F){texCoords.x, texCoords.y}; + vertexData_[i+2].vertices = [self vertexFromTexCoord:texCoords]; + } + + // Flip the texture coordinates if set + if (sprite_.flipY || sprite_.flipX) { + for(int i = 0; i < vertexDataCount_ - 1; ++i){ + if (sprite_.flipX) { + vertexData_[i].texCoords.u = tMax.x - vertexData_[i].texCoords.u; + } + if(sprite_.flipY){ + vertexData_[i].texCoords.v = tMax.y - vertexData_[i].texCoords.v; + } + } + } + } + + // hitpoint will go last + vertexData_[vertexDataCount_ - 1].texCoords = (ccTex2F){hit.x, hit.y}; + vertexData_[vertexDataCount_ - 1].vertices = [self vertexFromTexCoord:hit]; + + if (sprite_.flipY || sprite_.flipX) { + if (sprite_.flipX) { + vertexData_[vertexDataCount_ - 1].texCoords.u = tMax.x - vertexData_[vertexDataCount_ - 1].texCoords.u; + } + if(sprite_.flipY){ + vertexData_[vertexDataCount_ - 1].texCoords.v = tMax.y - vertexData_[vertexDataCount_ - 1].texCoords.v; + } + } +} + +/// +// Update does the work of mapping the texture onto the triangles for the bar +// It now doesn't occur the cost of free/alloc data every update cycle. +// It also only changes the percentage point but no other points if they have not +// been modified. +// +// It now deals with flipped texture. If you run into this problem, just use the +// sprite property and enable the methods flipX, flipY. +/// +-(void)updateBar +{ + + float alpha = percentage_ / 100.f; + + CGPoint tMax = ccp(sprite_.texture.maxS,sprite_.texture.maxT); + + unsigned char vIndexes[2] = {0,0}; + + // We know vertex data is always equal to the 4 corners + // If we don't have vertex data then we create it here and populate + // the side of the bar vertices that won't ever change. + if (!vertexData_) { + vertexDataCount_ = kProgressTextureCoordsCount; + vertexData_ = malloc(vertexDataCount_ * sizeof(ccV2F_C4F_T2F)); + NSAssert( vertexData_, @"CCProgressTimer. Not enough memory"); + + if(type_ == kCCProgressTimerTypeHorizontalBarLR){ + vertexData_[vIndexes[0] = 0].texCoords = (ccTex2F){0,0}; + vertexData_[vIndexes[1] = 1].texCoords = (ccTex2F){0, tMax.y}; + }else if (type_ == kCCProgressTimerTypeHorizontalBarRL) { + vertexData_[vIndexes[0] = 2].texCoords = (ccTex2F){tMax.x, tMax.y}; + vertexData_[vIndexes[1] = 3].texCoords = (ccTex2F){tMax.x, 0.f}; + }else if (type_ == kCCProgressTimerTypeVerticalBarBT) { + vertexData_[vIndexes[0] = 1].texCoords = (ccTex2F){0, tMax.y}; + vertexData_[vIndexes[1] = 3].texCoords = (ccTex2F){tMax.x, tMax.y}; + }else if (type_ == kCCProgressTimerTypeVerticalBarTB) { + vertexData_[vIndexes[0] = 0].texCoords = (ccTex2F){0, 0}; + vertexData_[vIndexes[1] = 2].texCoords = (ccTex2F){tMax.x, 0}; + } + + unsigned char index = vIndexes[0]; + vertexData_[index].vertices = [self vertexFromTexCoord:ccp(vertexData_[index].texCoords.u, vertexData_[index].texCoords.v)]; + + index = vIndexes[1]; + vertexData_[index].vertices = [self vertexFromTexCoord:ccp(vertexData_[index].texCoords.u, vertexData_[index].texCoords.v)]; + + if (sprite_.flipY || sprite_.flipX) { + if (sprite_.flipX) { + unsigned char index = vIndexes[0]; + vertexData_[index].texCoords.u = tMax.x - vertexData_[index].texCoords.u; + index = vIndexes[1]; + vertexData_[index].texCoords.u = tMax.x - vertexData_[index].texCoords.u; + } + if(sprite_.flipY){ + unsigned char index = vIndexes[0]; + vertexData_[index].texCoords.v = tMax.y - vertexData_[index].texCoords.v; + index = vIndexes[1]; + vertexData_[index].texCoords.v = tMax.y - vertexData_[index].texCoords.v; + } + } + + [self updateColor]; + } + + if(type_ == kCCProgressTimerTypeHorizontalBarLR){ + vertexData_[vIndexes[0] = 3].texCoords = (ccTex2F){tMax.x*alpha, tMax.y}; + vertexData_[vIndexes[1] = 2].texCoords = (ccTex2F){tMax.x*alpha, 0}; + }else if (type_ == kCCProgressTimerTypeHorizontalBarRL) { + vertexData_[vIndexes[0] = 1].texCoords = (ccTex2F){tMax.x*(1.f - alpha), 0}; + vertexData_[vIndexes[1] = 0].texCoords = (ccTex2F){tMax.x*(1.f - alpha), tMax.y}; + }else if (type_ == kCCProgressTimerTypeVerticalBarBT) { + vertexData_[vIndexes[0] = 0].texCoords = (ccTex2F){0, tMax.y*(1.f - alpha)}; + vertexData_[vIndexes[1] = 2].texCoords = (ccTex2F){tMax.x, tMax.y*(1.f - alpha)}; + }else if (type_ == kCCProgressTimerTypeVerticalBarTB) { + vertexData_[vIndexes[0] = 1].texCoords = (ccTex2F){0, tMax.y*alpha}; + vertexData_[vIndexes[1] = 3].texCoords = (ccTex2F){tMax.x, tMax.y*alpha}; + } + + unsigned char index = vIndexes[0]; + vertexData_[index].vertices = [self vertexFromTexCoord:ccp(vertexData_[index].texCoords.u, vertexData_[index].texCoords.v)]; + index = vIndexes[1]; + vertexData_[index].vertices = [self vertexFromTexCoord:ccp(vertexData_[index].texCoords.u, vertexData_[index].texCoords.v)]; + + if (sprite_.flipY || sprite_.flipX) { + if (sprite_.flipX) { + unsigned char index = vIndexes[0]; + vertexData_[index].texCoords.u = tMax.x - vertexData_[index].texCoords.u; + index = vIndexes[1]; + vertexData_[index].texCoords.u = tMax.x - vertexData_[index].texCoords.u; + } + if(sprite_.flipY){ + unsigned char index = vIndexes[0]; + vertexData_[index].texCoords.v = tMax.y - vertexData_[index].texCoords.v; + index = vIndexes[1]; + vertexData_[index].texCoords.v = tMax.y - vertexData_[index].texCoords.v; + } + } + +} + +-(CGPoint)boundaryTexCoord:(char)index +{ + if (index < kProgressTextureCoordsCount) { + switch (type_) { + case kCCProgressTimerTypeRadialCW: + return ccp((kProgressTextureCoords>>((index<<1)+1))&1,(kProgressTextureCoords>>(index<<1))&1); + case kCCProgressTimerTypeRadialCCW: + return ccp((kProgressTextureCoords>>(7-(index<<1)))&1,(kProgressTextureCoords>>(7-((index<<1)+1)))&1); + default: + break; + } + } + return CGPointZero; +} + +-(void)draw +{ + if(!vertexData_)return; + if(!sprite_)return; + ccBlendFunc blendFunc = sprite_.blendFunc; + BOOL newBlend = blendFunc.src != CC_BLEND_SRC || blendFunc.dst != CC_BLEND_DST; + if( newBlend ) + glBlendFunc( blendFunc.src, blendFunc.dst ); + + /// ======================================================================== + // Replaced [texture_ drawAtPoint:CGPointZero] with my own vertexData + // Everything above me and below me is copied from CCTextureNode's draw + glBindTexture(GL_TEXTURE_2D, sprite_.texture.name); + glVertexPointer(2, GL_FLOAT, sizeof(ccV2F_C4F_T2F), &vertexData_[0].vertices); + glTexCoordPointer(2, GL_FLOAT, sizeof(ccV2F_C4F_T2F), &vertexData_[0].texCoords); + glColorPointer(4, GL_FLOAT, sizeof(ccV2F_C4F_T2F), &vertexData_[0].colors); + if(type_ == kCCProgressTimerTypeRadialCCW || type_ == kCCProgressTimerTypeRadialCW){ + glDrawArrays(GL_TRIANGLE_FAN, 0, vertexDataCount_); + } else if (type_ == kCCProgressTimerTypeHorizontalBarLR || + type_ == kCCProgressTimerTypeHorizontalBarRL || + type_ == kCCProgressTimerTypeVerticalBarBT || + type_ == kCCProgressTimerTypeVerticalBarTB) { + glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexDataCount_); + } + //glDrawElements(GL_TRIANGLES, indicesCount_, GL_UNSIGNED_BYTE, indices_); + /// ======================================================================== + + if( newBlend ) + glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST); +} + +@end diff --git a/Classes/cocos2d/CCProtocols.h b/Classes/cocos2d/CCProtocols.h new file mode 100644 index 0000000..f40c1ab --- /dev/null +++ b/Classes/cocos2d/CCProtocols.h @@ -0,0 +1,124 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * + * 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. + */ + + +#import "ccTypes.h" +#import "CCTexture2D.h" + +#pragma mark - +#pragma mark CCRGBAProtocol + +/// CC RGBA protocol +@protocol CCRGBAProtocol +/** sets Color + @since v0.8 + */ +-(void) setColor:(ccColor3B)color; +/** returns the color + @since v0.8 + */ +-(ccColor3B) color; + +/// returns the opacity +-(GLubyte) opacity; +/** sets the opacity. + @warning If the the texture has premultiplied alpha then, the R, G and B channels will be modifed. + Values goes from 0 to 255, where 255 means fully opaque. + */ +-(void) setOpacity: (GLubyte) opacity; +@optional +/** sets the premultipliedAlphaOpacity property. + If set to NO then opacity will be applied as: glColor(R,G,B,opacity); + If set to YES then oapcity will be applied as: glColor(opacity, opacity, opacity, opacity ); + Textures with premultiplied alpha will have this property by default on YES. Otherwise the default value is NO + @since v0.8 + */ +-(void) setOpacityModifyRGB:(BOOL)boolean; +/** returns whether or not the opacity will be applied using glColor(R,G,B,opacity) or glColor(opacity, opacity, opacity, opacity); + @since v0.8 + */ + -(BOOL) doesOpacityModifyRGB; +@end + +#pragma mark - +#pragma mark CCBlendProtocol +/** + You can specify the blending fuction. + @since v0.99.0 + */ +@protocol CCBlendProtocol +/** set the source blending function for the texture */ +-(void) setBlendFunc:(ccBlendFunc)blendFunc; +/** returns the blending function used for the texture */ +-(ccBlendFunc) blendFunc; +@end + + +#pragma mark - +#pragma mark CCTextureProtocol + +/** CCNode objects that uses a Texture2D to render the images. + The texture can have a blending function. + If the texture has alpha premultiplied the default blending function is: + src=GL_ONE dst= GL_ONE_MINUS_SRC_ALPHA + else + src=GL_SRC_ALPHA dst= GL_ONE_MINUS_SRC_ALPHA + But you can change the blending funtion at any time. + @since v0.8.0 + */ +@protocol CCTextureProtocol +/** returns the used texture */ +-(CCTexture2D*) texture; +/** sets a new texture. it will be retained */ +-(void) setTexture:(CCTexture2D*)texture; +@end + +#pragma mark - +#pragma mark CCLabelProtocol +/** Common interface for Labels */ +@protocol CCLabelProtocol +/** sets a new label using an NSString. + The string will be copied. + */ +-(void) setString:(NSString*)label; +/** returns the string that is rendered */ +-(NSString*) string; +@optional +/** sets a new label using a CString. + It is faster than setString since it doesn't require to alloc/retain/release an NString object. + @since v0.99.0 + */ +-(void) setCString:(char*)label; +@end + + +#pragma mark - +#pragma mark CCProjectionProtocol +/** OpenGL projection protocol */ +@protocol CCProjectionProtocol +/** Called by CCDirector when the porjection is updated, and "custom" projection is used + @since v0.99.5 + */ +-(void) updateProjection; +@end \ No newline at end of file diff --git a/Classes/cocos2d/CCRenderTexture.h b/Classes/cocos2d/CCRenderTexture.h new file mode 100755 index 0000000..10500f4 --- /dev/null +++ b/Classes/cocos2d/CCRenderTexture.h @@ -0,0 +1,108 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Jason Booth + * + * 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. + * + */ + +#import +#import "CCNode.h" +#import "CCSprite.h" +#import "Support/OpenGL_Internal.h" + +#import +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +#import +#endif // iPHone + +enum +{ + kCCImageFormatJPG = 0, + kCCImageFormatPNG = 1, + kCCImageFormatRawData =2 +}; + + +/** + CCRenderTexture is a generic rendering target. To render things into it, + simply construct a render target, call begin on it, call visit on any cocos + scenes or objects to render them, and call end. For convienience, render texture + adds a sprite as it's display child with the results, so you can simply add + the render texture to your scene and treat it like any other CocosNode. + There are also functions for saving the render texture to disk in PNG or JPG format. + + @since v0.8.1 + */ +@interface CCRenderTexture : CCNode +{ + GLuint fbo_; + GLint oldFBO_; + CCTexture2D* texture_; + CCSprite* sprite_; + + GLenum pixelFormat_; + GLfloat clearColor_[4]; + +} + +/** The CCSprite being used. + The sprite, by default, will use the following blending function: GL_ONE, GL_ONE_MINUS_SRC_ALPHA. + The blending function can be changed in runtime by calling: + - [[renderTexture sprite] setBlendFunc:(ccBlendFunc){GL_ONE, GL_ONE_MINUS_SRC_ALPHA}]; +*/ +@property (nonatomic,readwrite, assign) CCSprite* sprite; + +/** creates a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid */ ++(id)renderTextureWithWidth:(int)w height:(int)h pixelFormat:(CCTexture2DPixelFormat) format; + +/** creates a RenderTexture object with width and height in Points, pixel format is RGBA8888 */ ++(id)renderTextureWithWidth:(int)w height:(int)h; + +/** initializes a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid */ +-(id)initWithWidth:(int)w height:(int)h pixelFormat:(CCTexture2DPixelFormat) format; + +/** starts grabbing */ +-(void)begin; + +/** starts rendering to the texture while clearing the texture first. + This is more efficient then calling -clear first and then -begin */ +-(void)beginWithClear:(float)r g:(float)g b:(float)b a:(float)a; + +/** ends grabbing */ +-(void)end; + +/** clears the texture with a color */ +-(void)clear:(float)r g:(float)g b:(float)b a:(float)a; + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + +/** saves the texture into a file */ +-(BOOL)saveBuffer:(NSString*)name; +/** saves the texture into a file. The format can be JPG or PNG */ +-(BOOL)saveBuffer:(NSString*)name format:(int)format; +/* get buffer as UIImage, can only save a render buffer which has a RGBA8888 pixel format */ +-(NSData*)getUIImageAsDataFromBuffer:(int) format; + +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED + +@end + + diff --git a/Classes/cocos2d/CCRenderTexture.m b/Classes/cocos2d/CCRenderTexture.m new file mode 100755 index 0000000..42e5f7b --- /dev/null +++ b/Classes/cocos2d/CCRenderTexture.m @@ -0,0 +1,308 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Jason Booth + * + * 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. + * + */ + +#import +#import "CCRenderTexture.h" +#import "CCDirector.h" +#import "ccMacros.h" +#import "Support/ccUtils.h" + +@interface CCRenderTexture (private) + +- (void) saveGLstate; +- (void) restoreGLstate; +@end + +@implementation CCRenderTexture + +@synthesize sprite=sprite_; + +// issue #994 ++(id)renderTextureWithWidth:(int)w height:(int)h pixelFormat:(CCTexture2DPixelFormat) format +{ + return [[[self alloc] initWithWidth:w height:h pixelFormat:format] autorelease]; +} + ++(id)renderTextureWithWidth:(int)w height:(int)h +{ + return [[[self alloc] initWithWidth:w height:h pixelFormat:kCCTexture2DPixelFormat_RGBA8888] autorelease]; +} + +-(id)initWithWidth:(int)w height:(int)h +{ + return [self initWithWidth:w height:h pixelFormat:kCCTexture2DPixelFormat_RGBA8888]; +} + +-(id)initWithWidth:(int)w height:(int)h pixelFormat:(CCTexture2DPixelFormat) format +{ + if ((self = [super init])) + { + NSAssert(format != kCCTexture2DPixelFormat_A8,@"only RGB and RGBA formats are valid for a render texture"); + + w *= CC_CONTENT_SCALE_FACTOR(); + h *= CC_CONTENT_SCALE_FACTOR(); + + glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &oldFBO_); + + // textures must be power of two + NSUInteger powW = ccNextPOT(w); + NSUInteger powH = ccNextPOT(h); + + void *data = malloc((int)(powW * powH * 4)); + memset(data, 0, (int)(powW * powH * 4)); + pixelFormat_=format; + + texture_ = [[CCTexture2D alloc] initWithData:data pixelFormat:pixelFormat_ pixelsWide:powW pixelsHigh:powH contentSize:CGSizeMake(w, h)]; + free( data ); + + // generate FBO + ccglGenFramebuffers(1, &fbo_); + ccglBindFramebuffer(CC_GL_FRAMEBUFFER, fbo_); + + // associate texture with FBO + ccglFramebufferTexture2D(CC_GL_FRAMEBUFFER, CC_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_.name, 0); + + // check if it worked (probably worth doing :) ) + GLuint status = ccglCheckFramebufferStatus(CC_GL_FRAMEBUFFER); + if (status != CC_GL_FRAMEBUFFER_COMPLETE) + { + [NSException raise:@"Render Texture" format:@"Could not attach texture to framebuffer"]; + } + [texture_ setAliasTexParameters]; + + sprite_ = [CCSprite spriteWithTexture:texture_]; + + [texture_ release]; + [sprite_ setScaleY:-1]; + [self addChild:sprite_]; + + // issue #937 + [sprite_ setBlendFunc:(ccBlendFunc){GL_ONE, GL_ONE_MINUS_SRC_ALPHA}]; + + ccglBindFramebuffer(CC_GL_FRAMEBUFFER, oldFBO_); + } + return self; +} + +-(void)dealloc +{ +// [self removeAllChildrenWithCleanup:YES]; + ccglDeleteFramebuffers(1, &fbo_); + [super dealloc]; +} + + +-(void)begin +{ + // issue #878 save opengl state + [self saveGLstate]; + + CC_DISABLE_DEFAULT_GL_STATES(); + // Save the current matrix + glPushMatrix(); + + CGSize texSize = [texture_ contentSizeInPixels]; + + // Calculate the adjustment ratios based on the old and new projections + CGSize size = [[CCDirector sharedDirector] displaySizeInPixels]; + float widthRatio = size.width / texSize.width; + float heightRatio = size.height / texSize.height; + + // Adjust the orthographic propjection and viewport + ccglOrtho((float)-1.0 / widthRatio, (float)1.0 / widthRatio, (float)-1.0 / heightRatio, (float)1.0 / heightRatio, -1,1); + glViewport(0, 0, texSize.width, texSize.height); + + glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &oldFBO_); + ccglBindFramebuffer(CC_GL_FRAMEBUFFER, fbo_);//Will direct drawing to the frame buffer created above + + CC_ENABLE_DEFAULT_GL_STATES(); +} + +-(void)beginWithClear:(float)r g:(float)g b:(float)b a:(float)a +{ + // issue #878 save opengl state + [self saveGLstate]; + + CC_DISABLE_DEFAULT_GL_STATES(); + // Save the current matrix + glPushMatrix(); + + CGSize texSize = [texture_ contentSizeInPixels]; + + // Calculate the adjustment ratios based on the old and new projections + CGSize size = [[CCDirector sharedDirector] displaySizeInPixels]; + float widthRatio = size.width / texSize.width; + float heightRatio = size.height / texSize.height; + + // Adjust the orthographic propjection and viewport + ccglOrtho((float)-1.0 / widthRatio, (float)1.0 / widthRatio, (float)-1.0 / heightRatio, (float)1.0 / heightRatio, -1,1); + glViewport(0, 0, texSize.width, texSize.height); + + glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &oldFBO_); + ccglBindFramebuffer(CC_GL_FRAMEBUFFER, fbo_);//Will direct drawing to the frame buffer created above + + glClearColor(r, g, b, a); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + CC_ENABLE_DEFAULT_GL_STATES(); +} + +-(void)end +{ + ccglBindFramebuffer(CC_GL_FRAMEBUFFER, oldFBO_); + // Restore the original matrix and viewport + glPopMatrix(); + CGSize size = [[CCDirector sharedDirector] displaySizeInPixels]; + glViewport(0, 0, size.width, size.height); + [self restoreGLstate]; + +} + +-(void)clear:(float)r g:(float)g b:(float)b a:(float)a +{ + [self begin]; + glClearColor(r, g, b, a); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + [self end]; +} + +-(void) saveGLstate +{ + glGetFloatv(GL_COLOR_CLEAR_VALUE,clearColor_); +} + +- (void) restoreGLstate +{ + glClearColor(clearColor_[0], clearColor_[1], clearColor_[2], clearColor_[3]); +} + +#pragma mark RenderTexture - Save Image + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +-(BOOL)saveBuffer:(NSString*)name +{ + return [self saveBuffer:name format:kCCImageFormatJPG]; +} + +-(BOOL)saveBuffer:(NSString*)fileName format:(int)format +{ + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:fileName]; + + NSData *data = [self getUIImageAsDataFromBuffer:format]; + + return [data writeToFile:fullPath atomically:YES]; +} + + +-(NSData*)getUIImageAsDataFromBuffer:(int) format +{ + NSAssert(pixelFormat_ == kCCTexture2DPixelFormat_RGBA8888,@"only RGBA8888 can be saved as image"); + + CGSize s = [texture_ contentSizeInPixels]; + int tx = s.width; + int ty = s.height; + + int bitsPerComponent=8; + int bitsPerPixel=32; + + int bytesPerRow = (bitsPerPixel/8) * tx; + NSInteger myDataLength = bytesPerRow * ty; + + GLubyte *buffer = malloc(sizeof(GLubyte)*myDataLength); + GLubyte *pixels = malloc(sizeof(GLubyte)*myDataLength); + + if( ! (buffer && pixels) ) { + CCLOG(@"cocos2d: CCRenderTexture#getUIImageFromBuffer: not enough memory"); + free(buffer); + free(pixels); + return nil; + } + + [self begin]; + glReadPixels(0,0,tx,ty,GL_RGBA,GL_UNSIGNED_BYTE, buffer); + [self end]; + + int x,y; + + for(y = 0; y