//----------------------------------------------------------------------------------------\r
// alignment macros\r
#if defined(__WINDOWS__)\r
-#define ALIGN(N) __declspec(align(N))\r
+#define MEM_ALIGN(N) __declspec(align(N))\r
#elif defined(__iOS__)\r
-#define ALIGN(N) __attribute__((aligned (N)))\r
+#define MEM_ALIGN(N) __attribute__((aligned (N)))\r
#endif\r
\r
#define IS_POWER_OF_TWO(x) ( ((x) & -(x)) == (x) )\r
--- /dev/null
+#pragma once
+
+#include "Foundation/Common/GlobalInclude.h"
+#include "Foundation/Math/MathInclude.h"
+
+//#include <OpenGLES/ES1/gl.h>
+#include <OpenGLES/ES2/gl.h>
+
+//----------------------------------------------------------------------------------------
+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 );
+};
--- /dev/null
+#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 );
+}
* we should never need to set context other than during startup or shutdown.
*****************************************************************************************/
-#include <OpenGLES/ES1/gl.h>
-#include <OpenGLES/ES1/glext.h>
+//#include <OpenGLES/ES1/gl.h>
+//#include <OpenGLES/ES1/glext.h>
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
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;
}
#include "Foundation/Math/MathOperations.h"\r
\r
//----------------------------------------------------------------------------------------\r
-struct Vector2\r
+struct Vec2\r
{\r
float x;\r
float y;\r
\r
- slInline explicit Vector2() {}\r
- slInline explicit Vector2(const float xy) {x = xy; y = xy;}\r
- slInline explicit Vector2(const float ix, const float iy) {x = ix; y = iy;}\r
+ slInline explicit Vec2() {}\r
+ slInline explicit Vec2(const float xy) {x = xy; y = xy;}\r
+ slInline explicit Vec2(const float ix, const float iy) {x = ix; y = iy;}\r
\r
- slInline Vector2(const Vector2& v) {x = v.x; y = v.y;} // copy constructor\r
+ slInline Vec2(const Vec2& v) {x = v.x; y = v.y;} // copy constructor\r
\r
slInline float* AsFloatArray() {return &x;}\r
slInline const float* AsFloatArray() const {return &x;}\r
\r
\r
//----------------------------------------------------------------------------------------\r
-struct Vector3\r
+struct Vec3\r
{\r
float x;\r
float y;\r
float z;\r
\r
- slInline explicit Vector3() {}\r
- slInline explicit Vector3(const float xyz) {x = xyz; y = xyz; z = xyz;}\r
- slInline explicit Vector3(const float ix, const float iy, const float iz) {x = ix; y = iy; z = iz;}\r
+ slInline explicit Vec3() {}\r
+ slInline explicit Vec3(const float xyz) {x = xyz; y = xyz; z = xyz;}\r
+ slInline explicit Vec3(const float ix, const float iy, const float iz) {x = ix; y = iy; z = iz;}\r
\r
- slInline explicit Vector3(const Vector2& v, const float iz) {x = v.x; y = v.y; z = iz;}\r
+ slInline explicit Vec3(const Vec2& v, const float iz) {x = v.x; y = v.y; z = iz;}\r
\r
- slInline Vector3(const Vector3& v) {x = v.x; y = v.y; z = v.z;} // copy constructor\r
+ slInline Vec3(const Vec3& v) {x = v.x; y = v.y; z = v.z;} // copy constructor\r
\r
- slInline Vector2 AsVector2() const {return Vector2(x, y);}\r
+ slInline Vec2 AsVec2() const {return Vec2(x, y);}\r
\r
slInline float* AsFloatArray() {return &x;}\r
slInline const float* AsFloatArray() const {return &x;}\r
\r
\r
//----------------------------------------------------------------------------------------\r
-struct Vector4\r
+struct Vec4\r
{\r
float x;\r
float y;\r
float z;\r
float w;\r
\r
- slInline explicit Vector4() {}\r
- slInline explicit Vector4(const float xyzw) {x = xyzw; y = xyzw; z = xyzw; w = xyzw;}\r
- slInline explicit Vector4(const float xyz, const float iw) {x = xyz; y = xyz; z = xyz; w = iw;}\r
- slInline explicit Vector4(const float ix, const float iy, const float iz, const float iw) {x = ix; y = iy; z = iz; w = iw;}\r
+ slInline explicit Vec4() {}\r
+ slInline explicit Vec4(const float xyzw) {x = xyzw; y = xyzw; z = xyzw; w = xyzw;}\r
+ slInline explicit Vec4(const float xyz, const float iw) {x = xyz; y = xyz; z = xyz; w = iw;}\r
+ slInline explicit Vec4(const float ix, const float iy, const float iz, const float iw) {x = ix; y = iy; z = iz; w = iw;}\r
\r
- slInline explicit Vector4(const Vector2& u, const Vector2& v) {x = u.x; y = u.y; z = v.x; w = v.y;}\r
- slInline explicit Vector4(const Vector2& v, const float iz, const float iw) {x = v.x; y = v.y; z = iz; w = iw;}\r
+ slInline explicit Vec4(const Vec2& u, const Vec2& v) {x = u.x; y = u.y; z = v.x; w = v.y;}\r
+ slInline explicit Vec4(const Vec2& v, const float iz, const float iw) {x = v.x; y = v.y; z = iz; w = iw;}\r
\r
- slInline explicit Vector4(const Vector3& v, const float iw) {x = v.x; y = v.y; z = v.z; w = iw;}\r
+ slInline explicit Vec4(const Vec3& v, const float iw) {x = v.x; y = v.y; z = v.z; w = iw;}\r
\r
- slInline Vector4(const Vector4& v) {x = v.x; y = v.y; z = v.z; w = v.w;} // copy constructor\r
+ slInline Vec4(const Vec4& v) {x = v.x; y = v.y; z = v.z; w = v.w;} // copy constructor\r
\r
- slInline Vector2 AsVector2() const {return Vector2(x, y);}\r
- slInline Vector3 AsVector3() const {return Vector3(x, y, z);}\r
+ slInline Vec2 AsVec2() const {return Vec2(x, y);}\r
+ slInline Vec3 AsVec3() const {return Vec3(x, y, z);}\r
\r
slInline float* AsFloatArray() {return &x;}\r
slInline const float* AsFloatArray() const {return &x;}\r
float s;\r
\r
slInline explicit Quaternion() {}\r
- explicit Quaternion(const float angle, const Vector3& normalized_axis);\r
+ explicit Quaternion(const float angle, const Vec3& normalized_axis);\r
explicit Quaternion(const float angle, const float x, const float y, const float z);\r
\r
slInline Quaternion(const Quaternion& q) {i = q.i; j = q.j; k = q.k; s = q.s;}\r
\r
- Vector4 AsVector4();\r
+ Vec4 AsVec4();\r
slInline float* AsFloatArray() {return &i;}\r
\r
- Vector3 GetImaginary();\r
+ Vec3 GetImaginary();\r
slInline float GetReal() {return s;}\r
};\r
\r
-slInline Quaternion::Quaternion(const float angle, const Vector3& normalized_axis)\r
+slInline Quaternion::Quaternion(const float angle, const Vec3& normalized_axis)\r
{\r
- Assert( EpsilonEquals(LengthVector3(normalized_axis), 1.0f, kEpsilon) );\r
+ Assert( EpsilonEquals(normalized_axis.x * normalized_axis.x + normalized_axis.y * normalized_axis.y + normalized_axis.z * normalized_axis.z, 1.0f, kSqrtEpsilon) );\r
float half_angle = angle * 0.5f;\r
- float sin_half_angle = Sinf(half_angle);\r
+ float sin_half_angle = (float)Sinf(half_angle);\r
i = normalized_axis.x * sin_half_angle;\r
j = normalized_axis.y * sin_half_angle;\r
k = normalized_axis.z * sin_half_angle;\r
- s = Cosf(half_angle);\r
+ s = (float)Cosf(half_angle);\r
}\r
\r
slInline Quaternion::Quaternion(const float angle, const float x, const float y, const float z)\r
{\r
Assert( EpsilonEquals(x * x + y * y + z * z, 1.0f, kSqrtEpsilon) );\r
float half_angle = angle * 0.5f;\r
- float sin_half_angle = Sinf(half_angle);\r
+ 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);\r
}\r
\r
-Vector4 Quaternion::AsVector4()\r
+Vec4 Quaternion::AsVec4()\r
{\r
- Vector4 r;\r
+ Vec4 r;\r
r.x = i;\r
r.y = j;\r
r.z = k;\r
return r;\r
}\r
\r
-Vector3 Quaternion::GetImaginary()\r
+Vec3 Quaternion::GetImaginary()\r
{\r
- Vector3 r;\r
+ Vec3 r;\r
r.x = i;\r
r.y = j;\r
r.z = k;\r
\r
\r
//----------------------------------------------------------------------------------------\r
-struct Matrix3\r
+struct Mat3\r
{\r
- Vector3 v[3];\r
+ Vec3 v[3];\r
\r
- slInline explicit Matrix3() {}\r
- explicit Matrix3(const Vector3& v0, const Vector3& v1, const Vector3& v2);\r
- explicit Matrix3(const float v00, const float v01, const float v02,\r
- const float v10, const float v11, const float v12,\r
- const float v20, const float v21, const float v22);\r
- Matrix3(Matrix3& m); // copy constructor\r
+ slInline explicit Mat3() {}\r
+ explicit Mat3(const Vec3& v0, const Vec3& v1, const Vec3& v2);\r
+ explicit Mat3(const float v00, const float v01, const float v02,\r
+ const float v10, const float v11, const float v12,\r
+ const float v20, const float v21, const float v22);\r
+ Mat3(const Mat3& m); // copy constructor\r
\r
float* AsFloatArray() {return &v[0].x;}\r
};\r
\r
-slInline Matrix3::Matrix3(const Vector3& v0, const Vector3& v1, const Vector3& v2)\r
+slInline Mat3::Mat3(const Vec3& v0, const Vec3& v1, const Vec3& v2)\r
{\r
v[0] = v0;\r
v[1] = v1;\r
v[2] = v2;\r
}\r
\r
-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)\r
+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)\r
{\r
v[0].x = v00; v[0].y = v01; v[0].z = v02;\r
v[1].x = v10; v[1].y = v11; v[1].z = v12;\r
v[2].x = v20; v[2].y = v21; v[2].z = v22;\r
}\r
\r
-slInline Matrix3::Matrix3(Matrix3& m)\r
+slInline Mat3::Mat3(const Mat3& m)\r
{\r
v[0] = m.v[0];\r
v[1] = m.v[1];\r
\r
\r
//----------------------------------------------------------------------------------------\r
-struct Matrix4\r
+struct Mat4\r
{\r
- Vector4 v[4];\r
+ Vec4 v[4];\r
\r
- slInline explicit Matrix4() {}\r
- explicit Matrix4(const Vector4& v0, const Vector4& v1, const Vector4& v2, const Vector4& v3);\r
- explicit Matrix4(const float v00, const float v01, const float v02, const float v03,\r
- const float v10, const float v11, const float v12, const float v13,\r
- const float v20, const float v21, const float v22, const float v23,\r
- const float v30, const float v31, const float v32, const float v33);\r
- explicit Matrix4(const Matrix3& m);\r
- Matrix4(const Matrix4& m); // copy constructor\r
+ slInline explicit Mat4() {}\r
+ explicit Mat4(const Vec4& v0, const Vec4& v1, const Vec4& v2, const Vec4& v3);\r
+ explicit Mat4(const float v00, const float v01, const float v02, const float v03,\r
+ const float v10, const float v11, const float v12, const float v13,\r
+ const float v20, const float v21, const float v22, const float v23,\r
+ const float v30, const float v31, const float v32, const float v33);\r
+ explicit Mat4(const Mat3& m);\r
+ Mat4(const Mat4& m); // copy constructor\r
\r
float* AsFloatArray() {return &v[0].x;}\r
};\r
\r
-slInline Matrix4::Matrix4(const Vector4& v0, const Vector4& v1, const Vector4& v2, const Vector4& v3)\r
+slInline Mat4::Mat4(const Vec4& v0, const Vec4& v1, const Vec4& v2, const Vec4& v3)\r
{\r
v[0] = v0;\r
v[1] = v1;\r
v[3] = v3;\r
}\r
\r
-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)\r
+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)\r
{\r
v[0].x = v00; v[0].y = v01; v[0].z = v02; v[0].w = v03;\r
v[1].x = v10; v[1].y = v11; v[1].z = v12; v[1].w = v13;\r
v[3].x = v30; v[3].y = v31; v[3].z = v32; v[3].w = v33;\r
}\r
\r
-slInline Matrix4::Matrix4(const Matrix3& m)\r
+slInline Mat4::Mat4(const Mat3& m)\r
{\r
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;\r
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;\r
v[3].x = 0.0f; v[3].y = 0.0f; v[3].z = 0.0f; v[3].w = 1.0f;\r
}\r
\r
-slInline Matrix4::Matrix4(const Matrix4& m)\r
+slInline Mat4::Mat4(const Mat4& m)\r
{\r
v[0] = m.v[0];\r
v[1] = m.v[1];\r
\r
\r
//----------------------------------------------------------------------------------------\r
-typedef ALIGN(8) Vector2 AlignedVector2;\r
-typedef ALIGN(16) Vector3 AlignedVector3;\r
-typedef ALIGN(16) Vector4 AlignedVector4;\r
+typedef MEM_ALIGN(8) Vec2 AlignedVec2;\r
+typedef MEM_ALIGN(16) Vec3 AlignedVec3;\r
+typedef MEM_ALIGN(16) Vec4 AlignedVec4;\r
\r
-typedef ALIGN(64) Matrix3 AlignedMatrix3;\r
-typedef ALIGN(64) Matrix4 AlignedMatrix4;\r
+typedef MEM_ALIGN(64) Mat3 AlignedMat3;\r
+typedef MEM_ALIGN(64) Mat4 AlignedMat4;\r
\r
\r
//----------------------------------------------------------------------------------------\r
// SIMD Structures\r
//----------------------------------------------------------------------------------------\r
-struct Vector2SOA\r
+struct Vec2SOA\r
{\r
uint32_t m_Count;\r
uint32_t m_MaxCount;\r
float* m_X;\r
float* m_Y;\r
\r
- slInline explicit Vector2SOA() {m_Count = 0; m_MaxCount = 0; m_X = NULL; m_Y = NULL;}\r
- bool InitVector2SOA(float* buffer, uint32_t buffer_size);\r
+ slInline explicit Vec2SOA() {m_Count = 0; m_MaxCount = 0; m_X = NULL; m_Y = NULL;}\r
+ bool InitVec2SOA(float* buffer, uint32_t buffer_size);\r
\r
- void GetVector2AtIndex(Vector2& v, uint32_t index) {Assert(index < m_Count); v.x = m_X[index]; v.y = m_Y[index];}\r
+ void GetVec2AtIndex(Vec2& v, uint32_t index) {Assert(index < m_Count); v.x = m_X[index]; v.y = m_Y[index];}\r
};\r
\r
-slInline bool Vector2SOA::InitVector2SOA(float* buffer, uint32_t max_count)\r
+slInline bool Vec2SOA::InitVec2SOA(float* buffer, uint32_t max_count)\r
{\r
m_Count = 0;\r
\r
\r
\r
//----------------------------------------------------------------------------------------\r
-struct Vector3SOA : public Vector2SOA\r
+struct Vec3SOA : public Vec2SOA\r
{\r
float* m_Z;\r
\r
- slInline explicit Vector3SOA() {m_Count = 0; m_MaxCount = 0; m_X = NULL; m_Y = NULL; m_Z = NULL;}\r
- bool InitVector3SOA(float* buffer, uint32_t buffer_size);\r
+ slInline explicit Vec3SOA() {m_Count = 0; m_MaxCount = 0; m_X = NULL; m_Y = NULL; m_Z = NULL;}\r
+ bool InitVec3SOA(float* buffer, uint32_t buffer_size);\r
\r
- 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];}\r
+ 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];}\r
};\r
\r
-slInline bool Vector3SOA::InitVector3SOA(float* buffer, uint32_t max_count)\r
+slInline bool Vec3SOA::InitVec3SOA(float* buffer, uint32_t max_count)\r
{\r
m_Count = 0;\r
\r
\r
\r
//----------------------------------------------------------------------------------------\r
-struct Vector4SOA : public Vector3SOA\r
+struct Vec4SOA : public Vec3SOA\r
{\r
float* m_W;\r
\r
- slInline explicit Vector4SOA() {m_Count = 0; m_MaxCount = 0; m_X = NULL; m_Y = NULL; m_Z = NULL; m_W = NULL;}\r
- bool InitVector4SOA(float* buffer, uint32_t buffer_size);\r
+ slInline explicit Vec4SOA() {m_Count = 0; m_MaxCount = 0; m_X = NULL; m_Y = NULL; m_Z = NULL; m_W = NULL;}\r
+ bool InitVec4SOA(float* buffer, uint32_t buffer_size);\r
\r
- 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];}\r
+ 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];}\r
};\r
\r
-slInline bool Vector4SOA::InitVector4SOA(float* buffer, uint32_t max_count)\r
+slInline bool Vec4SOA::InitVec4SOA(float* buffer, uint32_t max_count)\r
{\r
m_Count = 0;\r
\r
//----------------------------------------------------------------------------------------\r
\r
//----------------------------------------------------------------------------------------\r
-// Matrix3\r
+// Mat3\r
//----------------------------------------------------------------------------------------\r
-void SetMatrix3(Matrix3& r, const Matrix3& a);\r
-void SetMatrix3(Matrix3& r, const Vector3& v0, const Vector3& v1, const Vector3& v2);\r
+void SetMat3(Mat3& r, const Mat3& a);\r
+void SetMat3(Mat3& r, const Vec3& v0, const Vec3& v1, const Vec3& v2);\r
\r
-void ScaleMatrix3(Matrix3& r, const float s, const Matrix3& a);\r
-Matrix3 ScaleMatrix3(const float s, const Matrix3& a);\r
+void ScaleMat3(Mat3& r, const float s, const Mat3& a);\r
+Mat3 ScaleMat3(const float s, const Mat3& a);\r
\r
-float DeterminantOfMatrix3(const Matrix3& a);\r
+float DeterminantOfMat3(const Mat3& a);\r
\r
-void TransposeMatrix3(Matrix3& r, const Matrix3& a);\r
-Matrix3 TransposeMatrix3(const Matrix3& a);\r
+void TransposeMat3(Mat3& r, const Mat3& a);\r
+Mat3 TransposeMat3(const Mat3& a);\r
\r
-void InvertAffineMatrix3(Matrix3& r, const Matrix3& a);\r
-Matrix3 InvertAffineMatrix3(const Matrix3& a);\r
+void InvertAffineMat3(Mat3& r, const Mat3& a);\r
+Mat3 InvertAffineMat3(const Mat3& a);\r
\r
-void InvertGeneralMatrix3(Matrix3& r, const Matrix3& a);\r
-Matrix3 InvertGeneralMatrix3(const Matrix3& a);\r
+void InvertGeneralMat3(Mat3& r, const Mat3& a);\r
+Mat3 InvertGeneralMat3(const Mat3& a);\r
\r
-void MulMatrix3(Matrix3& r, const Matrix3& a, const Matrix3& b);\r
-Matrix3 MulMatrix3(const Matrix3& a, const Matrix3& b);\r
+void MulMat3(Mat3& r, const Mat3& a, const Mat3& b);\r
+Mat3 MulMat3(const Mat3& a, const Mat3& b);\r
\r
-void MulMatrix3ByTransposedMatrix3(Matrix3& r, const Matrix3& a, const Matrix3& b);\r
-Matrix3 MulMatrix3ByTransposedMatrix3(const Matrix3& a, const Matrix3& b);\r
+void MulMat3ByTransposedMat3(Mat3& r, const Mat3& a, const Mat3& b);\r
+Mat3 MulMat3ByTransposedMat3(const Mat3& a, const Mat3& b);\r
\r
-void MulVector3ByMatrix3(Vector3& r, const Vector3& v, const Matrix3& a);\r
-Vector3 MulVector3ByMatrix3(const Vector3& v, const Matrix3& a);\r
+void MulVec3ByMat3(Vec3& r, const Vec3& v, const Mat3& a);\r
+Vec3 MulVec3ByMat3(const Vec3& v, const Mat3& a);\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SetMatrix3(Matrix3& r, const Matrix3& a)\r
+slInline void SetMat3(Mat3& r, const Mat3& a)\r
{\r
r.v[0] = a.v[0];\r
r.v[1] = a.v[1];\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SetMatrix3(Matrix3& r, const Vector3& v0, const Vector3& v1, const Vector3& v2)\r
+slInline void SetMat3(Mat3& r, const Vec3& v0, const Vec3& v1, const Vec3& v2)\r
{\r
r.v[0] = v0;\r
r.v[1] = v1;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void ScaleMatrix3(Matrix3& r, const float s, const Matrix3& a)\r
+slInline void ScaleMat3(Mat3& r, const float s, const Mat3& a)\r
{\r
- ScaleVector3(r.v[0], s, a.v[0]);\r
- ScaleVector3(r.v[1], s, a.v[1]);\r
- ScaleVector3(r.v[2], s, a.v[2]);\r
+ ScaleVec3(r.v[0], s, a.v[0]);\r
+ ScaleVec3(r.v[1], s, a.v[1]);\r
+ ScaleVec3(r.v[2], s, a.v[2]);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Matrix3 ScaleMatrix3(const float s, const Matrix3& a)\r
+slInline Mat3 ScaleMat3(const float s, const Mat3& a)\r
{\r
- Matrix3 r;\r
- ScaleVector3(r.v[0], s, a.v[0]);\r
- ScaleVector3(r.v[1], s, a.v[1]);\r
- ScaleVector3(r.v[2], s, a.v[2]);\r
+ Mat3 r;\r
+ ScaleVec3(r.v[0], s, a.v[0]);\r
+ ScaleVec3(r.v[1], s, a.v[1]);\r
+ ScaleVec3(r.v[2], s, a.v[2]);\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float DeterminantOfMatrix3(const Matrix3& a)\r
+slInline float DeterminantOfMat3(const Mat3& a)\r
{\r
return a.v[0].x * (a.v[1].y * a.v[2].z - a.v[1].z * a.v[2].y)\r
+ a.v[0].y * (a.v[1].z * a.v[2].x - a.v[1].x * a.v[2].z)\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void TransposeMatrix3(Matrix3& r, const Matrix3& a)\r
+slInline void TransposeMat3(Mat3& r, const Mat3& a)\r
{\r
// a might be the same as r\r
r.v[0].x = a.v[0].x;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Matrix3 TransposeMatrix3(const Matrix3& a)\r
+slInline Mat3 TransposeMat3(const Mat3& a)\r
{\r
- Matrix3 r;\r
+ Mat3 r;\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
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
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
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void InvertAffineMatrix3(Matrix3& r, const Matrix3& a)\r
+slInline void InvertAffineMat3(Mat3& r, const Mat3& a)\r
{\r
- TransposeMatrix3(r, a);\r
+ TransposeMat3(r, a);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Matrix3 InvertAffineMatrix3(const Matrix3& a)\r
+slInline Mat3 InvertAffineMat3(const Mat3& a)\r
{\r
- return TransposeMatrix3(a);\r
+ return TransposeMat3(a);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void InvertGeneralMatrix3(Matrix3& r, const Matrix3& a)\r
+slInline void InvertGeneralMat3(Mat3& r, const Mat3& a)\r
{\r
- float inv_determinant = 1.0f / DeterminantOfMatrix3(a);\r
+ float inv_determinant = 1.0f / DeterminantOfMat3(a);\r
\r
- Matrix3 a_T;\r
- TransposeMatrix3(a_T, a);\r
- CrossVector3(r.v[0], a_T.v[1], a_T.v[2]);\r
- CrossVector3(r.v[1], a_T.v[2], a_T.v[0]);\r
- CrossVector3(r.v[2], a_T.v[0], a_T.v[1]);\r
+ Mat3 a_T;\r
+ TransposeMat3(a_T, a);\r
+ CrossVec3(r.v[0], a_T.v[1], a_T.v[2]);\r
+ CrossVec3(r.v[1], a_T.v[2], a_T.v[0]);\r
+ CrossVec3(r.v[2], a_T.v[0], a_T.v[1]);\r
\r
- ScaleMatrix3(r, inv_determinant, r);\r
+ ScaleMat3(r, inv_determinant, r);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Matrix3 InvertGeneralMatrix3(const Matrix3& a)\r
+slInline Mat3 InvertGeneralMat3(const Mat3& a)\r
{\r
- float inv_determinant = 1.0f / DeterminantOfMatrix3(a);\r
+ float inv_determinant = 1.0f / DeterminantOfMat3(a);\r
\r
- Matrix3 r;\r
- Matrix3 a_T = TransposeMatrix3(a);\r
- CrossVector3(r.v[0], a_T.v[1], a_T.v[2]);\r
- CrossVector3(r.v[1], a_T.v[2], a_T.v[0]);\r
- CrossVector3(r.v[2], a_T.v[0], a_T.v[1]);\r
+ Mat3 r;\r
+ Mat3 a_T = TransposeMat3(a);\r
+ CrossVec3(r.v[0], a_T.v[1], a_T.v[2]);\r
+ CrossVec3(r.v[1], a_T.v[2], a_T.v[0]);\r
+ CrossVec3(r.v[2], a_T.v[0], a_T.v[1]);\r
\r
- return ScaleMatrix3(inv_determinant, r);\r
+ return ScaleMat3(inv_determinant, r);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void MulMatrix3(Matrix3& r, const Matrix3& a, const Matrix3& b)\r
+slInline void MulMat3(Mat3& r, const Mat3& a, const Mat3& b)\r
{\r
- Matrix3 temp;\r
+ Mat3 temp;\r
\r
- temp.v[0].x = DotVector3(a.v[0], b.v[0].x, b.v[1].x, b.v[2].x);\r
- temp.v[0].y = DotVector3(a.v[0], b.v[0].y, b.v[1].y, b.v[2].y);\r
- temp.v[0].z = DotVector3(a.v[0], b.v[0].z, b.v[1].z, b.v[2].z);\r
+ temp.v[0].x = DotVec3(a.v[0], b.v[0].x, b.v[1].x, b.v[2].x);\r
+ temp.v[0].y = DotVec3(a.v[0], b.v[0].y, b.v[1].y, b.v[2].y);\r
+ temp.v[0].z = DotVec3(a.v[0], b.v[0].z, b.v[1].z, b.v[2].z);\r
\r
- temp.v[1].x = DotVector3(a.v[1], b.v[0].x, b.v[1].x, b.v[2].x);\r
- temp.v[1].y = DotVector3(a.v[1], b.v[0].y, b.v[1].y, b.v[2].y);\r
- temp.v[1].z = DotVector3(a.v[1], b.v[0].z, b.v[1].z, b.v[2].z);\r
+ temp.v[1].x = DotVec3(a.v[1], b.v[0].x, b.v[1].x, b.v[2].x);\r
+ temp.v[1].y = DotVec3(a.v[1], b.v[0].y, b.v[1].y, b.v[2].y);\r
+ temp.v[1].z = DotVec3(a.v[1], b.v[0].z, b.v[1].z, b.v[2].z);\r
\r
- temp.v[2].x = DotVector3(a.v[2], b.v[0].x, b.v[1].x, b.v[2].x);\r
- temp.v[2].y = DotVector3(a.v[2], b.v[0].y, b.v[1].y, b.v[2].y);\r
- temp.v[2].z = DotVector3(a.v[2], b.v[0].z, b.v[1].z, b.v[2].z);\r
+ temp.v[2].x = DotVec3(a.v[2], b.v[0].x, b.v[1].x, b.v[2].x);\r
+ temp.v[2].y = DotVec3(a.v[2], b.v[0].y, b.v[1].y, b.v[2].y);\r
+ temp.v[2].z = DotVec3(a.v[2], b.v[0].z, b.v[1].z, b.v[2].z);\r
\r
- SetMatrix3(r, temp);\r
+ SetMat3(r, temp);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Matrix3 MulMatrix3(const Matrix3& a, const Matrix3& b)\r
+slInline Mat3 MulMat3(const Mat3& a, const Mat3& b)\r
{\r
- Matrix3 r;\r
+ Mat3 r;\r
\r
- r.v[0].x = DotVector3(a.v[0], b.v[0].x, b.v[1].x, b.v[2].x);\r
- r.v[0].y = DotVector3(a.v[0], b.v[0].y, b.v[1].y, b.v[2].y);\r
- r.v[0].z = DotVector3(a.v[0], b.v[0].z, b.v[1].z, b.v[2].z);\r
+ r.v[0].x = DotVec3(a.v[0], b.v[0].x, b.v[1].x, b.v[2].x);\r
+ r.v[0].y = DotVec3(a.v[0], b.v[0].y, b.v[1].y, b.v[2].y);\r
+ r.v[0].z = DotVec3(a.v[0], b.v[0].z, b.v[1].z, b.v[2].z);\r
\r
- r.v[1].x = DotVector3(a.v[1], b.v[0].x, b.v[1].x, b.v[2].x);\r
- r.v[1].y = DotVector3(a.v[1], b.v[0].y, b.v[1].y, b.v[2].y);\r
- r.v[1].z = DotVector3(a.v[1], b.v[0].z, b.v[1].z, b.v[2].z);\r
+ r.v[1].x = DotVec3(a.v[1], b.v[0].x, b.v[1].x, b.v[2].x);\r
+ r.v[1].y = DotVec3(a.v[1], b.v[0].y, b.v[1].y, b.v[2].y);\r
+ r.v[1].z = DotVec3(a.v[1], b.v[0].z, b.v[1].z, b.v[2].z);\r
\r
- r.v[2].x = DotVector3(a.v[2], b.v[0].x, b.v[1].x, b.v[2].x);\r
- r.v[2].y = DotVector3(a.v[2], b.v[0].y, b.v[1].y, b.v[2].y);\r
- r.v[2].z = DotVector3(a.v[2], b.v[0].z, b.v[1].z, b.v[2].z);\r
+ r.v[2].x = DotVec3(a.v[2], b.v[0].x, b.v[1].x, b.v[2].x);\r
+ r.v[2].y = DotVec3(a.v[2], b.v[0].y, b.v[1].y, b.v[2].y);\r
+ r.v[2].z = DotVec3(a.v[2], b.v[0].z, b.v[1].z, b.v[2].z);\r
\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void MulMatrix3ByTransposedMatrix3(Matrix3& r, const Matrix3& a, const Matrix3& b)\r
+slInline void MulMat3ByTransposedMat3(Mat3& r, const Mat3& a, const Mat3& b)\r
{\r
- Matrix3 temp;\r
+ Mat3 temp;\r
\r
- temp.v[0].x = DotVector3(a.v[0], b.v[0]);\r
- temp.v[0].y = DotVector3(a.v[0], b.v[1]);\r
- temp.v[0].z = DotVector3(a.v[0], b.v[2]);\r
+ temp.v[0].x = DotVec3(a.v[0], b.v[0]);\r
+ temp.v[0].y = DotVec3(a.v[0], b.v[1]);\r
+ temp.v[0].z = DotVec3(a.v[0], b.v[2]);\r
\r
- temp.v[1].x = DotVector3(a.v[1], b.v[0]);\r
- temp.v[1].y = DotVector3(a.v[1], b.v[1]);\r
- temp.v[1].z = DotVector3(a.v[1], b.v[2]);\r
+ temp.v[1].x = DotVec3(a.v[1], b.v[0]);\r
+ temp.v[1].y = DotVec3(a.v[1], b.v[1]);\r
+ temp.v[1].z = DotVec3(a.v[1], b.v[2]);\r
\r
- temp.v[2].x = DotVector3(a.v[2], b.v[0]);\r
- temp.v[2].y = DotVector3(a.v[2], b.v[1]);\r
- temp.v[2].z = DotVector3(a.v[2], b.v[2]);\r
+ temp.v[2].x = DotVec3(a.v[2], b.v[0]);\r
+ temp.v[2].y = DotVec3(a.v[2], b.v[1]);\r
+ temp.v[2].z = DotVec3(a.v[2], b.v[2]);\r
\r
- SetMatrix3(r, temp);\r
+ SetMat3(r, temp);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Matrix3 MulMatrix3ByTransposedMatrix3(const Matrix3& a, const Matrix3& b)\r
+slInline Mat3 MulMat3ByTransposedMat3(const Mat3& a, const Mat3& b)\r
{\r
- Matrix3 r;\r
+ Mat3 r;\r
\r
- r.v[0].x = DotVector3(a.v[0], b.v[0]);\r
- r.v[0].y = DotVector3(a.v[0], b.v[1]);\r
- r.v[0].z = DotVector3(a.v[0], b.v[2]);\r
+ r.v[0].x = DotVec3(a.v[0], b.v[0]);\r
+ r.v[0].y = DotVec3(a.v[0], b.v[1]);\r
+ r.v[0].z = DotVec3(a.v[0], b.v[2]);\r
\r
- r.v[1].x = DotVector3(a.v[1], b.v[0]);\r
- r.v[1].y = DotVector3(a.v[1], b.v[1]);\r
- r.v[1].z = DotVector3(a.v[1], b.v[2]);\r
+ r.v[1].x = DotVec3(a.v[1], b.v[0]);\r
+ r.v[1].y = DotVec3(a.v[1], b.v[1]);\r
+ r.v[1].z = DotVec3(a.v[1], b.v[2]);\r
\r
- r.v[2].x = DotVector3(a.v[2], b.v[0]);\r
- r.v[2].y = DotVector3(a.v[2], b.v[1]);\r
- r.v[2].z = DotVector3(a.v[2], b.v[2]);\r
+ r.v[2].x = DotVec3(a.v[2], b.v[0]);\r
+ r.v[2].y = DotVec3(a.v[2], b.v[1]);\r
+ r.v[2].z = DotVec3(a.v[2], b.v[2]);\r
\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
// do NOT pass in components of a as the r vector\r
-slInline void MulVector3ByMatrix3(Vector3& r, const Vector3& v, const Matrix3& a)\r
+slInline void MulVec3ByMat3(Vec3& r, const Vec3& v, const Mat3& a)\r
{\r
float x = v.x * a.v[0].x + v.y * a.v[1].x + v.z * a.v[2].x;\r
float y = v.x * a.v[0].y + v.y * a.v[1].y + v.z * a.v[2].y;\r
float z = v.x * a.v[0].z + v.y * a.v[1].z + v.z * a.v[2].z;\r
- SetVector3(r, x, y, z);\r
+ SetVec3(r, x, y, z);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector3 MulVector3ByMatrix3(const Vector3& v, const Matrix3& a)\r
+slInline Vec3 MulVec3ByMat3(const Vec3& v, const Mat3& a)\r
{\r
- Vector3 r;\r
+ Vec3 r;\r
r.x = v.x * a.v[0].x + v.y * a.v[1].x + v.z * a.v[2].x;\r
r.y = v.x * a.v[0].y + v.y * a.v[1].y + v.z * a.v[2].y;\r
r.z = v.x * a.v[0].z + v.y * a.v[1].z + v.z * a.v[2].z;\r
\r
\r
//----------------------------------------------------------------------------------------\r
-// Matrix4\r
+// Mat4\r
//----------------------------------------------------------------------------------------\r
-void SetMatrix4(Matrix4& r, const Matrix4& a);\r
-void SetMatrix4(Matrix4& r, const Matrix3& a);\r
-void SetMatrix4(Matrix4& r, const Matrix3& a, const Vector3& position);\r
+void SetMat4(Mat4& r, const Mat4& a);\r
+void SetMat4(Mat4& r, const Mat3& a);\r
+void SetMat4(Mat4& r, const Mat3& a, const Vec3& position);\r
\r
-void ScaleMatrix4(Matrix4& r, const float s, const Matrix4& a);\r
-Matrix4 ScaleMatrix4(const float s, const Matrix4& a);\r
+void ScaleMat4(Mat4& r, const float s, const Mat4& a);\r
+Mat4 ScaleMat4(const float s, const Mat4& a);\r
\r
-float DeterminantOfMatrix4(const Matrix4& a);\r
+float DeterminantOfMat4(const Mat4& a);\r
\r
-void TransposeMatrix4(Matrix4& r, const Matrix4& a);\r
-Matrix4 TransposeMatrix4(const Matrix4& a);\r
+void TransposeMat4(Mat4& r, const Mat4& a);\r
+Mat4 TransposeMat4(const Mat4& a);\r
\r
-void InvertAffineMatrix4(Matrix4& r, const Matrix4& a);\r
-Matrix4 InvertAffineMatrix4(const Matrix4& a);\r
+void InvertAffineMat4(Mat4& r, const Mat4& a);\r
+Mat4 InvertAffineMat4(const Mat4& a);\r
\r
-void InvertGeneralMatrix4(Matrix4& r, const Matrix4& a);\r
-Matrix4 InvertGeneralMatrix4(const Matrix4& a);\r
+void InvertGeneralMat4(Mat4& r, const Mat4& a);\r
+Mat4 InvertGeneralMat4(const Mat4& a);\r
\r
-void MulMatrix4(Matrix4& r, const Matrix4& a, const Matrix4& b);\r
-Matrix4 MulMatrix4(const Matrix4& a, const Matrix4& b);\r
+void MulMat4(Mat4& r, const Mat4& a, const Mat4& b);\r
+Mat4 MulMat4(const Mat4& a, const Mat4& b);\r
\r
-void MulMatrix4ByTransposedMatrix4(Matrix4& r, const Matrix4& a, const Matrix4& t);\r
-Matrix4 MulMatrix4ByTransposedMatrix4(const Matrix4& a, Matrix4& t);\r
+void MulMat4ByTransposedMat4(Mat4& r, const Mat4& a, const Mat4& t);\r
+Mat4 MulMat4ByTransposedMat4(const Mat4& a, Mat4& t);\r
\r
-void MulVector4ByMatrix4(Vector4& r, const Vector4& v, const Matrix4& a);\r
-Vector4 MulVector4ByMatrix4(const Vector4& v, const Matrix4& a);\r
+void MulVec4ByMat4(Vec4& r, const Vec4& v, const Mat4& a);\r
+Vec4 MulVec4ByMat4(const Vec4& v, const Mat4& a);\r
\r
-void MulVector3ByMatrix4(Vector4& r, const Vector3& v, const float w, const Matrix4& a);\r
-Vector4 MulVector3ByMatrix4(const Vector3& v, const float w, const Matrix4& a);\r
+void MulVec3ByMat4(Vec4& r, const Vec3& v, const float w, const Mat4& a);\r
+Vec4 MulVec3ByMat4(const Vec3& v, const float w, const Mat4& a);\r
\r
-void MulVector4ByTransposedMatrix4(Vector4& r, const Vector4& v, const Matrix4& t);\r
-Vector4 MulVector4ByTransposedMatrix4(const Vector4& v, const Matrix4& t);\r
+void MulVec4ByTransposedMat4(Vec4& r, const Vec4& v, const Mat4& t);\r
+Vec4 MulVec4ByTransposedMat4(const Vec4& v, const Mat4& t);\r
\r
-void MulVector3ByTransposedMatrix4(Vector4& r, const Vector3& v, const float w, const Matrix4& t);\r
-Vector4 MulVector3ByTransposedMatrix4(const Vector3& v, const float w, const Matrix4& t);\r
+void MulVec3ByTransposedMat4(Vec4& r, const Vec3& v, const float w, const Mat4& t);\r
+Vec4 MulVec3ByTransposedMat4(const Vec3& v, const float w, const Mat4& t);\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SetMatrix4(Matrix4& r, const Matrix4& a)\r
+slInline void SetMat4(Mat4& r, const Mat4& a)\r
{\r
r.v[0] = a.v[0];\r
r.v[1] = a.v[1];\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SetMatrix4(Matrix4& r, const Matrix3& a)\r
+slInline void SetMat4(Mat4& r, const Mat3& a)\r
{\r
- SetVector4(r.v[0], a.v[0], 0.0f);\r
- SetVector4(r.v[1], a.v[1], 0.0f);\r
- SetVector4(r.v[2], a.v[2], 0.0f);\r
- SetVector4(r.v[3], 0.0f, 0.0f, 0.0f, 1.0f);\r
+ SetVec4(r.v[0], a.v[0], 0.0f);\r
+ SetVec4(r.v[1], a.v[1], 0.0f);\r
+ SetVec4(r.v[2], a.v[2], 0.0f);\r
+ SetVec4(r.v[3], 0.0f, 0.0f, 0.0f, 1.0f);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SetMatrix4(Matrix4& r, const Matrix3& a, const Vector3& position)\r
+slInline void SetMat4(Mat4& r, const Mat3& a, const Vec3& position)\r
{\r
- SetVector4(r.v[0], a.v[0], 0.0f);\r
- SetVector4(r.v[1], a.v[1], 0.0f);\r
- SetVector4(r.v[2], a.v[2], 0.0f);\r
- SetVector4(r.v[3], position, 1.0f);\r
+ SetVec4(r.v[0], a.v[0], 0.0f);\r
+ SetVec4(r.v[1], a.v[1], 0.0f);\r
+ SetVec4(r.v[2], a.v[2], 0.0f);\r
+ SetVec4(r.v[3], position, 1.0f);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void ScaleMatrix4(Matrix4& r, const float s, const Matrix4& a)\r
+slInline void ScaleMat4(Mat4& r, const float s, const Mat4& a)\r
{\r
- ScaleVector4(r.v[0], s, a.v[0]);\r
- ScaleVector4(r.v[1], s, a.v[1]);\r
- ScaleVector4(r.v[2], s, a.v[2]);\r
- ScaleVector4(r.v[3], s, a.v[3]);\r
+ ScaleVec4(r.v[0], s, a.v[0]);\r
+ ScaleVec4(r.v[1], s, a.v[1]);\r
+ ScaleVec4(r.v[2], s, a.v[2]);\r
+ ScaleVec4(r.v[3], s, a.v[3]);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Matrix4 ScaleMatrix4(const float s, const Matrix4& a)\r
+slInline Mat4 ScaleMat4(const float s, const Mat4& a)\r
{\r
- Matrix4 r;\r
- ScaleVector4(r.v[0], s, a.v[0]);\r
- ScaleVector4(r.v[1], s, a.v[1]);\r
- ScaleVector4(r.v[2], s, a.v[2]);\r
- ScaleVector4(r.v[3], s, a.v[3]);\r
+ Mat4 r;\r
+ ScaleVec4(r.v[0], s, a.v[0]);\r
+ ScaleVec4(r.v[1], s, a.v[1]);\r
+ ScaleVec4(r.v[2], s, a.v[2]);\r
+ ScaleVec4(r.v[3], s, a.v[3]);\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float DeterminantOfMatrix4(const Matrix4& a)\r
+slInline float DeterminantOfMat4(const Mat4& a)\r
{\r
// is this correct?\r
- Vector4 cross_product;\r
- CrossVector4(cross_product, a.v[1], a.v[2], a.v[3]);\r
- return DotVector4(a.v[0], cross_product);\r
+ Vec4 cross_product;\r
+ CrossVec4(cross_product, a.v[1], a.v[2], a.v[3]);\r
+ return DotVec4(a.v[0], cross_product);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void TransposeMatrix4(Matrix4& r, const Matrix4& a)\r
+slInline void TransposeMat4(Mat4& r, const Mat4& a)\r
{\r
// a might be the same as r\r
r.v[0].x = a.v[0].x;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Matrix4 TransposeMatrix4(const Matrix4& a)\r
+slInline Mat4 TransposeMat4(const Mat4& a)\r
{\r
- Matrix4 r;\r
+ Mat4 r;\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
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
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;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void InvertAffineMatrix4(Matrix4& r, const Matrix4& a)\r
+slInline void InvertAffineMat4(Mat4& r, const Mat4& a)\r
{\r
// this may not be correct...\r
- Matrix3 a3_T(a.v[0].AsVector3(), a.v[1].AsVector3(), a.v[2].AsVector3());\r
- InvertAffineMatrix3(a3_T, a3_T);\r
+ Mat3 a3_T(a.v[0].AsVec3(), a.v[1].AsVec3(), a.v[2].AsVec3());\r
+ InvertAffineMat3(a3_T, a3_T);\r
\r
- Vector3 transpose;\r
- MulVector3ByMatrix3(transpose, a.v[3].AsVector3(), a3_T);\r
+ Vec3 transpose;\r
+ MulVec3ByMat3(transpose, a.v[3].AsVec3(), a3_T);\r
\r
- SetMatrix4(r, a3_T, transpose);\r
+ SetMat4(r, a3_T, transpose);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Matrix4 InvertAffineMatrix4(const Matrix4& a)\r
+slInline Mat4 InvertAffineMat4(const Mat4& a)\r
{\r
- Matrix4 r;\r
+ Mat4 r;\r
\r
// this may not be correct...\r
- Matrix3 a3_T(a.v[0].AsVector3(), a.v[1].AsVector3(), a.v[2].AsVector3());\r
- InvertAffineMatrix3(a3_T, a3_T);\r
+ Mat3 a3_T(a.v[0].AsVec3(), a.v[1].AsVec3(), a.v[2].AsVec3());\r
+ InvertAffineMat3(a3_T, a3_T);\r
\r
- Vector3 transpose;\r
- MulVector3ByMatrix3(transpose, a.v[3].AsVector3(), a3_T);\r
+ Vec3 transpose;\r
+ MulVec3ByMat3(transpose, a.v[3].AsVec3(), a3_T);\r
\r
- SetMatrix4(r, a3_T, transpose);\r
+ SetMat4(r, a3_T, transpose);\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void InvertGeneralMatrix4(Matrix4& r, const Matrix4& a)\r
+slInline void InvertGeneralMat4(Mat4& r, const Mat4& a)\r
{\r
// does this work?\r
- float inv_determinant = 1.0f / DeterminantOfMatrix4(a);\r
+ float inv_determinant = 1.0f / DeterminantOfMat4(a);\r
\r
- Matrix4 a_T;\r
- TransposeMatrix4(a_T, a);\r
- CrossVector4(r.v[0], a_T.v[1], a_T.v[2], a_T.v[3]);\r
- CrossVector4(r.v[1], a_T.v[2], a_T.v[3], a_T.v[0]);\r
- CrossVector4(r.v[2], a_T.v[3], a_T.v[0], a_T.v[1]);\r
- CrossVector4(r.v[3], a_T.v[0], a_T.v[1], a_T.v[2]);\r
+ Mat4 a_T;\r
+ TransposeMat4(a_T, a);\r
+ CrossVec4(r.v[0], a_T.v[1], a_T.v[2], a_T.v[3]);\r
+ CrossVec4(r.v[1], a_T.v[2], a_T.v[3], a_T.v[0]);\r
+ CrossVec4(r.v[2], a_T.v[3], a_T.v[0], a_T.v[1]);\r
+ CrossVec4(r.v[3], a_T.v[0], a_T.v[1], a_T.v[2]);\r
\r
- ScaleMatrix4(r, inv_determinant, r);\r
+ ScaleMat4(r, inv_determinant, r);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Matrix4 InvertGeneralMatrix4(const Matrix4& a)\r
+slInline Mat4 InvertGeneralMat4(const Mat4& a)\r
{\r
// does this work?\r
- Matrix4 r;\r
- float inv_determinant = 1.0f / DeterminantOfMatrix4(a);\r
+ Mat4 r;\r
+ float inv_determinant = 1.0f / DeterminantOfMat4(a);\r
\r
- Matrix4 a_T;\r
- TransposeMatrix4(a_T, a);\r
- r.v[0] = CrossVector4(a_T.v[1], a_T.v[2], a_T.v[3]);\r
- r.v[1] = CrossVector4(a_T.v[2], a_T.v[3], a_T.v[0]);\r
- r.v[2] = CrossVector4(a_T.v[3], a_T.v[0], a_T.v[1]);\r
- r.v[3] = CrossVector4(a_T.v[0], a_T.v[1], a_T.v[2]);\r
+ Mat4 a_T;\r
+ TransposeMat4(a_T, a);\r
+ r.v[0] = CrossVec4(a_T.v[1], a_T.v[2], a_T.v[3]);\r
+ r.v[1] = CrossVec4(a_T.v[2], a_T.v[3], a_T.v[0]);\r
+ r.v[2] = CrossVec4(a_T.v[3], a_T.v[0], a_T.v[1]);\r
+ r.v[3] = CrossVec4(a_T.v[0], a_T.v[1], a_T.v[2]);\r
\r
- return ScaleMatrix4(inv_determinant, r);\r
+ return ScaleMat4(inv_determinant, r);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void MulMatrix4(Matrix4& r, const Matrix4& a, const Matrix4& b)\r
+slInline void MulMat4(Mat4& r, const Mat4& a, const Mat4& b)\r
{\r
- Matrix4 temp;\r
+ Mat4 temp;\r
\r
- temp.v[0].x = DotVector4(a.v[0], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x);\r
- temp.v[0].y = DotVector4(a.v[0], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y);\r
- temp.v[0].z = DotVector4(a.v[0], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z);\r
- temp.v[0].w = DotVector4(a.v[0], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w);\r
+ temp.v[0].x = DotVec4(a.v[0], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x);\r
+ temp.v[0].y = DotVec4(a.v[0], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y);\r
+ temp.v[0].z = DotVec4(a.v[0], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z);\r
+ temp.v[0].w = DotVec4(a.v[0], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w);\r
\r
- temp.v[1].x = DotVector4(a.v[1], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x);\r
- temp.v[1].y = DotVector4(a.v[1], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y);\r
- temp.v[1].z = DotVector4(a.v[1], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z);\r
- temp.v[1].w = DotVector4(a.v[1], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w);\r
+ temp.v[1].x = DotVec4(a.v[1], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x);\r
+ temp.v[1].y = DotVec4(a.v[1], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y);\r
+ temp.v[1].z = DotVec4(a.v[1], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z);\r
+ temp.v[1].w = DotVec4(a.v[1], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w);\r
\r
- temp.v[2].x = DotVector4(a.v[2], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x);\r
- temp.v[2].y = DotVector4(a.v[2], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y);\r
- temp.v[2].z = DotVector4(a.v[2], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z);\r
- temp.v[2].w = DotVector4(a.v[2], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w);\r
+ temp.v[2].x = DotVec4(a.v[2], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x);\r
+ temp.v[2].y = DotVec4(a.v[2], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y);\r
+ temp.v[2].z = DotVec4(a.v[2], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z);\r
+ temp.v[2].w = DotVec4(a.v[2], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w);\r
\r
- temp.v[3].x = DotVector4(a.v[3], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x);\r
- temp.v[3].y = DotVector4(a.v[3], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y);\r
- temp.v[3].z = DotVector4(a.v[3], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z);\r
- temp.v[3].w = DotVector4(a.v[3], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w);\r
+ temp.v[3].x = DotVec4(a.v[3], b.v[0].x, b.v[1].x, b.v[2].x, b.v[3].x);\r
+ temp.v[3].y = DotVec4(a.v[3], b.v[0].y, b.v[1].y, b.v[2].y, b.v[3].y);\r
+ temp.v[3].z = DotVec4(a.v[3], b.v[0].z, b.v[1].z, b.v[2].z, b.v[3].z);\r
+ temp.v[3].w = DotVec4(a.v[3], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w);\r
\r
- SetMatrix4(r, temp);\r
+ SetMat4(r, temp);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Matrix4 MulMatrix4(const Matrix4& a, const Matrix4& b)\r
+slInline Mat4 MulMat4(const Mat4& a, const Mat4& b)\r
{\r
- Matrix4 r;\r
+ Mat4 r;\r
\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
- 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
- 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
- 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
+ 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
+ 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
+ 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
+ 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
\r
- 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
- 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
- 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
- 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
+ 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
+ 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
+ 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
+ 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
\r
- 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
- 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
- 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
- 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
+ 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
+ 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
+ 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
+ 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
\r
- 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
- 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
- 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
- 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
+ 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
+ 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
+ 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
+ r.v[3].w = DotVec4(a.v[3], b.v[0].w, b.v[1].w, b.v[2].w, b.v[3].w);\r
\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void MulMatrix4ByTransposedMatrix4(Matrix4& r, const Matrix4& a, const Matrix4& t)\r
+slInline void MulMat4ByTransposedMat4(Mat4& r, const Mat4& a, const Mat4& t)\r
{\r
- Matrix4 temp;\r
+ Mat4 temp;\r
\r
- temp.v[0].x = DotVector4(a.v[0], b.v[0]);\r
- temp.v[0].y = DotVector4(a.v[0], b.v[1]);\r
- temp.v[0].z = DotVector4(a.v[0], b.v[2]);\r
- temp.v[0].w = DotVector4(a.v[0], b.v[3]);\r
+ temp.v[0].x = DotVec4(a.v[0], t.v[0]);\r
+ temp.v[0].y = DotVec4(a.v[0], t.v[1]);\r
+ temp.v[0].z = DotVec4(a.v[0], t.v[2]);\r
+ temp.v[0].w = DotVec4(a.v[0], t.v[3]);\r
\r
- temp.v[1].x = DotVector4(a.v[1], b.v[0]);\r
- temp.v[1].y = DotVector4(a.v[1], b.v[1]);\r
- temp.v[1].z = DotVector4(a.v[1], b.v[2]);\r
- temp.v[1].w = DotVector4(a.v[1], b.v[3]);\r
+ temp.v[1].x = DotVec4(a.v[1], t.v[0]);\r
+ temp.v[1].y = DotVec4(a.v[1], t.v[1]);\r
+ temp.v[1].z = DotVec4(a.v[1], t.v[2]);\r
+ temp.v[1].w = DotVec4(a.v[1], t.v[3]);\r
\r
- temp.v[2].x = DotVector4(a.v[2], b.v[0]);\r
- temp.v[2].y = DotVector4(a.v[2], b.v[1]);\r
- temp.v[2].z = DotVector4(a.v[2], b.v[2]);\r
- temp.v[2].w = DotVector4(a.v[2], b.v[3]);\r
+ temp.v[2].x = DotVec4(a.v[2], t.v[0]);\r
+ temp.v[2].y = DotVec4(a.v[2], t.v[1]);\r
+ temp.v[2].z = DotVec4(a.v[2], t.v[2]);\r
+ temp.v[2].w = DotVec4(a.v[2], t.v[3]);\r
\r
- temp.v[3].x = DotVector4(a.v[3], b.v[0]);\r
- temp.v[3].y = DotVector4(a.v[3], b.v[1]);\r
- temp.v[3].z = DotVector4(a.v[3], b.v[2]);\r
- temp.v[3].w = DotVector4(a.v[3], b.v[3]);\r
+ temp.v[3].x = DotVec4(a.v[3], t.v[0]);\r
+ temp.v[3].y = DotVec4(a.v[3], t.v[1]);\r
+ temp.v[3].z = DotVec4(a.v[3], t.v[2]);\r
+ temp.v[3].w = DotVec4(a.v[3], t.v[3]);\r
\r
- SetMatrix4(r, temp);\r
+ SetMat4(r, temp);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Matrix4 MulMatrix4ByTransposedMatrix4(const Matrix4& a, const Matrix4& t)\r
+slInline Mat4 MulMat4ByTransposedMat4(const Mat4& a, const Mat4& t)\r
{\r
- Matrix4 r;\r
+ Mat4 r;\r
\r
- r.v[0].x = DotVector4(a.v[0], b.v[0]);\r
- r.v[0].y = DotVector4(a.v[0], b.v[1]);\r
- r.v[0].z = DotVector4(a.v[0], b.v[2]);\r
- r.v[0].w = DotVector4(a.v[0], b.v[3]);\r
+ r.v[0].x = DotVec4(a.v[0], t.v[0]);\r
+ r.v[0].y = DotVec4(a.v[0], t.v[1]);\r
+ r.v[0].z = DotVec4(a.v[0], t.v[2]);\r
+ r.v[0].w = DotVec4(a.v[0], t.v[3]);\r
\r
- r.v[1].x = DotVector4(a.v[1], b.v[0]);\r
- r.v[1].y = DotVector4(a.v[1], b.v[1]);\r
- r.v[1].z = DotVector4(a.v[1], b.v[2]);\r
- r.v[1].w = DotVector4(a.v[1], b.v[3]);\r
+ r.v[1].x = DotVec4(a.v[1], t.v[0]);\r
+ r.v[1].y = DotVec4(a.v[1], t.v[1]);\r
+ r.v[1].z = DotVec4(a.v[1], t.v[2]);\r
+ r.v[1].w = DotVec4(a.v[1], t.v[3]);\r
\r
- r.v[2].x = DotVector4(a.v[2], b.v[0]);\r
- r.v[2].y = DotVector4(a.v[2], b.v[1]);\r
- r.v[2].z = DotVector4(a.v[2], b.v[2]);\r
- r.v[2].w = DotVector4(a.v[2], b.v[3]);\r
+ r.v[2].x = DotVec4(a.v[2], t.v[0]);\r
+ r.v[2].y = DotVec4(a.v[2], t.v[1]);\r
+ r.v[2].z = DotVec4(a.v[2], t.v[2]);\r
+ r.v[2].w = DotVec4(a.v[2], t.v[3]);\r
\r
- r.v[3].x = DotVector4(a.v[3], b.v[0]);\r
- r.v[3].y = DotVector4(a.v[3], b.v[1]);\r
- r.v[3].z = DotVector4(a.v[3], b.v[2]);\r
- r.v[3].w = DotVector4(a.v[3], b.v[3]);\r
+ r.v[3].x = DotVec4(a.v[3], t.v[0]);\r
+ r.v[3].y = DotVec4(a.v[3], t.v[1]);\r
+ r.v[3].z = DotVec4(a.v[3], t.v[2]);\r
+ r.v[3].w = DotVec4(a.v[3], t.v[3]);\r
\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void MulVector4ByMatrix4(Vector4& r, const Vector4& v, const Matrix4& a)\r
+slInline void MulVec4ByMat4(Vec4& r, const Vec4& v, const Mat4& a)\r
{\r
- Vector4 result;\r
- ScaleVector4(result, v.x, a.v[0]);\r
- ScaleAddVector4(result, v.y, a.v[1], result);\r
- ScaleAddVector4(result, v.z, a.v[2], result);\r
- ScaleAddVector4(result, v.w, a.v[3], result);\r
- SetVector4(r, result);\r
+ Vec4 result;\r
+ ScaleVec4(result, v.x, a.v[0]);\r
+ ScaleAddVec4(result, v.y, a.v[1], result);\r
+ ScaleAddVec4(result, v.z, a.v[2], result);\r
+ ScaleAddVec4(result, v.w, a.v[3], result);\r
+ SetVec4(r, result);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 MulVector4ByMatrix4(const Vector4& v, const Matrix4& a)\r
+slInline Vec4 MulVec4ByMat4(const Vec4& v, const Mat4& a)\r
{\r
- Vector4 r;\r
- ScaleVector4(r, v.x, a.v[0]);\r
- ScaleAddVector4(r, v.y, a.v[1], r);\r
- ScaleAddVector4(r, v.z, a.v[2], r);\r
- ScaleAddVector4(r, v.w, a.v[3], r);\r
+ Vec4 r;\r
+ ScaleVec4(r, v.x, a.v[0]);\r
+ ScaleAddVec4(r, v.y, a.v[1], r);\r
+ ScaleAddVec4(r, v.z, a.v[2], r);\r
+ ScaleAddVec4(r, v.w, a.v[3], r);\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void MulVector3ByMatrix4(Vector4& r, const Vector3& v, const float iw, const Matrix4& a)\r
+slInline void MulVec3ByMat4(Vec4& r, const Vec3& v, const float iw, const Mat4& a)\r
{\r
- Vector4 result;\r
- ScaleVector4(result, v.x, a.v[0]);\r
- ScaleAddVector4(result, v.y, a.v[1], result);\r
- ScaleAddVector4(result, v.z, a.v[2], result);\r
- ScaleAddVector4(result, iw, a.v[3], result);\r
- SetVector4(r, result);\r
+ Vec4 result;\r
+ ScaleVec4(result, v.x, a.v[0]);\r
+ ScaleAddVec4(result, v.y, a.v[1], result);\r
+ ScaleAddVec4(result, v.z, a.v[2], result);\r
+ ScaleAddVec4(result, iw, a.v[3], result);\r
+ SetVec4(r, result);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 MulVector3ByMatrix4(const Vector3& v, const float iw, const Matrix4& a)\r
+slInline Vec4 MulVec3ByMat4(const Vec3& v, const float iw, const Mat4& a)\r
{\r
- Vector4 r;\r
- ScaleVector4(r, v.x, a.v[0]);\r
- ScaleAddVector4(r, v.y, a.v[1], r);\r
- ScaleAddVector4(r, v.z, a.v[2], r);\r
- ScaleAddVector4(r, iw, a.v[3], r);\r
+ Vec4 r;\r
+ ScaleVec4(r, v.x, a.v[0]);\r
+ ScaleAddVec4(r, v.y, a.v[1], r);\r
+ ScaleAddVec4(r, v.z, a.v[2], r);\r
+ ScaleAddVec4(r, iw, a.v[3], r);\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void MulVector4ByTransposedMatrix4(Vector4& r, const Vector4& v, const Matrix4& t)\r
+slInline void MulVec4ByTransposedMat4(Vec4& r, const Vec4& v, const Mat4& t)\r
{\r
- float x = DotVector4(v, t.v[0]);\r
- float y = DotVector4(v, t.v[1]);\r
- float z = DotVector4(v, t.v[2]);\r
- float w = DotVector4(v, t.v[3]);\r
- SetVector4(r, x, y, z, w);\r
+ float x = DotVec4(v, t.v[0]);\r
+ float y = DotVec4(v, t.v[1]);\r
+ float z = DotVec4(v, t.v[2]);\r
+ float w = DotVec4(v, t.v[3]);\r
+ SetVec4(r, x, y, z, w);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 MulVector4ByTransposedMatrix4(const Vector4& v, const Matrix4& t)\r
+slInline Vec4 MulVec4ByTransposedMat4(const Vec4& v, const Mat4& t)\r
{\r
- Vector4 r;\r
- r.x = DotVector4(v, t.v[0]);\r
- r.y = DotVector4(v, t.v[1]);\r
- r.z = DotVector4(v, t.v[2]);\r
- r.w = DotVector4(v, t.v[3]);\r
+ Vec4 r;\r
+ r.x = DotVec4(v, t.v[0]);\r
+ r.y = DotVec4(v, t.v[1]);\r
+ r.z = DotVec4(v, t.v[2]);\r
+ r.w = DotVec4(v, t.v[3]);\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void MulVector3ByTransposedMatrix4(Vector4& r, const Vector3& v, const float w, const Matrix4& t)\r
+slInline void MulVec3ByTransposedMat4(Vec4& r, const Vec3& v, const float w, const Mat4& t)\r
{\r
- Vector4 v_new(v, w);\r
- MulVector4ByTransposedMatrix4(r, v_new, a);\r
+ Vec4 v_new(v, w);\r
+ MulVec4ByTransposedMat4(r, v_new, t);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 MulVector3ByTransposedMatrix4(const Vector3& v, const float w, const Matrix4& t)\r
+slInline Vec4 MulVec3ByTransposedMat4(const Vec3& v, const float w, const Mat4& t)\r
{\r
- Vector4 v_as_v4(v, w);\r
- return MulVector4ByTransposedMatrix4(v_as_v4, t);\r
+ Vec4 v_as_v4(v, w);\r
+ return MulVec4ByTransposedMat4(v_as_v4, t);\r
}\r
#pragma once\r
\r
#include "Foundation/Common/GlobalInclude.h"\r
-#include "Foundation/Common/MathTypes.h"\r
+#include "Foundation/Math/MathTypes.h"\r
#include "Foundation/Math/Vector.h"\r
\r
//----------------------------------------------------------------------------------------\r
// Quaternion\r
//----------------------------------------------------------------------------------------\r
void SetQuaternion(Quaternion& r, const float angle, const float x, const float y, const float z);\r
-void SetQuaternion(Quaternion& r, const float angle, const Vector3& rotation_axis);\r
+void SetQuaternion(Quaternion& r, const float angle, const Vec3& rotation_axis);\r
void ScaleQuaternion(Quaternion& r, const float s, const Quaternion& q);\r
void MulQuaternion(Quaternion& r, const Quaternion& p, const Quaternion& q);\r
void ConjugateOfQuaternion(Quaternion& r, const Quaternion& q);\r
//----------------------------------------------------------------------------------------\r
void SetQuaternion(Quaternion& r, const float angle, const float x, const float y, const float z)\r
{\r
- Assert( EpsilonEquals(LengthVector3(rotation_axis), 0.0f, kEpsilon) );\r
+ Assert( EpsilonEquals(x*x + y*y + z*z, 0.0f, kSqrtEpsilon) );\r
\r
float half_angle = angle * 0.5f;\r
- float sin_half_angle = Sinf(half_angle);\r
+ float sin_half_angle = (float)Sinf(half_angle);\r
\r
r.i = x * sin_half_angle;\r
r.j = y * sin_half_angle;\r
r.k = z * sin_half_angle;\r
- r.s = Cosf(half_angle);\r
+ r.s = (float)Cosf(half_angle);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-void SetQuaternion(Quaternion& r, const float angle, const Vector3& rotation_axis)\r
+void SetQuaternion(Quaternion& r, const float angle, const Vec3& rotation_axis)\r
{\r
- Assert( EpsilonEquals(LengthVector3(rotation_axis), 0.0f, kEpsilon) );\r
+ Assert( EpsilonEquals(rotation_axis.x * rotation_axis.x + rotation_axis.y * rotation_axis.y + rotation_axis.z * rotation_axis.z, 0.0f, kSqrtEpsilon) );\r
\r
float half_angle = angle * 0.5f;\r
- float sin_half_angle = Sinf(half_angle);\r
+ float sin_half_angle = (float)Sinf(half_angle);\r
\r
r.i = rotation_axis.x * sin_half_angle;\r
r.j = rotation_axis.y * sin_half_angle;\r
r.k = rotation_axis.z * sin_half_angle;\r
- r.s = Cosf(half_angle);\r
+ r.s = (float)Cosf(half_angle);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
//----------------------------------------------------------------------------------------\r
float NormOfQuaternion(const Quaternion& q)\r
{\r
- return Sqrtf( q.i * q.i + q.j * q.j + q.k * q.k + q.s * q.s);\r
+ return (float)Sqrtf( q.i * q.i + q.j * q.j + q.k * q.k + q.s * q.s);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
//----------------------------------------------------------------------------------------\r
void NormalizeQuaternion(Quaternion& r, Quaternion& q)\r
{\r
- float norm_scale = 1.0f / NormQuaternion( q );\r
+ float norm_scale = 1.0f / NormOfQuaternion( q );\r
ScaleQuaternion( r, norm_scale, q );\r
}\r
\r
#include "Foundation/Math/MathOperations.h"\r
\r
//----------------------------------------------------------------------------------------\r
-// Vector2\r
+// Vec2\r
//----------------------------------------------------------------------------------------\r
-void SetVector2(Vector2& r, const Vector2& v);\r
-void SetVector2(Vector2& r, const float x, const float y);\r
-void SetVector2(Vector2& r, const float xy);\r
-void AbsVector2(Vector2& r, const Vector2& v);\r
-float MinComponentVector2(const Vector2& v);\r
-float MaxComponentVector2(const Vector2& v);\r
-uint32_t MinIndexVector2(const Vector2& v);\r
-uint32_t MaxIndexVector2(const Vector2& v);\r
-float DotVector2(const Vector2& a, const Vector2& b);\r
-float DotVector2(const Vector2& a, const float x, const float y);\r
+void SetVec2(Vec2& r, const Vec2& v);\r
+void SetVec2(Vec2& r, const float x, const float y);\r
+void SetVec2(Vec2& r, const float xy);\r
+void AbsVec2(Vec2& r, const Vec2& v);\r
+float MinComponentVec2(const Vec2& v);\r
+float MaxComponentVec2(const Vec2& v);\r
+uint32_t MinIndexVec2(const Vec2& v);\r
+uint32_t MaxIndexVec2(const Vec2& v);\r
+float DotVec2(const Vec2& a, const Vec2& b);\r
+float DotVec2(const Vec2& a, const float x, const float y);\r
\r
-void PerpendicularVector2(Vector2& r, const Vector2& v);\r
-Vector2 PerpendicularVector2(const Vector2& v);\r
+void PerpendicularVec2(Vec2& r, const Vec2& v);\r
+Vec2 PerpendicularVec2(const Vec2& v);\r
\r
-void AddVector2ByScalar(Vector2& r, const float s, const Vector2& v);\r
-Vector2 AddVector2ByScalar(const float s, const Vector2& v);\r
+void AddVec2ByScalar(Vec2& r, const float s, const Vec2& v);\r
+Vec2 AddVec2ByScalar(const float s, const Vec2& v);\r
\r
-void AddVector2(Vector2& r, const Vector2& a, const Vector2& b);\r
-Vector2 AddVector2(const Vector2& a, const Vector2& b);\r
+void AddVec2(Vec2& r, const Vec2& a, const Vec2& b);\r
+Vec2 AddVec2(const Vec2& a, const Vec2& b);\r
\r
-void AddVector2(Vector2& r, const Vector2& a, const float x, const float y);\r
-Vector2 AddVector2(const Vector2& a, const float x, const float y);\r
+void AddVec2(Vec2& r, const Vec2& a, const float x, const float y);\r
+Vec2 AddVec2(const Vec2& a, const float x, const float y);\r
\r
-void SubVector2(Vector2& r, const Vector2& a, const Vector2& b);\r
-Vector2 SubVector2(const Vector2& a, const Vector2& b);\r
+void SubVec2(Vec2& r, const Vec2& a, const Vec2& b);\r
+Vec2 SubVec2(const Vec2& a, const Vec2& b);\r
\r
-void SubVector2(Vector2& r, const Vector2& a, const float x, const float y);\r
-Vector2 SubVector2(const Vector2& a, const float x, const float y);\r
+void SubVec2(Vec2& r, const Vec2& a, const float x, const float y);\r
+Vec2 SubVec2(const Vec2& a, const float x, const float y);\r
\r
-void ScaleVector2(Vector2& r, const float s, const Vector2& v);\r
-Vector2 ScaleVector2(const float s, const Vector2& v);\r
+void ScaleVec2(Vec2& r, const float s, const Vec2& v);\r
+Vec2 ScaleVec2(const float s, const Vec2& v);\r
\r
-void MulVector2(Vector2& r, const Vector2& a, const Vector2& b);\r
-Vector2 MulVector2(const Vector2& a, const Vector2& b);\r
+void MulVec2(Vec2& r, const Vec2& a, const Vec2& b);\r
+Vec2 MulVec2(const Vec2& a, const Vec2& b);\r
\r
-void MulVector2(Vector2& r, const Vector2& a, const float x, const float y);\r
-Vector2 MulVector2(const Vector2& a, const float x, const float y);\r
+void MulVec2(Vec2& r, const Vec2& a, const float x, const float y);\r
+Vec2 MulVec2(const Vec2& a, const float x, const float y);\r
\r
-void DivVector2(Vector2& r, const Vector2& a, const Vector2& b);\r
-Vector2 DivVector2(const Vector2& a, const Vector2& b);\r
+void DivVec2(Vec2& r, const Vec2& a, const Vec2& b);\r
+Vec2 DivVec2(const Vec2& a, const Vec2& b);\r
\r
-void DivVector2(Vector2& r, const Vector2& a, const float x, const float y);\r
-Vector2 DivVector2(const Vector2& a, const float x, const float y);\r
+void DivVec2(Vec2& r, const Vec2& a, const float x, const float y);\r
+Vec2 DivVec2(const Vec2& a, const float x, const float y);\r
\r
-void ScaleAddVector2(Vector2& r, const float s, const Vector2& v_scale, const Vector2& v_add);\r
-Vector2 ScaleAddVector2(const float s, const Vector2& v_scale, const Vector2& v_add);\r
+void ScaleAddVec2(Vec2& r, const float s, const Vec2& v_scale, const Vec2& v_add);\r
+Vec2 ScaleAddVec2(const float s, const Vec2& v_scale, const Vec2& v_add);\r
\r
-void NormalizeVector2(Vector2& r, const Vector2& a);\r
-Vector2 NormalizeVector2(const Vector2& a);\r
+void NormalizeVec2(Vec2& r, const Vec2& a);\r
+Vec2 NormalizeVec2(const Vec2& a);\r
\r
-float LengthOfVector2(const Vector2& a);\r
-float LengthSquaredOfVector2(const Vector2& a);\r
+float LengthOfVec2(const Vec2& a);\r
+float LengthSquaredOfVec2(const Vec2& a);\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SetVector2(Vector2& r, const Vector2& v)\r
+slInline void SetVec2(Vec2& r, const Vec2& v)\r
{\r
r.x = v.x;\r
r.y = v.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SetVector2(Vector2& r, const float x, const float y)\r
+slInline void SetVec2(Vec2& r, const float x, const float y)\r
{\r
r.x = x;\r
r.y = y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SetVector2(Vector2& r, const float xy)\r
+slInline void SetVec2(Vec2& r, const float xy)\r
{\r
r.x = xy;\r
r.y = xy;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-void AbsVector2(Vector2& r, const Vector2& v)\r
+void AbsVec2(Vec2& r, const Vec2& v)\r
{\r
r.x = Absf(v.x);\r
r.y = Absf(v.y);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-float MinComponentVector2(const Vector2& v)\r
+float MinComponentVec2(const Vec2& v)\r
{\r
return v.x <= v.y ? v.x : v.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-float MaxComponentVector2(const Vector2& v)\r
+float MaxComponentVec2(const Vec2& v)\r
{\r
return v.x >= v.y ? v.x : v.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-uint32_t MinIndexVector2(const Vector2& v)\r
+uint32_t MinIndexVec2(const Vec2& v)\r
{\r
return v.x <= v.y ? 0 : 1;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-uint32_t MaxIndexVector2(const Vector2& v)\r
+uint32_t MaxIndexVec2(const Vec2& v)\r
{\r
return v.x >= v.y ? 0 : 1;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float DotVector2(const Vector2& a, const Vector2& b)\r
+slInline float DotVec2(const Vec2& a, const Vec2& b)\r
{\r
return a.x * b.x + a.y * b.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float DotVector2(const Vector2& a, const float x, const float y)\r
+slInline float DotVec2(const Vec2& a, const float x, const float y)\r
{\r
return a.x * x + a.y * y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void PerpendicularVector2(Vector2& r, const Vector2& v)\r
+slInline void PerpendicularVec2(Vec2& r, const Vec2& v)\r
{\r
r.x = -v.y;\r
r.y = v.x;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector2 PerpendicularVector2(const Vector2& v)\r
+slInline Vec2 PerpendicularVec2(const Vec2& v)\r
{\r
- Vector2 r;\r
+ Vec2 r;\r
r.x = -v.y;\r
r.y = v.x;\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void AddVector2ByScalar(Vector2& r, const float s, Vector2& v)\r
+slInline void AddVec2ByScalar(Vec2& r, const float s, Vec2& v)\r
{\r
r.x = s + v.x;\r
r.y = s + v.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector2 AddVector2ByScalar(const float s, const Vector2& v)\r
+slInline Vec2 AddVec2ByScalar(const float s, const Vec2& v)\r
{\r
- Vector2 r;\r
+ Vec2 r;\r
r.x = s + v.x;\r
r.y = s + v.y;\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void AddVector2(Vector2& r, const Vector2& a, const Vector2& b)\r
+slInline void AddVec2(Vec2& r, const Vec2& a, const Vec2& b)\r
{\r
r.x = a.x + b.x;\r
r.y = a.y + b.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector2 AddVector2(const Vector2& a, const Vector2& b)\r
+slInline Vec2 AddVec2(const Vec2& a, const Vec2& b)\r
{\r
- Vector2 r;\r
+ Vec2 r;\r
r.x = a.x + b.x;\r
r.y = a.y + b.y;\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void AddVector2(Vector2& r, const Vector2& a, const float x, const float y)\r
+slInline void AddVec2(Vec2& r, const Vec2& a, const float x, const float y)\r
{\r
r.x = a.x + x;\r
r.y = a.y + y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector2 AddVector2(const Vector2& a, const float x, const float y)\r
+slInline Vec2 AddVec2(const Vec2& a, const float x, const float y)\r
{\r
- Vector2 r;\r
+ Vec2 r;\r
r.x = a.x + x;\r
r.y = a.y + y;\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SubVector2(Vector2& r, const Vector2& a, const Vector2& b)\r
+slInline void SubVec2(Vec2& r, const Vec2& a, const Vec2& b)\r
{\r
r.x = a.x - b.x;\r
r.y = a.y - b.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector2 SubVector2(const Vector2& a, const Vector2& b)\r
+slInline Vec2 SubVec2(const Vec2& a, const Vec2& b)\r
{\r
- Vector2 r;\r
+ Vec2 r;\r
r.x = a.x - b.x;\r
r.y = a.y - b.y;\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SubVector2(Vector2& r, const Vector2& a, const float x, const float y)\r
+slInline void SubVec2(Vec2& r, const Vec2& a, const float x, const float y)\r
{\r
r.x = a.x - x;\r
r.y = a.y - y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector2 SubVector2(const Vector2& a, const float x, const float y)\r
+slInline Vec2 SubVec2(const Vec2& a, const float x, const float y)\r
{\r
- Vector2 r;\r
+ Vec2 r;\r
r.x = a.x - x;\r
r.y = a.y - y;\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void ScaleVector2(Vector2& r, const float s, const Vector2& v)\r
+slInline void ScaleVec2(Vec2& r, const float s, const Vec2& v)\r
{\r
r.x = s * v.x;\r
r.y = s * v.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector2 ScaleVector2(const float s, const Vector2& v)\r
+slInline Vec2 ScaleVec2(const float s, const Vec2& v)\r
{\r
- Vector2 r;\r
+ Vec2 r;\r
r.x = s * v.x;\r
r.y = s * v.y;\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void MulVector2(Vector2& r, const Vector2& a, const Vector2& b)\r
+slInline void MulVec2(Vec2& r, const Vec2& a, const Vec2& b)\r
{\r
r.x = a.x * b.x;\r
r.y = a.y * b.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector2 MulVector2(const Vector2& a, const Vector2& b)\r
+slInline Vec2 MulVec2(const Vec2& a, const Vec2& b)\r
{\r
- Vector2 r;\r
+ Vec2 r;\r
r.x = a.x * b.x;\r
r.y = a.y * b.y;\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void MulVector2(Vector2& r, const Vector2& a, const float x, const float y)\r
+slInline void MulVec2(Vec2& r, const Vec2& a, const float x, const float y)\r
{\r
r.x = a.x * x;\r
r.y = a.y * y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector2 MulVector2(const Vector2& a, const float x, const float y)\r
+slInline Vec2 MulVec2(const Vec2& a, const float x, const float y)\r
{\r
- Vector2 r;\r
+ Vec2 r;\r
r.x = a.x * x;\r
r.y = a.y * y;\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void DivVector2(Vector2& r, const Vector2& a, const Vector2& b)\r
+slInline void DivVec2(Vec2& r, const Vec2& a, const Vec2& b)\r
{\r
r.x = a.x / b.x;\r
r.y = a.y / b.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector2 DivVector2(const Vector2& a, const Vector2& b)\r
+slInline Vec2 DivVec2(const Vec2& a, const Vec2& b)\r
{\r
- Vector2 r;\r
+ Vec2 r;\r
r.x = a.x / b.x;\r
r.y = a.y / b.y;\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void DivVector2(Vector2& r, const Vector2& a, const float x, const float y)\r
+slInline void DivVec2(Vec2& r, const Vec2& a, const float x, const float y)\r
{\r
r.x = a.x / x;\r
r.y = a.y / y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector2 DivVector2(const Vector2& a, const float x, const float y)\r
+slInline Vec2 DivVec2(const Vec2& a, const float x, const float y)\r
{\r
- Vector2 r;\r
+ Vec2 r;\r
r.x = a.x / x;\r
r.y = a.y / y;\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void ScaleAddVector2(Vector2& r, const float s, const Vector2& v_scale, const Vector2& v_add)\r
+slInline void ScaleAddVec2(Vec2& r, const float s, const Vec2& v_scale, const Vec2& v_add)\r
{\r
r.x = v_scale.x * s + v_add.x;\r
r.y = v_scale.y * s + v_add.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector2 ScaleAddVector2(const float s, const Vector2& v_scale, const Vector2& v_add)\r
+slInline Vec2 ScaleAddVec2(const float s, const Vec2& v_scale, const Vec2& v_add)\r
{\r
- Vector2 r;\r
+ Vec2 r;\r
r.x = v_scale.x * s + v_add.x;\r
r.y = v_scale.y * s + v_add.y;\r
return r;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void NormalizeVector2(Vector2& r, const Vector2& a)\r
+slInline void NormalizeVec2(Vec2& r, const Vec2& a)\r
{\r
- float scale = 1.0f / LengthOfVector2(a);\r
- ScaleVector2( r, scale, a );\r
+ float scale = 1.0f / LengthOfVec2(a);\r
+ ScaleVec2( r, scale, a );\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector2 NormalizeVector2(const Vector2& a)\r
+slInline Vec2 NormalizeVec2(const Vec2& a)\r
{\r
- float scale = 1.0f / LengthOfVector2(a);\r
- return ScaleVector2( scale, a );\r
+ float scale = 1.0f / LengthOfVec2(a);\r
+ return ScaleVec2( scale, a );\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float LengthOfVector2(const Vector2& a)\r
+slInline float LengthOfVec2(const Vec2& a)\r
{\r
- return Sqrtf( DotVector2(a, a) );\r
+ return (float)Sqrtf( DotVec2(a, a) );\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float LengthSquaredOfVector2(const Vector2& a)\r
+slInline float LengthSquaredOfVec2(const Vec2& a)\r
{\r
- return DotVector2(a, a);\r
+ return DotVec2(a, a);\r
}\r
\r
\r
\r
//----------------------------------------------------------------------------------------\r
-// Vector3\r
+// Vec3\r
//----------------------------------------------------------------------------------------\r
-void SetVector3(Vector3& r, const Vector3& v);\r
-void SetVector3(Vector3& r, const Vector2& v, const float z);\r
-void SetVector3(Vector3& r, const float xyz);\r
-void SetVector3(Vector3& r, const float x, const float y, const float z);\r
+void SetVec3(Vec3& r, const Vec3& v);\r
+void SetVec3(Vec3& r, const Vec2& v, const float z);\r
+void SetVec3(Vec3& r, const float xyz);\r
+void SetVec3(Vec3& r, const float x, const float y, const float z);\r
\r
-void AbsVector3(Vector3& r, const Vector3& v);\r
-Vector3 AbsVector3(const Vector3& v);\r
+void AbsVec3(Vec3& r, const Vec3& v);\r
+Vec3 AbsVec3(const Vec3& v);\r
\r
-float MinComponentVector3(const Vector3& v);\r
-float MaxComponentVector3(const Vector3& v);\r
-uint32_t MinIndexVector3(const Vector3& v);\r
-uint32_t MaxIndexVector3(const Vector3& v);\r
-float DotVector3(const Vector3& a, const Vector3& b);\r
-float DotVector3(const Vector3& a, const float x, const float y, const float z);\r
+float MinComponentVec3(const Vec3& v);\r
+float MaxComponentVec3(const Vec3& v);\r
+uint32_t MinIndexVec3(const Vec3& v);\r
+uint32_t MaxIndexVec3(const Vec3& v);\r
+float DotVec3(const Vec3& a, const Vec3& b);\r
+float DotVec3(const Vec3& a, const float x, const float y, const float z);\r
\r
-void CrossVector3(Vector3& r, const Vector3& a, const Vector3& b);\r
-Vector3 CrossVector3(const Vector3& a, const Vector3& b);\r
+void CrossVec3(Vec3& r, const Vec3& a, const Vec3& b);\r
+Vec3 CrossVec3(const Vec3& a, const Vec3& b);\r
\r
-void AddVector3ByScalar(Vector3& r, const float s, Vector3& v);\r
-Vector3 AddVector3ByScalar(const float s, Vector3& v);\r
+void AddVec3ByScalar(Vec3& r, const float s, Vec3& v);\r
+Vec3 AddVec3ByScalar(const float s, Vec3& v);\r
\r
-void AddVector3(Vector3& r, const Vector3& a, const Vector3& b);\r
-Vector3 AddVector3(const Vector3& a, const Vector3& b);\r
+void AddVec3(Vec3& r, const Vec3& a, const Vec3& b);\r
+Vec3 AddVec3(const Vec3& a, const Vec3& b);\r
\r
-void AddVector3(Vector3& r, const Vector3& a, const float x, const float y, const float z);\r
-Vector3 AddVector3(const Vector3& a, const float x, const float y, const float z);\r
+void AddVec3(Vec3& r, const Vec3& a, const float x, const float y, const float z);\r
+Vec3 AddVec3(const Vec3& a, const float x, const float y, const float z);\r
\r
-void SubVector3(Vector3& r, const Vector3& a, const Vector3& b);\r
-Vector3 SubVector3(const Vector3& a, const Vector3& b);\r
+void SubVec3(Vec3& r, const Vec3& a, const Vec3& b);\r
+Vec3 SubVec3(const Vec3& a, const Vec3& b);\r
\r
-void SubVector3(Vector3& r, const Vector3& a, const float x, const float y, const float z);\r
-Vector3 SubVector3(const Vector3& a, const float x, const float y, const float z);\r
+void SubVec3(Vec3& r, const Vec3& a, const float x, const float y, const float z);\r
+Vec3 SubVec3(const Vec3& a, const float x, const float y, const float z);\r
\r
-void ScaleVector3(Vector3& r, const float s, const Vector3& v);\r
-Vector3 ScaleVector3(const float s, const Vector3& v);\r
+void ScaleVec3(Vec3& r, const float s, const Vec3& v);\r
+Vec3 ScaleVec3(const float s, const Vec3& v);\r
\r
-void MulVector3(Vector3& r, const Vector3& a, const Vector3& b);\r
-Vector3 MulVector3(const Vector3& a, const Vector3& b);\r
+void MulVec3(Vec3& r, const Vec3& a, const Vec3& b);\r
+Vec3 MulVec3(const Vec3& a, const Vec3& b);\r
\r
-void MulVector3(Vector3& r, const Vector3& a, const float x, const float y, const float z);\r
-Vector3 MulVector3(const Vector3& a, const float x, const float y, const float z);\r
+void MulVec3(Vec3& r, const Vec3& a, const float x, const float y, const float z);\r
+Vec3 MulVec3(const Vec3& a, const float x, const float y, const float z);\r
\r
-void DivVector3(Vector3& r, const Vector3& a, const Vector3& b);\r
-Vector3 DivVector3(const Vector3& a, const Vector3& b);\r
+void DivVec3(Vec3& r, const Vec3& a, const Vec3& b);\r
+Vec3 DivVec3(const Vec3& a, const Vec3& b);\r
\r
-void DivVector3(Vector3& r, const Vector3& a, const float x, const float y, const float z);\r
-Vector3 DivVector3(const Vector3& a, const float x, const float y, const float z);\r
+void DivVec3(Vec3& r, const Vec3& a, const float x, const float y, const float z);\r
+Vec3 DivVec3(const Vec3& a, const float x, const float y, const float z);\r
\r
-void ScaleAddVector3(Vector3& r, const float s, const Vector3& v_scale, const Vector3& v_add);\r
-Vector3 ScaleAddVector3(const float s, const Vector3& v_scale, const Vector3& v_add);\r
+void ScaleAddVec3(Vec3& r, const float s, const Vec3& v_scale, const Vec3& v_add);\r
+Vec3 ScaleAddVec3(const float s, const Vec3& v_scale, const Vec3& v_add);\r
\r
-void NormalizeVector3(Vector3& r, const Vector3& a);\r
-Vector3 NormalizeVector3(const Vector3& a);\r
+void NormalizeVec3(Vec3& r, const Vec3& a);\r
+Vec3 NormalizeVec3(const Vec3& a);\r
\r
-float LengthVector3(const Vector3& a);\r
-float LengthSquaredVector3(const Vector3& a);\r
+float LengthOfVec3(const Vec3& a);\r
+float LengthSquaredVec3(const Vec3& a);\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SetVector3(Vector3& r, const Vector3& v)\r
+slInline void SetVec3(Vec3& r, const Vec3& v)\r
{\r
r.x = v.x;\r
r.y = v.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SetVector3(Vector3& r, const Vector2& v, const float z)\r
+slInline void SetVec3(Vec3& r, const Vec2& v, const float z)\r
{\r
r.x = v.x;\r
r.y = v.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SetVector3(Vector3& r, const float xyz)\r
+slInline void SetVec3(Vec3& r, const float xyz)\r
{\r
r.x = xyz;\r
r.y = xyz;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SetVector3(Vector3& r, const float x, const float y, const float z)\r
+slInline void SetVec3(Vec3& r, const float x, const float y, const float z)\r
{\r
r.x = x;\r
r.y = y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void AbsVector3(Vector3& r, const Vector3& v)\r
+slInline void AbsVec3(Vec3& r, const Vec3& v)\r
{\r
r.x = Absf(v.x);\r
r.y = Absf(v.y);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector3 AbsVector3(const Vector3& v)\r
+slInline Vec3 AbsVec3(const Vec3& v)\r
{\r
- Vector3 r;\r
+ Vec3 r;\r
r.x = Absf(v.x);\r
r.y = Absf(v.y);\r
r.z = Absf(v.z);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float MinComponentVector3(const Vector3& v)\r
+slInline float MinComponentVec3(const Vec3& v)\r
{\r
float xy = v.x <= v.y ? v.x : v.y;\r
return xy <= v.z ? xy : v.z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float MaxComponentVector3(const Vector3& v)\r
+slInline float MaxComponentVec3(const Vec3& v)\r
{\r
float xy = v.x >= v.y ? v.x : v.y;\r
return xy >= v.z ? xy : v.z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline uint32_t MinIndexVector3(const Vector3& v)\r
+slInline uint32_t MinIndexVec3(const Vec3& v)\r
{\r
const float* v_array = &v.x;\r
uint32_t xy = v.x <= v.y ? 0 : 1;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline uint32_t MaxIndexVector3(const Vector3& v)\r
+slInline uint32_t MaxIndexVec3(const Vec3& v)\r
{\r
const float* v_array = &v.x;\r
uint32_t xy = v.x >= v.y ? 0 : 1;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float DotVector3(const Vector3& a, const Vector3& b)\r
+slInline float DotVec3(const Vec3& a, const Vec3& b)\r
{\r
return a.x * b.x + a.y * b.y + a.z * b.z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float DotVector3(const Vector3& a, const float x, const float y, const float z)\r
+slInline float DotVec3(const Vec3& a, const float x, const float y, const float z)\r
{\r
return a.x * x + a.y * y + a.z * z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void CrossVector3(Vector3& r, const Vector3& a, const Vector3& b)\r
+slInline void CrossVec3(Vec3& r, const Vec3& a, const Vec3& b)\r
{\r
float x = a.y * b.z - b.y * a.z;\r
float y = a.z * b.x - b.z * a.x;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector3 CrossVector3(const Vector3& a, const Vector3& b)\r
+slInline Vec3 CrossVec3(const Vec3& a, const Vec3& b)\r
{\r
- Vector3 r;\r
+ Vec3 r;\r
r.x = a.y * b.z - b.y * a.z;\r
r.y = a.z * b.x - b.z * a.x;\r
r.z = a.x * b.y - b.x * a.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void AddVector3ByScalar(Vector3& r, const float s, Vector3& v)\r
+slInline void AddVec3ByScalar(Vec3& r, const float s, Vec3& v)\r
{\r
r.x = s + v.x;\r
r.y = s + v.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector3 AddVector3ByScalar(const float s, Vector3& v)\r
+slInline Vec3 AddVec3ByScalar(const float s, Vec3& v)\r
{\r
- Vector3 r;\r
+ Vec3 r;\r
r.x = s + v.x;\r
r.y = s + v.y;\r
r.z = s + v.z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void AddVector3(Vector3& r, const Vector3& a, const Vector3& b)\r
+slInline void AddVec3(Vec3& r, const Vec3& a, const Vec3& b)\r
{\r
r.x = a.x + b.x;\r
r.y = a.y + b.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector3 AddVector3(const Vector3& a, const Vector3& b)\r
+slInline Vec3 AddVec3(const Vec3& a, const Vec3& b)\r
{\r
- Vector3 r;\r
+ Vec3 r;\r
r.x = a.x + b.x;\r
r.y = a.y + b.y;\r
r.z = a.z + b.z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void AddVector3(Vector3& r, const Vector3& a, const float x, const float y, const float z)\r
+slInline void AddVec3(Vec3& r, const Vec3& a, const float x, const float y, const float z)\r
{\r
r.x = a.x + x;\r
r.y = a.y + y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector3 AddVector3(const Vector3& a, const float x, const float y, const float z)\r
+slInline Vec3 AddVec3(const Vec3& a, const float x, const float y, const float z)\r
{\r
- Vector3 r;\r
+ Vec3 r;\r
r.x = a.x + x;\r
r.y = a.y + y;\r
r.z = a.z + z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SubVector3(Vector3& r, const Vector3& a, const Vector3& b)\r
+slInline void SubVec3(Vec3& r, const Vec3& a, const Vec3& b)\r
{\r
r.x = a.x - b.x;\r
r.y = a.y - b.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector3 SubVector3(const Vector3& a, const Vector3& b)\r
+slInline Vec3 SubVec3(const Vec3& a, const Vec3& b)\r
{\r
- Vector3 r;\r
+ Vec3 r;\r
r.x = a.x - b.x;\r
r.y = a.y - b.y;\r
r.z = a.z - b.z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector3 SubVector3(const Vector3& a, const float x, const float y, const float z)\r
+slInline Vec3 SubVec3(const Vec3& a, const float x, const float y, const float z)\r
{\r
- Vector3 r;\r
+ Vec3 r;\r
r.x = a.x - x;\r
r.y = a.y - y;\r
r.z = a.z - z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void ScaleVector3(Vector3& r, const float s, const Vector3& v)\r
+slInline void ScaleVec3(Vec3& r, const float s, const Vec3& v)\r
{\r
r.x = s * v.x;\r
r.y = s * v.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector3 ScaleVector3(const float s, const Vector3& v)\r
+slInline Vec3 ScaleVec3(const float s, const Vec3& v)\r
{\r
- Vector3 r;\r
+ Vec3 r;\r
r.x = s * v.x;\r
r.y = s * v.y;\r
r.z = s * v.z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void MulVector3(Vector3& r, const Vector3& a, const Vector3& b)\r
+slInline void MulVec3(Vec3& r, const Vec3& a, const Vec3& b)\r
{\r
r.x = a.x * b.x;\r
r.y = a.y * b.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector3 MulVector3(const Vector3& a, const Vector3& b)\r
+slInline Vec3 MulVec3(const Vec3& a, const Vec3& b)\r
{\r
- Vector3 r;\r
+ Vec3 r;\r
r.x = a.x * b.x;\r
r.y = a.y * b.y;\r
r.z = a.z * b.z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void MulVector3(Vector3& r, const Vector3& a, const float x, const float y, const float z)\r
+slInline void MulVec3(Vec3& r, const Vec3& a, const float x, const float y, const float z)\r
{\r
r.x = a.x * x;\r
r.y = a.y * y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector3 MulVector3(const Vector3& a, const float x, const float y, const float z)\r
+slInline Vec3 MulVec3(const Vec3& a, const float x, const float y, const float z)\r
{\r
- Vector3 r;\r
+ Vec3 r;\r
r.x = a.x * x;\r
r.y = a.y * y;\r
r.z = a.z * z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void DivVector3(Vector3& r, const Vector3& a, const Vector3& b)\r
+slInline void DivVec3(Vec3& r, const Vec3& a, const Vec3& b)\r
{\r
r.x = a.x / b.x;\r
r.y = a.y / b.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector3 DivVector3(const Vector3& a, const Vector3& b)\r
+slInline Vec3 DivVec3(const Vec3& a, const Vec3& b)\r
{\r
- Vector3 r;\r
+ Vec3 r;\r
r.x = a.x / b.x;\r
r.y = a.y / b.y;\r
r.z = a.z / b.z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void DivVector3(Vector3& r, const Vector3& a, const float x, const float y, const float z)\r
+slInline void DivVec3(Vec3& r, const Vec3& a, const float x, const float y, const float z)\r
{\r
r.x = a.x / x;\r
r.y = a.y / y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector3 DivVector3(const Vector3& a, const float x, const float y, const float z)\r
+slInline Vec3 DivVec3(const Vec3& a, const float x, const float y, const float z)\r
{\r
- Vector3 r;\r
+ Vec3 r;\r
r.x = a.x / x;\r
r.y = a.y / y;\r
r.z = a.z / z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void ScaleAddVector3(Vector3& r, const float s, const Vector3& v_scale, const Vector3& v_add)\r
+slInline void ScaleAddVec3(Vec3& r, const float s, const Vec3& v_scale, const Vec3& v_add)\r
{\r
r.x = s * v_scale.x + v_add.x;\r
r.y = s * v_scale.y + v_add.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector3 ScaleAddVector3(const float s, const Vector3& v_scale, const Vector3& v_add)\r
+slInline Vec3 ScaleAddVec3(const float s, const Vec3& v_scale, const Vec3& v_add)\r
{\r
- Vector3 r;\r
+ Vec3 r;\r
r.x = s * v_scale.x + v_add.x;\r
r.y = s * v_scale.y + v_add.y;\r
r.z = s * v_scale.z + v_add.z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void NormalizeVector3(Vector3& r, const Vector3& a)\r
+slInline void NormalizeVec3(Vec3& r, const Vec3& a)\r
{\r
- float scale = 1.0f / LengthOfVector3( a );\r
- ScaleVector3( r, scale, a );\r
+ float scale = 1.0f / LengthOfVec3( a );\r
+ ScaleVec3( r, scale, a );\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector3 NormalizeVector3(const Vector3& a)\r
+slInline Vec3 NormalizeVec3(const Vec3& a)\r
{\r
- float scale = 1.0f / LengthOfVector3( a );\r
- return ScaleVector3( scale, a );\r
+ float scale = 1.0f / LengthOfVec3( a );\r
+ return ScaleVec3( scale, a );\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float LengthOfVector3(const Vector3& a)\r
+slInline float LengthOfVec3(const Vec3& a)\r
{\r
- return Sqrtf( DotVector3(a, a) );\r
+ return (float)Sqrtf( DotVec3(a, a) );\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float LengthSquaredOfVector3(const Vector3& a)\r
+slInline float LengthSquaredOfVec3(const Vec3& a)\r
{\r
- return DotVector3( a, a );\r
+ return DotVec3( a, a );\r
}\r
\r
\r
\r
//----------------------------------------------------------------------------------------\r
-// Vector4\r
+// Vec4\r
//----------------------------------------------------------------------------------------\r
-void SetVector4(Vector4& r, const Vector4& v);\r
-void SetVector4(Vector4& r, const Vector2& a, const Vector2& b);\r
-void SetVector4(Vector4& r, const Vector3& v, const float w);\r
-void SetVector4(Vector4& r, const float xyzw);\r
-void SetVector4(Vector4& r, const float x, const float y, const float z, const float w);\r
+void SetVec4(Vec4& r, const Vec4& v);\r
+void SetVec4(Vec4& r, const Vec2& a, const Vec2& b);\r
+void SetVec4(Vec4& r, const Vec3& v, const float w);\r
+void SetVec4(Vec4& r, const float xyzw);\r
+void SetVec4(Vec4& r, const float x, const float y, const float z, const float w);\r
\r
-void AbsVector4(Vector4& r, const Vector4& v);\r
-Vector4 AbsVector4(const Vector4& v);\r
+void AbsVec4(Vec4& r, const Vec4& v);\r
+Vec4 AbsVec4(const Vec4& v);\r
\r
-float MinComponentVector4(const Vector4& v);\r
-float MaxComponentVector4(const Vector4& v);\r
-uint32_t MinIndexVector4(const Vector4& v);\r
-uint32_t MaxIndexVector4(const Vector4& v);\r
-float DotVector4(const Vector4& a, const Vector4& b);\r
-float DotVector4(const Vector4& a, const float x, const float y, const float z, const float w);\r
+float MinComponentVec4(const Vec4& v);\r
+float MaxComponentVec4(const Vec4& v);\r
+uint32_t MinIndexVec4(const Vec4& v);\r
+uint32_t MaxIndexVec4(const Vec4& v);\r
+float DotVec4(const Vec4& a, const Vec4& b);\r
+float DotVec4(const Vec4& a, const float x, const float y, const float z, const float w);\r
\r
-void CrossVector4(Vector4& r, const Vector4& a, const Vector4& b, const Vector4& c);\r
-Vector4 CrossVector4(const Vector4& a, const Vector4& b, const Vector4& c);\r
+void CrossVec4(Vec4& r, const Vec4& a, const Vec4& b, const Vec4& c);\r
+Vec4 CrossVec4(const Vec4& a, const Vec4& b, const Vec4& c);\r
\r
-void AddVector4ByScalar(Vector4& r, const float s, Vector4& v);\r
-Vector4 AddVector4ByScalar(const float s, Vector4& v);\r
+void AddVec4ByScalar(Vec4& r, const float s, Vec4& v);\r
+Vec4 AddVec4ByScalar(const float s, Vec4& v);\r
\r
-void AddVector4(Vector4& r, const Vector4& a, const Vector4& b);\r
-Vector4 AddVector4(const Vector4& a, const Vector4& b);\r
+void AddVec4(Vec4& r, const Vec4& a, const Vec4& b);\r
+Vec4 AddVec4(const Vec4& a, const Vec4& b);\r
\r
-void AddVector4(Vector4& r, const Vector4& a, const float x, const float y, const float z, const float w);\r
-Vector4 AddVector4(const Vector4& a, const float x, const float y, const float z, const float w);\r
+void AddVec4(Vec4& r, const Vec4& a, const float x, const float y, const float z, const float w);\r
+Vec4 AddVec4(const Vec4& a, const float x, const float y, const float z, const float w);\r
\r
-void SubVector4(Vector4& r, const Vector4& a, const Vector4& b);\r
-Vector4 SubVector4(const Vector4& a, const Vector4& b);\r
+void SubVec4(Vec4& r, const Vec4& a, const Vec4& b);\r
+Vec4 SubVec4(const Vec4& a, const Vec4& b);\r
\r
-void SubVector4(Vector4& r, const Vector4& a, const float x, const float y, const float z, const float w);\r
-Vector4 SubVector4(const Vector4& a, const float x, const float y, const float z, const float w);\r
+void SubVec4(Vec4& r, const Vec4& a, const float x, const float y, const float z, const float w);\r
+Vec4 SubVec4(const Vec4& a, const float x, const float y, const float z, const float w);\r
\r
-void ScaleVector4(Vector4& r, const float s, const Vector4& v);\r
-Vector4 ScaleVector4(const float s, const Vector4& v);\r
+void ScaleVec4(Vec4& r, const float s, const Vec4& v);\r
+Vec4 ScaleVec4(const float s, const Vec4& v);\r
\r
-void MulVector4(Vector4& r, const Vector4& a, const Vector4& b);\r
-Vector4 MulVector4(const Vector4& a, const Vector4& b);\r
+void MulVec4(Vec4& r, const Vec4& a, const Vec4& b);\r
+Vec4 MulVec4(const Vec4& a, const Vec4& b);\r
\r
-void MulVector4(Vector4& r, const Vector4& a, const float x, const float y, const float z, const float w);\r
-Vector4 MulVector4(const Vector4& a, const float x, const float y, const float z, const float w);\r
+void MulVec4(Vec4& r, const Vec4& a, const float x, const float y, const float z, const float w);\r
+Vec4 MulVec4(const Vec4& a, const float x, const float y, const float z, const float w);\r
\r
-void DivVector4(Vector4& r, const Vector4& a, const Vector4& b);\r
-Vector4 DivVector4(const Vector4& a, const Vector4& b);\r
+void DivVec4(Vec4& r, const Vec4& a, const Vec4& b);\r
+Vec4 DivVec4(const Vec4& a, const Vec4& b);\r
\r
-void DivVector4(Vector4& r, const Vector4& a, const float x, const float y, const float z, const float w);\r
-Vector4 DivVector4(const Vector4& a, const float x, const float y, const float z, const float w);\r
+void DivVec4(Vec4& r, const Vec4& a, const float x, const float y, const float z, const float w);\r
+Vec4 DivVec4(const Vec4& a, const float x, const float y, const float z, const float w);\r
\r
-void ScaleAddVector4(Vector4& r, const float s, const Vector4& v_scale, const Vector4& v_add);\r
-Vector4 ScaleAddVector4(const float s, const Vector4& v_scale, const Vector4& v_add);\r
+void ScaleAddVec4(Vec4& r, const float s, const Vec4& v_scale, const Vec4& v_add);\r
+Vec4 ScaleAddVec4(const float s, const Vec4& v_scale, const Vec4& v_add);\r
\r
-void NormalizeVector4(Vector4& r, const Vector4& a);\r
-Vector4 NormalizeVector4(const Vector4& a);\r
+void NormalizeVec4(Vec4& r, const Vec4& a);\r
+Vec4 NormalizeVec4(const Vec4& a);\r
\r
-float LengthVector4(const Vector4& a);\r
-float LengthSquaredVector4(const Vector4& a);\r
+float LengthOfVec4(const Vec4& a);\r
+float LengthSquaredVec4(const Vec4& a);\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SetVector4(Vector4& r, const Vector4& v)\r
+slInline void SetVec4(Vec4& r, const Vec4& v)\r
{\r
r.x = v.x;\r
r.y = v.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SetVector4(Vector4& r, const Vector2& a, const Vector2& b)\r
+slInline void SetVec4(Vec4& r, const Vec2& a, const Vec2& b)\r
{\r
r.x = a.x;\r
r.y = a.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SetVector4(Vector4& r, const Vector3& v, const float w)\r
+slInline void SetVec4(Vec4& r, const Vec3& v, const float w)\r
{\r
r.x = v.x;\r
r.y = v.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SetVector4(Vector4& r, const float xyzw)\r
+slInline void SetVec4(Vec4& r, const float xyzw)\r
{\r
r.x = xyzw;\r
r.y = xyzw;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SetVector4(Vector4& r, const float x, const float y, const float z, const float w)\r
+slInline void SetVec4(Vec4& r, const float x, const float y, const float z, const float w)\r
{\r
r.x = x;\r
r.y = y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void AbsVector4(Vector4& r, const Vector4& v)\r
+slInline void AbsVec4(Vec4& r, const Vec4& v)\r
{\r
r.x = Absf(v.x);\r
r.y = Absf(v.y);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 AbsVector4(const Vector4& v)\r
+slInline Vec4 AbsVec4(const Vec4& v)\r
{\r
- Vector4 r;\r
+ Vec4 r;\r
r.x = Absf(v.x);\r
r.y = Absf(v.y);\r
r.z = Absf(v.z);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float MinComponentVector4(const Vector4& v)\r
+slInline float MinComponentVec4(const Vec4& v)\r
{\r
float xy = v.x <= v.y ? v.x : v.y;\r
float zw = v.z <= v.w ? v.z : v.w;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float MaxComponentVector4(const Vector4& v)\r
+slInline float MaxComponentVec4(const Vec4& v)\r
{\r
float xy = v.x >= v.y ? v.x : v.y;\r
float zw = v.z >= v.w ? v.z : v.w;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline uint32_t MinIndexVector4(const Vector4& v)\r
+slInline uint32_t MinIndexVec4(const Vec4& v)\r
{\r
const float* v_array = &v.x;\r
uint32_t xy = v.x <= v.y ? 0 : 1;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline uint32_t MaxIndexVector4(const Vector4& v)\r
+slInline uint32_t MaxIndexVec4(const Vec4& v)\r
{\r
const float* v_array = &v.x;\r
uint32_t xy = v.x >= v.y ? 0 : 1;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float DotVector4(const Vector4& a, const Vector4& b)\r
+slInline float DotVec4(const Vec4& a, const Vec4& b)\r
{\r
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float DotVector4(const Vector4& a, const float x, const float y, const float z, const float w)\r
+slInline float DotVec4(const Vec4& a, const float x, const float y, const float z, const float w)\r
{\r
return a.x * x + a.y * y + a.z * z + a.w * w;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void CrossVector4(Vector4& r, const Vector4& a, const Vector4& b, const Vector4& c)\r
+slInline void CrossVec4(Vec4& r, const Vec4& a, const Vec4& b, const Vec4& c)\r
{\r
// is this right?\r
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
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 CrossVector4(const Vector4& a, const Vector4& b, const Vector4& c)\r
+slInline Vec4 CrossVec4(const Vec4& a, const Vec4& b, const Vec4& c)\r
{\r
- Vector4 r;\r
+ Vec4 r;\r
// is this right?\r
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
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);\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void AddVector4ByScalar(Vector4& r, const float s, Vector4& v)\r
+slInline void AddVec4ByScalar(Vec4& r, const float s, Vec4& v)\r
{\r
r.x = s * v.x;\r
r.y = s * v.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 AddVector4ByScalar(const float s, Vector4& v)\r
+slInline Vec4 AddVec4ByScalar(const float s, Vec4& v)\r
{\r
- Vector4 r;\r
+ Vec4 r;\r
r.x = s * v.x;\r
r.y = s * v.y;\r
r.z = s * v.z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void AddVector4(Vector4& r, const Vector4& a, const Vector4& b)\r
+slInline void AddVec4(Vec4& r, const Vec4& a, const Vec4& b)\r
{\r
r.x = a.x + b.x;\r
r.y = a.y + b.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 AddVector4(const Vector4& a, const Vector4& b)\r
+slInline Vec4 AddVec4(const Vec4& a, const Vec4& b)\r
{\r
- Vector4 r;\r
+ Vec4 r;\r
r.x = a.x + b.x;\r
r.y = a.y + b.y;\r
r.z = a.z + b.z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void AddVector4(Vector4& r, const Vector4& a, const float x, const float y, const float z, const float w)\r
+slInline void AddVec4(Vec4& r, const Vec4& a, const float x, const float y, const float z, const float w)\r
{\r
r.x = a.x + x;\r
r.y = a.y + y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 AddVector4(const Vector4& a, const float x, const float y, const float z, const float w)\r
+slInline Vec4 AddVec4(const Vec4& a, const float x, const float y, const float z, const float w)\r
{\r
- Vector4 r;\r
+ Vec4 r;\r
r.x = a.x + x;\r
r.y = a.y + y;\r
r.z = a.z + z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SubVector4(Vector4& r, const Vector4& a, const Vector4& b)\r
+slInline void SubVec4(Vec4& r, const Vec4& a, const Vec4& b)\r
{\r
r.x = a.x - b.x;\r
r.y = a.y - b.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 SubVector4(const Vector4& a, const Vector4& b)\r
+slInline Vec4 SubVec4(const Vec4& a, const Vec4& b)\r
{\r
- Vector4 r;\r
+ Vec4 r;\r
r.x = a.x - b.x;\r
r.y = a.y - b.y;\r
r.z = a.z - b.z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void SubVector4(Vector4& r, const Vector4& a, const float x, const float y, const float z, const float w)\r
+slInline void SubVec4(Vec4& r, const Vec4& a, const float x, const float y, const float z, const float w)\r
{\r
r.x = a.x - x;\r
r.y = a.y - y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 SubVector4(const Vector4& a, const float x, const float y, const float z, const float w)\r
+slInline Vec4 SubVec4(const Vec4& a, const float x, const float y, const float z, const float w)\r
{\r
- Vector4 r;\r
+ Vec4 r;\r
r.x = a.x - x;\r
r.y = a.y - y;\r
r.z = a.z - z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void ScaleVector4(Vector4& r, const float s, const Vector4& v)\r
+slInline void ScaleVec4(Vec4& r, const float s, const Vec4& v)\r
{\r
r.x = s * v.x;\r
r.y = s * v.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 ScaleVector4(const float s, const Vector4& v)\r
+slInline Vec4 ScaleVec4(const float s, const Vec4& v)\r
{\r
- Vector4 r;\r
+ Vec4 r;\r
r.x = s * v.x;\r
r.y = s * v.y;\r
r.z = s * v.z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void MulVector4(Vector4& r, const Vector4& a, const Vector4& b)\r
+slInline void MulVec4(Vec4& r, const Vec4& a, const Vec4& b)\r
{\r
r.x = a.x * b.x;\r
r.y = a.y * b.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 MulVector4(const Vector4& a, const Vector4& b)\r
+slInline Vec4 MulVec4(const Vec4& a, const Vec4& b)\r
{\r
- Vector4 r;\r
+ Vec4 r;\r
r.x = a.x * b.x;\r
r.y = a.y * b.y;\r
r.z = a.z * b.z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void MulVector4(Vector4& r, const Vector4& a, const float x, const float y, const float z, const float w)\r
+slInline void MulVec4(Vec4& r, const Vec4& a, const float x, const float y, const float z, const float w)\r
{\r
r.x = a.x * x;\r
r.y = a.y * y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 MulVector4(const Vector4& a, const float x, const float y, const float z, const float w)\r
+slInline Vec4 MulVec4(const Vec4& a, const float x, const float y, const float z, const float w)\r
{\r
- Vector4 r;\r
+ Vec4 r;\r
r.x = a.x * x;\r
r.y = a.y * y;\r
r.z = a.z * z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void DivVector4(Vector4& r, const Vector4& a, const Vector4& b)\r
+slInline void DivVec4(Vec4& r, const Vec4& a, const Vec4& b)\r
{\r
r.x = a.x / b.x;\r
r.y = a.y / b.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 DivVector4(const Vector4& a, const Vector4& b)\r
+slInline Vec4 DivVec4(const Vec4& a, const Vec4& b)\r
{\r
- Vector4 r;\r
+ Vec4 r;\r
r.x = a.x / b.x;\r
r.y = a.y / b.y;\r
r.z = a.z / b.z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void DivVector4(Vector4& r, const Vector4& a, const float x, const float y, const float z, const float w)\r
+slInline void DivVec4(Vec4& r, const Vec4& a, const float x, const float y, const float z, const float w)\r
{\r
r.x = a.x / x;\r
r.y = a.y / y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 DivVector4(const Vector4& a, const float x, const float y, const float z, const float w)\r
+slInline Vec4 DivVec4(const Vec4& a, const float x, const float y, const float z, const float w)\r
{\r
- Vector4 r;\r
+ Vec4 r;\r
r.x = a.x / x;\r
r.y = a.y / y;\r
r.z = a.z / z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void ScaleAddVector4(Vector4& r, const float s, const Vector4& v_scale, const Vector4& v_add)\r
+slInline void ScaleAddVec4(Vec4& r, const float s, const Vec4& v_scale, const Vec4& v_add)\r
{\r
r.x = s * v_scale.x + v_add.x;\r
r.y = s * v_scale.y + v_add.y;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 ScaleAddVector4(const float s, const Vector4& v_scale, const Vector4& v_add)\r
+slInline Vec4 ScaleAddVec4(const float s, const Vec4& v_scale, const Vec4& v_add)\r
{\r
- Vector4 r;\r
+ Vec4 r;\r
r.x = s * v_scale.x + v_add.x;\r
r.y = s * v_scale.y + v_add.y;\r
r.z = s * v_scale.z + v_add.z;\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline void NormalizeVector4(Vector4& r, const Vector4& a)\r
+slInline void NormalizeVec4(Vec4& r, const Vec4& a)\r
{\r
- float scale = 1.0f / LengthOfVector4( a );\r
- ScaleVector4( r, scale, a );\r
+ float scale = 1.0f / LengthOfVec4( a );\r
+ ScaleVec4( r, scale, a );\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline Vector4 NormalizeVector4(const Vector4& a)\r
+slInline Vec4 NormalizeVec4(const Vec4& a)\r
{\r
- float scale = 1.0f / LengthOfVector4( a );\r
- return ScaleVector4( scale, a );\r
+ float scale = 1.0f / LengthOfVec4( a );\r
+ return ScaleVec4( scale, a );\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float LengthOfVector4(const Vector4& a)\r
+slInline float LengthOfVec4(const Vec4& a)\r
{\r
- return Sqrtf( DotVector4(a, a) );\r
+ return (float)Sqrtf( DotVec4(a, a) );\r
}\r
\r
//----------------------------------------------------------------------------------------\r
-slInline float LengthSquaredOfVector4(const Vector4& a)\r
+slInline float LengthSquaredOfVec4(const Vec4& a)\r
{\r
- return DotVector4( a, a );\r
+ return DotVec4( a, a );\r
}\r
--- /dev/null
+/*
+ * 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 <sys/time.h>
+#import <Foundation/Foundation.h>
+
+#import "ccTypes.h"
+
+enum {
+ //! Default tag
+ kCCActionTagInvalid = -1,
+};
+
+/** Base class for CCAction objects.
+ */
+@interface CCAction : NSObject <NSCopying>
+{
+ 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 <NSCopying>
+{
+ //! 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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+ /* 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
+
--- /dev/null
+/*
+ * 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 <Availability.h>
+#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
+
+
--- /dev/null
+/*
+ * 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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+ 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+ 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 <NSCopying> {} @end
+
+/** CCEaseOut action with a rate
+ */
+@interface CCEaseOut : CCEaseRateAction <NSCopying> {} @end
+
+/** CCEaseInOut action with a rate
+ */
+@interface CCEaseInOut : CCEaseRateAction <NSCopying> {} @end
+
+/** CCEase Exponential In
+ */
+@interface CCEaseExponentialIn : CCActionEase <NSCopying> {} @end
+/** Ease Exponential Out
+ */
+@interface CCEaseExponentialOut : CCActionEase <NSCopying> {} @end
+/** Ease Exponential InOut
+ */
+@interface CCEaseExponentialInOut : CCActionEase <NSCopying> {} @end
+/** Ease Sine In
+ */
+@interface CCEaseSineIn : CCActionEase <NSCopying> {} @end
+/** Ease Sine Out
+ */
+@interface CCEaseSineOut : CCActionEase <NSCopying> {} @end
+/** Ease Sine InOut
+ */
+@interface CCEaseSineInOut : CCActionEase <NSCopying> {} @end
+
+/** Ease Elastic abstract class
+ @since v0.8.2
+ */
+@interface CCEaseElastic : CCActionEase <NSCopying>
+{
+ 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 <NSCopying> {} @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 <NSCopying> {} @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 <NSCopying> {} @end
+
+/** CCEaseBounce abstract class.
+ @since v0.8.2
+*/
+@interface CCEaseBounce : CCActionEase <NSCopying> {} @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 <NSCopying> {} @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 <NSCopying> {} @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 <NSCopying> {} @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 <NSCopying> {} @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 <NSCopying> {} @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 <NSCopying> {} @end
+
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <NSCopying>
+{
+}
+@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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+ 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<NSCopying>
+{
+ 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<NSCopying>
+{
+ 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <sys/time.h>
+
+/** 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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+}
+/** 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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+}
+@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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+}
+@end
+
+/** Blinks a CCNode object by modifying it's visible attribute
+*/
+@interface CCBlink : CCActionInterval <NSCopying>
+{
+ 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 <NSCopying>
+{
+}
+@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 <NSCopying>
+{
+}
+@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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+}
+@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 <NSCopying>
+{
+ 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 <NSCopying>
+{
+ 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
--- /dev/null
+/*
+ * 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<CCRGBAProtocol>) target_ setOpacity: 255 *t];
+}
+
+-(CCActionInterval*) reverse
+{
+ return [CCFadeOut actionWithDuration:duration_];
+}
+@end
+
+//
+// FadeOut
+//
+#pragma mark -
+#pragma mark FadeOut
+@implementation CCFadeOut
+-(void) update: (ccTime) t
+{
+ [(id<CCRGBAProtocol>) 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<CCRGBAProtocol>)target_ opacity];
+}
+
+-(void) update: (ccTime) t
+{
+ [(id<CCRGBAProtocol>)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<CCRGBAProtocol> tn = (id<CCRGBAProtocol>) target_;
+ from = [tn color];
+}
+
+-(void) update: (ccTime) t
+{
+ id<CCRGBAProtocol> tn = (id<CCRGBAProtocol>) 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<CCRGBAProtocol> tn = (id<CCRGBAProtocol>) target_;
+ ccColor3B color = [tn color];
+ fromR = color.r;
+ fromG = color.g;
+ fromB = color.b;
+}
+
+-(void) update: (ccTime) t
+{
+ id<CCRGBAProtocol> tn = (id<CCRGBAProtocol>) 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
--- /dev/null
+/*
+ * 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
+
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+#import "CCProgressTimer.h"
+#import "CCActionInterval.h"
+
+/**
+ Progress to percentage
+@since v0.99.1
+*/
+@interface CCProgressTo : CCActionInterval <NSCopying>
+{
+ 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 <NSCopying>
+{
+ 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+#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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+
+@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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+
+@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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <CCRGBAProtocol, CCTextureProtocol>
+{
+ // 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+
+/** @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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+
+/*
+ * 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 <Foundation/Foundation.h>
+#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
--- /dev/null
+
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+
+#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
--- /dev/null
+/*
+ * 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 <Availability.h>
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#import <UIKit/UIKit.h> // 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
--- /dev/null
+/*
+ * 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<CCProjectionProtocol> 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<CCProjectionProtocol> 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
--- /dev/null
+/*
+ * 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 <unistd.h>
+#import <Availability.h>
+
+// 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
+
--- /dev/null
+/*
+ * 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 <Availability.h>
+#import <Foundation/Foundation.h>
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#import <CoreGraphics/CGGeometry.h> // 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
--- /dev/null
+/*
+ * 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 <math.h>
+#import <stdlib.h>
+#import <string.h>
+
+#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<numberOfPoints;i++)
+ newPoints[i] = (ccVertex2F){ points[i].x * CC_CONTENT_SCALE_FACTOR(), points[i].y * CC_CONTENT_SCALE_FACTOR() };
+
+ glVertexPointer(2, GL_FLOAT, 0, newPoints);
+
+ } else
+ glVertexPointer(2, GL_FLOAT, 0, points);
+
+ glDrawArrays(GL_POINTS, 0, numberOfPoints);
+
+ } else {
+
+ // Mac on 64-bit
+ for( NSUInteger i=0; i<numberOfPoints;i++)
+ newPoints[i] = (ccVertex2F) { points[i].x, points[i].y };
+
+ glVertexPointer(2, GL_FLOAT, 0, newPoints);
+ glDrawArrays(GL_POINTS, 0, numberOfPoints);
+
+ }
+
+
+ // restore default state
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_2D);
+}
+
+
+void ccDrawLine( CGPoint origin, CGPoint destination )
+{
+ ccVertex2F vertices[2] = {
+ {origin.x * CC_CONTENT_SCALE_FACTOR(), origin.y * CC_CONTENT_SCALE_FACTOR() },
+ {destination.x * CC_CONTENT_SCALE_FACTOR(), destination.y * CC_CONTENT_SCALE_FACTOR() }
+ };
+
+ // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
+ // Needed states: GL_VERTEX_ARRAY,
+ // Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
+ glDisable(GL_TEXTURE_2D);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ glDrawArrays(GL_LINES, 0, 2);
+
+ // restore default state
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_2D);
+}
+
+
+void ccDrawPoly( const CGPoint *poli, NSUInteger numberOfPoints, BOOL closePolygon )
+{
+ ccVertex2F newPoint[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);
+
+
+ // iPhone and 32-bit machines
+ if( sizeof(CGPoint) == sizeof(ccVertex2F) ) {
+
+ // convert to pixels ?
+ if( CC_CONTENT_SCALE_FACTOR() != 1 ) {
+ memcpy( newPoint, poli, numberOfPoints * sizeof(ccVertex2F) );
+ for( NSUInteger i=0; i<numberOfPoints;i++)
+ newPoint[i] = (ccVertex2F) { poli[i].x * CC_CONTENT_SCALE_FACTOR(), poli[i].y * CC_CONTENT_SCALE_FACTOR() };
+
+ glVertexPointer(2, GL_FLOAT, 0, newPoint);
+
+ } else
+ glVertexPointer(2, GL_FLOAT, 0, poli);
+
+
+ } else {
+ // 64-bit machines (Mac)
+
+ for( NSUInteger i=0; i<numberOfPoints;i++)
+ newPoint[i] = (ccVertex2F) { poli[i].x, poli[i].y };
+
+ glVertexPointer(2, GL_FLOAT, 0, newPoint );
+
+ }
+
+ if( closePolygon )
+ glDrawArrays(GL_LINE_LOOP, 0, numberOfPoints);
+ else
+ glDrawArrays(GL_LINE_STRIP, 0, numberOfPoints);
+
+ // restore default state
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_2D);
+}
+
+void ccDrawCircle( CGPoint center, float r, float a, NSUInteger segs, BOOL drawLineToCenter)
+{
+ int additionalSegment = 1;
+ if (drawLineToCenter)
+ additionalSegment++;
+
+ const float coef = 2.0f * (float)M_PI/segs;
+
+ GLfloat *vertices = calloc( sizeof(GLfloat)*2*(segs+2), 1);
+ if( ! vertices )
+ return;
+
+ for(NSUInteger i=0;i<=segs;i++)
+ {
+ float rads = i*coef;
+ GLfloat j = r * cosf(rads + a) + center.x;
+ GLfloat k = r * sinf(rads + a) + center.y;
+
+ vertices[i*2] = j * CC_CONTENT_SCALE_FACTOR();
+ vertices[i*2+1] =k * CC_CONTENT_SCALE_FACTOR();
+ }
+ vertices[(segs+1)*2] = center.x * CC_CONTENT_SCALE_FACTOR();
+ vertices[(segs+1)*2+1] = center.y * CC_CONTENT_SCALE_FACTOR();
+
+ // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
+ // Needed states: GL_VERTEX_ARRAY,
+ // Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
+ glDisable(GL_TEXTURE_2D);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ glDrawArrays(GL_LINE_STRIP, 0, segs+additionalSegment);
+
+ // restore default state
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_2D);
+
+ free( vertices );
+}
+
+void ccDrawQuadBezier(CGPoint origin, CGPoint control, CGPoint destination, NSUInteger segments)
+{
+ ccVertex2F vertices[segments + 1];
+
+ float t = 0.0f;
+ for(NSUInteger i = 0; i < segments; i++)
+ {
+ GLfloat x = powf(1 - t, 2) * origin.x + 2.0f * (1 - t) * t * control.x + t * t * destination.x;
+ GLfloat y = powf(1 - t, 2) * origin.y + 2.0f * (1 - t) * t * control.y + t * t * destination.y;
+ vertices[i] = (ccVertex2F) {x * CC_CONTENT_SCALE_FACTOR(), y * CC_CONTENT_SCALE_FACTOR() };
+ t += 1.0f / segments;
+ }
+ vertices[segments] = (ccVertex2F) {destination.x * CC_CONTENT_SCALE_FACTOR(), destination.y * CC_CONTENT_SCALE_FACTOR() };
+
+ // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
+ // Needed states: GL_VERTEX_ARRAY,
+ // Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
+ glDisable(GL_TEXTURE_2D);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ glDrawArrays(GL_LINE_STRIP, 0, segments + 1);
+
+ // restore default state
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_2D);
+}
+
+void ccDrawCubicBezier(CGPoint origin, CGPoint control1, CGPoint control2, CGPoint destination, NSUInteger segments)
+{
+ ccVertex2F vertices[segments + 1];
+
+ float t = 0;
+ for(NSUInteger i = 0; i < segments; i++)
+ {
+ GLfloat x = powf(1 - t, 3) * origin.x + 3.0f * powf(1 - t, 2) * t * control1.x + 3.0f * (1 - t) * t * t * control2.x + t * t * t * destination.x;
+ GLfloat y = powf(1 - t, 3) * origin.y + 3.0f * powf(1 - t, 2) * t * control1.y + 3.0f * (1 - t) * t * t * control2.y + t * t * t * destination.y;
+ vertices[i] = (ccVertex2F) {x * CC_CONTENT_SCALE_FACTOR(), y * CC_CONTENT_SCALE_FACTOR() };
+ t += 1.0f / segments;
+ }
+ vertices[segments] = (ccVertex2F) {destination.x * CC_CONTENT_SCALE_FACTOR(), destination.y * CC_CONTENT_SCALE_FACTOR() };
+
+ // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
+ // Needed states: GL_VERTEX_ARRAY,
+ // Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
+ glDisable(GL_TEXTURE_2D);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ glDrawArrays(GL_LINE_STRIP, 0, segments + 1);
+
+ // restore default state
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_2D);
+}
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+
+@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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+
+#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
--- /dev/null
+/*
+ * 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 <Availability.h>
+
+#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
--- /dev/null
+/*
+ * 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 <CCLabelProtocol>
+{
+ // 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
--- /dev/null
+/*
+ * 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<n; i++) {
+ unsigned char a = s[i] - mapStartChar;
+ float row = (a % itemsPerRow_);
+ float col = (a / itemsPerRow_);
+
+#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
+ // Issue #938. Don't use texStepX & texStepY
+ float left = (2*row*itemWidth_+1)/(2*textureWide);
+ float right = left+(itemWidth_*2-2)/(2*textureWide);
+ float top = (2*col*itemHeight_+1)/(2*textureHigh);
+ float bottom = top+(itemHeight_*2-2)/(2*textureHigh);
+#else
+ float left = row*itemWidth_/textureWide;
+ float right = left+itemWidth_/textureWide;
+ float top = col*itemHeight_/textureHigh;
+ float bottom = top+itemHeight_/textureHigh;
+#endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
+
+ quad.tl.texCoords.u = left;
+ quad.tl.texCoords.v = top;
+ quad.tr.texCoords.u = right;
+ quad.tr.texCoords.v = top;
+ quad.bl.texCoords.u = left;
+ quad.bl.texCoords.v = bottom;
+ quad.br.texCoords.u = right;
+ quad.br.texCoords.v = bottom;
+
+ quad.bl.vertices.x = (int) (i * itemWidth_);
+ quad.bl.vertices.y = 0;
+ quad.bl.vertices.z = 0.0f;
+ quad.br.vertices.x = (int)(i * itemWidth_ + itemWidth_);
+ quad.br.vertices.y = 0;
+ quad.br.vertices.z = 0.0f;
+ quad.tl.vertices.x = (int)(i * itemWidth_);
+ quad.tl.vertices.y = (int)(itemHeight_);
+ quad.tl.vertices.z = 0.0f;
+ quad.tr.vertices.x = (int)(i * itemWidth_ + itemWidth_);
+ quad.tr.vertices.y = (int)(itemHeight_);
+ quad.tr.vertices.z = 0.0f;
+
+ [textureAtlas_ updateQuad:&quad atIndex:i];
+ }
+}
+
+#pragma mark CCLabelAtlas - CCLabelProtocol
+
+- (void) setString:(NSString*) newString
+{
+ if( newString.length > 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
--- /dev/null
+/*
+ * 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 <CCLabelProtocol, CCRGBAProtocol>
+{
+ // 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
+
--- /dev/null
+/*
+ * 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; i<stringLen; i++) {
+ unichar c = [string_ characterAtIndex:i];
+ NSAssert( c < kCCBMFontMaxChars, @"BitmapFontAtlas: character outside bounds");
+
+ if (c == '\n') {
+ nextFontPositionX = 0;
+ nextFontPositionY -= configuration_->commonHeight_;
+ 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<CCRGBAProtocol> child;
+ CCARRAY_FOREACH(children_, child)
+ [child setOpacity:opacity_];
+}
+-(void) setOpacityModifyRGB:(BOOL)modify
+{
+ opacityModifyRGB_ = modify;
+
+ id<CCRGBAProtocol> 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
--- /dev/null
+/*
+ * 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 <CCLabelProtocol>
+{
+ 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
--- /dev/null
+/*
+ * 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 <Availability.h>
+
+#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
--- /dev/null
+/*
+ * 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 <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#import <UIKit/UIKit.h> // 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 <UIAccelerometerDelegate, CCStandardTouchDelegate, CCTargetedTouchDelegate>
+{
+ 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 <CCKeyboardEventDelegate, CCMouseEventDelegate>
+{
+ 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 <CCRGBAProtocol, CCBlendProtocol>
+{
+ 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
--- /dev/null
+/*
+ * 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 <stdarg.h>
+
+#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<sizeof(squareVertices) / sizeof( squareVertices[0]); i++ )
+ squareVertices[i] = 0.0f;
+
+ [self updateColor];
+ [self setContentSize:CGSizeMake(w, h) ];
+ }
+ return self;
+}
+
+- (id) initWithColor:(ccColor4B)color
+{
+ CGSize s = [[CCDirector sharedDirector] winSize];
+ return [self initWithColor:color width:s.width height:s.height];
+}
+
+// override contentSize
+-(void) setContentSize: (CGSize) size
+{
+ squareVertices[2] = size.width * CC_CONTENT_SCALE_FACTOR();
+ squareVertices[5] = size.height * CC_CONTENT_SCALE_FACTOR();
+ squareVertices[6] = size.width * CC_CONTENT_SCALE_FACTOR();
+ squareVertices[7] = size.height * CC_CONTENT_SCALE_FACTOR();
+
+ [super setContentSize:size];
+}
+
+- (void) changeWidth: (GLfloat) w height:(GLfloat) h
+{
+ [self setContentSize:CGSizeMake(w, h)];
+}
+
+-(void) changeWidth: (GLfloat) w
+{
+ [self setContentSize:CGSizeMake(w, contentSize_.height)];
+}
+
+-(void) changeHeight: (GLfloat) h
+{
+ [self setContentSize:CGSizeMake(contentSize_.width, h)];
+}
+
+- (void) updateColor
+{
+ for( NSUInteger i = 0; i < 4; i++ )
+ {
+ squareColors[i*4] = color_.r;
+ squareColors[i*4+1] = color_.g;
+ squareColors[i*4+2] = color_.b;
+ squareColors[i*4+3] = opacity_;
+ }
+}
+
+- (void)draw
+{
+ // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
+ // Needed states: GL_VERTEX_ARRAY, GL_COLOR_ARRAY
+ // Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisable(GL_TEXTURE_2D);
+
+ glVertexPointer(2, GL_FLOAT, 0, squareVertices);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, squareColors);
+
+
+ BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST;
+ if( newBlend )
+ glBlendFunc( blendFunc_.src, blendFunc_.dst );
+
+ else if( opacity_ != 255 ) {
+ newBlend = YES;
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ if( newBlend )
+ glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
+
+ // restore default GL state
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_2D);
+}
+
+#pragma mark Protocols
+// Color Protocol
+
+-(void) setColor:(ccColor3B)color
+{
+ color_ = color;
+ [self updateColor];
+}
+
+-(void) setOpacity: (GLubyte) o
+{
+ opacity_ = o;
+ [self updateColor];
+}
+@end
+
+// XXX Deprecated
+@implementation CCColorLayer
+@end
+
+
+#pragma mark -
+#pragma mark LayerGradient
+
+@implementation CCLayerGradient
+
+@synthesize startOpacity = startOpacity_;
+@synthesize endColor = endColor_, endOpacity = endOpacity_;
+@synthesize vector = vector_;
+
++ (id) layerWithColor: (ccColor4B) start fadingTo: (ccColor4B) end
+{
+ return [[[self alloc] initWithColor:start fadingTo:end] autorelease];
+}
+
++ (id) layerWithColor: (ccColor4B) start fadingTo: (ccColor4B) end alongVector: (CGPoint) v
+{
+ return [[[self alloc] initWithColor:start fadingTo:end alongVector:v] autorelease];
+}
+
+- (id) initWithColor: (ccColor4B) start fadingTo: (ccColor4B) end
+{
+ return [self initWithColor:start fadingTo:end alongVector:ccp(0, -1)];
+}
+
+- (id) initWithColor: (ccColor4B) start fadingTo: (ccColor4B) end alongVector: (CGPoint) v
+{
+ endColor_.r = end.r;
+ endColor_.g = end.g;
+ endColor_.b = end.b;
+
+ endOpacity_ = end.a;
+ startOpacity_ = start.a;
+ vector_ = v;
+
+ start.a = 255;
+ return [self initWithColor:start];
+}
+
+- (void) updateColor
+{
+ [super updateColor];
+
+ float h = sqrtf(vector_.x*vector_.x + vector_.y*vector_.y);
+ if (h == 0)
+ return;
+
+ double c = sqrt(2);
+ CGPoint u = ccp(vector_.x / h, vector_.y / h);
+
+ float opacityf = (float)opacity_/255.0f;
+
+ ccColor4B S = {
+ color_.r,
+ color_.g,
+ color_.b,
+ startOpacity_*opacityf
+ };
+
+ ccColor4B E = {
+ endColor_.r,
+ endColor_.g,
+ endColor_.b,
+ endOpacity_*opacityf
+ };
+
+ // (-1, -1)
+ squareColors[0] = E.r + (S.r - E.r) * ((c + u.x + u.y) / (2.0f * c));
+ squareColors[1] = E.g + (S.g - E.g) * ((c + u.x + u.y) / (2.0f * c));
+ squareColors[2] = E.b + (S.b - E.b) * ((c + u.x + u.y) / (2.0f * c));
+ squareColors[3] = E.a + (S.a - E.a) * ((c + u.x + u.y) / (2.0f * c));
+ // (1, -1)
+ squareColors[4] = E.r + (S.r - E.r) * ((c - u.x + u.y) / (2.0f * c));
+ squareColors[5] = E.g + (S.g - E.g) * ((c - u.x + u.y) / (2.0f * c));
+ squareColors[6] = E.b + (S.b - E.b) * ((c - u.x + u.y) / (2.0f * c));
+ squareColors[7] = E.a + (S.a - E.a) * ((c - u.x + u.y) / (2.0f * c));
+ // (-1, 1)
+ squareColors[8] = E.r + (S.r - E.r) * ((c + u.x - u.y) / (2.0f * c));
+ squareColors[9] = E.g + (S.g - E.g) * ((c + u.x - u.y) / (2.0f * c));
+ squareColors[10] = E.b + (S.b - E.b) * ((c + u.x - u.y) / (2.0f * c));
+ squareColors[11] = E.a + (S.a - E.a) * ((c + u.x - u.y) / (2.0f * c));
+ // (1, 1)
+ squareColors[12] = E.r + (S.r - E.r) * ((c - u.x - u.y) / (2.0f * c));
+ squareColors[13] = E.g + (S.g - E.g) * ((c - u.x - u.y) / (2.0f * c));
+ squareColors[14] = E.b + (S.b - E.b) * ((c - u.x - u.y) / (2.0f * c));
+ squareColors[15] = E.a + (S.a - E.a) * ((c - u.x - u.y) / (2.0f * c));
+}
+
+-(ccColor3B) startColor
+{
+ return color_;
+}
+
+-(void) setStartColor:(ccColor3B)colors
+{
+ [self setColor:colors];
+}
+
+-(void) setEndColor:(ccColor3B)colors
+{
+ endColor_ = colors;
+ [self updateColor];
+}
+
+-(void) setStartOpacity: (GLubyte) o
+{
+ startOpacity_ = o;
+ [self updateColor];
+}
+
+-(void) setEndOpacity: (GLubyte) o
+{
+ endOpacity_ = o;
+ [self updateColor];
+}
+
+-(void) setVector: (CGPoint) v
+{
+ vector_ = v;
+ [self updateColor];
+}
+
+@end
+
+#pragma mark -
+#pragma mark MultiplexLayer
+
+@implementation CCMultiplexLayer
++(id) layerWithLayers: (CCLayer*) layer, ...
+{
+ va_list args;
+ va_start(args,layer);
+
+ id s = [[[self alloc] initWithLayers: layer vaList:args] autorelease];
+
+ va_end(args);
+ return s;
+}
+
+-(id) initWithLayers: (CCLayer*) layer vaList:(va_list) params
+{
+ if( (self=[super init]) ) {
+
+ layers = [[NSMutableArray arrayWithCapacity:5] retain];
+
+ [layers addObject: layer];
+
+ CCLayer *l = va_arg(params,CCLayer*);
+ while( l ) {
+ [layers addObject: l];
+ l = va_arg(params,CCLayer*);
+ }
+
+ enabledLayer = 0;
+ [self addChild: [layers objectAtIndex: enabledLayer]];
+ }
+
+ return self;
+}
+
+-(void) dealloc
+{
+ [layers release];
+ [super dealloc];
+}
+
+-(void) switchTo: (unsigned int) n
+{
+ NSAssert( n < [layers count], @"Invalid index in MultiplexLayer switchTo message" );
+
+ [self removeChild: [layers objectAtIndex:enabledLayer] cleanup:YES];
+
+ enabledLayer = n;
+
+ [self addChild: [layers objectAtIndex:n]];
+}
+
+-(void) switchToAndReleaseMe: (unsigned int) n
+{
+ NSAssert( n < [layers count], @"Invalid index in MultiplexLayer switchTo message" );
+
+ [self removeChild: [layers objectAtIndex:enabledLayer] cleanup:YES];
+
+ [layers replaceObjectAtIndex:enabledLayer withObject:[NSNull null]];
+
+ enabledLayer = n;
+
+ [self addChild: [layers objectAtIndex:n]];
+}
+
+@end
--- /dev/null
+/*
+ * 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 "CCLayer.h"
+
+typedef enum {
+ kCCMenuStateWaiting,
+ kCCMenuStateTrackingTouch
+} tCCMenuState;
+
+enum {
+ //* priority used by the menu
+ kCCMenuTouchPriority = -128,
+};
+
+/** A CCMenu
+ *
+ * Features and Limitation:
+ * - You can add MenuItem objects in runtime using addChild:
+ * - But the only accecpted children are MenuItem objects
+ */
+@interface CCMenu : CCLayer <CCRGBAProtocol>
+{
+ 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
--- /dev/null
+/*
+ * 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 <Availability.h>
+#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<CCRGBAProtocol> item;
+ CCARRAY_FOREACH(children_, item)
+ [item setOpacity:opacity_];
+}
+
+-(void) setColor:(ccColor3B)color
+{
+ color_ = color;
+
+ id<CCRGBAProtocol> item;
+ CCARRAY_FOREACH(children_, item)
+ [item setColor:color_];
+}
+@end
--- /dev/null
+/*
+ * 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 <CCRGBAProtocol>
+{
+ CCNode<CCLabelProtocol, CCRGBAProtocol> *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<CCLabelProtocol, CCRGBAProtocol>* label;
+
+/** creates a CCMenuItemLabel with a Label, target and selector */
++(id) itemWithLabel:(CCNode<CCLabelProtocol,CCRGBAProtocol>*)label target:(id)target selector:(SEL)selector;
+
+/** initializes a CCMenuItemLabel with a Label, target and selector */
+-(id) initWithLabel:(CCNode<CCLabelProtocol,CCRGBAProtocol>*)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<CCLabelProtocol,CCRGBAProtocol>*)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<CCLabelProtocol,CCRGBAProtocol>*)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<CCRGBAProtocol> objects as items.
+ The images has 3 different states:
+ - unselected image
+ - selected image
+ - disabled image
+
+ @since v0.8.0
+ */
+@interface CCMenuItemSprite : CCMenuItem <CCRGBAProtocol>
+{
+ CCNode<CCRGBAProtocol> *normalImage_, *selectedImage_, *disabledImage_;
+}
+
+// weak references
+
+/** the image used when the item is not selected */
+@property (nonatomic,readwrite,assign) CCNode<CCRGBAProtocol> *normalImage;
+/** the image used when the item is selected */
+@property (nonatomic,readwrite,assign) CCNode<CCRGBAProtocol> *selectedImage;
+/** the image used when the item is disabled */
+@property (nonatomic,readwrite,assign) CCNode<CCRGBAProtocol> *disabledImage;
+
+/** creates a menu item with a normal and selected image*/
++(id) itemFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite;
+/** creates a menu item with a normal and selected image with target/selector */
++(id) itemFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite target:(id)target selector:(SEL)selector;
+/** creates a menu item with a normal,selected and disabled image with target/selector */
++(id) itemFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite disabledSprite:(CCNode<CCRGBAProtocol>*)disabledSprite target:(id)target selector:(SEL)selector;
+/** initializes a menu item with a normal, selected and disabled image with target/selector */
+-(id) initFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite disabledSprite:(CCNode<CCRGBAProtocol>*)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<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)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<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite disabledSprite:(CCNode<CCRGBAProtocol>*)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<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite disabledSprite:(CCNode<CCRGBAProtocol>*)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 <CCRGBAProtocol>
+{
+ 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
+
--- /dev/null
+/*
+ * 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<CCLabelProtocol,CCRGBAProtocol>*)label target:(id)target selector:(SEL)selector
+{
+ return [[[self alloc] initWithLabel:label target:target selector:selector] autorelease];
+}
+
+-(id) initWithLabel:(CCNode<CCLabelProtocol,CCRGBAProtocol>*)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<CCLabelProtocol,CCRGBAProtocol>*)label block:(void(^)(id sender))block {
+ return [[[self alloc] initWithLabel:label block:block] autorelease];
+}
+
+-(id) initWithLabel:(CCNode<CCLabelProtocol,CCRGBAProtocol>*)label block:(void(^)(id sender))block {
+ block_ = [block copy];
+ return [self initWithLabel:label target:block_ selector:@selector(ccCallbackBlockWithSender:)];
+}
+
+#endif // NS_BLOCKS_AVAILABLE
+
+-(CCNode<CCLabelProtocol, CCRGBAProtocol>*) label
+{
+ return label_;
+}
+-(void) setLabel:(CCNode<CCLabelProtocol, CCRGBAProtocol>*) 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<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite
+{
+ return [self itemFromNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:nil target:nil selector:nil];
+}
++(id) itemFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite target:(id)target selector:(SEL)selector
+{
+ return [self itemFromNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:nil target:target selector:selector];
+}
++(id) itemFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite disabledSprite:(CCNode<CCRGBAProtocol>*)disabledSprite target:(id)target selector:(SEL)selector
+{
+ return [[[self alloc] initFromNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:disabledSprite target:target selector:selector] autorelease];
+}
+-(id) initFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite disabledSprite:(CCNode<CCRGBAProtocol>*)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<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite block:(void(^)(id sender))block {
+ return [self itemFromNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:nil block:block];
+}
+
++(id) itemFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite disabledSprite:(CCNode<CCRGBAProtocol>*)disabledSprite block:(void(^)(id sender))block {
+ return [[[self alloc] initFromNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:disabledSprite block:block] autorelease];
+}
+
+-(id) initFromNormalSprite:(CCNode<CCRGBAProtocol>*)normalSprite selectedSprite:(CCNode<CCRGBAProtocol>*)selectedSprite disabledSprite:(CCNode<CCRGBAProtocol>*)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 <CCRGBAProtocol>*)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 <CCRGBAProtocol>*)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 <CCRGBAProtocol>*)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<CCRGBAProtocol> *normalImage = [CCSprite spriteWithFile:normalI];
+ CCNode<CCRGBAProtocol> *selectedImage = nil;
+ CCNode<CCRGBAProtocol> *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<CCRGBAProtocol>* item in subItems_)
+ [item setOpacity:opacity];
+}
+
+- (void) setColor:(ccColor3B)color
+{
+ color_ = color;
+ for(CCMenuItem<CCRGBAProtocol>* item in subItems_)
+ [item setColor:color];
+}
+
+@end
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+#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 <CCTextureProtocol>
+{
+ 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <Availability.h>
+
+#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
--- /dev/null
+/*
+ * 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 <Availability.h>
+#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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <Availability.h>
+
+#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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <CCTextureProtocol>
+{
+ // 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
+
--- /dev/null
+/*
+ * 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
+
+
--- /dev/null
+/*
+ * 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 <Availability.h>
+#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
--- /dev/null
+/*
+ * 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 <Availability.h>
+#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
+
+
--- /dev/null
+/*
+ * 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
+
--- /dev/null
+/*
+ * 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; i<totalParticles; i++) {
+ // bottom-left vertex:
+ quads_[i].bl.texCoords.u = left;
+ quads_[i].bl.texCoords.v = bottom;
+ // bottom-right vertex:
+ quads_[i].br.texCoords.u = right;
+ quads_[i].br.texCoords.v = bottom;
+ // top-left vertex:
+ quads_[i].tl.texCoords.u = left;
+ quads_[i].tl.texCoords.v = top;
+ // top-right vertex:
+ quads_[i].tr.texCoords.u = right;
+ quads_[i].tr.texCoords.v = top;
+ }
+}
+
+-(void) setTexture:(CCTexture2D *)texture withRect:(CGRect)rect
+{
+ // Only update the texture if is different from the current one
+ if( [texture name] != [texture_ name] )
+ [super setTexture:texture];
+
+ [self initTexCoordsWithRect:rect];
+}
+
+-(void) setTexture:(CCTexture2D *)texture
+{
+ [self setTexture:texture withRect:CGRectMake(0,0,
+ [texture pixelsWide] / CC_CONTENT_SCALE_FACTOR(),
+ [texture pixelsHigh] / CC_CONTENT_SCALE_FACTOR() )];
+}
+
+-(void) setDisplayFrame:(CCSpriteFrame *)spriteFrame
+{
+
+ NSAssert( CGPointEqualToPoint( spriteFrame.offsetInPixels , CGPointZero ), @"QuadParticle only supports SpriteFrames with no offsets");
+
+ // update texture before updating texture rect
+ if ( spriteFrame.texture.name != texture_.name )
+ [self setTexture: spriteFrame.texture];
+}
+
+-(void) initIndices
+{
+ for( NSUInteger i=0;i< totalParticles;i++) {
+ const int i6 = i*6;
+ const int i4 = i*4;
+ indices_[i6+0] = (GLushort) i4+0;
+ indices_[i6+1] = (GLushort) i4+1;
+ indices_[i6+2] = (GLushort) i4+2;
+
+ indices_[i6+5] = (GLushort) i4+1;
+ indices_[i6+4] = (GLushort) i4+2;
+ indices_[i6+3] = (GLushort) i4+3;
+ }
+}
+
+-(void) updateQuadWithParticle:(tCCParticle*)p newPosition:(CGPoint)newPos
+{
+ // colors
+ ccV2F_C4F_T2F_Quad *quad = &(quads_[particleIdx]);
+ quad->bl.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
+
+
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+#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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <NSObject>
+/** 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 <NSObject>
+/** 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 <CCBlendProtocol>
+/** 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 <NSObject>
+/** 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 <NSObject>
+/** 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
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+#import "CCNode.h"
+#import "CCSprite.h"
+#import "Support/OpenGL_Internal.h"
+
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#import <UIKit/UIKit.h>
+#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
+
+
--- /dev/null
+/*
+ * 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 <Availability.h>
+#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 <ty; y++) {
+ for(x = 0; x <tx * 4; x++) {
+ pixels[((ty - 1 - y) * tx * 4 + x)] = buffer[(y * 4 * tx + x)];
+ }
+ }
+
+ NSData* data;
+
+ if (format == kCCImageFormatRawData)
+ {
+ free(buffer);
+ //data frees buffer when it is deallocated
+ data = [NSData dataWithBytesNoCopy:pixels length:myDataLength];
+
+ } else {
+
+ /*
+ CGImageCreate(size_t width, size_t height,
+ size_t bitsPerComponent, size_t bitsPerPixel, size_t bytesPerRow,
+ CGColorSpaceRef space, CGBitmapInfo bitmapInfo, CGDataProviderRef provider,
+ const CGFloat decode[], bool shouldInterpolate,
+ CGColorRenderingIntent intent)
+ */
+ // make data provider with data.
+ CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault;
+ CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, myDataLength, NULL);
+ CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
+ CGImageRef iref = CGImageCreate(tx, ty,
+ bitsPerComponent, bitsPerPixel, bytesPerRow,
+ colorSpaceRef, bitmapInfo, provider,
+ NULL, false,
+ kCGRenderingIntentDefault);
+
+ UIImage* image = [[UIImage alloc] initWithCGImage:iref];
+
+ CGImageRelease(iref);
+ CGColorSpaceRelease(colorSpaceRef);
+ CGDataProviderRelease(provider);
+
+
+
+ if (format == kCCImageFormatPNG)
+ data = UIImagePNGRepresentation(image);
+ else
+ data = UIImageJPEGRepresentation(image, 1.0f);
+
+ [image release];
+
+ free(pixels);
+ free(buffer);
+ }
+
+ return data;
+}
+
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
+@end
--- /dev/null
+/*
+ * 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 "CCNode.h"
+#import "CCTexture2D.h"
+#import "CCProtocols.h"
+#import "Platforms/CCGL.h"
+
+/**
+ * A CCRibbon is a dynamically generated list of polygons drawn as a single or series
+ * of triangle strips. The primary use of CCRibbon is as the drawing class of Motion Streak,
+ * but it is quite useful on it's own. When manually drawing a ribbon, you can call addPointAt
+ * and pass in the parameters for the next location in the ribbon. The system will automatically
+ * generate new polygons, texture them accourding to your texture width, etc, etc.
+ *
+ * CCRibbon data is stored in a CCRibbonSegment class. This class statically allocates enough verticies and
+ * texture coordinates for 50 locations (100 verts or 48 triangles). The ribbon class will allocate
+ * new segments when they are needed, and reuse old ones if available. The idea is to avoid constantly
+ * allocating new memory and prefer a more static method. However, since there is no way to determine
+ * the maximum size of some ribbons (motion streaks), a truely static allocation is not possible.
+ *
+ * @since v0.8.1
+ */
+@interface CCRibbon : CCNode <CCTextureProtocol>
+{
+ NSMutableArray* segments_;
+ NSMutableArray* deletedSegments_;
+
+ CGPoint lastPoint1_;
+ CGPoint lastPoint2_;
+ CGPoint lastLocation_;
+ int vertCount_;
+ float texVPos_;
+ float curTime_;
+ float fadeTime_;
+ float delta_;
+ float lastWidth_;
+ float lastSign_;
+ BOOL pastFirstPoint_;
+
+ // Texture used
+ CCTexture2D* texture_;
+
+ // texture length
+ float textureLength_;
+
+ // RGBA protocol
+ ccColor4B color_;
+
+ // blend func
+ ccBlendFunc blendFunc_;
+}
+
+/** Texture used by the ribbon. Conforms to CCTextureProtocol protocol */
+@property (nonatomic,readwrite,retain) CCTexture2D* texture;
+
+/** Texture lengths in pixels */
+@property (nonatomic,readwrite) float textureLength;
+
+/** GL blendind function */
+@property (nonatomic,readwrite,assign) ccBlendFunc blendFunc;
+
+/** color used by the Ribbon (RGBA) */
+@property (nonatomic,readwrite) ccColor4B color;
+
+/** creates the ribbon */
++(id)ribbonWithWidth:(float)w image:(NSString*)path length:(float)l color:(ccColor4B)color fade:(float)fade;
+/** init the ribbon */
+-(id)initWithWidth:(float)w image:(NSString*)path length:(float)l color:(ccColor4B)color fade:(float)fade;
+/** add a point to the ribbon */
+-(void)addPointAt:(CGPoint)location width:(float)w;
+/** polling function */
+-(void)update:(ccTime)delta;
+/** determine side of line */
+-(float)sideOfLine:(CGPoint)p l1:(CGPoint)l1 l2:(CGPoint)l2;
+
+@end
+
+/** object to hold ribbon segment data */
+@interface CCRibbonSegment : NSObject
+{
+@public
+ GLfloat verts[50*6];
+ GLfloat coords[50*4];
+ GLubyte colors[50*8];
+ float creationTime[50];
+ BOOL finished;
+ uint end;
+ uint begin;
+}
+-(id)init;
+-(void)reset;
+-(void)draw:(float)curTime fadeTime:(float)fadeTime color:(ccColor4B)color;
+@end
--- /dev/null
+/*
+ * 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.
+ */
+
+/*
+ * A ribbon is a dynamically generated list of polygons drawn as a single or series
+ * of triangle strips. The primary use of Ribbon is as the drawing class of Motion Streak,
+ * but it is quite useful on it's own. When manually drawing a ribbon, you can call addPointAt
+ * and pass in the parameters for the next location in the ribbon. The system will automatically
+ * generate new polygons, texture them accourding to your texture width, etc, etc.
+ *
+ * Ribbon data is stored in a RibbonSegment class. This class statically allocates enough verticies and
+ * texture coordinates for 50 locations (100 verts or 48 triangles). The ribbon class will allocate
+ * new segments when they are needed, and reuse old ones if available. The idea is to avoid constantly
+ * allocating new memory and prefer a more static method. However, since there is no way to determine
+ * the maximum size of some ribbons (motion streaks), a truely static allocation is not possible.
+ *
+ */
+
+
+#import "CCRibbon.h"
+#import "CCTextureCache.h"
+#import "Support/CGPointExtension.h"
+#import "ccMacros.h"
+
+//
+// Ribbon
+//
+@implementation CCRibbon
+@synthesize blendFunc=blendFunc_;
+@synthesize color=color_;
+@synthesize textureLength = textureLength_;
+
++(id)ribbonWithWidth:(float)w image:(NSString*)path length:(float)l color:(ccColor4B)color fade:(float)fade
+{
+ self = [[[self alloc] initWithWidth:w image:path length:l color:color fade:fade] autorelease];
+ return self;
+}
+
+-(id)initWithWidth:(float)w image:(NSString*)path length:(float)l color:(ccColor4B)color fade:(float)fade
+{
+ self = [super init];
+ if (self)
+ {
+
+ segments_ = [[NSMutableArray alloc] init];
+ deletedSegments_ = [[NSMutableArray alloc] init];
+
+ /* 1 initial segment */
+ CCRibbonSegment* seg = [[CCRibbonSegment alloc] init];
+ [segments_ addObject:seg];
+ [seg release];
+
+ textureLength_ = l;
+
+ color_ = color;
+ fadeTime_ = fade;
+ lastLocation_ = CGPointZero;
+ lastWidth_ = w/2;
+ texVPos_ = 0.0f;
+
+ curTime_ = 0;
+ pastFirstPoint_ = NO;
+
+ /* XXX:
+ Ribbon, by default uses this blend function, which might not be correct
+ if you are using premultiplied alpha images,
+ but 99% you might want to use this blending function regarding of the texture
+ */
+ blendFunc_.src = GL_SRC_ALPHA;
+ blendFunc_.dst = GL_ONE_MINUS_SRC_ALPHA;
+
+ self.texture = [[CCTextureCache sharedTextureCache] addImage:path];
+
+ /* default texture parameter */
+ ccTexParams params = { GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT };
+ [texture_ setTexParameters:¶ms];
+ }
+ return self;
+}
+
+-(void)dealloc
+{
+ [segments_ release];
+ [deletedSegments_ release];
+ [texture_ release];
+ [super dealloc];
+}
+
+// rotates a point around 0, 0
+-(CGPoint)rotatePoint:(CGPoint)vec rotation:(float)a
+{
+ float xtemp = (vec.x * cosf(a)) - (vec.y * sinf(a));
+ vec.y = (vec.x * sinf(a)) + (vec.y * cosf(a));
+ vec.x = xtemp;
+ return vec;
+}
+
+-(void)update:(ccTime)delta
+{
+ curTime_+= delta;
+ delta_ = delta;
+}
+
+-(float)sideOfLine:(CGPoint)p l1:(CGPoint)l1 l2:(CGPoint)l2
+{
+ CGPoint vp = ccpPerp(ccpSub(l1, l2));
+ CGPoint vx = ccpSub(p, l1);
+ return ccpDot(vx, vp);
+}
+
+// adds a new segment to the ribbon
+-(void)addPointAt:(CGPoint)location width:(float)w
+{
+ location.x *= CC_CONTENT_SCALE_FACTOR();
+ location.y *= CC_CONTENT_SCALE_FACTOR();
+
+ w = w*0.5f;
+ // if this is the first point added, cache it and return
+ if (!pastFirstPoint_)
+ {
+ lastWidth_ = w;
+ lastLocation_ = location;
+ pastFirstPoint_ = YES;
+ return;
+ }
+
+ CGPoint sub = ccpSub(lastLocation_, location);
+ float r = ccpToAngle(sub) + (float)M_PI_2;
+ CGPoint p1 = ccpAdd([self rotatePoint:ccp(-w, 0) rotation:r], location);
+ CGPoint p2 = ccpAdd([self rotatePoint:ccp(w, 0) rotation:r], location);
+ float len = sqrtf(powf(lastLocation_.x - location.x, 2) + powf(lastLocation_.y - location.y, 2));
+ float tend = texVPos_ + len/textureLength_;
+ CCRibbonSegment* seg;
+ // grab last segment
+ seg = [segments_ lastObject];
+ // lets kill old segments
+ for (CCRibbonSegment* seg2 in segments_)
+ {
+ if (seg2 != seg && seg2->finished)
+ {
+ [deletedSegments_ addObject:seg2];
+ }
+ }
+ [segments_ removeObjectsInArray:deletedSegments_];
+ // is the segment full?
+ if (seg->end >= 50)
+ [segments_ removeObjectsInArray:deletedSegments_];
+ // grab last segment and append to it if it's not full
+ seg = [segments_ lastObject];
+ // is the segment full?
+ if (seg->end >= 50)
+ {
+ CCRibbonSegment* newSeg;
+ // grab it from the cache if we can
+ if ([deletedSegments_ count] > 0)
+ {
+ newSeg = [deletedSegments_ objectAtIndex:0];
+ [newSeg retain]; // will be released later
+ [deletedSegments_ removeObject:newSeg];
+ [newSeg reset];
+ }
+ else
+ {
+ newSeg = [[CCRibbonSegment alloc] init]; // will be released later
+ }
+
+ newSeg->creationTime[0] = seg->creationTime[seg->end - 1];
+ int v = (seg->end-1)*6;
+ int c = (seg->end-1)*4;
+ newSeg->verts[0] = seg->verts[v];
+ newSeg->verts[1] = seg->verts[v+1];
+ newSeg->verts[2] = seg->verts[v+2];
+ newSeg->verts[3] = seg->verts[v+3];
+ newSeg->verts[4] = seg->verts[v+4];
+ newSeg->verts[5] = seg->verts[v+5];
+
+ newSeg->coords[0] = seg->coords[c];
+ newSeg->coords[1] = seg->coords[c+1];
+ newSeg->coords[2] = seg->coords[c+2];
+ newSeg->coords[3] = seg->coords[c+3];
+ newSeg->end++;
+ seg = newSeg;
+ [segments_ addObject:seg];
+ [newSeg release]; // it was retained before
+
+ }
+ if (seg->end == 0)
+ {
+ // first edge has to get rotation from the first real polygon
+ CGPoint lp1 = ccpAdd([self rotatePoint:ccp(-lastWidth_, 0) rotation:r], lastLocation_);
+ CGPoint lp2 = ccpAdd([self rotatePoint:ccp(+lastWidth_, 0) rotation:r], lastLocation_);
+ seg->creationTime[0] = curTime_ - delta_;
+ seg->verts[0] = lp1.x;
+ seg->verts[1] = lp1.y;
+ seg->verts[2] = 0.0f;
+ seg->verts[3] = lp2.x;
+ seg->verts[4] = lp2.y;
+ seg->verts[5] = 0.0f;
+ seg->coords[0] = 0.0f;
+ seg->coords[1] = texVPos_;
+ seg->coords[2] = 1.0f;
+ seg->coords[3] = texVPos_;
+ seg->end++;
+ }
+
+ int v = seg->end*6;
+ int c = seg->end*4;
+ // add new vertex
+ seg->creationTime[seg->end] = curTime_;
+ seg->verts[v] = p1.x;
+ seg->verts[v+1] = p1.y;
+ seg->verts[v+2] = 0.0f;
+ seg->verts[v+3] = p2.x;
+ seg->verts[v+4] = p2.y;
+ seg->verts[v+5] = 0.0f;
+
+
+ seg->coords[c] = 0.0f;
+ seg->coords[c+1] = tend;
+ seg->coords[c+2] = 1.0f;
+ seg->coords[c+3] = tend;
+
+ texVPos_ = tend;
+ lastLocation_ = location;
+ lastPoint1_ = p1;
+ lastPoint2_ = p2;
+ lastWidth_ = w;
+ seg->end++;
+}
+
+-(void) draw
+{
+ if ([segments_ count] > 0)
+ {
+ // 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);
+
+ glBindTexture(GL_TEXTURE_2D, [texture_ name]);
+
+ BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST;
+ if( newBlend )
+ glBlendFunc( blendFunc_.src, blendFunc_.dst );
+
+ for (CCRibbonSegment* seg in segments_)
+ [seg draw:curTime_ fadeTime:fadeTime_ color:color_];
+
+ if( newBlend )
+ glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
+
+ // restore default GL state
+ glEnableClientState( GL_COLOR_ARRAY );
+ }
+}
+
+#pragma mark Ribbon - CocosNodeTexture protocol
+-(void) setTexture:(CCTexture2D*) texture
+{
+ [texture_ release];
+ texture_ = [texture retain];
+ [self setContentSizeInPixels: texture.contentSizeInPixels];
+ /* XXX Don't update blending function in Ribbons */
+}
+
+-(CCTexture2D*) texture
+{
+ return texture_;
+}
+
+@end
+
+
+#pragma mark -
+#pragma mark RibbonSegment
+
+@implementation CCRibbonSegment
+
+-(id)init
+{
+ self = [super init];
+ if (self)
+ {
+ [self reset];
+ }
+ return self;
+}
+
+- (NSString*) description
+{
+ return [NSString stringWithFormat:@"<%@ = %08X | end = %i, begin = %i>", [self class], self, end, begin];
+}
+
+- (void) dealloc
+{
+ CCLOGINFO(@"cocos2d: deallocing %@", self);
+ [super dealloc];
+}
+
+-(void)reset
+{
+ end = 0;
+ begin = 0;
+ finished = NO;
+}
+
+-(void)draw:(float)curTime fadeTime:(float)fadeTime color:(ccColor4B)color
+{
+ GLubyte r = color.r;
+ GLubyte g = color.g;
+ GLubyte b = color.b;
+ GLubyte a = color.a;
+
+ if (begin < 50)
+ {
+ // the motion streak class will call update and cause time to change, thus, if curTime_ != 0
+ // we have to generate alpha for the ribbon each frame.
+ if (curTime == 0)
+ {
+ // no alpha over time, so just set the color
+ glColor4ub(r,g,b,a);
+ }
+ else
+ {
+ // generate alpha/color for each point
+ glEnableClientState(GL_COLOR_ARRAY);
+ uint i = begin;
+ for (; i < end; ++i)
+ {
+ int idx = i*8;
+ colors[idx] = r;
+ colors[idx+1] = g;
+ colors[idx+2] = b;
+ colors[idx+4] = r;
+ colors[idx+5] = g;
+ colors[idx+6] = b;
+ float alive = ((curTime - creationTime[i]) / fadeTime);
+ if (alive > 1)
+ {
+ begin++;
+ colors[idx+3] = 0;
+ colors[idx+7] = 0;
+ }
+ else
+ {
+ colors[idx+3] = (GLubyte)(255.f - (alive * 255.f));
+ colors[idx+7] = colors[idx+3];
+ }
+ }
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, &colors[begin*8]);
+ }
+ glVertexPointer(3, GL_FLOAT, 0, &verts[begin*6]);
+ glTexCoordPointer(2, GL_FLOAT, 0, &coords[begin*4]);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, (end - begin) * 2);
+ }
+ else
+ finished = YES;
+}
+@end
+
--- /dev/null
+/*
+ * 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"
+
+/** CCScene is a subclass of CCNode that is used only as an abstract concept.
+
+ CCScene an CCNode are almost identical with the difference that CCScene has it's
+ anchor point (by default) at the center of the screen.
+
+ For the moment CCScene has no other logic than that, but in future releases it might have
+ additional logic.
+
+ It is a good practice to use and CCScene as the parent of all your nodes.
+*/
+@interface CCScene : CCNode
+{
+}
+@end
--- /dev/null
+/*
+ * 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 "CCScene.h"
+#import "Support/CGPointExtension.h"
+#import "CCDirector.h"
+
+
+@implementation CCScene
+-(id) init
+{
+ if( (self=[super init]) ) {
+ CGSize s = [[CCDirector sharedDirector] winSize];
+ self.isRelativeAnchorPoint = NO;
+ anchorPoint_ = ccp(0.5f, 0.5f);
+ [self setContentSize:s];
+ }
+
+ return self;
+}
+@end
--- /dev/null
+/*
+ * 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 "Support/uthash.h"
+#import "ccTypes.h"
+
+typedef void (*TICK_IMP)(id, SEL, ccTime);
+
+//
+// CCTimer
+//
+/** Light weight timer */
+@interface CCTimer : NSObject
+{
+ id target;
+ TICK_IMP impMethod;
+
+ ccTime elapsed;
+
+@public // optimization
+ ccTime interval;
+ SEL selector;
+}
+
+/** interval in seconds */
+@property (nonatomic,readwrite,assign) ccTime interval;
+
+/** Allocates a timer with a target and a selector.
+*/
++(id) timerWithTarget:(id) t selector:(SEL)s;
+
+/** Allocates a timer with a target, a selector and an interval in seconds.
+*/
++(id) timerWithTarget:(id) t selector:(SEL)s interval:(ccTime)seconds;
+
+/** Initializes a timer with a target and a selector.
+*/
+ -(id) initWithTarget:(id) t selector:(SEL)s;
+
+/** Initializes a timer with a target, a selector and an interval in seconds.
+*/
+-(id) initWithTarget:(id) t selector:(SEL)s interval:(ccTime)seconds;
+
+
+/** triggers the timer */
+-(void) update: (ccTime) dt;
+@end
+
+
+
+//
+// CCScheduler
+//
+/** Scheduler is responsible of triggering the scheduled callbacks.
+ You should not use NSTimer. Instead use this class.
+
+ There are 2 different types of callbacks (selectors):
+
+ - update selector: the 'update' selector will be called every frame. You can customize the priority.
+ - custom selector: A custom selector will be called every frame, or with a custom interval of time
+
+ The 'custom selectors' should be avoided when possible. It is faster, and consumes less memory to use the 'update selector'.
+
+*/
+
+struct _listEntry;
+struct _hashSelectorEntry;
+struct _hashUpdateEntry;
+
+@interface CCScheduler : NSObject
+{
+ ccTime timeScale_;
+
+ //
+ // "updates with priority" stuff
+ //
+ struct _listEntry *updatesNeg; // list of priority < 0
+ struct _listEntry *updates0; // list priority == 0
+ struct _listEntry *updatesPos; // list priority > 0
+ struct _hashUpdateEntry *hashForUpdates; // hash used to fetch quickly the list entries for pause,delete,etc.
+
+ // Used for "selectors with interval"
+ struct _hashSelectorEntry *hashForSelectors;
+ struct _hashSelectorEntry *currentTarget;
+ BOOL currentTargetSalvaged;
+
+ // Optimization
+ TICK_IMP impMethod;
+ SEL updateSelector;
+}
+
+/** Modifies the time of all scheduled callbacks.
+ You can use this property to create a 'slow motion' or 'fast fordward' effect.
+ Default is 1.0. To create a 'slow motion' effect, use values below 1.0.
+ To create a 'fast fordward' effect, use values higher than 1.0.
+ @since v0.8
+ @warning It will affect EVERY scheduled selector / action.
+ */
+@property (nonatomic,readwrite) ccTime timeScale;
+
+/** returns a shared instance of the Scheduler */
++(CCScheduler *)sharedScheduler;
+
+/** purges the shared scheduler. It releases the retained instance.
+ @since v0.99.0
+ */
++(void)purgeSharedScheduler;
+
+/** 'tick' the scheduler.
+ You should NEVER call this method, unless you know what you are doing.
+ */
+-(void) tick:(ccTime)dt;
+
+/** The scheduled method will be called every 'interval' seconds.
+ If paused is YES, then it won't be called until it is resumed.
+ If 'interval' is 0, it will be called every frame, but if so, it recommened to use 'scheduleUpdateForTarget:' instead.
+ If the selector is already scheduled, then only the interval parameter will be updated without re-scheduling it again.
+
+ @since v0.99.3
+ */
+-(void) scheduleSelector:(SEL)selector forTarget:(id)target interval:(ccTime)interval paused:(BOOL)paused;
+
+/** Schedules the 'update' selector for a given target with a given priority.
+ The 'update' selector will be called every frame.
+ The lower the priority, the earlier it is called.
+ @since v0.99.3
+ */
+-(void) scheduleUpdateForTarget:(id)target priority:(int)priority paused:(BOOL)paused;
+
+/** Unshedules a selector for a given target.
+ If you want to unschedule the "update", use unscheudleUpdateForTarget.
+ @since v0.99.3
+ */
+-(void) unscheduleSelector:(SEL)selector forTarget:(id)target;
+
+/** Unschedules the update selector for a given target
+ @since v0.99.3
+ */
+-(void) unscheduleUpdateForTarget:(id)target;
+
+/** Unschedules all selectors for a given target.
+ This also includes the "update" selector.
+ @since v0.99.3
+ */
+-(void) unscheduleAllSelectorsForTarget:(id)target;
+
+/** Unschedules all selectors from all targets.
+ You should NEVER call this method, unless you know what you are doing.
+
+ @since v0.99.3
+ */
+-(void) unscheduleAllSelectors;
+
+/** Pauses the target.
+ All scheduled selectors/update for a given target won't be 'ticked' until the target is resumed.
+ If the target is not present, nothing happens.
+ @since v0.99.3
+ */
+-(void) pauseTarget:(id)target;
+
+/** Resumes the target.
+ The 'target' will be unpaused, so all schedule selectors/update will be 'ticked' again.
+ If the target is not present, nothing happens.
+ @since v0.99.3
+ */
+-(void) resumeTarget:(id)target;
+
+
+/** schedules a Timer.
+ It will be fired in every frame.
+
+ @deprecated Use scheduleSelector:forTarget:interval:paused instead. Will be removed in 1.0
+ */
+-(void) scheduleTimer: (CCTimer*) timer DEPRECATED_ATTRIBUTE;
+
+/** unschedules an already scheduled Timer
+
+ @deprecated Use unscheduleSelector:forTarget. Will be removed in v1.0
+ */
+-(void) unscheduleTimer: (CCTimer*) timer DEPRECATED_ATTRIBUTE;
+
+/** unschedule all timers.
+ You should NEVER call this method, unless you know what you are doing.
+
+ @deprecated Use scheduleAllSelectors instead. Will be removed in 1.0
+ @since v0.8
+ */
+-(void) unscheduleAllTimers DEPRECATED_ATTRIBUTE;
+@end
--- /dev/null
+/*
+ * 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 imports
+#import "CCScheduler.h"
+#import "ccMacros.h"
+#import "Support/uthash.h"
+#import "Support/utlist.h"
+#import "Support/ccCArray.h"
+
+//
+// Data structures
+//
+#pragma mark -
+#pragma mark Data Structures
+
+// A list double-linked list used for "updates with priority"
+typedef struct _listEntry
+{
+ struct _listEntry *prev, *next;
+ TICK_IMP impMethod;
+ id target; // not retained (retained by hashUpdateEntry)
+ int priority;
+ BOOL paused;
+
+} tListEntry;
+
+typedef struct _hashUpdateEntry
+{
+ tListEntry **list; // Which list does it belong to ?
+ tListEntry *entry; // entry in the list
+ id target; // hash key (retained)
+ UT_hash_handle hh;
+} tHashUpdateEntry;
+
+// Hash Element used for "selectors with interval"
+typedef struct _hashSelectorEntry
+{
+ struct ccArray *timers;
+ id target; // hash key (retained)
+ unsigned int timerIndex;
+ CCTimer *currentTimer;
+ BOOL currentTimerSalvaged;
+ BOOL paused;
+ UT_hash_handle hh;
+} tHashSelectorEntry;
+
+
+
+//
+// CCTimer
+//
+#pragma mark -
+#pragma mark - CCTimer
+
+@implementation CCTimer
+
+@synthesize interval;
+
+-(id) init
+{
+ NSAssert(NO, @"CCTimer: Init not supported.");
+ [self release];
+ return nil;
+}
+
++(id) timerWithTarget:(id)t selector:(SEL)s
+{
+ return [[[self alloc] initWithTarget:t selector:s] autorelease];
+}
+
++(id) timerWithTarget:(id)t selector:(SEL)s interval:(ccTime) i
+{
+ return [[[self alloc] initWithTarget:t selector:s interval:i] autorelease];
+}
+
+-(id) initWithTarget:(id)t selector:(SEL)s
+{
+ return [self initWithTarget:t selector:s interval:0];
+}
+
+-(id) initWithTarget:(id)t selector:(SEL)s interval:(ccTime) seconds
+{
+ if( (self=[super init]) ) {
+#if COCOS2D_DEBUG
+ NSMethodSignature *sig = [t methodSignatureForSelector:s];
+ NSAssert(sig !=0 , @"Signature not found for selector - does it have the following form? -(void) name: (ccTime) dt");
+#endif
+
+ // target is not retained. It is retained in the hash structure
+ target = t;
+ selector = s;
+ impMethod = (TICK_IMP) [t methodForSelector:s];
+ elapsed = -1;
+ interval = seconds;
+ }
+ return self;
+}
+
+- (NSString*) description
+{
+ return [NSString stringWithFormat:@"<%@ = %08X | target:%@ selector:(%@)>", [self class], self, [target class], NSStringFromSelector(selector)];
+}
+
+-(void) dealloc
+{
+ CCLOGINFO(@"cocos2d: deallocing %@", self);
+ [super dealloc];
+}
+
+-(void) update: (ccTime) dt
+{
+ if( elapsed == - 1)
+ elapsed = 0;
+ else
+ elapsed += dt;
+ if( elapsed >= interval ) {
+ impMethod(target, selector, elapsed);
+ elapsed = 0;
+ }
+}
+@end
+
+//
+// CCScheduler
+//
+#pragma mark -
+#pragma mark - CCScheduler
+
+@interface CCScheduler (Private)
+-(void) removeHashElement:(tHashSelectorEntry*)element;
+@end
+
+@implementation CCScheduler
+
+static CCScheduler *sharedScheduler;
+
+@synthesize timeScale = timeScale_;
+
++ (CCScheduler *)sharedScheduler
+{
+ if (!sharedScheduler)
+ sharedScheduler = [[CCScheduler alloc] init];
+
+ return sharedScheduler;
+}
+
++(id)alloc
+{
+ NSAssert(sharedScheduler == nil, @"Attempted to allocate a second instance of a singleton.");
+ return [super alloc];
+}
+
++(void)purgeSharedScheduler
+{
+ [sharedScheduler release];
+ sharedScheduler = nil;
+}
+
+- (id) init
+{
+ if( (self=[super init]) ) {
+ timeScale_ = 1.0f;
+
+ // used to trigger CCTimer#update
+ updateSelector = @selector(update:);
+ impMethod = (TICK_IMP) [CCTimer instanceMethodForSelector:updateSelector];
+
+ // updates with priority
+ updates0 = NULL;
+ updatesNeg = NULL;
+ updatesPos = NULL;
+ hashForUpdates = NULL;
+
+ // selectors with interval
+ currentTarget = nil;
+ currentTargetSalvaged = NO;
+ hashForSelectors = nil;
+ }
+
+ return self;
+}
+
+- (void) dealloc
+{
+ CCLOG(@"cocos2d: deallocing %@", self);
+
+ [self unscheduleAllSelectors];
+
+ sharedScheduler = nil;
+
+ [super dealloc];
+}
+
+
+#pragma mark CCScheduler - Custom Selectors
+
+-(void) removeHashElement:(tHashSelectorEntry*)element
+{
+ ccArrayFree(element->timers);
+ [element->target release];
+ HASH_DEL(hashForSelectors, element);
+ free(element);
+}
+
+-(void) scheduleTimer: (CCTimer*) t
+{
+ NSAssert(NO, @"Not implemented. Use scheduleSelector:forTarget:");
+}
+
+-(void) unscheduleTimer: (CCTimer*) t
+{
+ NSAssert(NO, @"Not implemented. Use unscheduleSelector:forTarget:");
+}
+
+-(void) unscheduleAllTimers
+{
+ NSAssert(NO, @"Not implemented. Use unscheduleAllSelectors");
+}
+
+-(void) scheduleSelector:(SEL)selector forTarget:(id)target interval:(ccTime)interval paused:(BOOL)paused
+{
+ NSAssert( selector != nil, @"Argument selector must be non-nil");
+ NSAssert( target != nil, @"Argument target must be non-nil");
+
+ tHashSelectorEntry *element = NULL;
+ HASH_FIND_INT(hashForSelectors, &target, element);
+
+ if( ! element ) {
+ element = calloc( sizeof( *element ), 1 );
+ element->target = [target retain];
+ HASH_ADD_INT( hashForSelectors, target, element );
+
+ // Is this the 1st element ? Then set the pause level to all the selectors of this target
+ element->paused = paused;
+
+ } else
+ NSAssert( element->paused == paused, @"CCScheduler. Trying to schedule a selector with a pause value different than the target");
+
+
+ if( element->timers == nil )
+ element->timers = ccArrayNew(10);
+ else
+ {
+ for( unsigned int i=0; i< element->timers->num; i++ ) {
+ CCTimer *timer = element->timers->arr[i];
+ if( selector == timer->selector ) {
+ CCLOG(@"CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: %.2f to %.2f", timer->interval, interval);
+ timer->interval = interval;
+ return;
+ }
+ }
+ ccArrayEnsureExtraCapacity(element->timers, 1);
+ }
+
+ CCTimer *timer = [[CCTimer alloc] initWithTarget:target selector:selector interval:interval];
+ ccArrayAppendObject(element->timers, timer);
+ [timer release];
+}
+
+-(void) unscheduleSelector:(SEL)selector forTarget:(id)target
+{
+ // explicity handle nil arguments when removing an object
+ if( target==nil && selector==NULL)
+ return;
+
+ NSAssert( target != nil, @"Target MUST not be nil");
+ NSAssert( selector != NULL, @"Selector MUST not be NULL");
+
+ tHashSelectorEntry *element = NULL;
+ HASH_FIND_INT(hashForSelectors, &target, element);
+
+ if( element ) {
+
+ for( unsigned int i=0; i< element->timers->num; i++ ) {
+ CCTimer *timer = element->timers->arr[i];
+
+
+ if( selector == timer->selector ) {
+
+ if( timer == element->currentTimer && !element->currentTimerSalvaged ) {
+ [element->currentTimer retain];
+ element->currentTimerSalvaged = YES;
+ }
+
+ ccArrayRemoveObjectAtIndex(element->timers, i );
+
+ // update timerIndex in case we are in tick:, looping over the actions
+ if( element->timerIndex >= i )
+ element->timerIndex--;
+
+ if( element->timers->num == 0 ) {
+ if( currentTarget == element )
+ currentTargetSalvaged = YES;
+ else
+ [self removeHashElement: element];
+ }
+ return;
+ }
+ }
+ }
+
+ // Not Found
+// NSLog(@"CCScheduler#unscheduleSelector:forTarget: selector not found: %@", selString);
+
+}
+
+#pragma mark CCScheduler - Update Specific
+
+-(void) priorityIn:(tListEntry**)list target:(id)target priority:(int)priority paused:(BOOL)paused
+{
+ tListEntry *listElement = malloc( sizeof(*listElement) );
+
+ listElement->target = target;
+ listElement->priority = priority;
+ listElement->paused = paused;
+ listElement->impMethod = (TICK_IMP) [target methodForSelector:updateSelector];
+ listElement->next = listElement->prev = NULL;
+
+
+ // empty list ?
+ if( ! *list ) {
+ DL_APPEND( *list, listElement );
+
+ } else {
+ BOOL added = NO;
+
+ for( tListEntry *elem = *list; elem ; elem = elem->next ) {
+ if( priority < elem->priority ) {
+
+ if( elem == *list )
+ DL_PREPEND(*list, listElement);
+ else {
+ listElement->next = elem;
+ listElement->prev = elem->prev;
+
+ elem->prev->next = listElement;
+ elem->prev = listElement;
+ }
+
+ added = YES;
+ break;
+ }
+ }
+
+ // Not added? priority has the higher value. Append it.
+ if( !added )
+ DL_APPEND(*list, listElement);
+ }
+
+ // update hash entry for quicker access
+ tHashUpdateEntry *hashElement = calloc( sizeof(*hashElement), 1 );
+ hashElement->target = [target retain];
+ hashElement->list = list;
+ hashElement->entry = listElement;
+ HASH_ADD_INT(hashForUpdates, target, hashElement );
+}
+
+-(void) appendIn:(tListEntry**)list target:(id)target paused:(BOOL)paused
+{
+ tListEntry *listElement = malloc( sizeof( * listElement ) );
+
+ listElement->target = target;
+ listElement->paused = paused;
+ listElement->impMethod = (TICK_IMP) [target methodForSelector:updateSelector];
+
+ DL_APPEND(*list, listElement);
+
+
+ // update hash entry for quicker access
+ tHashUpdateEntry *hashElement = calloc( sizeof(*hashElement), 1 );
+ hashElement->target = [target retain];
+ hashElement->list = list;
+ hashElement->entry = listElement;
+ HASH_ADD_INT(hashForUpdates, target, hashElement );
+}
+
+-(void) scheduleUpdateForTarget:(id)target priority:(int)priority paused:(BOOL)paused
+{
+#if COCOS2D_DEBUG >= 1
+ tHashUpdateEntry * hashElement = NULL;
+ HASH_FIND_INT(hashForUpdates, &target, hashElement);
+ NSAssert( hashElement == NULL, @"CCScheduler: You can't re-schedule an 'update' selector'. Unschedule it first");
+#endif
+
+ // most of the updates are going to be 0, that's way there
+ // is an special list for updates with priority 0
+ if( priority == 0 )
+ [self appendIn:&updates0 target:target paused:paused];
+
+ else if( priority < 0 )
+ [self priorityIn:&updatesNeg target:target priority:priority paused:paused];
+
+ else // priority > 0
+ [self priorityIn:&updatesPos target:target priority:priority paused:paused];
+}
+
+-(void) unscheduleUpdateForTarget:(id)target
+{
+ if( target == nil )
+ return;
+
+ tHashUpdateEntry * element = NULL;
+ HASH_FIND_INT(hashForUpdates, &target, element);
+ if( element ) {
+
+ // list entry
+ DL_DELETE( *element->list, element->entry );
+ free( element->entry );
+
+ // hash entry
+ [element->target release];
+ HASH_DEL( hashForUpdates, element);
+ free(element);
+ }
+}
+
+#pragma mark CCScheduler - Common for Update selector & Custom Selectors
+
+-(void) unscheduleAllSelectors
+{
+ // Custom Selectors
+ for(tHashSelectorEntry *element=hashForSelectors; element != NULL; ) {
+ id target = element->target;
+ element=element->hh.next;
+ [self unscheduleAllSelectorsForTarget:target];
+ }
+
+ // Updates selectors
+ tListEntry *entry, *tmp;
+ DL_FOREACH_SAFE( updates0, entry, tmp ) {
+ [self unscheduleUpdateForTarget:entry->target];
+ }
+ DL_FOREACH_SAFE( updatesNeg, entry, tmp ) {
+ [self unscheduleUpdateForTarget:entry->target];
+ }
+ DL_FOREACH_SAFE( updatesPos, entry, tmp ) {
+ [self unscheduleUpdateForTarget:entry->target];
+ }
+
+}
+
+-(void) unscheduleAllSelectorsForTarget:(id)target
+{
+ // explicit nil handling
+ if( target == nil )
+ return;
+
+ // Custom Selectors
+ tHashSelectorEntry *element = NULL;
+ HASH_FIND_INT(hashForSelectors, &target, element);
+
+ if( element ) {
+ if( ccArrayContainsObject(element->timers, element->currentTimer) && !element->currentTimerSalvaged ) {
+ [element->currentTimer retain];
+ element->currentTimerSalvaged = YES;
+ }
+ ccArrayRemoveAllObjects(element->timers);
+ if( currentTarget == element )
+ currentTargetSalvaged = YES;
+ else
+ [self removeHashElement:element];
+ }
+
+ // Update Selector
+ [self unscheduleUpdateForTarget:target];
+}
+
+-(void) resumeTarget:(id)target
+{
+ NSAssert( target != nil, @"target must be non nil" );
+
+ // Custom Selectors
+ tHashSelectorEntry *element = NULL;
+ HASH_FIND_INT(hashForSelectors, &target, element);
+ if( element )
+ element->paused = NO;
+
+ // Update selector
+ tHashUpdateEntry * elementUpdate = NULL;
+ HASH_FIND_INT(hashForUpdates, &target, elementUpdate);
+ if( elementUpdate ) {
+ NSAssert( elementUpdate->entry != NULL, @"resumeTarget: unknown error");
+ elementUpdate->entry->paused = NO;
+ }
+}
+
+-(void) pauseTarget:(id)target
+{
+ NSAssert( target != nil, @"target must be non nil" );
+
+ // Custom selectors
+ tHashSelectorEntry *element = NULL;
+ HASH_FIND_INT(hashForSelectors, &target, element);
+ if( element )
+ element->paused = YES;
+
+ // Update selector
+ tHashUpdateEntry * elementUpdate = NULL;
+ HASH_FIND_INT(hashForUpdates, &target, elementUpdate);
+ if( elementUpdate ) {
+ NSAssert( elementUpdate->entry != NULL, @"pauseTarget: unknown error");
+ elementUpdate->entry->paused = YES;
+ }
+
+}
+
+#pragma mark CCScheduler - Main Loop
+
+-(void) tick: (ccTime) dt
+{
+ if( timeScale_ != 1.0f )
+ dt *= timeScale_;
+
+ // Iterate all over the Updates selectors
+ tListEntry *entry, *tmp;
+
+ // updates with priority < 0
+ DL_FOREACH_SAFE( updatesNeg, entry, tmp ) {
+ if( ! entry->paused )
+ entry->impMethod( entry->target, updateSelector, dt );
+ }
+
+ // updates with priority == 0
+ DL_FOREACH_SAFE( updates0, entry, tmp ) {
+ if( ! entry->paused )
+ entry->impMethod( entry->target, updateSelector, dt );
+ }
+
+ // updates with priority > 0
+ DL_FOREACH_SAFE( updatesPos, entry, tmp ) {
+ if( ! entry->paused )
+ entry->impMethod( entry->target, updateSelector, dt );
+ }
+
+ // Iterate all over the custome selectors
+ for(tHashSelectorEntry *elt=hashForSelectors; elt != NULL; ) {
+
+ currentTarget = elt;
+ currentTargetSalvaged = NO;
+
+ if( ! currentTarget->paused ) {
+
+ // The 'timers' ccArray may change while inside this loop.
+ for( elt->timerIndex = 0; elt->timerIndex < elt->timers->num; elt->timerIndex++) {
+ elt->currentTimer = elt->timers->arr[elt->timerIndex];
+ elt->currentTimerSalvaged = NO;
+
+ impMethod( elt->currentTimer, updateSelector, dt);
+
+ if( elt->currentTimerSalvaged ) {
+ // The currentTimer told the remove itself. To prevent the timer from
+ // accidentally deallocating itself before finishing its step, we retained
+ // it. Now that step is done, it's safe to release it.
+ [elt->currentTimer release];
+ }
+
+ elt->currentTimer = 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->timers->num == 0 )
+ [self removeHashElement:currentTarget];
+ }
+
+ currentTarget = nil;
+}
+
+@end
+
--- /dev/null
+/*
+ * 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 "CCProtocols.h"
+#import "CCTextureAtlas.h"
+
+@class CCSpriteBatchNode;
+@class CCSpriteSheet;
+@class CCSpriteSheetInternalOnly;
+@class CCSpriteFrame;
+@class CCAnimation;
+
+#pragma mark CCSprite
+
+enum {
+ /// CCSprite invalid index on the CCSpriteBatchode
+ CCSpriteIndexNotInitialized = 0xffffffff,
+};
+
+/**
+ Whether or not an CCSprite will rotate, scale or translate with it's parent.
+ Useful in health bars, when you want that the health bar translates with it's parent but you don't
+ want it to rotate with its parent.
+ @since v0.99.0
+ */
+typedef enum {
+ //! Translate with it's parent
+ CC_HONOR_PARENT_TRANSFORM_TRANSLATE = 1 << 0,
+ //! Rotate with it's parent
+ CC_HONOR_PARENT_TRANSFORM_ROTATE = 1 << 1,
+ //! Scale with it's parent
+ CC_HONOR_PARENT_TRANSFORM_SCALE = 1 << 2,
+
+ //! All possible transformation enabled. Default value.
+ CC_HONOR_PARENT_TRANSFORM_ALL = CC_HONOR_PARENT_TRANSFORM_TRANSLATE | CC_HONOR_PARENT_TRANSFORM_ROTATE | CC_HONOR_PARENT_TRANSFORM_SCALE,
+
+} ccHonorParentTransform;
+
+/** CCSprite is a 2d image ( http://en.wikipedia.org/wiki/Sprite_(computer_graphics) )
+ *
+ * CCSprite can be created with an image, or with a sub-rectangle of an image.
+ *
+ * If the parent or any of its ancestors is a CCSpriteBatchNode then the following features/limitations are valid
+ * - Features when the parent is a CCBatchNode:
+ * - MUCH faster rendering, specially if the CCSpriteBatchNode has many children. All the children will be drawn in a single batch.
+ *
+ * - Limitations
+ * - Camera is not supported yet (eg: CCOrbitCamera action doesn't work)
+ * - GridBase actions are not supported (eg: CCLens, CCRipple, CCTwirl)
+ * - The Alias/Antialias property belongs to CCSpriteBatchNode, so you can't individually set the aliased property.
+ * - The Blending function property belongs to CCSpriteBatchNode, so you can't individually set the blending function property.
+ * - Parallax scroller is not supported, but can be simulated with a "proxy" sprite.
+ *
+ * If the parent is an standard CCNode, then CCSprite behaves like any other CCNode:
+ * - It supports blending functions
+ * - It supports aliasing / antialiasing
+ * - But the rendering will be slower: 1 draw per children.
+ *
+ * The default anchorPoint in CCSprite is (0.5, 0.5).
+ */
+@interface CCSprite : CCNode <CCRGBAProtocol, CCTextureProtocol>
+{
+
+ //
+ // Data used when the sprite is rendered using a CCSpriteBatchNode
+ //
+ CCTextureAtlas *textureAtlas_; // Sprite Sheet texture atlas (weak reference)
+ NSUInteger atlasIndex_; // Absolute (real) Index on the batch node
+ CCSpriteBatchNode *batchNode_; // Used batch node (weak reference)
+ ccHonorParentTransform honorParentTransform_; // whether or not to transform according to its parent transformations
+ BOOL dirty_; // Sprite needs to be updated
+ BOOL recursiveDirty_; // Subchildren needs to be updated
+ BOOL hasChildren_; // optimization to check if it contain children
+
+ //
+ // Data used when the sprite is self-rendered
+ //
+ ccBlendFunc blendFunc_; // Needed for the texture protocol
+ CCTexture2D *texture_; // Texture used to render the sprite
+
+ //
+ // Shared data
+ //
+
+ // whether or not it's parent is a CCSpriteBatchNode
+ BOOL usesBatchNode_;
+
+ // texture
+ CGRect rect_;
+ CGRect rectInPixels_;
+ BOOL rectRotated_;
+
+ // Offset Position (used by Zwoptex)
+ CGPoint offsetPositionInPixels_;
+ CGPoint unflippedOffsetPositionFromCenter_;
+
+ // vertex coords, texture coords and color info
+ ccV3F_C4B_T2F_Quad quad_;
+
+ // opacity and RGB protocol
+ GLubyte opacity_;
+ ccColor3B color_;
+ ccColor3B colorUnmodified_;
+ BOOL opacityModifyRGB_;
+
+ // image is flipped
+ BOOL flipX_;
+ BOOL flipY_;
+
+
+ // Animations that belong to the sprite
+ NSMutableDictionary *animations_;
+
+@public
+ // used internally.
+ void (*updateMethod)(id, SEL);
+}
+
+/** whether or not the Sprite needs to be updated in the Atlas */
+@property (nonatomic,readwrite) BOOL dirty;
+/** the quad (tex coords, vertex coords and color) information */
+@property (nonatomic,readonly) ccV3F_C4B_T2F_Quad quad;
+/** The index used on the TextureATlas. Don't modify this value unless you know what you are doing */
+@property (nonatomic,readwrite) NSUInteger atlasIndex;
+/** returns the rect of the CCSprite in points */
+@property (nonatomic,readonly) CGRect textureRect;
+/** returns whether or not the texture rectangle is rotated */
+@property (nonatomic,readonly) BOOL textureRectRotated;
+/** whether or not the sprite is flipped horizontally.
+ It only flips the texture of the sprite, and not the texture of the sprite's children.
+ Also, flipping the texture doesn't alter the anchorPoint.
+ If you want to flip the anchorPoint too, and/or to flip the children too use:
+
+ sprite.scaleX *= -1;
+ */
+@property (nonatomic,readwrite) BOOL flipX;
+/** whether or not the sprite is flipped vertically.
+ It only flips the texture of the sprite, and not the texture of the sprite's children.
+ Also, flipping the texture doesn't alter the anchorPoint.
+ If you want to flip the anchorPoint too, and/or to flip the children too use:
+
+ sprite.scaleY *= -1;
+ */
+@property (nonatomic,readwrite) BOOL flipY;
+/** opacity: conforms to CCRGBAProtocol protocol */
+@property (nonatomic,readwrite) GLubyte opacity;
+/** RGB colors: conforms to CCRGBAProtocol protocol */
+@property (nonatomic,readwrite) ccColor3B color;
+/** whether or not the Sprite is rendered using a CCSpriteBatchNode */
+@property (nonatomic,readwrite) BOOL usesBatchNode;
+/** weak reference of the CCTextureAtlas used when the sprite is rendered using a CCSpriteBatchNode */
+@property (nonatomic,readwrite,assign) CCTextureAtlas *textureAtlas;
+/** weak reference to the CCSpriteBatchNode that renders the CCSprite */
+@property (nonatomic,readwrite,assign) CCSpriteBatchNode *batchNode;
+/** whether or not to transform according to its parent transfomrations.
+ Useful for health bars. eg: Don't rotate the health bar, even if the parent rotates.
+ IMPORTANT: Only valid if it is rendered using an CCSpriteBatchNode.
+ @since v0.99.0
+ */
+@property (nonatomic,readwrite) ccHonorParentTransform honorParentTransform;
+/** offset position in pixels of the sprite in points. Calculated automatically by editors like Zwoptex.
+ @since v0.99.0
+ */
+@property (nonatomic,readonly) CGPoint offsetPositionInPixels;
+/** conforms to CCTextureProtocol protocol */
+@property (nonatomic,readwrite) ccBlendFunc blendFunc;
+
+#pragma mark CCSprite - Initializers
+
+/** Creates an sprite with a texture.
+ The rect used will be the size of the texture.
+ The offset will be (0,0).
+ */
++(id) spriteWithTexture:(CCTexture2D*)texture;
+
+/** Creates an sprite with a texture and a rect.
+ The offset will be (0,0).
+ */
++(id) spriteWithTexture:(CCTexture2D*)texture rect:(CGRect)rect;
+
+/** Creates an sprite with an sprite frame.
+ */
++(id) spriteWithSpriteFrame:(CCSpriteFrame*)spriteFrame;
+
+/** Creates an sprite with an sprite frame name.
+ An CCSpriteFrame will be fetched from the CCSpriteFrameCache by name.
+ If the CCSpriteFrame doesn't exist it will raise an exception.
+ @since v0.9
+ */
++(id) spriteWithSpriteFrameName:(NSString*)spriteFrameName;
+
+/** Creates an sprite with an image filename.
+ The rect used will be the size of the image.
+ The offset will be (0,0).
+ */
++(id) spriteWithFile:(NSString*)filename;
+
+/** Creates an sprite with an image filename and a rect.
+ The offset will be (0,0).
+ */
++(id) spriteWithFile:(NSString*)filename rect:(CGRect)rect;
+
+/** Creates an sprite with a CGImageRef.
+ @deprecated Use spriteWithCGImage:key: instead. Will be removed in v1.0 final
+ */
++(id) spriteWithCGImage: (CGImageRef)image DEPRECATED_ATTRIBUTE;
+
+/** Creates an sprite with a CGImageRef and a key.
+ The key is used by the CCTextureCache to know if a texture was already created with this CGImage.
+ For example, a valid key is: @"sprite_frame_01".
+ If key is nil, then a new texture will be created each time by the CCTextureCache.
+ @since v0.99.0
+ */
++(id) spriteWithCGImage: (CGImageRef)image key:(NSString*)key;
+
+
+/** Creates an sprite with an CCBatchNode and a rect
+ */
++(id) spriteWithBatchNode:(CCSpriteBatchNode*)batchNode rect:(CGRect)rect;
+
++(id) spriteWithSpriteSheet:(CCSpriteSheetInternalOnly*)spritesheet rect:(CGRect)rect DEPRECATED_ATTRIBUTE;
+
+
+/** Initializes an sprite with a texture.
+ The rect used will be the size of the texture.
+ The offset will be (0,0).
+ */
+-(id) initWithTexture:(CCTexture2D*)texture;
+
+/** Initializes an sprite with a texture and a rect in points.
+ The offset will be (0,0).
+ */
+-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect;
+
+/** Initializes an sprite with an sprite frame.
+ */
+-(id) initWithSpriteFrame:(CCSpriteFrame*)spriteFrame;
+
+/** Initializes an sprite with an sprite frame name.
+ An CCSpriteFrame will be fetched from the CCSpriteFrameCache by name.
+ If the CCSpriteFrame doesn't exist it will raise an exception.
+ @since v0.9
+ */
+-(id) initWithSpriteFrameName:(NSString*)spriteFrameName;
+
+/** Initializes an sprite with an image filename.
+ The rect used will be the size of the image.
+ The offset will be (0,0).
+ */
+-(id) initWithFile:(NSString*)filename;
+
+/** Initializes an sprite with an image filename, and a rect.
+ The offset will be (0,0).
+ */
+-(id) initWithFile:(NSString*)filename rect:(CGRect)rect;
+
+/** Initializes an sprite with a CGImageRef
+ @deprecated Use spriteWithCGImage:key: instead. Will be removed in v1.0 final
+ */
+-(id) initWithCGImage: (CGImageRef)image DEPRECATED_ATTRIBUTE;
+
+/** Initializes an sprite with a CGImageRef and a key
+ The key is used by the CCTextureCache to know if a texture was already created with this CGImage.
+ For example, a valid key is: @"sprite_frame_01".
+ If key is nil, then a new texture will be created each time by the CCTextureCache.
+ @since v0.99.0
+ */
+-(id) initWithCGImage:(CGImageRef)image key:(NSString*)key;
+
+/** Initializes an sprite with an CCSpriteSheet and a rect in points
+ */
+-(id) initWithBatchNode:(CCSpriteBatchNode*)batchNode rect:(CGRect)rect;
+-(id) initWithSpriteSheet:(CCSpriteSheetInternalOnly*)spritesheet rect:(CGRect)rect DEPRECATED_ATTRIBUTE;
+
+/** Initializes an sprite with an CCSpriteSheet and a rect in pixels
+ @since v0.99.5
+ */
+-(id) initWithBatchNode:(CCSpriteBatchNode*)batchNode rectInPixels:(CGRect)rect;
+
+
+
+#pragma mark CCSprite - BatchNode methods
+
+/** updates the quad according the the rotation, position, scale values.
+ */
+-(void)updateTransform;
+
+/** updates the texture rect of the CCSprite in points.
+ */
+-(void) setTextureRect:(CGRect) rect;
+/** updates the texture rect, rectRotated and untrimmed size of the CCSprite in pixels
+ */
+-(void) setTextureRectInPixels:(CGRect)rect rotated:(BOOL)rotated untrimmedSize:(CGSize)size;
+
+/** tell the sprite to use self-render.
+ @since v0.99.0
+ */
+-(void) useSelfRender;
+
+/** tell the sprite to use sprite batch node
+ @since v0.99.0
+ */
+-(void) useBatchNode:(CCSpriteBatchNode*)batchNode;
+-(void) useSpriteSheetRender:(CCSpriteSheetInternalOnly*)spriteSheet DEPRECATED_ATTRIBUTE;
+
+
+#pragma mark CCSprite - Frames
+
+/** sets a new display frame to the CCSprite. */
+-(void) setDisplayFrame:(CCSpriteFrame*)newFrame;
+
+/** returns whether or not a CCSpriteFrame is being displayed */
+-(BOOL) isFrameDisplayed:(CCSpriteFrame*)frame;
+
+/** returns the current displayed frame. */
+-(CCSpriteFrame*) displayedFrame;
+
+#pragma mark CCSprite - Animation
+
+/** changes the display frame based on an animation and an index.
+ @deprecated Will be removed in 1.0.1. Use setDisplayFrameWithAnimationName:index instead
+ */
+-(void) setDisplayFrame: (NSString*) animationName index:(int) frameIndex DEPRECATED_ATTRIBUTE;
+
+/** changes the display frame with animation name and index.
+ The animation name will be get from the CCAnimationCache
+ @since v0.99.5
+ */
+-(void) setDisplayFrameWithAnimationName:(NSString*)animationName index:(int) frameIndex;
+
+/** returns an Animation given it's name.
+
+ @deprecated Use CCAnimationCache instead. Will be removed in 1.0.1
+ */
+-(CCAnimation*)animationByName: (NSString*) animationName DEPRECATED_ATTRIBUTE;
+
+/** adds an Animation to the Sprite.
+
+ @deprecated Use CCAnimationCache instead. Will be removed in 1.0.1
+ */
+-(void) addAnimation: (CCAnimation*) animation DEPRECATED_ATTRIBUTE;
+
+@end
--- /dev/null
+/*
+ * 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 <Availability.h>
+
+#import "ccConfig.h"
+#import "CCSpriteBatchNode.h"
+#import "CCSpriteSheet.h"
+#import "CCSprite.h"
+#import "CCSpriteFrame.h"
+#import "CCSpriteFrameCache.h"
+#import "CCAnimation.h"
+#import "CCAnimationCache.h"
+#import "CCTextureCache.h"
+#import "Support/CGPointExtension.h"
+#import "CCDrawingPrimitives.h"
+
+#pragma mark -
+#pragma mark CCSprite
+
+#if CC_SPRITEBATCHNODE_RENDER_SUBPIXEL
+#define RENDER_IN_SUBPIXEL
+#else
+#define RENDER_IN_SUBPIXEL(__A__) ( (int)(__A__))
+#endif
+
+// XXX: Optmization
+struct transformValues_ {
+ CGPoint pos; // position x and y
+ CGPoint scale; // scale x and y
+ float rotation;
+ CGPoint ap; // anchor point in pixels
+ BOOL visible;
+};
+
+@interface CCSprite (Private)
+-(void)updateTextureCoords:(CGRect)rect;
+-(void)updateBlendFunc;
+-(void) initAnimationDictionary;
+-(void) getTransformValues:(struct transformValues_*)tv; // optimization
+@end
+
+@implementation CCSprite
+
+@synthesize dirty = dirty_;
+@synthesize quad = quad_;
+@synthesize atlasIndex = atlasIndex_;
+@synthesize textureRect = rect_;
+@synthesize textureRectRotated = rectRotated_;
+@synthesize blendFunc = blendFunc_;
+@synthesize usesBatchNode = usesBatchNode_;
+@synthesize textureAtlas = textureAtlas_;
+@synthesize batchNode = batchNode_;
+@synthesize honorParentTransform = honorParentTransform_;
+@synthesize offsetPositionInPixels = offsetPositionInPixels_;
+
+
++(id)spriteWithTexture:(CCTexture2D*)texture
+{
+ return [[[self alloc] initWithTexture:texture] autorelease];
+}
+
++(id)spriteWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
+{
+ return [[[self alloc] initWithTexture:texture rect:rect] autorelease];
+}
+
++(id)spriteWithFile:(NSString*)filename
+{
+ return [[[self alloc] initWithFile:filename] autorelease];
+}
+
++(id)spriteWithFile:(NSString*)filename rect:(CGRect)rect
+{
+ return [[[self alloc] initWithFile:filename rect:rect] autorelease];
+}
+
++(id)spriteWithSpriteFrame:(CCSpriteFrame*)spriteFrame
+{
+ return [[[self alloc] initWithSpriteFrame:spriteFrame] autorelease];
+}
+
++(id)spriteWithSpriteFrameName:(NSString*)spriteFrameName
+{
+ CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:spriteFrameName];
+ return [self spriteWithSpriteFrame:frame];
+}
+
+// XXX: deprecated
++(id)spriteWithCGImage:(CGImageRef)image
+{
+ return [[[self alloc] initWithCGImage:image] autorelease];
+}
+
++(id)spriteWithCGImage:(CGImageRef)image key:(NSString*)key
+{
+ return [[[self alloc] initWithCGImage:image key:key] autorelease];
+}
+
++(id) spriteWithBatchNode:(CCSpriteBatchNode*)batchNode rect:(CGRect)rect
+{
+ return [[[self alloc] initWithBatchNode:batchNode rect:rect] autorelease];
+}
++(id) spriteWithSpriteSheet:(CCSpriteSheetInternalOnly*)spritesheet rect:(CGRect)rect // XXX DEPRECATED
+{
+ return [self spriteWithBatchNode:spritesheet rect:rect];
+}
+
+-(id) init
+{
+ if( (self=[super init]) ) {
+ dirty_ = recursiveDirty_ = NO;
+
+ // by default use "Self Render".
+ // if the sprite is added to an SpriteSheet, then it will automatically switch to "SpriteSheet Render"
+ [self useSelfRender];
+
+ opacityModifyRGB_ = YES;
+ opacity_ = 255;
+ color_ = colorUnmodified_ = ccWHITE;
+
+ blendFunc_.src = CC_BLEND_SRC;
+ blendFunc_.dst = CC_BLEND_DST;
+
+ // update texture (calls updateBlendFunc)
+ [self setTexture:nil];
+
+ // clean the Quad
+ bzero(&quad_, sizeof(quad_));
+
+ flipY_ = flipX_ = NO;
+
+ // lazy alloc
+ animations_ = nil;
+
+ // default transform anchor: center
+ anchorPoint_ = ccp(0.5f, 0.5f);
+
+ // zwoptex default values
+ offsetPositionInPixels_ = CGPointZero;
+
+ honorParentTransform_ = CC_HONOR_PARENT_TRANSFORM_ALL;
+ hasChildren_ = NO;
+
+ // Atlas: Color
+ ccColor4B tmpColor = {255,255,255,255};
+ quad_.bl.colors = tmpColor;
+ quad_.br.colors = tmpColor;
+ quad_.tl.colors = tmpColor;
+ quad_.tr.colors = tmpColor;
+
+ // Atlas: Vertex
+
+ // updated in "useSelfRender"
+
+ // Atlas: TexCoords
+ [self setTextureRectInPixels:CGRectZero rotated:NO untrimmedSize:CGSizeZero];
+
+ // updateMethod selector
+ updateMethod = (__typeof__(updateMethod))[self methodForSelector:@selector(updateTransform)];
+ }
+
+ return self;
+}
+
+-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
+{
+ NSAssert(texture!=nil, @"Invalid texture for sprite");
+ // IMPORTANT: [self init] and not [super init];
+ if( (self = [self init]) )
+ {
+ [self setTexture:texture];
+ [self setTextureRect:rect];
+ }
+ return self;
+}
+
+-(id) initWithTexture:(CCTexture2D*)texture
+{
+ NSAssert(texture!=nil, @"Invalid texture for sprite");
+
+ CGRect rect = CGRectZero;
+ rect.size = texture.contentSize;
+ return [self initWithTexture:texture rect:rect];
+}
+
+-(id) initWithFile:(NSString*)filename
+{
+ NSAssert(filename!=nil, @"Invalid filename for sprite");
+
+ CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage: filename];
+ if( texture ) {
+ CGRect rect = CGRectZero;
+ rect.size = texture.contentSize;
+ return [self initWithTexture:texture rect:rect];
+ }
+
+ [self release];
+ return nil;
+}
+
+-(id) initWithFile:(NSString*)filename rect:(CGRect)rect
+{
+ NSAssert(filename!=nil, @"Invalid filename for sprite");
+
+ CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage: filename];
+ if( texture )
+ return [self initWithTexture:texture rect:rect];
+
+ [self release];
+ return nil;
+}
+
+- (id) initWithSpriteFrame:(CCSpriteFrame*)spriteFrame
+{
+ NSAssert(spriteFrame!=nil, @"Invalid spriteFrame for sprite");
+
+ id ret = [self initWithTexture:spriteFrame.texture rect:spriteFrame.rect];
+ [self setDisplayFrame:spriteFrame];
+ return ret;
+}
+
+-(id)initWithSpriteFrameName:(NSString*)spriteFrameName
+{
+ NSAssert(spriteFrameName!=nil, @"Invalid spriteFrameName for sprite");
+
+ CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:spriteFrameName];
+ return [self initWithSpriteFrame:frame];
+}
+
+// XXX: deprecated
+- (id) initWithCGImage: (CGImageRef)image
+{
+ NSAssert(image!=nil, @"Invalid CGImageRef for sprite");
+
+ // XXX: possible bug. See issue #349. New API should be added
+ NSString *key = [NSString stringWithFormat:@"%08X",(unsigned long)image];
+ CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addCGImage:image forKey:key];
+
+ CGRect rect = CGRectZero;
+ rect.size = texture.contentSize;
+
+ return [self initWithTexture:texture rect:rect];
+}
+
+- (id) initWithCGImage:(CGImageRef)image key:(NSString*)key
+{
+ NSAssert(image!=nil, @"Invalid CGImageRef for sprite");
+
+ // XXX: possible bug. See issue #349. New API should be added
+ CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addCGImage:image forKey:key];
+
+ CGRect rect = CGRectZero;
+ rect.size = texture.contentSize;
+
+ return [self initWithTexture:texture rect:rect];
+}
+
+-(id) initWithBatchNode:(CCSpriteBatchNode*)batchNode rect:(CGRect)rect
+{
+ id ret = [self initWithTexture:batchNode.texture rect:rect];
+ [self useBatchNode:batchNode];
+
+ return ret;
+}
+
+-(id) initWithBatchNode:(CCSpriteBatchNode*)batchNode rectInPixels:(CGRect)rect
+{
+ id ret = [self initWithTexture:batchNode.texture];
+ [self setTextureRectInPixels:rect rotated:NO untrimmedSize:rect.size];
+ [self useBatchNode:batchNode];
+
+ return ret;
+}
+
+-(id) initWithSpriteSheet:(CCSpriteSheetInternalOnly*)spritesheet rect:(CGRect)rect // XXX DEPRECATED
+{
+ return [self initWithBatchNode:spritesheet rect:rect];
+}
+
+- (NSString*) description
+{
+ return [NSString stringWithFormat:@"<%@ = %08X | Rect = (%.2f,%.2f,%.2f,%.2f) | tag = %i | atlasIndex = %i>", [self class], self,
+ rect_.origin.x, rect_.origin.y, rect_.size.width, rect_.size.height,
+ tag_,
+ atlasIndex_
+ ];
+}
+
+- (void) dealloc
+{
+ [texture_ release];
+ [animations_ release];
+ [super dealloc];
+}
+
+-(void) useSelfRender
+{
+ atlasIndex_ = CCSpriteIndexNotInitialized;
+ usesBatchNode_ = NO;
+ textureAtlas_ = nil;
+ batchNode_ = nil;
+ dirty_ = recursiveDirty_ = NO;
+
+ float x1 = 0 + offsetPositionInPixels_.x;
+ float y1 = 0 + offsetPositionInPixels_.y;
+ float x2 = x1 + rectInPixels_.size.width;
+ float y2 = y1 + rectInPixels_.size.height;
+ quad_.bl.vertices = (ccVertex3F) { x1, y1, 0 };
+ quad_.br.vertices = (ccVertex3F) { x2, y1, 0 };
+ quad_.tl.vertices = (ccVertex3F) { x1, y2, 0 };
+ quad_.tr.vertices = (ccVertex3F) { x2, y2, 0 };
+}
+
+-(void) useBatchNode:(CCSpriteBatchNode*)batchNode
+{
+ usesBatchNode_ = YES;
+ textureAtlas_ = [batchNode textureAtlas]; // weak ref
+ batchNode_ = batchNode; // weak ref
+}
+-(void) useSpriteSheetRender:(CCSpriteSheetInternalOnly*)spriteSheet // XXX DEPRECATED
+{
+ [self useBatchNode:spriteSheet];
+}
+
+-(void) initAnimationDictionary
+{
+ animations_ = [[NSMutableDictionary alloc] initWithCapacity:2];
+}
+
+-(void)setTextureRect:(CGRect)rect
+{
+ CGRect rectInPixels = CC_RECT_POINTS_TO_PIXELS( rect );
+ [self setTextureRectInPixels:rectInPixels rotated:NO untrimmedSize:rectInPixels.size];
+}
+
+-(void)setTextureRectInPixels:(CGRect)rect rotated:(BOOL)rotated untrimmedSize:(CGSize)untrimmedSize
+{
+ rectInPixels_ = rect;
+ rect_ = CC_RECT_PIXELS_TO_POINTS( rect );
+ rectRotated_ = rotated;
+
+ [self setContentSizeInPixels:untrimmedSize];
+ [self updateTextureCoords:rectInPixels_];
+
+ CGPoint relativeOffsetInPixels = unflippedOffsetPositionFromCenter_;
+
+ // issue #732
+ if( flipX_ )
+ relativeOffsetInPixels.x = -relativeOffsetInPixels.x;
+ if( flipY_ )
+ relativeOffsetInPixels.y = -relativeOffsetInPixels.y;
+
+ offsetPositionInPixels_.x = relativeOffsetInPixels.x + (contentSizeInPixels_.width - rectInPixels_.size.width) / 2;
+ offsetPositionInPixels_.y = relativeOffsetInPixels.y + (contentSizeInPixels_.height - rectInPixels_.size.height) / 2;
+
+
+ // rendering using SpriteSheet
+ if( usesBatchNode_ ) {
+ // update dirty_, don't update recursiveDirty_
+ dirty_ = YES;
+ }
+
+ // self rendering
+ else
+ {
+ // Atlas: Vertex
+ float x1 = 0 + offsetPositionInPixels_.x;
+ float y1 = 0 + offsetPositionInPixels_.y;
+ float x2 = x1 + rectInPixels_.size.width;
+ float y2 = y1 + rectInPixels_.size.height;
+
+ // Don't update Z.
+ quad_.bl.vertices = (ccVertex3F) { x1, y1, 0 };
+ quad_.br.vertices = (ccVertex3F) { x2, y1, 0 };
+ quad_.tl.vertices = (ccVertex3F) { x1, y2, 0 };
+ quad_.tr.vertices = (ccVertex3F) { x2, y2, 0 };
+ }
+}
+
+-(void)updateTextureCoords:(CGRect)rect
+{
+ CCTexture2D *tex = (usesBatchNode_)?[textureAtlas_ texture]:texture_;
+ if(!tex)
+ return;
+
+ float atlasWidth = (float)tex.pixelsWide;
+ float atlasHeight = (float)tex.pixelsHigh;
+
+ float left,right,top,bottom;
+
+ if(rectRotated_){
+#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
+ left = (2*rect.origin.x+1)/(2*atlasWidth);
+ right = left+(rect.size.height*2-2)/(2*atlasWidth);
+ top = (2*rect.origin.y+1)/(2*atlasHeight);
+ bottom = top+(rect.size.width*2-2)/(2*atlasHeight);
+#else
+ left = rect.origin.x/atlasWidth;
+ right = left+(rect.size.height/atlasWidth);
+ top = rect.origin.y/atlasHeight;
+ bottom = top+(rect.size.width/atlasHeight);
+#endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
+
+ if( flipX_)
+ CC_SWAP(top,bottom);
+ if( flipY_)
+ CC_SWAP(left,right);
+
+ quad_.bl.texCoords.u = left;
+ quad_.bl.texCoords.v = top;
+ quad_.br.texCoords.u = left;
+ quad_.br.texCoords.v = bottom;
+ quad_.tl.texCoords.u = right;
+ quad_.tl.texCoords.v = top;
+ quad_.tr.texCoords.u = right;
+ quad_.tr.texCoords.v = bottom;
+ } else {
+#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
+ left = (2*rect.origin.x+1)/(2*atlasWidth);
+ right = left + (rect.size.width*2-2)/(2*atlasWidth);
+ top = (2*rect.origin.y+1)/(2*atlasHeight);
+ bottom = top + (rect.size.height*2-2)/(2*atlasHeight);
+#else
+ left = rect.origin.x/atlasWidth;
+ right = left + rect.size.width/atlasWidth;
+ top = rect.origin.y/atlasHeight;
+ bottom = top + rect.size.height/atlasHeight;
+#endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
+
+ if( flipX_)
+ CC_SWAP(left,right);
+ if( flipY_)
+ CC_SWAP(top,bottom);
+
+ quad_.bl.texCoords.u = left;
+ quad_.bl.texCoords.v = bottom;
+ quad_.br.texCoords.u = right;
+ quad_.br.texCoords.v = bottom;
+ quad_.tl.texCoords.u = left;
+ quad_.tl.texCoords.v = top;
+ quad_.tr.texCoords.u = right;
+ quad_.tr.texCoords.v = top;
+ }
+}
+
+-(void)updateTransform
+{
+ NSAssert( usesBatchNode_, @"updateTransform is only valid when CCSprite is being renderd using an CCSpriteBatchNode");
+
+ // optimization. Quick return if not dirty
+ if( ! dirty_ )
+ return;
+
+ CGAffineTransform matrix;
+
+ // Optimization: if it is not visible, then do nothing
+ if( ! visible_ ) {
+ quad_.br.vertices = quad_.tl.vertices = quad_.tr.vertices = quad_.bl.vertices = (ccVertex3F){0,0,0};
+ [textureAtlas_ updateQuad:&quad_ atIndex:atlasIndex_];
+ dirty_ = recursiveDirty_ = NO;
+ return ;
+ }
+
+
+ // Optimization: If parent is batchnode, or parent is nil
+ // build Affine transform manually
+ if( ! parent_ || parent_ == batchNode_ ) {
+
+ float radians = -CC_DEGREES_TO_RADIANS(rotation_);
+ float c = cosf(radians);
+ float s = sinf(radians);
+
+ matrix = CGAffineTransformMake( c * scaleX_, s * scaleX_,
+ -s * scaleY_, c * scaleY_,
+ positionInPixels_.x, positionInPixels_.y);
+ matrix = CGAffineTransformTranslate(matrix, -anchorPointInPixels_.x, -anchorPointInPixels_.y);
+
+
+ } else { // parent_ != batchNode_
+
+ // else do affine transformation according to the HonorParentTransform
+
+ matrix = CGAffineTransformIdentity;
+ ccHonorParentTransform prevHonor = CC_HONOR_PARENT_TRANSFORM_ALL;
+
+ for (CCNode *p = self ; p && p != batchNode_ ; p = p.parent) {
+
+ // Might happen. Issue #1053
+ NSAssert( [p isKindOfClass:[CCSprite class]], @"CCSprite should be a CCSprite subclass. Probably you initialized an sprite with a batchnode, but you didn't add it to the batch node." );
+
+ struct transformValues_ tv;
+ [(CCSprite*)p getTransformValues: &tv];
+
+ // If any of the parents are not visible, then don't draw this node
+ if( ! tv.visible ) {
+ quad_.br.vertices = quad_.tl.vertices = quad_.tr.vertices = quad_.bl.vertices = (ccVertex3F){0,0,0};
+ [textureAtlas_ updateQuad:&quad_ atIndex:atlasIndex_];
+ dirty_ = recursiveDirty_ = NO;
+ return;
+ }
+ CGAffineTransform newMatrix = CGAffineTransformIdentity;
+
+ // 2nd: Translate, Rotate, Scale
+ if( prevHonor & CC_HONOR_PARENT_TRANSFORM_TRANSLATE )
+ newMatrix = CGAffineTransformTranslate(newMatrix, tv.pos.x, tv.pos.y);
+ if( prevHonor & CC_HONOR_PARENT_TRANSFORM_ROTATE )
+ newMatrix = CGAffineTransformRotate(newMatrix, -CC_DEGREES_TO_RADIANS(tv.rotation));
+ if( prevHonor & CC_HONOR_PARENT_TRANSFORM_SCALE ) {
+ newMatrix = CGAffineTransformScale(newMatrix, tv.scale.x, tv.scale.y);
+ }
+
+ // 3rd: Translate anchor point
+ newMatrix = CGAffineTransformTranslate(newMatrix, -tv.ap.x, -tv.ap.y);
+
+ // 4th: Matrix multiplication
+ matrix = CGAffineTransformConcat( matrix, newMatrix);
+
+ prevHonor = [(CCSprite*)p honorParentTransform];
+ }
+ }
+
+
+ //
+ // calculate the Quad based on the Affine Matrix
+ //
+
+ CGSize size = rectInPixels_.size;
+
+ float x1 = offsetPositionInPixels_.x;
+ float y1 = offsetPositionInPixels_.y;
+
+ float x2 = x1 + size.width;
+ float y2 = y1 + size.height;
+ float x = matrix.tx;
+ float y = matrix.ty;
+
+ float cr = matrix.a;
+ float sr = matrix.b;
+ float cr2 = matrix.d;
+ float sr2 = -matrix.c;
+ float ax = x1 * cr - y1 * sr2 + x;
+ float ay = x1 * sr + y1 * cr2 + y;
+
+ float bx = x2 * cr - y1 * sr2 + x;
+ float by = x2 * sr + y1 * cr2 + y;
+
+ float cx = x2 * cr - y2 * sr2 + x;
+ float cy = x2 * sr + y2 * cr2 + y;
+
+ float dx = x1 * cr - y2 * sr2 + x;
+ float dy = x1 * sr + y2 * cr2 + y;
+
+ quad_.bl.vertices = (ccVertex3F) { RENDER_IN_SUBPIXEL(ax), RENDER_IN_SUBPIXEL(ay), vertexZ_ };
+ quad_.br.vertices = (ccVertex3F) { RENDER_IN_SUBPIXEL(bx), RENDER_IN_SUBPIXEL(by), vertexZ_ };
+ quad_.tl.vertices = (ccVertex3F) { RENDER_IN_SUBPIXEL(dx), RENDER_IN_SUBPIXEL(dy), vertexZ_ };
+ quad_.tr.vertices = (ccVertex3F) { RENDER_IN_SUBPIXEL(cx), RENDER_IN_SUBPIXEL(cy), vertexZ_ };
+
+ [textureAtlas_ updateQuad:&quad_ atIndex:atlasIndex_];
+ dirty_ = recursiveDirty_ = NO;
+}
+
+// XXX: Optimization: instead of calling 5 times the parent sprite to obtain: position, scale.x, scale.y, anchorpoint and rotation,
+// this fuction return the 5 values in 1 single call
+-(void) getTransformValues:(struct transformValues_*) tv
+{
+ tv->pos = positionInPixels_;
+ tv->scale.x = scaleX_;
+ tv->scale.y = scaleY_;
+ tv->rotation = rotation_;
+ tv->ap = anchorPointInPixels_;
+ tv->visible = visible_;
+}
+
+#pragma mark CCSprite - draw
+
+-(void) draw
+{
+ NSAssert(!usesBatchNode_, @"If CCSprite is being rendered by CCSpriteBatchNode, CCSprite#draw SHOULD NOT be called");
+
+ // 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: -
+
+ BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST;
+ if( newBlend )
+ glBlendFunc( blendFunc_.src, blendFunc_.dst );
+
+#define kQuadSize sizeof(quad_.bl)
+ glBindTexture(GL_TEXTURE_2D, [texture_ name]);
+
+ long offset = (long)&quad_;
+
+ // vertex
+ NSInteger diff = offsetof( ccV3F_C4B_T2F, vertices);
+ glVertexPointer(3, GL_FLOAT, kQuadSize, (void*) (offset + diff) );
+
+ // color
+ diff = offsetof( ccV3F_C4B_T2F, colors);
+ glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (void*)(offset + diff));
+
+ // tex coords
+ diff = offsetof( ccV3F_C4B_T2F, texCoords);
+ glTexCoordPointer(2, GL_FLOAT, kQuadSize, (void*)(offset + diff));
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ if( newBlend )
+ glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
+
+#if CC_SPRITE_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_TEXTURENODE_DEBUG_DRAW
+
+}
+
+#pragma mark CCSprite - CCNode overrides
+
+-(void) addChild:(CCSprite*)child z:(int)z tag:(int) aTag
+{
+ NSAssert( child != nil, @"Argument must be non-nil");
+
+ [super addChild:child z:z tag:aTag];
+
+ if( usesBatchNode_ ) {
+ NSAssert( [child isKindOfClass:[CCSprite class]], @"CCSprite only supports CCSprites as children when using CCSpriteBatchNode");
+ NSAssert( child.texture.name == textureAtlas_.texture.name, @"CCSprite is not using the same texture id");
+
+ NSUInteger index = [batchNode_ atlasIndexForChild:child atZ:z];
+ [batchNode_ insertChild:child inAtlasAtIndex:index];
+ }
+
+ hasChildren_ = YES;
+}
+
+-(void) reorderChild:(CCSprite*)child z:(int)z
+{
+ NSAssert( child != nil, @"Child must be non-nil");
+ NSAssert( [children_ containsObject:child], @"Child doesn't belong to Sprite" );
+
+ if( z == child.zOrder )
+ return;
+
+ if( usesBatchNode_ ) {
+ // XXX: Instead of removing/adding, it is more efficient to reorder manually
+ [child retain];
+ [self removeChild:child cleanup:NO];
+ [self addChild:child z:z];
+ [child release];
+ }
+
+ else
+ [super reorderChild:child z:z];
+}
+
+-(void)removeChild: (CCSprite *)sprite cleanup:(BOOL)doCleanup
+{
+ if( usesBatchNode_ )
+ [batchNode_ removeSpriteFromAtlas:sprite];
+
+ [super removeChild:sprite cleanup:doCleanup];
+
+ hasChildren_ = ( [children_ count] > 0 );
+}
+
+-(void)removeAllChildrenWithCleanup:(BOOL)doCleanup
+{
+ if( usesBatchNode_ ) {
+ CCSprite *child;
+ CCARRAY_FOREACH(children_, child)
+ [batchNode_ removeSpriteFromAtlas:child];
+ }
+
+ [super removeAllChildrenWithCleanup:doCleanup];
+
+ hasChildren_ = NO;
+}
+
+//
+// CCNode property overloads
+// used only when parent is CCSpriteBatchNode
+//
+#pragma mark CCSprite - property overloads
+
+
+-(void) setDirtyRecursively:(BOOL)b
+{
+ dirty_ = recursiveDirty_ = b;
+ // recursively set dirty
+ if( hasChildren_ ) {
+ CCSprite *child;
+ CCARRAY_FOREACH(children_, child)
+ [child setDirtyRecursively:YES];
+ }
+}
+
+// XXX HACK: optimization
+#define SET_DIRTY_RECURSIVELY() { \
+ if( usesBatchNode_ && ! recursiveDirty_ ) { \
+ dirty_ = recursiveDirty_ = YES; \
+ if( hasChildren_) \
+ [self setDirtyRecursively:YES]; \
+ } \
+ }
+
+-(void)setPosition:(CGPoint)pos
+{
+ [super setPosition:pos];
+ SET_DIRTY_RECURSIVELY();
+}
+
+-(void)setPositionInPixels:(CGPoint)pos
+{
+ [super setPositionInPixels:pos];
+ SET_DIRTY_RECURSIVELY();
+}
+
+-(void)setRotation:(float)rot
+{
+ [super setRotation:rot];
+ SET_DIRTY_RECURSIVELY();
+}
+
+-(void)setScaleX:(float) sx
+{
+ [super setScaleX:sx];
+ SET_DIRTY_RECURSIVELY();
+}
+
+-(void)setScaleY:(float) sy
+{
+ [super setScaleY:sy];
+ SET_DIRTY_RECURSIVELY();
+}
+
+-(void)setScale:(float) s
+{
+ [super setScale:s];
+ SET_DIRTY_RECURSIVELY();
+}
+
+-(void) setVertexZ:(float)z
+{
+ [super setVertexZ:z];
+ SET_DIRTY_RECURSIVELY();
+}
+
+-(void)setAnchorPoint:(CGPoint)anchor
+{
+ [super setAnchorPoint:anchor];
+ SET_DIRTY_RECURSIVELY();
+}
+
+-(void)setIsRelativeAnchorPoint:(BOOL)relative
+{
+ NSAssert( ! usesBatchNode_, @"relativeTransformAnchor is invalid in CCSprite");
+ [super setIsRelativeAnchorPoint:relative];
+}
+
+-(void)setVisible:(BOOL)v
+{
+ [super setVisible:v];
+ SET_DIRTY_RECURSIVELY();
+}
+
+-(void)setFlipX:(BOOL)b
+{
+ if( flipX_ != b ) {
+ flipX_ = b;
+ [self setTextureRectInPixels:rectInPixels_ rotated:rectRotated_ untrimmedSize:rectInPixels_.size];
+ }
+}
+-(BOOL) flipX
+{
+ return flipX_;
+}
+
+-(void) setFlipY:(BOOL)b
+{
+ if( flipY_ != b ) {
+ flipY_ = b;
+ [self setTextureRectInPixels:rectInPixels_ rotated:rectRotated_ untrimmedSize:rectInPixels_.size];
+ }
+}
+-(BOOL) flipY
+{
+ return flipY_;
+}
+
+//
+// RGBA protocol
+//
+#pragma mark CCSprite - RGBA protocol
+-(void) updateColor
+{
+ ccColor4B color4 = {color_.r, color_.g, color_.b, opacity_ };
+
+ quad_.bl.colors = color4;
+ quad_.br.colors = color4;
+ quad_.tl.colors = color4;
+ quad_.tr.colors = color4;
+
+ // renders using Sprite Manager
+ if( usesBatchNode_ ) {
+ if( atlasIndex_ != CCSpriteIndexNotInitialized)
+ [textureAtlas_ updateQuad:&quad_ atIndex:atlasIndex_];
+ else
+ // no need to set it recursively
+ // update dirty_, don't update recursiveDirty_
+ dirty_ = YES;
+ }
+ // self render
+ // do nothing
+}
+
+-(GLubyte) opacity
+{
+ return opacity_;
+}
+
+-(void) setOpacity:(GLubyte) anOpacity
+{
+ opacity_ = anOpacity;
+
+ // special opacity for premultiplied textures
+ if( opacityModifyRGB_ )
+ [self setColor: colorUnmodified_];
+
+ [self updateColor];
+}
+
+- (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;
+ }
+
+ [self updateColor];
+}
+
+-(void) setOpacityModifyRGB:(BOOL)modify
+{
+ ccColor3B oldColor = self.color;
+ opacityModifyRGB_ = modify;
+ self.color = oldColor;
+}
+
+-(BOOL) doesOpacityModifyRGB
+{
+ return opacityModifyRGB_;
+}
+
+//
+// Frames
+//
+#pragma mark CCSprite - Frames
+
+-(void) setDisplayFrame:(CCSpriteFrame*)frame
+{
+ unflippedOffsetPositionFromCenter_ = frame.offsetInPixels;
+
+ CCTexture2D *newTexture = [frame texture];
+ // update texture before updating texture rect
+ if ( newTexture.name != texture_.name )
+ [self setTexture: newTexture];
+
+ // update rect
+ rectRotated_ = frame.rotated;
+ [self setTextureRectInPixels:frame.rectInPixels rotated:frame.rotated untrimmedSize:frame.originalSizeInPixels];
+}
+
+// XXX deprecated
+-(void) setDisplayFrame: (NSString*) animationName index:(int) frameIndex
+{
+ if( ! animations_ )
+ [self initAnimationDictionary];
+
+ CCAnimation *a = [animations_ objectForKey: animationName];
+ CCSpriteFrame *frame = [[a frames] objectAtIndex:frameIndex];
+
+ NSAssert( frame, @"CCSprite#setDisplayFrame. Invalid frame");
+
+ [self setDisplayFrame:frame];
+}
+
+-(void) setDisplayFrameWithAnimationName: (NSString*) animationName index:(int) frameIndex
+{
+ NSAssert( animationName, @"CCSprite#setDisplayFrameWithAnimationName. animationName must not be nil");
+
+ CCAnimation *a = [[CCAnimationCache sharedAnimationCache] animationByName:animationName];
+
+ NSAssert( a, @"CCSprite#setDisplayFrameWithAnimationName: Frame not found");
+
+ CCSpriteFrame *frame = [[a frames] objectAtIndex:frameIndex];
+
+ NSAssert( frame, @"CCSprite#setDisplayFrame. Invalid frame");
+
+ [self setDisplayFrame:frame];
+}
+
+
+-(BOOL) isFrameDisplayed:(CCSpriteFrame*)frame
+{
+ CGRect r = [frame rect];
+ return ( CGRectEqualToRect(r, rect_) &&
+ frame.texture.name == self.texture.name );
+}
+
+-(CCSpriteFrame*) displayedFrame
+{
+ return [CCSpriteFrame frameWithTexture:self.texture rect:rect_];
+}
+
+-(void) addAnimation: (CCAnimation*) anim
+{
+ // lazy alloc
+ if( ! animations_ )
+ [self initAnimationDictionary];
+
+ [animations_ setObject:anim forKey:[anim name]];
+}
+
+-(CCAnimation*)animationByName: (NSString*) animationName
+{
+ NSAssert( animationName != nil, @"animationName parameter must be non nil");
+ return [animations_ objectForKey:animationName];
+}
+
+#pragma mark CCSprite - CocosNodeTexture protocol
+
+-(void) updateBlendFunc
+{
+ NSAssert( ! usesBatchNode_, @"CCSprite: updateBlendFunc doesn't work when the sprite is rendered using a CCSpriteBatchNode");
+
+ // it's possible to have an untextured sprite
+ if( !texture_ || ! [texture_ hasPremultipliedAlpha] ) {
+ blendFunc_.src = GL_SRC_ALPHA;
+ blendFunc_.dst = GL_ONE_MINUS_SRC_ALPHA;
+ [self setOpacityModifyRGB:NO];
+ } else {
+ blendFunc_.src = CC_BLEND_SRC;
+ blendFunc_.dst = CC_BLEND_DST;
+ [self setOpacityModifyRGB:YES];
+ }
+}
+
+-(void) setTexture:(CCTexture2D*)texture
+{
+ NSAssert( ! usesBatchNode_, @"CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteBatchNode");
+
+ // accept texture==nil as argument
+ NSAssert( !texture || [texture isKindOfClass:[CCTexture2D class]], @"setTexture expects a CCTexture2D. Invalid argument");
+
+ [texture_ release];
+ texture_ = [texture retain];
+
+ [self updateBlendFunc];
+}
+
+-(CCTexture2D*) texture
+{
+ return texture_;
+}
+
+@end
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * Copyright (c) 2009-2010 Ricardo Quesada
+ * Copyright (C) 2009 Matt Oswald
+ *
+ * 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 "CCProtocols.h"
+#import "CCTextureAtlas.h"
+#import "ccMacros.h"
+
+#pragma mark CCSpriteBatchNode
+
+@class CCSprite;
+
+/** CCSpriteBatchNode is like a batch node: if it contains children, it will draw them in 1 single OpenGL call
+ * (often known as "batch draw").
+ *
+ * A CCSpriteBatchNode can reference one and only one texture (one image file, one texture atlas).
+ * Only the CCSprites that are contained in that texture can be added to the CCSpriteBatchNode.
+ * All CCSprites added to a CCSpriteBatchNode are drawn in one OpenGL ES draw call.
+ * If the CCSprites are not added to a CCSpriteBatchNode then an OpenGL ES draw call will be needed for each one, which is less efficient.
+ *
+ *
+ * Limitations:
+ * - The only object that is accepted as child (or grandchild, grand-grandchild, etc...) is CCSprite or any subclass of CCSprite. eg: particles, labels and layer can't be added to a CCSpriteBatchNode.
+ * - Either all its children are Aliased or Antialiased. It can't be a mix. This is because "alias" is a property of the texture, and all the sprites share the same texture.
+ *
+ * @since v0.7.1
+ */
+@interface CCSpriteBatchNode : CCNode <CCTextureProtocol>
+{
+ CCTextureAtlas *textureAtlas_;
+ ccBlendFunc blendFunc_;
+
+ // all descendants: chlidren, gran children, etc...
+ CCArray *descendants_;
+}
+
+/** returns the TextureAtlas that is used */
+@property (nonatomic,readwrite,retain) CCTextureAtlas * textureAtlas;
+
+/** conforms to CCTextureProtocol protocol */
+@property (nonatomic,readwrite) ccBlendFunc blendFunc;
+
+/** descendants (children, gran children, etc) */
+@property (nonatomic,readonly) CCArray *descendants;
+
+/** creates a CCSpriteBatchNode with a texture2d and a default capacity of 29 children.
+ The capacity will be increased in 33% in runtime if it run out of space.
+ */
++(id)batchNodeWithTexture:(CCTexture2D *)tex;
++(id)spriteSheetWithTexture:(CCTexture2D *)tex DEPRECATED_ATTRIBUTE;
+
+/** creates a CCSpriteBatchNode with a texture2d and capacity of children.
+ The capacity will be increased in 33% in runtime if it run out of space.
+ */
++(id)batchNodeWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity;
++(id)spriteSheetWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity DEPRECATED_ATTRIBUTE;
+
+/** creates a CCSpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) with a default capacity of 29 children.
+ The capacity will be increased in 33% in runtime if it run out of space.
+ The file will be loaded using the TextureMgr.
+ */
++(id)batchNodeWithFile:(NSString*) fileImage;
++(id)spriteSheetWithFile:(NSString*) fileImage DEPRECATED_ATTRIBUTE;
+
+/** creates a CCSpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) and capacity of children.
+ The capacity will be increased in 33% in runtime if it run out of space.
+ The file will be loaded using the TextureMgr.
+*/
++(id)batchNodeWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity;
++(id)spriteSheetWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity DEPRECATED_ATTRIBUTE;
+
+/** initializes a CCSpriteBatchNode with a texture2d and capacity of children.
+ The capacity will be increased in 33% in runtime if it run out of space.
+ */
+-(id)initWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity;
+/** initializes a CCSpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) and a capacity of children.
+ The capacity will be increased in 33% in runtime if it run out of space.
+ The file will be loaded using the TextureMgr.
+ */
+-(id)initWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity;
+
+-(void) increaseAtlasCapacity;
+
+/** creates an sprite with a rect in the CCSpriteBatchNode.
+ It's the same as:
+ - create an standard CCSsprite
+ - set the usingSpriteSheet = YES
+ - set the textureAtlas to the same texture Atlas as the CCSpriteBatchNode
+ @deprecated Use [CCSprite spriteWithBatchNode:rect:] instead;
+ */
+-(CCSprite*) createSpriteWithRect:(CGRect)rect DEPRECATED_ATTRIBUTE;
+
+/** initializes a previously created sprite with a rect. This sprite will have the same texture as the CCSpriteBatchNode.
+ It's the same as:
+ - initialize an standard CCSsprite
+ - set the usingBatchNode = YES
+ - set the textureAtlas to the same texture Atlas as the CCSpriteBatchNode
+ @since v0.99.0
+ @deprecated Use [CCSprite initWithBatchNode:rect:] instead;
+*/
+-(void) initSprite:(CCSprite*)sprite rect:(CGRect)rect DEPRECATED_ATTRIBUTE;
+
+/** removes a child given a certain index. It will also cleanup the running actions depending on the cleanup parameter.
+ @warning Removing a child from a CCSpriteBatchNode is very slow
+ */
+-(void)removeChildAtIndex:(NSUInteger)index cleanup:(BOOL)doCleanup;
+
+/** removes a child given a reference. It will also cleanup the running actions depending on the cleanup parameter.
+ @warning Removing a child from a CCSpriteBatchNode is very slow
+ */
+-(void)removeChild: (CCSprite *)sprite cleanup:(BOOL)doCleanup;
+
+-(void) insertChild:(CCSprite*)child inAtlasAtIndex:(NSUInteger)index;
+-(void) removeSpriteFromAtlas:(CCSprite*)sprite;
+
+-(NSUInteger) rebuildIndexInOrder:(CCSprite*)parent atlasIndex:(NSUInteger)index;
+-(NSUInteger) atlasIndexForChild:(CCSprite*)sprite atZ:(int)z;
+
+@end
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * Copyright (c) 2009-2010 Ricardo Quesada
+ * Copyright (C) 2009 Matt Oswald
+ *
+ * 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 "CCSprite.h"
+#import "CCSpriteBatchNode.h"
+#import "CCGrid.h"
+#import "CCDrawingPrimitives.h"
+#import "CCTextureCache.h"
+#import "Support/CGPointExtension.h"
+
+const NSUInteger defaultCapacity = 29;
+
+#pragma mark -
+#pragma mark CCSpriteBatchNode
+
+static SEL selUpdate = NULL;
+
+@interface CCSpriteBatchNode (private)
+-(void) updateBlendFunc;
+@end
+
+@implementation CCSpriteBatchNode
+
+@synthesize textureAtlas = textureAtlas_;
+@synthesize blendFunc = blendFunc_;
+@synthesize descendants = descendants_;
+
+
++(void) initialize
+{
+ if ( self == [CCSpriteBatchNode class] ) {
+ selUpdate = @selector(updateTransform);
+ }
+}
+/*
+ * creation with CCTexture2D
+ */
++(id)batchNodeWithTexture:(CCTexture2D *)tex
+{
+ return [[[self alloc] initWithTexture:tex capacity:defaultCapacity] autorelease];
+}
++(id)spriteSheetWithTexture:(CCTexture2D *)tex // XXX DEPRECATED
+{
+ return [self batchNodeWithTexture:tex];
+}
+
++(id)batchNodeWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity
+{
+ return [[[self alloc] initWithTexture:tex capacity:capacity] autorelease];
+}
++(id)spriteSheetWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity // XXX DEPRECATED
+{
+ return [self batchNodeWithTexture:tex capacity:capacity];
+}
+
+/*
+ * creation with File Image
+ */
++(id)batchNodeWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity
+{
+ return [[[self alloc] initWithFile:fileImage capacity:capacity] autorelease];
+}
++(id)spriteSheetWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity // XXX DEPRECATED
+{
+ return [self batchNodeWithFile:fileImage capacity:capacity];
+}
+
++(id)batchNodeWithFile:(NSString*) imageFile
+{
+ return [[[self alloc] initWithFile:imageFile capacity:defaultCapacity] autorelease];
+}
++(id)spriteSheetWithFile:(NSString*) imageFile // XXX DEPRECATED
+{
+ return [self batchNodeWithFile:imageFile];
+}
+
+
+/*
+ * init with CCTexture2D
+ */
+-(id)initWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity
+{
+ if( (self=[super init])) {
+
+ blendFunc_.src = CC_BLEND_SRC;
+ blendFunc_.dst = CC_BLEND_DST;
+ textureAtlas_ = [[CCTextureAtlas alloc] initWithTexture:tex capacity:capacity];
+
+ [self updateBlendFunc];
+
+ // no lazy alloc in this node
+ children_ = [[CCArray alloc] initWithCapacity:capacity];
+ descendants_ = [[CCArray alloc] initWithCapacity:capacity];
+ }
+
+ return self;
+}
+
+/*
+ * init with FileImage
+ */
+-(id)initWithFile:(NSString *)fileImage capacity:(NSUInteger)capacity
+{
+ CCTexture2D *tex = [[CCTextureCache sharedTextureCache] addImage:fileImage];
+ return [self initWithTexture:tex capacity:capacity];
+}
+
+- (NSString*) description
+{
+ return [NSString stringWithFormat:@"<%@ = %08X | Tag = %i>", [self class], self, tag_ ];
+}
+
+-(void)dealloc
+{
+ [textureAtlas_ release];
+ [descendants_ release];
+
+ [super dealloc];
+}
+
+#pragma mark CCSpriteBatchNode - composition
+
+// override visit.
+// Don't call visit on it's children
+-(void) visit
+{
+
+ // CAREFUL:
+ // This visit is almost identical to CocosNode#visit
+ // with the exception that it doesn't call visit on it's children
+ //
+ // The alternative is to have a void CCSprite#visit, but
+ // although this is less mantainable, is faster
+ //
+ if (!visible_)
+ return;
+
+ glPushMatrix();
+
+ if ( grid_ && grid_.active) {
+ [grid_ beforeDraw];
+ [self transformAncestors];
+ }
+
+ [self transform];
+
+ [self draw];
+
+ if ( grid_ && grid_.active)
+ [grid_ afterDraw:self];
+
+ glPopMatrix();
+}
+
+// XXX deprecated
+-(CCSprite*) createSpriteWithRect:(CGRect)rect
+{
+ CCSprite *sprite = [CCSprite spriteWithTexture:textureAtlas_.texture rect:rect];
+ [sprite useBatchNode:self];
+
+ return sprite;
+}
+
+// XXX deprecated
+-(void) initSprite:(CCSprite*)sprite rect:(CGRect)rect
+{
+ [sprite initWithTexture:textureAtlas_.texture rect:rect];
+ [sprite useBatchNode:self];
+}
+
+// override addChild:
+-(void) addChild:(CCSprite*)child z:(int)z tag:(int) aTag
+{
+ NSAssert( child != nil, @"Argument must be non-nil");
+ NSAssert( [child isKindOfClass:[CCSprite class]], @"CCSpriteBatchNode only supports CCSprites as children");
+ NSAssert( child.texture.name == textureAtlas_.texture.name, @"CCSprite is not using the same texture id");
+
+ [super addChild:child z:z tag:aTag];
+
+ NSUInteger index = [self atlasIndexForChild:child atZ:z];
+ [self insertChild:child inAtlasAtIndex:index];
+}
+
+// override reorderChild
+-(void) reorderChild:(CCSprite*)child z:(int)z
+{
+ NSAssert( child != nil, @"Child must be non-nil");
+ NSAssert( [children_ containsObject:child], @"Child doesn't belong to Sprite" );
+
+ if( z == child.zOrder )
+ return;
+
+ // XXX: Instead of removing/adding, it is more efficient to reorder manually
+ [child retain];
+ [self removeChild:child cleanup:NO];
+ [self addChild:child z:z];
+ [child release];
+}
+
+// override removeChild:
+-(void)removeChild: (CCSprite *)sprite cleanup:(BOOL)doCleanup
+{
+ // explicit nil handling
+ if (sprite == nil)
+ return;
+
+ NSAssert([children_ containsObject:sprite], @"CCSpriteBatchNode doesn't contain the sprite. Can't remove it");
+
+ // cleanup before removing
+ [self removeSpriteFromAtlas:sprite];
+
+ [super removeChild:sprite cleanup:doCleanup];
+}
+
+-(void)removeChildAtIndex:(NSUInteger)index cleanup:(BOOL)doCleanup
+{
+ [self removeChild:(CCSprite *)[children_ objectAtIndex:index] cleanup:doCleanup];
+}
+
+-(void)removeAllChildrenWithCleanup:(BOOL)doCleanup
+{
+ // Invalidate atlas index. issue #569
+ [children_ makeObjectsPerformSelector:@selector(useSelfRender)];
+
+ [super removeAllChildrenWithCleanup:doCleanup];
+
+ [descendants_ removeAllObjects];
+ [textureAtlas_ removeAllQuads];
+}
+
+#pragma mark CCSpriteBatchNode - draw
+-(void) draw
+{
+ // Optimization: Fast Dispatch
+ if( textureAtlas_.totalQuads == 0 )
+ return;
+
+ CCSprite *child;
+ ccArray *array = descendants_->data;
+
+ NSUInteger i = array->num;
+ id *arr = array->arr;
+
+ if( i > 0 ) {
+
+ while (i-- > 0) {
+ child = *arr++;
+
+ // fast dispatch
+ child->updateMethod(child, selUpdate);
+
+#if CC_SPRITEBATCHNODE_DEBUG_DRAW
+ //Issue #528
+ CGRect rect = [child boundingBox];
+ CGPoint vertices[4]={
+ ccp(rect.origin.x,rect.origin.y),
+ ccp(rect.origin.x+rect.size.width,rect.origin.y),
+ ccp(rect.origin.x+rect.size.width,rect.origin.y+rect.size.height),
+ ccp(rect.origin.x,rect.origin.y+rect.size.height),
+ };
+ ccDrawPoly(vertices, 4, YES);
+#endif // CC_SPRITEBATCHNODE_DEBUG_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: -
+
+ 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);
+}
+
+#pragma mark CCSpriteBatchNode - private
+-(void) increaseAtlasCapacity
+{
+ // if we're going beyond the current TextureAtlas's capacity,
+ // all the previously initialized sprites will need to redo their texture coords
+ // this is likely computationally expensive
+ NSUInteger quantity = (textureAtlas_.capacity + 1) * 4 / 3;
+
+ CCLOG(@"cocos2d: CCSpriteBatchNode: resizing TextureAtlas capacity from [%u] to [%u].",
+ (unsigned int)textureAtlas_.capacity,
+ (unsigned int)quantity);
+
+
+ if( ! [textureAtlas_ resizeCapacity:quantity] ) {
+ // serious problems
+ CCLOG(@"cocos2d: WARNING: Not enough memory to resize the atlas");
+ NSAssert(NO,@"XXX: SpriteSheet#increaseAtlasCapacity SHALL handle this assert");
+ }
+}
+
+
+#pragma mark CCSpriteBatchNode - Atlas Index Stuff
+
+-(NSUInteger) rebuildIndexInOrder:(CCSprite*)node atlasIndex:(NSUInteger)index
+{
+ CCSprite *sprite;
+ CCARRAY_FOREACH(node.children, sprite){
+ if( sprite.zOrder < 0 )
+ index = [self rebuildIndexInOrder:sprite atlasIndex:index];
+ }
+
+ // ignore self (batch node)
+ if( ! [node isEqual:self]) {
+ node.atlasIndex = index;
+ index++;
+ }
+
+ CCARRAY_FOREACH(node.children, sprite){
+ if( sprite.zOrder >= 0 )
+ index = [self rebuildIndexInOrder:sprite atlasIndex:index];
+ }
+
+ return index;
+}
+
+-(NSUInteger) highestAtlasIndexInChild:(CCSprite*)sprite
+{
+ CCArray *array = [sprite children];
+ NSUInteger count = [array count];
+ if( count == 0 )
+ return sprite.atlasIndex;
+ else
+ return [self highestAtlasIndexInChild:[array lastObject]];
+}
+
+-(NSUInteger) lowestAtlasIndexInChild:(CCSprite*)sprite
+{
+ CCArray *array = [sprite children];
+ NSUInteger count = [array count];
+ if( count == 0 )
+ return sprite.atlasIndex;
+ else
+ return [self lowestAtlasIndexInChild:[array objectAtIndex:0] ];
+}
+
+
+-(NSUInteger)atlasIndexForChild:(CCSprite*)sprite atZ:(int)z
+{
+ CCArray *brothers = [[sprite parent] children];
+ NSUInteger childIndex = [brothers indexOfObject:sprite];
+
+ // ignore parent Z if parent is batchnode
+ BOOL ignoreParent = ( sprite.parent == self );
+ CCSprite *previous = nil;
+ if( childIndex > 0 )
+ previous = [brothers objectAtIndex:childIndex-1];
+
+ // first child of the sprite sheet
+ if( ignoreParent ) {
+ if( childIndex == 0 )
+ return 0;
+ // else
+ return [self highestAtlasIndexInChild: previous] + 1;
+ }
+
+ // parent is a CCSprite, so, it must be taken into account
+
+ // first child of an CCSprite ?
+ if( childIndex == 0 )
+ {
+ CCSprite *p = (CCSprite*) sprite.parent;
+
+ // less than parent and brothers
+ if( z < 0 )
+ return p.atlasIndex;
+ else
+ return p.atlasIndex+1;
+
+ } else {
+ // previous & sprite belong to the same branch
+ if( ( previous.zOrder < 0 && z < 0 )|| (previous.zOrder >= 0 && z >= 0) )
+ return [self highestAtlasIndexInChild:previous] + 1;
+
+ // else (previous < 0 and sprite >= 0 )
+ CCSprite *p = (CCSprite*) sprite.parent;
+ return p.atlasIndex + 1;
+ }
+
+ NSAssert( NO, @"Should not happen. Error calculating Z on Batch Node");
+ return 0;
+}
+
+#pragma mark CCSpriteBatchNode - add / remove / reorder helper methods
+// add child helper
+-(void) insertChild:(CCSprite*)sprite inAtlasAtIndex:(NSUInteger)index
+{
+ [sprite useBatchNode:self];
+ [sprite setAtlasIndex:index];
+ [sprite setDirty: YES];
+
+ if(textureAtlas_.totalQuads == textureAtlas_.capacity)
+ [self increaseAtlasCapacity];
+
+ ccV3F_C4B_T2F_Quad quad = [sprite quad];
+ [textureAtlas_ insertQuad:&quad atIndex:index];
+
+ ccArray *descendantsData = descendants_->data;
+
+ ccArrayInsertObjectAtIndex(descendantsData, sprite, index);
+
+ // update indices
+ NSUInteger i = index+1;
+ CCSprite *child;
+ for(; i<descendantsData->num; i++){
+ child = descendantsData->arr[i];
+ child.atlasIndex = child.atlasIndex + 1;
+ }
+
+ // add children recursively
+ CCARRAY_FOREACH(sprite.children, child){
+ NSUInteger index = [self atlasIndexForChild:child atZ: child.zOrder];
+ [self insertChild:child inAtlasAtIndex:index];
+ }
+}
+
+// remove child helper
+-(void) removeSpriteFromAtlas:(CCSprite*)sprite
+{
+ // remove from TextureAtlas
+ [textureAtlas_ removeQuadAtIndex:sprite.atlasIndex];
+
+ // Cleanup sprite. It might be reused (issue #569)
+ [sprite useSelfRender];
+
+ ccArray *descendantsData = descendants_->data;
+ NSUInteger index = ccArrayGetIndexOfObject(descendantsData, sprite);
+ if( index != NSNotFound ) {
+ ccArrayRemoveObjectAtIndex(descendantsData, index);
+
+ // update all sprites beyond this one
+ NSUInteger count = descendantsData->num;
+
+ for(; index < count; index++)
+ {
+ CCSprite *s = descendantsData->arr[index];
+ s.atlasIndex = s.atlasIndex - 1;
+ }
+ }
+
+ // remove children recursively
+ CCSprite *child;
+ CCARRAY_FOREACH(sprite.children, child)
+ [self removeSpriteFromAtlas:child];
+}
+
+#pragma mark CCSpriteBatchNode - 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];
+}
+
+-(CCTexture2D*) texture
+{
+ return textureAtlas_.texture;
+}
+@end
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+#import "CCNode.h"
+#import "CCProtocols.h"
+
+/** A CCSpriteFrame has:
+ - texture: A CCTexture2D that will be used by the CCSprite
+ - rectangle: A rectangle of the texture
+
+
+ You can modify the frame of a CCSprite by doing:
+
+ CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:texture rect:rect offset:offset];
+ [sprite setDisplayFrame:frame];
+ */
+@interface CCSpriteFrame : NSObject <NSCopying>
+{
+ CGRect rect_;
+ CGRect rectInPixels_;
+ BOOL rotated_;
+ CGPoint offsetInPixels_;
+ CGSize originalSizeInPixels_;
+ CCTexture2D *texture_;
+}
+/** rect of the frame in points */
+@property (nonatomic,readwrite) CGRect rect;
+
+/** rect of the frame in pixels */
+@property (nonatomic,readwrite) CGRect rectInPixels;
+
+/** whether or not the rect of the frame is rotated ( x = x+width, y = y+height, width = height, height = width ) */
+@property (nonatomic,readwrite) BOOL rotated;
+
+/** offset of the frame in pixels */
+@property (nonatomic,readwrite) CGPoint offsetInPixels;
+
+/** original size of the trimmed image in pixels */
+@property (nonatomic,readwrite) CGSize originalSizeInPixels;
+
+/** texture of the frame */
+@property (nonatomic, retain, readwrite) CCTexture2D *texture;
+
+/** Create a CCSpriteFrame with a texture, rect in points.
+ It is assumed that the frame was not trimmed.
+ */
++(id) frameWithTexture:(CCTexture2D*)texture rect:(CGRect)rect;
+
+/** Create a CCSpriteFrame with a texture, rect, rotated, offset and originalSize in pixels.
+ The originalSize is the size in points of the frame before being trimmed.
+ */
++(id) frameWithTexture:(CCTexture2D*)texture rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize;
+
+
+/** Initializes a CCSpriteFrame with a texture, rect in points;
+ It is assumed that the frame was not trimmed.
+ */
+-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect;
+
+/** Initializes a CCSpriteFrame with a texture, rect, rotated, offset and originalSize in pixels.
+ The originalSize is the size in points of the frame before being trimmed.
+ */
+-(id) initWithTexture:(CCTexture2D*)texture rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize;
+
+@end
+
--- /dev/null
+/*
+ * 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 "CCTextureCache.h"
+#import "CCSpriteFrame.h"
+#import "ccMacros.h"
+
+@implementation CCSpriteFrame
+@synthesize rect = rect_, rectInPixels=rectInPixels_;
+@synthesize rotated = rotated_, offsetInPixels = offsetInPixels_, texture = texture_;
+@synthesize originalSizeInPixels=originalSizeInPixels_;
+
++(id) frameWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
+{
+ return [[[self alloc] initWithTexture:texture rect:rect] autorelease];
+}
+
++(id) frameWithTexture:(CCTexture2D*)texture rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize
+{
+ return [[[self alloc] initWithTexture:texture rectInPixels:rect rotated:rotated offset:offset originalSize:originalSize] autorelease];
+}
+
+-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
+{
+ CGRect rectInPixels = CC_RECT_POINTS_TO_PIXELS( rect );
+ return [self initWithTexture:texture rectInPixels:rectInPixels rotated:NO offset:CGPointZero originalSize:rectInPixels.size];
+}
+
+-(id) initWithTexture:(CCTexture2D*)texture rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize
+{
+ if( (self=[super init]) ) {
+ self.texture = texture;
+ rectInPixels_ = rect;
+ rect_ = CC_RECT_PIXELS_TO_POINTS( rect );
+ rotated_ = rotated;
+ offsetInPixels_ = offset;
+ originalSizeInPixels_ = originalSize;
+ }
+ return self;
+}
+
+- (NSString*) description
+{
+ return [NSString stringWithFormat:@"<%@ = %08X | TextureName=%d, Rect = (%.2f,%.2f,%.2f,%.2f)>", [self class], self,
+ texture_.name,
+ rect_.origin.x,
+ rect_.origin.y,
+ rect_.size.width,
+ rect_.size.height];
+}
+
+- (void) dealloc
+{
+ CCLOGINFO( @"cocos2d: deallocing %@",self);
+ [texture_ release];
+ [super dealloc];
+}
+
+-(id) copyWithZone: (NSZone*) zone
+{
+ CCSpriteFrame *copy = [[[self class] allocWithZone: zone] initWithTexture:texture_ rectInPixels:rectInPixels_ rotated:rotated_ offset:offsetInPixels_ originalSize:originalSizeInPixels_];
+ return copy;
+}
+@end
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * Copyright (c) 2008-2010 Ricardo Quesada
+ * Copyright (c) 2009 Jason Booth
+ * Copyright (c) 2009 Robert J Payne
+ *
+ * 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.
+ *
+ */
+
+
+/*
+ * To create sprite frames and texture atlas, use this tool:
+ * http://zwoptex.zwopple.com/
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "CCSpriteFrame.h"
+#import "CCTexture2D.h"
+
+@class CCSprite;
+
+/** Singleton that handles the loading of the sprite frames.
+ It saves in a cache the sprite frames.
+ @since v0.9
+ */
+@interface CCSpriteFrameCache : NSObject
+{
+ NSMutableDictionary *spriteFrames_;
+ NSMutableDictionary *spriteFramesAliases_;
+}
+
+/** Retruns ths shared instance of the Sprite Frame cache */
++ (CCSpriteFrameCache *) sharedSpriteFrameCache;
+
+/** Purges the cache. It releases all the Sprite Frames and the retained instance.
+ */
++(void)purgeSharedSpriteFrameCache;
+
+
+/** Adds multiple Sprite Frames with a dictionary. The texture will be associated with the created sprite frames.
+ */
+-(void) addSpriteFramesWithDictionary:(NSDictionary*)dictionary texture:(CCTexture2D*)texture;
+
+/** Adds multiple Sprite Frames from a plist file.
+ * A texture will be loaded automatically. The texture name will composed by replacing the .plist suffix with .png
+ * If you want to use another texture, you should use the addSpriteFramesWithFile:texture method.
+ */
+-(void) addSpriteFramesWithFile:(NSString*)plist;
+
+/** Adds multiple Sprite Frames from a plist file. The texture will be associated with the created sprite frames.
+ */
+-(void) addSpriteFramesWithFile:(NSString*)plist texture:(CCTexture2D*)texture;
+
+/** Adds multiple Sprite Frames from a plist file. The texture will be associated with the created sprite frames.
+ @since v0.99.5
+ */
+-(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName;
+
+/** Adds an sprite frame with a given name.
+ If the name already exists, then the contents of the old name will be replaced with the new one.
+ */
+-(void) addSpriteFrame:(CCSpriteFrame*)frame name:(NSString*)frameName;
+
+
+/** Purges the dictionary of loaded sprite frames.
+ * Call this method if you receive the "Memory Warning".
+ * In the short term: it will free some resources preventing your app from being killed.
+ * In the medium term: it will allocate more resources.
+ * In the long term: it will be the same.
+ */
+-(void) removeSpriteFrames;
+
+/** Removes unused sprite frames.
+ * Sprite Frames that have a retain count of 1 will be deleted.
+ * It is convinient to call this method after when starting a new Scene.
+ */
+-(void) removeUnusedSpriteFrames;
+
+/** Deletes an sprite frame from the sprite frame cache.
+ */
+-(void) removeSpriteFrameByName:(NSString*)name;
+
+/** Removes multiple Sprite Frames from a plist file.
+* Sprite Frames stored in this file will be removed.
+* It is convinient to call this method when a specific texture needs to be removed.
+* @since v0.99.5
+*/
+- (void) removeSpriteFramesFromFile:(NSString*) plist;
+
+/** Removes multiple Sprite Frames from NSDictionary.
+ * @since v0.99.5
+ */
+- (void) removeSpriteFramesFromDictionary:(NSDictionary*) dictionary;
+
+/** Removes all Sprite Frames associated with the specified textures.
+ * It is convinient to call this method when a specific texture needs to be removed.
+ * @since v0.995.
+ */
+- (void) removeSpriteFramesFromTexture:(CCTexture2D*) texture;
+
+/** Returns an Sprite Frame 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.
+ */
+-(CCSpriteFrame*) spriteFrameByName:(NSString*)name;
+
+/** Creates an sprite with the name of an sprite frame.
+ The created sprite will contain the texture, rect and offset of the sprite frame.
+ It returns an autorelease object.
+ @deprecated use [CCSprite spriteWithSpriteFrameName:name]. This method will be removed on final v0.9
+ */
+-(CCSprite*) createSpriteWithFrameName:(NSString*)name DEPRECATED_ATTRIBUTE;
+
+@end
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * Copyright (c) 2008-2010 Ricardo Quesada
+ * Copyright (c) 2009 Jason Booth
+ * Copyright (c) 2009 Robert J Payne
+ *
+ * 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.
+ *
+ */
+
+/*
+ * To create sprite frames and texture atlas, use this tool:
+ * http://zwoptex.zwopple.com/
+ */
+
+#import "Platforms/CCNS.h"
+#import "ccMacros.h"
+#import "CCTextureCache.h"
+#import "CCSpriteFrameCache.h"
+#import "CCSpriteFrame.h"
+#import "CCSprite.h"
+#import "Support/CCFileUtils.h"
+
+
+@implementation CCSpriteFrameCache
+
+#pragma mark CCSpriteFrameCache - Alloc, Init & Dealloc
+
+static CCSpriteFrameCache *sharedSpriteFrameCache_=nil;
+
++ (CCSpriteFrameCache *)sharedSpriteFrameCache
+{
+ if (!sharedSpriteFrameCache_)
+ sharedSpriteFrameCache_ = [[CCSpriteFrameCache alloc] init];
+
+ return sharedSpriteFrameCache_;
+}
+
++(id)alloc
+{
+ NSAssert(sharedSpriteFrameCache_ == nil, @"Attempted to allocate a second instance of a singleton.");
+ return [super alloc];
+}
+
++(void)purgeSharedSpriteFrameCache
+{
+ [sharedSpriteFrameCache_ release];
+ sharedSpriteFrameCache_ = nil;
+}
+
+-(id) init
+{
+ if( (self=[super init]) ) {
+ spriteFrames_ = [[NSMutableDictionary alloc] initWithCapacity: 100];
+ spriteFramesAliases_ = [[NSMutableDictionary alloc] initWithCapacity:10];
+ }
+
+ return self;
+}
+
+- (NSString*) description
+{
+ return [NSString stringWithFormat:@"<%@ = %08X | num of sprite frames = %i>", [self class], self, [spriteFrames_ count]];
+}
+
+-(void) dealloc
+{
+ CCLOGINFO(@"cocos2d: deallocing %@", self);
+
+ [spriteFrames_ release];
+ [spriteFramesAliases_ release];
+ [super dealloc];
+}
+
+#pragma mark CCSpriteFrameCache - loading sprite frames
+
+-(void) addSpriteFramesWithDictionary:(NSDictionary*)dictionary texture:(CCTexture2D*)texture
+{
+ /*
+ Supported Zwoptex Formats:
+ ZWTCoordinatesFormatOptionXMLLegacy = 0, // Flash Version
+ ZWTCoordinatesFormatOptionXML1_0 = 1, // Desktop Version 0.0 - 0.4b
+ ZWTCoordinatesFormatOptionXML1_1 = 2, // Desktop Version 1.0.0 - 1.0.1
+ ZWTCoordinatesFormatOptionXML1_2 = 3, // Desktop Version 1.0.2+
+ */
+ NSDictionary *metadataDict = [dictionary objectForKey:@"metadata"];
+ NSDictionary *framesDict = [dictionary objectForKey:@"frames"];
+
+ int format = 0;
+
+ // get the format
+ if(metadataDict != nil)
+ format = [[metadataDict objectForKey:@"format"] intValue];
+
+ // check the format
+ NSAssert( format >= 0 && format <= 3, @"cocos2d: WARNING: format is not supported for CCSpriteFrameCache addSpriteFramesWithDictionary:texture:");
+
+
+ // add real frames
+ for(NSString *frameDictKey in framesDict) {
+ NSDictionary *frameDict = [framesDict objectForKey:frameDictKey];
+ CCSpriteFrame *spriteFrame;
+ if(format == 0) {
+ float x = [[frameDict objectForKey:@"x"] floatValue];
+ float y = [[frameDict objectForKey:@"y"] floatValue];
+ float w = [[frameDict objectForKey:@"width"] floatValue];
+ float h = [[frameDict objectForKey:@"height"] floatValue];
+ float ox = [[frameDict objectForKey:@"offsetX"] floatValue];
+ float oy = [[frameDict objectForKey:@"offsetY"] floatValue];
+ int ow = [[frameDict objectForKey:@"originalWidth"] intValue];
+ int oh = [[frameDict objectForKey:@"originalHeight"] intValue];
+ // check ow/oh
+ if(!ow || !oh)
+ CCLOG(@"cocos2d: WARNING: originalWidth/Height not found on the CCSpriteFrame. AnchorPoint won't work as expected. Regenerate the .plist");
+
+ // abs ow/oh
+ ow = abs(ow);
+ oh = abs(oh);
+ // create frame
+
+ spriteFrame = [[CCSpriteFrame alloc] initWithTexture:texture
+ rectInPixels:CGRectMake(x, y, w, h)
+ rotated:NO
+ offset:CGPointMake(ox, oy)
+ originalSize:CGSizeMake(ow, oh)];
+ } else if(format == 1 || format == 2) {
+ CGRect frame = CCRectFromString([frameDict objectForKey:@"frame"]);
+ BOOL rotated = NO;
+
+ // rotation
+ if(format == 2)
+ rotated = [[frameDict objectForKey:@"rotated"] boolValue];
+
+ CGPoint offset = CCPointFromString([frameDict objectForKey:@"offset"]);
+ CGSize sourceSize = CCSizeFromString([frameDict objectForKey:@"sourceSize"]);
+
+ // create frame
+ spriteFrame = [[CCSpriteFrame alloc] initWithTexture:texture
+ rectInPixels:frame
+ rotated:rotated
+ offset:offset
+ originalSize:sourceSize];
+ } else if(format == 3) {
+ // get values
+ CGSize spriteSize = CCSizeFromString([frameDict objectForKey:@"spriteSize"]);
+ CGPoint spriteOffset = CCPointFromString([frameDict objectForKey:@"spriteOffset"]);
+ CGSize spriteSourceSize = CCSizeFromString([frameDict objectForKey:@"spriteSourceSize"]);
+ CGRect textureRect = CCRectFromString([frameDict objectForKey:@"textureRect"]);
+ BOOL textureRotated = [[frameDict objectForKey:@"textureRotated"] boolValue];
+
+ // get aliases
+ NSArray *aliases = [frameDict objectForKey:@"aliases"];
+ for(NSString *alias in aliases) {
+ if( [spriteFramesAliases_ objectForKey:alias] )
+ CCLOG(@"cocos2d: WARNING: an alias with name %@ already exists",alias);
+
+ [spriteFramesAliases_ setObject:frameDictKey forKey:alias];
+ }
+
+ // create frame
+ spriteFrame = [[CCSpriteFrame alloc] initWithTexture:texture
+ rectInPixels:CGRectMake(textureRect.origin.x, textureRect.origin.y, spriteSize.width, spriteSize.height)
+ rotated:textureRotated
+ offset:spriteOffset
+ originalSize:spriteSourceSize];
+ }
+
+ // add sprite frame
+ [spriteFrames_ setObject:spriteFrame forKey:frameDictKey];
+ [spriteFrame release];
+ }
+}
+
+-(void) addSpriteFramesWithFile:(NSString*)plist texture:(CCTexture2D*)texture
+{
+ NSString *path = [CCFileUtils fullPathFromRelativePath:plist];
+ NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
+
+ return [self addSpriteFramesWithDictionary:dict texture:texture];
+}
+
+-(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName
+{
+ NSAssert( textureFileName, @"Invalid texture file name");
+ CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:textureFileName];
+
+ if( texture )
+ [self addSpriteFramesWithFile:plist texture:texture];
+ else
+ CCLOG(@"cocos2d: CCSpriteFrameCache: couldn't load texture file. File not found: %@", textureFileName);
+}
+
+-(void) addSpriteFramesWithFile:(NSString*)plist
+{
+ NSString *path = [CCFileUtils fullPathFromRelativePath:plist];
+ NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
+
+ NSString *texturePath = nil;
+ NSDictionary *metadataDict = [dict objectForKey:@"metadata"];
+ if( metadataDict )
+ // try to read texture file name from meta data
+ texturePath = [metadataDict objectForKey:@"textureFileName"];
+
+
+ if( texturePath )
+ {
+ // build texture path relative to plist file
+ NSString *textureBase = [plist stringByDeletingLastPathComponent];
+ texturePath = [textureBase stringByAppendingPathComponent:texturePath];
+ } else {
+ // build texture path by replacing file extension
+ texturePath = [plist stringByDeletingPathExtension];
+ texturePath = [texturePath stringByAppendingPathExtension:@"png"];
+
+ CCLOG(@"cocos2d: CCSpriteFrameCache: Trying to use file '%@' as texture", texturePath);
+ }
+
+ CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:texturePath];
+
+ if( texture )
+ [self addSpriteFramesWithDictionary:dict texture:texture];
+
+ else
+ CCLOG(@"cocos2d: CCSpriteFrameCache: Couldn't load texture");
+}
+
+-(void) addSpriteFrame:(CCSpriteFrame*)frame name:(NSString*)frameName
+{
+ [spriteFrames_ setObject:frame forKey:frameName];
+}
+
+#pragma mark CCSpriteFrameCache - removing
+
+-(void) removeSpriteFrames
+{
+ [spriteFrames_ removeAllObjects];
+ [spriteFramesAliases_ removeAllObjects];
+}
+
+-(void) removeUnusedSpriteFrames
+{
+ NSArray *keys = [spriteFrames_ allKeys];
+ for( id key in keys ) {
+ id value = [spriteFrames_ objectForKey:key];
+ if( [value retainCount] == 1 ) {
+ CCLOG(@"cocos2d: CCSpriteFrameCache: removing unused frame: %@", key);
+ [spriteFrames_ removeObjectForKey:key];
+ }
+ }
+}
+
+-(void) removeSpriteFrameByName:(NSString*)name
+{
+ // explicit nil handling
+ if( ! name )
+ return;
+
+ // Is this an alias ?
+ NSString *key = [spriteFramesAliases_ objectForKey:name];
+
+ if( key ) {
+ [spriteFrames_ removeObjectForKey:key];
+ [spriteFramesAliases_ removeObjectForKey:name];
+
+ } else
+ [spriteFrames_ removeObjectForKey:name];
+}
+
+- (void) removeSpriteFramesFromFile:(NSString*) plist
+{
+ NSString *path = [CCFileUtils fullPathFromRelativePath:plist];
+ NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
+
+ [self removeSpriteFramesFromDictionary:dict];
+}
+
+- (void) removeSpriteFramesFromDictionary:(NSDictionary*) dictionary
+{
+ NSDictionary *framesDict = [dictionary objectForKey:@"frames"];
+ NSMutableArray *keysToRemove=[NSMutableArray array];
+
+ for(NSString *frameDictKey in framesDict)
+ {
+ if ([spriteFrames_ objectForKey:frameDictKey]!=nil)
+ [keysToRemove addObject:frameDictKey];
+ }
+ [spriteFrames_ removeObjectsForKeys:keysToRemove];
+}
+
+- (void) removeSpriteFramesFromTexture:(CCTexture2D*) texture
+{
+ NSMutableArray *keysToRemove=[NSMutableArray array];
+
+ for (NSString *spriteFrameKey in spriteFrames_)
+ {
+ if ([[spriteFrames_ valueForKey:spriteFrameKey] texture] == texture)
+ [keysToRemove addObject:spriteFrameKey];
+
+ }
+ [spriteFrames_ removeObjectsForKeys:keysToRemove];
+}
+
+#pragma mark CCSpriteFrameCache - getting
+
+-(CCSpriteFrame*) spriteFrameByName:(NSString*)name
+{
+ CCSpriteFrame *frame = [spriteFrames_ objectForKey:name];
+ if( ! frame ) {
+ // try alias dictionary
+ NSString *key = [spriteFramesAliases_ objectForKey:name];
+ frame = [spriteFrames_ objectForKey:key];
+
+ if( ! frame )
+ CCLOG(@"cocos2d: CCSpriteFrameCache: Frame '%@' not found", name);
+ }
+
+ return frame;
+}
+
+#pragma mark CCSpriteFrameCache - sprite creation
+
+-(CCSprite*) createSpriteWithFrameName:(NSString*)name
+{
+ CCSpriteFrame *frame = [spriteFrames_ objectForKey:name];
+ return [CCSprite spriteWithSpriteFrame:frame];
+}
+@end
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * Copyright (c) 2009-2010 Ricardo Quesada
+ * Copyright (C) 2009 Matt Oswald
+ *
+ * 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 "CCSpriteBatchNode.h"
+
+#pragma mark CCSpriteSheet
+
+
+/* Added only to prevent GCC compile warnings
+ Will be removed in v1.1
+ */
+@interface CCSpriteSheetInternalOnly : CCSpriteBatchNode
+{
+}
+@end
+
+/** CCSpriteSheet is like a batch node: if it contains children, it will draw them in 1 single OpenGL call
+ * (often known as "batch draw").
+ *
+ * A CCSpriteSheet can reference one and only one texture (one image file, one texture atlas).
+ * Only the CCSprites that are contained in that texture can be added to the CCSpriteSheet.
+ * All CCSprites added to a CCSpriteSheet are drawn in one OpenGL ES draw call.
+ * If the CCSprites are not added to a CCSpriteSheet then an OpenGL ES draw call will be needed for each one, which is less efficient.
+ *
+ *
+ * Limitations:
+ * - The only object that is accepted as child (or grandchild, grand-grandchild, etc...) is CCSprite or any subclass of CCSprite. eg: particles, labels and layer can't be added to a CCSpriteSheet.
+ * - Either all its children are Aliased or Antialiased. It can't be a mix. This is because "alias" is a property of the texture, and all the sprites share the same texture.
+ *
+ * @since v0.7.1
+ *
+ * @deprecated Use CCSpriteBatchNode instead. This class will be removed in v1.1
+ */
+DEPRECATED_ATTRIBUTE @interface CCSpriteSheet : CCSpriteSheetInternalOnly
+{
+}
+@end
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * Copyright (c) 2009-2010 Ricardo Quesada
+ * Copyright (C) 2009 Matt Oswald
+ *
+ * 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 "CCSpriteSheet.h"
+
+#pragma mark -
+#pragma mark CCSpriteSheet
+
+@implementation CCSpriteSheetInternalOnly
+@end
+
+@implementation CCSpriteSheet
+@end
--- /dev/null
+/*
+ * 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.
+ *
+ *
+ * TMX Tiled Map support:
+ * http://www.mapeditor.org
+ *
+ */
+
+
+#import "CCAtlasNode.h"
+#import "CCSpriteBatchNode.h"
+
+
+@class CCTMXMapInfo;
+@class CCTMXLayerInfo;
+@class CCTMXTilesetInfo;
+
+/** CCTMXLayer represents the TMX layer.
+
+ It is a subclass of CCSpriteSheet. By default the tiles are rendered using a CCTextureAtlas.
+ If you mofify a tile on runtime, then, that tile will become a CCSprite, otherwise no CCSprite objects are created.
+ The benefits of using CCSprite objects as tiles are:
+ - tiles (CCSprite) can be rotated/scaled/moved with a nice API
+
+ If the layer contains a property named "cc_vertexz" with an integer (in can be positive or negative),
+ then all the tiles belonging to the layer will use that value as their OpenGL vertex Z for depth.
+
+ On the other hand, if the "cc_vertexz" property has the "automatic" value, then the tiles will use an automatic vertex Z value.
+ Also before drawing the tiles, GL_ALPHA_TEST will be enabled, and disabled after drawing them. The used alpha func will be:
+
+ glAlphaFunc( GL_GREATER, value )
+
+ "value" by default is 0, but you can change it from Tiled by adding the "cc_alpha_func" property to the layer.
+ The value 0 should work for most cases, but if you have tiles that are semi-transparent, then you might want to use a differnt
+ value, like 0.5.
+
+ For further information, please see the programming guide:
+
+ http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:tiled_maps
+
+ @since v0.8.1
+ */
+@interface CCTMXLayer : CCSpriteBatchNode
+{
+ CCTMXTilesetInfo *tileset_;
+ NSString *layerName_;
+ CGSize layerSize_;
+ CGSize mapTileSize_;
+ unsigned int *tiles_;
+ int layerOrientation_;
+ NSMutableArray *properties_;
+
+ unsigned char opacity_; // TMX Layer supports opacity
+
+ unsigned int minGID_;
+ unsigned int maxGID_;
+
+ // Only used when vertexZ is used
+ int vertexZvalue_;
+ BOOL useAutomaticVertexZ_;
+ float alphaFuncValue_;
+
+ // used for optimization
+ CCSprite *reusedTile_;
+ ccCArray *atlasIndexArray_;
+
+
+}
+/** name of the layer */
+@property (nonatomic,readwrite,retain) NSString *layerName;
+/** size of the layer in tiles */
+@property (nonatomic,readwrite) CGSize layerSize;
+/** size of the map's tile (could be differnt from the tile's size) */
+@property (nonatomic,readwrite) CGSize mapTileSize;
+/** pointer to the map of tiles */
+@property (nonatomic,readwrite) unsigned int *tiles;
+/** Tilset information for the layer */
+@property (nonatomic,readwrite,retain) CCTMXTilesetInfo *tileset;
+/** Layer orientation, which is the same as the map orientation */
+@property (nonatomic,readwrite) int layerOrientation;
+/** properties from the layer. They can be added using Tiled */
+@property (nonatomic,readwrite,retain) NSMutableArray *properties;
+
+/** creates a CCTMXLayer with an tileset info, a layer info and a map info */
++(id) layerWithTilesetInfo:(CCTMXTilesetInfo*)tilesetInfo layerInfo:(CCTMXLayerInfo*)layerInfo mapInfo:(CCTMXMapInfo*)mapInfo;
+/** initializes a CCTMXLayer with a tileset info, a layer info and a map info */
+-(id) initWithTilesetInfo:(CCTMXTilesetInfo*)tilesetInfo layerInfo:(CCTMXLayerInfo*)layerInfo mapInfo:(CCTMXMapInfo*)mapInfo;
+
+/** dealloc the map that contains the tile position from memory.
+ Unless you want to know at runtime the tiles positions, you can safely call this method.
+ If you are going to call [layer tileGIDAt:] then, don't release the map
+ */
+-(void) releaseMap;
+
+/** returns the tile (CCSprite) at a given a tile coordinate.
+ The returned CCSprite will be already added to the CCTMXLayer. Don't add it again.
+ The CCSprite can be treated like any other CCSprite: rotated, scaled, translated, opacity, color, etc.
+ You can remove either by calling:
+ - [layer removeChild:sprite cleanup:cleanup];
+ - or [layer removeTileAt:ccp(x,y)];
+ */
+-(CCSprite*) tileAt:(CGPoint)tileCoordinate;
+
+/** returns the tile gid at a given tile coordinate.
+ if it returns 0, it means that the tile is empty.
+ This method requires the the tile map has not been previously released (eg. don't call [layer releaseMap])
+ */
+-(unsigned int) tileGIDAt:(CGPoint)tileCoordinate;
+
+/** sets the tile gid (gid = tile global id) at a given tile coordinate.
+ The Tile GID can be obtained by using the method "tileGIDAt" or by using the TMX editor -> Tileset Mgr +1.
+ If a tile is already placed at that position, then it will be removed.
+ */
+-(void) setTileGID:(unsigned int)gid at:(CGPoint)tileCoordinate;
+
+/** removes a tile at given tile coordinate */
+-(void) removeTileAt:(CGPoint)tileCoordinate;
+
+/** returns the position in pixels of a given tile coordinate */
+-(CGPoint) positionAt:(CGPoint)tileCoordinate;
+
+/** return the value for the specific property name */
+-(id) propertyNamed:(NSString *)propertyName;
+
+/** Creates the tiles */
+-(void) setupTiles;
+
+/** CCTMXLayer doesn't support adding a CCSprite manually.
+ @warning addchild:z:tag: is not supported on CCTMXLayer. Instead of setTileGID:at:/tileAt:
+ */
+-(void) addChild: (CCNode*)node z:(int)z tag:(int)tag;
+@end
--- /dev/null
+/*
+ * 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.
+ *
+ *
+ * TMX Tiled Map support:
+ * http://www.mapeditor.org
+ *
+ */
+
+#import "CCTMXLayer.h"
+#import "CCTMXTiledMap.h"
+#import "CCTMXXMLParser.h"
+#import "CCSprite.h"
+#import "CCSpriteBatchNode.h"
+#import "CCTextureCache.h"
+#import "Support/CGPointExtension.h"
+
+#pragma mark -
+#pragma mark CCSpriteBatchNode Extension
+
+/* IMPORTANT XXX IMPORTNAT:
+ * These 2 methods can't be part of CCTMXLayer since they call [super add...], and CCSpriteSheet#add SHALL not be called
+ */
+@implementation CCSpriteBatchNode (TMXTiledMapExtension)
+
+/* Adds a quad into the texture atlas but it won't be added into the children array.
+ This method should be called only when you are dealing with very big AtlasSrite and when most of the CCSprite won't be updated.
+ For example: a tile map (CCTMXMap) or a label with lots of characgers (BitmapFontAtlas)
+ */
+-(void) addQuadFromSprite:(CCSprite*)sprite quadIndex:(unsigned int)index
+{
+ NSAssert( sprite != nil, @"Argument must be non-nil");
+ NSAssert( [sprite isKindOfClass:[CCSprite class]], @"CCSpriteSheet only supports CCSprites as children");
+
+
+ while(index >= textureAtlas_.capacity || textureAtlas_.capacity == textureAtlas_.totalQuads )
+ [self increaseAtlasCapacity];
+
+ //
+ // update the quad directly. Don't add the sprite to the scene graph
+ //
+
+ [sprite useBatchNode:self];
+ [sprite setAtlasIndex:index];
+
+ ccV3F_C4B_T2F_Quad quad = [sprite quad];
+ [textureAtlas_ insertQuad:&quad atIndex:index];
+
+ // XXX: updateTransform will update the textureAtlas too using updateQuad.
+ // XXX: so, it should be AFTER the insertQuad
+ [sprite setDirty:YES];
+ [sprite updateTransform];
+}
+
+/* This is the opposite of "addQuadFromSprite.
+ It add the sprite to the children and descendants array, but it doesn't update add it to the texture atlas
+ */
+-(id) addSpriteWithoutQuad:(CCSprite*)child z:(unsigned int)z tag:(int)aTag
+{
+ NSAssert( child != nil, @"Argument must be non-nil");
+ NSAssert( [child isKindOfClass:[CCSprite class]], @"CCSpriteSheet only supports CCSprites as children");
+
+ // quad index is Z
+ [child setAtlasIndex:z];
+
+ // XXX: optimize with a binary search
+ int i=0;
+ for( CCSprite *c in descendants_ ) {
+ if( c.atlasIndex >= z )
+ break;
+ i++;
+ }
+ [descendants_ insertObject:child atIndex:i];
+
+
+ // IMPORTANT: Call super, and not self. Avoid adding it to the texture atlas array
+ [super addChild:child z:z tag:aTag];
+ return self;
+}
+@end
+
+
+#pragma mark -
+#pragma mark CCTMXLayer
+
+@interface CCTMXLayer (Private)
+-(CGPoint) positionForIsoAt:(CGPoint)pos;
+-(CGPoint) positionForOrthoAt:(CGPoint)pos;
+-(CGPoint) positionForHexAt:(CGPoint)pos;
+
+-(CGPoint) calculateLayerOffset:(CGPoint)offset;
+
+/* optimization methos */
+-(CCSprite*) appendTileForGID:(unsigned int)gid at:(CGPoint)pos;
+-(CCSprite*) insertTileForGID:(unsigned int)gid at:(CGPoint)pos;
+-(CCSprite*) updateTileForGID:(unsigned int)gid at:(CGPoint)pos;
+
+/* The layer recognizes some special properties, like cc_vertez */
+-(void) parseInternalProperties;
+
+-(int) vertexZForPos:(CGPoint)pos;
+
+// adding quad from sprite
+-(void)addQuadFromSprite:(CCSprite*)sprite quadIndex:(unsigned int)index;
+
+// adds an sprite without the quad
+-(id)addSpriteWithoutQuad:(CCSprite*)child z:(int)z tag:(int)aTag;
+
+// index
+-(NSUInteger) atlasIndexForExistantZ:(NSUInteger)z;
+-(NSUInteger) atlasIndexForNewZ:(NSUInteger)z;
+@end
+
+@implementation CCTMXLayer
+@synthesize layerSize = layerSize_, layerName = layerName_, tiles = tiles_;
+@synthesize tileset = tileset_;
+@synthesize layerOrientation = layerOrientation_;
+@synthesize mapTileSize = mapTileSize_;
+@synthesize properties = properties_;
+
+#pragma mark CCTMXLayer - init & alloc & dealloc
+
++(id) layerWithTilesetInfo:(CCTMXTilesetInfo*)tilesetInfo layerInfo:(CCTMXLayerInfo*)layerInfo mapInfo:(CCTMXMapInfo*)mapInfo
+{
+ return [[[self alloc] initWithTilesetInfo:tilesetInfo layerInfo:layerInfo mapInfo:mapInfo] autorelease];
+}
+
+-(id) initWithTilesetInfo:(CCTMXTilesetInfo*)tilesetInfo layerInfo:(CCTMXLayerInfo*)layerInfo mapInfo:(CCTMXMapInfo*)mapInfo
+{
+ // XXX: is 35% a good estimate ?
+ CGSize size = layerInfo.layerSize;
+ float totalNumberOfTiles = size.width * size.height;
+ float capacity = totalNumberOfTiles * 0.35f + 1; // 35 percent is occupied ?
+
+ CCTexture2D *tex = nil;
+ if( tilesetInfo )
+ tex = [[CCTextureCache sharedTextureCache] addImage:tilesetInfo.sourceImage];
+
+ if((self = [super initWithTexture:tex capacity:capacity])) {
+
+ // layerInfo
+ self.layerName = layerInfo.name;
+ layerSize_ = layerInfo.layerSize;
+ tiles_ = layerInfo.tiles;
+ minGID_ = layerInfo.minGID;
+ maxGID_ = layerInfo.maxGID;
+ opacity_ = layerInfo.opacity;
+ self.properties = [NSMutableDictionary dictionaryWithDictionary:layerInfo.properties];
+
+ // tilesetInfo
+ self.tileset = tilesetInfo;
+
+ // mapInfo
+ mapTileSize_ = mapInfo.tileSize;
+ layerOrientation_ = mapInfo.orientation;
+
+ // offset (after layer orientation is set);
+ CGPoint offset = [self calculateLayerOffset:layerInfo.offset];
+ [self setPositionInPixels:offset];
+
+ atlasIndexArray_ = ccCArrayNew(totalNumberOfTiles);
+
+ [self setContentSizeInPixels: CGSizeMake( layerSize_.width * mapTileSize_.width, layerSize_.height * mapTileSize_.height )];
+
+ useAutomaticVertexZ_= NO;
+ vertexZvalue_ = 0;
+ alphaFuncValue_ = 0;
+
+ }
+ return self;
+}
+
+- (void) dealloc
+{
+ [layerName_ release];
+ [tileset_ release];
+ [reusedTile_ release];
+ [properties_ release];
+
+ if( atlasIndexArray_ ) {
+ ccCArrayFree(atlasIndexArray_);
+ atlasIndexArray_ = NULL;
+ }
+
+ if( tiles_ ) {
+ free(tiles_);
+ tiles_ = NULL;
+ }
+
+ [super dealloc];
+}
+
+-(void) releaseMap
+{
+ if( tiles_) {
+ free( tiles_);
+ tiles_ = NULL;
+ }
+
+ if( atlasIndexArray_ ) {
+ ccCArrayFree(atlasIndexArray_);
+ atlasIndexArray_ = NULL;
+ }
+}
+
+#pragma mark CCTMXLayer - setup Tiles
+
+-(void) setupTiles
+{
+ // Optimization: quick hack that sets the image size on the tileset
+ tileset_.imageSize = [textureAtlas_.texture contentSizeInPixels];
+
+ // By default all the tiles are aliased
+ // pros:
+ // - easier to render
+ // cons:
+ // - difficult to scale / rotate / etc.
+ [textureAtlas_.texture setAliasTexParameters];
+
+ CFByteOrder o = CFByteOrderGetCurrent();
+
+ // Parse cocos2d properties
+ [self parseInternalProperties];
+
+ for( unsigned int y=0; y < layerSize_.height; y++ ) {
+ for( unsigned int x=0; x < layerSize_.width; x++ ) {
+
+ unsigned int pos = x + layerSize_.width * y;
+ unsigned int gid = tiles_[ pos ];
+
+ // gid are stored in little endian.
+ // if host is big endian, then swap
+ if( o == CFByteOrderBigEndian )
+ gid = CFSwapInt32( gid );
+
+ // XXX: gid == 0 --> empty tile
+ if( gid != 0 ) {
+ [self appendTileForGID:gid at:ccp(x,y)];
+
+ // Optimization: update min and max GID rendered by the layer
+ minGID_ = MIN(gid, minGID_);
+ maxGID_ = MAX(gid, maxGID_);
+ }
+ }
+ }
+
+ NSAssert( maxGID_ >= tileset_.firstGid &&
+ minGID_ >= tileset_.firstGid, @"TMX: Only 1 tilset per layer is supported");
+}
+
+#pragma mark CCTMXLayer - Properties
+
+-(id) propertyNamed:(NSString *)propertyName
+{
+ return [properties_ valueForKey:propertyName];
+}
+
+-(void) parseInternalProperties
+{
+ // if cc_vertex=automatic, then tiles will be rendered using vertexz
+
+ NSString *vertexz = [self propertyNamed:@"cc_vertexz"];
+ if( vertexz ) {
+ if( [vertexz isEqualToString:@"automatic"] )
+ useAutomaticVertexZ_ = YES;
+ else
+ vertexZvalue_ = [vertexz intValue];
+ }
+
+ NSString *alphaFuncVal = [self propertyNamed:@"cc_alpha_func"];
+ alphaFuncValue_ = [alphaFuncVal floatValue];
+}
+
+#pragma mark CCTMXLayer - obtaining tiles/gids
+
+-(CCSprite*) tileAt:(CGPoint)pos
+{
+ NSAssert( pos.x < layerSize_.width && pos.y < layerSize_.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position");
+ NSAssert( tiles_ && atlasIndexArray_, @"TMXLayer: the tiles map has been released");
+
+ CCSprite *tile = nil;
+ unsigned int gid = [self tileGIDAt:pos];
+
+ // if GID == 0, then no tile is present
+ if( gid ) {
+ int z = pos.x + pos.y * layerSize_.width;
+ tile = (CCSprite*) [self getChildByTag:z];
+
+ // tile not created yet. create it
+ if( ! tile ) {
+ CGRect rect = [tileset_ rectForGID:gid];
+ tile = [[CCSprite alloc] initWithBatchNode:self rectInPixels:rect];
+ [tile setPositionInPixels: [self positionAt:pos]];
+ [tile setVertexZ: [self vertexZForPos:pos]];
+ tile.anchorPoint = CGPointZero;
+ [tile setOpacity:opacity_];
+
+ unsigned int indexForZ = [self atlasIndexForExistantZ:z];
+ [self addSpriteWithoutQuad:tile z:indexForZ tag:z];
+ [tile release];
+ }
+ }
+ return tile;
+}
+
+-(unsigned int) tileGIDAt:(CGPoint)pos
+{
+ NSAssert( pos.x < layerSize_.width && pos.y < layerSize_.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position");
+ NSAssert( tiles_ && atlasIndexArray_, @"TMXLayer: the tiles map has been released");
+
+ int idx = pos.x + pos.y * layerSize_.width;
+ return tiles_[ idx ];
+}
+
+#pragma mark CCTMXLayer - adding helper methods
+
+-(CCSprite*) insertTileForGID:(unsigned int)gid at:(CGPoint)pos
+{
+ CGRect rect = [tileset_ rectForGID:gid];
+
+ NSInteger z = pos.x + pos.y * layerSize_.width;
+
+ if( ! reusedTile_ )
+ reusedTile_ = [[CCSprite alloc] initWithBatchNode:self rectInPixels:rect];
+ else
+ [reusedTile_ initWithBatchNode:self rectInPixels:rect];
+
+ [reusedTile_ setPositionInPixels: [self positionAt:pos]];
+ [reusedTile_ setVertexZ: [self vertexZForPos:pos]];
+ reusedTile_.anchorPoint = CGPointZero;
+ [reusedTile_ setOpacity:opacity_];
+
+ // get atlas index
+ NSUInteger indexForZ = [self atlasIndexForNewZ:z];
+
+ // Optimization: add the quad without adding a child
+ [self addQuadFromSprite:reusedTile_ quadIndex:indexForZ];
+
+ // insert it into the local atlasindex array
+ ccCArrayInsertValueAtIndex(atlasIndexArray_, (void*)z, indexForZ);
+
+ // update possible children
+ CCSprite *sprite;
+ CCARRAY_FOREACH(children_, sprite) {
+ unsigned int ai = [sprite atlasIndex];
+ if( ai >= indexForZ)
+ [sprite setAtlasIndex: ai+1];
+ }
+
+ tiles_[z] = gid;
+
+ return reusedTile_;
+}
+
+-(CCSprite*) updateTileForGID:(unsigned int)gid at:(CGPoint)pos
+{
+ CGRect rect = [tileset_ rectForGID:gid];
+
+ int z = pos.x + pos.y * layerSize_.width;
+
+ if( ! reusedTile_ )
+ reusedTile_ = [[CCSprite alloc] initWithBatchNode:self rectInPixels:rect];
+ else
+ [reusedTile_ initWithBatchNode:self rectInPixels:rect];
+
+ [reusedTile_ setPositionInPixels: [self positionAt:pos]];
+ [reusedTile_ setVertexZ: [self vertexZForPos:pos]];
+ reusedTile_.anchorPoint = CGPointZero;
+ [reusedTile_ setOpacity:opacity_];
+
+ // get atlas index
+ unsigned int indexForZ = [self atlasIndexForExistantZ:z];
+
+ [reusedTile_ setAtlasIndex:indexForZ];
+ [reusedTile_ setDirty:YES];
+ [reusedTile_ updateTransform];
+ tiles_[z] = gid;
+
+ return reusedTile_;
+}
+
+
+// used only when parsing the map. useless after the map was parsed
+// since lot's of assumptions are no longer true
+-(CCSprite*) appendTileForGID:(unsigned int)gid at:(CGPoint)pos
+{
+ CGRect rect = [tileset_ rectForGID:gid];
+
+ NSInteger z = pos.x + pos.y * layerSize_.width;
+
+ if( ! reusedTile_ )
+ reusedTile_ = [[CCSprite alloc] initWithBatchNode:self rectInPixels:rect];
+ else
+ [reusedTile_ initWithBatchNode:self rectInPixels:rect];
+
+ [reusedTile_ setPositionInPixels: [self positionAt:pos]];
+ [reusedTile_ setVertexZ: [self vertexZForPos:pos]];
+ reusedTile_.anchorPoint = CGPointZero;
+ [reusedTile_ setOpacity:opacity_];
+
+ // optimization:
+ // The difference between appendTileForGID and insertTileforGID is that append is faster, since
+ // it appends the tile at the end of the texture atlas
+ NSUInteger indexForZ = atlasIndexArray_->num;
+
+
+ // don't add it using the "standard" way.
+ [self addQuadFromSprite:reusedTile_ quadIndex:indexForZ];
+
+
+ // append should be after addQuadFromSprite since it modifies the quantity values
+ ccCArrayInsertValueAtIndex(atlasIndexArray_, (void*)z, indexForZ);
+
+ return reusedTile_;
+}
+
+#pragma mark CCTMXLayer - atlasIndex and Z
+
+int compareInts (const void * a, const void * b)
+{
+ return ( *(int*)a - *(int*)b );
+}
+
+-(NSUInteger) atlasIndexForExistantZ:(NSUInteger)z
+{
+ NSInteger key = z;
+ NSInteger *item = bsearch((void*)&key, (void*)&atlasIndexArray_->arr[0], atlasIndexArray_->num, sizeof(void*), compareInts);
+
+ NSAssert( item, @"TMX atlas index not found. Shall not happen");
+
+ NSUInteger index = ((NSInteger)item - (NSInteger)atlasIndexArray_->arr) / sizeof(void*);
+ return index;
+}
+
+-(NSUInteger)atlasIndexForNewZ:(NSUInteger)z
+{
+ // XXX: This can be improved with a sort of binary search
+ NSUInteger i = 0;
+ for(i = 0; i< atlasIndexArray_->num; i++) {
+ NSUInteger val = (NSUInteger) atlasIndexArray_->arr[i];
+ if( z < val )
+ break;
+ }
+ return i;
+}
+
+#pragma mark CCTMXLayer - adding / remove tiles
+
+-(void) setTileGID:(unsigned int)gid at:(CGPoint)pos
+{
+ NSAssert( pos.x < layerSize_.width && pos.y < layerSize_.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position");
+ NSAssert( tiles_ && atlasIndexArray_, @"TMXLayer: the tiles map has been released");
+ NSAssert( gid == 0 || gid >= tileset_.firstGid, @"TMXLayer: invalid gid" );
+
+ unsigned int currentGID = [self tileGIDAt:pos];
+
+ if( currentGID != gid ) {
+
+ // setting gid=0 is equal to remove the tile
+ if( gid == 0 )
+ [self removeTileAt:pos];
+
+ // empty tile. create a new one
+ else if( currentGID == 0 )
+ [self insertTileForGID:gid at:pos];
+
+ // modifying an existing tile with a non-empty tile
+ else {
+
+ unsigned int z = pos.x + pos.y * layerSize_.width;
+ id sprite = [self getChildByTag:z];
+ if( sprite ) {
+ CGRect rect = [tileset_ rectForGID:gid];
+ [sprite setTextureRectInPixels:rect rotated:NO untrimmedSize:rect.size];
+ tiles_[z] = gid;
+ } else
+ [self updateTileForGID:gid at:pos];
+ }
+ }
+}
+
+-(void) addChild: (CCNode*)node z:(int)z tag:(int)tag
+{
+ NSAssert(NO, @"addChild: is not supported on CCTMXLayer. Instead use setTileGID:at:/tileAt:");
+}
+
+-(void) removeChild:(CCSprite*)sprite cleanup:(BOOL)cleanup
+{
+ // allows removing nil objects
+ if( ! sprite )
+ return;
+
+ NSAssert( [children_ containsObject:sprite], @"Tile does not belong to TMXLayer");
+
+ unsigned int atlasIndex = [sprite atlasIndex];
+ NSUInteger zz = (NSUInteger) atlasIndexArray_->arr[atlasIndex];
+ tiles_[zz] = 0;
+ ccCArrayRemoveValueAtIndex(atlasIndexArray_, atlasIndex);
+ [super removeChild:sprite cleanup:cleanup];
+}
+
+-(void) removeTileAt:(CGPoint)pos
+{
+ NSAssert( pos.x < layerSize_.width && pos.y < layerSize_.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position");
+ NSAssert( tiles_ && atlasIndexArray_, @"TMXLayer: the tiles map has been released");
+
+ unsigned int gid = [self tileGIDAt:pos];
+
+ if( gid ) {
+
+ unsigned int z = pos.x + pos.y * layerSize_.width;
+ unsigned atlasIndex = [self atlasIndexForExistantZ:z];
+
+ // remove tile from GID map
+ tiles_[z] = 0;
+
+ // remove tile from atlas position array
+ ccCArrayRemoveValueAtIndex(atlasIndexArray_, atlasIndex);
+
+ // remove it from sprites and/or texture atlas
+ id sprite = [self getChildByTag:z];
+ if( sprite )
+ [super removeChild:sprite cleanup:YES];
+ else {
+ [textureAtlas_ removeQuadAtIndex:atlasIndex];
+
+ // update possible children
+ CCSprite *sprite;
+ CCARRAY_FOREACH(children_, sprite) {
+ unsigned int ai = [sprite atlasIndex];
+ if( ai >= atlasIndex) {
+ [sprite setAtlasIndex: ai-1];
+ }
+ }
+ }
+ }
+}
+
+#pragma mark CCTMXLayer - obtaining positions, offset
+
+-(CGPoint) calculateLayerOffset:(CGPoint)pos
+{
+ CGPoint ret = CGPointZero;
+ switch( layerOrientation_ ) {
+ case CCTMXOrientationOrtho:
+ ret = ccp( pos.x * mapTileSize_.width, -pos.y *mapTileSize_.height);
+ break;
+ case CCTMXOrientationIso:
+ ret = ccp( (mapTileSize_.width /2) * (pos.x - pos.y),
+ (mapTileSize_.height /2 ) * (-pos.x - pos.y) );
+ break;
+ case CCTMXOrientationHex:
+ NSAssert(CGPointEqualToPoint(pos, CGPointZero), @"offset for hexagonal map not implemented yet");
+ break;
+ }
+ return ret;
+}
+
+-(CGPoint) positionAt:(CGPoint)pos
+{
+ CGPoint ret = CGPointZero;
+ switch( layerOrientation_ ) {
+ case CCTMXOrientationOrtho:
+ ret = [self positionForOrthoAt:pos];
+ break;
+ case CCTMXOrientationIso:
+ ret = [self positionForIsoAt:pos];
+ break;
+ case CCTMXOrientationHex:
+ ret = [self positionForHexAt:pos];
+ break;
+ }
+ return ret;
+}
+
+-(CGPoint) positionForOrthoAt:(CGPoint)pos
+{
+ CGPoint xy = {
+ pos.x * mapTileSize_.width,
+ (layerSize_.height - pos.y - 1) * mapTileSize_.height,
+ };
+ return xy;
+}
+
+-(CGPoint) positionForIsoAt:(CGPoint)pos
+{
+ CGPoint xy = {
+ mapTileSize_.width /2 * ( layerSize_.width + pos.x - pos.y - 1),
+ mapTileSize_.height /2 * (( layerSize_.height * 2 - pos.x - pos.y) - 2),
+ };
+ return xy;
+}
+
+-(CGPoint) positionForHexAt:(CGPoint)pos
+{
+ float diffY = 0;
+ if( (int)pos.x % 2 == 1 )
+ diffY = -mapTileSize_.height/2 ;
+
+ CGPoint xy = {
+ pos.x * mapTileSize_.width*3/4,
+ (layerSize_.height - pos.y - 1) * mapTileSize_.height + diffY
+ };
+ return xy;
+}
+
+-(int) vertexZForPos:(CGPoint)pos
+{
+ int ret = 0;
+ unsigned int maxVal = 0;
+ if( useAutomaticVertexZ_ ) {
+ switch( layerOrientation_ ) {
+ case CCTMXOrientationIso:
+ maxVal = layerSize_.width + layerSize_.height;
+ ret = -(maxVal - (pos.x + pos.y));
+ break;
+ case CCTMXOrientationOrtho:
+ ret = -(layerSize_.height-pos.y);
+ break;
+ case CCTMXOrientationHex:
+ NSAssert(NO,@"TMX Hexa zOrder not supported");
+ break;
+ default:
+ NSAssert(NO,@"TMX invalid value");
+ break;
+ }
+ } else
+ ret = vertexZvalue_;
+
+ return ret;
+}
+
+#pragma mark CCTMXLayer - draw
+
+-(void) draw
+{
+ if( useAutomaticVertexZ_ ) {
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GREATER, alphaFuncValue_);
+ }
+
+ [super draw];
+
+ if( useAutomaticVertexZ_ )
+ glDisable(GL_ALPHA_TEST);
+}
+@end
+
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * Copyright (c) 2010 Ricardo Quesada
+ * Copyright (c) 2010 Neophit
+ *
+ * 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.
+ *
+ *
+ * TMX Tiled Map support:
+ * http://www.mapeditor.org
+ *
+ */
+
+#import "CCSpriteSheet.h"
+
+
+@class CCTMXObjectGroup;
+
+
+/** CCTMXObjectGroup represents the TMX object group.
+@since v0.99.0
+*/
+@interface CCTMXObjectGroup : NSObject
+{
+ NSString *groupName_;
+ CGPoint positionOffset_;
+ NSMutableArray *objects_;
+ NSMutableDictionary *properties_;
+}
+
+/** name of the group */
+@property (nonatomic,readwrite,retain) NSString *groupName;
+/** offset position of child objects */
+@property (nonatomic,readwrite,assign) CGPoint positionOffset;
+/** array of the objects */
+@property (nonatomic,readwrite,retain) NSMutableArray *objects;
+/** list of properties stored in a dictionary */
+@property (nonatomic,readwrite,retain) NSMutableDictionary *properties;
+
+/** return the value for the specific property name */
+-(id) propertyNamed:(NSString *)propertyName;
+
+/** return the dictionary for the specific object name.
+ It will return the 1st object found on the array for the given name.
+ */
+-(NSMutableDictionary*) objectNamed:(NSString *)objectName;
+
+@end
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * Copyright (c) 2010 Ricardo Quesada
+ * Copyright (c) 2010 Neophit
+ *
+ * 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.
+ *
+ *
+ * TMX Tiled Map support:
+ * http://www.mapeditor.org
+ *
+ */
+
+#import "CCTMXObjectGroup.h"
+#import "CCTMXXMLParser.h"
+#import "Support/CGPointExtension.h"
+
+
+#pragma mark -
+#pragma mark TMXObjectGroup
+
+@implementation CCTMXObjectGroup
+
+@synthesize groupName = groupName_;
+@synthesize objects = objects_;
+@synthesize positionOffset = positionOffset_;
+@synthesize properties = properties_;
+
+-(id) init
+{
+ if (( self=[super init] )) {
+ self.groupName = nil;
+ self.positionOffset = CGPointZero;
+ self.objects = [NSMutableArray arrayWithCapacity:10];
+ self.properties = [NSMutableDictionary dictionaryWithCapacity:5];
+ }
+ return self;
+}
+
+-(void) dealloc
+{
+ CCLOGINFO( @"cocos2d: deallocing %@", self );
+
+ [groupName_ release];
+ [objects_ release];
+ [properties_ release];
+ [super dealloc];
+}
+
+-(NSMutableDictionary*) objectNamed:(NSString *)objectName
+{
+ for( id object in objects_ ) {
+ if( [[object valueForKey:@"name"] isEqual:objectName] )
+ return object;
+ }
+
+ // object not found
+ return nil;
+}
+
+-(id) propertyNamed:(NSString *)propertyName
+{
+ return [properties_ valueForKey:propertyName];
+}
+
+@end
--- /dev/null
+/*
+ * 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.
+ *
+ *
+ * TMX Tiled Map support:
+ * http://www.mapeditor.org
+ *
+ */
+
+#import "CCSpriteSheet.h"
+
+
+@class CCTMXLayer;
+@class CCTMXObjectGroup;
+
+/** Possible oritentations of the TMX map */
+enum
+{
+ /** Orthogonal orientation */
+ CCTMXOrientationOrtho,
+
+ /** Hexagonal orientation */
+ CCTMXOrientationHex,
+
+ /** Isometric orientation */
+ CCTMXOrientationIso,
+};
+
+/** CCTMXTiledMap knows how to parse and render a TMX map.
+
+ It adds support for the TMX tiled map format used by http://www.mapeditor.org
+ It supports isometric, hexagonal and orthogonal tiles.
+ It also supports object groups, objects, and properties.
+
+ Features:
+ - Each tile will be treated as an CCSprite
+ - The sprites are created on demand. They will be created only when you call "[layer tileAt:]"
+ - Each tile can be rotated / moved / scaled / tinted / "opacitied", since each tile is a CCSprite
+ - Tiles can be added/removed in runtime
+ - The z-order of the tiles can be modified in runtime
+ - Each tile has an anchorPoint of (0,0)
+ - The anchorPoint of the TMXTileMap is (0,0)
+ - The TMX layers will be added as a child
+ - The TMX layers will be aliased by default
+ - The tileset image will be loaded using the CCTextureCache
+ - Each tile will have a unique tag
+ - Each tile will have a unique z value. top-left: z=1, bottom-right: z=max z
+ - Each object group will be treated as an NSMutableArray
+ - Object class which will contain all the properties in a dictionary
+ - Properties can be assigned to the Map, Layer, Object Group, and Object
+
+ Limitations:
+ - It only supports one tileset per layer.
+ - Embeded images are not supported
+ - It only supports the XML format (the JSON format is not supported)
+
+ Technical description:
+ Each layer is created using an CCTMXLayer (subclass of CCSpriteSheet). If you have 5 layers, then 5 CCTMXLayer will be created,
+ unless the layer visibility is off. In that case, the layer won't be created at all.
+ You can obtain the layers (CCTMXLayer objects) at runtime by:
+ - [map getChildByTag: tag_number]; // 0=1st layer, 1=2nd layer, 2=3rd layer, etc...
+ - [map layerNamed: name_of_the_layer];
+
+ Each object group is created using a CCTMXObjectGroup which is a subclass of NSMutableArray.
+ You can obtain the object groups at runtime by:
+ - [map objectGroupNamed: name_of_the_object_group];
+
+ Each object is a CCTMXObject.
+
+ Each property is stored as a key-value pair in an NSMutableDictionary.
+ You can obtain the properties at runtime by:
+
+ [map propertyNamed: name_of_the_property];
+ [layer propertyNamed: name_of_the_property];
+ [objectGroup propertyNamed: name_of_the_property];
+ [object propertyNamed: name_of_the_property];
+
+ @since v0.8.1
+ */
+@interface CCTMXTiledMap : CCNode
+{
+ CGSize mapSize_;
+ CGSize tileSize_;
+ int mapOrientation_;
+ NSMutableArray *objectGroups_;
+ NSMutableDictionary *properties_;
+ NSMutableDictionary *tileProperties_;
+}
+
+/** the map's size property measured in tiles */
+@property (nonatomic,readonly) CGSize mapSize;
+/** the tiles's size property measured in pixels */
+@property (nonatomic,readonly) CGSize tileSize;
+/** map orientation */
+@property (nonatomic,readonly) int mapOrientation;
+/** object groups */
+@property (nonatomic,readwrite,retain) NSMutableArray *objectGroups;
+/** properties */
+@property (nonatomic,readwrite,retain) NSMutableDictionary *properties;
+
+/** creates a TMX Tiled Map with a TMX file.*/
++(id) tiledMapWithTMXFile:(NSString*)tmxFile;
+
+/** initializes a TMX Tiled Map with a TMX file */
+-(id) initWithTMXFile:(NSString*)tmxFile;
+
+/** return the TMXLayer for the specific layer */
+-(CCTMXLayer*) layerNamed:(NSString *)layerName;
+
+/** return the TMXObjectGroup for the secific group */
+-(CCTMXObjectGroup*) objectGroupNamed:(NSString *)groupName;
+
+/** return the TMXObjectGroup for the secific group
+ @deprecated Use map#objectGroupNamed instead
+ */
+-(CCTMXObjectGroup*) groupNamed:(NSString *)groupName DEPRECATED_ATTRIBUTE;
+
+/** return the value for the specific property name */
+-(id) propertyNamed:(NSString *)propertyName;
+
+/** return properties dictionary for tile GID */
+-(NSDictionary*)propertiesForGID:(unsigned int)GID;
+@end
+
--- /dev/null
+/*
+ * 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.
+ *
+ *
+ * TMX Tiled Map support:
+ * http://www.mapeditor.org
+ *
+ */
+
+#import "CCTMXTiledMap.h"
+#import "CCTMXXMLParser.h"
+#import "CCTMXLayer.h"
+#import "CCTMXObjectGroup.h"
+#import "CCSprite.h"
+#import "CCSpriteSheet.h"
+#import "CCTextureCache.h"
+#import "Support/CGPointExtension.h"
+
+
+#pragma mark -
+#pragma mark CCTMXTiledMap
+
+@interface CCTMXTiledMap (Private)
+-(id) parseLayer:(CCTMXLayerInfo*)layer map:(CCTMXMapInfo*)mapInfo;
+-(CCTMXTilesetInfo*) tilesetForLayer:(CCTMXLayerInfo*)layerInfo map:(CCTMXMapInfo*)mapInfo;
+@end
+
+@implementation CCTMXTiledMap
+@synthesize mapSize = mapSize_;
+@synthesize tileSize = tileSize_;
+@synthesize mapOrientation = mapOrientation_;
+@synthesize objectGroups = objectGroups_;
+@synthesize properties = properties_;
+
++(id) tiledMapWithTMXFile:(NSString*)tmxFile
+{
+ return [[[self alloc] initWithTMXFile:tmxFile] autorelease];
+}
+
+-(id) initWithTMXFile:(NSString*)tmxFile
+{
+ NSAssert(tmxFile != nil, @"TMXTiledMap: tmx file should not bi nil");
+
+ if ((self=[super init])) {
+
+ [self setContentSize:CGSizeZero];
+
+ CCTMXMapInfo *mapInfo = [CCTMXMapInfo formatWithTMXFile:tmxFile];
+
+ NSAssert( [mapInfo.tilesets count] != 0, @"TMXTiledMap: Map not found. Please check the filename.");
+
+ mapSize_ = mapInfo.mapSize;
+ tileSize_ = mapInfo.tileSize;
+ mapOrientation_ = mapInfo.orientation;
+ objectGroups_ = [mapInfo.objectGroups retain];
+ properties_ = [mapInfo.properties retain];
+ tileProperties_ = [mapInfo.tileProperties retain];
+
+ int idx=0;
+
+ for( CCTMXLayerInfo *layerInfo in mapInfo.layers ) {
+
+ if( layerInfo.visible ) {
+ CCNode *child = [self parseLayer:layerInfo map:mapInfo];
+ [self addChild:child z:idx tag:idx];
+
+ // update content size with the max size
+ CGSize childSize = [child contentSize];
+ CGSize currentSize = [self contentSize];
+ currentSize.width = MAX( currentSize.width, childSize.width );
+ currentSize.height = MAX( currentSize.height, childSize.height );
+ [self setContentSize:currentSize];
+
+ idx++;
+ }
+ }
+ }
+
+ return self;
+}
+
+-(void) dealloc
+{
+ [objectGroups_ release];
+ [properties_ release];
+ [tileProperties_ release];
+ [super dealloc];
+}
+
+// private
+-(id) parseLayer:(CCTMXLayerInfo*)layerInfo map:(CCTMXMapInfo*)mapInfo
+{
+ CCTMXTilesetInfo *tileset = [self tilesetForLayer:layerInfo map:mapInfo];
+ CCTMXLayer *layer = [CCTMXLayer layerWithTilesetInfo:tileset layerInfo:layerInfo mapInfo:mapInfo];
+
+ // tell the layerinfo to release the ownership of the tiles map.
+ layerInfo.ownTiles = NO;
+
+ [layer setupTiles];
+
+ return layer;
+}
+
+-(CCTMXTilesetInfo*) tilesetForLayer:(CCTMXLayerInfo*)layerInfo map:(CCTMXMapInfo*)mapInfo
+{
+ CCTMXTilesetInfo *tileset = nil;
+ CFByteOrder o = CFByteOrderGetCurrent();
+
+ CGSize size = layerInfo.layerSize;
+
+ id iter = [mapInfo.tilesets reverseObjectEnumerator];
+ for( CCTMXTilesetInfo* tileset in iter) {
+ for( unsigned int y = 0; y < size.height; y++ ) {
+ for( unsigned int x = 0; x < size.width; x++ ) {
+
+ unsigned int pos = x + size.width * y;
+ unsigned int gid = layerInfo.tiles[ pos ];
+
+ // gid are stored in little endian.
+ // if host is big endian, then swap
+ if( o == CFByteOrderBigEndian )
+ gid = CFSwapInt32( gid );
+
+ // XXX: gid == 0 --> empty tile
+ if( gid != 0 ) {
+
+ // Optimization: quick return
+ // if the layer is invalid (more than 1 tileset per layer) an assert will be thrown later
+ if( gid >= tileset.firstGid )
+ return tileset;
+ }
+ }
+ }
+ }
+
+ // If all the tiles are 0, return empty tileset
+ CCLOG(@"cocos2d: Warning: TMX Layer '%@' has no tiles", layerInfo.name);
+ return tileset;
+}
+
+
+// public
+
+-(CCTMXLayer*) layerNamed:(NSString *)layerName
+{
+ CCTMXLayer *layer;
+ CCARRAY_FOREACH(children_, layer) {
+ if([layer isKindOfClass:[CCTMXLayer class]])
+ if([layer.layerName isEqual:layerName])
+ return layer;
+ }
+
+ // layer not found
+ return nil;
+}
+
+-(CCTMXObjectGroup*) objectGroupNamed:(NSString *)groupName
+{
+ for( CCTMXObjectGroup *objectGroup in objectGroups_ ) {
+ if( [objectGroup.groupName isEqual:groupName] )
+ return objectGroup;
+ }
+
+ // objectGroup not found
+ return nil;
+}
+
+// XXX deprecated
+-(CCTMXObjectGroup*) groupNamed:(NSString *)groupName
+{
+ return [self objectGroupNamed:groupName];
+}
+
+-(id) propertyNamed:(NSString *)propertyName
+{
+ return [properties_ valueForKey:propertyName];
+}
+-(NSDictionary*)propertiesForGID:(unsigned int)GID{
+ return [tileProperties_ objectForKey:[NSNumber numberWithInt:GID]];
+}
+@end
+
--- /dev/null
+/*
+ * 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.
+ *
+ *
+ * TMX Tiled Map support:
+ * http://www.mapeditor.org
+ *
+ */
+
+/*
+ * Internal TMX parser
+ *
+ * IMPORTANT: These classed should not be documented using doxygen strings
+ * since the user should not use them.
+ *
+ */
+
+
+#import <Availability.h>
+#import <Foundation/Foundation.h>
+
+enum {
+ TMXLayerAttribNone = 1 << 0,
+ TMXLayerAttribBase64 = 1 << 1,
+ TMXLayerAttribGzip = 1 << 2,
+};
+
+enum {
+ TMXPropertyNone,
+ TMXPropertyMap,
+ TMXPropertyLayer,
+ TMXPropertyObjectGroup,
+ TMXPropertyObject,
+ TMXPropertyTile
+};
+
+/* CCTMXLayerInfo contains the information about the layers like:
+ - Layer name
+ - Layer size
+ - Layer opacity at creation time (it can be modified at runtime)
+ - Whether the layer is visible (if it's not visible, then the CocosNode won't be created)
+
+ This information is obtained from the TMX file.
+ */
+@interface CCTMXLayerInfo : NSObject
+{
+ NSString *name_;
+ CGSize layerSize_;
+ unsigned int *tiles_;
+ BOOL visible_;
+ unsigned char opacity_;
+ BOOL ownTiles_;
+ unsigned int minGID_;
+ unsigned int maxGID_;
+ NSMutableDictionary *properties_;
+ CGPoint offset_;
+}
+
+@property (nonatomic,readwrite,retain) NSString *name;
+@property (nonatomic,readwrite) CGSize layerSize;
+@property (nonatomic,readwrite) unsigned int *tiles;
+@property (nonatomic,readwrite) BOOL visible;
+@property (nonatomic,readwrite) unsigned char opacity;
+@property (nonatomic,readwrite) BOOL ownTiles;
+@property (nonatomic,readwrite) unsigned int minGID;
+@property (nonatomic,readwrite) unsigned int maxGID;
+@property (nonatomic,readwrite,retain) NSMutableDictionary *properties;
+@property (nonatomic,readwrite) CGPoint offset;
+@end
+
+/* CCTMXTilesetInfo contains the information about the tilesets like:
+ - Tileset name
+ - Tilset spacing
+ - Tileset margin
+ - size of the tiles
+ - Image used for the tiles
+ - Image size
+
+ This information is obtained from the TMX file.
+ */
+@interface CCTMXTilesetInfo : NSObject
+{
+ NSString *name_;
+ unsigned int firstGid_;
+ CGSize tileSize_;
+ unsigned int spacing_;
+ unsigned int margin_;
+
+ // filename containing the tiles (should be spritesheet / texture atlas)
+ NSString *sourceImage_;
+
+ // size in pixels of the image
+ CGSize imageSize_;
+}
+@property (nonatomic,readwrite,retain) NSString *name;
+@property (nonatomic,readwrite,assign) unsigned int firstGid;
+@property (nonatomic,readwrite,assign) CGSize tileSize;
+@property (nonatomic,readwrite,assign) unsigned int spacing;
+@property (nonatomic,readwrite,assign) unsigned int margin;
+@property (nonatomic,readwrite,retain) NSString *sourceImage;
+@property (nonatomic,readwrite,assign) CGSize imageSize;
+
+-(CGRect) rectForGID:(unsigned int)gid;
+@end
+
+/* CCTMXMapInfo contains the information about the map like:
+ - Map orientation (hexagonal, isometric or orthogonal)
+ - Tile size
+ - Map size
+
+ And it also contains:
+ - Layers (an array of TMXLayerInfo objects)
+ - Tilesets (an array of TMXTilesetInfo objects)
+ - ObjectGroups (an array of TMXObjectGroupInfo objects)
+
+ This information is obtained from the TMX file.
+
+ */
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#if defined(__IPHONE_4_0)
+@interface CCTMXMapInfo : NSObject <NSXMLParserDelegate>
+#else
+@interface CCTMXMapInfo : NSObject
+#endif
+
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+@interface CCTMXMapInfo : NSObject <NSXMLParserDelegate>
+#endif
+{
+ NSMutableString *currentString;
+ BOOL storingCharacters;
+ int layerAttribs;
+ int parentElement;
+ unsigned int parentGID_;
+
+
+ // tmx filename
+ NSString *filename_;
+
+ // map orientation
+ int orientation_;
+
+ // map width & height
+ CGSize mapSize_;
+
+ // tiles width & height
+ CGSize tileSize_;
+
+ // Layers
+ NSMutableArray *layers_;
+
+ // tilesets
+ NSMutableArray *tilesets_;
+
+ // ObjectGroups
+ NSMutableArray *objectGroups_;
+
+ // properties
+ NSMutableDictionary *properties_;
+
+ // tile properties
+ NSMutableDictionary *tileProperties_;
+}
+
+@property (nonatomic,readwrite,assign) int orientation;
+@property (nonatomic,readwrite,assign) CGSize mapSize;
+@property (nonatomic,readwrite,assign) CGSize tileSize;
+@property (nonatomic,readwrite,retain) NSMutableArray *layers;
+@property (nonatomic,readwrite,retain) NSMutableArray *tilesets;
+@property (nonatomic,readwrite,retain) NSString *filename;
+@property (nonatomic,readwrite,retain) NSMutableArray *objectGroups;
+@property (nonatomic,readwrite,retain) NSMutableDictionary *properties;
+@property (nonatomic,readwrite,retain) NSMutableDictionary *tileProperties;
+
+/** creates a TMX Format with a tmx file */
++(id) formatWithTMXFile:(NSString*)tmxFile;
+/** initializes a TMX format witha tmx file */
+-(id) initWithTMXFile:(NSString*)tmxFile;
+@end
+
--- /dev/null
+/*
+ * 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.
+ *
+ *
+ * TMX Tiled Map support:
+ * http://www.mapeditor.org
+ *
+ */
+
+
+#import <Foundation/Foundation.h>
+#include <zlib.h>
+
+#import "ccMacros.h"
+#import "Support/CGPointExtension.h"
+#import "CCTMXXMLParser.h"
+#import "CCTMXTiledMap.h"
+#import "CCTMXObjectGroup.h"
+#import "Support/base64.h"
+#import "Support/ZipUtils.h"
+#import "Support/CCFileUtils.h"
+
+#pragma mark -
+#pragma mark TMXLayerInfo
+
+
+@implementation CCTMXLayerInfo
+
+@synthesize name = name_, layerSize = layerSize_, tiles = tiles_, visible = visible_, opacity = opacity_, ownTiles = ownTiles_, minGID = minGID_, maxGID = maxGID_, properties = properties_;
+@synthesize offset = offset_;
+-(id) init
+{
+ if( (self=[super init])) {
+ ownTiles_ = YES;
+ minGID_ = 100000;
+ maxGID_ = 0;
+ self.name = nil;
+ tiles_ = NULL;
+ offset_ = CGPointZero;
+ self.properties = [NSMutableDictionary dictionaryWithCapacity:5];
+ }
+ return self;
+}
+- (void) dealloc
+{
+ CCLOGINFO(@"cocos2d: deallocing %@",self);
+
+ [name_ release];
+ [properties_ release];
+
+ if( ownTiles_ && tiles_ ) {
+ free( tiles_ );
+ tiles_ = NULL;
+ }
+ [super dealloc];
+}
+
+@end
+
+#pragma mark -
+#pragma mark TMXTilesetInfo
+@implementation CCTMXTilesetInfo
+
+@synthesize name = name_, firstGid = firstGid_, tileSize = tileSize_, spacing = spacing_, margin = margin_, sourceImage = sourceImage_, imageSize = imageSize_;
+
+- (void) dealloc
+{
+ CCLOGINFO(@"cocos2d: deallocing %@", self);
+ [sourceImage_ release];
+ [name_ release];
+ [super dealloc];
+}
+
+-(CGRect) rectForGID:(unsigned int)gid
+{
+ CGRect rect;
+ rect.size = tileSize_;
+
+ gid = gid - firstGid_;
+
+ int max_x = (imageSize_.width - margin_*2 + spacing_) / (tileSize_.width + spacing_);
+ // int max_y = (imageSize.height - margin*2 + spacing) / (tileSize.height + spacing);
+
+ rect.origin.x = (gid % max_x) * (tileSize_.width + spacing_) + margin_;
+ rect.origin.y = (gid / max_x) * (tileSize_.height + spacing_) + margin_;
+
+ return rect;
+}
+@end
+
+#pragma mark -
+#pragma mark CCTMXMapInfo
+
+@interface CCTMXMapInfo (Private)
+/* initalises parsing of an XML file, either a tmx (Map) file or tsx (Tileset) file */
+-(void) parseXMLFile:(NSString *)xmlFilename;
+@end
+
+
+@implementation CCTMXMapInfo
+
+@synthesize orientation = orientation_, mapSize = mapSize_, layers = layers_, tilesets = tilesets_, tileSize = tileSize_, filename = filename_, objectGroups = objectGroups_, properties = properties_;
+@synthesize tileProperties = tileProperties_;
+
++(id) formatWithTMXFile:(NSString*)tmxFile
+{
+ return [[[self alloc] initWithTMXFile:tmxFile] autorelease];
+}
+
+-(id) initWithTMXFile:(NSString*)tmxFile
+{
+ if( (self=[super init])) {
+
+ self.tilesets = [NSMutableArray arrayWithCapacity:4];
+ self.layers = [NSMutableArray arrayWithCapacity:4];
+ self.filename = tmxFile;
+ self.objectGroups = [NSMutableArray arrayWithCapacity:4];
+ self.properties = [NSMutableDictionary dictionaryWithCapacity:5];
+ self.tileProperties = [NSMutableDictionary dictionaryWithCapacity:5];
+
+ // tmp vars
+ currentString = [[NSMutableString alloc] initWithCapacity:1024];
+ storingCharacters = NO;
+ layerAttribs = TMXLayerAttribNone;
+ parentElement = TMXPropertyNone;
+
+ [self parseXMLFile:filename_];
+ }
+ return self;
+}
+- (void) dealloc
+{
+ CCLOGINFO(@"cocos2d: deallocing %@", self);
+ [tilesets_ release];
+ [layers_ release];
+ [filename_ release];
+ [currentString release];
+ [objectGroups_ release];
+ [properties_ release];
+ [tileProperties_ release];
+ [super dealloc];
+}
+
+- (void) parseXMLFile:(NSString *)xmlFilename
+{
+ NSURL *url = [NSURL fileURLWithPath:[CCFileUtils fullPathFromRelativePath:xmlFilename] ];
+ NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
+
+ // we'll do the parsing
+ [parser setDelegate:self];
+ [parser setShouldProcessNamespaces:NO];
+ [parser setShouldReportNamespacePrefixes:NO];
+ [parser setShouldResolveExternalEntities:NO];
+ [parser parse];
+
+ NSAssert1( ! [parser parserError], @"Error parsing file: %@.", xmlFilename );
+
+ [parser release];
+}
+
+// the XML parser calls here with all the elements
+-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
+{
+ if([elementName isEqualToString:@"map"]) {
+ NSString *version = [attributeDict valueForKey:@"version"];
+ if( ! [version isEqualToString:@"1.0"] )
+ CCLOG(@"cocos2d: TMXFormat: Unsupported TMX version: %@", version);
+ NSString *orientationStr = [attributeDict valueForKey:@"orientation"];
+ if( [orientationStr isEqualToString:@"orthogonal"])
+ orientation_ = CCTMXOrientationOrtho;
+ else if ( [orientationStr isEqualToString:@"isometric"])
+ orientation_ = CCTMXOrientationIso;
+ else if( [orientationStr isEqualToString:@"hexagonal"])
+ orientation_ = CCTMXOrientationHex;
+ else
+ CCLOG(@"cocos2d: TMXFomat: Unsupported orientation: %@", orientation_);
+
+ mapSize_.width = [[attributeDict valueForKey:@"width"] intValue];
+ mapSize_.height = [[attributeDict valueForKey:@"height"] intValue];
+ tileSize_.width = [[attributeDict valueForKey:@"tilewidth"] intValue];
+ tileSize_.height = [[attributeDict valueForKey:@"tileheight"] intValue];
+
+ // The parent element is now "map"
+ parentElement = TMXPropertyMap;
+ } else if([elementName isEqualToString:@"tileset"]) {
+
+ // If this is an external tileset then start parsing that
+ NSString *externalTilesetFilename = [attributeDict valueForKey:@"source"];
+ if (externalTilesetFilename) {
+ // Tileset file will be relative to the map file. So we need to convert it to an absolute path
+ NSString *dir = [filename_ stringByDeletingLastPathComponent]; // Directory of map file
+ externalTilesetFilename = [dir stringByAppendingPathComponent:externalTilesetFilename]; // Append path to tileset file
+
+ [self parseXMLFile:externalTilesetFilename];
+ } else {
+
+ CCTMXTilesetInfo *tileset = [CCTMXTilesetInfo new];
+ tileset.name = [attributeDict valueForKey:@"name"];
+ tileset.firstGid = [[attributeDict valueForKey:@"firstgid"] intValue];
+ tileset.spacing = [[attributeDict valueForKey:@"spacing"] intValue];
+ tileset.margin = [[attributeDict valueForKey:@"margin"] intValue];
+ CGSize s;
+ s.width = [[attributeDict valueForKey:@"tilewidth"] intValue];
+ s.height = [[attributeDict valueForKey:@"tileheight"] intValue];
+ tileset.tileSize = s;
+
+ [tilesets_ addObject:tileset];
+ [tileset release];
+ }
+
+ }else if([elementName isEqualToString:@"tile"]){
+ CCTMXTilesetInfo* info = [tilesets_ lastObject];
+ NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithCapacity:3];
+ parentGID_ = [info firstGid] + [[attributeDict valueForKey:@"id"] intValue];
+ [tileProperties_ setObject:dict forKey:[NSNumber numberWithInt:parentGID_]];
+
+ parentElement = TMXPropertyTile;
+
+ }else if([elementName isEqualToString:@"layer"]) {
+ CCTMXLayerInfo *layer = [CCTMXLayerInfo new];
+ layer.name = [attributeDict valueForKey:@"name"];
+
+ CGSize s;
+ s.width = [[attributeDict valueForKey:@"width"] intValue];
+ s.height = [[attributeDict valueForKey:@"height"] intValue];
+ layer.layerSize = s;
+
+ layer.visible = ![[attributeDict valueForKey:@"visible"] isEqualToString:@"0"];
+
+ if( [attributeDict valueForKey:@"opacity"] )
+ layer.opacity = 255 * [[attributeDict valueForKey:@"opacity"] floatValue];
+ else
+ layer.opacity = 255;
+
+ int x = [[attributeDict valueForKey:@"x"] intValue];
+ int y = [[attributeDict valueForKey:@"y"] intValue];
+ layer.offset = ccp(x,y);
+
+ [layers_ addObject:layer];
+ [layer release];
+
+ // The parent element is now "layer"
+ parentElement = TMXPropertyLayer;
+
+ } else if([elementName isEqualToString:@"objectgroup"]) {
+
+ CCTMXObjectGroup *objectGroup = [[CCTMXObjectGroup alloc] init];
+ objectGroup.groupName = [attributeDict valueForKey:@"name"];
+ CGPoint positionOffset;
+ positionOffset.x = [[attributeDict valueForKey:@"x"] intValue] * tileSize_.width;
+ positionOffset.y = [[attributeDict valueForKey:@"y"] intValue] * tileSize_.height;
+ objectGroup.positionOffset = positionOffset;
+
+ [objectGroups_ addObject:objectGroup];
+ [objectGroup release];
+
+ // The parent element is now "objectgroup"
+ parentElement = TMXPropertyObjectGroup;
+
+ } else if([elementName isEqualToString:@"image"]) {
+
+ CCTMXTilesetInfo *tileset = [tilesets_ lastObject];
+
+ // build full path
+ NSString *imagename = [attributeDict valueForKey:@"source"];
+ NSString *path = [filename_ stringByDeletingLastPathComponent];
+ tileset.sourceImage = [path stringByAppendingPathComponent:imagename];
+
+ } else if([elementName isEqualToString:@"data"]) {
+ NSString *encoding = [attributeDict valueForKey:@"encoding"];
+ NSString *compression = [attributeDict valueForKey:@"compression"];
+
+ if( [encoding isEqualToString:@"base64"] ) {
+ layerAttribs |= TMXLayerAttribBase64;
+ storingCharacters = YES;
+
+ if( [compression isEqualToString:@"gzip"] )
+ layerAttribs |= TMXLayerAttribGzip;
+
+ NSAssert( !compression || [compression isEqualToString:@"gzip"], @"TMX: unsupported compression method" );
+ }
+
+ NSAssert( layerAttribs != TMXLayerAttribNone, @"TMX tile map: Only base64 and/or gzip maps are supported" );
+
+ } else if([elementName isEqualToString:@"object"]) {
+
+ CCTMXObjectGroup *objectGroup = [objectGroups_ lastObject];
+
+ // The value for "type" was blank or not a valid class name
+ // Create an instance of TMXObjectInfo to store the object and its properties
+ NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:5];
+
+ // Set the name of the object to the value for "name"
+ [dict setValue:[attributeDict valueForKey:@"name"] forKey:@"name"];
+
+ // Assign all the attributes as key/name pairs in the properties dictionary
+ [dict setValue:[attributeDict valueForKey:@"type"] forKey:@"type"];
+ int x = [[attributeDict valueForKey:@"x"] intValue] + objectGroup.positionOffset.x;
+ [dict setValue:[NSNumber numberWithInt:x] forKey:@"x"];
+ int y = [[attributeDict valueForKey:@"y"] intValue] + objectGroup.positionOffset.y;
+ // Correct y position. (Tiled uses Flipped, cocos2d uses Standard)
+ y = (mapSize_.height * tileSize_.height) - y - [[attributeDict valueForKey:@"height"] intValue];
+ [dict setValue:[NSNumber numberWithInt:y] forKey:@"y"];
+ [dict setValue:[attributeDict valueForKey:@"width"] forKey:@"width"];
+ [dict setValue:[attributeDict valueForKey:@"height"] forKey:@"height"];
+
+ // Add the object to the objectGroup
+ [[objectGroup objects] addObject:dict];
+ [dict release];
+
+ // The parent element is now "object"
+ parentElement = TMXPropertyObject;
+
+ } else if([elementName isEqualToString:@"property"]) {
+
+ if ( parentElement == TMXPropertyNone ) {
+
+ CCLOG( @"TMX tile map: Parent element is unsupported. Cannot add property named '%@' with value '%@'",
+ [attributeDict valueForKey:@"name"], [attributeDict valueForKey:@"value"] );
+
+ } else if ( parentElement == TMXPropertyMap ) {
+
+ // The parent element is the map
+ [properties_ setValue:[attributeDict valueForKey:@"value"] forKey:[attributeDict valueForKey:@"name"]];
+
+ } else if ( parentElement == TMXPropertyLayer ) {
+
+ // The parent element is the last layer
+ CCTMXLayerInfo *layer = [layers_ lastObject];
+ // Add the property to the layer
+ [[layer properties] setValue:[attributeDict valueForKey:@"value"] forKey:[attributeDict valueForKey:@"name"]];
+
+ } else if ( parentElement == TMXPropertyObjectGroup ) {
+
+ // The parent element is the last object group
+ CCTMXObjectGroup *objectGroup = [objectGroups_ lastObject];
+ [[objectGroup properties] setValue:[attributeDict valueForKey:@"value"] forKey:[attributeDict valueForKey:@"name"]];
+
+ } else if ( parentElement == TMXPropertyObject ) {
+
+ // The parent element is the last object
+ CCTMXObjectGroup *objectGroup = [objectGroups_ lastObject];
+ NSMutableDictionary *dict = [[objectGroup objects] lastObject];
+
+ NSString *propertyName = [attributeDict valueForKey:@"name"];
+ NSString *propertyValue = [attributeDict valueForKey:@"value"];
+
+ [dict setValue:propertyValue forKey:propertyName];
+ } else if ( parentElement == TMXPropertyTile ) {
+
+ NSMutableDictionary* dict = [tileProperties_ objectForKey:[NSNumber numberWithInt:parentGID_]];
+ NSString *propertyName = [attributeDict valueForKey:@"name"];
+ NSString *propertyValue = [attributeDict valueForKey:@"value"];
+ [dict setObject:propertyValue forKey:propertyName];
+
+ }
+ }
+}
+
+- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
+{
+ int len = 0;
+
+ if([elementName isEqualToString:@"data"] && layerAttribs&TMXLayerAttribBase64) {
+ storingCharacters = NO;
+
+ CCTMXLayerInfo *layer = [layers_ lastObject];
+
+ unsigned char *buffer;
+ len = base64Decode((unsigned char*)[currentString UTF8String], [currentString length], &buffer);
+ if( ! buffer ) {
+ CCLOG(@"cocos2d: TiledMap: decode data error");
+ return;
+ }
+
+ if( layerAttribs & TMXLayerAttribGzip ) {
+ unsigned char *deflated;
+ ccInflateMemory(buffer, len, &deflated);
+ free( buffer );
+
+ if( ! deflated ) {
+ CCLOG(@"cocos2d: TiledMap: inflate data error");
+ return;
+ }
+
+ layer.tiles = (unsigned int*) deflated;
+ } else
+ layer.tiles = (unsigned int*) buffer;
+
+ [currentString setString:@""];
+
+ } else if ([elementName isEqualToString:@"map"]) {
+ // The map element has ended
+ parentElement = TMXPropertyNone;
+
+ } else if ([elementName isEqualToString:@"layer"]) {
+ // The layer element has ended
+ parentElement = TMXPropertyNone;
+
+ } else if ([elementName isEqualToString:@"objectgroup"]) {
+ // The objectgroup element has ended
+ parentElement = TMXPropertyNone;
+
+ } else if ([elementName isEqualToString:@"object"]) {
+ // The object element has ended
+ parentElement = TMXPropertyNone;
+ }
+}
+
+- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
+{
+ if (storingCharacters)
+ [currentString appendString:string];
+}
+
+
+//
+// the level did not load, file not found, etc.
+//
+-(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{
+ CCLOG(@"cocos2d: Error on XML Parse: %@", [parseError localizedDescription] );
+}
+
+@end
--- /dev/null
+/*
+
+===== IMPORTANT =====
+
+This is sample code demonstrating API, technology or techniques in development.
+Although this sample code has been reviewed for technical accuracy, it is not
+final. Apple is supplying this information to help you plan for the adoption of
+the technologies and programming interfaces described herein. This information
+is subject to change, and software implemented based on this sample code should
+be tested with final operating system software and final documentation. Newer
+versions of this sample code may be provided with future seeds of the API or
+technology. For information about updates to this and other developer
+documentation, view the New & Updated sidebars in subsequent documentation
+seeds.
+
+=====================
+
+File: Texture2D.h
+Abstract: Creates OpenGL 2D textures from images or text.
+
+Version: 1.6
+
+Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
+("Apple") in consideration of your agreement to the following terms, and your
+use, installation, modification or redistribution of this Apple software
+constitutes acceptance of these terms. If you do not agree with these terms,
+please do not use, install, modify or redistribute this Apple software.
+
+In consideration of your agreement to abide by the following terms, and subject
+to these terms, Apple grants you a personal, non-exclusive license, under
+Apple's copyrights in this original Apple software (the "Apple Software"), to
+use, reproduce, modify and redistribute the Apple Software, with or without
+modifications, in source and/or binary forms; provided that if you redistribute
+the Apple Software in its entirety and without modifications, you must retain
+this notice and the following text and disclaimers in all such redistributions
+of the Apple Software.
+Neither the name, trademarks, service marks or logos of Apple Inc. may be used
+to endorse or promote products derived from the Apple Software without specific
+prior written permission from Apple. Except as expressly stated in this notice,
+no other rights or licenses, express or implied, are granted by Apple herein,
+including but not limited to any patent rights that may be infringed by your
+derivative works or by other works in which the Apple Software may be
+incorporated.
+
+The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
+DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
+CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Copyright (C) 2008 Apple Inc. All Rights Reserved.
+
+*/
+
+#import <Availability.h>
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#import <UIKit/UIKit.h> // for UIImage
+#endif
+
+#import <Foundation/Foundation.h> // for NSObject
+
+#import "Platforms/CCGL.h" // OpenGL stuff
+#import "Platforms/CCNS.h" // Next-Step stuff
+
+//CONSTANTS:
+
+/** @typedef CCTexture2DPixelFormat
+ Possible texture pixel formats
+ */
+typedef enum {
+ kCCTexture2DPixelFormat_Automatic = 0,
+ //! 32-bit texture: RGBA8888
+ kCCTexture2DPixelFormat_RGBA8888,
+ //! 16-bit texture without Alpha channel
+ kCCTexture2DPixelFormat_RGB565,
+ //! 8-bit textures used as masks
+ kCCTexture2DPixelFormat_A8,
+ //! 16-bit textures: RGBA4444
+ kCCTexture2DPixelFormat_RGBA4444,
+ //! 16-bit textures: RGB5A1
+ kCCTexture2DPixelFormat_RGB5A1,
+
+ //! Default texture format: RGBA8888
+ kCCTexture2DPixelFormat_Default = kCCTexture2DPixelFormat_RGBA8888,
+
+ // backward compatibility stuff
+ kTexture2DPixelFormat_Automatic = kCCTexture2DPixelFormat_Automatic,
+ kTexture2DPixelFormat_RGBA8888 = kCCTexture2DPixelFormat_RGBA8888,
+ kTexture2DPixelFormat_RGB565 = kCCTexture2DPixelFormat_RGB565,
+ kTexture2DPixelFormat_A8 = kCCTexture2DPixelFormat_A8,
+ kTexture2DPixelFormat_RGBA4444 = kCCTexture2DPixelFormat_RGBA4444,
+ kTexture2DPixelFormat_RGB5A1 = kCCTexture2DPixelFormat_RGB5A1,
+ kTexture2DPixelFormat_Default = kCCTexture2DPixelFormat_Default
+
+} CCTexture2DPixelFormat;
+
+//CLASS INTERFACES:
+
+/** CCTexture2D class.
+ * This class allows to easily create OpenGL 2D textures from images, text or raw data.
+ * The created CCTexture2D object will always have power-of-two dimensions.
+ * Depending on how you create the CCTexture2D object, the actual image area of the texture might be smaller than the texture dimensions i.e. "contentSize" != (pixelsWide, pixelsHigh) and (maxS, maxT) != (1.0, 1.0).
+ * Be aware that the content of the generated textures will be upside-down!
+ */
+@interface CCTexture2D : NSObject
+{
+ GLuint name_;
+ CGSize size_;
+ NSUInteger width_,
+ height_;
+ CCTexture2DPixelFormat format_;
+ GLfloat maxS_,
+ maxT_;
+ BOOL hasPremultipliedAlpha_;
+}
+/** Intializes with a texture2d with data */
+- (id) initWithData:(const void*)data pixelFormat:(CCTexture2DPixelFormat)pixelFormat pixelsWide:(NSUInteger)width pixelsHigh:(NSUInteger)height contentSize:(CGSize)size;
+
+/** These functions are needed to create mutable textures */
+- (void) releaseData:(void*)data;
+- (void*) keepData:(void*)data length:(NSUInteger)length;
+
+/** pixel format of the texture */
+@property(nonatomic,readonly) CCTexture2DPixelFormat pixelFormat;
+/** width in pixels */
+@property(nonatomic,readonly) NSUInteger pixelsWide;
+/** hight in pixels */
+@property(nonatomic,readonly) NSUInteger pixelsHigh;
+
+/** texture name */
+@property(nonatomic,readonly) GLuint name;
+
+/** returns content size of the texture in pixels */
+@property(nonatomic,readonly, nonatomic) CGSize contentSizeInPixels;
+
+/** texture max S */
+@property(nonatomic,readwrite) GLfloat maxS;
+/** texture max T */
+@property(nonatomic,readwrite) GLfloat maxT;
+/** whether or not the texture has their Alpha premultiplied */
+@property(nonatomic,readonly) BOOL hasPremultipliedAlpha;
+
+/** returns the content size of the texture in points */
+-(CGSize) contentSize;
+@end
+
+/**
+Drawing extensions to make it easy to draw basic quads using a CCTexture2D object.
+These functions require GL_TEXTURE_2D and both GL_VERTEX_ARRAY and GL_TEXTURE_COORD_ARRAY client states to be enabled.
+*/
+@interface CCTexture2D (Drawing)
+/** draws a texture at a given point */
+- (void) drawAtPoint:(CGPoint)point;
+/** draws a texture inside a rect */
+- (void) drawInRect:(CGRect)rect;
+@end
+
+/**
+Extensions to make it easy to create a CCTexture2D object from an image file.
+Note that RGBA type textures will have their alpha premultiplied - use the blending mode (GL_ONE, GL_ONE_MINUS_SRC_ALPHA).
+*/
+@interface CCTexture2D (Image)
+/** Initializes a texture from a UIImage object */
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+- (id) initWithImage:(UIImage *)uiImage;
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+- (id) initWithImage:(CGImageRef)cgImage;
+#endif
+@end
+
+/**
+Extensions to make it easy to create a CCTexture2D object from a string of text.
+Note that the generated textures are of type A8 - use the blending mode (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
+*/
+@interface CCTexture2D (Text)
+/** Initializes a texture from a string with dimensions, alignment, font name and font size */
+- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size;
+/** Initializes a texture from a string with font name and font size */
+- (id) initWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size;
+@end
+
+
+/**
+ Extensions to make it easy to create a CCTexture2D object from a PVRTC file
+ Note that the generated textures don't have their alpha premultiplied - use the blending mode (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
+ */
+@interface CCTexture2D (PVRSupport)
+/** Initializes a texture from a PVR Texture Compressed (PVRTC) buffer
+ *
+ * IMPORTANT: This method is only defined on iOS. It is not supported on the Mac version.
+ */
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+-(id) initWithPVRTCData: (const void*)data level:(int)level bpp:(int)bpp hasAlpha:(BOOL)hasAlpha length:(int)length;
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
+/** Initializes a texture from a PVR file.
+
+ Supported PVR formats:
+ - BGRA 8888
+ - RGBA 8888
+ - RGBA 4444
+ - RGBA 5551
+ - RBG 565
+ - A 8
+ - I 8
+ - AI 8
+ - PVRTC 2BPP
+ - PVRTC 4BPP
+
+ By default PVR images are treated as if they alpha channel is NOT premultiplied. You can override this behavior with this class method:
+ - PVRImagesHavePremultipliedAlpha:(BOOL)haveAlphaPremultiplied;
+
+ IMPORTANT: This method is only defined on iOS. It is not supported on the Mac version.
+
+ */
+-(id) initWithPVRFile: (NSString*) file;
+
+/** treats (or not) PVR files as if they have alpha premultiplied.
+ Since it is impossible to know at runtime if the PVR images have the alpha channel premultiplied, it is
+ possible load them as if they have (or not) the alpha channel premultiplied.
+
+ By default it is disabled.
+
+ @since v0.99.5
+ */
++(void) PVRImagesHavePremultipliedAlpha:(BOOL)haveAlphaPremultiplied;
+@end
+
+/**
+ Extension to set the Min / Mag filter
+ */
+typedef struct _ccTexParams {
+ GLuint minFilter;
+ GLuint magFilter;
+ GLuint wrapS;
+ GLuint wrapT;
+} ccTexParams;
+
+@interface CCTexture2D (GLFilter)
+/** sets the min filter, mag filter, wrap s and wrap t texture parameters.
+ If the texture size is NPOT (non power of 2), then in can only use GL_CLAMP_TO_EDGE in GL_TEXTURE_WRAP_{S,T}.
+ @since v0.8
+ */
+-(void) setTexParameters: (ccTexParams*) texParams;
+
+/** sets antialias texture parameters:
+ - GL_TEXTURE_MIN_FILTER = GL_LINEAR
+ - GL_TEXTURE_MAG_FILTER = GL_LINEAR
+
+ @since v0.8
+ */
+- (void) setAntiAliasTexParameters;
+
+/** sets alias texture parameters:
+ - GL_TEXTURE_MIN_FILTER = GL_NEAREST
+ - GL_TEXTURE_MAG_FILTER = GL_NEAREST
+
+ @since v0.8
+ */
+- (void) setAliasTexParameters;
+
+
+/** Generates mipmap images for the texture.
+ It only works if the texture size is POT (power of 2).
+ @since v0.99.0
+ */
+-(void) generateMipmap;
+
+
+@end
+
+@interface CCTexture2D (PixelFormat)
+/** sets the default pixel format for UIImages that contains alpha channel.
+ If the UIImage contains alpha channel, then the options are:
+ - generate 32-bit textures: kCCTexture2DPixelFormat_RGBA8888 (default one)
+ - generate 16-bit textures: kCCTexture2DPixelFormat_RGBA4444
+ - generate 16-bit textures: kCCTexture2DPixelFormat_RGB5A1
+ - generate 16-bit textures: kCCTexture2DPixelFormat_RGB565
+ - generate 8-bit textures: kCCTexture2DPixelFormat_A8 (only use it if you use just 1 color)
+
+ How does it work ?
+ - If the image is an RGBA (with Alpha) then the default pixel format will be used (it can be a 8-bit, 16-bit or 32-bit texture)
+ - If the image is an RGB (without Alpha) then an RGB565 texture will be used (16-bit texture)
+
+ This parameter is not valid for PVR images.
+
+ @since v0.8
+ */
++(void) setDefaultAlphaPixelFormat:(CCTexture2DPixelFormat)format;
+
+/** returns the alpha pixel format
+ @since v0.8
+ */
++(CCTexture2DPixelFormat) defaultAlphaPixelFormat;
+@end
+
+
+
+
+
--- /dev/null
+/*
+
+===== IMPORTANT =====
+
+This is sample code demonstrating API, technology or techniques in development.
+Although this sample code has been reviewed for technical accuracy, it is not
+final. Apple is supplying this information to help you plan for the adoption of
+the technologies and programming interfaces described herein. This information
+is subject to change, and software implemented based on this sample code should
+be tested with final operating system software and final documentation. Newer
+versions of this sample code may be provided with future seeds of the API or
+technology. For information about updates to this and other developer
+documentation, view the New & Updated sidebars in subsequent documentationd
+seeds.
+
+=====================
+
+File: Texture2D.m
+Abstract: Creates OpenGL 2D textures from images or text.
+
+Version: 1.6
+
+Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
+("Apple") in consideration of your agreement to the following terms, and your
+use, installation, modification or redistribution of this Apple software
+constitutes acceptance of these terms. If you do not agree with these terms,
+please do not use, install, modify or redistribute this Apple software.
+
+In consideration of your agreement to abide by the following terms, and subject
+to these terms, Apple grants you a personal, non-exclusive license, under
+Apple's copyrights in this original Apple software (the "Apple Software"), to
+use, reproduce, modify and redistribute the Apple Software, with or without
+modifications, in source and/or binary forms; provided that if you redistribute
+the Apple Software in its entirety and without modifications, you must retain
+this notice and the following text and disclaimers in all such redistributions
+of the Apple Software.
+Neither the name, trademarks, service marks or logos of Apple Inc. may be used
+to endorse or promote products derived from the Apple Software without specific
+prior written permission from Apple. Except as expressly stated in this notice,
+no other rights or licenses, express or implied, are granted by Apple herein,
+including but not limited to any patent rights that may be infringed by your
+derivative works or by other works in which the Apple Software may be
+incorporated.
+
+The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
+DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
+CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Copyright (C) 2008 Apple Inc. All Rights Reserved.
+
+*/
+
+/*
+ * Support for RGBA_4_4_4_4 and RGBA_5_5_5_1 was copied from:
+ * https://devforums.apple.com/message/37855#37855 by a1studmuffin
+ */
+
+
+#import <Availability.h>
+
+#import "Platforms/CCGL.h"
+#import "Platforms/CCNS.h"
+
+
+#import "CCTexture2D.h"
+#import "ccConfig.h"
+#import "ccMacros.h"
+#import "CCConfiguration.h"
+#import "Support/ccUtils.h"
+#import "CCTexturePVR.h"
+
+#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && CC_FONT_LABEL_SUPPORT
+// FontLabel support
+#import "FontManager.h"
+#import "FontLabelStringDrawing.h"
+#endif// CC_FONT_LABEL_SUPPORT
+
+
+// For Labels use 32-bit textures on iPhone 3GS / iPads since A8 textures are very slow
+#if defined(__ARM_NEON__) && CC_USE_RGBA32_LABELS_ON_NEON_ARCH
+#define USE_TEXT_WITH_A8_TEXTURES 0
+
+#else
+#define USE_TEXT_WITH_A8_TEXTURES 1
+#endif
+
+//CLASS IMPLEMENTATIONS:
+
+
+// If the image has alpha, you can create RGBA8 (32-bit) or RGBA4 (16-bit) or RGB5A1 (16-bit)
+// Default is: RGBA8888 (32-bit textures)
+static CCTexture2DPixelFormat defaultAlphaPixelFormat_ = kCCTexture2DPixelFormat_Default;
+
+#pragma mark -
+#pragma mark CCTexture2D - Main
+
+@implementation CCTexture2D
+
+@synthesize contentSizeInPixels = size_, pixelFormat = format_, pixelsWide = width_, pixelsHigh = height_, name = name_, maxS = maxS_, maxT = maxT_;
+@synthesize hasPremultipliedAlpha = hasPremultipliedAlpha_;
+
+- (id) initWithData:(const void*)data pixelFormat:(CCTexture2DPixelFormat)pixelFormat pixelsWide:(NSUInteger)width pixelsHigh:(NSUInteger)height contentSize:(CGSize)size
+{
+ if((self = [super init])) {
+ glGenTextures(1, &name_);
+ glBindTexture(GL_TEXTURE_2D, name_);
+
+ [self setAntiAliasTexParameters];
+
+ // Specify OpenGL texture image
+
+ switch(pixelFormat)
+ {
+ case kCCTexture2DPixelFormat_RGBA8888:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ break;
+ case kCCTexture2DPixelFormat_RGBA4444:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data);
+ break;
+ case kCCTexture2DPixelFormat_RGB5A1:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, data);
+ break;
+ case kCCTexture2DPixelFormat_RGB565:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
+ break;
+ case kCCTexture2DPixelFormat_A8:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data);
+ break;
+ default:
+ [NSException raise:NSInternalInconsistencyException format:@""];
+
+ }
+
+ size_ = size;
+ width_ = width;
+ height_ = height;
+ format_ = pixelFormat;
+ maxS_ = size.width / (float)width;
+ maxT_ = size.height / (float)height;
+
+ hasPremultipliedAlpha_ = NO;
+ }
+ return self;
+}
+
+- (void) releaseData:(void*)data
+{
+ //Free data
+ free(data);
+}
+
+- (void*) keepData:(void*)data length:(NSUInteger)length
+{
+ //The texture data mustn't be saved becuase it isn't a mutable texture.
+ return data;
+}
+
+- (void) dealloc
+{
+ CCLOGINFO(@"cocos2d: deallocing %@", self);
+ if(name_)
+ glDeleteTextures(1, &name_);
+
+ [super dealloc];
+}
+
+- (NSString*) description
+{
+ return [NSString stringWithFormat:@"<%@ = %08X | Name = %i | Dimensions = %ix%i | Coordinates = (%.2f, %.2f)>", [self class], self, name_, width_, height_, maxS_, maxT_];
+}
+
+-(CGSize) contentSize
+{
+ CGSize ret;
+ ret.width = size_.width / CC_CONTENT_SCALE_FACTOR();
+ ret.height = size_.height / CC_CONTENT_SCALE_FACTOR();
+
+ return ret;
+}
+@end
+
+#pragma mark -
+#pragma mark CCTexture2D - Image
+
+@implementation CCTexture2D (Image)
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+- (id) initWithImage:(UIImage *)uiImage
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+- (id) initWithImage:(CGImageRef)CGImage
+#endif
+{
+ NSUInteger POTWide, POTHigh;
+ CGContextRef context = nil;
+ void* data = nil;;
+ CGColorSpaceRef colorSpace;
+ void* tempData;
+ unsigned int* inPixel32;
+ unsigned short* outPixel16;
+ BOOL hasAlpha;
+ CGImageAlphaInfo info;
+ CGSize imageSize;
+ CCTexture2DPixelFormat pixelFormat;
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+ CGImageRef CGImage = uiImage.CGImage;
+#endif
+
+ if(CGImage == NULL) {
+ CCLOG(@"cocos2d: CCTexture2D. Can't create Texture. UIImage is nil");
+ [self release];
+ return nil;
+ }
+
+ CCConfiguration *conf = [CCConfiguration sharedConfiguration];
+
+#if CC_TEXTURE_NPOT_SUPPORT
+ if( [conf supportsNPOT] ) {
+ POTWide = CGImageGetWidth(CGImage);
+ POTHigh = CGImageGetHeight(CGImage);
+
+ } else
+#endif
+ {
+ POTWide = ccNextPOT(CGImageGetWidth(CGImage));
+ POTHigh = ccNextPOT(CGImageGetHeight(CGImage));
+ }
+
+ NSUInteger maxTextureSize = [conf maxTextureSize];
+ if( POTHigh > maxTextureSize || POTWide > maxTextureSize ) {
+ CCLOG(@"cocos2d: WARNING: Image (%d x %d) is bigger than the supported %d x %d",
+ (unsigned int)POTWide, (unsigned int)POTHigh,
+ (unsigned int)maxTextureSize, (unsigned int)maxTextureSize);
+ [self release];
+ return nil;
+ }
+
+ info = CGImageGetAlphaInfo(CGImage);
+ hasAlpha = ((info == kCGImageAlphaPremultipliedLast) || (info == kCGImageAlphaPremultipliedFirst) || (info == kCGImageAlphaLast) || (info == kCGImageAlphaFirst) ? YES : NO);
+
+ size_t bpp = CGImageGetBitsPerComponent(CGImage);
+ colorSpace = CGImageGetColorSpace(CGImage);
+
+ if(colorSpace) {
+ if(hasAlpha || bpp >= 8)
+ pixelFormat = defaultAlphaPixelFormat_;
+ else {
+ CCLOG(@"cocos2d: CCTexture2D: Using RGB565 texture since image has no alpha");
+ pixelFormat = kCCTexture2DPixelFormat_RGB565;
+ }
+ } else {
+ // NOTE: No colorspace means a mask image
+ CCLOG(@"cocos2d: CCTexture2D: Using A8 texture since image is a mask");
+ pixelFormat = kCCTexture2DPixelFormat_A8;
+ }
+
+ imageSize = CGSizeMake(CGImageGetWidth(CGImage), CGImageGetHeight(CGImage));
+
+ // Create the bitmap graphics context
+
+ switch(pixelFormat) {
+ case kCCTexture2DPixelFormat_RGBA8888:
+ case kCCTexture2DPixelFormat_RGBA4444:
+ case kCCTexture2DPixelFormat_RGB5A1:
+ colorSpace = CGColorSpaceCreateDeviceRGB();
+ data = malloc(POTHigh * POTWide * 4);
+ info = hasAlpha ? kCGImageAlphaPremultipliedLast : kCGImageAlphaNoneSkipLast;
+// info = kCGImageAlphaPremultipliedLast; // issue #886. This patch breaks BMP images.
+ context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, 4 * POTWide, colorSpace, info | kCGBitmapByteOrder32Big);
+ CGColorSpaceRelease(colorSpace);
+ break;
+
+ case kCCTexture2DPixelFormat_RGB565:
+ colorSpace = CGColorSpaceCreateDeviceRGB();
+ data = malloc(POTHigh * POTWide * 4);
+ info = kCGImageAlphaNoneSkipLast;
+ context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, 4 * POTWide, colorSpace, info | kCGBitmapByteOrder32Big);
+ CGColorSpaceRelease(colorSpace);
+ break;
+ case kCCTexture2DPixelFormat_A8:
+ data = malloc(POTHigh * POTWide);
+ info = kCGImageAlphaOnly;
+ context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, POTWide, NULL, info);
+ break;
+ default:
+ [NSException raise:NSInternalInconsistencyException format:@"Invalid pixel format"];
+ }
+
+
+ CGContextClearRect(context, CGRectMake(0, 0, POTWide, POTHigh));
+ CGContextTranslateCTM(context, 0, POTHigh - imageSize.height);
+ CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(CGImage), CGImageGetHeight(CGImage)), CGImage);
+
+ // Repack the pixel data into the right format
+
+ if(pixelFormat == kCCTexture2DPixelFormat_RGB565) {
+ //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB"
+ tempData = malloc(POTHigh * POTWide * 2);
+ inPixel32 = (unsigned int*)data;
+ outPixel16 = (unsigned short*)tempData;
+ for(unsigned int i = 0; i < POTWide * POTHigh; ++i, ++inPixel32)
+ *outPixel16++ = ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | ((((*inPixel32 >> 8) & 0xFF) >> 2) << 5) | ((((*inPixel32 >> 16) & 0xFF) >> 3) << 0);
+ free(data);
+ data = tempData;
+
+ }
+ else if (pixelFormat == kCCTexture2DPixelFormat_RGBA4444) {
+ //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRGGGGBBBBAAAA"
+ tempData = malloc(POTHigh * POTWide * 2);
+ inPixel32 = (unsigned int*)data;
+ outPixel16 = (unsigned short*)tempData;
+ for(unsigned int i = 0; i < POTWide * POTHigh; ++i, ++inPixel32)
+ *outPixel16++ =
+ ((((*inPixel32 >> 0) & 0xFF) >> 4) << 12) | // R
+ ((((*inPixel32 >> 8) & 0xFF) >> 4) << 8) | // G
+ ((((*inPixel32 >> 16) & 0xFF) >> 4) << 4) | // B
+ ((((*inPixel32 >> 24) & 0xFF) >> 4) << 0); // A
+
+
+ free(data);
+ data = tempData;
+
+ }
+ else if (pixelFormat == kCCTexture2DPixelFormat_RGB5A1) {
+ //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGBBBBBA"
+ tempData = malloc(POTHigh * POTWide * 2);
+ inPixel32 = (unsigned int*)data;
+ outPixel16 = (unsigned short*)tempData;
+ for(unsigned int i = 0; i < POTWide * POTHigh; ++i, ++inPixel32)
+ *outPixel16++ =
+ ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | // R
+ ((((*inPixel32 >> 8) & 0xFF) >> 3) << 6) | // G
+ ((((*inPixel32 >> 16) & 0xFF) >> 3) << 1) | // B
+ ((((*inPixel32 >> 24) & 0xFF) >> 7) << 0); // A
+
+
+ free(data);
+ data = tempData;
+ }
+ self = [self initWithData:data pixelFormat:pixelFormat pixelsWide:POTWide pixelsHigh:POTHigh contentSize:imageSize];
+
+ // should be after calling super init
+ hasPremultipliedAlpha_ = (info == kCGImageAlphaPremultipliedLast || info == kCGImageAlphaPremultipliedFirst);
+
+ CGContextRelease(context);
+ [self releaseData:data];
+
+ return self;
+}
+@end
+
+#pragma mark -
+#pragma mark CCTexture2D - Text
+
+@implementation CCTexture2D (Text)
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment font:(id)uifont
+{
+ NSAssert( uifont, @"Invalid font");
+
+ NSUInteger POTWide = ccNextPOT(dimensions.width);
+ NSUInteger POTHigh = ccNextPOT(dimensions.height);
+ unsigned char* data;
+
+ CGContextRef context;
+ CGColorSpaceRef colorSpace;
+
+#if USE_TEXT_WITH_A8_TEXTURES
+ colorSpace = CGColorSpaceCreateDeviceGray();
+ data = calloc(POTHigh, POTWide);
+ context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, POTWide, colorSpace, kCGImageAlphaNone);
+#else
+ colorSpace = CGColorSpaceCreateDeviceRGB();
+ data = calloc(POTHigh, POTWide * 4);
+ context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, 4 * POTWide, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
+#endif
+
+ CGColorSpaceRelease(colorSpace);
+
+ if( ! context ) {
+ free(data);
+ [self release];
+ return nil;
+ }
+
+ CGContextSetGrayFillColor(context, 1.0f, 1.0f);
+ CGContextTranslateCTM(context, 0.0f, POTHigh);
+ CGContextScaleCTM(context, 1.0f, -1.0f); //NOTE: NSString draws in UIKit referential i.e. renders upside-down compared to CGBitmapContext referential
+
+ UIGraphicsPushContext(context);
+
+ // normal fonts
+ if( [uifont isKindOfClass:[UIFont class] ] )
+ [string drawInRect:CGRectMake(0, 0, dimensions.width, dimensions.height) withFont:uifont lineBreakMode:UILineBreakModeWordWrap alignment:alignment];
+
+#if CC_FONT_LABEL_SUPPORT
+ else // ZFont class
+ [string drawInRect:CGRectMake(0, 0, dimensions.width, dimensions.height) withZFont:uifont lineBreakMode:UILineBreakModeWordWrap alignment:alignment];
+#endif
+
+ UIGraphicsPopContext();
+
+#if USE_TEXT_WITH_A8_TEXTURES
+ self = [self initWithData:data pixelFormat:kCCTexture2DPixelFormat_A8 pixelsWide:POTWide pixelsHigh:POTHigh contentSize:dimensions];
+#else
+ self = [self initWithData:data pixelFormat:kCCTexture2DPixelFormat_RGBA8888 pixelsWide:POTWide pixelsHigh:POTHigh contentSize:dimensions];
+#endif
+ CGContextRelease(context);
+ [self releaseData:data];
+
+ return self;
+}
+
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+
+- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment attributedString:(NSAttributedString*)stringWithAttributes
+{
+ NSAssert( stringWithAttributes, @"Invalid stringWithAttributes");
+
+ NSUInteger POTWide = ccNextPOT(dimensions.width);
+ NSUInteger POTHigh = ccNextPOT(dimensions.height);
+ unsigned char* data;
+
+ NSSize realDimensions = [stringWithAttributes size];
+
+ //Alignment
+ float xPadding = 0;
+
+ // Mac crashes if the width or height is 0
+ if( realDimensions.width > 0 && realDimensions.height > 0 ) {
+ switch (alignment) {
+ case CCTextAlignmentLeft: xPadding = 0; break;
+ case CCTextAlignmentCenter: xPadding = (dimensions.width-realDimensions.width)/2.0f; break;
+ case CCTextAlignmentRight: xPadding = dimensions.width-realDimensions.width; break;
+ default: break;
+ }
+
+ //Disable antialias
+ [[NSGraphicsContext currentContext] setShouldAntialias:NO];
+
+ NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(POTWide, POTHigh)];
+ [image lockFocus];
+
+ [stringWithAttributes drawAtPoint:NSMakePoint(xPadding, POTHigh-dimensions.height)]; // draw at offset position
+
+ NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect (0.0f, 0.0f, POTWide, POTHigh)];
+ [image unlockFocus];
+
+ data = (unsigned char*) [bitmap bitmapData]; //Use the same buffer to improve the performance.
+
+ NSUInteger textureSize = POTWide*POTHigh;
+ for(int i = 0; i<textureSize; i++) //Convert RGBA8888 to A8
+ data[i] = data[i*4+3];
+
+ data = [self keepData:data length:textureSize];
+ self = [self initWithData:data pixelFormat:kCCTexture2DPixelFormat_A8 pixelsWide:POTWide pixelsHigh:POTHigh contentSize:dimensions];
+
+ [bitmap release];
+ [image release];
+
+ } else {
+ [self release];
+ return nil;
+ }
+
+ return self;
+}
+#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
+
+- (id) initWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size
+{
+ CGSize dim;
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+ id font;
+ font = [UIFont fontWithName:name size:size];
+ if( font )
+ dim = [string sizeWithFont:font];
+
+#if CC_FONT_LABEL_SUPPORT
+ if( ! font ){
+ font = [[FontManager sharedManager] zFontWithName:name pointSize:size];
+ if (font)
+ dim = [string sizeWithZFont:font];
+ }
+#endif // CC_FONT_LABEL_SUPPORT
+
+ if( ! font ) {
+ CCLOG(@"cocos2d: Unable to load font %@", name);
+ [self release];
+ return nil;
+ }
+
+ return [self initWithString:string dimensions:dim alignment:CCTextAlignmentCenter font:font];
+
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+ {
+
+ NSAttributedString *stringWithAttributes =
+ [[[NSAttributedString alloc] initWithString:string
+ attributes:[NSDictionary dictionaryWithObject:[[NSFontManager sharedFontManager]
+ fontWithFamily:name
+ traits:NSUnboldFontMask | NSUnitalicFontMask
+ weight:0
+ size:size]
+ forKey:NSFontAttributeName]
+ ]
+ autorelease];
+
+ dim = NSSizeToCGSize( [stringWithAttributes size] );
+
+ return [self initWithString:string dimensions:dim alignment:CCTextAlignmentCenter attributedString:stringWithAttributes];
+ }
+#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
+
+}
+
+- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size
+{
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+ id uifont = nil;
+
+ uifont = [UIFont fontWithName:name size:size];
+
+#if CC_FONT_LABEL_SUPPORT
+ if( ! uifont )
+ uifont = [[FontManager sharedManager] zFontWithName:name pointSize:size];
+#endif // CC_FONT_LABEL_SUPPORT
+ if( ! uifont ) {
+ CCLOG(@"cocos2d: Texture2d: Invalid Font: %@. Verify the .ttf name", name);
+ [self release];
+ return nil;
+ }
+
+ return [self initWithString:string dimensions:dimensions alignment:alignment font:uifont];
+
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+
+ //String with attributes
+ NSAttributedString *stringWithAttributes =
+ [[[NSAttributedString alloc] initWithString:string
+ attributes:[NSDictionary dictionaryWithObject:[[NSFontManager sharedFontManager]
+ fontWithFamily:name
+ traits:NSUnboldFontMask | NSUnitalicFontMask
+ weight:0
+ size:size]
+ forKey:NSFontAttributeName]
+ ]
+ autorelease];
+
+ return [self initWithString:string dimensions:dimensions alignment:CCTextAlignmentCenter attributedString:stringWithAttributes];
+
+#endif // Mac
+}
+@end
+
+#pragma mark -
+#pragma mark CCTexture2D - PVRSupport
+
+@implementation CCTexture2D (PVRSupport)
+
+// By default PVR images are treated as if they don't have the alpha channel premultiplied
+static BOOL PVRHaveAlphaPremultiplied_ = NO;
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+-(id) initWithPVRTCData: (const void*)data level:(int)level bpp:(int)bpp hasAlpha:(BOOL)hasAlpha length:(int)length
+{
+ // GLint saveName;
+
+ if( ! [[CCConfiguration sharedConfiguration] supportsPVRTC] ) {
+ CCLOG(@"cocos2d: WARNING: PVRTC images is not supported");
+ [self release];
+ return nil;
+ }
+
+ if((self = [super init])) {
+ glGenTextures(1, &name_);
+ glBindTexture(GL_TEXTURE_2D, name_);
+
+ [self setAntiAliasTexParameters];
+
+ GLenum format;
+ GLsizei size = length * length * bpp / 8;
+ if(hasAlpha)
+ format = (bpp == 4) ? GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG : GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
+ else
+ format = (bpp == 4) ? GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG : GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
+
+ if(size < 32)
+ size = 32;
+
+ glCompressedTexImage2D(GL_TEXTURE_2D, level, format, length, length, 0, size, data);
+
+ size_ = CGSizeMake(length, length);
+ width_ = length;
+ height_ = length;
+ maxS_ = 1.0f;
+ maxT_ = 1.0f;
+ hasPremultipliedAlpha_ = PVRHaveAlphaPremultiplied_;
+ }
+ return self;
+}
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
+
+-(id) initWithPVRFile: (NSString*) file
+{
+ if( (self = [super init]) ) {
+ CCTexturePVR *pvr = [[CCTexturePVR alloc] initWithContentsOfFile:file];
+ if( pvr ) {
+ pvr.retainName = YES; // don't dealloc texture on release
+
+ name_ = pvr.name; // texture id
+ maxS_ = 1; // only POT texture are supported
+ maxT_ = 1;
+ width_ = pvr.width;
+ height_ = pvr.height;
+ size_ = CGSizeMake(width_, height_);
+ hasPremultipliedAlpha_ = PVRHaveAlphaPremultiplied_;
+
+ [pvr release];
+
+ [self setAntiAliasTexParameters];
+ } else {
+
+ CCLOG(@"cocos2d: Couldn't load PVR image: %@", file);
+ [self release];
+ return nil;
+ }
+ }
+ return self;
+}
+
++(void) PVRImagesHavePremultipliedAlpha:(BOOL)haveAlphaPremultiplied
+{
+ PVRHaveAlphaPremultiplied_ = haveAlphaPremultiplied;
+}
+@end
+
+#pragma mark -
+#pragma mark CCTexture2D - Drawing
+
+@implementation CCTexture2D (Drawing)
+
+- (void) drawAtPoint:(CGPoint)point
+{
+ GLfloat coordinates[] = { 0.0f, maxT_,
+ maxS_, maxT_,
+ 0.0f, 0.0f,
+ maxS_, 0.0f };
+ GLfloat width = (GLfloat)width_ * maxS_,
+ height = (GLfloat)height_ * maxT_;
+
+ GLfloat vertices[] = { point.x, point.y, 0.0f,
+ width + point.x, point.y, 0.0f,
+ point.x, height + point.y, 0.0f,
+ width + point.x, height + point.y, 0.0f };
+
+ glBindTexture(GL_TEXTURE_2D, name_);
+ glVertexPointer(3, GL_FLOAT, 0, vertices);
+ glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+}
+
+
+- (void) drawInRect:(CGRect)rect
+{
+ GLfloat coordinates[] = { 0.0f, maxT_,
+ maxS_, maxT_,
+ 0.0f, 0.0f,
+ maxS_, 0.0f };
+ GLfloat vertices[] = { rect.origin.x, rect.origin.y, /*0.0f,*/
+ rect.origin.x + rect.size.width, rect.origin.y, /*0.0f,*/
+ rect.origin.x, rect.origin.y + rect.size.height, /*0.0f,*/
+ rect.origin.x + rect.size.width, rect.origin.y + rect.size.height, /*0.0f*/ };
+
+ glBindTexture(GL_TEXTURE_2D, name_);
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+}
+
+@end
+
+
+#pragma mark -
+#pragma mark CCTexture2D - GLFilter
+
+//
+// Use to apply MIN/MAG filter
+//
+@implementation CCTexture2D (GLFilter)
+
+-(void) generateMipmap
+{
+ NSAssert( width_ == ccNextPOT(width_) && height_ == ccNextPOT(height_), @"Mimpap texture only works in POT textures");
+ glBindTexture( GL_TEXTURE_2D, name_ );
+ ccglGenerateMipmap(GL_TEXTURE_2D);
+}
+
+-(void) setTexParameters: (ccTexParams*) texParams
+{
+ NSAssert( (width_ == ccNextPOT(width_) && height_ == ccNextPOT(height_)) ||
+ (texParams->wrapS == GL_CLAMP_TO_EDGE && texParams->wrapT == GL_CLAMP_TO_EDGE),
+ @"GL_CLAMP_TO_EDGE should be used in NPOT textures");
+ glBindTexture( GL_TEXTURE_2D, self.name );
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texParams->minFilter );
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texParams->magFilter );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texParams->wrapS );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texParams->wrapT );
+}
+
+-(void) setAliasTexParameters
+{
+ ccTexParams texParams = { GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE };
+ [self setTexParameters: &texParams];
+}
+
+-(void) setAntiAliasTexParameters
+{
+ ccTexParams texParams = { GL_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE };
+ [self setTexParameters: &texParams];
+}
+@end
+
+
+#pragma mark -
+#pragma mark CCTexture2D - Pixel Format
+
+//
+// Texture options for images that contains alpha
+//
+@implementation CCTexture2D (PixelFormat)
++(void) setDefaultAlphaPixelFormat:(CCTexture2DPixelFormat)format
+{
+ defaultAlphaPixelFormat_ = format;
+}
+
++(CCTexture2DPixelFormat) defaultAlphaPixelFormat
+{
+ return defaultAlphaPixelFormat_;
+}
+@end
+
--- /dev/null
+/*
+ * 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 "ccTypes.h"
+#import "ccConfig.h"
+
+/** A class that implements a Texture Atlas.
+ Supported features:
+ * The atlas file can be a PVRTC, PNG or any other fomrat supported by Texture2D
+ * Quads can be udpated in runtime
+ * Quads can be added in runtime
+ * Quads can be removed in runtime
+ * Quads can be re-ordered in runtime
+ * The TextureAtlas capacity can be increased or decreased in runtime
+ * OpenGL component: V3F, C4B, T2F.
+ The quads are rendered using an OpenGL ES VBO.
+ To render the quads using an interleaved vertex array list, you should modify the ccConfig.h file
+ */
+@interface CCTextureAtlas : NSObject
+{
+ NSUInteger totalQuads_;
+ NSUInteger capacity_;
+ ccV3F_C4B_T2F_Quad *quads_; // quads to be rendered
+ GLushort *indices_;
+ CCTexture2D *texture_;
+#if CC_USES_VBO
+ GLuint buffersVBO_[2]; //0: vertex 1: indices
+#endif // CC_USES_VBO
+}
+
+/** quantity of quads that are going to be drawn */
+@property (nonatomic,readonly) NSUInteger totalQuads;
+/** quantity of quads that can be stored with the current texture atlas size */
+@property (nonatomic,readonly) NSUInteger capacity;
+/** Texture of the texture atlas */
+@property (nonatomic,retain) CCTexture2D *texture;
+/** Quads that are going to be rendered */
+@property (nonatomic,readwrite) ccV3F_C4B_T2F_Quad *quads;
+
+/** creates a TextureAtlas with an filename and with an initial capacity for Quads.
+ * The TextureAtlas capacity can be increased in runtime.
+ */
++(id) textureAtlasWithFile:(NSString*)file capacity:(NSUInteger)capacity;
+
+/** initializes a TextureAtlas with a filename and with a certain capacity for Quads.
+ * The TextureAtlas capacity can be increased in runtime.
+ *
+ * WARNING: Do not reinitialize the TextureAtlas because it will leak memory (issue #706)
+ */
+-(id) initWithFile: (NSString*) file capacity:(NSUInteger)capacity;
+
+/** creates a TextureAtlas with a previously initialized Texture2D object, and
+ * with an initial capacity for n Quads.
+ * The TextureAtlas capacity can be increased in runtime.
+ */
++(id) textureAtlasWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity;
+
+/** initializes a TextureAtlas with a previously initialized Texture2D object, and
+ * with an initial capacity for Quads.
+ * The TextureAtlas capacity can be increased in runtime.
+ *
+ * WARNING: Do not reinitialize the TextureAtlas because it will leak memory (issue #706)
+ */
+-(id) initWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity;
+
+/** updates a Quad (texture, vertex and color) at a certain index
+ * index must be between 0 and the atlas capacity - 1
+ @since v0.8
+ */
+-(void) updateQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger)index;
+
+/** Inserts a Quad (texture, vertex and color) at a certain index
+ index must be between 0 and the atlas capacity - 1
+ @since v0.8
+ */
+-(void) insertQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger)index;
+
+/** Removes the quad that is located at a certain index and inserts it at a new index
+ This operation is faster than removing and inserting in a quad in 2 different steps
+ @since v0.7.2
+*/
+-(void) insertQuadFromIndex:(NSUInteger)fromIndex atIndex:(NSUInteger)newIndex;
+
+/** removes a quad at a given index number.
+ The capacity remains the same, but the total number of quads to be drawn is reduced in 1
+ @since v0.7.2
+ */
+-(void) removeQuadAtIndex:(NSUInteger) index;
+
+/** removes all Quads.
+ The TextureAtlas capacity remains untouched. No memory is freed.
+ The total number of quads to be drawn will be 0
+ @since v0.7.2
+ */
+-(void) removeAllQuads;
+
+
+/** resize the capacity of the Texture Atlas.
+ * The new capacity can be lower or higher than the current one
+ * It returns YES if the resize was successful.
+ * If it fails to resize the capacity it will return NO with a new capacity of 0.
+ */
+-(BOOL) resizeCapacity: (NSUInteger) n;
+
+
+/** draws n quads
+ * n can't be greater than the capacity of the Atlas
+ */
+-(void) drawNumberOfQuads: (NSUInteger) n;
+
+/** draws all the Atlas's Quads
+ */
+-(void) drawQuads;
+
+@end
--- /dev/null
+/*
+ * 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 "CCTextureAtlas.h"
+#import "ccMacros.h"
+#import "CCTexture2D.h"
+#import "CCTextureCache.h"
+
+
+@interface CCTextureAtlas (Private)
+-(void) initIndices;
+@end
+
+//According to some tests GL_TRIANGLE_STRIP is slower, MUCH slower. Probably I'm doing something very wrong
+
+@implementation CCTextureAtlas
+
+@synthesize totalQuads = totalQuads_, capacity = capacity_;
+@synthesize texture = texture_;
+@synthesize quads = quads_;
+
+#pragma mark TextureAtlas - alloc & init
+
++(id) textureAtlasWithFile:(NSString*) file capacity: (NSUInteger) n
+{
+ return [[[self alloc] initWithFile:file capacity:n] autorelease];
+}
+
++(id) textureAtlasWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)n
+{
+ return [[[self alloc] initWithTexture:tex capacity:n] autorelease];
+}
+
+-(id) initWithFile:(NSString*)file capacity:(NSUInteger)n
+{
+ // retained in property
+ CCTexture2D *tex = [[CCTextureCache sharedTextureCache] addImage:file];
+ if( tex )
+ return [self initWithTexture:tex capacity:n];
+
+ // else
+ {
+ CCLOG(@"cocos2d: Could not open file: %@", file);
+ [self release];
+ return nil;
+ }
+}
+
+-(id) initWithTexture:(CCTexture2D*)tex capacity:(NSUInteger)n
+{
+ if( (self=[super init]) ) {
+
+ capacity_ = n;
+ totalQuads_ = 0;
+
+ // retained in property
+ self.texture = tex;
+
+ quads_ = calloc( sizeof(quads_[0]) * capacity_, 1 );
+ indices_ = calloc( sizeof(indices_[0]) * capacity_ * 6, 1 );
+
+ if( ! ( quads_ && indices_) ) {
+ CCLOG(@"cocos2d: CCTextureAtlas: not enough memory");
+ if( quads_ )
+ free(quads_);
+ if( indices_ )
+ free(indices_);
+ return nil;
+ }
+
+#if CC_USES_VBO
+ // initial binding
+ glGenBuffers(2, &buffersVBO_[0]);
+#endif // CC_USES_VBO
+
+ [self initIndices];
+ }
+
+ return self;
+}
+
+- (NSString*) description
+{
+ return [NSString stringWithFormat:@"<%@ = %08X | totalQuads = %i>", [self class], self, totalQuads_];
+}
+
+-(void) dealloc
+{
+ CCLOGINFO(@"cocos2d: deallocing %@",self);
+
+ free(quads_);
+ free(indices_);
+
+#if CC_USES_VBO
+ glDeleteBuffers(2, buffersVBO_);
+#endif // CC_USES_VBO
+
+
+ [texture_ release];
+
+ [super dealloc];
+}
+
+-(void) initIndices
+{
+ for( NSUInteger i=0;i< capacity_;i++) {
+#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
+ indices_[i*6+0] = i*4+0;
+ indices_[i*6+1] = i*4+0;
+ indices_[i*6+2] = i*4+2;
+ indices_[i*6+3] = i*4+1;
+ indices_[i*6+4] = i*4+3;
+ indices_[i*6+5] = i*4+3;
+#else
+ indices_[i*6+0] = i*4+0;
+ indices_[i*6+1] = i*4+1;
+ indices_[i*6+2] = i*4+2;
+
+ // inverted index. issue #179
+ indices_[i*6+3] = i*4+3;
+ indices_[i*6+4] = i*4+2;
+ indices_[i*6+5] = i*4+1;
+// indices_[i*6+3] = i*4+2;
+// indices_[i*6+4] = i*4+3;
+// indices_[i*6+5] = i*4+1;
+#endif
+ }
+
+#if CC_USES_VBO
+ glBindBuffer(GL_ARRAY_BUFFER, buffersVBO_[0]);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(quads_[0]) * capacity_, quads_, GL_DYNAMIC_DRAW);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffersVBO_[1]);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices_[0]) * capacity_ * 6, indices_, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+#endif // CC_USES_VBO
+}
+
+#pragma mark TextureAtlas - Update, Insert, Move & Remove
+
+-(void) updateQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger) n
+{
+ NSAssert(n < capacity_, @"updateQuadWithTexture: Invalid index");
+
+ totalQuads_ = MAX( n+1, totalQuads_);
+
+ quads_[n] = *quad;
+}
+
+
+-(void) insertQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger)index
+{
+ NSAssert(index < capacity_, @"insertQuadWithTexture: Invalid index");
+
+ totalQuads_++;
+ NSAssert( totalQuads_ <= capacity_, @"invalid totalQuads");
+
+ // issue #575. index can be > totalQuads
+ NSInteger remaining = (totalQuads_-1) - index;
+
+ // last object doesn't need to be moved
+ if( remaining > 0)
+ // tex coordinates
+ memmove( &quads_[index+1],&quads_[index], sizeof(quads_[0]) * remaining );
+
+ quads_[index] = *quad;
+}
+
+
+-(void) insertQuadFromIndex:(NSUInteger)oldIndex atIndex:(NSUInteger)newIndex
+{
+ NSAssert(newIndex < totalQuads_, @"insertQuadFromIndex:atIndex: Invalid index");
+ NSAssert(oldIndex < totalQuads_, @"insertQuadFromIndex:atIndex: Invalid index");
+
+ if( oldIndex == newIndex )
+ return;
+
+ NSUInteger howMany = abs( oldIndex - newIndex);
+ NSUInteger dst = oldIndex;
+ NSUInteger src = oldIndex + 1;
+ if( oldIndex > newIndex) {
+ dst = newIndex+1;
+ src = newIndex;
+ }
+
+ // tex coordinates
+ ccV3F_C4B_T2F_Quad quadsBackup = quads_[oldIndex];
+ memmove( &quads_[dst],&quads_[src], sizeof(quads_[0]) * howMany );
+ quads_[newIndex] = quadsBackup;
+}
+
+-(void) removeQuadAtIndex:(NSUInteger) index
+{
+ NSAssert(index < totalQuads_, @"removeQuadAtIndex: Invalid index");
+
+ NSUInteger remaining = (totalQuads_-1) - index;
+
+
+ // last object doesn't need to be moved
+ if( remaining )
+ // tex coordinates
+ memmove( &quads_[index],&quads_[index+1], sizeof(quads_[0]) * remaining );
+
+ totalQuads_--;
+}
+
+-(void) removeAllQuads
+{
+ totalQuads_ = 0;
+}
+
+#pragma mark TextureAtlas - Resize
+
+-(BOOL) resizeCapacity: (NSUInteger) newCapacity
+{
+ if( newCapacity == capacity_ )
+ return YES;
+
+ // update capacity and totolQuads
+ totalQuads_ = MIN(totalQuads_,newCapacity);
+ capacity_ = newCapacity;
+
+ void * tmpQuads = realloc( quads_, sizeof(quads_[0]) * capacity_ );
+ void * tmpIndices = realloc( indices_, sizeof(indices_[0]) * capacity_ * 6 );
+
+ if( ! ( tmpQuads && tmpIndices) ) {
+ CCLOG(@"cocos2d: CCTextureAtlas: not enough memory");
+ if( tmpQuads )
+ free(tmpQuads);
+ else
+ free(quads_);
+
+ if( tmpIndices )
+ free(tmpIndices);
+ else
+ free(indices_);
+
+ indices_ = nil;
+ quads_ = nil;
+ capacity_ = totalQuads_ = 0;
+ return NO;
+ }
+
+ quads_ = tmpQuads;
+ indices_ = tmpIndices;
+
+ [self initIndices];
+
+ return YES;
+}
+
+#pragma mark TextureAtlas - Drawing
+
+-(void) drawQuads
+{
+ return [self drawNumberOfQuads: totalQuads_];
+}
+
+-(void) drawNumberOfQuads: (NSUInteger) n
+{
+ // 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, buffersVBO_[0]);
+
+ // XXX: update is done in draw... perhaps it should be done in a timer
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(quads_[0]) * n, quads_);
+
+ // vertices
+ glVertexPointer(3, GL_FLOAT, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, vertices));
+
+ // colors
+ glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, colors));
+
+ // tex coords
+ glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, texCoords));
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffersVBO_[1]);
+#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
+ glDrawElements(GL_TRIANGLE_STRIP, n*6, GL_UNSIGNED_SHORT, (GLvoid*)0);
+#else
+ glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, (GLvoid*)0);
+#endif // CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+#else // ! CC_USES_VBO
+
+ NSUInteger offset = (NSUInteger)quads_;
+
+ // vertex
+ NSUInteger diff = offsetof( ccV3F_C4B_T2F, vertices);
+ glVertexPointer(3, GL_FLOAT, kQuadSize, (GLvoid*) (offset + diff) );
+
+ // color
+ diff = offsetof( ccV3F_C4B_T2F, colors);
+ glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*)(offset + diff));
+
+ // tex coords
+ diff = offsetof( ccV3F_C4B_T2F, texCoords);
+ glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*)(offset + diff));
+
+#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
+ glDrawElements(GL_TRIANGLE_STRIP, n*6, GL_UNSIGNED_SHORT, indices_);
+#else
+ glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, indices_);
+#endif
+
+#endif // CC_USES_VBO
+}
+
+@end
--- /dev/null
+/*
+ * 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 <Availability.h>
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#import <CoreGraphics/CGImage.h>
+#endif
+
+#import <Foundation/Foundation.h>
+
+@class CCTexture2D;
+
+/** Singleton that handles the loading of textures
+ * Once the texture is loaded, the next time it will return
+ * a reference of the previously loaded texture reducing GPU & CPU memory
+ */
+@interface CCTextureCache : NSObject
+{
+ NSMutableDictionary *textures_;
+ NSLock *dictLock_;
+ NSLock *contextLock_;
+}
+
+/** Retruns ths shared instance of the cache */
++ (CCTextureCache *) sharedTextureCache;
+
+/** purges the cache. It releases the retained instance.
+ @since v0.99.0
+ */
++(void)purgeSharedTextureCache;
+
+
+/** Returns a Texture2D object given an file image
+ * If the file image was not previously loaded, it will create a new CCTexture2D
+ * object and it will return it. It will use the filename as a key.
+ * Otherwise it will return a reference of a previosly loaded image.
+ * Supported image extensions: .png, .bmp, .tiff, .jpeg, .pvr, .gif
+ */
+-(CCTexture2D*) addImage: (NSString*) fileimage;
+
+/** Returns a Texture2D object given a file image
+ * If the file image was not previously loaded, it will create a new CCTexture2D object and it will return it.
+ * Otherwise it will load a texture in a new thread, and when the image is loaded, the callback will be called with the Texture2D as a parameter.
+ * The callback will be called from the main thread, so it is safe to create any cocos2d object from the callback.
+ * Supported image extensions: .png, .bmp, .tiff, .jpeg, .pvr, .gif
+ * @since v0.8
+ */
+-(void) addImageAsync:(NSString*) filename target:(id)target selector:(SEL)selector;
+
+/** Returns a Texture2D object given an CGImageRef image
+ * If the image was not previously loaded, it will create a new CCTexture2D object and it will return it.
+ * Otherwise it will return a reference of a previously loaded image
+ * The "key" parameter will be used as the "key" for the cache.
+ * If "key" is nil, then a new texture will be created each time.
+ * @since v0.8
+ */
+-(CCTexture2D*) addCGImage: (CGImageRef) image forKey: (NSString *)key;
+
+/** Returns an already created texture. Returns nil if the texture doesn't exist.
+ @since v0.99.5
+ */
+-(CCTexture2D *) textureForKey:(NSString *)key;
+
+/** Purges the dictionary of loaded textures.
+ * Call this method if you receive the "Memory Warning"
+ * In the short term: it will free some resources preventing your app from being killed
+ * In the medium term: it will allocate more resources
+ * In the long term: it will be the same
+ */
+-(void) removeAllTextures;
+
+/** Removes unused textures
+ * Textures that have a retain count of 1 will be deleted
+ * It is convinient to call this method after when starting a new Scene
+ * @since v0.8
+ */
+-(void) removeUnusedTextures;
+
+/** Deletes a texture from the cache given a texture
+ */
+-(void) removeTexture: (CCTexture2D*) tex;
+
+/** Deletes a texture from the cache given a its key name
+ @since v0.99.4
+ */
+-(void) removeTextureForKey: (NSString*) textureKeyName;
+
+@end
+
+
+@interface CCTextureCache (PVRSupport)
+
+/** Returns a Texture2D object given an PVRTC RAW filename
+ * If the file image was not previously loaded, it will create a new CCTexture2D
+ * object and it will return it. Otherwise it will return a reference of a previosly loaded image
+ *
+ * It can only load square images: width == height, and it must be a power of 2 (128,256,512...)
+ * bpp can only be 2 or 4. 2 means more compression but lower quality.
+ * hasAlpha: whether or not the image contains alpha channel
+ *
+ * IMPORTANT: This method is only defined on iOS. It is not supported on the Mac version.
+ */
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+-(CCTexture2D*) addPVRTCImage:(NSString*)fileimage bpp:(int)bpp hasAlpha:(BOOL)alpha width:(int)w;
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
+
+/** Returns a Texture2D object given an PVR filename.
+ * If the file image was not previously loaded, it will create a new CCTexture2D
+ * object and it will return it. Otherwise it will return a reference of a previosly loaded image
+ *
+ */
+-(CCTexture2D*) addPVRImage:(NSString*) filename;
+
+@end
+
+
--- /dev/null
+/*
+ * 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 <Availability.h>
+
+#import "Platforms/CCGL.h"
+#import "CCTextureCache.h"
+#import "CCTexture2D.h"
+#import "CCTexturePVR.h"
+#import "ccMacros.h"
+#import "CCConfiguration.h"
+#import "Support/CCFileUtils.h"
+#import "CCDirector.h"
+#import "ccConfig.h"
+
+// needed for CCCallFuncO in Mac-display_link version
+#import "CCActionManager.h"
+#import "CCActionInstant.h"
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+static EAGLContext *auxGLcontext = nil;
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+static NSOpenGLContext *auxGLcontext = nil;
+#endif
+
+
+@interface CCAsyncObject : NSObject
+{
+ SEL selector_;
+ id target_;
+ id data_;
+}
+@property (readwrite,assign) SEL selector;
+@property (readwrite,retain) id target;
+@property (readwrite,retain) id data;
+@end
+
+@implementation CCAsyncObject
+@synthesize selector = selector_;
+@synthesize target = target_;
+@synthesize data = data_;
+- (void) dealloc
+{
+ CCLOGINFO(@"cocos2d: deallocing %@", self);
+ [target_ release];
+ [data_ release];
+ [super dealloc];
+}
+@end
+
+
+@implementation CCTextureCache
+
+#pragma mark TextureCache - Alloc, Init & Dealloc
+static CCTextureCache *sharedTextureCache;
+
++ (CCTextureCache *)sharedTextureCache
+{
+ if (!sharedTextureCache)
+ sharedTextureCache = [[CCTextureCache alloc] init];
+
+ return sharedTextureCache;
+}
+
++(id)alloc
+{
+ NSAssert(sharedTextureCache == nil, @"Attempted to allocate a second instance of a singleton.");
+ return [super alloc];
+}
+
++(void)purgeSharedTextureCache
+{
+ [sharedTextureCache release];
+ sharedTextureCache = nil;
+}
+
+-(id) init
+{
+ if( (self=[super init]) ) {
+ textures_ = [[NSMutableDictionary dictionaryWithCapacity: 10] retain];
+ dictLock_ = [[NSLock alloc] init];
+ contextLock_ = [[NSLock alloc] init];
+ }
+
+ return self;
+}
+
+- (NSString*) description
+{
+ return [NSString stringWithFormat:@"<%@ = %08X | num of textures = %i | keys: %@>",
+ [self class],
+ self,
+ [textures_ count],
+ [textures_ allKeys]
+ ];
+
+}
+
+-(void) dealloc
+{
+ CCLOG(@"cocos2d: deallocing %@", self);
+
+ [textures_ release];
+ [dictLock_ release];
+ [contextLock_ release];
+ [auxGLcontext release];
+ auxGLcontext = nil;
+ sharedTextureCache = nil;
+ [super dealloc];
+}
+
+#pragma mark TextureCache - Add Images
+
+-(void) addImageWithAsyncObject:(CCAsyncObject*)async
+{
+ NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+ // textures will be created on the main OpenGL context
+ // it seems that in SDK 2.2.x there can't be 2 threads creating textures at the same time
+ // the lock is used for this purpose: issue #472
+ [contextLock_ lock];
+ if( auxGLcontext == nil ) {
+ auxGLcontext = [[EAGLContext alloc]
+ initWithAPI:kEAGLRenderingAPIOpenGLES1
+ sharegroup:[[[[CCDirector sharedDirector] openGLView] context] sharegroup]];
+
+ if( ! auxGLcontext )
+ CCLOG(@"cocos2d: TextureCache: Could not create EAGL context");
+ }
+
+ if( [EAGLContext setCurrentContext:auxGLcontext] ) {
+
+ // load / create the texture
+ CCTexture2D *tex = [self addImage:async.data];
+
+ // The callback will be executed on the main thread
+ [async.target performSelectorOnMainThread:async.selector withObject:tex waitUntilDone:NO];
+
+ [EAGLContext setCurrentContext:nil];
+ } else {
+ CCLOG(@"cocos2d: TetureCache: EAGLContext error");
+ }
+ [contextLock_ unlock];
+
+ [autoreleasepool release];
+
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+
+ [contextLock_ lock];
+ if( auxGLcontext == nil ) {
+
+ MacGLView *view = [[CCDirector sharedDirector] openGLView];
+
+ NSOpenGLPixelFormat *pf = [view pixelFormat];
+ NSOpenGLContext *share = [view openGLContext];
+
+ auxGLcontext = [[NSOpenGLContext alloc] initWithFormat:pf shareContext:share];
+
+ if( ! auxGLcontext )
+ CCLOG(@"cocos2d: TextureCache: Could not create NSOpenGLContext");
+ }
+
+ [auxGLcontext makeCurrentContext];
+
+ // load / create the texture
+ CCTexture2D *tex = [self addImage:async.data];
+
+#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
+ id action = [CCCallFuncO actionWithTarget:async.target selector:async.selector object:tex];
+ [[CCActionManager sharedManager] addAction:action target:async.target paused:NO];
+#else
+ // The callback will be executed on the main thread
+ [async.target performSelector:async.selector
+ onThread:[[CCDirector sharedDirector] runningThread]
+ withObject:tex
+ waitUntilDone:NO];
+#endif
+
+
+ [NSOpenGLContext clearCurrentContext];
+
+ [contextLock_ unlock];
+
+ [autoreleasepool release];
+
+#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
+}
+
+-(void) addImageAsync: (NSString*)path target:(id)target selector:(SEL)selector
+{
+ NSAssert(path != nil, @"TextureCache: fileimage MUST not be nill");
+
+ // optimization
+
+ CCTexture2D * tex;
+
+ path = ccRemoveHDSuffixFromFile(path);
+
+ if( (tex=[textures_ objectForKey: path] ) ) {
+ [target performSelector:selector withObject:tex];
+ return;
+ }
+
+ // schedule the load
+
+ CCAsyncObject *asyncObject = [[CCAsyncObject alloc] init];
+ asyncObject.selector = selector;
+ asyncObject.target = target;
+ asyncObject.data = path;
+
+ [NSThread detachNewThreadSelector:@selector(addImageWithAsyncObject:) toTarget:self withObject:asyncObject];
+ [asyncObject release];
+}
+
+-(CCTexture2D*) addImage: (NSString*) path
+{
+ NSAssert(path != nil, @"TextureCache: fileimage MUST not be nill");
+
+ CCTexture2D * tex = nil;
+
+ // MUTEX:
+ // Needed since addImageAsync calls this method from a different thread
+ [dictLock_ lock];
+
+ // remove possible -HD suffix to prevent caching the same image twice (issue #1040)
+ path = ccRemoveHDSuffixFromFile( path );
+
+ tex=[textures_ objectForKey: path];
+
+ if( ! tex ) {
+
+ NSString *lowerCase = [path lowercaseString];
+ // all images are handled by UIImage except PVR extension that is handled by our own handler
+
+ if ( [lowerCase hasSuffix:@".pvr"] || [lowerCase hasSuffix:@".pvr.gz"] || [lowerCase hasSuffix:@".pvr.ccz"] )
+ tex = [self addPVRImage:path];
+
+ // Only iPhone
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+ // Issue #886: TEMPORARY FIX FOR TRANSPARENT JPEGS IN IOS4
+ else if ( ( [[CCConfiguration sharedConfiguration] OSVersion] >= kCCiOSVersion_4_0) &&
+ ( [lowerCase hasSuffix:@".jpg"] || [lowerCase hasSuffix:@".jpeg"] )
+ ) {
+ // convert jpg to png before loading the texture
+
+ NSString *fullpath = [CCFileUtils fullPathFromRelativePath: path ];
+
+ UIImage *jpg = [[UIImage alloc] initWithContentsOfFile:fullpath];
+ UIImage *png = [[UIImage alloc] initWithData:UIImagePNGRepresentation(jpg)];
+ tex = [ [CCTexture2D alloc] initWithImage: png ];
+ [png release];
+ [jpg release];
+
+ if( tex )
+ [textures_ setObject: tex forKey:path];
+ else
+ CCLOG(@"cocos2d: Couldn't add image:%@ in CCTextureCache", path);
+
+ [tex release];
+ }
+
+ else {
+
+ // prevents overloading the autorelease pool
+ NSString *fullpath = [CCFileUtils fullPathFromRelativePath: path ];
+
+ UIImage *image = [ [UIImage alloc] initWithContentsOfFile: fullpath ];
+ tex = [ [CCTexture2D alloc] initWithImage: image ];
+ [image release];
+
+ if( tex )
+ [textures_ setObject: tex forKey:path];
+ else
+ CCLOG(@"cocos2d: Couldn't add image:%@ in CCTextureCache", path);
+
+ [tex release];
+ }
+
+ // Only in Mac
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+ else {
+ NSString *fullpath = [CCFileUtils fullPathFromRelativePath: path ];
+
+ NSData *data = [[NSData alloc] initWithContentsOfFile:fullpath];
+ NSBitmapImageRep *image = [[NSBitmapImageRep alloc] initWithData:data];
+ tex = [ [CCTexture2D alloc] initWithImage:[image CGImage]];
+
+ [data release];
+ [image release];
+
+ if( tex )
+ [textures_ setObject: tex forKey:path];
+ else
+ CCLOG(@"cocos2d: Couldn't add image:%@ in CCTextureCache", path);
+
+ [tex release];
+ }
+#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
+
+ }
+
+ [dictLock_ unlock];
+
+ return tex;
+}
+
+
+-(CCTexture2D*) addCGImage: (CGImageRef) imageref forKey: (NSString *)key
+{
+ NSAssert(imageref != nil, @"TextureCache: image MUST not be nill");
+
+ CCTexture2D * tex = nil;
+
+ // If key is nil, then create a new texture each time
+ if( key && (tex=[textures_ objectForKey: key] ) ) {
+ return tex;
+ }
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+ // prevents overloading the autorelease pool
+ UIImage *image = [[UIImage alloc] initWithCGImage:imageref];
+ tex = [[CCTexture2D alloc] initWithImage: image];
+ [image release];
+
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+ tex = [[CCTexture2D alloc] initWithImage: imageref];
+#endif
+
+ if(tex && key)
+ [textures_ setObject: tex forKey:key];
+ else
+ CCLOG(@"cocos2d: Couldn't add CGImage in CCTextureCache");
+
+ return [tex autorelease];
+}
+
+#pragma mark TextureCache - Remove
+
+-(void) removeAllTextures
+{
+ [textures_ removeAllObjects];
+}
+
+-(void) removeUnusedTextures
+{
+ NSArray *keys = [textures_ allKeys];
+ for( id key in keys ) {
+ id value = [textures_ objectForKey:key];
+ if( [value retainCount] == 1 ) {
+ CCLOG(@"cocos2d: CCTextureCache: removing unused texture: %@", key);
+ [textures_ removeObjectForKey:key];
+ }
+ }
+}
+
+-(void) removeTexture: (CCTexture2D*) tex
+{
+ if( ! tex )
+ return;
+
+ NSArray *keys = [textures_ allKeysForObject:tex];
+
+ for( NSUInteger i = 0; i < [keys count]; i++ )
+ [textures_ removeObjectForKey:[keys objectAtIndex:i]];
+}
+
+-(void) removeTextureForKey:(NSString*)name
+{
+ if( ! name )
+ return;
+
+ [textures_ removeObjectForKey:name];
+}
+
+#pragma mark TextureCache - Get
+- (CCTexture2D *)textureForKey:(NSString *)key
+{
+ return [textures_ objectForKey:key];
+}
+
+@end
+
+
+@implementation CCTextureCache (PVRSupport)
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+-(CCTexture2D*) addPVRTCImage:(NSString*)path bpp:(int)bpp hasAlpha:(BOOL)alpha width:(int)w
+{
+ NSAssert(path != nil, @"TextureCache: fileimage MUST not be nill");
+ NSAssert( bpp==2 || bpp==4, @"TextureCache: bpp must be either 2 or 4");
+
+ CCTexture2D * tex;
+
+ // remove possible -HD suffix to prevent caching the same image twice (issue #1040)
+ path = ccRemoveHDSuffixFromFile( path );
+
+ if( (tex=[textures_ objectForKey: path] ) ) {
+ return tex;
+ }
+
+ // Split up directory and filename
+ NSString *fullpath = [CCFileUtils fullPathFromRelativePath:path];
+
+ NSData *nsdata = [[NSData alloc] initWithContentsOfFile:fullpath];
+ tex = [[CCTexture2D alloc] initWithPVRTCData:[nsdata bytes] level:0 bpp:bpp hasAlpha:alpha length:w];
+ if( tex )
+ [textures_ setObject: tex forKey:path];
+ else
+ CCLOG(@"cocos2d: Couldn't add PVRTCImage:%@ in CCTextureCache",path);
+
+ [nsdata release];
+
+ return [tex autorelease];
+}
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
+
+-(CCTexture2D*) addPVRImage:(NSString*)path
+{
+ NSAssert(path != nil, @"TextureCache: fileimage MUST not be nill");
+
+ CCTexture2D * tex;
+
+ // remove possible -HD suffix to prevent caching the same image twice (issue #1040)
+ path = ccRemoveHDSuffixFromFile( path );
+
+ if( (tex=[textures_ objectForKey: path] ) ) {
+ return tex;
+ }
+
+ // Split up directory and filename
+ NSString *fullpath = [CCFileUtils fullPathFromRelativePath:path];
+
+ tex = [[CCTexture2D alloc] initWithPVRFile: fullpath];
+ if( tex )
+ [textures_ setObject: tex forKey:path];
+ else
+ CCLOG(@"cocos2d: Couldn't add PVRImage:%@ in CCTextureCache",path);
+
+ return [tex autorelease];
+}
+
+@end
--- /dev/null
+/*
+
+File: PVRTexture.h
+Abstract: The PVRTexture class is responsible for loading .pvr files.
+
+Version: 1.0
+
+Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
+("Apple") in consideration of your agreement to the following terms, and your
+use, installation, modification or redistribution of this Apple software
+constitutes acceptance of these terms. If you do not agree with these terms,
+please do not use, install, modify or redistribute this Apple software.
+
+In consideration of your agreement to abide by the following terms, and subject
+to these terms, Apple grants you a personal, non-exclusive license, under
+Apple's copyrights in this original Apple software (the "Apple Software"), to
+use, reproduce, modify and redistribute the Apple Software, with or without
+modifications, in source and/or binary forms; provided that if you redistribute
+the Apple Software in its entirety and without modifications, you must retain
+this notice and the following text and disclaimers in all such redistributions
+of the Apple Software.
+Neither the name, trademarks, service marks or logos of Apple Inc. may be used
+to endorse or promote products derived from the Apple Software without specific
+prior written permission from Apple. Except as expressly stated in this notice,
+no other rights or licenses, express or implied, are granted by Apple herein,
+including but not limited to any patent rights that may be infringed by your
+derivative works or by other works in which the Apple Software may be
+incorporated.
+
+The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
+DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
+CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Copyright (C) 2008 Apple Inc. All Rights Reserved.
+
+*/
+
+#import <Foundation/Foundation.h>
+
+#import "Platforms/CCGL.h"
+#import "CCTextureCache.h"
+#import "CCTexture2D.h"
+#import "ccCArray.h"
+
+#pragma mark -
+#pragma mark CCTexturePVR
+
+struct CCPVRMipmap {
+ unsigned char *address;
+ unsigned int len;
+};
+
+enum {
+ CC_PVRMIPMAP_MAX = 16,
+};
+
+/** CCTexturePVR
+
+ Object that loads PVR images.
+
+ Supported PVR formats:
+ - RGBA8888
+ - BGRA8888
+ - RGBA4444
+ - RGBA5551
+ - RGB565
+ - A8
+ - I8
+ - AI88
+ - PVRTC 4BPP
+ - PVRTC 2BPP
+
+ Limitations:
+ Pre-generated mipmaps, such as PVR textures with mipmap levels embedded in file,
+ are only supported if all individual sprites are of _square_ size.
+ To use mipmaps with non-square textures, instead call CCTexture2D#generateMipmap on the sheet texture itself
+ (and to save space, save the PVR sprite sheet without mip maps included).
+ */
+@interface CCTexturePVR : NSObject
+{
+ struct CCPVRMipmap mipmaps_[CC_PVRMIPMAP_MAX]; // pointer to mipmap images
+ int numberOfMipmaps_; // number of mipmap used
+
+ unsigned int tableFormatIndex_;
+ uint32_t width_, height_;
+ GLuint name_;
+ BOOL hasAlpha_;
+
+ // cocos2d integration
+ BOOL retainName_;
+}
+
+- (id)initWithContentsOfFile:(NSString *)path;
+- (id)initWithContentsOfURL:(NSURL *)url;
++ (id)pvrTextureWithContentsOfFile:(NSString *)path;
++ (id)pvrTextureWithContentsOfURL:(NSURL *)url;
+
+@property (nonatomic,readonly) GLuint name;
+@property (nonatomic,readonly) uint32_t width;
+@property (nonatomic,readonly) uint32_t height;
+@property (nonatomic,readonly) BOOL hasAlpha;
+
+// cocos2d integration
+@property (nonatomic,readwrite) BOOL retainName;
+
+@end
+
+
--- /dev/null
+/*
+
+File: PVRTexture.m
+Abstract: The PVRTexture class is responsible for loading .pvr files.
+
+Version: 1.0
+
+Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
+("Apple") in consideration of your agreement to the following terms, and your
+use, installation, modification or redistribution of this Apple software
+constitutes acceptance of these terms. If you do not agree with these terms,
+please do not use, install, modify or redistribute this Apple software.
+
+In consideration of your agreement to abide by the following terms, and subject
+to these terms, Apple grants you a personal, non-exclusive license, under
+Apple's copyrights in this original Apple software (the "Apple Software"), to
+use, reproduce, modify and redistribute the Apple Software, with or without
+modifications, in source and/or binary forms; provided that if you redistribute
+the Apple Software in its entirety and without modifications, you must retain
+this notice and the following text and disclaimers in all such redistributions
+of the Apple Software.
+Neither the name, trademarks, service marks or logos of Apple Inc. may be used
+to endorse or promote products derived from the Apple Software without specific
+prior written permission from Apple. Except as expressly stated in this notice,
+no other rights or licenses, express or implied, are granted by Apple herein,
+including but not limited to any patent rights that may be infringed by your
+derivative works or by other works in which the Apple Software may be
+incorporated.
+
+The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
+DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
+CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Copyright (C) 2008 Apple Inc. All Rights Reserved.
+
+*/
+
+/*
+ * Extended PVR formats for cocos2d project ( http://www.cocos2d-iphone.org )
+ * - RGBA8888
+ * - BGRA8888
+ * - RGBA4444
+ * - RGBA5551
+ * - RGB565
+ * - A8
+ * - I8
+ * - AI88
+ */
+
+#import <Availability.h>
+
+#import <zlib.h>
+
+#import "CCTexturePVR.h"
+#import "ccMacros.h"
+#import "CCConfiguration.h"
+#import "Support/ccUtils.h"
+#import "Support/CCFileUtils.h"
+#import "Support/ZipUtils.h"
+
+#pragma mark -
+#pragma mark CCTexturePVR
+
+#define PVR_TEXTURE_FLAG_TYPE_MASK 0xff
+#define PVR_TEXTURE_FLAG_FLIPPED_MASK 0x10000
+
+static char gPVRTexIdentifier[4] = "PVR!";
+
+enum
+{
+ kPVRTextureFlagTypeRGBA_4444= 0x10,
+ kPVRTextureFlagTypeRGBA_5551,
+ kPVRTextureFlagTypeRGBA_8888,
+ kPVRTextureFlagTypeRGB_565,
+ kPVRTextureFlagTypeRGB_555, // unsupported
+ kPVRTextureFlagTypeRGB_888, // unsupported
+ kPVRTextureFlagTypeI_8,
+ kPVRTextureFlagTypeAI_88,
+ kPVRTextureFlagTypePVRTC_2,
+ kPVRTextureFlagTypePVRTC_4,
+ kPVRTextureFlagTypeBGRA_8888,
+ kPVRTextureFlagTypeA_8,
+};
+
+static const uint32_t tableFormats[][6] = {
+
+ // - PVR texture format
+ // - OpenGL internal format
+ // - OpenGL format
+ // - OpenGL type
+ // - bpp
+ // - compressed
+ { kPVRTextureFlagTypeRGBA_4444, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 16, NO },
+ { kPVRTextureFlagTypeRGBA_5551, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 16, NO },
+ { kPVRTextureFlagTypeRGBA_8888, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 32, NO },
+ { kPVRTextureFlagTypeRGB_565, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 16, NO },
+ { kPVRTextureFlagTypeI_8, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 8, NO },
+ { kPVRTextureFlagTypeAI_88, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 16, NO },
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+ { kPVRTextureFlagTypePVRTC_2, GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, -1, -1, 2, YES },
+ { kPVRTextureFlagTypePVRTC_4, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, -1, -1, 4, YES },
+#endif // iphone only
+ { kPVRTextureFlagTypeBGRA_8888, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE, 32, NO },
+ { kPVRTextureFlagTypeA_8, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, 8, NO },
+};
+#define MAX_TABLE_ELEMENTS (sizeof(tableFormats) / sizeof(tableFormats[0]))
+
+enum {
+ kCCInternalPVRTextureFormat,
+ kCCInternalOpenGLInternalFormat,
+ kCCInternalOpenGLFormat,
+ kCCInternalOpenGLType,
+ kCCInternalBPP,
+ kCCInternalCompressedImage,
+};
+
+typedef struct _PVRTexHeader
+{
+ uint32_t headerLength;
+ uint32_t height;
+ uint32_t width;
+ uint32_t numMipmaps;
+ uint32_t flags;
+ uint32_t dataLength;
+ uint32_t bpp;
+ uint32_t bitmaskRed;
+ uint32_t bitmaskGreen;
+ uint32_t bitmaskBlue;
+ uint32_t bitmaskAlpha;
+ uint32_t pvrTag;
+ uint32_t numSurfs;
+} PVRTexHeader;
+
+
+@implementation CCTexturePVR
+
+@synthesize name = name_;
+@synthesize width = width_;
+@synthesize height = height_;
+@synthesize hasAlpha = hasAlpha_;
+
+// cocos2d integration
+@synthesize retainName = retainName_;
+
+
+- (BOOL)unpackPVRData:(unsigned char*)data PVRLen:(unsigned int)len
+{
+ BOOL success = FALSE;
+ PVRTexHeader *header = NULL;
+ uint32_t flags, pvrTag;
+ uint32_t dataLength = 0, dataOffset = 0, dataSize = 0;
+ uint32_t blockSize = 0, widthBlocks = 0, heightBlocks = 0;
+ uint32_t width = 0, height = 0, bpp = 4;
+ uint8_t *bytes = NULL;
+ uint32_t formatFlags;
+
+ header = (PVRTexHeader *)data;
+
+ pvrTag = CFSwapInt32LittleToHost(header->pvrTag);
+
+ if ((uint32_t)gPVRTexIdentifier[0] != ((pvrTag >> 0) & 0xff) ||
+ (uint32_t)gPVRTexIdentifier[1] != ((pvrTag >> 8) & 0xff) ||
+ (uint32_t)gPVRTexIdentifier[2] != ((pvrTag >> 16) & 0xff) ||
+ (uint32_t)gPVRTexIdentifier[3] != ((pvrTag >> 24) & 0xff))
+ {
+ return FALSE;
+ }
+
+ flags = CFSwapInt32LittleToHost(header->flags);
+ formatFlags = flags & PVR_TEXTURE_FLAG_TYPE_MASK;
+ BOOL flipped = flags & PVR_TEXTURE_FLAG_FLIPPED_MASK;
+ if( flipped )
+ CCLOG(@"cocos2d: WARNING: Image is flipped. Regenerate it using PVRTexTool");
+
+ if( header->width != ccNextPOT(header->width) || header->height != ccNextPOT(header->height) ) {
+ CCLOG(@"cocos2d: WARNING: PVR NPOT textures are not supported. Regenerate it.");
+ return FALSE;
+ }
+
+ for( tableFormatIndex_=0; tableFormatIndex_ < (unsigned int)MAX_TABLE_ELEMENTS ; tableFormatIndex_++) {
+ if( tableFormats[tableFormatIndex_][kCCInternalPVRTextureFormat] == formatFlags ) {
+
+ numberOfMipmaps_ = 0;
+
+ width_ = width = CFSwapInt32LittleToHost(header->width);
+ height_ = height = CFSwapInt32LittleToHost(header->height);
+
+ if (CFSwapInt32LittleToHost(header->bitmaskAlpha))
+ hasAlpha_ = TRUE;
+ else
+ hasAlpha_ = FALSE;
+
+ dataLength = CFSwapInt32LittleToHost(header->dataLength);
+ bytes = ((uint8_t *)data) + sizeof(PVRTexHeader);
+
+ // Calculate the data size for each texture level and respect the minimum number of blocks
+ while (dataOffset < dataLength)
+ {
+ switch (formatFlags) {
+ case kPVRTextureFlagTypePVRTC_2:
+ blockSize = 8 * 4; // Pixel by pixel block size for 2bpp
+ widthBlocks = width / 8;
+ heightBlocks = height / 4;
+ bpp = 2;
+ break;
+ case kPVRTextureFlagTypePVRTC_4:
+ blockSize = 4 * 4; // Pixel by pixel block size for 4bpp
+ widthBlocks = width / 4;
+ heightBlocks = height / 4;
+ bpp = 4;
+ break;
+ case kPVRTextureFlagTypeBGRA_8888:
+ if( ! [[CCConfiguration sharedConfiguration] supportsBGRA8888] ) {
+ CCLOG(@"cocos2d: TexturePVR. BGRA8888 not supported on this device");
+ return FALSE;
+ }
+ default:
+ blockSize = 1;
+ widthBlocks = width;
+ heightBlocks = height;
+ bpp = tableFormats[ tableFormatIndex_][ kCCInternalBPP];
+ break;
+ }
+
+ // Clamp to minimum number of blocks
+ if (widthBlocks < 2)
+ widthBlocks = 2;
+ if (heightBlocks < 2)
+ heightBlocks = 2;
+
+ dataSize = widthBlocks * heightBlocks * ((blockSize * bpp) / 8);
+ float packetLenght = (dataLength-dataOffset);
+ packetLenght = packetLenght > dataSize ? dataSize : packetLenght;
+
+ mipmaps_[numberOfMipmaps_].address = bytes+dataOffset;
+ mipmaps_[numberOfMipmaps_].len = packetLenght;
+ numberOfMipmaps_++;
+
+ NSAssert( numberOfMipmaps_ < CC_PVRMIPMAP_MAX, @"TexturePVR: Maximum number of mimpaps reached. Increate the CC_PVRMIPMAP_MAX value");
+
+ dataOffset += packetLenght;
+
+ width = MAX(width >> 1, 1);
+ height = MAX(height >> 1, 1);
+ }
+
+ success = TRUE;
+ break;
+ }
+ }
+
+ if( ! success )
+ CCLOG(@"cocos2d: WARNING: Unssupported PVR Pixel Format: 0x%2x", formatFlags);
+
+ return success;
+}
+
+
+- (BOOL)createGLTexture
+{
+ NSUInteger width = width_;
+ NSUInteger height = height_;
+ GLenum err;
+
+ if (numberOfMipmaps_ > 0)
+ {
+ if (name_ != 0)
+ glDeleteTextures(1, &name_);
+
+ glGenTextures(1, &name_);
+ glBindTexture(GL_TEXTURE_2D, name_);
+ }
+
+ // Generate textures with mipmaps
+ for (NSUInteger i=0; i < numberOfMipmaps_; i++)
+ {
+ GLenum internalFormat = tableFormats[tableFormatIndex_][kCCInternalOpenGLInternalFormat];
+ GLenum format = tableFormats[tableFormatIndex_][kCCInternalOpenGLFormat];
+ GLenum type = tableFormats[tableFormatIndex_][kCCInternalOpenGLType];
+ BOOL compressed = tableFormats[tableFormatIndex_][kCCInternalCompressedImage];
+
+ if( compressed && ! [[CCConfiguration sharedConfiguration] supportsPVRTC] ) {
+ CCLOG(@"cocos2d: WARNING: PVRTC images are not supported");
+ return FALSE;
+ }
+
+ unsigned char *data = mipmaps_[i].address;
+ unsigned int datalen = mipmaps_[i].len;
+
+ if( compressed)
+ glCompressedTexImage2D(GL_TEXTURE_2D, i, internalFormat, width, height, 0, datalen, data);
+ else
+ glTexImage2D(GL_TEXTURE_2D, i, internalFormat, width, height, 0, format, type, data);
+
+ if( i > 0 && (width != height || ccNextPOT(width) != width ) )
+ CCLOG(@"cocos2d: TexturePVR. WARNING. Mipmap level %lu is not squared. Texture won't render correctly. width=%lu != height=%lu", i, width, height);
+
+ err = glGetError();
+ if (err != GL_NO_ERROR)
+ {
+ CCLOG(@"cocos2d: TexturePVR: Error uploading compressed texture level: %u . glError: 0x%04X", (unsigned int)i, err);
+ return FALSE;
+ }
+
+ width = MAX(width >> 1, 1);
+ height = MAX(height >> 1, 1);
+ }
+
+ return TRUE;
+}
+
+
+- (id)initWithContentsOfFile:(NSString *)path
+{
+ if((self = [super init]))
+ {
+ unsigned char *pvrdata = NULL;
+ int pvrlen = 0;
+ NSString *lowerCase = [path lowercaseString];
+
+ if ( [lowerCase hasSuffix:@".ccz"])
+ pvrlen = ccInflateCCZFile( [path UTF8String], &pvrdata );
+
+ else if( [lowerCase hasSuffix:@".gz"] )
+ pvrlen = ccInflateGZipFile( [path UTF8String], &pvrdata );
+
+ else
+ pvrlen = ccLoadFileIntoMemory( [path UTF8String], &pvrdata );
+
+ if( pvrlen < 0 ) {
+ [self release];
+ return nil;
+ }
+
+
+ numberOfMipmaps_ = 0;
+
+ name_ = 0;
+ width_ = height_ = 0;
+ tableFormatIndex_ = -1;
+ hasAlpha_ = FALSE;
+
+ retainName_ = NO; // cocos2d integration
+
+ if( ! [self unpackPVRData:pvrdata PVRLen:pvrlen] || ![self createGLTexture] ) {
+ free(pvrdata);
+ [self release];
+ return nil;
+ }
+
+ free(pvrdata);
+
+ }
+
+ return self;
+}
+
+- (id)initWithContentsOfURL:(NSURL *)url
+{
+ if (![url isFileURL])
+ {
+ CCLOG(@"cocos2d: CCPVRTexture: Only files are supported");
+ [self release];
+ return nil;
+ }
+
+ return [self initWithContentsOfFile:[url path]];
+}
+
+
++ (id)pvrTextureWithContentsOfFile:(NSString *)path
+{
+ return [[[self alloc] initWithContentsOfFile:path] autorelease];
+}
+
+
++ (id)pvrTextureWithContentsOfURL:(NSURL *)url
+{
+ if (![url isFileURL])
+ return nil;
+
+ return [CCTexturePVR pvrTextureWithContentsOfFile:[url path]];
+}
+
+
+- (void)dealloc
+{
+ CCLOGINFO( @"cocos2d: deallocing %@", self);
+
+ if (name_ != 0 && ! retainName_ )
+ glDeleteTextures(1, &name_);
+
+ [super dealloc];
+}
+
+@end
+
--- /dev/null
+/*
+ * 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 "CCAtlasNode.h"
+#import "Support/TGAlib.h"
+
+/** CCTileMapAtlas is a subclass of CCAtlasNode.
+
+ It knows how to render a map based of tiles.
+ The tiles must be in a .PNG format while the map must be a .TGA file.
+
+ For more information regarding the format, please see this post:
+ http://www.cocos2d-iphone.org/archives/27
+
+ All features from CCAtlasNode are valid in CCTileMapAtlas
+
+ IMPORTANT:
+ This class is deprecated. It is maintained for compatibility reasons only.
+ You SHOULD not use this class.
+ Instead, use the newer TMX file format: CCTMXTiledMap
+ */
+@interface CCTileMapAtlas : CCAtlasNode
+{
+
+ /// info about the map file
+ tImageTGA *tgaInfo;
+
+ /// x,y to altas dicctionary
+ NSMutableDictionary *posToAtlasIndex;
+
+ /// numbers of tiles to render
+ int itemsToRender;
+}
+
+/** TileMap info */
+@property (nonatomic,readonly) tImageTGA *tgaInfo;
+
+/** creates a CCTileMap with a tile file (atlas) with a map file and the width and height of each tile in points.
+ The tile file will be loaded using the TextureMgr.
+ */
++(id) tileMapAtlasWithTileFile:(NSString*)tile mapFile:(NSString*)map tileWidth:(int)w tileHeight:(int)h;
+
+/** initializes a CCTileMap with a tile file (atlas) with a map file and the width and height of each tile in points.
+ The file will be loaded using the TextureMgr.
+ */
+-(id) initWithTileFile:(NSString*)tile mapFile:(NSString*)map tileWidth:(int)w tileHeight:(int)h;
+
+/** returns a tile from position x,y.
+ For the moment only channel R is used
+ */
+-(ccColor3B) tileAt: (ccGridSize) position;
+
+/** sets a tile at position x,y.
+ For the moment only channel R is used
+ */
+-(void) setTile:(ccColor3B)tile at:(ccGridSize)position;
+/** dealloc the map from memory */
+-(void) releaseMap;
+@end
--- /dev/null
+/*
+ * 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 "CCTileMapAtlas.h"
+#import "ccMacros.h"
+#import "Support/CCFileUtils.h"
+
+@interface CCTileMapAtlas (Private)
+-(void) loadTGAfile:(NSString*)file;
+-(void) calculateItemsToRender;
+-(void) updateAtlasValueAt:(ccGridSize)pos withValue:(ccColor3B)value withIndex:(int)idx;
+@end
+
+
+@implementation CCTileMapAtlas
+
+@synthesize tgaInfo;
+
+#pragma mark CCTileMapAtlas - Creation & Init
++(id) tileMapAtlasWithTileFile:(NSString*)tile mapFile:(NSString*)map tileWidth:(int)w tileHeight:(int)h
+{
+ return [[[self alloc] initWithTileFile:tile mapFile:map tileWidth:w tileHeight:h] autorelease];
+}
+
+
+-(id) initWithTileFile:(NSString*)tile mapFile:(NSString*)map tileWidth:(int)w tileHeight:(int)h
+{
+ [self loadTGAfile: map];
+ [self calculateItemsToRender];
+
+ if( (self=[super initWithTileFile:tile tileWidth:w tileHeight:h itemsToRender: itemsToRender]) ) {
+
+ posToAtlasIndex = [[NSMutableDictionary dictionaryWithCapacity:itemsToRender] retain];
+
+ [self updateAtlasValues];
+
+ [self setContentSize: CGSizeMake(tgaInfo->width*itemWidth_, tgaInfo->height*itemHeight_)];
+ }
+
+ return self;
+}
+
+-(void) dealloc
+{
+ if( tgaInfo )
+ tgaDestroy(tgaInfo);
+
+ [posToAtlasIndex release];
+
+ [super dealloc];
+}
+
+-(void) releaseMap
+{
+ if( tgaInfo )
+ tgaDestroy(tgaInfo);
+
+ tgaInfo = nil;
+
+ [posToAtlasIndex release];
+ posToAtlasIndex = nil;
+}
+
+-(void) calculateItemsToRender
+{
+ NSAssert( tgaInfo != nil, @"tgaInfo must be non-nil");
+
+ itemsToRender = 0;
+ for(int x = 0;x < tgaInfo->width; x++ ) {
+ for(int y = 0; y < tgaInfo->height; y++ ) {
+ ccColor3B *ptr = (ccColor3B*) tgaInfo->imageData;
+ ccColor3B value = ptr[x + y * tgaInfo->width];
+ if( value.r )
+ itemsToRender++;
+ }
+ }
+}
+
+-(void) loadTGAfile:(NSString*)file
+{
+ NSAssert( file != nil, @"file must be non-nil");
+
+ NSString *path = [CCFileUtils fullPathFromRelativePath:file ];
+
+// //Find the path of the file
+// NSBundle *mainBndl = [CCDirector sharedDirector].loadingBundle;
+// NSString *resourcePath = [mainBndl resourcePath];
+// NSString * path = [resourcePath stringByAppendingPathComponent:file];
+
+ tgaInfo = tgaLoad( [path UTF8String] );
+#if 1
+ if( tgaInfo->status != TGA_OK )
+ [NSException raise:@"TileMapAtlasLoadTGA" format:@"TileMapAtas cannot load TGA file"];
+
+#endif
+}
+
+#pragma mark CCTileMapAtlas - Atlas generation / updates
+
+-(void) setTile:(ccColor3B) tile at:(ccGridSize) pos
+{
+ NSAssert( tgaInfo != nil, @"tgaInfo must not be nil");
+ NSAssert( posToAtlasIndex != nil, @"posToAtlasIndex must not be nil");
+ NSAssert( pos.x < tgaInfo->width, @"Invalid position.x");
+ NSAssert( pos.y < tgaInfo->height, @"Invalid position.x");
+ NSAssert( tile.r != 0, @"R component must be non 0");
+
+ ccColor3B *ptr = (ccColor3B*) tgaInfo->imageData;
+ ccColor3B value = ptr[pos.x + pos.y * tgaInfo->width];
+ if( value.r == 0 )
+ CCLOG(@"cocos2d: Value.r must be non 0.");
+ else {
+ ptr[pos.x + pos.y * tgaInfo->width] = tile;
+
+ // XXX: this method consumes a lot of memory
+ // XXX: a tree of something like that shall be impolemented
+ NSNumber *num = [posToAtlasIndex objectForKey: [NSString stringWithFormat:@"%d,%d", pos.x, pos.y]];
+ [self updateAtlasValueAt:pos withValue:tile withIndex: [num integerValue]];
+ }
+}
+
+-(ccColor3B) tileAt:(ccGridSize) pos
+{
+ NSAssert( tgaInfo != nil, @"tgaInfo must not be nil");
+ NSAssert( pos.x < tgaInfo->width, @"Invalid position.x");
+ NSAssert( pos.y < tgaInfo->height, @"Invalid position.y");
+
+ ccColor3B *ptr = (ccColor3B*) tgaInfo->imageData;
+ ccColor3B value = ptr[pos.x + pos.y * tgaInfo->width];
+
+ return value;
+}
+
+-(void) updateAtlasValueAt:(ccGridSize)pos withValue:(ccColor3B)value withIndex:(int)idx
+{
+ ccV3F_C4B_T2F_Quad quad;
+
+ int x = pos.x;
+ int y = pos.y;
+ float row = (value.r % itemsPerRow_);
+ float col = (value.r / itemsPerRow_);
+
+ float textureWide = [[textureAtlas_ texture] pixelsWide];
+ float textureHigh = [[textureAtlas_ texture] pixelsHigh];
+
+#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
+ float left = (2*row*itemWidth_+1)/(2*textureWide);
+ float right = left+(itemWidth_*2-2)/(2*textureWide);
+ float top = (2*col*itemHeight_+1)/(2*textureHigh);
+ float bottom = top+(itemHeight_*2-2)/(2*textureHigh);
+#else
+ float left = (row*itemWidth_)/textureWide;
+ float right = left+itemWidth_/textureWide;
+ float top = (col*itemHeight_)/textureHigh;
+ float bottom = top+itemHeight_/textureHigh;
+#endif
+
+
+ quad.tl.texCoords.u = left;
+ quad.tl.texCoords.v = top;
+ quad.tr.texCoords.u = right;
+ quad.tr.texCoords.v = top;
+ quad.bl.texCoords.u = left;
+ quad.bl.texCoords.v = bottom;
+ quad.br.texCoords.u = right;
+ quad.br.texCoords.v = bottom;
+
+ quad.bl.vertices.x = (int) (x * itemWidth_);
+ quad.bl.vertices.y = (int) (y * itemHeight_);
+ quad.bl.vertices.z = 0.0f;
+ quad.br.vertices.x = (int)(x * itemWidth_ + itemWidth_);
+ quad.br.vertices.y = (int)(y * itemHeight_);
+ quad.br.vertices.z = 0.0f;
+ quad.tl.vertices.x = (int)(x * itemWidth_);
+ quad.tl.vertices.y = (int)(y * itemHeight_ + itemHeight_);
+ quad.tl.vertices.z = 0.0f;
+ quad.tr.vertices.x = (int)(x * itemWidth_ + itemWidth_);
+ quad.tr.vertices.y = (int)(y * itemHeight_ + itemHeight_);
+ quad.tr.vertices.z = 0.0f;
+
+ [textureAtlas_ updateQuad:&quad atIndex:idx];
+}
+
+-(void) updateAtlasValues
+{
+ NSAssert( tgaInfo != nil, @"tgaInfo must be non-nil");
+
+
+ int total = 0;
+
+ for(int x = 0;x < tgaInfo->width; x++ ) {
+ for(int y = 0; y < tgaInfo->height; y++ ) {
+ if( total < itemsToRender ) {
+ ccColor3B *ptr = (ccColor3B*) tgaInfo->imageData;
+ ccColor3B value = ptr[x + y * tgaInfo->width];
+
+ if( value.r != 0 ) {
+ [self updateAtlasValueAt:ccg(x,y) withValue:value withIndex:total];
+
+ NSString *key = [NSString stringWithFormat:@"%d,%d", x,y];
+ NSNumber *num = [NSNumber numberWithInt:total];
+ [posToAtlasIndex setObject:num forKey:key];
+
+ total++;
+ }
+ }
+ }
+ }
+}
+@end
--- /dev/null
+/*
+ * 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 "CCScene.h"
+@class CCActionInterval;
+@class CCNode;
+
+/** CCTransitionEaseScene can ease the actions of the scene protocol.
+ @since v0.8.2
+ */
+@protocol CCTransitionEaseScene <NSObject>
+/** returns the Ease action that will be performed on a linear action.
+ @since v0.8.2
+ */
+-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action;
+@end
+
+/** Orientation Type used by some transitions
+ */
+typedef enum {
+ /// An horizontal orientation where the Left is nearer
+ kOrientationLeftOver = 0,
+ /// An horizontal orientation where the Right is nearer
+ kOrientationRightOver = 1,
+ /// A vertical orientation where the Up is nearer
+ kOrientationUpOver = 0,
+ /// A vertical orientation where the Bottom is nearer
+ kOrientationDownOver = 1,
+} tOrientation;
+
+/** Base class for CCTransition scenes
+ */
+@interface CCTransitionScene : CCScene
+{
+ CCScene *inScene_;
+ CCScene *outScene_;
+ ccTime duration_;
+ BOOL inSceneOnTop_;
+ BOOL sendCleanupToScene_;
+}
+/** creates a base transition with duration and incoming scene */
++(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s;
+/** initializes a transition with duration and incoming scene */
+-(id) initWithDuration:(ccTime) t scene:(CCScene*)s;
+/** called after the transition finishes */
+-(void) finish;
+/** used by some transitions to hide the outter scene */
+-(void) hideOutShowIn;
+@end
+
+/** A CCTransition that supports orientation like.
+ * Possible orientation: LeftOver, RightOver, UpOver, DownOver
+ */
+@interface CCTransitionSceneOriented : CCTransitionScene
+{
+ tOrientation orientation;
+}
+/** creates a base transition with duration and incoming scene */
++(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s orientation:(tOrientation)o;
+/** initializes a transition with duration and incoming scene */
+-(id) initWithDuration:(ccTime) t scene:(CCScene*)s orientation:(tOrientation)o;
+@end
+
+
+/** CCTransitionRotoZoom:
+ Rotate and zoom out the outgoing scene, and then rotate and zoom in the incoming
+ */
+@interface CCTransitionRotoZoom : CCTransitionScene
+{}
+@end
+
+/** CCTransitionJumpZoom:
+ Zoom out and jump the outgoing scene, and then jump and zoom in the incoming
+*/
+@interface CCTransitionJumpZoom : CCTransitionScene
+{}
+@end
+
+/** CCTransitionMoveInL:
+ Move in from to the left the incoming scene.
+*/
+@interface CCTransitionMoveInL : CCTransitionScene <CCTransitionEaseScene>
+{}
+/** initializes the scenes */
+-(void) initScenes;
+/** returns the action that will be performed */
+-(CCActionInterval*) action;
+@end
+
+/** CCTransitionMoveInR:
+ Move in from to the right the incoming scene.
+ */
+@interface CCTransitionMoveInR : CCTransitionMoveInL
+{}
+@end
+
+/** CCTransitionMoveInT:
+ Move in from to the top the incoming scene.
+ */
+@interface CCTransitionMoveInT : CCTransitionMoveInL
+{}
+@end
+
+/** CCTransitionMoveInB:
+ Move in from to the bottom the incoming scene.
+ */
+@interface CCTransitionMoveInB : CCTransitionMoveInL
+{}
+@end
+
+/** CCTransitionSlideInL:
+ Slide in the incoming scene from the left border.
+ */
+@interface CCTransitionSlideInL : CCTransitionScene <CCTransitionEaseScene>
+{}
+/** initializes the scenes */
+-(void) initScenes;
+/** returns the action that will be performed by the incomming and outgoing scene */
+-(CCActionInterval*) action;
+@end
+
+/** CCTransitionSlideInR:
+ Slide in the incoming scene from the right border.
+ */
+@interface CCTransitionSlideInR : CCTransitionSlideInL
+{}
+@end
+
+/** CCTransitionSlideInB:
+ Slide in the incoming scene from the bottom border.
+ */
+@interface CCTransitionSlideInB : CCTransitionSlideInL
+{}
+@end
+
+/** CCTransitionSlideInT:
+ Slide in the incoming scene from the top border.
+ */
+@interface CCTransitionSlideInT : CCTransitionSlideInL
+{}
+@end
+
+/**
+ Shrink the outgoing scene while grow the incoming scene
+ */
+@interface CCTransitionShrinkGrow : CCTransitionScene <CCTransitionEaseScene>
+{}
+@end
+
+/** CCTransitionFlipX:
+ Flips the screen horizontally.
+ The front face is the outgoing scene and the back face is the incoming scene.
+ */
+@interface CCTransitionFlipX : CCTransitionSceneOriented
+{}
+@end
+
+/** CCTransitionFlipY:
+ Flips the screen vertically.
+ The front face is the outgoing scene and the back face is the incoming scene.
+ */
+@interface CCTransitionFlipY : CCTransitionSceneOriented
+{}
+@end
+
+/** CCTransitionFlipAngular:
+ Flips the screen half horizontally and half vertically.
+ The front face is the outgoing scene and the back face is the incoming scene.
+ */
+@interface CCTransitionFlipAngular : CCTransitionSceneOriented
+{}
+@end
+
+/** CCTransitionZoomFlipX:
+ Flips the screen horizontally doing a zoom out/in
+ The front face is the outgoing scene and the back face is the incoming scene.
+ */
+@interface CCTransitionZoomFlipX : CCTransitionSceneOriented
+{}
+@end
+
+/** CCTransitionZoomFlipY:
+ Flips the screen vertically doing a little zooming out/in
+ The front face is the outgoing scene and the back face is the incoming scene.
+ */
+@interface CCTransitionZoomFlipY : CCTransitionSceneOriented
+{}
+@end
+
+/** CCTransitionZoomFlipAngular:
+ Flips the screen half horizontally and half vertically doing a little zooming out/in.
+ The front face is the outgoing scene and the back face is the incoming scene.
+ */
+@interface CCTransitionZoomFlipAngular : CCTransitionSceneOriented
+{}
+@end
+
+/** CCTransitionFade:
+ Fade out the outgoing scene and then fade in the incoming scene.'''
+ */
+@interface CCTransitionFade : CCTransitionScene
+{
+ ccColor4B color;
+}
+/** creates the transition with a duration and with an RGB color
+ * Example: [FadeTransition transitionWithDuration:2 scene:s withColor:ccc3(255,0,0)]; // red color
+ */
++(id) transitionWithDuration:(ccTime)duration scene:(CCScene*)scene withColor:(ccColor3B)color;
+/** initializes the transition with a duration and with an RGB color */
+-(id) initWithDuration:(ccTime)duration scene:(CCScene*)scene withColor:(ccColor3B)color;
+@end
+
+
+/**
+ CCTransitionCrossFade:
+ Cross fades two scenes using the CCRenderTexture object.
+ */
+@class CCRenderTexture;
+@interface CCTransitionCrossFade : CCTransitionScene
+{}
+@end
+
+/** CCTransitionTurnOffTiles:
+ Turn off the tiles of the outgoing scene in random order
+ */
+@interface CCTransitionTurnOffTiles : CCTransitionScene <CCTransitionEaseScene>
+{}
+@end
+
+/** CCTransitionSplitCols:
+ The odd columns goes upwards while the even columns goes downwards.
+ */
+@interface CCTransitionSplitCols : CCTransitionScene <CCTransitionEaseScene>
+{}
+-(CCActionInterval*) action;
+@end
+
+/** CCTransitionSplitRows:
+ The odd rows goes to the left while the even rows goes to the right.
+ */
+@interface CCTransitionSplitRows : CCTransitionSplitCols
+{}
+@end
+
+/** CCTransitionFadeTR:
+ Fade the tiles of the outgoing scene from the left-bottom corner the to top-right corner.
+ */
+@interface CCTransitionFadeTR : CCTransitionScene <CCTransitionEaseScene>
+{}
+-(CCActionInterval*) actionWithSize:(ccGridSize) vector;
+@end
+
+/** CCTransitionFadeBL:
+ Fade the tiles of the outgoing scene from the top-right corner to the bottom-left corner.
+ */
+@interface CCTransitionFadeBL : CCTransitionFadeTR
+{}
+@end
+
+/** CCTransitionFadeUp:
+ * Fade the tiles of the outgoing scene from the bottom to the top.
+ */
+@interface CCTransitionFadeUp : CCTransitionFadeTR
+{}
+@end
+
+/** CCTransitionFadeDown:
+ * Fade the tiles of the outgoing scene from the top to the bottom.
+ */
+@interface CCTransitionFadeDown : CCTransitionFadeTR
+{}
+@end
--- /dev/null
+/*
+ * 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 "CCTransition.h"
+#import "CCNode.h"
+#import "CCDirector.h"
+#import "CCActionInterval.h"
+#import "CCActionInstant.h"
+#import "CCActionCamera.h"
+#import "CCLayer.h"
+#import "CCCamera.h"
+#import "CCActionTiledGrid.h"
+#import "CCActionEase.h"
+#import "CCRenderTexture.h"
+#import "Support/CGPointExtension.h"
+
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#import "Platforms/iOS/CCTouchDispatcher.h"
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+#import "Platforms/Mac/CCEventDispatcher.h"
+#endif
+
+enum {
+ kSceneFade = 0xFADEFADE,
+};
+
+@interface CCTransitionScene (Private)
+-(void) sceneOrder;
+- (void)setNewScene:(ccTime)dt;
+@end
+
+@implementation CCTransitionScene
++(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s
+{
+ return [[[self alloc] initWithDuration:t scene:s] autorelease];
+}
+
+-(id) initWithDuration:(ccTime) t scene:(CCScene*)s
+{
+ NSAssert( s != nil, @"Argument scene must be non-nil");
+
+ if( (self=[super init]) ) {
+
+ duration_ = t;
+
+ // retain
+ inScene_ = [s retain];
+ outScene_ = [[CCDirector sharedDirector] runningScene];
+ [outScene_ retain];
+
+ NSAssert( inScene_ != outScene_, @"Incoming scene must be different from the outgoing scene" );
+
+ // disable events while transitions
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+ [[CCTouchDispatcher sharedDispatcher] setDispatchEvents: NO];
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+ [[CCEventDispatcher sharedDispatcher] setDispatchEvents: NO];
+#endif
+
+ [self sceneOrder];
+ }
+ return self;
+}
+-(void) sceneOrder
+{
+ inSceneOnTop_ = YES;
+}
+
+-(void) draw
+{
+ if( inSceneOnTop_ ) {
+ [outScene_ visit];
+ [inScene_ visit];
+ } else {
+ [inScene_ visit];
+ [outScene_ visit];
+ }
+}
+
+-(void) finish
+{
+ /* clean up */
+ [inScene_ setVisible:YES];
+ [inScene_ setPosition:ccp(0,0)];
+ [inScene_ setScale:1.0f];
+ [inScene_ setRotation:0.0f];
+ [inScene_.camera restore];
+
+ [outScene_ setVisible:NO];
+ [outScene_ setPosition:ccp(0,0)];
+ [outScene_ setScale:1.0f];
+ [outScene_ setRotation:0.0f];
+ [outScene_.camera restore];
+
+ [self schedule:@selector(setNewScene:) interval:0];
+}
+
+-(void) setNewScene: (ccTime) dt
+{
+ [self unschedule:_cmd];
+
+ CCDirector *director = [CCDirector sharedDirector];
+
+ // Before replacing, save the "send cleanup to scene"
+ sendCleanupToScene_ = [director sendCleanupToScene];
+
+ [director replaceScene: inScene_];
+
+ // enable events while transitions
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+ [[CCTouchDispatcher sharedDispatcher] setDispatchEvents: YES];
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+ [[CCEventDispatcher sharedDispatcher] setDispatchEvents: YES];
+#endif
+
+ // issue #267
+ [outScene_ setVisible:YES];
+}
+
+-(void) hideOutShowIn
+{
+ [inScene_ setVisible:YES];
+ [outScene_ setVisible:NO];
+}
+
+// custom onEnter
+-(void) onEnter
+{
+ [super onEnter];
+ [inScene_ onEnter];
+ // outScene_ should not receive the onEnter callback
+}
+
+// custom onExit
+-(void) onExit
+{
+ [super onExit];
+ [outScene_ onExit];
+
+ // inScene_ should not receive the onExit callback
+ // only the onEnterTransitionDidFinish
+ [inScene_ onEnterTransitionDidFinish];
+}
+
+// custom cleanup
+-(void) cleanup
+{
+ [super cleanup];
+
+ if( sendCleanupToScene_ )
+ [outScene_ cleanup];
+}
+
+-(void) dealloc
+{
+ [inScene_ release];
+ [outScene_ release];
+ [super dealloc];
+}
+@end
+
+//
+// Oriented Transition
+//
+@implementation CCTransitionSceneOriented
++(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s orientation:(tOrientation)o
+{
+ return [[[self alloc] initWithDuration:t scene:s orientation:o] autorelease];
+}
+
+-(id) initWithDuration:(ccTime) t scene:(CCScene*)s orientation:(tOrientation)o
+{
+ if( (self=[super initWithDuration:t scene:s]) )
+ orientation = o;
+ return self;
+}
+@end
+
+
+//
+// RotoZoom
+//
+@implementation CCTransitionRotoZoom
+-(void) onEnter
+{
+ [super onEnter];
+
+ [inScene_ setScale:0.001f];
+ [outScene_ setScale:1.0f];
+
+ [inScene_ setAnchorPoint:ccp(0.5f, 0.5f)];
+ [outScene_ setAnchorPoint:ccp(0.5f, 0.5f)];
+
+ CCActionInterval *rotozoom = [CCSequence actions: [CCSpawn actions:
+ [CCScaleBy actionWithDuration:duration_/2 scale:0.001f],
+ [CCRotateBy actionWithDuration:duration_/2 angle:360 *2],
+ nil],
+ [CCDelayTime actionWithDuration:duration_/2],
+ nil];
+
+
+ [outScene_ runAction: rotozoom];
+ [inScene_ runAction: [CCSequence actions:
+ [rotozoom reverse],
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ nil]];
+}
+@end
+
+//
+// JumpZoom
+//
+@implementation CCTransitionJumpZoom
+-(void) onEnter
+{
+ [super onEnter];
+ CGSize s = [[CCDirector sharedDirector] winSize];
+
+ [inScene_ setScale:0.5f];
+ [inScene_ setPosition:ccp( s.width,0 )];
+
+ [inScene_ setAnchorPoint:ccp(0.5f, 0.5f)];
+ [outScene_ setAnchorPoint:ccp(0.5f, 0.5f)];
+
+ CCActionInterval *jump = [CCJumpBy actionWithDuration:duration_/4 position:ccp(-s.width,0) height:s.width/4 jumps:2];
+ CCActionInterval *scaleIn = [CCScaleTo actionWithDuration:duration_/4 scale:1.0f];
+ CCActionInterval *scaleOut = [CCScaleTo actionWithDuration:duration_/4 scale:0.5f];
+
+ CCActionInterval *jumpZoomOut = [CCSequence actions: scaleOut, jump, nil];
+ CCActionInterval *jumpZoomIn = [CCSequence actions: jump, scaleIn, nil];
+
+ CCActionInterval *delay = [CCDelayTime actionWithDuration:duration_/2];
+
+ [outScene_ runAction: jumpZoomOut];
+ [inScene_ runAction: [CCSequence actions: delay,
+ jumpZoomIn,
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ nil] ];
+}
+@end
+
+//
+// MoveInL
+//
+@implementation CCTransitionMoveInL
+-(void) onEnter
+{
+ [super onEnter];
+
+ [self initScenes];
+
+ CCActionInterval *a = [self action];
+
+ [inScene_ runAction: [CCSequence actions:
+ [self easeActionWithAction:a],
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ nil]
+ ];
+
+}
+-(CCActionInterval*) action
+{
+ return [CCMoveTo actionWithDuration:duration_ position:ccp(0,0)];
+}
+
+-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action
+{
+ return [CCEaseOut actionWithAction:action rate:2.0f];
+// return [EaseElasticOut actionWithAction:action period:0.4f];
+}
+
+-(void) initScenes
+{
+ CGSize s = [[CCDirector sharedDirector] winSize];
+ [inScene_ setPosition: ccp( -s.width,0) ];
+}
+@end
+
+//
+// MoveInR
+//
+@implementation CCTransitionMoveInR
+-(void) initScenes
+{
+ CGSize s = [[CCDirector sharedDirector] winSize];
+ [inScene_ setPosition: ccp( s.width,0) ];
+}
+@end
+
+//
+// MoveInT
+//
+@implementation CCTransitionMoveInT
+-(void) initScenes
+{
+ CGSize s = [[CCDirector sharedDirector] winSize];
+ [inScene_ setPosition: ccp( 0, s.height) ];
+}
+@end
+
+//
+// MoveInB
+//
+@implementation CCTransitionMoveInB
+-(void) initScenes
+{
+ CGSize s = [[CCDirector sharedDirector] winSize];
+ [inScene_ setPosition: ccp( 0, -s.height) ];
+}
+@end
+
+//
+// SlideInL
+//
+
+// The adjust factor is needed to prevent issue #442
+// One solution is to use DONT_RENDER_IN_SUBPIXELS images, but NO
+// The other issue is that in some transitions (and I don't know why)
+// the order should be reversed (In in top of Out or vice-versa).
+#define ADJUST_FACTOR 0.5f
+@implementation CCTransitionSlideInL
+-(void) onEnter
+{
+ [super onEnter];
+
+ [self initScenes];
+
+ CCActionInterval *in = [self action];
+ CCActionInterval *out = [self action];
+
+ id inAction = [self easeActionWithAction:in];
+ id outAction = [CCSequence actions:
+ [self easeActionWithAction:out],
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ nil];
+
+ [inScene_ runAction: inAction];
+ [outScene_ runAction: outAction];
+}
+-(void) sceneOrder
+{
+ inSceneOnTop_ = NO;
+}
+-(void) initScenes
+{
+ CGSize s = [[CCDirector sharedDirector] winSize];
+ [inScene_ setPosition: ccp( -(s.width-ADJUST_FACTOR),0) ];
+}
+-(CCActionInterval*) action
+{
+ CGSize s = [[CCDirector sharedDirector] winSize];
+ return [CCMoveBy actionWithDuration:duration_ position:ccp(s.width-ADJUST_FACTOR,0)];
+}
+
+-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action
+{
+ return [CCEaseOut actionWithAction:action rate:2.0f];
+// return [EaseElasticOut actionWithAction:action period:0.4f];
+}
+
+@end
+
+//
+// SlideInR
+//
+@implementation CCTransitionSlideInR
+-(void) sceneOrder
+{
+ inSceneOnTop_ = YES;
+}
+-(void) initScenes
+{
+ CGSize s = [[CCDirector sharedDirector] winSize];
+ [inScene_ setPosition: ccp( s.width-ADJUST_FACTOR,0) ];
+}
+
+-(CCActionInterval*) action
+{
+ CGSize s = [[CCDirector sharedDirector] winSize];
+ return [CCMoveBy actionWithDuration:duration_ position:ccp(-(s.width-ADJUST_FACTOR),0)];
+}
+
+@end
+
+//
+// SlideInT
+//
+@implementation CCTransitionSlideInT
+-(void) sceneOrder
+{
+ inSceneOnTop_ = NO;
+}
+-(void) initScenes
+{
+ CGSize s = [[CCDirector sharedDirector] winSize];
+ [inScene_ setPosition: ccp(0,s.height-ADJUST_FACTOR) ];
+}
+
+-(CCActionInterval*) action
+{
+ CGSize s = [[CCDirector sharedDirector] winSize];
+ return [CCMoveBy actionWithDuration:duration_ position:ccp(0,-(s.height-ADJUST_FACTOR))];
+}
+
+@end
+
+//
+// SlideInB
+//
+@implementation CCTransitionSlideInB
+-(void) sceneOrder
+{
+ inSceneOnTop_ = YES;
+}
+
+-(void) initScenes
+{
+ CGSize s = [[CCDirector sharedDirector] winSize];
+ [inScene_ setPosition: ccp(0,-(s.height-ADJUST_FACTOR)) ];
+}
+
+-(CCActionInterval*) action
+{
+ CGSize s = [[CCDirector sharedDirector] winSize];
+ return [CCMoveBy actionWithDuration:duration_ position:ccp(0,s.height-ADJUST_FACTOR)];
+}
+@end
+
+//
+// ShrinkGrow Transition
+//
+@implementation CCTransitionShrinkGrow
+-(void) onEnter
+{
+ [super onEnter];
+
+ [inScene_ setScale:0.001f];
+ [outScene_ setScale:1.0f];
+
+ [inScene_ setAnchorPoint:ccp(2/3.0f,0.5f)];
+ [outScene_ setAnchorPoint:ccp(1/3.0f,0.5f)];
+
+ CCActionInterval *scaleOut = [CCScaleTo actionWithDuration:duration_ scale:0.01f];
+ CCActionInterval *scaleIn = [CCScaleTo actionWithDuration:duration_ scale:1.0f];
+
+ [inScene_ runAction: [self easeActionWithAction:scaleIn]];
+ [outScene_ runAction: [CCSequence actions:
+ [self easeActionWithAction:scaleOut],
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ nil] ];
+}
+-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action
+{
+ return [CCEaseOut actionWithAction:action rate:2.0f];
+// return [EaseElasticOut actionWithAction:action period:0.3f];
+}
+@end
+
+//
+// FlipX Transition
+//
+@implementation CCTransitionFlipX
+-(void) onEnter
+{
+ [super onEnter];
+
+ CCActionInterval *inA, *outA;
+ [inScene_ setVisible: NO];
+
+ float inDeltaZ, inAngleZ;
+ float outDeltaZ, outAngleZ;
+
+ if( orientation == kOrientationRightOver ) {
+ inDeltaZ = 90;
+ inAngleZ = 270;
+ outDeltaZ = 90;
+ outAngleZ = 0;
+ } else {
+ inDeltaZ = -90;
+ inAngleZ = 90;
+ outDeltaZ = -90;
+ outAngleZ = 0;
+ }
+
+ inA = [CCSequence actions:
+ [CCDelayTime actionWithDuration:duration_/2],
+ [CCShow action],
+ [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:0 deltaAngleX:0],
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ nil ];
+ outA = [CCSequence actions:
+ [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:0 deltaAngleX:0],
+ [CCHide action],
+ [CCDelayTime actionWithDuration:duration_/2],
+ nil ];
+
+ [inScene_ runAction: inA];
+ [outScene_ runAction: outA];
+
+}
+@end
+
+//
+// FlipY Transition
+//
+@implementation CCTransitionFlipY
+-(void) onEnter
+{
+ [super onEnter];
+
+ CCActionInterval *inA, *outA;
+ [inScene_ setVisible: NO];
+
+ float inDeltaZ, inAngleZ;
+ float outDeltaZ, outAngleZ;
+
+ if( orientation == kOrientationUpOver ) {
+ inDeltaZ = 90;
+ inAngleZ = 270;
+ outDeltaZ = 90;
+ outAngleZ = 0;
+ } else {
+ inDeltaZ = -90;
+ inAngleZ = 90;
+ outDeltaZ = -90;
+ outAngleZ = 0;
+ }
+ inA = [CCSequence actions:
+ [CCDelayTime actionWithDuration:duration_/2],
+ [CCShow action],
+ [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:90 deltaAngleX:0],
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ nil ];
+ outA = [CCSequence actions:
+ [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:90 deltaAngleX:0],
+ [CCHide action],
+ [CCDelayTime actionWithDuration:duration_/2],
+ nil ];
+
+ [inScene_ runAction: inA];
+ [outScene_ runAction: outA];
+
+}
+@end
+
+//
+// FlipAngular Transition
+//
+@implementation CCTransitionFlipAngular
+-(void) onEnter
+{
+ [super onEnter];
+
+ CCActionInterval *inA, *outA;
+ [inScene_ setVisible: NO];
+
+ float inDeltaZ, inAngleZ;
+ float outDeltaZ, outAngleZ;
+
+ if( orientation == kOrientationRightOver ) {
+ inDeltaZ = 90;
+ inAngleZ = 270;
+ outDeltaZ = 90;
+ outAngleZ = 0;
+ } else {
+ inDeltaZ = -90;
+ inAngleZ = 90;
+ outDeltaZ = -90;
+ outAngleZ = 0;
+ }
+ inA = [CCSequence actions:
+ [CCDelayTime actionWithDuration:duration_/2],
+ [CCShow action],
+ [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:-45 deltaAngleX:0],
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ nil ];
+ outA = [CCSequence actions:
+ [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:45 deltaAngleX:0],
+ [CCHide action],
+ [CCDelayTime actionWithDuration:duration_/2],
+ nil ];
+
+ [inScene_ runAction: inA];
+ [outScene_ runAction: outA];
+}
+@end
+
+//
+// ZoomFlipX Transition
+//
+@implementation CCTransitionZoomFlipX
+-(void) onEnter
+{
+ [super onEnter];
+
+ CCActionInterval *inA, *outA;
+ [inScene_ setVisible: NO];
+
+ float inDeltaZ, inAngleZ;
+ float outDeltaZ, outAngleZ;
+
+ if( orientation == kOrientationRightOver ) {
+ inDeltaZ = 90;
+ inAngleZ = 270;
+ outDeltaZ = 90;
+ outAngleZ = 0;
+ } else {
+ inDeltaZ = -90;
+ inAngleZ = 90;
+ outDeltaZ = -90;
+ outAngleZ = 0;
+ }
+ inA = [CCSequence actions:
+ [CCDelayTime actionWithDuration:duration_/2],
+ [CCSpawn actions:
+ [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:0 deltaAngleX:0],
+ [CCScaleTo actionWithDuration:duration_/2 scale:1],
+ [CCShow action],
+ nil],
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ nil ];
+ outA = [CCSequence actions:
+ [CCSpawn actions:
+ [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:0 deltaAngleX:0],
+ [CCScaleTo actionWithDuration:duration_/2 scale:0.5f],
+ nil],
+ [CCHide action],
+ [CCDelayTime actionWithDuration:duration_/2],
+ nil ];
+
+ inScene_.scale = 0.5f;
+ [inScene_ runAction: inA];
+ [outScene_ runAction: outA];
+}
+@end
+
+//
+// ZoomFlipY Transition
+//
+@implementation CCTransitionZoomFlipY
+-(void) onEnter
+{
+ [super onEnter];
+
+ CCActionInterval *inA, *outA;
+ [inScene_ setVisible: NO];
+
+ float inDeltaZ, inAngleZ;
+ float outDeltaZ, outAngleZ;
+
+ if( orientation == kOrientationUpOver ) {
+ inDeltaZ = 90;
+ inAngleZ = 270;
+ outDeltaZ = 90;
+ outAngleZ = 0;
+ } else {
+ inDeltaZ = -90;
+ inAngleZ = 90;
+ outDeltaZ = -90;
+ outAngleZ = 0;
+ }
+
+ inA = [CCSequence actions:
+ [CCDelayTime actionWithDuration:duration_/2],
+ [CCSpawn actions:
+ [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:90 deltaAngleX:0],
+ [CCScaleTo actionWithDuration:duration_/2 scale:1],
+ [CCShow action],
+ nil],
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ nil ];
+ outA = [CCSequence actions:
+ [CCSpawn actions:
+ [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:90 deltaAngleX:0],
+ [CCScaleTo actionWithDuration:duration_/2 scale:0.5f],
+ nil],
+ [CCHide action],
+ [CCDelayTime actionWithDuration:duration_/2],
+ nil ];
+
+ inScene_.scale = 0.5f;
+ [inScene_ runAction: inA];
+ [outScene_ runAction: outA];
+}
+@end
+
+//
+// ZoomFlipAngular Transition
+//
+@implementation CCTransitionZoomFlipAngular
+-(void) onEnter
+{
+ [super onEnter];
+
+ CCActionInterval *inA, *outA;
+ [inScene_ setVisible: NO];
+
+ float inDeltaZ, inAngleZ;
+ float outDeltaZ, outAngleZ;
+
+ if( orientation == kOrientationRightOver ) {
+ inDeltaZ = 90;
+ inAngleZ = 270;
+ outDeltaZ = 90;
+ outAngleZ = 0;
+ } else {
+ inDeltaZ = -90;
+ inAngleZ = 90;
+ outDeltaZ = -90;
+ outAngleZ = 0;
+ }
+
+ inA = [CCSequence actions:
+ [CCDelayTime actionWithDuration:duration_/2],
+ [CCSpawn actions:
+ [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:-45 deltaAngleX:0],
+ [CCScaleTo actionWithDuration:duration_/2 scale:1],
+ [CCShow action],
+ nil],
+ [CCShow action],
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ nil ];
+ outA = [CCSequence actions:
+ [CCSpawn actions:
+ [CCOrbitCamera actionWithDuration: duration_/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:45 deltaAngleX:0],
+ [CCScaleTo actionWithDuration:duration_/2 scale:0.5f],
+ nil],
+ [CCHide action],
+ [CCDelayTime actionWithDuration:duration_/2],
+ nil ];
+
+ inScene_.scale = 0.5f;
+ [inScene_ runAction: inA];
+ [outScene_ runAction: outA];
+}
+@end
+
+
+//
+// Fade Transition
+//
+@implementation CCTransitionFade
++(id) transitionWithDuration:(ccTime)d scene:(CCScene*)s withColor:(ccColor3B)color
+{
+ return [[[self alloc] initWithDuration:d scene:s withColor:color] autorelease];
+}
+
+-(id) initWithDuration:(ccTime)d scene:(CCScene*)s withColor:(ccColor3B)aColor
+{
+ if( (self=[super initWithDuration:d scene:s]) ) {
+ color.r = aColor.r;
+ color.g = aColor.g;
+ color.b = aColor.b;
+ }
+
+ return self;
+}
+
+-(id) initWithDuration:(ccTime)d scene:(CCScene*)s
+{
+ return [self initWithDuration:d scene:s withColor:ccBLACK];
+}
+
+-(void) onEnter
+{
+ [super onEnter];
+
+ CCLayerColor *l = [CCLayerColor layerWithColor:color];
+ [inScene_ setVisible: NO];
+
+ [self addChild: l z:2 tag:kSceneFade];
+
+
+ CCNode *f = [self getChildByTag:kSceneFade];
+
+ CCActionInterval *a = [CCSequence actions:
+ [CCFadeIn actionWithDuration:duration_/2],
+ [CCCallFunc actionWithTarget:self selector:@selector(hideOutShowIn)],
+ [CCFadeOut actionWithDuration:duration_/2],
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ nil ];
+ [f runAction: a];
+}
+
+-(void) onExit
+{
+ [super onExit];
+ [self removeChildByTag:kSceneFade cleanup:NO];
+}
+@end
+
+
+//
+// Cross Fade Transition
+//
+@implementation CCTransitionCrossFade
+
+-(void) draw
+{
+ // override draw since both scenes (textures) are rendered in 1 scene
+}
+
+-(void) onEnter
+{
+ [super onEnter];
+
+ // create a transparent color layer
+ // in which we are going to add our rendertextures
+ ccColor4B color = {0,0,0,0};
+ CGSize size = [[CCDirector sharedDirector] winSize];
+ CCLayerColor * layer = [CCLayerColor layerWithColor:color];
+
+ // create the first render texture for inScene_
+ CCRenderTexture *inTexture = [CCRenderTexture renderTextureWithWidth:size.width height:size.height];
+ inTexture.sprite.anchorPoint= ccp(0.5f,0.5f);
+ inTexture.position = ccp(size.width/2, size.height/2);
+ inTexture.anchorPoint = ccp(0.5f,0.5f);
+
+ // render inScene_ to its texturebuffer
+ [inTexture begin];
+ [inScene_ visit];
+ [inTexture end];
+
+ // create the second render texture for outScene_
+ CCRenderTexture *outTexture = [CCRenderTexture renderTextureWithWidth:size.width height:size.height];
+ outTexture.sprite.anchorPoint= ccp(0.5f,0.5f);
+ outTexture.position = ccp(size.width/2, size.height/2);
+ outTexture.anchorPoint = ccp(0.5f,0.5f);
+
+ // render outScene_ to its texturebuffer
+ [outTexture begin];
+ [outScene_ visit];
+ [outTexture end];
+
+ // create blend functions
+
+ ccBlendFunc blend1 = {GL_ONE, GL_ONE}; // inScene_ will lay on background and will not be used with alpha
+ ccBlendFunc blend2 = {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA}; // we are going to blend outScene_ via alpha
+
+ // set blendfunctions
+ [inTexture.sprite setBlendFunc:blend1];
+ [outTexture.sprite setBlendFunc:blend2];
+
+ // add render textures to the layer
+ [layer addChild:inTexture];
+ [layer addChild:outTexture];
+
+ // initial opacity:
+ [inTexture.sprite setOpacity:255];
+ [outTexture.sprite setOpacity:255];
+
+ // create the blend action
+ CCActionInterval * layerAction = [CCSequence actions:
+ [CCFadeTo actionWithDuration:duration_ opacity:0],
+ [CCCallFunc actionWithTarget:self selector:@selector(hideOutShowIn)],
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ nil ];
+
+
+ // run the blend action
+ [outTexture.sprite runAction: layerAction];
+
+ // add the layer (which contains our two rendertextures) to the scene
+ [self addChild: layer z:2 tag:kSceneFade];
+}
+
+// clean up on exit
+-(void) onExit
+{
+ // remove our layer and release all containing objects
+ [self removeChildByTag:kSceneFade cleanup:NO];
+
+ [super onExit];
+}
+@end
+
+//
+// TurnOffTilesTransition
+//
+@implementation CCTransitionTurnOffTiles
+
+// override addScenes, and change the order
+-(void) sceneOrder
+{
+ inSceneOnTop_ = NO;
+}
+
+-(void) onEnter
+{
+ [super onEnter];
+ CGSize s = [[CCDirector sharedDirector] winSize];
+ float aspect = s.width / s.height;
+ int x = 12 * aspect;
+ int y = 12;
+
+ id toff = [CCTurnOffTiles actionWithSize: ccg(x,y) duration:duration_];
+ id action = [self easeActionWithAction:toff];
+ [outScene_ runAction: [CCSequence actions: action,
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ [CCStopGrid action],
+ nil]
+ ];
+
+}
+-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action
+{
+ return action;
+// return [EaseIn actionWithAction:action rate:2.0f];
+}
+@end
+
+#pragma mark Split Transitions
+
+//
+// SplitCols Transition
+//
+@implementation CCTransitionSplitCols
+
+-(void) onEnter
+{
+ [super onEnter];
+
+ inScene_.visible = NO;
+
+ id split = [self action];
+ id seq = [CCSequence actions:
+ split,
+ [CCCallFunc actionWithTarget:self selector:@selector(hideOutShowIn)],
+ [split reverse],
+ nil
+ ];
+ [self runAction: [CCSequence actions:
+ [self easeActionWithAction:seq],
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ [CCStopGrid action],
+ nil]
+ ];
+}
+
+-(CCActionInterval*) action
+{
+ return [CCSplitCols actionWithCols:3 duration:duration_/2.0f];
+}
+
+-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action
+{
+ return [CCEaseInOut actionWithAction:action rate:3.0f];
+}
+@end
+
+//
+// SplitRows Transition
+//
+@implementation CCTransitionSplitRows
+-(CCActionInterval*) action
+{
+ return [CCSplitRows actionWithRows:3 duration:duration_/2.0f];
+}
+@end
+
+
+#pragma mark Fade Grid Transitions
+
+//
+// FadeTR Transition
+//
+@implementation CCTransitionFadeTR
+-(void) sceneOrder
+{
+ inSceneOnTop_ = NO;
+}
+
+-(void) onEnter
+{
+ [super onEnter];
+
+ CGSize s = [[CCDirector sharedDirector] winSize];
+ float aspect = s.width / s.height;
+ int x = 12 * aspect;
+ int y = 12;
+
+ id action = [self actionWithSize:ccg(x,y)];
+
+ [outScene_ runAction: [CCSequence actions:
+ [self easeActionWithAction:action],
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ [CCStopGrid action],
+ nil]
+ ];
+}
+
+-(CCActionInterval*) actionWithSize: (ccGridSize) v
+{
+ return [CCFadeOutTRTiles actionWithSize:v duration:duration_];
+}
+
+-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action
+{
+ return action;
+// return [EaseIn actionWithAction:action rate:2.0f];
+}
+@end
+
+//
+// FadeBL Transition
+//
+@implementation CCTransitionFadeBL
+-(CCActionInterval*) actionWithSize: (ccGridSize) v
+{
+ return [CCFadeOutBLTiles actionWithSize:v duration:duration_];
+}
+@end
+
+//
+// FadeUp Transition
+//
+@implementation CCTransitionFadeUp
+-(CCActionInterval*) actionWithSize: (ccGridSize) v
+{
+ return [CCFadeOutUpTiles actionWithSize:v duration:duration_];
+}
+@end
+
+//
+// FadeDown Transition
+//
+@implementation CCTransitionFadeDown
+-(CCActionInterval*) actionWithSize: (ccGridSize) v
+{
+ return [CCFadeOutDownTiles actionWithSize:v duration:duration_];
+}
+@end
--- /dev/null
+/*
+ * 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 "CCTransition.h"
+
+/** CCTransitionPageTurn transition.
+ * A transition which peels back the bottom right hand corner of a scene
+ * to transition to the scene beneath it simulating a page turn
+ *
+ * This uses a 3DAction so it's strongly recommended that depth buffering
+ * is turned on in CCDirector using:
+ *
+ * [[CCDirector sharedDirector] setDepthBufferFormat:kCCDepthBuffer16];
+ *
+ * @since v0.8.2
+ */
+@interface CCTransitionPageTurn : CCTransitionScene
+{
+ BOOL back_;
+}
+/**
+ * creates a base transition with duration and incoming scene
+ * if back is TRUE then the effect is reversed to appear as if the incoming
+ * scene is being turned from left over the outgoing scene
+ */
++(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s backwards:(BOOL) back;
+
+/**
+ * creates a base transition with duration and incoming scene
+ * if back is TRUE then the effect is reversed to appear as if the incoming
+ * scene is being turned from left over the outgoing scene
+ */
+-(id) initWithDuration:(ccTime) t scene:(CCScene*)s backwards:(BOOL) back;
+
+-(CCActionInterval*) actionWithSize:(ccGridSize) vector;
+
+@end
--- /dev/null
+/*
+ * 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 "CCTransitionPageTurn.h"
+#import "CCActionPageTurn3D.h"
+#import "CCDirector.h"
+
+@implementation CCTransitionPageTurn
+
+/** creates a base transition with duration and incoming scene */
++(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s backwards:(BOOL) back
+{
+ return [[[self alloc] initWithDuration:t scene:s backwards:back] autorelease];
+}
+
+/** initializes a transition with duration and incoming scene */
+-(id) initWithDuration:(ccTime) t scene:(CCScene*)s backwards:(BOOL) back
+{
+ // XXX: needed before [super init]
+ back_ = back;
+
+ if( ( self = [super initWithDuration:t scene:s] ) )
+ {
+ // do something
+ }
+ return self;
+}
+
+-(void) sceneOrder
+{
+ inSceneOnTop_ = back_;
+}
+
+//
+-(void) onEnter
+{
+ [super onEnter];
+
+ CGSize s = [[CCDirector sharedDirector] winSize];
+ int x, y;
+ if( s.width > s.height)
+ {
+ x = 16;
+ y = 12;
+ }
+ else
+ {
+ x = 12;
+ y = 16;
+ }
+
+ id action = [self actionWithSize:ccg(x,y)];
+
+ if(! back_ )
+ {
+ [outScene_ runAction: [CCSequence actions:
+ action,
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ [CCStopGrid action],
+ nil]
+ ];
+ }
+ else
+ {
+ // to prevent initial flicker
+ inScene_.visible = NO;
+ [inScene_ runAction: [CCSequence actions:
+ [CCShow action],
+ action,
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ [CCStopGrid action],
+ nil]
+ ];
+ }
+
+}
+
+-(CCActionInterval*) actionWithSize: (ccGridSize) v
+{
+ if( back_ )
+ {
+ // Get hold of the PageTurn3DAction
+ return [CCReverseTime actionWithAction:
+ [CCPageTurn3D actionWithSize:v duration:duration_]];
+ }
+ else
+ {
+ // Get hold of the PageTurn3DAction
+ return [CCPageTurn3D actionWithSize:v duration:duration_];
+ }
+}
+
+@end
+
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * Copyright (c) 2009 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 "CCTransition.h"
+#import "CCProgressTimer.h"
+#import "CCActionProgressTimer.h"
+
+/** CCTransitionRadialCCW transition.
+ A counter colock-wise radial transition to the next scene
+ */
+@interface CCTransitionRadialCCW : CCTransitionScene
+@end
+
+/** CCTransitionRadialCW transition.
+ A counter colock-wise radial transition to the next scene
+*/
+@interface CCTransitionRadialCW : CCTransitionRadialCCW
+@end
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * Copyright (c) 2009 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 "CCDirector.h"
+#import "CCTransitionRadial.h"
+#import "CCRenderTexture.h"
+#import "CCLayer.h"
+#import "CCActionInstant.h"
+#import "Support/CGPointExtension.h"
+
+enum {
+ kSceneRadial = 0xc001,
+};
+
+#pragma mark -
+#pragma mark Transition Radial CCW
+
+@implementation CCTransitionRadialCCW
+-(void) sceneOrder
+{
+ inSceneOnTop_ = NO;
+}
+
+-(CCProgressTimerType) radialType
+{
+ return kCCProgressTimerTypeRadialCCW;
+}
+
+-(void) onEnter
+{
+ [super onEnter];
+ // create a transparent color layer
+ // in which we are going to add our rendertextures
+ CGSize size = [[CCDirector sharedDirector] winSize];
+
+ // create the second render texture for outScene
+ CCRenderTexture *outTexture = [CCRenderTexture renderTextureWithWidth:size.width height:size.height];
+ outTexture.sprite.anchorPoint= ccp(0.5f,0.5f);
+ outTexture.position = ccp(size.width/2, size.height/2);
+ outTexture.anchorPoint = ccp(0.5f,0.5f);
+
+ // render outScene to its texturebuffer
+ [outTexture clear:0 g:0 b:0 a:1];
+ [outTexture begin];
+ [outScene_ visit];
+ [outTexture end];
+
+ // Since we've passed the outScene to the texture we don't need it.
+ [self hideOutShowIn];
+
+ // We need the texture in RenderTexture.
+ CCProgressTimer *outNode = [CCProgressTimer progressWithTexture:outTexture.sprite.texture];
+ // but it's flipped upside down so we flip the sprite
+ outNode.sprite.flipY = YES;
+ // Return the radial type that we want to use
+ outNode.type = [self radialType];
+ outNode.percentage = 100.f;
+ outNode.position = ccp(size.width/2, size.height/2);
+ outNode.anchorPoint = ccp(0.5f,0.5f);
+
+ // create the blend action
+ CCActionInterval * layerAction = [CCSequence actions:
+ [CCProgressFromTo actionWithDuration:duration_ from:100.f to:0.f],
+ [CCCallFunc actionWithTarget:self selector:@selector(finish)],
+ nil ];
+ // run the blend action
+ [outNode runAction: layerAction];
+
+ // add the layer (which contains our two rendertextures) to the scene
+ [self addChild: outNode z:2 tag:kSceneRadial];
+}
+
+// clean up on exit
+-(void) onExit
+{
+ // remove our layer and release all containing objects
+ [self removeChildByTag:kSceneRadial cleanup:NO];
+ [super onExit];
+}
+@end
+
+#pragma mark -
+#pragma mark Transition Radial CW
+
+@implementation CCTransitionRadialCW
+-(CCProgressTimerType) radialType
+{
+ return kCCProgressTimerTypeRadialCW;
+}
+@end
+
--- /dev/null
+/*
+ * 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.
+ */
+
+//
+// Common layer for OpenGL stuff
+//
+
+#import <Availability.h>
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#import <OpenGLES/ES1/gl.h>
+#import <OpenGLES/ES1/glext.h>
+#import <OpenGLES/EAGL.h>
+#import "iOS/glu.h"
+#import "iOS/EAGLView.h"
+
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+#import <OpenGL/gl.h>
+#import <OpenGL/glu.h>
+#import <Cocoa/Cocoa.h> // needed for NSOpenGLView
+#import "Mac/MacGLView.h"
+#endif
+
+
+// iOS
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#define CC_GLVIEW EAGLView
+#define ccglOrtho glOrthof
+#define ccglClearDepth glClearDepthf
+#define ccglGenerateMipmap glGenerateMipmapOES
+#define ccglGenFramebuffers glGenFramebuffersOES
+#define ccglBindFramebuffer glBindFramebufferOES
+#define ccglFramebufferTexture2D glFramebufferTexture2DOES
+#define ccglDeleteFramebuffers glDeleteFramebuffersOES
+#define ccglCheckFramebufferStatus glCheckFramebufferStatusOES
+#define ccglTranslate glTranslatef
+
+#define CC_GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
+#define CC_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_OES
+#define CC_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_OES
+#define CC_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES
+
+// Mac
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+#define CC_GLVIEW MacGLView
+#define ccglOrtho glOrtho
+#define ccglClearDepth glClearDepth
+#define ccglGenerateMipmap glGenerateMipmap
+#define ccglGenFramebuffers glGenFramebuffers
+#define ccglBindFramebuffer glBindFramebuffer
+#define ccglFramebufferTexture2D glFramebufferTexture2D
+#define ccglDeleteFramebuffers glDeleteFramebuffers
+#define ccglCheckFramebufferStatus glCheckFramebufferStatus
+#define ccglTranslate glTranslated
+
+#define CC_GL_FRAMEBUFFER GL_FRAMEBUFFER
+#define CC_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING
+#define CC_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0
+#define CC_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE
+
+#endif
--- /dev/null
+/*
+ * 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.
+ */
+
+//
+// Common layer for NS (Next-Step) stuff
+//
+
+#import <Availability.h>
+
+#import <Foundation/Foundation.h> // for NSObject
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+#define CCRectFromString(__r__) CGRectFromString(__r__)
+#define CCPointFromString(__p__) CGPointFromString(__p__)
+#define CCSizeFromString(__s__) CGSizeFromString(__s__)
+#define CCNSSizeToCGSize
+#define CCNSRectToCGRect
+#define CCNSPointToCGPoint
+#define CCTextAlignment UITextAlignment
+#define CCTextAlignmentCenter UITextAlignmentCenter
+#define CCTextAlignmentLeft UITextAlignmentLeft
+#define CCTextAlignmentRight UITextAlignmentRight
+
+
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+
+#define CCRectFromString(__r__) NSRectToCGRect( NSRectFromString(__r__) )
+#define CCPointFromString(__p__) NSPointToCGPoint( NSPointFromString(__p__) )
+#define CCSizeFromString(__s__) NSSizeToCGSize( NSSizeFromString(__s__) )
+#define CCNSSizeToCGSize NSSizeToCGSize
+#define CCNSRectToCGRect NSRectToCGRect
+#define CCNSPointToCGPoint NSPointToCGPoint
+#define CCTextAlignment NSTextAlignment
+#define CCTextAlignmentCenter NSCenterTextAlignment
+#define CCTextAlignmentLeft NSLeftTextAlignment
+#define CCTextAlignmentRight NSRightTextAlignment
+
+#endif
+
+
--- /dev/null
+/*
+ * 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.
+ */
+
+
+// Only compile this code on Mac. These files should not be included on your iOS project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+
+#import <QuartzCore/CVDisplayLink.h>
+#import "../../CCDirector.h"
+
+enum {
+ /// If the window is resized, it won't be autoscaled
+ kCCDirectorResize_NoScale,
+ /// If the window is resized, it will be autoscaled (default behavior)
+ kCCDirectorResize_AutoScale,
+};
+
+@interface CCDirector (MacExtension)
+/** converts an NSEvent to GL coordinates */
+-(CGPoint) convertEventToGL:(NSEvent*)event;
+@end
+
+/** Base class of Mac directors
+ @since v0.99.5
+ */
+@interface CCDirectorMac : CCDirector
+{
+ BOOL isFullScreen_;
+ int resizeMode_;
+ CGPoint winOffset_;
+ CGSize originalWinSize_;
+
+ MacGLView *fullScreenGLView_;
+ NSWindow *fullScreenWindow_;
+
+ // cache
+ MacGLView *windowGLView_;
+}
+
+// whether or not the view is in fullscreen mode
+@property (nonatomic, readonly) BOOL isFullScreen;
+
+// resize mode: with or without scaling
+@property (nonatomic, readwrite) int resizeMode;
+
+/** Sets the view in fullscreen or window mode */
+- (void) setFullScreen:(BOOL)fullscreen;
+
+/** Converts window size coordiantes to logical coordinates.
+ Useful only if resizeMode is kCCDirectorResize_Scale.
+ If resizeMode is kCCDirectorResize_NoScale, then no conversion will be done.
+*/
+- (CGPoint) convertToLogicalCoordinates:(CGPoint)coordinates;
+@end
+
+
+/** DisplayLinkDirector is a Director that synchronizes timers with the refresh rate of the display.
+ *
+ * Features and Limitations:
+ * - Only available on 3.1+
+ * - Scheduled timers & drawing are synchronizes with the refresh rate of the display
+ * - Only supports animation intervals of 1/60 1/30 & 1/15
+ *
+ * It is the recommended Director if the SDK is 3.1 or newer
+ *
+ * @since v0.8.2
+ */
+@interface CCDirectorDisplayLink : CCDirectorMac
+{
+ CVDisplayLinkRef displayLink;
+}
+@end
+
+#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
+
--- /dev/null
+/*
+ * 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.
+ */
+
+// Only compile this code on Mac. These files should not be included on your iOS project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+
+#import <sys/time.h>
+
+#import "CCDirectorMac.h"
+#import "CCEventDispatcher.h"
+#import "MacGLView.h"
+
+#import "../../CCNode.h"
+#import "../../CCScheduler.h"
+#import "../../ccMacros.h"
+
+#pragma mark -
+#pragma mark Director Mac extensions
+
+
+@interface CCDirector ()
+-(void) setNextScene;
+-(void) showFPS;
+-(void) calculateDeltaTime;
+@end
+
+@implementation CCDirector (MacExtension)
+-(CGPoint) convertEventToGL:(NSEvent*)event
+{
+ NSPoint point = [openGLView_ convertPoint:[event locationInWindow] fromView:nil];
+ CGPoint p = NSPointToCGPoint(point);
+
+ return [(CCDirectorMac*)self convertToLogicalCoordinates:p];
+}
+
+@end
+
+#pragma mark -
+#pragma mark Director Mac
+
+@implementation CCDirectorMac
+
+@synthesize isFullScreen = isFullScreen_;
+
+-(id) init
+{
+ if( (self = [super init]) ) {
+ isFullScreen_ = NO;
+ resizeMode_ = kCCDirectorResize_AutoScale;
+
+ fullScreenGLView_ = nil;
+ fullScreenWindow_ = nil;
+ windowGLView_ = nil;
+ winOffset_ = CGPointZero;
+ }
+
+ return self;
+}
+
+- (void) dealloc
+{
+ [fullScreenGLView_ release];
+ [fullScreenWindow_ release];
+ [windowGLView_ release];
+ [super dealloc];
+}
+
+//
+// setFullScreen code taken from GLFullScreen example by Apple
+//
+- (void) setFullScreen:(BOOL)fullscreen
+{
+ // Mac OS X 10.6 and later offer a simplified mechanism to create full-screen contexts
+#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
+
+ if( isFullScreen_ != fullscreen ) {
+
+ isFullScreen_ = fullscreen;
+
+ if( fullscreen ) {
+
+ // create the fullscreen view/window
+ NSRect mainDisplayRect, viewRect;
+
+ // Create a screen-sized window on the display you want to take over
+ // Note, mainDisplayRect has a non-zero origin if the key window is on a secondary display
+ mainDisplayRect = [[NSScreen mainScreen] frame];
+ fullScreenWindow_ = [[NSWindow alloc] initWithContentRect:mainDisplayRect
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:YES];
+
+ // Set the window level to be above the menu bar
+ [fullScreenWindow_ setLevel:NSMainMenuWindowLevel+1];
+
+ // Perform any other window configuration you desire
+ [fullScreenWindow_ setOpaque:YES];
+ [fullScreenWindow_ setHidesOnDeactivate:YES];
+
+ // Create a view with a double-buffered OpenGL context and attach it to the window
+ // By specifying the non-fullscreen context as the shareContext, we automatically inherit the OpenGL objects (textures, etc) it has defined
+ viewRect = NSMakeRect(0.0, 0.0, mainDisplayRect.size.width, mainDisplayRect.size.height);
+
+ fullScreenGLView_ = [[MacGLView alloc] initWithFrame:viewRect shareContext:[openGLView_ openGLContext]];
+
+ [fullScreenWindow_ setContentView:fullScreenGLView_];
+
+ // Show the window
+ [fullScreenWindow_ makeKeyAndOrderFront:self];
+
+ [self setOpenGLView:fullScreenGLView_];
+
+ } else {
+
+ [fullScreenWindow_ release];
+ [fullScreenGLView_ release];
+ fullScreenWindow_ = nil;
+ fullScreenGLView_ = nil;
+
+ [[windowGLView_ openGLContext] makeCurrentContext];
+ [self setOpenGLView:windowGLView_];
+
+ }
+
+ [openGLView_ setNeedsDisplay:YES];
+ }
+#else
+#error Full screen is not supported for Mac OS 10.5 or older yet
+#error If you don't want FullScreen support, you can safely remove these 2 lines
+#endif
+}
+
+-(void) setOpenGLView:(MacGLView *)view
+{
+ [super setOpenGLView:view];
+
+ // cache the NSWindow and NSOpenGLView created from the NIB
+ if( ! isFullScreen_ && ! windowGLView_) {
+ windowGLView_ = [view retain];
+ originalWinSize_ = winSizeInPixels_;
+ }
+}
+
+-(int) resizeMode
+{
+ return resizeMode_;
+}
+
+-(void) setResizeMode:(int)mode
+{
+ if( mode != resizeMode_ ) {
+ resizeMode_ = mode;
+
+ [openGLView_ setNeedsDisplay: YES];
+
+ [self setProjection:projection_];
+
+ if( mode == kCCDirectorResize_AutoScale ) {
+ originalWinSize_ = winSizeInPixels_;
+ CCLOG(@"cocos2d: Warning. Switching back to AutoScale might break some stuff. Experimental stuff");
+ }
+ }
+}
+
+-(void) setProjection:(ccDirectorProjection)projection
+{
+ CGSize size = winSizeInPixels_;
+
+ CGPoint offset = CGPointZero;
+ float widthAspect = size.width;
+ float heightAspect = size.height;
+
+
+ if( resizeMode_ == kCCDirectorResize_AutoScale && ! CGSizeEqualToSize(originalWinSize_, CGSizeZero ) ) {
+
+ size = originalWinSize_;
+
+ float aspect = originalWinSize_.width / originalWinSize_.height;
+ widthAspect = winSizeInPixels_.width;
+ heightAspect = winSizeInPixels_.width / aspect;
+
+ if( heightAspect > winSizeInPixels_.height ) {
+ widthAspect = winSizeInPixels_.height * aspect;
+ heightAspect = winSizeInPixels_.height;
+ }
+
+ winOffset_.x = (winSizeInPixels_.width - widthAspect) / 2;
+ winOffset_.y = (winSizeInPixels_.height - heightAspect) / 2;
+
+ offset = winOffset_;
+
+ }
+
+ switch (projection) {
+ case kCCDirectorProjection2D:
+ glViewport(offset.x, offset.y, widthAspect, heightAspect);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ ccglOrtho(0, size.width, 0, size.height, -1024, 1024);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ break;
+
+ case kCCDirectorProjection3D:
+ glViewport(offset.x, offset.y, widthAspect, heightAspect);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(60, (GLfloat)widthAspect/heightAspect, 0.1f, 1500.0f);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ float eyeZ = size.height * [self getZEye] / winSizeInPixels_.height;
+
+ gluLookAt( size.width/2, size.height/2, eyeZ,
+ size.width/2, size.height/2, 0,
+ 0.0f, 1.0f, 0.0f);
+ break;
+
+ case kCCDirectorProjectionCustom:
+ if( projectionDelegate_ )
+ [projectionDelegate_ updateProjection];
+ break;
+
+ default:
+ CCLOG(@"cocos2d: Director: unrecognized projecgtion");
+ break;
+ }
+
+ projection_ = projection;
+}
+
+// If scaling is supported, then it should always return the original size
+// otherwise it should return the "real" size.
+-(CGSize) winSize
+{
+ if( resizeMode_ == kCCDirectorResize_AutoScale )
+ return originalWinSize_;
+ return winSizeInPixels_;
+}
+
+-(CGSize) winSizeInPixels
+{
+ return [self winSize];
+}
+
+- (CGPoint) convertToLogicalCoordinates:(CGPoint)coords
+{
+ CGPoint ret;
+
+ if( resizeMode_ == kCCDirectorResize_NoScale )
+ ret = coords;
+
+ else {
+
+ float x_diff = originalWinSize_.width / (winSizeInPixels_.width - winOffset_.x * 2);
+ float y_diff = originalWinSize_.height / (winSizeInPixels_.height - winOffset_.y * 2);
+
+ float adjust_x = (winSizeInPixels_.width * x_diff - originalWinSize_.width ) / 2;
+ float adjust_y = (winSizeInPixels_.height * y_diff - originalWinSize_.height ) / 2;
+
+ ret = CGPointMake( (x_diff * coords.x) - adjust_x, ( y_diff * coords.y ) - adjust_y );
+ }
+
+ return ret;
+}
+@end
+
+
+#pragma mark -
+#pragma mark DirectorDisplayLink
+
+
+@implementation CCDirectorDisplayLink
+
+- (CVReturn) getFrameForTime:(const CVTimeStamp*)outputTime
+{
+#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
+ if( ! runningThread_ )
+ runningThread_ = [NSThread currentThread];
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ [self drawScene];
+ [[CCEventDispatcher sharedDispatcher] dispatchQueuedEvents];
+
+ [[NSRunLoop currentRunLoop] run];
+
+ [pool release];
+
+#else
+ [self performSelector:@selector(drawScene) onThread:runningThread_ withObject:nil waitUntilDone:YES];
+#endif
+
+ return kCVReturnSuccess;
+}
+
+// This is the renderer output callback function
+static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
+{
+ CVReturn result = [(CCDirectorDisplayLink*)displayLinkContext getFrameForTime:outputTime];
+ return result;
+}
+
+- (void) startAnimation
+{
+#if ! CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
+ runningThread_ = [[NSThread alloc] initWithTarget:self selector:@selector(mainLoop) object:nil];
+ [runningThread_ start];
+#endif
+
+ gettimeofday( &lastUpdate_, NULL);
+
+ // Create a display link capable of being used with all active displays
+ CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
+
+ // Set the renderer output callback function
+ CVDisplayLinkSetOutputCallback(displayLink, &MyDisplayLinkCallback, self);
+
+ // Set the display link for the current renderer
+ CGLContextObj cglContext = [[openGLView_ openGLContext] CGLContextObj];
+ CGLPixelFormatObj cglPixelFormat = [[openGLView_ pixelFormat] CGLPixelFormatObj];
+ CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat);
+
+ // Activate the display link
+ CVDisplayLinkStart(displayLink);
+}
+
+- (void) stopAnimation
+{
+ if( displayLink ) {
+ CVDisplayLinkStop(displayLink);
+ CVDisplayLinkRelease(displayLink);
+ displayLink = NULL;
+
+#if ! CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
+ [runningThread_ cancel];
+ [runningThread_ release];
+ runningThread_ = nil;
+#endif
+ }
+}
+
+-(void) dealloc
+{
+ if( displayLink ) {
+ CVDisplayLinkStop(displayLink);
+ CVDisplayLinkRelease(displayLink);
+ }
+ [super dealloc];
+}
+
+//
+// Mac Director has its own thread
+//
+-(void) mainLoop
+{
+ while( ![[NSThread currentThread] isCancelled] ) {
+ // There is no autorelease pool when this method is called because it will be called from a background thread
+ // It's important to create one or you will leak objects
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ [[NSRunLoop currentRunLoop] run];
+
+ [pool release];
+ }
+}
+
+//
+// Draw the Scene
+//
+- (void) drawScene
+{
+ // We draw on a secondary thread through the display link
+ // When resizing the view, -reshape is called automatically on the main thread
+ // Add a mutex around to avoid the threads accessing the context simultaneously when resizing
+ CGLLockContext([[openGLView_ openGLContext] CGLContextObj]);
+ [[openGLView_ openGLContext] makeCurrentContext];
+
+ /* calculate "global" dt */
+ [self calculateDeltaTime];
+
+ /* tick before glClear: issue #533 */
+ if( ! isPaused_ ) {
+ [[CCScheduler sharedScheduler] tick: dt];
+ }
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ /* to avoid flickr, nextScene MUST be here: after tick and before draw.
+ XXX: Which bug is this one. It seems that it can't be reproduced with v0.9 */
+ if( nextScene_ )
+ [self setNextScene];
+
+ glPushMatrix();
+
+
+ // By default enable VertexArray, ColorArray, TextureCoordArray and Texture2D
+ CC_ENABLE_DEFAULT_GL_STATES();
+
+ /* draw the scene */
+ [runningScene_ visit];
+
+ /* draw the notification node */
+ [notificationNode_ visit];
+
+ if( displayFPS_ )
+ [self showFPS];
+
+#if CC_ENABLE_PROFILERS
+ [self showProfilers];
+#endif
+
+ CC_DISABLE_DEFAULT_GL_STATES();
+
+ glPopMatrix();
+
+ [[openGLView_ openGLContext] flushBuffer];
+ CGLUnlockContext([[openGLView_ openGLContext] CGLContextObj]);
+}
+
+// set the event dispatcher
+-(void) setOpenGLView:(MacGLView *)view
+{
+ if( view != openGLView_ ) {
+
+ [super setOpenGLView:view];
+
+ CCEventDispatcher *eventDispatcher = [CCEventDispatcher sharedDispatcher];
+ [openGLView_ setEventDelegate: eventDispatcher];
+ [eventDispatcher setDispatchEvents: YES];
+
+ // Enable Touches. Default no.
+ [view setAcceptsTouchEvents:NO];
+// [view setAcceptsTouchEvents:YES];
+
+
+ // Synchronize buffer swaps with vertical refresh rate
+ [[view openGLContext] makeCurrentContext];
+ GLint swapInt = 1;
+ [[view openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
+ }
+}
+
+@end
+
+#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
--- /dev/null
+/*
+ * 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.
+ */
+
+// Only compile this code on Mac. These files should not be included on your iOS project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+
+#import <Cocoa/Cocoa.h>
+
+#import "MacGLView.h"
+#import "../../Support/uthash.h" // hack: uthash needs to be imported before utlist to prevent warning
+#import "../../Support/utlist.h"
+#import "../../ccConfig.h"
+
+#pragma mark -
+#pragma mark CCMouseEventDelegate
+
+/** CCMouseEventDelegate protocol.
+ Implement it in your node to receive any of mouse events
+ */
+@protocol CCMouseEventDelegate <NSObject>
+@optional
+
+//
+// left
+//
+/** called when the "mouseDown" event is received.
+ Return YES to avoid propagating the event to other delegates.
+ */
+-(BOOL) ccMouseDown:(NSEvent*)event;
+
+/** called when the "mouseDragged" event is received.
+ Return YES to avoid propagating the event to other delegates.
+ */
+-(BOOL) ccMouseDragged:(NSEvent*)event;
+
+/** called when the "mouseMoved" event is received.
+ Return YES to avoid propagating the event to other delegates.
+ By default, "mouseMoved" is disabled. To enable it, send the "setAcceptsMouseMovedEvents:YES" message to the main window.
+ */
+-(BOOL) ccMouseMoved:(NSEvent*)event;
+
+/** called when the "mouseUp" event is received.
+ Return YES to avoid propagating the event to other delegates.
+ */
+-(BOOL) ccMouseUp:(NSEvent*)event;
+
+
+//
+// right
+//
+
+/** called when the "rightMouseDown" event is received.
+ Return YES to avoid propagating the event to other delegates.
+ */
+-(BOOL) ccRightMouseDown:(NSEvent*)event;
+
+/** called when the "rightMouseDragged" event is received.
+ Return YES to avoid propagating the event to other delegates.
+ */
+-(BOOL) ccRightMouseDragged:(NSEvent*)event;
+
+/** called when the "rightMouseUp" event is received.
+ Return YES to avoid propagating the event to other delegates.
+ */
+-(BOOL) ccRightMouseUp:(NSEvent*)event;
+
+//
+// other
+//
+
+/** called when the "otherMouseDown" event is received.
+ Return YES to avoid propagating the event to other delegates.
+ */
+-(BOOL) ccOtherMouseDown:(NSEvent*)event;
+
+/** called when the "otherMouseDragged" event is received.
+ Return YES to avoid propagating the event to other delegates.
+ */
+-(BOOL) ccOtherMouseDragged:(NSEvent*)event;
+
+/** called when the "otherMouseUp" event is received.
+ Return YES to avoid propagating the event to other delegates.
+ */
+-(BOOL) ccOtherMouseUp:(NSEvent*)event;
+
+//
+// scroll wheel
+//
+
+/** called when the "scrollWheel" event is received.
+ Return YES to avoid propagating the event to other delegates.
+ */
+- (BOOL)ccScrollWheel:(NSEvent *)theEvent;
+
+
+//
+// enter / exit
+//
+
+/** called when the "mouseEntered" event is received.
+ Return YES to avoid propagating the event to other delegates.
+ */
+- (void)ccMouseEntered:(NSEvent *)theEvent;
+
+/** called when the "mouseExited" event is received.
+ Return YES to avoid propagating the event to other delegates.
+ */
+- (void)ccMouseExited:(NSEvent *)theEvent;
+
+@end
+
+#pragma mark -
+#pragma mark CCKeyboardEventDelegate
+
+/** CCKeyboardEventDelegate protocol.
+ Implement it in your node to receive any of keyboard events
+ */
+@protocol CCKeyboardEventDelegate <NSObject>
+@optional
+/** called when the "keyUp" event is received.
+ Return YES to avoid propagating the event to other delegates.
+ */
+-(BOOL) ccKeyUp:(NSEvent*)event;
+
+/** called when the "keyDown" event is received.
+ Return YES to avoid propagating the event to other delegates.
+ */
+-(BOOL) ccKeyDown:(NSEvent*)event;
+/** called when the "flagsChanged" event is received.
+ Return YES to avoid propagating the event to other delegates.
+ */
+-(BOOL) ccFlagsChanged:(NSEvent*)event;
+@end
+
+
+#pragma mark -
+#pragma mark CCEventDispatcher
+
+struct _listEntry;
+
+/** CCEventDispatcher
+
+ This is object is responsible for dispatching the events:
+ - Mouse events
+ - Keyboard events
+ - Touch events
+
+ Only available on Mac
+ */
+@interface CCEventDispatcher : NSObject <MacEventDelegate> {
+
+ BOOL dispatchEvents_;
+
+ struct _listEntry *keyboardDelegates_;
+ struct _listEntry *mouseDelegates_;
+}
+
+@property (nonatomic, readwrite) BOOL dispatchEvents;
+
+
+/** CCEventDispatcher singleton */
++(CCEventDispatcher*) sharedDispatcher;
+
+#pragma mark CCEventDispatcher - Mouse
+
+/** Adds a mouse delegate to the dispatcher's list.
+ Delegates with a lower priority value will be called before higher priority values.
+ All the events will be propgated to all the delegates, unless the one delegate returns YES.
+
+ IMPORTANT: The delegate will be retained.
+ */
+-(void) addMouseDelegate:(id<CCMouseEventDelegate>) delegate priority:(NSInteger)priority;
+
+/** removes a mouse delegate */
+-(void) removeMouseDelegate:(id) delegate;
+
+/** Removes all mouse delegates, releasing all the delegates */
+-(void) removeAllMouseDelegates;
+
+#pragma mark CCEventDispatcher - Keyboard
+
+/** Adds a Keyboard delegate to the dispatcher's list.
+ Delegates with a lower priority value will be called before higher priority values.
+ All the events will be propgated to all the delegates, unless the one delegate returns YES.
+
+ IMPORTANT: The delegate will be retained.
+ */
+-(void) addKeyboardDelegate:(id<CCKeyboardEventDelegate>) delegate priority:(NSInteger)priority;
+
+/** removes a mouse delegate */
+-(void) removeKeyboardDelegate:(id) delegate;
+
+/** Removes all mouse delegates, releasing all the delegates */
+-(void) removeAllKeyboardDelegates;
+
+#pragma mark CCEventDispatcher - Touches
+
+// XXX
+
+#pragma mark CCEventDispatcher - Dispatch Events
+
+#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
+-(void) dispatchQueuedEvents;
+#endif
+
+@end
+
+
+#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
--- /dev/null
+/*
+ * 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.
+ */
+
+// Only compile this code on Mac. These files should not be included on your iOS project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+
+#import "CCEventDispatcher.h"
+#import "../../ccConfig.h"
+
+static CCEventDispatcher *sharedDispatcher = nil;
+
+enum {
+ // mouse
+ kCCImplementsMouseDown = 1 << 0,
+ kCCImplementsMouseMoved = 1 << 1,
+ kCCImplementsMouseDragged = 1 << 2,
+ kCCImplementsMouseUp = 1 << 3,
+ kCCImplementsRightMouseDown = 1 << 4,
+ kCCImplementsRightMouseDragged = 1 << 5,
+ kCCImplementsRightMouseUp = 1 << 6,
+ kCCImplementsOtherMouseDown = 1 << 7,
+ kCCImplementsOtherMouseDragged = 1 << 8,
+ kCCImplementsOtherMouseUp = 1 << 9,
+ kCCImplementsScrollWheel = 1 << 10,
+ kCCImplementsMouseEntered = 1 << 11,
+ kCCImplementsMouseExited = 1 << 12,
+
+ // keyboard
+ kCCImplementsKeyUp = 1 << 0,
+ kCCImplementsKeyDown = 1 << 1,
+ kCCImplementsFlagsChanged = 1 << 2,
+};
+
+
+typedef struct _listEntry
+{
+ struct _listEntry *prev, *next;
+ id delegate;
+ NSInteger priority;
+ NSUInteger flags;
+} tListEntry;
+
+
+#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
+
+#define QUEUE_EVENT_MAX 128
+struct _eventQueue {
+ SEL selector;
+ NSEvent *event;
+};
+
+static struct _eventQueue eventQueue[QUEUE_EVENT_MAX];
+static int eventQueueCount;
+
+#endif // CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
+
+
+@implementation CCEventDispatcher
+
+@synthesize dispatchEvents=dispatchEvents_;
+
+
++(CCEventDispatcher*) sharedDispatcher
+{
+ @synchronized(self) {
+ if (sharedDispatcher == nil)
+ sharedDispatcher = [[self alloc] init]; // assignment not done here
+ }
+ return sharedDispatcher;
+}
+
++(id) allocWithZone:(NSZone *)zone
+{
+ @synchronized(self) {
+ NSAssert(sharedDispatcher == nil, @"Attempted to allocate a second instance of a singleton.");
+ return [super allocWithZone:zone];
+ }
+ return nil; // on subsequent allocation attempts return nil
+}
+
+-(id) init
+{
+ if( (self = [super init]) )
+ {
+ // events enabled by default
+ dispatchEvents_ = YES;
+
+ // delegates
+ keyboardDelegates_ = NULL;
+ mouseDelegates_ = NULL;
+
+#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
+ eventQueueCount = 0;
+#endif
+ }
+
+ return self;
+}
+
+- (void) dealloc
+{
+ [super dealloc];
+}
+
+#pragma mark CCEventDispatcher - add / remove delegates
+
+-(void) addDelegate:(id)delegate priority:(NSInteger)priority flags:(NSUInteger)flags list:(tListEntry**)list
+{
+ tListEntry *listElement = malloc( sizeof(*listElement) );
+
+ listElement->delegate = [delegate retain];
+ listElement->priority = priority;
+ listElement->flags = flags;
+ listElement->next = listElement->prev = NULL;
+
+ // empty list ?
+ if( ! *list ) {
+ DL_APPEND( *list, listElement );
+
+ } else {
+ BOOL added = NO;
+
+ for( tListEntry *elem = *list; elem ; elem = elem->next ) {
+ if( priority < elem->priority ) {
+
+ if( elem == *list )
+ DL_PREPEND(*list, listElement);
+ else {
+ listElement->next = elem;
+ listElement->prev = elem->prev;
+
+ elem->prev->next = listElement;
+ elem->prev = listElement;
+ }
+
+ added = YES;
+ break;
+ }
+ }
+
+ // Not added? priority has the higher value. Append it.
+ if( !added )
+ DL_APPEND(*list, listElement);
+ }
+}
+
+-(void) removeDelegate:(id)delegate fromList:(tListEntry**)list
+{
+ tListEntry *entry, *tmp;
+
+ // updates with priority < 0
+ DL_FOREACH_SAFE( *list, entry, tmp ) {
+ if( entry->delegate == delegate ) {
+ DL_DELETE( *list, entry );
+ [delegate release];
+ free(entry);
+ break;
+ }
+ }
+}
+
+-(void) removeAllDelegatesFromList:(tListEntry**)list
+{
+ tListEntry *entry, *tmp;
+
+ DL_FOREACH_SAFE( *list, entry, tmp ) {
+ DL_DELETE( *list, entry );
+ free(entry);
+ }
+}
+
+
+-(void) addMouseDelegate:(id<CCMouseEventDelegate>) delegate priority:(NSInteger)priority
+{
+ NSUInteger flags = 0;
+
+ flags |= ( [delegate respondsToSelector:@selector(ccMouseDown:)] ? kCCImplementsMouseDown : 0 );
+ flags |= ( [delegate respondsToSelector:@selector(ccMouseDragged:)] ? kCCImplementsMouseDragged : 0 );
+ flags |= ( [delegate respondsToSelector:@selector(ccMouseMoved:)] ? kCCImplementsMouseMoved : 0 );
+ flags |= ( [delegate respondsToSelector:@selector(ccMouseUp:)] ? kCCImplementsMouseUp : 0 );
+
+ flags |= ( [delegate respondsToSelector:@selector(ccRightMouseDown:)] ? kCCImplementsRightMouseDown : 0 );
+ flags |= ( [delegate respondsToSelector:@selector(ccRightMouseDragged:)] ? kCCImplementsRightMouseDragged : 0 );
+ flags |= ( [delegate respondsToSelector:@selector(ccRightMouseUp:)] ? kCCImplementsRightMouseUp : 0 );
+
+ flags |= ( [delegate respondsToSelector:@selector(ccOtherMouseDown:)] ? kCCImplementsOtherMouseDown : 0 );
+ flags |= ( [delegate respondsToSelector:@selector(ccOtherMouseDragged:)] ? kCCImplementsOtherMouseDragged : 0 );
+ flags |= ( [delegate respondsToSelector:@selector(ccOtherMouseUp:)] ? kCCImplementsOtherMouseUp : 0 );
+
+ flags |= ( [delegate respondsToSelector:@selector(ccMouseEntered:)] ? kCCImplementsMouseEntered : 0 );
+ flags |= ( [delegate respondsToSelector:@selector(ccMouseExited:)] ? kCCImplementsMouseExited : 0 );
+
+ flags |= ( [delegate respondsToSelector:@selector(ccScrollWheel:)] ? kCCImplementsScrollWheel : 0 );
+
+ [self addDelegate:delegate priority:priority flags:flags list:&mouseDelegates_];
+}
+
+-(void) removeMouseDelegate:(id) delegate
+{
+ [self removeDelegate:delegate fromList:&mouseDelegates_];
+}
+
+-(void) removeAllMouseDelegates
+{
+ [self removeAllDelegatesFromList:&mouseDelegates_];
+}
+
+-(void) addKeyboardDelegate:(id<CCKeyboardEventDelegate>) delegate priority:(NSInteger)priority
+{
+ NSUInteger flags = 0;
+
+ flags |= ( [delegate respondsToSelector:@selector(ccKeyUp:)] ? kCCImplementsKeyUp : 0 );
+ flags |= ( [delegate respondsToSelector:@selector(ccKeyDown:)] ? kCCImplementsKeyDown : 0 );
+ flags |= ( [delegate respondsToSelector:@selector(ccFlagsChanged:)] ? kCCImplementsFlagsChanged : 0 );
+
+ [self addDelegate:delegate priority:priority flags:flags list:&keyboardDelegates_];
+}
+
+-(void) removeKeyboardDelegate:(id) delegate
+{
+ [self removeDelegate:delegate fromList:&keyboardDelegates_];
+}
+
+-(void) removeAllKeyboardDelegates
+{
+ [self removeAllDelegatesFromList:&keyboardDelegates_];
+}
+
+#pragma mark CCEventDispatcher - Mouse events
+//
+// Mouse events
+//
+
+//
+// Left
+//
+- (void)mouseDown:(NSEvent *)event
+{
+ if( dispatchEvents_ ) {
+ tListEntry *entry, *tmp;
+
+ DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
+ if ( entry->flags & kCCImplementsMouseDown ) {
+ void *swallows = [entry->delegate performSelector:@selector(ccMouseDown:) withObject:event];
+ if( swallows )
+ break;
+ }
+ }
+ }
+}
+
+- (void)mouseMoved:(NSEvent *)event
+{
+ if( dispatchEvents_ ) {
+ tListEntry *entry, *tmp;
+
+ DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
+ if ( entry->flags & kCCImplementsMouseMoved ) {
+ void *swallows = [entry->delegate performSelector:@selector(ccMouseMoved:) withObject:event];
+ if( swallows )
+ break;
+ }
+ }
+ }
+}
+
+- (void)mouseDragged:(NSEvent *)event
+{
+ if( dispatchEvents_ ) {
+ tListEntry *entry, *tmp;
+
+ DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
+ if ( entry->flags & kCCImplementsMouseDragged ) {
+ void *swallows = [entry->delegate performSelector:@selector(ccMouseDragged:) withObject:event];
+ if( swallows )
+ break;
+ }
+ }
+ }
+}
+
+- (void)mouseUp:(NSEvent *)event
+{
+ if( dispatchEvents_ ) {
+ tListEntry *entry, *tmp;
+
+ DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
+ if ( entry->flags & kCCImplementsMouseUp ) {
+ void *swallows = [entry->delegate performSelector:@selector(ccMouseUp:) withObject:event];
+ if( swallows )
+ break;
+ }
+ }
+ }
+}
+
+//
+// Mouse Right
+//
+- (void)rightMouseDown:(NSEvent *)event
+{
+ if( dispatchEvents_ ) {
+ tListEntry *entry, *tmp;
+
+ DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
+ if ( entry->flags & kCCImplementsRightMouseDown ) {
+ void *swallows = [entry->delegate performSelector:@selector(ccRightMouseDown:) withObject:event];
+ if( swallows )
+ break;
+ }
+ }
+ }
+}
+
+- (void)rightMouseDragged:(NSEvent *)event
+{
+ if( dispatchEvents_ ) {
+ tListEntry *entry, *tmp;
+
+ DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
+ if ( entry->flags & kCCImplementsRightMouseDragged ) {
+ void *swallows = [entry->delegate performSelector:@selector(ccRightMouseDragged:) withObject:event];
+ if( swallows )
+ break;
+ }
+ }
+ }
+}
+
+- (void)rightMouseUp:(NSEvent *)event
+{
+ if( dispatchEvents_ ) {
+ tListEntry *entry, *tmp;
+
+ DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
+ if ( entry->flags & kCCImplementsRightMouseUp ) {
+ void *swallows = [entry->delegate performSelector:@selector(ccRightMouseUp:) withObject:event];
+ if( swallows )
+ break;
+ }
+ }
+ }
+}
+
+//
+// Mouse Other
+//
+- (void)otherMouseDown:(NSEvent *)event
+{
+ if( dispatchEvents_ ) {
+ tListEntry *entry, *tmp;
+
+ DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
+ if ( entry->flags & kCCImplementsOtherMouseDown ) {
+ void *swallows = [entry->delegate performSelector:@selector(ccOtherMouseDown:) withObject:event];
+ if( swallows )
+ break;
+ }
+ }
+ }
+}
+
+- (void)otherMouseDragged:(NSEvent *)event
+{
+ if( dispatchEvents_ ) {
+ tListEntry *entry, *tmp;
+
+ DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
+ if ( entry->flags & kCCImplementsOtherMouseDragged ) {
+ void *swallows = [entry->delegate performSelector:@selector(ccOtherMouseDragged:) withObject:event];
+ if( swallows )
+ break;
+ }
+ }
+ }
+}
+
+- (void)otherMouseUp:(NSEvent *)event
+{
+ if( dispatchEvents_ ) {
+ tListEntry *entry, *tmp;
+
+ DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
+ if ( entry->flags & kCCImplementsOtherMouseUp ) {
+ void *swallows = [entry->delegate performSelector:@selector(ccOtherMouseUp:) withObject:event];
+ if( swallows )
+ break;
+ }
+ }
+ }
+}
+
+//
+// Scroll Wheel
+//
+- (void)scrollWheel:(NSEvent *)event
+{
+ if( dispatchEvents_ ) {
+ tListEntry *entry, *tmp;
+
+ DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
+ if ( entry->flags & kCCImplementsScrollWheel ) {
+ void *swallows = [entry->delegate performSelector:@selector(ccScrollWheel:) withObject:event];
+ if( swallows )
+ break;
+ }
+ }
+ }
+}
+
+//
+// Mouse enter / exit
+- (void)mouseExited:(NSEvent *)event
+{
+ if( dispatchEvents_ ) {
+ tListEntry *entry, *tmp;
+
+ DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
+ if ( entry->flags & kCCImplementsMouseEntered ) {
+ void *swallows = [entry->delegate performSelector:@selector(ccMouseEntered:) withObject:event];
+ if( swallows )
+ break;
+ }
+ }
+ }
+}
+
+- (void)mouseEntered:(NSEvent *)event
+{
+ if( dispatchEvents_ ) {
+ tListEntry *entry, *tmp;
+
+ DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
+ if ( entry->flags & kCCImplementsMouseExited) {
+ void *swallows = [entry->delegate performSelector:@selector(ccMouseExited:) withObject:event];
+ if( swallows )
+ break;
+ }
+ }
+ }
+}
+
+
+#pragma mark CCEventDispatcher - Keyboard events
+
+// Keyboard events
+- (void)keyDown:(NSEvent *)event
+{
+ if( dispatchEvents_ ) {
+ tListEntry *entry, *tmp;
+
+ DL_FOREACH_SAFE( keyboardDelegates_, entry, tmp ) {
+ if ( entry->flags & kCCImplementsKeyDown ) {
+ void *swallows = [entry->delegate performSelector:@selector(ccKeyDown:) withObject:event];
+ if( swallows )
+ break;
+ }
+ }
+ }
+}
+
+- (void)keyUp:(NSEvent *)event
+{
+ if( dispatchEvents_ ) {
+ tListEntry *entry, *tmp;
+
+ DL_FOREACH_SAFE( keyboardDelegates_, entry, tmp ) {
+ if ( entry->flags & kCCImplementsKeyUp ) {
+ void *swallows = [entry->delegate performSelector:@selector(ccKeyUp:) withObject:event];
+ if( swallows )
+ break;
+ }
+ }
+ }
+}
+
+- (void)flagsChanged:(NSEvent *)event
+{
+ if( dispatchEvents_ ) {
+ tListEntry *entry, *tmp;
+
+ DL_FOREACH_SAFE( keyboardDelegates_, entry, tmp ) {
+ if ( entry->flags & kCCImplementsKeyUp ) {
+ void *swallows = [entry->delegate performSelector:@selector(ccFlagsChanged:) withObject:event];
+ if( swallows )
+ break;
+ }
+ }
+ }
+}
+
+
+#pragma mark CCEventDispatcher - Touch events
+
+- (void)touchesBeganWithEvent:(NSEvent *)event
+{
+ if (dispatchEvents_ ) {
+ NSLog(@"Touch Events: Not supported yet");
+ }
+}
+
+- (void)touchesMovedWithEvent:(NSEvent *)event
+{
+ if (dispatchEvents_ ) {
+ NSLog(@"Touch Events: Not supported yet");
+ }
+}
+
+- (void)touchesEndedWithEvent:(NSEvent *)event
+{
+ if (dispatchEvents_ ) {
+ NSLog(@"Touch Events: Not supported yet");
+ }
+}
+
+- (void)touchesCancelledWithEvent:(NSEvent *)event
+{
+ if (dispatchEvents_ ) {
+ NSLog(@"Touch Events: Not supported yet");
+ }
+}
+
+#pragma mark CCEventDispatcher - queue events
+
+#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
+-(void) queueEvent:(NSEvent*)event selector:(SEL)selector
+{
+ NSAssert( eventQueueCount < QUEUE_EVENT_MAX, @"CCEventDispatcher: recompile. Increment QUEUE_EVENT_MAX value");
+
+ eventQueue[eventQueueCount].selector = selector;
+ eventQueue[eventQueueCount].event = [event copy];
+
+ eventQueueCount++;
+}
+
+-(void) dispatchQueuedEvents
+{
+ for( int i=0; i < eventQueueCount; i++ ) {
+ SEL sel = eventQueue[i].selector;
+ NSEvent *event = eventQueue[i].event;
+
+ [self performSelector:sel withObject:event];
+
+ [event release];
+ }
+
+ eventQueueCount = 0;
+}
+#endif // CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
+
+
+@end
+
+#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
\ No newline at end of file
--- /dev/null
+/*
+ * 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.
+ */
+
+// Only compile this code on Mac. These files should not be included on your iOS project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+
+#import <Cocoa/Cocoa.h>
+
+#import "../../ccConfig.h"
+
+//PROTOCOLS:
+
+@protocol MacEventDelegate <NSObject>
+// Mouse
+- (void)mouseDown:(NSEvent *)theEvent;
+- (void)mouseUp:(NSEvent *)theEvent;
+- (void)mouseMoved:(NSEvent *)theEvent;
+- (void)mouseDragged:(NSEvent *)theEvent;
+- (void)rightMouseDown:(NSEvent*)event;
+- (void)rightMouseDragged:(NSEvent*)event;
+- (void)rightMouseUp:(NSEvent*)event;
+- (void)otherMouseDown:(NSEvent*)event;
+- (void)otherMouseDragged:(NSEvent*)event;
+- (void)otherMouseUp:(NSEvent*)event;
+- (void)scrollWheel:(NSEvent *)theEvent;
+- (void)mouseEntered:(NSEvent *)theEvent;
+- (void)mouseExited:(NSEvent *)theEvent;
+
+
+// Keyboard
+- (void)keyDown:(NSEvent *)theEvent;
+- (void)keyUp:(NSEvent *)theEvent;
+- (void)flagsChanged:(NSEvent *)theEvent;
+
+// Touches
+- (void)touchesBeganWithEvent:(NSEvent *)event;
+- (void)touchesMovedWithEvent:(NSEvent *)event;
+- (void)touchesEndedWithEvent:(NSEvent *)event;
+- (void)touchesCancelledWithEvent:(NSEvent *)event;
+
+#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
+- (void)queueEvent:(NSEvent*)event selector:(SEL)selector;
+#endif
+
+@end
+
+/** MacGLView
+
+ Only available for Mac OS X
+ */
+@interface MacGLView : NSOpenGLView {
+ id<MacEventDelegate> eventDelegate_;
+}
+
+@property (nonatomic, readwrite, assign) id<MacEventDelegate> eventDelegate;
+
+// initializes the MacGLView with a frame rect and an OpenGL context
+- (id) initWithFrame:(NSRect)frameRect shareContext:(NSOpenGLContext*)context;
+
+// private
++(void) load_;
+@end
+
+#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
\ No newline at end of file
--- /dev/null
+/*
+ * 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.
+ */
+
+/*
+ * Idea of subclassing NSOpenGLView was taken from "TextureUpload" Apple's sample
+ */
+
+// Only compile this code on Mac. These files should not be included on your iOS project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+
+#import "MacGLView.h"
+#import <OpenGL/gl.h>
+
+#import "CCDirectorMac.h"
+#import "../../ccConfig.h"
+
+
+@implementation MacGLView
+
+@synthesize eventDelegate = eventDelegate_;
+
++(void) load_
+{
+ NSLog(@"%@ loaded", self);
+}
+
+- (id) initWithFrame:(NSRect)frameRect
+{
+ self = [self initWithFrame:frameRect shareContext:nil];
+ return self;
+}
+
+- (id) initWithFrame:(NSRect)frameRect shareContext:(NSOpenGLContext*)context
+{
+ NSOpenGLPixelFormatAttribute attribs[] =
+ {
+ NSOpenGLPFAAccelerated,
+ NSOpenGLPFANoRecovery,
+ NSOpenGLPFADoubleBuffer,
+ NSOpenGLPFADepthSize, 24,
+
+ 0
+ };
+
+ NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
+
+ if (!pixelFormat)
+ NSLog(@"No OpenGL pixel format");
+
+ if (self = [super initWithFrame:frameRect pixelFormat:[pixelFormat autorelease]]) {
+
+ if( context )
+ [self setOpenGLContext:context];
+
+ // Synchronize buffer swaps with vertical refresh rate
+ GLint swapInt = 1;
+ [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
+
+// GLint order = -1;
+// [[self openGLContext] setValues:&order forParameter:NSOpenGLCPSurfaceOrder];
+
+ // event delegate
+ eventDelegate_ = nil;
+ }
+
+ return self;
+}
+
+- (void) reshape
+{
+ // We draw on a secondary thread through the display link
+ // When resizing the view, -reshape is called automatically on the main thread
+ // Add a mutex around to avoid the threads accessing the context simultaneously when resizing
+ CGLLockContext([[self openGLContext] CGLContextObj]);
+
+ NSRect rect = [self bounds];
+
+ CCDirector *director = [CCDirector sharedDirector];
+ [director reshapeProjection: NSSizeToCGSize(rect.size) ];
+
+ // avoid flicker
+ [director drawScene];
+// [self setNeedsDisplay:YES];
+
+ CGLUnlockContext([[self openGLContext] CGLContextObj]);
+}
+
+- (void) dealloc
+{
+
+ [super dealloc];
+}
+
+#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
+#define DISPATCH_EVENT(__event__, __selector__) [eventDelegate_ queueEvent:__event__ selector:__selector__];
+#else
+#define DISPATCH_EVENT(__event__, __selector__) \
+ id obj = eventDelegate_; \
+ [obj performSelector:__selector__ \
+ onThread:[(CCDirectorMac*)[CCDirector sharedDirector] runningThread] \
+ withObject:__event__ \
+ waitUntilDone:NO];
+#endif
+
+#pragma mark MacGLView - Mouse events
+- (void)mouseDown:(NSEvent *)theEvent
+{
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+- (void)mouseMoved:(NSEvent *)theEvent
+{
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+- (void)mouseDragged:(NSEvent *)theEvent
+{
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+- (void)mouseUp:(NSEvent *)theEvent
+{
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+- (void)rightMouseDown:(NSEvent *)theEvent {
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+- (void)rightMouseDragged:(NSEvent *)theEvent {
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+- (void)rightMouseUp:(NSEvent *)theEvent {
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+- (void)otherMouseDown:(NSEvent *)theEvent {
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+- (void)otherMouseDragged:(NSEvent *)theEvent {
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+- (void)otherMouseUp:(NSEvent *)theEvent {
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+- (void)mouseEntered:(NSEvent *)theEvent {
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+- (void)mouseExited:(NSEvent *)theEvent {
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+-(void) scrollWheel:(NSEvent *)theEvent {
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+#pragma mark MacGLView - Key events
+
+-(BOOL) becomeFirstResponder
+{
+ return YES;
+}
+
+-(BOOL) acceptsFirstResponder
+{
+ return YES;
+}
+
+-(BOOL) resignFirstResponder
+{
+ return YES;
+}
+
+- (void)keyDown:(NSEvent *)theEvent
+{
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+- (void)keyUp:(NSEvent *)theEvent
+{
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+- (void)flagsChanged:(NSEvent *)theEvent
+{
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+#pragma mark MacGLView - Touch events
+- (void)touchesBeganWithEvent:(NSEvent *)theEvent
+{
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+- (void)touchesMovedWithEvent:(NSEvent *)theEvent
+{
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+- (void)touchesEndedWithEvent:(NSEvent *)theEvent
+{
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+- (void)touchesCancelledWithEvent:(NSEvent *)theEvent
+{
+ DISPATCH_EVENT(theEvent, _cmd);
+}
+
+@end
+
+#endif // __MAC_OS_X_VERSION_MAX_ALLOWED
\ No newline at end of file
--- /dev/null
+/*
+ * 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.
+ */
+
+
+// Only compile this code on iOS. These files should NOT be included on your Mac project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+#import "../../CCDirector.h"
+
+/** @typedef ccDeviceOrientation
+ Possible device orientations
+ */
+typedef enum {
+ /// Device oriented vertically, home button on the bottom
+ kCCDeviceOrientationPortrait = UIDeviceOrientationPortrait,
+ /// Device oriented vertically, home button on the top
+ kCCDeviceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
+ /// Device oriented horizontally, home button on the right
+ kCCDeviceOrientationLandscapeLeft = UIDeviceOrientationLandscapeLeft,
+ /// Device oriented horizontally, home button on the left
+ kCCDeviceOrientationLandscapeRight = UIDeviceOrientationLandscapeRight,
+
+ // Backward compatibility stuff
+ CCDeviceOrientationPortrait = kCCDeviceOrientationPortrait,
+ CCDeviceOrientationPortraitUpsideDown = kCCDeviceOrientationPortraitUpsideDown,
+ CCDeviceOrientationLandscapeLeft = kCCDeviceOrientationLandscapeLeft,
+ CCDeviceOrientationLandscapeRight = kCCDeviceOrientationLandscapeRight,
+} ccDeviceOrientation;
+
+/** @typedef tPixelFormat
+ Possible Pixel Formats for the OpenGL View.
+
+ @deprecated Will be removed in v1.0
+ */
+typedef enum {
+ /** RGB565 pixel format. No alpha. 16-bit. (Default) */
+ kCCPixelFormatRGB565,
+ /** RGBA format. 32-bit. Needed for some 3D effects. It is not as fast as the RGB565 format. */
+ kCCPixelFormatRGBA8888,
+ /** default pixel format */
+ kCCPixelFormatDefault = kCCPixelFormatRGB565,
+
+ // backward compatibility stuff
+ kPixelFormatRGB565 = kCCPixelFormatRGB565,
+ kRGB565 = kCCPixelFormatRGB565,
+ kPixelFormatRGBA8888 = kCCPixelFormatRGBA8888,
+ kRGBA8 = kCCPixelFormatRGBA8888,
+} tPixelFormat;
+
+/** @typedef tDepthBufferFormat
+ Possible DepthBuffer Formats for the OpenGLView.
+ Use 16 or 24 bit depth buffers if you are going to use real 3D objects.
+
+ @deprecated Will be removed in v1.0
+ */
+typedef enum {
+ /// A Depth Buffer of 0 bits will be used (default)
+ kCCDepthBufferNone,
+ /// A depth buffer of 16 bits will be used
+ kCCDepthBuffer16,
+ /// A depth buffer of 24 bits will be used
+ kCCDepthBuffer24,
+
+ // backward compatibility stuff
+ kDepthBuffer16 = kCCDepthBuffer16,
+ kDepthBuffer24 = kCCDepthBuffer24,
+} tDepthBufferFormat;
+
+/** @typedef ccDirectorType
+ Possible Director Types.
+ @since v0.8.2
+ */
+typedef enum {
+ /** Will use a Director that triggers the main loop from an NSTimer object
+ *
+ * Features and Limitations:
+ * - Integrates OK with UIKit objects
+ * - It the slowest director
+ * - The invertal update is customizable from 1 to 60
+ */
+ kCCDirectorTypeNSTimer,
+
+ /** will use a Director that triggers the main loop from a custom main loop.
+ *
+ * Features and Limitations:
+ * - Faster than NSTimer Director
+ * - It doesn't integrate well with UIKit objecgts
+ * - The interval update can't be customizable
+ */
+ kCCDirectorTypeMainLoop,
+
+ /** Will use a Director that triggers the main loop from a thread, but the main loop will be executed on the main thread.
+ *
+ * Features and Limitations:
+ * - Faster than NSTimer Director
+ * - It doesn't integrate well with UIKit objecgts
+ * - The interval update can't be customizable
+ */
+ kCCDirectorTypeThreadMainLoop,
+
+ /** Will use a Director that synchronizes timers with the refresh rate of the display.
+ *
+ * Features and Limitations:
+ * - Faster than NSTimer Director
+ * - Only available on 3.1+
+ * - Scheduled timers & drawing are synchronizes with the refresh rate of the display
+ * - Integrates OK with UIKit objects
+ * - The interval update can be 1/60, 1/30, 1/15
+ */
+ kCCDirectorTypeDisplayLink,
+
+ /** Default director is the NSTimer directory */
+ kCCDirectorTypeDefault = kCCDirectorTypeNSTimer,
+
+ // backward compatibility stuff
+ CCDirectorTypeNSTimer = kCCDirectorTypeNSTimer,
+ CCDirectorTypeMainLoop = kCCDirectorTypeMainLoop,
+ CCDirectorTypeThreadMainLoop = kCCDirectorTypeThreadMainLoop,
+ CCDirectorTypeDisplayLink = kCCDirectorTypeDisplayLink,
+ CCDirectorTypeDefault = kCCDirectorTypeDefault,
+
+
+} ccDirectorType;
+
+/** CCDirector extensions for iPhone
+ */
+@interface CCDirector (iOSExtension)
+
+// rotates the screen if an orientation differnent than Portrait is used
+-(void) applyOrientation;
+
+/** Sets the device orientation.
+ If the orientation is going to be controlled by an UIViewController, then the orientation should be Portrait
+ */
+-(void) setDeviceOrientation:(ccDeviceOrientation)orientation;
+
+/** returns the device orientation */
+-(ccDeviceOrientation) deviceOrientation;
+
+/** The size in pixels of the surface. It could be different than the screen size.
+ High-res devices might have a higher surface size than the screen size.
+ In non High-res device the contentScale will be emulated.
+
+ The recommend way to enable Retina Display is by using the "enableRetinaDisplay:(BOOL)enabled" method.
+
+ @since v0.99.4
+ */
+-(void) setContentScaleFactor:(CGFloat)scaleFactor;
+
+/** Will enable Retina Display on devices that supports it.
+ It will enable Retina Display on iPhone4 and iPod Touch 4.
+ It will return YES, if it could enabled it, otherwise it will return NO.
+
+ This is the recommened way to enable Retina Display.
+ @since v0.99.5
+ */
+-(BOOL) enableRetinaDisplay:(BOOL)yes;
+
+
+/** returns the content scale factor */
+-(CGFloat) contentScaleFactor;
+@end
+
+@interface CCDirector (iOSExtensionClassMethods)
+
+/** There are 4 types of Director.
+ - kCCDirectorTypeNSTimer (default)
+ - kCCDirectorTypeMainLoop
+ - kCCDirectorTypeThreadMainLoop
+ - kCCDirectorTypeDisplayLink
+
+ Each Director has it's own benefits, limitations.
+ If you are using SDK 3.1 or newer it is recommed to use the DisplayLink director
+
+ This method should be called before any other call to the director.
+
+ It will return NO if the director type is kCCDirectorTypeDisplayLink and the running SDK is < 3.1. Otherwise it will return YES.
+
+ @since v0.8.2
+ */
++(BOOL) setDirectorType:(ccDirectorType) directorType;
+@end
+
+#pragma mark -
+#pragma mark CCDirectorIOS
+
+/** CCDirectorIOS: Base class of iOS directors
+ @since v0.99.5
+ */
+@interface CCDirectorIOS : CCDirector
+{
+ /* orientation */
+ ccDeviceOrientation deviceOrientation_;
+
+ /* contentScaleFactor could be simulated */
+ BOOL isContentScaleSupported_;
+
+ tPixelFormat pixelFormat_; // Deprecated. Will be removed in 1.0
+ tDepthBufferFormat depthBufferFormat_; // Deprecated. Will be removed in 1.0
+}
+
+// iPhone Specific
+
+/** Pixel format used to create the context */
+@property (nonatomic,readonly) tPixelFormat pixelFormat DEPRECATED_ATTRIBUTE;
+
+/** Uses a new pixel format for the EAGLView.
+ Call this class method before attaching it to a UIView
+ Default pixel format: kRGB565. Supported pixel formats: kRGBA8 and kRGB565
+
+ @deprecated Set the pixel format when creating the EAGLView. This method will be removed in v1.0
+ */
+-(void) setPixelFormat: (tPixelFormat)p DEPRECATED_ATTRIBUTE;
+
+/** Change depth buffer format of the render buffer.
+ Call this class method before attaching it to a UIWindow/UIView
+ Default depth buffer: 0 (none). Supported: kCCDepthBufferNone, kCCDepthBuffer16, and kCCDepthBuffer24
+
+ @deprecated Set the depth buffer format when creating the EAGLView. This method will be removed in v1.0
+ */
+-(void) setDepthBufferFormat: (tDepthBufferFormat)db DEPRECATED_ATTRIBUTE;
+
+// Integration with UIKit
+/** detach the cocos2d view from the view/window */
+-(BOOL)detach DEPRECATED_ATTRIBUTE;
+
+/** attach in UIWindow using the full frame.
+ It will create a EAGLView.
+
+ @deprecated set setOpenGLView instead. Will be removed in v1.0
+ */
+-(BOOL)attachInWindow:(UIWindow *)window DEPRECATED_ATTRIBUTE;
+
+/** attach in UIView using the full frame.
+ It will create a EAGLView.
+
+ @deprecated set setOpenGLView instead. Will be removed in v1.0
+ */
+-(BOOL)attachInView:(UIView *)view DEPRECATED_ATTRIBUTE;
+
+/** attach in UIView using the given frame.
+ It will create a EAGLView and use it.
+
+ @deprecated set setOpenGLView instead. Will be removed in v1.0
+ */
+-(BOOL)attachInView:(UIView *)view withFrame:(CGRect)frame DEPRECATED_ATTRIBUTE;
+
+@end
+
+/** FastDirector is a Director that triggers the main loop as fast as possible.
+ *
+ * Features and Limitations:
+ * - Faster than "normal" director
+ * - Consumes more battery than the "normal" director
+ * - It has some issues while using UIKit objects
+ */
+@interface CCDirectorFast : CCDirectorIOS
+{
+ BOOL isRunning;
+
+ NSAutoreleasePool *autoreleasePool;
+}
+-(void) mainLoop;
+@end
+
+/** ThreadedFastDirector is a Director that triggers the main loop from a thread.
+ *
+ * Features and Limitations:
+ * - Faster than "normal" director
+ * - Consumes more battery than the "normal" director
+ * - It can be used with UIKit objects
+ *
+ * @since v0.8.2
+ */
+@interface CCDirectorFastThreaded : CCDirectorIOS
+{
+ BOOL isRunning;
+}
+-(void) mainLoop;
+@end
+
+/** DisplayLinkDirector is a Director that synchronizes timers with the refresh rate of the display.
+ *
+ * Features and Limitations:
+ * - Only available on 3.1+
+ * - Scheduled timers & drawing are synchronizes with the refresh rate of the display
+ * - Only supports animation intervals of 1/60 1/30 & 1/15
+ *
+ * It is the recommended Director if the SDK is 3.1 or newer
+ *
+ * @since v0.8.2
+ */
+@interface CCDirectorDisplayLink : CCDirectorIOS
+{
+ id displayLink;
+}
+-(void) mainLoop:(id)sender;
+@end
+
+/** TimerDirector is a Director that calls the main loop from an NSTimer object
+ *
+ * Features and Limitations:
+ * - Integrates OK with UIKit objects
+ * - It the slowest director
+ * - The invertal update is customizable from 1 to 60
+ *
+ * It is the default Director.
+ */
+@interface CCDirectorTimer : CCDirectorIOS
+{
+ NSTimer *animationTimer;
+}
+-(void) mainLoop;
+@end
+
+// optimization. Should only be used to read it. Never to write it.
+extern CGFloat __ccContentScaleFactor;
+
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
--- /dev/null
+/*
+ * 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.
+ *
+ */
+
+// Only compile this code on iOS. These files should NOT be included on your Mac project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+#import <unistd.h>
+
+// cocos2d imports
+#import "CCDirectorIOS.h"
+#import "CCTouchDelegateProtocol.h"
+#import "CCTouchDispatcher.h"
+#import "../../CCScheduler.h"
+#import "../../CCActionManager.h"
+#import "../../CCTextureCache.h"
+#import "../../ccMacros.h"
+#import "../../CCScene.h"
+
+// support imports
+#import "glu.h"
+#import "../../Support/OpenGL_Internal.h"
+#import "../../Support/CGPointExtension.h"
+
+#import "CCLayer.h"
+
+#if CC_ENABLE_PROFILERS
+#import "../../Support/CCProfiling.h"
+#endif
+
+
+#pragma mark -
+#pragma mark Director - global variables (optimization)
+
+CGFloat __ccContentScaleFactor = 1;
+
+#pragma mark -
+#pragma mark Director iOS
+
+@interface CCDirector ()
+-(void) setNextScene;
+-(void) showFPS;
+-(void) calculateDeltaTime;
+@end
+
+@implementation CCDirector (iOSExtensionClassMethods)
+
++(Class) defaultDirector
+{
+ return [CCDirectorTimer class];
+}
+
++ (BOOL) setDirectorType:(ccDirectorType)type
+{
+ if( type == CCDirectorTypeDisplayLink ) {
+ NSString *reqSysVer = @"3.1";
+ NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
+
+ if([currSysVer compare:reqSysVer options:NSNumericSearch] == NSOrderedAscending)
+ return NO;
+ }
+ switch (type) {
+ case CCDirectorTypeNSTimer:
+ [CCDirectorTimer sharedDirector];
+ break;
+ case CCDirectorTypeDisplayLink:
+ [CCDirectorDisplayLink sharedDirector];
+ break;
+ case CCDirectorTypeMainLoop:
+ [CCDirectorFast sharedDirector];
+ break;
+ case CCDirectorTypeThreadMainLoop:
+ [CCDirectorFastThreaded sharedDirector];
+ break;
+ default:
+ NSAssert(NO,@"Unknown director type");
+ }
+
+ return YES;
+}
+
+@end
+
+
+
+#pragma mark -
+#pragma mark CCDirectorIOS
+
+@interface CCDirectorIOS ()
+-(BOOL)isOpenGLAttached;
+-(BOOL)initOpenGLViewWithView:(UIView *)view withFrame:(CGRect)rect;
+
+-(void) updateContentScaleFactor;
+
+@end
+
+@implementation CCDirectorIOS
+
+@synthesize pixelFormat=pixelFormat_;
+
+- (id) init
+{
+ if( (self=[super init]) ) {
+
+
+ // default values
+ pixelFormat_ = kCCPixelFormatDefault; // DEPRECATED. Will be removed in 1.0
+ depthBufferFormat_ = 0; // DEPRECATED. Will be removed in 1.0
+
+ // portrait mode default
+ deviceOrientation_ = CCDeviceOrientationPortrait;
+
+ __ccContentScaleFactor = 1;
+ isContentScaleSupported_ = NO;
+
+ // running thread is main thread on iOS
+ runningThread_ = [NSThread currentThread];
+ }
+
+ return self;
+}
+
+- (void) dealloc
+{
+ [super dealloc];
+}
+
+//
+// Draw the Scene
+//
+- (void) drawScene
+{
+ /* calculate "global" dt */
+ [self calculateDeltaTime];
+
+ /* tick before glClear: issue #533 */
+ if( ! isPaused_ ) {
+ [[CCScheduler sharedScheduler] tick: dt];
+ }
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ /* to avoid flickr, nextScene MUST be here: after tick and before draw.
+ XXX: Which bug is this one. It seems that it can't be reproduced with v0.9 */
+ if( nextScene_ )
+ [self setNextScene];
+
+ glPushMatrix();
+
+ [self applyOrientation];
+
+ // By default enable VertexArray, ColorArray, TextureCoordArray and Texture2D
+ CC_ENABLE_DEFAULT_GL_STATES();
+
+ /* draw the scene */
+ [runningScene_ visit];
+
+ /* draw the notification node */
+ [notificationNode_ visit];
+
+ if( displayFPS_ )
+ [self showFPS];
+
+#if CC_ENABLE_PROFILERS
+ [self showProfilers];
+#endif
+
+ CC_DISABLE_DEFAULT_GL_STATES();
+
+ glPopMatrix();
+
+ [openGLView_ swapBuffers];
+}
+
+-(void) setProjection:(ccDirectorProjection)projection
+{
+ CGSize size = winSizeInPixels_;
+
+ switch (projection) {
+ case kCCDirectorProjection2D:
+ glViewport(0, 0, size.width, size.height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ ccglOrtho(0, size.width, 0, size.height, -1024 * CC_CONTENT_SCALE_FACTOR(), 1024 * CC_CONTENT_SCALE_FACTOR());
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ break;
+
+ case kCCDirectorProjection3D:
+ glViewport(0, 0, size.width, size.height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(60, (GLfloat)size.width/size.height, 0.5f, 1500.0f);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ gluLookAt( size.width/2, size.height/2, [self getZEye],
+ size.width/2, size.height/2, 0,
+ 0.0f, 1.0f, 0.0f);
+ break;
+
+ case kCCDirectorProjectionCustom:
+ if( projectionDelegate_ )
+ [projectionDelegate_ updateProjection];
+ break;
+
+ default:
+ CCLOG(@"cocos2d: Director: unrecognized projecgtion");
+ break;
+ }
+
+ projection_ = projection;
+}
+
+#pragma mark Director Scene iPhone Specific
+
+-(void) setPixelFormat: (tPixelFormat) format
+{
+ NSAssert( ! [self isOpenGLAttached], @"Can't change the pixel format after the director was initialized" );
+ pixelFormat_ = format;
+}
+
+-(void) setDepthBufferFormat: (tDepthBufferFormat) format
+{
+ NSAssert( ! [self isOpenGLAttached], @"Can't change the depth buffer format after the director was initialized");
+ depthBufferFormat_ = format;
+}
+
+#pragma mark Director Integration with a UIKit view
+
+// is the view currently attached
+-(BOOL)isOpenGLAttached
+{
+ return ([openGLView_ superview]!=nil);
+}
+
+// XXX: deprecated
+-(BOOL)detach
+{
+ NSAssert([self isOpenGLAttached], @"FATAL: Director: Can't detach the OpenGL View, because it is not attached. Attach it first.");
+
+ // remove from the superview
+ [openGLView_ removeFromSuperview];
+
+ NSAssert(![self isOpenGLAttached], @"FATAL: Director: Can't detach the OpenGL View, it is still attached to the superview.");
+
+
+ return YES;
+}
+
+// XXX: Deprecated method
+-(BOOL)attachInWindow:(UIWindow *)window
+{
+ if([self initOpenGLViewWithView:window withFrame:[window bounds]])
+ {
+ return YES;
+ }
+
+ return NO;
+}
+
+// XXX: Deprecated method
+-(BOOL)attachInView:(UIView *)view
+{
+ if([self initOpenGLViewWithView:view withFrame:[view bounds]])
+ {
+ return YES;
+ }
+
+ return NO;
+}
+
+// XXX: Deprecated method
+-(BOOL)attachInView:(UIView *)view withFrame:(CGRect)frame
+{
+ if([self initOpenGLViewWithView:view withFrame:frame])
+ {
+ return YES;
+ }
+
+ return NO;
+}
+
+// XXX: Deprecated method
+-(BOOL)initOpenGLViewWithView:(UIView *)view withFrame:(CGRect)rect
+{
+ NSAssert( ! [self isOpenGLAttached], @"FATAL: Can't re-attach the OpenGL View, because it is already attached. Detach it first");
+
+ // check if the view is not initialized
+ if(!openGLView_)
+ {
+ // define the pixel format
+ NSString *pFormat = nil;
+ GLuint depthFormat = 0;
+
+ if(pixelFormat_==kCCPixelFormatRGBA8888)
+ pFormat = kEAGLColorFormatRGBA8;
+ else if(pixelFormat_== kCCPixelFormatRGB565)
+ pFormat = kEAGLColorFormatRGB565;
+ else {
+ CCLOG(@"cocos2d: Director: Unknown pixel format.");
+ }
+
+ if(depthBufferFormat_ == kCCDepthBuffer16)
+ depthFormat = GL_DEPTH_COMPONENT16_OES;
+ else if(depthBufferFormat_ == kCCDepthBuffer24)
+ depthFormat = GL_DEPTH_COMPONENT24_OES;
+ else if(depthBufferFormat_ == kCCDepthBufferNone)
+ depthFormat = 0;
+ else {
+ CCLOG(@"cocos2d: Director: Unknown buffer depth.");
+ }
+
+ // alloc and init the opengl view
+ openGLView_ = [[EAGLView alloc] initWithFrame:rect
+ pixelFormat:pFormat
+ depthFormat:depthFormat
+ preserveBackbuffer:NO
+ sharegroup:nil
+ multiSampling:NO
+ numberOfSamples:0];
+
+ // check if the view was alloced and initialized
+ NSAssert( openGLView_, @"FATAL: Could not alloc and init the OpenGL view. ");
+
+ // opaque by default (faster)
+ openGLView_.opaque = YES;
+ }
+ else
+ {
+ // set the (new) frame of the glview
+ [openGLView_ setFrame:rect];
+ }
+
+ winSizeInPoints_ = rect.size;
+ winSizeInPixels_ = CGSizeMake(winSizeInPoints_.width * __ccContentScaleFactor, winSizeInPoints_.height * __ccContentScaleFactor);
+
+
+ // set the touch delegate of the glview to self
+ [openGLView_ setTouchDelegate: [CCTouchDispatcher sharedDispatcher]];
+
+
+ // check if the superview has touchs enabled and enable it in our view
+ if([view isUserInteractionEnabled])
+ {
+ [openGLView_ setUserInteractionEnabled:YES];
+ [[CCTouchDispatcher sharedDispatcher] setDispatchEvents: YES];
+ }
+ else
+ {
+ [openGLView_ setUserInteractionEnabled:NO];
+ [[CCTouchDispatcher sharedDispatcher] setDispatchEvents: NO];
+ }
+
+ // check if multi touches are enabled and set them
+ if([view isMultipleTouchEnabled])
+ {
+ [openGLView_ setMultipleTouchEnabled:YES];
+ }
+ else
+ {
+ [openGLView_ setMultipleTouchEnabled:NO];
+ }
+
+ // add the glview to his (new) superview
+ [view addSubview:openGLView_];
+
+
+ NSAssert( [self isOpenGLAttached], @"FATAL: Director: Could not attach OpenGL view");
+
+ [self setGLDefaultValues];
+ return YES;
+}
+
+-(void) setOpenGLView:(EAGLView *)view
+{
+ if( view != openGLView_ ) {
+
+ [super setOpenGLView:view];
+
+ // set size
+ winSizeInPixels_ = CGSizeMake(winSizeInPoints_.width * __ccContentScaleFactor, winSizeInPoints_.height *__ccContentScaleFactor);
+
+ if( __ccContentScaleFactor != 1 )
+ [self updateContentScaleFactor];
+
+ CCTouchDispatcher *touchDispatcher = [CCTouchDispatcher sharedDispatcher];
+ [openGLView_ setTouchDelegate: touchDispatcher];
+ [touchDispatcher setDispatchEvents: YES];
+ }
+}
+
+#pragma mark Director - Retina Display
+
+-(CGFloat) contentScaleFactor
+{
+ return __ccContentScaleFactor;
+}
+
+-(void) setContentScaleFactor:(CGFloat)scaleFactor
+{
+ if( scaleFactor != __ccContentScaleFactor ) {
+
+ __ccContentScaleFactor = scaleFactor;
+ winSizeInPixels_ = CGSizeMake( winSizeInPoints_.width * scaleFactor, winSizeInPoints_.height * scaleFactor );
+
+ if( openGLView_ )
+ [self updateContentScaleFactor];
+
+ // update projection
+ [self setProjection:projection_];
+ }
+}
+
+-(void) updateContentScaleFactor
+{
+ // Based on code snippet from: http://developer.apple.com/iphone/prerelease/library/snippets/sp2010/sp28.html
+ if ([openGLView_ respondsToSelector:@selector(setContentScaleFactor:)])
+ {
+ [openGLView_ setContentScaleFactor: __ccContentScaleFactor];
+
+ isContentScaleSupported_ = YES;
+ }
+ else
+ CCLOG(@"cocos2d: 'setContentScaleFactor:' is not supported on this device");
+}
+
+-(BOOL) enableRetinaDisplay:(BOOL)enabled
+{
+ // Already enabled ?
+ if( enabled && __ccContentScaleFactor == 2 )
+ return YES;
+
+ // Already disabled
+ if( ! enabled && __ccContentScaleFactor == 1 )
+ return YES;
+
+ // setContentScaleFactor is not supported
+ if (! [openGLView_ respondsToSelector:@selector(setContentScaleFactor:)])
+ return NO;
+
+ // SD device
+ if ([[UIScreen mainScreen] scale] == 1.0)
+ return NO;
+
+ float newScale = enabled ? 2 : 1;
+ [self setContentScaleFactor:newScale];
+
+ return YES;
+}
+
+// overriden, don't call super
+-(void) reshapeProjection:(CGSize)size
+{
+ winSizeInPoints_ = [openGLView_ bounds].size;
+ winSizeInPixels_ = CGSizeMake(winSizeInPoints_.width * __ccContentScaleFactor, winSizeInPoints_.height *__ccContentScaleFactor);
+
+ [self setProjection:projection_];
+}
+
+#pragma mark Director Scene Landscape
+
+-(CGPoint)convertToGL:(CGPoint)uiPoint
+{
+ CGSize s = winSizeInPoints_;
+ float newY = s.height - uiPoint.y;
+ float newX = s.width - uiPoint.x;
+
+ CGPoint ret = CGPointZero;
+ switch ( deviceOrientation_) {
+ case CCDeviceOrientationPortrait:
+ ret = ccp( uiPoint.x, newY );
+ break;
+ case CCDeviceOrientationPortraitUpsideDown:
+ ret = ccp(newX, uiPoint.y);
+ break;
+ case CCDeviceOrientationLandscapeLeft:
+ ret.x = uiPoint.y;
+ ret.y = uiPoint.x;
+ break;
+ case CCDeviceOrientationLandscapeRight:
+ ret.x = newY;
+ ret.y = newX;
+ break;
+ }
+
+// if( __ccContentScaleFactor != 1 && isContentScaleSupported_ )
+// ret = ccpMult(ret, __ccContentScaleFactor);
+ return ret;
+}
+
+-(CGPoint)convertToUI:(CGPoint)glPoint
+{
+ CGSize winSize = winSizeInPoints_;
+ int oppositeX = winSize.width - glPoint.x;
+ int oppositeY = winSize.height - glPoint.y;
+ CGPoint uiPoint = CGPointZero;
+ switch ( deviceOrientation_) {
+ case CCDeviceOrientationPortrait:
+ uiPoint = ccp(glPoint.x, oppositeY);
+ break;
+ case CCDeviceOrientationPortraitUpsideDown:
+ uiPoint = ccp(oppositeX, glPoint.y);
+ break;
+ case CCDeviceOrientationLandscapeLeft:
+ uiPoint = ccp(glPoint.y, glPoint.x);
+ break;
+ case CCDeviceOrientationLandscapeRight:
+ // Can't use oppositeX/Y because x/y are flipped
+ uiPoint = ccp(winSize.width-glPoint.y, winSize.height-glPoint.x);
+ break;
+ }
+
+ uiPoint = ccpMult(uiPoint, 1/__ccContentScaleFactor);
+ return uiPoint;
+}
+
+// get the current size of the glview
+-(CGSize) winSize
+{
+ CGSize s = winSizeInPoints_;
+
+ if( deviceOrientation_ == CCDeviceOrientationLandscapeLeft || deviceOrientation_ == CCDeviceOrientationLandscapeRight ) {
+ // swap x,y in landscape mode
+ CGSize tmp = s;
+ s.width = tmp.height;
+ s.height = tmp.width;
+ }
+ return s;
+}
+
+-(CGSize) winSizeInPixels
+{
+ CGSize s = [self winSize];
+
+ s.width *= CC_CONTENT_SCALE_FACTOR();
+ s.height *= CC_CONTENT_SCALE_FACTOR();
+
+ return s;
+}
+
+-(ccDeviceOrientation) deviceOrientation
+{
+ return deviceOrientation_;
+}
+
+- (void) setDeviceOrientation:(ccDeviceOrientation) orientation
+{
+ if( deviceOrientation_ != orientation ) {
+ deviceOrientation_ = orientation;
+ switch( deviceOrientation_) {
+ case CCDeviceOrientationPortrait:
+ [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationPortrait animated:NO];
+ break;
+ case CCDeviceOrientationPortraitUpsideDown:
+ [[UIApplication sharedApplication] setStatusBarOrientation: UIDeviceOrientationPortraitUpsideDown animated:NO];
+ break;
+ case CCDeviceOrientationLandscapeLeft:
+ [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationLandscapeRight animated:NO];
+ break;
+ case CCDeviceOrientationLandscapeRight:
+ [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationLandscapeLeft animated:NO];
+ break;
+ default:
+ NSLog(@"Director: Unknown device orientation");
+ break;
+ }
+ }
+}
+
+-(void) applyOrientation
+{
+ CGSize s = winSizeInPixels_;
+ float w = s.width / 2;
+ float h = s.height / 2;
+
+ // XXX it's using hardcoded values.
+ // What if the the screen size changes in the future?
+ switch ( deviceOrientation_ ) {
+ case CCDeviceOrientationPortrait:
+ // nothing
+ break;
+ case CCDeviceOrientationPortraitUpsideDown:
+ // upside down
+ glTranslatef(w,h,0);
+ glRotatef(180,0,0,1);
+ glTranslatef(-w,-h,0);
+ break;
+ case CCDeviceOrientationLandscapeRight:
+ glTranslatef(w,h,0);
+ glRotatef(90,0,0,1);
+ glTranslatef(-h,-w,0);
+ break;
+ case CCDeviceOrientationLandscapeLeft:
+ glTranslatef(w,h,0);
+ glRotatef(-90,0,0,1);
+ glTranslatef(-h,-w,0);
+ break;
+ }
+}
+
+-(void) end
+{
+ // don't release the event handlers
+ // They are needed in case the director is run again
+ [[CCTouchDispatcher sharedDispatcher] removeAllDelegates];
+
+ [super end];
+}
+
+@end
+
+
+#pragma mark -
+#pragma mark Director TimerDirector
+
+@implementation CCDirectorTimer
+- (void)startAnimation
+{
+ NSAssert( animationTimer == nil, @"animationTimer must be nil. Calling startAnimation twice?");
+
+ if( gettimeofday( &lastUpdate_, NULL) != 0 ) {
+ CCLOG(@"cocos2d: Director: Error in gettimeofday");
+ }
+
+ animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval_ target:self selector:@selector(mainLoop) userInfo:nil repeats:YES];
+
+ //
+ // If you want to attach the opengl view into UIScrollView
+ // uncomment this line to prevent 'freezing'.
+ // It doesn't work on with the Fast Director
+ //
+ // [[NSRunLoop currentRunLoop] addTimer:animationTimer
+ // forMode:NSRunLoopCommonModes];
+}
+
+-(void) mainLoop
+{
+ [self drawScene];
+}
+
+- (void)stopAnimation
+{
+ [animationTimer invalidate];
+ animationTimer = nil;
+}
+
+- (void)setAnimationInterval:(NSTimeInterval)interval
+{
+ animationInterval_ = interval;
+
+ if(animationTimer) {
+ [self stopAnimation];
+ [self startAnimation];
+ }
+}
+
+-(void) dealloc
+{
+ [animationTimer release];
+ [super dealloc];
+}
+@end
+
+
+#pragma mark -
+#pragma mark Director DirectorFast
+
+@implementation CCDirectorFast
+
+- (id) init
+{
+ if(( self = [super init] )) {
+
+#if CC_DIRECTOR_DISPATCH_FAST_EVENTS
+ CCLOG(@"cocos2d: Fast Events enabled");
+#else
+ CCLOG(@"cocos2d: Fast Events disabled");
+#endif
+ isRunning = NO;
+
+ // XXX:
+ // XXX: Don't create any autorelease object before calling "fast director"
+ // XXX: else it will be leaked
+ // XXX:
+ autoreleasePool = [NSAutoreleasePool new];
+ }
+
+ return self;
+}
+
+- (void) startAnimation
+{
+ // XXX:
+ // XXX: release autorelease objects created
+ // XXX: between "use fast director" and "runWithScene"
+ // XXX:
+ [autoreleasePool release];
+ autoreleasePool = nil;
+
+ if ( gettimeofday( &lastUpdate_, NULL) != 0 ) {
+ CCLOG(@"cocos2d: Director: Error in gettimeofday");
+ }
+
+
+ isRunning = YES;
+
+ SEL selector = @selector(mainLoop);
+ NSMethodSignature* sig = [[[CCDirector sharedDirector] class]
+ instanceMethodSignatureForSelector:selector];
+ NSInvocation* invocation = [NSInvocation
+ invocationWithMethodSignature:sig];
+ [invocation setTarget:[CCDirector sharedDirector]];
+ [invocation setSelector:selector];
+ [invocation performSelectorOnMainThread:@selector(invokeWithTarget:)
+ withObject:[CCDirector sharedDirector] waitUntilDone:NO];
+
+// NSInvocationOperation *loopOperation = [[[NSInvocationOperation alloc]
+// initWithTarget:self selector:@selector(mainLoop) object:nil]
+// autorelease];
+//
+// [loopOperation performSelectorOnMainThread:@selector(start) withObject:nil
+// waitUntilDone:NO];
+}
+
+-(void) mainLoop
+{
+ while (isRunning) {
+
+ NSAutoreleasePool *loopPool = [NSAutoreleasePool new];
+
+#if CC_DIRECTOR_DISPATCH_FAST_EVENTS
+ while( CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.004f, FALSE) == kCFRunLoopRunHandledSource);
+#else
+ while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE) == kCFRunLoopRunHandledSource);
+#endif
+
+ if (isPaused_) {
+ usleep(250000); // Sleep for a quarter of a second (250,000 microseconds) so that the framerate is 4 fps.
+ }
+
+ [self drawScene];
+
+#if CC_DIRECTOR_DISPATCH_FAST_EVENTS
+ while( CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.004f, FALSE) == kCFRunLoopRunHandledSource);
+#else
+ while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE) == kCFRunLoopRunHandledSource);
+#endif
+
+ [loopPool release];
+ }
+}
+- (void) stopAnimation
+{
+ isRunning = NO;
+}
+
+- (void)setAnimationInterval:(NSTimeInterval)interval
+{
+ NSLog(@"FastDirectory doesn't support setAnimationInterval, yet");
+}
+@end
+
+#pragma mark -
+#pragma mark Director DirectorThreadedFast
+
+@implementation CCDirectorFastThreaded
+
+- (id) init
+{
+ if(( self = [super init] )) {
+ isRunning = NO;
+ }
+
+ return self;
+}
+
+- (void) startAnimation
+{
+
+ if ( gettimeofday( &lastUpdate_, NULL) != 0 ) {
+ CCLOG(@"cocos2d: ThreadedFastDirector: Error on gettimeofday");
+ }
+
+ isRunning = YES;
+
+ NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(mainLoop) object:nil];
+ [thread start];
+ [thread release];
+}
+
+-(void) mainLoop
+{
+ while( ![[NSThread currentThread] isCancelled] ) {
+ if( isRunning )
+ [self performSelectorOnMainThread:@selector(drawScene) withObject:nil waitUntilDone:YES];
+
+ if (isPaused_) {
+ usleep(250000); // Sleep for a quarter of a second (250,000 microseconds) so that the framerate is 4 fps.
+ } else {
+// usleep(2000);
+ }
+ }
+}
+- (void) stopAnimation
+{
+ isRunning = NO;
+}
+
+- (void)setAnimationInterval:(NSTimeInterval)interval
+{
+ NSLog(@"FastDirector doesn't support setAnimationInterval, yet");
+}
+@end
+
+#pragma mark -
+#pragma mark DirectorDisplayLink
+
+// Allows building DisplayLinkDirector for pre-3.1 SDKS
+// without getting compiler warnings.
+@interface NSObject(CADisplayLink)
++ (id) displayLinkWithTarget:(id)arg1 selector:(SEL)arg2;
+- (void) addToRunLoop:(id)arg1 forMode:(id)arg2;
+- (void) setFrameInterval:(int)interval;
+- (void) invalidate;
+@end
+
+@implementation CCDirectorDisplayLink
+
+- (void)setAnimationInterval:(NSTimeInterval)interval
+{
+ animationInterval_ = interval;
+ if(displayLink){
+ [self stopAnimation];
+ [self startAnimation];
+ }
+}
+
+- (void) startAnimation
+{
+ if ( gettimeofday( &lastUpdate_, NULL) != 0 ) {
+ CCLOG(@"cocos2d: DisplayLinkDirector: Error on gettimeofday");
+ }
+
+ // approximate frame rate
+ // assumes device refreshes at 60 fps
+ int frameInterval = (int) floor(animationInterval_ * 60.0f);
+
+ CCLOG(@"cocos2d: Frame interval: %d", frameInterval);
+
+ displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(mainLoop:)];
+ [displayLink setFrameInterval:frameInterval];
+ [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
+}
+
+-(void) mainLoop:(id)sender
+{
+ [self drawScene];
+}
+
+- (void) stopAnimation
+{
+ [displayLink invalidate];
+ displayLink = nil;
+}
+
+-(void) dealloc
+{
+ [displayLink release];
+ [super dealloc];
+}
+@end
+
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * 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.
+ *
+ */
+
+// Only compile this code on iOS. These files should NOT be included on your Mac project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+#import <UIKit/UIKit.h>
+
+/**
+ CCTargetedTouchDelegate.
+
+ Using this type of delegate results in two benefits:
+ 1. You don't need to deal with NSSets, the dispatcher does the job of splitting
+ them. You get exactly one UITouch per call.
+ 2. You can *claim* a UITouch by returning YES in ccTouchBegan. Updates of claimed
+ touches are sent only to the delegate(s) that claimed them. So if you get a move/
+ ended/cancelled update you're sure it's your touch. This frees you from doing a
+ lot of checks when doing multi-touch.
+
+ (The name TargetedTouchDelegate relates to updates "targeting" their specific
+ handler, without bothering the other handlers.)
+ @since v0.8
+ */
+@protocol CCTargetedTouchDelegate <NSObject>
+
+/** Return YES to claim the touch.
+ @since v0.8
+ */
+- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event;
+@optional
+// touch updates:
+- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event;
+- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event;
+- (void)ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event;
+@end
+
+/**
+ CCStandardTouchDelegate.
+
+ This type of delegate is the same one used by CocoaTouch. You will receive all the events (Began,Moved,Ended,Cancelled).
+ @since v0.8
+*/
+@protocol CCStandardTouchDelegate <NSObject>
+@optional
+- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
+- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
+- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
+- (void)ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
+@end
+
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * 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.
+ *
+ */
+
+// Only compile this code on iOS. These files should NOT be included on your Mac project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+#import "CCTouchDelegateProtocol.h"
+#import "EAGLView.h"
+
+
+typedef enum
+{
+ kCCTouchSelectorBeganBit = 1 << 0,
+ kCCTouchSelectorMovedBit = 1 << 1,
+ kCCTouchSelectorEndedBit = 1 << 2,
+ kCCTouchSelectorCancelledBit = 1 << 3,
+ kCCTouchSelectorAllBits = ( kCCTouchSelectorBeganBit | kCCTouchSelectorMovedBit | kCCTouchSelectorEndedBit | kCCTouchSelectorCancelledBit),
+} ccTouchSelectorFlag;
+
+
+enum {
+ kCCTouchBegan,
+ kCCTouchMoved,
+ kCCTouchEnded,
+ kCCTouchCancelled,
+
+ kCCTouchMax,
+};
+
+struct ccTouchHandlerHelperData {
+ SEL touchesSel;
+ SEL touchSel;
+ ccTouchSelectorFlag type;
+};
+
+/** CCTouchDispatcher.
+ Singleton that handles all the touch events.
+ The dispatcher dispatches events to the registered TouchHandlers.
+ There are 2 different type of touch handlers:
+ - Standard Touch Handlers
+ - Targeted Touch Handlers
+
+ The Standard Touch Handlers work like the CocoaTouch touch handler: a set of touches is passed to the delegate.
+ On the other hand, the Targeted Touch Handlers only receive 1 touch at the time, and they can "swallow" touches (avoid the propagation of the event).
+
+ Firstly, the dispatcher sends the received touches to the targeted touches.
+ These touches can be swallowed by the Targeted Touch Handlers. If there are still remaining touches, then the remaining touches will be sent
+ to the Standard Touch Handlers.
+
+ @since v0.8.0
+ */
+@interface CCTouchDispatcher : NSObject <EAGLTouchDelegate>
+{
+ NSMutableArray *targetedHandlers;
+ NSMutableArray *standardHandlers;
+
+ BOOL locked;
+ BOOL toAdd;
+ BOOL toRemove;
+ NSMutableArray *handlersToAdd;
+ NSMutableArray *handlersToRemove;
+ BOOL toQuit;
+
+ BOOL dispatchEvents;
+
+ // 4, 1 for each type of event
+ struct ccTouchHandlerHelperData handlerHelperData[kCCTouchMax];
+}
+
+/** singleton of the CCTouchDispatcher */
++ (CCTouchDispatcher*)sharedDispatcher;
+
+/** Whether or not the events are going to be dispatched. Default: YES */
+@property (nonatomic,readwrite, assign) BOOL dispatchEvents;
+
+/** Adds a standard touch delegate to the dispatcher's list.
+ See StandardTouchDelegate description.
+ IMPORTANT: The delegate will be retained.
+ */
+-(void) addStandardDelegate:(id<CCStandardTouchDelegate>) delegate priority:(int)priority;
+/** Adds a targeted touch delegate to the dispatcher's list.
+ See TargetedTouchDelegate description.
+ IMPORTANT: The delegate will be retained.
+ */
+-(void) addTargetedDelegate:(id<CCTargetedTouchDelegate>) delegate priority:(int)priority swallowsTouches:(BOOL)swallowsTouches;
+/** Removes a touch delegate.
+ The delegate will be released
+ */
+-(void) removeDelegate:(id) delegate;
+/** Removes all touch delegates, releasing all the delegates */
+-(void) removeAllDelegates;
+/** Changes the priority of a previously added delegate. The lower the number,
+ the higher the priority */
+-(void) setPriority:(int) priority forDelegate:(id) delegate;
+
+@end
+
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * 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.
+ *
+ */
+
+// Only compile this code on iOS. These files should NOT be included on your Mac project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+
+#import "CCTouchDispatcher.h"
+#import "CCTouchHandler.h"
+
+
+@implementation CCTouchDispatcher
+
+@synthesize dispatchEvents;
+
+static CCTouchDispatcher *sharedDispatcher = nil;
+
++(CCTouchDispatcher*) sharedDispatcher
+{
+ @synchronized(self) {
+ if (sharedDispatcher == nil)
+ sharedDispatcher = [[self alloc] init]; // assignment not done here
+ }
+ return sharedDispatcher;
+}
+
++(id) allocWithZone:(NSZone *)zone
+{
+ @synchronized(self) {
+ NSAssert(sharedDispatcher == nil, @"Attempted to allocate a second instance of a singleton.");
+ return [super allocWithZone:zone];
+ }
+ return nil; // on subsequent allocation attempts return nil
+}
+
+-(id) init
+{
+ if((self = [super init])) {
+
+ dispatchEvents = YES;
+ targetedHandlers = [[NSMutableArray alloc] initWithCapacity:8];
+ standardHandlers = [[NSMutableArray alloc] initWithCapacity:4];
+
+ handlersToAdd = [[NSMutableArray alloc] initWithCapacity:8];
+ handlersToRemove = [[NSMutableArray alloc] initWithCapacity:8];
+
+ toRemove = NO;
+ toAdd = NO;
+ toQuit = NO;
+ locked = NO;
+
+ handlerHelperData[kCCTouchBegan] = (struct ccTouchHandlerHelperData) {@selector(ccTouchesBegan:withEvent:),@selector(ccTouchBegan:withEvent:),kCCTouchSelectorBeganBit};
+ handlerHelperData[kCCTouchMoved] = (struct ccTouchHandlerHelperData) {@selector(ccTouchesMoved:withEvent:),@selector(ccTouchMoved:withEvent:),kCCTouchSelectorMovedBit};
+ handlerHelperData[kCCTouchEnded] = (struct ccTouchHandlerHelperData) {@selector(ccTouchesEnded:withEvent:),@selector(ccTouchEnded:withEvent:),kCCTouchSelectorEndedBit};
+ handlerHelperData[kCCTouchCancelled] = (struct ccTouchHandlerHelperData) {@selector(ccTouchesCancelled:withEvent:),@selector(ccTouchCancelled:withEvent:),kCCTouchSelectorCancelledBit};
+
+ }
+
+ return self;
+}
+
+-(void) dealloc
+{
+ [targetedHandlers release];
+ [standardHandlers release];
+ [handlersToAdd release];
+ [handlersToRemove release];
+ [super dealloc];
+}
+
+//
+// handlers management
+//
+
+#pragma mark TouchDispatcher - Add Hanlder
+
+-(void) forceAddHandler:(CCTouchHandler*)handler array:(NSMutableArray*)array
+{
+ NSUInteger i = 0;
+
+ for( CCTouchHandler *h in array ) {
+ if( h.priority < handler.priority )
+ i++;
+
+ NSAssert( h.delegate != handler.delegate, @"Delegate already added to touch dispatcher.");
+ }
+ [array insertObject:handler atIndex:i];
+}
+
+-(void) addStandardDelegate:(id<CCStandardTouchDelegate>) delegate priority:(int)priority
+{
+ CCTouchHandler *handler = [CCStandardTouchHandler handlerWithDelegate:delegate priority:priority];
+ if( ! locked ) {
+ [self forceAddHandler:handler array:standardHandlers];
+ } else {
+ [handlersToAdd addObject:handler];
+ toAdd = YES;
+ }
+}
+
+-(void) addTargetedDelegate:(id<CCTargetedTouchDelegate>) delegate priority:(int)priority swallowsTouches:(BOOL)swallowsTouches
+{
+ CCTouchHandler *handler = [CCTargetedTouchHandler handlerWithDelegate:delegate priority:priority swallowsTouches:swallowsTouches];
+ if( ! locked ) {
+ [self forceAddHandler:handler array:targetedHandlers];
+ } else {
+ [handlersToAdd addObject:handler];
+ toAdd = YES;
+ }
+}
+
+#pragma mark TouchDispatcher - removeDelegate
+
+-(void) forceRemoveDelegate:(id)delegate
+{
+ // XXX: remove it from both handlers ???
+
+ for( CCTouchHandler *handler in targetedHandlers ) {
+ if( handler.delegate == delegate ) {
+ [targetedHandlers removeObject:handler];
+ break;
+ }
+ }
+
+ for( CCTouchHandler *handler in standardHandlers ) {
+ if( handler.delegate == delegate ) {
+ [standardHandlers removeObject:handler];
+ break;
+ }
+ }
+}
+
+-(void) removeDelegate:(id) delegate
+{
+ if( delegate == nil )
+ return;
+
+ if( ! locked ) {
+ [self forceRemoveDelegate:delegate];
+ } else {
+ [handlersToRemove addObject:delegate];
+ toRemove = YES;
+ }
+}
+
+#pragma mark TouchDispatcher - removeAllDelegates
+
+-(void) forceRemoveAllDelegates
+{
+ [standardHandlers removeAllObjects];
+ [targetedHandlers removeAllObjects];
+}
+-(void) removeAllDelegates
+{
+ if( ! locked )
+ [self forceRemoveAllDelegates];
+ else
+ toQuit = YES;
+}
+
+#pragma mark Changing priority of added handlers
+
+-(void) setPriority:(int) priority forDelegate:(id) delegate
+{
+ NSAssert(NO, @"Set priority no implemented yet. Don't forget to report this bug!");
+// if( delegate == nil )
+// [NSException raise:NSInvalidArgumentException format:@"Got nil touch delegate"];
+//
+// CCTouchHandler *handler = nil;
+// for( handler in touchHandlers )
+// if( handler.delegate == delegate ) break;
+//
+// if( handler == nil )
+// [NSException raise:NSInvalidArgumentException format:@"Touch delegate not found"];
+//
+// if( handler.priority != priority ) {
+// handler.priority = priority;
+//
+// [handler retain];
+// [touchHandlers removeObject:handler];
+// [self addHandler:handler];
+// [handler release];
+// }
+}
+
+
+//
+// dispatch events
+//
+-(void) touches:(NSSet*)touches withEvent:(UIEvent*)event withTouchType:(unsigned int)idx;
+{
+ NSAssert(idx < 4, @"Invalid idx value");
+
+ id mutableTouches;
+ locked = YES;
+
+ // optimization to prevent a mutable copy when it is not necessary
+ unsigned int targetedHandlersCount = [targetedHandlers count];
+ unsigned int standardHandlersCount = [standardHandlers count];
+ BOOL needsMutableSet = (targetedHandlersCount && standardHandlersCount);
+
+ mutableTouches = (needsMutableSet ? [touches mutableCopy] : touches);
+
+ struct ccTouchHandlerHelperData helper = handlerHelperData[idx];
+ //
+ // process the target handlers 1st
+ //
+ if( targetedHandlersCount > 0 ) {
+ for( UITouch *touch in touches ) {
+ for(CCTargetedTouchHandler *handler in targetedHandlers) {
+
+ BOOL claimed = NO;
+ if( idx == kCCTouchBegan ) {
+ claimed = [handler.delegate ccTouchBegan:touch withEvent:event];
+ if( claimed )
+ [handler.claimedTouches addObject:touch];
+ }
+
+ // else (moved, ended, cancelled)
+ else if( [handler.claimedTouches containsObject:touch] ) {
+ claimed = YES;
+ if( handler.enabledSelectors & helper.type )
+ [handler.delegate performSelector:helper.touchSel withObject:touch withObject:event];
+
+ if( helper.type & (kCCTouchSelectorCancelledBit | kCCTouchSelectorEndedBit) )
+ [handler.claimedTouches removeObject:touch];
+ }
+
+ if( claimed && handler.swallowsTouches ) {
+ if( needsMutableSet )
+ [mutableTouches removeObject:touch];
+ break;
+ }
+ }
+ }
+ }
+
+ //
+ // process standard handlers 2nd
+ //
+ if( standardHandlersCount > 0 && [mutableTouches count]>0 ) {
+ for( CCTouchHandler *handler in standardHandlers ) {
+ if( handler.enabledSelectors & helper.type )
+ [handler.delegate performSelector:helper.touchesSel withObject:mutableTouches withObject:event];
+ }
+ }
+ if( needsMutableSet )
+ [mutableTouches release];
+
+ //
+ // Optimization. To prevent a [handlers copy] which is expensive
+ // the add/removes/quit is done after the iterations
+ //
+ locked = NO;
+ if( toRemove ) {
+ toRemove = NO;
+ for( id delegate in handlersToRemove )
+ [self forceRemoveDelegate:delegate];
+ [handlersToRemove removeAllObjects];
+ }
+ if( toAdd ) {
+ toAdd = NO;
+ for( CCTouchHandler *handler in handlersToAdd ) {
+ Class targetedClass = [CCTargetedTouchHandler class];
+ if( [handler isKindOfClass:targetedClass] )
+ [self forceAddHandler:handler array:targetedHandlers];
+ else
+ [self forceAddHandler:handler array:standardHandlers];
+ }
+ [handlersToAdd removeAllObjects];
+ }
+ if( toQuit ) {
+ toQuit = NO;
+ [self forceRemoveAllDelegates];
+ }
+}
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ if( dispatchEvents )
+ [self touches:touches withEvent:event withTouchType:kCCTouchBegan];
+}
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ if( dispatchEvents )
+ [self touches:touches withEvent:event withTouchType:kCCTouchMoved];
+}
+
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ if( dispatchEvents )
+ [self touches:touches withEvent:event withTouchType:kCCTouchEnded];
+}
+
+- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ if( dispatchEvents )
+ [self touches:touches withEvent:event withTouchType:kCCTouchCancelled];
+}
+@end
+
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * 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.
+ *
+ */
+
+// Only compile this code on iOS. These files should NOT be included on your Mac project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+/*
+ * This file contains the delegates of the touches
+ * There are 2 possible delegates:
+ * - CCStandardTouchHandler: propagates all the events at once
+ * - CCTargetedTouchHandler: propagates 1 event at the time
+ */
+
+#import "CCTouchDelegateProtocol.h"
+#import "CCTouchDispatcher.h"
+
+/**
+ CCTouchHandler
+ Object than contains the delegate and priority of the event handler.
+*/
+@interface CCTouchHandler : NSObject {
+ id delegate;
+ int priority;
+ ccTouchSelectorFlag enabledSelectors_;
+}
+
+/** delegate */
+@property(nonatomic, readwrite, retain) id delegate;
+/** priority */
+@property(nonatomic, readwrite) int priority; // default 0
+/** enabled selectors */
+@property(nonatomic,readwrite) ccTouchSelectorFlag enabledSelectors;
+
+/** allocates a TouchHandler with a delegate and a priority */
++ (id)handlerWithDelegate:(id)aDelegate priority:(int)priority;
+/** initializes a TouchHandler with a delegate and a priority */
+- (id)initWithDelegate:(id)aDelegate priority:(int)priority;
+@end
+
+/** CCStandardTouchHandler
+ It forwardes each event to the delegate.
+ */
+@interface CCStandardTouchHandler : CCTouchHandler
+{
+}
+@end
+
+/**
+ CCTargetedTouchHandler
+ Object than contains the claimed touches and if it swallos touches.
+ Used internally by TouchDispatcher
+ */
+@interface CCTargetedTouchHandler : CCTouchHandler {
+ BOOL swallowsTouches;
+ NSMutableSet *claimedTouches;
+}
+/** whether or not the touches are swallowed */
+@property(nonatomic, readwrite) BOOL swallowsTouches; // default NO
+/** MutableSet that contains the claimed touches */
+@property(nonatomic, readonly) NSMutableSet *claimedTouches;
+
+/** allocates a TargetedTouchHandler with a delegate, a priority and whether or not it swallows touches or not */
++ (id)handlerWithDelegate:(id) aDelegate priority:(int)priority swallowsTouches:(BOOL)swallowsTouches;
+/** initializes a TargetedTouchHandler with a delegate, a priority and whether or not it swallows touches or not */
+- (id)initWithDelegate:(id) aDelegate priority:(int)priority swallowsTouches:(BOOL)swallowsTouches;
+
+@end
+
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * 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.
+ *
+ */
+
+
+// Only compile this code on iOS. These files should NOT be included on your Mac project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+/*
+ * This file contains the delegates of the touches
+ * There are 2 possible delegates:
+ * - CCStandardTouchHandler: propagates all the events at once
+ * - CCTargetedTouchHandler: propagates 1 event at the time
+ */
+
+#import "CCTouchHandler.h"
+#import "../../ccMacros.h"
+
+#pragma mark -
+#pragma mark TouchHandler
+@implementation CCTouchHandler
+
+@synthesize delegate, priority;
+@synthesize enabledSelectors=enabledSelectors_;
+
++ (id)handlerWithDelegate:(id) aDelegate priority:(int)aPriority
+{
+ return [[[self alloc] initWithDelegate:aDelegate priority:aPriority] autorelease];
+}
+
+- (id)initWithDelegate:(id) aDelegate priority:(int)aPriority
+{
+ NSAssert(aDelegate != nil, @"Touch delegate may not be nil");
+
+ if ((self = [super init])) {
+ self.delegate = aDelegate;
+ priority = aPriority;
+ enabledSelectors_ = 0;
+ }
+
+ return self;
+}
+
+- (void)dealloc {
+ CCLOGINFO(@"cocos2d: deallocing %@", self);
+ [delegate release];
+ [super dealloc];
+}
+@end
+
+#pragma mark -
+#pragma mark StandardTouchHandler
+@implementation CCStandardTouchHandler
+-(id) initWithDelegate:(id)del priority:(int)pri
+{
+ if( (self=[super initWithDelegate:del priority:pri]) ) {
+ if( [del respondsToSelector:@selector(ccTouchesBegan:withEvent:)] )
+ enabledSelectors_ |= kCCTouchSelectorBeganBit;
+ if( [del respondsToSelector:@selector(ccTouchesMoved:withEvent:)] )
+ enabledSelectors_ |= kCCTouchSelectorMovedBit;
+ if( [del respondsToSelector:@selector(ccTouchesEnded:withEvent:)] )
+ enabledSelectors_ |= kCCTouchSelectorEndedBit;
+ if( [del respondsToSelector:@selector(ccTouchesCancelled:withEvent:)] )
+ enabledSelectors_ |= kCCTouchSelectorCancelledBit;
+ }
+ return self;
+}
+@end
+
+#pragma mark -
+#pragma mark TargetedTouchHandler
+
+@interface CCTargetedTouchHandler (private)
+-(void) updateKnownTouches:(NSMutableSet *)touches withEvent:(UIEvent *)event selector:(SEL)selector unclaim:(BOOL)doUnclaim;
+@end
+
+@implementation CCTargetedTouchHandler
+
+@synthesize swallowsTouches, claimedTouches;
+
++ (id)handlerWithDelegate:(id)aDelegate priority:(int)priority swallowsTouches:(BOOL)swallow
+{
+ return [[[self alloc] initWithDelegate:aDelegate priority:priority swallowsTouches:swallow] autorelease];
+}
+
+- (id)initWithDelegate:(id)aDelegate priority:(int)aPriority swallowsTouches:(BOOL)swallow
+{
+ if ((self = [super initWithDelegate:aDelegate priority:aPriority])) {
+ claimedTouches = [[NSMutableSet alloc] initWithCapacity:2];
+ swallowsTouches = swallow;
+
+ if( [aDelegate respondsToSelector:@selector(ccTouchBegan:withEvent:)] )
+ enabledSelectors_ |= kCCTouchSelectorBeganBit;
+ if( [aDelegate respondsToSelector:@selector(ccTouchMoved:withEvent:)] )
+ enabledSelectors_ |= kCCTouchSelectorMovedBit;
+ if( [aDelegate respondsToSelector:@selector(ccTouchEnded:withEvent:)] )
+ enabledSelectors_ |= kCCTouchSelectorEndedBit;
+ if( [aDelegate respondsToSelector:@selector(ccTouchCancelled:withEvent:)] )
+ enabledSelectors_ |= kCCTouchSelectorCancelledBit;
+ }
+
+ return self;
+}
+
+- (void)dealloc {
+ [claimedTouches release];
+ [super dealloc];
+}
+@end
+
+
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
\ No newline at end of file
--- /dev/null
+/*
+
+===== IMPORTANT =====
+
+This is sample code demonstrating API, technology or techniques in development.
+Although this sample code has been reviewed for technical accuracy, it is not
+final. Apple is supplying this information to help you plan for the adoption of
+the technologies and programming interfaces described herein. This information
+is subject to change, and software implemented based on this sample code should
+be tested with final operating system software and final documentation. Newer
+versions of this sample code may be provided with future seeds of the API or
+technology. For information about updates to this and other developer
+documentation, view the New & Updated sidebars in subsequent documentation
+seeds.
+
+=====================
+
+File: EAGLView.h
+Abstract: Convenience class that wraps the CAEAGLLayer from CoreAnimation into a
+UIView subclass.
+
+Version: 1.3
+
+Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
+("Apple") in consideration of your agreement to the following terms, and your
+use, installation, modification or redistribution of this Apple software
+constitutes acceptance of these terms. If you do not agree with these terms,
+please do not use, install, modify or redistribute this Apple software.
+
+In consideration of your agreement to abide by the following terms, and subject
+to these terms, Apple grants you a personal, non-exclusive license, under
+Apple's copyrights in this original Apple software (the "Apple Software"), to
+use, reproduce, modify and redistribute the Apple Software, with or without
+modifications, in source and/or binary forms; provided that if you redistribute
+the Apple Software in its entirety and without modifications, you must retain
+this notice and the following text and disclaimers in all such redistributions
+of the Apple Software.
+Neither the name, trademarks, service marks or logos of Apple Inc. may be used
+to endorse or promote products derived from the Apple Software without specific
+prior written permission from Apple. Except as expressly stated in this notice,
+no other rights or licenses, express or implied, are granted by Apple herein,
+including but not limited to any patent rights that may be infringed by your
+derivative works or by other works in which the Apple Software may be
+incorporated.
+
+The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
+DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
+CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Copyright (C) 2008 Apple Inc. All Rights Reserved.
+
+*/
+
+// Only compile this code on iOS. These files should NOT be included on your Mac project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+#import <UIKit/UIKit.h>
+#import <OpenGLES/EAGL.h>
+#import <OpenGLES/EAGLDrawable.h>
+#import <OpenGLES/ES1/gl.h>
+#import <OpenGLES/ES1/glext.h>
+
+#import "ESRenderer.h"
+
+//CLASSES:
+
+@class EAGLView;
+@class EAGLSharegroup;
+
+//PROTOCOLS:
+
+@protocol EAGLTouchDelegate <NSObject>
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
+- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
+@end
+
+//CLASS INTERFACE:
+
+/** EAGLView Class.
+ * This class wraps the CAEAGLLayer from CoreAnimation into a convenient UIView subclass.
+ * The view content is basically an EAGL surface you render your OpenGL scene into.
+ * Note that setting the view non-opaque will only work if the EAGL surface has an alpha channel.
+ */
+@interface EAGLView : UIView
+{
+ id<ESRenderer> renderer_;
+ EAGLContext *context_; // weak ref
+
+ NSString *pixelformat_;
+ GLuint depthFormat_;
+ BOOL preserveBackbuffer_;
+
+ CGSize size_;
+ BOOL discardFramebufferSupported_;
+ id<EAGLTouchDelegate> touchDelegate_;
+
+ //fsaa addition
+ BOOL multisampling_;
+ unsigned int requestedSamples_;
+}
+
+/** creates an initializes an EAGLView with a frame and 0-bit depth buffer, and a RGB565 color buffer. */
++ (id) viewWithFrame:(CGRect)frame;
+/** creates an initializes an EAGLView with a frame, a color buffer format, and 0-bit depth buffer. */
++ (id) viewWithFrame:(CGRect)frame pixelFormat:(NSString*)format;
+/** creates an initializes an EAGLView with a frame, a color buffer format, and a depth buffer. */
++ (id) viewWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth;
+/** creates an initializes an EAGLView with a frame, a color buffer format, a depth buffer format, a sharegroup, and multisamping */
++ (id) viewWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth preserveBackbuffer:(BOOL)retained sharegroup:(EAGLSharegroup*)sharegroup multiSampling:(BOOL)multisampling numberOfSamples:(unsigned int)samples;
+
+/** Initializes an EAGLView with a frame and 0-bit depth buffer, and a RGB565 color buffer */
+- (id) initWithFrame:(CGRect)frame; //These also set the current context
+/** Initializes an EAGLView with a frame, a color buffer format, and 0-bit depth buffer */
+- (id) initWithFrame:(CGRect)frame pixelFormat:(NSString*)format;
+/** Initializes an EAGLView with a frame, a color buffer format, a depth buffer format, a sharegroup and multisampling support */
+- (id) initWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth preserveBackbuffer:(BOOL)retained sharegroup:(EAGLSharegroup*)sharegroup multiSampling:(BOOL)sampling numberOfSamples:(unsigned int)nSamples;
+
+/** pixel format: it could be RGBA8 (32-bit) or RGB565 (16-bit) */
+@property(nonatomic,readonly) NSString* pixelFormat;
+/** depth format of the render buffer: 0, 16 or 24 bits*/
+@property(nonatomic,readonly) GLuint depthFormat;
+
+/** returns surface size in pixels */
+@property(nonatomic,readonly) CGSize surfaceSize;
+
+/** OpenGL context */
+@property(nonatomic,readonly) EAGLContext *context;
+
+@property(nonatomic,readwrite) BOOL multiSampling;
+
+/** touch delegate */
+@property(nonatomic,readwrite,assign) id<EAGLTouchDelegate> touchDelegate;
+
+/** EAGLView uses double-buffer. This method swaps the buffers */
+-(void) swapBuffers;
+
+- (CGPoint) convertPointFromViewToSurface:(CGPoint)point;
+- (CGRect) convertRectFromViewToSurface:(CGRect)rect;
+@end
+
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
\ No newline at end of file
--- /dev/null
+/*
+
+===== IMPORTANT =====
+
+This is sample code demonstrating API, technology or techniques in development.
+Although this sample code has been reviewed for technical accuracy, it is not
+final. Apple is supplying this information to help you plan for the adoption of
+the technologies and programming interfaces described herein. This information
+is subject to change, and software implemented based on this sample code should
+be tested with final operating system software and final documentation. Newer
+versions of this sample code may be provided with future seeds of the API or
+technology. For information about updates to this and other developer
+documentation, view the New & Updated sidebars in subsequent documentation
+seeds.
+
+=====================
+
+File: EAGLView.m
+Abstract: Convenience class that wraps the CAEAGLLayer from CoreAnimation into a
+UIView subclass.
+
+Version: 1.3
+
+Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
+("Apple") in consideration of your agreement to the following terms, and your
+use, installation, modification or redistribution of this Apple software
+constitutes acceptance of these terms. If you do not agree with these terms,
+please do not use, install, modify or redistribute this Apple software.
+
+In consideration of your agreement to abide by the following terms, and subject
+to these terms, Apple grants you a personal, non-exclusive license, under
+Apple's copyrights in this original Apple software (the "Apple Software"), to
+use, reproduce, modify and redistribute the Apple Software, with or without
+modifications, in source and/or binary forms; provided that if you redistribute
+the Apple Software in its entirety and without modifications, you must retain
+this notice and the following text and disclaimers in all such redistributions
+of the Apple Software.
+Neither the name, trademarks, service marks or logos of Apple Inc. may be used
+to endorse or promote products derived from the Apple Software without specific
+prior written permission from Apple. Except as expressly stated in this notice,
+no other rights or licenses, express or implied, are granted by Apple herein,
+including but not limited to any patent rights that may be infringed by your
+derivative works or by other works in which the Apple Software may be
+incorporated.
+
+The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
+DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
+CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Copyright (C) 2008 Apple Inc. All Rights Reserved.
+
+*/
+
+// Only compile this code on iOS. These files should NOT be included on your Mac project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+#import <QuartzCore/QuartzCore.h>
+
+#import "EAGLView.h"
+#import "ES1Renderer.h"
+#import "../../CCDirector.h"
+#import "../../ccMacros.h"
+#import "../../CCConfiguration.h"
+#import "../../Support/OpenGL_Internal.h"
+
+
+//CLASS IMPLEMENTATIONS:
+
+@interface EAGLView (Private)
+- (BOOL) setupSurfaceWithSharegroup:(EAGLSharegroup*)sharegroup;
+- (unsigned int) convertPixelFormat:(NSString*) pixelFormat;
+@end
+
+@implementation EAGLView
+
+@synthesize surfaceSize=size_;
+@synthesize pixelFormat=pixelformat_, depthFormat=depthFormat_;
+@synthesize touchDelegate=touchDelegate_;
+@synthesize context=context_;
+@synthesize multiSampling=multiSampling_;
+
++ (Class) layerClass
+{
+ return [CAEAGLLayer class];
+}
+
++ (id) viewWithFrame:(CGRect)frame
+{
+ return [[[self alloc] initWithFrame:frame] autorelease];
+}
+
++ (id) viewWithFrame:(CGRect)frame pixelFormat:(NSString*)format
+{
+ return [[[self alloc] initWithFrame:frame pixelFormat:format] autorelease];
+}
+
++ (id) viewWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth
+{
+ return [[[self alloc] initWithFrame:frame pixelFormat:format depthFormat:depth preserveBackbuffer:NO sharegroup:nil multiSampling:NO numberOfSamples:0] autorelease];
+}
+
++ (id) viewWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth preserveBackbuffer:(BOOL)retained sharegroup:(EAGLSharegroup*)sharegroup multiSampling:(BOOL)multisampling numberOfSamples:(unsigned int)samples
+{
+ return [[[self alloc] initWithFrame:frame pixelFormat:format depthFormat:depth preserveBackbuffer:retained sharegroup:sharegroup multiSampling:multisampling numberOfSamples:samples] autorelease];
+}
+
+- (id) initWithFrame:(CGRect)frame
+{
+ return [self initWithFrame:frame pixelFormat:kEAGLColorFormatRGB565 depthFormat:0 preserveBackbuffer:NO sharegroup:nil multiSampling:NO numberOfSamples:0];
+}
+
+- (id) initWithFrame:(CGRect)frame pixelFormat:(NSString*)format
+{
+ return [self initWithFrame:frame pixelFormat:format depthFormat:0 preserveBackbuffer:NO sharegroup:nil multiSampling:NO numberOfSamples:0];
+}
+
+- (id) initWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth preserveBackbuffer:(BOOL)retained sharegroup:(EAGLSharegroup*)sharegroup multiSampling:(BOOL)sampling numberOfSamples:(unsigned int)nSamples
+{
+ if((self = [super initWithFrame:frame]))
+ {
+ pixelformat_ = format;
+ depthFormat_ = depth;
+ multiSampling_ = sampling;
+ requestedSamples_ = nSamples;
+ preserveBackbuffer_ = retained;
+
+ if( ! [self setupSurfaceWithSharegroup:sharegroup] ) {
+ [self release];
+ return nil;
+ }
+ }
+
+ return self;
+}
+
+-(id) initWithCoder:(NSCoder *)aDecoder
+{
+ if( (self = [super initWithCoder:aDecoder]) ) {
+
+ CAEAGLLayer* eaglLayer = (CAEAGLLayer*)[self layer];
+
+ pixelformat_ = kEAGLColorFormatRGB565;
+ depthFormat_ = 0; // GL_DEPTH_COMPONENT24_OES;
+ multiSampling_= NO;
+ requestedSamples_ = 0;
+ size_ = [eaglLayer bounds].size;
+
+ if( ! [self setupSurfaceWithSharegroup:nil] ) {
+ [self release];
+ return nil;
+ }
+ }
+
+ return self;
+}
+
+-(BOOL) setupSurfaceWithSharegroup:(EAGLSharegroup*)sharegroup
+{
+ CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
+
+ eaglLayer.opaque = YES;
+ eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithBool:preserveBackbuffer_], kEAGLDrawablePropertyRetainedBacking,
+ pixelformat_, kEAGLDrawablePropertyColorFormat, nil];
+
+
+ renderer_ = [[ES1Renderer alloc] initWithDepthFormat:depthFormat_
+ withPixelFormat:[self convertPixelFormat:pixelformat_]
+ withSharegroup:sharegroup
+ withMultiSampling:multiSampling_
+ withNumberOfSamples:requestedSamples_];
+ if (!renderer_)
+ return NO;
+
+ context_ = [renderer_ context];
+ [context_ renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:eaglLayer];
+
+ discardFramebufferSupported_ = [[CCConfiguration sharedConfiguration] supportsDiscardFramebuffer];
+
+ return YES;
+}
+
+- (void) dealloc
+{
+ CCLOGINFO(@"cocos2d: deallocing %@", self);
+
+
+ [renderer_ release];
+ [super dealloc];
+}
+
+- (void) layoutSubviews
+{
+ [renderer_ resizeFromLayer:(CAEAGLLayer*)self.layer];
+ size_ = [renderer_ backingSize];
+
+ // Issue #914 #924
+ CCDirector *director = [CCDirector sharedDirector];
+ [director reshapeProjection:size_];
+
+ // Avoid flicker. Issue #350
+ [director performSelectorOnMainThread:@selector(drawScene) withObject:nil waitUntilDone:YES];
+}
+
+- (void) swapBuffers
+{
+ // IMPORTANT:
+ // - preconditions
+ // -> context_ MUST be the OpenGL context
+ // -> renderbuffer_ must be the the RENDER BUFFER
+
+#ifdef __IPHONE_4_0
+
+ if (multiSampling_)
+ {
+ /* Resolve from msaaFramebuffer to resolveFramebuffer */
+ //glDisable(GL_SCISSOR_TEST);
+ glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, [renderer_ msaaFrameBuffer]);
+ glBindFramebufferOES(GL_DRAW_FRAMEBUFFER_APPLE, [renderer_ defaultFrameBuffer]);
+ glResolveMultisampleFramebufferAPPLE();
+ }
+
+ if( discardFramebufferSupported_)
+ {
+ if (multiSampling_)
+ {
+ if (depthFormat_)
+ {
+ GLenum attachments[] = {GL_COLOR_ATTACHMENT0_OES, GL_DEPTH_ATTACHMENT_OES};
+ glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 2, attachments);
+ }
+ else
+ {
+ GLenum attachments[] = {GL_COLOR_ATTACHMENT0_OES};
+ glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 1, attachments);
+ }
+
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, [renderer_ colorRenderBuffer]);
+
+ }
+
+ // not MSAA
+ else if (depthFormat_ ) {
+ GLenum attachments[] = { GL_DEPTH_ATTACHMENT_OES};
+ glDiscardFramebufferEXT(GL_FRAMEBUFFER_OES, 1, attachments);
+ }
+ }
+
+#endif // __IPHONE_4_0
+
+ if(![context_ presentRenderbuffer:GL_RENDERBUFFER_OES])
+ CCLOG(@"cocos2d: Failed to swap renderbuffer in %s\n", __FUNCTION__);
+
+#if COCOS2D_DEBUG
+ CHECK_GL_ERROR();
+#endif
+
+ // We can safely re-bind the framebuffer here, since this will be the
+ // 1st instruction of the new main loop
+ if( multiSampling_ )
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, [renderer_ msaaFrameBuffer]);
+}
+
+- (unsigned int) convertPixelFormat:(NSString*) pixelFormat
+{
+ // define the pixel format
+ GLenum pFormat;
+
+
+ if([pixelFormat isEqualToString:@"EAGLColorFormat565"])
+ pFormat = GL_RGB565_OES;
+ else
+ pFormat = GL_RGBA8_OES;
+
+ return pFormat;
+}
+
+#pragma mark EAGLView - Point conversion
+
+- (CGPoint) convertPointFromViewToSurface:(CGPoint)point
+{
+ CGRect bounds = [self bounds];
+
+ return CGPointMake((point.x - bounds.origin.x) / bounds.size.width * size_.width, (point.y - bounds.origin.y) / bounds.size.height * size_.height);
+}
+
+- (CGRect) convertRectFromViewToSurface:(CGRect)rect
+{
+ CGRect bounds = [self bounds];
+
+ return CGRectMake((rect.origin.x - bounds.origin.x) / bounds.size.width * size_.width, (rect.origin.y - bounds.origin.y) / bounds.size.height * size_.height, rect.size.width / bounds.size.width * size_.width, rect.size.height / bounds.size.height * size_.height);
+}
+
+// Pass the touches to the superview
+#pragma mark EAGLView - Touch Delegate
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ if(touchDelegate_)
+ {
+ [touchDelegate_ touchesBegan:touches withEvent:event];
+ }
+}
+
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ if(touchDelegate_)
+ {
+ [touchDelegate_ touchesMoved:touches withEvent:event];
+ }
+}
+
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ if(touchDelegate_)
+ {
+ [touchDelegate_ touchesEnded:touches withEvent:event];
+ }
+}
+- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ if(touchDelegate_)
+ {
+ [touchDelegate_ touchesCancelled:touches withEvent:event];
+ }
+}
+
+@end
+
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
\ No newline at end of file
--- /dev/null
+/*
+ * 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.
+ *
+ *
+ * File autogenerated with Xcode. Adapted for cocos2d needs.
+ */
+
+// Only compile this code on iOS. These files should NOT be included on your Mac project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+
+#import "ESRenderer.h"
+
+#import <OpenGLES/ES1/gl.h>
+#import <OpenGLES/ES1/glext.h>
+
+@interface ES1Renderer : NSObject <ESRenderer>
+{
+ // The pixel dimensions of the CAEAGLLayer
+ GLint backingWidth_;
+ GLint backingHeight_;
+
+ unsigned int samplesToUse_;
+ BOOL multiSampling_;
+
+ unsigned int depthFormat_;
+ unsigned int pixelFormat_;
+
+ // The OpenGL ES names for the framebuffer and renderbuffer used to render to this view
+ GLuint defaultFramebuffer_;
+ GLuint colorRenderbuffer_;
+ GLuint depthBuffer_;
+
+
+ //buffers for MSAA
+ GLuint msaaFramebuffer_;
+ GLuint msaaColorbuffer_;
+
+ EAGLContext *context_;
+}
+
+/** EAGLContext */
+@property (nonatomic,readonly) EAGLContext* context;
+
+- (BOOL)resizeFromLayer:(CAEAGLLayer *)layer;
+
+@end
+
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
--- /dev/null
+/*
+ * 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.
+ *
+ *
+ * File autogenerated with Xcode. Adapted for cocos2d needs.
+ */
+
+// Only compile this code on iOS. These files should NOT be included on your Mac project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+#import "ES1Renderer.h"
+#import "../../Support/OpenGL_Internal.h"
+#import "../../ccMacros.h"
+
+
+@interface ES1Renderer (private)
+
+- (GLenum) convertPixelFormat:(int) pixelFormat;
+
+@end
+
+
+@implementation ES1Renderer
+
+@synthesize context=context_;
+
+- (id) initWithDepthFormat:(unsigned int)depthFormat withPixelFormat:(unsigned int)pixelFormat withSharegroup:(EAGLSharegroup*)sharegroup withMultiSampling:(BOOL) multiSampling withNumberOfSamples:(unsigned int) requestedSamples
+{
+ if ((self = [super init]))
+ {
+ if ( sharegroup == nil )
+ {
+ context_ = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
+ }
+ else
+ {
+ context_ = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1 sharegroup:sharegroup];
+ }
+
+ if (!context_ || ![EAGLContext setCurrentContext:context_])
+ {
+ [self release];
+ return nil;
+ }
+
+ // Create default framebuffer object. The backing will be allocated for the current layer in -resizeFromLayer
+ glGenFramebuffersOES(1, &defaultFramebuffer_);
+ NSAssert( defaultFramebuffer_, @"Can't create default frame buffer");
+ glGenRenderbuffersOES(1, &colorRenderbuffer_);
+ NSAssert( colorRenderbuffer_, @"Can't create default render buffer");
+
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer_);
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer_);
+ glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer_);
+
+ depthFormat_ = depthFormat;
+
+ if( depthFormat_ ) {
+// glGenRenderbuffersOES(1, &depthBuffer_);
+// glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthBuffer_);
+// glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthFormat_, 100, 100);
+// glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthBuffer_);
+
+ // default buffer
+// glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer_);
+ }
+
+ pixelFormat_ = pixelFormat;
+ multiSampling_ = multiSampling;
+ if (multiSampling_)
+ {
+ GLint maxSamplesAllowed;
+ glGetIntegerv(GL_MAX_SAMPLES_APPLE, &maxSamplesAllowed);
+ samplesToUse_ = MIN(maxSamplesAllowed,requestedSamples);
+
+ /* Create the MSAA framebuffer (offscreen) */
+ glGenFramebuffersOES(1, &msaaFramebuffer_);
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, msaaFramebuffer_);
+
+ }
+
+ CHECK_GL_ERROR();
+ }
+
+ return self;
+}
+
+- (BOOL)resizeFromLayer:(CAEAGLLayer *)layer
+{
+ // Allocate color buffer backing based on the current layer size
+
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer_);
+
+ if (![context_ renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:layer])
+ {
+ CCLOG(@"failed to call context");
+ }
+
+ glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth_);
+ glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight_);
+
+ CCLOG(@"cocos2d: surface size: %dx%d", (int)backingWidth_, (int)backingHeight_);
+
+ if (multiSampling_)
+ {
+ /* Create the offscreen MSAA color buffer.
+ After rendering, the contents of this will be blitted into ColorRenderbuffer */
+
+ //msaaFrameBuffer needs to be binded
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, msaaFramebuffer_);
+ glGenRenderbuffersOES(1, &msaaColorbuffer_);
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, msaaColorbuffer_);
+ glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, samplesToUse_,pixelFormat_ , backingWidth_, backingHeight_);
+ glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, msaaColorbuffer_);
+
+ if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
+ {
+ CCLOG(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
+ return NO;
+ }
+ }
+
+ if (depthFormat_)
+ {
+ if( ! depthBuffer_ )
+ glGenRenderbuffersOES(1, &depthBuffer_);
+
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthBuffer_);
+ if( multiSampling_ )
+ glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, samplesToUse_, depthFormat_,backingWidth_, backingHeight_);
+ else
+ glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthFormat_, backingWidth_, backingHeight_);
+ glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthBuffer_);
+
+ // bind color buffer
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer_);
+ }
+
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer_);
+
+ if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
+ {
+ CCLOG(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
+ return NO;
+ }
+
+ CHECK_GL_ERROR();
+
+ return YES;
+}
+
+-(CGSize) backingSize
+{
+ return CGSizeMake( backingWidth_, backingHeight_);
+}
+
+- (NSString*) description
+{
+ return [NSString stringWithFormat:@"<%@ = %08X | size = %ix%i>", [self class], self, backingWidth_, backingHeight_];
+}
+
+
+- (void)dealloc
+{
+ CCLOGINFO(@"cocos2d: deallocing %@", self);
+
+ // Tear down GL
+ if(defaultFramebuffer_)
+ {
+ glDeleteFramebuffersOES(1, &defaultFramebuffer_);
+ defaultFramebuffer_ = 0;
+ }
+
+ if(colorRenderbuffer_)
+ {
+ glDeleteRenderbuffersOES(1, &colorRenderbuffer_);
+ colorRenderbuffer_ = 0;
+ }
+
+ if( depthBuffer_ )
+ {
+ glDeleteRenderbuffersOES(1, &depthBuffer_);
+ depthBuffer_ = 0;
+ }
+
+ if ( msaaColorbuffer_)
+ {
+ glDeleteRenderbuffersOES(1, &msaaColorbuffer_);
+ msaaColorbuffer_ = 0;
+ }
+
+ if ( msaaFramebuffer_)
+ {
+ glDeleteRenderbuffersOES(1, &msaaFramebuffer_);
+ msaaFramebuffer_ = 0;
+ }
+
+ // Tear down context
+ if ([EAGLContext currentContext] == context_)
+ [EAGLContext setCurrentContext:nil];
+
+ [context_ release];
+ context_ = nil;
+
+ [super dealloc];
+}
+
+- (unsigned int) colorRenderBuffer
+{
+ return colorRenderbuffer_;
+}
+
+- (unsigned int) defaultFrameBuffer
+{
+ return defaultFramebuffer_;
+}
+
+- (unsigned int) msaaFrameBuffer
+{
+ return msaaFramebuffer_;
+}
+
+- (unsigned int) msaaColorBuffer
+{
+ return msaaColorbuffer_;
+}
+
+@end
+
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
--- /dev/null
+/*
+ * 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.
+ *
+ *
+ * File autogenerated with Xcode. Adapted for cocos2d needs.
+ */
+
+// Only compile this code on iOS. These files should NOT be included on your Mac project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+#import <QuartzCore/QuartzCore.h>
+
+#import <OpenGLES/EAGL.h>
+#import <OpenGLES/EAGLDrawable.h>
+
+@protocol ESRenderer <NSObject>
+
+- (id) initWithDepthFormat:(unsigned int)depthFormat withPixelFormat:(unsigned int)pixelFormat withSharegroup:(EAGLSharegroup*)sharegroup withMultiSampling:(BOOL) multiSampling withNumberOfSamples:(unsigned int) requestedSamples;
+
+- (BOOL) resizeFromLayer:(CAEAGLLayer *)layer;
+
+- (EAGLContext*) context;
+- (CGSize) backingSize;
+
+- (unsigned int) colorRenderBuffer;
+- (unsigned int) defaultFrameBuffer;
+- (unsigned int) msaaFrameBuffer;
+- (unsigned int) msaaColorBuffer;
+@end
+
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
--- /dev/null
+//
+// cocos2d (incomplete) GLU implementation
+//
+// gluLookAt and gluPerspective from:
+// http://jet.ro/creations (San Angeles Observation)
+//
+//
+
+// Only compile this code on iOS. These files should NOT be included on your Mac project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+#import <OpenGLES/ES1/gl.h>
+#import <math.h>
+#import "../../Support/OpenGL_Internal.h"
+#include "glu.h"
+
+void gluPerspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
+{
+ GLfloat xmin, xmax, ymin, ymax;
+
+ ymax = zNear * (GLfloat)tanf(fovy * (float)M_PI / 360);
+ ymin = -ymax;
+ xmin = ymin * aspect;
+ xmax = ymax * aspect;
+
+ glFrustumf(xmin, xmax,
+ ymin, ymax,
+ zNear, zFar);
+}
+
+void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez,
+ GLfloat centerx, GLfloat centery, GLfloat centerz,
+ GLfloat upx, GLfloat upy, GLfloat upz)
+{
+ GLfloat m[16];
+ GLfloat x[3], y[3], z[3];
+ GLfloat mag;
+
+ /* Make rotation matrix */
+
+ /* Z vector */
+ z[0] = eyex - centerx;
+ z[1] = eyey - centery;
+ z[2] = eyez - centerz;
+ mag = (float)sqrtf(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
+ if (mag) {
+ z[0] /= mag;
+ z[1] /= mag;
+ z[2] /= mag;
+ }
+
+ /* Y vector */
+ y[0] = upx;
+ y[1] = upy;
+ y[2] = upz;
+
+ /* X vector = Y cross Z */
+ x[0] = y[1] * z[2] - y[2] * z[1];
+ x[1] = -y[0] * z[2] + y[2] * z[0];
+ x[2] = y[0] * z[1] - y[1] * z[0];
+
+ /* Recompute Y = Z cross X */
+ y[0] = z[1] * x[2] - z[2] * x[1];
+ y[1] = -z[0] * x[2] + z[2] * x[0];
+ y[2] = z[0] * x[1] - z[1] * x[0];
+
+ /* cross product gives area of parallelogram, which is < 1.0 for
+ * non-perpendicular unit-length vectors; so normalize x, y here
+ */
+
+ mag = (float)sqrtf(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
+ if (mag) {
+ x[0] /= mag;
+ x[1] /= mag;
+ x[2] /= mag;
+ }
+
+ mag = (float)sqrtf(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
+ if (mag) {
+ y[0] /= mag;
+ y[1] /= mag;
+ y[2] /= mag;
+ }
+
+#define M(row,col) m[col*4+row]
+ M(0, 0) = x[0];
+ M(0, 1) = x[1];
+ M(0, 2) = x[2];
+ M(0, 3) = 0.0f;
+ M(1, 0) = y[0];
+ M(1, 1) = y[1];
+ M(1, 2) = y[2];
+ M(1, 3) = 0.0f;
+ M(2, 0) = z[0];
+ M(2, 1) = z[1];
+ M(2, 2) = z[2];
+ M(2, 3) = 0.0f;
+ M(3, 0) = 0.0f;
+ M(3, 1) = 0.0f;
+ M(3, 2) = 0.0f;
+ M(3, 3) = 1.0f;
+#undef M
+
+ glMultMatrixf(m);
+
+
+ /* Translate Eye to Origin */
+ glTranslatef(-eyex, -eyey, -eyez);
+}
+
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
--- /dev/null
+//
+// cocos2d GLU implementation
+//
+// implementation of GLU functions
+//
+#ifndef __COCOS2D_GLU_H
+#define __COCOS2D_GLU_H
+
+// Only compile this code on iOS. These files should NOT be included on your Mac project.
+// But in case they are included, it won't be compiled.
+#import <Availability.h>
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+#import <OpenGLES/ES1/gl.h>
+
+/**
+ @file
+ cocos2d OpenGL GLU implementation
+ */
+
+/** OpenGL gluLookAt implementation */
+void gluLookAt(float eyeX, float eyeY, float eyeZ, float lookAtX, float lookAtY, float lookAtZ, float upX, float upY, float upZ);
+/** OpenGL gluPerspective implementation */
+void gluPerspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar);
+
+#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
+
+#endif /* __COCOS2D_GLU_H */
+
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * Copyright (c) 2010 Abstraction Works. http://www.abstractionworks.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 "ccCArray.h"
+
+
+/** A faster alternative of NSArray.
+ CCArray uses internally a c-array.
+ @since v0.99.4
+ */
+
+
+/** @def CCARRAY_FOREACH
+ A convience macro to iterate over a CCArray using. It is faster than the "fast enumeration" interface.
+ @since v0.99.4
+ */
+
+#define CCARRAY_FOREACH(__array__, __object__) \
+if (__array__ && __array__->data->num > 0) \
+for(id *arr = __array__->data->arr, *end = __array__->data->arr + __array__->data->num-1; \
+ arr <= end && ((__object__ = *arr) != nil || true); \
+ arr++)
+
+@interface CCArray : NSObject <NSFastEnumeration, NSCoding, NSCopying>
+{
+ @public ccArray *data;
+}
+
++ (id) array;
++ (id) arrayWithCapacity:(NSUInteger)capacity;
++ (id) arrayWithArray:(CCArray*)otherArray;
++ (id) arrayWithNSArray:(NSArray*)otherArray;
+
+
+- (id) initWithCapacity:(NSUInteger)capacity;
+- (id) initWithArray:(CCArray*)otherArray;
+- (id) initWithNSArray:(NSArray*)otherArray;
+
+
+- (NSUInteger) count;
+- (NSUInteger) capacity;
+- (NSUInteger) indexOfObject:(id)object;
+- (id) objectAtIndex:(NSUInteger)index;
+- (id) lastObject;
+- (id) randomObject;
+- (BOOL) containsObject:(id)object;
+
+#pragma mark Adding Objects
+
+- (void) addObject:(id)object;
+- (void) addObjectsFromArray:(CCArray*)otherArray;
+- (void) addObjectsFromNSArray:(NSArray*)otherArray;
+- (void) insertObject:(id)object atIndex:(NSUInteger)index;
+
+#pragma mark Removing Objects
+
+- (void) removeLastObject;
+- (void) removeObject:(id)object;
+- (void) removeObjectAtIndex:(NSUInteger)index;
+- (void) removeObjectsInArray:(CCArray*)otherArray;
+- (void) removeAllObjects;
+- (void) fastRemoveObject:(id)object;
+- (void) fastRemoveObjectAtIndex:(NSUInteger)index;
+
+- (void) makeObjectsPerformSelector:(SEL)aSelector;
+- (void) makeObjectsPerformSelector:(SEL)aSelector withObject:(id)object;
+
+- (NSArray*) getNSArray;
+
+@end
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * Copyright (c) 2010 Abstraction Works. http://www.abstractionworks.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 "CCArray.h"
+#import "../ccMacros.h"
+
+
+@implementation CCArray
+
++ (id) array
+{
+ return [[[self alloc] init] autorelease];
+}
+
++ (id) arrayWithCapacity:(NSUInteger)capacity
+{
+ return [[[self alloc] initWithCapacity:capacity] autorelease];
+}
+
++ (id) arrayWithArray:(CCArray*)otherArray
+{
+ return [[(CCArray*)[self alloc] initWithArray:otherArray] autorelease];
+}
+
++ (id) arrayWithNSArray:(NSArray*)otherArray
+{
+ return [[(CCArray*)[self alloc] initWithNSArray:otherArray] autorelease];
+}
+
+- (id) init
+{
+ self = [self initWithCapacity:2];
+ return self;
+}
+
+- (id) initWithCapacity:(NSUInteger)capacity
+{
+ self = [super init];
+ if (self != nil) {
+ data = ccArrayNew(capacity);
+ }
+ return self;
+}
+
+- (id) initWithArray:(CCArray*)otherArray
+{
+ self = [self initWithCapacity:otherArray->data->num];
+ if (self != nil) {
+ [self addObjectsFromArray:otherArray];
+ }
+ return self;
+}
+
+- (id) initWithNSArray:(NSArray*)otherArray
+{
+ self = [self initWithCapacity:otherArray.count];
+ if (self != nil) {
+ [self addObjectsFromNSArray:otherArray];
+ }
+ return self;
+}
+
+
+
+- (id) initWithCoder:(NSCoder*)coder
+{
+ self = [self initWithNSArray:[coder decodeObjectForKey:@"nsarray"]];
+ return self;
+}
+- (void)encodeWithCoder:(NSCoder *)coder
+{
+ [coder encodeObject:[self getNSArray] forKey:@"nsarray"];
+}
+
+
+
+- (NSUInteger) count
+{
+ return data->num;
+}
+
+- (NSUInteger) capacity
+{
+ return data->max;
+}
+
+- (NSUInteger) indexOfObject:(id)object
+{
+ return ccArrayGetIndexOfObject(data, object);
+}
+
+- (id) objectAtIndex:(NSUInteger)index
+{
+ if( index >= data->num )
+ [NSException raise:NSRangeException
+ format: @"index out of range in objectAtIndex(%d)", data->num ];
+
+ return data->arr[index];
+}
+
+- (id) lastObject
+{
+ if( data->num > 0 )
+ return data->arr[data->num-1];
+ return nil;
+}
+
+- (id) randomObject
+{
+ if(data->num==0) return nil;
+ return data->arr[(int)(data->num*CCRANDOM_0_1())];
+}
+
+- (BOOL) containsObject:(id)object
+{
+ return ccArrayContainsObject(data, object);
+}
+
+#pragma mark Adding Objects
+
+- (void) addObject:(id)object
+{
+ ccArrayAppendObjectWithResize(data, object);
+}
+
+- (void) addObjectsFromArray:(CCArray*)otherArray
+{
+ ccArrayAppendArrayWithResize(data, otherArray->data);
+}
+
+- (void) addObjectsFromNSArray:(NSArray*)otherArray
+{
+ ccArrayEnsureExtraCapacity(data, otherArray.count);
+ for(id object in otherArray)
+ ccArrayAppendObject(data, object);
+}
+
+- (void) insertObject:(id)object atIndex:(NSUInteger)index
+{
+ ccArrayInsertObjectAtIndex(data, object, index);
+}
+
+#pragma mark Removing Objects
+
+
+- (void) removeLastObject
+{
+ if( data->num == 0 )
+ [NSException raise:NSRangeException
+ format: @"no objects added"];
+ ccArrayRemoveObjectAtIndex(data, data->num-1);
+}
+
+- (void) removeObject:(id)object
+{
+ ccArrayRemoveObject(data, object);
+}
+
+- (void) removeObjectAtIndex:(NSUInteger)index
+{
+ ccArrayRemoveObjectAtIndex(data, index);
+}
+
+- (void) removeObjectsInArray:(CCArray*)otherArray
+{
+ ccArrayRemoveArray(data, otherArray->data);
+}
+
+- (void) removeAllObjects
+{
+ ccArrayRemoveAllObjects(data);
+}
+
+- (void) fastRemoveObjectAtIndex:(NSUInteger)index
+{
+ ccArrayFastRemoveObjectAtIndex(data, index);
+}
+
+- (void) fastRemoveObject:(id)object
+{
+ ccArrayFastRemoveObject(data, object);
+}
+
+- (void) makeObjectsPerformSelector:(SEL)aSelector
+{
+ ccArrayMakeObjectsPerformSelector(data, aSelector);
+}
+
+- (void) makeObjectsPerformSelector:(SEL)aSelector withObject:(id)object
+{
+ ccArrayMakeObjectsPerformSelectorWithObject(data, aSelector, object);
+}
+
+- (NSArray*) getNSArray
+{
+ return [NSArray arrayWithObjects:data->arr count:data->num];
+}
+
+- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len
+{
+ if(state->state == 1) return 0;
+
+ state->mutationsPtr = (unsigned long *)self;
+ state->itemsPtr = &data->arr[0];
+ state->state = 1;
+ return data->num;
+}
+
+- (void) dealloc
+{
+ ccArrayFree(data);
+ [super dealloc];
+}
+
+#pragma mark CCArray - NSCopying protocol
+
+- (id)copyWithZone:(NSZone *)zone
+{
+ NSArray *nsArray = [self getNSArray];
+ CCArray *newArray = [[[self class] allocWithZone:zone] initWithNSArray:nsArray];
+ return newArray;
+}
+
+@end
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+
+
+/** Helper class to handle file operations */
+@interface CCFileUtils : NSObject
+{
+}
+
+/** Returns the fullpath of an filename.
+
+ If this method is when Retina Display is enabled, then the
+ Retina Display suffix will be appended to the file (See ccConfig.h).
+
+ If the Retina Display image doesn't exist, then it will return the "non-Retina Display" image
+
+ */
++(NSString*) fullPathFromRelativePath:(NSString*) relPath;
+@end
+
+/** loads a file into memory.
+ the caller should release the allocated buffer.
+
+ @returns the size of the allocated buffer
+ @since v0.99.5
+ */
+int ccLoadFileIntoMemory(const char *filename, unsigned char **out);
+
+
+/** removes the HD suffix from a path
+
+ @returns NSString * without the HD suffix
+ @since v0.99.5
+ */
+NSString *ccRemoveHDSuffixFromFile( NSString *path );
+
--- /dev/null
+/*
+ * 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 <Availability.h>
+#import "CCFileUtils.h"
+#import "../CCConfiguration.h"
+#import "../ccMacros.h"
+#import "../ccConfig.h"
+
+static NSFileManager *__localFileManager=nil;
+
+//
+int ccLoadFileIntoMemory(const char *filename, unsigned char **out)
+{
+ assert( out );
+ assert( &*out );
+
+ int size = 0;
+ FILE *f = fopen(filename, "rb");
+ if( !f ) {
+ *out = NULL;
+ return -1;
+ }
+
+ fseek(f, 0, SEEK_END);
+ size = ftell(f);
+ fseek(f, 0, SEEK_SET);
+
+ *out = malloc(size);
+ int read = fread(*out, 1, size, f);
+ if( read != size ) {
+ free(*out);
+ *out = NULL;
+ return -1;
+ }
+
+ fclose(f);
+
+ return size;
+}
+
+NSString *ccRemoveHDSuffixFromFile( NSString *path )
+{
+#if CC_IS_RETINA_DISPLAY_SUPPORTED
+
+ if( CC_CONTENT_SCALE_FACTOR() == 2 ) {
+
+ NSString *name = [path lastPathComponent];
+
+ // check if path already has the suffix.
+ if( [name rangeOfString:CC_RETINA_DISPLAY_FILENAME_SUFFIX].location != NSNotFound ) {
+
+ CCLOG(@"cocos2d: Filename(%@) contains %@ suffix. Removing it. See cocos2d issue #1040", path, CC_RETINA_DISPLAY_FILENAME_SUFFIX);
+
+ NSString *newLastname = [name stringByReplacingOccurrencesOfString:CC_RETINA_DISPLAY_FILENAME_SUFFIX withString:@""];
+
+ NSString *pathWithoutLastname = [path stringByDeletingLastPathComponent];
+ return [pathWithoutLastname stringByAppendingPathComponent:newLastname];
+ }
+ }
+
+#endif // CC_IS_RETINA_DISPLAY_SUPPORTED
+
+ return path;
+
+}
+
+
+@implementation CCFileUtils
+
++(void) initialize
+{
+ if( self == [CCFileUtils class] )
+ __localFileManager = [[NSFileManager alloc] init];
+}
+
++(NSString*) getDoubleResolutionImage:(NSString*)path
+{
+#if CC_IS_RETINA_DISPLAY_SUPPORTED
+
+ if( CC_CONTENT_SCALE_FACTOR() == 2 )
+ {
+
+ NSString *pathWithoutExtension = [path stringByDeletingPathExtension];
+ NSString *name = [pathWithoutExtension lastPathComponent];
+
+ // check if path already has the suffix.
+ if( [name rangeOfString:CC_RETINA_DISPLAY_FILENAME_SUFFIX].location != NSNotFound ) {
+
+ CCLOG(@"cocos2d: WARNING Filename(%@) already has the suffix %@. Using it.", name, CC_RETINA_DISPLAY_FILENAME_SUFFIX);
+ return path;
+ }
+
+
+ NSString *extension = [path pathExtension];
+
+ if( [extension isEqualToString:@"ccz"] || [extension isEqualToString:@"gz"] )
+ {
+ // All ccz / gz files should be in the format filename.xxx.ccz
+ // so we need to pull off the .xxx part of the extension as well
+ extension = [NSString stringWithFormat:@"%@.%@", [pathWithoutExtension pathExtension], extension];
+ pathWithoutExtension = [pathWithoutExtension stringByDeletingPathExtension];
+ }
+
+
+ NSString *retinaName = [pathWithoutExtension stringByAppendingString:CC_RETINA_DISPLAY_FILENAME_SUFFIX];
+ retinaName = [retinaName stringByAppendingPathExtension:extension];
+
+ if( [__localFileManager fileExistsAtPath:retinaName] )
+ return retinaName;
+
+ CCLOG(@"cocos2d: CCFileUtils: Warning HD file not found: %@", [retinaName lastPathComponent] );
+ }
+
+#endif // CC_IS_RETINA_DISPLAY_SUPPORTED
+
+ return path;
+}
+
++(NSString*) fullPathFromRelativePath:(NSString*) relPath
+{
+ NSAssert(relPath != nil, @"CCFileUtils: Invalid path");
+
+ NSString *fullpath = nil;
+
+ // only if it is not an absolute path
+ if( ! [relPath isAbsolutePath] )
+ {
+ NSString *file = [relPath lastPathComponent];
+ NSString *imageDirectory = [relPath stringByDeletingLastPathComponent];
+
+ fullpath = [[NSBundle mainBundle] pathForResource:file
+ ofType:nil
+ inDirectory:imageDirectory];
+ }
+
+ if (fullpath == nil)
+ fullpath = relPath;
+
+ fullpath = [self getDoubleResolutionImage:fullpath];
+
+ return fullpath;
+}
+
+@end
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+#import <sys/time.h>
+
+@class CCProfilingTimer;
+
+@interface CCProfiler : NSObject {
+ NSMutableArray* activeTimers;
+}
+
++ (CCProfiler*)sharedProfiler;
++ (CCProfilingTimer*)timerWithName:(NSString*)timerName andInstance:(id)instance;
++ (void)releaseTimer:(CCProfilingTimer*)timer;
+- (void)displayTimers;
+
+@end
+
+
+@interface CCProfilingTimer : NSObject {
+ NSString* name;
+ struct timeval startTime;
+ double averageTime;
+}
+
+@end
+
+extern void CCProfilingBeginTimingBlock(CCProfilingTimer* timer);
+extern void CCProfilingEndTimingBlock(CCProfilingTimer* timer);
--- /dev/null
+/*
+ * 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 "../ccConfig.h"
+
+#if CC_ENABLE_PROFILERS
+
+#import "CCProfiling.h"
+
+@interface CCProfilingTimer()
+- (id)initWithName:(NSString*)timerName andInstance:(id)instance;
+@end
+
+@implementation CCProfiler
+
+static CCProfiler* g_sharedProfiler;
+
++ (CCProfiler*)sharedProfiler {
+ if (!g_sharedProfiler)
+ g_sharedProfiler = [[CCProfiler alloc] init];
+
+ return g_sharedProfiler;
+}
+
++ (CCProfilingTimer*)timerWithName:(NSString*)timerName andInstance:(id)instance {
+ CCProfiler* p = [CCProfiler sharedProfiler];
+ CCProfilingTimer* t = [[CCProfilingTimer alloc] initWithName:timerName andInstance:instance];
+ [p->activeTimers addObject:t];
+ [t release];
+ return t;
+}
+
++ (void)releaseTimer:(CCProfilingTimer*)timer {
+ CCProfiler* p = [CCProfiler sharedProfiler];
+ [p->activeTimers removeObject:timer];
+}
+
+- (id)init {
+ if (!(self = [super init])) return nil;
+
+ activeTimers = [[NSMutableArray alloc] init];
+
+ return self;
+}
+
+- (void)dealloc {
+ [activeTimers release];
+ [super dealloc];
+}
+
+- (void)displayTimers {
+ for (id timer in activeTimers) {
+ printf("%s\n", [[timer description] cStringUsingEncoding:[NSString defaultCStringEncoding]]);
+ }
+}
+
+@end
+
+@implementation CCProfilingTimer
+
+- (id)initWithName:(NSString*)timerName andInstance:(id)instance {
+ if (!(self = [super init])) return nil;
+
+ name = [[NSString stringWithFormat:@"%@ (0x%.8x)", timerName, instance] retain];
+
+ return self;
+}
+
+- (void)dealloc {
+ [name release];
+ [super dealloc];
+}
+
+- (NSString*)description {
+ return [NSString stringWithFormat:@"%@ : avg time, %fms", name, averageTime];
+}
+
+void CCProfilingBeginTimingBlock(CCProfilingTimer* timer) {
+ gettimeofday(&timer->startTime, NULL);
+}
+
+typedef unsigned int uint32;
+void CCProfilingEndTimingBlock(CCProfilingTimer* timer) {
+ struct timeval currentTime;
+ gettimeofday(¤tTime, NULL);
+ timersub(¤tTime, &timer->startTime, ¤tTime);
+ double duration = currentTime.tv_sec * 1000.0 + currentTime.tv_usec / 1000.0;
+
+ // return in milliseconds
+ timer->averageTime = (timer->averageTime + duration) / 2.0f;
+}
+
+@end
+
+#endif
--- /dev/null
+/* cocos2d for iPhone
+ * http://www.cocos2d-iphone.org
+ *
+ * Copyright (c) 2007 Scott Lembcke
+ * 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.
+ */
+
+/*
+ * Some of the functions were based on Chipmunk's cpVect.h.
+ */
+
+/**
+ @file
+ CGPoint extensions based on Chipmunk's cpVect file.
+ These extensions work both with CGPoint and cpVect.
+
+ The "ccp" prefix means: "CoCos2d Point"
+
+ Examples:
+ - ccpAdd( ccp(1,1), ccp(2,2) ); // preferred cocos2d way
+ - ccpAdd( CGPointMake(1,1), CGPointMake(2,2) ); // also ok but more verbose
+
+ - cpvadd( cpv(1,1), cpv(2,2) ); // way of the chipmunk
+ - ccpAdd( cpv(1,1), cpv(2,2) ); // mixing chipmunk and cocos2d (avoid)
+ - cpvadd( CGPointMake(1,1), CGPointMake(2,2) ); // mixing chipmunk and CG (avoid)
+ */
+
+#import <Availability.h>
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#import <CoreGraphics/CGGeometry.h>
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+#import <Foundation/Foundation.h>
+#endif
+
+#import <math.h>
+#import <objc/objc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Helper macro that creates a CGPoint
+ @return CGPoint
+ @since v0.7.2
+ */
+#define ccp(__X__,__Y__) CGPointMake(__X__,__Y__)
+
+
+/** Returns opposite of point.
+ @return CGPoint
+ @since v0.7.2
+ */
+static inline CGPoint
+ccpNeg(const CGPoint v)
+{
+ return ccp(-v.x, -v.y);
+}
+
+/** Calculates sum of two points.
+ @return CGPoint
+ @since v0.7.2
+ */
+static inline CGPoint
+ccpAdd(const CGPoint v1, const CGPoint v2)
+{
+ return ccp(v1.x + v2.x, v1.y + v2.y);
+}
+
+/** Calculates difference of two points.
+ @return CGPoint
+ @since v0.7.2
+ */
+static inline CGPoint
+ccpSub(const CGPoint v1, const CGPoint v2)
+{
+ return ccp(v1.x - v2.x, v1.y - v2.y);
+}
+
+/** Returns point multiplied by given factor.
+ @return CGPoint
+ @since v0.7.2
+ */
+static inline CGPoint
+ccpMult(const CGPoint v, const CGFloat s)
+{
+ return ccp(v.x*s, v.y*s);
+}
+
+/** Calculates midpoint between two points.
+ @return CGPoint
+ @since v0.7.2
+ */
+static inline CGPoint
+ccpMidpoint(const CGPoint v1, const CGPoint v2)
+{
+ return ccpMult(ccpAdd(v1, v2), 0.5f);
+}
+
+/** Calculates dot product of two points.
+ @return CGFloat
+ @since v0.7.2
+ */
+static inline CGFloat
+ccpDot(const CGPoint v1, const CGPoint v2)
+{
+ return v1.x*v2.x + v1.y*v2.y;
+}
+
+/** Calculates cross product of two points.
+ @return CGFloat
+ @since v0.7.2
+ */
+static inline CGFloat
+ccpCross(const CGPoint v1, const CGPoint v2)
+{
+ return v1.x*v2.y - v1.y*v2.x;
+}
+
+/** Calculates perpendicular of v, rotated 90 degrees counter-clockwise -- cross(v, perp(v)) >= 0
+ @return CGPoint
+ @since v0.7.2
+ */
+static inline CGPoint
+ccpPerp(const CGPoint v)
+{
+ return ccp(-v.y, v.x);
+}
+
+/** Calculates perpendicular of v, rotated 90 degrees clockwise -- cross(v, rperp(v)) <= 0
+ @return CGPoint
+ @since v0.7.2
+ */
+static inline CGPoint
+ccpRPerp(const CGPoint v)
+{
+ return ccp(v.y, -v.x);
+}
+
+/** Calculates the projection of v1 over v2.
+ @return CGPoint
+ @since v0.7.2
+ */
+static inline CGPoint
+ccpProject(const CGPoint v1, const CGPoint v2)
+{
+ return ccpMult(v2, ccpDot(v1, v2)/ccpDot(v2, v2));
+}
+
+/** Rotates two points.
+ @return CGPoint
+ @since v0.7.2
+ */
+static inline CGPoint
+ccpRotate(const CGPoint v1, const CGPoint v2)
+{
+ return ccp(v1.x*v2.x - v1.y*v2.y, v1.x*v2.y + v1.y*v2.x);
+}
+
+/** Unrotates two points.
+ @return CGPoint
+ @since v0.7.2
+ */
+static inline CGPoint
+ccpUnrotate(const CGPoint v1, const CGPoint v2)
+{
+ return ccp(v1.x*v2.x + v1.y*v2.y, v1.y*v2.x - v1.x*v2.y);
+}
+
+/** Calculates the square length of a CGPoint (not calling sqrt() )
+ @return CGFloat
+ @since v0.7.2
+ */
+static inline CGFloat
+ccpLengthSQ(const CGPoint v)
+{
+ return ccpDot(v, v);
+}
+
+/** Calculates distance between point an origin
+ @return CGFloat
+ @since v0.7.2
+ */
+CGFloat ccpLength(const CGPoint v);
+
+/** Calculates the distance between two points
+ @return CGFloat
+ @since v0.7.2
+ */
+CGFloat ccpDistance(const CGPoint v1, const CGPoint v2);
+
+/** Returns point multiplied to a length of 1.
+ @return CGPoint
+ @since v0.7.2
+ */
+CGPoint ccpNormalize(const CGPoint v);
+
+/** Converts radians to a normalized vector.
+ @return CGPoint
+ @since v0.7.2
+ */
+CGPoint ccpForAngle(const CGFloat a);
+
+/** Converts a vector to radians.
+ @return CGFloat
+ @since v0.7.2
+ */
+CGFloat ccpToAngle(const CGPoint v);
+
+
+/** Clamp a value between from and to.
+ @since v0.99.1
+ */
+float clampf(float value, float min_inclusive, float max_inclusive);
+
+/** Clamp a point between from and to.
+ @since v0.99.1
+ */
+CGPoint ccpClamp(CGPoint p, CGPoint from, CGPoint to);
+
+/** Quickly convert CGSize to a CGPoint
+ @since v0.99.1
+ */
+CGPoint ccpFromSize(CGSize s);
+
+/** Run a math operation function on each point component
+ * absf, fllorf, ceilf, roundf
+ * any function that has the signature: float func(float);
+ * For example: let's try to take the floor of x,y
+ * ccpCompOp(p,floorf);
+ @since v0.99.1
+ */
+CGPoint ccpCompOp(CGPoint p, float (*opFunc)(float));
+
+/** Linear Interpolation between two points a and b
+ @returns
+ alpha == 0 ? a
+ alpha == 1 ? b
+ otherwise a value between a..b
+ @since v0.99.1
+ */
+CGPoint ccpLerp(CGPoint a, CGPoint b, float alpha);
+
+
+/** @returns if points have fuzzy equality which means equal with some degree of variance.
+ @since v0.99.1
+ */
+BOOL ccpFuzzyEqual(CGPoint a, CGPoint b, float variance);
+
+
+/** Multiplies a nd b components, a.x*b.x, a.y*b.y
+ @returns a component-wise multiplication
+ @since v0.99.1
+ */
+CGPoint ccpCompMult(CGPoint a, CGPoint b);
+
+/** @returns the signed angle in radians between two vector directions
+ @since v0.99.1
+ */
+float ccpAngleSigned(CGPoint a, CGPoint b);
+
+/** @returns the angle in radians between two vector directions
+ @since v0.99.1
+*/
+float ccpAngle(CGPoint a, CGPoint b);
+
+/** Rotates a point counter clockwise by the angle around a pivot
+ @param v is the point to rotate
+ @param pivot is the pivot, naturally
+ @param angle is the angle of rotation cw in radians
+ @returns the rotated point
+ @since v0.99.1
+ */
+CGPoint ccpRotateByAngle(CGPoint v, CGPoint pivot, float angle);
+
+/** A general line-line intersection test
+ @param p1
+ is the startpoint for the first line P1 = (p1 - p2)
+ @param p2
+ is the endpoint for the first line P1 = (p1 - p2)
+ @param p3
+ is the startpoint for the second line P2 = (p3 - p4)
+ @param p4
+ is the endpoint for the second line P2 = (p3 - p4)
+ @param s
+ is the range for a hitpoint in P1 (pa = p1 + s*(p2 - p1))
+ @param t
+ is the range for a hitpoint in P3 (pa = p2 + t*(p4 - p3))
+ @return bool
+ indicating successful intersection of a line
+ note that to truly test intersection for segments we have to make
+ sure that s & t lie within [0..1] and for rays, make sure s & t > 0
+ the hit point is p3 + t * (p4 - p3);
+ the hit point also is p1 + s * (p2 - p1);
+ @since v0.99.1
+ */
+BOOL ccpLineIntersect(CGPoint p1, CGPoint p2,
+ CGPoint p3, CGPoint p4,
+ float *s, float *t);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* cocos2d for iPhone
+ * http://www.cocos2d-iphone.org
+ *
+ * Copyright (c) 2007 Scott Lembcke
+ * 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.
+ */
+
+#include "stdio.h"
+#include "math.h"
+
+#import "../ccMacros.h" // CC_SWAP
+#include "CGPointExtension.h"
+
+#define kCGPointEpsilon FLT_EPSILON
+
+CGFloat
+ccpLength(const CGPoint v)
+{
+ return sqrtf(ccpLengthSQ(v));
+}
+
+CGFloat
+ccpDistance(const CGPoint v1, const CGPoint v2)
+{
+ return ccpLength(ccpSub(v1, v2));
+}
+
+CGPoint
+ccpNormalize(const CGPoint v)
+{
+ return ccpMult(v, 1.0f/ccpLength(v));
+}
+
+CGPoint
+ccpForAngle(const CGFloat a)
+{
+ return ccp(cosf(a), sinf(a));
+}
+
+CGFloat
+ccpToAngle(const CGPoint v)
+{
+ return atan2f(v.y, v.x);
+}
+
+CGPoint ccpLerp(CGPoint a, CGPoint b, float alpha)
+{
+ return ccpAdd(ccpMult(a, 1.f - alpha), ccpMult(b, alpha));
+}
+
+float clampf(float value, float min_inclusive, float max_inclusive)
+{
+ if (min_inclusive > max_inclusive) {
+ CC_SWAP(min_inclusive,max_inclusive);
+ }
+ return value < min_inclusive ? min_inclusive : value < max_inclusive? value : max_inclusive;
+}
+
+CGPoint ccpClamp(CGPoint p, CGPoint min_inclusive, CGPoint max_inclusive)
+{
+ return ccp(clampf(p.x,min_inclusive.x,max_inclusive.x), clampf(p.y, min_inclusive.y, max_inclusive.y));
+}
+
+CGPoint ccpFromSize(CGSize s)
+{
+ return ccp(s.width, s.height);
+}
+
+CGPoint ccpCompOp(CGPoint p, float (*opFunc)(float)){
+ return ccp(opFunc(p.x), opFunc(p.y));
+}
+
+BOOL ccpFuzzyEqual(CGPoint a, CGPoint b, float var)
+{
+ if(a.x - var <= b.x && b.x <= a.x + var)
+ if(a.y - var <= b.y && b.y <= a.y + var)
+ return true;
+ return false;
+}
+
+CGPoint ccpCompMult(CGPoint a, CGPoint b)
+{
+ return ccp(a.x * b.x, a.y * b.y);
+}
+
+float ccpAngleSigned(CGPoint a, CGPoint b)
+{
+ CGPoint a2 = ccpNormalize(a); CGPoint b2 = ccpNormalize(b);
+ float angle = atan2f(a2.x * b2.y - a2.y * b2.x, ccpDot(a2, b2));
+ if( fabs(angle) < kCGPointEpsilon ) return 0.f;
+ return angle;
+}
+
+CGPoint ccpRotateByAngle(CGPoint v, CGPoint pivot, float angle) {
+ CGPoint r = ccpSub(v, pivot);
+ float t = r.x;
+ float cosa = cosf(angle), sina = sinf(angle);
+ r.x = t*cosa - r.y*sina;
+ r.y = t*sina + r.y*cosa;
+ r = ccpAdd(r, pivot);
+ return r;
+}
+
+BOOL ccpLineIntersect(CGPoint p1, CGPoint p2,
+ CGPoint p3, CGPoint p4,
+ float *s, float *t){
+ CGPoint p13, p43, p21;
+ float d1343, d4321, d1321, d4343, d2121;
+ float numer, denom;
+
+ p13 = ccpSub(p1, p3);
+
+ p43 = ccpSub(p4, p3);
+
+ //Roughly equal to zero but with an epsilon deviation for float
+ //correction
+ if (ccpFuzzyEqual(p43, CGPointZero, kCGPointEpsilon))
+ return false;
+
+ p21 = ccpSub(p2, p1);
+
+ //Roughly equal to zero
+ if (ccpFuzzyEqual(p21,CGPointZero, kCGPointEpsilon))
+ return false;
+
+ d1343 = ccpDot(p13, p43);
+ d4321 = ccpDot(p43, p21);
+ d1321 = ccpDot(p13, p21);
+ d4343 = ccpDot(p43, p43);
+ d2121 = ccpDot(p21, p21);
+
+ denom = d2121 * d4343 - d4321 * d4321;
+ if (fabs(denom) < kCGPointEpsilon)
+ return false;
+ numer = d1343 * d4321 - d1321 * d4343;
+
+ *s = numer / denom;
+ *t = (d1343 + d4321 *(*s)) / d4343;
+
+ return true;
+}
+
+float ccpAngle(CGPoint a, CGPoint b)
+{
+ float angle = acosf(ccpDot(ccpNormalize(a), ccpNormalize(b)));
+ if( fabs(angle) < kCGPointEpsilon ) return 0.f;
+ return angle;
+}
+
--- /dev/null
+/*
+
+===== IMPORTANT =====
+
+This is sample code demonstrating API, technology or techniques in development.
+Although this sample code has been reviewed for technical accuracy, it is not
+final. Apple is supplying this information to help you plan for the adoption of
+the technologies and programming interfaces described herein. This information
+is subject to change, and software implemented based on this sample code should
+be tested with final operating system software and final documentation. Newer
+versions of this sample code may be provided with future seeds of the API or
+technology. For information about updates to this and other developer
+documentation, view the New & Updated sidebars in subsequent documentation
+seeds.
+
+=====================
+
+File: OpenGL_Internal.h
+Abstract: This file is included for support purposes and isn't necessary for
+understanding this sample.
+
+Version: 1.0
+
+Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
+("Apple") in consideration of your agreement to the following terms, and your
+use, installation, modification or redistribution of this Apple software
+constitutes acceptance of these terms. If you do not agree with these terms,
+please do not use, install, modify or redistribute this Apple software.
+
+In consideration of your agreement to abide by the following terms, and subject
+to these terms, Apple grants you a personal, non-exclusive license, under
+Apple's copyrights in this original Apple software (the "Apple Software"), to
+use, reproduce, modify and redistribute the Apple Software, with or without
+modifications, in source and/or binary forms; provided that if you redistribute
+the Apple Software in its entirety and without modifications, you must retain
+this notice and the following text and disclaimers in all such redistributions
+of the Apple Software.
+Neither the name, trademarks, service marks or logos of Apple Inc. may be used
+to endorse or promote products derived from the Apple Software without specific
+prior written permission from Apple. Except as expressly stated in this notice,
+no other rights or licenses, express or implied, are granted by Apple herein,
+including but not limited to any patent rights that may be infringed by your
+derivative works or by other works in which the Apple Software may be
+incorporated.
+
+The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
+DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
+CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Copyright (C) 2008 Apple Inc. All Rights Reserved.
+
+*/
+
+/* Generic error reporting */
+#define REPORT_ERROR(__FORMAT__, ...) printf("%s: %s\n", __FUNCTION__, [[NSString stringWithFormat:__FORMAT__, __VA_ARGS__] UTF8String])
+
+/* EAGL and GL functions calling wrappers that log on error */
+#define CALL_EAGL_FUNCTION(__FUNC__, ...) ({ EAGLError __error = __FUNC__( __VA_ARGS__ ); if(__error != kEAGLErrorSuccess) printf("%s() called from %s returned error %i\n", #__FUNC__, __FUNCTION__, __error); (__error ? NO : YES); })
+//#define CHECK_GL_ERROR() ({ GLenum __error = glGetError(); if(__error) printf("OpenGL error 0x%04X in %s\n", __error, __FUNCTION__); (__error ? NO : YES); })
+#define CHECK_GL_ERROR() ({ GLenum __error = glGetError(); if(__error) printf("OpenGL error 0x%04X in %s\n", __error, __FUNCTION__); })
+
+/* Optional delegate methods support */
+#ifndef __DELEGATE_IVAR__
+#define __DELEGATE_IVAR__ _delegate
+#endif
+#ifndef __DELEGATE_METHODS_IVAR__
+#define __DELEGATE_METHODS_IVAR__ _delegateMethods
+#endif
+#define TEST_DELEGATE_METHOD_BIT(__BIT__) (self->__DELEGATE_METHODS_IVAR__ & (1 << __BIT__))
+#define SET_DELEGATE_METHOD_BIT(__BIT__, __NAME__) { if([self->__DELEGATE_IVAR__ respondsToSelector:@selector(__NAME__)]) self->__DELEGATE_METHODS_IVAR__ |= (1 << __BIT__); else self->__DELEGATE_METHODS_IVAR__ &= ~(1 << __BIT__); }
--- /dev/null
+//
+// TGA lib for cocos2d-iphone
+//
+// sources from: http://www.lighthouse3d.com/opengl/terrain/index.php3?tgasource
+//
+
+//#ifndef TGA_LIB
+//#define TGA_LIB
+
+/**
+ @file
+ TGA image support
+ */
+
+enum {
+ TGA_OK,
+ TGA_ERROR_FILE_OPEN,
+ TGA_ERROR_READING_FILE,
+ TGA_ERROR_INDEXED_COLOR,
+ TGA_ERROR_MEMORY,
+ TGA_ERROR_COMPRESSED_FILE,
+};
+
+/** TGA format */
+typedef struct sImageTGA {
+ int status;
+ unsigned char type, pixelDepth;
+
+ /** map width */
+ short int width;
+
+ /** map height */
+ short int height;
+
+ /** raw data */
+ unsigned char *imageData;
+ int flipped;
+} tImageTGA;
+
+/// load the image header fields. We only keep those that matter!
+void tgaLoadHeader(FILE *file, tImageTGA *info);
+
+/// loads the image pixels. You shouldn't call this function directly
+void tgaLoadImageData(FILE *file, tImageTGA *info);
+
+/// this is the function to call when we want to load an image
+tImageTGA * tgaLoad(const char *filename);
+
+// /converts RGB to greyscale
+void tgaRGBtogreyscale(tImageTGA *info);
+
+/// releases the memory used for the image
+void tgaDestroy(tImageTGA *info);
+
+//#endif // TGA_LIB
--- /dev/null
+//
+// TGA lib for cocos2d-iphone
+//
+// sources from: http://www.lighthouse3d.com/opengl/terrain/index.php3?tgasource
+//
+// TGA RLE compression support by Ernesto Corvi
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#import "TGAlib.h"
+
+
+// load the image header fields. We only keep those that matter!
+void tgaLoadHeader(FILE *file, tImageTGA *info) {
+ unsigned char cGarbage;
+ short int iGarbage;
+
+ fread(&cGarbage, sizeof(unsigned char), 1, file);
+ fread(&cGarbage, sizeof(unsigned char), 1, file);
+
+ // type must be 2 or 3
+ fread(&info->type, sizeof(unsigned char), 1, file);
+
+ fread(&iGarbage, sizeof(short int), 1, file);
+ fread(&iGarbage, sizeof(short int), 1, file);
+ fread(&cGarbage, sizeof(unsigned char), 1, file);
+ fread(&iGarbage, sizeof(short int), 1, file);
+ fread(&iGarbage, sizeof(short int), 1, file);
+
+ fread(&info->width, sizeof(short int), 1, file);
+ fread(&info->height, sizeof(short int), 1, file);
+ fread(&info->pixelDepth, sizeof(unsigned char), 1, file);
+
+ fread(&cGarbage, sizeof(unsigned char), 1, file);
+
+ info->flipped = 0;
+ if ( cGarbage & 0x20 ) info->flipped = 1;
+}
+
+// loads the image pixels. You shouldn't call this function directly
+void tgaLoadImageData(FILE *file, tImageTGA *info) {
+
+ int mode,total,i;
+ unsigned char aux;
+
+ // mode equal the number of components for each pixel
+ mode = info->pixelDepth / 8;
+ // total is the number of unsigned chars we'll have to read
+ total = info->height * info->width * mode;
+
+ fread(info->imageData,sizeof(unsigned char),total,file);
+
+ // mode=3 or 4 implies that the image is RGB(A). However TGA
+ // stores it as BGR(A) so we'll have to swap R and B.
+ if (mode >= 3)
+ for (i=0; i < total; i+= mode) {
+ aux = info->imageData[i];
+ info->imageData[i] = info->imageData[i+2];
+ info->imageData[i+2] = aux;
+ }
+}
+
+// loads the RLE encoded image pixels. You shouldn't call this function directly
+void tgaLoadRLEImageData(FILE *file, tImageTGA *info)
+{
+ unsigned int mode,total,i, index = 0;
+ unsigned char aux[4], runlength = 0;
+ unsigned int skip = 0, flag = 0;
+
+ // mode equal the number of components for each pixel
+ mode = info->pixelDepth / 8;
+ // total is the number of unsigned chars we'll have to read
+ total = info->height * info->width;
+
+ for( i = 0; i < total; i++ )
+ {
+ // if we have a run length pending, run it
+ if ( runlength != 0 )
+ {
+ // we do, update the run length count
+ runlength--;
+ skip = (flag != 0);
+ }
+ else
+ {
+ // otherwise, read in the run length token
+ if ( fread(&runlength,sizeof(unsigned char),1,file) != 1 )
+ return;
+
+ // see if it's a RLE encoded sequence
+ flag = runlength & 0x80;
+ if ( flag ) runlength -= 128;
+ skip = 0;
+ }
+
+ // do we need to skip reading this pixel?
+ if ( !skip )
+ {
+ // no, read in the pixel data
+ if ( fread(aux,sizeof(unsigned char),mode,file) != mode )
+ return;
+
+ // mode=3 or 4 implies that the image is RGB(A). However TGA
+ // stores it as BGR(A) so we'll have to swap R and B.
+ if ( mode >= 3 )
+ {
+ unsigned char tmp;
+
+ tmp = aux[0];
+ aux[0] = aux[2];
+ aux[2] = tmp;
+ }
+ }
+
+ // add the pixel to our image
+ memcpy(&info->imageData[index], aux, mode);
+ index += mode;
+ }
+}
+
+void tgaFlipImage( tImageTGA *info )
+{
+ // mode equal the number of components for each pixel
+ int mode = info->pixelDepth / 8;
+ int rowbytes = info->width*mode;
+ unsigned char *row = (unsigned char *)malloc(rowbytes);
+ int y;
+
+ if (row == NULL) return;
+
+ for( y = 0; y < (info->height/2); y++ )
+ {
+ memcpy(row, &info->imageData[y*rowbytes],rowbytes);
+ memcpy(&info->imageData[y*rowbytes], &info->imageData[(info->height-(y+1))*rowbytes], rowbytes);
+ memcpy(&info->imageData[(info->height-(y+1))*rowbytes], row, rowbytes);
+ }
+
+ free(row);
+ info->flipped = 0;
+}
+
+// this is the function to call when we want to load an image
+tImageTGA * tgaLoad(const char *filename) {
+
+ FILE *file;
+ tImageTGA *info;
+ int mode,total;
+
+ // allocate memory for the info struct and check!
+ info = (tImageTGA *)malloc(sizeof(tImageTGA));
+ if (info == NULL)
+ return(NULL);
+
+
+ // open the file for reading (binary mode)
+ file = fopen(filename, "rb");
+ if (file == NULL) {
+ info->status = TGA_ERROR_FILE_OPEN;
+ return(info);
+ }
+
+ // load the header
+ tgaLoadHeader(file,info);
+
+ // check for errors when loading the header
+ if (ferror(file)) {
+ info->status = TGA_ERROR_READING_FILE;
+ fclose(file);
+ return(info);
+ }
+
+ // check if the image is color indexed
+ if (info->type == 1) {
+ info->status = TGA_ERROR_INDEXED_COLOR;
+ fclose(file);
+ return(info);
+ }
+ // check for other types (compressed images)
+ if ((info->type != 2) && (info->type !=3) && (info->type !=10) ) {
+ info->status = TGA_ERROR_COMPRESSED_FILE;
+ fclose(file);
+ return(info);
+ }
+
+ // mode equals the number of image components
+ mode = info->pixelDepth / 8;
+ // total is the number of unsigned chars to read
+ total = info->height * info->width * mode;
+ // allocate memory for image pixels
+ info->imageData = (unsigned char *)malloc(sizeof(unsigned char) *
+ total);
+
+ // check to make sure we have the memory required
+ if (info->imageData == NULL) {
+ info->status = TGA_ERROR_MEMORY;
+ fclose(file);
+ return(info);
+ }
+ // finally load the image pixels
+ if ( info->type == 10 )
+ tgaLoadRLEImageData(file, info);
+ else
+ tgaLoadImageData(file,info);
+
+ // check for errors when reading the pixels
+ if (ferror(file)) {
+ info->status = TGA_ERROR_READING_FILE;
+ fclose(file);
+ return(info);
+ }
+ fclose(file);
+ info->status = TGA_OK;
+
+ if ( info->flipped )
+ {
+ tgaFlipImage( info );
+ if ( info->flipped ) info->status = TGA_ERROR_MEMORY;
+ }
+
+ return(info);
+}
+
+// converts RGB to greyscale
+void tgaRGBtogreyscale(tImageTGA *info) {
+
+ int mode,i,j;
+
+ unsigned char *newImageData;
+
+ // if the image is already greyscale do nothing
+ if (info->pixelDepth == 8)
+ return;
+
+ // compute the number of actual components
+ mode = info->pixelDepth / 8;
+
+ // allocate an array for the new image data
+ newImageData = (unsigned char *)malloc(sizeof(unsigned char) *
+ info->height * info->width);
+ if (newImageData == NULL) {
+ return;
+ }
+
+ // convert pixels: greyscale = o.30 * R + 0.59 * G + 0.11 * B
+ for (i = 0,j = 0; j < info->width * info->height; i +=mode, j++)
+ newImageData[j] =
+ (unsigned char)(0.30 * info->imageData[i] +
+ 0.59 * info->imageData[i+1] +
+ 0.11 * info->imageData[i+2]);
+
+
+ //free old image data
+ free(info->imageData);
+
+ // reassign pixelDepth and type according to the new image type
+ info->pixelDepth = 8;
+ info->type = 3;
+ // reassing imageData to the new array.
+ info->imageData = newImageData;
+}
+
+// releases the memory used for the image
+void tgaDestroy(tImageTGA *info) {
+
+ if (info != NULL) {
+ if (info->imageData != NULL)
+ free(info->imageData);
+ free(info);
+ }
+}
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * 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 <Availability.h>
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#import <UIKit/UIKit.h>
+#import <OpenGLES/ES1/gl.h>
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+#import <OpenGL/gl.h>
+#import <Foundation/Foundation.h>
+#endif
+
+void CGAffineToGL(const CGAffineTransform *t, GLfloat *m);
+void GLToCGAffine(const GLfloat *m, CGAffineTransform *t);
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ * 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 "TransformUtils.h"
+
+void CGAffineToGL(const CGAffineTransform *t, GLfloat *m)
+{
+ // | m[0] m[4] m[8] m[12] | | m11 m21 m31 m41 | | a c 0 tx |
+ // | m[1] m[5] m[9] m[13] | | m12 m22 m32 m42 | | b d 0 ty |
+ // | m[2] m[6] m[10] m[14] | <=> | m13 m23 m33 m43 | <=> | 0 0 1 0 |
+ // | m[3] m[7] m[11] m[15] | | m14 m24 m34 m44 | | 0 0 0 1 |
+
+ m[2] = m[3] = m[6] = m[7] = m[8] = m[9] = m[11] = m[14] = 0.0f;
+ m[10] = m[15] = 1.0f;
+ m[0] = t->a; m[4] = t->c; m[12] = t->tx;
+ m[1] = t->b; m[5] = t->d; m[13] = t->ty;
+}
+
+void GLToCGAffine(const GLfloat *m, CGAffineTransform *t)
+{
+ t->a = m[0]; t->c = m[4]; t->tx = m[12];
+ t->b = m[1]; t->d = m[5]; t->ty = m[13];
+}
--- /dev/null
+/* cocos2d for iPhone
+ *
+ * http://www.cocos2d-iphone.org
+ *
+ *
+ * inflateMemory_ based on zlib example code
+ * http://www.zlib.net
+ *
+ * Some ideas were taken from:
+ * http://themanaworld.org/
+ * from the mapreader.cpp file
+ *
+ */
+
+#ifndef __CC_ZIP_UTILS_H
+#define __CC_ZIP_UTILS_H
+
+#import <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /* XXX: pragma pack ??? */
+ /** @struct CCZHeader
+ */
+ struct CCZHeader {
+ uint8_t sig[4]; // signature. Should be 'CCZ!' 4 bytes
+ uint16_t compression_type; // should 0
+ uint16_t version; // should be 2 (although version type==1 is also supported)
+ uint32_t reserved; // Reserverd for users.
+ uint32_t len; // size of the uncompressed file
+ };
+
+ enum {
+ CCZ_COMPRESSION_ZLIB, // zlib format.
+ CCZ_COMPRESSION_BZIP2, // bzip2 format (not supported yet)
+ CCZ_COMPRESSION_GZIP, // gzip format (not supported yet)
+ CCZ_COMPRESSION_NONE, // plain (not supported yet)
+ };
+
+/** @file
+ * Zip helper functions
+ */
+
+/**
+ * Inflates either zlib or gzip deflated memory. The inflated memory is
+ * expected to be freed by the caller.
+ *
+ * @returns the length of the deflated buffer
+ *
+ @since v0.8.1
+ */
+int ccInflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out);
+
+
+/** inflates a GZip file into memory
+ *
+ * @returns the length of the deflated buffer
+ *
+ * @since v0.99.5
+ */
+int ccInflateGZipFile(const char *filename, unsigned char **out);
+
+/** inflates a CCZ file into memory
+ *
+ * @returns the length of the deflated buffer
+ *
+ * @since v0.99.5
+ */
+int ccInflateCCZFile(const char *filename, unsigned char **out);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __CC_ZIP_UTILS_H
--- /dev/null
+/* cocos2d for iPhone
+ *
+ * http://www.cocos2d-iphone.org
+ *
+ *
+ * Inflates either zlib or gzip deflated memory. The inflated memory is
+ * expected to be freed by the caller.
+ *
+ * inflateMemory_ based on zlib example code
+ * http://www.zlib.net
+ *
+ * Some ideas were taken from:
+ * http://themanaworld.org/
+ * from the mapreader.cpp file
+ */
+
+#import <Availability.h>
+
+#import <zlib.h>
+#import <stdlib.h>
+#import <assert.h>
+#import <stdio.h>
+
+#import "ZipUtils.h"
+#import "CCFileUtils.h"
+#import "../ccMacros.h"
+
+// memory in iPhone is precious
+// Should buffer factor be 1.5 instead of 2 ?
+#define BUFFER_INC_FACTOR (2)
+
+static int inflateMemory_(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int *outLength)
+{
+ /* ret value */
+ int err = Z_OK;
+
+ /* 256k initial decompress buffer */
+ int bufferSize = 256 * 1024;
+ *out = (unsigned char*) malloc(bufferSize);
+
+ z_stream d_stream; /* decompression stream */
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = in;
+ d_stream.avail_in = inLength;
+ d_stream.next_out = *out;
+ d_stream.avail_out = bufferSize;
+
+ /* window size to hold 256k */
+ if( (err = inflateInit2(&d_stream, 15 + 32)) != Z_OK )
+ return err;
+
+ for (;;) {
+ err = inflate(&d_stream, Z_NO_FLUSH);
+
+ if (err == Z_STREAM_END)
+ break;
+
+ switch (err) {
+ case Z_NEED_DICT:
+ err = Z_DATA_ERROR;
+ case Z_DATA_ERROR:
+ case Z_MEM_ERROR:
+ inflateEnd(&d_stream);
+ return err;
+ }
+
+ // not enough memory ?
+ if (err != Z_STREAM_END) {
+
+ unsigned char *tmp = realloc(*out, bufferSize * BUFFER_INC_FACTOR);
+
+ /* not enough memory, ouch */
+ if (! tmp ) {
+ CCLOG(@"cocos2d: ZipUtils: realloc failed");
+ inflateEnd(&d_stream);
+ return Z_MEM_ERROR;
+ }
+ /* only assign to *out if tmp is valid. it's not guaranteed that realloc will reuse the memory */
+ *out = tmp;
+
+ d_stream.next_out = *out + bufferSize;
+ d_stream.avail_out = bufferSize;
+ bufferSize *= BUFFER_INC_FACTOR;
+ }
+ }
+
+
+ *outLength = bufferSize - d_stream.avail_out;
+ err = inflateEnd(&d_stream);
+ return err;
+}
+
+int ccInflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out)
+{
+ unsigned int outLength = 0;
+ int err = inflateMemory_(in, inLength, out, &outLength);
+
+ if (err != Z_OK || *out == NULL) {
+ if (err == Z_MEM_ERROR)
+ CCLOG(@"cocos2d: ZipUtils: Out of memory while decompressing map data!");
+
+ else if (err == Z_VERSION_ERROR)
+ CCLOG(@"cocos2d: ZipUtils: Incompatible zlib version!");
+
+ else if (err == Z_DATA_ERROR)
+ CCLOG(@"cocos2d: ZipUtils: Incorrect zlib compressed data!");
+
+ else
+ CCLOG(@"cocos2d: ZipUtils: Unknown error while decompressing map data!");
+
+ free(*out);
+ *out = NULL;
+ outLength = 0;
+ }
+
+ return outLength;
+}
+
+int ccInflateGZipFile(const char *path, unsigned char **out)
+{
+ int len;
+ unsigned int offset = 0;
+
+ assert( out );
+ assert( &*out );
+
+ gzFile inFile = gzopen(path, "rb");
+ if( inFile == NULL ) {
+ CCLOG(@"cocos2d: ZipUtils: error open gzip file: %s", path);
+ return -1;
+ }
+
+ /* 512k initial decompress buffer */
+ unsigned int bufferSize = 512 * 1024;
+ unsigned int totalBufferSize = bufferSize;
+
+ *out = malloc( bufferSize );
+ if( ! out ) {
+ CCLOG(@"cocos2d: ZipUtils: out of memory");
+ return -1;
+ }
+
+ for (;;) {
+ len = gzread(inFile, *out + offset, bufferSize);
+ if (len < 0) {
+ CCLOG(@"cocos2d: ZipUtils: error in gzread");
+ free( *out );
+ *out = NULL;
+ return -1;
+ }
+ if (len == 0)
+ break;
+
+ offset += len;
+
+ // finish reading the file
+ if( len < bufferSize )
+ break;
+
+ bufferSize *= BUFFER_INC_FACTOR;
+ totalBufferSize += bufferSize;
+ unsigned char *tmp = realloc(*out, totalBufferSize );
+
+ if( ! tmp ) {
+ CCLOG(@"cocos2d: ZipUtils: out of memory");
+ free( *out );
+ *out = NULL;
+ return -1;
+ }
+
+ *out = tmp;
+ }
+
+ if (gzclose(inFile) != Z_OK)
+ CCLOG(@"cocos2d: ZipUtils: gzclose failed");
+
+ return offset;
+}
+
+int ccInflateCCZFile(const char *path, unsigned char **out)
+{
+ assert( out );
+ assert( &*out );
+
+ // load file into memory
+ unsigned char *compressed = NULL;
+ int fileLen = ccLoadFileIntoMemory( path, &compressed );
+ if( fileLen < 0 ) {
+ CCLOG(@"cocos2d: Error loading CCZ compressed file");
+ }
+
+ struct CCZHeader *header = (struct CCZHeader*) compressed;
+
+ // verify header
+ if( header->sig[0] != 'C' || header->sig[1] != 'C' || header->sig[2] != 'Z' || header->sig[3] != '!' ) {
+ CCLOG(@"cocos2d: Invalid CCZ file");
+ free(compressed);
+ return -1;
+ }
+
+ // verify header version
+ uint16_t version = CFSwapInt16BigToHost( header->version );
+ if( version > 2 ) {
+ CCLOG(@"cocos2d: Unsupported CCZ header format");
+ free(compressed);
+ return -1;
+ }
+
+ // verify compression format
+ if( CFSwapInt16BigToHost(header->compression_type) != CCZ_COMPRESSION_ZLIB ) {
+ CCLOG(@"cocos2d: CCZ Unsupported compression method");
+ free(compressed);
+ return -1;
+ }
+
+ uint32_t len = CFSwapInt32BigToHost( header->len );
+
+ *out = malloc( len );
+ if(! *out )
+ {
+ CCLOG(@"cocos2d: CCZ: Failed to allocate memory for texture");
+ free(compressed);
+ return -1;
+ }
+
+
+ uLongf destlen = len;
+ uLongf source = (uLongf) compressed + sizeof(*header);
+ int ret = uncompress(*out, &destlen, (Bytef*)source, fileLen - sizeof(*header) );
+
+ free( compressed );
+
+ if( ret != Z_OK )
+ {
+ CCLOG(@"cocos2d: CCZ: Failed to uncompress data");
+ free( *out );
+ *out = NULL;
+ return -1;
+ }
+
+
+ return len;
+}
\ No newline at end of file
--- /dev/null
+/*
+ public domain BASE64 code
+
+ modified for cocos2d-iphone: http://www.cocos2d-iphone.org
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+unsigned char alphabet[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+int _base64Decode( unsigned char *input, unsigned int input_len, unsigned char *output, unsigned int *output_len )
+{
+ static char inalphabet[256], decoder[256];
+ int i, bits, c, char_count, errors = 0;
+ unsigned int input_idx = 0;
+ unsigned int output_idx = 0;
+
+ for (i = (sizeof alphabet) - 1; i >= 0 ; i--) {
+ inalphabet[alphabet[i]] = 1;
+ decoder[alphabet[i]] = i;
+ }
+
+ char_count = 0;
+ bits = 0;
+ for( input_idx=0; input_idx < input_len ; input_idx++ ) {
+ c = input[ input_idx ];
+ if (c == '=')
+ break;
+ if (c > 255 || ! inalphabet[c])
+ continue;
+ bits += decoder[c];
+ char_count++;
+ if (char_count == 4) {
+ output[ output_idx++ ] = (bits >> 16);
+ output[ output_idx++ ] = ((bits >> 8) & 0xff);
+ output[ output_idx++ ] = ( bits & 0xff);
+ bits = 0;
+ char_count = 0;
+ } else {
+ bits <<= 6;
+ }
+ }
+
+ if( c == '=' ) {
+ switch (char_count) {
+ case 1:
+ fprintf(stderr, "base64Decode: encoding incomplete: at least 2 bits missing");
+ errors++;
+ break;
+ case 2:
+ output[ output_idx++ ] = ( bits >> 10 );
+ break;
+ case 3:
+ output[ output_idx++ ] = ( bits >> 16 );
+ output[ output_idx++ ] = (( bits >> 8 ) & 0xff);
+ break;
+ }
+ } else if ( input_idx < input_len ) {
+ if (char_count) {
+ fprintf(stderr, "base64 encoding incomplete: at least %d bits truncated",
+ ((4 - char_count) * 6));
+ errors++;
+ }
+ }
+
+ *output_len = output_idx;
+ return errors;
+}
+
+int base64Decode(unsigned char *in, unsigned int inLength, unsigned char **out)
+{
+ unsigned int outLength = 0;
+
+ //should be enough to store 6-bit buffers in 8-bit buffers
+ *out = malloc( inLength * 3.0f / 4.0f + 1 );
+ if( *out ) {
+ int ret = _base64Decode(in, inLength, *out, &outLength);
+
+ if (ret > 0 )
+ {
+ printf("Base64Utils: error decoding");
+ free(*out);
+ *out = NULL;
+ outLength = 0;
+ }
+ }
+ return outLength;
+}
--- /dev/null
+/*
+ public domain BASE64 code
+
+ modified for cocos2d-iphone: http://www.cocos2d-iphone.org
+ */
+
+#ifndef __CC_BASE64_DECODE_H
+#define __CC_BASE64_DECODE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** @file
+ base64 helper functions
+ */
+
+/**
+ * Decodes a 64base encoded memory. The decoded memory is
+ * expected to be freed by the caller.
+ *
+ * @returns the length of the out buffer
+ *
+ @since v0.8.1
+ */
+int base64Decode(unsigned char *in, unsigned int inLength, unsigned char **out);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __CC_BASE64_DECODE_H
--- /dev/null
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+/**
+ @file
+ Based on Chipmunk cpArray.
+ ccArray is a faster alternative to NSMutableArray, it does pretty much the
+ same thing (stores NSObjects and retains/releases them appropriately). It's
+ faster because:
+ - it uses a plain C interface so it doesn't incur Objective-c messaging overhead
+ - it assumes you know what you're doing, so it doesn't spend time on safety checks
+ (index out of bounds, required capacity etc.)
+ - comparisons are done using pointer equality instead of isEqual
+
+ There are 2 kind of functions:
+ - ccArray functions that manipulates objective-c objects (retain and release are performanced)
+ - ccCArray functions that manipulates values like if they were standard C structures (no retain/release is performed)
+ */
+
+#ifndef CC_ARRAY_H
+#define CC_ARRAY_H
+
+#import <Foundation/Foundation.h>
+
+#import <stdlib.h>
+#import <string.h>
+
+
+#pragma mark -
+#pragma mark ccArray for Objects
+
+// Easy integration
+#define CCARRAYDATA_FOREACH(__array__, __object__) \
+__object__=__array__->arr[0]; for(NSUInteger i=0, num=__array__->num; i<num; i++, __object__=__array__->arr[i]) \
+
+
+typedef struct ccArray {
+ NSUInteger num, max;
+ id *arr;
+} ccArray;
+
+/** Allocates and initializes a new array with specified capacity */
+static inline ccArray* ccArrayNew(NSUInteger capacity) {
+ if (capacity == 0)
+ capacity = 1;
+
+ ccArray *arr = (ccArray*)malloc( sizeof(ccArray) );
+ arr->num = 0;
+ arr->arr = (id*) malloc( capacity * sizeof(id) );
+ arr->max = capacity;
+
+ return arr;
+}
+
+static inline void ccArrayRemoveAllObjects(ccArray *arr);
+
+/** Frees array after removing all remaining objects. Silently ignores nil arr. */
+static inline void ccArrayFree(ccArray *arr)
+{
+ if( arr == nil ) return;
+
+ ccArrayRemoveAllObjects(arr);
+
+ free(arr->arr);
+ free(arr);
+}
+
+/** Doubles array capacity */
+static inline void ccArrayDoubleCapacity(ccArray *arr)
+{
+ arr->max *= 2;
+ arr->arr = (id*) realloc( arr->arr, arr->max * sizeof(id) );
+}
+
+/** Increases array capacity such that max >= num + extra. */
+static inline void ccArrayEnsureExtraCapacity(ccArray *arr, NSUInteger extra)
+{
+ while (arr->max < arr->num + extra)
+ ccArrayDoubleCapacity(arr);
+}
+
+/** Returns index of first occurence of object, NSNotFound if object not found. */
+static inline NSUInteger ccArrayGetIndexOfObject(ccArray *arr, id object)
+{
+ for( NSUInteger i = 0; i < arr->num; i++)
+ if( arr->arr[i] == object ) return i;
+ return NSNotFound;
+}
+
+/** Returns a Boolean value that indicates whether object is present in array. */
+static inline BOOL ccArrayContainsObject(ccArray *arr, id object)
+{
+ return ccArrayGetIndexOfObject(arr, object) != NSNotFound;
+}
+
+/** Appends an object. Bahaviour undefined if array doesn't have enough capacity. */
+static inline void ccArrayAppendObject(ccArray *arr, id object)
+{
+ arr->arr[arr->num] = [object retain];
+ arr->num++;
+}
+
+/** Appends an object. Capacity of arr is increased if needed. */
+static inline void ccArrayAppendObjectWithResize(ccArray *arr, id object)
+{
+ ccArrayEnsureExtraCapacity(arr, 1);
+ ccArrayAppendObject(arr, object);
+}
+
+/** Appends objects from plusArr to arr. Behaviour undefined if arr doesn't have
+ enough capacity. */
+static inline void ccArrayAppendArray(ccArray *arr, ccArray *plusArr)
+{
+ for( NSUInteger i = 0; i < plusArr->num; i++)
+ ccArrayAppendObject(arr, plusArr->arr[i]);
+}
+
+/** Appends objects from plusArr to arr. Capacity of arr is increased if needed. */
+static inline void ccArrayAppendArrayWithResize(ccArray *arr, ccArray *plusArr)
+{
+ ccArrayEnsureExtraCapacity(arr, plusArr->num);
+ ccArrayAppendArray(arr, plusArr);
+}
+
+static inline void ccArrayInsertObjectAtIndex(ccArray *arr, id object, NSUInteger index)
+{
+ NSCAssert(index<=arr->num, @"Invalid index. Out of bounds");
+
+ ccArrayEnsureExtraCapacity(arr, 1);
+
+ int remaining = arr->num - index;
+ if( remaining > 0)
+ memmove(&arr->arr[index+1], &arr->arr[index], sizeof(id) * remaining );
+
+ arr->arr[index] = [object retain];
+ arr->num++;
+}
+
+/** Removes all objects from arr */
+static inline void ccArrayRemoveAllObjects(ccArray *arr)
+{
+ while( arr->num > 0 )
+ [arr->arr[--arr->num] release];
+}
+
+/** Removes object at specified index and pushes back all subsequent objects.
+ Behaviour undefined if index outside [0, num-1]. */
+static inline void ccArrayRemoveObjectAtIndex(ccArray *arr, NSUInteger index)
+{
+ [arr->arr[index] release];
+ arr->num--;
+
+ int remaining = arr->num - index;
+ if(remaining>0)
+ memmove(&arr->arr[index], &arr->arr[index+1], remaining * sizeof(id));
+}
+
+/** Removes object at specified index and fills the gap with the last object,
+ thereby avoiding the need to push back subsequent objects.
+ Behaviour undefined if index outside [0, num-1]. */
+static inline void ccArrayFastRemoveObjectAtIndex(ccArray *arr, NSUInteger index)
+{
+ [arr->arr[index] release];
+ NSUInteger last = --arr->num;
+ arr->arr[index] = arr->arr[last];
+}
+
+static inline void ccArrayFastRemoveObject(ccArray *arr, id object)
+{
+ NSUInteger index = ccArrayGetIndexOfObject(arr, object);
+ if (index != NSNotFound)
+ ccArrayFastRemoveObjectAtIndex(arr, index);
+}
+
+/** Searches for the first occurance of object and removes it. If object is not
+ found the function has no effect. */
+static inline void ccArrayRemoveObject(ccArray *arr, id object)
+{
+ NSUInteger index = ccArrayGetIndexOfObject(arr, object);
+ if (index != NSNotFound)
+ ccArrayRemoveObjectAtIndex(arr, index);
+}
+
+/** Removes from arr all objects in minusArr. For each object in minusArr, the
+ first matching instance in arr will be removed. */
+static inline void ccArrayRemoveArray(ccArray *arr, ccArray *minusArr)
+{
+ for( NSUInteger i = 0; i < minusArr->num; i++)
+ ccArrayRemoveObject(arr, minusArr->arr[i]);
+}
+
+/** Removes from arr all objects in minusArr. For each object in minusArr, all
+ matching instances in arr will be removed. */
+static inline void ccArrayFullRemoveArray(ccArray *arr, ccArray *minusArr)
+{
+ NSUInteger back = 0;
+
+ for( NSUInteger i = 0; i < arr->num; i++) {
+ if( ccArrayContainsObject(minusArr, arr->arr[i]) ) {
+ [arr->arr[i] release];
+ back++;
+ } else
+ arr->arr[i - back] = arr->arr[i];
+ }
+
+ arr->num -= back;
+}
+
+/** Sends to each object in arr the message identified by given selector. */
+static inline void ccArrayMakeObjectsPerformSelector(ccArray *arr, SEL sel)
+{
+ for( NSUInteger i = 0; i < arr->num; i++)
+ [arr->arr[i] performSelector:sel];
+}
+
+static inline void ccArrayMakeObjectsPerformSelectorWithObject(ccArray *arr, SEL sel, id object)
+{
+ for( NSUInteger i = 0; i < arr->num; i++)
+ [arr->arr[i] performSelector:sel withObject:object];
+}
+
+
+#pragma mark -
+#pragma mark ccCArray for Values (c structures)
+
+typedef ccArray ccCArray;
+
+static inline void ccCArrayRemoveAllValues(ccCArray *arr);
+
+/** Allocates and initializes a new C array with specified capacity */
+static inline ccCArray* ccCArrayNew(NSUInteger capacity) {
+ if (capacity == 0)
+ capacity = 1;
+
+ ccCArray *arr = (ccCArray*)malloc( sizeof(ccCArray) );
+ arr->num = 0;
+ arr->arr = (id*) malloc( capacity * sizeof(id) );
+ arr->max = capacity;
+
+ return arr;
+}
+
+/** Frees C array after removing all remaining values. Silently ignores nil arr. */
+static inline void ccCArrayFree(ccCArray *arr)
+{
+ if( arr == nil ) return;
+
+ ccCArrayRemoveAllValues(arr);
+
+ free(arr->arr);
+ free(arr);
+}
+
+/** Doubles C array capacity */
+static inline void ccCArrayDoubleCapacity(ccCArray *arr)
+{
+ return ccArrayDoubleCapacity(arr);
+}
+
+/** Increases array capacity such that max >= num + extra. */
+static inline void ccCArrayEnsureExtraCapacity(ccCArray *arr, NSUInteger extra)
+{
+ return ccArrayEnsureExtraCapacity(arr,extra);
+}
+
+/** Returns index of first occurence of value, NSNotFound if value not found. */
+static inline NSUInteger ccCArrayGetIndexOfValue(ccCArray *arr, void* value)
+{
+ for( NSUInteger i = 0; i < arr->num; i++)
+ if( arr->arr[i] == value ) return i;
+ return NSNotFound;
+}
+
+/** Returns a Boolean value that indicates whether value is present in the C array. */
+static inline BOOL ccCArrayContainsValue(ccCArray *arr, void* value)
+{
+ return ccCArrayGetIndexOfValue(arr, value) != NSNotFound;
+}
+
+/** Inserts a value at a certain position. Behaviour undefined if aray doesn't have enough capacity */
+static inline void ccCArrayInsertValueAtIndex( ccCArray *arr, void *value, NSUInteger index)
+{
+ assert( index < arr->max );
+
+ int remaining = arr->num - index;
+
+ // last Value doesn't need to be moved
+ if( remaining > 0) {
+ // tex coordinates
+ memmove( &arr->arr[index+1],&arr->arr[index], sizeof(void*) * remaining );
+ }
+
+ arr->num++;
+ arr->arr[index] = (id) value;
+}
+
+/** Appends an value. Bahaviour undefined if array doesn't have enough capacity. */
+static inline void ccCArrayAppendValue(ccCArray *arr, void* value)
+{
+ arr->arr[arr->num] = (id) value;
+ arr->num++;
+}
+
+/** Appends an value. Capacity of arr is increased if needed. */
+static inline void ccCArrayAppendValueWithResize(ccCArray *arr, void* value)
+{
+ ccCArrayEnsureExtraCapacity(arr, 1);
+ ccCArrayAppendValue(arr, value);
+}
+
+/** Appends values from plusArr to arr. Behaviour undefined if arr doesn't have
+ enough capacity. */
+static inline void ccCArrayAppendArray(ccCArray *arr, ccCArray *plusArr)
+{
+ for( NSUInteger i = 0; i < plusArr->num; i++)
+ ccCArrayAppendValue(arr, plusArr->arr[i]);
+}
+
+/** Appends values from plusArr to arr. Capacity of arr is increased if needed. */
+static inline void ccCArrayAppendArrayWithResize(ccCArray *arr, ccCArray *plusArr)
+{
+ ccCArrayEnsureExtraCapacity(arr, plusArr->num);
+ ccCArrayAppendArray(arr, plusArr);
+}
+
+/** Removes all values from arr */
+static inline void ccCArrayRemoveAllValues(ccCArray *arr)
+{
+ arr->num = 0;
+}
+
+/** Removes value at specified index and pushes back all subsequent values.
+ Behaviour undefined if index outside [0, num-1].
+ @since v0.99.4
+ */
+static inline void ccCArrayRemoveValueAtIndex(ccCArray *arr, NSUInteger index)
+{
+ for( NSUInteger last = --arr->num; index < last; index++)
+ arr->arr[index] = arr->arr[index + 1];
+}
+
+/** Removes value at specified index and fills the gap with the last value,
+ thereby avoiding the need to push back subsequent values.
+ Behaviour undefined if index outside [0, num-1].
+ @since v0.99.4
+ */
+static inline void ccCArrayFastRemoveValueAtIndex(ccCArray *arr, NSUInteger index)
+{
+ NSUInteger last = --arr->num;
+ arr->arr[index] = arr->arr[last];
+}
+
+/** Searches for the first occurance of value and removes it. If value is not found the function has no effect.
+ @since v0.99.4
+ */
+static inline void ccCArrayRemoveValue(ccCArray *arr, void* value)
+{
+ NSUInteger index = ccCArrayGetIndexOfValue(arr, value);
+ if (index != NSNotFound)
+ ccCArrayRemoveValueAtIndex(arr, index);
+}
+
+/** Removes from arr all values in minusArr. For each Value in minusArr, the first matching instance in arr will be removed.
+ @since v0.99.4
+ */
+static inline void ccCArrayRemoveArray(ccCArray *arr, ccCArray *minusArr)
+{
+ for( NSUInteger i = 0; i < minusArr->num; i++)
+ ccCArrayRemoveValue(arr, minusArr->arr[i]);
+}
+
+/** Removes from arr all values in minusArr. For each value in minusArr, all matching instances in arr will be removed.
+ @since v0.99.4
+ */
+static inline void ccCArrayFullRemoveArray(ccCArray *arr, ccCArray *minusArr)
+{
+ NSUInteger back = 0;
+
+ for( NSUInteger i = 0; i < arr->num; i++) {
+ if( ccCArrayContainsValue(minusArr, arr->arr[i]) ) {
+ back++;
+ } else
+ arr->arr[i - back] = arr->arr[i];
+ }
+
+ arr->num -= back;
+}
+#endif // CC_ARRAY_H
\ No newline at end of file
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ */
+
+/*
+ ccNextPOT function is licensed under the same license that is used in CCTexture2D.m.
+ */
+#include "ccUtils.h"
+
+unsigned int ccNextPOT(unsigned int x)
+{
+ x = x - 1;
+ x = x | (x >> 1);
+ x = x | (x >> 2);
+ x = x | (x >> 4);
+ x = x | (x >> 8);
+ x = x | (x >>16);
+ return x + 1;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * cocos2d for iPhone: http://www.cocos2d-iphone.org
+ *
+ */
+
+#ifndef __CC_UTILS_H
+#define __CC_UTILS_H
+
+/** @file ccUtils.h
+ Misc free functions
+ */
+
+/*
+ ccNextPOT function is licensed under the same license that is used in CCTexture2D.m.
+ */
+
+/** returns the Next Power of Two value.
+
+ Examples:
+ - If "value" is 15, it will return 16.
+ - If "value" is 16, it will return 16.
+ - If "value" is 17, it will return 32.
+
+ @since v0.99.5
+ */
+
+unsigned int ccNextPOT( unsigned int value );
+
+#endif // ! __CC_UTILS_H
--- /dev/null
+/*
+Copyright (c) 2003-2010, Troy D. Hanson http://uthash.sourceforge.net
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef UTHASH_H
+#define UTHASH_H
+
+#include <string.h> /* memcmp,strlen */
+#include <stddef.h> /* ptrdiff_t */
+
+/* These macros use decltype or the earlier __typeof GNU extension.
+ As decltype is only available in newer compilers (VS2010 or gcc 4.3+
+ when compiling c++ source) this code uses whatever method is needed
+ or, for VS2008 where neither is available, uses casting workarounds. */
+#ifdef _MSC_VER /* MS compiler */
+#if _MSC_VER >= 1600 && __cplusplus /* VS2010 or newer in C++ mode */
+#define DECLTYPE(x) (decltype(x))
+#else /* VS2008 or older (or VS2010 in C mode) */
+#define NO_DECLTYPE
+#define DECLTYPE(x)
+#endif
+#else /* GNU, Sun and other compilers */
+#define DECLTYPE(x) (__typeof(x))
+#endif
+
+#ifdef NO_DECLTYPE
+#define DECLTYPE_ASSIGN(dst,src) \
+do { \
+ char **_da_dst = (char**)(&(dst)); \
+ *_da_dst = (char*)(src); \
+} while(0)
+#else
+#define DECLTYPE_ASSIGN(dst,src) \
+do { \
+ (dst) = DECLTYPE(dst)(src); \
+} while(0)
+#endif
+
+/* a number of the hash function use uint32_t which isn't defined on win32 */
+#ifdef _MSC_VER
+typedef unsigned int uint32_t;
+#else
+#include <inttypes.h> /* uint32_t */
+#endif
+
+#define UTHASH_VERSION 1.9
+
+#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
+#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
+#define uthash_free(ptr) free(ptr) /* free fcn */
+
+#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
+#define uthash_expand_fyi(tbl) /* can be defined to log expands */
+
+/* initial number of buckets */
+#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */
+#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */
+#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */
+
+/* calculate the element whose hash handle address is hhe */
+#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
+
+#define HASH_FIND(hh,head,keyptr,keylen,out) \
+do { \
+ unsigned _hf_bkt,_hf_hashv; \
+ out=NULL; \
+ if (head) { \
+ HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
+ if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \
+ HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \
+ keyptr,keylen,out); \
+ } \
+ } \
+} while (0)
+
+#ifdef HASH_BLOOM
+#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
+#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
+#define HASH_BLOOM_MAKE(tbl) \
+do { \
+ (tbl)->bloom_nbits = HASH_BLOOM; \
+ (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
+ if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \
+ memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
+ (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
+} while (0);
+
+#define HASH_BLOOM_FREE(tbl) \
+do { \
+ uthash_free((tbl)->bloom_bv); \
+} while (0);
+
+#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
+#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
+
+#define HASH_BLOOM_ADD(tbl,hashv) \
+ HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
+
+#define HASH_BLOOM_TEST(tbl,hashv) \
+ HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
+
+#else
+#define HASH_BLOOM_MAKE(tbl)
+#define HASH_BLOOM_FREE(tbl)
+#define HASH_BLOOM_ADD(tbl,hashv)
+#define HASH_BLOOM_TEST(tbl,hashv) (1)
+#endif
+
+#define HASH_MAKE_TABLE(hh,head) \
+do { \
+ (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \
+ sizeof(UT_hash_table)); \
+ if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
+ memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
+ (head)->hh.tbl->tail = &((head)->hh); \
+ (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
+ (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
+ (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
+ (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
+ HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
+ if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
+ memset((head)->hh.tbl->buckets, 0, \
+ HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
+ HASH_BLOOM_MAKE((head)->hh.tbl); \
+ (head)->hh.tbl->signature = HASH_SIGNATURE; \
+} while(0)
+
+#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
+ HASH_ADD_KEYPTR(hh,head,&add->fieldname,keylen_in,add)
+
+#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
+do { \
+ unsigned _ha_bkt; \
+ (add)->hh.next = NULL; \
+ (add)->hh.key = (char*)keyptr; \
+ (add)->hh.keylen = keylen_in; \
+ if (!(head)) { \
+ head = (add); \
+ (head)->hh.prev = NULL; \
+ HASH_MAKE_TABLE(hh,head); \
+ } else { \
+ (head)->hh.tbl->tail->next = (add); \
+ (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
+ (head)->hh.tbl->tail = &((add)->hh); \
+ } \
+ (head)->hh.tbl->num_items++; \
+ (add)->hh.tbl = (head)->hh.tbl; \
+ HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \
+ (add)->hh.hashv, _ha_bkt); \
+ HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
+ HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
+ HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
+ HASH_FSCK(hh,head); \
+} while(0)
+
+#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
+do { \
+ bkt = ((hashv) & ((num_bkts) - 1)); \
+} while(0)
+
+/* delete "delptr" from the hash table.
+ * "the usual" patch-up process for the app-order doubly-linked-list.
+ * The use of _hd_hh_del below deserves special explanation.
+ * These used to be expressed using (delptr) but that led to a bug
+ * if someone used the same symbol for the head and deletee, like
+ * HASH_DELETE(hh,users,users);
+ * We want that to work, but by changing the head (users) below
+ * we were forfeiting our ability to further refer to the deletee (users)
+ * in the patch-up process. Solution: use scratch space to
+ * copy the deletee pointer, then the latter references are via that
+ * scratch pointer rather than through the repointed (users) symbol.
+ */
+#define HASH_DELETE(hh,head,delptr) \
+do { \
+ unsigned _hd_bkt; \
+ struct UT_hash_handle *_hd_hh_del; \
+ if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
+ uthash_free((head)->hh.tbl->buckets ); \
+ HASH_BLOOM_FREE((head)->hh.tbl); \
+ uthash_free((head)->hh.tbl); \
+ head = NULL; \
+ } else { \
+ _hd_hh_del = &((delptr)->hh); \
+ if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \
+ (head)->hh.tbl->tail = \
+ (UT_hash_handle*)((char*)((delptr)->hh.prev) + \
+ (head)->hh.tbl->hho); \
+ } \
+ if ((delptr)->hh.prev) { \
+ ((UT_hash_handle*)((char*)((delptr)->hh.prev) + \
+ (head)->hh.tbl->hho))->next = (delptr)->hh.next; \
+ } else { \
+ DECLTYPE_ASSIGN(head,(delptr)->hh.next); \
+ } \
+ if (_hd_hh_del->next) { \
+ ((UT_hash_handle*)((char*)_hd_hh_del->next + \
+ (head)->hh.tbl->hho))->prev = \
+ _hd_hh_del->prev; \
+ } \
+ HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
+ HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
+ (head)->hh.tbl->num_items--; \
+ } \
+ HASH_FSCK(hh,head); \
+} while (0)
+
+
+/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
+#define HASH_FIND_STR(head,findstr,out) \
+ HASH_FIND(hh,head,findstr,strlen(findstr),out)
+#define HASH_ADD_STR(head,strfield,add) \
+ HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
+#define HASH_FIND_INT(head,findint,out) \
+ HASH_FIND(hh,head,findint,sizeof(int),out)
+#define HASH_ADD_INT(head,intfield,add) \
+ HASH_ADD(hh,head,intfield,sizeof(int),add)
+#define HASH_DEL(head,delptr) \
+ HASH_DELETE(hh,head,delptr)
+
+/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
+ * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
+ */
+#ifdef HASH_DEBUG
+#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
+#define HASH_FSCK(hh,head) \
+do { \
+ unsigned _bkt_i; \
+ unsigned _count, _bkt_count; \
+ char *_prev; \
+ struct UT_hash_handle *_thh; \
+ if (head) { \
+ _count = 0; \
+ for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
+ _bkt_count = 0; \
+ _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
+ _prev = NULL; \
+ while (_thh) { \
+ if (_prev != (char*)(_thh->hh_prev)) { \
+ HASH_OOPS("invalid hh_prev %p, actual %p\n", \
+ _thh->hh_prev, _prev ); \
+ } \
+ _bkt_count++; \
+ _prev = (char*)(_thh); \
+ _thh = _thh->hh_next; \
+ } \
+ _count += _bkt_count; \
+ if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
+ HASH_OOPS("invalid bucket count %d, actual %d\n", \
+ (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
+ } \
+ } \
+ if (_count != (head)->hh.tbl->num_items) { \
+ HASH_OOPS("invalid hh item count %d, actual %d\n", \
+ (head)->hh.tbl->num_items, _count ); \
+ } \
+ /* traverse hh in app order; check next/prev integrity, count */ \
+ _count = 0; \
+ _prev = NULL; \
+ _thh = &(head)->hh; \
+ while (_thh) { \
+ _count++; \
+ if (_prev !=(char*)(_thh->prev)) { \
+ HASH_OOPS("invalid prev %p, actual %p\n", \
+ _thh->prev, _prev ); \
+ } \
+ _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
+ _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \
+ (head)->hh.tbl->hho) : NULL ); \
+ } \
+ if (_count != (head)->hh.tbl->num_items) { \
+ HASH_OOPS("invalid app item count %d, actual %d\n", \
+ (head)->hh.tbl->num_items, _count ); \
+ } \
+ } \
+} while (0)
+#else
+#define HASH_FSCK(hh,head)
+#endif
+
+/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
+ * the descriptor to which this macro is defined for tuning the hash function.
+ * The app can #include <unistd.h> to get the prototype for write(2). */
+#ifdef HASH_EMIT_KEYS
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
+do { \
+ unsigned _klen = fieldlen; \
+ write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
+ write(HASH_EMIT_KEYS, keyptr, fieldlen); \
+} while (0)
+#else
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
+#endif
+
+/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
+#ifdef HASH_FUNCTION
+#define HASH_FCN HASH_FUNCTION
+#else
+#define HASH_FCN HASH_JEN
+#endif
+
+/* The Bernstein hash function, used in Perl prior to v5.6 */
+#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \
+do { \
+ unsigned _hb_keylen=keylen; \
+ char *_hb_key=(char*)key; \
+ (hashv) = 0; \
+ while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \
+ bkt = (hashv) & (num_bkts-1); \
+} while (0)
+
+
+/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
+ * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
+#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
+do { \
+ unsigned _sx_i; \
+ char *_hs_key=(char*)key; \
+ hashv = 0; \
+ for(_sx_i=0; _sx_i < keylen; _sx_i++) \
+ hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
+ bkt = hashv & (num_bkts-1); \
+} while (0)
+
+#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \
+do { \
+ unsigned _fn_i; \
+ char *_hf_key=(char*)key; \
+ hashv = 2166136261UL; \
+ for(_fn_i=0; _fn_i < keylen; _fn_i++) \
+ hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \
+ bkt = hashv & (num_bkts-1); \
+} while(0);
+
+#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \
+do { \
+ unsigned _ho_i; \
+ char *_ho_key=(char*)key; \
+ hashv = 0; \
+ for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
+ hashv += _ho_key[_ho_i]; \
+ hashv += (hashv << 10); \
+ hashv ^= (hashv >> 6); \
+ } \
+ hashv += (hashv << 3); \
+ hashv ^= (hashv >> 11); \
+ hashv += (hashv << 15); \
+ bkt = hashv & (num_bkts-1); \
+} while(0)
+
+#define HASH_JEN_MIX(a,b,c) \
+do { \
+ a -= b; a -= c; a ^= ( c >> 13 ); \
+ b -= c; b -= a; b ^= ( a << 8 ); \
+ c -= a; c -= b; c ^= ( b >> 13 ); \
+ a -= b; a -= c; a ^= ( c >> 12 ); \
+ b -= c; b -= a; b ^= ( a << 16 ); \
+ c -= a; c -= b; c ^= ( b >> 5 ); \
+ a -= b; a -= c; a ^= ( c >> 3 ); \
+ b -= c; b -= a; b ^= ( a << 10 ); \
+ c -= a; c -= b; c ^= ( b >> 15 ); \
+} while (0)
+
+#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \
+do { \
+ unsigned _hj_i,_hj_j,_hj_k; \
+ char *_hj_key=(char*)key; \
+ hashv = 0xfeedbeef; \
+ _hj_i = _hj_j = 0x9e3779b9; \
+ _hj_k = keylen; \
+ while (_hj_k >= 12) { \
+ _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
+ + ( (unsigned)_hj_key[2] << 16 ) \
+ + ( (unsigned)_hj_key[3] << 24 ) ); \
+ _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
+ + ( (unsigned)_hj_key[6] << 16 ) \
+ + ( (unsigned)_hj_key[7] << 24 ) ); \
+ hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
+ + ( (unsigned)_hj_key[10] << 16 ) \
+ + ( (unsigned)_hj_key[11] << 24 ) ); \
+ \
+ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
+ \
+ _hj_key += 12; \
+ _hj_k -= 12; \
+ } \
+ hashv += keylen; \
+ switch ( _hj_k ) { \
+ case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \
+ case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \
+ case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \
+ case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \
+ case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \
+ case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \
+ case 5: _hj_j += _hj_key[4]; \
+ case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \
+ case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \
+ case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \
+ case 1: _hj_i += _hj_key[0]; \
+ } \
+ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
+ bkt = hashv & (num_bkts-1); \
+} while(0)
+
+/* The Paul Hsieh hash function */
+#undef get16bits
+#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
+ || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
+#define get16bits(d) (*((const uint16_t *) (d)))
+#endif
+
+#if !defined (get16bits)
+#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
+ +(uint32_t)(((const uint8_t *)(d))[0]) )
+#endif
+#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \
+do { \
+ char *_sfh_key=(char*)key; \
+ uint32_t _sfh_tmp, _sfh_len = keylen; \
+ \
+ int _sfh_rem = _sfh_len & 3; \
+ _sfh_len >>= 2; \
+ hashv = 0xcafebabe; \
+ \
+ /* Main loop */ \
+ for (;_sfh_len > 0; _sfh_len--) { \
+ hashv += get16bits (_sfh_key); \
+ _sfh_tmp = (get16bits (_sfh_key+2) << 11) ^ hashv; \
+ hashv = (hashv << 16) ^ _sfh_tmp; \
+ _sfh_key += 2*sizeof (uint16_t); \
+ hashv += hashv >> 11; \
+ } \
+ \
+ /* Handle end cases */ \
+ switch (_sfh_rem) { \
+ case 3: hashv += get16bits (_sfh_key); \
+ hashv ^= hashv << 16; \
+ hashv ^= _sfh_key[sizeof (uint16_t)] << 18; \
+ hashv += hashv >> 11; \
+ break; \
+ case 2: hashv += get16bits (_sfh_key); \
+ hashv ^= hashv << 11; \
+ hashv += hashv >> 17; \
+ break; \
+ case 1: hashv += *_sfh_key; \
+ hashv ^= hashv << 10; \
+ hashv += hashv >> 1; \
+ } \
+ \
+ /* Force "avalanching" of final 127 bits */ \
+ hashv ^= hashv << 3; \
+ hashv += hashv >> 5; \
+ hashv ^= hashv << 4; \
+ hashv += hashv >> 17; \
+ hashv ^= hashv << 25; \
+ hashv += hashv >> 6; \
+ bkt = hashv & (num_bkts-1); \
+} while(0);
+
+#ifdef HASH_USING_NO_STRICT_ALIASING
+/* The MurmurHash exploits some CPU's (e.g. x86) tolerance for unaligned reads.
+ * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
+ * So MurmurHash comes in two versions, the faster unaligned one and the slower
+ * aligned one. We only use the faster one on CPU's where we know it's safe.
+ *
+ * Note the preprocessor built-in defines can be emitted using:
+ *
+ * gcc -m64 -dM -E - < /dev/null (on gcc)
+ * cc -## a.c (where a.c is a simple test file) (Sun Studio)
+ */
+#if (defined(__i386__) || defined(__x86_64__))
+#define HASH_MUR HASH_MUR_UNALIGNED
+#else
+#define HASH_MUR HASH_MUR_ALIGNED
+#endif
+
+/* Appleby's MurmurHash fast version for unaligned-tolerant archs like i386 */
+#define HASH_MUR_UNALIGNED(key,keylen,num_bkts,hashv,bkt) \
+do { \
+ const unsigned int _mur_m = 0x5bd1e995; \
+ const int _mur_r = 24; \
+ hashv = 0xcafebabe ^ keylen; \
+ char *_mur_key = (char *)key; \
+ uint32_t _mur_tmp, _mur_len = keylen; \
+ \
+ for (;_mur_len >= 4; _mur_len-=4) { \
+ _mur_tmp = *(uint32_t *)_mur_key; \
+ _mur_tmp *= _mur_m; \
+ _mur_tmp ^= _mur_tmp >> _mur_r; \
+ _mur_tmp *= _mur_m; \
+ hashv *= _mur_m; \
+ hashv ^= _mur_tmp; \
+ _mur_key += 4; \
+ } \
+ \
+ switch(_mur_len) \
+ { \
+ case 3: hashv ^= _mur_key[2] << 16; \
+ case 2: hashv ^= _mur_key[1] << 8; \
+ case 1: hashv ^= _mur_key[0]; \
+ hashv *= _mur_m; \
+ }; \
+ \
+ hashv ^= hashv >> 13; \
+ hashv *= _mur_m; \
+ hashv ^= hashv >> 15; \
+ \
+ bkt = hashv & (num_bkts-1); \
+} while(0)
+
+/* Appleby's MurmurHash version for alignment-sensitive archs like Sparc */
+#define HASH_MUR_ALIGNED(key,keylen,num_bkts,hashv,bkt) \
+do { \
+ const unsigned int _mur_m = 0x5bd1e995; \
+ const int _mur_r = 24; \
+ hashv = 0xcafebabe ^ keylen; \
+ char *_mur_key = (char *)key; \
+ uint32_t _mur_len = keylen; \
+ int _mur_align = (int)_mur_key & 3; \
+ \
+ if (_mur_align && (_mur_len >= 4)) { \
+ unsigned _mur_t = 0, _mur_d = 0; \
+ switch(_mur_align) { \
+ case 1: _mur_t |= _mur_key[2] << 16; \
+ case 2: _mur_t |= _mur_key[1] << 8; \
+ case 3: _mur_t |= _mur_key[0]; \
+ } \
+ _mur_t <<= (8 * _mur_align); \
+ _mur_key += 4-_mur_align; \
+ _mur_len -= 4-_mur_align; \
+ int _mur_sl = 8 * (4-_mur_align); \
+ int _mur_sr = 8 * _mur_align; \
+ \
+ for (;_mur_len >= 4; _mur_len-=4) { \
+ _mur_d = *(unsigned *)_mur_key; \
+ _mur_t = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
+ unsigned _mur_k = _mur_t; \
+ _mur_k *= _mur_m; \
+ _mur_k ^= _mur_k >> _mur_r; \
+ _mur_k *= _mur_m; \
+ hashv *= _mur_m; \
+ hashv ^= _mur_k; \
+ _mur_t = _mur_d; \
+ _mur_key += 4; \
+ } \
+ _mur_d = 0; \
+ if(_mur_len >= _mur_align) { \
+ switch(_mur_align) { \
+ case 3: _mur_d |= _mur_key[2] << 16; \
+ case 2: _mur_d |= _mur_key[1] << 8; \
+ case 1: _mur_d |= _mur_key[0]; \
+ } \
+ unsigned _mur_k = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
+ _mur_k *= _mur_m; \
+ _mur_k ^= _mur_k >> _mur_r; \
+ _mur_k *= _mur_m; \
+ hashv *= _mur_m; \
+ hashv ^= _mur_k; \
+ _mur_k += _mur_align; \
+ _mur_len -= _mur_align; \
+ \
+ switch(_mur_len) \
+ { \
+ case 3: hashv ^= _mur_key[2] << 16; \
+ case 2: hashv ^= _mur_key[1] << 8; \
+ case 1: hashv ^= _mur_key[0]; \
+ hashv *= _mur_m; \
+ } \
+ } else { \
+ switch(_mur_len) \
+ { \
+ case 3: _mur_d ^= _mur_key[2] << 16; \
+ case 2: _mur_d ^= _mur_key[1] << 8; \
+ case 1: _mur_d ^= _mur_key[0]; \
+ case 0: hashv ^= (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
+ hashv *= _mur_m; \
+ } \
+ } \
+ \
+ hashv ^= hashv >> 13; \
+ hashv *= _mur_m; \
+ hashv ^= hashv >> 15; \
+ } else { \
+ for (;_mur_len >= 4; _mur_len-=4) { \
+ unsigned _mur_k = *(unsigned*)_mur_key; \
+ _mur_k *= _mur_m; \
+ _mur_k ^= _mur_k >> _mur_r; \
+ _mur_k *= _mur_m; \
+ hashv *= _mur_m; \
+ hashv ^= _mur_k; \
+ _mur_key += 4; \
+ } \
+ switch(_mur_len) \
+ { \
+ case 3: hashv ^= _mur_key[2] << 16; \
+ case 2: hashv ^= _mur_key[1] << 8; \
+ case 1: hashv ^= _mur_key[0]; \
+ hashv *= _mur_m; \
+ } \
+ \
+ hashv ^= hashv >> 13; \
+ hashv *= _mur_m; \
+ hashv ^= hashv >> 15; \
+ } \
+ bkt = hashv & (num_bkts-1); \
+} while(0)
+#endif /* HASH_USING_NO_STRICT_ALIASING */
+
+/* key comparison function; return 0 if keys equal */
+#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
+
+/* iterate over items in a known bucket to find desired item */
+#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
+do { \
+ if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \
+ else out=NULL; \
+ while (out) { \
+ if (out->hh.keylen == keylen_in) { \
+ if ((HASH_KEYCMP(out->hh.key,keyptr,keylen_in)) == 0) break; \
+ } \
+ if (out->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,out->hh.hh_next)); \
+ else out = NULL; \
+ } \
+} while(0)
+
+/* add an item to a bucket */
+#define HASH_ADD_TO_BKT(head,addhh) \
+do { \
+ head.count++; \
+ (addhh)->hh_next = head.hh_head; \
+ (addhh)->hh_prev = NULL; \
+ if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \
+ (head).hh_head=addhh; \
+ if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \
+ && (addhh)->tbl->noexpand != 1) { \
+ HASH_EXPAND_BUCKETS((addhh)->tbl); \
+ } \
+} while(0)
+
+/* remove an item from a given bucket */
+#define HASH_DEL_IN_BKT(hh,head,hh_del) \
+ (head).count--; \
+ if ((head).hh_head == hh_del) { \
+ (head).hh_head = hh_del->hh_next; \
+ } \
+ if (hh_del->hh_prev) { \
+ hh_del->hh_prev->hh_next = hh_del->hh_next; \
+ } \
+ if (hh_del->hh_next) { \
+ hh_del->hh_next->hh_prev = hh_del->hh_prev; \
+ }
+
+/* Bucket expansion has the effect of doubling the number of buckets
+ * and redistributing the items into the new buckets. Ideally the
+ * items will distribute more or less evenly into the new buckets
+ * (the extent to which this is true is a measure of the quality of
+ * the hash function as it applies to the key domain).
+ *
+ * With the items distributed into more buckets, the chain length
+ * (item count) in each bucket is reduced. Thus by expanding buckets
+ * the hash keeps a bound on the chain length. This bounded chain
+ * length is the essence of how a hash provides constant time lookup.
+ *
+ * The calculation of tbl->ideal_chain_maxlen below deserves some
+ * explanation. First, keep in mind that we're calculating the ideal
+ * maximum chain length based on the *new* (doubled) bucket count.
+ * In fractions this is just n/b (n=number of items,b=new num buckets).
+ * Since the ideal chain length is an integer, we want to calculate
+ * ceil(n/b). We don't depend on floating point arithmetic in this
+ * hash, so to calculate ceil(n/b) with integers we could write
+ *
+ * ceil(n/b) = (n/b) + ((n%b)?1:0)
+ *
+ * and in fact a previous version of this hash did just that.
+ * But now we have improved things a bit by recognizing that b is
+ * always a power of two. We keep its base 2 log handy (call it lb),
+ * so now we can write this with a bit shift and logical AND:
+ *
+ * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
+ *
+ */
+#define HASH_EXPAND_BUCKETS(tbl) \
+do { \
+ unsigned _he_bkt; \
+ unsigned _he_bkt_i; \
+ struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
+ UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
+ _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
+ 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
+ if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \
+ memset(_he_new_buckets, 0, \
+ 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
+ tbl->ideal_chain_maxlen = \
+ (tbl->num_items >> (tbl->log2_num_buckets+1)) + \
+ ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \
+ tbl->nonideal_items = 0; \
+ for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \
+ { \
+ _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \
+ while (_he_thh) { \
+ _he_hh_nxt = _he_thh->hh_next; \
+ HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \
+ _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \
+ if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
+ tbl->nonideal_items++; \
+ _he_newbkt->expand_mult = _he_newbkt->count / \
+ tbl->ideal_chain_maxlen; \
+ } \
+ _he_thh->hh_prev = NULL; \
+ _he_thh->hh_next = _he_newbkt->hh_head; \
+ if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \
+ _he_thh; \
+ _he_newbkt->hh_head = _he_thh; \
+ _he_thh = _he_hh_nxt; \
+ } \
+ } \
+ tbl->num_buckets *= 2; \
+ tbl->log2_num_buckets++; \
+ uthash_free( tbl->buckets ); \
+ tbl->buckets = _he_new_buckets; \
+ tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \
+ (tbl->ineff_expands+1) : 0; \
+ if (tbl->ineff_expands > 1) { \
+ tbl->noexpand=1; \
+ uthash_noexpand_fyi(tbl); \
+ } \
+ uthash_expand_fyi(tbl); \
+} while(0)
+
+
+/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
+/* Note that HASH_SORT assumes the hash handle name to be hh.
+ * HASH_SRT was added to allow the hash handle name to be passed in. */
+#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
+#define HASH_SRT(hh,head,cmpfcn) \
+do { \
+ unsigned _hs_i; \
+ unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
+ struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
+ if (head) { \
+ _hs_insize = 1; \
+ _hs_looping = 1; \
+ _hs_list = &((head)->hh); \
+ while (_hs_looping) { \
+ _hs_p = _hs_list; \
+ _hs_list = NULL; \
+ _hs_tail = NULL; \
+ _hs_nmerges = 0; \
+ while (_hs_p) { \
+ _hs_nmerges++; \
+ _hs_q = _hs_p; \
+ _hs_psize = 0; \
+ for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \
+ _hs_psize++; \
+ _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
+ ((void*)((char*)(_hs_q->next) + \
+ (head)->hh.tbl->hho)) : NULL); \
+ if (! (_hs_q) ) break; \
+ } \
+ _hs_qsize = _hs_insize; \
+ while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \
+ if (_hs_psize == 0) { \
+ _hs_e = _hs_q; \
+ _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
+ ((void*)((char*)(_hs_q->next) + \
+ (head)->hh.tbl->hho)) : NULL); \
+ _hs_qsize--; \
+ } else if ( (_hs_qsize == 0) || !(_hs_q) ) { \
+ _hs_e = _hs_p; \
+ _hs_p = (UT_hash_handle*)((_hs_p->next) ? \
+ ((void*)((char*)(_hs_p->next) + \
+ (head)->hh.tbl->hho)) : NULL); \
+ _hs_psize--; \
+ } else if (( \
+ cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
+ DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
+ ) <= 0) { \
+ _hs_e = _hs_p; \
+ _hs_p = (UT_hash_handle*)((_hs_p->next) ? \
+ ((void*)((char*)(_hs_p->next) + \
+ (head)->hh.tbl->hho)) : NULL); \
+ _hs_psize--; \
+ } else { \
+ _hs_e = _hs_q; \
+ _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
+ ((void*)((char*)(_hs_q->next) + \
+ (head)->hh.tbl->hho)) : NULL); \
+ _hs_qsize--; \
+ } \
+ if ( _hs_tail ) { \
+ _hs_tail->next = ((_hs_e) ? \
+ ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \
+ } else { \
+ _hs_list = _hs_e; \
+ } \
+ _hs_e->prev = ((_hs_tail) ? \
+ ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \
+ _hs_tail = _hs_e; \
+ } \
+ _hs_p = _hs_q; \
+ } \
+ _hs_tail->next = NULL; \
+ if ( _hs_nmerges <= 1 ) { \
+ _hs_looping=0; \
+ (head)->hh.tbl->tail = _hs_tail; \
+ DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
+ } \
+ _hs_insize *= 2; \
+ } \
+ HASH_FSCK(hh,head); \
+ } \
+} while (0)
+
+/* This function selects items from one hash into another hash.
+ * The end result is that the selected items have dual presence
+ * in both hashes. There is no copy of the items made; rather
+ * they are added into the new hash through a secondary hash
+ * hash handle that must be present in the structure. */
+#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
+do { \
+ unsigned _src_bkt, _dst_bkt; \
+ void *_last_elt=NULL, *_elt; \
+ UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
+ ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
+ if (src) { \
+ for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
+ for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
+ _src_hh; \
+ _src_hh = _src_hh->hh_next) { \
+ _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
+ if (cond(_elt)) { \
+ _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
+ _dst_hh->key = _src_hh->key; \
+ _dst_hh->keylen = _src_hh->keylen; \
+ _dst_hh->hashv = _src_hh->hashv; \
+ _dst_hh->prev = _last_elt; \
+ _dst_hh->next = NULL; \
+ if (_last_elt_hh) { _last_elt_hh->next = _elt; } \
+ if (!dst) { \
+ DECLTYPE_ASSIGN(dst,_elt); \
+ HASH_MAKE_TABLE(hh_dst,dst); \
+ } else { \
+ _dst_hh->tbl = (dst)->hh_dst.tbl; \
+ } \
+ HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
+ HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \
+ (dst)->hh_dst.tbl->num_items++; \
+ _last_elt = _elt; \
+ _last_elt_hh = _dst_hh; \
+ } \
+ } \
+ } \
+ } \
+ HASH_FSCK(hh_dst,dst); \
+} while (0)
+
+#define HASH_CLEAR(hh,head) \
+do { \
+ if (head) { \
+ uthash_free((head)->hh.tbl->buckets ); \
+ uthash_free((head)->hh.tbl); \
+ (head)=NULL; \
+ } \
+} while(0)
+
+/* obtain a count of items in the hash */
+#define HASH_COUNT(head) HASH_CNT(hh,head)
+#define HASH_CNT(hh,head) (head?(head->hh.tbl->num_items):0)
+
+typedef struct UT_hash_bucket {
+ struct UT_hash_handle *hh_head;
+ unsigned count;
+
+ /* expand_mult is normally set to 0. In this situation, the max chain length
+ * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
+ * the bucket's chain exceeds this length, bucket expansion is triggered).
+ * However, setting expand_mult to a non-zero value delays bucket expansion
+ * (that would be triggered by additions to this particular bucket)
+ * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
+ * (The multiplier is simply expand_mult+1). The whole idea of this
+ * multiplier is to reduce bucket expansions, since they are expensive, in
+ * situations where we know that a particular bucket tends to be overused.
+ * It is better to let its chain length grow to a longer yet-still-bounded
+ * value, than to do an O(n) bucket expansion too often.
+ */
+ unsigned expand_mult;
+
+} UT_hash_bucket;
+
+/* random signature used only to find hash tables in external analysis */
+#define HASH_SIGNATURE 0xa0111fe1
+#define HASH_BLOOM_SIGNATURE 0xb12220f2
+
+typedef struct UT_hash_table {
+ UT_hash_bucket *buckets;
+ unsigned num_buckets, log2_num_buckets;
+ unsigned num_items;
+ struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
+ ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
+
+ /* in an ideal situation (all buckets used equally), no bucket would have
+ * more than ceil(#items/#buckets) items. that's the ideal chain length. */
+ unsigned ideal_chain_maxlen;
+
+ /* nonideal_items is the number of items in the hash whose chain position
+ * exceeds the ideal chain maxlen. these items pay the penalty for an uneven
+ * hash distribution; reaching them in a chain traversal takes >ideal steps */
+ unsigned nonideal_items;
+
+ /* ineffective expands occur when a bucket doubling was performed, but
+ * afterward, more than half the items in the hash had nonideal chain
+ * positions. If this happens on two consecutive expansions we inhibit any
+ * further expansion, as it's not helping; this happens when the hash
+ * function isn't a good fit for the key domain. When expansion is inhibited
+ * the hash will still work, albeit no longer in constant time. */
+ unsigned ineff_expands, noexpand;
+
+ uint32_t signature; /* used only to find hash tables in external analysis */
+#ifdef HASH_BLOOM
+ uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
+ uint8_t *bloom_bv;
+ char bloom_nbits;
+#endif
+
+} UT_hash_table;
+
+typedef struct UT_hash_handle {
+ struct UT_hash_table *tbl;
+ void *prev; /* prev element in app order */
+ void *next; /* next element in app order */
+ struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
+ struct UT_hash_handle *hh_next; /* next hh in bucket order */
+ void *key; /* ptr to enclosing struct's key */
+ unsigned keylen; /* enclosing struct's key len */
+ unsigned hashv; /* result of hash-fcn(key) */
+} UT_hash_handle;
+
+#endif /* UTHASH_H */
--- /dev/null
+/*
+Copyright (c) 2007-2010, Troy D. Hanson http://uthash.sourceforge.net
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef UTLIST_H
+#define UTLIST_H
+
+#define UTLIST_VERSION 1.9
+
+/*
+ * This file contains macros to manipulate singly and doubly-linked lists.
+ *
+ * 1. LL_ macros: singly-linked lists.
+ * 2. DL_ macros: doubly-linked lists.
+ * 3. CDL_ macros: circular doubly-linked lists.
+ *
+ * To use singly-linked lists, your structure must have a "next" pointer.
+ * To use doubly-linked lists, your structure must "prev" and "next" pointers.
+ * Either way, the pointer to the head of the list must be initialized to NULL.
+ *
+ * ----------------.EXAMPLE -------------------------
+ * struct item {
+ * int id;
+ * struct item *prev, *next;
+ * }
+ *
+ * struct item *list = NULL:
+ *
+ * int main() {
+ * struct item *item;
+ * ... allocate and populate item ...
+ * DL_APPEND(list, item);
+ * }
+ * --------------------------------------------------
+ *
+ * For doubly-linked lists, the append and delete macros are O(1)
+ * For singly-linked lists, append and delete are O(n) but prepend is O(1)
+ * The sort macro is O(n log(n)) for all types of single/double/circular lists.
+ */
+
+/* These macros use decltype or the earlier __typeof GNU extension.
+ As decltype is only available in newer compilers (VS2010 or gcc 4.3+
+ when compiling c++ code), this code uses whatever method is needed
+ or, for VS2008 where neither is available, uses casting workarounds. */
+
+#ifndef DECLTYPE
+#ifdef _MSC_VER /* MS compiler */
+#if _MSC_VER >= 1600 && __cplusplus /* VS2010 and newer in C++ mode */
+#define DECLTYPE(x) decltype(x)
+#else /* VS2008 or older (or VS2010 in C mode) */
+#define NO_DECLTYPE
+#define DECLTYPE(x) char*
+#endif
+#else /* GNU, Sun and other compilers */
+#define DECLTYPE(x) __typeof(x)
+#endif
+#endif // DECLTYPE
+
+/* for VS2008 we use some workarounds to get around the lack of decltype,
+ * namely, we always reassign our tmp variable to the list head if we need
+ * to dereference its prev/next pointers, and save/restore the real head.*/
+#ifdef NO_DECLTYPE
+#define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
+#define _NEXT(elt,list) ((char*)((list)->next))
+#define _NEXTASGN(elt,list,to) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
+#define _PREV(elt,list) ((char*)((list)->prev))
+#define _PREVASGN(elt,list,to) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
+#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
+#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
+#else
+#define _SV(elt,list)
+#define _NEXT(elt,list) ((elt)->next)
+#define _NEXTASGN(elt,list,to) ((elt)->next)=(to)
+#define _PREV(elt,list) ((elt)->prev)
+#define _PREVASGN(elt,list,to) ((elt)->prev)=(to)
+#define _RS(list)
+#define _CASTASGN(a,b) (a)=(b)
+#endif
+
+/******************************************************************************
+ * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort *
+ * Unwieldy variable names used here to avoid shadowing passed-in variables. *
+ *****************************************************************************/
+#define LL_SORT(list, cmp) \
+do { \
+ DECLTYPE(list) _ls_p; \
+ DECLTYPE(list) _ls_q; \
+ DECLTYPE(list) _ls_e; \
+ DECLTYPE(list) _ls_tail; \
+ DECLTYPE(list) _ls_oldhead; \
+ DECLTYPE(list) _tmp; \
+ int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
+ if (list) { \
+ _ls_insize = 1; \
+ _ls_looping = 1; \
+ while (_ls_looping) { \
+ _CASTASGN(_ls_p,list); \
+ _CASTASGN(_ls_oldhead,list); \
+ list = NULL; \
+ _ls_tail = NULL; \
+ _ls_nmerges = 0; \
+ while (_ls_p) { \
+ _ls_nmerges++; \
+ _ls_q = _ls_p; \
+ _ls_psize = 0; \
+ for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
+ _ls_psize++; \
+ _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
+ if (!_ls_q) break; \
+ } \
+ _ls_qsize = _ls_insize; \
+ while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
+ if (_ls_psize == 0) { \
+ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
+ } else if (_ls_qsize == 0 || !_ls_q) { \
+ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
+ } else if (cmp(_ls_p,_ls_q) <= 0) { \
+ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
+ } else { \
+ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
+ } \
+ if (_ls_tail) { \
+ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
+ } else { \
+ _CASTASGN(list,_ls_e); \
+ } \
+ _ls_tail = _ls_e; \
+ } \
+ _ls_p = _ls_q; \
+ } \
+ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
+ if (_ls_nmerges <= 1) { \
+ _ls_looping=0; \
+ } \
+ _ls_insize *= 2; \
+ } \
+ } else _tmp=NULL; /* quiet gcc unused variable warning */ \
+} while (0)
+
+#define DL_SORT(list, cmp) \
+do { \
+ DECLTYPE(list) _ls_p; \
+ DECLTYPE(list) _ls_q; \
+ DECLTYPE(list) _ls_e; \
+ DECLTYPE(list) _ls_tail; \
+ DECLTYPE(list) _ls_oldhead; \
+ DECLTYPE(list) _tmp; \
+ int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
+ if (list) { \
+ _ls_insize = 1; \
+ _ls_looping = 1; \
+ while (_ls_looping) { \
+ _CASTASGN(_ls_p,list); \
+ _CASTASGN(_ls_oldhead,list); \
+ list = NULL; \
+ _ls_tail = NULL; \
+ _ls_nmerges = 0; \
+ while (_ls_p) { \
+ _ls_nmerges++; \
+ _ls_q = _ls_p; \
+ _ls_psize = 0; \
+ for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
+ _ls_psize++; \
+ _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
+ if (!_ls_q) break; \
+ } \
+ _ls_qsize = _ls_insize; \
+ while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
+ if (_ls_psize == 0) { \
+ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
+ } else if (_ls_qsize == 0 || !_ls_q) { \
+ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
+ } else if (cmp(_ls_p,_ls_q) <= 0) { \
+ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
+ } else { \
+ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
+ } \
+ if (_ls_tail) { \
+ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
+ } else { \
+ _CASTASGN(list,_ls_e); \
+ } \
+ _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
+ _ls_tail = _ls_e; \
+ } \
+ _ls_p = _ls_q; \
+ } \
+ _CASTASGN(list->prev, _ls_tail); \
+ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
+ if (_ls_nmerges <= 1) { \
+ _ls_looping=0; \
+ } \
+ _ls_insize *= 2; \
+ } \
+ } else _tmp=NULL; /* quiet gcc unused variable warning */ \
+} while (0)
+
+#define CDL_SORT(list, cmp) \
+do { \
+ DECLTYPE(list) _ls_p; \
+ DECLTYPE(list) _ls_q; \
+ DECLTYPE(list) _ls_e; \
+ DECLTYPE(list) _ls_tail; \
+ DECLTYPE(list) _ls_oldhead; \
+ DECLTYPE(list) _tmp; \
+ DECLTYPE(list) _tmp2; \
+ int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
+ if (list) { \
+ _ls_insize = 1; \
+ _ls_looping = 1; \
+ while (_ls_looping) { \
+ _CASTASGN(_ls_p,list); \
+ _CASTASGN(_ls_oldhead,list); \
+ list = NULL; \
+ _ls_tail = NULL; \
+ _ls_nmerges = 0; \
+ while (_ls_p) { \
+ _ls_nmerges++; \
+ _ls_q = _ls_p; \
+ _ls_psize = 0; \
+ for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
+ _ls_psize++; \
+ _SV(_ls_q,list); \
+ if (_NEXT(_ls_q,list) == _ls_oldhead) { \
+ _ls_q = NULL; \
+ } else { \
+ _ls_q = _NEXT(_ls_q,list); \
+ } \
+ _RS(list); \
+ if (!_ls_q) break; \
+ } \
+ _ls_qsize = _ls_insize; \
+ while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
+ if (_ls_psize == 0) { \
+ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
+ if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
+ } else if (_ls_qsize == 0 || !_ls_q) { \
+ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
+ if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
+ } else if (cmp(_ls_p,_ls_q) <= 0) { \
+ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
+ if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
+ } else { \
+ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
+ if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
+ } \
+ if (_ls_tail) { \
+ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
+ } else { \
+ _CASTASGN(list,_ls_e); \
+ } \
+ _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
+ _ls_tail = _ls_e; \
+ } \
+ _ls_p = _ls_q; \
+ } \
+ _CASTASGN(list->prev,_ls_tail); \
+ _CASTASGN(_tmp2,list); \
+ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp2); _RS(list); \
+ if (_ls_nmerges <= 1) { \
+ _ls_looping=0; \
+ } \
+ _ls_insize *= 2; \
+ } \
+ } else _tmp=NULL; /* quiet gcc unused variable warning */ \
+} while (0)
+
+/******************************************************************************
+ * singly linked list macros (non-circular) *
+ *****************************************************************************/
+#define LL_PREPEND(head,add) \
+do { \
+ (add)->next = head; \
+ head = add; \
+} while (0)
+
+#define LL_APPEND(head,add) \
+do { \
+ DECLTYPE(head) _tmp; \
+ (add)->next=NULL; \
+ if (head) { \
+ _tmp = head; \
+ while (_tmp->next) { _tmp = _tmp->next; } \
+ _tmp->next=(add); \
+ } else { \
+ (head)=(add); \
+ } \
+} while (0)
+
+#define LL_DELETE(head,del) \
+do { \
+ DECLTYPE(head) _tmp; \
+ if ((head) == (del)) { \
+ (head)=(head)->next; \
+ } else { \
+ _tmp = head; \
+ while (_tmp->next && (_tmp->next != (del))) { \
+ _tmp = _tmp->next; \
+ } \
+ if (_tmp->next) { \
+ _tmp->next = ((del)->next); \
+ } \
+ } \
+} while (0)
+
+/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */
+#define LL_APPEND_VS2008(head,add) \
+do { \
+ if (head) { \
+ (add)->next = head; /* use add->next as a temp variable */ \
+ while ((add)->next->next) { (add)->next = (add)->next->next; } \
+ (add)->next->next=(add); \
+ } else { \
+ (head)=(add); \
+ } \
+ (add)->next=NULL; \
+} while (0)
+
+#define LL_DELETE_VS2008(head,del) \
+do { \
+ if ((head) == (del)) { \
+ (head)=(head)->next; \
+ } else { \
+ char *_tmp = (char*)(head); \
+ while (head->next && (head->next != (del))) { \
+ head = head->next; \
+ } \
+ if (head->next) { \
+ head->next = ((del)->next); \
+ } \
+ { \
+ char **_head_alias = (char**)&(head); \
+ *_head_alias = _tmp; \
+ } \
+ } \
+} while (0)
+#ifdef NO_DECLTYPE
+#undef LL_APPEND
+#define LL_APPEND LL_APPEND_VS2008
+#undef LL_DELETE
+#define LL_DELETE LL_DELETE_VS2008
+#endif
+/* end VS2008 replacements */
+
+#define LL_FOREACH(head,el) \
+ for(el=head;el;el=el->next)
+
+#define LL_FOREACH_SAFE(head,el,tmp) \
+ for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
+
+#define LL_SEARCH_SCALAR(head,out,field,val) \
+do { \
+ LL_FOREACH(head,out) { \
+ if ((out)->field == (val)) break; \
+ } \
+} while(0)
+
+#define LL_SEARCH(head,out,elt,cmp) \
+do { \
+ LL_FOREACH(head,out) { \
+ if ((cmp(out,elt))==0) break; \
+ } \
+} while(0)
+
+/******************************************************************************
+ * doubly linked list macros (non-circular) *
+ *****************************************************************************/
+#define DL_PREPEND(head,add) \
+do { \
+ (add)->next = head; \
+ if (head) { \
+ (add)->prev = (head)->prev; \
+ (head)->prev = (add); \
+ } else { \
+ (add)->prev = (add); \
+ } \
+ (head) = (add); \
+} while (0)
+
+#define DL_APPEND(head,add) \
+do { \
+ if (head) { \
+ (add)->prev = (head)->prev; \
+ (head)->prev->next = (add); \
+ (head)->prev = (add); \
+ (add)->next = NULL; \
+ } else { \
+ (head)=(add); \
+ (head)->prev = (head); \
+ (head)->next = NULL; \
+ } \
+} while (0);
+
+#define DL_DELETE(head,del) \
+do { \
+ if ((del)->prev == (del)) { \
+ (head)=NULL; \
+ } else if ((del)==(head)) { \
+ (del)->next->prev = (del)->prev; \
+ (head) = (del)->next; \
+ } else { \
+ (del)->prev->next = (del)->next; \
+ if ((del)->next) { \
+ (del)->next->prev = (del)->prev; \
+ } else { \
+ (head)->prev = (del)->prev; \
+ } \
+ } \
+} while (0);
+
+
+#define DL_FOREACH(head,el) \
+ for(el=head;el;el=el->next)
+
+/* this version is safe for deleting the elements during iteration */
+#define DL_FOREACH_SAFE(head,el,tmp) \
+ for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
+
+/* these are identical to their singly-linked list counterparts */
+#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
+#define DL_SEARCH LL_SEARCH
+
+/******************************************************************************
+ * circular doubly linked list macros *
+ *****************************************************************************/
+#define CDL_PREPEND(head,add) \
+do { \
+ if (head) { \
+ (add)->prev = (head)->prev; \
+ (add)->next = (head); \
+ (head)->prev = (add); \
+ (add)->prev->next = (add); \
+ } else { \
+ (add)->prev = (add); \
+ (add)->next = (add); \
+ } \
+(head)=(add); \
+} while (0)
+
+#define CDL_DELETE(head,del) \
+do { \
+ if ( ((head)==(del)) && ((head)->next == (head))) { \
+ (head) = 0L; \
+ } else { \
+ (del)->next->prev = (del)->prev; \
+ (del)->prev->next = (del)->next; \
+ if ((del) == (head)) (head)=(del)->next; \
+ } \
+} while (0);
+
+#define CDL_FOREACH(head,el) \
+ for(el=head;el;el=(el->next==head ? 0L : el->next))
+
+#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
+ for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \
+ (el) && ((tmp2)=(el)->next, 1); \
+ ((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
+
+#define CDL_SEARCH_SCALAR(head,out,field,val) \
+do { \
+ CDL_FOREACH(head,out) { \
+ if ((out)->field == (val)) break; \
+ } \
+} while(0)
+
+#define CDL_SEARCH(head,out,elt,cmp) \
+do { \
+ CDL_FOREACH(head,out) { \
+ if ((cmp(out,elt))==0) break; \
+ } \
+} while(0)
+
+#endif /* UTLIST_H */
+
--- /dev/null
+/*
+ * 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 <Availability.h>
+
+/**
+ @file
+ cocos2d (cc) configuration file
+*/
+
+/** @def CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
+ If enabled, the texture coordinates will be calculated by using this formula:
+ - texCoord.left = (rect.origin.x*2+1) / (texture.wide*2);
+ - texCoord.right = texCoord.left + (rect.size.width*2-2)/(texture.wide*2);
+
+ The same for bottom and top.
+
+ This formula prevents artifacts by using 99% of the texture.
+ The "correct" way to prevent artifacts is by using the spritesheet-artifact-fixer.py or a similar tool.
+
+ Affected nodes:
+ - CCSprite / CCSpriteBatchNode and subclasses: CCBitmapFontAtlas, CCTMXTiledMap
+ - CCLabelAtlas
+ - CCQuadParticleSystem
+ - CCTileMap
+
+ To enabled set it to 1. Disabled by default.
+
+ @since v0.99.5
+ */
+#define CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL 0
+
+
+/** @def CC_FONT_LABEL_SUPPORT
+ If enabled, FontLabel will be used to render .ttf files.
+ If the .ttf file is not found, then it will use the standard UIFont class
+ If disabled, the standard UIFont class will be used.
+
+ To disable set it to 0. Enabled by default.
+
+ Only valid for cocos2d-ios. Not supported on cocos2d-mac
+ */
+#define CC_FONT_LABEL_SUPPORT 1
+
+/** @def CC_DIRECTOR_FAST_FPS
+ If enabled, then the FPS will be drawn using CCLabelAtlas (fast rendering).
+ You will need to add the fps_images.png to your project.
+ If disabled, the FPS will be rendered using CCLabel (slow rendering)
+
+ To enable set it to a value different than 0. Enabled by default.
+ */
+#define CC_DIRECTOR_FAST_FPS 1
+
+/** @def CC_DIRECTOR_FPS_INTERVAL
+ Senconds between FPS updates.
+ 0.5 seconds, means that the FPS number will be updated every 0.5 seconds.
+ Having a bigger number means a more reliable FPS
+
+ Default value: 0.1f
+ */
+#define CC_DIRECTOR_FPS_INTERVAL (0.1f)
+
+/** @def CC_DIRECTOR_DISPATCH_FAST_EVENTS
+ If enabled, and only when it is used with CCFastDirector, the main loop will wait 0.04 seconds to
+ dispatch all the events, even if there are not events to dispatch.
+ If your game uses lot's of events (eg: touches) it might be a good idea to enable this feature.
+ Otherwise, it is safe to leave it disabled.
+
+ To enable set it to 1. Disabled by default.
+
+ @warning This feature is experimental
+ */
+#define CC_DIRECTOR_DISPATCH_FAST_EVENTS 0
+
+/** @def CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
+ If enabled, cocos2d-mac will run on the Display Link thread. If disabled cocos2d-mac will run in its own thread.
+
+ If enabled, the images will be drawn at the "correct" time, but the events might not be very responsive.
+ If disabled, some frames might be skipped, but the events will be dispatched as they arrived.
+
+ To enable set it to a 1, to disable it set to 0. Enabled by default.
+
+ Only valid for cocos2d-mac. Not supported on cocos2d-ios.
+
+ */
+#define CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD 1
+
+/** @def CC_COCOSNODE_RENDER_SUBPIXEL
+ If enabled, the CCNode objects (CCSprite, CCLabel,etc) will be able to render in subpixels.
+ If disabled, integer pixels will be used.
+
+ To enable set it to 1. Enabled by default.
+ */
+#define CC_COCOSNODE_RENDER_SUBPIXEL 1
+
+/** @def CC_SPRITEBATCHNODE_RENDER_SUBPIXEL
+ If enabled, the CCSprite objects rendered with CCSpriteBatchNode will be able to render in subpixels.
+ If disabled, integer pixels will be used.
+
+ To enable set it to 1. Enabled by default.
+ */
+#define CC_SPRITEBATCHNODE_RENDER_SUBPIXEL 1
+
+
+#if defined(__ARM_NEON__) || TARGET_IPHONE_SIMULATOR || defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+/** @def CC_USES_VBO
+ If enabled, batch nodes (texture atlas and particle system) will use VBO instead of vertex list (VBO is recommended by Apple)
+
+ To enable set it to 1.
+ Enabled by default on iPhone with ARMv7 processors, iPhone Simulator and Mac
+ Disabled by default on iPhone with ARMv6 processors.
+
+ @since v0.99.5
+ */
+#define CC_USES_VBO 1
+#else
+#define CC_USES_VBO 0
+#endif
+
+/** @def CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
+ If enabled, CCNode will transform the nodes using a cached Affine matrix.
+ If disabled, the node will be transformed using glTranslate,glRotate,glScale.
+ Using the affine matrix only requires 2 GL calls.
+ Using the translate/rotate/scale requires 5 GL calls.
+ But computing the Affine matrix is relative expensive.
+ But according to performance tests, Affine matrix performs better.
+ This parameter doesn't affect SpriteSheet nodes.
+
+ To enable set it to a value different than 0. Enabled by default.
+
+ */
+#define CC_NODE_TRANSFORM_USING_AFFINE_MATRIX 1
+
+/** @def CC_OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA
+ If most of your imamges have pre-multiplied alpha, set it to 1 (if you are going to use .PNG/.JPG file images).
+ Only set to 0 if ALL your images by-pass Apple UIImage loading system (eg: if you use libpng or PVR images)
+
+ To enable set it to a value different than 0. Enabled by default.
+
+ @since v0.99.5
+ */
+#define CC_OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA 1
+
+/** @def CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
+ Use GL_TRIANGLE_STRIP instead of GL_TRIANGLES when rendering the texture atlas.
+ It seems it is the recommend way, but it is much slower, so, enable it at your own risk
+
+ To enable set it to a value different than 0. Disabled by default.
+
+ */
+#define CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP 0
+
+
+/** @def CC_TEXTURE_NPOT_SUPPORT
+ If enabled, NPOT textures will be used where available. Only 3rd gen (and newer) devices support NPOT 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}
+
+ To enable set it to a value different than 0. Disabled by default.
+
+ @since v0.99.2
+ */
+#define CC_TEXTURE_NPOT_SUPPORT 0
+
+/** @def CC_RETINA_DISPLAY_SUPPORT
+ If enabled, cocos2d supports retina display.
+ For performance reasons, it's recommended disable it in games without retina display support, like iPad only games.
+
+ To enable set it to 1. Use 0 to disable it. Enabled by default.
+
+ @since v0.99.5
+ */
+#define CC_RETINA_DISPLAY_SUPPORT 1
+
+/** @def CC_RETINA_DISPLAY_FILENAME_SUFFIX
+ It's the suffix that will be appended to the files in order to load "retina display" images.
+
+ On an iPhone4 with Retina Display support enabled, the file @"sprite-hd.png" will be loaded instead of @"sprite.png".
+ If the file doesn't exist it will use the non-retina display image.
+
+ Platforms: Only used on Retina Display devices like iPhone 4.
+
+ @since v0.99.5
+ */
+#define CC_RETINA_DISPLAY_FILENAME_SUFFIX @"-hd"
+
+/** @def CC_USE_RGBA32_LABELS_ON_NEON_ARCH
+ If enabled, it will use RGBA8888 (32-bit textures) on Neon devices for CCLabelTTF objects.
+ If it is disabled, or if it is used on another architecture it will use A8 (8-bit textures).
+ On Neon devices, RGBA8888 textures are 6% faster than A8 textures, but then will consule 4x memory.
+
+ This feature is disabled by default.
+
+ Platforms: Only used on ARM Neon architectures like iPhone 3GS or newer and iPad.
+
+ @since v0.99.5
+ */
+#define CC_USE_RGBA32_LABELS_ON_NEON_ARCH 0
+
+/** @def CC_SPRITE_DEBUG_DRAW
+ If enabled, all subclasses of CCSprite will draw a bounding box
+ Useful for debugging purposes only. It is recommened to leave it disabled.
+
+ To enable set it to a value different than 0. Disabled by default.
+ */
+#define CC_SPRITE_DEBUG_DRAW 0
+
+/** @def CC_SPRITEBATCHNODE_DEBUG_DRAW
+ If enabled, all subclasses of CCSprite that are rendered using an CCSpriteSheet draw a bounding box.
+ Useful for debugging purposes only. It is recommened to leave it disabled.
+
+ To enable set it to a value different than 0. Disabled by default.
+ */
+#define CC_SPRITEBATCHNODE_DEBUG_DRAW 0
+
+/** @def CC_BITMAPFONTATLAS_DEBUG_DRAW
+ If enabled, all subclasses of BitmapFontAtlas will draw a bounding box
+ Useful for debugging purposes only. It is recommened to leave it disabled.
+
+ To enable set it to a value different than 0. Disabled by default.
+ */
+#define CC_BITMAPFONTATLAS_DEBUG_DRAW 0
+
+/** @def CC_LABELATLAS_DEBUG_DRAW
+ If enabled, all subclasses of LabeltAtlas will draw a bounding box
+ Useful for debugging purposes only. It is recommened to leave it disabled.
+
+ To enable set it to a value different than 0. Disabled by default.
+ */
+#define CC_LABELATLAS_DEBUG_DRAW 0
+
+/** @def CC_ENABLE_PROFILERS
+ If enabled, will activate various profilers withing cocos2d. This statistical data will be output to the console
+ once per second showing average time (in milliseconds) required to execute the specific routine(s).
+ Useful for debugging purposes only. It is recommened to leave it disabled.
+
+ To enable set it to a value different than 0. Disabled by default.
+ */
+#define CC_ENABLE_PROFILERS 0
+
+/** @def CC_COMPATIBILITY_WITH_0_8
+ Enable it if you want to support v0.8 compatbility.
+ Basically, classes without namespaces will work.
+ It is recommended to disable compatibility once you have migrated your game to v0.9 to avoid class name polution
+
+ To enable set it to a value different than 0. Disabled by default.
+ */
+#define CC_COMPATIBILITY_WITH_0_8 0
+
+
+//
+// DON'T edit this macro.
+//
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+
+#if CC_RETINA_DISPLAY_SUPPORT
+#define CC_IS_RETINA_DISPLAY_SUPPORTED 1
+#else
+#define CC_IS_RETINA_DISPLAY_SUPPORTED 0
+#endif
+
+#elif __MAC_OS_X_VERSION_MAX_ALLOWED
+
+#define CC_IS_RETINA_DISPLAY_SUPPORTED 0
+
+#endif
+
+
--- /dev/null
+/*
+ * 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 <math.h>
+#import "ccConfig.h"
+
+#import <Foundation/Foundation.h>
+#import <Availability.h>
+
+/**
+ @file
+ cocos2d helper macros
+ */
+
+/*
+ * if COCOS2D_DEBUG is not defined, or if it is 0 then
+ * all CCLOGXXX macros will be disabled
+ *
+ * if COCOS2D_DEBUG==1 then:
+ * CCLOG() will be enabled
+ * CCLOGERROR() will be enabled
+ * CCLOGINFO() will be disabled
+ *
+ * if COCOS2D_DEBUG==2 or higher then:
+ * CCLOG() will be enabled
+ * CCLOGERROR() will be enabled
+ * CCLOGINFO() will be enabled
+ */
+#if !defined(COCOS2D_DEBUG) || COCOS2D_DEBUG == 0
+#define CCLOG(...) do {} while (0)
+#define CCLOGINFO(...) do {} while (0)
+#define CCLOGERROR(...) do {} while (0)
+
+#elif COCOS2D_DEBUG == 1
+#define CCLOG(...) NSLog(__VA_ARGS__)
+#define CCLOGERROR(...) NSLog(__VA_ARGS__)
+#define CCLOGINFO(...) do {} while (0)
+
+#elif COCOS2D_DEBUG > 1
+#define CCLOG(...) NSLog(__VA_ARGS__)
+#define CCLOGERROR(...) NSLog(__VA_ARGS__)
+#define CCLOGINFO(...) NSLog(__VA_ARGS__)
+#endif // COCOS2D_DEBUG
+
+/** @def CC_SWAP
+simple macro that swaps 2 variables
+*/
+#define CC_SWAP( x, y ) \
+({ __typeof__(x) temp = (x); \
+ x = y; y = temp; \
+})
+
+
+/** @def CCRANDOM_MINUS1_1
+ returns a random float between -1 and 1
+ */
+#define CCRANDOM_MINUS1_1() ((random() / (float)0x3fffffff )-1.0f)
+
+/** @def CCRANDOM_0_1
+ returns a random float between 0 and 1
+ */
+#define CCRANDOM_0_1() ((random() / (float)0x7fffffff ))
+
+/** @def CC_DEGREES_TO_RADIANS
+ converts degrees to radians
+ */
+#define CC_DEGREES_TO_RADIANS(__ANGLE__) ((__ANGLE__) * 0.01745329252f) // PI / 180
+
+/** @def CC_RADIANS_TO_DEGREES
+ converts radians to degrees
+ */
+#define CC_RADIANS_TO_DEGREES(__ANGLE__) ((__ANGLE__) * 57.29577951f) // PI * 180
+
+/** @def CC_BLEND_SRC
+default gl blend src function. Compatible with premultiplied alpha images.
+*/
+#if CC_OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA
+#define CC_BLEND_SRC GL_ONE
+#define CC_BLEND_DST GL_ONE_MINUS_SRC_ALPHA
+#else
+#define CC_BLEND_SRC GL_SRC_ALPHA
+#define CC_BLEND_DST GL_ONE_MINUS_SRC_ALPHA
+#endif // ! CC_OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA
+
+/** @def CC_ENABLE_DEFAULT_GL_STATES
+ GL states that are enabled:
+ - GL_TEXTURE_2D
+ - GL_VERTEX_ARRAY
+ - GL_TEXTURE_COORD_ARRAY
+ - GL_COLOR_ARRAY
+ */
+#define CC_ENABLE_DEFAULT_GL_STATES() { \
+ glEnableClientState(GL_VERTEX_ARRAY); \
+ glEnableClientState(GL_COLOR_ARRAY); \
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY); \
+ glEnable(GL_TEXTURE_2D); \
+}
+
+/** @def CC_DISABLE_DEFAULT_GL_STATES
+ Disable default GL states:
+ - GL_TEXTURE_2D
+ - GL_VERTEX_ARRAY
+ - GL_TEXTURE_COORD_ARRAY
+ - GL_COLOR_ARRAY
+ */
+#define CC_DISABLE_DEFAULT_GL_STATES() { \
+ glDisable(GL_TEXTURE_2D); \
+ glDisableClientState(GL_COLOR_ARRAY); \
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY); \
+ glDisableClientState(GL_VERTEX_ARRAY); \
+}
+
+/** @def CC_DIRECTOR_INIT
+ - Initializes an EAGLView with 0-bit depth format, and RGB565 render buffer.
+ - The EAGLView view will have multiple touches disabled.
+ - It will create a UIWindow and it will assign it the 'window' variable. 'window' must be declared before calling this marcro.
+ - It will parent the EAGLView to the created window
+ - If the firmware >= 3.1 it will create a Display Link Director. Else it will create an NSTimer director.
+ - It will try to run at 60 FPS.
+ - The FPS won't be displayed.
+ - The orientation will be portrait.
+ - It will connect the director with the EAGLView.
+
+ IMPORTANT: If you want to use another type of render buffer (eg: RGBA8)
+ or if you want to use a 16-bit or 24-bit depth buffer, you should NOT
+ use this macro. Instead, you should create the EAGLView manually.
+
+ @since v0.99.4
+ */
+#define CC_DIRECTOR_INIT() \
+do { \
+ window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; \
+ if( ! [CCDirector setDirectorType:kCCDirectorTypeDisplayLink] ) \
+ [CCDirector setDirectorType:kCCDirectorTypeNSTimer]; \
+ CCDirector *__director = [CCDirector sharedDirector]; \
+ [__director setDeviceOrientation:kCCDeviceOrientationPortrait]; \
+ [__director setDisplayFPS:NO]; \
+ [__director setAnimationInterval:1.0/60]; \
+ EAGLView *__glView = [EAGLView viewWithFrame:[window bounds] \
+ pixelFormat:kEAGLColorFormatRGB565 \
+ depthFormat:0 /* GL_DEPTH_COMPONENT24_OES */ \
+ preserveBackbuffer:NO \
+ sharegroup:nil \
+ multiSampling:NO \
+ numberOfSamples:0 \
+ ]; \
+ [__director setOpenGLView:__glView]; \
+ [window addSubview:__glView]; \
+ [window makeKeyAndVisible]; \
+} while(0)
+
+ /** @def CC_DIRECTOR_END
+ Stops and removes the director from memory.
+ Removes the EAGLView from its parent
+
+ @since v0.99.4
+ */
+#define CC_DIRECTOR_END() \
+do { \
+ CCDirector *__director = [CCDirector sharedDirector]; \
+ CC_GLVIEW *__view = [__director openGLView]; \
+ [__view removeFromSuperview]; \
+ [__director end]; \
+} while(0)
+
+
+#if CC_IS_RETINA_DISPLAY_SUPPORTED
+
+/****************************/
+/** RETINA DISPLAY ENABLED **/
+/****************************/
+
+/** @def CC_CONTENT_SCALE_FACTOR
+ On Mac it returns 1;
+ On iPhone it returns 2 if RetinaDisplay is On. Otherwise it returns 1
+ */
+#import "Platforms/iOS/CCDirectorIOS.h"
+#define CC_CONTENT_SCALE_FACTOR() __ccContentScaleFactor
+
+
+/** @def CC_RECT_PIXELS_TO_POINTS
+ Converts a rect in pixels to points
+ */
+#define CC_RECT_PIXELS_TO_POINTS(__pixels__) \
+ CGRectMake( (__pixels__).origin.x / CC_CONTENT_SCALE_FACTOR(), (__pixels__).origin.y / CC_CONTENT_SCALE_FACTOR(), \
+ (__pixels__).size.width / CC_CONTENT_SCALE_FACTOR(), (__pixels__).size.height / CC_CONTENT_SCALE_FACTOR() )
+
+/** @def CC_RECT_POINTS_TO_PIXELS
+ Converts a rect in points to pixels
+ */
+#define CC_RECT_POINTS_TO_PIXELS(__points__) \
+ CGRectMake( (__points__).origin.x * CC_CONTENT_SCALE_FACTOR(), (__points__).origin.y * CC_CONTENT_SCALE_FACTOR(), \
+ (__points__).size.width * CC_CONTENT_SCALE_FACTOR(), (__points__).size.height * CC_CONTENT_SCALE_FACTOR() )
+
+#else // retina disabled
+
+/*****************************/
+/** RETINA DISPLAY DISABLED **/
+/*****************************/
+
+#define CC_CONTENT_SCALE_FACTOR() 1
+#define CC_RECT_PIXELS_TO_POINTS(__pixels__) __pixels__
+#define CC_RECT_POINTS_TO_PIXELS(__points__) __points__
+
+#endif // CC_IS_RETINA_DISPLAY_SUPPORTED
--- /dev/null
+/*
+ * 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.
+ */
+
+
+/**
+ @file
+ cocos2d (cc) types
+*/
+
+#import <Availability.h>
+#import <Foundation/Foundation.h>
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#import <CoreGraphics/CGGeometry.h> // CGPoint
+#endif
+
+#import "Platforms/CCGL.h"
+
+/** RGB color composed of bytes 3 bytes
+@since v0.8
+ */
+typedef struct _ccColor3B
+{
+ GLubyte r;
+ GLubyte g;
+ GLubyte b;
+} ccColor3B;
+
+//! helper macro that creates an ccColor3B type
+static inline ccColor3B
+ccc3(const GLubyte r, const GLubyte g, const GLubyte b)
+{
+ ccColor3B c = {r, g, b};
+ return c;
+}
+//ccColor3B predefined colors
+//! White color (255,255,255)
+static const ccColor3B ccWHITE = {255,255,255};
+//! Yellow color (255,255,0)
+static const ccColor3B ccYELLOW = {255,255,0};
+//! Blue color (0,0,255)
+static const ccColor3B ccBLUE = {0,0,255};
+//! Green Color (0,255,0)
+static const ccColor3B ccGREEN = {0,255,0};
+//! Red Color (255,0,0,)
+static const ccColor3B ccRED = {255,0,0};
+//! Magenta Color (255,0,255)
+static const ccColor3B ccMAGENTA = {255,0,255};
+//! Black Color (0,0,0)
+static const ccColor3B ccBLACK = {0,0,0};
+//! Orange Color (255,127,0)
+static const ccColor3B ccORANGE = {255,127,0};
+//! Gray Color (166,166,166)
+static const ccColor3B ccGRAY = {166,166,166};
+
+/** RGBA color composed of 4 bytes
+@since v0.8
+*/
+typedef struct _ccColor4B
+{
+ GLubyte r;
+ GLubyte g;
+ GLubyte b;
+ GLubyte a;
+} ccColor4B;
+//! helper macro that creates an ccColor4B type
+static inline ccColor4B
+ccc4(const GLubyte r, const GLubyte g, const GLubyte b, const GLubyte o)
+{
+ ccColor4B c = {r, g, b, o};
+ return c;
+}
+
+
+/** RGBA color composed of 4 floats
+@since v0.8
+*/
+typedef struct _ccColor4F {
+ GLfloat r;
+ GLfloat g;
+ GLfloat b;
+ GLfloat a;
+} ccColor4F;
+
+/** Returns a ccColor4F from a ccColor3B. Alpha will be 1.
+ @since v0.99.1
+ */
+static inline ccColor4F ccc4FFromccc3B(ccColor3B c)
+{
+ return (ccColor4F){c.r/255.f, c.g/255.f, c.b/255.f, 1.f};
+}
+
+/** Returns a ccColor4F from a ccColor4B.
+ @since v0.99.1
+ */
+static inline ccColor4F ccc4FFromccc4B(ccColor4B c)
+{
+ return (ccColor4F){c.r/255.f, c.g/255.f, c.b/255.f, c.a/255.f};
+}
+
+/** returns YES if both ccColor4F are equal. Otherwise it returns NO.
+ @since v0.99.1
+ */
+static inline BOOL ccc4FEqual(ccColor4F a, ccColor4F b)
+{
+ return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
+}
+
+/** A vertex composed of 2 GLfloats: x, y
+ @since v0.8
+ */
+typedef struct _ccVertex2F
+{
+ GLfloat x;
+ GLfloat y;
+} ccVertex2F;
+
+/** A vertex composed of 2 floats: x, y
+ @since v0.8
+ */
+typedef struct _ccVertex3F
+{
+ GLfloat x;
+ GLfloat y;
+ GLfloat z;
+} ccVertex3F;
+
+/** A texcoord composed of 2 floats: u, y
+ @since v0.8
+ */
+typedef struct _ccTex2F {
+ GLfloat u;
+ GLfloat v;
+} ccTex2F;
+
+
+//! Point Sprite component
+typedef struct _ccPointSprite
+{
+ ccVertex2F pos; // 8 bytes
+ ccColor4F colors; // 16 bytes
+ GLfloat size; // 4 bytes
+} ccPointSprite;
+
+//! A 2D Quad. 4 * 2 floats
+typedef struct _ccQuad2 {
+ ccVertex2F tl;
+ ccVertex2F tr;
+ ccVertex2F bl;
+ ccVertex2F br;
+} ccQuad2;
+
+
+//! A 3D Quad. 4 * 3 floats
+typedef struct _ccQuad3 {
+ ccVertex3F bl;
+ ccVertex3F br;
+ ccVertex3F tl;
+ ccVertex3F tr;
+} ccQuad3;
+
+//! A 2D grid size
+typedef struct _ccGridSize
+{
+ NSInteger x;
+ NSInteger y;
+} ccGridSize;
+
+//! helper function to create a ccGridSize
+static inline ccGridSize
+ccg(const NSInteger x, const NSInteger y)
+{
+ ccGridSize v = {x, y};
+ return v;
+}
+
+//! a Point with a vertex point, a tex coord point and a color 4F
+typedef struct _ccV2F_C4F_T2F
+{
+ //! vertices (2F)
+ ccVertex2F vertices;
+ //! colors (4F)
+ ccColor4F colors;
+ //! tex coords (2F)
+ ccTex2F texCoords;
+} ccV2F_C4F_T2F;
+
+//! a Point with a vertex point, a tex coord point and a color 4B
+typedef struct _ccV3F_C4B_T2F
+{
+ //! vertices (3F)
+ ccVertex3F vertices; // 12 bytes
+// char __padding__[4];
+
+ //! colors (4B)
+ ccColor4B colors; // 4 bytes
+// char __padding2__[4];
+
+ // tex coords (2F)
+ ccTex2F texCoords; // 8 byts
+} ccV3F_C4B_T2F;
+
+//! 4 ccVertex3FTex2FColor4B
+typedef struct _ccV3F_C4B_T2F_Quad
+{
+ //! top left
+ ccV3F_C4B_T2F tl;
+ //! bottom left
+ ccV3F_C4B_T2F bl;
+ //! top right
+ ccV3F_C4B_T2F tr;
+ //! bottom right
+ ccV3F_C4B_T2F br;
+} ccV3F_C4B_T2F_Quad;
+
+//! 4 ccVertex2FTex2FColor4F Quad
+typedef struct _ccV2F_C4F_T2F_Quad
+{
+ //! bottom left
+ ccV2F_C4F_T2F bl;
+ //! bottom right
+ ccV2F_C4F_T2F br;
+ //! top left
+ ccV2F_C4F_T2F tl;
+ //! top right
+ ccV2F_C4F_T2F tr;
+} ccV2F_C4F_T2F_Quad;
+
+//! Blend Function used for textures
+typedef struct _ccBlendFunc
+{
+ //! source blend function
+ GLenum src;
+ //! destination blend function
+ GLenum dst;
+} ccBlendFunc;
+
+//! delta time type
+//! if you want more resolution redefine it as a double
+typedef float ccTime;
+//typedef double ccTime;
--- /dev/null
+/*
+ * 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.
+ */
+
+/** @mainpage cocos2d for iPhone API reference
+ *
+ * @image html Icon.png
+ *
+ * @section intro Introduction
+ * This is cocos2d API reference
+ *
+ * The programming guide is hosted here: http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:index
+ *
+ * <hr>
+ *
+ * @todo A native english speaker should check the grammar. We need your help!
+ *
+ */
+
+// 0x00 HI ME LO
+// 00 00 99 05
+#define COCOS2D_VERSION 0x00009905
+
+#import <Availability.h>
+
+//
+// all cocos2d include files
+//
+#import "ccConfig.h" // should be included first
+
+#import "CCActionManager.h"
+#import "CCAction.h"
+#import "CCActionInstant.h"
+#import "CCActionInterval.h"
+#import "CCActionEase.h"
+#import "CCActionCamera.h"
+#import "CCActionTween.h"
+#import "CCActionEase.h"
+#import "CCActionTiledGrid.h"
+#import "CCActionGrid3D.h"
+#import "CCActionGrid.h"
+#import "CCActionProgressTimer.h"
+#import "CCActionPageTurn3D.h"
+
+#import "CCAnimation.h"
+#import "CCAnimationCache.h"
+#import "CCSprite.h"
+#import "CCSpriteFrame.h"
+#import "CCSpriteSheet.h"
+#import "CCSpriteBatchNode.h"
+#import "CCSpriteFrameCache.h"
+
+#import "CCLabelTTF.h"
+#import "CCLabelBMFont.h"
+#import "CCLabelAtlas.h"
+
+#import "CCParticleSystem.h"
+#import "CCParticleSystemPoint.h"
+#import "CCParticleSystemQuad.h"
+#import "CCParticleExamples.h"
+
+#import "CCTexture2D.h"
+#import "CCTexturePVR.h"
+#import "CCTextureCache.h"
+#import "CCTextureAtlas.h"
+
+#import "CCTransition.h"
+#import "CCTransitionPageTurn.h"
+#import "CCTransitionRadial.h"
+
+#import "CCTMXTiledMap.h"
+#import "CCTMXLayer.h"
+#import "CCTMXObjectGroup.h"
+#import "CCTMXXMLParser.h"
+#import "CCTileMapAtlas.h"
+
+#import "CCLayer.h"
+#import "CCMenu.h"
+#import "CCMenuItem.h"
+#import "CCDrawingPrimitives.h"
+#import "CCScene.h"
+#import "CCScheduler.h"
+#import "CCBlockSupport.h"
+#import "CCCamera.h"
+#import "CCProtocols.h"
+#import "CCNode.h"
+#import "CCDirector.h"
+#import "CCAtlasNode.h"
+#import "CCGrabber.h"
+#import "CCGrid.h"
+#import "CCParallaxNode.h"
+#import "CCRenderTexture.h"
+#import "CCMotionStreak.h"
+#import "CCConfiguration.h"
+
+//
+// cocos2d macros
+//
+#import "ccTypes.h"
+#import "ccMacros.h"
+
+
+// Platform common
+#import "Platforms/CCGL.h"
+#import "Platforms/CCNS.h"
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#import "Platforms/iOS/CCTouchDispatcher.h"
+#import "Platforms/iOS/CCTouchDelegateProtocol.h"
+#import "Platforms/iOS/CCTouchHandler.h"
+#import "Platforms/iOS/EAGLView.h"
+#import "Platforms/iOS/CCDirectorIOS.h"
+
+#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+#import "Platforms/Mac/MacGLView.h"
+#import "Platforms/Mac/CCDirectorMac.h"
+#endif
+
+//
+// cocos2d helper files
+//
+#import "Support/OpenGL_Internal.h"
+#import "Support/CCFileUtils.h"
+#import "Support/CGPointExtension.h"
+#import "Support/ccCArray.h"
+#import "Support/CCArray.h"
+#import "Support/ccUtils.h"
+
+#if CC_ENABLE_PROFILERS
+#import "Support/CCProfiling.h"
+#endif // CC_ENABLE_PROFILERS
+
+
+// compatibility with v0.8
+#import "CCCompatibility.h"
+
+
+// free functions
+NSString * cocos2dVersion(void);
+
+#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
+#ifndef __IPHONE_4_0
+#error "If you are targeting iPad, you should set BASE SDK = 4.0 (or 4.1, or 4.2), and set the 'iOS deploy target' = 3.2"
+#endif
+#endif
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+
+static NSString *version = @"cocos2d v0.99.5";
+
+NSString *cocos2dVersion()
+{
+ return version;
+}
4BA0CDCE12BD655200EBB6F0 /* OpenGLServices.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BA0CDCD12BD655200EBB6F0 /* OpenGLServices.mm */; };
4BA0CDF112BD6FE100EBB6F0 /* RenderTarget.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BA0CDF012BD6FE100EBB6F0 /* RenderTarget.mm */; };
4BA0CF4C12BEA74F00EBB6F0 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BA0CF4B12BEA74F00EBB6F0 /* CoreGraphics.framework */; };
+ 4BA0CF7A12BEB78600EBB6F0 /* BasicPrimitives.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BA0CF7912BEB78600EBB6F0 /* BasicPrimitives.mm */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
4BA0CDEF12BD6EB200EBB6F0 /* RenderTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderTarget.h; sourceTree = "<group>"; };
4BA0CDF012BD6FE100EBB6F0 /* RenderTarget.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RenderTarget.mm; sourceTree = "<group>"; };
4BA0CF4B12BEA74F00EBB6F0 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 4BA0CF7812BEB78600EBB6F0 /* BasicPrimitives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BasicPrimitives.h; path = Geometry/BasicPrimitives.h; sourceTree = "<group>"; };
+ 4BA0CF7912BEB78600EBB6F0 /* BasicPrimitives.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = BasicPrimitives.mm; path = Geometry/BasicPrimitives.mm; sourceTree = "<group>"; };
8D1107310486CEB800E47090 /* Littlest-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Littlest-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; };
/* End PBXFileReference section */
4B68587312BC27FD005667D3 /* GraphicsServices */ = {
isa = PBXGroup;
children = (
+ 4BA0CF7712BEB74B00EBB6F0 /* Geometry */,
4B68587412BC27FD005667D3 /* OpenGLServices.h */,
4BA0CDCD12BD655200EBB6F0 /* OpenGLServices.mm */,
4BA0CDEF12BD6EB200EBB6F0 /* RenderTarget.h */,
name = Standard;
sourceTree = "<group>";
};
+ 4BA0CF7712BEB74B00EBB6F0 /* Geometry */ = {
+ isa = PBXGroup;
+ children = (
+ 4BA0CF7812BEB78600EBB6F0 /* BasicPrimitives.h */,
+ 4BA0CF7912BEB78600EBB6F0 /* BasicPrimitives.mm */,
+ );
+ name = Geometry;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
4B68588812BC288E005667D3 /* LittlestViewController.m in Sources */,
4BA0CDCE12BD655200EBB6F0 /* OpenGLServices.mm in Sources */,
4BA0CDF112BD6FE100EBB6F0 /* RenderTarget.mm in Sources */,
+ 4BA0CF7A12BEB78600EBB6F0 /* BasicPrimitives.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};