This commit is contained in:
minggo 2010-12-29 18:01:37 +08:00
parent 355570ea8f
commit dc55c164ba
20 changed files with 3494 additions and 780 deletions

View File

@ -350,28 +350,6 @@ void CCDirector::setDeviceOrientation(ccDeviceOrientation kDeviceOrientation)
// m_obSurfaceSize = CGSizeMake(m_obScreenSize.width * m_fContentScaleFactor,
// m_obScreenSize.height * m_fContentScaleFactor);
}
// if (m_eDeviceOrientation != kDeviceOrientation)
// {
// switch (m_eDeviceOrientation)
// {
// case CCDeviceOrientationPortrait:
// CCXApplication::sharedApplication()->setDeviceOrientation(CCDeviceOrientationPortrait);
// break;
// case CCDeviceOrientationPortraitUpsideDown:
// CCXApplication::sharedApplication()->setDeviceOrientation(CCDeviceOrientationPortraitUpsideDown);
// break;
// case CCDeviceOrientationLandscapeLeft:
// CCXApplication::sharedApplication()->setDeviceOrientation(CCDeviceOrientationLandscapeLeft);
// break;
// case CCDeviceOrientationLandscapeRight:
// CCXApplication::sharedApplication()->setDeviceOrientation(CCDeviceOrientationLandscapeRight);
// break;
// default:
// CCLOG("Director: Unknown device orientation");
// break;
// }
// }
}
void CCDirector::setProjection(ccDirectorProjection kProjection)
@ -546,12 +524,22 @@ CGSize CCDirector::getWinSize(void)
return s;
}
CGSize CCDirector::getWinSizeInPixels()
{
return CGSizeZero;
}
// return the current frame size
CGSize CCDirector::getDisplaySize(void)
CGSize CCDirector::getDisplaySizeInPiXels(void)
{
return m_obSurfaceSize;
}
void CCDirector::reshapeProjection(CGSize newWindowSize)
{
}
void CCDirector::applyOrientation(void)
{
CGSize s = m_obSurfaceSize;
@ -792,6 +780,11 @@ void CCDirector::calculateFramerateDeltaTime(void)
*m_pLastComputeFrameRate = now;
}
void CCDirector::showProfilers()
{
}
void CCDirector::computeFrameRate()
{
static bool bInvoked = true;

View File

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

View File

@ -34,10 +34,18 @@ THE SOFTWARE.
#include "CGGeometry.h"
#include "CCXEGLView.h"
#include "ccxCommon.h"
#include "CCGL.h"
#include <assert.h>
namespace cocos2d {
enum {
/// If the window is resized, it won't be autoscaled
kCCDirectorResize_NoScale,
/// If the window is resized, it will be autoscaled (default behavior)
kCCDirectorResize_AutoScale,
};
/** @typedef tPixelFormat
Possible Pixel Formats for the CCXEGLView
*/
@ -83,7 +91,7 @@ typedef enum {
/// sets a 3D projection with a fovy=60, znear=0.5f and zfar=1500.
kCCDirectorProjection3D,
/// it does nothing. But if you are using a custom projection set it this value.
/// it calls "updateProjection" on the projection delegate.
kCCDirectorProjectionCustom,
/// Detault projection is 3D projection
@ -172,22 +180,23 @@ typedef enum {
class CCLabelTTF;
class CCScene;
class cocos2d::CCXEGLView;
class NSEvent;
/**
@brief Class that creates and handle the main Window and manages how
and when to execute the Scenes.
The CCDirector is also responsible for:
- initializing the OpenGL ES context
- setting the OpenGL ES pixel format (default on is RGB565)
- setting the OpenGL ES buffer depth (default one is 0-bit)
- setting the projection (default one is 2D)
- initializing the OpenGL context
- setting the OpenGL pixel format (default on is RGB565)
- setting the OpenGL buffer depth (default one is 0-bit)
- setting the projection (default one is 3D)
- setting the orientation (default one is Protrait)
Since the CCDirector is a singleton, the standard way to use it is by calling:
_ CCDirector::sharedDirector()->xxx();
_ CCDirector::sharedDirector()->methodName();
The CCDirector also sets the default OpenGL ES context:
The CCDirector also sets the default OpenGL context:
- GL_TEXTURE_2D is enabled
- GL_VERTEX_ARRAY is enabled
- GL_COLOR_ARRAY is enabled
@ -216,15 +225,12 @@ public:
inline void setDisplayFPS(bool bDisplayFPS) { m_bDisplayFPS = bDisplayFPS; }
/** Get the CCXEGLView, where everything is rendered */
inline cocos2d::CCXEGLView* getOpenGLView(void) { return m_pobOpenGLView; }
void setOpenGLView(cocos2d::CCXEGLView *pobOpenGLView);
inline CC_GLVIEW* getOpenGLView(void) { return m_pobOpenGLView; }
void setOpenGLView(CC_GLVIEW *pobOpenGLView);
inline bool isNextDeltaTimeZero(void) { return m_bNextDeltaTimeZero; }
void setNextDeltaTimeZero(bool bNextDeltaTimeZero);
inline ccDeviceOrientation getDeviceOrientation(void) { return m_eDeviceOrientation; }
void setDeviceOrientation(ccDeviceOrientation kDeviceOrientation);
/** Whether or not the Director is paused */
inline bool isPaused(void) { return m_bPaused; }
@ -241,54 +247,27 @@ public:
*/
inline bool isSendCleanupToScene(void) { return m_bSendCleanupToScene; }
/** The size in pixels of the surface. It could be different than the screen size.
High-res devices might have a higher surface size than the screen size.
Only available when compiled using SDK >= 4.0.
@since v0.99.4
*/
void setContentScaleFactor(CGFloat scaleFactor);
inline CGFloat getContentScaleFactor(void) { return m_fContentScaleFactor; }
// UI dependent
// window size
/** Uses a new pixel format for the CCXEGLView.
Call this class method before attaching it to a UIView
Default pixel format: kRGB565. Supported pixel formats: kRGBA8 and kRGB565
@deprecated Set the pixel format when creating the CCXEGLView. This method will be removed in v1.0
*/
inline void setPixelFormat(tPixelFormat kPixelFormat)
{
// assert(! isOpenGLAttached());
m_ePixelFormat = kPixelFormat;
}
/** Pixel format used to create the context */
inline tPixelFormat getPiexFormat(void) { return m_ePixelFormat; }
/** Change depth buffer format of the render buffer.
Call this class method before attaching it to a UIWindow/UIView
Default depth buffer: 0 (none). Supported: kCCDepthBufferNone, kCCDepthBuffer16, and kCCDepthBuffer24
@deprecated Set the depth buffer format when creating the CCXEGLView. This method will be removed in v1.0
*/
inline void setDepthBufferFormat(tDepthBufferFormat kDepthBufferFormat)
{
assert(! isOpenGLAttached());
m_eDepthBufferFormat = kDepthBufferFormat;
}
// Integration with UI
/** detach the cocos2d view from the view/window */
bool detach(void);
// Landspace
/** returns the size of the OpenGL view in pixels, according to the landspace */
/** returns the size of the OpenGL view in points.
It takes into account any possible rotation (device orientation) of the window
*/
CGSize getWinSize(void);
/** returns the display size of the OpenGL view in pixels */
CGSize getDisplaySize(void);
/** returns the size of the OpenGL view in pixels.
It takes into account any possible rotation (device orientation) of the window.
On Mac winSize and winSizeInPixels return the same value.
*/
CGSize getWinSizeInPixels(void);
/** returns the display size of the OpenGL view in pixels.
It doesn't take into account any possible rotation of the window.
*/
CGSize getDisplaySizeInPiXels(void);
/** changes the projection size */
void reshapeProjection(CGSize newWindowSize);
/** converts a UIKit coordinate to an OpenGL coordinate
Useful to convert (multi) touches coordinates to the current layout (portrait or landscape)
@ -300,9 +279,6 @@ public:
*/
CGPoint convertToUI(CGPoint obPoint);
/** rotates the screen if an orientation different than Portrait is used */
void applyOrientation(void);
/// XXX: missing description
float getZEye(void);
@ -385,36 +361,103 @@ public:
/** enables/disables OpenGL depth test */
void setDepthTest(bool bOn);
virtual void preMainLoop(void);
virtual void mainLoop(void);
// Profiler
void showProfilers(void);
/***************************************************
* mobile platforms specific functions
**************************************************/
/** rotates the screen if an orientation different than Portrait is used */
void applyOrientation(void);
ccDeviceOrientation getDeviceOrientation(void);
void setDeviceOrientation(ccDeviceOrientation kDeviceOrientation);
/** The size in pixels of the surface. It could be different than the screen size.
High-res devices might have a higher surface size than the screen size.
Only available when compiled using SDK >= 4.0.
@since v0.99.4
*/
void setContentScaleFactor(CGFloat scaleFactor);
CGFloat getContentScaleFactor(void);
/** Will enable Retina Display on devices that supports it.
It will enable Retina Display on iPhone4 and iPod Touch 4.
It will return YES, if it could enabled it, otherwise it will return NO.
This is the recommened way to enable Retina Display.
@since v0.99.5
*/
bool enableRetinaDisplay(bool enabled);
/** There are 4 types of Director.
- kCCDirectorTypeNSTimer (default)
- kCCDirectorTypeMainLoop
- kCCDirectorTypeThreadMainLoop
- kCCDirectorTypeDisplayLink
Each Director has it's own benefits, limitations.
Now we only support DisplayLink director, so it has not effect.
This method should be called before any other call to the director.
@since v0.8.2
*/
static bool setDirectorType(ccDirectorType obDirectorType);
/** Uses a new pixel format for the CCXEGLView.
Call this class method before attaching it to a UIView
Default pixel format: kRGB565. Supported pixel formats: kRGBA8 and kRGB565
@deprecated Set the pixel format when creating the CCXEGLView. This method will be removed in v1.0
*/
void setPixelFormat(tPixelFormat kPixelFormat);
/** Pixel format used to create the context */
tPixelFormat getPiexFormat(void);
/** Change depth buffer format of the render buffer.
Call this class method before attaching it to a UIWindow/UIView
Default depth buffer: 0 (none). Supported: kCCDepthBufferNone, kCCDepthBuffer16, and kCCDepthBuffer24
@deprecated Set the depth buffer format when creating the CCXEGLView. This method will be removed in v1.0
*/
void setDepthBufferFormat(tDepthBufferFormat kDepthBufferFormat);
/** detach the cocos2d view from the view/window */
bool detach(void);
/***************************************************
* PC platforms specific functions, such as mac
**************************************************/
CGPoint convertEventToGL(NSEvent *event);
// whether or not the view is in fullscreen mode
bool isFullScreen(void);
// resize mode: with or without scaling
void setResizeMode(int resizeMode);
int getResizeMode(void);
/** Sets the view in fullscreen or window mode */
void setFullScreen(bool fullscreen);
/** Converts window size coordiantes to logical coordinates.
Useful only if resizeMode is kCCDirectorResize_Scale.
If resizeMode is kCCDirectorResize_NoScale, then no conversion will be done.
*/
CGPoint convertToLogicalCoordinates(CGPoint coordinates);
public:
/** returns a shared instance of the director */
static CCDirector* sharedDirector(void);
/** There are 4 types of Director.
- kCCDirectorTypeNSTimer (default)
- kCCDirectorTypeMainLoop
- kCCDirectorTypeThreadMainLoop
- kCCDirectorTypeDisplayLink
Each Director has it's own benefits, limitations.
Now we only support DisplayLink director, so it has not effect.
This method should be called before any other call to the director.
@since v0.8.2
*/
static bool setDirectorType(ccDirectorType obDirectorType);
/** recalculate the projection view and projection size based on the EAGLVIEW
@since v0.99.4
*/
void recalculateProjectionAndEAGLViewSize();
protected:
/***************************************************
* mobile platforms specific functions
**************************************************/
bool isOpenGLAttached(void);
void updateContentScaleFactor(void);
void setNextScene(void);
#if CC_DIRECTOR_FAST_FPS
@ -427,32 +470,22 @@ protected:
/** calculates delta time since last time it was called */
void calculateDeltaTime();
#if CC_ENABLE_PROFILERS
void showProfilers(void);
#endif // CC_ENABLE_PROFILERS
protected:
// compute frame rate
void computeFrameRate(void);
void computeFrameRate(void);
// compute delta time between computing frame rate
void calculateFramerateDeltaTime(void);
protected:
/* The CCXEGLView, where everything is rendered */
cocos2d::CCXEGLView *m_pobOpenGLView;
CC_GLVIEW *m_pobOpenGLView;
double m_dAnimationInterval;
double m_dOldAnimationInterval;
tPixelFormat m_ePixelFormat;
tDepthBufferFormat m_eDepthBufferFormat;
/* landscape mode ? */
bool m_bLandscape;
/* The device orientation */
ccDeviceOrientation m_eDeviceOrientation;
bool m_bDisplayFPS;
int m_nFrames;
ccTime m_fAccumDt;
@ -494,21 +527,49 @@ protected:
/* projection used */
ccDirectorProjection m_eProjection;
/* screen, different than surface size */
CGSize m_obScreenSize;
/* screen, different than surface size */
CGSize m_obSurfaceSize;
/* window size in points */
CGSize m_obWinSizeInPoints;
/* window size in pixels */
CGSize m_obWinSizeInPixels;
/* content scale factor */
CGFloat m_fContentScaleFactor;
/* contentScaleFactor could be simulated */
bool m_bIsContentScaleSupported;
/* store the fps string */
char *m_pszFPS;
/* This object will be visited after the scene. Useful to hook a notification node */
CCNode *m_pNotificationNode;
/* Projection protocol delegate */
CCProjectionProtocol *m_pProjectionDelegate;
/***************************************************
* mobile platforms specific members
**************************************************/
/* The device orientation */
ccDeviceOrientation m_eDeviceOrientation;
/* contentScaleFactor could be simulated */
bool m_bIsContentScaleSupported;
// Deprecated. Will be removed in 1.0
tPixelFormat m_ePixelFormat;
tDepthBufferFormat m_eDepthBufferFormat;
/***************************************************
* mac platforms specific members
**************************************************/
bool m_bIsFullScreen;
int m_nResizeMode;
CGPoint m_winOffset;
CGSize m_originalWinSize;
MacGLView *m_pFullScreenGLView;
NSWindow *m_pFullScreenWindow;
// cache
MacGLView *m_pWindowGLView;
#if CC_ENABLE_PROFILERS
ccTime m_fAccumDtForProfiler;
@ -529,7 +590,7 @@ class CCDisplayLinkDirector : public CCDirector
public:
CCDisplayLinkDirector(void) {}
virtual void preMainLoop(void);
virtual void mainLoop(void);
virtual void setAnimationInterval(double dValue);
virtual void startAnimation(void);
virtual void stopAnimation();

View File

@ -116,7 +116,7 @@ public:
};
/** OpenGL projection protocol */
class CCX_DLL CCProjectionProtocol
class CCX_DLL CCProjectionProtocol : public NSObject
{
/** Called by CCDirector when the porjection is updated, and "custom" projection is used
@since v0.99.5

View File

@ -191,7 +191,7 @@ Platforms: Only used on Retina Display devices like iPhone 4.
@since v0.99.5
*/
#define CC_RETINA_DISPLAY_FILENAME_SUFFIX @"-hd"
#define CC_RETINA_DISPLAY_FILENAME_SUFFIX "-hd"
/** @def CC_USE_RGBA32_LABELS_ON_NEON_ARCH
If enabled, it will use RGBA8888 (32-bit textures) on Neon devices for CCLabelTTF objects.

View File

@ -0,0 +1,989 @@
/****************************************************************************
Copyright (c) 2010 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "CCDirector.h"
#include "CCScene.h"
#include "NSMutableArray.h"
#include "CCScheduler.h"
#include "ccMacros.h"
#include "CCXCocos2dDefine.h"
#include "CCTouchDispatcher.h"
#include "support/opengl_support/glu.h"
#include "CGPointExtension.h"
#include "CCTransition.h"
#include "CCTextureCache.h"
#include "CCTransition.h"
#include "CCSpriteFrameCache.h"
#include "NSAutoreleasePool.h"
#include "platform/platform.h"
#include "CCXApplication.h"
#include "CCLabelBMFont.h"
#include "CCActionManager.h"
#include "CCLabelTTF.h"
#include "CCConfiguration.h"
#include "CCKeypadDispatcher.h"
#include "CCGL.h"
#if CC_ENABLE_PROFILERS
#include "support/CCProfiling.h"
#endif // CC_ENABLE_PROFILERS
#include <string>
using namespace std;
using namespace cocos2d;
namespace cocos2d
{
// singleton stuff
static CCDisplayLinkDirector s_sharedDirector;
static bool s_bFirstRun = true;
#define kDefaultFPS 60 // 60 frames per second
extern const char* cocos2dVersion(void);
CCDirector* CCDirector::sharedDirector(void)
{
if (s_bFirstRun)
{
s_sharedDirector.init();
s_bFirstRun = false;
}
return &s_sharedDirector;
}
bool CCDirector::init(void)
{
CCLOG("cocos2d: %s", cocos2dVersion());
CCLOG("cocos2d: Using Director Type: CCDirectorDisplayLink");
// scenes
m_pRunningScene = NULL;
m_pNextScene = NULL;
m_pNotificationNode = NULL;
m_dOldAnimationInterval = m_dAnimationInterval = 1.0 / kDefaultFPS;
m_pobScenesStack = new NSMutableArray<CCScene*>();
// Set default projection (3D)
m_eProjection = kCCDirectorProjectionDefault;
// projection delegate if "Custom" projection is used
m_pProjectionDelegate = NULL;
// FPS
m_bDisplayFPS = false;
m_nFrames = 0;
m_pszFPS = new char[10];
m_fExpectedFrameRate = (ccTime)(1 / m_dAnimationInterval);
m_fComputeFrameRateDeltaTime = 0;
m_pLastComputeFrameRate = new struct cc_timeval();
m_pLastUpdate = new struct cc_timeval();
// paused ?
m_bPaused = false;
m_obWinSizeInPixels = m_obWinSizeInPoints = CGSizeZero;
// default values
m_ePixelFormat = kCCPixelFormatDefault;
m_eDepthBufferFormat = kCCDepthBufferNone; // 0
// portrait mode default
m_eDeviceOrientation = CCDeviceOrientationPortrait;
m_pobOpenGLView = NULL;
m_fContentScaleFactor = 1;
m_bIsContentScaleSupported = false;
// create autorelease pool
NSPoolManager::getInstance()->push();
return true;
}
CCDirector::~CCDirector(void)
{
CCLOGINFO("cocos2d: deallocing %p", this);
#if CC_DIRECTOR_FAST_FPS
CCX_SAFE_RELEASE(m_pFPSLabel);
#endif
CCX_SAFE_RELEASE(m_pRunningScene);
CCX_SAFE_RELEASE(m_pNotificationNode);
CCX_SAFE_RELEASE(m_pobScenesStack);
// pop the autorelease pool
NSPoolManager::getInstance()->pop();
// delete m_pLastUpdate
CCX_SAFE_DELETE(m_pLastUpdate);
// delete last compute time
CCX_SAFE_DELETE(m_pLastComputeFrameRate);
CCKeypadDispatcher::purgeSharedDispatcher();
// delete fps string
delete []m_pszFPS;
}
void CCDirector::setGLDefaultValues(void)
{
// This method SHOULD be called only after openGLView_ was initialized
assert(m_pobOpenGLView);
setAlphaBlending(true);
setDepthTest(true);
setProjection(m_eProjection);
// set other opengl default values
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
#if CC_DIRECTOR_FAST_FPS
if (! m_pFPSLabel)
{
m_pFPSLabel = CCLabelTTF::labelWithString("00.0", "XXX", 24);
m_pFPSLabel->retain();
}
#endif
}
// Draw the SCene
void CCDirector::drawScene(void)
{
// calculate "global" dt
calculateDeltaTime();
//tick before glClear: issue #533
if (! m_bPaused)
{
CCScheduler::sharedScheduler()->tick(m_fDeltaTime);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* to avoid flickr, nextScene MUST be here: after tick and before draw.
XXX: Which bug is this one. It seems that it can't be reproduced with v0.9 */
if (m_pNextScene)
{
setNextScene();
}
glPushMatrix();
applyOrientation();
// By default enable VertexArray, ColorArray, TextureCoordArray and Texture2D
CC_ENABLE_DEFAULT_GL_STATES();
// draw the scene
if (m_pRunningScene)
{
m_pRunningScene->visit();
}
// draw the notifications node
if (m_pNotificationNode)
{
m_pNotificationNode->visit();
}
if (m_bDisplayFPS)
{
showFPS();
}
#if CC_ENABLE_PROFILERS
showProfilers();
#endif
CC_DISABLE_DEFAULT_GL_STATES();
glPopMatrix();
// swap buffers
if (m_pobOpenGLView)
{
m_pobOpenGLView->swapBuffers();
}
}
void CCDirector::calculateDeltaTime(void)
{
struct cc_timeval now;
if (CCTime::gettimeofdayCocos2d(&now, NULL) != 0)
{
CCLOG("error in gettimeofday");
m_fDeltaTime = 0;
return;
}
// new delta time
if (m_bNextDeltaTimeZero)
{
m_fDeltaTime = 0;
m_bNextDeltaTimeZero = false;
}
else
{
m_fDeltaTime = (now.tv_sec - m_pLastUpdate->tv_sec) + (now.tv_usec - m_pLastUpdate->tv_usec) / 1000000.0f;
m_fDeltaTime = MAX(0, m_fDeltaTime);
}
*m_pLastUpdate = now;
}
// m_dAnimationInterval
void CCDirector::setAnimationInterval(double dValue)
{
CCLOG("cocos2d: Director#setAnimationInterval. Overrride me");
assert(0);
}
// m_pobOpenGLView
void CCDirector::setOpenGLView(CC_GLVIEW *pobOpenGLView)
{
assert(pobOpenGLView);
if (m_pobOpenGLView != pobOpenGLView)
{
// because EAGLView is not kind of NSObject
delete m_pobOpenGLView; // [openGLView_ release]
m_pobOpenGLView = pobOpenGLView;
setGLDefaultValues();
// set size
m_obWinSizeInPoints = CCNSSizeToCGSize(m_pobOpenGLView->getSize());
m_obWinSizeInPixels = CGSizeMake(m_obWinSizeInPoints.width * m_fContentScaleFactor, m_obWinSizeInPoints * m_fContentScaleFactor);
if (m_fContentScaleFactor != 1)
{
updateContentScaleFactor();
}
CCTouchDispatcher *pTouchDispatcher = CCTouchDispatcher::sharedDispatcher();
m_pobOpenGLView->setTouchDelegate(pTouchDispatcher);
pTouchDispatcher->setDispatchEvents(true);
}
}
void CCDirector::setNextDeltaTimeZero(bool bNextDeltaTimeZero)
{
m_bNextDeltaTimeZero = bNextDeltaTimeZero;
}
void CCDirector::setProjection(ccDirectorProjection kProjection)
{
CGSize size = m_obWinSizeInPixels;
switch (kProjection)
{
case kCCDirectorProjection2D:
glViewport((GLsizei)0, (GLsizei)0, (GLsizei)size.width, (GLsizei)size.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
ccglOrtho(0, size.width, 0, size.height, -1024 * CC_CONTENT_SCALE_FACTOR(),
1024 * CC_CONTENT_SCALE_FACTOR());
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
break;
case kCCDirectorProjection3D:
glViewport(0, 0, (GLsizei)size.width, (GLsizei)size.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (GLfloat)size.width/size.height, 0.5f, 1500.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt( size.width/2, size.height/2, getZEye(),
size.width/2, size.height/2, 0,
0.0f, 1.0f, 0.0f);
break;
case kCCDirectorProjectionCustom:
if (m_pProjectionDelegate)
{
m_pProjectionDelegate->updateProjection();
}
break;
default:
CCLOG("cocos2d: Director: unrecognized projecgtion");
break;
}
m_eProjection = kProjection;
}
void CCDirector::purgeCachedData(void)
{
CCLabelBMFont::purgeCachedData();
CCTextureCache::purgeSharedTextureCache();
}
float CCDirector::getZEye(void)
{
return (m_obWinSizeInPixels.height / 1.1566f);
}
void CCDirector::setAlphaBlending(bool bOn)
{
if (bOn)
{
glEnable(GL_BLEND);
glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
}
else
{
glDisable(GL_BLEND);
}
}
void CCDirector::setDepthTest(bool bOn)
{
if (bOn)
{
ccglClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
else
{
glDisable(GL_DEPTH_TEST);
}
}
CGPoint CCDirector::convertToGL(CGPoint obPoint)
{
CGSize s = m_obWinSizeInPoints;
float newY = s.height - obPoint.y;
float newX = s.width - obPoint.x;
CGPoint ret = CGPointZero;
switch (m_eDeviceOrientation)
{
case CCDeviceOrientationPortrait:
ret = ccp(obPoint.x, newY);
break;
case CCDeviceOrientationPortraitUpsideDown:
ret = ccp(newX, obPoint.y);
break;
case CCDeviceOrientationLandscapeLeft:
ret.x = obPoint.y;
ret.y = obPoint.x;
break;
case CCDeviceOrientationLandscapeRight:
ret.x = newY;
ret.y = newX;
break;
}
// if (m_fContentScaleFactor != 1 && m_bIsContentScaleSupported)
// {
// ret = ccpMult(ret, m_fContentScaleFactor);
// }
return ret;
}
CGPoint CCDirector::convertToUI(CGPoint obPoint)
{
CGSize winSize = m_obWinSizeInPoints;
float oppositeX = winSize.width - obPoint.x;
float oppositeY = winSize.height - obPoint.y;
CGPoint uiPoint = CGPointZero;
switch (m_eDeviceOrientation)
{
case CCDeviceOrientationPortrait:
uiPoint = ccp(obPoint.x, oppositeY);
break;
case CCDeviceOrientationPortraitUpsideDown:
uiPoint = ccp(oppositeX, obPoint.y);
break;
case CCDeviceOrientationLandscapeLeft:
uiPoint = ccp(obPoint.y, obPoint.x);
break;
case CCDeviceOrientationLandscapeRight:
// Can't use oppositeX/Y because x/y are flipped
uiPoint = ccp(winSize.width - obPoint.y, winSize.height - obPoint.x);
break;
}
uiPoint = ccpMult(uiPoint, 1/m_fContentScaleFactor);
return uiPoint;
}
CGSize CCDirector::getWinSize(void)
{
CGSize s = m_obWinSizeInPoints;
if (m_eDeviceOrientation == CCDeviceOrientationLandscapeLeft
|| m_eDeviceOrientation == CCDeviceOrientationLandscapeRight)
{
// swap x,y in landspace mode
CGSize tmp = s;
s.width = tmp.height;
s.height = tmp.width;
}
return s;
}
CGSize CCDirector::getWinSizeInPixels()
{
CGSize s = getWinSize();
s.width *= CC_CONTENT_SCALE_FACTOR();
s.height *= CC_CONTENT_SCALE_FACTOR();
return s;
}
// return the current frame size
CGSize CCDirector::getDisplaySizeInPiXels(void)
{
return m_obWinSizeInPixels;
}
void CCDirector::reshapeProjection(CGSize newWindowSize)
{
m_obWinSizeInPoints = m_pobOpenGLView->getSize();
m_obWinSizeInPixels = CGSizeMake(m_obWinSizeInPoints.width * m_fContentScaleFactor,
m_obWinSizeInPoints.height * m_fContentScaleFactor);
setProjection(m_eProjection);
}
// scene management
void CCDirector::runWithScene(CCScene *pScene)
{
assert(pScene != NULL);
assert(m_pRunningScene == NULL);
pushScene(pScene);
startAnimation();
}
void CCDirector::replaceScene(CCScene *pScene)
{
assert(pScene != NULL);
unsigned int index = m_pobScenesStack->count();
m_bSendCleanupToScene = true;
m_pobScenesStack->replaceObjectAtIndex(index - 1, pScene);
m_pNextScene = pScene;
}
void CCDirector::pushScene(CCScene *pScene)
{
assert(pScene);
m_bSendCleanupToScene = false;
m_pobScenesStack->addObject(pScene);
m_pNextScene = pScene;
}
void CCDirector::popScene(void)
{
assert(m_pRunningScene != NULL);
m_pobScenesStack->removeLastObject();
unsigned int c = m_pobScenesStack->count();
if (c == 0)
{
end();
}
else
{
m_bSendCleanupToScene = true;
m_pNextScene = m_pobScenesStack->getObjectAtIndex(c - 1);
}
}
void CCDirector::end(void)
{
// don't release the event handlers
// They are needed in case the director is run again
CCTouchDispatcher::sharedDispatcher()->removeAllDelegates();
m_pRunningScene->onExit();
m_pRunningScene->cleanup();
m_pRunningScene->release();
m_pRunningScene = NULL;
m_pNextScene = NULL;
// remove all objects, but don't release it.
// runWithScene might be executed after 'end'.
m_pobScenesStack->removeAllObjects();
stopAnimation();
#if CC_DIRECTOR_FAST_FPS
CCX_SAFE_RELEASE_NULL(m_pFPSLabel);
#endif
CCX_SAFE_RELEASE_NULL(m_pProjectionDelegate);
// purge bitmap cache
CCLabelBMFont::purgeCachedData();
// purge all managers
CCAnimationCache::purgeSharedAnimationCache();
CCSpriteFrameCache::purgeSharedSpriteFrameCache();
CCActionManager::sharedManager()->purgeSharedManager();
CCScheduler::purgeSharedScheduler();
CCTextureCache::purgeSharedTextureCache();
// OpenGL view
m_pobOpenGLView->release();
m_pobOpenGLView = NULL;
}
void CCDirector::setNextScene(void)
{
ccSceneFlag runningSceneType = ccNormalScene;
ccSceneFlag newSceneType = m_pNextScene->getSceneType();
if (m_pRunningScene)
{
runningSceneType = m_pRunningScene->getSceneType();
}
// If it is not a transition, call onExit/cleanup
/*if (! newIsTransition)*/
if (! (newSceneType & ccTransitionScene))
{
if (m_pRunningScene)
{
m_pRunningScene->onExit();
}
// issue #709. the root node (scene) should receive the cleanup message too
// otherwise it might be leaked.
if (m_bSendCleanupToScene && m_pRunningScene)
{
m_pRunningScene->cleanup();
}
}
if (m_pRunningScene)
{
m_pRunningScene->release();
}
m_pRunningScene = m_pNextScene;
m_pNextScene->retain();
m_pNextScene = NULL;
if (! (runningSceneType & ccTransitionScene) && m_pRunningScene)
{
m_pRunningScene->onEnter();
m_pRunningScene->onEnterTransitionDidFinish();
}
}
void CCDirector::pause(void)
{
if (m_bPaused)
{
return;
}
m_dOldAnimationInterval = m_dAnimationInterval;
// when paused, don't consume CPU
setAnimationInterval(1 / 4.0);
m_bPaused = true;
}
void CCDirector::resume(void)
{
if (! m_bPaused)
{
return;
}
setAnimationInterval(m_dOldAnimationInterval);
if (CCTime::gettimeofdayCocos2d(m_pLastUpdate, NULL) != 0)
{
CCLOG("cocos2d: Director: Error in gettimeofday");
}
m_bPaused = false;
m_fDeltaTime = 0;
}
void CCDirector::startAnimation(void)
{
CCLOG("cocos2d: Director#startAnimation. Overrride me");
assert(0);
}
void CCDirector::stopAnimation(void)
{
CCLOG("cocos2d: Director#stopAnimation. Overrride me");
assert(0);
}
void CCDirector::mainLoop(void)
{
CCLOG("cocos2d: Director#preMainLoop. Overrride me");
assert(0);
}
#if CC_DIRECTOR_FAST_FPS
// display the FPS using a LabelAtlas
// updates the FPS every frame
void CCDirector::showFPS(void)
{
sprintf(m_pszFPS, "%.1f", m_fFrameRate);
m_pFPSLabel->setString(m_pszFPS);
m_pFPSLabel->draw();
}
#endif // CC_DIRECTOR_FAST_FPS
void CCDirector::calculateFramerateDeltaTime(void)
{
struct cc_timeval now;
if (CCTime::gettimeofdayCocos2d(&now, NULL) != 0)
{
CCLOG("error in gettimeofday");
m_fComputeFrameRateDeltaTime = 0;
return;
}
m_fComputeFrameRateDeltaTime = (now.tv_sec - m_pLastComputeFrameRate->tv_sec) + (now.tv_usec - m_pLastComputeFrameRate->tv_usec) / 1000000.0f;
m_fComputeFrameRateDeltaTime = MAX(0, m_fComputeFrameRateDeltaTime);
*m_pLastComputeFrameRate = now;
}
void CCDirector::computeFrameRate()
{
static bool bInvoked = true;
// compute delta time
calculateFramerateDeltaTime();
// only add frames if the director really draw the scene
if (bInvoked)
{
m_nFrames++;
}
m_fAccumDt += m_fComputeFrameRateDeltaTime;
if (m_fAccumDt > CC_DIRECTOR_FPS_INTERVAL)
{
m_fFrameRate = m_nFrames / m_fAccumDt;
if (m_fFrameRate > m_fExpectedFrameRate)
{
bInvoked = false;
}
else
{
m_nFrames = 0;
m_fAccumDt = 0;
bInvoked = true;
}
}
}
void CCDirector::showProfilers()
{
#if CC_ENABLE_PROFILERS
m_fAccumDtForProfiler += m_fDeltaTime;
if (m_fAccumDtForProfiler > 1.0f)
{
m_fAccumDtForProfiler = 0;
CCProfiler::sharedProfiler()->displayTimers();
}
#endif
}
/***************************************************
* mobile platforms specific functions
**************************************************/
// is the view currently attached
bool CCDirector::isOpenGLAttached(void)
{
return m_pobOpenGLView->isOpenGLReady();
}
void CCDirector::updateContentScaleFactor()
{
// [openGLView responseToSelector:@selector(setContentScaleFactor)]
if (m_pobOpenGLView->canSetContentScaleFactor())
{
m_pobOpenGLView->setContentScaleFactor(m_fContentScaleFactor);
m_bIsContentScaleSupported = true;
}
else
{
CCLOG("cocos2d: setContentScaleFactor:'is not supported on this device");
}
}
// detach or attach to a view or a window
bool CCDirector::detach(void)
{
assert(isOpenGLAttached());
CCX_SAFE_DELETE(m_pobOpenGLView);
return true;
}
void CCDirector::setDepthBufferFormat(tDepthBufferFormat kDepthBufferFormat)
{
assert(! isOpenGLAttached());
m_eDepthBufferFormat = kDepthBufferFormat;
}
void CCDirector::setPixelFormat(tPixelFormat kPixelFormat)
{
m_ePixelFormat = kPixelFormat;
}
tPixelFormat CCDirector::getPiexFormat(void)
{
return m_ePixelFormat;
}
bool CCDirector::setDirectorType(ccDirectorType obDirectorType)
{
// we only support CCDisplayLinkDirector
CCDirector::sharedDirector();
return true;
}
bool CCDirector::enableRetinaDisplay(bool enabled)
{
// Already enabled?
if (enabled && m_fContentScaleFactor == 2)
{
return true;
}
// Already diabled?
if (!enabled && m_fContentScaleFactor == 1)
{
return false;
}
// setContentScaleFactor is not supported
if (! m_pobOpenGLView->canSetContentScaleFactor())
{
return false;
}
///@todo SD device iphone specific
// if ([[UIScreen mainScreen] scale] == 1.0)
// return NO; float newScale = enabled ? 2 : 1; setContentScaleFactor(newScale);
return true;
}
CGFloat CCDirector::getContentScaleFactor(void)
{
return m_fContentScaleFactor;
}
void CCDirector::setContentScaleFactor(CGFloat scaleFactor)
{
if (scaleFactor != m_fContentScaleFactor)
{
m_fContentScaleFactor = scaleFactor;
m_obWinSizeInPixels = CGSizeMake(m_obWinSizeInPoints.width * scaleFactor, m_obWinSizeInPoints.height * scaleFactor);
if (m_pobOpenGLView)
{
updateContentScaleFactor();
}
// update projection
setProjection(m_eProjection);
}
}
void CCDirector::applyOrientation(void)
{
CGSize s = m_obWinSizeInPixels;
float w = s.width / 2;
float h = s.height / 2;
// XXX it's using hardcoded values.
// What if the the screen size changes in the future?
switch (m_eDeviceOrientation)
{
case CCDeviceOrientationPortrait:
// nothing
break;
case CCDeviceOrientationPortraitUpsideDown:
// upside down
glTranslatef(w,h,0);
glRotatef(180,0,0,1);
glTranslatef(-w,-h,0);
break;
case CCDeviceOrientationLandscapeRight:
glTranslatef(w,h,0);
glRotatef(90,0,0,1);
glTranslatef(-h,-w,0);
break;
case CCDeviceOrientationLandscapeLeft:
glTranslatef(w,h,0);
glRotatef(-90,0,0,1);
glTranslatef(-h,-w,0);
break;
}
}
ccDeviceOrientation CCDirector::getDeviceOrientation(void)
{
return m_eDeviceOrientation;
}
void CCDirector::setDeviceOrientation(ccDeviceOrientation kDeviceOrientation)
{
ccDeviceOrientation eNewOrientation;
eNewOrientation = CCXApplication::sharedApplication()->setDeviceOrientation(kDeviceOrientation);
if (m_eDeviceOrientation != eNewOrientation)
{
m_eDeviceOrientation = kDeviceOrientation;
}
}
/***************************************************
* PC platforms specific functions, such as mac
**************************************************/
CGPoint CCDirector::convertEventToGL(NSEvent *event);
{
assert(false);
return CGPointZero;
}
bool CCDirector::isFullScreen(void)
{
assert(false);
return false;
}
void CCDirector::setResizeMode(int resizeMode)
{
assert(false);
}
int CCDirector::getResizeMode(void);
{
assert(false);
return -1;
}
void CCDirector::setFullScreen(bool fullscreen)
{
assert(false);
}
CGPoint CCDirector::convertToLogicalCoordinates(CGPoint coordinates)
{
assert(false);
}
/***************************************************
* implementation of DisplayLinkDirector
**************************************************/
// should we afford 4 types of director ??
// I think DisplayLinkDirector is enough
// so we now only support DisplayLinkDirector
void CCDisplayLinkDirector::startAnimation(void)
{
if (CCTime::gettimeofdayCocos2d(m_pLastUpdate, NULL) != 0)
{
CCLOG("cocos2d: DisplayLinkDirector: Error on gettimeofday");
}
m_bInvalid = false;
}
void CCDisplayLinkDirector::mainLoop(void)
{
if (! m_bInvalid)
{
// compute frame rate
computeFrameRate();
// control frame rate
if (m_fFrameRate <= m_fExpectedFrameRate)
{
drawScene();
// release the objects
NSPoolManager::getInstance()->pop();
}
}
}
void CCDisplayLinkDirector::stopAnimation(void)
{
m_bInvalid = true;
}
void CCDisplayLinkDirector::setAnimationInterval(double dValue)
{
m_dAnimationInterval = dValue;
m_fExpectedFrameRate = (ccTime)(1 / m_dAnimationInterval);
if (! m_bInvalid)
{
stopAnimation();
startAnimation();
}
}
} //namespace cocos2d

View File

@ -43,11 +43,9 @@ THE SOFTWARE.
#error
#endif
#define CC_GLVIEW CCXEGLView
// iOS
#if defined(CCX_PLATFORM_MOBILE)
#define CC_GLVIEW cocos2d::CCXEGLView
#define ccglOrtho glOrthof
#define ccglClearDepth glClearDepthf
#define ccglGenerateMipmap glGenerateMipmapOES
@ -65,6 +63,7 @@ THE SOFTWARE.
// Mac
#elif defined(CCX_PLATFORM_PC)
#define CC_GLVIEW MacGLView
#define ccglOrtho glOrtho
#define ccglClearDepth glClearDepth
#define ccglGenerateMipmap glGenerateMipmap

View File

@ -43,11 +43,15 @@ THE SOFTWARE.
#define CCTextAlignmentLeft UITextAlignmentLeft
#define CCTextAlignmentRight UITextAlignmentRight
#define MacGLView void
#define NSWindow void
#elif defined(CCX_PLATFORM_MAC)
#include <Availability.h>
#include <Foundation/Foundation.h>
#include "platform/MacGLView.h"
#define CCRectFromString(__r__) NSRectToCGRect( NSRectFromString(__r__) )
#define CCPointFromString(__p__) NSPointToCGPoint( NSPointFromString(__p__) )
@ -68,14 +72,17 @@ THE SOFTWARE.
#define CCRectFromString(__r__) CGRectZero
#define CCPointFromString(__p__) CGPointZero
#define CCSizeFromString(__s__) CGSizeZero
#define CCNSSizeToCGSize CGSizeZero
#define CCNSRectToCGRect CGRectZero
#define CCNSPointToCGPoint CGPointZero
#define CCNSSizeToCGSize
#define CCNSRectToCGRect
#define CCNSPointToCGPoint
#define CCTextAlignment 0
#define CCTextAlignmentCenter 0
#define CCTextAlignmentLeft 0
#define CCTextAlignmentRight 0
#define MacGLView void
#define NSWindow void
#endif
#endif // __PLATFOMR_CCNS_H__

View File

@ -0,0 +1,44 @@
/****************************************************************************
Copyright (c) 2010 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#ifndef __PLATFORM_MAC_CCDIRECTOR_DISPLAYLINK_MAC_WRAPPER
#define __PLATFORM_MAC_CCDIRECTOR_DISPLAYLINK_MAC_WRAPPER
#import <QuartzCore/CVDisplayLink.h>
@interface CCDirectorDisplayLinkMacWrapper
{
CVDisplayLinkRef displayLink;
NSThread *runningThread_;
}
@property(nonatomic, readonly)NSThread *runningThread_;
+(CCDirectorDisplayLinkMacWrapper*)sharedDisplayLinkMacWrapper;
-(void)startAnimation;
-(void)stopAnimation;
@end
#endif // __PLATFORM_MAC_CCDIRECTOR_DISPLAYLINK_MAC_WRAPPER

View File

@ -0,0 +1,141 @@
/****************************************************************************
Copyright (c) 2010 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#import "CCDirectorDisplayLinkMacWrapper.h"
#import "ccConfig.h"
@implementation CCDirectorDisplayLinkMacWrapper
static CCDirectorDisplayLinkMacWrapper* sharedDisplayLinkMacWrapper;
@synthesize runningThread = runningThread_;
+(CCDirectorDisplayLinkMacWrapper*)sharedDisplayLinkMacWrapper
{
if (! sharedDisplayLinkMacWrapper)
{
sharedDiplayLinkMacWrapper = [CCDirectorDisplayLinkMacWrapper new];
}
return sharedDiplayLinkMacWrapper;
}
- (void) init
{
runningThread_ = nil;
displayLink = nil;
}
- (CVReturn) getFrameForTime:(const CVTimeStamp*)outputTime
{
#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
if( ! runningThread_ )
runningThread_ = [NSThread currentThread];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[self drawScene];
[[CCEventDispatcher sharedDispatcher] dispatchQueuedEvents];
[[NSRunLoop currentRunLoop] run];
[pool release];
#else
[self performSelector:@selector(drawScene) onThread:runningThread_ withObject:nil waitUntilDone:YES];
#endif
return kCVReturnSuccess;
}
// This is the renderer output callback function
static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
{
CVReturn result = [(CCDirectorDisplayLinkMacWrapper*)displayLinkContext getFrameForTime:outputTime];
return result;
}
- (void) startAnimation
{
#if ! CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
runningThread_ = [[NSThread alloc] initWithTarget:self selector:@selector(mainLoop) object:nil];
[runningThread_ start];
#endif
// Create a display link capable of being used with all active displays
CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
// Set the renderer output callback function
CVDisplayLinkSetOutputCallback(displayLink, &MyDisplayLinkCallback, self);
// Set the display link for the current renderer
CGLContextObj cglContext = [[openGLView_ openGLContext] CGLContextObj];
CGLPixelFormatObj cglPixelFormat = [[openGLView_ pixelFormat] CGLPixelFormatObj];
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat);
// Activate the display link
CVDisplayLinkStart(displayLink);
}
- (void) mainLoop
{
cocos2d::CCDirector::sharedDirector()->mainLoop();
}
- (void) stopAnimation
{
if( displayLink ) {
CVDisplayLinkStop(displayLink);
CVDisplayLinkRelease(displayLink);
displayLink = NULL;
#if ! CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
[runningThread_ cancel];
[runningThread_ release];
runningThread_ = nil;
#endif
}
}
-(void) dealloc
{
if( displayLink )
{
CVDisplayLinkStop(displayLink);
CVDisplayLinkRelease(displayLink);
}
sharedDisplayLinkMacWrapper = nil;
[super dealloc];
}
//
// Draw the Scene
//
- (void) drawScene
{
cocos2d::CCDirector::sharedDirector()->drawScene();
}
@end

View File

@ -0,0 +1,973 @@
/****************************************************************************
Copyright (c) 2010 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "CCDirector.h"
#include "CCScene.h"
#include "NSMutableArray.h"
#include "CCScheduler.h"
#include "ccMacros.h"
#include "CCXCocos2dDefine.h"
#include "CCTouchDispatcher.h"
#include "support/opengl_support/glu.h"
#include "CGPointExtension.h"
#include "CCTransition.h"
#include "CCTextureCache.h"
#include "CCTransition.h"
#include "CCSpriteFrameCache.h"
#include "NSAutoreleasePool.h"
#include "platform/platform.h"
#include "CCXApplication.h"
#include "CCLabelBMFont.h"
#include "CCActionManager.h"
#include "CCLabelTTF.h"
#include "CCConfiguration.h"
#include "CCKeypadDispatcher.h"
#include "CCGL.h"
#include "CCDirectorDisplayLinkMacWrapper.h"
#if CC_ENABLE_PROFILERS
#include "support/CCProfiling.h"
#endif // CC_ENABLE_PROFILERS
#include <string>
using namespace std;
using namespace cocos2d;
namespace cocos2d
{
// singleton stuff
static CCDisplayLinkDirector s_sharedDirector;
static bool s_bFirstRun = true;
#define kDefaultFPS 60 // 60 frames per second
extern const char* cocos2dVersion(void);
CCDirector* CCDirector::sharedDirector(void)
{
if (s_bFirstRun)
{
s_sharedDirector.init();
s_bFirstRun = false;
}
return &s_sharedDirector;
}
bool CCDirector::init(void)
{
CCLOG("cocos2d: %s", cocos2dVersion());
CCLOG("cocos2d: Using Director Type: CCDirectorDisplayLink");
// scenes
m_pRunningScene = NULL;
m_pNextScene = NULL;
m_pNotificationNode = NULL;
m_dOldAnimationInterval = m_dAnimationInterval = 1.0 / kDefaultFPS;
m_pobScenesStack = new NSMutableArray<CCScene*>();
// Set default projection (3D)
m_eProjection = kCCDirectorProjectionDefault;
// projection delegate if "Custom" projection is used
m_pProjectionDelegate = NULL;
// FPS
m_bDisplayFPS = false;
m_nFrames = 0;
m_pszFPS = new char[10];
m_fExpectedFrameRate = (ccTime)(1 / m_dAnimationInterval);
m_fComputeFrameRateDeltaTime = 0;
m_pLastComputeFrameRate = new struct cc_timeval();
m_pLastUpdate = new struct cc_timeval();
// paused ?
m_bPaused = false;
m_obWinSizeInPixels = m_obWinSizeInPoints = CGSizeZero;
m_pobOpenGLView = NULL;
m_bIsFullScreen = false;
m_nResizeMode = kCCDirectorResize_AutoScale;
m_pFullScreenGLView = NULL;
m_pFullScreenWindow = NULL;
m_pWindowGLView = NULL;
m_winOffset = CGPointZero;
// create autorelease pool
NSPoolManager::getInstance()->push();
return true;
}
CCDirector::~CCDirector(void)
{
CCLOGINFO("cocos2d: deallocing %p", this);
#if CC_DIRECTOR_FAST_FPS
CCX_SAFE_RELEASE(m_pFPSLabel);
#endif
CCX_SAFE_RELEASE(m_pRunningScene);
CCX_SAFE_RELEASE(m_pNotificationNode);
CCX_SAFE_RELEASE(m_pobScenesStack);
// pop the autorelease pool
NSPoolManager::getInstance()->pop();
// delete m_pLastUpdate
CCX_SAFE_DELETE(m_pLastUpdate);
// delete last compute time
CCX_SAFE_DELETE(m_pLastComputeFrameRate);
CCKeypadDispatcher::purgeSharedDispatcher();
// delete fps string
delete []m_pszFPS;
[m_pFullScreenGLView release];
[m_pFullScreenWindow release];
[m_pWindowGLView release];
[[CCDirectorDisplayLinkMacWrapper sharedDisplayLinkMacWrapper] release];
}
void CCDirector::setGLDefaultValues(void)
{
// This method SHOULD be called only after openGLView_ was initialized
assert(m_pobOpenGLView);
setAlphaBlending(true);
setDepthTest(true);
setProjection(m_eProjection);
// set other opengl default values
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
#if CC_DIRECTOR_FAST_FPS
if (! m_pFPSLabel)
{
m_pFPSLabel = CCLabelTTF::labelWithString("00.0", "XXX", 24);
m_pFPSLabel->retain();
}
#endif
}
// Draw the SCene
void CCDirector::drawScene(void)
{
// calculate "global" dt
calculateDeltaTime();
//tick before glClear: issue #533
if (! m_bPaused)
{
CCScheduler::sharedScheduler()->tick(m_fDeltaTime);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* to avoid flickr, nextScene MUST be here: after tick and before draw.
XXX: Which bug is this one. It seems that it can't be reproduced with v0.9 */
if (m_pNextScene)
{
setNextScene();
}
glPushMatrix();
// By default enable VertexArray, ColorArray, TextureCoordArray and Texture2D
CC_ENABLE_DEFAULT_GL_STATES();
// draw the scene
if (m_pRunningScene)
{
m_pRunningScene->visit();
}
// draw the notifications node
if (m_pNotificationNode)
{
m_pNotificationNode->visit();
}
if (m_bDisplayFPS)
{
showFPS();
}
#if CC_ENABLE_PROFILERS
showProfilers();
#endif
CC_DISABLE_DEFAULT_GL_STATES();
glPopMatrix();
// swap buffers
if (m_pobOpenGLView)
{
m_pobOpenGLView->swapBuffers();
}
}
void CCDirector::calculateDeltaTime(void)
{
struct cc_timeval now;
if (CCTime::gettimeofdayCocos2d(&now, NULL) != 0)
{
CCLOG("error in gettimeofday");
m_fDeltaTime = 0;
return;
}
// new delta time
if (m_bNextDeltaTimeZero)
{
m_fDeltaTime = 0;
m_bNextDeltaTimeZero = false;
}
else
{
m_fDeltaTime = (now.tv_sec - m_pLastUpdate->tv_sec) + (now.tv_usec - m_pLastUpdate->tv_usec) / 1000000.0f;
m_fDeltaTime = MAX(0, m_fDeltaTime);
}
*m_pLastUpdate = now;
}
// m_dAnimationInterval
void CCDirector::setAnimationInterval(double dValue)
{
CCLOG("cocos2d: Director#setAnimationInterval. Overrride me");
assert(0);
}
// m_pobOpenGLView
void CCDirector::setOpenGLView(CC_GLVIEW *pobOpenGLView)
{
assert(pobOpenGLView);
if (m_pobOpenGLView != pobOpenGLView)
{
[m_pobOpenGLView release];
m_pobOpenGLView = [pobOpenGLView retain];
// set size
m_obWinSizeInPixels = m_obWinSizeInPoints = CCNSSizeToCGSize([pobOpenGLView bounds].size);
setGLDefaultValues();
// cache the NSWindow and NSOpgenGLView created from the NIB
if (!m_bIsFullScreen && !m_pWindowGLView)
{
m_pWindowGLView = [pobOpenGLView retain];
m_originalWinSize = m_obWinSizeInPixels;
}
// for DirectorDisplayLink, because the it doesn't override setOpenGLView
CCEventDispatcher *eventDispatcher = [CCEventDispatcher sharedDispatcher];
[m_pobOpenGLView setEventDelegate: eventDispatcher];
[eventDispatcher setDispatchEvents: YES];
// Enable Touches. Default no.
[pobOpenGLView setAcceptsTouchEvents:NO];
// [view setAcceptsTouchEvents:YES];
// Synchronize buffer swaps with vertical refresh rate
[[pobOpenGLView openGLContext] makeCurrentContext];
GLint swapInt = 1;
[[pobOpenGLView openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
}
}
void CCDirector::setNextDeltaTimeZero(bool bNextDeltaTimeZero)
{
m_bNextDeltaTimeZero = bNextDeltaTimeZero;
}
void CCDirector::setProjection(ccDirectorProjection kProjection)
{
CGSize size = m_obWinSizeInPixels;
CGPoint offset = CGPointZero;
float widthAspect = size.width;
float heightAspect = size.height;
if( m_nResizeMode == kCCDirectorResize_AutoScale && ! CGSizeEqualToSize(m_originalWinSize, CGSizeZero ) )
{
size = m_originalWinSize;
float aspect = m_originalWinSize.width / m_originalWinSize.height;
widthAspect = m_obWinSizeInPixels.width;
heightAspect = m_obWinSizeInPixels.width / aspect;
if( heightAspect > m_obWinSizeInPixels.height )
{
widthAspect = m_obWinSizeInPixels.height * aspect;
heightAspect = m_obWinSizeInPixels.height;
}
m_winOffset.x = (m_obWinSizeInPixels.width - widthAspect) / 2;
m_winOffset.y = (m_obWinSizeInPixels.height - heightAspect) / 2;
offset = m_winOffset;
}
switch (kProjection) {
case kCCDirectorProjection2D:
glViewport(offset.x, offset.y, widthAspect, heightAspect);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
ccglOrtho(0, size.width, 0, size.height, -1024, 1024);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
break;
case kCCDirectorProjection3D:
glViewport(offset.x, offset.y, widthAspect, heightAspect);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (GLfloat)widthAspect/heightAspect, 0.1f, 1500.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
float eyeZ = size.height * getZEye() / m_obWinSizeInPixels.height;
gluLookAt( size.width/2, size.height/2, eyeZ,
size.width/2, size.height/2, 0,
0.0f, 1.0f, 0.0f);
break;
case kCCDirectorProjectionCustom:
if(m_pProjectionDelegate)
{
m_pProjectionDelegate->updateProjection();
}
break;
default:
CCLOG("cocos2d: Director: unrecognized projecgtion");
break;
}
m_eProjection = kProjection;
}
void CCDirector::purgeCachedData(void)
{
CCLabelBMFont::purgeCachedData();
CCTextureCache::purgeSharedTextureCache();
}
float CCDirector::getZEye(void)
{
return (m_obWinSizeInPixels.height / 1.1566f);
}
void CCDirector::setAlphaBlending(bool bOn)
{
if (bOn)
{
glEnable(GL_BLEND);
glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
}
else
{
glDisable(GL_BLEND);
}
}
void CCDirector::setDepthTest(bool bOn)
{
if (bOn)
{
ccglClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
else
{
glDisable(GL_DEPTH_TEST);
}
}
CGPoint CCDirector::convertToGL(CGPoint obPoint)
{
assert(0);
return CGPointZero;
}
CGPoint CCDirector::convertToUI(CGPoint obPoint)
{
assert(0);
return CGPointZero;
}
CGSize CCDirector::getWinSize(void)
{
if (m_nResizeMode == kCCDirectorResize_AutoScale)
{
return m_originalWinSize;
}
return m_obWinSizeInPixels;
}
CGSize CCDirector::getWinSizeInPixels()
{
return getWinSize();
}
// return the current frame size
CGSize CCDirector::getDisplaySizeInPiXels(void)
{
return m_obWinSizeInPixels;
}
void CCDirector::reshapeProjection(CGSize newWindowSize)
{
m_obWinSizeInPixels = m_originalWinSize = newWindowSize;
setProjection(m_eProjection);
}
// scene management
void CCDirector::runWithScene(CCScene *pScene)
{
assert(pScene != NULL);
assert(m_pRunningScene == NULL);
pushScene(pScene);
startAnimation();
}
void CCDirector::replaceScene(CCScene *pScene)
{
assert(pScene != NULL);
unsigned int index = m_pobScenesStack->count();
m_bSendCleanupToScene = true;
m_pobScenesStack->replaceObjectAtIndex(index - 1, pScene);
m_pNextScene = pScene;
}
void CCDirector::pushScene(CCScene *pScene)
{
assert(pScene);
m_bSendCleanupToScene = false;
m_pobScenesStack->addObject(pScene);
m_pNextScene = pScene;
}
void CCDirector::popScene(void)
{
assert(m_pRunningScene != NULL);
m_pobScenesStack->removeLastObject();
unsigned int c = m_pobScenesStack->count();
if (c == 0)
{
end();
}
else
{
m_bSendCleanupToScene = true;
m_pNextScene = m_pobScenesStack->getObjectAtIndex(c - 1);
}
}
void CCDirector::end(void)
{
// don't release the event handlers
// They are needed in case the director is run again
CCTouchDispatcher::sharedDispatcher()->removeAllDelegates();
m_pRunningScene->onExit();
m_pRunningScene->cleanup();
m_pRunningScene->release();
m_pRunningScene = NULL;
m_pNextScene = NULL;
// remove all objects, but don't release it.
// runWithScene might be executed after 'end'.
m_pobScenesStack->removeAllObjects();
stopAnimation();
#if CC_DIRECTOR_FAST_FPS
CCX_SAFE_RELEASE_NULL(m_pFPSLabel);
#endif
CCX_SAFE_RELEASE_NULL(m_pProjectionDelegate);
// purge bitmap cache
CCLabelBMFont::purgeCachedData();
// purge all managers
CCAnimationCache::purgeSharedAnimationCache();
CCSpriteFrameCache::purgeSharedSpriteFrameCache();
CCActionManager::sharedManager()->purgeSharedManager();
CCScheduler::purgeSharedScheduler();
CCTextureCache::purgeSharedTextureCache();
// OpenGL view
[m_pobOpenGLView release];
m_pobOpenGLView = NULL;
}
void CCDirector::setNextScene(void)
{
ccSceneFlag runningSceneType = ccNormalScene;
ccSceneFlag newSceneType = m_pNextScene->getSceneType();
if (m_pRunningScene)
{
runningSceneType = m_pRunningScene->getSceneType();
}
// If it is not a transition, call onExit/cleanup
/*if (! newIsTransition)*/
if (! (newSceneType & ccTransitionScene))
{
if (m_pRunningScene)
{
m_pRunningScene->onExit();
}
// issue #709. the root node (scene) should receive the cleanup message too
// otherwise it might be leaked.
if (m_bSendCleanupToScene && m_pRunningScene)
{
m_pRunningScene->cleanup();
}
}
if (m_pRunningScene)
{
m_pRunningScene->release();
}
m_pRunningScene = m_pNextScene;
m_pNextScene->retain();
m_pNextScene = NULL;
if (! (runningSceneType & ccTransitionScene) && m_pRunningScene)
{
m_pRunningScene->onEnter();
m_pRunningScene->onEnterTransitionDidFinish();
}
}
void CCDirector::pause(void)
{
if (m_bPaused)
{
return;
}
m_dOldAnimationInterval = m_dAnimationInterval;
// when paused, don't consume CPU
setAnimationInterval(1 / 4.0);
m_bPaused = true;
}
void CCDirector::resume(void)
{
if (! m_bPaused)
{
return;
}
setAnimationInterval(m_dOldAnimationInterval);
if (CCTime::gettimeofdayCocos2d(m_pLastUpdate, NULL) != 0)
{
CCLOG("cocos2d: Director: Error in gettimeofday");
}
m_bPaused = false;
m_fDeltaTime = 0;
}
void CCDirector::startAnimation(void)
{
CCLOG("cocos2d: Director#startAnimation. Overrride me");
assert(0);
}
void CCDirector::stopAnimation(void)
{
CCLOG("cocos2d: Director#stopAnimation. Overrride me");
assert(0);
}
void CCDirector::mainLoop(void)
{
CCLOG("cocos2d: Director#preMainLoop. Overrride me");
assert(0);
}
#if CC_DIRECTOR_FAST_FPS
// display the FPS using a LabelAtlas
// updates the FPS every frame
void CCDirector::showFPS(void)
{
sprintf(m_pszFPS, "%.1f", m_fFrameRate);
m_pFPSLabel->setString(m_pszFPS);
m_pFPSLabel->draw();
}
#endif // CC_DIRECTOR_FAST_FPS
void CCDirector::calculateFramerateDeltaTime(void)
{
struct cc_timeval now;
if (CCTime::gettimeofdayCocos2d(&now, NULL) != 0)
{
CCLOG("error in gettimeofday");
m_fComputeFrameRateDeltaTime = 0;
return;
}
m_fComputeFrameRateDeltaTime = (now.tv_sec - m_pLastComputeFrameRate->tv_sec) + (now.tv_usec - m_pLastComputeFrameRate->tv_usec) / 1000000.0f;
m_fComputeFrameRateDeltaTime = MAX(0, m_fComputeFrameRateDeltaTime);
*m_pLastComputeFrameRate = now;
}
void CCDirector::computeFrameRate()
{
static bool bInvoked = true;
// compute delta time
calculateFramerateDeltaTime();
// only add frames if the director really draw the scene
if (bInvoked)
{
m_nFrames++;
}
m_fAccumDt += m_fComputeFrameRateDeltaTime;
if (m_fAccumDt > CC_DIRECTOR_FPS_INTERVAL)
{
m_fFrameRate = m_nFrames / m_fAccumDt;
if (m_fFrameRate > m_fExpectedFrameRate)
{
bInvoked = false;
}
else
{
m_nFrames = 0;
m_fAccumDt = 0;
bInvoked = true;
}
}
}
void CCDirector::showProfilers()
{
#if CC_ENABLE_PROFILERS
m_fAccumDtForProfiler += m_fDeltaTime;
if (m_fAccumDtForProfiler > 1.0f)
{
m_fAccumDtForProfiler = 0;
CCProfiler::sharedProfiler()->displayTimers();
}
#endif
}
/***************************************************
* mobile platforms specific functions
**************************************************/
// is the view currently attached
bool CCDirector::isOpenGLAttached(void)
{
assert(false);
return false;
}
void CCDirector::updateContentScaleFactor()
{
assert(0);
}
// detach or attach to a view or a window
bool CCDirector::detach(void)
{
assert(false);
return false;
}
void CCDirector::setDepthBufferFormat(tDepthBufferFormat kDepthBufferFormat)
{
assert(false);
}
void CCDirector::setPixelFormat(tPixelFormat kPixelFormat)
{
assert(false);
}
tPixelFormat CCDirector::getPiexFormat(void)
{
assert(false);
return m_ePixelFormat;
}
bool CCDirector::setDirectorType(ccDirectorType obDirectorType)
{
// we only support CCDisplayLinkDirector
CCDirector::sharedDirector();
return true;
}
bool CCDirector::enableRetinaDisplay(bool enabled)
{
assert(false);
return false;
}
CGFloat CCDirector::getContentScaleFactor(void)
{
assert(false);
return m_fContentScaleFactor;
}
void CCDirector::setContentScaleFactor(CGFloat scaleFactor)
{
assert(false);
}
void CCDirector::applyOrientation(void)
{
assert(false);
}
ccDeviceOrientation CCDirector::getDeviceOrientation(void)
{
assert(false);
return m_eDeviceOrientation;
}
void CCDirector::setDeviceOrientation(ccDeviceOrientation kDeviceOrientation)
{
assert(false);
}
/***************************************************
* PC platforms specific functions, such as mac
**************************************************/
CGPoint CCDirector::convertEventToGL(NSEvent *event);
{
///@todo NSEvent have not implemented
return CGPointZero;
}
bool CCDirector::isFullScreen(void)
{
return m_bIsFullScreen;
}
void CCDirector::setResizeMode(int resizeMode)
{
assert("not supported.");
}
int CCDirector::getResizeMode(void);
{
assert("not supported.");
return -1;
}
void CCDirector::setFullScreen(bool fullscreen)
{
// Mac OS X 10.6 and later offer a simplified mechanism to create full-screen contexts
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
if( m_bIsFullScreen != fullscreen )
{
m_bIsFullScreen = fullscreen;
if( fullscreen )
{
// create the fullscreen view/window
NSRect mainDisplayRect, viewRect;
// Create a screen-sized window on the display you want to take over
// Note, mainDisplayRect has a non-zero origin if the key window is on a secondary display
mainDisplayRect = [[NSScreen mainScreen] frame];
m_pFullScreenWindow = [[NSWindow alloc] initWithContentRect:mainDisplayRect
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:YES];
// Set the window level to be above the menu bar
[m_pFullScreenWindow setLevel:NSMainMenuWindowLevel+1];
// Perform any other window configuration you desire
[m_pFullScreenWindow setOpaque:YES];
[m_pFullScreenWindow setHidesOnDeactivate:YES];
// Create a view with a double-buffered OpenGL context and attach it to the window
// By specifying the non-fullscreen context as the shareContext, we automatically inherit the OpenGL objects (textures, etc) it has defined
viewRect = NSMakeRect(0.0, 0.0, mainDisplayRect.size.width, mainDisplayRect.size.height);
m_pFullScreenGLView = [[MacGLView alloc] initWithFrame:viewRect shareContext:[m_pobOpenGLView openGLContext]];
[m_pFullScreenWindow setContentView:m_pFullScreenGLView];
// Show the window
[m_pFullScreenWindow makeKeyAndOrderFront:self];
[self setOpenGLView:fullScreenGLView_];
}
else
{
[m_pFullScreenWindow release];
[m_pFullScreenGLView release];
m_pFullScreenWindow = nil;
m_pFullScreenGLView = nil;
[[m_pFullScreenGLView openGLContext] makeCurrentContext];
setOpenGLView(m_pFullScreenGLView);
}
[m_pobOpenGLView setNeedsDisplay:YES];
}
#else
#error Full screen is not supported for Mac OS 10.5 or older yet
#error If you don't want FullScreen support, you can safely remove these 2 lines
#endif
}
CGPoint CCDirector::convertToLogicalCoordinates(CGPoint coordinates)
{
CGPoint ret;
if( m_nResizeMode == kCCDirectorResize_NoScale )
{
ret = coordinates;
}
else
{
float x_diff = m_originalWinSize.width / (m_obWinSizeInPixels.width - m_winOffset.x * 2);
float y_diff = m_originalWinSize.height / (m_obWinSizeInPixels.height - m_winOffset.y * 2);
float adjust_x = (m_obWinSizeInPixels.width * x_diff - m_originalWinSize.width ) / 2;
float adjust_y = (m_obWinSizeInPixels.height * y_diff - m_originalWinSize.height ) / 2;
ret = CGPointMake( (x_diff * coordinates.x) - adjust_x, ( y_diff * coordinates.y ) - adjust_y );
}
return ret;
}
/***************************************************
* implementation of DisplayLinkDirector
**************************************************/
// should we afford 4 types of director ??
// I think DisplayLinkDirector is enough
// so we now only support DisplayLinkDirector
void CCDisplayLinkDirector::startAnimation(void)
{
if (CCTime::gettimeofdayCocos2d(m_pLastUpdate, NULL) != 0)
{
CCLOG("cocos2d: DisplayLinkDirector: Error on gettimeofday");
}
m_bInvalid = false;
[[CCDirectorDisplayLinkMacWrapper sharedDisplayLinkMacWrapper] startAnimation];
}
void CCDisplayLinkDirector::mainLoop(void)
{
if (! m_bInvalid)
{
// compute frame rate
computeFrameRate();
// control frame rate
if (m_fFrameRate <= m_fExpectedFrameRate)
{
drawScene();
// release the objects
NSPoolManager::getInstance()->pop();
}
}
}
void CCDisplayLinkDirector::stopAnimation(void)
{
m_bInvalid = true;
[[CCDirectorDisplayLinkMacWrapper sharedDisplayLinkMacWrapper] stopAnimation];
}
void CCDisplayLinkDirector::setAnimationInterval(double dValue)
{
m_dAnimationInterval = dValue;
m_fExpectedFrameRate = (ccTime)(1 / m_dAnimationInterval);
if (! m_bInvalid)
{
stopAnimation();
startAnimation();
}
}
} //namespace cocos2d

View File

@ -0,0 +1,233 @@
/*
* cocos2d for iPhone: http://www.cocos2d-iphone.org
*
* Copyright (c) 2010 Ricardo Quesada
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
// Only compile this code on Mac. These files should not be included on your iOS project.
// But in case they are included, it won't be compiled.
#import <Availability.h>
#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
#import <Cocoa/Cocoa.h>
#import "MacGLView.h"
#import "../../Support/uthash.h" // hack: uthash needs to be imported before utlist to prevent warning
#import "../../Support/utlist.h"
#import "../../ccConfig.h"
#pragma mark -
#pragma mark CCMouseEventDelegate
/** CCMouseEventDelegate protocol.
Implement it in your node to receive any of mouse events
*/
@protocol CCMouseEventDelegate <NSObject>
@optional
//
// left
//
/** called when the "mouseDown" event is received.
Return YES to avoid propagating the event to other delegates.
*/
-(BOOL) ccMouseDown:(NSEvent*)event;
/** called when the "mouseDragged" event is received.
Return YES to avoid propagating the event to other delegates.
*/
-(BOOL) ccMouseDragged:(NSEvent*)event;
/** called when the "mouseMoved" event is received.
Return YES to avoid propagating the event to other delegates.
By default, "mouseMoved" is disabled. To enable it, send the "setAcceptsMouseMovedEvents:YES" message to the main window.
*/
-(BOOL) ccMouseMoved:(NSEvent*)event;
/** called when the "mouseUp" event is received.
Return YES to avoid propagating the event to other delegates.
*/
-(BOOL) ccMouseUp:(NSEvent*)event;
//
// right
//
/** called when the "rightMouseDown" event is received.
Return YES to avoid propagating the event to other delegates.
*/
-(BOOL) ccRightMouseDown:(NSEvent*)event;
/** called when the "rightMouseDragged" event is received.
Return YES to avoid propagating the event to other delegates.
*/
-(BOOL) ccRightMouseDragged:(NSEvent*)event;
/** called when the "rightMouseUp" event is received.
Return YES to avoid propagating the event to other delegates.
*/
-(BOOL) ccRightMouseUp:(NSEvent*)event;
//
// other
//
/** called when the "otherMouseDown" event is received.
Return YES to avoid propagating the event to other delegates.
*/
-(BOOL) ccOtherMouseDown:(NSEvent*)event;
/** called when the "otherMouseDragged" event is received.
Return YES to avoid propagating the event to other delegates.
*/
-(BOOL) ccOtherMouseDragged:(NSEvent*)event;
/** called when the "otherMouseUp" event is received.
Return YES to avoid propagating the event to other delegates.
*/
-(BOOL) ccOtherMouseUp:(NSEvent*)event;
//
// scroll wheel
//
/** called when the "scrollWheel" event is received.
Return YES to avoid propagating the event to other delegates.
*/
- (BOOL)ccScrollWheel:(NSEvent *)theEvent;
//
// enter / exit
//
/** called when the "mouseEntered" event is received.
Return YES to avoid propagating the event to other delegates.
*/
- (void)ccMouseEntered:(NSEvent *)theEvent;
/** called when the "mouseExited" event is received.
Return YES to avoid propagating the event to other delegates.
*/
- (void)ccMouseExited:(NSEvent *)theEvent;
@end
#pragma mark -
#pragma mark CCKeyboardEventDelegate
/** CCKeyboardEventDelegate protocol.
Implement it in your node to receive any of keyboard events
*/
@protocol CCKeyboardEventDelegate <NSObject>
@optional
/** called when the "keyUp" event is received.
Return YES to avoid propagating the event to other delegates.
*/
-(BOOL) ccKeyUp:(NSEvent*)event;
/** called when the "keyDown" event is received.
Return YES to avoid propagating the event to other delegates.
*/
-(BOOL) ccKeyDown:(NSEvent*)event;
/** called when the "flagsChanged" event is received.
Return YES to avoid propagating the event to other delegates.
*/
-(BOOL) ccFlagsChanged:(NSEvent*)event;
@end
#pragma mark -
#pragma mark CCEventDispatcher
struct _listEntry;
/** CCEventDispatcher
This is object is responsible for dispatching the events:
- Mouse events
- Keyboard events
- Touch events
Only available on Mac
*/
@interface CCEventDispatcher : NSObject <MacEventDelegate> {
BOOL dispatchEvents_;
struct _listEntry *keyboardDelegates_;
struct _listEntry *mouseDelegates_;
}
@property (nonatomic, readwrite) BOOL dispatchEvents;
/** CCEventDispatcher singleton */
+(CCEventDispatcher*) sharedDispatcher;
#pragma mark CCEventDispatcher - Mouse
/** Adds a mouse delegate to the dispatcher's list.
Delegates with a lower priority value will be called before higher priority values.
All the events will be propgated to all the delegates, unless the one delegate returns YES.
IMPORTANT: The delegate will be retained.
*/
-(void) addMouseDelegate:(id<CCMouseEventDelegate>) delegate priority:(NSInteger)priority;
/** removes a mouse delegate */
-(void) removeMouseDelegate:(id) delegate;
/** Removes all mouse delegates, releasing all the delegates */
-(void) removeAllMouseDelegates;
#pragma mark CCEventDispatcher - Keyboard
/** Adds a Keyboard delegate to the dispatcher's list.
Delegates with a lower priority value will be called before higher priority values.
All the events will be propgated to all the delegates, unless the one delegate returns YES.
IMPORTANT: The delegate will be retained.
*/
-(void) addKeyboardDelegate:(id<CCKeyboardEventDelegate>) delegate priority:(NSInteger)priority;
/** removes a mouse delegate */
-(void) removeKeyboardDelegate:(id) delegate;
/** Removes all mouse delegates, releasing all the delegates */
-(void) removeAllKeyboardDelegates;
#pragma mark CCEventDispatcher - Touches
// XXX
#pragma mark CCEventDispatcher - Dispatch Events
#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
-(void) dispatchQueuedEvents;
#endif
@end
#endif // __MAC_OS_X_VERSION_MAX_ALLOWED

View File

@ -0,0 +1,578 @@
/*
* cocos2d for iPhone: http://www.cocos2d-iphone.org
*
* Copyright (c) 2010 Ricardo Quesada
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
// Only compile this code on Mac. These files should not be included on your iOS project.
// But in case they are included, it won't be compiled.
#import <Availability.h>
#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
#import "CCEventDispatcher.h"
#import "../../ccConfig.h"
static CCEventDispatcher *sharedDispatcher = nil;
enum {
// mouse
kCCImplementsMouseDown = 1 << 0,
kCCImplementsMouseMoved = 1 << 1,
kCCImplementsMouseDragged = 1 << 2,
kCCImplementsMouseUp = 1 << 3,
kCCImplementsRightMouseDown = 1 << 4,
kCCImplementsRightMouseDragged = 1 << 5,
kCCImplementsRightMouseUp = 1 << 6,
kCCImplementsOtherMouseDown = 1 << 7,
kCCImplementsOtherMouseDragged = 1 << 8,
kCCImplementsOtherMouseUp = 1 << 9,
kCCImplementsScrollWheel = 1 << 10,
kCCImplementsMouseEntered = 1 << 11,
kCCImplementsMouseExited = 1 << 12,
// keyboard
kCCImplementsKeyUp = 1 << 0,
kCCImplementsKeyDown = 1 << 1,
kCCImplementsFlagsChanged = 1 << 2,
};
typedef struct _listEntry
{
struct _listEntry *prev, *next;
id delegate;
NSInteger priority;
NSUInteger flags;
} tListEntry;
#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
#define QUEUE_EVENT_MAX 128
struct _eventQueue {
SEL selector;
NSEvent *event;
};
static struct _eventQueue eventQueue[QUEUE_EVENT_MAX];
static int eventQueueCount;
#endif // CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
@implementation CCEventDispatcher
@synthesize dispatchEvents=dispatchEvents_;
+(CCEventDispatcher*) sharedDispatcher
{
@synchronized(self) {
if (sharedDispatcher == nil)
sharedDispatcher = [[self alloc] init]; // assignment not done here
}
return sharedDispatcher;
}
+(id) allocWithZone:(NSZone *)zone
{
@synchronized(self) {
NSAssert(sharedDispatcher == nil, @"Attempted to allocate a second instance of a singleton.");
return [super allocWithZone:zone];
}
return nil; // on subsequent allocation attempts return nil
}
-(id) init
{
if( (self = [super init]) )
{
// events enabled by default
dispatchEvents_ = YES;
// delegates
keyboardDelegates_ = NULL;
mouseDelegates_ = NULL;
#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
eventQueueCount = 0;
#endif
}
return self;
}
- (void) dealloc
{
[super dealloc];
}
#pragma mark CCEventDispatcher - add / remove delegates
-(void) addDelegate:(id)delegate priority:(NSInteger)priority flags:(NSUInteger)flags list:(tListEntry**)list
{
tListEntry *listElement = malloc( sizeof(*listElement) );
listElement->delegate = [delegate retain];
listElement->priority = priority;
listElement->flags = flags;
listElement->next = listElement->prev = NULL;
// empty list ?
if( ! *list ) {
DL_APPEND( *list, listElement );
} else {
BOOL added = NO;
for( tListEntry *elem = *list; elem ; elem = elem->next ) {
if( priority < elem->priority ) {
if( elem == *list )
DL_PREPEND(*list, listElement);
else {
listElement->next = elem;
listElement->prev = elem->prev;
elem->prev->next = listElement;
elem->prev = listElement;
}
added = YES;
break;
}
}
// Not added? priority has the higher value. Append it.
if( !added )
DL_APPEND(*list, listElement);
}
}
-(void) removeDelegate:(id)delegate fromList:(tListEntry**)list
{
tListEntry *entry, *tmp;
// updates with priority < 0
DL_FOREACH_SAFE( *list, entry, tmp ) {
if( entry->delegate == delegate ) {
DL_DELETE( *list, entry );
[delegate release];
free(entry);
break;
}
}
}
-(void) removeAllDelegatesFromList:(tListEntry**)list
{
tListEntry *entry, *tmp;
DL_FOREACH_SAFE( *list, entry, tmp ) {
DL_DELETE( *list, entry );
free(entry);
}
}
-(void) addMouseDelegate:(id<CCMouseEventDelegate>) delegate priority:(NSInteger)priority
{
NSUInteger flags = 0;
flags |= ( [delegate respondsToSelector:@selector(ccMouseDown:)] ? kCCImplementsMouseDown : 0 );
flags |= ( [delegate respondsToSelector:@selector(ccMouseDragged:)] ? kCCImplementsMouseDragged : 0 );
flags |= ( [delegate respondsToSelector:@selector(ccMouseMoved:)] ? kCCImplementsMouseMoved : 0 );
flags |= ( [delegate respondsToSelector:@selector(ccMouseUp:)] ? kCCImplementsMouseUp : 0 );
flags |= ( [delegate respondsToSelector:@selector(ccRightMouseDown:)] ? kCCImplementsRightMouseDown : 0 );
flags |= ( [delegate respondsToSelector:@selector(ccRightMouseDragged:)] ? kCCImplementsRightMouseDragged : 0 );
flags |= ( [delegate respondsToSelector:@selector(ccRightMouseUp:)] ? kCCImplementsRightMouseUp : 0 );
flags |= ( [delegate respondsToSelector:@selector(ccOtherMouseDown:)] ? kCCImplementsOtherMouseDown : 0 );
flags |= ( [delegate respondsToSelector:@selector(ccOtherMouseDragged:)] ? kCCImplementsOtherMouseDragged : 0 );
flags |= ( [delegate respondsToSelector:@selector(ccOtherMouseUp:)] ? kCCImplementsOtherMouseUp : 0 );
flags |= ( [delegate respondsToSelector:@selector(ccMouseEntered:)] ? kCCImplementsMouseEntered : 0 );
flags |= ( [delegate respondsToSelector:@selector(ccMouseExited:)] ? kCCImplementsMouseExited : 0 );
flags |= ( [delegate respondsToSelector:@selector(ccScrollWheel:)] ? kCCImplementsScrollWheel : 0 );
[self addDelegate:delegate priority:priority flags:flags list:&mouseDelegates_];
}
-(void) removeMouseDelegate:(id) delegate
{
[self removeDelegate:delegate fromList:&mouseDelegates_];
}
-(void) removeAllMouseDelegates
{
[self removeAllDelegatesFromList:&mouseDelegates_];
}
-(void) addKeyboardDelegate:(id<CCKeyboardEventDelegate>) delegate priority:(NSInteger)priority
{
NSUInteger flags = 0;
flags |= ( [delegate respondsToSelector:@selector(ccKeyUp:)] ? kCCImplementsKeyUp : 0 );
flags |= ( [delegate respondsToSelector:@selector(ccKeyDown:)] ? kCCImplementsKeyDown : 0 );
flags |= ( [delegate respondsToSelector:@selector(ccFlagsChanged:)] ? kCCImplementsFlagsChanged : 0 );
[self addDelegate:delegate priority:priority flags:flags list:&keyboardDelegates_];
}
-(void) removeKeyboardDelegate:(id) delegate
{
[self removeDelegate:delegate fromList:&keyboardDelegates_];
}
-(void) removeAllKeyboardDelegates
{
[self removeAllDelegatesFromList:&keyboardDelegates_];
}
#pragma mark CCEventDispatcher - Mouse events
//
// Mouse events
//
//
// Left
//
- (void)mouseDown:(NSEvent *)event
{
if( dispatchEvents_ ) {
tListEntry *entry, *tmp;
DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
if ( entry->flags & kCCImplementsMouseDown ) {
void *swallows = [entry->delegate performSelector:@selector(ccMouseDown:) withObject:event];
if( swallows )
break;
}
}
}
}
- (void)mouseMoved:(NSEvent *)event
{
if( dispatchEvents_ ) {
tListEntry *entry, *tmp;
DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
if ( entry->flags & kCCImplementsMouseMoved ) {
void *swallows = [entry->delegate performSelector:@selector(ccMouseMoved:) withObject:event];
if( swallows )
break;
}
}
}
}
- (void)mouseDragged:(NSEvent *)event
{
if( dispatchEvents_ ) {
tListEntry *entry, *tmp;
DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
if ( entry->flags & kCCImplementsMouseDragged ) {
void *swallows = [entry->delegate performSelector:@selector(ccMouseDragged:) withObject:event];
if( swallows )
break;
}
}
}
}
- (void)mouseUp:(NSEvent *)event
{
if( dispatchEvents_ ) {
tListEntry *entry, *tmp;
DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
if ( entry->flags & kCCImplementsMouseUp ) {
void *swallows = [entry->delegate performSelector:@selector(ccMouseUp:) withObject:event];
if( swallows )
break;
}
}
}
}
//
// Mouse Right
//
- (void)rightMouseDown:(NSEvent *)event
{
if( dispatchEvents_ ) {
tListEntry *entry, *tmp;
DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
if ( entry->flags & kCCImplementsRightMouseDown ) {
void *swallows = [entry->delegate performSelector:@selector(ccRightMouseDown:) withObject:event];
if( swallows )
break;
}
}
}
}
- (void)rightMouseDragged:(NSEvent *)event
{
if( dispatchEvents_ ) {
tListEntry *entry, *tmp;
DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
if ( entry->flags & kCCImplementsRightMouseDragged ) {
void *swallows = [entry->delegate performSelector:@selector(ccRightMouseDragged:) withObject:event];
if( swallows )
break;
}
}
}
}
- (void)rightMouseUp:(NSEvent *)event
{
if( dispatchEvents_ ) {
tListEntry *entry, *tmp;
DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
if ( entry->flags & kCCImplementsRightMouseUp ) {
void *swallows = [entry->delegate performSelector:@selector(ccRightMouseUp:) withObject:event];
if( swallows )
break;
}
}
}
}
//
// Mouse Other
//
- (void)otherMouseDown:(NSEvent *)event
{
if( dispatchEvents_ ) {
tListEntry *entry, *tmp;
DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
if ( entry->flags & kCCImplementsOtherMouseDown ) {
void *swallows = [entry->delegate performSelector:@selector(ccOtherMouseDown:) withObject:event];
if( swallows )
break;
}
}
}
}
- (void)otherMouseDragged:(NSEvent *)event
{
if( dispatchEvents_ ) {
tListEntry *entry, *tmp;
DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
if ( entry->flags & kCCImplementsOtherMouseDragged ) {
void *swallows = [entry->delegate performSelector:@selector(ccOtherMouseDragged:) withObject:event];
if( swallows )
break;
}
}
}
}
- (void)otherMouseUp:(NSEvent *)event
{
if( dispatchEvents_ ) {
tListEntry *entry, *tmp;
DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
if ( entry->flags & kCCImplementsOtherMouseUp ) {
void *swallows = [entry->delegate performSelector:@selector(ccOtherMouseUp:) withObject:event];
if( swallows )
break;
}
}
}
}
//
// Scroll Wheel
//
- (void)scrollWheel:(NSEvent *)event
{
if( dispatchEvents_ ) {
tListEntry *entry, *tmp;
DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
if ( entry->flags & kCCImplementsScrollWheel ) {
void *swallows = [entry->delegate performSelector:@selector(ccScrollWheel:) withObject:event];
if( swallows )
break;
}
}
}
}
//
// Mouse enter / exit
- (void)mouseExited:(NSEvent *)event
{
if( dispatchEvents_ ) {
tListEntry *entry, *tmp;
DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
if ( entry->flags & kCCImplementsMouseEntered ) {
void *swallows = [entry->delegate performSelector:@selector(ccMouseEntered:) withObject:event];
if( swallows )
break;
}
}
}
}
- (void)mouseEntered:(NSEvent *)event
{
if( dispatchEvents_ ) {
tListEntry *entry, *tmp;
DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) {
if ( entry->flags & kCCImplementsMouseExited) {
void *swallows = [entry->delegate performSelector:@selector(ccMouseExited:) withObject:event];
if( swallows )
break;
}
}
}
}
#pragma mark CCEventDispatcher - Keyboard events
// Keyboard events
- (void)keyDown:(NSEvent *)event
{
if( dispatchEvents_ ) {
tListEntry *entry, *tmp;
DL_FOREACH_SAFE( keyboardDelegates_, entry, tmp ) {
if ( entry->flags & kCCImplementsKeyDown ) {
void *swallows = [entry->delegate performSelector:@selector(ccKeyDown:) withObject:event];
if( swallows )
break;
}
}
}
}
- (void)keyUp:(NSEvent *)event
{
if( dispatchEvents_ ) {
tListEntry *entry, *tmp;
DL_FOREACH_SAFE( keyboardDelegates_, entry, tmp ) {
if ( entry->flags & kCCImplementsKeyUp ) {
void *swallows = [entry->delegate performSelector:@selector(ccKeyUp:) withObject:event];
if( swallows )
break;
}
}
}
}
- (void)flagsChanged:(NSEvent *)event
{
if( dispatchEvents_ ) {
tListEntry *entry, *tmp;
DL_FOREACH_SAFE( keyboardDelegates_, entry, tmp ) {
if ( entry->flags & kCCImplementsKeyUp ) {
void *swallows = [entry->delegate performSelector:@selector(ccFlagsChanged:) withObject:event];
if( swallows )
break;
}
}
}
}
#pragma mark CCEventDispatcher - Touch events
- (void)touchesBeganWithEvent:(NSEvent *)event
{
if (dispatchEvents_ ) {
NSLog(@"Touch Events: Not supported yet");
}
}
- (void)touchesMovedWithEvent:(NSEvent *)event
{
if (dispatchEvents_ ) {
NSLog(@"Touch Events: Not supported yet");
}
}
- (void)touchesEndedWithEvent:(NSEvent *)event
{
if (dispatchEvents_ ) {
NSLog(@"Touch Events: Not supported yet");
}
}
- (void)touchesCancelledWithEvent:(NSEvent *)event
{
if (dispatchEvents_ ) {
NSLog(@"Touch Events: Not supported yet");
}
}
#pragma mark CCEventDispatcher - queue events
#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
-(void) queueEvent:(NSEvent*)event selector:(SEL)selector
{
NSAssert( eventQueueCount < QUEUE_EVENT_MAX, @"CCEventDispatcher: recompile. Increment QUEUE_EVENT_MAX value");
eventQueue[eventQueueCount].selector = selector;
eventQueue[eventQueueCount].event = [event copy];
eventQueueCount++;
}
-(void) dispatchQueuedEvents
{
for( int i=0; i < eventQueueCount; i++ ) {
SEL sel = eventQueue[i].selector;
NSEvent *event = eventQueue[i].event;
[self performSelector:sel withObject:event];
[event release];
}
eventQueueCount = 0;
}
#endif // CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
@end
#endif // __MAC_OS_X_VERSION_MAX_ALLOWED

View File

@ -0,0 +1,83 @@
/*
* cocos2d for iPhone: http://www.cocos2d-iphone.org
*
* Copyright (c) 2010 Ricardo Quesada
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
// Only compile this code on Mac. These files should not be included on your iOS project.
// But in case they are included, it won't be compiled.
#import <Availability.h>
#import <Cocoa/Cocoa.h>
#import "ccConfig.h"
//PROTOCOLS:
@protocol MacEventDelegate <NSObject>
// Mouse
- (void)mouseDown:(NSEvent *)theEvent;
- (void)mouseUp:(NSEvent *)theEvent;
- (void)mouseMoved:(NSEvent *)theEvent;
- (void)mouseDragged:(NSEvent *)theEvent;
- (void)rightMouseDown:(NSEvent*)event;
- (void)rightMouseDragged:(NSEvent*)event;
- (void)rightMouseUp:(NSEvent*)event;
- (void)otherMouseDown:(NSEvent*)event;
- (void)otherMouseDragged:(NSEvent*)event;
- (void)otherMouseUp:(NSEvent*)event;
- (void)scrollWheel:(NSEvent *)theEvent;
- (void)mouseEntered:(NSEvent *)theEvent;
- (void)mouseExited:(NSEvent *)theEvent;
// Keyboard
- (void)keyDown:(NSEvent *)theEvent;
- (void)keyUp:(NSEvent *)theEvent;
- (void)flagsChanged:(NSEvent *)theEvent;
// Touches
- (void)touchesBeganWithEvent:(NSEvent *)event;
- (void)touchesMovedWithEvent:(NSEvent *)event;
- (void)touchesEndedWithEvent:(NSEvent *)event;
- (void)touchesCancelledWithEvent:(NSEvent *)event;
#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
- (void)queueEvent:(NSEvent*)event selector:(SEL)selector;
#endif
@end
/** MacGLView
Only available for Mac OS X
*/
@interface MacGLView : NSOpenGLView {
id<MacEventDelegate> eventDelegate_;
}
@property (nonatomic, readwrite, assign) id<MacEventDelegate> eventDelegate;
// initializes the MacGLView with a frame rect and an OpenGL context
- (id) initWithFrame:(NSRect)frameRect shareContext:(NSOpenGLContext*)context;
// private
+(void) load_;
@end

View File

@ -0,0 +1,241 @@
/*
* cocos2d for iPhone: http://www.cocos2d-iphone.org
*
* Copyright (c) 2010 Ricardo Quesada
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* Idea of subclassing NSOpenGLView was taken from "TextureUpload" Apple's sample
*/
// Only compile this code on Mac. These files should not be included on your iOS project.
// But in case they are included, it won't be compiled.
#import <Availability.h>
#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
#import "MacGLView.h"
#import <OpenGL/gl.h>
#import "CCDirectorMac.h"
#import "ccConfig.h"
@implementation MacGLView
@synthesize eventDelegate = eventDelegate_;
+(void) load_
{
NSLog(@"%@ loaded", self);
}
- (id) initWithFrame:(NSRect)frameRect
{
self = [self initWithFrame:frameRect shareContext:nil];
return self;
}
- (id) initWithFrame:(NSRect)frameRect shareContext:(NSOpenGLContext*)context
{
NSOpenGLPixelFormatAttribute attribs[] =
{
NSOpenGLPFAAccelerated,
NSOpenGLPFANoRecovery,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFADepthSize, 24,
0
};
NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
if (!pixelFormat)
NSLog(@"No OpenGL pixel format");
if (self = [super initWithFrame:frameRect pixelFormat:[pixelFormat autorelease]]) {
if( context )
[self setOpenGLContext:context];
// Synchronize buffer swaps with vertical refresh rate
GLint swapInt = 1;
[[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
// GLint order = -1;
// [[self openGLContext] setValues:&order forParameter:NSOpenGLCPSurfaceOrder];
// event delegate
eventDelegate_ = nil;
}
return self;
}
- (void) reshape
{
// We draw on a secondary thread through the display link
// When resizing the view, -reshape is called automatically on the main thread
// Add a mutex around to avoid the threads accessing the context simultaneously when resizing
CGLLockContext([[self openGLContext] CGLContextObj]);
NSRect rect = [self bounds];
CCDirector *director = cocos2d::CCDirector::sharedDirector();
director->reshapeProjection(NSSizeToCGSize(rect.size));
// avoid flicker
director->drawScene();
// [self setNeedsDisplay:YES];
CGLUnlockContext([[self openGLContext] CGLContextObj]);
}
- (void) dealloc
{
[super dealloc];
}
#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD
#define DISPATCH_EVENT(__event__, __selector__) [eventDelegate_ queueEvent:__event__ selector:__selector__];
#else
#define DISPATCH_EVENT(__event__, __selector__) \
id obj = eventDelegate_; \
[obj performSelector:__selector__ \
onThread:[[CCDirectorDisplayLinkMacWrapper sharedDisplayLinkMacWrapper] runningThread] \
withObject:__event__ \
waitUntilDone:NO];
#endif
#pragma mark MacGLView - Mouse events
- (void)mouseDown:(NSEvent *)theEvent
{
DISPATCH_EVENT(theEvent, _cmd);
}
- (void)mouseMoved:(NSEvent *)theEvent
{
DISPATCH_EVENT(theEvent, _cmd);
}
- (void)mouseDragged:(NSEvent *)theEvent
{
DISPATCH_EVENT(theEvent, _cmd);
}
- (void)mouseUp:(NSEvent *)theEvent
{
DISPATCH_EVENT(theEvent, _cmd);
}
- (void)rightMouseDown:(NSEvent *)theEvent {
DISPATCH_EVENT(theEvent, _cmd);
}
- (void)rightMouseDragged:(NSEvent *)theEvent {
DISPATCH_EVENT(theEvent, _cmd);
}
- (void)rightMouseUp:(NSEvent *)theEvent {
DISPATCH_EVENT(theEvent, _cmd);
}
- (void)otherMouseDown:(NSEvent *)theEvent {
DISPATCH_EVENT(theEvent, _cmd);
}
- (void)otherMouseDragged:(NSEvent *)theEvent {
DISPATCH_EVENT(theEvent, _cmd);
}
- (void)otherMouseUp:(NSEvent *)theEvent {
DISPATCH_EVENT(theEvent, _cmd);
}
- (void)mouseEntered:(NSEvent *)theEvent {
DISPATCH_EVENT(theEvent, _cmd);
}
- (void)mouseExited:(NSEvent *)theEvent {
DISPATCH_EVENT(theEvent, _cmd);
}
-(void) scrollWheel:(NSEvent *)theEvent {
DISPATCH_EVENT(theEvent, _cmd);
}
#pragma mark MacGLView - Key events
-(BOOL) becomeFirstResponder
{
return YES;
}
-(BOOL) acceptsFirstResponder
{
return YES;
}
-(BOOL) resignFirstResponder
{
return YES;
}
- (void)keyDown:(NSEvent *)theEvent
{
DISPATCH_EVENT(theEvent, _cmd);
}
- (void)keyUp:(NSEvent *)theEvent
{
DISPATCH_EVENT(theEvent, _cmd);
}
- (void)flagsChanged:(NSEvent *)theEvent
{
DISPATCH_EVENT(theEvent, _cmd);
}
#pragma mark MacGLView - Touch events
- (void)touchesBeganWithEvent:(NSEvent *)theEvent
{
DISPATCH_EVENT(theEvent, _cmd);
}
- (void)touchesMovedWithEvent:(NSEvent *)theEvent
{
DISPATCH_EVENT(theEvent, _cmd);
}
- (void)touchesEndedWithEvent:(NSEvent *)theEvent
{
DISPATCH_EVENT(theEvent, _cmd);
}
- (void)touchesCancelledWithEvent:(NSEvent *)theEvent
{
DISPATCH_EVENT(theEvent, _cmd);
}
@end
#endif // __MAC_OS_X_VERSION_MAX_ALLOWED

View File

@ -458,4 +458,15 @@ void CCXEGLView::swapBuffers()
}
}
bool CCXEGLView::canSetContentScaleFactor()
{
// can scale content?
return false;
}
void CCXEGLView::setContentScaleFactor(float contentScaleFactor)
{
// if it supports scaling content, set it
}
} // end of namespace cocos2d

View File

@ -55,6 +55,8 @@ public:
void release();
void setTouchDelegate(EGLTouchDelegate * pDelegate);
void swapBuffers();
bool canSetContentScaleFactor();
void setContentScaleFactor(float contentScaleFactor);
protected:
Boolean OnPenDown(EventType* pEvent, Int32 nIndex);

View File

@ -912,6 +912,10 @@
<Filter
Name="platform"
>
<File
RelativePath="..\platform\CCDirector_mobile.cpp"
>
</File>
<File
RelativePath="..\platform\CCFileUtils_platform.h"
>
@ -1089,10 +1093,6 @@
RelativePath="..\CCConfiguration.h"
>
</File>
<File
RelativePath="..\CCDirector.cpp"
>
</File>
<File
RelativePath="..\CCDrawingPrimitives.cpp"
>

View File

@ -102,7 +102,7 @@ namespace cocos2d
return err;
}
int ZipUtils::ccccInflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out)
int ZipUtils::ccInflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out)
{
unsigned int outLength = 0;
int err = inflateMemory_(in, inLength, out, &outLength);

View File

@ -55,7 +55,7 @@ namespace cocos2d
*
@since v0.8.1
*/
static int ccccInflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out);
static int ccInflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out);
/** inflates a GZip file into memory
*