PageRenderTime 82ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/libs/cocos2d/CCDirector.m

https://bitbucket.org/stavrossk/ipong
Objective C | 594 lines | 392 code | 130 blank | 72 comment | 33 complexity | 9ecf65afe041e32aa111bedcb20f25e0 MD5 | raw file
  1. /*
  2. * cocos2d for iPhone: http://www.cocos2d-iphone.org
  3. *
  4. * Copyright (c) 2008-2010 Ricardo Quesada
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. /* Idea of decoupling Window from Director taken from OC3D project: http://code.google.com/p/oc3d/
  25. */
  26. #import <unistd.h>
  27. #import <Availability.h>
  28. // cocos2d imports
  29. #import "CCDirector.h"
  30. #import "CCScheduler.h"
  31. #import "CCActionManager.h"
  32. #import "CCTextureCache.h"
  33. #import "CCAnimationCache.h"
  34. #import "CCLabelAtlas.h"
  35. #import "ccMacros.h"
  36. #import "CCTransition.h"
  37. #import "CCScene.h"
  38. #import "CCSpriteFrameCache.h"
  39. #import "CCTexture2D.h"
  40. #import "CCLabelBMFont.h"
  41. #import "CCLayer.h"
  42. // support imports
  43. #import "Platforms/CCGL.h"
  44. #import "Platforms/CCNS.h"
  45. #import "Support/OpenGL_Internal.h"
  46. #import "Support/CGPointExtension.h"
  47. #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
  48. #import "Platforms/iOS/CCDirectorIOS.h"
  49. #define CC_DIRECTOR_DEFAULT CCDirectorTimer
  50. #elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
  51. #import "Platforms/Mac/CCDirectorMac.h"
  52. #define CC_DIRECTOR_DEFAULT CCDirectorDisplayLink
  53. #endif
  54. #import "Support/CCProfiling.h"
  55. #define kDefaultFPS 60.0 // 60 frames per second
  56. extern NSString * cocos2dVersion(void);
  57. @interface CCDirector (Private)
  58. -(void) setNextScene;
  59. // shows the FPS in the screen
  60. -(void) showFPS;
  61. // calculates delta time since last time it was called
  62. -(void) calculateDeltaTime;
  63. @end
  64. @implementation CCDirector
  65. @synthesize animationInterval=animationInterval_;
  66. @synthesize runningScene = runningScene_;
  67. @synthesize displayFPS = displayFPS_;
  68. @synthesize nextDeltaTimeZero=nextDeltaTimeZero_;
  69. @synthesize isPaused=isPaused_;
  70. @synthesize sendCleanupToScene=sendCleanupToScene_;
  71. @synthesize runningThread=runningThread_;
  72. @synthesize notificationNode=notificationNode_;
  73. @synthesize projectionDelegate=projectionDelegate_;
  74. //
  75. // singleton stuff
  76. //
  77. static CCDirector *_sharedDirector = nil;
  78. + (CCDirector *)sharedDirector
  79. {
  80. if (!_sharedDirector) {
  81. //
  82. // Default Director is TimerDirector
  83. //
  84. if( [ [CCDirector class] isEqual:[self class]] )
  85. _sharedDirector = [[CC_DIRECTOR_DEFAULT alloc] init];
  86. else
  87. _sharedDirector = [[self alloc] init];
  88. }
  89. return _sharedDirector;
  90. }
  91. +(id)alloc
  92. {
  93. NSAssert(_sharedDirector == nil, @"Attempted to allocate a second instance of a singleton.");
  94. return [super alloc];
  95. }
  96. - (id) init
  97. {
  98. CCLOG(@"cocos2d: %@", cocos2dVersion() );
  99. if( (self=[super init]) ) {
  100. CCLOG(@"cocos2d: Using Director Type:%@", [self class]);
  101. // scenes
  102. runningScene_ = nil;
  103. nextScene_ = nil;
  104. notificationNode_ = nil;
  105. oldAnimationInterval_ = animationInterval_ = 1.0 / kDefaultFPS;
  106. scenesStack_ = [[NSMutableArray alloc] initWithCapacity:10];
  107. // Set default projection (3D)
  108. projection_ = kCCDirectorProjectionDefault;
  109. // projection delegate if "Custom" projection is used
  110. projectionDelegate_ = nil;
  111. // FPS
  112. displayFPS_ = NO;
  113. frames_ = 0;
  114. // paused ?
  115. isPaused_ = NO;
  116. // running thread
  117. runningThread_ = nil;
  118. winSizeInPixels_ = winSizeInPoints_ = CGSizeZero;
  119. }
  120. return self;
  121. }
  122. - (void) dealloc
  123. {
  124. CCLOGINFO(@"cocos2d: deallocing %@", self);
  125. #if CC_DIRECTOR_FAST_FPS
  126. [FPSLabel_ release];
  127. #endif
  128. [runningScene_ release];
  129. [notificationNode_ release];
  130. [scenesStack_ release];
  131. [projectionDelegate_ release];
  132. _sharedDirector = nil;
  133. [super dealloc];
  134. }
  135. -(void) setGLDefaultValues
  136. {
  137. // This method SHOULD be called only after openGLView_ was initialized
  138. NSAssert( openGLView_, @"openGLView_ must be initialized");
  139. [self setAlphaBlending: YES];
  140. [self setDepthTest: YES];
  141. [self setProjection: projection_];
  142. // set other opengl default values
  143. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  144. #if CC_DIRECTOR_FAST_FPS
  145. if (!FPSLabel_) {
  146. CCTexture2DPixelFormat currentFormat = [CCTexture2D defaultAlphaPixelFormat];
  147. [CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA4444];
  148. FPSLabel_ = [[CCLabelAtlas labelWithString:@"00.0" charMapFile:@"fps_images.png" itemWidth:16 itemHeight:24 startCharMap:'.'] retain];
  149. [CCTexture2D setDefaultAlphaPixelFormat:currentFormat];
  150. }
  151. #endif // CC_DIRECTOR_FAST_FPS
  152. }
  153. //
  154. // Draw the Scene
  155. //
  156. - (void) drawScene
  157. {
  158. // Override me
  159. }
  160. -(void) calculateDeltaTime
  161. {
  162. struct timeval now;
  163. if( gettimeofday( &now, NULL) != 0 ) {
  164. CCLOG(@"cocos2d: error in gettimeofday");
  165. dt = 0;
  166. return;
  167. }
  168. // new delta time
  169. if( nextDeltaTimeZero_ ) {
  170. dt = 0;
  171. nextDeltaTimeZero_ = NO;
  172. } else {
  173. dt = (now.tv_sec - lastUpdate_.tv_sec) + (now.tv_usec - lastUpdate_.tv_usec) / 1000000.0f;
  174. dt = MAX(0,dt);
  175. }
  176. lastUpdate_ = now;
  177. }
  178. #pragma mark Director - Memory Helper
  179. -(void) purgeCachedData
  180. {
  181. [CCLabelBMFont purgeCachedData];
  182. [CCTextureCache purgeSharedTextureCache];
  183. }
  184. #pragma mark Director - Scene OpenGL Helper
  185. -(ccDirectorProjection) projection
  186. {
  187. return projection_;
  188. }
  189. -(float) getZEye
  190. {
  191. return ( winSizeInPixels_.height / 1.1566f );
  192. }
  193. -(void) setProjection:(ccDirectorProjection)projection
  194. {
  195. CGSize size = winSizeInPixels_;
  196. // XXX: quick & dirty hack to obtain the content scale factor
  197. int scale = winSizeInPixels_.height / winSizeInPoints_.height;
  198. switch (projection) {
  199. case kCCDirectorProjection2D:
  200. glViewport(0, 0, size.width, size.height);
  201. glMatrixMode(GL_PROJECTION);
  202. glLoadIdentity();
  203. ccglOrtho(0, size.width, 0, size.height, -1024 * scale, 1024 * scale);
  204. glMatrixMode(GL_MODELVIEW);
  205. glLoadIdentity();
  206. break;
  207. case kCCDirectorProjection3D:
  208. glViewport(0, 0, size.width, size.height);
  209. glMatrixMode(GL_PROJECTION);
  210. glLoadIdentity();
  211. gluPerspective(60, (GLfloat)size.width/size.height, 0.5f, 1500.0f);
  212. glMatrixMode(GL_MODELVIEW);
  213. glLoadIdentity();
  214. gluLookAt( size.width/2, size.height/2, [self getZEye],
  215. size.width/2, size.height/2, 0,
  216. 0.0f, 1.0f, 0.0f);
  217. break;
  218. case kCCDirectorProjectionCustom:
  219. if( projectionDelegate_ )
  220. [projectionDelegate_ updateProjection];
  221. break;
  222. default:
  223. CCLOG(@"cocos2d: Director: unrecognized projecgtion");
  224. break;
  225. }
  226. projection_ = projection;
  227. }
  228. - (void) setAlphaBlending: (BOOL) on
  229. {
  230. if (on) {
  231. glEnable(GL_BLEND);
  232. glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
  233. } else
  234. glDisable(GL_BLEND);
  235. }
  236. - (void) setDepthTest: (BOOL) on
  237. {
  238. if (on) {
  239. ccglClearDepth(1.0f);
  240. glEnable(GL_DEPTH_TEST);
  241. glDepthFunc(GL_LEQUAL);
  242. glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  243. } else
  244. glDisable( GL_DEPTH_TEST );
  245. }
  246. #pragma mark Director Integration with a UIKit view
  247. -(CC_GLVIEW*) openGLView
  248. {
  249. return openGLView_;
  250. }
  251. -(void) setOpenGLView:(CC_GLVIEW *)view
  252. {
  253. NSAssert( view, @"OpenGLView must be non-nil");
  254. if( view != openGLView_ ) {
  255. [openGLView_ release];
  256. openGLView_ = [view retain];
  257. // set size
  258. winSizeInPixels_ = winSizeInPoints_ = CCNSSizeToCGSize( [view bounds].size );
  259. [self setGLDefaultValues];
  260. }
  261. }
  262. #pragma mark Director Scene Landscape
  263. -(CGPoint)convertToGL:(CGPoint)uiPoint
  264. {
  265. CCLOG(@"CCDirector#convertToGL: OVERRIDE ME.");
  266. return CGPointZero;
  267. }
  268. -(CGPoint)convertToUI:(CGPoint)glPoint
  269. {
  270. CCLOG(@"CCDirector#convertToUI: OVERRIDE ME.");
  271. return CGPointZero;
  272. }
  273. -(CGSize)winSize
  274. {
  275. return winSizeInPoints_;
  276. }
  277. -(CGSize)winSizeInPixels
  278. {
  279. return winSizeInPixels_;
  280. }
  281. -(CGSize)displaySizeInPixels
  282. {
  283. return winSizeInPixels_;
  284. }
  285. -(void) reshapeProjection:(CGSize)newWindowSize
  286. {
  287. winSizeInPixels_ = winSizeInPoints_ = newWindowSize;
  288. [self setProjection:projection_];
  289. }
  290. #pragma mark Director Scene Management
  291. - (void)runWithScene:(CCScene*) scene
  292. {
  293. NSAssert( scene != nil, @"Argument must be non-nil");
  294. NSAssert( runningScene_ == nil, @"You can't run an scene if another Scene is running. Use replaceScene or pushScene instead");
  295. [self pushScene:scene];
  296. [self startAnimation];
  297. }
  298. -(void) replaceScene: (CCScene*) scene
  299. {
  300. NSAssert( scene != nil, @"Argument must be non-nil");
  301. NSUInteger index = [scenesStack_ count];
  302. sendCleanupToScene_ = YES;
  303. [scenesStack_ replaceObjectAtIndex:index-1 withObject:scene];
  304. nextScene_ = scene; // nextScene_ is a weak ref
  305. }
  306. - (void) pushScene: (CCScene*) scene
  307. {
  308. NSAssert( scene != nil, @"Argument must be non-nil");
  309. sendCleanupToScene_ = NO;
  310. [scenesStack_ addObject: scene];
  311. nextScene_ = scene; // nextScene_ is a weak ref
  312. }
  313. -(void) popScene
  314. {
  315. NSAssert( runningScene_ != nil, @"A running Scene is needed");
  316. [scenesStack_ removeLastObject];
  317. NSUInteger c = [scenesStack_ count];
  318. if( c == 0 ) {
  319. [self end];
  320. } else {
  321. nextScene_ = [scenesStack_ objectAtIndex:c-1];
  322. }
  323. }
  324. -(void) end
  325. {
  326. [runningScene_ onExit];
  327. [runningScene_ cleanup];
  328. [runningScene_ release];
  329. runningScene_ = nil;
  330. nextScene_ = nil;
  331. // remove all objects, but don't release it.
  332. // runWithScene might be executed after 'end'.
  333. [scenesStack_ removeAllObjects];
  334. [self stopAnimation];
  335. #if CC_DIRECTOR_FAST_FPS
  336. [FPSLabel_ release];
  337. FPSLabel_ = nil;
  338. #endif
  339. [projectionDelegate_ release];
  340. projectionDelegate_ = nil;
  341. // Purge bitmap cache
  342. [CCLabelBMFont purgeCachedData];
  343. // Purge all managers
  344. [CCAnimationCache purgeSharedAnimationCache];
  345. [CCSpriteFrameCache purgeSharedSpriteFrameCache];
  346. [CCScheduler purgeSharedScheduler];
  347. [CCActionManager purgeSharedManager];
  348. [CCTextureCache purgeSharedTextureCache];
  349. // OpenGL view
  350. // Since the director doesn't attach the openglview to the window
  351. // it shouldn't remove it from the window too.
  352. // [openGLView_ removeFromSuperview];
  353. [openGLView_ release];
  354. openGLView_ = nil;
  355. }
  356. -(void) setNextScene
  357. {
  358. Class transClass = [CCTransitionScene class];
  359. BOOL runningIsTransition = [runningScene_ isKindOfClass:transClass];
  360. BOOL newIsTransition = [nextScene_ isKindOfClass:transClass];
  361. // If it is not a transition, call onExit/cleanup
  362. if( ! newIsTransition ) {
  363. [runningScene_ onExit];
  364. // issue #709. the root node (scene) should receive the cleanup message too
  365. // otherwise it might be leaked.
  366. if( sendCleanupToScene_)
  367. [runningScene_ cleanup];
  368. }
  369. [runningScene_ release];
  370. runningScene_ = [nextScene_ retain];
  371. nextScene_ = nil;
  372. if( ! runningIsTransition ) {
  373. [runningScene_ onEnter];
  374. [runningScene_ onEnterTransitionDidFinish];
  375. }
  376. }
  377. -(void) pause
  378. {
  379. if( isPaused_ )
  380. return;
  381. oldAnimationInterval_ = animationInterval_;
  382. // when paused, don't consume CPU
  383. [self setAnimationInterval:1/4.0];
  384. isPaused_ = YES;
  385. }
  386. -(void) resume
  387. {
  388. if( ! isPaused_ )
  389. return;
  390. [self setAnimationInterval: oldAnimationInterval_];
  391. if( gettimeofday( &lastUpdate_, NULL) != 0 ) {
  392. CCLOG(@"cocos2d: Director: Error in gettimeofday");
  393. }
  394. isPaused_ = NO;
  395. dt = 0;
  396. }
  397. - (void)startAnimation
  398. {
  399. CCLOG(@"cocos2d: Director#startAnimation. Override me");
  400. }
  401. - (void)stopAnimation
  402. {
  403. CCLOG(@"cocos2d: Director#stopAnimation. Override me");
  404. }
  405. - (void)setAnimationInterval:(NSTimeInterval)interval
  406. {
  407. CCLOG(@"cocos2d: Director#setAnimationInterval. Override me");
  408. }
  409. #if CC_DIRECTOR_FAST_FPS
  410. // display the FPS using a LabelAtlas
  411. // updates the FPS every frame
  412. -(void) showFPS
  413. {
  414. frames_++;
  415. accumDt_ += dt;
  416. if ( accumDt_ > CC_DIRECTOR_FPS_INTERVAL) {
  417. frameRate_ = frames_/accumDt_;
  418. frames_ = 0;
  419. accumDt_ = 0;
  420. // sprintf(format,"%.1f",frameRate);
  421. // [FPSLabel setCString:format];
  422. NSString *str = [[NSString alloc] initWithFormat:@"%.1f", frameRate_];
  423. [FPSLabel_ setString:str];
  424. [str release];
  425. }
  426. [FPSLabel_ draw];
  427. }
  428. #else
  429. // display the FPS using a manually generated Texture (very slow)
  430. // updates the FPS 3 times per second aprox.
  431. -(void) showFPS
  432. {
  433. frames_++;
  434. accumDt_ += dt;
  435. if ( accumDt_ > CC_DIRECTOR_FPS_INTERVAL) {
  436. frameRate_ = frames_/accumDt_;
  437. frames_ = 0;
  438. accumDt_ = 0;
  439. }
  440. NSString *str = [NSString stringWithFormat:@"%.2f",frameRate_];
  441. CCTexture2D *texture = [[CCTexture2D alloc] initWithString:str dimensions:CGSizeMake(100,30) alignment:UITextAlignmentLeft fontName:@"Arial" fontSize:24];
  442. // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
  443. // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY
  444. // Unneeded states: GL_COLOR_ARRAY
  445. glDisableClientState(GL_COLOR_ARRAY);
  446. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  447. glColor4ub(224,224,244,200);
  448. [texture drawAtPoint: ccp(5,2)];
  449. [texture release];
  450. glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
  451. // restore default GL state
  452. glEnableClientState(GL_COLOR_ARRAY);
  453. }
  454. #endif
  455. - (void) showProfilers {
  456. #if CC_ENABLE_PROFILERS
  457. accumDtForProfiler_ += dt;
  458. if (accumDtForProfiler_ > 1.0f) {
  459. accumDtForProfiler_ = 0;
  460. [[CCProfiler sharedProfiler] displayTimers];
  461. }
  462. #endif // CC_ENABLE_PROFILERS
  463. }
  464. @end