summary refs log tree commit diff stats
path: root/libs/cocos2d/CCNode.m
diff options
context:
space:
mode:
authorStarla Insigna <starla4444@gmail.com>2011-07-30 11:19:14 -0400
committerStarla Insigna <starla4444@gmail.com>2011-07-30 11:19:14 -0400
commit9cd57b731ab1c666d4a1cb725538fdc137763d12 (patch)
tree5bac45ae5157a1cb10c6e45500cbf72789917980 /libs/cocos2d/CCNode.m
downloadcartcollect-9cd57b731ab1c666d4a1cb725538fdc137763d12.tar.gz
cartcollect-9cd57b731ab1c666d4a1cb725538fdc137763d12.tar.bz2
cartcollect-9cd57b731ab1c666d4a1cb725538fdc137763d12.zip
Initial commit (version 0.2.1)
Diffstat (limited to 'libs/cocos2d/CCNode.m')
-rwxr-xr-xlibs/cocos2d/CCNode.m921
1 files changed, 921 insertions, 0 deletions
diff --git a/libs/cocos2d/CCNode.m b/libs/cocos2d/CCNode.m new file mode 100755 index 0000000..569cb22 --- /dev/null +++ b/libs/cocos2d/CCNode.m
@@ -0,0 +1,921 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Valentin Milea
5 *
6 * Copyright (c) 2008-2010 Ricardo Quesada
7 * Copyright (c) 2011 Zynga Inc.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 */
27
28#import "CCNode.h"
29#import "CCGrid.h"
30#import "CCDirector.h"
31#import "CCActionManager.h"
32#import "CCCamera.h"
33#import "CCScheduler.h"
34#import "ccConfig.h"
35#import "ccMacros.h"
36#import "Support/CGPointExtension.h"
37#import "Support/ccCArray.h"
38#import "Support/TransformUtils.h"
39#import "ccMacros.h"
40
41#import <Availability.h>
42#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
43#import "Platforms/iOS/CCDirectorIOS.h"
44#endif
45
46
47#if CC_COCOSNODE_RENDER_SUBPIXEL
48#define RENDER_IN_SUBPIXEL
49#else
50#define RENDER_IN_SUBPIXEL (NSInteger)
51#endif
52
53@interface CCNode ()
54// lazy allocs
55-(void) childrenAlloc;
56// helper that reorder a child
57-(void) insertChild:(CCNode*)child z:(NSInteger)z;
58// used internally to alter the zOrder variable. DON'T call this method manually
59-(void) _setZOrder:(NSInteger) z;
60-(void) detachChild:(CCNode *)child cleanup:(BOOL)doCleanup;
61@end
62
63@implementation CCNode
64
65@synthesize children = children_;
66@synthesize visible = visible_;
67@synthesize parent = parent_;
68@synthesize grid = grid_;
69@synthesize zOrder = zOrder_;
70@synthesize tag = tag_;
71@synthesize vertexZ = vertexZ_;
72@synthesize isRunning = isRunning_;
73@synthesize userData = userData_;
74
75#pragma mark CCNode - Transform related properties
76
77@synthesize rotation = rotation_, scaleX = scaleX_, scaleY = scaleY_;
78@synthesize skewX = skewX_, skewY = skewY_;
79@synthesize position = position_, positionInPixels = positionInPixels_;
80@synthesize anchorPoint = anchorPoint_, anchorPointInPixels = anchorPointInPixels_;
81@synthesize contentSize = contentSize_, contentSizeInPixels = contentSizeInPixels_;
82@synthesize isRelativeAnchorPoint = isRelativeAnchorPoint_;
83
84// getters synthesized, setters explicit
85
86-(void) setSkewX:(float)newSkewX
87{
88 skewX_ = newSkewX;
89 isTransformDirty_ = isInverseDirty_ = YES;
90#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
91 isTransformGLDirty_ = YES;
92#endif
93}
94
95-(void) setSkewY:(float)newSkewY
96{
97 skewY_ = newSkewY;
98 isTransformDirty_ = isInverseDirty_ = YES;
99#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
100 isTransformGLDirty_ = YES;
101#endif
102}
103
104-(void) setRotation: (float)newRotation
105{
106 rotation_ = newRotation;
107 isTransformDirty_ = isInverseDirty_ = YES;
108#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
109 isTransformGLDirty_ = YES;
110#endif
111}
112
113-(void) setScaleX: (float)newScaleX
114{
115 scaleX_ = newScaleX;
116 isTransformDirty_ = isInverseDirty_ = YES;
117#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
118 isTransformGLDirty_ = YES;
119#endif
120}
121
122-(void) setScaleY: (float)newScaleY
123{
124 scaleY_ = newScaleY;
125 isTransformDirty_ = isInverseDirty_ = YES;
126#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
127 isTransformGLDirty_ = YES;
128#endif
129}
130
131-(void) setPosition: (CGPoint)newPosition
132{
133 position_ = newPosition;
134 if( CC_CONTENT_SCALE_FACTOR() == 1 )
135 positionInPixels_ = position_;
136 else
137 positionInPixels_ = ccpMult( newPosition, CC_CONTENT_SCALE_FACTOR() );
138
139 isTransformDirty_ = isInverseDirty_ = YES;
140#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
141 isTransformGLDirty_ = YES;
142#endif
143}
144
145-(void) setPositionInPixels:(CGPoint)newPosition
146{
147 positionInPixels_ = newPosition;
148
149 if( CC_CONTENT_SCALE_FACTOR() == 1 )
150 position_ = positionInPixels_;
151 else
152 position_ = ccpMult( newPosition, 1/CC_CONTENT_SCALE_FACTOR() );
153
154 isTransformDirty_ = isInverseDirty_ = YES;
155#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
156 isTransformGLDirty_ = YES;
157#endif
158}
159
160-(void) setIsRelativeAnchorPoint: (BOOL)newValue
161{
162 isRelativeAnchorPoint_ = newValue;
163 isTransformDirty_ = isInverseDirty_ = YES;
164#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
165 isTransformGLDirty_ = YES;
166#endif
167}
168
169-(void) setAnchorPoint:(CGPoint)point
170{
171 if( ! CGPointEqualToPoint(point, anchorPoint_) ) {
172 anchorPoint_ = point;
173 anchorPointInPixels_ = ccp( contentSizeInPixels_.width * anchorPoint_.x, contentSizeInPixels_.height * anchorPoint_.y );
174 isTransformDirty_ = isInverseDirty_ = YES;
175#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
176 isTransformGLDirty_ = YES;
177#endif
178 }
179}
180
181-(void) setContentSize:(CGSize)size
182{
183 if( ! CGSizeEqualToSize(size, contentSize_) ) {
184 contentSize_ = size;
185
186 if( CC_CONTENT_SCALE_FACTOR() == 1 )
187 contentSizeInPixels_ = contentSize_;
188 else
189 contentSizeInPixels_ = CGSizeMake( size.width * CC_CONTENT_SCALE_FACTOR(), size.height * CC_CONTENT_SCALE_FACTOR() );
190
191 anchorPointInPixels_ = ccp( contentSizeInPixels_.width * anchorPoint_.x, contentSizeInPixels_.height * anchorPoint_.y );
192 isTransformDirty_ = isInverseDirty_ = YES;
193#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
194 isTransformGLDirty_ = YES;
195#endif
196 }
197}
198
199-(void) setContentSizeInPixels:(CGSize)size
200{
201 if( ! CGSizeEqualToSize(size, contentSizeInPixels_) ) {
202 contentSizeInPixels_ = size;
203
204 if( CC_CONTENT_SCALE_FACTOR() == 1 )
205 contentSize_ = contentSizeInPixels_;
206 else
207 contentSize_ = CGSizeMake( size.width / CC_CONTENT_SCALE_FACTOR(), size.height / CC_CONTENT_SCALE_FACTOR() );
208
209 anchorPointInPixels_ = ccp( contentSizeInPixels_.width * anchorPoint_.x, contentSizeInPixels_.height * anchorPoint_.y );
210 isTransformDirty_ = isInverseDirty_ = YES;
211#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
212 isTransformGLDirty_ = YES;
213#endif
214 }
215}
216
217- (CGRect) boundingBox
218{
219 CGRect ret = [self boundingBoxInPixels];
220 return CC_RECT_PIXELS_TO_POINTS( ret );
221}
222
223- (CGRect) boundingBoxInPixels
224{
225 CGRect rect = CGRectMake(0, 0, contentSizeInPixels_.width, contentSizeInPixels_.height);
226 return CGRectApplyAffineTransform(rect, [self nodeToParentTransform]);
227}
228
229-(void) setVertexZ:(float)vertexZ
230{
231 vertexZ_ = vertexZ * CC_CONTENT_SCALE_FACTOR();
232}
233
234-(float) scale
235{
236 NSAssert( scaleX_ == scaleY_, @"CCNode#scale. ScaleX != ScaleY. Don't know which one to return");
237 return scaleX_;
238}
239
240-(void) setScale:(float) s
241{
242 scaleX_ = scaleY_ = s;
243 isTransformDirty_ = isInverseDirty_ = YES;
244#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
245 isTransformGLDirty_ = YES;
246#endif
247}
248
249#pragma mark CCNode - Init & cleanup
250
251+(id) node
252{
253 return [[[self alloc] init] autorelease];
254}
255
256-(id) init
257{
258 if ((self=[super init]) ) {
259
260 isRunning_ = NO;
261
262 skewX_ = skewY_ = 0.0f;
263 rotation_ = 0.0f;
264 scaleX_ = scaleY_ = 1.0f;
265 positionInPixels_ = position_ = CGPointZero;
266 anchorPointInPixels_ = anchorPoint_ = CGPointZero;
267 contentSizeInPixels_ = contentSize_ = CGSizeZero;
268
269
270 // "whole screen" objects. like Scenes and Layers, should set isRelativeAnchorPoint to NO
271 isRelativeAnchorPoint_ = YES;
272
273 isTransformDirty_ = isInverseDirty_ = YES;
274#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
275 isTransformGLDirty_ = YES;
276#endif
277
278 vertexZ_ = 0;
279
280 grid_ = nil;
281
282 visible_ = YES;
283
284 tag_ = kCCNodeTagInvalid;
285
286 zOrder_ = 0;
287
288 // lazy alloc
289 camera_ = nil;
290
291 // children (lazy allocs)
292 children_ = nil;
293
294 // userData is always inited as nil
295 userData_ = nil;
296
297 //initialize parent to nil
298 parent_ = nil;
299 }
300
301 return self;
302}
303
304- (void)cleanup
305{
306 // actions
307 [self stopAllActions];
308 [self unscheduleAllSelectors];
309
310 // timers
311 [children_ makeObjectsPerformSelector:@selector(cleanup)];
312}
313
314- (NSString*) description
315{
316 return [NSString stringWithFormat:@"<%@ = %08X | Tag = %i>", [self class], self, tag_];
317}
318
319- (void) dealloc
320{
321 CCLOGINFO( @"cocos2d: deallocing %@", self);
322
323 // attributes
324 [camera_ release];
325
326 [grid_ release];
327
328 // children
329 CCNode *child;
330 CCARRAY_FOREACH(children_, child)
331 child.parent = nil;
332
333 [children_ release];
334
335 [super dealloc];
336}
337
338#pragma mark CCNode Composition
339
340-(void) childrenAlloc
341{
342 children_ = [[CCArray alloc] initWithCapacity:4];
343}
344
345// camera: lazy alloc
346-(CCCamera*) camera
347{
348 if( ! camera_ ) {
349 camera_ = [[CCCamera alloc] init];
350
351 // by default, center camera at the Sprite's anchor point
352 // [camera_ setCenterX:anchorPointInPixels_.x centerY:anchorPointInPixels_.y centerZ:0];
353 // [camera_ setEyeX:anchorPointInPixels_.x eyeY:anchorPointInPixels_.y eyeZ:1];
354
355 // [camera_ setCenterX:0 centerY:0 centerZ:0];
356 // [camera_ setEyeX:0 eyeY:0 eyeZ:1];
357
358 }
359
360 return camera_;
361}
362
363-(CCNode*) getChildByTag:(NSInteger) aTag
364{
365 NSAssert( aTag != kCCNodeTagInvalid, @"Invalid tag");
366
367 CCNode *node;
368 CCARRAY_FOREACH(children_, node){
369 if( node.tag == aTag )
370 return node;
371 }
372 // not found
373 return nil;
374}
375
376/* "add" logic MUST only be on this method
377 * If a class want's to extend the 'addChild' behaviour it only needs
378 * to override this method
379 */
380-(void) addChild: (CCNode*) child z:(NSInteger)z tag:(NSInteger) aTag
381{
382 NSAssert( child != nil, @"Argument must be non-nil");
383 NSAssert( child.parent == nil, @"child already added. It can't be added again");
384
385 if( ! children_ )
386 [self childrenAlloc];
387
388 [self insertChild:child z:z];
389
390 child.tag = aTag;
391
392 [child setParent: self];
393
394 if( isRunning_ ) {
395 [child onEnter];
396 [child onEnterTransitionDidFinish];
397 }
398}
399
400-(void) addChild: (CCNode*) child z:(NSInteger)z
401{
402 NSAssert( child != nil, @"Argument must be non-nil");
403 [self addChild:child z:z tag:child.tag];
404}
405
406-(void) addChild: (CCNode*) child
407{
408 NSAssert( child != nil, @"Argument must be non-nil");
409 [self addChild:child z:child.zOrder tag:child.tag];
410}
411
412-(void) removeFromParentAndCleanup:(BOOL)cleanup
413{
414 [parent_ removeChild:self cleanup:cleanup];
415}
416
417/* "remove" logic MUST only be on this method
418 * If a class want's to extend the 'removeChild' behavior it only needs
419 * to override this method
420 */
421-(void) removeChild: (CCNode*)child cleanup:(BOOL)cleanup
422{
423 // explicit nil handling
424 if (child == nil)
425 return;
426
427 if ( [children_ containsObject:child] )
428 [self detachChild:child cleanup:cleanup];
429}
430
431-(void) removeChildByTag:(NSInteger)aTag cleanup:(BOOL)cleanup
432{
433 NSAssert( aTag != kCCNodeTagInvalid, @"Invalid tag");
434
435 CCNode *child = [self getChildByTag:aTag];
436
437 if (child == nil)
438 CCLOG(@"cocos2d: removeChildByTag: child not found!");
439 else
440 [self removeChild:child cleanup:cleanup];
441}
442
443-(void) removeAllChildrenWithCleanup:(BOOL)cleanup
444{
445 // not using detachChild improves speed here
446 CCNode *c;
447 CCARRAY_FOREACH(children_, c)
448 {
449 // IMPORTANT:
450 // -1st do onExit
451 // -2nd cleanup
452 if (isRunning_)
453 [c onExit];
454
455 if (cleanup)
456 [c cleanup];
457
458 // set parent nil at the end (issue #476)
459 [c setParent:nil];
460 }
461
462 [children_ removeAllObjects];
463}
464
465-(void) detachChild:(CCNode *)child cleanup:(BOOL)doCleanup
466{
467 // IMPORTANT:
468 // -1st do onExit
469 // -2nd cleanup
470 if (isRunning_)
471 [child onExit];
472
473 // If you don't do cleanup, the child's actions will not get removed and the
474 // its scheduledSelectors_ dict will not get released!
475 if (doCleanup)
476 [child cleanup];
477
478 // set parent nil at the end (issue #476)
479 [child setParent:nil];
480
481 [children_ removeObject:child];
482}
483
484// used internally to alter the zOrder variable. DON'T call this method manually
485-(void) _setZOrder:(NSInteger) z
486{
487 zOrder_ = z;
488}
489
490// helper used by reorderChild & add
491-(void) insertChild:(CCNode*)child z:(NSInteger)z
492{
493 NSUInteger index=0;
494 CCNode *a = [children_ lastObject];
495
496 // quick comparison to improve performance
497 if (!a || a.zOrder <= z)
498 [children_ addObject:child];
499
500 else
501 {
502 CCARRAY_FOREACH(children_, a) {
503 if ( a.zOrder > z ) {
504 [children_ insertObject:child atIndex:index];
505 break;
506 }
507 index++;
508 }
509 }
510
511 [child _setZOrder:z];
512}
513
514-(void) reorderChild:(CCNode*) child z:(NSInteger)z
515{
516 NSAssert( child != nil, @"Child must be non-nil");
517
518 [child retain];
519 [children_ removeObject:child];
520
521 [self insertChild:child z:z];
522
523 [child release];
524}
525
526#pragma mark CCNode Draw
527
528-(void) draw
529{
530 // override me
531 // Only use this function to draw your staff.
532 // DON'T draw your stuff outside this method
533}
534
535-(void) visit
536{
537 // quick return if not visible
538 if (!visible_)
539 return;
540
541 glPushMatrix();
542
543 if ( grid_ && grid_.active) {
544 [grid_ beforeDraw];
545 [self transformAncestors];
546 }
547
548 [self transform];
549
550 if(children_) {
551 ccArray *arrayData = children_->data;
552 NSUInteger i = 0;
553
554 // draw children zOrder < 0
555 for( ; i < arrayData->num; i++ ) {
556 CCNode *child = arrayData->arr[i];
557 if ( [child zOrder] < 0 )
558 [child visit];
559 else
560 break;
561 }
562
563 // self draw
564 [self draw];
565
566 // draw children zOrder >= 0
567 for( ; i < arrayData->num; i++ ) {
568 CCNode *child = arrayData->arr[i];
569 [child visit];
570 }
571
572 } else
573 [self draw];
574
575 if ( grid_ && grid_.active)
576 [grid_ afterDraw:self];
577
578 glPopMatrix();
579}
580
581#pragma mark CCNode - Transformations
582
583-(void) transformAncestors
584{
585 if( parent_ ) {
586 [parent_ transformAncestors];
587 [parent_ transform];
588 }
589}
590
591-(void) transform
592{
593 // transformations
594
595#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
596 // BEGIN alternative -- using cached transform
597 //
598 if( isTransformGLDirty_ ) {
599 CGAffineTransform t = [self nodeToParentTransform];
600 CGAffineToGL(&t, transformGL_);
601 isTransformGLDirty_ = NO;
602 }
603
604 glMultMatrixf(transformGL_);
605 if( vertexZ_ )
606 glTranslatef(0, 0, vertexZ_);
607
608 // XXX: Expensive calls. Camera should be integrated into the cached affine matrix
609 if ( camera_ && !(grid_ && grid_.active) )
610 {
611 BOOL translate = (anchorPointInPixels_.x != 0.0f || anchorPointInPixels_.y != 0.0f);
612
613 if( translate )
614 ccglTranslate(RENDER_IN_SUBPIXEL(anchorPointInPixels_.x), RENDER_IN_SUBPIXEL(anchorPointInPixels_.y), 0);
615
616 [camera_ locate];
617
618 if( translate )
619 ccglTranslate(RENDER_IN_SUBPIXEL(-anchorPointInPixels_.x), RENDER_IN_SUBPIXEL(-anchorPointInPixels_.y), 0);
620 }
621
622
623 // END alternative
624
625#else
626 // BEGIN original implementation
627 //
628 // translate
629 if ( isRelativeAnchorPoint_ && (anchorPointInPixels_.x != 0 || anchorPointInPixels_.y != 0 ) )
630 glTranslatef( RENDER_IN_SUBPIXEL(-anchorPointInPixels_.x), RENDER_IN_SUBPIXEL(-anchorPointInPixels_.y), 0);
631
632 if (anchorPointInPixels_.x != 0 || anchorPointInPixels_.y != 0)
633 glTranslatef( RENDER_IN_SUBPIXEL(positionInPixels_.x + anchorPointInPixels_.x), RENDER_IN_SUBPIXEL(positionInPixels_.y + anchorPointInPixels_.y), vertexZ_);
634 else if ( positionInPixels_.x !=0 || positionInPixels_.y !=0 || vertexZ_ != 0)
635 glTranslatef( RENDER_IN_SUBPIXEL(positionInPixels_.x), RENDER_IN_SUBPIXEL(positionInPixels_.y), vertexZ_ );
636
637 // rotate
638 if (rotation_ != 0.0f )
639 glRotatef( -rotation_, 0.0f, 0.0f, 1.0f );
640
641 // skew
642 if ( (skewX_ != 0.0f) || (skewY_ != 0.0f) ) {
643 CGAffineTransform skewMatrix = CGAffineTransformMake( 1.0f, tanf(CC_DEGREES_TO_RADIANS(skewY_)), tanf(CC_DEGREES_TO_RADIANS(skewX_)), 1.0f, 0.0f, 0.0f );
644 GLfloat glMatrix[16];
645 CGAffineToGL(&skewMatrix, glMatrix);
646 glMultMatrixf(glMatrix);
647 }
648
649 // scale
650 if (scaleX_ != 1.0f || scaleY_ != 1.0f)
651 glScalef( scaleX_, scaleY_, 1.0f );
652
653 if ( camera_ && !(grid_ && grid_.active) )
654 [camera_ locate];
655
656 // restore and re-position point
657 if (anchorPointInPixels_.x != 0.0f || anchorPointInPixels_.y != 0.0f)
658 glTranslatef(RENDER_IN_SUBPIXEL(-anchorPointInPixels_.x), RENDER_IN_SUBPIXEL(-anchorPointInPixels_.y), 0);
659
660 //
661 // END original implementation
662#endif
663
664}
665
666#pragma mark CCNode SceneManagement
667
668-(void) onEnter
669{
670 [children_ makeObjectsPerformSelector:@selector(onEnter)];
671 [self resumeSchedulerAndActions];
672
673 isRunning_ = YES;
674}
675
676-(void) onEnterTransitionDidFinish
677{
678 [children_ makeObjectsPerformSelector:@selector(onEnterTransitionDidFinish)];
679}
680
681-(void) onExit
682{
683 [self pauseSchedulerAndActions];
684 isRunning_ = NO;
685
686 [children_ makeObjectsPerformSelector:@selector(onExit)];
687}
688
689#pragma mark CCNode Actions
690
691-(CCAction*) runAction:(CCAction*) action
692{
693 NSAssert( action != nil, @"Argument must be non-nil");
694
695 [[CCActionManager sharedManager] addAction:action target:self paused:!isRunning_];
696 return action;
697}
698
699-(void) stopAllActions
700{
701 [[CCActionManager sharedManager] removeAllActionsFromTarget:self];
702}
703
704-(void) stopAction: (CCAction*) action
705{
706 [[CCActionManager sharedManager] removeAction:action];
707}
708
709-(void) stopActionByTag:(NSInteger)aTag
710{
711 NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag");
712 [[CCActionManager sharedManager] removeActionByTag:aTag target:self];
713}
714
715-(CCAction*) getActionByTag:(NSInteger) aTag
716{
717 NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag");
718 return [[CCActionManager sharedManager] getActionByTag:aTag target:self];
719}
720
721-(NSUInteger) numberOfRunningActions
722{
723 return [[CCActionManager sharedManager] numberOfRunningActionsInTarget:self];
724}
725
726#pragma mark CCNode - Scheduler
727
728-(void) scheduleUpdate
729{
730 [self scheduleUpdateWithPriority:0];
731}
732
733-(void) scheduleUpdateWithPriority:(NSInteger)priority
734{
735 [[CCScheduler sharedScheduler] scheduleUpdateForTarget:self priority:priority paused:!isRunning_];
736}
737
738-(void) unscheduleUpdate
739{
740 [[CCScheduler sharedScheduler] unscheduleUpdateForTarget:self];
741}
742
743-(void) schedule:(SEL)selector
744{
745 [self schedule:selector interval:0];
746}
747
748-(void) schedule:(SEL)selector interval:(ccTime)interval
749{
750 NSAssert( selector != nil, @"Argument must be non-nil");
751 NSAssert( interval >=0, @"Arguemnt must be positive");
752
753 [[CCScheduler sharedScheduler] scheduleSelector:selector forTarget:self interval:interval paused:!isRunning_];
754}
755
756-(void) unschedule:(SEL)selector
757{
758 // explicit nil handling
759 if (selector == nil)
760 return;
761
762 [[CCScheduler sharedScheduler] unscheduleSelector:selector forTarget:self];
763}
764
765-(void) unscheduleAllSelectors
766{
767 [[CCScheduler sharedScheduler] unscheduleAllSelectorsForTarget:self];
768}
769- (void) resumeSchedulerAndActions
770{
771 [[CCScheduler sharedScheduler] resumeTarget:self];
772 [[CCActionManager sharedManager] resumeTarget:self];
773}
774
775- (void) pauseSchedulerAndActions
776{
777 [[CCScheduler sharedScheduler] pauseTarget:self];
778 [[CCActionManager sharedManager] pauseTarget:self];
779}
780
781#pragma mark CCNode Transform
782
783- (CGAffineTransform)nodeToParentTransform
784{
785 if ( isTransformDirty_ ) {
786
787 transform_ = CGAffineTransformIdentity;
788
789 if ( !isRelativeAnchorPoint_ && !CGPointEqualToPoint(anchorPointInPixels_, CGPointZero) )
790 transform_ = CGAffineTransformTranslate(transform_, anchorPointInPixels_.x, anchorPointInPixels_.y);
791
792 if( ! CGPointEqualToPoint(positionInPixels_, CGPointZero) )
793 transform_ = CGAffineTransformTranslate(transform_, positionInPixels_.x, positionInPixels_.y);
794
795 if( rotation_ != 0 )
796 transform_ = CGAffineTransformRotate(transform_, -CC_DEGREES_TO_RADIANS(rotation_));
797
798 if( skewX_ != 0 || skewY_ != 0 ) {
799 // create a skewed coordinate system
800 CGAffineTransform skew = CGAffineTransformMake(1.0f, tanf(CC_DEGREES_TO_RADIANS(skewY_)), tanf(CC_DEGREES_TO_RADIANS(skewX_)), 1.0f, 0.0f, 0.0f);
801 // apply the skew to the transform
802 transform_ = CGAffineTransformConcat(skew, transform_);
803 }
804
805 if( ! (scaleX_ == 1 && scaleY_ == 1) )
806 transform_ = CGAffineTransformScale(transform_, scaleX_, scaleY_);
807
808 if( ! CGPointEqualToPoint(anchorPointInPixels_, CGPointZero) )
809 transform_ = CGAffineTransformTranslate(transform_, -anchorPointInPixels_.x, -anchorPointInPixels_.y);
810
811 isTransformDirty_ = NO;
812 }
813
814 return transform_;
815}
816
817- (CGAffineTransform)parentToNodeTransform
818{
819 if ( isInverseDirty_ ) {
820 inverse_ = CGAffineTransformInvert([self nodeToParentTransform]);
821 isInverseDirty_ = NO;
822 }
823
824 return inverse_;
825}
826
827- (CGAffineTransform)nodeToWorldTransform
828{
829 CGAffineTransform t = [self nodeToParentTransform];
830
831 for (CCNode *p = parent_; p != nil; p = p.parent)
832 t = CGAffineTransformConcat(t, [p nodeToParentTransform]);
833
834 return t;
835}
836
837- (CGAffineTransform)worldToNodeTransform
838{
839 return CGAffineTransformInvert([self nodeToWorldTransform]);
840}
841
842- (CGPoint)convertToNodeSpace:(CGPoint)worldPoint
843{
844 CGPoint ret;
845 if( CC_CONTENT_SCALE_FACTOR() == 1 )
846 ret = CGPointApplyAffineTransform(worldPoint, [self worldToNodeTransform]);
847 else {
848 ret = ccpMult( worldPoint, CC_CONTENT_SCALE_FACTOR() );
849 ret = CGPointApplyAffineTransform(ret, [self worldToNodeTransform]);
850 ret = ccpMult( ret, 1/CC_CONTENT_SCALE_FACTOR() );
851 }
852
853 return ret;
854}
855
856- (CGPoint)convertToWorldSpace:(CGPoint)nodePoint
857{
858 CGPoint ret;
859 if( CC_CONTENT_SCALE_FACTOR() == 1 )
860 ret = CGPointApplyAffineTransform(nodePoint, [self nodeToWorldTransform]);
861 else {
862 ret = ccpMult( nodePoint, CC_CONTENT_SCALE_FACTOR() );
863 ret = CGPointApplyAffineTransform(ret, [self nodeToWorldTransform]);
864 ret = ccpMult( ret, 1/CC_CONTENT_SCALE_FACTOR() );
865 }
866
867 return ret;
868}
869
870- (CGPoint)convertToNodeSpaceAR:(CGPoint)worldPoint
871{
872 CGPoint nodePoint = [self convertToNodeSpace:worldPoint];
873 CGPoint anchorInPoints;
874 if( CC_CONTENT_SCALE_FACTOR() == 1 )
875 anchorInPoints = anchorPointInPixels_;
876 else
877 anchorInPoints = ccpMult( anchorPointInPixels_, 1/CC_CONTENT_SCALE_FACTOR() );
878
879 return ccpSub(nodePoint, anchorInPoints);
880}
881
882- (CGPoint)convertToWorldSpaceAR:(CGPoint)nodePoint
883{
884 CGPoint anchorInPoints;
885 if( CC_CONTENT_SCALE_FACTOR() == 1 )
886 anchorInPoints = anchorPointInPixels_;
887 else
888 anchorInPoints = ccpMult( anchorPointInPixels_, 1/CC_CONTENT_SCALE_FACTOR() );
889
890 nodePoint = ccpAdd(nodePoint, anchorInPoints);
891 return [self convertToWorldSpace:nodePoint];
892}
893
894- (CGPoint)convertToWindowSpace:(CGPoint)nodePoint
895{
896 CGPoint worldPoint = [self convertToWorldSpace:nodePoint];
897 return [[CCDirector sharedDirector] convertToUI:worldPoint];
898}
899
900// convenience methods which take a UITouch instead of CGPoint
901
902#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
903
904- (CGPoint)convertTouchToNodeSpace:(UITouch *)touch
905{
906 CGPoint point = [touch locationInView: [touch view]];
907 point = [[CCDirector sharedDirector] convertToGL: point];
908 return [self convertToNodeSpace:point];
909}
910
911- (CGPoint)convertTouchToNodeSpaceAR:(UITouch *)touch
912{
913 CGPoint point = [touch locationInView: [touch view]];
914 point = [[CCDirector sharedDirector] convertToGL: point];
915 return [self convertToNodeSpaceAR:point];
916}
917
918#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
919
920
921@end