mirror of https://github.com/axmolengine/axmol.git
Merge branch 'upto-0.99.5' of https://github.com/yangws/cocos2d-x into yangws-upto-0.99.5
This commit is contained in:
commit
4e35a660dc
|
@ -23,50 +23,54 @@ THE SOFTWARE.
|
|||
****************************************************************************/
|
||||
#ifndef __CCMOTION_STREAK_H__
|
||||
#define __CCMOTION_STREAK_H__
|
||||
|
||||
#include "CCNode.h"
|
||||
#include "CCProtocols.h"
|
||||
|
||||
namespace cocos2d {
|
||||
class CCRibbon;
|
||||
/**
|
||||
* @brief CCMotionStreak manages a Ribbon based on it's motion in absolute space.
|
||||
* You construct it with a fadeTime, minimum segment size, texture path, texture
|
||||
* length and color. The fadeTime controls how long it takes each vertex in
|
||||
* the streak to fade out, the minimum segment size it how many pixels the
|
||||
* streak will move before adding a new ribbon segement, and the texture
|
||||
* length is the how many pixels the texture is stretched across. The texture
|
||||
* is vertically aligned along the streak segemnts.
|
||||
*
|
||||
* Limitations:
|
||||
* CCMotionStreak, by default, will use the GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA blending function.
|
||||
* This blending function might not be the correct one for certain textures.
|
||||
* But you can change it by using:
|
||||
* [obj setBlendFunc: (ccBlendfunc) {new_src_blend_func, new_dst_blend_func}];
|
||||
*
|
||||
* @since v0.8.1
|
||||
*/
|
||||
class CCX_DLL CCMotionStreak : public CCNode, public CCTextureProtocol
|
||||
{
|
||||
/** Ribbon used by MotionStreak (weak reference) */
|
||||
CCX_PROPERTY_READONLY(CCRibbon*, m_pRibbon, Ribbon)
|
||||
//CCTextureProtocol methods
|
||||
CCX_PROPERTY(CCTexture2D*, m_pTexture, Texture)
|
||||
CCX_PROPERTY(ccBlendFunc, m_tBlendFunc, BlendFunc)
|
||||
public:
|
||||
CCMotionStreak(){}
|
||||
virtual ~CCMotionStreak(){}
|
||||
/** creates the a MotionStreak. The image will be loaded using the TextureMgr. */
|
||||
static CCMotionStreak * streakWithFade(float fade, float seg, const char *imagePath, float width, float length, ccColor4B color);
|
||||
|
||||
class CCRibbon;
|
||||
/**
|
||||
* @brief CCMotionStreak manages a Ribbon based on it's motion in absolute space.
|
||||
* You construct it with a fadeTime, minimum segment size, texture path, texture
|
||||
* length and color. The fadeTime controls how long it takes each vertex in
|
||||
* the streak to fade out, the minimum segment size it how many pixels the
|
||||
* streak will move before adding a new ribbon segement, and the texture
|
||||
* length is the how many pixels the texture is stretched across. The texture
|
||||
* is vertically aligned along the streak segemnts.
|
||||
*
|
||||
* Limitations:
|
||||
* CCMotionStreak, by default, will use the GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA blending function.
|
||||
* This blending function might not be the correct one for certain textures.
|
||||
* But you can change it by using:
|
||||
* [obj setBlendFunc: (ccBlendfunc) {new_src_blend_func, new_dst_blend_func}];
|
||||
*
|
||||
* @since v0.8.1
|
||||
*/
|
||||
class CCX_DLL CCMotionStreak : public CCNode, public CCTextureProtocol
|
||||
{
|
||||
/** Ribbon used by MotionStreak (weak reference) */
|
||||
CCX_PROPERTY_READONLY(CCRibbon*, m_pRibbon, Ribbon)
|
||||
//CCTextureProtocol methods
|
||||
CCX_PROPERTY(CCTexture2D*, m_pTexture, Texture)
|
||||
CCX_PROPERTY(ccBlendFunc, m_tBlendFunc, BlendFunc)
|
||||
public:
|
||||
CCMotionStreak(){}
|
||||
virtual ~CCMotionStreak(){}
|
||||
/** creates the a MotionStreak. The image will be loaded using the TextureMgr. */
|
||||
static CCMotionStreak * streakWithFade(float fade, float seg, const char *imagePath, float width, float length, ccColor4B color);
|
||||
|
||||
/** initializes a MotionStreak. The file will be loaded using the TextureMgr. */
|
||||
bool initWithFade(float fade, float seg, const char *imagePath, float width, float length, ccColor4B color);
|
||||
/** initializes a MotionStreak. The file will be loaded using the TextureMgr. */
|
||||
bool initWithFade(float fade, float seg, const char *imagePath, float width, float length, ccColor4B color);
|
||||
|
||||
/** polling function */
|
||||
void update(ccTime delta);
|
||||
protected:
|
||||
float m_fSegThreshold;
|
||||
float m_fWidth;
|
||||
CGPoint m_tLastLocation;
|
||||
};
|
||||
/** polling function */
|
||||
void update(ccTime delta);
|
||||
protected:
|
||||
float m_fSegThreshold;
|
||||
float m_fWidth;
|
||||
CGPoint m_tLastLocation;
|
||||
};
|
||||
|
||||
} // namespace cocos2d
|
||||
|
||||
#endif //__CCMOTION_STREAK_H__
|
||||
#endif //__CCMOTION_STREAK_H__
|
||||
|
|
|
@ -80,7 +80,7 @@ public:
|
|||
static CCProgressTimer* progressWithTexture(CCTexture2D *pTexture);
|
||||
|
||||
protected:
|
||||
CGPoint vertexFromTexCoord(CGPoint texCoord);
|
||||
ccVertex2F vertexFromTexCoord(CGPoint texCoord);
|
||||
void updateProgress(void);
|
||||
void updateBar(void);
|
||||
void updateRadial(void);
|
||||
|
|
|
@ -24,50 +24,81 @@ THE SOFTWARE.
|
|||
#ifndef __CCRENDER_TEXTURE_H__
|
||||
#define __CCRENDER_TEXTURE_H__
|
||||
|
||||
#include "NSData.h"
|
||||
#include "CCNode.h"
|
||||
#include "CCSprite.h"
|
||||
|
||||
namespace cocos2d {
|
||||
enum tImageFormat
|
||||
{
|
||||
kImageFormatJPG = 0,
|
||||
kImageFormatPNG = 1
|
||||
};
|
||||
/**
|
||||
@brief RenderTexture is a generic rendering target. To render things into it,
|
||||
simply construct a render target, call begin on it, call visit on any cocos
|
||||
scenes or objects to render them, and call end. For convienience, render texture
|
||||
adds a sprite as it's display child with the results, so you can simply add
|
||||
the render texture to your scene and treat it like any other CocosNode.
|
||||
There are also functions for saving the render texture to disk in PNG or JPG format.
|
||||
|
||||
enum eImageFormat
|
||||
{
|
||||
kCCImageFormatJPG = 0,
|
||||
kCCImageFormatPNG = 1,
|
||||
kCCImageFormatRawData = 2
|
||||
};
|
||||
/**
|
||||
@brief CCRenderTexture is a generic rendering target. To render things into it,
|
||||
simply construct a render target, call begin on it, call visit on any cocos
|
||||
scenes or objects to render them, and call end. For convienience, render texture
|
||||
adds a sprite as it's display child with the results, so you can simply add
|
||||
the render texture to your scene and treat it like any other CocosNode.
|
||||
There are also functions for saving the render texture to disk in PNG or JPG format.
|
||||
|
||||
@since v0.8.1
|
||||
*/
|
||||
class CCX_DLL CCRenderTexture : public CCNode
|
||||
{
|
||||
/** sprite being used */
|
||||
CCX_PROPERTY(CCSprite*, m_pSprite, Sprite)
|
||||
public:
|
||||
CCRenderTexture(){}
|
||||
virtual ~CCRenderTexture();
|
||||
/** creates a RenderTexture object with width and height */
|
||||
static CCRenderTexture *renderTextureWithWidthAndHeight(int width, int height);
|
||||
/** initializes a RenderTexture object with width and height */
|
||||
bool initWithWidthAndHeight(int width, int height);
|
||||
void begin();
|
||||
void end();
|
||||
/** get buffer as UIImage */
|
||||
UIImage *getUIImageFromBuffer();
|
||||
/** saves the texture into a file */
|
||||
bool saveBuffer(const char *name);
|
||||
/** saves the texture into a file. The format can be JPG or PNG */
|
||||
bool saveBuffer(const char *name, int format);
|
||||
/** clears the texture with a color */
|
||||
void clear(float r, float g, float b, float a);
|
||||
protected:
|
||||
GLuint m_uFBO;
|
||||
GLint m_nOldFBO;
|
||||
CCTexture2D* m_pTexture;
|
||||
};
|
||||
@since v0.8.1
|
||||
*/
|
||||
class CCX_DLL CCRenderTexture : public CCNode
|
||||
{
|
||||
/** The CCSprite being used.
|
||||
The sprite, by default, will use the following blending function: GL_ONE, GL_ONE_MINUS_SRC_ALPHA.
|
||||
The blending function can be changed in runtime by calling:
|
||||
- [[renderTexture sprite] setBlendFunc:(ccBlendFunc){GL_ONE, GL_ONE_MINUS_SRC_ALPHA}];
|
||||
*/
|
||||
CCX_PROPERTY(CCSprite*, m_pSprite, Sprite)
|
||||
public:
|
||||
CCRenderTexture(){}
|
||||
virtual ~CCRenderTexture();
|
||||
/** creates a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid */
|
||||
static CCRenderTexture * renderTextureWithWidthAndHeight(int w, int h, CCTexture2DPixelFormat eFormat);
|
||||
|
||||
/** creates a RenderTexture object with width and height in Points, pixel format is RGBA8888 */
|
||||
static CCRenderTexture * renderTextureWithWidthAndHeight(int w, int h);
|
||||
|
||||
/** initializes a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid */
|
||||
bool initWithWidthAndHeight(int w, int h, CCTexture2DPixelFormat eFormat);
|
||||
|
||||
/** starts grabbing */
|
||||
void begin();
|
||||
|
||||
/** starts rendering to the texture while clearing the texture first.
|
||||
This is more efficient then calling -clear first and then -begin */
|
||||
void beginWithClear(float r, float g, float b, float a);
|
||||
|
||||
/** ends grabbing */
|
||||
void end();
|
||||
|
||||
/** clears the texture with a color */
|
||||
void clear(float r, float g, float b, float a);
|
||||
|
||||
/** saves the texture into a file */
|
||||
bool saveBuffer(const char *name);
|
||||
/** saves the texture into a file. The format can be JPG or PNG */
|
||||
bool saveBuffer(const char *name, int format);
|
||||
|
||||
/* get buffer as UIImage, can only save a render buffer which has a RGBA8888 pixel format */
|
||||
NSData *getUIImageAsDataFromBuffer(int format);
|
||||
protected:
|
||||
GLuint m_uFBO;
|
||||
GLint m_nOldFBO;
|
||||
CCTexture2D* m_pTexture;
|
||||
|
||||
GLenum m_ePixelFormat;
|
||||
GLfloat m_aClearColor[4];
|
||||
|
||||
private:
|
||||
void saveGLstate();
|
||||
void restoreGLstate();
|
||||
};
|
||||
|
||||
} // namespace cocos2d
|
||||
|
||||
#endif //__CCRENDER_TEXTURE_H__
|
|
@ -23,89 +23,96 @@ THE SOFTWARE.
|
|||
****************************************************************************/
|
||||
#ifndef __CCRIBBON_H__
|
||||
#define __CCRIBBON_H__
|
||||
|
||||
/*#include <GLES/egl.h>*/
|
||||
#include "CCNode.h"
|
||||
#include "CCProtocols.h"
|
||||
|
||||
namespace cocos2d {
|
||||
class CCRibbonSegment;
|
||||
/**
|
||||
* @brief A CCRibbon is a dynamically generated list of polygons drawn as a single or series
|
||||
* of triangle strips. The primary use of CCRibbon is as the drawing class of Motion Streak,
|
||||
* but it is quite useful on it's own. When manually drawing a ribbon, you can call addPointAt
|
||||
* and pass in the parameters for the next location in the ribbon. The system will automatically
|
||||
* generate new polygons, texture them accourding to your texture width, etc, etc.
|
||||
*
|
||||
* CCRibbon data is stored in a CCRibbonSegment class. This class statically allocates enough verticies and
|
||||
* texture coordinates for 50 locations (100 verts or 48 triangles). The ribbon class will allocate
|
||||
* new segments when they are needed, and reuse old ones if available. The idea is to avoid constantly
|
||||
* allocating new memory and prefer a more static method. However, since there is no way to determine
|
||||
* the maximum size of some ribbons (motion streaks), a truely static allocation is not possible.
|
||||
*
|
||||
* @since v0.8.1
|
||||
*/
|
||||
class CCX_DLL CCRibbon : public CCNode, public CCTextureProtocol
|
||||
{
|
||||
/** Texture used by the ribbon. Conforms to CCTextureProtocol protocol */
|
||||
CCX_PROPERTY(CCTexture2D*, m_pTexture, Texture)
|
||||
/** Texture lenghts in pixels */
|
||||
CCX_PROPERTY(float, m_fTextureLength, TextureLength)
|
||||
/** GL blendind function */
|
||||
CCX_PROPERTY(ccBlendFunc, m_tBlendFunc, BlendFunc)
|
||||
/** color used by the Ribbon (RGBA) */
|
||||
CCX_PROPERTY(ccColor4B, m_tColor, Color)
|
||||
public:
|
||||
CCRibbon(){}
|
||||
virtual ~CCRibbon();
|
||||
/** creates the ribbon */
|
||||
static CCRibbon * ribbonWithWidth(float w, const char *path, float length, ccColor4B color, float fade);
|
||||
/** init the ribbon */
|
||||
bool initWithWidth(float w, const char *path, float length, ccColor4B color, float fade);
|
||||
/** add a point to the ribbon */
|
||||
void addPointAt(CGPoint location, float width);
|
||||
/** polling function */
|
||||
void update(ccTime delta);
|
||||
/** determine side of line */
|
||||
float sideOfLine(CGPoint p, CGPoint l1, CGPoint l2);
|
||||
// super method
|
||||
virtual void draw();
|
||||
private:
|
||||
/** rotates a point around 0, 0 */
|
||||
CGPoint rotatePoint(CGPoint vec, float rotation);
|
||||
protected:
|
||||
NSMutableArray<CCRibbonSegment*> *m_pSegments;
|
||||
NSMutableArray<CCRibbonSegment*> *m_pDeletedSegments;
|
||||
|
||||
class CCRibbonSegment;
|
||||
/**
|
||||
* @brief A CCRibbon is a dynamically generated list of polygons drawn as a single or series
|
||||
* of triangle strips. The primary use of CCRibbon is as the drawing class of Motion Streak,
|
||||
* but it is quite useful on it's own. When manually drawing a ribbon, you can call addPointAt
|
||||
* and pass in the parameters for the next location in the ribbon. The system will automatically
|
||||
* generate new polygons, texture them accourding to your texture width, etc, etc.
|
||||
*
|
||||
* CCRibbon data is stored in a CCRibbonSegment class. This class statically allocates enough verticies and
|
||||
* texture coordinates for 50 locations (100 verts or 48 triangles). The ribbon class will allocate
|
||||
* new segments when they are needed, and reuse old ones if available. The idea is to avoid constantly
|
||||
* allocating new memory and prefer a more static method. However, since there is no way to determine
|
||||
* the maximum size of some ribbons (motion streaks), a truely static allocation is not possible.
|
||||
*
|
||||
* @since v0.8.1
|
||||
*/
|
||||
class CCX_DLL CCRibbon : public CCNode, public CCTextureProtocol
|
||||
{
|
||||
/** Texture used by the ribbon. Conforms to CCTextureProtocol protocol */
|
||||
CCX_PROPERTY(CCTexture2D*, m_pTexture, Texture)
|
||||
/** Texture lengths in pixels */
|
||||
CCX_PROPERTY(float, m_fTextureLength, TextureLength)
|
||||
/** GL blendind function */
|
||||
CCX_PROPERTY(ccBlendFunc, m_tBlendFunc, BlendFunc)
|
||||
/** color used by the Ribbon (RGBA) */
|
||||
CCX_PROPERTY(ccColor4B, m_tColor, Color)
|
||||
|
||||
public:
|
||||
CCRibbon() : m_pTexture(0), m_pSegments(0), m_pDeletedSegments(0){}
|
||||
virtual ~CCRibbon();
|
||||
|
||||
/** creates the ribbon */
|
||||
static CCRibbon * ribbonWithWidth(float w, const char *path, float length, ccColor4B color, float fade);
|
||||
/** init the ribbon */
|
||||
bool initWithWidth(float w, const char *path, float length, ccColor4B color, float fade);
|
||||
/** add a point to the ribbon */
|
||||
void addPointAt(CGPoint location, float width);
|
||||
/** polling function */
|
||||
void update(ccTime delta);
|
||||
/** determine side of line */
|
||||
float sideOfLine(CGPoint p, CGPoint l1, CGPoint l2);
|
||||
// super method
|
||||
virtual void draw();
|
||||
private:
|
||||
/** rotates a point around 0, 0 */
|
||||
CGPoint rotatePoint(CGPoint vec, float rotation);
|
||||
protected:
|
||||
NSMutableArray<CCRibbonSegment*> *m_pSegments;
|
||||
NSMutableArray<CCRibbonSegment*> *m_pDeletedSegments;
|
||||
|
||||
CGPoint m_tLastPoint1;
|
||||
CGPoint m_tLastPoint2;
|
||||
CGPoint m_tLastLocation;
|
||||
int m_nVertCount_;
|
||||
float m_fTexVPos;
|
||||
float m_fCurTime;
|
||||
float m_fFadeTime;
|
||||
float m_fDelta;
|
||||
float m_fLastWidth;
|
||||
float m_fLastSign;
|
||||
bool m_bPastFirstPoint;
|
||||
};
|
||||
CGPoint m_tLastPoint1;
|
||||
CGPoint m_tLastPoint2;
|
||||
CGPoint m_tLastLocation;
|
||||
// int m_nVertCount_;
|
||||
float m_fTexVPos;
|
||||
float m_fCurTime;
|
||||
float m_fFadeTime;
|
||||
float m_fDelta;
|
||||
float m_fLastWidth;
|
||||
float m_fLastSign;
|
||||
bool m_bPastFirstPoint;
|
||||
};
|
||||
|
||||
/** @brief object to hold ribbon segment data */
|
||||
class CCX_DLL CCRibbonSegment : public NSObject
|
||||
{
|
||||
public:
|
||||
GLfloat m_pVerts[50*6];
|
||||
GLfloat m_pCoords[50*4];
|
||||
GLubyte m_pColors[50*8];
|
||||
float m_pCreationTime[50];
|
||||
bool m_bFinished;
|
||||
unsigned int m_uEnd;
|
||||
unsigned int m_uBegin;
|
||||
public:
|
||||
CCRibbonSegment(){}
|
||||
virtual ~CCRibbonSegment();
|
||||
char * description();
|
||||
bool init();
|
||||
void reset();
|
||||
void draw(float curTime, float fadeTime, ccColor4B color);
|
||||
};
|
||||
/** @brief object to hold ribbon segment data */
|
||||
class CCX_DLL CCRibbonSegment : public NSObject
|
||||
{
|
||||
public:
|
||||
GLfloat m_pVerts[50*6];
|
||||
GLfloat m_pCoords[50*4];
|
||||
GLubyte m_pColors[50*8];
|
||||
float m_pCreationTime[50];
|
||||
bool m_bFinished;
|
||||
unsigned int m_uEnd;
|
||||
unsigned int m_uBegin;
|
||||
public:
|
||||
CCRibbonSegment(){}
|
||||
virtual ~CCRibbonSegment();
|
||||
char * description();
|
||||
bool init();
|
||||
void reset();
|
||||
void draw(float curTime, float fadeTime, ccColor4B color);
|
||||
};
|
||||
|
||||
} // namespace cocos2d
|
||||
|
||||
#endif //__CCRIBBON_H__
|
|
@ -25,74 +25,81 @@ THE SOFTWARE.
|
|||
#include "CGPointExtension.h"
|
||||
#include "CCRibbon.h"
|
||||
namespace cocos2d {
|
||||
/*
|
||||
* Motion Streak manages a Ribbon based on it's motion in absolute space.
|
||||
* You construct it with a fadeTime, minimum segment size, texture path, texture
|
||||
* length and color. The fadeTime controls how long it takes each vertex in
|
||||
* the streak to fade out, the minimum segment size it how many pixels the
|
||||
* streak will move before adding a new ribbon segement, and the texture
|
||||
* length is the how many pixels the texture is stretched across. The texture
|
||||
* is vertically aligned along the streak segemnts.
|
||||
*/
|
||||
//implementation CCMotionStreak
|
||||
|
||||
CCMotionStreak * CCMotionStreak::streakWithFade(float fade, float seg, const char *imagePath, float width, float length, ccColor4B color)
|
||||
{
|
||||
CCMotionStreak *pRet = new CCMotionStreak();
|
||||
if(pRet && pRet->initWithFade(fade, seg, imagePath, width, length, color))
|
||||
{
|
||||
pRet->autorelease();
|
||||
return pRet;
|
||||
}
|
||||
CCX_SAFE_DELETE(pRet)
|
||||
return NULL;
|
||||
}
|
||||
bool CCMotionStreak::initWithFade(float fade, float seg, const char *imagePath, float width, float length, ccColor4B color)
|
||||
{
|
||||
m_fSegThreshold = seg;
|
||||
m_fWidth = width;
|
||||
m_tLastLocation = CGPointZero;
|
||||
m_pRibbon = CCRibbon::ribbonWithWidth(m_fWidth, imagePath, length, color, fade);
|
||||
this->addChild(m_pRibbon);
|
||||
|
||||
// update ribbon position
|
||||
this->schedule(schedule_selector(CCMotionStreak::update), 0);
|
||||
return true;
|
||||
}
|
||||
void CCMotionStreak::update(ccTime delta)
|
||||
{
|
||||
CGPoint location = this->convertToWorldSpace(CGPointZero);
|
||||
m_pRibbon->setPosition(ccp(-1*location.x, -1*location.y));
|
||||
float len = sqrtf(powf(m_tLastLocation.x - location.x, 2) + powf(m_tLastLocation.y - location.y, 2));
|
||||
if (len > m_fSegThreshold)
|
||||
{
|
||||
m_pRibbon->addPointAt(location, m_fWidth);
|
||||
m_tLastLocation = location;
|
||||
}
|
||||
m_pRibbon->update(delta);
|
||||
}
|
||||
|
||||
//MotionStreak - CocosNodeTexture protocol
|
||||
|
||||
void CCMotionStreak::setTexture(CCTexture2D* texture)
|
||||
{
|
||||
m_pRibbon->setTexture(texture);
|
||||
}
|
||||
CCTexture2D * CCMotionStreak::getTexture()
|
||||
{
|
||||
return m_pRibbon->getTexture();
|
||||
}
|
||||
ccBlendFunc CCMotionStreak::getBlendFunc()
|
||||
{
|
||||
return m_pRibbon->getBlendFunc();
|
||||
}
|
||||
void CCMotionStreak::setBlendFunc(ccBlendFunc blendFunc)
|
||||
{
|
||||
m_pRibbon->setBlendFunc(blendFunc);
|
||||
}
|
||||
CCRibbon * CCMotionStreak::getRibbon()
|
||||
{
|
||||
return m_pRibbon;
|
||||
}
|
||||
|
||||
}// namespace cocos2d
|
||||
/*
|
||||
* Motion Streak manages a Ribbon based on it's motion in absolute space.
|
||||
* You construct it with a fadeTime, minimum segment size, texture path, texture
|
||||
* length and color. The fadeTime controls how long it takes each vertex in
|
||||
* the streak to fade out, the minimum segment size it how many pixels the
|
||||
* streak will move before adding a new ribbon segement, and the texture
|
||||
* length is the how many pixels the texture is stretched across. The texture
|
||||
* is vertically aligned along the streak segemnts.
|
||||
*/
|
||||
//implementation CCMotionStreak
|
||||
|
||||
CCMotionStreak * CCMotionStreak::streakWithFade(float fade, float seg, const char *imagePath, float width, float length, ccColor4B color)
|
||||
{
|
||||
CCMotionStreak *pRet = new CCMotionStreak();
|
||||
if(pRet && pRet->initWithFade(fade, seg, imagePath, width, length, color))
|
||||
{
|
||||
pRet->autorelease();
|
||||
return pRet;
|
||||
}
|
||||
CCX_SAFE_DELETE(pRet)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool CCMotionStreak::initWithFade(float fade, float seg, const char *imagePath, float width, float length, ccColor4B color)
|
||||
{
|
||||
m_fSegThreshold = seg;
|
||||
m_fWidth = width;
|
||||
m_tLastLocation = CGPointZero;
|
||||
m_pRibbon = CCRibbon::ribbonWithWidth(m_fWidth, imagePath, length, color, fade);
|
||||
this->addChild(m_pRibbon);
|
||||
|
||||
// update ribbon position
|
||||
this->schedule(schedule_selector(CCMotionStreak::update), 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCMotionStreak::update(ccTime delta)
|
||||
{
|
||||
CGPoint location = this->convertToWorldSpace(CGPointZero);
|
||||
m_pRibbon->setPosition(ccp(-1*location.x, -1*location.y));
|
||||
float len = ccpLength(ccpSub(m_tLastLocation, location));
|
||||
if (len > m_fSegThreshold)
|
||||
{
|
||||
m_pRibbon->addPointAt(location, m_fWidth);
|
||||
m_tLastLocation = location;
|
||||
}
|
||||
m_pRibbon->update(delta);
|
||||
}
|
||||
|
||||
//MotionStreak - CocosNodeTexture protocol
|
||||
|
||||
void CCMotionStreak::setTexture(CCTexture2D* texture)
|
||||
{
|
||||
m_pRibbon->setTexture(texture);
|
||||
}
|
||||
|
||||
CCTexture2D * CCMotionStreak::getTexture()
|
||||
{
|
||||
return m_pRibbon->getTexture();
|
||||
}
|
||||
|
||||
ccBlendFunc CCMotionStreak::getBlendFunc()
|
||||
{
|
||||
return m_pRibbon->getBlendFunc();
|
||||
}
|
||||
|
||||
void CCMotionStreak::setBlendFunc(ccBlendFunc blendFunc)
|
||||
{
|
||||
m_pRibbon->setBlendFunc(blendFunc);
|
||||
}
|
||||
|
||||
CCRibbon * CCMotionStreak::getRibbon()
|
||||
{
|
||||
return m_pRibbon;
|
||||
}
|
||||
|
||||
}// namespace cocos2d
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -26,145 +26,312 @@ THE SOFTWARE.
|
|||
#include "CCDirector.h"
|
||||
#include "platform/platform.h"
|
||||
#include "CCXUIImage.h"
|
||||
#include "Support/ccUtls.h"
|
||||
|
||||
#include <GLES/glext.h>
|
||||
|
||||
namespace cocos2d {
|
||||
|
||||
// implementation CCRenderTexture
|
||||
CCSprite * CCRenderTexture::getSprite()
|
||||
{
|
||||
return m_pSprite;
|
||||
}
|
||||
void CCRenderTexture::setSprite(CCSprite* var)
|
||||
{
|
||||
m_pSprite = var;
|
||||
}
|
||||
// implementation CCRenderTexture
|
||||
CCRenderTexture::CCRenderTexture()
|
||||
: m_pSprite(NULL)
|
||||
, m_uFBO(0)
|
||||
, m_nOldFBO(0)
|
||||
, m_pTexture(0)
|
||||
, m_ePixelFormat(kCCPixelFormatRGBA8888)
|
||||
{
|
||||
memset(m_aClearColor, 0, sizeof(m_aClearColor));
|
||||
}
|
||||
|
||||
CCRenderTexture * CCRenderTexture::renderTextureWithWidthAndHeight(int width, int height)
|
||||
{
|
||||
CCRenderTexture *pRet = new CCRenderTexture();
|
||||
CCRenderTexture::~CCRenderTexture()
|
||||
{
|
||||
removeAllChildrenWithCleanup(true);
|
||||
ccglDeleteFramebuffers(1, &m_uFBO);
|
||||
}
|
||||
|
||||
if(pRet && pRet->initWithWidthAndHeight(width,height))
|
||||
{
|
||||
pRet->autorelease();
|
||||
return pRet;
|
||||
}
|
||||
CCX_SAFE_DELETE(pRet)
|
||||
return NULL;
|
||||
}
|
||||
bool CCRenderTexture::initWithWidthAndHeight(int width, int height)
|
||||
{
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &m_nOldFBO);
|
||||
CCTexture2DPixelFormat format = kCCTexture2DPixelFormat_RGBA8888;
|
||||
// textures must be power of two squared
|
||||
int pow = 8;
|
||||
while (pow < width || pow < height)
|
||||
{
|
||||
pow*=2;
|
||||
}
|
||||
void *data = malloc((int)(pow * pow * 4));
|
||||
memset(data, 0, (int)(pow * pow * 4));
|
||||
m_pTexture = new CCTexture2D();
|
||||
m_pTexture->initWithData(data, format, pow, pow, CGSizeMake((float)width, (float)height));
|
||||
free( data );
|
||||
// generate FBO
|
||||
glGenFramebuffersOES(1, &m_uFBO);
|
||||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_uFBO);
|
||||
// associate texture with FBO
|
||||
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, m_pTexture->getName(), 0);
|
||||
CCSprite * CCRenderTexture::getSprite()
|
||||
{
|
||||
return m_pSprite;
|
||||
}
|
||||
void CCRenderTexture::setSprite(CCSprite* var)
|
||||
{
|
||||
m_pSprite = var;
|
||||
}
|
||||
|
||||
// check if it worked (probably worth doing :) )
|
||||
GLuint status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE_OES)
|
||||
{
|
||||
NSAssert(0, "Render Texture : Could not attach texture to framebuffer")
|
||||
CCX_SAFE_DELETE(m_pTexture);
|
||||
return false;
|
||||
}
|
||||
m_pSprite = CCSprite::spriteWithTexture(m_pTexture);
|
||||
m_pTexture->release();
|
||||
m_pSprite->setScaleY(-1);
|
||||
this->addChild(m_pSprite);
|
||||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_nOldFBO);
|
||||
return true;
|
||||
}
|
||||
CCRenderTexture::~CCRenderTexture()
|
||||
{
|
||||
glDeleteFramebuffersOES(1, &m_uFBO);
|
||||
}
|
||||
void CCRenderTexture::begin()
|
||||
{
|
||||
CC_DISABLE_DEFAULT_GL_STATES();
|
||||
// Save the current matrix
|
||||
glPushMatrix();
|
||||
CCRenderTexture * CCRenderTexture::renderTextureWithWidthAndHeight(int w, int h, CCTexture2DPixelFormat eFormat)
|
||||
{
|
||||
CCRenderTexture *pRet = new CCRenderTexture();
|
||||
|
||||
CGSize textureSize = m_pTexture->getContentSize();
|
||||
if(pRet && pRet->initWithWidthAndHeight(w, h, eFormat))
|
||||
{
|
||||
pRet->autorelease();
|
||||
return pRet;
|
||||
}
|
||||
CCX_SAFE_DELETE(pRet);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Calculate the adjustment ratios based on the old and new projections
|
||||
CGSize size = CCDirector::sharedDirector()->getDisplaySize();
|
||||
float widthRatio = size.width / textureSize.width;
|
||||
float heightRatio = size.height / textureSize.height;
|
||||
CCRenderTexture * CCRenderTexture::renderTextureWithWidthAndHeight(int w, int h)
|
||||
{
|
||||
CCRenderTexture *pRet = new CCRenderTexture();
|
||||
|
||||
// Adjust the orthographic propjection and viewport
|
||||
glOrthof((float)-1.0 / widthRatio, (float)1.0 / widthRatio, (float)-1.0 / heightRatio, (float)1.0 / heightRatio, -1,1);
|
||||
glViewport(0, 0, (GLsizei)textureSize.width, (GLsizei)textureSize.height);
|
||||
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &m_nOldFBO);
|
||||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_uFBO);//Will direct drawing to the frame buffer created above
|
||||
|
||||
CC_ENABLE_DEFAULT_GL_STATES();
|
||||
}
|
||||
void CCRenderTexture::end()
|
||||
if(pRet && pRet->initWithWidthAndHeight(w, h, kCCTexture2DPixelFormat_RGBA8888))
|
||||
{
|
||||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_nOldFBO);
|
||||
// Restore the original matrix and viewport
|
||||
glPopMatrix();
|
||||
CGSize size = CCDirector::sharedDirector()->getDisplaySize();
|
||||
glViewport(0, 0, (GLsizei)size.width, (GLsizei)size.height);
|
||||
pRet->autorelease();
|
||||
return pRet;
|
||||
}
|
||||
CCX_SAFE_DELETE(pRet)
|
||||
return NULL;
|
||||
}
|
||||
bool CCRenderTexture::initWithWidthAndHeight(int w, int h, CCTexture2DPixelFormat eFormat)
|
||||
{
|
||||
bool bRet = false;
|
||||
do
|
||||
{
|
||||
w *= CC_CONTENT_SCALE_FACTOR();
|
||||
h *= CC_CONTENT_SCALE_FACTOR();
|
||||
|
||||
glColorMask(true, true, true, true);
|
||||
}
|
||||
void CCRenderTexture::clear(float r, float g, float b, float a)
|
||||
{
|
||||
this->begin();
|
||||
glClearColor(r, g, b, a);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glColorMask(true, true, true, false);
|
||||
this->end();
|
||||
}
|
||||
bool CCRenderTexture::saveBuffer(const char *name)
|
||||
{
|
||||
return this->saveBuffer(name, kImageFormatJPG);
|
||||
}
|
||||
bool CCRenderTexture::saveBuffer(const char *name, int format)
|
||||
{
|
||||
bool bRet = false;
|
||||
UIImage *myImage = this->getUIImageFromBuffer();
|
||||
if (myImage)
|
||||
{
|
||||
bRet = myImage->save(name, format);
|
||||
delete myImage;
|
||||
}
|
||||
return bRet;
|
||||
}
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &m_nOldFBO);
|
||||
|
||||
/* get buffer as UIImage */
|
||||
UIImage * CCRenderTexture::getUIImageFromBuffer()
|
||||
{
|
||||
int tx = (int)m_pTexture->getContentSize().width;
|
||||
int ty = (int)m_pTexture->getContentSize().height;
|
||||
|
||||
char * pBuffer = new char[tx * ty * 4];
|
||||
|
||||
this->begin();
|
||||
glReadPixels(0,0,tx,ty,GL_RGBA,GL_UNSIGNED_BYTE, pBuffer);
|
||||
this->end();
|
||||
|
||||
UIImage *pRet = new UIImage();
|
||||
pRet->initWithBuffer(tx, ty, (unsigned char*)pBuffer);
|
||||
delete[] pBuffer;
|
||||
return pRet;
|
||||
}
|
||||
// textures must be power of two squared
|
||||
unsigned int powW = ccNextPOT(w);
|
||||
unsigned int powH = ccNextPOT(h);
|
||||
|
||||
void *data = malloc((int)(powW * powH * 4));
|
||||
CCX_BREAK_IF(! data);
|
||||
|
||||
memset(data, 0, (int)(powW * powH * 4));
|
||||
m_ePixelFormat = eFormat;
|
||||
|
||||
m_pTexture = new CCTexture2D();
|
||||
CCX_BREAK_IF(! m_pTexture);
|
||||
|
||||
m_pTexture->initWithData(data, m_ePixelFormat, powW, powH, CGSizeMake((float)w, (float)h));
|
||||
free( data );
|
||||
|
||||
// generate FBO
|
||||
ccglGenFramebuffers(1, &m_uFBO);
|
||||
ccglBindFramebuffer(CC_GL_FRAMEBUFFER, m_uFBO);
|
||||
|
||||
// associate texture with FBO
|
||||
ccglFramebufferTexture2D(CC_GL_FRAMEBUFFER, CC_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTexture->getName(), 0);
|
||||
|
||||
// check if it worked (probably worth doing :) )
|
||||
GLuint status = ccglCheckFramebufferStatus(CC_GL_FRAMEBUFFER);
|
||||
if (status != CC_GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
NSAssert(0, "Render Texture : Could not attach texture to framebuffer");
|
||||
CCX_SAFE_DELETE(m_pTexture);
|
||||
break;
|
||||
}
|
||||
|
||||
m_pTexture->setAliasTexParameters();
|
||||
|
||||
m_pSprite = CCSprite::spriteWithTexture(m_pTexture);
|
||||
|
||||
m_pTexture->release();
|
||||
m_pSprite->setScaleY(-1);
|
||||
this->addChild(m_pSprite);
|
||||
|
||||
ccBlendFunc tBlendFunc = {GL_ONE, GL_ONE_MINUS_SRC_ALPHA };
|
||||
m_pSprite->setBlendFunc(tBlendFunc);
|
||||
|
||||
ccglBindFramebuffer(CC_GL_FRAMEBUFFER, m_nOldFBO);
|
||||
bRet = true;
|
||||
} while (0);
|
||||
return bRet;
|
||||
|
||||
}
|
||||
|
||||
void CCRenderTexture::begin()
|
||||
{
|
||||
saveGLstate();
|
||||
|
||||
CC_DISABLE_DEFAULT_GL_STATES();
|
||||
// Save the current matrix
|
||||
glPushMatrix();
|
||||
|
||||
CGSize texSize = m_pTexture->getContentSizeInPixels();
|
||||
|
||||
// Calculate the adjustment ratios based on the old and new projections
|
||||
CGSize size = CCDirector::sharedDirector()->getDisplaySizeInPixels();
|
||||
float widthRatio = size.width / texSize.width;
|
||||
float heightRatio = size.height / texSize.height;
|
||||
|
||||
// Adjust the orthographic propjection and viewport
|
||||
ccglOrtho((float)-1.0 / widthRatio, (float)1.0 / widthRatio, (float)-1.0 / heightRatio, (float)1.0 / heightRatio, -1,1);
|
||||
glViewport(0, 0, (GLsizei)texSize.width, (GLsizei)texSize.height);
|
||||
|
||||
glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &m_nOldFBO);
|
||||
ccglBindFramebuffer(CC_GL_FRAMEBUFFER, m_uFBO);//Will direct drawing to the frame buffer created above
|
||||
|
||||
CC_ENABLE_DEFAULT_GL_STATES();
|
||||
}
|
||||
|
||||
void CCRenderTexture::beginWithClear(float r, float g, float b, float a)
|
||||
{
|
||||
this->saveGLstate();
|
||||
|
||||
CC_DISABLE_DEFAULT_GL_STATES();
|
||||
// Save the current matrix
|
||||
glPushMatrix();
|
||||
|
||||
CGSize texSize = m_pTexture->getContentSizeInPixels();
|
||||
|
||||
// Calculate the adjustment ratios based on the old and new projections
|
||||
CGSize size = CCDirector::sharedDirector()->getDisplaySizeInPixels();
|
||||
float widthRatio = size.width / texSize.width;
|
||||
float heightRatio = size.height / texSize.height;
|
||||
|
||||
// Adjust the orthographic propjection and viewport
|
||||
ccglOrtho((float)-1.0 / widthRatio, (float)1.0 / widthRatio, (float)-1.0 / heightRatio, (float)1.0 / heightRatio, -1,1);
|
||||
glViewport(0, 0, texSize.width, texSize.height);
|
||||
|
||||
glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &m_oldFBO);
|
||||
ccglBindFramebuffer(CC_GL_FRAMEBUFFER, m_fbo);//Will direct drawing to the frame buffer created above
|
||||
|
||||
glClearColor(r, g, b, a);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
CC_ENABLE_DEFAULT_GL_STATES();
|
||||
}
|
||||
|
||||
void CCRenderTexture::end()
|
||||
{
|
||||
ccglBindFramebuffer(CC_GL_FRAMEBUFFER, m_nOldFBO);
|
||||
// Restore the original matrix and viewport
|
||||
glPopMatrix();
|
||||
CGSize size = CCDirector::sharedDirector()->getDisplaySizeInPixels();
|
||||
glViewport(0, 0, (GLsizei)size.width, (GLsizei)size.height);
|
||||
this->restoreGLstate();
|
||||
}
|
||||
|
||||
void CCRenderTexture::clear(float r, float g, float b, float a)
|
||||
{
|
||||
this->begin();
|
||||
glClearColor(r, g, b, a);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
this->end();
|
||||
}
|
||||
|
||||
void CCRenderTexture::saveGLstate()
|
||||
{
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, m_aClearColor);
|
||||
}
|
||||
|
||||
void CCRenderTexture::restoreGLstate()
|
||||
{
|
||||
glClearColor(m_aClearColor[0], m_aClearColor[1], m_aClearColor[2], m_aClearColor[3]);
|
||||
}
|
||||
|
||||
|
||||
bool CCRenderTexture::saveBuffer(const char *name)
|
||||
{
|
||||
return this->saveBuffer(name, kCCImageFormatJPG);
|
||||
}
|
||||
bool CCRenderTexture::saveBuffer(const char *fileName, int format)
|
||||
{
|
||||
bool bRet = false;
|
||||
//@ todo CCRenderTexture::saveBuffer
|
||||
// UIImage *myImage = this->getUIImageFromBuffer(format);
|
||||
// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
// NSString *documentsDirectory = [paths objectAtIndex:0];
|
||||
// NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:fileName];
|
||||
|
||||
// NSData * data = this->getUIImageAsDataFromBuffer(format);
|
||||
// if (data)
|
||||
// {
|
||||
// bRet = data->writeToFile(path, true);
|
||||
// delete data;
|
||||
// bRet = true;
|
||||
// }
|
||||
return bRet;
|
||||
}
|
||||
|
||||
NSData * CCRenderTexture::getUIImageAsDataFromBuffer(int format)
|
||||
{
|
||||
NSData * pData = NULL;
|
||||
//@ todo CCRenderTexture::getUIImageAsDataFromBuffer
|
||||
|
||||
// #include "Availability.h"
|
||||
// #include "UIKit.h"
|
||||
|
||||
// GLubyte * pBuffer = NULL;
|
||||
// GLubyte * pPixels = NULL;
|
||||
// do
|
||||
// {
|
||||
// CCX_BREAK_IF(! m_pTexture);
|
||||
//
|
||||
// NSAssert(m_ePixelFormat == kCCTexture2DPixelFormat_RGBA8888, "only RGBA8888 can be saved as image");
|
||||
//
|
||||
// CGSize s = m_pTexture->getContentSizeInPixels();
|
||||
// int tx = s.width;
|
||||
// int ty = s.height;
|
||||
//
|
||||
// int bitsPerComponent = 8;
|
||||
// int bitsPerPixel = 32;
|
||||
//
|
||||
// int bytesPerRow = (bitsPerPixel / 8) * tx;
|
||||
// int myDataLength = bytesPerRow * ty;
|
||||
//
|
||||
// CCX_BREAK_IF(! (pBuffer = new GLubyte[tx * ty * 4]));
|
||||
// CCX_BREAK_IF(! (pPixels = new GLubyte[tx * ty * 4]));
|
||||
//
|
||||
// this->begin();
|
||||
// glReadPixels(0,0,tx,ty,GL_RGBA,GL_UNSIGNED_BYTE, pBuffer);
|
||||
// this->end();
|
||||
//
|
||||
// int x,y;
|
||||
//
|
||||
// for(y = 0; y <ty; y++) {
|
||||
// for(x = 0; x <tx * 4; x++) {
|
||||
// pPixels[((ty - 1 - y) * tx * 4 + x)] = pBuffer[(y * 4 * tx + x)];
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (format == kCCImageFormatRawData)
|
||||
// {
|
||||
// pData = NSData::dataWithBytesNoCopy(pPixels, myDataLength);
|
||||
// break;
|
||||
// }
|
||||
|
||||
//@ todo impliment save to jpg or png
|
||||
/*
|
||||
CGImageCreate(size_t width, size_t height,
|
||||
size_t bitsPerComponent, size_t bitsPerPixel, size_t bytesPerRow,
|
||||
CGColorSpaceRef space, CGBitmapInfo bitmapInfo, CGDataProviderRef provider,
|
||||
const CGFloat decode[], bool shouldInterpolate,
|
||||
CGColorRenderingIntent intent)
|
||||
*/
|
||||
// make data provider with data.
|
||||
// CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault;
|
||||
// CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, myDataLength, NULL);
|
||||
// CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
|
||||
// CGImageRef iref = CGImageCreate(tx, ty,
|
||||
// bitsPerComponent, bitsPerPixel, bytesPerRow,
|
||||
// colorSpaceRef, bitmapInfo, provider,
|
||||
// NULL, false,
|
||||
// kCGRenderingIntentDefault);
|
||||
//
|
||||
// UIImage* image = [[UIImage alloc] initWithCGImage:iref];
|
||||
//
|
||||
// CGImageRelease(iref);
|
||||
// CGColorSpaceRelease(colorSpaceRef);
|
||||
// CGDataProviderRelease(provider);
|
||||
//
|
||||
//
|
||||
//
|
||||
// if (format == kCCImageFormatPNG)
|
||||
// data = UIImagePNGRepresentation(image);
|
||||
// else
|
||||
// data = UIImageJPEGRepresentation(image, 1.0f);
|
||||
//
|
||||
// [image release];
|
||||
// } while (0);
|
||||
//
|
||||
// CCX_SAFE_DELETE_ARRAY(pBuffer);
|
||||
// CCX_SAFE_DELETE_ARRAY(pPixels);
|
||||
return pData;
|
||||
}
|
||||
|
||||
} // namespace cocos2d
|
||||
|
|
|
@ -21,380 +21,399 @@ LIABILITY, WHETHER IN AN ACTION 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 "CCRibbon.h"
|
||||
#include "CCTextureCache.h"
|
||||
#include "CGPointExtension.h"
|
||||
|
||||
namespace cocos2d {
|
||||
|
||||
/*
|
||||
* A ribbon is a dynamically generated list of polygons drawn as a single or series
|
||||
* of triangle strips. The primary use of Ribbon is as the drawing class of Motion Streak,
|
||||
* but it is quite useful on it's own. When manually drawing a ribbon, you can call addPointAt
|
||||
* and pass in the parameters for the next location in the ribbon. The system will automatically
|
||||
* generate new polygons, texture them accourding to your texture width, etc, etc.
|
||||
*
|
||||
* Ribbon data is stored in a RibbonSegment class. This class statically allocates enough verticies and
|
||||
* texture coordinates for 50 locations (100 verts or 48 triangles). The ribbon class will allocate
|
||||
* new segments when they are needed, and reuse old ones if available. The idea is to avoid constantly
|
||||
* allocating new memory and prefer a more static method. However, since there is no way to determine
|
||||
* the maximum size of some ribbons (motion streaks), a truely static allocation is not possible.
|
||||
*
|
||||
/*
|
||||
* A ribbon is a dynamically generated list of polygons drawn as a single or series
|
||||
* of triangle strips. The primary use of Ribbon is as the drawing class of Motion Streak,
|
||||
* but it is quite useful on it's own. When manually drawing a ribbon, you can call addPointAt
|
||||
* and pass in the parameters for the next location in the ribbon. The system will automatically
|
||||
* generate new polygons, texture them accourding to your texture width, etc, etc.
|
||||
*
|
||||
* Ribbon data is stored in a RibbonSegment class. This class statically allocates enough verticies and
|
||||
* texture coordinates for 50 locations (100 verts or 48 triangles). The ribbon class will allocate
|
||||
* new segments when they are needed, and reuse old ones if available. The idea is to avoid constantly
|
||||
* allocating new memory and prefer a more static method. However, since there is no way to determine
|
||||
* the maximum size of some ribbons (motion streaks), a truely static allocation is not possible.
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// Ribbon
|
||||
//
|
||||
CCRibbon * CCRibbon::ribbonWithWidth(float w, const char *path, float length, ccColor4B color, float fade)
|
||||
{
|
||||
CCRibbon *pRet = new CCRibbon();
|
||||
if(pRet && pRet->initWithWidth(w, path, length, color, fade))
|
||||
{
|
||||
pRet->autorelease();
|
||||
return pRet;
|
||||
}
|
||||
CCX_SAFE_DELETE(pRet)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool CCRibbon::initWithWidth(float w, const char *path, float length, ccColor4B color, float fade)
|
||||
{
|
||||
m_pSegments = new NSMutableArray<CCRibbonSegment*>();
|
||||
m_pDeletedSegments = new NSMutableArray<CCRibbonSegment*>();
|
||||
|
||||
/* 1 initial segment */
|
||||
CCRibbonSegment* seg = new CCRibbonSegment();
|
||||
seg->init();
|
||||
m_pSegments->addObject(seg);
|
||||
seg->release();
|
||||
|
||||
m_fTextureLength = length;
|
||||
|
||||
m_tColor = color;
|
||||
m_fFadeTime = fade;
|
||||
m_tLastLocation = CGPointZero;
|
||||
m_fLastWidth = w/2;
|
||||
m_fTexVPos = 0.0f;
|
||||
|
||||
m_fCurTime = 0;
|
||||
m_bPastFirstPoint = false;
|
||||
|
||||
/* XXX:
|
||||
Ribbon, by default uses this blend function, which might not be correct
|
||||
if you are using premultiplied alpha images,
|
||||
but 99% you might want to use this blending function regarding of the texture
|
||||
*/
|
||||
m_tBlendFunc.src = GL_SRC_ALPHA;
|
||||
m_tBlendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
|
||||
|
||||
//
|
||||
// Ribbon
|
||||
//
|
||||
CCRibbon * CCRibbon::ribbonWithWidth(float w, const char *path, float length, ccColor4B color, float fade)
|
||||
m_pTexture = CCTextureCache::sharedTextureCache()->addImage(path);
|
||||
CCX_SAFE_RETAIN(m_pTexture);
|
||||
|
||||
/* default texture parameter */
|
||||
ccTexParams params = { GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT };
|
||||
m_pTexture->setTexParameters(¶ms);
|
||||
return true;
|
||||
}
|
||||
|
||||
CCRibbon::~CCRibbon()
|
||||
{
|
||||
CCX_SAFE_RELEASE(m_pSegments);
|
||||
CCX_SAFE_RELEASE(m_pDeletedSegments);
|
||||
CCX_SAFE_RELEASE(m_pTexture);
|
||||
}
|
||||
|
||||
CGPoint CCRibbon::rotatePoint(CGPoint vec, float rotation)
|
||||
{
|
||||
float xtemp = (vec.x * cosf(rotation)) - (vec.y * sinf(rotation));
|
||||
vec.y = (vec.x * sinf(rotation)) + (vec.y * cosf(rotation));
|
||||
vec.x = xtemp;
|
||||
return vec;
|
||||
}
|
||||
|
||||
void CCRibbon::update(ccTime delta)
|
||||
{
|
||||
m_fCurTime += delta;
|
||||
m_fDelta = delta;
|
||||
}
|
||||
|
||||
float CCRibbon::sideOfLine(CGPoint p, CGPoint l1, CGPoint l2)
|
||||
{
|
||||
CGPoint vp = ccpPerp(ccpSub(l1, l2));
|
||||
CGPoint vx = ccpSub(p, l1);
|
||||
return ccpDot(vx, vp);
|
||||
}
|
||||
|
||||
// adds a new segment to the ribbon
|
||||
void CCRibbon::addPointAt(CGPoint location, float width)
|
||||
{
|
||||
location.x *= CC_CONTENT_SCALE_FACTOR();
|
||||
location.y *= CC_CONTENT_SCALE_FACTOR();
|
||||
|
||||
width = width * 0.5f;
|
||||
// if this is the first point added, cache it and return
|
||||
if (!m_bPastFirstPoint)
|
||||
{
|
||||
CCRibbon *pRet = new CCRibbon();
|
||||
if(pRet && pRet->initWithWidth(w, path, length, color, fade))
|
||||
{
|
||||
pRet->autorelease();
|
||||
return pRet;
|
||||
}
|
||||
CCX_SAFE_DELETE(pRet)
|
||||
return NULL;
|
||||
}
|
||||
bool CCRibbon::initWithWidth(float w, const char *path, float length, ccColor4B color, float fade)
|
||||
{
|
||||
m_pSegments = new NSMutableArray<CCRibbonSegment*>();
|
||||
m_pDeletedSegments = new NSMutableArray<CCRibbonSegment*>();
|
||||
|
||||
/* 1 initial segment */
|
||||
CCRibbonSegment* seg = new CCRibbonSegment();
|
||||
seg->init();
|
||||
m_pSegments->addObject(seg);
|
||||
seg->release();
|
||||
|
||||
m_fTextureLength = length;
|
||||
|
||||
m_tColor = color;
|
||||
m_fFadeTime = fade;
|
||||
m_tLastLocation = CGPointZero;
|
||||
m_fLastWidth = w/2;
|
||||
m_fTexVPos = 0.0f;
|
||||
|
||||
m_fCurTime = 0;
|
||||
m_bPastFirstPoint = false;
|
||||
|
||||
/* XXX:
|
||||
Ribbon, by default uses this blend function, which might not be correct
|
||||
if you are using premultiplied alpha images,
|
||||
but 99% you might want to use this blending function regarding of the texture
|
||||
*/
|
||||
m_tBlendFunc.src = GL_SRC_ALPHA;
|
||||
m_tBlendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
|
||||
|
||||
m_pTexture = CCTextureCache::sharedTextureCache()->addImage(path);
|
||||
CCX_SAFE_RETAIN(m_pTexture);
|
||||
|
||||
/* default texture parameter */
|
||||
ccTexParams params = { GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT };
|
||||
m_pTexture->setTexParameters(¶ms);
|
||||
return true;
|
||||
}
|
||||
CCRibbon::~CCRibbon()
|
||||
{
|
||||
m_pSegments->release();
|
||||
m_pDeletedSegments->release();
|
||||
m_pTexture->release();
|
||||
}
|
||||
CGPoint CCRibbon::rotatePoint(CGPoint vec, float rotation)
|
||||
{
|
||||
float xtemp = (vec.x * cosf(rotation)) - (vec.y * sinf(rotation));
|
||||
vec.y = (vec.x * sinf(rotation)) + (vec.y * cosf(rotation));
|
||||
vec.x = xtemp;
|
||||
return vec;
|
||||
}
|
||||
void CCRibbon::update(ccTime delta)
|
||||
{
|
||||
m_fCurTime += delta;
|
||||
m_fDelta = delta;
|
||||
}
|
||||
float CCRibbon::sideOfLine(CGPoint p, CGPoint l1, CGPoint l2)
|
||||
{
|
||||
CGPoint vp = ccpPerp(ccpSub(l1, l2));
|
||||
CGPoint vx = ccpSub(p, l1);
|
||||
return ccpDot(vx, vp);
|
||||
}
|
||||
|
||||
// adds a new segment to the ribbon
|
||||
void CCRibbon::addPointAt(CGPoint location, float width)
|
||||
{
|
||||
width = width * 0.5f;
|
||||
// if this is the first point added, cache it and return
|
||||
if (!m_bPastFirstPoint)
|
||||
{
|
||||
m_fLastWidth = width;
|
||||
m_tLastLocation = location;
|
||||
m_bPastFirstPoint = true;
|
||||
return;
|
||||
}
|
||||
|
||||
CGPoint sub = ccpSub(m_tLastLocation, location);
|
||||
float r = ccpToAngle(sub) + (float)M_PI_2;
|
||||
CGPoint p1 = ccpAdd(this->rotatePoint(ccp(-width, 0), r), location);
|
||||
CGPoint p2 = ccpAdd(this->rotatePoint(ccp(+width, 0), r), location);
|
||||
float len = sqrtf(powf(m_tLastLocation.x - location.x, 2) + powf(m_tLastLocation.y - location.y, 2));
|
||||
float tend = m_fTexVPos + len/m_fTextureLength;
|
||||
CCRibbonSegment* seg;
|
||||
// grab last segment
|
||||
seg = m_pSegments->getLastObject();
|
||||
// lets kill old segments
|
||||
if (m_pSegments && m_pSegments->count()>0)
|
||||
{
|
||||
NSMutableArray<CCRibbonSegment*>::NSMutableArrayIterator it;
|
||||
for (it = m_pSegments->begin(); it != m_pSegments->end(); ++it)
|
||||
{
|
||||
if (*it != seg && (*it)->m_bFinished)
|
||||
{
|
||||
m_pDeletedSegments->addObject(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_pSegments->removeObjectsInArray(m_pDeletedSegments);
|
||||
// is the segment full?
|
||||
if (seg->m_uEnd >= 50)
|
||||
{
|
||||
m_pSegments->removeObjectsInArray(m_pDeletedSegments);
|
||||
}
|
||||
// grab last segment and append to it if it's not full
|
||||
seg = m_pSegments->getLastObject();
|
||||
// is the segment full?
|
||||
if (seg->m_uEnd >= 50)
|
||||
{
|
||||
CCRibbonSegment* newSeg;
|
||||
// grab it from the cache if we can
|
||||
if (m_pDeletedSegments->count() > 0)
|
||||
{
|
||||
newSeg = m_pDeletedSegments->getObjectAtIndex(0);
|
||||
newSeg->retain(); // will be released later
|
||||
m_pDeletedSegments->removeObject(newSeg);
|
||||
newSeg->reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
newSeg = new CCRibbonSegment(); // will be released later
|
||||
newSeg->init();
|
||||
}
|
||||
|
||||
newSeg->m_pCreationTime[0] = seg->m_pCreationTime[seg->m_uEnd- 1];
|
||||
int v = (seg->m_uEnd-1)*6;
|
||||
int c = (seg->m_uEnd-1)*4;
|
||||
newSeg->m_pVerts[0] = seg->m_pVerts[v];
|
||||
newSeg->m_pVerts[1] = seg->m_pVerts[v+1];
|
||||
newSeg->m_pVerts[2] = seg->m_pVerts[v+2];
|
||||
newSeg->m_pVerts[3] = seg->m_pVerts[v+3];
|
||||
newSeg->m_pVerts[4] = seg->m_pVerts[v+4];
|
||||
newSeg->m_pVerts[5] = seg->m_pVerts[v+5];
|
||||
|
||||
newSeg->m_pCoords[0] = seg->m_pCoords[c];
|
||||
newSeg->m_pCoords[1] = seg->m_pCoords[c+1];
|
||||
newSeg->m_pCoords[2] = seg->m_pCoords[c+2];
|
||||
newSeg->m_pCoords[3] = seg->m_pCoords[c+3];
|
||||
newSeg->m_uEnd++;
|
||||
seg = newSeg;
|
||||
m_pSegments->addObject(seg);
|
||||
newSeg->release();// it was retained before
|
||||
}
|
||||
if (seg->m_uEnd == 0)
|
||||
{
|
||||
// first edge has to get rotation from the first real polygon
|
||||
CGPoint lp1 = ccpAdd(this->rotatePoint(ccp(-m_fLastWidth, 0), r), m_tLastLocation);
|
||||
CGPoint lp2 = ccpAdd(this->rotatePoint(ccp(+m_fLastWidth, 0), r), m_tLastLocation);
|
||||
seg->m_pCreationTime[0] = m_fCurTime - m_fDelta;
|
||||
seg->m_pVerts[0] = lp1.x;
|
||||
seg->m_pVerts[1] = lp1.y;
|
||||
seg->m_pVerts[2] = 0.0f;
|
||||
seg->m_pVerts[3] = lp2.x;
|
||||
seg->m_pVerts[4] = lp2.y;
|
||||
seg->m_pVerts[5] = 0.0f;
|
||||
seg->m_pCoords[0] = 0.0f;
|
||||
seg->m_pCoords[1] = m_fTexVPos;
|
||||
seg->m_pCoords[2] = 1.0f;
|
||||
seg->m_pCoords[3] = m_fTexVPos;
|
||||
seg->m_uEnd++;
|
||||
}
|
||||
|
||||
int v = seg->m_uEnd*6;
|
||||
int c = seg->m_uEnd*4;
|
||||
// add new vertex
|
||||
seg->m_pCreationTime[seg->m_uEnd] = m_fCurTime;
|
||||
seg->m_pVerts[v] = p1.x;
|
||||
seg->m_pVerts[v+1] = p1.y;
|
||||
seg->m_pVerts[v+2] = 0.0f;
|
||||
seg->m_pVerts[v+3] = p2.x;
|
||||
seg->m_pVerts[v+4] = p2.y;
|
||||
seg->m_pVerts[v+5] = 0.0f;
|
||||
|
||||
|
||||
seg->m_pCoords[c] = 0.0f;
|
||||
seg->m_pCoords[c+1] = tend;
|
||||
seg->m_pCoords[c+2] = 1.0f;
|
||||
seg->m_pCoords[c+3] = tend;
|
||||
|
||||
m_fTexVPos = tend;
|
||||
m_tLastLocation = location;
|
||||
m_tLastPoint1 = p1;
|
||||
m_tLastPoint2 = p2;
|
||||
m_fLastWidth = width;
|
||||
seg->m_uEnd++;
|
||||
m_tLastLocation = location;
|
||||
m_bPastFirstPoint = true;
|
||||
return;
|
||||
}
|
||||
void CCRibbon::draw()
|
||||
|
||||
CGPoint sub = ccpSub(m_tLastLocation, location);
|
||||
float r = ccpToAngle(sub) + (float)M_PI_2;
|
||||
CGPoint p1 = ccpAdd(this->rotatePoint(ccp(-width, 0), r), location);
|
||||
CGPoint p2 = ccpAdd(this->rotatePoint(ccp(+width, 0), r), location);
|
||||
float len = sqrtf(powf(m_tLastLocation.x - location.x, 2) + powf(m_tLastLocation.y - location.y, 2));
|
||||
float tend = m_fTexVPos + len/m_fTextureLength;
|
||||
CCRibbonSegment* seg;
|
||||
// grab last segment
|
||||
seg = m_pSegments->getLastObject();
|
||||
// lets kill old segments
|
||||
if (m_pSegments && m_pSegments->count()>0)
|
||||
{
|
||||
if (m_pSegments->count() > 0)
|
||||
NSMutableArray<CCRibbonSegment*>::NSMutableArrayIterator it;
|
||||
for (it = m_pSegments->begin(); it != m_pSegments->end(); ++it)
|
||||
{
|
||||
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
|
||||
// Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY
|
||||
// Unneeded states: GL_COLOR_ARRAY
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_pTexture->getName());
|
||||
|
||||
bool newBlend = false;
|
||||
if( m_tBlendFunc.src != CC_BLEND_SRC || m_tBlendFunc.dst != CC_BLEND_DST )
|
||||
if (*it != seg && (*it)->m_bFinished)
|
||||
{
|
||||
newBlend = true;
|
||||
glBlendFunc( m_tBlendFunc.src, m_tBlendFunc.dst );
|
||||
m_pDeletedSegments->addObject(*it);
|
||||
}
|
||||
|
||||
if(m_pSegments && m_pSegments->count() > 0)
|
||||
{
|
||||
CCRibbonSegment* seg;
|
||||
NSMutableArray<CCRibbonSegment*>::NSMutableArrayIterator it;
|
||||
for( it = m_pSegments->begin(); it != m_pSegments->end(); it++)
|
||||
{
|
||||
seg = (CCRibbonSegment*)*it;
|
||||
seg->draw(m_fCurTime, m_fFadeTime, m_tColor);
|
||||
}
|
||||
}
|
||||
|
||||
if( newBlend )
|
||||
{
|
||||
glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
|
||||
}
|
||||
|
||||
// restore default GL state
|
||||
glEnableClientState( GL_COLOR_ARRAY );
|
||||
}
|
||||
}
|
||||
|
||||
// Ribbon - CocosNodeTexture protocol
|
||||
void CCRibbon::setTexture(CCTexture2D* var)
|
||||
|
||||
m_pSegments->removeObjectsInArray(m_pDeletedSegments);
|
||||
// is the segment full?
|
||||
if (seg->m_uEnd >= 50)
|
||||
{
|
||||
CCX_SAFE_RETAIN(var);
|
||||
CCX_SAFE_RELEASE(m_pTexture);
|
||||
m_pTexture = var;
|
||||
this->setContentSize(m_pTexture->getContentSize());
|
||||
/* XXX Don't update blending function in Ribbons */
|
||||
m_pSegments->removeObjectsInArray(m_pDeletedSegments);
|
||||
}
|
||||
CCTexture2D *CCRibbon::getTexture()
|
||||
// grab last segment and append to it if it's not full
|
||||
seg = m_pSegments->getLastObject();
|
||||
// is the segment full?
|
||||
if (seg->m_uEnd >= 50)
|
||||
{
|
||||
return m_pTexture;
|
||||
}
|
||||
void CCRibbon::setTextureLength(float var)
|
||||
{
|
||||
m_fTextureLength = var;
|
||||
}
|
||||
float CCRibbon::getTextureLength()
|
||||
{
|
||||
return m_fTextureLength;
|
||||
}
|
||||
void CCRibbon::setBlendFunc(ccBlendFunc var)
|
||||
{
|
||||
m_tBlendFunc = var;
|
||||
}
|
||||
ccBlendFunc CCRibbon::getBlendFunc()
|
||||
{
|
||||
return m_tBlendFunc;
|
||||
}
|
||||
void CCRibbon::setColor(ccColor4B var)
|
||||
{
|
||||
m_tColor = var;
|
||||
}
|
||||
ccColor4B CCRibbon::getColor()
|
||||
{
|
||||
return m_tColor;
|
||||
}
|
||||
|
||||
//
|
||||
//RibbonSegment
|
||||
//
|
||||
bool CCRibbonSegment::init()
|
||||
{
|
||||
this->reset();
|
||||
return true;
|
||||
}
|
||||
char * CCRibbonSegment::description()
|
||||
{
|
||||
char *ret = new char[100] ;
|
||||
sprintf(ret, "<CCRibbonSegment | end = %u, begin = %u>", m_uEnd, m_uBegin);
|
||||
return ret;
|
||||
}
|
||||
CCRibbonSegment::~CCRibbonSegment()
|
||||
{
|
||||
CCLOGINFO("cocos2d: deallocing.");
|
||||
}
|
||||
void CCRibbonSegment::reset()
|
||||
{
|
||||
m_uEnd = 0;
|
||||
m_uBegin = 0;
|
||||
m_bFinished = false;
|
||||
}
|
||||
void CCRibbonSegment::draw(float curTime, float fadeTime, ccColor4B color)
|
||||
{
|
||||
GLubyte r = color.r;
|
||||
GLubyte g = color.g;
|
||||
GLubyte b = color.b;
|
||||
GLubyte a = color.a;
|
||||
|
||||
if (m_uBegin < 50)
|
||||
CCRibbonSegment* newSeg;
|
||||
// grab it from the cache if we can
|
||||
if (m_pDeletedSegments->count() > 0)
|
||||
{
|
||||
// the motion streak class will call update and cause time to change, thus, if curTime_ != 0
|
||||
// we have to generate alpha for the ribbon each frame.
|
||||
if (curTime == 0)
|
||||
{
|
||||
// no alpha over time, so just set the color
|
||||
glColor4ub(r,g,b,a);
|
||||
}
|
||||
else
|
||||
{
|
||||
// generate alpha/color for each point
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
unsigned int i = m_uBegin;
|
||||
for (; i < m_uEnd; ++i)
|
||||
{
|
||||
int idx = i*8;
|
||||
m_pColors[idx] = r;
|
||||
m_pColors[idx+1] = g;
|
||||
m_pColors[idx+2] = b;
|
||||
m_pColors[idx+4] = r;
|
||||
m_pColors[idx+5] = g;
|
||||
m_pColors[idx+6] = b;
|
||||
float alive = ((curTime - m_pCreationTime[i]) / fadeTime);
|
||||
if (alive > 1)
|
||||
{
|
||||
m_uBegin++;
|
||||
m_pColors[idx+3] = 0;
|
||||
m_pColors[idx+7] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pColors[idx+3] = (GLubyte)(255.f - (alive * 255.f));
|
||||
m_pColors[idx+7] = m_pColors[idx+3];
|
||||
}
|
||||
}
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, 0, &m_pColors[m_uBegin*8]);
|
||||
}
|
||||
glVertexPointer(3, GL_FLOAT, 0, &m_pVerts[m_uBegin*6]);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, &m_pCoords[m_uBegin*4]);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, (m_uEnd - m_uBegin) * 2);
|
||||
newSeg = m_pDeletedSegments->getObjectAtIndex(0);
|
||||
newSeg->retain(); // will be released later
|
||||
m_pDeletedSegments->removeObject(newSeg);
|
||||
newSeg->reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bFinished = true;
|
||||
newSeg = new CCRibbonSegment(); // will be released later
|
||||
newSeg->init();
|
||||
}
|
||||
|
||||
newSeg->m_pCreationTime[0] = seg->m_pCreationTime[seg->m_uEnd- 1];
|
||||
int v = (seg->m_uEnd-1)*6;
|
||||
int c = (seg->m_uEnd-1)*4;
|
||||
newSeg->m_pVerts[0] = seg->m_pVerts[v];
|
||||
newSeg->m_pVerts[1] = seg->m_pVerts[v+1];
|
||||
newSeg->m_pVerts[2] = seg->m_pVerts[v+2];
|
||||
newSeg->m_pVerts[3] = seg->m_pVerts[v+3];
|
||||
newSeg->m_pVerts[4] = seg->m_pVerts[v+4];
|
||||
newSeg->m_pVerts[5] = seg->m_pVerts[v+5];
|
||||
|
||||
newSeg->m_pCoords[0] = seg->m_pCoords[c];
|
||||
newSeg->m_pCoords[1] = seg->m_pCoords[c+1];
|
||||
newSeg->m_pCoords[2] = seg->m_pCoords[c+2];
|
||||
newSeg->m_pCoords[3] = seg->m_pCoords[c+3];
|
||||
newSeg->m_uEnd++;
|
||||
seg = newSeg;
|
||||
m_pSegments->addObject(seg);
|
||||
newSeg->release();// it was retained before
|
||||
}
|
||||
if (seg->m_uEnd == 0)
|
||||
{
|
||||
// first edge has to get rotation from the first real polygon
|
||||
CGPoint lp1 = ccpAdd(this->rotatePoint(ccp(-m_fLastWidth, 0), r), m_tLastLocation);
|
||||
CGPoint lp2 = ccpAdd(this->rotatePoint(ccp(+m_fLastWidth, 0), r), m_tLastLocation);
|
||||
seg->m_pCreationTime[0] = m_fCurTime - m_fDelta;
|
||||
seg->m_pVerts[0] = lp1.x;
|
||||
seg->m_pVerts[1] = lp1.y;
|
||||
seg->m_pVerts[2] = 0.0f;
|
||||
seg->m_pVerts[3] = lp2.x;
|
||||
seg->m_pVerts[4] = lp2.y;
|
||||
seg->m_pVerts[5] = 0.0f;
|
||||
seg->m_pCoords[0] = 0.0f;
|
||||
seg->m_pCoords[1] = m_fTexVPos;
|
||||
seg->m_pCoords[2] = 1.0f;
|
||||
seg->m_pCoords[3] = m_fTexVPos;
|
||||
seg->m_uEnd++;
|
||||
}
|
||||
|
||||
}// namespace cocos2d
|
||||
int v = seg->m_uEnd*6;
|
||||
int c = seg->m_uEnd*4;
|
||||
// add new vertex
|
||||
seg->m_pCreationTime[seg->m_uEnd] = m_fCurTime;
|
||||
seg->m_pVerts[v] = p1.x;
|
||||
seg->m_pVerts[v+1] = p1.y;
|
||||
seg->m_pVerts[v+2] = 0.0f;
|
||||
seg->m_pVerts[v+3] = p2.x;
|
||||
seg->m_pVerts[v+4] = p2.y;
|
||||
seg->m_pVerts[v+5] = 0.0f;
|
||||
|
||||
|
||||
seg->m_pCoords[c] = 0.0f;
|
||||
seg->m_pCoords[c+1] = tend;
|
||||
seg->m_pCoords[c+2] = 1.0f;
|
||||
seg->m_pCoords[c+3] = tend;
|
||||
|
||||
m_fTexVPos = tend;
|
||||
m_tLastLocation = location;
|
||||
m_tLastPoint1 = p1;
|
||||
m_tLastPoint2 = p2;
|
||||
m_fLastWidth = width;
|
||||
seg->m_uEnd++;
|
||||
}
|
||||
|
||||
void CCRibbon::draw()
|
||||
{
|
||||
if (m_pSegments->count() > 0)
|
||||
{
|
||||
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
|
||||
// Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY
|
||||
// Unneeded states: GL_COLOR_ARRAY
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_pTexture->getName());
|
||||
|
||||
bool newBlend = ( m_tBlendFunc.src != CC_BLEND_SRC || m_tBlendFunc.dst != CC_BLEND_DST ) ? true : false;
|
||||
if( newBlend )
|
||||
{
|
||||
glBlendFunc( m_tBlendFunc.src, m_tBlendFunc.dst );
|
||||
}
|
||||
|
||||
if(m_pSegments && m_pSegments->count() > 0)
|
||||
{
|
||||
CCRibbonSegment* seg;
|
||||
NSMutableArray<CCRibbonSegment*>::NSMutableArrayIterator it;
|
||||
for( it = m_pSegments->begin(); it != m_pSegments->end(); it++)
|
||||
{
|
||||
seg = (CCRibbonSegment*)*it;
|
||||
seg->draw(m_fCurTime, m_fFadeTime, m_tColor);
|
||||
}
|
||||
}
|
||||
|
||||
if( newBlend )
|
||||
{
|
||||
glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
|
||||
}
|
||||
|
||||
// restore default GL state
|
||||
glEnableClientState( GL_COLOR_ARRAY );
|
||||
}
|
||||
}
|
||||
|
||||
// Ribbon - CocosNodeTexture protocol
|
||||
void CCRibbon::setTexture(CCTexture2D* var)
|
||||
{
|
||||
CCX_SAFE_RETAIN(var);
|
||||
CCX_SAFE_RELEASE(m_pTexture);
|
||||
m_pTexture = var;
|
||||
this->setContentSize(m_pTexture->getContentSizeInPixels());
|
||||
/* XXX Don't update blending function in Ribbons */
|
||||
}
|
||||
|
||||
CCTexture2D *CCRibbon::getTexture()
|
||||
{
|
||||
return m_pTexture;
|
||||
}
|
||||
|
||||
void CCRibbon::setTextureLength(float var)
|
||||
{
|
||||
m_fTextureLength = var;
|
||||
}
|
||||
|
||||
float CCRibbon::getTextureLength()
|
||||
{
|
||||
return m_fTextureLength;
|
||||
}
|
||||
void CCRibbon::setBlendFunc(ccBlendFunc var)
|
||||
{
|
||||
m_tBlendFunc = var;
|
||||
}
|
||||
|
||||
ccBlendFunc CCRibbon::getBlendFunc()
|
||||
{
|
||||
return m_tBlendFunc;
|
||||
}
|
||||
|
||||
void CCRibbon::setColor(ccColor4B var)
|
||||
{
|
||||
m_tColor = var;
|
||||
}
|
||||
ccColor4B CCRibbon::getColor()
|
||||
{
|
||||
return m_tColor;
|
||||
}
|
||||
|
||||
//
|
||||
//RibbonSegment
|
||||
//
|
||||
bool CCRibbonSegment::init()
|
||||
{
|
||||
this->reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
char * CCRibbonSegment::description()
|
||||
{
|
||||
char *ret = new char[100] ;
|
||||
sprintf(ret, "<CCRibbonSegment | end = %u, begin = %u>", m_uEnd, m_uBegin);
|
||||
return ret;
|
||||
}
|
||||
|
||||
CCRibbonSegment::~CCRibbonSegment()
|
||||
{
|
||||
CCLOGINFO("cocos2d: deallocing.");
|
||||
}
|
||||
|
||||
void CCRibbonSegment::reset()
|
||||
{
|
||||
m_uEnd = 0;
|
||||
m_uBegin = 0;
|
||||
m_bFinished = false;
|
||||
}
|
||||
|
||||
void CCRibbonSegment::draw(float curTime, float fadeTime, ccColor4B color)
|
||||
{
|
||||
GLubyte r = color.r;
|
||||
GLubyte g = color.g;
|
||||
GLubyte b = color.b;
|
||||
GLubyte a = color.a;
|
||||
|
||||
if (m_uBegin < 50)
|
||||
{
|
||||
// the motion streak class will call update and cause time to change, thus, if curTime_ != 0
|
||||
// we have to generate alpha for the ribbon each frame.
|
||||
if (curTime == 0)
|
||||
{
|
||||
// no alpha over time, so just set the color
|
||||
glColor4ub(r,g,b,a);
|
||||
}
|
||||
else
|
||||
{
|
||||
// generate alpha/color for each point
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
unsigned int i = m_uBegin;
|
||||
for (; i < m_uEnd; ++i)
|
||||
{
|
||||
int idx = i*8;
|
||||
m_pColors[idx] = r;
|
||||
m_pColors[idx+1] = g;
|
||||
m_pColors[idx+2] = b;
|
||||
m_pColors[idx+4] = r;
|
||||
m_pColors[idx+5] = g;
|
||||
m_pColors[idx+6] = b;
|
||||
float alive = ((curTime - m_pCreationTime[i]) / fadeTime);
|
||||
if (alive > 1)
|
||||
{
|
||||
m_uBegin++;
|
||||
m_pColors[idx+3] = 0;
|
||||
m_pColors[idx+7] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pColors[idx+3] = (GLubyte)(255.f - (alive * 255.f));
|
||||
m_pColors[idx+7] = m_pColors[idx+3];
|
||||
}
|
||||
}
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, 0, &m_pColors[m_uBegin*8]);
|
||||
}
|
||||
glVertexPointer(3, GL_FLOAT, 0, &m_pVerts[m_uBegin*6]);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, &m_pCoords[m_uBegin*4]);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, (m_uEnd - m_uBegin) * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bFinished = true;
|
||||
}
|
||||
}
|
||||
|
||||
}// namespace cocos2d
|
||||
|
|
|
@ -81,6 +81,7 @@ public: inline varType get##funName(void){ return varName; }\
|
|||
public: inline void set##funName(varType var){ varName = var; }
|
||||
|
||||
#define CCX_SAFE_DELETE(p) if(p) { delete p; p=NULL; }
|
||||
#define CCX_SAFE_DELETE_ARRAY(p) if(p) { delete[] p; p=NULL; }
|
||||
#define CCX_SAFE_FREE(p) if(p) { free(p); p=NULL; }
|
||||
#define CCX_SAFE_RELEASE(p) if(p) { p->release(); }
|
||||
#define CCX_SAFE_RELEASE_NULL(p) if(p) { p->release(); p = NULL; }
|
||||
|
|
|
@ -116,7 +116,7 @@ UIImage::~UIImage(void)
|
|||
}
|
||||
}
|
||||
|
||||
bool UIImage::initWithContentsOfFile(const string &strPath, tImageFormat imageType)
|
||||
bool UIImage::initWithContentsOfFile(const string &strPath, eImageFormat imageType)
|
||||
{
|
||||
bool bRet = false;
|
||||
|
||||
|
@ -138,11 +138,11 @@ bool UIImage::initWithContentsOfFile(const string &strPath, tImageFormat imageTy
|
|||
{
|
||||
switch (imageType)
|
||||
{
|
||||
case kImageFormatPNG:
|
||||
case kCCImageFormatPNG:
|
||||
// use libpng load image
|
||||
bRet = loadPngFromStream(pBuffer, nSize);
|
||||
break;
|
||||
case kImageFormatJPG:
|
||||
case kCCImageFormatJPG:
|
||||
bRet = loadJpgFromStream(pBuffer, nSize);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
- kImageFormatJPG -> jpeg
|
||||
@return true if load correctly
|
||||
*/
|
||||
bool initWithContentsOfFile(const std::string &strPath, tImageFormat imageType = kImageFormatPNG);
|
||||
bool initWithContentsOfFile(const std::string &strPath, eImageFormat imageType = kCCImageFormatPNG);
|
||||
/**
|
||||
Load image from stream buffer.
|
||||
@param pBuffer stream buffer that hold the image data
|
||||
|
|
|
@ -207,7 +207,7 @@ CCTexture2D * CCTextureCache::addImage(const char * path)
|
|||
else if (std::string::npos != lowerCase.find(".jpg") || std::string::npos != lowerCase.find(".jpeg"))
|
||||
{
|
||||
UIImage * image = new UIImage();
|
||||
if(! image->initWithContentsOfFile(fullpath, kImageFormatJPG))
|
||||
if(! image->initWithContentsOfFile(fullpath, kCCImageFormatJPG))
|
||||
{
|
||||
delete image;
|
||||
break;
|
||||
|
@ -235,7 +235,7 @@ CCTexture2D * CCTextureCache::addImage(const char * path)
|
|||
#else
|
||||
// prevents overloading the autorelease pool
|
||||
UIImage * image = new UIImage();
|
||||
if(! image->initWithContentsOfFile(fullpath, kImageFormatPNG))
|
||||
if(! image->initWithContentsOfFile(fullpath, kCCImageFormatPNG))
|
||||
{
|
||||
delete image;
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue