summary refs log tree commit diff stats
path: root/libs/cocos2d/CCDirector.m
diff options
context:
space:
mode:
Diffstat (limited to 'libs/cocos2d/CCDirector.m')
-rwxr-xr-xlibs/cocos2d/CCDirector.m565
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
67extern 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//
93static 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