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