merge mingo-upto-0.99.5 to upto-0.99.5

This commit is contained in:
minggo 2010-12-27 11:06:44 +08:00
commit 33ad2881b7
21 changed files with 3209 additions and 1235 deletions

View File

@ -43,10 +43,10 @@ namespace cocos2d
glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &m_oldFBO);
// bind
glBindFramebufferOES(CC_GL_FRAMEBUFFER, m_fbo);
ccglBindFramebuffer(CC_GL_FRAMEBUFFER, m_fbo);
// associate texture with FBO
glFramebufferTexture2DOES(CC_GL_FRAMEBUFFER, CC_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
ccglFramebufferTexture2D(CC_GL_FRAMEBUFFER, CC_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
pTexture->getName(), 0);
// check if it worked (probably worth doing :) )

View File

@ -26,7 +26,7 @@ THE SOFTWARE.
#include "CCDirector.h"
#include "CCGrabber.h"
#include "support/opengl_support/glu.h"
#include "CCGL.h"
#include "CGPointExtension.h"
namespace cocos2d

View File

@ -0,0 +1,160 @@
/****************************************************************************
Copyright (c) 2010 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#ifndef __CC_ANIMATION_H__
#define __CC_ANIMATION_H__
#include "NSObject.h"
#include "NSMutableArray.h"
#include "CGGeometry.h"
#include "CCXCocos2dDefine.h"
#include <string.h>
namespace cocos2d {
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]];
*/
class CCX_DLL CCAnimation : public NSObject
{
protected:
std::string m_nameStr;
float m_fDelay;
NSMutableArray<CCSpriteFrame*> *m_pobFrames;
public:
// attributes
/** get name of the animation */
inline const char* getName(void) { return m_nameStr.c_str(); }
/** set name of the animation */
inline void setName(const char *pszName){ m_nameStr = pszName; }
/** get delay between frames in seconds */
inline float getDelay(void) { return m_fDelay; }
/** set delay between frames in seconds */
inline void setDelay(float fDelay) { m_fDelay = fDelay; }
/** get array of frames */
inline NSMutableArray<CCSpriteFrame*>* getFrames(void) { return m_pobFrames; }
/** set array of frames, the Frames is retained */
inline void setFrames(NSMutableArray<CCSpriteFrame*> *pFrames)
{
CCX_SAFE_RETAIN(pFrames);
CCX_SAFE_RELEASE(m_pobFrames);
m_pobFrames = pFrames;
}
public:
~CCAnimation(void);
/** Initializes a CCAnimation with frames.
@since v0.99.5
*/
bool initWithFrames(NSArray<CCSpriteFrame*> *pFrames);
/** Initializes a CCAnimation with frames and a delay between frames
@since v0.99.5
*/
bool initWithFrames(NSArray<CCSpriteFrame*> *pFrames, float delay);
/** Initializes a CCAnimation with a name
@since v0.99.3
@deprecated Will be removed in 1.0.1. Use "init" instead.
*/
bool initWithName(const char *pszName);
/** Initializes a CCAnimation with a name and frames
@since v0.99.3
@deprecated Will be removed in 1.0.1. Use "initWithFrames" instead.
*/
bool initWithName(const char *pszName, NSArray<CCSpriteFrame*> *pFrames);
/** Initializes a CCAnimation with a name and delay between frames.
@deprecated Will be removed in 1.0.1. Use "initWithFrames:nil delay:delay" instead.
*/
bool initWithName(const char *pszName, float fDelay);
/** 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.
*/
bool initWithName(const char *pszName, float fDelay, NSArray<CCSpriteFrame*> *pFrames);
/** adds a frame to a CCAnimation */
void addFrame(CCSpriteFrame *pFrame);
/** 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(const char *pszFileName);
/** 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* pobTexture, CGRect rect);
bool init(void);
public:
/** Creates an animation
@since v0.99.5
*/
static CCAnimation* animation(void);
/** Creates an animation with frames.
@since v0.99.5
*/
static CCAnimation* animationWithFrames(NSArray<CCSpriteFrame*> *frames);
/* Creates an animation with frames and a delay between frames.
@since v0.99.5
*/
static CCAnimation* animationWithFrames(NSArray<CCSpriteFrame*> *frames, float delay);
/** Creates a CCAnimation with a name
@since v0.99.3
@deprecated Will be removed in 1.0.1. Use "animation" instead.
*/
static CCAnimation* animationWithName(const char *pszName);
/** Creates a CCAnimation with a name and frames
@since v0.99.3
@deprecated Will be removed in 1.0.1. Use "animationWithFrames" instead.
*/
static CCAnimation* animationWithName(const char *pszName, NSArray<CCSpriteFrame*> *pFrames);
/** Creates a CCAnimation with a name and delay between frames. */
static CCAnimation* animationWithName(const char *pszName, float fDelay);
/** Creates a CCAnimation with a name, delay and an array of CCSpriteFrames. */
static CCAnimation* animationWithName(const char *pszName, float fDelay, NSArray<CCSpriteFrame*> *pFrames);
};
} // end of name sapce cocos2d
#endif // __CC_ANIMATION_H__

View File

@ -0,0 +1,70 @@
/****************************************************************************
Copyright (c) 2010 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#ifndef __CC_ANIMATION_CACHE_H__
#define __CC_ANIMATION_CACHE_H__
#include "NSObject.h"
#include "NSMutableArray.h"
namespace cocos2d
{
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
*/
class CCX_DLL CCAnimationCache : public NSObject
{
public:
/** Retruns ths shared instance of the Animation cache */
static CCAnimationCache* sharedAnimationCache(void);
/** Purges the cache. It releases all the CCAnimation objects and the shared instance.
*/
static void purgeSharedAnimationCache(void);
/** Adds a CCAnimation with a name.
*/
void addAnimation(CCAnimation *animation, const char * name);
/** Deletes a CCAnimation from the cache.
*/
void removeAnimationByName(const char* 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(const char* name);
private:
NSMutableArray<CCAnimation*> *m_pAnimations;
};
}
#endif // __CC_ANIMATION_CACHE_H__

View File

@ -25,7 +25,6 @@ THE SOFTWARE.
#ifndef __PLATFOMR_CCNODE_H__
#define __PLATFOMR_CCNODE_H__
#include "config_platform.h"
#include "CCXCocos2dDefine.h"
#include "ccMacros.h"
#include "CGAffineTransform.h"

View File

