Merge pull request #864 from minggo/gles20

reload image data and recreate buffer of object when backing to foreground
This commit is contained in:
minggo 2012-04-24 00:04:50 -07:00
commit 2eda8db7f6
21 changed files with 263 additions and 169 deletions

View File

@ -38,9 +38,11 @@ void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv* env, jobject thi
{ {
ccDrawInit(); ccDrawInit();
ccGLInvalidateStateCache(); ccGLInvalidateStateCache();
cocos2d::CCDirector::sharedDirector()->setGLDefaultValues();
CCShaderCache::sharedShaderCache()->reloadDefaultShaders(); CCShaderCache::sharedShaderCache()->reloadDefaultShaders();
cocos2d::CCTextureCache::reloadAllTextures(); cocos2d::CCTextureCache::reloadAllTextures();
cocos2d::CCNotificationCenter::sharedNotificationCenter()->postNotification(EVNET_COME_TO_FOREGROUND, NULL);
cocos2d::CCDirector::sharedDirector()->setGLDefaultValues();
} }
} }

View File

@ -567,7 +567,7 @@ void CCDirector::purgeDirector()
// cocos2d-x specific data structures // cocos2d-x specific data structures
CCUserDefault::purgeSharedUserDefault(); CCUserDefault::purgeSharedUserDefault();
CCNotificationCenter::purgeNotifCenter(); CCNotificationCenter::purgeNotificationCenter();
ccGLInvalidateStateCache(); ccGLInvalidateStateCache();

View File

@ -43,7 +43,7 @@ CCNotificationCenter::~CCNotificationCenter()
m_observers->release(); m_observers->release();
} }
CCNotificationCenter *CCNotificationCenter::sharedNotifCenter(void) CCNotificationCenter *CCNotificationCenter::sharedNotificationCenter(void)
{ {
if (!s_sharedNotifCenter) if (!s_sharedNotifCenter)
{ {
@ -52,7 +52,7 @@ CCNotificationCenter *CCNotificationCenter::sharedNotifCenter(void)
return s_sharedNotifCenter; return s_sharedNotifCenter;
} }
void CCNotificationCenter::purgeNotifCenter(void) void CCNotificationCenter::purgeNotificationCenter(void)
{ {
CC_SAFE_RELEASE_NULL(s_sharedNotifCenter); CC_SAFE_RELEASE_NULL(s_sharedNotifCenter);
} }

View File

@ -37,8 +37,8 @@ public:
CCNotificationCenter(); CCNotificationCenter();
~CCNotificationCenter(); ~CCNotificationCenter();
static CCNotificationCenter *sharedNotifCenter(void); static CCNotificationCenter *sharedNotificationCenter(void);
static void purgeNotifCenter(void); static void purgeNotificationCenter(void);
void addObserver(CCObject *target, void addObserver(CCObject *target,
SEL_CallFuncO selector, SEL_CallFuncO selector,

View File

@ -0,0 +1,11 @@
#ifndef __CCEVENT_TYPE_H__
#define __CCEVENT_TYPE_H__
/**
* This header is used for defining event types using in CCNotificationCenter
*/
#define EVNET_COME_TO_FOREGROUND "event_come_to_foreground"
#endif // __CCEVENT_TYPE_H__

View File

@ -92,6 +92,10 @@ public:
virtual void draw(); virtual void draw();
virtual void setBatchNode(CCParticleBatchNode* batchNode); virtual void setBatchNode(CCParticleBatchNode* batchNode);
virtual void setTotalParticles(unsigned int tp); virtual void setTotalParticles(unsigned int tp);
/** listen the event that coming to foreground on Android
*/
void listenBackToForeground(CCObject *obj);
private: private:
#if CC_TEXTURE_ATLAS_USE_VAO #if CC_TEXTURE_ATLAS_USE_VAO
void setupVBOandVAO(); void setupVBOandVAO();

View File

@ -193,6 +193,9 @@ public:
/** draws all the Atlas's Quads /** draws all the Atlas's Quads
*/ */
void drawQuads(); void drawQuads();
/** listen the event that coming to foreground on Android
*/
void listenBackToForeground(CCObject *obj);
private: private:
void setupIndices(); void setupIndices();
void mapBuffers(); void mapBuffers();

View File

@ -175,6 +175,7 @@ typedef enum {
kImageFile, kImageFile,
kImageData, kImageData,
kString, kString,
kImage,
}ccCachedImageType; }ccCachedImageType;
public: public:
@ -184,6 +185,7 @@ public:
static void addImageTexture(CCTexture2D *tt, const char* imageFileName, CCImage::EImageFormat format); static void addImageTexture(CCTexture2D *tt, const char* imageFileName, CCImage::EImageFormat format);
static void addStringTexture(CCTexture2D *tt, const char* text, const CCSize& dimensions, CCTextAlignment alignment, const char *fontName, float fontSize); static void addStringTexture(CCTexture2D *tt, const char* text, const CCSize& dimensions, CCTextAlignment alignment, const char *fontName, float fontSize);
static void addDataTexture(CCTexture2D *tt, void* data, CCTexture2DPixelFormat pixelFormat, const CCSize& contentSize); static void addDataTexture(CCTexture2D *tt, void* data, CCTexture2DPixelFormat pixelFormat, const CCSize& contentSize);
static void addCCImage(CCTexture2D *tt, CCImage *image);
static void removeTexture(CCTexture2D *t); static void removeTexture(CCTexture2D *t);
static void reloadAllTextures(); static void reloadAllTextures();
@ -191,9 +193,16 @@ public:
public: public:
static std::list<VolatileTexture*> textures; static std::list<VolatileTexture*> textures;
static bool isReloading; static bool isReloading;
private:
// find VolatileTexture by CCTexture2D*
// if not found, create a new one
static VolatileTexture* findVolotileTexture(CCTexture2D *tt);
protected: protected:
CCTexture2D *texture; CCTexture2D *texture;
CCImage *uiImage;
ccCachedImageType m_eCashedImageType; ccCachedImageType m_eCashedImageType;

View File

@ -225,7 +225,7 @@ It should work same as apples CFSwapInt32LittleToHost(..)
do { \ do { \
GLenum __error = glGetError(); \ GLenum __error = glGetError(); \
if(__error) { \ if(__error) { \
CCLog("OpenGL error 0x%04X in %s %d\n", __error, __FUNCTION__, __LINE__); \ CCLog("OpenGL error 0x%04X in %s %s %d\n", __error, __FILE__, __FUNCTION__, __LINE__); \
} \ } \
} while (false) } while (false)
#endif #endif

View File

@ -269,62 +269,61 @@ bool CCParticleSystem::initWithDictionary(CCDictionary *dictionary)
//don't get the internal texture if a batchNode is used //don't get the internal texture if a batchNode is used
if (!m_pBatchNode) if (!m_pBatchNode)
{ {
// texture // texture
// Try to get the texture from the cache // Try to get the texture from the cache
const char* textureName = dictionary->valueForKey("textureFileName")->getCString(); const char* textureName = dictionary->valueForKey("textureFileName")->getCString();
std::string fullpath = CCFileUtils::fullPathFromRelativeFile(textureName, m_sPlistFile.c_str()); std::string fullpath = CCFileUtils::fullPathFromRelativeFile(textureName, m_sPlistFile.c_str());
CCTexture2D *tex = NULL; CCTexture2D *tex = NULL;
if (strlen(textureName) > 0) if (strlen(textureName) > 0)
{
// set not pop-up message box when load image failed
bool bNotify = CCFileUtils::getIsPopupNotify();
CCFileUtils::setIsPopupNotify(false);
tex = CCTextureCache::sharedTextureCache()->addImage(fullpath.c_str());
// reset the value of UIImage notify
CCFileUtils::setIsPopupNotify(bNotify);
}
if (tex)
{
setTexture(tex);
}
else
{
const char *textureData = dictionary->valueForKey("textureImageData")->getCString();
CCAssert(textureData, "");
int dataLen = strlen(textureData);
if(dataLen != 0)
{ {
// if it fails, try to get it from the base64-gzipped data // set not pop-up message box when load image failed
int decodeLen = base64Decode((unsigned char*)textureData, (unsigned int)dataLen, &buffer); bool bNotify = CCFileUtils::getIsPopupNotify();
CCAssert( buffer != NULL, "CCParticleSystem: error decoding textureImageData"); CCFileUtils::setIsPopupNotify(false);
CC_BREAK_IF(!buffer); tex = CCTextureCache::sharedTextureCache()->addImage(fullpath.c_str());
// reset the value of UIImage notify
CCFileUtils::setIsPopupNotify(bNotify);
}
if (tex)
{
setTexture(tex);
}
else
{
const char *textureData = dictionary->valueForKey("textureImageData")->getCString();
CCAssert(textureData, "");
int dataLen = strlen(textureData);
if(dataLen != 0)
{
// if it fails, try to get it from the base64-gzipped data
int decodeLen = base64Decode((unsigned char*)textureData, (unsigned int)dataLen, &buffer);
CCAssert( buffer != NULL, "CCParticleSystem: error decoding textureImageData");
CC_BREAK_IF(!buffer);
int deflatedLen = ZipUtils::ccInflateMemory(buffer, decodeLen, &deflated); int deflatedLen = ZipUtils::ccInflateMemory(buffer, decodeLen, &deflated);
CCAssert( deflated != NULL, "CCParticleSystem: error ungzipping textureImageData"); CCAssert( deflated != NULL, "CCParticleSystem: error ungzipping textureImageData");
CC_BREAK_IF(!deflated); CC_BREAK_IF(!deflated);
// don't delete image, VolatileTexture use it in CCTextureCache::sharedTextureCache()->addUIImage()
image = new CCImage(); image = new CCImage();
bool isOK = image->initWithImageData(deflated, deflatedLen); bool isOK = image->initWithImageData(deflated, deflatedLen);
CCAssert(isOK, "CCParticleSystem: error init image with Data"); CCAssert(isOK, "CCParticleSystem: error init image with Data");
CC_BREAK_IF(!isOK); CC_BREAK_IF(!isOK);
setTexture(CCTextureCache::sharedTextureCache()->addUIImage(image, fullpath.c_str())); setTexture(CCTextureCache::sharedTextureCache()->addUIImage(image, fullpath.c_str()));
}
} }
} CCAssert( this->m_pTexture != NULL, "CCParticleSystem: error loading the texture");
CCAssert( this->m_pTexture != NULL, "CCParticleSystem: error loading the texture");
} }
bRet = true; bRet = true;
} }
} while (0); } while (0);
CC_SAFE_DELETE_ARRAY(buffer); CC_SAFE_DELETE_ARRAY(buffer);
CC_SAFE_DELETE_ARRAY(deflated); CC_SAFE_DELETE_ARRAY(deflated);
CC_SAFE_DELETE(image);
return bRet; return bRet;
} }
@ -470,7 +469,7 @@ void CCParticleSystem::initParticle(tCCParticle* particle)
float a = CC_DEGREES_TO_RADIANS( m_fAngle + m_fAngleVar * CCRANDOM_MINUS1_1() ); float a = CC_DEGREES_TO_RADIANS( m_fAngle + m_fAngleVar * CCRANDOM_MINUS1_1() );
// Mode Gravity: A // Mode Gravity: A
if( m_nEmitterMode == kCCParticleModeGravity ) if (m_nEmitterMode == kCCParticleModeGravity)
{ {
CCPoint v(cosf( a ), sinf( a )); CCPoint v(cosf( a ), sinf( a ));
float s = modeA.speed + modeA.speedVar * CCRANDOM_MINUS1_1(); float s = modeA.speed + modeA.speedVar * CCRANDOM_MINUS1_1();
@ -488,17 +487,22 @@ void CCParticleSystem::initParticle(tCCParticle* particle)
} }
// Mode Radius: B // Mode Radius: B
else { else
{
// Set the default diameter of the particle from the source position // Set the default diameter of the particle from the source position
float startRadius = modeB.startRadius + modeB.startRadiusVar * CCRANDOM_MINUS1_1(); float startRadius = modeB.startRadius + modeB.startRadiusVar * CCRANDOM_MINUS1_1();
float endRadius = modeB.endRadius + modeB.endRadiusVar * CCRANDOM_MINUS1_1(); float endRadius = modeB.endRadius + modeB.endRadiusVar * CCRANDOM_MINUS1_1();
particle->modeB.radius = startRadius; particle->modeB.radius = startRadius;
if( modeB.endRadius == kCCParticleStartRadiusEqualToEndRadius ) if(modeB.endRadius == kCCParticleStartRadiusEqualToEndRadius)
{
particle->modeB.deltaRadius = 0; particle->modeB.deltaRadius = 0;
}
else else
{
particle->modeB.deltaRadius = (endRadius - startRadius) / particle->timeToLive; particle->modeB.deltaRadius = (endRadius - startRadius) / particle->timeToLive;
}
particle->modeB.angle = a; particle->modeB.angle = a;
particle->modeB.degreesPerSecond = CC_DEGREES_TO_RADIANS(modeB.rotatePerSecond + modeB.rotatePerSecondVar * CCRANDOM_MINUS1_1()); particle->modeB.degreesPerSecond = CC_DEGREES_TO_RADIANS(modeB.rotatePerSecond + modeB.rotatePerSecondVar * CCRANDOM_MINUS1_1());
@ -532,7 +536,7 @@ void CCParticleSystem::update(ccTime dt)
{ {
CC_PROFILER_START_CATEGORY(kCCProfilerCategoryParticles , "CCParticleSystem - update"); CC_PROFILER_START_CATEGORY(kCCProfilerCategoryParticles , "CCParticleSystem - update");
if( m_bIsActive && m_fEmissionRate ) if (m_bIsActive && m_fEmissionRate)
{ {
float rate = 1.0f / m_fEmissionRate; float rate = 1.0f / m_fEmissionRate;
//issue #1201, prevent bursts of particles, due to too high emitCounter //issue #1201, prevent bursts of particles, due to too high emitCounter
@ -541,14 +545,14 @@ void CCParticleSystem::update(ccTime dt)
m_fEmitCounter += dt; m_fEmitCounter += dt;
} }
while( m_uParticleCount < m_uTotalParticles && m_fEmitCounter > rate ) while (m_uParticleCount < m_uTotalParticles && m_fEmitCounter > rate)
{ {
this->addParticle(); this->addParticle();
m_fEmitCounter -= rate; m_fEmitCounter -= rate;
} }
m_fElapsed += dt; m_fElapsed += dt;
if(m_fDuration != -1 && m_fDuration < m_fElapsed) if (m_fDuration != -1 && m_fDuration < m_fElapsed)
{ {
this->stopSystem(); this->stopSystem();
} }
@ -557,35 +561,37 @@ void CCParticleSystem::update(ccTime dt)
m_uParticleIdx = 0; m_uParticleIdx = 0;
CCPoint currentPosition = CCPointZero; CCPoint currentPosition = CCPointZero;
if( m_ePositionType == kCCPositionTypeFree ) if (m_ePositionType == kCCPositionTypeFree)
{ {
currentPosition = this->convertToWorldSpace(CCPointZero); currentPosition = this->convertToWorldSpace(CCPointZero);
} }
else if ( m_ePositionType == kCCPositionTypeRelative ) else if (m_ePositionType == kCCPositionTypeRelative)
{ {
currentPosition = m_tPosition; currentPosition = m_tPosition;
} }
if (m_bIsVisible) if (m_bIsVisible)
{ {
while( m_uParticleIdx < m_uParticleCount ) while (m_uParticleIdx < m_uParticleCount)
{ {
tCCParticle *p = &m_pParticles[m_uParticleIdx]; tCCParticle *p = &m_pParticles[m_uParticleIdx];
// life // life
p->timeToLive -= dt; p->timeToLive -= dt;
if( p->timeToLive > 0 ) if (p->timeToLive > 0)
{ {
// Mode A: gravity, direction, tangential accel & radial accel // Mode A: gravity, direction, tangential accel & radial accel
if( m_nEmitterMode == kCCParticleModeGravity ) if (m_nEmitterMode == kCCParticleModeGravity)
{ {
CCPoint tmp, radial, tangential; CCPoint tmp, radial, tangential;
radial = CCPointZero; radial = CCPointZero;
// radial acceleration // radial acceleration
if(p->pos.x || p->pos.y) if (p->pos.x || p->pos.y)
{
radial = ccpNormalize(p->pos); radial = ccpNormalize(p->pos);
}
tangential = radial; tangential = radial;
radial = ccpMult(radial, p->modeA.radialAccel); radial = ccpMult(radial, p->modeA.radialAccel);
@ -604,7 +610,8 @@ void CCParticleSystem::update(ccTime dt)
} }
// Mode B: radius movement // Mode B: radius movement
else { else
{
// Update the angle and radius of the particle. // Update the angle and radius of the particle.
p->modeB.angle += p->modeB.degreesPerSecond * dt; p->modeB.angle += p->modeB.degreesPerSecond * dt;
p->modeB.radius += p->modeB.deltaRadius * dt; p->modeB.radius += p->modeB.deltaRadius * dt;
@ -632,7 +639,7 @@ void CCParticleSystem::update(ccTime dt)
CCPoint newPos; CCPoint newPos;
if( m_ePositionType == kCCPositionTypeFree || m_ePositionType == kCCPositionTypeRelative ) if (m_ePositionType == kCCPositionTypeFree || m_ePositionType == kCCPositionTypeRelative)
{ {
CCPoint diff = ccpSub( currentPosition, p->startPos ); CCPoint diff = ccpSub( currentPosition, p->startPos );
newPos = ccpSub(p->pos, diff); newPos = ccpSub(p->pos, diff);
@ -655,7 +662,6 @@ void CCParticleSystem::update(ccTime dt)
// update particle counter // update particle counter
++m_uParticleIdx; ++m_uParticleIdx;
} }
else else
{ {
@ -687,8 +693,10 @@ void CCParticleSystem::update(ccTime dt)
} //while } //while
m_bTransformSystemDirty = false; m_bTransformSystemDirty = false;
} }
if (!m_pBatchNode) if (! m_pBatchNode)
{
postStep(); postStep();
}
CC_PROFILER_STOP_CATEGORY(kCCProfilerCategoryParticles , "CCParticleSystem - update"); CC_PROFILER_STOP_CATEGORY(kCCProfilerCategoryParticles , "CCParticleSystem - update");
} }

View File

@ -38,6 +38,8 @@ THE SOFTWARE.
#include "ccGLStateCache.h" #include "ccGLStateCache.h"
#include "CCGLProgram.h" #include "CCGLProgram.h"
#include "support/TransformUtils.h" #include "support/TransformUtils.h"
#include "extensions/CCNotificationCenter/CCNotificationCenter.h"
#include "CCEventType.h"
// extern // extern
#include "kazmath/GL/matrix.h" #include "kazmath/GL/matrix.h"
@ -65,6 +67,14 @@ bool CCParticleSystemQuad::initWithTotalParticles(unsigned int numberOfParticles
#endif #endif
setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTextureColor)); setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTextureColor));
// Need to listen the event only when not use batchnode, because it will use VBO
CCNotificationCenter::sharedNotificationCenter()->addObserver(this,
callfuncO_selector(CCParticleSystemQuad::listenBackToForeground),
EVNET_COME_TO_FOREGROUND,
NULL);
return true; return true;
} }
return false; return false;
@ -91,6 +101,8 @@ CCParticleSystemQuad::~CCParticleSystemQuad()
glDeleteVertexArrays(1, &m_uVAOname); glDeleteVertexArrays(1, &m_uVAOname);
#endif #endif
} }
CCNotificationCenter::sharedNotificationCenter()->removeObserver(this, EVNET_COME_TO_FOREGROUND);
} }
// implementation CCParticleSystemQuad // implementation CCParticleSystemQuad
@ -236,7 +248,7 @@ void CCParticleSystemQuad::updateQuadWithParticle(tCCParticle* particle, const C
// vertices // vertices
GLfloat size_2 = particle->size/2; GLfloat size_2 = particle->size/2;
if( particle->rotation ) if (particle->rotation)
{ {
GLfloat x1 = -size_2; GLfloat x1 = -size_2;
GLfloat y1 = -size_2; GLfloat y1 = -size_2;
@ -273,7 +285,9 @@ void CCParticleSystemQuad::updateQuadWithParticle(tCCParticle* particle, const C
// top-right vertex: // top-right vertex:
quad->tr.vertices.x = cx; quad->tr.vertices.x = cx;
quad->tr.vertices.y = cy; quad->tr.vertices.y = cy;
} else { }
else
{
// bottom-left vertex: // bottom-left vertex:
quad->bl.vertices.x = newPosition.x - size_2; quad->bl.vertices.x = newPosition.x - size_2;
quad->bl.vertices.y = newPosition.y - size_2; quad->bl.vertices.y = newPosition.y - size_2;
@ -477,6 +491,15 @@ void CCParticleSystemQuad::setupVBO()
#endif #endif
void CCParticleSystemQuad::listenBackToForeground(CCObject *obj)
{
#if CC_TEXTURE_ATLAS_USE_VAO
setupVBOandVAO();
#else
setupVBO();
#endif
}
bool CCParticleSystemQuad::allocMemory() bool CCParticleSystemQuad::allocMemory()
{ {
CCAssert( ( !m_pQuads && !m_pIndices), "Memory already alloced"); CCAssert( ( !m_pQuads && !m_pIndices), "Memory already alloced");

View File

@ -87,7 +87,7 @@
} }
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR();
} }
return self; return self;

View File

@ -262,7 +262,7 @@ static cocos2d::CCTouch *s_pTouches[MAX_TOUCHES];
//discardFramebufferSupported_ = [[CCConfiguration sharedConfiguration] supportsDiscardFramebuffer]; //discardFramebufferSupported_ = [[CCConfiguration sharedConfiguration] supportsDiscardFramebuffer];
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR();
return YES; return YES;
} }

