2010-08-02 10:58:00 +08:00
/****************************************************************************
2011-03-19 14:45:51 +08:00
Copyright ( c ) 2010 - 2011 cocos2d - x . org
Copyright ( c ) 2008 - 2010 Ricardo Quesada
2011-07-01 16:11:31 +08:00
Copyright ( c ) 2011 Zynga Inc .
2010-08-02 10:58:00 +08:00
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-12-27 10:26:56 +08:00
# include "CCSpriteBatchNode.h"
# include "CCAnimation.h"
# include "CCAnimationCache.h"
2010-08-02 10:58:00 +08:00
# include "ccConfig.h"
# include "CCSprite.h"
# include "CCSpriteFrame.h"
# include "CCSpriteFrameCache.h"
# include "CCTextureCache.h"
2011-03-07 17:11:57 +08:00
# include "CCPointExtension.h"
2010-08-02 10:58:00 +08:00
# include "CCDrawingPrimitives.h"
2011-03-07 17:11:57 +08:00
# include "CCGeometry.h"
2010-08-02 10:58:00 +08:00
# include "CCTexture2D.h"
2011-03-07 17:11:57 +08:00
# include "CCAffineTransform.h"
2010-10-08 17:53:04 +08:00
2010-08-02 10:58:00 +08:00
# include <string.h>
using namespace std ;
2010-11-12 15:55:28 +08:00
namespace cocos2d {
2010-08-02 10:58:00 +08:00
2010-12-27 10:26:56 +08:00
# if CC_SPRITEBATCHNODE_RENDER_SUBPIXEL
2010-07-22 14:54:47 +08:00
# define RENDER_IN_SUBPIXEL
# else
# define RENDER_IN_SUBPIXEL(__A__) ( (int)(__A__))
# endif
// XXX: Optmization
struct transformValues_ {
2011-11-18 21:23:54 +08:00
CCPoint pos ; // position x and y
CCPoint scale ; // scale x and y
float rotation ;
2011-07-01 16:11:31 +08:00
CCPoint skew ; // skew x and y
2011-11-18 21:23:54 +08:00
CCPoint ap ; // anchor point in pixels
bool visible ;
2010-07-22 14:54:47 +08:00
} ;
2011-08-17 21:19:57 +08:00
CCSprite * CCSprite : : spriteWithBatchNode ( CCSpriteBatchNode * batchNode , const CCRect & rect )
2010-12-27 10:26:56 +08:00
{
2011-11-18 21:23:54 +08:00
CCSprite * pobSprite = new CCSprite ( ) ;
if ( pobSprite & & pobSprite - > initWithBatchNode ( batchNode , rect ) )
{
2010-12-27 10:26:56 +08:00
pobSprite - > autorelease ( ) ;
2011-03-31 14:56:49 +08:00
return pobSprite ;
}
CC_SAFE_DELETE ( pobSprite ) ;
2011-11-18 21:23:54 +08:00
return NULL ;
2010-12-27 10:26:56 +08:00
}
2011-08-17 21:19:57 +08:00
bool CCSprite : : initWithBatchNode ( CCSpriteBatchNode * batchNode , const CCRect & rect )
2010-12-27 10:26:56 +08:00
{
2011-11-18 21:23:54 +08:00
if ( initWithTexture ( batchNode - > getTexture ( ) , rect ) )
2011-03-31 14:56:49 +08:00
{
2011-11-18 21:23:54 +08:00
useBatchNode ( batchNode ) ;
2011-03-31 14:56:49 +08:00
return true ;
}
2011-11-18 21:23:54 +08:00
return false ;
2010-12-27 10:26:56 +08:00
}
2011-08-17 21:19:57 +08:00
bool CCSprite : : initWithBatchNodeRectInPixels ( CCSpriteBatchNode * batchNode , const CCRect & rect )
2010-12-27 10:26:56 +08:00
{
2011-11-18 21:23:54 +08:00
if ( initWithTexture ( batchNode - > getTexture ( ) ) )
2011-03-31 14:56:49 +08:00
{
2011-11-18 21:23:54 +08:00
setTextureRectInPixels ( rect , false , rect . size ) ;
useBatchNode ( batchNode ) ;
2011-03-31 14:56:49 +08:00
return true ;
}
2011-11-18 21:23:54 +08:00
return false ;
2010-12-27 10:26:56 +08:00
}
2010-07-22 14:54:47 +08:00
CCSprite * CCSprite : : spriteWithTexture ( CCTexture2D * pTexture )
{
2011-11-18 21:23:54 +08:00
CCSprite * pobSprite = new CCSprite ( ) ;
if ( pobSprite & & pobSprite - > initWithTexture ( pTexture ) )
2011-03-31 14:56:49 +08:00
{
2011-11-18 21:23:54 +08:00
pobSprite - > autorelease ( ) ;
2011-03-31 14:56:49 +08:00
return pobSprite ;
}
CC_SAFE_DELETE ( pobSprite ) ;
2011-11-18 21:23:54 +08:00
return NULL ;
2010-07-22 14:54:47 +08:00
}
2011-08-17 21:19:57 +08:00
CCSprite * CCSprite : : spriteWithTexture ( CCTexture2D * pTexture , const CCRect & rect )
2010-07-22 14:54:47 +08:00
{
CCSprite * pobSprite = new CCSprite ( ) ;
2011-11-18 21:23:54 +08:00
if ( pobSprite & & pobSprite - > initWithTexture ( pTexture , rect ) )
2011-03-31 14:56:49 +08:00
{
2011-11-18 21:23:54 +08:00
pobSprite - > autorelease ( ) ;
2011-03-31 14:56:49 +08:00
return pobSprite ;
}
CC_SAFE_DELETE ( pobSprite ) ;
2011-11-18 21:23:54 +08:00
return NULL ;
2010-07-22 14:54:47 +08:00
}
2011-08-17 21:19:57 +08:00
CCSprite * CCSprite : : spriteWithTexture ( CCTexture2D * pTexture , const CCRect & rect , const CCPoint & offset )
2010-07-22 14:54:47 +08:00
{
2011-06-10 17:51:37 +08:00
CC_UNUSED_PARAM ( pTexture ) ;
CC_UNUSED_PARAM ( rect ) ;
CC_UNUSED_PARAM ( offset ) ;
2011-11-18 21:23:54 +08:00
// not implement
assert ( 0 ) ;
return NULL ;
2010-07-22 14:54:47 +08:00
}
CCSprite * CCSprite : : spriteWithFile ( const char * pszFileName )
{
CCSprite * pobSprite = new CCSprite ( ) ;
2011-03-31 14:56:49 +08:00
if ( pobSprite & & pobSprite - > initWithFile ( pszFileName ) )
{
pobSprite - > autorelease ( ) ;
return pobSprite ;
}
CC_SAFE_DELETE ( pobSprite ) ;
2011-11-18 21:23:54 +08:00
return NULL ;
2010-07-22 14:54:47 +08:00
}
2011-08-17 21:19:57 +08:00
CCSprite * CCSprite : : spriteWithFile ( const char * pszFileName , const CCRect & rect )
2010-07-22 14:54:47 +08:00
{
CCSprite * pobSprite = new CCSprite ( ) ;
2011-11-18 21:23:54 +08:00
if ( pobSprite & & pobSprite - > initWithFile ( pszFileName , rect ) )
2011-03-31 14:56:49 +08:00
{
2011-11-18 21:23:54 +08:00
pobSprite - > autorelease ( ) ;
2011-03-31 14:56:49 +08:00
return pobSprite ;
}
CC_SAFE_DELETE ( pobSprite ) ;
2011-11-18 21:23:54 +08:00
return NULL ;
2010-07-22 14:54:47 +08:00
}
CCSprite * CCSprite : : spriteWithSpriteFrame ( CCSpriteFrame * pSpriteFrame )
{
CCSprite * pobSprite = new CCSprite ( ) ;
2011-03-31 14:56:49 +08:00
if ( pobSprite & & pobSprite - > initWithSpriteFrame ( pSpriteFrame ) )
{
2011-11-18 21:23:54 +08:00
pobSprite - > autorelease ( ) ;
2011-03-31 14:56:49 +08:00
return pobSprite ;
}
CC_SAFE_DELETE ( pobSprite ) ;
2011-11-18 21:23:54 +08:00
return NULL ;
2010-07-22 14:54:47 +08:00
}
CCSprite * CCSprite : : spriteWithSpriteFrameName ( const char * pszSpriteFrameName )
{
2011-11-18 21:23:54 +08:00
CCSpriteFrame * pFrame = CCSpriteFrameCache : : sharedSpriteFrameCache ( ) - > spriteFrameByName ( pszSpriteFrameName ) ;
2011-07-08 15:02:46 +08:00
char msg [ 256 ] = { 0 } ;
sprintf ( msg , " Invalid spriteFrameName: %s " , pszSpriteFrameName ) ;
CCAssert ( pFrame ! = NULL , msg ) ;
2011-11-18 21:23:54 +08:00
return spriteWithSpriteFrame ( pFrame ) ;
2010-07-22 14:54:47 +08:00
}
2010-09-04 12:02:52 +08:00
bool CCSprite : : init ( void )
2010-07-22 14:54:47 +08:00
{
2011-11-18 21:23:54 +08:00
m_bDirty = m_bRecursiveDirty = false ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
// by default use "Self Render".
// if the sprite is added to an batchnode, then it will automatically switch to "SpriteSheet Render"
2010-07-22 14:54:47 +08:00
useSelfRender ( ) ;
2011-11-18 21:23:54 +08:00
m_bOpacityModifyRGB = true ;
m_nOpacity = 255 ;
m_sColor = m_sColorUnmodified = ccWHITE ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
m_sBlendFunc . src = CC_BLEND_SRC ;
m_sBlendFunc . dst = CC_BLEND_DST ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
// update texture (calls updateBlendFunc)
setTexture ( NULL ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
// clean the Quad
memset ( & m_sQuad , 0 , sizeof ( m_sQuad ) ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
m_bFlipX = m_bFlipY = false ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
// default transform anchor: center
setAnchorPoint ( ccp ( 0.5f , 0.5f ) ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
// zwoptex default values
2011-03-07 17:11:57 +08:00
m_obOffsetPositionInPixels = CCPointZero ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
m_eHonorParentTransform = CC_HONOR_PARENT_TRANSFORM_ALL ;
m_bHasChildren = false ;
// Atlas: Color
ccColor4B tmpColor = { 255 , 255 , 255 , 255 } ;
m_sQuad . bl . colors = tmpColor ;
m_sQuad . br . colors = tmpColor ;
m_sQuad . tl . colors = tmpColor ;
m_sQuad . tr . colors = tmpColor ;
// Atlas: Vertex
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
// updated in "useSelfRender"
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
// Atlas: TexCoords
setTextureRectInPixels ( CCRectZero , false , CCSizeZero ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
return true ;
2010-07-22 14:54:47 +08:00
}
2011-08-17 21:19:57 +08:00
bool CCSprite : : initWithTexture ( CCTexture2D * pTexture , const CCRect & rect )
2010-07-22 14:54:47 +08:00
{
2011-11-18 21:23:54 +08:00
assert ( pTexture ! = NULL ) ;
// IMPORTANT: [self init] and not [super init];
init ( ) ;
setTexture ( pTexture ) ;
setTextureRect ( rect ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
return true ;
2010-07-22 14:54:47 +08:00
}
2010-09-04 12:02:52 +08:00
bool CCSprite : : initWithTexture ( CCTexture2D * pTexture )
2010-07-22 14:54:47 +08:00
{
2011-11-18 21:23:54 +08:00
assert ( pTexture ! = NULL ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
CCRect rect = CCRectZero ;
rect . size = pTexture - > getContentSize ( ) ;
return initWithTexture ( pTexture , rect ) ;
2010-07-22 14:54:47 +08:00
}
2010-09-04 12:02:52 +08:00
bool CCSprite : : initWithFile ( const char * pszFilename )
2010-07-22 14:54:47 +08:00
{
2011-11-18 21:23:54 +08:00
assert ( pszFilename ! = NULL ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
CCTexture2D * pTexture = CCTextureCache : : sharedTextureCache ( ) - > addImage ( pszFilename ) ;
if ( pTexture )
{
CCRect rect = CCRectZero ;
rect . size = pTexture - > getContentSize ( ) ;
return initWithTexture ( pTexture , rect ) ;
}
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
// don't release here.
// when load texture failed, it's better to get a "transparent" sprite then a crashed program
// this->release();
return false ;
2010-07-22 14:54:47 +08:00
}
2011-08-17 21:19:57 +08:00
bool CCSprite : : initWithFile ( const char * pszFilename , const CCRect & rect )
2010-07-22 14:54:47 +08:00
{
2011-11-18 21:23:54 +08:00
assert ( pszFilename ! = NULL ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
CCTexture2D * pTexture = CCTextureCache : : sharedTextureCache ( ) - > addImage ( pszFilename ) ;
if ( pTexture )
{
return initWithTexture ( pTexture , rect ) ;
}
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
// don't release here.
// when load texture failed, it's better to get a "transparent" sprite then a crashed program
// this->release();
return false ;
2010-07-22 14:54:47 +08:00
}
2010-09-04 12:02:52 +08:00
bool CCSprite : : initWithSpriteFrame ( CCSpriteFrame * pSpriteFrame )
2010-07-22 14:54:47 +08:00
{
2011-11-18 21:23:54 +08:00
assert ( pSpriteFrame ! = NULL ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
bool bRet = initWithTexture ( pSpriteFrame - > getTexture ( ) , pSpriteFrame - > getRect ( ) ) ;
setDisplayFrame ( pSpriteFrame ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
return bRet ;
2010-07-22 14:54:47 +08:00
}
2010-09-04 12:02:52 +08:00
bool CCSprite : : initWithSpriteFrameName ( const char * pszSpriteFrameName )
2010-07-22 14:54:47 +08:00
{
2011-11-18 21:23:54 +08:00
assert ( pszSpriteFrameName ! = NULL ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
CCSpriteFrame * pFrame = CCSpriteFrameCache : : sharedSpriteFrameCache ( ) - > spriteFrameByName ( pszSpriteFrameName ) ;
return initWithSpriteFrame ( pFrame ) ;
2010-07-22 14:54:47 +08:00
}
// XXX: deprecated
/*
CCSprite * CCSprite : : initWithCGImage ( CGImageRef pImage )
{
// todo
// because it is deprecated, so we do not impelment it
return NULL ;
}
*/
/*
CCSprite * CCSprite : : initWithCGImage ( CGImageRef pImage , const char * pszKey )
{
assert ( pImage ! = NULL ) ;
// XXX: possible bug. See issue #349. New API should be added
CCTexture2D * pTexture = CCTextureCache : : sharedTextureCache ( ) - > addCGImage ( pImage , pszKey ) ;
2011-08-17 21:19:57 +08:00
const CCSize & size = pTexture - > getContentSize ( ) ;
2011-03-07 17:11:57 +08:00
CCRect rect = CCRectMake ( 0 , 0 , size . width , size . height ) ;
2010-07-22 14:54:47 +08:00
return initWithTexture ( texture , rect ) ;
}
*/
2010-09-09 10:17:38 +08:00
CCSprite : : CCSprite ( )
2011-11-18 21:23:54 +08:00
: m_pobTexture ( NULL )
2010-09-09 10:17:38 +08:00
{
}
2010-07-22 14:54:47 +08:00
CCSprite : : ~ CCSprite ( void )
{
2011-11-18 21:23:54 +08:00
CC_SAFE_RELEASE ( m_pobTexture ) ;
2010-07-22 14:54:47 +08:00
}
void CCSprite : : useSelfRender ( void )
{
m_uAtlasIndex = CCSpriteIndexNotInitialized ;
2011-11-18 21:23:54 +08:00
m_bUsesBatchNode = false ;
m_pobTextureAtlas = NULL ;
2010-12-27 10:26:56 +08:00
m_pobBatchNode = NULL ;
2011-11-18 21:23:54 +08:00
m_bDirty = m_bRecursiveDirty = false ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
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 ) ;
2010-07-22 14:54:47 +08:00
}
2010-12-27 10:26:56 +08:00
void CCSprite : : useBatchNode ( CCSpriteBatchNode * batchNode )
{
m_bUsesBatchNode = true ;
2011-11-18 21:23:54 +08:00
m_pobTextureAtlas = batchNode - > getTextureAtlas ( ) ; // weak ref
2011-01-05 17:01:08 +08:00
m_pobBatchNode = batchNode ;
2010-12-27 10:26:56 +08:00
}
2011-08-17 21:19:57 +08:00
void CCSprite : : setTextureRect ( const CCRect & rect )
2010-07-22 14:54:47 +08:00
{
2011-11-18 21:23:54 +08:00
CCRect rectInPixels = CC_RECT_POINTS_TO_PIXELS ( rect ) ;
setTextureRectInPixels ( rectInPixels , false , rectInPixels . size ) ;
2010-07-22 14:54:47 +08:00
}
2010-12-27 10:26:56 +08:00
2011-08-17 21:19:57 +08:00
void CCSprite : : setTextureRectInPixels ( const CCRect & rect , bool rotated , const CCSize & size )
2010-07-22 14:54:47 +08:00
{
2011-11-18 21:23:54 +08:00
m_obRectInPixels = rect ;
m_obRect = CC_RECT_PIXELS_TO_POINTS ( rect ) ;
m_bRectRotated = rotated ;
setContentSizeInPixels ( size ) ;
updateTextureCoords ( m_obRectInPixels ) ;
CCPoint relativeOffsetInPixels = m_obUnflippedOffsetPositionFromCenter ;
// issue #732
if ( m_bFlipX )
{
relativeOffsetInPixels . x = - relativeOffsetInPixels . x ;
}
if ( m_bFlipY )
{
relativeOffsetInPixels . y = - relativeOffsetInPixels . y ;
}
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 batch node
if ( m_bUsesBatchNode )
{
// update dirty_, don't update recursiveDirty_
m_bDirty = true ;
}
else
{
// self rendering
// Atlas: Vertex
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 ) ;
m_sQuad . br . vertices = vertex3 ( x2 , y1 , 0 ) ;
m_sQuad . tl . vertices = vertex3 ( x1 , y2 , 0 ) ;
m_sQuad . tr . vertices = vertex3 ( x2 , y2 , 0 ) ;
}
2010-07-22 14:54:47 +08:00
}
2010-12-27 10:26:56 +08:00
2011-08-17 21:19:57 +08:00
void CCSprite : : updateTextureCoords ( const CCRect & rect )
2010-07-22 14:54:47 +08:00
{
2011-11-18 21:23:54 +08:00
CCTexture2D * tex = m_bUsesBatchNode ? m_pobTextureAtlas - > getTexture ( ) : m_pobTexture ;
if ( ! tex )
{
return ;
}
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
float atlasWidth = ( float ) tex - > getPixelsWide ( ) ;
float atlasHeight = ( float ) tex - > getPixelsHigh ( ) ;
2010-12-27 10:26:56 +08:00
2011-11-18 21:23:54 +08:00
float left , right , top , bottom ;
2010-12-27 10:26:56 +08:00
2011-11-18 21:23:54 +08:00
if ( m_bRectRotated )
{
2010-12-27 10:26:56 +08:00
# if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
2011-11-18 21:23:54 +08:00
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 ) ;
2010-12-27 10:26:56 +08:00
# else
2011-11-18 21:23:54 +08:00
left = rect . origin . x / atlasWidth ;
right = left + ( rect . size . height / atlasWidth ) ;
top = rect . origin . y / atlasHeight ;
bottom = top + ( rect . size . width / atlasHeight ) ;
2010-12-27 10:26:56 +08:00
# endif // CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
if ( m_bFlipX )
{
CC_SWAP ( top , bottom , float ) ;
}
if ( m_bFlipY )
{
CC_SWAP ( left , right , float ) ;
}
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
{
2011-03-15 10:27:16 +08:00
# if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
2011-11-18 21:23:54 +08:00
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 ) ;
2011-03-15 10:27:16 +08:00
# else
2011-11-18 21:23:54 +08:00
left = rect . origin . x / atlasWidth ;
right = left + rect . size . width / atlasWidth ;
top = rect . origin . y / atlasHeight ;
bottom = top + rect . size . height / atlasHeight ;
2011-03-15 10:27:16 +08:00
# endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
2011-11-18 21:23:54 +08:00
if ( m_bFlipX )
{
CC_SWAP ( left , right , float ) ;
}
2011-03-15 10:27:16 +08:00
2011-11-18 21:23:54 +08:00
if ( m_bFlipY )
{
CC_SWAP ( top , bottom , float ) ;
}
2011-03-15 10:27:16 +08:00
2011-11-18 21:23:54 +08:00
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 ;
}
2010-07-22 14:54:47 +08:00
}
void CCSprite : : updateTransform ( void )
{
2011-11-18 21:23:54 +08:00
assert ( m_bUsesBatchNode ) ;
// optimization. Quick return if not dirty
if ( ! m_bDirty )
{
return ;
}
CCAffineTransform matrix ;
// Optimization: if it is not visible, then do nothing
if ( ! m_bIsVisible )
{
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 ;
}
// Optimization: If parent is batchnode, or parent is nil
// build Affine transform manually
if ( ! m_pParent | | m_pParent = = m_pobBatchNode )
{
float radians = - CC_DEGREES_TO_RADIANS ( m_fRotation ) ;
float c = cosf ( radians ) ;
float s = sinf ( radians ) ;
2010-07-22 14:54:47 +08:00
2011-03-07 17:11:57 +08:00
matrix = CCAffineTransformMake ( c * m_fScaleX , s * m_fScaleX ,
2011-11-18 21:23:54 +08:00
- s * m_fScaleY , c * m_fScaleY ,
m_tPositionInPixels . x , m_tPositionInPixels . y ) ;
if ( m_fSkewX | | m_fSkewY )
{
CCAffineTransform skewMatrix = CCAffineTransformMake ( 1.0f , tanf ( CC_DEGREES_TO_RADIANS ( m_fSkewY ) ) ,
tanf ( CC_DEGREES_TO_RADIANS ( m_fSkewX ) ) , 1.0f ,
0.0f , 0.0f ) ;
matrix = CCAffineTransformConcat ( skewMatrix , matrix ) ;
2011-07-01 16:11:31 +08:00
}
2011-11-18 21:23:54 +08:00
matrix = CCAffineTransformTranslate ( matrix , - m_tAnchorPointInPixels . x , - m_tAnchorPointInPixels . y ) ;
} else // parent_ != batchNode_
{
// else do affine transformation according to the HonorParentTransform
matrix = CCAffineTransformIdentity ;
ccHonorParentTransform prevHonor = CC_HONOR_PARENT_TRANSFORM_ALL ;
for ( CCNode * p = this ; p & & p ! = m_pobBatchNode ; p = p - > getParent ( ) )
{
// Might happen. Issue #1053
// how to implement, we can not use dynamic
// CCAssert( [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 ;
}
CCAffineTransform newMatrix = CCAffineTransformIdentity ;
// 2nd: Translate, Skew, Rotate, Scale
if ( prevHonor & CC_HONOR_PARENT_TRANSFORM_TRANSLATE )
{
newMatrix = CCAffineTransformTranslate ( newMatrix , tv . pos . x , tv . pos . y ) ;
2011-07-01 16:11:31 +08:00
}
2011-11-18 21:23:54 +08:00
if ( prevHonor & CC_HONOR_PARENT_TRANSFORM_ROTATE )
{
newMatrix = CCAffineTransformRotate ( newMatrix , - CC_DEGREES_TO_RADIANS ( tv . rotation ) ) ;
}
if ( prevHonor & CC_HONOR_PARENT_TRANSFORM_SKEW )
{
CCAffineTransform skew = CCAffineTransformMake ( 1.0f , tanf ( CC_DEGREES_TO_RADIANS ( tv . skew . y ) ) , tanf ( CC_DEGREES_TO_RADIANS ( tv . skew . x ) ) , 1.0f , 0.0f , 0.0f ) ;
// apply the skew to the transform
newMatrix = CCAffineTransformConcat ( skew , newMatrix ) ;
}
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
if ( prevHonor & CC_HONOR_PARENT_TRANSFORM_SCALE )
{
newMatrix = CCAffineTransformScale ( newMatrix , tv . scale . x , tv . scale . y ) ;
}
// 3rd: Translate anchor point
newMatrix = CCAffineTransformTranslate ( newMatrix , - tv . ap . x , - tv . ap . y ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
// 4th: Matrix multiplication
matrix = CCAffineTransformConcat ( matrix , newMatrix ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
prevHonor = ( ( CCSprite * ) p ) - > getHornorParentTransform ( ) ;
}
}
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
//
// calculate the Quad based on the Affine Matrix
//
CCSize size = m_obRectInPixels . size ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
float x1 = m_obOffsetPositionInPixels . x ;
float y1 = m_obOffsetPositionInPixels . y ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
float x2 = x1 + size . width ;
float y2 = y1 + size . height ;
2010-07-22 14:54:47 +08:00
float x = matrix . tx ;
2011-11-18 21:23:54 +08:00
float y = matrix . ty ;
float cr = matrix . a ;
float sr = matrix . b ;
float cr2 = matrix . d ;
float sr2 = - matrix . c ;
float ax = x1 * cr - y1 * sr2 + x ;
float ay = x1 * sr + y1 * cr2 + y ;
float bx = x2 * cr - y1 * sr2 + x ;
float by = x2 * sr + y1 * cr2 + y ;
float cx = x2 * cr - y2 * sr2 + x ;
float cy = x2 * sr + y2 * cr2 + y ;
float dx = x1 * cr - y2 * sr2 + x ;
float dy = x1 * sr + y2 * cr2 + y ;
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 ;
2010-07-22 14:54:47 +08:00
}
// 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
2010-12-27 10:26:56 +08:00
void CCSprite : : getTransformValues ( struct transformValues_ * tv )
2010-07-22 14:54:47 +08:00
{
2011-11-18 21:23:54 +08:00
tv - > pos = m_tPositionInPixels ;
tv - > scale . x = m_fScaleX ;
tv - > scale . y = m_fScaleY ;
tv - > rotation = m_fRotation ;
tv - > skew . x = m_fSkewX ;
2011-07-01 16:11:31 +08:00
tv - > skew . y = m_fSkewY ;
2011-11-18 21:23:54 +08:00
tv - > ap = m_tAnchorPointInPixels ;
tv - > visible = m_bIsVisible ;
2010-07-22 14:54:47 +08:00
}
// draw
void CCSprite : : draw ( void )
{
2011-11-18 21:23:54 +08:00
CCNode : : draw ( ) ;
2011-07-12 11:20:41 +08:00
2011-11-18 21:23:54 +08:00
assert ( ! m_bUsesBatchNode ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
// 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_sBlendFunc . src ! = CC_BLEND_SRC | | m_sBlendFunc . dst ! = CC_BLEND_DST ;
if ( newBlend )
{
glBlendFunc ( m_sBlendFunc . src , m_sBlendFunc . dst ) ;
}
2010-07-22 14:54:47 +08:00
# define kQuadSize sizeof(m_sQuad.bl)
2010-08-02 18:04:24 +08:00
if ( m_pobTexture )
{
glBindTexture ( GL_TEXTURE_2D , m_pobTexture - > getName ( ) ) ;
}
else
{
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
}
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
long offset = ( long ) & m_sQuad ;
// vertex
int diff = offsetof ( ccV3F_C4B_T2F , vertices ) ;
glVertexPointer ( 3 , GL_FLOAT , kQuadSize , ( void * ) ( offset + diff ) ) ;
// color
diff = offsetof ( ccV3F_C4B_T2F , colors ) ;
glColorPointer ( 4 , GL_UNSIGNED_BYTE , kQuadSize , ( void * ) ( offset + diff ) ) ;
// tex coords
diff = offsetof ( ccV3F_C4B_T2F , texCoords ) ;
glTexCoordPointer ( 2 , GL_FLOAT , kQuadSize , ( void * ) ( offset + diff ) ) ;
glDrawArrays ( GL_TRIANGLE_STRIP , 0 , 4 ) ;
if ( newBlend )
{
glBlendFunc ( CC_BLEND_SRC , CC_BLEND_DST ) ;
}
# if CC_SPRITE_DEBUG_DRAW == 1
// draw bounding box
CCSize s = m_tContentSize ;
CCPoint vertices [ 4 ] = {
ccp ( 0 , 0 ) , ccp ( s . width , 0 ) ,
ccp ( s . width , s . height ) , ccp ( 0 , s . height )
} ;
ccDrawPoly ( vertices , 4 , true ) ;
# elif CC_SPRITE_DEBUG_DRAW == 2
// draw texture box
const CCSize & s = m_obRect . size ;
const CCPoint & offsetPix = getOffsetPositionInPixels ( ) ;
CCPoint vertices [ 4 ] = {
ccp ( offsetPix . x , offsetPix . y ) , ccp ( offsetPix . x + s . width , offsetPix . y ) ,
ccp ( offsetPix . x + s . width , offsetPix . y + s . height ) , ccp ( offsetPix . x , offsetPix . y + s . height )
} ;
ccDrawPoly ( vertices , 4 , true ) ;
2010-07-22 14:54:47 +08:00
# endif // CC_SPRITE_DEBUG_DRAW
}
// CCNode overrides
2010-12-27 10:26:56 +08:00
void CCSprite : : addChild ( CCNode * pChild )
2010-07-22 14:54:47 +08:00
{
2011-11-18 21:23:54 +08:00
CCNode : : addChild ( pChild ) ;
2010-07-22 14:54:47 +08:00
}
2010-12-27 10:26:56 +08:00
void CCSprite : : addChild ( CCNode * pChild , int zOrder )
2010-07-22 14:54:47 +08:00
{
2011-11-18 21:23:54 +08:00
CCNode : : addChild ( pChild , zOrder ) ;
2010-07-22 14:54:47 +08:00
}
2010-12-27 10:26:56 +08:00
void CCSprite : : addChild ( CCNode * pChild , int zOrder , int tag )
2010-07-22 14:54:47 +08:00
{
2011-11-18 21:23:54 +08:00
assert ( pChild ! = NULL ) ;
CCNode : : addChild ( pChild , zOrder , tag ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
if ( m_bUsesBatchNode )
{
assert ( ( ( CCSprite * ) pChild ) - > getTexture ( ) - > getName ( ) = = m_pobTextureAtlas - > getTexture ( ) - > getName ( ) ) ;
unsigned int index = m_pobBatchNode - > atlasIndexForChild ( ( CCSprite * ) ( pChild ) , zOrder ) ;
m_pobBatchNode - > insertChild ( ( CCSprite * ) ( pChild ) , index ) ;
}
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
m_bHasChildren = true ;
2010-07-22 14:54:47 +08:00
}
2010-08-02 10:58:00 +08:00
void CCSprite : : reorderChild ( CCNode * pChild , int zOrder )
2010-07-22 14:54:47 +08:00
{
assert ( pChild ! = NULL ) ;
2011-11-18 21:23:54 +08:00
assert ( m_pChildren - > containsObject ( pChild ) ) ;
if ( zOrder = = pChild - > getZOrder ( ) )
{
return ;
}
if ( m_bUsesBatchNode )
{
// XXX: Instead of removing/adding, it is more efficient to reorder manually
pChild - > retain ( ) ;
removeChild ( pChild , false ) ;
addChild ( pChild , zOrder ) ;
pChild - > release ( ) ;
}
else
{
CCNode : : reorderChild ( pChild , zOrder ) ;
}
2010-07-22 14:54:47 +08:00
}
void CCSprite : : removeChild ( CCNode * pChild , bool bCleanup )
{
2011-11-18 21:23:54 +08:00
if ( m_bUsesBatchNode )
{
m_pobBatchNode - > removeSpriteFromAtlas ( ( CCSprite * ) ( pChild ) ) ;
}
CCNode : : removeChild ( pChild , bCleanup ) ;
2010-07-22 14:54:47 +08:00
}
void CCSprite : : removeAllChildrenWithCleanup ( bool bCleanup )
{
2011-11-18 21:23:54 +08:00
if ( m_bUsesBatchNode )
{
2011-04-21 14:46:15 +08:00
CCObject * pObject = NULL ;
CCARRAY_FOREACH ( m_pChildren , pObject )
{
CCSprite * pChild = ( CCSprite * ) pObject ;
2011-11-18 21:23:54 +08:00
if ( pChild )
2011-04-21 14:46:15 +08:00
{
m_pobBatchNode - > removeSpriteFromAtlas ( pChild ) ;
}
}
2011-11-18 21:23:54 +08:00
}
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
CCNode : : removeAllChildrenWithCleanup ( bCleanup ) ;
m_bHasChildren = false ;
2010-07-22 14:54:47 +08:00
}
//
// CCNode property overloads
2010-12-27 10:26:56 +08:00
// used only when parent is CCSpriteBatchNode
2010-07-22 14:54:47 +08:00
//
void CCSprite : : setDirtyRecursively ( bool bValue )
{
2011-11-18 21:23:54 +08:00
m_bDirty = m_bRecursiveDirty = bValue ;
// recursively set dirty
if ( m_bHasChildren )
{
2011-04-21 14:46:15 +08:00
CCObject * pObject = NULL ;
CCARRAY_FOREACH ( m_pChildren , pObject )
{
CCSprite * pChild = ( CCSprite * ) pObject ;
2011-11-18 21:23:54 +08:00
if ( pChild )
2011-04-21 14:46:15 +08:00
{
pChild - > setDirtyRecursively ( true ) ;
}
}
2011-11-18 21:23:54 +08:00
}
2010-07-22 14:54:47 +08:00
}
// XXX HACK: optimization
# define SET_DIRTY_RECURSIVELY() { \
2010-12-27 10:26:56 +08:00
if ( m_bUsesBatchNode & & ! m_bRecursiveDirty ) { \
2010-07-22 14:54:47 +08:00
m_bDirty = m_bRecursiveDirty = true ; \
if ( m_bHasChildren ) \
setDirtyRecursively ( true ) ; \
} \
}
2011-08-17 21:19:57 +08:00
void CCSprite : : setPosition ( const CCPoint & pos )
2010-07-22 14:54:47 +08:00
{
2011-11-18 21:23:54 +08:00
CCNode : : setPosition ( pos ) ;
2010-12-27 10:26:56 +08:00
SET_DIRTY_RECURSIVELY ( ) ;
}
2011-11-18 21:23:54 +08:00
void CCSprite : : setPosition ( float x , float y )
{
setPosition ( ccp ( x , y ) ) ;
}
2011-08-17 21:19:57 +08:00
void CCSprite : : setPositionInPixels ( const CCPoint & pos )
2010-12-27 10:26:56 +08:00
{
2011-11-18 21:23:54 +08:00
CCNode : : setPositionInPixels ( pos ) ;
SET_DIRTY_RECURSIVELY ( ) ;
}
void CCSprite : : setPositionInPixels ( float x , float y )
{
setPositionInPixels ( ccp ( x , y ) ) ;
2010-07-22 14:54:47 +08:00
}
void CCSprite : : setRotation ( float fRotation )
{
2011-11-18 21:23:54 +08:00
CCNode : : setRotation ( fRotation ) ;
SET_DIRTY_RECURSIVELY ( ) ;
}
void CCSprite : : setSkewX ( float sx )
{
CCNode : : setSkewX ( sx ) ;
SET_DIRTY_RECURSIVELY ( ) ;
2010-07-22 14:54:47 +08:00
}
2011-11-18 21:23:54 +08:00
void CCSprite : : setSkewY ( float sy )
{
CCNode : : setSkewY ( sy ) ;
SET_DIRTY_RECURSIVELY ( ) ;
}
2011-07-01 16:11:31 +08:00
2010-07-22 14:54:47 +08:00
void CCSprite : : setScaleX ( float fScaleX )
{
2011-11-18 21:23:54 +08:00
CCNode : : setScaleX ( fScaleX ) ;
SET_DIRTY_RECURSIVELY ( ) ;
2010-07-22 14:54:47 +08:00
}
void CCSprite : : setScaleY ( float fScaleY )
{
2011-11-18 21:23:54 +08:00
CCNode : : setScaleY ( fScaleY ) ;
SET_DIRTY_RECURSIVELY ( ) ;
2010-07-22 14:54:47 +08:00
}
void CCSprite : : setScale ( float fScale )
{
2011-11-18 21:23:54 +08:00
CCNode : : setScale ( fScale ) ;
SET_DIRTY_RECURSIVELY ( ) ;
2010-07-22 14:54:47 +08:00
}
void CCSprite : : setVertexZ ( float fVertexZ )
{
2011-11-18 21:23:54 +08:00
CCNode : : setVertexZ ( fVertexZ ) ;
SET_DIRTY_RECURSIVELY ( ) ;
2010-07-22 14:54:47 +08:00
}
2011-08-17 21:19:57 +08:00
void CCSprite : : setAnchorPoint ( const CCPoint & anchor )
2010-07-22 14:54:47 +08:00
{
2011-11-18 21:23:54 +08:00
CCNode : : setAnchorPoint ( anchor ) ;
SET_DIRTY_RECURSIVELY ( ) ;
2010-07-22 14:54:47 +08:00
}
void CCSprite : : setIsRelativeAnchorPoint ( bool bRelative )
{
2011-11-18 21:23:54 +08:00
assert ( ! m_bUsesBatchNode ) ;
CCNode : : setIsRelativeAnchorPoint ( bRelative ) ;
2010-07-22 14:54:47 +08:00
}
void CCSprite : : setIsVisible ( bool bVisible )
{
2011-11-18 21:23:54 +08:00
CCNode : : setIsVisible ( bVisible ) ;
SET_DIRTY_RECURSIVELY ( ) ;
2010-07-22 14:54:47 +08:00
}
void CCSprite : : setFlipX ( bool bFlipX )
{
2011-11-18 21:23:54 +08:00
if ( m_bFlipX ! = bFlipX )
{
m_bFlipX = bFlipX ;
setTextureRectInPixels ( m_obRectInPixels , m_bRectRotated , m_tContentSizeInPixels ) ;
}
2010-07-22 14:54:47 +08:00
}
bool CCSprite : : isFlipX ( void )
{
2011-11-18 21:23:54 +08:00
return m_bFlipX ;
2010-07-22 14:54:47 +08:00
}
void CCSprite : : setFlipY ( bool bFlipY )
{
2011-11-18 21:23:54 +08:00
if ( m_bFlipY ! = bFlipY )
{
m_bFlipY = bFlipY ;
setTextureRectInPixels ( m_obRectInPixels , m_bRectRotated , m_tContentSizeInPixels ) ;
}
2010-07-22 14:54:47 +08:00
}
bool CCSprite : : isFlipY ( void )
{
2011-11-18 21:23:54 +08:00
return m_bFlipY ;
2010-07-22 14:54:47 +08:00
}
//
// RGBA protocol
//
void CCSprite : : updateColor ( void )
{
2011-11-18 21:23:54 +08:00
ccColor4B color4 = { m_sColor . r , m_sColor . g , m_sColor . b , m_nOpacity } ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
m_sQuad . bl . colors = color4 ;
m_sQuad . br . colors = color4 ;
m_sQuad . tl . colors = color4 ;
m_sQuad . tr . colors = color4 ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
// renders using Sprite Manager
if ( m_bUsesBatchNode )
{
if ( m_uAtlasIndex ! = CCSpriteIndexNotInitialized )
{
m_pobTextureAtlas - > updateQuad ( & m_sQuad , m_uAtlasIndex ) ;
}
else
{
// no need to set it recursively
// update dirty_, don't update recursiveDirty_
m_bDirty = true ;
}
}
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
// self render
// do nothing
2010-07-22 14:54:47 +08:00
}
GLubyte CCSprite : : getOpacity ( void )
{
2011-11-18 21:23:54 +08:00
return m_nOpacity ;
2010-07-22 14:54:47 +08:00
}
void CCSprite : : setOpacity ( GLubyte opacity )
{
2011-11-18 21:23:54 +08:00
m_nOpacity = opacity ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
// special opacity for premultiplied textures
if ( m_bOpacityModifyRGB )
{
setColor ( m_sColorUnmodified ) ;
}
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
updateColor ( ) ;
2010-07-22 14:54:47 +08:00
}
2011-08-17 21:19:57 +08:00
const ccColor3B & CCSprite : : getColor ( void )
2010-07-22 14:54:47 +08:00
{
2011-11-18 21:23:54 +08:00
if ( m_bOpacityModifyRGB )
{
return m_sColorUnmodified ;
}
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
return m_sColor ;
2010-07-22 14:54:47 +08:00
}
2011-08-17 21:19:57 +08:00
void CCSprite : : setColor ( const ccColor3B & color3 )
2010-07-22 14:54:47 +08:00
{
m_sColor = m_sColorUnmodified = color3 ;
2011-11-18 21:23:54 +08:00
if ( m_bOpacityModifyRGB )
{
m_sColor . r = color3 . r * m_nOpacity / 255 ;
m_sColor . g = color3 . g * m_nOpacity / 255 ;
m_sColor . b = color3 . b * m_nOpacity / 255 ;
}
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
updateColor ( ) ;
2010-07-22 14:54:47 +08:00
}
void CCSprite : : setIsOpacityModifyRGB ( bool bValue )
{
2011-11-18 21:23:54 +08:00
ccColor3B oldColor = m_sColor ;
m_bOpacityModifyRGB = bValue ;
m_sColor = oldColor ;
2010-07-22 14:54:47 +08:00
}
bool CCSprite : : getIsOpacityModifyRGB ( void )
{
2011-11-18 21:23:54 +08:00
return m_bOpacityModifyRGB ;
2010-07-22 14:54:47 +08:00
}
2010-12-27 10:26:56 +08:00
// Frames
2010-07-22 14:54:47 +08:00
void CCSprite : : setDisplayFrame ( CCSpriteFrame * pNewFrame )
{
2011-11-18 21:23:54 +08:00
m_obUnflippedOffsetPositionFromCenter = pNewFrame - > getOffsetInPixels ( ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
CCTexture2D * pNewTexture = pNewFrame - > getTexture ( ) ;
// update texture before updating texture rect
2011-03-11 17:41:19 +08:00
if ( pNewTexture ! = m_pobTexture )
2011-03-11 17:00:10 +08:00
{
2010-07-22 14:54:47 +08:00
setTexture ( pNewTexture ) ;
2011-03-11 17:00:10 +08:00
}
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
// update rect
m_bRectRotated = pNewFrame - > isRotated ( ) ;
setTextureRectInPixels ( pNewFrame - > getRectInPixels ( ) , pNewFrame - > isRotated ( ) , pNewFrame - > getOriginalSizeInPixels ( ) ) ;
2010-07-22 14:54:47 +08:00
}
2010-12-27 10:26:56 +08:00
void CCSprite : : setDisplayFrameWithAnimationName ( const char * animationName , int frameIndex )
{
2011-11-18 21:23:54 +08:00
assert ( animationName ) ;
2010-12-27 10:26:56 +08:00
2011-11-18 21:23:54 +08:00
CCAnimation * a = CCAnimationCache : : sharedAnimationCache ( ) - > animationByName ( animationName ) ;
2010-12-27 10:26:56 +08:00
2011-11-18 21:23:54 +08:00
assert ( a ) ;
2010-12-27 10:26:56 +08:00
2011-11-18 21:23:54 +08:00
CCSpriteFrame * frame = a - > getFrames ( ) - > getObjectAtIndex ( frameIndex ) ;
2010-12-27 10:26:56 +08:00
2011-11-18 21:23:54 +08:00
assert ( frame ) ;
2010-12-27 10:26:56 +08:00
2011-11-18 21:23:54 +08:00
setDisplayFrame ( frame ) ;
2010-12-27 10:26:56 +08:00
}
2010-07-22 14:54:47 +08:00
bool CCSprite : : isFrameDisplayed ( CCSpriteFrame * pFrame )
{
2011-11-18 21:23:54 +08:00
CCRect r = pFrame - > getRect ( ) ;
2010-12-27 10:26:56 +08:00
2011-11-18 21:23:54 +08:00
return ( CCRect : : CCRectEqualToRect ( r , m_obRect ) & &
pFrame - > getTexture ( ) - > getName ( ) = = m_pobTexture - > getName ( ) ) ;
2010-07-22 14:54:47 +08:00
}
CCSpriteFrame * CCSprite : : displayedFrame ( void )
{
2011-11-18 21:23:54 +08:00
return CCSpriteFrame : : frameWithTexture ( m_pobTexture ,
2011-07-01 16:11:31 +08:00
m_obRectInPixels ,
m_bRectRotated ,
m_obUnflippedOffsetPositionFromCenter ,
m_tContentSizeInPixels ) ;
2010-07-22 14:54:47 +08:00
}
// Texture protocol
void CCSprite : : updateBlendFunc ( void )
{
2011-11-18 21:23:54 +08:00
// CCSprite: updateBlendFunc doesn't work when the sprite is rendered using a CCSpriteSheet
assert ( ! m_bUsesBatchNode ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
// it's possible to have an untextured sprite
if ( ! m_pobTexture | | ! m_pobTexture - > getHasPremultipliedAlpha ( ) )
{
m_sBlendFunc . src = GL_SRC_ALPHA ;
m_sBlendFunc . dst = GL_ONE_MINUS_SRC_ALPHA ;
setIsOpacityModifyRGB ( false ) ;
}
else
{
m_sBlendFunc . src = CC_BLEND_SRC ;
m_sBlendFunc . dst = CC_BLEND_DST ;
setIsOpacityModifyRGB ( true ) ;
}
2010-07-22 14:54:47 +08:00
}
void CCSprite : : setTexture ( CCTexture2D * texture )
{
2011-11-18 21:23:54 +08:00
// CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteSheet
assert ( ! m_bUsesBatchNode ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
// we can not use RTTI, so we do not known the type of object
// accept texture==nil as argument
/*assert((! texture) || dynamic_cast<CCTexture2D*>(texture));*/
2010-07-30 18:17:13 +08:00
2011-11-18 21:23:54 +08:00
CC_SAFE_RELEASE ( m_pobTexture ) ;
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
m_pobTexture = texture ;
if ( texture )
{
texture - > retain ( ) ;
}
2010-07-22 14:54:47 +08:00
2011-11-18 21:23:54 +08:00
updateBlendFunc ( ) ;
2010-07-28 15:16:00 +08:00
}
CCTexture2D * CCSprite : : getTexture ( void )
{
2011-11-18 21:23:54 +08:00
return m_pobTexture ;
2010-07-28 15:16:00 +08:00
}
2011-11-18 21:23:54 +08:00
} //namespace cocos2d