@ -35,7 +35,9 @@ THE SOFTWARE.
#include <string>
namespace cocos2d {
class CCSpriteBatchNode;
class CCSpriteSheet;
class CCSpriteSheetInternalOnly;
class CCSpriteFrame;
class CCAnimation;
class CGRect;
@ -45,7 +47,7 @@ class CCTexture2D;
struct transformValues_;
enum {
/// CCSprite invalid index on the CCSpriteSheet
/// CCSprite invalid index on the CCSpriteBatchNode
CCSpriteIndexNotInitialized = 0xffffffff,
};
@ -68,27 +70,28 @@ typedef enum {
} ccHonorParentTransform;
/** @brief 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 CCSpriteSheet then the following features/limitations are valid
* - Features when the parent is a CCSpriteSheet:
* - MUCH faster rendering, specially if the CCSpriteSheet 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 CCSpriteSheet, so you can't individually set the aliased property.
* - The Blending function property belongs to CCSpriteSheet, 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.
*
*/
/** 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).
*/
class CCX_DLL CCSprite : public CCNode, public CCTextureProtocol, public CCRGBAProtocol
{
public:
@ -104,6 +107,9 @@ public:
/** get the quad (tex coords, vertex coords and color) information */
inline ccV3F_C4B_T2F_Quad getQuad(void) { return m_sQuad; }
/** returns whether or not the texture rectangle is rotated */
inline bool isTextureRectTotated(void) { return m_bRectRotated; }
/** Set the index used on the TextureAtlas. */
inline unsigned int getAtlasIndex(void) { return m_uAtlasIndex; }
@ -112,19 +118,19 @@ public:
*/
inline void setAtlasIndex(unsigned int uAtlasIndex) { m_uAtlasIndex = uAtlasIndex; }
/** returns the rect of the CCSprite */
/** returns the rect of the CCSprite in points */
inline CGRect getTextureRect(void) { return m_obRect; }
/** whether or not the Sprite is rendered using a CCSpriteSheet */
inline bool isUsesSpriteSheet(void) { return m_bUsesSpriteSheet; }
/** make the Sprite been rendered using a CCSpriteSheet */
inline void setUsesSpriteSheet(bool bUsesSpriteSheet) { m_bUsesSpriteSheet = bUsesSpriteSheet; }
/** whether or not the Sprite is rendered using a CCSpriteBatchNode */
inline bool isUsesBatchNode(void) { return m_bUsesBatchNode; }
/** make the Sprite been rendered using a CCSpriteBatchNode */
inline void setUsesSpriteBatchNode(bool bUsesSpriteBatchNode) { m_bUsesBatchNode = bUsesSpriteBatchNode; }
inline CCTextureAtlas* getTextureAtlas(void) { return m_pobTextureAtlas; }
inline void setTextureAtlas(CCTextureAtlas *pobTextureAtlas) { m_pobTextureAtlas = pobTextureAtlas; }
inline CCSpriteSheet* getSpriteSheet(void) { return m_pobSpriteSheet; }
inline void setSpriteSheet(CCSpriteSheet *pobSpriteSheet) { m_pobSpriteSheet = pobSpriteSheet; }
inline CCSpriteBatchNode* getSpriteBatchNode(void) { return m_pobBatchNode; }
inline void setSpriteBatchNode(CCSpriteBatchNode *pobSpriteBatchNode) { m_pobBatchNode = pobSpriteBatchNode; }
/** whether or not to transform according to its parent transformations.
Useful for health bars. eg: Don't rotate the health bar, even if the parent rotates.
@ -142,7 +148,7 @@ public:
/** Get offset position of the sprite. Calculated automatically by editors like Zwoptex.
@since v0.99.0
*/
inline CGPoint getOffsetPosition(void) { return m_obOffsetPosition; }
inline CGPoint getOffsetPositionInPixels(void) { return m_obOffsetPositionInPixels; }
/** conforms to CCTextureProtocol protocol */
inline ccBlendFunc getBlendFunc(void) { return m_sBlendFunc; }
@ -184,12 +190,12 @@ public:
The offset will be (0,0).
*/
static CCSprite* spriteWithFile(const char *pszFileName, CGRect rect);
/** Creates an sprite with an CCBatchNode and a rect
*/
static CCSprite* spriteWithBatchNode(CCSpriteBatchNode *batchNode, CGRect rect);
/** Creates an sprite with an CCSpriteSheet and a rect */
static CCSprite* spriteWithSpriteSheet(CCSpriteSheet *pSpriteSheet, CGRect rect);
/** Creates an sprite with a texture, a rect and offset. */
static CCSprite* spriteWithSpriteSheet(CCSpriteSheet *pSpriteSheet, CGRect rect, CGPoint offset);
static CCSprite* spriteWithSpriteSheet(CCSpriteSheetInternalOnly *pSpriteSheet, CGRect rect);
public:
bool init(void);
@ -199,12 +205,13 @@ public:
virtual void removeChild(CCNode* pChild, bool bCleanup);
virtual void removeAllChildrenWithCleanup(bool bCleanup);
virtual void reorderChild(CCNode *pChild, int zOrder);
virtual CCNode* addChild(CCNode *pChild);
virtual CCNode* addChild(CCNode *pChild, int zOrder);
virtual CCNode* addChild(CCNode *pChild, int zOrder, int tag);
virtual void addChild(CCNode *pChild);
virtual void addChild(CCNode *pChild, int zOrder);
virtual void addChild(CCNode *pChild, int zOrder, int tag);
virtual void setDirtyRecursively(bool bValue);
virtual void setPosition(CGPoint pos);
virtual void setPositionInPixels(CGPoint pos);
virtual void setRotation(float fRotation);
virtual void setScaleX(float fScaleX);
virtual void setScaleY(float fScaleY);
@ -281,10 +288,16 @@ public:
*/
bool initWithFile(const char *pszFilename, CGRect rect);
/** Initializes an sprite with an CCSpriteSheet and a rect */
bool initWithSpriteSheet(CCSpriteSheet *pSpriteSheet, CGRect rect);
/** Initializes an sprite with an CCSpriteSheet and a rect in points */
bool initWithBatchNode(CCSpriteBatchNode *batchNode, CGRect rect);
bool initWithSpriteSheet(CCSpriteSheetInternalOnly *pSpriteSheet, CGRect rect);
// sprite sheet methods
/** Initializes an sprite with an CCSpriteSheet and a rect in pixels
@since v0.99.5
*/
bool initWithBatchNodeRectInPixels(CCSpriteBatchNode *batchNode, CGRect rect);
// BatchNode methods
/** updates the quad according the the rotation, position, scale values. */
void updateTransform(void);
@ -294,13 +307,18 @@ public:
*/
void useSelfRender(void);
/** updates the texture rect of the CCSprite. */
/** updates the texture rect of the CCSprite in points. */
void setTextureRect(CGRect rect);
/** tell the sprite to use sprite sheet render.
/** updates the texture rect, rectRotated and untrimmed size of the CCSprite in pixels
*/
void setTextureRectInPixels(CGRect rect, bool rotated, CGSize size);
/** tell the sprite to use batch node render.
@since v0.99.0
*/
void useSpriteSheetRender(CCSpriteSheet *pSpriteSheet);
void useBatchNode(CCSpriteBatchNode *batchNode);
void useSpriteSheetRender(CCSpriteSheetInternalOnly *pSpriteSheet);
// Frames
@ -313,23 +331,36 @@ public:
/** returns the current displayed frame. */
CCSpriteFrame* displayedFrame(void);
/** adds an Animation to the Sprite. */
/** adds an Animation to the Sprite.
@deprecated Use CCAnimationCache instead. Will be removed in 1.0.1
*/
void addAnimation(CCAnimation *pAnimation);
/** returns an Animation given it's name. */
/** returns an Animation given it's name.
@deprecated Use CCAnimationCache instead. Will be removed in 1.0.1
*/
CCAnimation* animationByName(const char *pszAnimationName);
// Animation
/** changes the display frame based on an animation and an index. */
/** 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(const char *pszAnimationName, int nFrameIndex);
/** changes the display frame with animation name and index.
The animation name will be get from the CCAnimationCache
@since v0.99.5
*/
void setDisplayFrameWithAnimationName(const char *animationName, int frameIndex);
protected:
void updateTextureCoords(CGRect rect);
void updateBlendFunc(void);
void initAnimationDictionary(void);
void setTextureRect(CGRect rect, CGSize size);
struct transformValues_ getTransformValues(void);
void getTransformValues(struct transformValues_ *tv); // optimization
protected:
//
@ -337,7 +368,7 @@ protected:
//
CCTextureAtlas *m_pobTextureAtlas; // Sprite Sheet texture atlas (weak reference)
unsigned int m_uAtlasIndex; // Absolute (real) Index on the SpriteSheet
CCSpriteSheet *m_pobSpriteSheet; // Used spritesheet (weak reference)
CCSpriteBatchNode *m_pobBatchNode; // Used batch node (weak reference)
ccHonorParentTransform m_eHonorParentTransform;// whether or not to transform according to its parent transformations
bool m_bDirty; // Sprite needs to be updated
bool m_bRecursiveDirty; // Subchildren needs to be updated
@ -353,14 +384,16 @@ protected:
// Shared data
//
// whether or not it's parent is a CCSpriteSheet
bool m_bUsesSpriteSheet;
// whether or not it's parent is a CCSpriteBatchNode
bool m_bUsesBatchNode;
// texture pixels
// texture
CGRect m_obRect;
CGRect m_obRectInPixels;
bool m_bRectRotated;
// Offset Position (used by Zwoptex)
CGPoint m_obOffsetPosition; // absolute
CGPoint m_obOffsetPositionInPixels; // absolute
CGPoint m_obUnflippedOffsetPositionFromCenter;
// vertex coords, texture coords and color info

View File

@ -0,0 +1,178 @@
/****************************************************************************
Copyright (c) 2010 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#ifndef __CC_SPRITE_BATCH_NODE_H__
#define __CC_SPRITE_BATCH_NODE_H__
#include "CCNode.h"
#include "CCProtocols.h"
#include "CCTextureAtlas.h"
#include "ccMacros.h"
#include "NSMutableArray.h"
#include "CCXCocos2dDefine.h"
namespace cocos2d
{
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
*/
class CCX_DLL CCSpriteBatchNode : public CCNode, public CCTextureProtocol
{
public:
~CCSpriteBatchNode();
// property
// retain
inline CCTextureAtlas* getTextureAtlas(void) { return m_pobTextureAtlas; }
inline void setTextureAtlas(CCTextureAtlas* textureAtlas)
{
if (textureAtlas != m_pobTextureAtlas)
{
CCX_SAFE_RETAIN(textureAtlas);
CCX_SAFE_RELEASE(m_pobTextureAtlas);
m_pobTextureAtlas = textureAtlas;
}
}
inline NSArray<CCSprite*>* getDescendants(void) { return m_pobDescendants; }
/** 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.
*/
static CCSpriteBatchNode* batchNodeWithTexture(CCTexture2D *tex);
static CCSpriteBatchNode* spriteSheetWithTexture(CCTexture2D *tex); // deprecated
/** 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.
*/
static CCSpriteBatchNode* batchNodeWithTexture(CCTexture2D* tex, unsigned int capacity);
static CCSpriteBatchNode* spriteSheetWithTexture(CCTexture2D *tex, unsigned int capacity); // deprecated
/** 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.
*/
static CCSpriteBatchNode* batchNodeWithFile(const char* fileImage);
static CCSpriteBatchNode* spriteSheetWithFile(const char* fileImage); // deprecated
/** 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.
*/
static CCSpriteBatchNode* batchNodeWithFile(const char* fileImage, unsigned int capacity);
static CCSpriteBatchNode* spriteSheetWithFile(const char* fileImage, unsigned int capacity); // deprecated
/** 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.
*/
bool initWithTexture(CCTexture2D *tex, unsigned int 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.
*/
bool initWithFile(const char* fileImage, unsigned int 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);
/** 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, CGRect rect);
/** 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(unsigned int index, 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, bool doCleanup);
void insertChild(CCSprite *child, unsigned int index);
void removeSpriteFromAtlas(CCSprite *sprite);
unsigned int rebuildIndexInOrder(CCSprite *parent, unsigned int index);
unsigned int highestAtlasIndexInChild(CCSprite *sprite);
unsigned int lowestAtlasIndexInChild(CCSprite *sprite);
unsigned int atlasIndexForChild(CCSprite *sprite, int z);
// CCTextureProtocol
virtual CCTexture2D* getTexture(void);
virtual void setTexture(CCTexture2D *texture);
virtual void setBlendFunc(ccBlendFunc blendFunc);
virtual ccBlendFunc getBlendFunc(void);
virtual void visit(void);
virtual void addChild(CCNode * child);
virtual void addChild(CCNode * child, int zOrder);
virtual void addChild(CCNode * child, int zOrder, int tag);
virtual void reorderChild(CCNode * child, int zOrder);
virtual void removeChild(CCNode* child, bool cleanup);
virtual void removeAllChildrenWithCleanup(bool cleanup);
virtual void draw(void);
private:
void updateBlendFunc();
private:
CCTextureAtlas *m_pobTextureAtlas;
ccBlendFunc m_blendFunc;
// all descendants: chlidren, gran children, etc...
NSArray<CCSprite*>* m_pobDescendants;
};
}
#endif // __CC_SPRITE_BATCH_NODE_H__

View File

@ -27,11 +27,8 @@ THE SOFTWARE.
#include "CCNode.h"
#include "CCProtocols.h"
#include "NSMutableArray.h"
#include "NSObject.h"
#include <string.h>
namespace cocos2d {
class CGRect;
class CGPoint;
@ -54,20 +51,26 @@ class CCX_DLL CCSpriteFrame : public NSObject
public:
// attributes
inline CGRect getRectInPixels(void) { return m_obRectInPixels; }
inline void setRectInPixels(CGRect rectInPixels) { m_obRectInPixels = rectInPixels; }
inline bool isRotated(void) { return m_bRotated; }
inline void setRotated(bool bRotated) { m_bRotated = bRotated; }
/** get rect of the frame */
inline CGRect getRect(void) { return m_obRect; }
/** set rect of the frame */
inline void setRect(CGRect rect) { m_obRect = rect; }
/** get offset of the frame */
inline CGPoint getOffset(void) { return m_obOffset; }
inline CGPoint getOffsetInPixels(void) { return m_obOffsetInPixels; }
/** set offset of the frame */
inline void setOffset(CGPoint offset) { m_obOffset = offset; }
inline void setOffsetInPixels(CGPoint offsetInPixels) { m_obOffsetInPixels = offsetInPixels; }
/** get original size of the trimmed image */
inline CGSize getOriginalSize(void) { return m_obOriginalSize; }
inline CGSize getOriginalSizeInPixels(void) { return m_obOriginalSizeInPixels; }
/** set original size of the trimmed image */
inline void setOriginalSize(CGSize size) { m_obOriginalSize = size; }
inline void setOriginalSizeInPixels(CGSize sizeInPixels) { m_obOriginalSizeInPixels = sizeInPixels; }
/** get texture of the frame */
inline CCTexture2D* getTexture(void) { return m_pobTexture; }
@ -83,113 +86,35 @@ public:
~CCSpriteFrame(void);
virtual NSObject* copyWithZone(NSZone *pZone);
/** Create a CCSpriteFrame with a texture, rect and offset.
/** Create a CCSpriteFrame with a texture, rect in points.
It is assumed that the frame was not trimmed.
*/
static CCSpriteFrame* frameWithTexture(CCTexture2D* pobTexture, CGRect rect, CGPoint offset);
static CCSpriteFrame* frameWithTexture(CCTexture2D* pobTexture, CGRect rect);
/** Create a CCSpriteFrame with a texture, rect, offset and originalSize.
The originalSize is the size in pixels of the frame before being trimmed.
/** 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.
*/
static CCSpriteFrame* frameWithTexture(CCTexture2D* pobTexture, CGRect rect, CGPoint offset, CGSize originalSize);
static CCSpriteFrame* frameWithTexture(CCTexture2D* pobTexture, CGRect rect, bool rotated, CGPoint offset, CGSize originalSize);
public:
/** Initializes a CCSpriteFrame with a texture, rect and offset.
/** Initializes a CCSpriteFrame with a texture, rect in points.
It is assumed that the frame was not trimmed.
*/
bool initWithTexture(CCTexture2D* pobTexture, CGRect rect, CGPoint offset);
bool initWithTexture(CCTexture2D* pobTexture, CGRect rect);
/** Initializes a CCSpriteFrame with a texture, rect, offset and originalSize.
The originalSize is the size in pixels of the frame before being trimmed.
*/
bool initWithTexture(CCTexture2D* pobTexture, CGRect rect, CGPoint offset, CGSize originalSize);
/** 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.
*/
bool initWithTexture(CCTexture2D* pobTexture, CGRect rect, bool rotated, CGPoint offset, CGSize originalSize);
protected:
CGRect m_obRectInPixels;
bool m_bRotated;
CGRect m_obRect;
CGPoint m_obOffset;
CGSize m_obOriginalSize;
CGPoint m_obOffsetInPixels;
CGSize m_obOriginalSizeInPixels;
CCTexture2D *m_pobTexture;
};
//! @brief an Animation object used within Sprites to perform animations
class CCX_DLL CCAnimation : public NSObject
{
protected:
std::string m_nameStr;
float m_fDelay;
NSMutableArray<CCSpriteFrame*> *m_pobFrames;
public:
// attributes
/** get name of the animation */
inline const char* getName(void) { return m_nameStr.c_str(); }
/** set name of the animation */
inline void setName(const char *pszName){ m_nameStr = pszName; }
/** get delay between frames in seconds */
inline float getDelay(void) { return m_fDelay; }
/** set delay between frames in seconds */
inline void setDelay(float fDelay) { m_fDelay = fDelay; }
/** get array of frames */
inline NSMutableArray<CCSpriteFrame*>* getFrames(void) { return m_pobFrames; }
/** set array of frames, the Frames is retained */
inline void setFrames(NSMutableArray<CCSpriteFrame*> *pFrames)
{
CCX_SAFE_RETAIN(pFrames);
CCX_SAFE_RELEASE(m_pobFrames);
m_pobFrames = pFrames;
}
public:
~CCAnimation(void);
/** Initializes a CCAnimation with a name
@since v0.99.3
*/
bool initWithName(const char *pszName);
/** Initializes a CCAnimation with a name and frames
@since v0.99.3
*/
bool initWithName(const char *pszName, NSArray<CCSpriteFrame*> *pFrames);
/** Initializes a CCAnimation with a name and delay between frames. */
bool initWithName(const char *pszName, float fDelay);
/** Initializes a CCAnimation with a name, delay and an array of CCSpriteFrames. */
bool initWithName(const char *pszName, float fDelay, NSArray<CCSpriteFrame*> *pFrames);
/** adds a frame to a CCAnimation */
void addFrame(CCSpriteFrame *pFrame);
/** 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(const char *pszFileName);
/** 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* pobTexture, CGRect rect);
public:
/** Creates a CCAnimation with a name
@since v0.99.3
*/
static CCAnimation* animationWithName(const char *pszName);
/** Creates a CCAnimation with a name and frames
@since v0.99.3
*/
static CCAnimation* animationWithName(const char *pszName, NSArray<CCSpriteFrame*> *pFrames);
/** Creates a CCAnimation with a name and delay between frames. */
static CCAnimation* animationWithName(const char *pszName, float fDelay);
/** Creates a CCAnimation with a name, delay and an array of CCSpriteFrames. */
static CCAnimation* animationWithName(const char *pszName, float fDelay, NSArray<CCSpriteFrame*> *pFrames);
};
}//namespace cocos2d
#endif //__SPRITE_CCSPRITE_FRAME_H__

View File

@ -59,6 +59,11 @@ public:
*/
void addSpriteFramesWithFile(const char *pszPlist);
/** Adds multiple Sprite Frames from a plist file. The texture will be associated with the created sprite frames.
@since v0.99.5
*/
void addSpriteFramesWithFile(const char* plist, const char* textureFileName);
/** Adds multiple Sprite Frames from a plist file. The texture will be associated with the created sprite frames. */
void addSpriteFramesWithFile(const char *pszPlist, CCTexture2D *pobTexture);
@ -84,6 +89,24 @@ public:
/** Deletes an sprite frame from the sprite frame cache. */
void removeSpriteFrameByName(const char *pszName);
/** 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(const char* plist);
/** Removes multiple Sprite Frames from NSDictionary.
* @since v0.99.5
*/
void removeSpriteFramesFromDictionary(NSDictionary<std::string, CCSpriteFrame*> *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.
@ -110,6 +133,7 @@ private:
protected:
NSDictionary<std::string, CCSpriteFrame*> *m_pSpriteFrames;
NSDictionary<std::string, CCSpriteFrame*> *m_pSpriteFramesAliases;
};
}//namespace cocos2d

View File

@ -25,164 +25,36 @@ THE SOFTWARE.
#ifndef __SPRITE_CCSPRITE_SHEET_H__
#define __SPRITE_CCSPRITE_SHEET_H__
#include "CCNode.h"
#include "CCProtocols.h"
#include "CCTextureAtlas.h"
#include "ccMacros.h"
#include "NSMutableArray.h"
#include "CCSpriteBatchNode.h"
namespace cocos2d {
class CCSprite;
class CGRect;
/** @brief 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) 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
*/
class CCX_DLL CCSpriteSheet : public CCNode, public CCTextureProtocol
{
public:
~CCSpriteSheet(void);
/** initializes a CCSpriteSheet with a texture2d and capacity of children.
The capacity will be increased in 33% in runtime if it run out of space.
*/
bool initWithTexture(CCTexture2D *pobTexture, unsigned int uCapacity);
/** initializes a CCSpriteSheet 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.
*/
bool initWithFile(const char *pszFileImage, unsigned int uCapacity);
void increaseAtlasCapacity(void);
/** creates an sprite with a rect in the CCSpriteSheet.
It's the same as:
- create an standard CCSsprite
- set the usingSpriteSheet = true
- set the textureAtlas to the same texture Atlas as the CCSpriteSheet
@deprecated Use CCSprite::spriteWithSpriteSheet(rect) instead;
*/
CCSprite* createSpriteWithRect(CGRect rect);
/** initializes a previously created sprite with a rect. This sprite will have the same texture as the CCSpriteSheet.
It's the same as:
- initialize an standard CCSsprite
- set the usingSpriteSheet = true
- set the textureAtlas to the same texture Atlas as the CCSpriteSheet
@since v0.99.0
@deprecated Use CCSprite::spriteWithSpriteSheet(rect) instead;
*/
void initSprite(CCSprite* pobSprite, CGRect rect);
/** 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 CCSpriteSheet is very slow
*/
void removeChildAtIndex(unsigned int uIndex, bool bDoCleanup);
void insertChild(CCSprite *pobSprite, unsigned int uIndex);
void removeSpriteFromAtlas(CCSprite *pobSprite);
unsigned int rebuildIndexInOrder(CCSprite *pobParent, unsigned int uIndex);
unsigned int atlasIndexForChild(CCSprite *pobSprite, int nZ);
unsigned int highestAtlasIndexInChild(CCSprite *pSprite);
unsigned int lowestAtlasIndexInChild(CCSprite *pSprite);
// CCTextureProtocol
virtual CCTexture2D* getTexture(void);
virtual void setTexture(CCTexture2D *texture);
virtual void setBlendFunc(ccBlendFunc blendFunc);
virtual ccBlendFunc getBlendFunc(void);
virtual void visit(void);
virtual CCNode * addChild(CCNode * child);
virtual CCNode * addChild(CCNode * child, int zOrder);
virtual CCNode * addChild(CCNode * child, int zOrder, int tag);
virtual void reorderChild(CCNode * child, int zOrder);
/** removes a child given a reference. It will also cleanup the running actions depending on the cleanup parameter.
@warning Removing a child from a CCSpriteSheet is very slow
/* Added only to prevent GCC compile warnings
Will be removed in v1.1
*/
virtual void removeChild(CCNode* child, bool cleanup);
virtual void removeAllChildrenWithCleanup(bool cleanup);
virtual void draw(void);
public:
/** creates a CCSpriteSheet 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.
*/
static CCSpriteSheet* spriteSheetWithTexture(CCTexture2D *pobTexture);
/** creates a CCSpriteSheet with a texture2d and capacity of children.
The capacity will be increased in 33% in runtime if it run out of space.
*/
static CCSpriteSheet* spriteSheetWithTexture(CCTexture2D *pobTexture, unsigned int uCapacity);
/** creates a CCSpriteSheet 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.
*/
static CCSpriteSheet* spriteSheetWithFile(const char *pszFileImage);
/** creates a CCSpriteSheet 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.
*/
static CCSpriteSheet* spriteSheetWithFile(const char *pszFileImage, unsigned int uCapacity);
private:
void updateBlendFunc(void);
public:
// attributes
// descendants (children, gran children, etc)
inline NSArray<CCSprite*>* getDescendants(void) { return m_pobDescendants; }
// TextureAtlas
inline CCTextureAtlas* getTextureAtlas(void) { return m_pobTextureAtlas; }
inline void setTextureAtlas(CCTextureAtlas *pTextureAtlas)
class CCX_DLL CCSpriteSheetInternalOnly : public CCSpriteBatchNode
{
m_pobTextureAtlas = pTextureAtlas;
if (pTextureAtlas)
{
pTextureAtlas->retain();
}
}
};
protected:
CCTextureAtlas *m_pobTextureAtlas;
ccBlendFunc m_blendFunc;
// all descendants: children, gran children, etc...
NSArray<CCSprite*> *m_pobDescendants;
protected:
/* IMPORTANT XXX IMPORTNAT:
* These 2 methods can't be part of CCTMXLayer since they call [super add...], and CCSpriteSheet#add SHALL not be called
*/
/* 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 characters (BitmapFontAtlas)
/** @brief 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) 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
*/
void addQuadFromSprite(CCSprite *sprite, unsigned int index);
/* 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
*/
CCSpriteSheet * addSpriteWithoutQuad(CCSprite*child, unsigned int z, int aTag);
class CCX_DLL CCSpriteSheet: public CCSpriteSheetInternalOnly
{
};
};
}//namespace cocos2d
#endif // __SPRITE_CCSPRITE_SHEET_H__

View File

@ -53,6 +53,11 @@ namespace cocos2d {
{
return (float)atof(m_sString.c_str());
}
bool isEmpty()
{
return m_sString.empty();
}
};
}// namespace cocos2d
#endif //__NSSTRING_H__

View File

