diff options
Diffstat (limited to 'libs/cocos2d/Platforms/iOS/CCDirectorIOS.m')
-rwxr-xr-x | libs/cocos2d/Platforms/iOS/CCDirectorIOS.m | 735 |
1 files changed, 735 insertions, 0 deletions
diff --git a/libs/cocos2d/Platforms/iOS/CCDirectorIOS.m b/libs/cocos2d/Platforms/iOS/CCDirectorIOS.m new file mode 100755 index 0000000..c483665 --- /dev/null +++ b/libs/cocos2d/Platforms/iOS/CCDirectorIOS.m | |||
@@ -0,0 +1,735 @@ | |||
1 | /* | ||
2 | * cocos2d for iPhone: http://www.cocos2d-iphone.org | ||
3 | * | ||
4 | * Copyright (c) 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 | // Only compile this code on iOS. These files should NOT be included on your Mac project. | ||
28 | // But in case they are included, it won't be compiled. | ||
29 | #import <Availability.h> | ||
30 | #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED | ||
31 | |||
32 | #import <unistd.h> | ||
33 | |||
34 | // cocos2d imports | ||
35 | #import "CCDirectorIOS.h" | ||
36 | #import "CCTouchDelegateProtocol.h" | ||
37 | #import "CCTouchDispatcher.h" | ||
38 | #import "../../CCScheduler.h" | ||
39 | #import "../../CCActionManager.h" | ||
40 | #import "../../CCTextureCache.h" | ||
41 | #import "../../ccMacros.h" | ||
42 | #import "../../CCScene.h" | ||
43 | |||
44 | // support imports | ||
45 | #import "glu.h" | ||
46 | #import "../../Support/OpenGL_Internal.h" | ||
47 | #import "../../Support/CGPointExtension.h" | ||
48 | |||
49 | #import "CCLayer.h" | ||
50 | |||
51 | #if CC_ENABLE_PROFILERS | ||
52 | #import "../../Support/CCProfiling.h" | ||
53 | #endif | ||
54 | |||
55 | |||
56 | #pragma mark - | ||
57 | #pragma mark Director - global variables (optimization) | ||
58 | |||
59 | CGFloat __ccContentScaleFactor = 1; | ||
60 | |||
61 | #pragma mark - | ||
62 | #pragma mark Director iOS | ||
63 | |||
64 | @interface CCDirector () | ||
65 | -(void) setNextScene; | ||
66 | -(void) showFPS; | ||
67 | -(void) calculateDeltaTime; | ||
68 | @end | ||
69 | |||
70 | @implementation CCDirector (iOSExtensionClassMethods) | ||
71 | |||
72 | +(Class) defaultDirector | ||
73 | { | ||
74 | return [CCDirectorTimer class]; | ||
75 | } | ||
76 | |||
77 | + (BOOL) setDirectorType:(ccDirectorType)type | ||
78 | { | ||
79 | if( type == CCDirectorTypeDisplayLink ) { | ||
80 | NSString *reqSysVer = @"3.1"; | ||
81 | NSString *currSysVer = [[UIDevice currentDevice] systemVersion]; | ||
82 | |||
83 | if([currSysVer compare:reqSysVer options:NSNumericSearch] == NSOrderedAscending) | ||
84 | return NO; | ||
85 | } | ||
86 | switch (type) { | ||
87 | case CCDirectorTypeNSTimer: | ||
88 | [CCDirectorTimer sharedDirector]; | ||
89 | break; | ||
90 | case CCDirectorTypeDisplayLink: | ||
91 | [CCDirectorDisplayLink sharedDirector]; | ||
92 | break; | ||
93 | case CCDirectorTypeMainLoop: | ||
94 | [CCDirectorFast sharedDirector]; | ||
95 | break; | ||
96 | case CCDirectorTypeThreadMainLoop: | ||
97 | [CCDirectorFastThreaded sharedDirector]; | ||
98 | break; | ||
99 | default: | ||
100 | NSAssert(NO,@"Unknown director type"); | ||
101 | } | ||
102 | |||
103 | return YES; | ||
104 | } | ||
105 | |||
106 | @end | ||
107 | |||
108 | |||
109 | |||
110 | #pragma mark - | ||
111 | #pragma mark CCDirectorIOS | ||
112 | |||
113 | @interface CCDirectorIOS () | ||
114 | -(void) updateContentScaleFactor; | ||
115 | |||
116 | @end | ||
117 | |||
118 | @implementation CCDirectorIOS | ||
119 | |||
120 | - (id) init | ||
121 | { | ||
122 | if( (self=[super init]) ) { | ||
123 | |||
124 | // portrait mode default | ||
125 | deviceOrientation_ = CCDeviceOrientationPortrait; | ||
126 | |||
127 | __ccContentScaleFactor = 1; | ||
128 | isContentScaleSupported_ = NO; | ||
129 | |||
130 | // running thread is main thread on iOS | ||
131 | runningThread_ = [NSThread currentThread]; | ||
132 | } | ||
133 | |||
134 | return self; | ||
135 | } | ||
136 | |||
137 | - (void) dealloc | ||
138 | { | ||
139 | [super dealloc]; | ||
140 | } | ||
141 | |||
142 | // | ||
143 | // Draw the Scene | ||
144 | // | ||
145 | - (void) drawScene | ||
146 | { | ||
147 | /* calculate "global" dt */ | ||
148 | [self calculateDeltaTime]; | ||
149 | |||
150 | /* tick before glClear: issue #533 */ | ||
151 | if( ! isPaused_ ) { | ||
152 | [[CCScheduler sharedScheduler] tick: dt]; | ||
153 | } | ||
154 | |||
155 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | ||
156 | |||
157 | /* to avoid flickr, nextScene MUST be here: after tick and before draw. | ||
158 | XXX: Which bug is this one. It seems that it can't be reproduced with v0.9 */ | ||
159 | if( nextScene_ ) | ||
160 | [self setNextScene]; | ||
161 | |||
162 | glPushMatrix(); | ||
163 | |||
164 | [self applyOrientation]; | ||
165 | |||
166 | // By default enable VertexArray, ColorArray, TextureCoordArray and Texture2D | ||
167 | CC_ENABLE_DEFAULT_GL_STATES(); | ||
168 | |||
169 | /* draw the scene */ | ||
170 | [runningScene_ visit]; | ||
171 | |||
172 | /* draw the notification node */ | ||
173 | [notificationNode_ visit]; | ||
174 | |||
175 | if( displayFPS_ ) | ||
176 | [self showFPS]; | ||
177 | |||
178 | #if CC_ENABLE_PROFILERS | ||
179 | [self showProfilers]; | ||
180 | #endif | ||
181 | |||
182 | CC_DISABLE_DEFAULT_GL_STATES(); | ||
183 | |||
184 | glPopMatrix(); | ||
185 | |||
186 | [openGLView_ swapBuffers]; | ||
187 | } | ||
188 | |||
189 | -(void) setProjection:(ccDirectorProjection)projection | ||
190 | { | ||
191 | CGSize size = winSizeInPixels_; | ||
192 | |||
193 | switch (projection) { | ||
194 | case kCCDirectorProjection2D: | ||
195 | glViewport(0, 0, size.width, size.height); | ||
196 | glMatrixMode(GL_PROJECTION); | ||
197 | glLoadIdentity(); | ||
198 | ccglOrtho(0, size.width, 0, size.height, -1024 * CC_CONTENT_SCALE_FACTOR(), 1024 * CC_CONTENT_SCALE_FACTOR()); | ||
199 | glMatrixMode(GL_MODELVIEW); | ||
200 | glLoadIdentity(); | ||
201 | break; | ||
202 | |||
203 | case kCCDirectorProjection3D: | ||
204 | { | ||
205 | float zeye = [self getZEye]; | ||
206 | |||
207 | glViewport(0, 0, size.width, size.height); | ||
208 | glMatrixMode(GL_PROJECTION); | ||
209 | glLoadIdentity(); | ||
210 | // gluPerspective(60, (GLfloat)size.width/size.height, zeye-size.height/2, zeye+size.height/2 ); | ||
211 | gluPerspective(60, (GLfloat)size.width/size.height, 0.5f, 1500); | ||
212 | |||
213 | glMatrixMode(GL_MODELVIEW); | ||
214 | glLoadIdentity(); | ||
215 | gluLookAt( size.width/2, size.height/2, zeye, | ||
216 | size.width/2, size.height/2, 0, | ||
217 | 0.0f, 1.0f, 0.0f); | ||
218 | break; | ||
219 | } | ||
220 | |||
221 | case kCCDirectorProjectionCustom: | ||
222 | if( projectionDelegate_ ) | ||
223 | [projectionDelegate_ updateProjection]; | ||
224 | break; | ||
225 | |||
226 | default: | ||
227 | CCLOG(@"cocos2d: Director: unrecognized projecgtion"); | ||
228 | break; | ||
229 | } | ||
230 | |||
231 | projection_ = projection; | ||
232 | } | ||
233 | |||
234 | #pragma mark Director Integration with a UIKit view | ||
235 | |||
236 | -(void) setOpenGLView:(EAGLView *)view | ||
237 | { | ||
238 | if( view != openGLView_ ) { | ||
239 | |||
240 | [super setOpenGLView:view]; | ||
241 | |||
242 | // set size | ||
243 | winSizeInPixels_ = CGSizeMake(winSizeInPoints_.width * __ccContentScaleFactor, winSizeInPoints_.height *__ccContentScaleFactor); | ||
244 | |||
245 | if( __ccContentScaleFactor != 1 ) | ||
246 | [self updateContentScaleFactor]; | ||
247 | |||
248 | CCTouchDispatcher *touchDispatcher = [CCTouchDispatcher sharedDispatcher]; | ||
249 | [openGLView_ setTouchDelegate: touchDispatcher]; | ||
250 | [touchDispatcher setDispatchEvents: YES]; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | #pragma mark Director - Retina Display | ||
255 | |||
256 | -(CGFloat) contentScaleFactor | ||
257 | { | ||
258 | return __ccContentScaleFactor; | ||
259 | } | ||
260 | |||
261 | -(void) setContentScaleFactor:(CGFloat)scaleFactor | ||
262 | { | ||
263 | if( scaleFactor != __ccContentScaleFactor ) { | ||
264 | |||
265 | __ccContentScaleFactor = scaleFactor; | ||
266 | winSizeInPixels_ = CGSizeMake( winSizeInPoints_.width * scaleFactor, winSizeInPoints_.height * scaleFactor ); | ||
267 | |||
268 | if( openGLView_ ) | ||
269 | [self updateContentScaleFactor]; | ||
270 | |||
271 | // update projection | ||
272 | [self setProjection:projection_]; | ||
273 | } | ||
274 | } | ||
275 | |||
276 | -(void) updateContentScaleFactor | ||
277 | { | ||
278 | // Based on code snippet from: http://developer.apple.com/iphone/prerelease/library/snippets/sp2010/sp28.html | ||
279 | if ([openGLView_ respondsToSelector:@selector(setContentScaleFactor:)]) | ||
280 | { | ||
281 | [openGLView_ setContentScaleFactor: __ccContentScaleFactor]; | ||
282 | |||
283 | isContentScaleSupported_ = YES; | ||
284 | } | ||
285 | else | ||
286 | CCLOG(@"cocos2d: 'setContentScaleFactor:' is not supported on this device"); | ||
287 | } | ||
288 | |||
289 | -(BOOL) enableRetinaDisplay:(BOOL)enabled | ||
290 | { | ||
291 | // Already enabled ? | ||
292 | if( enabled && __ccContentScaleFactor == 2 ) | ||
293 | return YES; | ||
294 | |||
295 | // Already disabled | ||
296 | if( ! enabled && __ccContentScaleFactor == 1 ) | ||
297 | return YES; | ||
298 | |||
299 | // setContentScaleFactor is not supported | ||
300 | if (! [openGLView_ respondsToSelector:@selector(setContentScaleFactor:)]) | ||
301 | return NO; | ||
302 | |||
303 | // SD device | ||
304 | if ([[UIScreen mainScreen] scale] == 1.0) | ||
305 | return NO; | ||
306 | |||
307 | float newScale = enabled ? 2 : 1; | ||
308 | [self setContentScaleFactor:newScale]; | ||
309 | |||
310 | return YES; | ||
311 | } | ||
312 | |||
313 | // overriden, don't call super | ||
314 | -(void) reshapeProjection:(CGSize)size | ||
315 | { | ||
316 | winSizeInPoints_ = [openGLView_ bounds].size; | ||
317 | winSizeInPixels_ = CGSizeMake(winSizeInPoints_.width * __ccContentScaleFactor, winSizeInPoints_.height *__ccContentScaleFactor); | ||
318 | |||
319 | [self setProjection:projection_]; | ||
320 | } | ||
321 | |||
322 | #pragma mark Director Scene Landscape | ||
323 | |||
324 | -(CGPoint)convertToGL:(CGPoint)uiPoint | ||
325 | { | ||
326 | CGSize s = winSizeInPoints_; | ||
327 | float newY = s.height - uiPoint.y; | ||
328 | float newX = s.width - uiPoint.x; | ||
329 | |||
330 | CGPoint ret = CGPointZero; | ||
331 | switch ( deviceOrientation_) { | ||
332 | case CCDeviceOrientationPortrait: | ||
333 | ret = ccp( uiPoint.x, newY ); | ||
334 | break; | ||
335 | case CCDeviceOrientationPortraitUpsideDown: | ||
336 | ret = ccp(newX, uiPoint.y); | ||
337 | break; | ||
338 | case CCDeviceOrientationLandscapeLeft: | ||
339 | ret.x = uiPoint.y; | ||
340 | ret.y = uiPoint.x; | ||
341 | break; | ||
342 | case CCDeviceOrientationLandscapeRight: | ||
343 | ret.x = newY; | ||
344 | ret.y = newX; | ||
345 | break; | ||
346 | } | ||
347 | return ret; | ||
348 | } | ||
349 | |||
350 | -(CGPoint)convertToUI:(CGPoint)glPoint | ||
351 | { | ||
352 | CGSize winSize = winSizeInPoints_; | ||
353 | int oppositeX = winSize.width - glPoint.x; | ||
354 | int oppositeY = winSize.height - glPoint.y; | ||
355 | CGPoint uiPoint = CGPointZero; | ||
356 | switch ( deviceOrientation_) { | ||
357 | case CCDeviceOrientationPortrait: | ||
358 | uiPoint = ccp(glPoint.x, oppositeY); | ||
359 | break; | ||
360 | case CCDeviceOrientationPortraitUpsideDown: | ||
361 | uiPoint = ccp(oppositeX, glPoint.y); | ||
362 | break; | ||
363 | case CCDeviceOrientationLandscapeLeft: | ||
364 | uiPoint = ccp(glPoint.y, glPoint.x); | ||
365 | break; | ||
366 | case CCDeviceOrientationLandscapeRight: | ||
367 | // Can't use oppositeX/Y because x/y are flipped | ||
368 | uiPoint = ccp(winSize.width-glPoint.y, winSize.height-glPoint.x); | ||
369 | break; | ||
370 | } | ||
371 | return uiPoint; | ||
372 | } | ||
373 | |||
374 | // get the current size of the glview | ||
375 | -(CGSize) winSize | ||
376 | { | ||
377 | CGSize s = winSizeInPoints_; | ||
378 | |||
379 | if( deviceOrientation_ == CCDeviceOrientationLandscapeLeft || deviceOrientation_ == CCDeviceOrientationLandscapeRight ) { | ||
380 | // swap x,y in landscape mode | ||
381 | CGSize tmp = s; | ||
382 | s.width = tmp.height; | ||
383 | s.height = tmp.width; | ||
384 | } | ||
385 | return s; | ||
386 | } | ||
387 | |||
388 | -(CGSize) winSizeInPixels | ||
389 | { | ||
390 | CGSize s = [self winSize]; | ||
391 | |||
392 | s.width *= CC_CONTENT_SCALE_FACTOR(); | ||
393 | s.height *= CC_CONTENT_SCALE_FACTOR(); | ||
394 | |||
395 | return s; | ||
396 | } | ||
397 | |||
398 | -(ccDeviceOrientation) deviceOrientation | ||
399 | { | ||
400 | return deviceOrientation_; | ||
401 | } | ||
402 | |||
403 | - (void) setDeviceOrientation:(ccDeviceOrientation) orientation | ||
404 | { | ||
405 | if( deviceOrientation_ != orientation ) { | ||
406 | deviceOrientation_ = orientation; | ||
407 | switch( deviceOrientation_) { | ||
408 | case CCDeviceOrientationPortrait: | ||
409 | [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationPortrait animated:NO]; | ||
410 | break; | ||
411 | case CCDeviceOrientationPortraitUpsideDown: | ||
412 | [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationPortraitUpsideDown animated:NO]; | ||
413 | break; | ||
414 | case CCDeviceOrientationLandscapeLeft: | ||
415 | [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationLandscapeRight animated:NO]; | ||
416 | break; | ||
417 | case CCDeviceOrientationLandscapeRight: | ||
418 | [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationLandscapeLeft animated:NO]; | ||
419 | break; | ||
420 | default: | ||
421 | NSLog(@"Director: Unknown device orientation"); | ||
422 | break; | ||
423 | } | ||
424 | } | ||
425 | } | ||
426 | |||
427 | -(void) applyOrientation | ||
428 | { | ||
429 | CGSize s = winSizeInPixels_; | ||
430 | float w = s.width / 2; | ||
431 | float h = s.height / 2; | ||
432 | |||
433 | // XXX it's using hardcoded values. | ||
434 | // What if the the screen size changes in the future? | ||
435 | switch ( deviceOrientation_ ) { | ||
436 | case CCDeviceOrientationPortrait: | ||
437 | // nothing | ||
438 | break; | ||
439 | case CCDeviceOrientationPortraitUpsideDown: | ||
440 | // upside down | ||
441 | glTranslatef(w,h,0); | ||
442 | glRotatef(180,0,0,1); | ||
443 | glTranslatef(-w,-h,0); | ||
444 | break; | ||
445 | case CCDeviceOrientationLandscapeRight: | ||
446 | glTranslatef(w,h,0); | ||
447 | glRotatef(90,0,0,1); | ||
448 | glTranslatef(-h,-w,0); | ||
449 | break; | ||
450 | case CCDeviceOrientationLandscapeLeft: | ||
451 | glTranslatef(w,h,0); | ||
452 | glRotatef(-90,0,0,1); | ||
453 | glTranslatef(-h,-w,0); | ||
454 | break; | ||
455 | } | ||
456 | } | ||
457 | |||
458 | -(void) end | ||
459 | { | ||
460 | // don't release the event handlers | ||
461 | // They are needed in case the director is run again | ||
462 | [[CCTouchDispatcher sharedDispatcher] removeAllDelegates]; | ||
463 | |||
464 | [super end]; | ||
465 | } | ||
466 | |||
467 | @end | ||
468 | |||
469 | |||
470 | #pragma mark - | ||
471 | #pragma mark Director TimerDirector | ||
472 | |||
473 | @implementation CCDirectorTimer | ||
474 | - (void)startAnimation | ||
475 | { | ||
476 | NSAssert( animationTimer == nil, @"animationTimer must be nil. Calling startAnimation twice?"); | ||
477 | |||
478 | if( gettimeofday( &lastUpdate_, NULL) != 0 ) { | ||
479 | CCLOG(@"cocos2d: Director: Error in gettimeofday"); | ||
480 | } | ||
481 | |||
482 | animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval_ target:self selector:@selector(mainLoop) userInfo:nil repeats:YES]; | ||
483 | |||
484 | // | ||
485 | // If you want to attach the opengl view into UIScrollView | ||
486 | // uncomment this line to prevent 'freezing'. | ||
487 | // It doesn't work on with the Fast Director | ||
488 | // | ||
489 | // [[NSRunLoop currentRunLoop] addTimer:animationTimer | ||
490 | // forMode:NSRunLoopCommonModes]; | ||
491 | } | ||
492 | |||
493 | -(void) mainLoop | ||
494 | { | ||
495 | [self drawScene]; | ||
496 | } | ||
497 | |||
498 | - (void)stopAnimation | ||
499 | { | ||
500 | [animationTimer invalidate]; | ||
501 | animationTimer = nil; | ||
502 | } | ||
503 | |||
504 | - (void)setAnimationInterval:(NSTimeInterval)interval | ||
505 | { | ||
506 | animationInterval_ = interval; | ||
507 | |||
508 | if(animationTimer) { | ||
509 | [self stopAnimation]; | ||
510 | [self startAnimation]; | ||
511 | } | ||
512 | } | ||
513 | |||
514 | -(void) dealloc | ||
515 | { | ||
516 | [animationTimer release]; | ||
517 | [super dealloc]; | ||
518 | } | ||
519 | @end | ||
520 | |||
521 | |||
522 | #pragma mark - | ||
523 | #pragma mark Director DirectorFast | ||
524 | |||
525 | @implementation CCDirectorFast | ||
526 | |||
527 | - (id) init | ||
528 | { | ||
529 | if(( self = [super init] )) { | ||
530 | |||
531 | #if CC_DIRECTOR_DISPATCH_FAST_EVENTS | ||
532 | CCLOG(@"cocos2d: Fast Events enabled"); | ||
533 | #else | ||
534 | CCLOG(@"cocos2d: Fast Events disabled"); | ||
535 | #endif | ||
536 | isRunning = NO; | ||
537 | |||
538 | // XXX: | ||
539 | // XXX: Don't create any autorelease object before calling "fast director" | ||
540 | // XXX: else it will be leaked | ||
541 | // XXX: | ||
542 | autoreleasePool = [NSAutoreleasePool new]; | ||
543 | } | ||
544 | |||
545 | return self; | ||
546 | } | ||
547 | |||
548 | - (void) startAnimation | ||
549 | { | ||
550 | NSAssert( isRunning == NO, @"isRunning must be NO. Calling startAnimation twice?"); | ||
551 | |||
552 | // XXX: | ||
553 | // XXX: release autorelease objects created | ||
554 | // XXX: between "use fast director" and "runWithScene" | ||
555 | // XXX: | ||
556 | [autoreleasePool release]; | ||
557 | autoreleasePool = nil; | ||
558 | |||
559 | if ( gettimeofday( &lastUpdate_, NULL) != 0 ) { | ||
560 | CCLOG(@"cocos2d: Director: Error in gettimeofday"); | ||
561 | } | ||
562 | |||
563 | |||
564 | isRunning = YES; | ||
565 | |||
566 | SEL selector = @selector(mainLoop); | ||
567 | NSMethodSignature* sig = [[[CCDirector sharedDirector] class] | ||
568 | instanceMethodSignatureForSelector:selector]; | ||
569 | NSInvocation* invocation = [NSInvocation | ||
570 | invocationWithMethodSignature:sig]; | ||
571 | [invocation setTarget:[CCDirector sharedDirector]]; | ||
572 | [invocation setSelector:selector]; | ||
573 | [invocation performSelectorOnMainThread:@selector(invokeWithTarget:) | ||
574 | withObject:[CCDirector sharedDirector] waitUntilDone:NO]; | ||
575 | |||
576 | // NSInvocationOperation *loopOperation = [[[NSInvocationOperation alloc] | ||
577 | // initWithTarget:self selector:@selector(mainLoop) object:nil] | ||
578 | // autorelease]; | ||
579 | // | ||
580 | // [loopOperation performSelectorOnMainThread:@selector(start) withObject:nil | ||
581 | // waitUntilDone:NO]; | ||
582 | } | ||
583 | |||
584 | -(void) mainLoop | ||
585 | { | ||
586 | while (isRunning) { | ||
587 | |||
588 | NSAutoreleasePool *loopPool = [NSAutoreleasePool new]; | ||
589 | |||
590 | #if CC_DIRECTOR_DISPATCH_FAST_EVENTS | ||
591 | while( CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.004f, FALSE) == kCFRunLoopRunHandledSource); | ||
592 | #else | ||
593 | while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE) == kCFRunLoopRunHandledSource); | ||
594 | #endif | ||
595 | |||
596 | if (isPaused_) { | ||
597 | usleep(250000); // Sleep for a quarter of a second (250,000 microseconds) so that the framerate is 4 fps. | ||
598 | } | ||
599 | |||
600 | [self drawScene]; | ||
601 | |||
602 | #if CC_DIRECTOR_DISPATCH_FAST_EVENTS | ||
603 | while( CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.004f, FALSE) == kCFRunLoopRunHandledSource); | ||
604 | #else | ||
605 | while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE) == kCFRunLoopRunHandledSource); | ||
606 | #endif | ||
607 | |||
608 | [loopPool release]; | ||
609 | } | ||
610 | } | ||
611 | - (void) stopAnimation | ||
612 | { | ||
613 | isRunning = NO; | ||
614 | } | ||
615 | |||
616 | - (void)setAnimationInterval:(NSTimeInterval)interval | ||
617 | { | ||
618 | NSLog(@"FastDirectory doesn't support setAnimationInterval, yet"); | ||
619 | } | ||
620 | @end | ||
621 | |||
622 | #pragma mark - | ||
623 | #pragma mark Director DirectorThreadedFast | ||
624 | |||
625 | @implementation CCDirectorFastThreaded | ||
626 | |||
627 | - (id) init | ||
628 | { | ||
629 | if(( self = [super init] )) { | ||
630 | isRunning = NO; | ||
631 | } | ||
632 | |||
633 | return self; | ||
634 | } | ||
635 | |||
636 | - (void) startAnimation | ||
637 | { | ||
638 | NSAssert( isRunning == NO, @"isRunning must be NO. Calling startAnimation twice?"); | ||
639 | |||
640 | if ( gettimeofday( &lastUpdate_, NULL) != 0 ) { | ||
641 | CCLOG(@"cocos2d: ThreadedFastDirector: Error on gettimeofday"); | ||
642 | } | ||
643 | |||
644 | isRunning = YES; | ||
645 | |||
646 | NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(mainLoop) object:nil]; | ||
647 | [thread start]; | ||
648 | [thread release]; | ||
649 | } | ||
650 | |||
651 | -(void) mainLoop | ||
652 | { | ||
653 | while( ![[NSThread currentThread] isCancelled] ) { | ||
654 | if( isRunning ) | ||
655 | [self performSelectorOnMainThread:@selector(drawScene) withObject:nil waitUntilDone:YES]; | ||
656 | |||
657 | if (isPaused_) { | ||
658 | usleep(250000); // Sleep for a quarter of a second (250,000 microseconds) so that the framerate is 4 fps. | ||
659 | } else { | ||
660 | // usleep(2000); | ||
661 | } | ||
662 | } | ||
663 | } | ||
664 | - (void) stopAnimation | ||
665 | { | ||
666 | isRunning = NO; | ||
667 | } | ||
668 | |||
669 | - (void)setAnimationInterval:(NSTimeInterval)interval | ||
670 | { | ||
671 | NSLog(@"FastDirector doesn't support setAnimationInterval, yet"); | ||
672 | } | ||
673 | @end | ||
674 | |||
675 | #pragma mark - | ||
676 | #pragma mark DirectorDisplayLink | ||
677 | |||
678 | // Allows building DisplayLinkDirector for pre-3.1 SDKS | ||
679 | // without getting compiler warnings. | ||
680 | @interface NSObject(CADisplayLink) | ||
681 | + (id) displayLinkWithTarget:(id)arg1 selector:(SEL)arg2; | ||
682 | - (void) addToRunLoop:(id)arg1 forMode:(id)arg2; | ||
683 | - (void) setFrameInterval:(int)interval; | ||
684 | - (void) invalidate; | ||
685 | @end | ||
686 | |||
687 | @implementation CCDirectorDisplayLink | ||
688 | |||
689 | - (void)setAnimationInterval:(NSTimeInterval)interval | ||
690 | { | ||
691 | animationInterval_ = interval; | ||
692 | if(displayLink){ | ||
693 | [self stopAnimation]; | ||
694 | [self startAnimation]; | ||
695 | } | ||
696 | } | ||
697 | |||
698 | - (void) startAnimation | ||
699 | { | ||
700 | NSAssert( displayLink == nil, @"displayLink must be nil. Calling startAnimation twice?"); | ||
701 | |||
702 | if ( gettimeofday( &lastUpdate_, NULL) != 0 ) { | ||
703 | CCLOG(@"cocos2d: DisplayLinkDirector: Error on gettimeofday"); | ||
704 | } | ||
705 | |||
706 | // approximate frame rate | ||
707 | // assumes device refreshes at 60 fps | ||
708 | int frameInterval = (int) floor(animationInterval_ * 60.0f); | ||
709 | |||
710 | CCLOG(@"cocos2d: Frame interval: %d", frameInterval); | ||
711 | |||
712 | displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(mainLoop:)]; | ||
713 | [displayLink setFrameInterval:frameInterval]; | ||
714 | [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; | ||
715 | } | ||
716 | |||
717 | -(void) mainLoop:(id)sender | ||
718 | { | ||
719 | [self drawScene]; | ||
720 | } | ||
721 | |||
722 | - (void) stopAnimation | ||
723 | { | ||
724 | [displayLink invalidate]; | ||
725 | displayLink = nil; | ||
726 | } | ||
727 | |||
728 | -(void) dealloc | ||
729 | { | ||
730 | [displayLink release]; | ||
731 | [super dealloc]; | ||
732 | } | ||
733 | @end | ||
734 | |||
735 | #endif // __IPHONE_OS_VERSION_MAX_ALLOWED | ||