View File

@ -246,34 +246,22 @@ bool CCTexture2D::initWithImage(CCImage *uiImage)
bool CCTexture2D::initWithImage(CCImage * uiImage, ccResolutionType resolution) bool CCTexture2D::initWithImage(CCImage * uiImage, ccResolutionType resolution)
{ {
unsigned int POTWide, POTHigh; if (uiImage == NULL)
if(uiImage == NULL)
{ {
CCLOG("cocos2d: CCTexture2D. Can't create Texture. UIImage is nil"); CCLOG("cocos2d: CCTexture2D. Can't create Texture. UIImage is nil");
this->release(); this->release();
return false; return false;
} }
unsigned int imageWidth = uiImage->getWidth();
unsigned int imageHeight = uiImage->getHeight();
CCConfiguration *conf = CCConfiguration::sharedConfiguration(); CCConfiguration *conf = CCConfiguration::sharedConfiguration();
#if CC_TEXTURE_NPOT_SUPPORT
if( conf->isSupportsNPOT() )
{
POTWide = uiImage->getWidth();
POTHigh = uiImage->getHeight();
}
else
#endif
{
POTWide = ccNextPOT(uiImage->getWidth());
POTHigh = ccNextPOT(uiImage->getHeight());
}
unsigned maxTextureSize = conf->getMaxTextureSize(); unsigned maxTextureSize = conf->getMaxTextureSize();
if( POTHigh > maxTextureSize || POTWide > maxTextureSize ) if (imageWidth > maxTextureSize || imageHeight > maxTextureSize)
{ {
CCLOG("cocos2d: WARNING: Image (%u x %u) is bigger than the supported %u x %u", POTWide, POTHigh, maxTextureSize, maxTextureSize); CCLOG("cocos2d: WARNING: Image (%u x %u) is bigger than the supported %u x %u", imageWidth, imageHeight, maxTextureSize, maxTextureSize);
this->release(); this->release();
return NULL; return NULL;
} }
@ -281,7 +269,7 @@ bool CCTexture2D::initWithImage(CCImage * uiImage, ccResolutionType resolution)
m_eResolutionType = resolution; m_eResolutionType = resolution;
// always load premultiplied images // always load premultiplied images
return initPremultipliedATextureWithImage(uiImage, POTWide, POTHigh); return initPremultipliedATextureWithImage(uiImage, imageWidth, imageHeight);
} }
bool CCTexture2D::initPremultipliedATextureWithImage(CCImage *image, unsigned int POTWide, unsigned int POTHigh) bool CCTexture2D::initPremultipliedATextureWithImage(CCImage *image, unsigned int POTWide, unsigned int POTHigh)
{ {

View File

@ -30,6 +30,8 @@ THE SOFTWARE.
#include "ccMacros.h" #include "ccMacros.h"
#include "CCGLProgram.h" #include "CCGLProgram.h"
#include "ccGLStateCache.h" #include "ccGLStateCache.h"
#include "extensions/CCNotificationCenter/CCNotificationCenter.h"
#include "CCEventType.h"
// support // support
#include "CCTexture2D.h" #include "CCTexture2D.h"
#include "CCString.h" #include "CCString.h"
@ -61,6 +63,8 @@ CCTextureAtlas::~CCTextureAtlas()
glDeleteVertexArrays(1, &m_uVAOname); glDeleteVertexArrays(1, &m_uVAOname);
#endif #endif
CC_SAFE_RELEASE(m_pTexture); CC_SAFE_RELEASE(m_pTexture);
CCNotificationCenter::sharedNotificationCenter()->removeObserver(this, EVNET_COME_TO_FOREGROUND);
} }
unsigned int CCTextureAtlas::getTotalQuads() unsigned int CCTextureAtlas::getTotalQuads()
@ -171,6 +175,12 @@ bool CCTextureAtlas::initWithTexture(CCTexture2D *texture, unsigned int capacity
memset( m_pQuads, 0, m_uCapacity * sizeof(ccV3F_C4B_T2F_Quad) ); memset( m_pQuads, 0, m_uCapacity * sizeof(ccV3F_C4B_T2F_Quad) );
memset( m_pIndices, 0, m_uCapacity * 6 * sizeof(GLushort) ); memset( m_pIndices, 0, m_uCapacity * 6 * sizeof(GLushort) );
// listen the event when app go to background
CCNotificationCenter::sharedNotificationCenter()->addObserver(this,
callfuncO_selector(CCTextureAtlas::listenBackToForeground),
EVNET_COME_TO_FOREGROUND,
NULL);
this->setupIndices(); this->setupIndices();
@ -185,6 +195,18 @@ bool CCTextureAtlas::initWithTexture(CCTexture2D *texture, unsigned int capacity
return true; return true;
} }
void CCTextureAtlas::listenBackToForeground(CCObject *obj)
{
#if CC_TEXTURE_ATLAS_USE_VAO
setupVBOandVAO();
#else
setupVBO();
#endif
// set m_bDirty to true to force it rebinding buffer
m_bDirty = true;
}
const char* CCTextureAtlas::description() const char* CCTextureAtlas::description()
{ {
return CCString::stringWithFormat("<CCTextureAtlas | totalQuads = %u>", m_uTotalQuads)->getCString(); return CCString::stringWithFormat("<CCTextureAtlas | totalQuads = %u>", m_uTotalQuads)->getCString();
@ -561,8 +583,11 @@ void CCTextureAtlas::drawNumberOfQuads(unsigned int n)
void CCTextureAtlas::drawNumberOfQuads(unsigned int n, unsigned int start) void CCTextureAtlas::drawNumberOfQuads(unsigned int n, unsigned int start)
{ {
if (0 == n) return; if (0 == n)
ccGLBindTexture2D( m_pTexture->getName() ); {
return;
}
ccGLBindTexture2D(m_pTexture->getName());
#if CC_TEXTURE_ATLAS_USE_VAO #if CC_TEXTURE_ATLAS_USE_VAO
@ -580,7 +605,7 @@ void CCTextureAtlas::drawNumberOfQuads(unsigned int n, unsigned int start)
m_bDirty = false; m_bDirty = false;
} }
glBindVertexArray( m_uVAOname ); glBindVertexArray(m_uVAOname);
#if CC_REBIND_INDICES_BUFFER #if CC_REBIND_INDICES_BUFFER
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_pBuffersVBO[1]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_pBuffersVBO[1]);
@ -608,28 +633,29 @@ void CCTextureAtlas::drawNumberOfQuads(unsigned int n, unsigned int start)
glBindBuffer(GL_ARRAY_BUFFER, m_pBuffersVBO[0]); glBindBuffer(GL_ARRAY_BUFFER, m_pBuffersVBO[0]);
// XXX: update is done in draw... perhaps it should be done in a timer // XXX: update is done in draw... perhaps it should be done in a timer
if (m_bDirty) { if (m_bDirty)
{
glBufferSubData(GL_ARRAY_BUFFER, sizeof(m_pQuads[0])*start, sizeof(m_pQuads[0]) * n , &m_pQuads[start] ); glBufferSubData(GL_ARRAY_BUFFER, sizeof(m_pQuads[0])*start, sizeof(m_pQuads[0]) * n , &m_pQuads[start] );
m_bDirty = false; m_bDirty = false;
} }
ccGLEnableVertexAttribs( kCCVertexAttribFlag_PosColorTex ); ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex);
// vertices // vertices
glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, vertices)); glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof(ccV3F_C4B_T2F, vertices));
// colors // colors
glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, colors)); glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (GLvoid*) offsetof(ccV3F_C4B_T2F, colors));
// tex coords // tex coords
glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, texCoords)); glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof(ccV3F_C4B_T2F, texCoords));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_pBuffersVBO[1]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_pBuffersVBO[1]);
#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP #if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
glDrawElements(GL_TRIANGLE_STRIP, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(m_pIndices[0])) ); glDrawElements(GL_TRIANGLE_STRIP, (GLsizei)n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(m_pIndices[0])));
#else #else
glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(m_pIndices[0])) ); glDrawElements(GL_TRIANGLES, (GLsizei)n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(m_pIndices[0])));
#endif // CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP #endif // CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);