@ -0,0 +1,640 @@
/****************************************************************************
Copyright (c) 2010 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "ccMacros.h"
#include "CCGrid.h"
#include "CCDirector.h"
#include "CCGrabber.h"
#include "CCGL.h"
#include "CGPointExtension.h"
namespace cocos2d
{
// implementation of CCGridBase
CCGridBase* CCGridBase::gridWithSize(cocos2d::ccGridSize gridSize)
{
CCGridBase *pGridBase = new CCGridBase();
if (pGridBase)
{
if (pGridBase->initWithSize(gridSize))
{
pGridBase->autorelease();
}
else
{
CCX_SAFE_RELEASE_NULL(pGridBase);
}
}
return pGridBase;
}
CCGridBase* CCGridBase::gridWithSize(ccGridSize gridSize, CCTexture2D *texture, bool flipped)
{
CCGridBase *pGridBase = new CCGridBase();
if (pGridBase)
{
if (pGridBase->initWithSize(gridSize, texture, flipped))
{
pGridBase->autorelease();
}
else
{
CCX_SAFE_RELEASE_NULL(pGridBase);
}
}
return pGridBase;
}
bool CCGridBase::initWithSize(ccGridSize gridSize, CCTexture2D *pTexture, bool bFlipped)
{
bool bRet = true;
m_bActive = false;
m_nReuseGrid = 0;
m_sGridSize = gridSize;
m_pTexture = pTexture;
CCX_SAFE_RETAIN(m_pTexture);
m_bIsTextureFlipped = bFlipped;
CGSize texSize = m_pTexture->getContentSizeInPixels();
m_obStep.x = texSize.width / m_sGridSize.x;
m_obStep.y = texSize.height / m_sGridSize.y;
m_pGrabber = new CCGrabber();
if (m_pGrabber)
{
m_pGrabber->grab(m_pTexture);
}
else
{
bRet = false;
}
calculateVertexPoints();
return bRet;
}
bool CCGridBase::initWithSize(ccGridSize gridSize)
{
CCDirector *pDirector = CCDirector::sharedDirector();
CGSize s = pDirector->getWinSizeInPixels();
unsigned int POTWide = ccNextPOT(s.width);
unsigned int POTHigh = ccNextPOT(s.height);
CCTexture2DPixelFormat format = pDirector->getPiexFormat() == kCCPixelFormatRGB565 ? kCCTexture2DPixelFormat_RGB565 : kCCTexture2DPixelFormat_RGBA8888;
void *data = calloc((int)(POTWide * POTHigh * 4), 1);
if (! data)
{
CCLOG("cocos2d: CCGrid: not enough memory.");
this->release();
return false;
}
CCTexture2D *pTexture = new CCTexture2D();
pTexture->initWithData(data, format, textureSize, textureSize, s);
free(data);
if (! pTexture)
{
CCLOG("cocos2d: CCGrid: error creating texture");
delete this;
return false;
}
if (initWithSize(gridSize, pTexture, false))
{
// do something
}
pTexture->release();
return true;
}
CCGridBase::~CCGridBase(void)
{
CCLOGINFO("cocos2d: deallocing %p", this);
setActive(false);
CCX_SAFE_RELEASE(m_pTexture);
CCX_SAFE_RELEASE(m_pGrabber);
}
// properties
void CCGridBase::setActive(bool bActive)
{
m_bActive = bActive;
if (! bActive)
{
CCDirector *pDirector = CCDirector::sharedDirector();
ccDirectorProjection proj = pDirector->getProjection();
pDirector->setProjection(proj);
}
}
void CCGridBase::setIsTextureFlipped(bool bFlipped)
{
if (m_bIsTextureFlipped != bFlipped)
{
m_bIsTextureFlipped = bFlipped;
calculateVertexPoints();
}
}
// This routine can be merged with Director
void CCGridBase::applyLandscape(void)
{
CCDirector *pDirector = CCDirector::sharedDirector();
CGSize winSize = pDirector->getDisplaySize();
float w = winSize.width / 2;
float h = winSize.height / 2;
ccDeviceOrientation orientation = pDirector->getDeviceOrientation();
switch (orientation)
{
case CCDeviceOrientationLandscapeLeft:
glTranslatef(w,h,0);
glRotatef(-90,0,0,1);
glTranslatef(-h,-w,0);
break;
case CCDeviceOrientationLandscapeRight:
glTranslatef(w,h,0);
glRotatef(90,0,0,1);
glTranslatef(-h,-w,0);
break;
case CCDeviceOrientationPortraitUpsideDown:
glTranslatef(w,h,0);
glRotatef(180,0,0,1);
glTranslatef(-w,-h,0);
break;
default:
break;
}
}
void CCGridBase::set2DProjection()
{
CGSize winSize = CCDirector::sharedDirector()->getWinSizeInPixels();
glLoadIdentity();
glViewport((GLsizei)0, (GLsizei)0, (GLsizei)winSize.width, (GLsizei)winSize.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
ccglOrtho(0, winSize.width, 0, winSize.height, -1024, 1024);
glMatrixMode(GL_MODELVIEW);
}
// This routine can be merged with Director
void CCGridBase::set3DProjection()
{
CGSize winSize = CCDirector::sharedDirector()->getDisplaySizeInPixels();
glViewport(0, 0, (GLsizei)winSize.width, (GLsizei)winSize.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (GLfloat)winSize.width/winSize.height, 0.5f, 1500.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt( winSize.width/2, winSize.height/2, CCDirector::sharedDirector()->getZEye(),
winSize.width/2, winSize.height/2, 0,
0.0f, 1.0f, 0.0f
);
}
void CCGridBase::beforeDraw(void)
{
set2DProjection();
m_pGrabber->beforeRender(m_pTexture);
}
void CCGridBase::afterDraw(cocos2d::CCNode *pTarget)
{
m_pGrabber->afterRender(m_pTexture);
set3DProjection();
applyLandscape();
if (pTarget->getCamera()->getDirty())
{
CGPoint offset = pTarget->getAnchorPointInPixels();
//
// XXX: Camera should be applied in the AnchorPoint
//
ccglTranslate(offset.x, offset.y, 0);
pTarget->getCamera()->locate();
ccglTranslate(-offset.x, -offset.y, 0);
}
glBindTexture(GL_TEXTURE_2D, m_pTexture->getName());
blit();
}
void CCGridBase::blit(void)
{
assert(0);
}
void CCGridBase::reuse(void)
{
assert(0);
}
void CCGridBase::calculateVertexPoints(void)
{
assert(0);
}
// implementation of CCGrid3D
CCGrid3D* CCGrid3D::gridWithSize(ccGridSize gridSize, CCTexture2D *pTexture, bool bFlipped)
{
CCGrid3D *pRet= new CCGrid3D();
if (pRet)
{
if (pRet->initWithSize(gridSize, pTexture, bFlipped))
{
pRet->autorelease();
}
else
{
delete pRet;
pRet = NULL;
}
}
return pRet;
}
CCGrid3D* CCGrid3D::gridWithSize(ccGridSize gridSize)
{
CCGrid3D *pRet= new CCGrid3D();
if (pRet)
{
if (pRet->initWithSize(gridSize))
{
pRet->autorelease();
}
else
{
delete pRet;
pRet = NULL;
}
}
return pRet;
}
CCGrid3D::~CCGrid3D(void)
{
free(m_pTexCoordinates);
free(m_pVertices);
free(m_pIndices);
free(m_pOriginalVertices);
}
void CCGrid3D::blit(void)
{
int n = m_sGridSize.x * m_sGridSize.y;
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY
// Unneeded states: GL_COLOR_ARRAY
glDisableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, m_pVertices);
glTexCoordPointer(2, GL_FLOAT, 0, m_pTexCoordinates);
glDrawElements(GL_TRIANGLES, n * 6, GL_UNSIGNED_SHORT, m_pIndices);
// restore GL default state
glEnableClientState(GL_COLOR_ARRAY);
}
void CCGrid3D::calculateVertexPoints(void)
{
float width = (float)m_pTexture->getPixelsWide();
float height = (float)m_pTexture->getPixelsHigh();
float imageH = m_pTexture->getContentSizeInPixels().height;
int x, y, i;
m_pVertices = malloc((m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(ccVertex3F));
m_pOriginalVertices = malloc((m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(ccVertex3F));
m_pTexCoordinates = malloc((m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(CGPoint));
m_pIndices = (GLushort*)malloc(m_sGridSize.x * m_sGridSize.y * sizeof(GLushort) * 6);
float *vertArray = (float*)m_pVertices;
float *texArray = (float*)m_pTexCoordinates;
GLushort *idxArray = m_pIndices;
for (x = 0; x < m_sGridSize.x; ++x)
{
for (y = 0; y < m_sGridSize.y; ++y)
{
int idx = (y * m_sGridSize.x) + x;
float x1 = x * m_obStep.x;
float x2 = x1 + m_obStep.x;
float y1 = y * m_obStep.y;
float y2= y1 + m_obStep.y;
GLushort a = x * (m_sGridSize.y + 1) + y;
GLushort b = (x + 1) * (m_sGridSize.y + 1) + y;
GLushort c = (x + 1) * (m_sGridSize.y + 1) + (y + 1);
GLushort d = x * (m_sGridSize.y + 1) + (y + 1);
GLushort tempidx[6] = {a, b, d, b, c, d};
memcpy(&idxArray[6*idx], tempidx, 6*sizeof(GLushort));
int l1[4] = {a*3, b*3, c*3, d*3};
ccVertex3F e = {x1, y1, 0};
ccVertex3F f = {x2, y1, 0};
ccVertex3F g = {x2, y2, 0};
ccVertex3F h = {x1, y2, 0};
ccVertex3F l2[4] = {e, f, g, h};
int tex1[4] = {a*2, b*2, c*2, d*2};
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 (m_bIsTextureFlipped)
{
texArray[tex1[i] + 1] = (imageH - tex2[i].y) / height;
}
else
{
texArray[tex1[i] + 1] = tex2[i].y / height;
}
}
}
}
memcpy(m_pOriginalVertices, m_pVertices, (m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(ccVertex3F));
}
ccVertex3F CCGrid3D::vertex(ccGridSize pos)
{
int index = (pos.x * (m_sGridSize.y+1) + pos.y) * 3;
float *vertArray = (float*)m_pVertices;
ccVertex3F vert = {vertArray[index], vertArray[index+1], vertArray[index+2]};
return vert;
}
ccVertex3F CCGrid3D::originalVertex(cocos2d::ccGridSize pos)
{
int index = (pos.x * (m_sGridSize.y+1) + pos.y) * 3;
float *vertArray = (float*)m_pOriginalVertices;
ccVertex3F vert = {vertArray[index], vertArray[index+1], vertArray[index+2]};
return vert;
}
void CCGrid3D::setVertex(ccGridSize pos, ccVertex3F vertex)
{
int index = (pos.x * (m_sGridSize.y + 1) + pos.y) * 3;
float *vertArray = (float*)m_pVertices;
vertArray[index] = vertex.x;
vertArray[index+1] = vertex.y;
vertArray[index+2] = vertex.z;
}
void CCGrid3D::reuse(void)
{
if (m_nReuseGrid > 0)
{
memcpy(m_pOriginalVertices, m_pVertices, (m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(ccVertex3F));
--m_nReuseGrid;
}
}
// implementation of CCTiledGrid3D
CCTiledGrid3D::~CCTiledGrid3D(void)
{
free(m_pTexCoordinates);
free(m_pVertices);
free(m_pOriginalVertices);
free(m_pIndices);
}
CCTiledGrid3D* CCTiledGrid3D::gridWithSize(cocos2d::ccGridSize gridSize, cocos2d::CCTexture2D *pTexture, bool bFlipped)
{
CCTiledGrid3D *pRet= new CCTiledGrid3D();
if (pRet)
{
if (pRet->initWithSize(gridSize, pTexture, bFlipped))
{
pRet->autorelease();
}
else
{
delete pRet;
pRet = NULL;
}
}
return pRet;
}
CCTiledGrid3D* CCTiledGrid3D::gridWithSize(cocos2d::ccGridSize gridSize)
{
CCTiledGrid3D *pRet= new CCTiledGrid3D();
if (pRet)
{
if (pRet->initWithSize(gridSize))
{
pRet->autorelease();
}
else
{
delete pRet;
pRet = NULL;
}
}
return pRet;
}
void CCTiledGrid3D::blit(void)
{
int n = m_sGridSize.x * m_sGridSize.y;
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY
// Unneeded states: GL_COLOR_ARRAY
glDisableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, m_pVertices);
glTexCoordPointer(2, GL_FLOAT, 0, m_pTexCoordinates);
glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, m_pIndices);
// restore default GL state
glEnableClientState(GL_COLOR_ARRAY);
}
void CCTiledGrid3D::calculateVertexPoints(void)
{
float width = (float)m_pTexture->getPixelsWide();
float height = (float)m_pTexture->getPixelsHigh();
float imageH = m_pTexture->getContentSizeInPixels().height;
int numQuads = m_sGridSize.x * m_sGridSize.y;
m_pVertices = malloc(numQuads * 12 * sizeof(GLfloat));
m_pOriginalVertices = malloc(numQuads * 12 * sizeof(GLfloat));
m_pTexCoordinates = malloc(numQuads * 8 * sizeof(GLfloat));
m_pIndices = (GLushort *)malloc(numQuads * 6 * sizeof(GLushort));
float *vertArray = (float*)m_pVertices;
float *texArray = (float*)m_pTexCoordinates;
GLushort *idxArray = m_pIndices;
int x, y;
for( x = 0; x < m_sGridSize.x; x++ )
{
for( y = 0; y < m_sGridSize.y; y++ )
{
float x1 = x * m_obStep.x;
float x2 = x1 + m_obStep.x;
float y1 = y * m_obStep.y;
float y2 = y1 + m_obStep.y;
*vertArray++ = x1;
*vertArray++ = y1;
*vertArray++ = 0;
*vertArray++ = x2;
*vertArray++ = y1;
*vertArray++ = 0;
*vertArray++ = x1;
*vertArray++ = y2;
*vertArray++ = 0;
*vertArray++ = x2;
*vertArray++ = y2;
*vertArray++ = 0;
float newY1 = y1;
float newY2 = y2;
if (m_bIsTextureFlipped)
{
newY1 = imageH - y1;
newY2 = imageH - y2;
}
*texArray++ = x1 / width;
*texArray++ = newY1 / height;
*texArray++ = x2 / width;
*texArray++ = newY1 / height;
*texArray++ = x1 / width;
*texArray++ = newY2 / height;
*texArray++ = x2 / width;
*texArray++ = newY2 / height;
}
}
for (x = 0; x < numQuads; x++)
{
idxArray[x*6+0] = 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(m_pOriginalVertices, m_pVertices, numQuads * 12 * sizeof(GLfloat));
}
void CCTiledGrid3D::setTile(cocos2d::ccGridSize pos, cocos2d::ccQuad3 coords)
{
int idx = (m_sGridSize.y * pos.x + pos.y) * 4 * 3;
float *vertArray = (float*)m_pVertices;
memcpy(&vertArray[idx], &coords, sizeof(ccQuad3));
}
ccQuad3 CCTiledGrid3D::originalTile(ccGridSize pos)
{
int idx = (m_sGridSize.y * pos.x + pos.y) * 4 * 3;
float *vertArray = (float*)m_pOriginalVertices;
ccQuad3 ret;
memcpy(&ret, &vertArray[idx], sizeof(ccQuad3));
return ret;
}
ccQuad3 CCTiledGrid3D::tile(cocos2d::ccGridSize pos)
{
int idx = (m_sGridSize.y * pos.x + pos.y) * 4 * 3;
float *vertArray = (float*)m_pVertices;
ccQuad3 ret;
memcpy(&ret, &vertArray[idx], sizeof(ccQuad3));
return ret;
}
void CCTiledGrid3D::reuse(void)
{
if (m_nReuseGrid > 0)
{
int numQuads = m_sGridSize.x * m_sGridSize.y;
memcpy(m_pOriginalVertices, m_pVertices, numQuads * 12 * sizeof(GLfloat));
--m_nReuseGrid;
}
}
} // end of namespace cocos2d

83
cocos2dx/platform/CCNS.h Normal file
View File

@ -0,0 +1,83 @@
/****************************************************************************
Copyright (c) 2010 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#ifndef __PLATFOMR_CCNS_H__
#define __PLATFOMR_CCNS_H__
#include "config_platform.h"
#ifdef CCX_PLATFORM_IPHONE
#include <Availability.h>
#include <Foundation/Foundation.h>
#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(CCX_PLATFORM_MAC)
#include <Availability.h>
#include <Foundation/Foundation.h>
#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
#else
/// @todo
#include "CGGeometry.h"
#define CCRectFromString(__r__) CGRectZero
#define CCPointFromString(__p__) CGPointZero
#define CCSizeFromString(__s__) CGSizeZero
#define CCNSSizeToCGSize CGSizeZero
#define CCNSRectToCGRect CGRectZero
#define CCNSPointToCGPoint CGPointZero
#define CCTextAlignment 0
#define CCTextAlignmentCenter 0
#define CCTextAlignmentLeft 0
#define CCTextAlignmentRight 0
#endif
#endif // __PLATFOMR_CCNS_H__

View File

@ -0,0 +1,614 @@
/****************************************************************************
Copyright (c) 2010 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "ccMacros.h"
#include "CCGrid.h"
#include "CCDirector.h"
#include "CCGrabber.h"
#include "CCGL.h"
#include "CGPointExtension.h"
namespace cocos2d
{
// implementation of CCGridBase
CCGridBase* CCGridBase::gridWithSize(cocos2d::ccGridSize gridSize)
{
CCGridBase *pGridBase = new CCGridBase();
if (pGridBase)
{
if (pGridBase->initWithSize(gridSize))
{
pGridBase->autorelease();
}
else
{
CCX_SAFE_RELEASE_NULL(pGridBase);
}
}
return pGridBase;
}
CCGridBase* CCGridBase::gridWithSize(ccGridSize gridSize, CCTexture2D *texture, bool flipped)
{
CCGridBase *pGridBase = new CCGridBase();
if (pGridBase)
{
if (pGridBase->initWithSize(gridSize, texture, flipped))
{
pGridBase->autorelease();
}
else
{
CCX_SAFE_RELEASE_NULL(pGridBase);
}
}
return pGridBase;
}
bool CCGridBase::initWithSize(ccGridSize gridSize, CCTexture2D *pTexture, bool bFlipped)
{
bool bRet = true;
m_bActive = false;
m_nReuseGrid = 0;
m_sGridSize = gridSize;
m_pTexture = pTexture;
CCX_SAFE_RETAIN(m_pTexture);
m_bIsTextureFlipped = bFlipped;
CGSize texSize = m_pTexture->getContentSizeInPixels();
m_obStep.x = texSize.width / m_sGridSize.x;
m_obStep.y = texSize.height / m_sGridSize.y;
m_pGrabber = new CCGrabber();
if (m_pGrabber)
{
m_pGrabber->grab(m_pTexture);
}
else
{
bRet = false;
}
calculateVertexPoints();
return bRet;
}
bool CCGridBase::initWithSize(ccGridSize gridSize)
{
CCDirector *pDirector = CCDirector::sharedDirector();
CGSize s = pDirector->getWinSizeInPixels();
unsigned int POTWide = ccNextPOT(s.width);
unsigned int POTHigh = ccNextPOT(s.height);
// on mac, it use kCCTexture2DPixelFormat_RGBA8888
CCTexture2DPixelFormat format = kCCTexture2DPixelFormat_RGBA8888;
void *data = calloc((int)(POTWide * POTHigh * 4), 1);
if (! data)
{
CCLOG("cocos2d: CCGrid: not enough memory.");
this->release();
return false;
}
CCTexture2D *pTexture = new CCTexture2D();
pTexture->initWithData(data, format, textureSize, textureSize, s);
free(data);
if (! pTexture)
{
CCLOG("cocos2d: CCGrid: error creating texture");
delete this;
return false;
}
if (initWithSize(gridSize, pTexture, false))
{
// do something
}
pTexture->release();
return true;
}
CCGridBase::~CCGridBase(void)
{
CCLOGINFO("cocos2d: deallocing %p", this);
setActive(false);
CCX_SAFE_RELEASE(m_pTexture);
CCX_SAFE_RELEASE(m_pGrabber);
}
// properties
void CCGridBase::setActive(bool bActive)
{
m_bActive = bActive;
if (! bActive)
{
CCDirector *pDirector = CCDirector::sharedDirector();
ccDirectorProjection proj = pDirector->getProjection();
pDirector->setProjection(proj);
}
}
void CCGridBase::setIsTextureFlipped(bool bFlipped)
{
if (m_bIsTextureFlipped != bFlipped)
{
m_bIsTextureFlipped = bFlipped;
calculateVertexPoints();
}
}
// mac can not applay land space
void CCGridBase::applyLandscape(void)
{
}
void CCGridBase::set2DProjection()
{
CGSize winSize = CCDirector::sharedDirector()->getWinSizeInPixels();
glLoadIdentity();
glViewport((GLsizei)0, (GLsizei)0, (GLsizei)winSize.width, (GLsizei)winSize.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
ccglOrtho(0, winSize.width, 0, winSize.height, -1024, 1024);
glMatrixMode(GL_MODELVIEW);
}
// This routine can be merged with Director
void CCGridBase::set3DProjection()
{
CGSize winSize = CCDirector::sharedDirector()->getDisplaySizeInPixels();
glViewport(0, 0, (GLsizei)winSize.width, (GLsizei)winSize.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (GLfloat)winSize.width/winSize.height, 0.5f, 1500.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt( winSize.width/2, winSize.height/2, CCDirector::sharedDirector()->getZEye(),
winSize.width/2, winSize.height/2, 0,
0.0f, 1.0f, 0.0f
);
}
void CCGridBase::beforeDraw(void)
{
set2DProjection();
m_pGrabber->beforeRender(m_pTexture);
}
void CCGridBase::afterDraw(cocos2d::CCNode *pTarget)
{
m_pGrabber->afterRender(m_pTexture);
set3DProjection();
// mac can not applay land space
//applyLandscape();
if (pTarget->getCamera()->getDirty())
{
CGPoint offset = pTarget->getAnchorPointInPixels();
//
// XXX: Camera should be applied in the AnchorPoint
//
ccglTranslate(offset.x, offset.y, 0);
pTarget->getCamera()->locate();
ccglTranslate(-offset.x, -offset.y, 0);
}
glBindTexture(GL_TEXTURE_2D, m_pTexture->getName());
blit();
}
void CCGridBase::blit(void)
{
assert(0);
}
void CCGridBase::reuse(void)
{
assert(0);
}
void CCGridBase::calculateVertexPoints(void)
{
assert(0);
}
// implementation of CCGrid3D
CCGrid3D* CCGrid3D::gridWithSize(ccGridSize gridSize, CCTexture2D *pTexture, bool bFlipped)
{
CCGrid3D *pRet= new CCGrid3D();
if (pRet)
{
if (pRet->initWithSize(gridSize, pTexture, bFlipped))
{
pRet->autorelease();
}
else
{
delete pRet;
pRet = NULL;
}
}
return pRet;
}
CCGrid3D* CCGrid3D::gridWithSize(ccGridSize gridSize)
{
CCGrid3D *pRet= new CCGrid3D();
if (pRet)
{
if (pRet->initWithSize(gridSize))
{
pRet->autorelease();
}
else
{
delete pRet;
pRet = NULL;
}
}
return pRet;
}
CCGrid3D::~CCGrid3D(void)
{
free(m_pTexCoordinates);
free(m_pVertices);
free(m_pIndices);
free(m_pOriginalVertices);
}
void CCGrid3D::blit(void)
{
int n = m_sGridSize.x * m_sGridSize.y;
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY
// Unneeded states: GL_COLOR_ARRAY
glDisableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, m_pVertices);
glTexCoordPointer(2, GL_FLOAT, 0, m_pTexCoordinates);
glDrawElements(GL_TRIANGLES, n * 6, GL_UNSIGNED_SHORT, m_pIndices);
// restore GL default state
glEnableClientState(GL_COLOR_ARRAY);
}
void CCGrid3D::calculateVertexPoints(void)
{
float width = (float)m_pTexture->getPixelsWide();
float height = (float)m_pTexture->getPixelsHigh();
float imageH = m_pTexture->getContentSizeInPixels().height;
int x, y, i;
m_pVertices = malloc((m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(ccVertex3F));
m_pOriginalVertices = malloc((m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(ccVertex3F));
m_pTexCoordinates = malloc((m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(CGPoint));
m_pIndices = (GLushort*)malloc(m_sGridSize.x * m_sGridSize.y * sizeof(GLushort) * 6);
float *vertArray = (float*)m_pVertices;
float *texArray = (float*)m_pTexCoordinates;
GLushort *idxArray = m_pIndices;
for (x = 0; x < m_sGridSize.x; ++x)
{
for (y = 0; y < m_sGridSize.y; ++y)
{
int idx = (y * m_sGridSize.x) + x;
float x1 = x * m_obStep.x;
float x2 = x1 + m_obStep.x;
float y1 = y * m_obStep.y;
float y2= y1 + m_obStep.y;
GLushort a = x * (m_sGridSize.y + 1) + y;
GLushort b = (x + 1) * (m_sGridSize.y + 1) + y;
GLushort c = (x + 1) * (m_sGridSize.y + 1) + (y + 1);
GLushort d = x * (m_sGridSize.y + 1) + (y + 1);
GLushort tempidx[6] = {a, b, d, b, c, d};
memcpy(&idxArray[6*idx], tempidx, 6*sizeof(GLushort));
int l1[4] = {a*3, b*3, c*3, d*3};
ccVertex3F e = {x1, y1, 0};
ccVertex3F f = {x2, y1, 0};
ccVertex3F g = {x2, y2, 0};
ccVertex3F h = {x1, y2, 0};
ccVertex3F l2[4] = {e, f, g, h};
int tex1[4] = {a*2, b*2, c*2, d*2};
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 (m_bIsTextureFlipped)
{
texArray[tex1[i] + 1] = (imageH - tex2[i].y) / height;
}
else
{
texArray[tex1[i] + 1] = tex2[i].y / height;
}
}
}
}
memcpy(m_pOriginalVertices, m_pVertices, (m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(ccVertex3F));
}
ccVertex3F CCGrid3D::vertex(ccGridSize pos)
{
int index = (pos.x * (m_sGridSize.y+1) + pos.y) * 3;
float *vertArray = (float*)m_pVertices;
ccVertex3F vert = {vertArray[index], vertArray[index+1], vertArray[index+2]};
return vert;
}
ccVertex3F CCGrid3D::originalVertex(cocos2d::ccGridSize pos)
{
int index = (pos.x * (m_sGridSize.y+1) + pos.y) * 3;
float *vertArray = (float*)m_pOriginalVertices;
ccVertex3F vert = {vertArray[index], vertArray[index+1], vertArray[index+2]};
return vert;
}
void CCGrid3D::setVertex(ccGridSize pos, ccVertex3F vertex)
{
int index = (pos.x * (m_sGridSize.y + 1) + pos.y) * 3;
float *vertArray = (float*)m_pVertices;
vertArray[index] = vertex.x;
vertArray[index+1] = vertex.y;
vertArray[index+2] = vertex.z;
}
void CCGrid3D::reuse(void)
{
if (m_nReuseGrid > 0)
{
memcpy(m_pOriginalVertices, m_pVertices, (m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(ccVertex3F));
--m_nReuseGrid;
}
}
// implementation of CCTiledGrid3D
CCTiledGrid3D::~CCTiledGrid3D(void)
{
free(m_pTexCoordinates);
free(m_pVertices);
free(m_pOriginalVertices);
free(m_pIndices);
}
CCTiledGrid3D* CCTiledGrid3D::gridWithSize(cocos2d::ccGridSize gridSize, cocos2d::CCTexture2D *pTexture, bool bFlipped)
{
CCTiledGrid3D *pRet= new CCTiledGrid3D();
if (pRet)
{
if (pRet->initWithSize(gridSize, pTexture, bFlipped))
{
pRet->autorelease();
}
else
{
delete pRet;
pRet = NULL;
}
}
return pRet;
}
CCTiledGrid3D* CCTiledGrid3D::gridWithSize(cocos2d::ccGridSize gridSize)
{
CCTiledGrid3D *pRet= new CCTiledGrid3D();
if (pRet)
{
if (pRet->initWithSize(gridSize))
{
pRet->autorelease();
}
else
{
delete pRet;
pRet = NULL;
}
}
return pRet;
}
void CCTiledGrid3D::blit(void)
{
int n = m_sGridSize.x * m_sGridSize.y;
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY
// Unneeded states: GL_COLOR_ARRAY
glDisableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, m_pVertices);
glTexCoordPointer(2, GL_FLOAT, 0, m_pTexCoordinates);
glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, m_pIndices);
// restore default GL state
glEnableClientState(GL_COLOR_ARRAY);
}
void CCTiledGrid3D::calculateVertexPoints(void)
{
float width = (float)m_pTexture->getPixelsWide();
float height = (float)m_pTexture->getPixelsHigh();
float imageH = m_pTexture->getContentSizeInPixels().height;
int numQuads = m_sGridSize.x * m_sGridSize.y;
m_pVertices = malloc(numQuads * 12 * sizeof(GLfloat));
m_pOriginalVertices = malloc(numQuads * 12 * sizeof(GLfloat));
m_pTexCoordinates = malloc(numQuads * 8 * sizeof(GLfloat));
m_pIndices = (GLushort *)malloc(numQuads * 6 * sizeof(GLushort));
float *vertArray = (float*)m_pVertices;
float *texArray = (float*)m_pTexCoordinates;
GLushort *idxArray = m_pIndices;
int x, y;
for( x = 0; x < m_sGridSize.x; x++ )
{
for( y = 0; y < m_sGridSize.y; y++ )
{
float x1 = x * m_obStep.x;
float x2 = x1 + m_obStep.x;
float y1 = y * m_obStep.y;
float y2 = y1 + m_obStep.y;
*vertArray++ = x1;
*vertArray++ = y1;
*vertArray++ = 0;
*vertArray++ = x2;
*vertArray++ = y1;
*vertArray++ = 0;
*vertArray++ = x1;
*vertArray++ = y2;
*vertArray++ = 0;
*vertArray++ = x2;
*vertArray++ = y2;
*vertArray++ = 0;
float newY1 = y1;
float newY2 = y2;
if (m_bIsTextureFlipped)
{
newY1 = imageH - y1;
newY2 = imageH - y2;
}
*texArray++ = x1 / width;
*texArray++ = newY1 / height;
*texArray++ = x2 / width;
*texArray++ = newY1 / height;
*texArray++ = x1 / width;
*texArray++ = newY2 / height;
*texArray++ = x2 / width;
*texArray++ = newY2 / height;
}
}
for (x = 0; x < numQuads; x++)
{
idxArray[x*6+0] = 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(m_pOriginalVertices, m_pVertices, numQuads * 12 * sizeof(GLfloat));
}
void CCTiledGrid3D::setTile(cocos2d::ccGridSize pos, cocos2d::ccQuad3 coords)
{
int idx = (m_sGridSize.y * pos.x + pos.y) * 4 * 3;
float *vertArray = (float*)m_pVertices;
memcpy(&vertArray[idx], &coords, sizeof(ccQuad3));
}
ccQuad3 CCTiledGrid3D::originalTile(ccGridSize pos)
{
int idx = (m_sGridSize.y * pos.x + pos.y) * 4 * 3;
float *vertArray = (float*)m_pOriginalVertices;
ccQuad3 ret;
memcpy(&ret, &vertArray[idx], sizeof(ccQuad3));
return ret;
}
ccQuad3 CCTiledGrid3D::tile(cocos2d::ccGridSize pos)
{
int idx = (m_sGridSize.y * pos.x + pos.y) * 4 * 3;
float *vertArray = (float*)m_pVertices;
ccQuad3 ret;
memcpy(&ret, &vertArray[idx], sizeof(ccQuad3));
return ret;
}
void CCTiledGrid3D::reuse(void)
{
if (m_nReuseGrid > 0)
{
int numQuads = m_sGridSize.x * m_sGridSize.y;
memcpy(m_pOriginalVertices, m_pVertices, numQuads * 12 * sizeof(GLfloat));
--m_nReuseGrid;
}
}
} // end of namespace cocos2d

View File

@ -308,6 +308,14 @@
RelativePath="..\include\CCActionTiledGrid.h"
>
</File>
<File
RelativePath="..\include\CCAnimation.h"
>
</File>
<File
RelativePath="..\include\CCAnimationCache.h"
>
</File>
<File
RelativePath="..\include\CCAtlasNode.h"
>
@ -420,6 +428,10 @@
RelativePath="..\include\CCSprite.h"
>
</File>
<File
RelativePath="..\include\CCSpriteBatchNode.h"
>
</File>
<File
RelativePath="..\include\CCSpriteFrame.h"
>
@ -656,10 +668,18 @@
<Filter
Name="sprite_nodes"
>
<File
RelativePath="..\sprite_nodes\CCAnimation.cpp"
>
</File>
<File
RelativePath="..\sprite_nodes\CCSprite.cpp"
>
</File>
<File
RelativePath="..\sprite_nodes\CCSpriteBatchNode.cpp"
>
</File>
<File
RelativePath="..\sprite_nodes\CCSpriteFrame.cpp"
>
@ -888,6 +908,14 @@
RelativePath="..\platform\CCMenu_mobile.cpp"
>
</File>
<File
RelativePath="..\platform\CCGL.h"
>
</File>
<File
RelativePath="..\platform\CCGrid_mobile.cpp"
>
</File>
<File
RelativePath="..\platform\CCNode_mobile.cpp"
>
@ -896,6 +924,10 @@
RelativePath="..\platform\CCTransition_mobile.cpp"
>
</File>
<File
RelativePath="..\platform\CCNS.h"
>
</File>
<File
RelativePath="..\platform\CCXApplication_platform.h"
>

View File

@ -0,0 +1,166 @@
/****************************************************************************
Copyright (c) 2010 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "CCAnimation.h"
#include "CCTextureCache.h"
#include "CCTexture2D.h"
#include "ccMacros.h"
#include "CCSpriteFrame.h"
namespace cocos2d
{
// implementation of CCAnimation
CCAnimation* CCAnimation::animation()
{
CCAnimation *pAnimation = new CCAnimation();
pAnimation->init();
pAnimation->autorelease();
return pAnimation;
}
bool CCAnimation::init()
{
return initWithFrames(NULL, 0);
}
CCAnimation* CCAnimation::animationWithFrames(NSArray<CCSpriteFrame*> *frames)
{
CCAnimation *pAnimation = new CCAnimation();
pAnimation->initWithFrames(frames);
pAnimation->autorelease();
return pAnimation;
}
CCAnimation* CCAnimation::animationWithFrames(NSArray<CCSpriteFrame*> *frames, float delay)
{
CCAnimation *pAnimation = new CCAnimation();
pAnimation->initWithFrames(frames, delay);
pAnimation->autorelease();
return pAnimation;
}
CCAnimation* CCAnimation::animationWithName(const char *pszName)
{
CCAnimation *pAnimation = new CCAnimation();
pAnimation->initWithName(pszName);
pAnimation->autorelease();
return pAnimation;
}
CCAnimation* CCAnimation::animationWithName(const char *pszName, NSMutableArray<CCSpriteFrame*> *pFrames)
{
CCAnimation *pAnimation = new CCAnimation();
pAnimation->initWithName(pszName, pFrames);
pAnimation->autorelease();
return pAnimation;
}
CCAnimation* CCAnimation::animationWithName(const char *pszName, float fDelay, NSMutableArray<CCSpriteFrame*> *pFrames)
{
CCAnimation *pAnimation = new CCAnimation();
pAnimation->initWithName(pszName, fDelay, pFrames);
pAnimation->autorelease();
return pAnimation;
}
CCAnimation* CCAnimation::animationWithName(const char *pszName, float fDelay)
{
CCAnimation *pAnimation = new CCAnimation();
pAnimation->initWithName(pszName, fDelay);
pAnimation->autorelease();
return pAnimation;
}
bool CCAnimation::initWithFrames(NSArray<CCSpriteFrame*> *pFrames, float delay)
{
m_fDelay = delay;
m_pobFrames = NSMutableArray<CCSpriteFrame*>::arrayWithArray(pFrames);
return true;
}
bool CCAnimation::initWithFrames(NSArray<CCSpriteFrame*> *pFrames)
{
return initWithFrames(pFrames, 0);
}
bool CCAnimation::initWithName(const char *pszName)
{
return initWithName(pszName, 0, NULL);
}
bool CCAnimation::initWithName(const char *pszName, float fDelay)
{
return initWithName(pszName, fDelay, NULL);
}
bool CCAnimation::initWithName(const char *pszName, NSMutableArray<CCSpriteFrame*> *pFrames)
{
return initWithName(pszName, 0, pFrames);
}
bool CCAnimation::initWithName(const char *pszName, float fDelay, NSMutableArray<CCSpriteFrame*> *pFrames)
{
m_fDelay = fDelay;
m_nameStr = pszName;
m_pobFrames = NSMutableArray<CCSpriteFrame*>::arrayWithArray(pFrames);
return true;
}
CCAnimation::~CCAnimation(void)
{
CCLOGINFO("cocos2d, deallocing %p", this);
// [name_ release];
m_nameStr.clear();
CCX_SAFE_RELEASE(m_pobFrames);
}
void CCAnimation::addFrame(CCSpriteFrame *pFrame)
{
m_pobFrames->addObject(pFrame);
}
void CCAnimation::addFrameWithFileName(const char *pszFileName)
{
CCTexture2D *pTexture = CCTextureCache::sharedTextureCache()->addImage(pszFileName);
CGRect rect = CGRectZero;
rect.size = pTexture->getContentSize();
CCSpriteFrame *pFrame = CCSpriteFrame::frameWithTexture(pTexture, rect);
m_pobFrames->addObject(pFrame);
}
void CCAnimation::addFrameWithTexture(CCTexture2D *pobTexture, CGRect rect)
{
CCSpriteFrame *pFrame = CCSpriteFrame::frameWithTexture(pobTexture, rect);
m_pobFrames->addObject(pFrame);
}
}

View File

@ -22,6 +22,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "CCSpriteBatchNode.h"
#include "CCAnimation.h"
#include "CCAnimationCache.h"
#include "CCSpriteSheet.h"
#include "ccConfig.h"
#include "CCSprite.h"
@ -39,7 +42,7 @@ THE SOFTWARE.
using namespace std;
namespace cocos2d {
#if CC_SPRITESHEET_RENDER_SUBPIXEL
#if CC_SPRITEBATCHNODE_RENDER_SUBPIXEL
#define RENDER_IN_SUBPIXEL
#else
#define RENDER_IN_SUBPIXEL(__A__) ( (int)(__A__))
@ -51,8 +54,42 @@ struct transformValues_ {
CGPoint scale; // scale x and y
float rotation;
CGPoint ap; // anchor point in pixels
bool visible;
};
CCSprite* CCSprite::spriteWithBatchNode(CCSpriteBatchNode *batchNode, CGRect rect)
{
CCSprite *pobSprite = new CCSprite();
if (pobSprite->initWithBatchNode(batchNode, rect))
{
pobSprite->autorelease();
}
else
{
delete pobSprite;
pobSprite = NULL;
}
return pobSprite;
}
bool CCSprite::initWithBatchNode(CCSpriteBatchNode *batchNode, CGRect rect)
{
bool ret = initWithTexture(batchNode->getTexture(), rect);
useBatchNode(batchNode);
return ret;
}
bool CCSprite::initWithBatchNodeRectInPixels(CCSpriteBatchNode *batchNode, CGRect rect)
{
bool ret = initWithTexture(batchNode->getTexture());
setTextureRectInPixels(rect, false, rect.size);
useBatchNode(batchNode);
return ret;
}
CCSprite* CCSprite::spriteWithTexture(CCTexture2D *pTexture)
{
CCSprite *pobSprite = new CCSprite();
@ -111,37 +148,9 @@ CCSprite* CCSprite::spriteWithSpriteFrameName(const char *pszSpriteFrameName)
return spriteWithSpriteFrame(pFrame);
}
// XXX: deprecated
/*
CCSprite* CCSprite::spriteWithCGImage(CGImageRef pImage)
CCSprite* CCSprite::spriteWithSpriteSheet(CCSpriteSheetInternalOnly *pSpriteSheet, CGRect rect)
{
CCSprite *pobSprite = new CCSprite();
pobSprite->initWithCGImage(pImage);
pobSprite->autorelease();
return pobSprite;
}
*/
/*
CCSprite* CCSprite::spriteWithCGImage(CGImageRef pImage, const char *pszKey)
{
CCSprite *pobSprite = new CCSprite();
pobSprite->initWithCGImage(pImage, pszKey);
pobSprite->autorelease();
return pobSprite;
}
*/
CCSprite* CCSprite::spriteWithSpriteSheet(CCSpriteSheet *pSpriteSheet, CGRect rect)
{
CCSprite *pobSprite = new CCSprite();
pobSprite->initWithSpriteSheet(pSpriteSheet, rect);
pobSprite->autorelease();
return pobSprite;
return spriteWithBatchNode(pSpriteSheet, rect);
}
bool CCSprite::init(void)
@ -174,7 +183,7 @@ bool CCSprite::init(void)
m_tAnchorPoint = ccp(0.5f, 0.5f);
// zwoptex default values
m_obOffsetPosition = CGPointZero;
m_obOffsetPositionInPixels = CGPointZero;
m_eHonorParentTransform = CC_HONOR_PARENT_TRANSFORM_ALL;
m_bHasChildren = false;
@ -191,7 +200,7 @@ bool CCSprite::init(void)
// updated in "useSelfRender"
// Atlas: TexCoords
setTextureRect(CGRectZero);
setTextureRectInPixels(CGRectZero, false, CGSizeZero);
return true;
}
@ -295,13 +304,9 @@ CCSprite* CCSprite::initWithCGImage(CGImageRef pImage, const char *pszKey)
}
*/
bool CCSprite::initWithSpriteSheet(CCSpriteSheet *pSpriteSheet, CGRect rect)
bool CCSprite::initWithSpriteSheet(CCSpriteSheetInternalOnly *pSpriteSheet, CGRect rect)
{
assert(pSpriteSheet != NULL);
bool bRet = initWithTexture(pSpriteSheet->getTexture(), rect);
useSpriteSheetRender(pSpriteSheet);
return bRet;
return initWithBatchNode(pSpriteSheet, rect);
}
CCSprite::CCSprite()
@ -319,26 +324,30 @@ CCSprite::~CCSprite(void)
void CCSprite::useSelfRender(void)
{
m_uAtlasIndex = CCSpriteIndexNotInitialized;
m_bUsesSpriteSheet = false;
m_bUsesBatchNode = false;
m_pobTextureAtlas = NULL;
m_pobSpriteSheet = NULL;
m_pobBatchNode = NULL;
m_bDirty = m_bRecursiveDirty = false;
float x1 = 0 + m_obOffsetPosition.x;
float y1 = 0 + m_obOffsetPosition.y;
float x2 = x1 + m_obRect.size.width;
float y2 = y1 + m_obRect.size.height;
float x1 = 0 + m_obOffsetPositionInPixels.x;
float y1 = 0 + m_obOffsetPositionInPixels.y;
float x2 = x1 + m_obRectInPixels.size.width;
float y2 = y1 + m_obRectInPixels.size.height;
m_sQuad.bl.vertices = vertex3(x1, y1, 0);
m_sQuad.br.vertices = vertex3(x2, y1, 0);
m_sQuad.tl.vertices = vertex3(x1, y2, 0);
m_sQuad.tr.vertices = vertex3(x2, y2, 0);
}
void CCSprite::useSpriteSheetRender(CCSpriteSheet *pSpriteSheet)
void CCSprite::useBatchNode(CCSpriteBatchNode *batchNode)
{
m_bUsesSpriteSheet = true;
m_pobTextureAtlas = pSpriteSheet->getTextureAtlas();
m_pobSpriteSheet = pSpriteSheet;
m_bUsesBatchNode = true;
m_pobTextureAtlas = m_pobBatchNode->getTextureAtlas(); // weak ref
}
void CCSprite::useSpriteSheetRender(CCSpriteSheetInternalOnly *pSpriteSheet)
{
useBatchNode(pSpriteSheet);
}
void CCSprite::initAnimationDictionary(void)
@ -348,33 +357,37 @@ void CCSprite::initAnimationDictionary(void)
void CCSprite::setTextureRect(CGRect rect)
{
setTextureRect(rect, rect.size);
CGRect rectInPixels = CC_RECT_POINTS_TO_PIXELS(rect);
setTextureRectInPixels(rectInPixels, false, rectInPixels.size);
}
void CCSprite::setTextureRect(CGRect rect, CGSize size)
void CCSprite::setTextureRectInPixels(CGRect rect, bool rotated, CGSize size)
{
m_obRect = rect;
m_obRectInPixels = rect;
m_obRect = CC_RECT_PIXELS_TO_POINTS(rect);
m_bRectRotated = rotated;
setContentSize(size);
updateTextureCoords(rect);
setContentSizeInPixels(size);
updateTextureCoords(m_obRectInPixels);
CGPoint relativeOffset = m_obUnflippedOffsetPositionFromCenter;
CGPoint relativeOffsetInPixels = m_obUnflippedOffsetPositionFromCenter;
// issue #732
if (m_bFlipX)
{
relativeOffset.x = -relativeOffset.x;
relativeOffsetInPixels.x = -relativeOffsetInPixels.x;
}
if (m_bFlipY)
{
relativeOffset.y = -relativeOffset.y;
relativeOffsetInPixels.y = -relativeOffsetInPixels.y;
}
m_obOffsetPosition.x = relativeOffset.x + (m_tContentSize.width - m_obRect.size.width) / 2;
m_obOffsetPosition.y = relativeOffset.y + (m_tContentSize.height - m_obRect.size.height) / 2;
m_obOffsetPositionInPixels.x = relativeOffsetInPixels.x + (m_tContentSizeInPixels.width - m_obRectInPixels.size.width) / 2;
m_obOffsetPositionInPixels.y = relativeOffsetInPixels.y + (m_tContentSizeInPixels.height - m_obRectInPixels.size.height) / 2;
// rendering using SpriteSheet
if (m_bUsesSpriteSheet)
if (m_bUsesBatchNode)
{
// update dirty_, don't update recursiveDirty_
m_bDirty = true;
@ -384,10 +397,10 @@ void CCSprite::setTextureRect(CGRect rect, CGSize size)
// self rendering
// Atlas: Vertex
float x1 = 0 + m_obOffsetPosition.x;
float y1 = 0 + m_obOffsetPosition.y;
float x2 = x1 + m_obRect.size.width;
float y2 = y1 + m_obRect.size.height;
float x1 = 0 + m_obOffsetPositionInPixels.x;
float y1 = 0 + m_obOffsetPositionInPixels.y;
float x2 = x1 + m_obRectInPixels.size.width;
float y2 = y1 + m_obRectInPixels.size.height;
// Don't update Z.
m_sQuad.bl.vertices = vertex3(x1, y1, 0);
@ -397,46 +410,97 @@ void CCSprite::setTextureRect(CGRect rect, CGSize size)
}
}
void CCSprite::updateTextureCoords(CGRect rect)
{
if (m_pobTexture)
CCTexture2D *tex = m_bUsesBatchNode ? m_pobTextureAtlas->getTexture() : m_pobTexture;
if (! tex)
{
float atlasWidth = (float)m_pobTexture->getPixelsWide();
float atlasHeight = (float)m_pobTexture->getPixelsHigh();
return;
}
float left = m_obRect.origin.x / atlasWidth;
float right = (m_obRect.origin.x + m_obRect.size.width) / atlasWidth;
float top = m_obRect.origin.y / atlasHeight;
float bottom = (m_obRect.origin.y + m_obRect.size.height) / atlasHeight;
float atlasWidth = (float)tex->getPixelsWide();
float atlasHeight = (float)tex->getPixelsHigh();
float left, right, top, bottom;
if (m_bRectRotated)
{
#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 (m_bFlipX)
{
float tmp = left;
left = right;
right = tmp;
CC_SWAP(top, bottom, float);
}
if (m_bFlipY)
{
float tmp = top;
top = bottom;
bottom = tmp;
CC_SWAP(left, right, float);
}
m_sQuad.bl.texCoords.u = left;
m_sQuad.bl.texCoords.v = bottom;
m_sQuad.br.texCoords.u = right;
m_sQuad.br.texCoords.v = bottom;
m_sQuad.tl.texCoords.u = left;
m_sQuad.tl.texCoords.v = top;
m_sQuad.tr.texCoords.u = right;
m_sQuad.bl.texCoords.u = left;
m_sQuad.bl.texCoords.v = top;
m_sQuad.br.texCoords.u = left;
m_sQuad.br.texCoords.v = bottom;
m_sQuad.tl.texCoords.u = right;
m_sQuad.tl.texCoords.v = top;
m_sQuad.tr.texCoords.u = right;
m_sQuad.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(m_bFlipX)
{
CC_SWAP(left,right,float);
}
if(m_bFlipY)
{
CC_SWAP(top,bottom,float);
}
m_sQuad.bl.texCoords.u = left;
m_sQuad.bl.texCoords.v = bottom;
m_sQuad.br.texCoords.u = right;
m_sQuad.br.texCoords.v = bottom;
m_sQuad.tl.texCoords.u = left;
m_sQuad.tl.texCoords.v = top;
m_sQuad.tr.texCoords.u = right;
m_sQuad.tr.texCoords.v = top;
}
}
void CCSprite::updateTransform(void)
{
assert(m_bUsesSpriteSheet);
assert(m_bUsesBatchNode);
// optimization. Quick return if not dirty
if (! m_bDirty)
{
return;
}
CGAffineTransform matrix;
@ -449,9 +513,9 @@ void CCSprite::updateTransform(void)
return;
}
// Optimization: If parent is spritesheet, or parent is nil
// Optimization: If parent is batchnode, or parent is nil
// build Affine transform manually
if (! m_pParent || m_pParent == m_pobSpriteSheet)
if (! m_pParent || m_pParent == m_pobBatchNode)
{
float radians = -CC_DEGREES_TO_RADIANS(m_fRotation);
float c = cosf(radians);
@ -459,18 +523,31 @@ void CCSprite::updateTransform(void)
matrix = CGAffineTransformMake(c * m_fScaleX, s * m_fScaleX,
-s * m_fScaleY, c * m_fScaleY,
m_tPosition.x, m_tPosition.y);
m_tPositionInPixels.x, m_tPositionInPixels.y);
matrix = CGAffineTransformTranslate(matrix, -m_tAnchorPointInPixels.x, -m_tAnchorPointInPixels.y);
} else
if (m_pParent != m_pobSpriteSheet)
} else // parent_ != batchNode_
{
// else do affine transformation according to the HonorParentTransform
matrix = CGAffineTransformIdentity;
ccHonorParentTransform prevHonor = CC_HONOR_PARENT_TRANSFORM_ALL;
for (CCNode *p = this; p && p != m_pobSpriteSheet; p = p->getParent())
for (CCNode *p = this; p && p != m_pobBatchNode; p = p->getParent())
{
struct transformValues_ tv = ((CCSprite*)p)->getTransformValues();
// Might happen. Issue #1053
// how to implement, we can not use dynamic
// 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)
{
m_sQuad.br.vertices = m_sQuad.tl.vertices = m_sQuad.tr.vertices = m_sQuad.bl.vertices = vertex3(0,0,0);
m_pobTextureAtlas->updateQuad(&m_sQuad, m_uAtlasIndex);
m_bDirty = m_bRecursiveDirty = false;
return;
}
CGAffineTransform newMatrix = CGAffineTransformIdentity;
@ -503,10 +580,10 @@ void CCSprite::updateTransform(void)
//
// calculate the Quad based on the Affine Matrix
//
CGSize size = m_obRect.size;
CGSize size = m_obRectInPixels.size;
float x1 = m_obOffsetPosition.x;
float y1 = m_obOffsetPosition.y;
float x1 = m_obOffsetPositionInPixels.x;
float y1 = m_obOffsetPositionInPixels.y;
float x2 = x1 + size.width;
float y2 = y1 + size.height;
@ -529,10 +606,10 @@ void CCSprite::updateTransform(void)
float dx = x1 * cr - y2 * sr2 + x;
float dy = x1 * sr + y2 * cr2 + y;
m_sQuad.bl.vertices = vertex3(RENDER_IN_SUBPIXEL(ax), RENDER_IN_SUBPIXEL(ay), m_fVertexZ);
m_sQuad.br.vertices = vertex3(RENDER_IN_SUBPIXEL(bx), RENDER_IN_SUBPIXEL(by), m_fVertexZ);
m_sQuad.tl.vertices = vertex3(RENDER_IN_SUBPIXEL(dx), RENDER_IN_SUBPIXEL(dy), m_fVertexZ);
m_sQuad.tr.vertices = vertex3(RENDER_IN_SUBPIXEL(cx), RENDER_IN_SUBPIXEL(cy), m_fVertexZ);
m_sQuad.bl.vertices = vertex3((float)RENDER_IN_SUBPIXEL(ax), (float)RENDER_IN_SUBPIXEL(ay), m_fVertexZ);
m_sQuad.br.vertices = vertex3((float)RENDER_IN_SUBPIXEL(bx), (float)RENDER_IN_SUBPIXEL(by), m_fVertexZ);
m_sQuad.tl.vertices = vertex3((float)RENDER_IN_SUBPIXEL(dx), (float)RENDER_IN_SUBPIXEL(dy), m_fVertexZ);
m_sQuad.tr.vertices = vertex3((float)RENDER_IN_SUBPIXEL(cx), (float)RENDER_IN_SUBPIXEL(cy), m_fVertexZ);
m_pobTextureAtlas->updateQuad(&m_sQuad, m_uAtlasIndex);
m_bDirty = m_bRecursiveDirty = false;
@ -540,31 +617,28 @@ void CCSprite::updateTransform(void)
// 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
struct transformValues_ CCSprite::getTransformValues(void)
void CCSprite::getTransformValues(struct transformValues_ *tv)
{
struct transformValues_ tv;
tv.pos = m_tPosition;
tv.scale.x = m_fScaleX;
tv.scale.y = m_fScaleY;
tv.rotation = m_fRotation;
tv.ap = m_tAnchorPointInPixels;
return tv;
tv->pos = m_tPositionInPixels;
tv->scale.x = m_fScaleX;
tv->scale.y = m_fScaleY;
tv->rotation = m_fRotation;
tv->ap = m_tAnchorPointInPixels;
tv->visible = m_bIsVisible;
}
// draw
void CCSprite::draw(void)
{
assert(! m_bUsesSpriteSheet);
assert(! m_bUsesBatchNode);
// 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 = false;
if (m_sBlendFunc.src != CC_BLEND_SRC || m_sBlendFunc.dst != CC_BLEND_DST)
bool newBlend = m_sBlendFunc.src != CC_BLEND_SRC || m_sBlendFunc.dst != CC_BLEND_DST;
if (newBlend)
{
newBlend = true;
glBlendFunc(m_sBlendFunc.src, m_sBlendFunc.dst);
}
@ -578,7 +652,7 @@ void CCSprite::draw(void)
glBindTexture(GL_TEXTURE_2D, 0);
}
int offset = (int)&m_sQuad;
long offset = (long)&m_sQuad;
// vertex
int diff = offsetof(ccV3F_C4B_T2F, vertices);
@ -611,30 +685,29 @@ void CCSprite::draw(void)
// CCNode overrides
CCNode* CCSprite::addChild(CCNode* pChild)
void CCSprite::addChild(CCNode* pChild)
{
return CCNode::addChild(pChild);
CCNode::addChild(pChild);
}
CCNode* CCSprite::addChild(CCNode *pChild, int zOrder)
void CCSprite::addChild(CCNode *pChild, int zOrder)
{
return CCNode::addChild(pChild, zOrder);
CCNode::addChild(pChild, zOrder);
}
CCNode* CCSprite::addChild(CCNode *pChild, int zOrder, int tag)
void CCSprite::addChild(CCNode *pChild, int zOrder, int tag)
{
assert(pChild != NULL);
CCNode* pRet = CCNode::addChild(pChild, zOrder, tag);
CCNode::addChild(pChild, zOrder, tag);
if (m_bUsesSpriteSheet)
if (m_bUsesBatchNode)
{
unsigned int index = m_pobSpriteSheet->atlasIndexForChild((CCSprite*)(pChild), zOrder);
m_pobSpriteSheet->insertChild((CCSprite*)(pChild), index);
assert(((CCSprite*)pChild)->getTexture()->getName() == m_pobTextureAtlas->getTexture()->getName());
unsigned int index = m_pobBatchNode->atlasIndexForChild((CCSprite*)(pChild), zOrder);
m_pobBatchNode->insertChild((CCSprite*)(pChild), index);
}
m_bHasChildren = true;
return pRet;
}
void CCSprite::reorderChild(CCNode *pChild, int zOrder)
@ -647,7 +720,7 @@ void CCSprite::reorderChild(CCNode *pChild, int zOrder)
return;
}
if (m_bUsesSpriteSheet)
if (m_bUsesBatchNode)
{
// XXX: Instead of removing/adding, it is more efficient to reorder manually
pChild->retain();
@ -663,9 +736,9 @@ void CCSprite::reorderChild(CCNode *pChild, int zOrder)
void CCSprite::removeChild(CCNode *pChild, bool bCleanup)
{
if (m_bUsesSpriteSheet)
if (m_bUsesBatchNode)
{
m_pobSpriteSheet->removeSpriteFromAtlas((CCSprite*)(pChild));
m_pobBatchNode->removeSpriteFromAtlas((CCSprite*)(pChild));
}
CCNode::removeChild(pChild, bCleanup);
@ -674,7 +747,7 @@ void CCSprite::removeChild(CCNode *pChild, bool bCleanup)
void CCSprite::removeAllChildrenWithCleanup(bool bCleanup)
{
if (m_bUsesSpriteSheet)
if (m_bUsesBatchNode)
{
CCSprite *pChild;
NSMutableArray<CCNode*>::NSMutableArrayIterator iter;
@ -682,7 +755,7 @@ void CCSprite::removeAllChildrenWithCleanup(bool bCleanup)
{
pChild = (CCSprite*)(*iter);
CCX_BREAK_IF(! pChild);
m_pobSpriteSheet->removeSpriteFromAtlas(pChild);
m_pobBatchNode->removeSpriteFromAtlas(pChild);
}
}
@ -693,7 +766,7 @@ void CCSprite::removeAllChildrenWithCleanup(bool bCleanup)
//
// CCNode property overloads
// used only when parent is CCSpriteSheet
// used only when parent is CCSpriteBatchNode
//
void CCSprite::setDirtyRecursively(bool bValue)
@ -715,7 +788,7 @@ void CCSprite::setDirtyRecursively(bool bValue)
// XXX HACK: optimization
#define SET_DIRTY_RECURSIVELY() { \
if (m_bUsesSpriteSheet && ! m_bRecursiveDirty) { \
if (m_bUsesBatchNode && ! m_bRecursiveDirty) { \
m_bDirty = m_bRecursiveDirty = true; \
if ( m_bHasChildren) \
setDirtyRecursively(true); \
@ -725,6 +798,12 @@ void CCSprite::setDirtyRecursively(bool bValue)
void CCSprite::setPosition(CGPoint pos)
{
CCNode::setPosition(pos);
SET_DIRTY_RECURSIVELY();
}
void CCSprite::setPositionInPixels(CGPoint pos)
{
CCNode::setPositionInPixels(pos);
SET_DIRTY_RECURSIVELY();
}
@ -766,32 +845,14 @@ void CCSprite::setAnchorPoint(CGPoint anchor)
void CCSprite::setIsRelativeAnchorPoint(bool bRelative)
{
assert(! m_bUsesSpriteSheet);
assert(! m_bUsesBatchNode);
CCNode::setIsRelativeAnchorPoint(bRelative);
}
void CCSprite::setIsVisible(bool bVisible)
{
if (bVisible != m_bIsVisible)
{
CCNode::setIsVisible(bVisible);
if (m_bUsesSpriteSheet && m_bRecursiveDirty)
{
m_bDirty = m_bRecursiveDirty = true;
CCNode *pChild;
NSMutableArray<CCNode*>::NSMutableArrayIterator iter;
if (m_pChildren && m_pChildren->count() != 0)
{
for (iter = m_pChildren->begin(); iter != m_pChildren->end(); ++iter)
{
pChild = *iter;
CCX_BREAK_IF(! pChild);
pChild->setIsVisible(bVisible);
}
}
}
}
CCNode::setIsVisible(bVisible);
SET_DIRTY_RECURSIVELY();
}
void CCSprite::setFlipX(bool bFlipX)
@ -799,7 +860,7 @@ void CCSprite::setFlipX(bool bFlipX)
if (m_bFlipX != bFlipX)
{
m_bFlipX = bFlipX;
setTextureRect(m_obRect);
setTextureRectInPixels(m_obRectInPixels, m_bRectRotated, m_obRectInPixels.size);
}
}
@ -813,7 +874,7 @@ void CCSprite::setFlipY(bool bFlipY)
if (m_bFlipY != bFlipY)
{
m_bFlipY = bFlipY;
setTextureRect(m_obRect);
setTextureRectInPixels(m_obRectInPixels, m_bRectRotated, m_obRectInPixels.size);
}
}
@ -836,7 +897,7 @@ void CCSprite::updateColor(void)
m_sQuad.tr.colors = color4;
// renders using Sprite Manager
if (m_bUsesSpriteSheet)
if (m_bUsesBatchNode)
{
if (m_uAtlasIndex != CCSpriteIndexNotInitialized)
{
@ -908,11 +969,11 @@ bool CCSprite::getIsOpacityModifyRGB(void)
return m_bOpacityModifyRGB;
}
// CCFrameProtocol protocol
// Frames
void CCSprite::setDisplayFrame(CCSpriteFrame *pNewFrame)
{
m_obUnflippedOffsetPositionFromCenter = pNewFrame->getOffset();
m_obUnflippedOffsetPositionFromCenter = pNewFrame->getOffsetInPixels();
CCTexture2D *pNewTexture = pNewFrame->getTexture();
// update texture before updating texture rect
@ -923,9 +984,11 @@ void CCSprite::setDisplayFrame(CCSpriteFrame *pNewFrame)
}
// update rect
setTextureRect(pNewFrame->getRect(), pNewFrame->getOriginalSize());
m_bRectRotated = pNewFrame->isRotated();
setTextureRectInPixels(pNewFrame->getRectInPixels(), pNewFrame->isRotated(), pNewFrame->getOriginalSizeInPixels());
}
// XXX deprecated
void CCSprite::setDisplayFrame(const char *pszAnimationName, int nFrameIndex)
{
if (! m_pAnimations)
@ -941,18 +1004,32 @@ void CCSprite::setDisplayFrame(const char *pszAnimationName, int nFrameIndex)
setDisplayFrame(pFrame);
}
void CCSprite::setDisplayFrameWithAnimationName(const char *animationName, int frameIndex)
{
assert(animationName);
CCAnimation *a = CCAnimationCache::sharedAnimationCache()->animationByName(animationName);
assert(a);
CCSpriteFrame *frame = a->getFrames()->getObjectAtIndex(frameIndex);
assert(frame);
setDisplayFrame(frame);
}
bool CCSprite::isFrameDisplayed(CCSpriteFrame *pFrame)
{
CGRect r = pFrame->getRect();
CGPoint p = pFrame->getOffset();
return (CGRect::CGRectEqualToRect(r, m_obRect) &&
pFrame->getTexture()->getName() == m_pobTexture->getName() &&
CGPoint::CGPointEqualToPoint(p, m_obOffsetPosition));
pFrame->getTexture()->getName() == m_pobTexture->getName());
}
CCSpriteFrame* CCSprite::displayedFrame(void)
{
return CCSpriteFrame::frameWithTexture(m_pobTexture, m_obRect, CGPointZero);
return CCSpriteFrame::frameWithTexture(m_pobTexture, m_obRect);
}
void CCSprite::addAnimation(CCAnimation *pAnimation)
@ -978,7 +1055,7 @@ CCAnimation* CCSprite::animationByName(const char *pszAnimationName)
void CCSprite::updateBlendFunc(void)
{
// CCSprite: updateBlendFunc doesn't work when the sprite is rendered using a CCSpriteSheet
assert (! m_bUsesSpriteSheet);
assert (! m_bUsesBatchNode);
// it's possible to have an untextured sprite
if (! m_pobTexture || ! m_pobTexture->getHasPremultipliedAlpha())
@ -998,7 +1075,7 @@ void CCSprite::updateBlendFunc(void)
void CCSprite::setTexture(CCTexture2D *texture)
{
// CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteSheet
assert(! m_bUsesSpriteSheet);
assert(! m_bUsesBatchNode);
// we can not use RTTI, so we do not known the type of object
// accept texture==nil as argument

View File

@ -0,0 +1,628 @@
/****************************************************************************
Copyright (c) 2010 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "CCSpriteBatchNode.h"
#include "ccConfig.h"
#include "CCSprite.h"
#include "effects/CCGrid.h"
#include "CCDrawingPrimitives.h"
#include "CCTextureCache.h"
#include "CGPointExtension.h"
namespace cocos2d
{
const int defaultCapacity = 29;
/*
* creation with CCTexture2D
*/
CCSpriteBatchNode* CCSpriteBatchNode::batchNodeWithTexture(cocos2d::CCTexture2D *tex)
{
CCSpriteBatchNode *batchNode = new CCSpriteBatchNode();
batchNode->initWithTexture(tex, defaultCapacity);
batchNode->autorelease();
return batchNode;
}
CCSpriteBatchNode* CCSpriteBatchNode::spriteSheetWithTexture(cocos2d::CCTexture2D *tex)
{
return batchNodeWithTexture(tex);
}
CCSpriteBatchNode* CCSpriteBatchNode::batchNodeWithTexture(CCTexture2D* tex, unsigned int capacity)
{
CCSpriteBatchNode *batchNode = new CCSpriteBatchNode();
batchNode->initWithTexture(tex, capacity);
batchNode->autorelease();
return batchNode;
}
CCSpriteBatchNode* CCSpriteBatchNode::spriteSheetWithTexture(CCTexture2D *tex, unsigned int capacity)
{
return batchNodeWithTexture(tex, capacity);
}
/*
* creation with File Image
*/
CCSpriteBatchNode* CCSpriteBatchNode::batchNodeWithFile(const char *fileImage, unsigned int capacity)
{
CCSpriteBatchNode *batchNode = new CCSpriteBatchNode();
batchNode->initWithFile(fileImage, capacity);
batchNode->autorelease();
return batchNode;
}
CCSpriteBatchNode* CCSpriteBatchNode::spriteSheetWithFile(const char *fileImage, unsigned int capacity)
{
return batchNodeWithFile(fileImage, capacity);
}
CCSpriteBatchNode* CCSpriteBatchNode::batchNodeWithFile(const char *fileImage)
{
CCSpriteBatchNode *batchNode = new CCSpriteBatchNode();
batchNode->initWithFile(fileImage, defaultCapacity);
batchNode->autorelease();
return batchNode;
}
CCSpriteBatchNode* CCSpriteBatchNode::spriteSheetWithFile(const char *fileImage)
{
return batchNodeWithFile(fileImage);
}
/*
* init with CCTexture2D
*/
bool CCSpriteBatchNode::initWithTexture(cocos2d::CCTexture2D *tex, unsigned int capacity)
{
m_blendFunc.src = CC_BLEND_SRC;
m_blendFunc.dst = CC_BLEND_DST;
m_pobTextureAtlas = new CCTextureAtlas();
m_pobTextureAtlas->initWithTexture(tex, capacity);
updateBlendFunc();
// no lazy alloc in this node
m_pChildren = new NSMutableArray<CCNode*>();
m_pobDescendants = new NSMutableArray<CCSprite*>();
return true;
}
/*
* init with FileImage
*/
bool CCSpriteBatchNode::initWithFile(const char* fileImage, unsigned int capacity)
{
CCTexture2D *pTexture2D = CCTextureCache::sharedTextureCache()->addImage(fileImage);
return initWithTexture(pTexture2D, capacity);
}
CCSpriteBatchNode::~CCSpriteBatchNode()
{
m_pobTextureAtlas->release();
m_pobDescendants->release();
}
// override visit
// don't call visit on it's children
void CCSpriteBatchNode::visit(void)
{
// 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 (! m_bIsVisible)
{
return;
}
glPushMatrix();
if (m_pGrid && m_pGrid->isActive())
{
m_pGrid->beforeDraw();
transformAncestors();
}
transform();
draw();
if (m_pGrid && m_pGrid->isActive())
{
m_pGrid->afterDraw(this);
}
glPopMatrix();
}
// xxx deprecated
CCSprite* CCSpriteBatchNode::createSpriteWithRect(CGRect rect)
{
CCSprite *pSprite = CCSprite::spriteWithTexture(m_pobTextureAtlas->getTexture(), rect);
pSprite->useBatchNode(this);
return pSprite;
}
// XXX deprecated
void CCSpriteBatchNode::initSprite(cocos2d::CCSprite *sprite, cocos2d::CGRect rect)
{
if (sprite)
{
sprite->initWithTexture(m_pobTextureAtlas->getTexture(), rect);
sprite->useBatchNode(this);
}
}
void CCSpriteBatchNode::addChild(CCNode *child, int zOrder, int tag)
{
assert(child != NULL);
CCSprite *pSprite = (CCSprite*)(child);
// check CCSprite is using the same texture id
assert(pSprite->getTexture()->getName() == m_pobTextureAtlas->getTexture()->getName());
CCNode::addChild(child, zOrder, tag);
unsigned int uIndex = atlasIndexForChild(pSprite, zOrder);
insertChild(pSprite, uIndex);
}
void CCSpriteBatchNode::addChild(CCNode *child)
{
CCNode::addChild(child);
}
void CCSpriteBatchNode::addChild(CCNode *child, int zOrder)
{
CCNode::addChild(child, zOrder);
}
// override reorderChild
void CCSpriteBatchNode::reorderChild(CCNode *child, int zOrder)
{
assert(child != NULL);
assert(m_pChildren->containsObject(child));
if (zOrder == child->getZOrder())
{
return;
}
// xxx: instead of removing/adding, it is more efficient ot reorder manually
child->retain();
removeChild(child, false);
addChild(child, zOrder);
child->release();
}
// override remove child
void CCSpriteBatchNode::removeChild(CCNode *child, bool cleanup)
{
CCSprite *pSprite = (CCSprite*)(child);
// explicit null handling
if (pSprite == NULL)
{
return;
}
assert(m_pChildren->containsObject(pSprite));
// cleanup before removing
removeSpriteFromAtlas(pSprite);
CCNode::removeChild(pSprite, cleanup);
}
void CCSpriteBatchNode::removeChildAtIndex(unsigned int uIndex, bool bDoCleanup)
{
removeChild((CCSprite*)(m_pChildren->getObjectAtIndex(uIndex)), bDoCleanup);
}
void CCSpriteBatchNode::removeAllChildrenWithCleanup(bool bCleanup)
{
// Invalidate atlas index. issue #569
if (m_pChildren && m_pChildren->count() > 0)
{
CCSprite *pSprite;
NSMutableArray<CCNode*>::NSMutableArrayIterator iter;
for (iter = m_pChildren->begin(); iter != m_pChildren->end(); ++iter)
{
pSprite = (CCSprite*)(*iter);
if (! pSprite)
{
break;
}
pSprite->useSelfRender();
}
}
CCNode::removeAllChildrenWithCleanup(bCleanup);
m_pobDescendants->removeAllObjects();
m_pobTextureAtlas->removeAllQuads();
}
// draw
void CCSpriteBatchNode::draw(void)
{
// Optimization: Fast Dispatch
if (m_pobTextureAtlas->getTotalQuads() == 0)
{
return;
}
if (m_pobDescendants && m_pobDescendants->count() > 0)
{
CCSprite *pSprite;
NSMutableArray<CCSprite*>::NSMutableArrayIterator iter;
for (iter = m_pobDescendants->begin(); iter != m_pobDescendants->end(); ++iter)
{
pSprite = *iter;
if (! pSprite)
{
break;
}
// fast dispatch
pSprite->updateTransform();
#if CC_SPRITESHEET_DEBUG_DRAW
// issue #528
CGRect rect = pSprite->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, true);
#endif // CC_SPRITESHEET_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 = m_blendFunc.src != CC_BLEND_SRC || m_blendFunc.dst != CC_BLEND_DST;
if (newBlend)
{
glBlendFunc(m_blendFunc.src, m_blendFunc.dst);
}
m_pobTextureAtlas->drawQuads();
if (newBlend)
{
glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
}
}
void CCSpriteBatchNode::increaseAtlasCapacity(void)
{
// 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
unsigned int quantity = (m_pobTextureAtlas->getCapacity() + 1) * 4 / 3;
CCLOG("cocos2d: CCSpriteSheet: resizing TextureAtlas capacity from %u to %u.",
(unsigned int)m_pobTextureAtlas->getCapacity(), (unsigned int)quantity);
if (! m_pobTextureAtlas->resizeCapacity(quantity))
{
// serious problems
CCLOG("cocos2d: WARNING: Not enough memory to resize the atlas");
assert(false);
}
}
unsigned int CCSpriteBatchNode::rebuildIndexInOrder(CCSprite *pobParent, unsigned int uIndex)
{
NSMutableArray<CCNode*> *pChildren = pobParent->getChildren();
if (pChildren && pChildren->count() > 0)
{
CCSprite *pSprite;
NSMutableArray<CCNode*>::NSMutableArrayIterator iter;
for (iter = pChildren->begin(); iter != pChildren->end(); ++iter)
{
pSprite = (CCSprite*)(*iter);
if (! pSprite)
{
break;
}
if (pSprite->getZOrder() < 0)
{
uIndex = rebuildIndexInOrder(pSprite, uIndex);
}
}
}
// ignore self (batch node)
if (! pobParent->isEqual(this))
{
pobParent->setAtlasIndex(uIndex);
uIndex++;
}
if (pChildren && pChildren->count() > 0)
{
CCSprite *pSprite;
NSMutableArray<CCNode*>::NSMutableArrayIterator iter;
for (iter = pChildren->begin(); iter != pChildren->end(); ++iter)
{
pSprite = (CCSprite*)(*iter);
if (! pSprite)
{
break;
}
if (pSprite->getZOrder() >= 0)
{
uIndex = rebuildIndexInOrder(pSprite, uIndex);
}
}
}
return uIndex;
}
unsigned int CCSpriteBatchNode::highestAtlasIndexInChild(CCSprite *pSprite)
{
NSMutableArray<CCNode*> *pChildren = pSprite->getChildren();
if (! pChildren || pChildren->count() == 0)
{
return pSprite->getAtlasIndex();
}
else
{
return highestAtlasIndexInChild((CCSprite*)(pChildren->getLastObject()));
}
}
unsigned int CCSpriteBatchNode::lowestAtlasIndexInChild(CCSprite *pSprite)
{
NSMutableArray<CCNode*> *pChildren = pSprite->getChildren();
if (! pChildren || pChildren->count() == 0)
{
return pSprite->getAtlasIndex();
}
else
{
return lowestAtlasIndexInChild((CCSprite*)(pChildren->getObjectAtIndex(0)));
}
}
unsigned int CCSpriteBatchNode::atlasIndexForChild(CCSprite *pobSprite, int nZ)
{
NSMutableArray<CCNode*> *pBrothers = pobSprite->getParent()->getChildren();
unsigned int uChildIndex = pBrothers->getIndexOfObject(pobSprite);
// ignore parent Z if parent is spriteSheet
bool bIgnoreParent = (CCSpriteBatchNode*)(pobSprite->getParent()) == this;
CCSprite *pPrevious = NULL;
if (uChildIndex > 0)
{
pPrevious = (CCSprite*)(pBrothers->getObjectAtIndex(uChildIndex - 1));
}
// first child of the sprite sheet
if (bIgnoreParent)
{
if (uChildIndex == 0)
{
return 0;
}
return highestAtlasIndexInChild(pPrevious) + 1;
}
// parent is a CCSprite, so, it must be taken into account
// first child of an CCSprite ?
if (uChildIndex == 0)
{
CCSprite *p = (CCSprite*)(pobSprite->getParent());
// less than parent and brothers
if (nZ < 0)
{
return p->getAtlasIndex();
}
else
{
return p->getAtlasIndex() + 1;
}
}
else
{
// previous & sprite belong to the same branch
if ((pPrevious->getZOrder() < 0 && nZ < 0) || (pPrevious->getZOrder() >= 0 && nZ >= 0))
{
return highestAtlasIndexInChild(pPrevious) + 1;
}
// else (previous < 0 and sprite >= 0 )
CCSprite *p = (CCSprite*)(pobSprite->getParent());
return p->getAtlasIndex() + 1;
}
// Should not happen. Error calculating Z on SpriteSheet
assert(0);
return 0;
}
// add child helper
void CCSpriteBatchNode::insertChild(CCSprite *pobSprite, unsigned int uIndex)
{
pobSprite->useBatchNode(this);
pobSprite->setAtlasIndex(uIndex);
pobSprite->setDirty(true);
if (m_pobTextureAtlas->getTotalQuads() == m_pobTextureAtlas->getCapacity())
{
increaseAtlasCapacity();
}
ccV3F_C4B_T2F_Quad quad = pobSprite->getQuad();
m_pobTextureAtlas->insertQuad(&quad, uIndex);
m_pobDescendants->insertObjectAtIndex(pobSprite, uIndex);
// update indices
unsigned int i = 0;
if (m_pobDescendants && m_pobDescendants->count() > 0)
{
NSMutableArray<CCSprite*>::NSMutableArrayIterator iter;
for (iter = m_pobDescendants->begin(); iter != m_pobDescendants->end(); ++iter)
{
if (! *iter)
{
break;
}
if (i > uIndex)
{
(*iter)->setAtlasIndex((*iter)->getAtlasIndex() + 1);
}
++i;
}
}
// add children recursively
NSMutableArray<CCNode*> *pChildren = pobSprite->getChildren();
if (pChildren && pChildren->count() > 0)
{
NSMutableArray<CCNode*>::NSMutableArrayIterator iterNode;
CCSprite *pSprite;
for (iterNode = pChildren->begin(); iterNode != pChildren->end(); ++iterNode)
{
pSprite = (CCSprite*)(*iterNode);
if (! pSprite)
{
break;
}
unsigned int uIndex = atlasIndexForChild(pSprite, pSprite->getZOrder());
insertChild(pSprite, uIndex);
}
}
}
void CCSpriteBatchNode::removeSpriteFromAtlas(CCSprite *pobSprite)
{
// remove from TextureAtlas
m_pobTextureAtlas->removeQuadAtIndex(pobSprite->getAtlasIndex());
// Cleanup sprite. It might be reused (issue #569)
pobSprite->useSelfRender();
unsigned int uIndex = m_pobDescendants->getIndexOfObject(pobSprite);
if (uIndex != -1)
{
m_pobDescendants->removeObjectAtIndex(uIndex);
// update all sprites beyond this one
unsigned int count = m_pobDescendants->count();
for(; uIndex < count; ++uIndex)
{
CCSprite* s = (CCSprite*)(m_pobDescendants->getObjectAtIndex(uIndex));
s->setAtlasIndex( s->getAtlasIndex() - 1 );
}
}
// remove children recursively
NSMutableArray<CCNode*> *pChildren = pobSprite->getChildren();
if (pChildren && pChildren->count() > 0)
{
CCSprite *pSprite;
NSMutableArray<CCNode*>::NSMutableArrayIterator iter;
for (iter = pChildren->begin(); iter != pChildren->end(); ++iter)
{
pSprite = (CCSprite*)(*iter);
if (! pSprite)
{
break;
}
removeSpriteFromAtlas(pSprite);
}
}
}
void CCSpriteBatchNode::updateBlendFunc(void)
{
if (! m_pobTextureAtlas->getTexture()->getHasPremultipliedAlpha())
{
m_blendFunc.src = GL_SRC_ALPHA;
m_blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
}
}
// CocosNodeTexture protocol
void CCSpriteBatchNode::setBlendFunc(ccBlendFunc blendFunc)
{
m_blendFunc = blendFunc;
}
ccBlendFunc CCSpriteBatchNode::getBlendFunc(void)
{
return m_blendFunc;
}
CCTexture2D* CCSpriteBatchNode::getTexture(void)
{
return m_pobTextureAtlas->getTexture();
}
void CCSpriteBatchNode::setTexture(CCTexture2D *texture)
{
m_pobTextureAtlas->setTexture(texture);
updateBlendFunc();
}
}

View File

@ -22,136 +22,45 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "CCTextureCache.h"
#include "CCSpriteFrame.h"
#include "ccMacros.h"
#include "CCTexture2D.h"
#include "CGGeometry.h"
namespace cocos2d {
// implementation of CCAnimation
CCAnimation* CCAnimation::animationWithName(const char *pszName)
{
CCAnimation *pAnimation = new CCAnimation();
pAnimation->initWithName(pszName);
pAnimation->autorelease();
return pAnimation;
}
CCAnimation* CCAnimation::animationWithName(const char *pszName, NSMutableArray<CCSpriteFrame*> *pFrames)
{
CCAnimation *pAnimation = new CCAnimation();
pAnimation->initWithName(pszName, pFrames);
pAnimation->autorelease();
return pAnimation;
}
CCAnimation* CCAnimation::animationWithName(const char *pszName, float fDelay, NSMutableArray<CCSpriteFrame*> *pFrames)
{
CCAnimation *pAnimation = new CCAnimation();
pAnimation->initWithName(pszName, fDelay, pFrames);
pAnimation->autorelease();
return pAnimation;
}
CCAnimation* CCAnimation::animationWithName(const char *pszName, float fDelay)
{
CCAnimation *pAnimation = new CCAnimation();
pAnimation->initWithName(pszName, fDelay);
pAnimation->autorelease();
return pAnimation;
}
bool CCAnimation::initWithName(const char *pszName)
{
return initWithName(pszName, 0, NULL);
}
bool CCAnimation::initWithName(const char *pszName, float fDelay)
{
return initWithName(pszName, fDelay, NULL);
}
bool CCAnimation::initWithName(const char *pszName, NSMutableArray<CCSpriteFrame*> *pFrames)
{
return initWithName(pszName, 0, pFrames);
}
bool CCAnimation::initWithName(const char *pszName, float fDelay, NSMutableArray<CCSpriteFrame*> *pFrames)
{
m_fDelay = fDelay;
m_nameStr = pszName;
m_pobFrames = NSMutableArray<CCSpriteFrame*>::arrayWithArray(pFrames);
return true;
}
CCAnimation::~CCAnimation(void)
{
CCLOGINFO("cocos2d, deallocing %p", this);
// [name_ release];
m_nameStr.clear();
CCX_SAFE_RELEASE(m_pobFrames);
}
void CCAnimation::addFrame(CCSpriteFrame *pFrame)
{
m_pobFrames->addObject(pFrame);
}
void CCAnimation::addFrameWithFileName(const char *pszFileName)
{
CCTexture2D *pTexture = CCTextureCache::sharedTextureCache()->addImage(pszFileName);
CGRect rect = CGRectZero;
rect.size = pTexture->getContentSize();
CCSpriteFrame *pFrame = CCSpriteFrame::frameWithTexture(pTexture, rect, CGPointZero);
m_pobFrames->addObject(pFrame);
}
void CCAnimation::addFrameWithTexture(CCTexture2D *pobTexture, CGRect rect)
{
CCSpriteFrame *pFrame = CCSpriteFrame::frameWithTexture(pobTexture, rect, CGPointZero);
m_pobFrames->addObject(pFrame);
}
// implementation of CCSpriteFrame
CCSpriteFrame* CCSpriteFrame::frameWithTexture(CCTexture2D *pobTexture, CGRect rect, CGPoint offset)
CCSpriteFrame* CCSpriteFrame::frameWithTexture(CCTexture2D *pobTexture, CGRect rect)
{
CCSpriteFrame *pSpriteFrame = new CCSpriteFrame();;
pSpriteFrame->initWithTexture(pobTexture, rect, offset, rect.size);
pSpriteFrame->initWithTexture(pobTexture, rect);
pSpriteFrame->autorelease();
return pSpriteFrame;
}
CCSpriteFrame* CCSpriteFrame::frameWithTexture(CCTexture2D *pobTexture, CGRect rect, CGPoint offset, CGSize originalSize)
CCSpriteFrame* CCSpriteFrame::frameWithTexture(CCTexture2D* pobTexture, CGRect rect, bool rotated, CGPoint offset, CGSize originalSize)
{
CCSpriteFrame *pSpriteFrame = new CCSpriteFrame();;
pSpriteFrame->initWithTexture(pobTexture, rect, offset, originalSize);
pSpriteFrame->initWithTexture(pobTexture, rect, rotated, offset, originalSize);
pSpriteFrame->autorelease();
return pSpriteFrame;
}
bool CCSpriteFrame::initWithTexture(CCTexture2D *pobTexture, CGRect rect, CGPoint offset)
bool CCSpriteFrame::initWithTexture(CCTexture2D* pobTexture, CGRect rect)
{
return initWithTexture(pobTexture, rect, offset, rect.size);
CGRect rectInPixels = CC_RECT_POINTS_TO_PIXELS(rect);
return initWithTexture(pobTexture, rectInPixels, false, CGPointZero, rectInPixels.size);
}
bool CCSpriteFrame::initWithTexture(CCTexture2D *pobTexture, CGRect rect, CGPoint offset, CGSize originalSize)
bool CCSpriteFrame::initWithTexture(CCTexture2D* pobTexture, CGRect rect, bool rotated, CGPoint offset, CGSize originalSize)
{
m_pobTexture = pobTexture;
pobTexture->retain();
m_obOffset = offset;
m_obRect = rect;
m_obOriginalSize = originalSize;
m_obRectInPixels = rect;
m_obRect = CC_RECT_PIXELS_TO_POINTS(rect);
m_bRotated = rotated;
m_obOffsetInPixels = offset;
m_obOriginalSizeInPixels = originalSize;
return true;
}
@ -166,7 +75,7 @@ NSObject* CCSpriteFrame::copyWithZone(NSZone *pZone)
{
CCSpriteFrame *pCopy = new CCSpriteFrame();
pCopy->initWithTexture(m_pobTexture, m_obRect, m_obOffset, m_obOriginalSize);
pCopy->initWithTexture(m_pobTexture, m_obRectInPixels, m_bRotated, m_obOffsetInPixels, m_obOriginalSizeInPixels);
return pCopy;
}

View File

@ -22,6 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "platform/CCNS.h"
#include "ccMacros.h"
#include "CCTextureCache.h"
#include "CCSpriteFrameCache.h"
@ -54,22 +55,25 @@ void CCSpriteFrameCache::purgeSharedSpriteFrameCache(void)
bool CCSpriteFrameCache::init(void)
{
m_pSpriteFrames= new NSDictionary<std::string, CCSpriteFrame*>();
m_pSpriteFramesAliases = new NSDictionary<std::string, CCSpriteFrame*>();
return true;
}
CCSpriteFrameCache::~CCSpriteFrameCache(void)
{
m_pSpriteFrames->release();
m_pSpriteFramesAliases->release();
}
void CCSpriteFrameCache::addSpriteFramesWithDictionary(NSDictionary<std::string, NSObject*> *dictionary, CCTexture2D *pobTexture)
{
/*
Supported Zwoptex Formats:
enum {
ZWTCoordinatesListXMLFormat_Legacy = 0
ZWTCoordinatesListXMLFormat_v1_0,
};
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<std::string, NSObject*> *metadataDict = (NSDictionary<std::string, NSObject*>*)dictionary->objectForKey(std::string("metadata"));
@ -83,11 +87,7 @@ void CCSpriteFrameCache::addSpriteFramesWithDictionary(NSDictionary<std::string,
}
// check the format
if(format < 0 || format > 1)
{
NSAssert(0, "cocos2d: WARNING: format is not supported for CCSpriteFrameCache addSpriteFramesWithDictionary:texture:");
return;
}
assert(format >=0 && format <= 3);
framesDict->begin();
std::string key = "";
@ -119,25 +119,69 @@ void CCSpriteFrameCache::addSpriteFramesWithDictionary(NSDictionary<std::string,
ow = abs(ow);
oh = abs(oh);
// create frame
spriteFrame = CCSpriteFrame::frameWithTexture(pobTexture, CGRectMake(x, y, w, h), CGPointMake(ox, oy), CGSizeMake((float)ow, (float)oh));
spriteFrame = new CCSpriteFrame();
spriteFrame->initWithTexture(pobTexture,
CGRectMake(x, y, w, h),
false,
CGPointMake(ox, oy),
CGSizeMake((float)ow, (float)oh)
);
}
else if(format == 1)
else if(format == 1 || format == 2)
{
/** @todo
CGRect frame = CGRectFromString([frameDict objectForKey:@"frame"]);
CGPoint offset = CGPointFromString([frameDict objectForKey:@"offset"]);
CGSize sourceSize = CGSizeFromString([frameDict objectForKey:@"sourceSize"]);
CGRect frame = CCRectFromString(valueForKey("frame", frameDict));
bool rotated = false;
// rotation
if (format == 2)
{
rotated = atoi(valueForKey("rotated", frameDict)) == 0 ? false : true;
}
CGPoint offset = CCPointFromString(valueForKey("offset", frameDict));
CGSize sourceSize = CCSizeFromString(valueForKey("sourceSize", frameDict));
// create frame
spriteFrame = [CCSpriteFrame frameWithTexture:texture rect:frame offset:offset originalSize:sourceSize];
spriteFrame = new CCSpriteFrame();
spriteFrame->initWithTexture(pobTexture,
frame,
rotated,
offset,
sourceSize
);
} else
if (format == 3)
{
/// @todo what's the format look like?
assert(false);
return;
/*
// get values
CGSize spriteSize = CCSizeFromString(valueForKey("spriteSize", frameDict));
CGPoint spriteOffset = CCPointFromString(valueForKey("spriteOffset", frameDict));
CGSize spriteSourceSize = CCSizeFromString(valueForKey("spriteSourceSize", frameDict));
CGRect textureRect = CCRectFromString(valueForKey("textureRect", frameDict));
bool textureRotated = atoi(valueForKey("textureRotated", frameDict)) == 0;
// get aliases
NSArray<NSString*> *aliases = NSArray<NSString*>dictionary->objectForKey(std::string("aliases"));
while( alias = (NSDictionary<std::string, NSObject*>*)aliases->next(&key) )
{
std::string value = ((NSString*)alias->objectForKey(key))->m_sString();
if (m_pSpriteFramesAliases->objectForKey(value))
{
CCLOG("cocos2d: WARNING: an alias with name %s already exists", value.c_str());
}
m_pSpriteFramesAliases->setObject(frameDict, value);
}
*/
}
else
{
CCLOG("cocos2d: Unsupported Zwoptex version. Update cocos2d.");
}
// add sprite frame
m_pSpriteFrames->setObject(spriteFrame, key);
spriteFrame->release();
}
}
@ -149,23 +193,79 @@ void CCSpriteFrameCache::addSpriteFramesWithFile(const char *pszPlist, CCTexture
return addSpriteFramesWithDictionary(dict, pobTexture);
}
void CCSpriteFrameCache::addSpriteFramesWithFile(const char* plist, const char* textureFileName)
{
assert(textureFileName);
CCTexture2D *texture = CCTextureCache::sharedTextureCache()->addImage(textureFileName);
if (texture)
{
addSpriteFramesWithFile(plist, texture);
}
else
{
CCLOG("cocos2d: CCSpriteFrameCache: couldn't load texture file. File not found %s", textureFileName);
}
}
void CCSpriteFrameCache::addSpriteFramesWithFile(const char *pszPlist)
{
const char *pszPath = CCFileUtils::fullPathFromRelativePath(pszPlist);
NSDictionary<std::string, NSObject*> *dict = CCFileUtils::dictionaryWithContentsOfFile(pszPath);
string texturePath = string(pszPlist);
string texturePath("");
// remove .xxx
size_t startPos = texturePath.find_last_of(".");
texturePath = texturePath.erase(startPos);
NSDictionary<std::string, NSObject*>* metadataDict = (NSDictionary<std::string, NSObject*>*)dict->objectForKey(string("metadata"));
if (metadataDict)
{
// try to read texture file name from meta data
texturePath = string(valueForKey("textureFileName", metadataDict));
}
// append .png
texturePath = texturePath.append(".png");
if (! texturePath.empty())
{
// build texture path relative to plist file
// stringByDeletingLastPathComponent
string textureBase(pszPlist);
int indexOfLastSeperator = textureBase.find_last_of('/');
if (indexOfLastSeperator == textureBase.length() - 1)
{
textureBase.erase(indexOfLastSeperator, 1);
indexOfLastSeperator = textureBase.find_last_of('/');
}
textureBase.erase(indexOfLastSeperator);
// stringByAppendingPathComponent
if (! textureBase.empty())
{
texturePath = textureBase + "/" + texturePath;
}
}
else
{
// build texture path by replacing file extension
// remove .xxx
size_t startPos = texturePath.find_last_of(".");
texturePath = texturePath.erase(startPos);
// append .png
texturePath = texturePath.append(".png");
CCLOG("cocos2d: CCSpriteFrameCache: Trying to use file %s as texture", texturePath);
}
CCTexture2D *pTexture = CCTextureCache::sharedTextureCache()->addImage(texturePath.c_str());
return addSpriteFramesWithDictionary(dict, pTexture);
if (pTexture)
{
addSpriteFramesWithDictionary(dict, pTexture);
}
else
{
CCLOG("cocos2d: CCSpriteFrameCache: Couldn't load texture");
}
}
void CCSpriteFrameCache::addSpriteFrame(CCSpriteFrame *pobFrame, const char *pszFrameName)
@ -176,6 +276,7 @@ void CCSpriteFrameCache::addSpriteFrame(CCSpriteFrame *pobFrame, const char *psz
void CCSpriteFrameCache::removeSpriteFrames(void)
{
m_pSpriteFrames->removeAllObjects();
m_pSpriteFramesAliases->removeAllObjects();
}
void CCSpriteFrameCache::removeUnusedSpriteFrames(void)
@ -197,15 +298,97 @@ void CCSpriteFrameCache::removeUnusedSpriteFrames(void)
void CCSpriteFrameCache::removeSpriteFrameByName(const char *pszName)
{
m_pSpriteFrames->removeObjectForKey(std::string(pszName));
// explicit nil handling
if( ! pszName )
{
return;
}
// Is this an alias ?
NSString *key = (NSString*)m_pSpriteFramesAliases->objectForKey(string(pszName));
if (key)
{
m_pSpriteFrames->removeObjectForKey(key->m_sString);
m_pSpriteFramesAliases->removeObjectForKey(key->m_sString);
}
else
{
m_pSpriteFrames->removeObjectForKey(std::string(pszName));
}
}
void CCSpriteFrameCache::removeSpriteFramesFromFile(const char* plist)
{
const char* path = CCFileUtils::fullPathFromRelativePath(plist);
NSDictionary<std::string, NSObject*>* dict = CCFileUtils::dictionaryWithContentsOfFile(path);
removeSpriteFramesFromDictionary((NSDictionary<std::string, CCSpriteFrame*>*)dict);
}
void CCSpriteFrameCache::removeSpriteFramesFromDictionary(NSDictionary<std::string, CCSpriteFrame*> *dictionary)
{
NSDictionary<std::string, NSObject*>* framesDict = (NSDictionary<std::string, NSObject*>*)dictionary->objectForKey(string("frames"));
vector<string> keysToRemove;
framesDict->begin();
std::string key = "";
NSDictionary<std::string, NSObject*> *frameDict = NULL;
while( frameDict = (NSDictionary<std::string, NSObject*>*)framesDict->next(&key) )
{
if (m_pSpriteFrames->objectForKey(key))
{
keysToRemove.push_back(key);
}
}
framesDict->end();
vector<string>::iterator iter;
for (iter = keysToRemove.begin(); iter != keysToRemove.end(); iter++)
{
m_pSpriteFrames->removeObjectForKey(*iter);
}
}
void CCSpriteFrameCache::removeSpriteFramesFromTexture(CCTexture2D* texture)
{
vector<string> keysToRemove;
m_pSpriteFrames->begin();
std::string key = "";
NSDictionary<std::string, NSObject*> *frameDict = NULL;
while( frameDict = (NSDictionary<std::string, NSObject*>*)m_pSpriteFrames->next(&key) )
{
CCSpriteFrame *frame = m_pSpriteFrames->objectForKey(key);
if (frame && (frame->getTexture() == texture))
{
keysToRemove.push_back(key);
}
}
m_pSpriteFrames->end();
vector<string>::iterator iter;
for (iter = keysToRemove.begin(); iter != keysToRemove.end(); iter++)
{
m_pSpriteFrames->removeObjectForKey(*iter);
}
}
CCSpriteFrame* CCSpriteFrameCache::spriteFrameByName(const char *pszName)
{
CCSpriteFrame *frame = m_pSpriteFrames->objectForKey(std::string(pszName));
if( ! frame )
if (! frame)
{
CCLOG("cocos2d: CCSpriteFrameCache: Frame '%s' not found", pszName);
// try alias dictionary
NSString *key = (NSString*)m_pSpriteFramesAliases->objectForKey(string(pszName));
if (key)
{
frame = m_pSpriteFrames->objectForKey(key->m_sString);
if (! frame)
{
CCLOG("cocos2d: CCSpriteFrameCahce: Frame '%s' not found", pszName);
}
}
}
return frame;
}

View File

@ -22,632 +22,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "ccConfig.h"
#include "CCSprite.h"
#include "CCSpriteSheet.h"
#include "effects/CCGrid.h"
#include "CCDrawingPrimitives.h"
#include "CCTextureCache.h"
#include "CGPointExtension.h"
namespace cocos2d {
const int defaultCapacity = 29;
// creation with CCTexture2D
CCSpriteSheet* CCSpriteSheet::spriteSheetWithTexture(CCTexture2D *pobTexture)
{
CCSpriteSheet *pSpriteSheet = new CCSpriteSheet();
pSpriteSheet->initWithTexture(pobTexture, defaultCapacity);
pSpriteSheet->autorelease();
return pSpriteSheet;
}
CCSpriteSheet* CCSpriteSheet::spriteSheetWithTexture(CCTexture2D *pobTexture, unsigned int uCapacity)
{
CCSpriteSheet *pSpriteSheet = new CCSpriteSheet();
pSpriteSheet->initWithTexture(pobTexture, uCapacity);
pSpriteSheet->autorelease();
return pSpriteSheet;
}
// creation with file image
CCSpriteSheet* CCSpriteSheet::spriteSheetWithFile(const char *pszFileImage, unsigned int uCapacity)
{
CCSpriteSheet *pSpriteSheet = new CCSpriteSheet();
pSpriteSheet->initWithFile(pszFileImage, uCapacity);
pSpriteSheet->autorelease();
return pSpriteSheet;
}
CCSpriteSheet* CCSpriteSheet::spriteSheetWithFile(const char *pszFileImage)
{
CCSpriteSheet *pSpriteSheet = new CCSpriteSheet();
pSpriteSheet->initWithFile(pszFileImage, defaultCapacity);
pSpriteSheet->autorelease();
return pSpriteSheet;
}
// init with CCTexture2D
bool CCSpriteSheet::initWithTexture(CCTexture2D *pobTexture, unsigned int uCapacity)
{
m_blendFunc.src = CC_BLEND_SRC;
m_blendFunc.dst = CC_BLEND_DST;
m_pobTextureAtlas = new CCTextureAtlas();
m_pobTextureAtlas->initWithTexture(pobTexture, uCapacity);
updateBlendFunc();
// no lazy alloc in this node
m_pChildren = new NSMutableArray<CCNode*>();
m_pobDescendants = new NSMutableArray<CCSprite*>();
return true;
}
// init with FileImage
bool CCSpriteSheet::initWithFile(const char *pszFileImage, unsigned int uCapacity)
{
CCTexture2D *pTexture2D = CCTextureCache::sharedTextureCache()->addImage(pszFileImage);
return initWithTexture(pTexture2D, uCapacity);
}
CCSpriteSheet::~CCSpriteSheet(void)
{
m_pobTextureAtlas->release();
m_pobDescendants->release();
}
// composition
// override visit
// don't call visit on it's children
void CCSpriteSheet::visit(void)
{
// 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 (! m_bIsVisible)
{
return;
}
glPushMatrix();
if (m_pGrid && m_pGrid->isActive())
{
m_pGrid->beforeDraw();
transformAncestors();
}
transform();
draw();
if (m_pGrid && m_pGrid->isActive())
{
m_pGrid->afterDraw(this);
}
glPopMatrix();
}
// xxx deprecated
CCSprite* CCSpriteSheet::createSpriteWithRect(CGRect rect)
{
CCSprite *pSprite = CCSprite::spriteWithTexture(m_pobTextureAtlas->getTexture(), rect);
pSprite->useSpriteSheetRender(this);
return pSprite;
}
// override add child
CCNode* CCSpriteSheet::addChild(CCNode *child)
{
return CCNode::addChild(child);
}
CCNode* CCSpriteSheet::addChild(CCNode *child, int zOrder)
{
return CCNode::addChild(child, zOrder);
}
CCNode* CCSpriteSheet::addChild(CCNode *child, int zOrder, int tag)
{
assert(child != NULL);
CCSprite *pSprite = (CCSprite*)(child);
// check CCSprite is using the same texture id
assert(pSprite->getTexture()->getName() == m_pobTextureAtlas->getTexture()->getName());
CCNode *pRet = CCNode::addChild(child, zOrder, tag);
unsigned int uIndex = atlasIndexForChild(pSprite, zOrder);
insertChild(pSprite, uIndex);
return pRet;
}
// override reorderChild
void CCSpriteSheet::reorderChild(CCNode *child, int zOrder)
{
assert(child != NULL);
assert(m_pChildren->containsObject(child));
if (zOrder == child->getZOrder())
{
return;
}
// xxx: instead of removing/adding, it is more efficient ot reorder manually
child->retain();
removeChild(child, false);
addChild(child, zOrder);
child->release();
}
// override remove child
void CCSpriteSheet::removeChild(CCNode *child, bool cleanup)
{
CCSprite *pSprite = (CCSprite*)(child);
// explicit null handling
if (pSprite == NULL)
{
return;
}
assert(m_pChildren->containsObject(pSprite));
// cleanup before removing
removeSpriteFromAtlas(pSprite);
CCNode::removeChild(pSprite, cleanup);
}
void CCSpriteSheet::removeChildAtIndex(unsigned int uIndex, bool bDoCleanup)
{
removeChild((CCSprite*)(m_pChildren->getObjectAtIndex(uIndex)), bDoCleanup);
}
void CCSpriteSheet::removeAllChildrenWithCleanup(bool bCleanup)
{
// Invalidate atlas index. issue #569
if (m_pChildren && m_pChildren->count() > 0)
{
CCSprite *pSprite;
NSMutableArray<CCNode*>::NSMutableArrayIterator iter;
for (iter = m_pChildren->begin(); iter != m_pChildren->end(); ++iter)
{
pSprite = (CCSprite*)(*iter);
if (! pSprite)
{
break;
}
pSprite->useSelfRender();
}
}
CCNode::removeAllChildrenWithCleanup(bCleanup);
m_pobDescendants->removeAllObjects();
m_pobTextureAtlas->removeAllQuads();
}
// draw
void CCSpriteSheet::draw(void)
{
if (m_pobTextureAtlas->getTotalQuads() == 0)
{
return;
}
if (m_pobDescendants && m_pobDescendants->count() > 0)
{
CCSprite *pSprite;
NSMutableArray<CCSprite*>::NSMutableArrayIterator iter;
for (iter = m_pobDescendants->begin(); iter != m_pobDescendants->end(); ++iter)
{
pSprite = *iter;
if (! pSprite)
{
break;
}
// fast dispatch
if (pSprite->isDirty())
{
pSprite->updateTransform();
}
#if CC_SPRITESHEET_DEBUG_DRAW
CGRect rect = pSprite->boundingBox(); // Issue #528
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_SPRITESHEET_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 = false;
if (m_blendFunc.src != CC_BLEND_SRC || m_blendFunc.dst != CC_BLEND_DST)
{
newBlend = true;
glBlendFunc(m_blendFunc.src, m_blendFunc.dst);
}
m_pobTextureAtlas->drawQuads();
if (newBlend)
{
glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
}
}
void CCSpriteSheet::increaseAtlasCapacity(void)
{
// 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
unsigned int quantity = (m_pobTextureAtlas->getCapacity() + 1) * 4 / 3;
CCLOG("cocos2d: CCSpriteSheet: resizing TextureAtlas capacity from %d to %d.",
m_pobTextureAtlas->getCapacity(), quantity);
if (! m_pobTextureAtlas->resizeCapacity(quantity))
{
// serious problems
CCLOG("cocos2d: WARNING: Not enough memory to resize the atlas");
assert(false);
}
}
unsigned int CCSpriteSheet::rebuildIndexInOrder(CCSprite *pobParent, unsigned int uIndex)
{
NSMutableArray<CCNode*> *pChildren = pobParent->getChildren();
if (pChildren && pChildren->count() > 0)
{
CCSprite *pSprite;
NSMutableArray<CCNode*>::NSMutableArrayIterator iter;
for (iter = pChildren->begin(); iter != pChildren->end(); ++iter)
{
pSprite = (CCSprite*)(*iter);
if (! pSprite)
{
break;
}
if (pSprite->getZOrder() < 0)
{
uIndex = rebuildIndexInOrder(pSprite, uIndex);
}
}
}
// ignore self (spritesheet)
if (! pobParent->isEqual(this))
{
pobParent->setAtlasIndex(uIndex);
uIndex++;
}
if (pChildren && pChildren->count() > 0)
{
CCSprite *pSprite;
NSMutableArray<CCNode*>::NSMutableArrayIterator iter;
for (iter = pChildren->begin(); iter != pChildren->end(); ++iter)
{
pSprite = (CCSprite*)(*iter);
if (! pSprite)
{
break;
}
if (pSprite->getZOrder() >= 0)
{
uIndex = rebuildIndexInOrder(pSprite, uIndex);
}
}
}
return uIndex;
}
unsigned int CCSpriteSheet::highestAtlasIndexInChild(CCSprite *pSprite)
{
NSMutableArray<CCNode*> *pChildren = pSprite->getChildren();
if (! pChildren || pChildren->count() == 0)
{
return pSprite->getAtlasIndex();
}
else
{
return highestAtlasIndexInChild((CCSprite*)(pChildren->getLastObject()));
}
}
unsigned int CCSpriteSheet::lowestAtlasIndexInChild(CCSprite *pSprite)
{
NSMutableArray<CCNode*> *pChildren = pSprite->getChildren();
if (! pChildren || pChildren->count() == 0)
{
return pSprite->getAtlasIndex();
}
else
{
return lowestAtlasIndexInChild((CCSprite*)(pChildren->getObjectAtIndex(0)));
}
}
unsigned int CCSpriteSheet::atlasIndexForChild(CCSprite *pobSprite, int nZ)
{
NSMutableArray<CCNode*> *pBrothers = pobSprite->getParent()->getChildren();
unsigned int uChildIndex = pBrothers->getIndexOfObject(pobSprite);
// ignore parent Z if parent is spriteSheet
bool bIgnoreParent = (CCSpriteSheet*)(pobSprite->getParent()) == this;
CCSprite *pPrevious = NULL;
if (uChildIndex > 0)
{
pPrevious = (CCSprite*)(pBrothers->getObjectAtIndex(uChildIndex - 1));
}
// first child of the sprite sheet
if (bIgnoreParent)
{
if (uChildIndex == 0)
{
return 0;
}
return highestAtlasIndexInChild(pPrevious) + 1;
}
// parent is a CCSprite, so, it must be taken into account
// first child of an CCSprite ?
if (uChildIndex == 0)
{
CCSprite *p = (CCSprite*)(pobSprite->getParent());
// less than parent and brothers
if (nZ < 0)
{
return p->getAtlasIndex();
}
else
{
return p->getAtlasIndex() + 1;
}
}
else
{
// previous & sprite belong to the same branch
if ((pPrevious->getZOrder() < 0 && nZ < 0) || (pPrevious->getZOrder() >= 0 && nZ >= 0))
{
return highestAtlasIndexInChild(pPrevious) + 1;
}
// else (previous < 0 and sprite >= 0 )
CCSprite *p = (CCSprite*)(pobSprite->getParent());
return p->getAtlasIndex() + 1;
}
// Should not happen. Error calculating Z on SpriteSheet
assert(0);
return 0;
}
// add child helper
void CCSpriteSheet::insertChild(CCSprite *pobSprite, unsigned int uIndex)
{
pobSprite->useSpriteSheetRender(this);
pobSprite->setAtlasIndex(uIndex);
pobSprite->setDirty(true);
if (m_pobTextureAtlas->getTotalQuads() == m_pobTextureAtlas->getCapacity())
{
increaseAtlasCapacity();
}
ccV3F_C4B_T2F_Quad quad = pobSprite->getQuad();
m_pobTextureAtlas->insertQuad(&quad, uIndex);
m_pobDescendants->insertObjectAtIndex(pobSprite, uIndex);
// update indices
unsigned int i = 0;
if (m_pobDescendants && m_pobDescendants->count() > 0)
{
NSMutableArray<CCSprite*>::NSMutableArrayIterator iter;
for (iter = m_pobDescendants->begin(); iter != m_pobDescendants->end(); ++iter)
{
if (! *iter)
{
break;
}
if (i > uIndex)
{
(*iter)->setAtlasIndex((*iter)->getAtlasIndex() + 1);
}
++i;
}
}
// add children recursively
NSMutableArray<CCNode*> *pChildren = pobSprite->getChildren();
if (pChildren && pChildren->count() > 0)
{
NSMutableArray<CCNode*>::NSMutableArrayIterator iterNode;
CCSprite *pSprite;
for (iterNode = pChildren->begin(); iterNode != pChildren->end(); ++iterNode)
{
pSprite = (CCSprite*)(*iterNode);
if (! pSprite)
{
break;
}
unsigned int uIndex = atlasIndexForChild(pSprite, pSprite->getZOrder());
insertChild(pSprite, uIndex);
}
}
}
void CCSpriteSheet::removeSpriteFromAtlas(CCSprite *pobSprite)
{
// remove from TextureAtlas
m_pobTextureAtlas->removeQuadAtIndex(pobSprite->getAtlasIndex());
// Cleanup sprite. It might be reused (issue #569)
pobSprite->useSelfRender();
unsigned int uIndex = m_pobDescendants->getIndexOfObject(pobSprite);
if (uIndex != -1)
{
m_pobDescendants->removeObjectAtIndex(uIndex);
// update all sprites beyond this one
unsigned int count = m_pobDescendants->count();
for(; uIndex < count; ++uIndex)
{
CCSprite* s = (CCSprite*)(m_pobDescendants->getObjectAtIndex(uIndex));
s->setAtlasIndex( s->getAtlasIndex() - 1 );
}
}
// remove children recursively
NSMutableArray<CCNode*> *pChildren = pobSprite->getChildren();
if (pChildren && pChildren->count() > 0)
{
CCSprite *pSprite;
NSMutableArray<CCNode*>::NSMutableArrayIterator iter;
for (iter = pChildren->begin(); iter != pChildren->end(); ++iter)
{
pSprite = (CCSprite*)(*iter);
if (! pSprite)
{
break;
}
removeSpriteFromAtlas(pSprite);
}
}
}
void CCSpriteSheet::updateBlendFunc(void)
{
if (! m_pobTextureAtlas->getTexture()->getHasPremultipliedAlpha())
{
m_blendFunc.src = GL_SRC_ALPHA;
m_blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
}
}
// CocosNodeTexture protocol
void CCSpriteSheet::setBlendFunc(ccBlendFunc blendFunc)
{
m_blendFunc = blendFunc;
}
ccBlendFunc CCSpriteSheet::getBlendFunc(void)
{
return m_blendFunc;
}
CCTexture2D* CCSpriteSheet::getTexture(void)
{
return m_pobTextureAtlas->getTexture();
}
void CCSpriteSheet::setTexture(CCTexture2D *texture)
{
m_pobTextureAtlas->setTexture(texture);
}
// CCSpriteSheet Extension
//implementation CCSpriteSheet (TMXTiledMapExtension)
void CCSpriteSheet::addQuadFromSprite(CCSprite *sprite, unsigned int index)
{
NSAssert( sprite != NULL, "Argument must be non-nil");
/// @todo NSAssert( [sprite isKindOfClass:[CCSprite class]], @"CCSpriteSheet only supports CCSprites as children");
while(index >= m_pobTextureAtlas->getCapacity() || m_pobTextureAtlas->getCapacity() == m_pobTextureAtlas->getTotalQuads())
{
this->increaseAtlasCapacity();
}
//
// update the quad directly. Don't add the sprite to the scene graph
//
sprite->useSpriteSheetRender(this);
sprite->setAtlasIndex(index);
ccV3F_C4B_T2F_Quad quad = sprite->getQuad();
m_pobTextureAtlas->insertQuad(&quad, index);
// XXX: updateTransform will update the textureAtlas too using updateQuad.
// XXX: so, it should be AFTER the insertQuad
sprite->updateTransform();
}
CCSpriteSheet * CCSpriteSheet::addSpriteWithoutQuad(CCSprite*child, unsigned int z, int aTag)
{
NSAssert( child != NULL, "Argument must be non-nil");
/// @todo 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;
if (m_pobDescendants && m_pobDescendants->count() > 0)
{
NSMutableArray<CCSprite*>::NSMutableArrayIterator iter;
for (iter = m_pobDescendants->begin(); iter != m_pobDescendants->end(); ++iter)
{
// fast dispatch
if (!(*iter) || (*iter)->getAtlasIndex() >=z)
{
break;
}
++i;
}
}
m_pobDescendants->insertObjectAtIndex(child, i);
// IMPORTANT: Call super, and not self. Avoid adding it to the texture atlas array
CCNode::addChild(child, z, aTag);
return this;
}
}//namespace cocos2d