View File

@ -525,6 +525,10 @@ CCTexture2D* CCTextureCache::addUIImage(CCImage *image, const char *key)
} while (0); } while (0);
#if CC_ENABLE_CACHE_TEXTTURE_DATA
VolatileTexture::addCCImage(texture, image);
#endif
return texture; return texture;
} }
@ -626,6 +630,7 @@ VolatileTexture::VolatileTexture(CCTexture2D *t)
, m_alignment(CCTextAlignmentCenter) , m_alignment(CCTextAlignmentCenter)
, m_strFontName("") , m_strFontName("")
, m_strText("") , m_strText("")
, uiImage(NULL)
, m_fFontSize(0.0f) , m_fFontSize(0.0f)
{ {
m_size = CCSizeMake(0, 0); m_size = CCSizeMake(0, 0);
@ -635,26 +640,17 @@ VolatileTexture::VolatileTexture(CCTexture2D *t)
VolatileTexture::~VolatileTexture() VolatileTexture::~VolatileTexture()
{ {
textures.remove(this); textures.remove(this);
CC_SAFE_FREE(uiImage);
} }
void VolatileTexture::addImageTexture(CCTexture2D *tt, const char* imageFileName, CCImage::EImageFormat format) void VolatileTexture::addImageTexture(CCTexture2D *tt, const char* imageFileName, CCImage::EImageFormat format)
{ {
if (isReloading) if (isReloading)
return;
VolatileTexture *vt = 0;
std::list<VolatileTexture *>::iterator i = textures.begin();
while( i != textures.end() )
{ {
VolatileTexture *v = *i++; return;
if (v->texture == tt) {
vt = v;
break;
}
} }
if (!vt) VolatileTexture *vt = findVolotileTexture(tt);
vt = new VolatileTexture(tt);
vt->m_eCashedImageType = kImageFile; vt->m_eCashedImageType = kImageFile;
vt->m_strFileName = imageFileName; vt->m_strFileName = imageFileName;
@ -662,24 +658,44 @@ void VolatileTexture::addImageTexture(CCTexture2D *tt, const char* imageFileName
vt->m_PixelFormat = tt->getPixelFormat(); vt->m_PixelFormat = tt->getPixelFormat();
} }
void VolatileTexture::addDataTexture(CCTexture2D *tt, void* data, CCTexture2DPixelFormat pixelFormat, const CCSize& contentSize) void VolatileTexture::addCCImage(CCTexture2D *tt, CCImage *image)
{ {
if (isReloading) VolatileTexture *vt = findVolotileTexture(tt);
return;
vt->uiImage = image;
vt->m_eCashedImageType = kImage;
}
VolatileTexture* VolatileTexture::findVolotileTexture(CCTexture2D *tt)
{
VolatileTexture *vt = 0; VolatileTexture *vt = 0;
std::list<VolatileTexture *>::iterator i = textures.begin(); std::list<VolatileTexture *>::iterator i = textures.begin();
while( i != textures.end() ) while (i != textures.end())
{ {
VolatileTexture *v = *i++; VolatileTexture *v = *i++;
if (v->texture == tt) { if (v->texture == tt)
{
vt = v; vt = v;
break; break;
} }
} }
if (!vt) if (! vt)
{
vt = new VolatileTexture(tt); vt = new VolatileTexture(tt);
}
return vt;
}
void VolatileTexture::addDataTexture(CCTexture2D *tt, void* data, CCTexture2DPixelFormat pixelFormat, const CCSize& contentSize)
{
if (isReloading)
{
return;
}
VolatileTexture *vt = findVolotileTexture(tt);
vt->m_eCashedImageType = kImageData; vt->m_eCashedImageType = kImageData;
vt->m_pTextureData = data; vt->m_pTextureData = data;
@ -690,21 +706,11 @@ void VolatileTexture::addDataTexture(CCTexture2D *tt, void* data, CCTexture2DPix
void VolatileTexture::addStringTexture(CCTexture2D *tt, const char* text, const CCSize& dimensions, CCTextAlignment alignment, const char *fontName, float fontSize) void VolatileTexture::addStringTexture(CCTexture2D *tt, const char* text, const CCSize& dimensions, CCTextAlignment alignment, const char *fontName, float fontSize)
{ {
if (isReloading) if (isReloading)
return;
VolatileTexture *vt = 0;
std::list<VolatileTexture *>::iterator i = textures.begin();
while( i != textures.end() )
{ {
VolatileTexture *v = *i++; return;
if (v->texture == tt) {
vt = v;
break;
}
} }
if (!vt) VolatileTexture *vt = findVolotileTexture(tt);
vt = new VolatileTexture(tt);
vt->m_eCashedImageType = kString; vt->m_eCashedImageType = kString;
vt->m_size = dimensions; vt->m_size = dimensions;
@ -714,13 +720,15 @@ void VolatileTexture::addStringTexture(CCTexture2D *tt, const char* text, const
vt->m_strText = text; vt->m_strText = text;
} }
void VolatileTexture::removeTexture(CCTexture2D *t) { void VolatileTexture::removeTexture(CCTexture2D *t)
{
std::list<VolatileTexture *>::iterator i = textures.begin(); std::list<VolatileTexture *>::iterator i = textures.begin();
while( i != textures.end() ) while (i != textures.end())
{ {
VolatileTexture *vt = *i++; VolatileTexture *vt = *i++;
if (vt->texture == t) { if (vt->texture == t)
{
delete vt; delete vt;
break; break;
} }
@ -732,11 +740,11 @@ void VolatileTexture::reloadAllTextures()
isReloading = true; isReloading = true;
CCLOG("reload all texture"); CCLOG("reload all texture");
std::list<VolatileTexture *>::iterator i = textures.begin(); std::list<VolatileTexture *>::iterator iter = textures.begin();
while( i != textures.end() ) while (iter != textures.end())
{ {
VolatileTexture *vt = *i++; VolatileTexture *vt = *iter++;
switch (vt->m_eCashedImageType) switch (vt->m_eCashedImageType)
{ {
@ -775,10 +783,11 @@ void VolatileTexture::reloadAllTextures()
break; break;
case kImageData: case kImageData:
{ {
unsigned int nPOTWide, nPOTHigh; vt->texture->initWithData(vt->m_pTextureData,
nPOTWide = ccNextPOT((int)vt->m_TextureSize.width); vt->m_PixelFormat,
nPOTHigh = ccNextPOT((int)vt->m_TextureSize.height); vt->m_TextureSize.width,
vt->texture->initWithData(vt->m_pTextureData, vt->m_PixelFormat, nPOTWide, nPOTHigh, vt->m_TextureSize); vt->m_TextureSize.height,
vt->m_TextureSize);
} }
break; break;
case kString: case kString:
@ -790,6 +799,12 @@ void VolatileTexture::reloadAllTextures()
vt->m_fFontSize); vt->m_fFontSize);
} }
break; break;
case kImage:
{
vt->texture->initWithImage(vt->uiImage,
kCCResolutionUnknown);
}
break;
default: default:
break; break;
} }

View File

@ -1,5 +1,6 @@
#include "AppDelegate.h" #include "AppDelegate.h"
#include "cocos2d.h" #include "cocos2d.h"
#include "CCEventType.h"
#include "platform/android/jni/JniHelper.h" #include "platform/android/jni/JniHelper.h"
#include <jni.h> #include <jni.h>
#include <android/log.h> #include <android/log.h>
@ -36,9 +37,11 @@ void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv* env, jobject thi
{ {
ccDrawInit(); ccDrawInit();
ccGLInvalidateStateCache(); ccGLInvalidateStateCache();
cocos2d::CCDirector::sharedDirector()->setGLDefaultValues();
CCShaderCache::sharedShaderCache()->reloadDefaultShaders(); CCShaderCache::sharedShaderCache()->reloadDefaultShaders();
cocos2d::CCTextureCache::reloadAllTextures(); cocos2d::CCTextureCache::reloadAllTextures();
cocos2d::CCNotificationCenter::sharedNotificationCenter()->postNotification(EVNET_COME_TO_FOREGROUND, NULL);
cocos2d::CCDirector::sharedDirector()->setGLDefaultValues();
} }
} }

View File

@ -1 +1 @@
f46f3ef49ab63a9336441503e20945a3e8a6d6f6 9626f4fb8d0744f491070885ee99b8cf28bb2889

View File

@ -34,7 +34,7 @@ Light::Light()
Light::~Light() Light::~Light()
{ {
CCNotificationCenter::sharedNotifCenter()->removeObserver(this, MSG_SWITCH_STATE); CCNotificationCenter::sharedNotificationCenter()->removeObserver(this, MSG_SWITCH_STATE);
} }
Light* Light::lightWithFile(const char* name) Light* Light::lightWithFile(const char* name)
@ -50,11 +50,11 @@ void Light::setIsConnectToSwitch(bool bConnectToSwitch)
m_bConnected = bConnectToSwitch; m_bConnected = bConnectToSwitch;
if (m_bConnected) if (m_bConnected)
{ {
CCNotificationCenter::sharedNotifCenter()->addObserver(this, callfuncO_selector(Light::switchStateChanged), MSG_SWITCH_STATE, NULL); CCNotificationCenter::sharedNotificationCenter()->addObserver(this, callfuncO_selector(Light::switchStateChanged), MSG_SWITCH_STATE, NULL);
} }
else else
{ {
CCNotificationCenter::sharedNotifCenter()->removeObserver(this, MSG_SWITCH_STATE); CCNotificationCenter::sharedNotificationCenter()->removeObserver(this, MSG_SWITCH_STATE);
} }
updateLightState(); updateLightState();
} }
@ -128,7 +128,7 @@ NotificationCenterTest::NotificationCenterTest()
light->setIsConnectToSwitch(bConnected); light->setIsConnectToSwitch(bConnected);
} }
CCNotificationCenter::sharedNotifCenter()->postNotification(MSG_SWITCH_STATE, (CCObject*)item->getSelectedIndex()); CCNotificationCenter::sharedNotificationCenter()->postNotification(MSG_SWITCH_STATE, (CCObject*)item->getSelectedIndex());
} }
void NotificationCenterTest::toExtensionsMainLayer(cocos2d::CCObject* sender) void NotificationCenterTest::toExtensionsMainLayer(cocos2d::CCObject* sender)
@ -142,7 +142,7 @@ void NotificationCenterTest::toggleSwitch(CCObject *sender)
{ {
CCMenuItemToggle* item = (CCMenuItemToggle*)sender; CCMenuItemToggle* item = (CCMenuItemToggle*)sender;
int index = item->getSelectedIndex(); int index = item->getSelectedIndex();
CCNotificationCenter::sharedNotifCenter()->postNotification(MSG_SWITCH_STATE, (CCObject*)index); CCNotificationCenter::sharedNotificationCenter()->postNotification(MSG_SWITCH_STATE, (CCObject*)index);
} }
void NotificationCenterTest::connectToSwitch(CCObject *sender) void NotificationCenterTest::connectToSwitch(CCObject *sender)

View File

@ -1057,13 +1057,19 @@ CCLayer* restartParticleAction()
return pLayer; return pLayer;
} }
ParticleDemo::~ParticleDemo(void)
ParticleDemo::ParticleDemo(void)
{ {
CC_SAFE_RELEASE(m_emitter);
}
void ParticleDemo::onEnter(void)
{
CCLayer::onEnter();
initWithColor( ccc4(127,127,127,255) ); initWithColor( ccc4(127,127,127,255) );
m_emitter = NULL; m_emitter = NULL;
setIsTouchEnabled( true ); setIsTouchEnabled( true );
CCSize s = CCDirector::sharedDirector()->getWinSize(); CCSize s = CCDirector::sharedDirector()->getWinSize();
@ -1071,30 +1077,31 @@ ParticleDemo::ParticleDemo(void)
addChild(label, 100, 1000); addChild(label, 100, 1000);
label->setPosition( CCPointMake(s.width/2, s.height-50) ); label->setPosition( CCPointMake(s.width/2, s.height-50) );
CCLabelTTF *tapScreen = CCLabelTTF::labelWithString("(Tap the Screen)", "Arial", 20); CCLabelTTF *sub = CCLabelTTF::labelWithString(subtitle().c_str(), "Arial", 16);
tapScreen->setPosition( CCPointMake(s.width/2, s.height-80) ); addChild(sub, 100);
addChild(tapScreen, 100); sub->setPosition(CCPointMake(s.width/2, s.height-80));
CCMenuItemImage* item1 = CCMenuItemImage::itemWithNormalImage(s_pPathB1, s_pPathB2, this, menu_selector(ParticleDemo::backCallback) ); CCMenuItemImage* item1 = CCMenuItemImage::itemWithNormalImage(s_pPathB1, s_pPathB2, this, menu_selector(ParticleDemo::backCallback) );
CCMenuItemImage* item2 = CCMenuItemImage::itemWithNormalImage(s_pPathR1, s_pPathR2, this, menu_selector(ParticleDemo::restartCallback) ); CCMenuItemImage* item2 = CCMenuItemImage::itemWithNormalImage(s_pPathR1, s_pPathR2, this, menu_selector(ParticleDemo::restartCallback) );
CCMenuItemImage* item3 = CCMenuItemImage::itemWithNormalImage(s_pPathF1, s_pPathF2, this, menu_selector(ParticleDemo::nextCallback) ); CCMenuItemImage* item3 = CCMenuItemImage::itemWithNormalImage(s_pPathF1, s_pPathF2, this, menu_selector(ParticleDemo::nextCallback) );
CCMenuItemToggle* item4 = CCMenuItemToggle::itemWithTarget( this, CCMenuItemToggle* item4 = CCMenuItemToggle::itemWithTarget( this,
menu_selector(ParticleDemo::toggleCallback), menu_selector(ParticleDemo::toggleCallback),
CCMenuItemFont::itemWithString( "Free Movement" ), CCMenuItemFont::itemWithString( "Free Movement" ),
CCMenuItemFont::itemWithString( "Relative Movement" ), CCMenuItemFont::itemWithString( "Relative Movement" ),
CCMenuItemFont::itemWithString( "Grouped Movement" ), CCMenuItemFont::itemWithString( "Grouped Movement" ),
NULL ); NULL );
CCMenu *menu = CCMenu::menuWithItems(item1, item2, item3, item4, NULL); CCMenu *menu = CCMenu::menuWithItems(item1, item2, item3, item4, NULL);
menu->setPosition( CCPointZero ); menu->setPosition( CCPointZero );
item1->setPosition( CCPointMake( s.width/2 - 100,30) ); item1->setPosition( CCPointMake( s.width/2 - 100,30) );
item2->setPosition( CCPointMake( s.width/2, 30) ); item2->setPosition( CCPointMake( s.width/2, 30) );
item3->setPosition( CCPointMake( s.width/2 + 100,30) ); item3->setPosition( CCPointMake( s.width/2 + 100,30) );
item4->setPosition( CCPointMake( 0, 100) ); item4->setPosition( CCPointMake( 0, 100) );
item4->setAnchorPoint( CCPointMake(0,0) ); item4->setAnchorPoint( CCPointMake(0,0) );
addChild( menu, 100 ); addChild( menu, 100 );
CCLabelAtlas* labelAtlas = CCLabelAtlas::labelWithString("0000", "fonts/fps_images.png", 16, 24, '.'); CCLabelAtlas* labelAtlas = CCLabelAtlas::labelWithString("0000", "fonts/fps_images.png", 16, 24, '.');
@ -1105,7 +1112,7 @@ ParticleDemo::ParticleDemo(void)
m_background = CCSprite::spriteWithFile(s_back3); m_background = CCSprite::spriteWithFile(s_back3);
addChild(m_background, 5); addChild(m_background, 5);
m_background->setPosition( CCPointMake(s.width/2, s.height-180) ); m_background->setPosition( CCPointMake(s.width/2, s.height-180) );
CCActionInterval* move = CCMoveBy::actionWithDuration(4, CCPointMake(300,0) ); CCActionInterval* move = CCMoveBy::actionWithDuration(4, CCPointMake(300,0) );
CCActionInterval* move_back = move->reverse(); CCActionInterval* move_back = move->reverse();
CCFiniteTimeAction* seq = CCSequence::actions( move, move_back, NULL); CCFiniteTimeAction* seq = CCSequence::actions( move, move_back, NULL);
@ -1113,16 +1120,6 @@ ParticleDemo::ParticleDemo(void)
scheduleUpdate(); scheduleUpdate();
}
ParticleDemo::~ParticleDemo(void)
{
CC_SAFE_RELEASE(m_emitter);
}
void ParticleDemo::onEnter(void)
{
CCLayer::onEnter();
CCLabelTTF* pLabel = (CCLabelTTF*)(this->getChildByTag(1000)); CCLabelTTF* pLabel = (CCLabelTTF*)(this->getChildByTag(1000));
pLabel->setString(title().c_str()); pLabel->setString(title().c_str());
@ -1133,6 +1130,11 @@ std::string ParticleDemo::title()
return "No title"; return "No title";
} }
std::string ParticleDemo::subtitle()
{
return "No titile";
}
void ParticleDemo::registerWithTouchDispatcher() void ParticleDemo::registerWithTouchDispatcher()
{ {
CCDirector* pDirector = CCDirector::sharedDirector(); CCDirector* pDirector = CCDirector::sharedDirector();

View File

@ -19,12 +19,12 @@ protected:
CCSprite* m_background; CCSprite* m_background;
public: public:
ParticleDemo(void);
~ParticleDemo(void); ~ParticleDemo(void);
virtual void onEnter(void); virtual void onEnter(void);
virtual std::string title(); virtual std::string title();
virtual std::string subtitle();
void restartCallback(CCObject* pSender); void restartCallback(CCObject* pSender);
void nextCallback(CCObject* pSender); void nextCallback(CCObject* pSender);