diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..85e9021 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,11 @@ +Changes: + +June 18, 2012: Send current page is done typing message to the delegate after a touch completes the page - Tebruno99 + +June 16, 2012: Add new notification that the current page is done typing. - Tebruno99 + +June 16, 2012: Refactor the typing so that text speed is settable and it uses characters per second. -Tebruno99 + +June 16, 2012: Fix performance issue with main for loop in TextBoxLayer by elminating the for loop and not iterating over the entire array of characters. - Tebruno99 + +June 16, 2012: Updated to 1.1beta2 cocos2d - Tebruno99 \ No newline at end of file diff --git a/Classes/HelloWorldScene.m b/Classes/HelloWorldScene.m index 6c75aaf..fdc593f 100755 --- a/Classes/HelloWorldScene.m +++ b/Classes/HelloWorldScene.m @@ -44,11 +44,11 @@ -(id) init NSString *txt = @"This is a purposefully long text so as to test the wrapping functionality of the TextBoxLayer, as well as the multiple pages. That's it! This is the end, my only friend, the end."; - textBox = [[TextBoxLayer alloc] initWithColor:[UIColor blueColor] width:200 height:80 padding:10 text:txt]; + textBox = [[TextBoxLayer alloc] initWithColor:[UIColor blueColor] width:200 height:80 padding:10 speed:0.01f text:txt]; textBox.position = ccp( size.width /2 , size.height/2 ); textBox.delegate = self; - textBoxView = [[TextBoxView alloc] initWithColor:[UIColor blueColor] width:200 height:80 padding:10 text:txt]; + textBoxView = [[TextBoxView alloc] initWithColor:[UIColor blueColor] width:200 height:80 padding:10 speed:80 text:txt]; textBoxView.center = ccp( size.width /2 , size.height/2 ); textBoxView.delegate = self; diff --git a/Classes/TextBox.h b/Classes/TextBox.h index cf64527..12fc282 100644 --- a/Classes/TextBox.h +++ b/Classes/TextBox.h @@ -16,7 +16,8 @@ - (id) initWithColor:(UIColor *)color width:(CGFloat)w height:(CGFloat)h - padding:(CGFloat)padding + padding:(CGFloat)padding + speed:(CGFloat)ts text:(NSString *)txt; - (void)update:(float)dt; @@ -29,5 +30,5 @@ @optional - (void)textBox:(id)tbox didMoveToPage:(int)p; - +- (void)textBox:(id)tbox didFinishAllTextOnPage:(int)p; @end diff --git a/Classes/TextBoxLayer.h b/Classes/TextBoxLayer.h index f36fb0a..ee62fd6 100644 --- a/Classes/TextBoxLayer.h +++ b/Classes/TextBoxLayer.h @@ -22,7 +22,9 @@ int currentPageIndex; NSMutableString *currentPage; int currentPageCharCount; - + CGFloat textSpeed; + ccTime countDownTimer; + int totalPages; id delegate; diff --git a/Classes/TextBoxLayer.m b/Classes/TextBoxLayer.m index 981d945..3794872 100644 --- a/Classes/TextBoxLayer.m +++ b/Classes/TextBoxLayer.m @@ -7,12 +7,13 @@ // #import "TextBoxLayer.h" +#import "uthash.h" @implementation TextBoxLayer @synthesize delegate; -- (id) initWithColor:(UIColor *)color width:(CGFloat)w height:(CGFloat)h padding:(CGFloat)padding text:(NSString *)txt { +- (id) initWithColor:(UIColor *)color width:(CGFloat)w height:(CGFloat)h padding:(CGFloat)padding speed:(CGFloat)ts text:(NSString *)txt { int numComponents = CGColorGetNumberOfComponents(color.CGColor); @@ -30,9 +31,11 @@ - (id) initWithColor:(UIColor *)color width:(CGFloat)w height:(CGFloat)h padding ccColor4B col = ccc4((GLubyte) r * 255 , (GLubyte) g * 255, (GLubyte) b * 255, (GLubyte) a * 255); if ((self = [super initWithColor:col width:w + (padding * 2) height:h + (padding * 2)])) { + + self.isTouchEnabled = YES; - self.isTouchEnabled = YES; - + textSpeed = ts; + countDownTimer = textSpeed; // Arm the countdown timer. ended = NO; currentPageIndex = 0; @@ -103,30 +106,33 @@ - (void)dealloc { [super dealloc]; } -- (void)update:(float)dt { - - progress += (dt * TEXT_SPEED); - - int visible = progress; - - if (visible > currentPageCharCount) { - progress = visible = currentPageCharCount; - } - - // Each character sprite is assigned a tag corresponding to its index in the string, - // and even though line-breaks are skipped, they are still counted for tag purposes. - // Therefore, we use an offset so that the tag is correct. - int offset = 0; - - for (int i = 0; i < visible; i++) { - - if ([currentPage characterAtIndex:i + offset] == '\n') { - offset++; - } - - CCSprite *charSpr = (CCSprite *) [textLabel getChildByTag:i + offset]; - charSpr.opacity = 255; - } +- (void)update:(ccTime)dt { + static int newLineOffset = 0; + if(progress > currentPageCharCount - 1) { + newLineOffset = 0; + return; + } + + countDownTimer = countDownTimer - dt; + + if(countDownTimer < 0) { + if ([currentPage characterAtIndex:progress + newLineOffset] == '\n') { + newLineOffset++; + } + + CCSprite *charSpr = (CCSprite *) [textLabel getChildByTag:progress + newLineOffset]; + charSpr.opacity = 255; + + progress++; + + countDownTimer = textSpeed; + } + + if(progress > currentPageCharCount - 1) { + if ([delegate respondsToSelector:@selector(textBox:didFinishAllTextOnPage:)]) { + [delegate textBox:(id) self didFinishAllTextOnPage:currentPageIndex]; + } + } } - (NSString *)nextPage { @@ -160,8 +166,9 @@ - (int)calculateStringSize:(NSString *)txt { for (int i = 0; i < [txt length] / [CCDirector sharedDirector].contentScaleFactor; i++) { int c = [txt characterAtIndex:i]; - ccBMFontDef def = conf->BMFontArray_[c]; - totalSize += def.xAdvance; + ccBMFontDef *def = NULL; + HASH_FIND_INT(conf->BMFontHash_,&c,def); + totalSize += def->xAdvance; } return totalSize; @@ -176,6 +183,11 @@ -(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { charSpr.opacity = 255; } progress = currentPageCharCount; + if(progress > currentPageCharCount - 1) { + if ([delegate respondsToSelector:@selector(textBox:didFinishAllTextOnPage:)]) { + [delegate textBox:(id) self didFinishAllTextOnPage:currentPageIndex]; + } + } } else { diff --git a/Classes/TextBoxView.h b/Classes/TextBoxView.h index 0a586f2..8920a9d 100644 --- a/Classes/TextBoxView.h +++ b/Classes/TextBoxView.h @@ -19,6 +19,7 @@ float progress; int currentPage; + CGFloat textSpeed; NSMutableArray *pages; diff --git a/Classes/TextBoxView.m b/Classes/TextBoxView.m index a65337d..67212f6 100644 --- a/Classes/TextBoxView.m +++ b/Classes/TextBoxView.m @@ -13,7 +13,7 @@ @implementation TextBoxView @synthesize delegate; -- (id) initWithColor:(UIColor *)color width:(CGFloat)w height:(CGFloat)h padding:(CGFloat)padding text:(NSString *)txt { +- (id) initWithColor:(UIColor *)color width:(CGFloat)w height:(CGFloat)h padding:(CGFloat)padding speed:(CGFloat)ts text:(NSString *)txt { if ((self = [super initWithFrame:CGRectMake(0, 0, w + (padding * 2), h + (padding * 2))])) { self.backgroundColor = color; @@ -21,6 +21,7 @@ - (id) initWithColor:(UIColor *)color width:(CGFloat)w height:(CGFloat)h padding width = w; height = h; + textSpeed = ts; currentPage = 0; text = [txt retain]; @@ -68,7 +69,7 @@ - (void)update:(float)dt { NSString *page = [pages objectAtIndex:currentPage]; - progress += (dt * TEXT_SPEED); + progress += (dt * textSpeed); int visible = progress; if (visible > [page length]) { diff --git a/TextBoxLayerSample.xcodeproj/project.pbxproj b/TextBoxLayerSample.xcodeproj/project.pbxproj index 7782217..0db13e4 100755 --- a/TextBoxLayerSample.xcodeproj/project.pbxproj +++ b/TextBoxLayerSample.xcodeproj/project.pbxproj @@ -54,12 +54,8 @@ 50F41335106926B2002A0D5E /* CDataScanner.m in Sources */ = {isa = PBXBuildFile; fileRef = 50F41313106926B2002A0D5E /* CDataScanner.m */; }; 50F41336106926B2002A0D5E /* CDataScanner_Extensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 50F41315106926B2002A0D5E /* CDataScanner_Extensions.h */; }; 50F41337106926B2002A0D5E /* CDataScanner_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 50F41316106926B2002A0D5E /* CDataScanner_Extensions.m */; }; - 50F41338106926B2002A0D5E /* NSCharacterSet_Extensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 50F41317106926B2002A0D5E /* NSCharacterSet_Extensions.h */; }; - 50F41339106926B2002A0D5E /* NSCharacterSet_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 50F41318106926B2002A0D5E /* NSCharacterSet_Extensions.m */; }; 50F4133A106926B2002A0D5E /* NSDictionary_JSONExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 50F41319106926B2002A0D5E /* NSDictionary_JSONExtensions.h */; }; 50F4133B106926B2002A0D5E /* NSDictionary_JSONExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 50F4131A106926B2002A0D5E /* NSDictionary_JSONExtensions.m */; }; - 50F4133C106926B2002A0D5E /* NSScanner_Extensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 50F4131B106926B2002A0D5E /* NSScanner_Extensions.h */; }; - 50F4133D106926B2002A0D5E /* NSScanner_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 50F4131C106926B2002A0D5E /* NSScanner_Extensions.m */; }; 50F4133E106926B2002A0D5E /* CJSONDeserializer.h in Headers */ = {isa = PBXBuildFile; fileRef = 50F4131E106926B2002A0D5E /* CJSONDeserializer.h */; }; 50F4133F106926B2002A0D5E /* CJSONDeserializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 50F4131F106926B2002A0D5E /* CJSONDeserializer.m */; }; 50F41340106926B2002A0D5E /* CJSONScanner.h in Headers */ = {isa = PBXBuildFile; fileRef = 50F41320106926B2002A0D5E /* CJSONScanner.h */; }; @@ -84,173 +80,174 @@ E02BB507126CA50F006E46A2 /* Icon-Small-50.png in Resources */ = {isa = PBXBuildFile; fileRef = E02BB501126CA50F006E46A2 /* Icon-Small-50.png */; }; E02BB508126CA50F006E46A2 /* Icon-72.png in Resources */ = {isa = PBXBuildFile; fileRef = E02BB502126CA50F006E46A2 /* Icon-72.png */; }; E02BB763126CC1E0006E46A2 /* iTunesArtwork in Resources */ = {isa = PBXBuildFile; fileRef = E02BB762126CC1E0006E46A2 /* iTunesArtwork */; }; - E02BB80F126CC224006E46A2 /* CCAction.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB765126CC223006E46A2 /* CCAction.h */; }; - E02BB810126CC224006E46A2 /* CCAction.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB766126CC223006E46A2 /* CCAction.m */; }; - E02BB811126CC224006E46A2 /* CCActionCamera.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB767126CC223006E46A2 /* CCActionCamera.h */; }; - E02BB812126CC224006E46A2 /* CCActionCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB768126CC223006E46A2 /* CCActionCamera.m */; }; - E02BB813126CC224006E46A2 /* CCActionEase.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB769126CC223006E46A2 /* CCActionEase.h */; }; - E02BB814126CC224006E46A2 /* CCActionEase.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB76A126CC223006E46A2 /* CCActionEase.m */; }; - E02BB815126CC224006E46A2 /* CCActionGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB76B126CC223006E46A2 /* CCActionGrid.h */; }; - E02BB816126CC224006E46A2 /* CCActionGrid.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB76C126CC223006E46A2 /* CCActionGrid.m */; }; - E02BB817126CC224006E46A2 /* CCActionGrid3D.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB76D126CC223006E46A2 /* CCActionGrid3D.h */; }; - E02BB818126CC224006E46A2 /* CCActionGrid3D.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB76E126CC223006E46A2 /* CCActionGrid3D.m */; }; - E02BB819126CC224006E46A2 /* CCActionInstant.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB76F126CC223006E46A2 /* CCActionInstant.h */; }; - E02BB81A126CC224006E46A2 /* CCActionInstant.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB770126CC223006E46A2 /* CCActionInstant.m */; }; - E02BB81B126CC224006E46A2 /* CCActionInterval.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB771126CC223006E46A2 /* CCActionInterval.h */; }; - E02BB81C126CC224006E46A2 /* CCActionInterval.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB772126CC223006E46A2 /* CCActionInterval.m */; }; - E02BB81D126CC224006E46A2 /* CCActionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB773126CC223006E46A2 /* CCActionManager.h */; }; - E02BB81E126CC224006E46A2 /* CCActionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB774126CC223006E46A2 /* CCActionManager.m */; }; - E02BB81F126CC224006E46A2 /* CCActionPageTurn3D.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB775126CC223006E46A2 /* CCActionPageTurn3D.h */; }; - E02BB820126CC224006E46A2 /* CCActionPageTurn3D.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB776126CC223006E46A2 /* CCActionPageTurn3D.m */; }; - E02BB821126CC224006E46A2 /* CCActionProgressTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB777126CC223006E46A2 /* CCActionProgressTimer.h */; }; - E02BB822126CC224006E46A2 /* CCActionProgressTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB778126CC223006E46A2 /* CCActionProgressTimer.m */; }; - E02BB823126CC224006E46A2 /* CCActionTiledGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB779126CC223006E46A2 /* CCActionTiledGrid.h */; }; - E02BB824126CC224006E46A2 /* CCActionTiledGrid.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB77A126CC223006E46A2 /* CCActionTiledGrid.m */; }; - E02BB825126CC224006E46A2 /* CCActionTween.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB77B126CC223006E46A2 /* CCActionTween.h */; }; - E02BB826126CC224006E46A2 /* CCActionTween.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB77C126CC223006E46A2 /* CCActionTween.m */; }; - E02BB827126CC224006E46A2 /* CCAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB77D126CC223006E46A2 /* CCAnimation.h */; }; - E02BB828126CC224006E46A2 /* CCAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB77E126CC223006E46A2 /* CCAnimation.m */; }; - E02BB829126CC224006E46A2 /* CCAnimationCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB77F126CC223006E46A2 /* CCAnimationCache.h */; }; - E02BB82A126CC224006E46A2 /* CCAnimationCache.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB780126CC223006E46A2 /* CCAnimationCache.m */; }; - E02BB82B126CC224006E46A2 /* CCAtlasNode.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB781126CC223006E46A2 /* CCAtlasNode.h */; }; - E02BB82C126CC224006E46A2 /* CCAtlasNode.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB782126CC223006E46A2 /* CCAtlasNode.m */; }; - E02BB82D126CC224006E46A2 /* CCBlockSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB783126CC223006E46A2 /* CCBlockSupport.h */; }; - E02BB82E126CC224006E46A2 /* CCBlockSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB784126CC223006E46A2 /* CCBlockSupport.m */; }; - E02BB82F126CC224006E46A2 /* CCCamera.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB785126CC223006E46A2 /* CCCamera.h */; }; - E02BB830126CC224006E46A2 /* CCCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB786126CC223006E46A2 /* CCCamera.m */; }; - E02BB831126CC224006E46A2 /* CCCompatibility.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB787126CC223006E46A2 /* CCCompatibility.h */; }; - E02BB832126CC224006E46A2 /* CCCompatibility.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB788126CC223006E46A2 /* CCCompatibility.m */; }; - E02BB833126CC224006E46A2 /* ccConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB789126CC223006E46A2 /* ccConfig.h */; }; - E02BB834126CC224006E46A2 /* CCConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB78A126CC223006E46A2 /* CCConfiguration.h */; }; - E02BB835126CC224006E46A2 /* CCConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB78B126CC223006E46A2 /* CCConfiguration.m */; }; - E02BB836126CC224006E46A2 /* CCDirector.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB78C126CC223006E46A2 /* CCDirector.h */; }; - E02BB837126CC224006E46A2 /* CCDirector.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB78D126CC223006E46A2 /* CCDirector.m */; }; - E02BB838126CC224006E46A2 /* CCDrawingPrimitives.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB78E126CC223006E46A2 /* CCDrawingPrimitives.h */; }; - E02BB839126CC224006E46A2 /* CCDrawingPrimitives.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB78F126CC223006E46A2 /* CCDrawingPrimitives.m */; }; - E02BB83A126CC224006E46A2 /* CCGrabber.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB790126CC223006E46A2 /* CCGrabber.h */; }; - E02BB83B126CC224006E46A2 /* CCGrabber.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB791126CC223006E46A2 /* CCGrabber.m */; }; - E02BB83C126CC224006E46A2 /* CCGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB792126CC223006E46A2 /* CCGrid.h */; }; - E02BB83D126CC224006E46A2 /* CCGrid.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB793126CC223006E46A2 /* CCGrid.m */; }; - E02BB83E126CC224006E46A2 /* CCLabelAtlas.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB794126CC223006E46A2 /* CCLabelAtlas.h */; }; - E02BB83F126CC224006E46A2 /* CCLabelAtlas.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB795126CC223006E46A2 /* CCLabelAtlas.m */; }; - E02BB840126CC224006E46A2 /* CCLabelBMFont.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB796126CC223006E46A2 /* CCLabelBMFont.h */; }; - E02BB841126CC224006E46A2 /* CCLabelBMFont.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB797126CC223006E46A2 /* CCLabelBMFont.m */; }; - E02BB842126CC224006E46A2 /* CCLabelTTF.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB798126CC223006E46A2 /* CCLabelTTF.h */; }; - E02BB843126CC224006E46A2 /* CCLabelTTF.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB799126CC223006E46A2 /* CCLabelTTF.m */; }; - E02BB844126CC224006E46A2 /* CCLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB79A126CC223006E46A2 /* CCLayer.h */; }; - E02BB845126CC224006E46A2 /* CCLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB79B126CC223006E46A2 /* CCLayer.m */; }; - E02BB846126CC224006E46A2 /* ccMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB79C126CC223006E46A2 /* ccMacros.h */; }; - E02BB847126CC224006E46A2 /* CCMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB79D126CC223006E46A2 /* CCMenu.h */; }; - E02BB848126CC224006E46A2 /* CCMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB79E126CC223006E46A2 /* CCMenu.m */; }; - E02BB849126CC224006E46A2 /* CCMenuItem.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB79F126CC224006E46A2 /* CCMenuItem.h */; }; - E02BB84A126CC224006E46A2 /* CCMenuItem.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7A0126CC224006E46A2 /* CCMenuItem.m */; }; - E02BB84B126CC224006E46A2 /* CCMotionStreak.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7A1126CC224006E46A2 /* CCMotionStreak.h */; }; - E02BB84C126CC224006E46A2 /* CCMotionStreak.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7A2126CC224006E46A2 /* CCMotionStreak.m */; }; - E02BB84D126CC224006E46A2 /* CCNode.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7A3126CC224006E46A2 /* CCNode.h */; }; - E02BB84E126CC224006E46A2 /* CCNode.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7A4126CC224006E46A2 /* CCNode.m */; }; - E02BB84F126CC224006E46A2 /* CCParallaxNode.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7A5126CC224006E46A2 /* CCParallaxNode.h */; }; - E02BB850126CC224006E46A2 /* CCParallaxNode.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7A6126CC224006E46A2 /* CCParallaxNode.m */; }; - E02BB851126CC224006E46A2 /* CCParticleExamples.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7A7126CC224006E46A2 /* CCParticleExamples.h */; }; - E02BB852126CC224006E46A2 /* CCParticleExamples.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7A8126CC224006E46A2 /* CCParticleExamples.m */; }; - E02BB853126CC224006E46A2 /* CCParticleSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7A9126CC224006E46A2 /* CCParticleSystem.h */; }; - E02BB854126CC224006E46A2 /* CCParticleSystem.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7AA126CC224006E46A2 /* CCParticleSystem.m */; }; - E02BB855126CC224006E46A2 /* CCParticleSystemPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7AB126CC224006E46A2 /* CCParticleSystemPoint.h */; }; - E02BB856126CC224006E46A2 /* CCParticleSystemPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7AC126CC224006E46A2 /* CCParticleSystemPoint.m */; }; - E02BB857126CC224006E46A2 /* CCParticleSystemQuad.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7AD126CC224006E46A2 /* CCParticleSystemQuad.h */; }; - E02BB858126CC224006E46A2 /* CCParticleSystemQuad.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7AE126CC224006E46A2 /* CCParticleSystemQuad.m */; }; - E02BB859126CC224006E46A2 /* CCProgressTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7AF126CC224006E46A2 /* CCProgressTimer.h */; }; - E02BB85A126CC224006E46A2 /* CCProgressTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7B0126CC224006E46A2 /* CCProgressTimer.m */; }; - E02BB85B126CC224006E46A2 /* CCProtocols.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7B1126CC224006E46A2 /* CCProtocols.h */; }; - E02BB85C126CC224006E46A2 /* CCRenderTexture.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7B2126CC224006E46A2 /* CCRenderTexture.h */; }; - E02BB85D126CC224006E46A2 /* CCRenderTexture.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7B3126CC224006E46A2 /* CCRenderTexture.m */; }; - E02BB85E126CC224006E46A2 /* CCRibbon.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7B4126CC224006E46A2 /* CCRibbon.h */; }; - E02BB85F126CC224006E46A2 /* CCRibbon.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7B5126CC224006E46A2 /* CCRibbon.m */; }; - E02BB860126CC224006E46A2 /* CCScene.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7B6126CC224006E46A2 /* CCScene.h */; }; - E02BB861126CC224006E46A2 /* CCScene.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7B7126CC224006E46A2 /* CCScene.m */; }; - E02BB862126CC224006E46A2 /* CCScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7B8126CC224006E46A2 /* CCScheduler.h */; }; - E02BB863126CC224006E46A2 /* CCScheduler.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7B9126CC224006E46A2 /* CCScheduler.m */; }; - E02BB864126CC224006E46A2 /* CCSprite.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7BA126CC224006E46A2 /* CCSprite.h */; }; - E02BB865126CC224006E46A2 /* CCSprite.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7BB126CC224006E46A2 /* CCSprite.m */; }; - E02BB866126CC224006E46A2 /* CCSpriteBatchNode.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7BC126CC224006E46A2 /* CCSpriteBatchNode.h */; }; - E02BB867126CC224006E46A2 /* CCSpriteBatchNode.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7BD126CC224006E46A2 /* CCSpriteBatchNode.m */; }; - E02BB868126CC224006E46A2 /* CCSpriteFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7BE126CC224006E46A2 /* CCSpriteFrame.h */; }; - E02BB869126CC224006E46A2 /* CCSpriteFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7BF126CC224006E46A2 /* CCSpriteFrame.m */; }; - E02BB86A126CC224006E46A2 /* CCSpriteFrameCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7C0126CC224006E46A2 /* CCSpriteFrameCache.h */; }; - E02BB86B126CC224006E46A2 /* CCSpriteFrameCache.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7C1126CC224006E46A2 /* CCSpriteFrameCache.m */; }; - E02BB86C126CC224006E46A2 /* CCSpriteSheet.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7C2126CC224006E46A2 /* CCSpriteSheet.h */; }; - E02BB86D126CC224006E46A2 /* CCSpriteSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7C3126CC224006E46A2 /* CCSpriteSheet.m */; }; - E02BB86E126CC224006E46A2 /* CCTexture2D.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7C4126CC224006E46A2 /* CCTexture2D.h */; }; - E02BB86F126CC224006E46A2 /* CCTexture2D.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7C5126CC224006E46A2 /* CCTexture2D.m */; }; - E02BB870126CC224006E46A2 /* CCTextureAtlas.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7C6126CC224006E46A2 /* CCTextureAtlas.h */; }; - E02BB871126CC224006E46A2 /* CCTextureAtlas.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7C7126CC224006E46A2 /* CCTextureAtlas.m */; }; - E02BB872126CC224006E46A2 /* CCTextureCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7C8126CC224006E46A2 /* CCTextureCache.h */; }; - E02BB873126CC224006E46A2 /* CCTextureCache.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7C9126CC224006E46A2 /* CCTextureCache.m */; }; - E02BB874126CC224006E46A2 /* CCTexturePVR.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7CA126CC224006E46A2 /* CCTexturePVR.h */; }; - E02BB875126CC224006E46A2 /* CCTexturePVR.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7CB126CC224006E46A2 /* CCTexturePVR.m */; }; - E02BB876126CC224006E46A2 /* CCTileMapAtlas.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7CC126CC224006E46A2 /* CCTileMapAtlas.h */; }; - E02BB877126CC224006E46A2 /* CCTileMapAtlas.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7CD126CC224006E46A2 /* CCTileMapAtlas.m */; }; - E02BB878126CC224006E46A2 /* CCTMXLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7CE126CC224006E46A2 /* CCTMXLayer.h */; }; - E02BB879126CC224006E46A2 /* CCTMXLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7CF126CC224006E46A2 /* CCTMXLayer.m */; }; - E02BB87A126CC224006E46A2 /* CCTMXObjectGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7D0126CC224006E46A2 /* CCTMXObjectGroup.h */; }; - E02BB87B126CC224006E46A2 /* CCTMXObjectGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7D1126CC224006E46A2 /* CCTMXObjectGroup.m */; }; - E02BB87C126CC224006E46A2 /* CCTMXTiledMap.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7D2126CC224006E46A2 /* CCTMXTiledMap.h */; }; - E02BB87D126CC224006E46A2 /* CCTMXTiledMap.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7D3126CC224006E46A2 /* CCTMXTiledMap.m */; }; - E02BB87E126CC224006E46A2 /* CCTMXXMLParser.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7D4126CC224006E46A2 /* CCTMXXMLParser.h */; }; - E02BB87F126CC224006E46A2 /* CCTMXXMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7D5126CC224006E46A2 /* CCTMXXMLParser.m */; }; - E02BB880126CC224006E46A2 /* CCTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7D6126CC224006E46A2 /* CCTransition.h */; }; - E02BB881126CC224006E46A2 /* CCTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7D7126CC224006E46A2 /* CCTransition.m */; }; - E02BB882126CC224006E46A2 /* CCTransitionPageTurn.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7D8126CC224006E46A2 /* CCTransitionPageTurn.h */; }; - E02BB883126CC224006E46A2 /* CCTransitionPageTurn.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7D9126CC224006E46A2 /* CCTransitionPageTurn.m */; }; - E02BB884126CC224006E46A2 /* CCTransitionRadial.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7DA126CC224006E46A2 /* CCTransitionRadial.h */; }; - E02BB885126CC224006E46A2 /* CCTransitionRadial.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7DB126CC224006E46A2 /* CCTransitionRadial.m */; }; - E02BB886126CC224006E46A2 /* ccTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7DC126CC224006E46A2 /* ccTypes.h */; }; - E02BB887126CC224006E46A2 /* cocos2d.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7DD126CC224006E46A2 /* cocos2d.h */; }; - E02BB888126CC224006E46A2 /* cocos2d.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7DE126CC224006E46A2 /* cocos2d.m */; }; - E02BB889126CC224006E46A2 /* CCGL.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7E0126CC224006E46A2 /* CCGL.h */; }; - E02BB88A126CC224006E46A2 /* CCNS.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7E1126CC224006E46A2 /* CCNS.h */; }; - E02BB88B126CC224006E46A2 /* CCDirectorIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7E3126CC224006E46A2 /* CCDirectorIOS.h */; }; - E02BB88C126CC224006E46A2 /* CCDirectorIOS.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7E4126CC224006E46A2 /* CCDirectorIOS.m */; }; - E02BB88D126CC224006E46A2 /* CCTouchDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7E5126CC224006E46A2 /* CCTouchDelegateProtocol.h */; }; - E02BB88E126CC224006E46A2 /* CCTouchDispatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7E6126CC224006E46A2 /* CCTouchDispatcher.h */; }; - E02BB88F126CC224006E46A2 /* CCTouchDispatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7E7126CC224006E46A2 /* CCTouchDispatcher.m */; }; - E02BB890126CC224006E46A2 /* CCTouchHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7E8126CC224006E46A2 /* CCTouchHandler.h */; }; - E02BB891126CC224006E46A2 /* CCTouchHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7E9126CC224006E46A2 /* CCTouchHandler.m */; }; - E02BB892126CC224006E46A2 /* EAGLView.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7EA126CC224006E46A2 /* EAGLView.h */; }; - E02BB893126CC224006E46A2 /* EAGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7EB126CC224006E46A2 /* EAGLView.m */; }; - E02BB894126CC224006E46A2 /* ES1Renderer.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7EC126CC224006E46A2 /* ES1Renderer.h */; }; - E02BB895126CC224006E46A2 /* ES1Renderer.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7ED126CC224006E46A2 /* ES1Renderer.m */; }; - E02BB896126CC224006E46A2 /* ESRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7EE126CC224006E46A2 /* ESRenderer.h */; }; - E02BB897126CC224006E46A2 /* glu.c in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7EF126CC224006E46A2 /* glu.c */; }; - E02BB898126CC224006E46A2 /* glu.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7F0126CC224006E46A2 /* glu.h */; }; - E02BB899126CC224006E46A2 /* CCDirectorMac.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7F2126CC224006E46A2 /* CCDirectorMac.h */; }; - E02BB89A126CC224006E46A2 /* CCDirectorMac.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7F3126CC224006E46A2 /* CCDirectorMac.m */; }; - E02BB89B126CC224006E46A2 /* CCEventDispatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7F4126CC224006E46A2 /* CCEventDispatcher.h */; }; - E02BB89C126CC224006E46A2 /* CCEventDispatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7F5126CC224006E46A2 /* CCEventDispatcher.m */; }; - E02BB89D126CC224006E46A2 /* MacGLView.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7F6126CC224006E46A2 /* MacGLView.h */; }; - E02BB89E126CC224006E46A2 /* MacGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7F7126CC224006E46A2 /* MacGLView.m */; }; - E02BB89F126CC224006E46A2 /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7F9126CC224006E46A2 /* base64.c */; }; - E02BB8A0126CC224006E46A2 /* base64.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7FA126CC224006E46A2 /* base64.h */; }; - E02BB8A1126CC224006E46A2 /* CCArray.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7FB126CC224006E46A2 /* CCArray.h */; }; - E02BB8A2126CC224006E46A2 /* CCArray.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7FC126CC224006E46A2 /* CCArray.m */; }; - E02BB8A3126CC224006E46A2 /* ccCArray.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7FD126CC224006E46A2 /* ccCArray.h */; }; - E02BB8A4126CC224006E46A2 /* CCFileUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB7FE126CC224006E46A2 /* CCFileUtils.h */; }; - E02BB8A5126CC224006E46A2 /* CCFileUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB7FF126CC224006E46A2 /* CCFileUtils.m */; }; - E02BB8A6126CC224006E46A2 /* CCProfiling.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB800126CC224006E46A2 /* CCProfiling.h */; }; - E02BB8A7126CC224006E46A2 /* CCProfiling.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB801126CC224006E46A2 /* CCProfiling.m */; }; - E02BB8A8126CC224006E46A2 /* ccUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = E02BB802126CC224006E46A2 /* ccUtils.c */; }; - E02BB8A9126CC224006E46A2 /* ccUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB803126CC224006E46A2 /* ccUtils.h */; }; - E02BB8AA126CC224006E46A2 /* CGPointExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB804126CC224006E46A2 /* CGPointExtension.h */; }; - E02BB8AB126CC224006E46A2 /* CGPointExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB805126CC224006E46A2 /* CGPointExtension.m */; }; - E02BB8AC126CC224006E46A2 /* OpenGL_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB806126CC224006E46A2 /* OpenGL_Internal.h */; }; - E02BB8AD126CC224006E46A2 /* TGAlib.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB807126CC224006E46A2 /* TGAlib.h */; }; - E02BB8AE126CC224006E46A2 /* TGAlib.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB808126CC224006E46A2 /* TGAlib.m */; }; - E02BB8AF126CC224006E46A2 /* TransformUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB809126CC224006E46A2 /* TransformUtils.h */; }; - E02BB8B0126CC224006E46A2 /* TransformUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB80A126CC224006E46A2 /* TransformUtils.m */; }; - E02BB8B1126CC224006E46A2 /* uthash.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB80B126CC224006E46A2 /* uthash.h */; }; - E02BB8B2126CC224006E46A2 /* utlist.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB80C126CC224006E46A2 /* utlist.h */; }; - E02BB8B3126CC224006E46A2 /* ZipUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB80D126CC224006E46A2 /* ZipUtils.h */; }; - E02BB8B4126CC224006E46A2 /* ZipUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = E02BB80E126CC224006E46A2 /* ZipUtils.m */; }; E0F80F60120A0182005866B8 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E0F80F5F120A0182005866B8 /* RootViewController.m */; }; + E293337D158D26470078A28A /* CCAction.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332D3158D26470078A28A /* CCAction.h */; }; + E293337E158D26470078A28A /* CCAction.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332D4158D26470078A28A /* CCAction.m */; }; + E293337F158D26470078A28A /* CCActionCamera.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332D5158D26470078A28A /* CCActionCamera.h */; }; + E2933380158D26470078A28A /* CCActionCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332D6158D26470078A28A /* CCActionCamera.m */; }; + E2933381158D26470078A28A /* CCActionEase.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332D7158D26470078A28A /* CCActionEase.h */; }; + E2933382158D26470078A28A /* CCActionEase.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332D8158D26470078A28A /* CCActionEase.m */; }; + E2933383158D26470078A28A /* CCActionGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332D9158D26470078A28A /* CCActionGrid.h */; }; + E2933384158D26470078A28A /* CCActionGrid.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332DA158D26470078A28A /* CCActionGrid.m */; }; + E2933385158D26470078A28A /* CCActionGrid3D.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332DB158D26470078A28A /* CCActionGrid3D.h */; }; + E2933386158D26470078A28A /* CCActionGrid3D.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332DC158D26470078A28A /* CCActionGrid3D.m */; }; + E2933387158D26470078A28A /* CCActionInstant.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332DD158D26470078A28A /* CCActionInstant.h */; }; + E2933388158D26470078A28A /* CCActionInstant.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332DE158D26470078A28A /* CCActionInstant.m */; }; + E2933389158D26470078A28A /* CCActionInterval.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332DF158D26470078A28A /* CCActionInterval.h */; }; + E293338A158D26470078A28A /* CCActionInterval.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332E0158D26470078A28A /* CCActionInterval.m */; }; + E293338B158D26470078A28A /* CCActionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332E1158D26470078A28A /* CCActionManager.h */; }; + E293338C158D26470078A28A /* CCActionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332E2158D26470078A28A /* CCActionManager.m */; }; + E293338D158D26470078A28A /* CCActionPageTurn3D.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332E3158D26470078A28A /* CCActionPageTurn3D.h */; }; + E293338E158D26470078A28A /* CCActionPageTurn3D.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332E4158D26470078A28A /* CCActionPageTurn3D.m */; }; + E293338F158D26470078A28A /* CCActionProgressTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332E5158D26470078A28A /* CCActionProgressTimer.h */; }; + E2933390158D26470078A28A /* CCActionProgressTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332E6158D26470078A28A /* CCActionProgressTimer.m */; }; + E2933391158D26470078A28A /* CCActionTiledGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332E7158D26470078A28A /* CCActionTiledGrid.h */; }; + E2933392158D26470078A28A /* CCActionTiledGrid.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332E8158D26470078A28A /* CCActionTiledGrid.m */; }; + E2933393158D26470078A28A /* CCActionTween.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332E9158D26470078A28A /* CCActionTween.h */; }; + E2933394158D26470078A28A /* CCActionTween.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332EA158D26470078A28A /* CCActionTween.m */; }; + E2933395158D26470078A28A /* CCAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332EB158D26470078A28A /* CCAnimation.h */; }; + E2933396158D26470078A28A /* CCAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332EC158D26470078A28A /* CCAnimation.m */; }; + E2933397158D26470078A28A /* CCAnimationCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332ED158D26470078A28A /* CCAnimationCache.h */; }; + E2933398158D26470078A28A /* CCAnimationCache.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332EE158D26470078A28A /* CCAnimationCache.m */; }; + E2933399158D26470078A28A /* CCAtlasNode.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332EF158D26470078A28A /* CCAtlasNode.h */; }; + E293339A158D26470078A28A /* CCAtlasNode.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332F0158D26470078A28A /* CCAtlasNode.m */; }; + E293339B158D26470078A28A /* CCBlockSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332F1158D26470078A28A /* CCBlockSupport.h */; }; + E293339C158D26470078A28A /* CCBlockSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332F2158D26470078A28A /* CCBlockSupport.m */; }; + E293339D158D26470078A28A /* CCCamera.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332F3158D26470078A28A /* CCCamera.h */; }; + E293339E158D26470078A28A /* CCCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332F4158D26470078A28A /* CCCamera.m */; }; + E293339F158D26470078A28A /* ccConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332F5158D26470078A28A /* ccConfig.h */; }; + E29333A0158D26470078A28A /* CCConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332F6158D26470078A28A /* CCConfiguration.h */; }; + E29333A1158D26470078A28A /* CCConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332F7158D26470078A28A /* CCConfiguration.m */; }; + E29333A2158D26470078A28A /* CCDirector.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332F8158D26470078A28A /* CCDirector.h */; }; + E29333A3158D26470078A28A /* CCDirector.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332F9158D26470078A28A /* CCDirector.m */; }; + E29333A4158D26470078A28A /* CCDrawingPrimitives.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332FA158D26470078A28A /* CCDrawingPrimitives.h */; }; + E29333A5158D26470078A28A /* CCDrawingPrimitives.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332FB158D26470078A28A /* CCDrawingPrimitives.m */; }; + E29333A6158D26470078A28A /* CCGrabber.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332FC158D26470078A28A /* CCGrabber.h */; }; + E29333A7158D26470078A28A /* CCGrabber.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332FD158D26470078A28A /* CCGrabber.m */; }; + E29333A8158D26470078A28A /* CCGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = E29332FE158D26470078A28A /* CCGrid.h */; }; + E29333A9158D26470078A28A /* CCGrid.m in Sources */ = {isa = PBXBuildFile; fileRef = E29332FF158D26470078A28A /* CCGrid.m */; }; + E29333AA158D26470078A28A /* CCLabelAtlas.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933300158D26470078A28A /* CCLabelAtlas.h */; }; + E29333AB158D26470078A28A /* CCLabelAtlas.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933301158D26470078A28A /* CCLabelAtlas.m */; }; + E29333AC158D26470078A28A /* CCLabelBMFont.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933302158D26470078A28A /* CCLabelBMFont.h */; }; + E29333AD158D26470078A28A /* CCLabelBMFont.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933303158D26470078A28A /* CCLabelBMFont.m */; }; + E29333AE158D26470078A28A /* CCLabelTTF.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933304158D26470078A28A /* CCLabelTTF.h */; }; + E29333AF158D26470078A28A /* CCLabelTTF.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933305158D26470078A28A /* CCLabelTTF.m */; }; + E29333B0158D26470078A28A /* CCLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933306158D26470078A28A /* CCLayer.h */; }; + E29333B1158D26470078A28A /* CCLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933307158D26470078A28A /* CCLayer.m */; }; + E29333B2158D26470078A28A /* ccMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933308158D26470078A28A /* ccMacros.h */; }; + E29333B3158D26470078A28A /* CCMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933309158D26470078A28A /* CCMenu.h */; }; + E29333B4158D26470078A28A /* CCMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = E293330A158D26470078A28A /* CCMenu.m */; }; + E29333B5158D26470078A28A /* CCMenuItem.h in Headers */ = {isa = PBXBuildFile; fileRef = E293330B158D26470078A28A /* CCMenuItem.h */; }; + E29333B6158D26470078A28A /* CCMenuItem.m in Sources */ = {isa = PBXBuildFile; fileRef = E293330C158D26470078A28A /* CCMenuItem.m */; }; + E29333B7158D26470078A28A /* CCMotionStreak.h in Headers */ = {isa = PBXBuildFile; fileRef = E293330D158D26470078A28A /* CCMotionStreak.h */; }; + E29333B8158D26470078A28A /* CCMotionStreak.m in Sources */ = {isa = PBXBuildFile; fileRef = E293330E158D26470078A28A /* CCMotionStreak.m */; }; + E29333B9158D26470078A28A /* CCNode.h in Headers */ = {isa = PBXBuildFile; fileRef = E293330F158D26470078A28A /* CCNode.h */; }; + E29333BA158D26470078A28A /* CCNode.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933310158D26470078A28A /* CCNode.m */; }; + E29333BB158D26470078A28A /* CCParallaxNode.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933311158D26470078A28A /* CCParallaxNode.h */; }; + E29333BC158D26470078A28A /* CCParallaxNode.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933312158D26470078A28A /* CCParallaxNode.m */; }; + E29333BD158D26470078A28A /* CCParticleBatchNode.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933313158D26470078A28A /* CCParticleBatchNode.h */; }; + E29333BE158D26470078A28A /* CCParticleBatchNode.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933314158D26470078A28A /* CCParticleBatchNode.m */; }; + E29333BF158D26470078A28A /* CCParticleExamples.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933315158D26470078A28A /* CCParticleExamples.h */; }; + E29333C0158D26470078A28A /* CCParticleExamples.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933316158D26470078A28A /* CCParticleExamples.m */; }; + E29333C1158D26470078A28A /* CCParticleSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933317158D26470078A28A /* CCParticleSystem.h */; }; + E29333C2158D26470078A28A /* CCParticleSystem.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933318158D26470078A28A /* CCParticleSystem.m */; }; + E29333C3158D26470078A28A /* CCParticleSystemPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933319158D26470078A28A /* CCParticleSystemPoint.h */; }; + E29333C4158D26470078A28A /* CCParticleSystemPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = E293331A158D26470078A28A /* CCParticleSystemPoint.m */; }; + E29333C5158D26470078A28A /* CCParticleSystemQuad.h in Headers */ = {isa = PBXBuildFile; fileRef = E293331B158D26470078A28A /* CCParticleSystemQuad.h */; }; + E29333C6158D26470078A28A /* CCParticleSystemQuad.m in Sources */ = {isa = PBXBuildFile; fileRef = E293331C158D26470078A28A /* CCParticleSystemQuad.m */; }; + E29333C7158D26470078A28A /* CCProgressTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = E293331D158D26470078A28A /* CCProgressTimer.h */; }; + E29333C8158D26470078A28A /* CCProgressTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = E293331E158D26470078A28A /* CCProgressTimer.m */; }; + E29333C9158D26470078A28A /* CCProtocols.h in Headers */ = {isa = PBXBuildFile; fileRef = E293331F158D26470078A28A /* CCProtocols.h */; }; + E29333CA158D26470078A28A /* CCRenderTexture.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933320158D26470078A28A /* CCRenderTexture.h */; }; + E29333CB158D26470078A28A /* CCRenderTexture.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933321158D26470078A28A /* CCRenderTexture.m */; }; + E29333CC158D26470078A28A /* CCRibbon.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933322158D26470078A28A /* CCRibbon.h */; }; + E29333CD158D26470078A28A /* CCRibbon.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933323158D26470078A28A /* CCRibbon.m */; }; + E29333CE158D26470078A28A /* CCScene.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933324158D26470078A28A /* CCScene.h */; }; + E29333CF158D26470078A28A /* CCScene.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933325158D26470078A28A /* CCScene.m */; }; + E29333D0158D26470078A28A /* CCScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933326158D26470078A28A /* CCScheduler.h */; }; + E29333D1158D26470078A28A /* CCScheduler.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933327158D26470078A28A /* CCScheduler.m */; }; + E29333D2158D26470078A28A /* CCSprite.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933328158D26470078A28A /* CCSprite.h */; }; + E29333D3158D26470078A28A /* CCSprite.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933329158D26470078A28A /* CCSprite.m */; }; + E29333D4158D26470078A28A /* CCSpriteBatchNode.h in Headers */ = {isa = PBXBuildFile; fileRef = E293332A158D26470078A28A /* CCSpriteBatchNode.h */; }; + E29333D5158D26470078A28A /* CCSpriteBatchNode.m in Sources */ = {isa = PBXBuildFile; fileRef = E293332B158D26470078A28A /* CCSpriteBatchNode.m */; }; + E29333D6158D26470078A28A /* CCSpriteFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = E293332C158D26470078A28A /* CCSpriteFrame.h */; }; + E29333D7158D26470078A28A /* CCSpriteFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = E293332D158D26470078A28A /* CCSpriteFrame.m */; }; + E29333D8158D26470078A28A /* CCSpriteFrameCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E293332E158D26470078A28A /* CCSpriteFrameCache.h */; }; + E29333D9158D26470078A28A /* CCSpriteFrameCache.m in Sources */ = {isa = PBXBuildFile; fileRef = E293332F158D26470078A28A /* CCSpriteFrameCache.m */; }; + E29333DA158D26470078A28A /* CCTexture2D.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933330158D26470078A28A /* CCTexture2D.h */; }; + E29333DB158D26470078A28A /* CCTexture2D.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933331158D26470078A28A /* CCTexture2D.m */; }; + E29333DC158D26470078A28A /* CCTextureAtlas.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933332158D26470078A28A /* CCTextureAtlas.h */; }; + E29333DD158D26470078A28A /* CCTextureAtlas.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933333158D26470078A28A /* CCTextureAtlas.m */; }; + E29333DE158D26470078A28A /* CCTextureCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933334158D26470078A28A /* CCTextureCache.h */; }; + E29333DF158D26470078A28A /* CCTextureCache.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933335158D26470078A28A /* CCTextureCache.m */; }; + E29333E0158D26470078A28A /* CCTexturePVR.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933336158D26470078A28A /* CCTexturePVR.h */; }; + E29333E1158D26470078A28A /* CCTexturePVR.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933337158D26470078A28A /* CCTexturePVR.m */; }; + E29333E2158D26470078A28A /* CCTileMapAtlas.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933338158D26470078A28A /* CCTileMapAtlas.h */; }; + E29333E3158D26470078A28A /* CCTileMapAtlas.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933339158D26470078A28A /* CCTileMapAtlas.m */; }; + E29333E4158D26470078A28A /* CCTMXLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = E293333A158D26470078A28A /* CCTMXLayer.h */; }; + E29333E5158D26470078A28A /* CCTMXLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = E293333B158D26470078A28A /* CCTMXLayer.m */; }; + E29333E6158D26470078A28A /* CCTMXObjectGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = E293333C158D26470078A28A /* CCTMXObjectGroup.h */; }; + E29333E7158D26470078A28A /* CCTMXObjectGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = E293333D158D26470078A28A /* CCTMXObjectGroup.m */; }; + E29333E8158D26470078A28A /* CCTMXTiledMap.h in Headers */ = {isa = PBXBuildFile; fileRef = E293333E158D26470078A28A /* CCTMXTiledMap.h */; }; + E29333E9158D26470078A28A /* CCTMXTiledMap.m in Sources */ = {isa = PBXBuildFile; fileRef = E293333F158D26470078A28A /* CCTMXTiledMap.m */; }; + E29333EA158D26470078A28A /* CCTMXXMLParser.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933340158D26470078A28A /* CCTMXXMLParser.h */; }; + E29333EB158D26470078A28A /* CCTMXXMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933341158D26470078A28A /* CCTMXXMLParser.m */; }; + E29333EC158D26470078A28A /* CCTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933342158D26470078A28A /* CCTransition.h */; }; + E29333ED158D26470078A28A /* CCTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933343158D26470078A28A /* CCTransition.m */; }; + E29333EE158D26470078A28A /* CCTransitionPageTurn.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933344158D26470078A28A /* CCTransitionPageTurn.h */; }; + E29333EF158D26470078A28A /* CCTransitionPageTurn.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933345158D26470078A28A /* CCTransitionPageTurn.m */; }; + E29333F0158D26470078A28A /* CCTransitionRadial.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933346158D26470078A28A /* CCTransitionRadial.h */; }; + E29333F1158D26470078A28A /* CCTransitionRadial.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933347158D26470078A28A /* CCTransitionRadial.m */; }; + E29333F2158D26470078A28A /* ccTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933348158D26470078A28A /* ccTypes.h */; }; + E29333F3158D26470078A28A /* cocos2d.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933349158D26470078A28A /* cocos2d.h */; }; + E29333F4158D26470078A28A /* cocos2d.m in Sources */ = {isa = PBXBuildFile; fileRef = E293334A158D26470078A28A /* cocos2d.m */; }; + E29333F5158D26470078A28A /* CCGL.h in Headers */ = {isa = PBXBuildFile; fileRef = E293334C158D26470078A28A /* CCGL.h */; }; + E29333F6158D26470078A28A /* CCNS.h in Headers */ = {isa = PBXBuildFile; fileRef = E293334D158D26470078A28A /* CCNS.h */; }; + E29333F7158D26470078A28A /* CCDirectorIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = E293334F158D26470078A28A /* CCDirectorIOS.h */; }; + E29333F8158D26470078A28A /* CCDirectorIOS.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933350158D26470078A28A /* CCDirectorIOS.m */; }; + E29333F9158D26470078A28A /* CCTouchDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933351158D26470078A28A /* CCTouchDelegateProtocol.h */; }; + E29333FA158D26470078A28A /* CCTouchDispatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933352158D26470078A28A /* CCTouchDispatcher.h */; }; + E29333FB158D26470078A28A /* CCTouchDispatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933353158D26470078A28A /* CCTouchDispatcher.m */; }; + E29333FC158D26470078A28A /* CCTouchHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933354158D26470078A28A /* CCTouchHandler.h */; }; + E29333FD158D26470078A28A /* CCTouchHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933355158D26470078A28A /* CCTouchHandler.m */; }; + E29333FE158D26470078A28A /* EAGLView.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933356158D26470078A28A /* EAGLView.h */; }; + E29333FF158D26470078A28A /* EAGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933357158D26470078A28A /* EAGLView.m */; }; + E2933400158D26470078A28A /* ES1Renderer.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933358158D26470078A28A /* ES1Renderer.h */; }; + E2933401158D26470078A28A /* ES1Renderer.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933359158D26470078A28A /* ES1Renderer.m */; }; + E2933402158D26470078A28A /* ESRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = E293335A158D26470078A28A /* ESRenderer.h */; }; + E2933403158D26470078A28A /* glu.c in Sources */ = {isa = PBXBuildFile; fileRef = E293335B158D26470078A28A /* glu.c */; }; + E2933404158D26470078A28A /* glu.h in Headers */ = {isa = PBXBuildFile; fileRef = E293335C158D26470078A28A /* glu.h */; }; + E2933405158D26470078A28A /* CCDirectorMac.h in Headers */ = {isa = PBXBuildFile; fileRef = E293335E158D26470078A28A /* CCDirectorMac.h */; }; + E2933406158D26470078A28A /* CCDirectorMac.m in Sources */ = {isa = PBXBuildFile; fileRef = E293335F158D26470078A28A /* CCDirectorMac.m */; }; + E2933407158D26470078A28A /* CCEventDispatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933360158D26470078A28A /* CCEventDispatcher.h */; }; + E2933408158D26470078A28A /* CCEventDispatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933361158D26470078A28A /* CCEventDispatcher.m */; }; + E2933409158D26470078A28A /* MacGLView.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933362158D26470078A28A /* MacGLView.h */; }; + E293340A158D26470078A28A /* MacGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933363158D26470078A28A /* MacGLView.m */; }; + E293340B158D26470078A28A /* MacWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933364158D26470078A28A /* MacWindow.h */; }; + E293340C158D26470078A28A /* MacWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933365158D26470078A28A /* MacWindow.m */; }; + E293340D158D26470078A28A /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = E2933367158D26470078A28A /* base64.c */; }; + E293340E158D26470078A28A /* base64.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933368158D26470078A28A /* base64.h */; }; + E293340F158D26470078A28A /* CCArray.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933369158D26470078A28A /* CCArray.h */; }; + E2933410158D26470078A28A /* CCArray.m in Sources */ = {isa = PBXBuildFile; fileRef = E293336A158D26470078A28A /* CCArray.m */; }; + E2933411158D26470078A28A /* ccCArray.h in Headers */ = {isa = PBXBuildFile; fileRef = E293336B158D26470078A28A /* ccCArray.h */; }; + E2933412158D26470078A28A /* CCFileUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = E293336C158D26470078A28A /* CCFileUtils.h */; }; + E2933413158D26470078A28A /* CCFileUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = E293336D158D26470078A28A /* CCFileUtils.m */; }; + E2933414158D26470078A28A /* CCProfiling.h in Headers */ = {isa = PBXBuildFile; fileRef = E293336E158D26470078A28A /* CCProfiling.h */; }; + E2933415158D26470078A28A /* CCProfiling.m in Sources */ = {isa = PBXBuildFile; fileRef = E293336F158D26470078A28A /* CCProfiling.m */; }; + E2933416158D26470078A28A /* ccUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = E2933370158D26470078A28A /* ccUtils.c */; }; + E2933417158D26470078A28A /* ccUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933371158D26470078A28A /* ccUtils.h */; }; + E2933418158D26470078A28A /* CGPointExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933372158D26470078A28A /* CGPointExtension.h */; }; + E2933419158D26470078A28A /* CGPointExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933373158D26470078A28A /* CGPointExtension.m */; }; + E293341A158D26470078A28A /* OpenGL_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933374158D26470078A28A /* OpenGL_Internal.h */; }; + E293341B158D26470078A28A /* TGAlib.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933375158D26470078A28A /* TGAlib.h */; }; + E293341C158D26470078A28A /* TGAlib.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933376158D26470078A28A /* TGAlib.m */; }; + E293341D158D26470078A28A /* TransformUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933377158D26470078A28A /* TransformUtils.h */; }; + E293341E158D26470078A28A /* TransformUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = E2933378158D26470078A28A /* TransformUtils.m */; }; + E293341F158D26470078A28A /* uthash.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933379158D26470078A28A /* uthash.h */; }; + E2933420158D26470078A28A /* utlist.h in Headers */ = {isa = PBXBuildFile; fileRef = E293337A158D26470078A28A /* utlist.h */; }; + E2933421158D26470078A28A /* ZipUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = E293337B158D26470078A28A /* ZipUtils.h */; }; + E2933422158D26470078A28A /* ZipUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = E293337C158D26470078A28A /* ZipUtils.m */; }; + E2933424158D26B90078A28A /* JSONRepresentation.h in Headers */ = {isa = PBXBuildFile; fileRef = E2933423158D26B90078A28A /* JSONRepresentation.h */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -313,12 +310,8 @@ 50F41313106926B2002A0D5E /* CDataScanner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDataScanner.m; sourceTree = ""; }; 50F41315106926B2002A0D5E /* CDataScanner_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDataScanner_Extensions.h; sourceTree = ""; }; 50F41316106926B2002A0D5E /* CDataScanner_Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDataScanner_Extensions.m; sourceTree = ""; }; - 50F41317106926B2002A0D5E /* NSCharacterSet_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSCharacterSet_Extensions.h; sourceTree = ""; }; - 50F41318106926B2002A0D5E /* NSCharacterSet_Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSCharacterSet_Extensions.m; sourceTree = ""; }; 50F41319106926B2002A0D5E /* NSDictionary_JSONExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSDictionary_JSONExtensions.h; sourceTree = ""; }; 50F4131A106926B2002A0D5E /* NSDictionary_JSONExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSDictionary_JSONExtensions.m; sourceTree = ""; }; - 50F4131B106926B2002A0D5E /* NSScanner_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSScanner_Extensions.h; sourceTree = ""; }; - 50F4131C106926B2002A0D5E /* NSScanner_Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSScanner_Extensions.m; sourceTree = ""; }; 50F4131E106926B2002A0D5E /* CJSONDeserializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONDeserializer.h; sourceTree = ""; }; 50F4131F106926B2002A0D5E /* CJSONDeserializer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CJSONDeserializer.m; sourceTree = ""; }; 50F41320106926B2002A0D5E /* CJSONScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONScanner.h; sourceTree = ""; }; @@ -344,175 +337,176 @@ E02BB501126CA50F006E46A2 /* Icon-Small-50.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-50.png"; sourceTree = ""; }; E02BB502126CA50F006E46A2 /* Icon-72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-72.png"; sourceTree = ""; }; E02BB762126CC1E0006E46A2 /* iTunesArtwork */ = {isa = PBXFileReference; lastKnownFileType = file; path = iTunesArtwork; sourceTree = ""; }; - E02BB765126CC223006E46A2 /* CCAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCAction.h; sourceTree = ""; }; - E02BB766126CC223006E46A2 /* CCAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCAction.m; sourceTree = ""; }; - E02BB767126CC223006E46A2 /* CCActionCamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionCamera.h; sourceTree = ""; }; - E02BB768126CC223006E46A2 /* CCActionCamera.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionCamera.m; sourceTree = ""; }; - E02BB769126CC223006E46A2 /* CCActionEase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionEase.h; sourceTree = ""; }; - E02BB76A126CC223006E46A2 /* CCActionEase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionEase.m; sourceTree = ""; }; - E02BB76B126CC223006E46A2 /* CCActionGrid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionGrid.h; sourceTree = ""; }; - E02BB76C126CC223006E46A2 /* CCActionGrid.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionGrid.m; sourceTree = ""; }; - E02BB76D126CC223006E46A2 /* CCActionGrid3D.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionGrid3D.h; sourceTree = ""; }; - E02BB76E126CC223006E46A2 /* CCActionGrid3D.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionGrid3D.m; sourceTree = ""; }; - E02BB76F126CC223006E46A2 /* CCActionInstant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionInstant.h; sourceTree = ""; }; - E02BB770126CC223006E46A2 /* CCActionInstant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionInstant.m; sourceTree = ""; }; - E02BB771126CC223006E46A2 /* CCActionInterval.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionInterval.h; sourceTree = ""; }; - E02BB772126CC223006E46A2 /* CCActionInterval.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionInterval.m; sourceTree = ""; }; - E02BB773126CC223006E46A2 /* CCActionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionManager.h; sourceTree = ""; }; - E02BB774126CC223006E46A2 /* CCActionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionManager.m; sourceTree = ""; }; - E02BB775126CC223006E46A2 /* CCActionPageTurn3D.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionPageTurn3D.h; sourceTree = ""; }; - E02BB776126CC223006E46A2 /* CCActionPageTurn3D.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionPageTurn3D.m; sourceTree = ""; }; - E02BB777126CC223006E46A2 /* CCActionProgressTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionProgressTimer.h; sourceTree = ""; }; - E02BB778126CC223006E46A2 /* CCActionProgressTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionProgressTimer.m; sourceTree = ""; }; - E02BB779126CC223006E46A2 /* CCActionTiledGrid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionTiledGrid.h; sourceTree = ""; }; - E02BB77A126CC223006E46A2 /* CCActionTiledGrid.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionTiledGrid.m; sourceTree = ""; }; - E02BB77B126CC223006E46A2 /* CCActionTween.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionTween.h; sourceTree = ""; }; - E02BB77C126CC223006E46A2 /* CCActionTween.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionTween.m; sourceTree = ""; }; - E02BB77D126CC223006E46A2 /* CCAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCAnimation.h; sourceTree = ""; }; - E02BB77E126CC223006E46A2 /* CCAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCAnimation.m; sourceTree = ""; }; - E02BB77F126CC223006E46A2 /* CCAnimationCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCAnimationCache.h; sourceTree = ""; }; - E02BB780126CC223006E46A2 /* CCAnimationCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCAnimationCache.m; sourceTree = ""; }; - E02BB781126CC223006E46A2 /* CCAtlasNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCAtlasNode.h; sourceTree = ""; }; - E02BB782126CC223006E46A2 /* CCAtlasNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCAtlasNode.m; sourceTree = ""; }; - E02BB783126CC223006E46A2 /* CCBlockSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCBlockSupport.h; sourceTree = ""; }; - E02BB784126CC223006E46A2 /* CCBlockSupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCBlockSupport.m; sourceTree = ""; }; - E02BB785126CC223006E46A2 /* CCCamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCCamera.h; sourceTree = ""; }; - E02BB786126CC223006E46A2 /* CCCamera.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCCamera.m; sourceTree = ""; }; - E02BB787126CC223006E46A2 /* CCCompatibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCCompatibility.h; sourceTree = ""; }; - E02BB788126CC223006E46A2 /* CCCompatibility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCCompatibility.m; sourceTree = ""; }; - E02BB789126CC223006E46A2 /* ccConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ccConfig.h; sourceTree = ""; }; - E02BB78A126CC223006E46A2 /* CCConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCConfiguration.h; sourceTree = ""; }; - E02BB78B126CC223006E46A2 /* CCConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCConfiguration.m; sourceTree = ""; }; - E02BB78C126CC223006E46A2 /* CCDirector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCDirector.h; sourceTree = ""; }; - E02BB78D126CC223006E46A2 /* CCDirector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCDirector.m; sourceTree = ""; }; - E02BB78E126CC223006E46A2 /* CCDrawingPrimitives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCDrawingPrimitives.h; sourceTree = ""; }; - E02BB78F126CC223006E46A2 /* CCDrawingPrimitives.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCDrawingPrimitives.m; sourceTree = ""; }; - E02BB790126CC223006E46A2 /* CCGrabber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCGrabber.h; sourceTree = ""; }; - E02BB791126CC223006E46A2 /* CCGrabber.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCGrabber.m; sourceTree = ""; }; - E02BB792126CC223006E46A2 /* CCGrid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCGrid.h; sourceTree = ""; }; - E02BB793126CC223006E46A2 /* CCGrid.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCGrid.m; sourceTree = ""; }; - E02BB794126CC223006E46A2 /* CCLabelAtlas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLabelAtlas.h; sourceTree = ""; }; - E02BB795126CC223006E46A2 /* CCLabelAtlas.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLabelAtlas.m; sourceTree = ""; }; - E02BB796126CC223006E46A2 /* CCLabelBMFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLabelBMFont.h; sourceTree = ""; }; - E02BB797126CC223006E46A2 /* CCLabelBMFont.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLabelBMFont.m; sourceTree = ""; }; - E02BB798126CC223006E46A2 /* CCLabelTTF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLabelTTF.h; sourceTree = ""; }; - E02BB799126CC223006E46A2 /* CCLabelTTF.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLabelTTF.m; sourceTree = ""; }; - E02BB79A126CC223006E46A2 /* CCLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLayer.h; sourceTree = ""; }; - E02BB79B126CC223006E46A2 /* CCLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLayer.m; sourceTree = ""; }; - E02BB79C126CC223006E46A2 /* ccMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ccMacros.h; sourceTree = ""; }; - E02BB79D126CC223006E46A2 /* CCMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCMenu.h; sourceTree = ""; }; - E02BB79E126CC223006E46A2 /* CCMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCMenu.m; sourceTree = ""; }; - E02BB79F126CC224006E46A2 /* CCMenuItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCMenuItem.h; sourceTree = ""; }; - E02BB7A0126CC224006E46A2 /* CCMenuItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCMenuItem.m; sourceTree = ""; }; - E02BB7A1126CC224006E46A2 /* CCMotionStreak.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCMotionStreak.h; sourceTree = ""; }; - E02BB7A2126CC224006E46A2 /* CCMotionStreak.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCMotionStreak.m; sourceTree = ""; }; - E02BB7A3126CC224006E46A2 /* CCNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCNode.h; sourceTree = ""; }; - E02BB7A4126CC224006E46A2 /* CCNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCNode.m; sourceTree = ""; }; - E02BB7A5126CC224006E46A2 /* CCParallaxNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCParallaxNode.h; sourceTree = ""; }; - E02BB7A6126CC224006E46A2 /* CCParallaxNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCParallaxNode.m; sourceTree = ""; }; - E02BB7A7126CC224006E46A2 /* CCParticleExamples.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCParticleExamples.h; sourceTree = ""; }; - E02BB7A8126CC224006E46A2 /* CCParticleExamples.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCParticleExamples.m; sourceTree = ""; }; - E02BB7A9126CC224006E46A2 /* CCParticleSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCParticleSystem.h; sourceTree = ""; }; - E02BB7AA126CC224006E46A2 /* CCParticleSystem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCParticleSystem.m; sourceTree = ""; }; - E02BB7AB126CC224006E46A2 /* CCParticleSystemPoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCParticleSystemPoint.h; sourceTree = ""; }; - E02BB7AC126CC224006E46A2 /* CCParticleSystemPoint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCParticleSystemPoint.m; sourceTree = ""; }; - E02BB7AD126CC224006E46A2 /* CCParticleSystemQuad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCParticleSystemQuad.h; sourceTree = ""; }; - E02BB7AE126CC224006E46A2 /* CCParticleSystemQuad.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCParticleSystemQuad.m; sourceTree = ""; }; - E02BB7AF126CC224006E46A2 /* CCProgressTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCProgressTimer.h; sourceTree = ""; }; - E02BB7B0126CC224006E46A2 /* CCProgressTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCProgressTimer.m; sourceTree = ""; }; - E02BB7B1126CC224006E46A2 /* CCProtocols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCProtocols.h; sourceTree = ""; }; - E02BB7B2126CC224006E46A2 /* CCRenderTexture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCRenderTexture.h; sourceTree = ""; }; - E02BB7B3126CC224006E46A2 /* CCRenderTexture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCRenderTexture.m; sourceTree = ""; }; - E02BB7B4126CC224006E46A2 /* CCRibbon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCRibbon.h; sourceTree = ""; }; - E02BB7B5126CC224006E46A2 /* CCRibbon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCRibbon.m; sourceTree = ""; }; - E02BB7B6126CC224006E46A2 /* CCScene.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCScene.h; sourceTree = ""; }; - E02BB7B7126CC224006E46A2 /* CCScene.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCScene.m; sourceTree = ""; }; - E02BB7B8126CC224006E46A2 /* CCScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCScheduler.h; sourceTree = ""; }; - E02BB7B9126CC224006E46A2 /* CCScheduler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCScheduler.m; sourceTree = ""; }; - E02BB7BA126CC224006E46A2 /* CCSprite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCSprite.h; sourceTree = ""; }; - E02BB7BB126CC224006E46A2 /* CCSprite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCSprite.m; sourceTree = ""; }; - E02BB7BC126CC224006E46A2 /* CCSpriteBatchNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCSpriteBatchNode.h; sourceTree = ""; }; - E02BB7BD126CC224006E46A2 /* CCSpriteBatchNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCSpriteBatchNode.m; sourceTree = ""; }; - E02BB7BE126CC224006E46A2 /* CCSpriteFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCSpriteFrame.h; sourceTree = ""; }; - E02BB7BF126CC224006E46A2 /* CCSpriteFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCSpriteFrame.m; sourceTree = ""; }; - E02BB7C0126CC224006E46A2 /* CCSpriteFrameCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCSpriteFrameCache.h; sourceTree = ""; }; - E02BB7C1126CC224006E46A2 /* CCSpriteFrameCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCSpriteFrameCache.m; sourceTree = ""; }; - E02BB7C2126CC224006E46A2 /* CCSpriteSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCSpriteSheet.h; sourceTree = ""; }; - E02BB7C3126CC224006E46A2 /* CCSpriteSheet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCSpriteSheet.m; sourceTree = ""; }; - E02BB7C4126CC224006E46A2 /* CCTexture2D.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTexture2D.h; sourceTree = ""; }; - E02BB7C5126CC224006E46A2 /* CCTexture2D.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTexture2D.m; sourceTree = ""; }; - E02BB7C6126CC224006E46A2 /* CCTextureAtlas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTextureAtlas.h; sourceTree = ""; }; - E02BB7C7126CC224006E46A2 /* CCTextureAtlas.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTextureAtlas.m; sourceTree = ""; }; - E02BB7C8126CC224006E46A2 /* CCTextureCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTextureCache.h; sourceTree = ""; }; - E02BB7C9126CC224006E46A2 /* CCTextureCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTextureCache.m; sourceTree = ""; }; - E02BB7CA126CC224006E46A2 /* CCTexturePVR.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTexturePVR.h; sourceTree = ""; }; - E02BB7CB126CC224006E46A2 /* CCTexturePVR.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTexturePVR.m; sourceTree = ""; }; - E02BB7CC126CC224006E46A2 /* CCTileMapAtlas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTileMapAtlas.h; sourceTree = ""; }; - E02BB7CD126CC224006E46A2 /* CCTileMapAtlas.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTileMapAtlas.m; sourceTree = ""; }; - E02BB7CE126CC224006E46A2 /* CCTMXLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTMXLayer.h; sourceTree = ""; }; - E02BB7CF126CC224006E46A2 /* CCTMXLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTMXLayer.m; sourceTree = ""; }; - E02BB7D0126CC224006E46A2 /* CCTMXObjectGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTMXObjectGroup.h; sourceTree = ""; }; - E02BB7D1126CC224006E46A2 /* CCTMXObjectGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTMXObjectGroup.m; sourceTree = ""; }; - E02BB7D2126CC224006E46A2 /* CCTMXTiledMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTMXTiledMap.h; sourceTree = ""; }; - E02BB7D3126CC224006E46A2 /* CCTMXTiledMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTMXTiledMap.m; sourceTree = ""; }; - E02BB7D4126CC224006E46A2 /* CCTMXXMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTMXXMLParser.h; sourceTree = ""; }; - E02BB7D5126CC224006E46A2 /* CCTMXXMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTMXXMLParser.m; sourceTree = ""; }; - E02BB7D6126CC224006E46A2 /* CCTransition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTransition.h; sourceTree = ""; }; - E02BB7D7126CC224006E46A2 /* CCTransition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTransition.m; sourceTree = ""; }; - E02BB7D8126CC224006E46A2 /* CCTransitionPageTurn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTransitionPageTurn.h; sourceTree = ""; }; - E02BB7D9126CC224006E46A2 /* CCTransitionPageTurn.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTransitionPageTurn.m; sourceTree = ""; }; - E02BB7DA126CC224006E46A2 /* CCTransitionRadial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTransitionRadial.h; sourceTree = ""; }; - E02BB7DB126CC224006E46A2 /* CCTransitionRadial.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTransitionRadial.m; sourceTree = ""; }; - E02BB7DC126CC224006E46A2 /* ccTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ccTypes.h; sourceTree = ""; }; - E02BB7DD126CC224006E46A2 /* cocos2d.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocos2d.h; sourceTree = ""; }; - E02BB7DE126CC224006E46A2 /* cocos2d.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = cocos2d.m; sourceTree = ""; }; - E02BB7E0126CC224006E46A2 /* CCGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCGL.h; sourceTree = ""; }; - E02BB7E1126CC224006E46A2 /* CCNS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCNS.h; sourceTree = ""; }; - E02BB7E3126CC224006E46A2 /* CCDirectorIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCDirectorIOS.h; sourceTree = ""; }; - E02BB7E4126CC224006E46A2 /* CCDirectorIOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCDirectorIOS.m; sourceTree = ""; }; - E02BB7E5126CC224006E46A2 /* CCTouchDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTouchDelegateProtocol.h; sourceTree = ""; }; - E02BB7E6126CC224006E46A2 /* CCTouchDispatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTouchDispatcher.h; sourceTree = ""; }; - E02BB7E7126CC224006E46A2 /* CCTouchDispatcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTouchDispatcher.m; sourceTree = ""; }; - E02BB7E8126CC224006E46A2 /* CCTouchHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTouchHandler.h; sourceTree = ""; }; - E02BB7E9126CC224006E46A2 /* CCTouchHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTouchHandler.m; sourceTree = ""; }; - E02BB7EA126CC224006E46A2 /* EAGLView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EAGLView.h; sourceTree = ""; }; - E02BB7EB126CC224006E46A2 /* EAGLView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EAGLView.m; sourceTree = ""; }; - E02BB7EC126CC224006E46A2 /* ES1Renderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ES1Renderer.h; sourceTree = ""; }; - E02BB7ED126CC224006E46A2 /* ES1Renderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ES1Renderer.m; sourceTree = ""; }; - E02BB7EE126CC224006E46A2 /* ESRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ESRenderer.h; sourceTree = ""; }; - E02BB7EF126CC224006E46A2 /* glu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = glu.c; sourceTree = ""; }; - E02BB7F0126CC224006E46A2 /* glu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glu.h; sourceTree = ""; }; - E02BB7F2126CC224006E46A2 /* CCDirectorMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCDirectorMac.h; sourceTree = ""; }; - E02BB7F3126CC224006E46A2 /* CCDirectorMac.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCDirectorMac.m; sourceTree = ""; }; - E02BB7F4126CC224006E46A2 /* CCEventDispatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCEventDispatcher.h; sourceTree = ""; }; - E02BB7F5126CC224006E46A2 /* CCEventDispatcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCEventDispatcher.m; sourceTree = ""; }; - E02BB7F6126CC224006E46A2 /* MacGLView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacGLView.h; sourceTree = ""; }; - E02BB7F7126CC224006E46A2 /* MacGLView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MacGLView.m; sourceTree = ""; }; - E02BB7F9126CC224006E46A2 /* base64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = base64.c; sourceTree = ""; }; - E02BB7FA126CC224006E46A2 /* base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base64.h; sourceTree = ""; }; - E02BB7FB126CC224006E46A2 /* CCArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCArray.h; sourceTree = ""; }; - E02BB7FC126CC224006E46A2 /* CCArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCArray.m; sourceTree = ""; }; - E02BB7FD126CC224006E46A2 /* ccCArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ccCArray.h; sourceTree = ""; }; - E02BB7FE126CC224006E46A2 /* CCFileUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCFileUtils.h; sourceTree = ""; }; - E02BB7FF126CC224006E46A2 /* CCFileUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCFileUtils.m; sourceTree = ""; }; - E02BB800126CC224006E46A2 /* CCProfiling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCProfiling.h; sourceTree = ""; }; - E02BB801126CC224006E46A2 /* CCProfiling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCProfiling.m; sourceTree = ""; }; - E02BB802126CC224006E46A2 /* ccUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ccUtils.c; sourceTree = ""; }; - E02BB803126CC224006E46A2 /* ccUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ccUtils.h; sourceTree = ""; }; - E02BB804126CC224006E46A2 /* CGPointExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGPointExtension.h; sourceTree = ""; }; - E02BB805126CC224006E46A2 /* CGPointExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CGPointExtension.m; sourceTree = ""; }; - E02BB806126CC224006E46A2 /* OpenGL_Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenGL_Internal.h; sourceTree = ""; }; - E02BB807126CC224006E46A2 /* TGAlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGAlib.h; sourceTree = ""; }; - E02BB808126CC224006E46A2 /* TGAlib.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGAlib.m; sourceTree = ""; }; - E02BB809126CC224006E46A2 /* TransformUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TransformUtils.h; sourceTree = ""; }; - E02BB80A126CC224006E46A2 /* TransformUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TransformUtils.m; sourceTree = ""; }; - E02BB80B126CC224006E46A2 /* uthash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uthash.h; sourceTree = ""; }; - E02BB80C126CC224006E46A2 /* utlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utlist.h; sourceTree = ""; }; - E02BB80D126CC224006E46A2 /* ZipUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZipUtils.h; sourceTree = ""; }; - E02BB80E126CC224006E46A2 /* ZipUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZipUtils.m; sourceTree = ""; }; E0F80F5D120A0182005866B8 /* GameConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GameConfig.h; sourceTree = ""; }; E0F80F5E120A0182005866B8 /* RootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootViewController.h; sourceTree = ""; }; E0F80F5F120A0182005866B8 /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootViewController.m; sourceTree = ""; }; + E29332D3158D26470078A28A /* CCAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCAction.h; sourceTree = ""; }; + E29332D4158D26470078A28A /* CCAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCAction.m; sourceTree = ""; }; + E29332D5158D26470078A28A /* CCActionCamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionCamera.h; sourceTree = ""; }; + E29332D6158D26470078A28A /* CCActionCamera.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionCamera.m; sourceTree = ""; }; + E29332D7158D26470078A28A /* CCActionEase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionEase.h; sourceTree = ""; }; + E29332D8158D26470078A28A /* CCActionEase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionEase.m; sourceTree = ""; }; + E29332D9158D26470078A28A /* CCActionGrid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionGrid.h; sourceTree = ""; }; + E29332DA158D26470078A28A /* CCActionGrid.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionGrid.m; sourceTree = ""; }; + E29332DB158D26470078A28A /* CCActionGrid3D.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionGrid3D.h; sourceTree = ""; }; + E29332DC158D26470078A28A /* CCActionGrid3D.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionGrid3D.m; sourceTree = ""; }; + E29332DD158D26470078A28A /* CCActionInstant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionInstant.h; sourceTree = ""; }; + E29332DE158D26470078A28A /* CCActionInstant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionInstant.m; sourceTree = ""; }; + E29332DF158D26470078A28A /* CCActionInterval.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionInterval.h; sourceTree = ""; }; + E29332E0158D26470078A28A /* CCActionInterval.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionInterval.m; sourceTree = ""; }; + E29332E1158D26470078A28A /* CCActionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionManager.h; sourceTree = ""; }; + E29332E2158D26470078A28A /* CCActionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionManager.m; sourceTree = ""; }; + E29332E3158D26470078A28A /* CCActionPageTurn3D.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionPageTurn3D.h; sourceTree = ""; }; + E29332E4158D26470078A28A /* CCActionPageTurn3D.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionPageTurn3D.m; sourceTree = ""; }; + E29332E5158D26470078A28A /* CCActionProgressTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionProgressTimer.h; sourceTree = ""; }; + E29332E6158D26470078A28A /* CCActionProgressTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionProgressTimer.m; sourceTree = ""; }; + E29332E7158D26470078A28A /* CCActionTiledGrid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionTiledGrid.h; sourceTree = ""; }; + E29332E8158D26470078A28A /* CCActionTiledGrid.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionTiledGrid.m; sourceTree = ""; }; + E29332E9158D26470078A28A /* CCActionTween.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCActionTween.h; sourceTree = ""; }; + E29332EA158D26470078A28A /* CCActionTween.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCActionTween.m; sourceTree = ""; }; + E29332EB158D26470078A28A /* CCAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCAnimation.h; sourceTree = ""; }; + E29332EC158D26470078A28A /* CCAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCAnimation.m; sourceTree = ""; }; + E29332ED158D26470078A28A /* CCAnimationCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCAnimationCache.h; sourceTree = ""; }; + E29332EE158D26470078A28A /* CCAnimationCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCAnimationCache.m; sourceTree = ""; }; + E29332EF158D26470078A28A /* CCAtlasNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCAtlasNode.h; sourceTree = ""; }; + E29332F0158D26470078A28A /* CCAtlasNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCAtlasNode.m; sourceTree = ""; }; + E29332F1158D26470078A28A /* CCBlockSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCBlockSupport.h; sourceTree = ""; }; + E29332F2158D26470078A28A /* CCBlockSupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCBlockSupport.m; sourceTree = ""; }; + E29332F3158D26470078A28A /* CCCamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCCamera.h; sourceTree = ""; }; + E29332F4158D26470078A28A /* CCCamera.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCCamera.m; sourceTree = ""; }; + E29332F5158D26470078A28A /* ccConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ccConfig.h; sourceTree = ""; }; + E29332F6158D26470078A28A /* CCConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCConfiguration.h; sourceTree = ""; }; + E29332F7158D26470078A28A /* CCConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCConfiguration.m; sourceTree = ""; }; + E29332F8158D26470078A28A /* CCDirector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCDirector.h; sourceTree = ""; }; + E29332F9158D26470078A28A /* CCDirector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCDirector.m; sourceTree = ""; }; + E29332FA158D26470078A28A /* CCDrawingPrimitives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCDrawingPrimitives.h; sourceTree = ""; }; + E29332FB158D26470078A28A /* CCDrawingPrimitives.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCDrawingPrimitives.m; sourceTree = ""; }; + E29332FC158D26470078A28A /* CCGrabber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCGrabber.h; sourceTree = ""; }; + E29332FD158D26470078A28A /* CCGrabber.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCGrabber.m; sourceTree = ""; }; + E29332FE158D26470078A28A /* CCGrid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCGrid.h; sourceTree = ""; }; + E29332FF158D26470078A28A /* CCGrid.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCGrid.m; sourceTree = ""; }; + E2933300158D26470078A28A /* CCLabelAtlas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLabelAtlas.h; sourceTree = ""; }; + E2933301158D26470078A28A /* CCLabelAtlas.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLabelAtlas.m; sourceTree = ""; }; + E2933302158D26470078A28A /* CCLabelBMFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLabelBMFont.h; sourceTree = ""; }; + E2933303158D26470078A28A /* CCLabelBMFont.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLabelBMFont.m; sourceTree = ""; }; + E2933304158D26470078A28A /* CCLabelTTF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLabelTTF.h; sourceTree = ""; }; + E2933305158D26470078A28A /* CCLabelTTF.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLabelTTF.m; sourceTree = ""; }; + E2933306158D26470078A28A /* CCLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLayer.h; sourceTree = ""; }; + E2933307158D26470078A28A /* CCLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLayer.m; sourceTree = ""; }; + E2933308158D26470078A28A /* ccMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ccMacros.h; sourceTree = ""; }; + E2933309158D26470078A28A /* CCMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCMenu.h; sourceTree = ""; }; + E293330A158D26470078A28A /* CCMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCMenu.m; sourceTree = ""; }; + E293330B158D26470078A28A /* CCMenuItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCMenuItem.h; sourceTree = ""; }; + E293330C158D26470078A28A /* CCMenuItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCMenuItem.m; sourceTree = ""; }; + E293330D158D26470078A28A /* CCMotionStreak.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCMotionStreak.h; sourceTree = ""; }; + E293330E158D26470078A28A /* CCMotionStreak.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCMotionStreak.m; sourceTree = ""; }; + E293330F158D26470078A28A /* CCNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCNode.h; sourceTree = ""; }; + E2933310158D26470078A28A /* CCNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCNode.m; sourceTree = ""; }; + E2933311158D26470078A28A /* CCParallaxNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCParallaxNode.h; sourceTree = ""; }; + E2933312158D26470078A28A /* CCParallaxNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCParallaxNode.m; sourceTree = ""; }; + E2933313158D26470078A28A /* CCParticleBatchNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCParticleBatchNode.h; sourceTree = ""; }; + E2933314158D26470078A28A /* CCParticleBatchNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCParticleBatchNode.m; sourceTree = ""; }; + E2933315158D26470078A28A /* CCParticleExamples.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCParticleExamples.h; sourceTree = ""; }; + E2933316158D26470078A28A /* CCParticleExamples.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCParticleExamples.m; sourceTree = ""; }; + E2933317158D26470078A28A /* CCParticleSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCParticleSystem.h; sourceTree = ""; }; + E2933318158D26470078A28A /* CCParticleSystem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCParticleSystem.m; sourceTree = ""; }; + E2933319158D26470078A28A /* CCParticleSystemPoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCParticleSystemPoint.h; sourceTree = ""; }; + E293331A158D26470078A28A /* CCParticleSystemPoint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCParticleSystemPoint.m; sourceTree = ""; }; + E293331B158D26470078A28A /* CCParticleSystemQuad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCParticleSystemQuad.h; sourceTree = ""; }; + E293331C158D26470078A28A /* CCParticleSystemQuad.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCParticleSystemQuad.m; sourceTree = ""; }; + E293331D158D26470078A28A /* CCProgressTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCProgressTimer.h; sourceTree = ""; }; + E293331E158D26470078A28A /* CCProgressTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCProgressTimer.m; sourceTree = ""; }; + E293331F158D26470078A28A /* CCProtocols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCProtocols.h; sourceTree = ""; }; + E2933320158D26470078A28A /* CCRenderTexture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCRenderTexture.h; sourceTree = ""; }; + E2933321158D26470078A28A /* CCRenderTexture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCRenderTexture.m; sourceTree = ""; }; + E2933322158D26470078A28A /* CCRibbon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCRibbon.h; sourceTree = ""; }; + E2933323158D26470078A28A /* CCRibbon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCRibbon.m; sourceTree = ""; }; + E2933324158D26470078A28A /* CCScene.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCScene.h; sourceTree = ""; }; + E2933325158D26470078A28A /* CCScene.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCScene.m; sourceTree = ""; }; + E2933326158D26470078A28A /* CCScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCScheduler.h; sourceTree = ""; }; + E2933327158D26470078A28A /* CCScheduler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCScheduler.m; sourceTree = ""; }; + E2933328158D26470078A28A /* CCSprite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCSprite.h; sourceTree = ""; }; + E2933329158D26470078A28A /* CCSprite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCSprite.m; sourceTree = ""; }; + E293332A158D26470078A28A /* CCSpriteBatchNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCSpriteBatchNode.h; sourceTree = ""; }; + E293332B158D26470078A28A /* CCSpriteBatchNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCSpriteBatchNode.m; sourceTree = ""; }; + E293332C158D26470078A28A /* CCSpriteFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCSpriteFrame.h; sourceTree = ""; }; + E293332D158D26470078A28A /* CCSpriteFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCSpriteFrame.m; sourceTree = ""; }; + E293332E158D26470078A28A /* CCSpriteFrameCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCSpriteFrameCache.h; sourceTree = ""; }; + E293332F158D26470078A28A /* CCSpriteFrameCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCSpriteFrameCache.m; sourceTree = ""; }; + E2933330158D26470078A28A /* CCTexture2D.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTexture2D.h; sourceTree = ""; }; + E2933331158D26470078A28A /* CCTexture2D.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTexture2D.m; sourceTree = ""; }; + E2933332158D26470078A28A /* CCTextureAtlas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTextureAtlas.h; sourceTree = ""; }; + E2933333158D26470078A28A /* CCTextureAtlas.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTextureAtlas.m; sourceTree = ""; }; + E2933334158D26470078A28A /* CCTextureCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTextureCache.h; sourceTree = ""; }; + E2933335158D26470078A28A /* CCTextureCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTextureCache.m; sourceTree = ""; }; + E2933336158D26470078A28A /* CCTexturePVR.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTexturePVR.h; sourceTree = ""; }; + E2933337158D26470078A28A /* CCTexturePVR.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTexturePVR.m; sourceTree = ""; }; + E2933338158D26470078A28A /* CCTileMapAtlas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTileMapAtlas.h; sourceTree = ""; }; + E2933339158D26470078A28A /* CCTileMapAtlas.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTileMapAtlas.m; sourceTree = ""; }; + E293333A158D26470078A28A /* CCTMXLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTMXLayer.h; sourceTree = ""; }; + E293333B158D26470078A28A /* CCTMXLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTMXLayer.m; sourceTree = ""; }; + E293333C158D26470078A28A /* CCTMXObjectGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTMXObjectGroup.h; sourceTree = ""; }; + E293333D158D26470078A28A /* CCTMXObjectGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTMXObjectGroup.m; sourceTree = ""; }; + E293333E158D26470078A28A /* CCTMXTiledMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTMXTiledMap.h; sourceTree = ""; }; + E293333F158D26470078A28A /* CCTMXTiledMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTMXTiledMap.m; sourceTree = ""; }; + E2933340158D26470078A28A /* CCTMXXMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTMXXMLParser.h; sourceTree = ""; }; + E2933341158D26470078A28A /* CCTMXXMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTMXXMLParser.m; sourceTree = ""; }; + E2933342158D26470078A28A /* CCTransition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTransition.h; sourceTree = ""; }; + E2933343158D26470078A28A /* CCTransition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTransition.m; sourceTree = ""; }; + E2933344158D26470078A28A /* CCTransitionPageTurn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTransitionPageTurn.h; sourceTree = ""; }; + E2933345158D26470078A28A /* CCTransitionPageTurn.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTransitionPageTurn.m; sourceTree = ""; }; + E2933346158D26470078A28A /* CCTransitionRadial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTransitionRadial.h; sourceTree = ""; }; + E2933347158D26470078A28A /* CCTransitionRadial.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTransitionRadial.m; sourceTree = ""; }; + E2933348158D26470078A28A /* ccTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ccTypes.h; sourceTree = ""; }; + E2933349158D26470078A28A /* cocos2d.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocos2d.h; sourceTree = ""; }; + E293334A158D26470078A28A /* cocos2d.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = cocos2d.m; sourceTree = ""; }; + E293334C158D26470078A28A /* CCGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCGL.h; sourceTree = ""; }; + E293334D158D26470078A28A /* CCNS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCNS.h; sourceTree = ""; }; + E293334F158D26470078A28A /* CCDirectorIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCDirectorIOS.h; sourceTree = ""; }; + E2933350158D26470078A28A /* CCDirectorIOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCDirectorIOS.m; sourceTree = ""; }; + E2933351158D26470078A28A /* CCTouchDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTouchDelegateProtocol.h; sourceTree = ""; }; + E2933352158D26470078A28A /* CCTouchDispatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTouchDispatcher.h; sourceTree = ""; }; + E2933353158D26470078A28A /* CCTouchDispatcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTouchDispatcher.m; sourceTree = ""; }; + E2933354158D26470078A28A /* CCTouchHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTouchHandler.h; sourceTree = ""; }; + E2933355158D26470078A28A /* CCTouchHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTouchHandler.m; sourceTree = ""; }; + E2933356158D26470078A28A /* EAGLView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EAGLView.h; sourceTree = ""; }; + E2933357158D26470078A28A /* EAGLView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EAGLView.m; sourceTree = ""; }; + E2933358158D26470078A28A /* ES1Renderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ES1Renderer.h; sourceTree = ""; }; + E2933359158D26470078A28A /* ES1Renderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ES1Renderer.m; sourceTree = ""; }; + E293335A158D26470078A28A /* ESRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ESRenderer.h; sourceTree = ""; }; + E293335B158D26470078A28A /* glu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = glu.c; sourceTree = ""; }; + E293335C158D26470078A28A /* glu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glu.h; sourceTree = ""; }; + E293335E158D26470078A28A /* CCDirectorMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCDirectorMac.h; sourceTree = ""; }; + E293335F158D26470078A28A /* CCDirectorMac.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCDirectorMac.m; sourceTree = ""; }; + E2933360158D26470078A28A /* CCEventDispatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCEventDispatcher.h; sourceTree = ""; }; + E2933361158D26470078A28A /* CCEventDispatcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCEventDispatcher.m; sourceTree = ""; }; + E2933362158D26470078A28A /* MacGLView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacGLView.h; sourceTree = ""; }; + E2933363158D26470078A28A /* MacGLView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MacGLView.m; sourceTree = ""; }; + E2933364158D26470078A28A /* MacWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacWindow.h; sourceTree = ""; }; + E2933365158D26470078A28A /* MacWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MacWindow.m; sourceTree = ""; }; + E2933367158D26470078A28A /* base64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = base64.c; sourceTree = ""; }; + E2933368158D26470078A28A /* base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base64.h; sourceTree = ""; }; + E2933369158D26470078A28A /* CCArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCArray.h; sourceTree = ""; }; + E293336A158D26470078A28A /* CCArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCArray.m; sourceTree = ""; }; + E293336B158D26470078A28A /* ccCArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ccCArray.h; sourceTree = ""; }; + E293336C158D26470078A28A /* CCFileUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCFileUtils.h; sourceTree = ""; }; + E293336D158D26470078A28A /* CCFileUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCFileUtils.m; sourceTree = ""; }; + E293336E158D26470078A28A /* CCProfiling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCProfiling.h; sourceTree = ""; }; + E293336F158D26470078A28A /* CCProfiling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCProfiling.m; sourceTree = ""; }; + E2933370158D26470078A28A /* ccUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ccUtils.c; sourceTree = ""; }; + E2933371158D26470078A28A /* ccUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ccUtils.h; sourceTree = ""; }; + E2933372158D26470078A28A /* CGPointExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGPointExtension.h; sourceTree = ""; }; + E2933373158D26470078A28A /* CGPointExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CGPointExtension.m; sourceTree = ""; }; + E2933374158D26470078A28A /* OpenGL_Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenGL_Internal.h; sourceTree = ""; }; + E2933375158D26470078A28A /* TGAlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGAlib.h; sourceTree = ""; }; + E2933376158D26470078A28A /* TGAlib.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGAlib.m; sourceTree = ""; }; + E2933377158D26470078A28A /* TransformUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TransformUtils.h; sourceTree = ""; }; + E2933378158D26470078A28A /* TransformUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TransformUtils.m; sourceTree = ""; }; + E2933379158D26470078A28A /* uthash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uthash.h; sourceTree = ""; }; + E293337A158D26470078A28A /* utlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utlist.h; sourceTree = ""; }; + E293337B158D26470078A28A /* ZipUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZipUtils.h; sourceTree = ""; }; + E293337C158D26470078A28A /* ZipUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZipUtils.m; sourceTree = ""; }; + E2933423158D26B90078A28A /* JSONRepresentation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONRepresentation.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -635,7 +629,7 @@ 506EDAA3102F461B00A389B3 /* cocos2d Sources */ = { isa = PBXGroup; children = ( - E02BB764126CC223006E46A2 /* cocos2d */, + E29332D2158D26470078A28A /* cocos2d */, 507ED63211C638C6002ED3FC /* CocosDenshion */, 504DFBC710AF12E9006D82FE /* cocoslive */, 50F41306106926B2002A0D5E /* FontLabel */, @@ -697,12 +691,8 @@ children = ( 50F41315106926B2002A0D5E /* CDataScanner_Extensions.h */, 50F41316106926B2002A0D5E /* CDataScanner_Extensions.m */, - 50F41317106926B2002A0D5E /* NSCharacterSet_Extensions.h */, - 50F41318106926B2002A0D5E /* NSCharacterSet_Extensions.m */, 50F41319106926B2002A0D5E /* NSDictionary_JSONExtensions.h */, 50F4131A106926B2002A0D5E /* NSDictionary_JSONExtensions.m */, - 50F4131B106926B2002A0D5E /* NSScanner_Extensions.h */, - 50F4131C106926B2002A0D5E /* NSScanner_Extensions.m */, ); path = Extensions; sourceTree = ""; @@ -710,6 +700,7 @@ 50F4131D106926B2002A0D5E /* JSON */ = { isa = PBXGroup; children = ( + E2933423158D26B90078A28A /* JSONRepresentation.h */, 50F4131E106926B2002A0D5E /* CJSONDeserializer.h */, 50F4131F106926B2002A0D5E /* CJSONDeserializer.m */, 50F41320106926B2002A0D5E /* CJSONScanner.h */, @@ -741,208 +732,208 @@ path = Resources; sourceTree = ""; }; - E02BB764126CC223006E46A2 /* cocos2d */ = { + E29332D2158D26470078A28A /* cocos2d */ = { isa = PBXGroup; children = ( - E02BB765126CC223006E46A2 /* CCAction.h */, - E02BB766126CC223006E46A2 /* CCAction.m */, - E02BB767126CC223006E46A2 /* CCActionCamera.h */, - E02BB768126CC223006E46A2 /* CCActionCamera.m */, - E02BB769126CC223006E46A2 /* CCActionEase.h */, - E02BB76A126CC223006E46A2 /* CCActionEase.m */, - E02BB76B126CC223006E46A2 /* CCActionGrid.h */, - E02BB76C126CC223006E46A2 /* CCActionGrid.m */, - E02BB76D126CC223006E46A2 /* CCActionGrid3D.h */, - E02BB76E126CC223006E46A2 /* CCActionGrid3D.m */, - E02BB76F126CC223006E46A2 /* CCActionInstant.h */, - E02BB770126CC223006E46A2 /* CCActionInstant.m */, - E02BB771126CC223006E46A2 /* CCActionInterval.h */, - E02BB772126CC223006E46A2 /* CCActionInterval.m */, - E02BB773126CC223006E46A2 /* CCActionManager.h */, - E02BB774126CC223006E46A2 /* CCActionManager.m */, - E02BB775126CC223006E46A2 /* CCActionPageTurn3D.h */, - E02BB776126CC223006E46A2 /* CCActionPageTurn3D.m */, - E02BB777126CC223006E46A2 /* CCActionProgressTimer.h */, - E02BB778126CC223006E46A2 /* CCActionProgressTimer.m */, - E02BB779126CC223006E46A2 /* CCActionTiledGrid.h */, - E02BB77A126CC223006E46A2 /* CCActionTiledGrid.m */, - E02BB77B126CC223006E46A2 /* CCActionTween.h */, - E02BB77C126CC223006E46A2 /* CCActionTween.m */, - E02BB77D126CC223006E46A2 /* CCAnimation.h */, - E02BB77E126CC223006E46A2 /* CCAnimation.m */, - E02BB77F126CC223006E46A2 /* CCAnimationCache.h */, - E02BB780126CC223006E46A2 /* CCAnimationCache.m */, - E02BB781126CC223006E46A2 /* CCAtlasNode.h */, - E02BB782126CC223006E46A2 /* CCAtlasNode.m */, - E02BB783126CC223006E46A2 /* CCBlockSupport.h */, - E02BB784126CC223006E46A2 /* CCBlockSupport.m */, - E02BB785126CC223006E46A2 /* CCCamera.h */, - E02BB786126CC223006E46A2 /* CCCamera.m */, - E02BB787126CC223006E46A2 /* CCCompatibility.h */, - E02BB788126CC223006E46A2 /* CCCompatibility.m */, - E02BB789126CC223006E46A2 /* ccConfig.h */, - E02BB78A126CC223006E46A2 /* CCConfiguration.h */, - E02BB78B126CC223006E46A2 /* CCConfiguration.m */, - E02BB78C126CC223006E46A2 /* CCDirector.h */, - E02BB78D126CC223006E46A2 /* CCDirector.m */, - E02BB78E126CC223006E46A2 /* CCDrawingPrimitives.h */, - E02BB78F126CC223006E46A2 /* CCDrawingPrimitives.m */, - E02BB790126CC223006E46A2 /* CCGrabber.h */, - E02BB791126CC223006E46A2 /* CCGrabber.m */, - E02BB792126CC223006E46A2 /* CCGrid.h */, - E02BB793126CC223006E46A2 /* CCGrid.m */, - E02BB794126CC223006E46A2 /* CCLabelAtlas.h */, - E02BB795126CC223006E46A2 /* CCLabelAtlas.m */, - E02BB796126CC223006E46A2 /* CCLabelBMFont.h */, - E02BB797126CC223006E46A2 /* CCLabelBMFont.m */, - E02BB798126CC223006E46A2 /* CCLabelTTF.h */, - E02BB799126CC223006E46A2 /* CCLabelTTF.m */, - E02BB79A126CC223006E46A2 /* CCLayer.h */, - E02BB79B126CC223006E46A2 /* CCLayer.m */, - E02BB79C126CC223006E46A2 /* ccMacros.h */, - E02BB79D126CC223006E46A2 /* CCMenu.h */, - E02BB79E126CC223006E46A2 /* CCMenu.m */, - E02BB79F126CC224006E46A2 /* CCMenuItem.h */, - E02BB7A0126CC224006E46A2 /* CCMenuItem.m */, - E02BB7A1126CC224006E46A2 /* CCMotionStreak.h */, - E02BB7A2126CC224006E46A2 /* CCMotionStreak.m */, - E02BB7A3126CC224006E46A2 /* CCNode.h */, - E02BB7A4126CC224006E46A2 /* CCNode.m */, - E02BB7A5126CC224006E46A2 /* CCParallaxNode.h */, - E02BB7A6126CC224006E46A2 /* CCParallaxNode.m */, - E02BB7A7126CC224006E46A2 /* CCParticleExamples.h */, - E02BB7A8126CC224006E46A2 /* CCParticleExamples.m */, - E02BB7A9126CC224006E46A2 /* CCParticleSystem.h */, - E02BB7AA126CC224006E46A2 /* CCParticleSystem.m */, - E02BB7AB126CC224006E46A2 /* CCParticleSystemPoint.h */, - E02BB7AC126CC224006E46A2 /* CCParticleSystemPoint.m */, - E02BB7AD126CC224006E46A2 /* CCParticleSystemQuad.h */, - E02BB7AE126CC224006E46A2 /* CCParticleSystemQuad.m */, - E02BB7AF126CC224006E46A2 /* CCProgressTimer.h */, - E02BB7B0126CC224006E46A2 /* CCProgressTimer.m */, - E02BB7B1126CC224006E46A2 /* CCProtocols.h */, - E02BB7B2126CC224006E46A2 /* CCRenderTexture.h */, - E02BB7B3126CC224006E46A2 /* CCRenderTexture.m */, - E02BB7B4126CC224006E46A2 /* CCRibbon.h */, - E02BB7B5126CC224006E46A2 /* CCRibbon.m */, - E02BB7B6126CC224006E46A2 /* CCScene.h */, - E02BB7B7126CC224006E46A2 /* CCScene.m */, - E02BB7B8126CC224006E46A2 /* CCScheduler.h */, - E02BB7B9126CC224006E46A2 /* CCScheduler.m */, - E02BB7BA126CC224006E46A2 /* CCSprite.h */, - E02BB7BB126CC224006E46A2 /* CCSprite.m */, - E02BB7BC126CC224006E46A2 /* CCSpriteBatchNode.h */, - E02BB7BD126CC224006E46A2 /* CCSpriteBatchNode.m */, - E02BB7BE126CC224006E46A2 /* CCSpriteFrame.h */, - E02BB7BF126CC224006E46A2 /* CCSpriteFrame.m */, - E02BB7C0126CC224006E46A2 /* CCSpriteFrameCache.h */, - E02BB7C1126CC224006E46A2 /* CCSpriteFrameCache.m */, - E02BB7C2126CC224006E46A2 /* CCSpriteSheet.h */, - E02BB7C3126CC224006E46A2 /* CCSpriteSheet.m */, - E02BB7C4126CC224006E46A2 /* CCTexture2D.h */, - E02BB7C5126CC224006E46A2 /* CCTexture2D.m */, - E02BB7C6126CC224006E46A2 /* CCTextureAtlas.h */, - E02BB7C7126CC224006E46A2 /* CCTextureAtlas.m */, - E02BB7C8126CC224006E46A2 /* CCTextureCache.h */, - E02BB7C9126CC224006E46A2 /* CCTextureCache.m */, - E02BB7CA126CC224006E46A2 /* CCTexturePVR.h */, - E02BB7CB126CC224006E46A2 /* CCTexturePVR.m */, - E02BB7CC126CC224006E46A2 /* CCTileMapAtlas.h */, - E02BB7CD126CC224006E46A2 /* CCTileMapAtlas.m */, - E02BB7CE126CC224006E46A2 /* CCTMXLayer.h */, - E02BB7CF126CC224006E46A2 /* CCTMXLayer.m */, - E02BB7D0126CC224006E46A2 /* CCTMXObjectGroup.h */, - E02BB7D1126CC224006E46A2 /* CCTMXObjectGroup.m */, - E02BB7D2126CC224006E46A2 /* CCTMXTiledMap.h */, - E02BB7D3126CC224006E46A2 /* CCTMXTiledMap.m */, - E02BB7D4126CC224006E46A2 /* CCTMXXMLParser.h */, - E02BB7D5126CC224006E46A2 /* CCTMXXMLParser.m */, - E02BB7D6126CC224006E46A2 /* CCTransition.h */, - E02BB7D7126CC224006E46A2 /* CCTransition.m */, - E02BB7D8126CC224006E46A2 /* CCTransitionPageTurn.h */, - E02BB7D9126CC224006E46A2 /* CCTransitionPageTurn.m */, - E02BB7DA126CC224006E46A2 /* CCTransitionRadial.h */, - E02BB7DB126CC224006E46A2 /* CCTransitionRadial.m */, - E02BB7DC126CC224006E46A2 /* ccTypes.h */, - E02BB7DD126CC224006E46A2 /* cocos2d.h */, - E02BB7DE126CC224006E46A2 /* cocos2d.m */, - E02BB7DF126CC224006E46A2 /* Platforms */, - E02BB7F8126CC224006E46A2 /* Support */, + E29332D3158D26470078A28A /* CCAction.h */, + E29332D4158D26470078A28A /* CCAction.m */, + E29332D5158D26470078A28A /* CCActionCamera.h */, + E29332D6158D26470078A28A /* CCActionCamera.m */, + E29332D7158D26470078A28A /* CCActionEase.h */, + E29332D8158D26470078A28A /* CCActionEase.m */, + E29332D9158D26470078A28A /* CCActionGrid.h */, + E29332DA158D26470078A28A /* CCActionGrid.m */, + E29332DB158D26470078A28A /* CCActionGrid3D.h */, + E29332DC158D26470078A28A /* CCActionGrid3D.m */, + E29332DD158D26470078A28A /* CCActionInstant.h */, + E29332DE158D26470078A28A /* CCActionInstant.m */, + E29332DF158D26470078A28A /* CCActionInterval.h */, + E29332E0158D26470078A28A /* CCActionInterval.m */, + E29332E1158D26470078A28A /* CCActionManager.h */, + E29332E2158D26470078A28A /* CCActionManager.m */, + E29332E3158D26470078A28A /* CCActionPageTurn3D.h */, + E29332E4158D26470078A28A /* CCActionPageTurn3D.m */, + E29332E5158D26470078A28A /* CCActionProgressTimer.h */, + E29332E6158D26470078A28A /* CCActionProgressTimer.m */, + E29332E7158D26470078A28A /* CCActionTiledGrid.h */, + E29332E8158D26470078A28A /* CCActionTiledGrid.m */, + E29332E9158D26470078A28A /* CCActionTween.h */, + E29332EA158D26470078A28A /* CCActionTween.m */, + E29332EB158D26470078A28A /* CCAnimation.h */, + E29332EC158D26470078A28A /* CCAnimation.m */, + E29332ED158D26470078A28A /* CCAnimationCache.h */, + E29332EE158D26470078A28A /* CCAnimationCache.m */, + E29332EF158D26470078A28A /* CCAtlasNode.h */, + E29332F0158D26470078A28A /* CCAtlasNode.m */, + E29332F1158D26470078A28A /* CCBlockSupport.h */, + E29332F2158D26470078A28A /* CCBlockSupport.m */, + E29332F3158D26470078A28A /* CCCamera.h */, + E29332F4158D26470078A28A /* CCCamera.m */, + E29332F5158D26470078A28A /* ccConfig.h */, + E29332F6158D26470078A28A /* CCConfiguration.h */, + E29332F7158D26470078A28A /* CCConfiguration.m */, + E29332F8158D26470078A28A /* CCDirector.h */, + E29332F9158D26470078A28A /* CCDirector.m */, + E29332FA158D26470078A28A /* CCDrawingPrimitives.h */, + E29332FB158D26470078A28A /* CCDrawingPrimitives.m */, + E29332FC158D26470078A28A /* CCGrabber.h */, + E29332FD158D26470078A28A /* CCGrabber.m */, + E29332FE158D26470078A28A /* CCGrid.h */, + E29332FF158D26470078A28A /* CCGrid.m */, + E2933300158D26470078A28A /* CCLabelAtlas.h */, + E2933301158D26470078A28A /* CCLabelAtlas.m */, + E2933302158D26470078A28A /* CCLabelBMFont.h */, + E2933303158D26470078A28A /* CCLabelBMFont.m */, + E2933304158D26470078A28A /* CCLabelTTF.h */, + E2933305158D26470078A28A /* CCLabelTTF.m */, + E2933306158D26470078A28A /* CCLayer.h */, + E2933307158D26470078A28A /* CCLayer.m */, + E2933308158D26470078A28A /* ccMacros.h */, + E2933309158D26470078A28A /* CCMenu.h */, + E293330A158D26470078A28A /* CCMenu.m */, + E293330B158D26470078A28A /* CCMenuItem.h */, + E293330C158D26470078A28A /* CCMenuItem.m */, + E293330D158D26470078A28A /* CCMotionStreak.h */, + E293330E158D26470078A28A /* CCMotionStreak.m */, + E293330F158D26470078A28A /* CCNode.h */, + E2933310158D26470078A28A /* CCNode.m */, + E2933311158D26470078A28A /* CCParallaxNode.h */, + E2933312158D26470078A28A /* CCParallaxNode.m */, + E2933313158D26470078A28A /* CCParticleBatchNode.h */, + E2933314158D26470078A28A /* CCParticleBatchNode.m */, + E2933315158D26470078A28A /* CCParticleExamples.h */, + E2933316158D26470078A28A /* CCParticleExamples.m */, + E2933317158D26470078A28A /* CCParticleSystem.h */, + E2933318158D26470078A28A /* CCParticleSystem.m */, + E2933319158D26470078A28A /* CCParticleSystemPoint.h */, + E293331A158D26470078A28A /* CCParticleSystemPoint.m */, + E293331B158D26470078A28A /* CCParticleSystemQuad.h */, + E293331C158D26470078A28A /* CCParticleSystemQuad.m */, + E293331D158D26470078A28A /* CCProgressTimer.h */, + E293331E158D26470078A28A /* CCProgressTimer.m */, + E293331F158D26470078A28A /* CCProtocols.h */, + E2933320158D26470078A28A /* CCRenderTexture.h */, + E2933321158D26470078A28A /* CCRenderTexture.m */, + E2933322158D26470078A28A /* CCRibbon.h */, + E2933323158D26470078A28A /* CCRibbon.m */, + E2933324158D26470078A28A /* CCScene.h */, + E2933325158D26470078A28A /* CCScene.m */, + E2933326158D26470078A28A /* CCScheduler.h */, + E2933327158D26470078A28A /* CCScheduler.m */, + E2933328158D26470078A28A /* CCSprite.h */, + E2933329158D26470078A28A /* CCSprite.m */, + E293332A158D26470078A28A /* CCSpriteBatchNode.h */, + E293332B158D26470078A28A /* CCSpriteBatchNode.m */, + E293332C158D26470078A28A /* CCSpriteFrame.h */, + E293332D158D26470078A28A /* CCSpriteFrame.m */, + E293332E158D26470078A28A /* CCSpriteFrameCache.h */, + E293332F158D26470078A28A /* CCSpriteFrameCache.m */, + E2933330158D26470078A28A /* CCTexture2D.h */, + E2933331158D26470078A28A /* CCTexture2D.m */, + E2933332158D26470078A28A /* CCTextureAtlas.h */, + E2933333158D26470078A28A /* CCTextureAtlas.m */, + E2933334158D26470078A28A /* CCTextureCache.h */, + E2933335158D26470078A28A /* CCTextureCache.m */, + E2933336158D26470078A28A /* CCTexturePVR.h */, + E2933337158D26470078A28A /* CCTexturePVR.m */, + E2933338158D26470078A28A /* CCTileMapAtlas.h */, + E2933339158D26470078A28A /* CCTileMapAtlas.m */, + E293333A158D26470078A28A /* CCTMXLayer.h */, + E293333B158D26470078A28A /* CCTMXLayer.m */, + E293333C158D26470078A28A /* CCTMXObjectGroup.h */, + E293333D158D26470078A28A /* CCTMXObjectGroup.m */, + E293333E158D26470078A28A /* CCTMXTiledMap.h */, + E293333F158D26470078A28A /* CCTMXTiledMap.m */, + E2933340158D26470078A28A /* CCTMXXMLParser.h */, + E2933341158D26470078A28A /* CCTMXXMLParser.m */, + E2933342158D26470078A28A /* CCTransition.h */, + E2933343158D26470078A28A /* CCTransition.m */, + E2933344158D26470078A28A /* CCTransitionPageTurn.h */, + E2933345158D26470078A28A /* CCTransitionPageTurn.m */, + E2933346158D26470078A28A /* CCTransitionRadial.h */, + E2933347158D26470078A28A /* CCTransitionRadial.m */, + E2933348158D26470078A28A /* ccTypes.h */, + E2933349158D26470078A28A /* cocos2d.h */, + E293334A158D26470078A28A /* cocos2d.m */, + E293334B158D26470078A28A /* Platforms */, + E2933366158D26470078A28A /* Support */, ); name = cocos2d; path = libs/cocos2d; sourceTree = ""; }; - E02BB7DF126CC224006E46A2 /* Platforms */ = { + E293334B158D26470078A28A /* Platforms */ = { isa = PBXGroup; children = ( - E02BB7E0126CC224006E46A2 /* CCGL.h */, - E02BB7E1126CC224006E46A2 /* CCNS.h */, - E02BB7E2126CC224006E46A2 /* iOS */, - E02BB7F1126CC224006E46A2 /* Mac */, + E293334C158D26470078A28A /* CCGL.h */, + E293334D158D26470078A28A /* CCNS.h */, + E293334E158D26470078A28A /* iOS */, + E293335D158D26470078A28A /* Mac */, ); path = Platforms; sourceTree = ""; }; - E02BB7E2126CC224006E46A2 /* iOS */ = { + E293334E158D26470078A28A /* iOS */ = { isa = PBXGroup; children = ( - E02BB7E3126CC224006E46A2 /* CCDirectorIOS.h */, - E02BB7E4126CC224006E46A2 /* CCDirectorIOS.m */, - E02BB7E5126CC224006E46A2 /* CCTouchDelegateProtocol.h */, - E02BB7E6126CC224006E46A2 /* CCTouchDispatcher.h */, - E02BB7E7126CC224006E46A2 /* CCTouchDispatcher.m */, - E02BB7E8126CC224006E46A2 /* CCTouchHandler.h */, - E02BB7E9126CC224006E46A2 /* CCTouchHandler.m */, - E02BB7EA126CC224006E46A2 /* EAGLView.h */, - E02BB7EB126CC224006E46A2 /* EAGLView.m */, - E02BB7EC126CC224006E46A2 /* ES1Renderer.h */, - E02BB7ED126CC224006E46A2 /* ES1Renderer.m */, - E02BB7EE126CC224006E46A2 /* ESRenderer.h */, - E02BB7EF126CC224006E46A2 /* glu.c */, - E02BB7F0126CC224006E46A2 /* glu.h */, + E293334F158D26470078A28A /* CCDirectorIOS.h */, + E2933350158D26470078A28A /* CCDirectorIOS.m */, + E2933351158D26470078A28A /* CCTouchDelegateProtocol.h */, + E2933352158D26470078A28A /* CCTouchDispatcher.h */, + E2933353158D26470078A28A /* CCTouchDispatcher.m */, + E2933354158D26470078A28A /* CCTouchHandler.h */, + E2933355158D26470078A28A /* CCTouchHandler.m */, + E2933356158D26470078A28A /* EAGLView.h */, + E2933357158D26470078A28A /* EAGLView.m */, + E2933358158D26470078A28A /* ES1Renderer.h */, + E2933359158D26470078A28A /* ES1Renderer.m */, + E293335A158D26470078A28A /* ESRenderer.h */, + E293335B158D26470078A28A /* glu.c */, + E293335C158D26470078A28A /* glu.h */, ); path = iOS; sourceTree = ""; }; - E02BB7F1126CC224006E46A2 /* Mac */ = { + E293335D158D26470078A28A /* Mac */ = { isa = PBXGroup; children = ( - E02BB7F2126CC224006E46A2 /* CCDirectorMac.h */, - E02BB7F3126CC224006E46A2 /* CCDirectorMac.m */, - E02BB7F4126CC224006E46A2 /* CCEventDispatcher.h */, - E02BB7F5126CC224006E46A2 /* CCEventDispatcher.m */, - E02BB7F6126CC224006E46A2 /* MacGLView.h */, - E02BB7F7126CC224006E46A2 /* MacGLView.m */, + E293335E158D26470078A28A /* CCDirectorMac.h */, + E293335F158D26470078A28A /* CCDirectorMac.m */, + E2933360158D26470078A28A /* CCEventDispatcher.h */, + E2933361158D26470078A28A /* CCEventDispatcher.m */, + E2933362158D26470078A28A /* MacGLView.h */, + E2933363158D26470078A28A /* MacGLView.m */, + E2933364158D26470078A28A /* MacWindow.h */, + E2933365158D26470078A28A /* MacWindow.m */, ); path = Mac; sourceTree = ""; }; - E02BB7F8126CC224006E46A2 /* Support */ = { + E2933366158D26470078A28A /* Support */ = { isa = PBXGroup; children = ( - E02BB7F9126CC224006E46A2 /* base64.c */, - E02BB7FA126CC224006E46A2 /* base64.h */, - E02BB7FB126CC224006E46A2 /* CCArray.h */, - E02BB7FC126CC224006E46A2 /* CCArray.m */, - E02BB7FD126CC224006E46A2 /* ccCArray.h */, - E02BB7FE126CC224006E46A2 /* CCFileUtils.h */, - E02BB7FF126CC224006E46A2 /* CCFileUtils.m */, - E02BB800126CC224006E46A2 /* CCProfiling.h */, - E02BB801126CC224006E46A2 /* CCProfiling.m */, - E02BB802126CC224006E46A2 /* ccUtils.c */, - E02BB803126CC224006E46A2 /* ccUtils.h */, - E02BB804126CC224006E46A2 /* CGPointExtension.h */, - E02BB805126CC224006E46A2 /* CGPointExtension.m */, - E02BB806126CC224006E46A2 /* OpenGL_Internal.h */, - E02BB807126CC224006E46A2 /* TGAlib.h */, - E02BB808126CC224006E46A2 /* TGAlib.m */, - E02BB809126CC224006E46A2 /* TransformUtils.h */, - E02BB80A126CC224006E46A2 /* TransformUtils.m */, - E02BB80B126CC224006E46A2 /* uthash.h */, - E02BB80C126CC224006E46A2 /* utlist.h */, - E02BB80D126CC224006E46A2 /* ZipUtils.h */, - E02BB80E126CC224006E46A2 /* ZipUtils.m */, + E2933367158D26470078A28A /* base64.c */, + E2933368158D26470078A28A /* base64.h */, + E2933369158D26470078A28A /* CCArray.h */, + E293336A158D26470078A28A /* CCArray.m */, + E293336B158D26470078A28A /* ccCArray.h */, + E293336C158D26470078A28A /* CCFileUtils.h */, + E293336D158D26470078A28A /* CCFileUtils.m */, + E293336E158D26470078A28A /* CCProfiling.h */, + E293336F158D26470078A28A /* CCProfiling.m */, + E2933370158D26470078A28A /* ccUtils.c */, + E2933371158D26470078A28A /* ccUtils.h */, + E2933372158D26470078A28A /* CGPointExtension.h */, + E2933373158D26470078A28A /* CGPointExtension.m */, + E2933374158D26470078A28A /* OpenGL_Internal.h */, + E2933375158D26470078A28A /* TGAlib.h */, + E2933376158D26470078A28A /* TGAlib.m */, + E2933377158D26470078A28A /* TransformUtils.h */, + E2933378158D26470078A28A /* TransformUtils.m */, + E2933379158D26470078A28A /* uthash.h */, + E293337A158D26470078A28A /* utlist.h */, + E293337B158D26470078A28A /* ZipUtils.h */, + E293337C158D26470078A28A /* ZipUtils.m */, ); path = Support; sourceTree = ""; @@ -960,9 +951,7 @@ 50F41332106926B2002A0D5E /* ZFont.h in Headers */, 50F41334106926B2002A0D5E /* CDataScanner.h in Headers */, 50F41336106926B2002A0D5E /* CDataScanner_Extensions.h in Headers */, - 50F41338106926B2002A0D5E /* NSCharacterSet_Extensions.h in Headers */, 50F4133A106926B2002A0D5E /* NSDictionary_JSONExtensions.h in Headers */, - 50F4133C106926B2002A0D5E /* NSScanner_Extensions.h in Headers */, 50F4133E106926B2002A0D5E /* CJSONDeserializer.h in Headers */, 50F41340106926B2002A0D5E /* CJSONScanner.h in Headers */, 50F41342106926B2002A0D5E /* CJSONSerializer.h in Headers */, @@ -976,95 +965,96 @@ 507ED63F11C638C6002ED3FC /* CDOpenALSupport.h in Headers */, 507ED64111C638C6002ED3FC /* CocosDenshion.h in Headers */, 507ED64311C638C6002ED3FC /* SimpleAudioEngine.h in Headers */, - E02BB80F126CC224006E46A2 /* CCAction.h in Headers */, - E02BB811126CC224006E46A2 /* CCActionCamera.h in Headers */, - E02BB813126CC224006E46A2 /* CCActionEase.h in Headers */, - E02BB815126CC224006E46A2 /* CCActionGrid.h in Headers */, - E02BB817126CC224006E46A2 /* CCActionGrid3D.h in Headers */, - E02BB819126CC224006E46A2 /* CCActionInstant.h in Headers */, - E02BB81B126CC224006E46A2 /* CCActionInterval.h in Headers */, - E02BB81D126CC224006E46A2 /* CCActionManager.h in Headers */, - E02BB81F126CC224006E46A2 /* CCActionPageTurn3D.h in Headers */, - E02BB821126CC224006E46A2 /* CCActionProgressTimer.h in Headers */, - E02BB823126CC224006E46A2 /* CCActionTiledGrid.h in Headers */, - E02BB825126CC224006E46A2 /* CCActionTween.h in Headers */, - E02BB827126CC224006E46A2 /* CCAnimation.h in Headers */, - E02BB829126CC224006E46A2 /* CCAnimationCache.h in Headers */, - E02BB82B126CC224006E46A2 /* CCAtlasNode.h in Headers */, - E02BB82D126CC224006E46A2 /* CCBlockSupport.h in Headers */, - E02BB82F126CC224006E46A2 /* CCCamera.h in Headers */, - E02BB831126CC224006E46A2 /* CCCompatibility.h in Headers */, - E02BB833126CC224006E46A2 /* ccConfig.h in Headers */, - E02BB834126CC224006E46A2 /* CCConfiguration.h in Headers */, - E02BB836126CC224006E46A2 /* CCDirector.h in Headers */, - E02BB838126CC224006E46A2 /* CCDrawingPrimitives.h in Headers */, - E02BB83A126CC224006E46A2 /* CCGrabber.h in Headers */, - E02BB83C126CC224006E46A2 /* CCGrid.h in Headers */, - E02BB83E126CC224006E46A2 /* CCLabelAtlas.h in Headers */, - E02BB840126CC224006E46A2 /* CCLabelBMFont.h in Headers */, - E02BB842126CC224006E46A2 /* CCLabelTTF.h in Headers */, - E02BB844126CC224006E46A2 /* CCLayer.h in Headers */, - E02BB846126CC224006E46A2 /* ccMacros.h in Headers */, - E02BB847126CC224006E46A2 /* CCMenu.h in Headers */, - E02BB849126CC224006E46A2 /* CCMenuItem.h in Headers */, - E02BB84B126CC224006E46A2 /* CCMotionStreak.h in Headers */, - E02BB84D126CC224006E46A2 /* CCNode.h in Headers */, - E02BB84F126CC224006E46A2 /* CCParallaxNode.h in Headers */, - E02BB851126CC224006E46A2 /* CCParticleExamples.h in Headers */, - E02BB853126CC224006E46A2 /* CCParticleSystem.h in Headers */, - E02BB855126CC224006E46A2 /* CCParticleSystemPoint.h in Headers */, - E02BB857126CC224006E46A2 /* CCParticleSystemQuad.h in Headers */, - E02BB859126CC224006E46A2 /* CCProgressTimer.h in Headers */, - E02BB85B126CC224006E46A2 /* CCProtocols.h in Headers */, - E02BB85C126CC224006E46A2 /* CCRenderTexture.h in Headers */, - E02BB85E126CC224006E46A2 /* CCRibbon.h in Headers */, - E02BB860126CC224006E46A2 /* CCScene.h in Headers */, - E02BB862126CC224006E46A2 /* CCScheduler.h in Headers */, - E02BB864126CC224006E46A2 /* CCSprite.h in Headers */, - E02BB866126CC224006E46A2 /* CCSpriteBatchNode.h in Headers */, - E02BB868126CC224006E46A2 /* CCSpriteFrame.h in Headers */, - E02BB86A126CC224006E46A2 /* CCSpriteFrameCache.h in Headers */, - E02BB86C126CC224006E46A2 /* CCSpriteSheet.h in Headers */, - E02BB86E126CC224006E46A2 /* CCTexture2D.h in Headers */, - E02BB870126CC224006E46A2 /* CCTextureAtlas.h in Headers */, - E02BB872126CC224006E46A2 /* CCTextureCache.h in Headers */, - E02BB874126CC224006E46A2 /* CCTexturePVR.h in Headers */, - E02BB876126CC224006E46A2 /* CCTileMapAtlas.h in Headers */, - E02BB878126CC224006E46A2 /* CCTMXLayer.h in Headers */, - E02BB87A126CC224006E46A2 /* CCTMXObjectGroup.h in Headers */, - E02BB87C126CC224006E46A2 /* CCTMXTiledMap.h in Headers */, - E02BB87E126CC224006E46A2 /* CCTMXXMLParser.h in Headers */, - E02BB880126CC224006E46A2 /* CCTransition.h in Headers */, - E02BB882126CC224006E46A2 /* CCTransitionPageTurn.h in Headers */, - E02BB884126CC224006E46A2 /* CCTransitionRadial.h in Headers */, - E02BB886126CC224006E46A2 /* ccTypes.h in Headers */, - E02BB887126CC224006E46A2 /* cocos2d.h in Headers */, - E02BB889126CC224006E46A2 /* CCGL.h in Headers */, - E02BB88A126CC224006E46A2 /* CCNS.h in Headers */, - E02BB88B126CC224006E46A2 /* CCDirectorIOS.h in Headers */, - E02BB88D126CC224006E46A2 /* CCTouchDelegateProtocol.h in Headers */, - E02BB88E126CC224006E46A2 /* CCTouchDispatcher.h in Headers */, - E02BB890126CC224006E46A2 /* CCTouchHandler.h in Headers */, - E02BB892126CC224006E46A2 /* EAGLView.h in Headers */, - E02BB894126CC224006E46A2 /* ES1Renderer.h in Headers */, - E02BB896126CC224006E46A2 /* ESRenderer.h in Headers */, - E02BB898126CC224006E46A2 /* glu.h in Headers */, - E02BB899126CC224006E46A2 /* CCDirectorMac.h in Headers */, - E02BB89B126CC224006E46A2 /* CCEventDispatcher.h in Headers */, - E02BB89D126CC224006E46A2 /* MacGLView.h in Headers */, - E02BB8A0126CC224006E46A2 /* base64.h in Headers */, - E02BB8A1126CC224006E46A2 /* CCArray.h in Headers */, - E02BB8A3126CC224006E46A2 /* ccCArray.h in Headers */, - E02BB8A4126CC224006E46A2 /* CCFileUtils.h in Headers */, - E02BB8A6126CC224006E46A2 /* CCProfiling.h in Headers */, - E02BB8A9126CC224006E46A2 /* ccUtils.h in Headers */, - E02BB8AA126CC224006E46A2 /* CGPointExtension.h in Headers */, - E02BB8AC126CC224006E46A2 /* OpenGL_Internal.h in Headers */, - E02BB8AD126CC224006E46A2 /* TGAlib.h in Headers */, - E02BB8AF126CC224006E46A2 /* TransformUtils.h in Headers */, - E02BB8B1126CC224006E46A2 /* uthash.h in Headers */, - E02BB8B2126CC224006E46A2 /* utlist.h in Headers */, - E02BB8B3126CC224006E46A2 /* ZipUtils.h in Headers */, + E293337D158D26470078A28A /* CCAction.h in Headers */, + E293337F158D26470078A28A /* CCActionCamera.h in Headers */, + E2933381158D26470078A28A /* CCActionEase.h in Headers */, + E2933383158D26470078A28A /* CCActionGrid.h in Headers */, + E2933385158D26470078A28A /* CCActionGrid3D.h in Headers */, + E2933387158D26470078A28A /* CCActionInstant.h in Headers */, + E2933389158D26470078A28A /* CCActionInterval.h in Headers */, + E293338B158D26470078A28A /* CCActionManager.h in Headers */, + E293338D158D26470078A28A /* CCActionPageTurn3D.h in Headers */, + E293338F158D26470078A28A /* CCActionProgressTimer.h in Headers */, + E2933391158D26470078A28A /* CCActionTiledGrid.h in Headers */, + E2933393158D26470078A28A /* CCActionTween.h in Headers */, + E2933395158D26470078A28A /* CCAnimation.h in Headers */, + E2933397158D26470078A28A /* CCAnimationCache.h in Headers */, + E2933399158D26470078A28A /* CCAtlasNode.h in Headers */, + E293339B158D26470078A28A /* CCBlockSupport.h in Headers */, + E293339D158D26470078A28A /* CCCamera.h in Headers */, + E293339F158D26470078A28A /* ccConfig.h in Headers */, + E29333A0158D26470078A28A /* CCConfiguration.h in Headers */, + E29333A2158D26470078A28A /* CCDirector.h in Headers */, + E29333A4158D26470078A28A /* CCDrawingPrimitives.h in Headers */, + E29333A6158D26470078A28A /* CCGrabber.h in Headers */, + E29333A8158D26470078A28A /* CCGrid.h in Headers */, + E29333AA158D26470078A28A /* CCLabelAtlas.h in Headers */, + E29333AC158D26470078A28A /* CCLabelBMFont.h in Headers */, + E29333AE158D26470078A28A /* CCLabelTTF.h in Headers */, + E29333B0158D26470078A28A /* CCLayer.h in Headers */, + E29333B2158D26470078A28A /* ccMacros.h in Headers */, + E29333B3158D26470078A28A /* CCMenu.h in Headers */, + E29333B5158D26470078A28A /* CCMenuItem.h in Headers */, + E29333B7158D26470078A28A /* CCMotionStreak.h in Headers */, + E29333B9158D26470078A28A /* CCNode.h in Headers */, + E29333BB158D26470078A28A /* CCParallaxNode.h in Headers */, + E29333BD158D26470078A28A /* CCParticleBatchNode.h in Headers */, + E29333BF158D26470078A28A /* CCParticleExamples.h in Headers */, + E29333C1158D26470078A28A /* CCParticleSystem.h in Headers */, + E29333C3158D26470078A28A /* CCParticleSystemPoint.h in Headers */, + E29333C5158D26470078A28A /* CCParticleSystemQuad.h in Headers */, + E29333C7158D26470078A28A /* CCProgressTimer.h in Headers */, + E29333C9158D26470078A28A /* CCProtocols.h in Headers */, + E29333CA158D26470078A28A /* CCRenderTexture.h in Headers */, + E29333CC158D26470078A28A /* CCRibbon.h in Headers */, + E29333CE158D26470078A28A /* CCScene.h in Headers */, + E29333D0158D26470078A28A /* CCScheduler.h in Headers */, + E29333D2158D26470078A28A /* CCSprite.h in Headers */, + E29333D4158D26470078A28A /* CCSpriteBatchNode.h in Headers */, + E29333D6158D26470078A28A /* CCSpriteFrame.h in Headers */, + E29333D8158D26470078A28A /* CCSpriteFrameCache.h in Headers */, + E29333DA158D26470078A28A /* CCTexture2D.h in Headers */, + E29333DC158D26470078A28A /* CCTextureAtlas.h in Headers */, + E29333DE158D26470078A28A /* CCTextureCache.h in Headers */, + E29333E0158D26470078A28A /* CCTexturePVR.h in Headers */, + E29333E2158D26470078A28A /* CCTileMapAtlas.h in Headers */, + E29333E4158D26470078A28A /* CCTMXLayer.h in Headers */, + E29333E6158D26470078A28A /* CCTMXObjectGroup.h in Headers */, + E29333E8158D26470078A28A /* CCTMXTiledMap.h in Headers */, + E29333EA158D26470078A28A /* CCTMXXMLParser.h in Headers */, + E29333EC158D26470078A28A /* CCTransition.h in Headers */, + E29333EE158D26470078A28A /* CCTransitionPageTurn.h in Headers */, + E29333F0158D26470078A28A /* CCTransitionRadial.h in Headers */, + E29333F2158D26470078A28A /* ccTypes.h in Headers */, + E29333F3158D26470078A28A /* cocos2d.h in Headers */, + E29333F5158D26470078A28A /* CCGL.h in Headers */, + E29333F6158D26470078A28A /* CCNS.h in Headers */, + E29333F7158D26470078A28A /* CCDirectorIOS.h in Headers */, + E29333F9158D26470078A28A /* CCTouchDelegateProtocol.h in Headers */, + E29333FA158D26470078A28A /* CCTouchDispatcher.h in Headers */, + E29333FC158D26470078A28A /* CCTouchHandler.h in Headers */, + E29333FE158D26470078A28A /* EAGLView.h in Headers */, + E2933400158D26470078A28A /* ES1Renderer.h in Headers */, + E2933402158D26470078A28A /* ESRenderer.h in Headers */, + E2933404158D26470078A28A /* glu.h in Headers */, + E2933405158D26470078A28A /* CCDirectorMac.h in Headers */, + E2933407158D26470078A28A /* CCEventDispatcher.h in Headers */, + E2933409158D26470078A28A /* MacGLView.h in Headers */, + E293340B158D26470078A28A /* MacWindow.h in Headers */, + E293340E158D26470078A28A /* base64.h in Headers */, + E293340F158D26470078A28A /* CCArray.h in Headers */, + E2933411158D26470078A28A /* ccCArray.h in Headers */, + E2933412158D26470078A28A /* CCFileUtils.h in Headers */, + E2933414158D26470078A28A /* CCProfiling.h in Headers */, + E2933417158D26470078A28A /* ccUtils.h in Headers */, + E2933418158D26470078A28A /* CGPointExtension.h in Headers */, + E293341A158D26470078A28A /* OpenGL_Internal.h in Headers */, + E293341B158D26470078A28A /* TGAlib.h in Headers */, + E293341D158D26470078A28A /* TransformUtils.h in Headers */, + E293341F158D26470078A28A /* uthash.h in Headers */, + E2933420158D26470078A28A /* utlist.h in Headers */, + E2933421158D26470078A28A /* ZipUtils.h in Headers */, + E2933424158D26B90078A28A /* JSONRepresentation.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1178,9 +1168,7 @@ 50F41333106926B2002A0D5E /* ZFont.m in Sources */, 50F41335106926B2002A0D5E /* CDataScanner.m in Sources */, 50F41337106926B2002A0D5E /* CDataScanner_Extensions.m in Sources */, - 50F41339106926B2002A0D5E /* NSCharacterSet_Extensions.m in Sources */, 50F4133B106926B2002A0D5E /* NSDictionary_JSONExtensions.m in Sources */, - 50F4133D106926B2002A0D5E /* NSScanner_Extensions.m in Sources */, 50F4133F106926B2002A0D5E /* CJSONDeserializer.m in Sources */, 50F41341106926B2002A0D5E /* CJSONScanner.m in Sources */, 50F41343106926B2002A0D5E /* CJSONSerializer.m in Sources */, @@ -1192,83 +1180,83 @@ 507ED64011C638C6002ED3FC /* CDOpenALSupport.m in Sources */, 507ED64211C638C6002ED3FC /* CocosDenshion.m in Sources */, 507ED64411C638C6002ED3FC /* SimpleAudioEngine.m in Sources */, - E02BB810126CC224006E46A2 /* CCAction.m in Sources */, - E02BB812126CC224006E46A2 /* CCActionCamera.m in Sources */, - E02BB814126CC224006E46A2 /* CCActionEase.m in Sources */, - E02BB816126CC224006E46A2 /* CCActionGrid.m in Sources */, - E02BB818126CC224006E46A2 /* CCActionGrid3D.m in Sources */, - E02BB81A126CC224006E46A2 /* CCActionInstant.m in Sources */, - E02BB81C126CC224006E46A2 /* CCActionInterval.m in Sources */, - E02BB81E126CC224006E46A2 /* CCActionManager.m in Sources */, - E02BB820126CC224006E46A2 /* CCActionPageTurn3D.m in Sources */, - E02BB822126CC224006E46A2 /* CCActionProgressTimer.m in Sources */, - E02BB824126CC224006E46A2 /* CCActionTiledGrid.m in Sources */, - E02BB826126CC224006E46A2 /* CCActionTween.m in Sources */, - E02BB828126CC224006E46A2 /* CCAnimation.m in Sources */, - E02BB82A126CC224006E46A2 /* CCAnimationCache.m in Sources */, - E02BB82C126CC224006E46A2 /* CCAtlasNode.m in Sources */, - E02BB82E126CC224006E46A2 /* CCBlockSupport.m in Sources */, - E02BB830126CC224006E46A2 /* CCCamera.m in Sources */, - E02BB832126CC224006E46A2 /* CCCompatibility.m in Sources */, - E02BB835126CC224006E46A2 /* CCConfiguration.m in Sources */, - E02BB837126CC224006E46A2 /* CCDirector.m in Sources */, - E02BB839126CC224006E46A2 /* CCDrawingPrimitives.m in Sources */, - E02BB83B126CC224006E46A2 /* CCGrabber.m in Sources */, - E02BB83D126CC224006E46A2 /* CCGrid.m in Sources */, - E02BB83F126CC224006E46A2 /* CCLabelAtlas.m in Sources */, - E02BB841126CC224006E46A2 /* CCLabelBMFont.m in Sources */, - E02BB843126CC224006E46A2 /* CCLabelTTF.m in Sources */, - E02BB845126CC224006E46A2 /* CCLayer.m in Sources */, - E02BB848126CC224006E46A2 /* CCMenu.m in Sources */, - E02BB84A126CC224006E46A2 /* CCMenuItem.m in Sources */, - E02BB84C126CC224006E46A2 /* CCMotionStreak.m in Sources */, - E02BB84E126CC224006E46A2 /* CCNode.m in Sources */, - E02BB850126CC224006E46A2 /* CCParallaxNode.m in Sources */, - E02BB852126CC224006E46A2 /* CCParticleExamples.m in Sources */, - E02BB854126CC224006E46A2 /* CCParticleSystem.m in Sources */, - E02BB856126CC224006E46A2 /* CCParticleSystemPoint.m in Sources */, - E02BB858126CC224006E46A2 /* CCParticleSystemQuad.m in Sources */, - E02BB85A126CC224006E46A2 /* CCProgressTimer.m in Sources */, - E02BB85D126CC224006E46A2 /* CCRenderTexture.m in Sources */, - E02BB85F126CC224006E46A2 /* CCRibbon.m in Sources */, - E02BB861126CC224006E46A2 /* CCScene.m in Sources */, - E02BB863126CC224006E46A2 /* CCScheduler.m in Sources */, - E02BB865126CC224006E46A2 /* CCSprite.m in Sources */, - E02BB867126CC224006E46A2 /* CCSpriteBatchNode.m in Sources */, - E02BB869126CC224006E46A2 /* CCSpriteFrame.m in Sources */, - E02BB86B126CC224006E46A2 /* CCSpriteFrameCache.m in Sources */, - E02BB86D126CC224006E46A2 /* CCSpriteSheet.m in Sources */, - E02BB86F126CC224006E46A2 /* CCTexture2D.m in Sources */, - E02BB871126CC224006E46A2 /* CCTextureAtlas.m in Sources */, - E02BB873126CC224006E46A2 /* CCTextureCache.m in Sources */, - E02BB875126CC224006E46A2 /* CCTexturePVR.m in Sources */, - E02BB877126CC224006E46A2 /* CCTileMapAtlas.m in Sources */, - E02BB879126CC224006E46A2 /* CCTMXLayer.m in Sources */, - E02BB87B126CC224006E46A2 /* CCTMXObjectGroup.m in Sources */, - E02BB87D126CC224006E46A2 /* CCTMXTiledMap.m in Sources */, - E02BB87F126CC224006E46A2 /* CCTMXXMLParser.m in Sources */, - E02BB881126CC224006E46A2 /* CCTransition.m in Sources */, - E02BB883126CC224006E46A2 /* CCTransitionPageTurn.m in Sources */, - E02BB885126CC224006E46A2 /* CCTransitionRadial.m in Sources */, - E02BB888126CC224006E46A2 /* cocos2d.m in Sources */, - E02BB88C126CC224006E46A2 /* CCDirectorIOS.m in Sources */, - E02BB88F126CC224006E46A2 /* CCTouchDispatcher.m in Sources */, - E02BB891126CC224006E46A2 /* CCTouchHandler.m in Sources */, - E02BB893126CC224006E46A2 /* EAGLView.m in Sources */, - E02BB895126CC224006E46A2 /* ES1Renderer.m in Sources */, - E02BB897126CC224006E46A2 /* glu.c in Sources */, - E02BB89A126CC224006E46A2 /* CCDirectorMac.m in Sources */, - E02BB89C126CC224006E46A2 /* CCEventDispatcher.m in Sources */, - E02BB89E126CC224006E46A2 /* MacGLView.m in Sources */, - E02BB89F126CC224006E46A2 /* base64.c in Sources */, - E02BB8A2126CC224006E46A2 /* CCArray.m in Sources */, - E02BB8A5126CC224006E46A2 /* CCFileUtils.m in Sources */, - E02BB8A7126CC224006E46A2 /* CCProfiling.m in Sources */, - E02BB8A8126CC224006E46A2 /* ccUtils.c in Sources */, - E02BB8AB126CC224006E46A2 /* CGPointExtension.m in Sources */, - E02BB8AE126CC224006E46A2 /* TGAlib.m in Sources */, - E02BB8B0126CC224006E46A2 /* TransformUtils.m in Sources */, - E02BB8B4126CC224006E46A2 /* ZipUtils.m in Sources */, + E293337E158D26470078A28A /* CCAction.m in Sources */, + E2933380158D26470078A28A /* CCActionCamera.m in Sources */, + E2933382158D26470078A28A /* CCActionEase.m in Sources */, + E2933384158D26470078A28A /* CCActionGrid.m in Sources */, + E2933386158D26470078A28A /* CCActionGrid3D.m in Sources */, + E2933388158D26470078A28A /* CCActionInstant.m in Sources */, + E293338A158D26470078A28A /* CCActionInterval.m in Sources */, + E293338C158D26470078A28A /* CCActionManager.m in Sources */, + E293338E158D26470078A28A /* CCActionPageTurn3D.m in Sources */, + E2933390158D26470078A28A /* CCActionProgressTimer.m in Sources */, + E2933392158D26470078A28A /* CCActionTiledGrid.m in Sources */, + E2933394158D26470078A28A /* CCActionTween.m in Sources */, + E2933396158D26470078A28A /* CCAnimation.m in Sources */, + E2933398158D26470078A28A /* CCAnimationCache.m in Sources */, + E293339A158D26470078A28A /* CCAtlasNode.m in Sources */, + E293339C158D26470078A28A /* CCBlockSupport.m in Sources */, + E293339E158D26470078A28A /* CCCamera.m in Sources */, + E29333A1158D26470078A28A /* CCConfiguration.m in Sources */, + E29333A3158D26470078A28A /* CCDirector.m in Sources */, + E29333A5158D26470078A28A /* CCDrawingPrimitives.m in Sources */, + E29333A7158D26470078A28A /* CCGrabber.m in Sources */, + E29333A9158D26470078A28A /* CCGrid.m in Sources */, + E29333AB158D26470078A28A /* CCLabelAtlas.m in Sources */, + E29333AD158D26470078A28A /* CCLabelBMFont.m in Sources */, + E29333AF158D26470078A28A /* CCLabelTTF.m in Sources */, + E29333B1158D26470078A28A /* CCLayer.m in Sources */, + E29333B4158D26470078A28A /* CCMenu.m in Sources */, + E29333B6158D26470078A28A /* CCMenuItem.m in Sources */, + E29333B8158D26470078A28A /* CCMotionStreak.m in Sources */, + E29333BA158D26470078A28A /* CCNode.m in Sources */, + E29333BC158D26470078A28A /* CCParallaxNode.m in Sources */, + E29333BE158D26470078A28A /* CCParticleBatchNode.m in Sources */, + E29333C0158D26470078A28A /* CCParticleExamples.m in Sources */, + E29333C2158D26470078A28A /* CCParticleSystem.m in Sources */, + E29333C4158D26470078A28A /* CCParticleSystemPoint.m in Sources */, + E29333C6158D26470078A28A /* CCParticleSystemQuad.m in Sources */, + E29333C8158D26470078A28A /* CCProgressTimer.m in Sources */, + E29333CB158D26470078A28A /* CCRenderTexture.m in Sources */, + E29333CD158D26470078A28A /* CCRibbon.m in Sources */, + E29333CF158D26470078A28A /* CCScene.m in Sources */, + E29333D1158D26470078A28A /* CCScheduler.m in Sources */, + E29333D3158D26470078A28A /* CCSprite.m in Sources */, + E29333D5158D26470078A28A /* CCSpriteBatchNode.m in Sources */, + E29333D7158D26470078A28A /* CCSpriteFrame.m in Sources */, + E29333D9158D26470078A28A /* CCSpriteFrameCache.m in Sources */, + E29333DB158D26470078A28A /* CCTexture2D.m in Sources */, + E29333DD158D26470078A28A /* CCTextureAtlas.m in Sources */, + E29333DF158D26470078A28A /* CCTextureCache.m in Sources */, + E29333E1158D26470078A28A /* CCTexturePVR.m in Sources */, + E29333E3158D26470078A28A /* CCTileMapAtlas.m in Sources */, + E29333E5158D26470078A28A /* CCTMXLayer.m in Sources */, + E29333E7158D26470078A28A /* CCTMXObjectGroup.m in Sources */, + E29333E9158D26470078A28A /* CCTMXTiledMap.m in Sources */, + E29333EB158D26470078A28A /* CCTMXXMLParser.m in Sources */, + E29333ED158D26470078A28A /* CCTransition.m in Sources */, + E29333EF158D26470078A28A /* CCTransitionPageTurn.m in Sources */, + E29333F1158D26470078A28A /* CCTransitionRadial.m in Sources */, + E29333F4158D26470078A28A /* cocos2d.m in Sources */, + E29333F8158D26470078A28A /* CCDirectorIOS.m in Sources */, + E29333FB158D26470078A28A /* CCTouchDispatcher.m in Sources */, + E29333FD158D26470078A28A /* CCTouchHandler.m in Sources */, + E29333FF158D26470078A28A /* EAGLView.m in Sources */, + E2933401158D26470078A28A /* ES1Renderer.m in Sources */, + E2933403158D26470078A28A /* glu.c in Sources */, + E2933406158D26470078A28A /* CCDirectorMac.m in Sources */, + E2933408158D26470078A28A /* CCEventDispatcher.m in Sources */, + E293340A158D26470078A28A /* MacGLView.m in Sources */, + E293340C158D26470078A28A /* MacWindow.m in Sources */, + E293340D158D26470078A28A /* base64.c in Sources */, + E2933410158D26470078A28A /* CCArray.m in Sources */, + E2933413158D26470078A28A /* CCFileUtils.m in Sources */, + E2933415158D26470078A28A /* CCProfiling.m in Sources */, + E2933416158D26470078A28A /* ccUtils.c in Sources */, + E2933419158D26470078A28A /* CGPointExtension.m in Sources */, + E293341C158D26470078A28A /* TGAlib.m in Sources */, + E293341E158D26470078A28A /* TransformUtils.m in Sources */, + E2933422158D26470078A28A /* ZipUtils.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/libs/CocosDenshion/CDAudioManager.h b/libs/CocosDenshion/CDAudioManager.h index a245465..2475929 100644 --- a/libs/CocosDenshion/CDAudioManager.h +++ b/libs/CocosDenshion/CDAudioManager.h @@ -51,6 +51,8 @@ typedef enum { kAMRBStop //Background music is stopped on resign but not resumed - maybe because you want to do this from within your game } tAudioManagerResignBehavior; +/** Notifications */ +extern NSString * const kCDN_AudioManagerInitialised; @interface CDAsynchInitialiser : NSOperation {} @end diff --git a/libs/CocosDenshion/CDAudioManager.m b/libs/CocosDenshion/CDAudioManager.m index 6f25a54..0929f3c 100644 --- a/libs/CocosDenshion/CDAudioManager.m +++ b/libs/CocosDenshion/CDAudioManager.m @@ -25,18 +25,7 @@ of this software and associated documentation files (the "Software"), to deal #import "CDAudioManager.h" -//Audio session interruption callback - used if sound engine is -//handling audio session interruption automatically -/* -extern void managerInterruptionCallback (void *inUserData, UInt32 interruptionState ) { - CDAudioManager *controller = (CDAudioManager *) inUserData; - if (interruptionState == kAudioSessionBeginInterruption) { - [controller audioSessionInterrupted]; - } else if (interruptionState == kAudioSessionEndInterruption) { - [controller audioSessionResumed]; - } -} -*/ +NSString * const kCDN_AudioManagerInitialised = @"kCDN_AudioManagerInitialised"; //NSOperation object used to asynchronously initialise @implementation CDAsynchInitialiser @@ -63,7 +52,7 @@ -(id) init { } -(void) dealloc { - CDLOG(@"Denshion::CDLongAudioSource - deallocating %@", self); + CDLOGINFO(@"Denshion::CDLongAudioSource - deallocating %@", self); [audioSourcePlayer release]; [audioSourceFilePath release]; [super dealloc]; @@ -72,7 +61,7 @@ -(void) dealloc { -(void) load:(NSString*) filePath { //We have alread loaded a file previously, check if we are being asked to load the same file if (state == kLAS_Init || ![filePath isEqualToString:audioSourceFilePath]) { - CDLOG(@"Denshion::CDLongAudioSource - Loading new audio source %@",filePath); + CDLOGINFO(@"Denshion::CDLongAudioSource - Loading new audio source %@",filePath); //New file if (state != kLAS_Init) { [audioSourceFilePath release];//Release old file path @@ -107,7 +96,7 @@ -(void) play { self->systemPaused = NO; [audioSourcePlayer play]; } else { - CDLOG(@"Denshion::CDLongAudioSource long audio source didn't play because it is disabled"); + CDLOGINFO(@"Denshion::CDLongAudioSource long audio source didn't play because it is disabled"); } } @@ -195,9 +184,9 @@ -(void) setNumberOfLoops:(NSInteger) loopCount } - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { - CDLOG(@"Denshion::CDLongAudioSource - audio player finished"); + CDLOGINFO(@"Denshion::CDLongAudioSource - audio player finished"); #if TARGET_IPHONE_SIMULATOR - CDLOG(@"Denshion::CDLongAudioSource - workaround for OpenAL clobbered audio issue"); + CDLOGINFO(@"Denshion::CDLongAudioSource - workaround for OpenAL clobbered audio issue"); //This is a workaround for an issue in all simulators (tested to 3.1.2). Problem is //that OpenAL audio playback is clobbered when an AVAudioPlayer stops. Workaround //is to keep the player playing on an endless loop with 0 volume and then when @@ -213,11 +202,11 @@ - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)f } -(void)audioPlayerBeginInterruption:(AVAudioPlayer *)player { - CDLOG(@"Denshion::CDLongAudioSource - audio player interrupted"); + CDLOGINFO(@"Denshion::CDLongAudioSource - audio player interrupted"); } -(void)audioPlayerEndInterruption:(AVAudioPlayer *)player { - CDLOG(@"Denshion::CDLongAudioSource - audio player resumed"); + CDLOGINFO(@"Denshion::CDLongAudioSource - audio player resumed"); if (self.backgroundMusic) { //Check if background music can play as rules may have changed during //the interruption. This is to address a specific issue in 4.x when @@ -253,7 +242,7 @@ -(BOOL) audioSessionSetActive:(BOOL) active { NSError *activationError = nil; if ([[AVAudioSession sharedInstance] setActive:active error:&activationError]) { _audioSessionActive = active; - CDLOG(@"Denshion::CDAudioManager - Audio session set active %i succeeded", active); + CDLOGINFO(@"Denshion::CDAudioManager - Audio session set active %i succeeded", active); return YES; } else { //Failed @@ -265,7 +254,7 @@ -(BOOL) audioSessionSetActive:(BOOL) active { -(BOOL) audioSessionSetCategory:(NSString*) category { NSError *categoryError = nil; if ([[AVAudioSession sharedInstance] setCategory:category error:&categoryError]) { - CDLOG(@"Denshion::CDAudioManager - Audio session set category %@ succeeded", category); + CDLOGINFO(@"Denshion::CDAudioManager - Audio session set category %@ succeeded", category); return YES; } else { //Failed @@ -285,6 +274,7 @@ + (CDAudioManager *) sharedManager } sharedManager = [[CDAudioManager alloc] init:configuredMode]; _sharedManagerState = kAMStateInitialised;//This is only really relevant when using asynchronous initialisation + [[NSNotificationCenter defaultCenter] postNotificationName:kCDN_AudioManagerInitialised object:nil]; } } return sharedManager; @@ -340,7 +330,7 @@ -(void) setMode:(tAudioManagerMode) mode { case kAMM_FxOnly: //Share audio with other app - CDLOG(@"Denshion::CDAudioManager - Audio will be shared"); + CDLOGINFO(@"Denshion::CDAudioManager - Audio will be shared"); //_audioSessionCategory = kAudioSessionCategory_AmbientSound; _audioSessionCategory = AVAudioSessionCategoryAmbient; willPlayBackgroundMusic = NO; @@ -348,7 +338,7 @@ -(void) setMode:(tAudioManagerMode) mode { case kAMM_FxPlusMusic: //Use audio exclusively - if other audio is playing it will be stopped - CDLOG(@"Denshion::CDAudioManager - Audio will be exclusive"); + CDLOGINFO(@"Denshion::CDAudioManager - Audio will be exclusive"); //_audioSessionCategory = kAudioSessionCategory_SoloAmbientSound; _audioSessionCategory = AVAudioSessionCategorySoloAmbient; willPlayBackgroundMusic = YES; @@ -356,7 +346,7 @@ -(void) setMode:(tAudioManagerMode) mode { case kAMM_MediaPlayback: //Use audio exclusively, ignore mute switch and sleep - CDLOG(@"Denshion::CDAudioManager - Media playback mode, audio will be exclusive"); + CDLOGINFO(@"Denshion::CDAudioManager - Media playback mode, audio will be exclusive"); //_audioSessionCategory = kAudioSessionCategory_MediaPlayback; _audioSessionCategory = AVAudioSessionCategoryPlayback; willPlayBackgroundMusic = YES; @@ -364,7 +354,7 @@ -(void) setMode:(tAudioManagerMode) mode { case kAMM_PlayAndRecord: //Use audio exclusively, ignore mute switch and sleep, has inputs and outputs - CDLOG(@"Denshion::CDAudioManager - Play and record mode, audio will be exclusive"); + CDLOGINFO(@"Denshion::CDAudioManager - Play and record mode, audio will be exclusive"); //_audioSessionCategory = kAudioSessionCategory_PlayAndRecord; _audioSessionCategory = AVAudioSessionCategoryPlayAndRecord; willPlayBackgroundMusic = YES; @@ -373,12 +363,12 @@ -(void) setMode:(tAudioManagerMode) mode { default: //kAudioManagerFxPlusMusicIfNoOtherAudio if ([self isOtherAudioPlaying]) { - CDLOG(@"Denshion::CDAudioManager - Other audio is playing audio will be shared"); + CDLOGINFO(@"Denshion::CDAudioManager - Other audio is playing audio will be shared"); //_audioSessionCategory = kAudioSessionCategory_AmbientSound; _audioSessionCategory = AVAudioSessionCategoryAmbient; willPlayBackgroundMusic = NO; } else { - CDLOG(@"Denshion::CDAudioManager - Other audio is not playing audio will be exclusive"); + CDLOGINFO(@"Denshion::CDAudioManager - Other audio is not playing audio will be exclusive"); //_audioSessionCategory = kAudioSessionCategory_SoloAmbientSound; _audioSessionCategory = AVAudioSessionCategorySoloAmbient; willPlayBackgroundMusic = YES; @@ -437,14 +427,14 @@ - (id) init: (tAudioManagerMode) mode { backgroundMusic.delegate = self; //Add handler for bad al context messages, these are posted by the sound engine. - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(badAlContextHandler) name:CD_MSG_BAD_AL_CONTEXT object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(badAlContextHandler) name:kCDN_BadAlContext object:nil]; } return self; } -(void) dealloc { - CDLOG(@"Denshion::CDAudioManager - deallocating"); + CDLOGINFO(@"Denshion::CDAudioManager - deallocating"); [self stopBackgroundMusic]; [soundEngine release]; [[NSNotificationCenter defaultCenter] removeObserver:self]; @@ -553,7 +543,7 @@ -(void) playBackgroundMusic:(NSString*) filePath loop:(BOOL) loop [self.backgroundMusic load:filePath]; if (!willPlayBackgroundMusic || _mute) { - CDLOG(@"Denshion::CDAudioManager - play bgm aborted because audio is not exclusive or sound is muted"); + CDLOGINFO(@"Denshion::CDAudioManager - play bgm aborted because audio is not exclusive or sound is muted"); return; } @@ -578,7 +568,7 @@ -(void) pauseBackgroundMusic -(void) resumeBackgroundMusic { if (!willPlayBackgroundMusic || _mute) { - CDLOG(@"Denshion::CDAudioManager - resume bgm aborted because audio is not exclusive or sound is muted"); + CDLOGINFO(@"Denshion::CDAudioManager - resume bgm aborted because audio is not exclusive or sound is muted"); return; } @@ -651,7 +641,7 @@ - (void) applicationWillResignActive { break; } - CDLOG(@"Denshion::CDAudioManager - handled resign active"); + CDLOGINFO(@"Denshion::CDAudioManager - handled resign active"); } //Called when application resigns active only if setResignBehavior has been called @@ -688,7 +678,7 @@ - (void) applicationDidBecomeActive { break; } - CDLOG(@"Denshion::CDAudioManager - audio manager handled become active"); + CDLOGINFO(@"Denshion::CDAudioManager - audio manager handled become active"); } } @@ -701,31 +691,31 @@ - (void) applicationDidBecomeActive:(NSNotification *) notification //Called when application terminates only if setResignBehavior has been called - (void) applicationWillTerminate:(NSNotification *) notification { - CDLOG(@"Denshion::CDAudioManager - audio manager handling terminate"); + CDLOGINFO(@"Denshion::CDAudioManager - audio manager handling terminate"); [self stopBackgroundMusic]; } /** The audio source completed playing */ - (void) cdAudioSourceDidFinishPlaying:(CDLongAudioSource *) audioSource { - CDLOG(@"Denshion::CDAudioManager - audio manager got told background music finished"); + CDLOGINFO(@"Denshion::CDAudioManager - audio manager got told background music finished"); if (backgroundMusicCompletionSelector != nil) { [backgroundMusicCompletionListener performSelector:backgroundMusicCompletionSelector]; } } -(void) beginInterruption { - CDLOG(@"Denshion::CDAudioManager - begin interruption"); + CDLOGINFO(@"Denshion::CDAudioManager - begin interruption"); [self audioSessionInterrupted]; } -(void) endInterruption { - CDLOG(@"Denshion::CDAudioManager - end interruption"); + CDLOGINFO(@"Denshion::CDAudioManager - end interruption"); [self audioSessionResumed]; } #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000 -(void) endInterruptionWithFlags:(NSUInteger)flags { - CDLOG(@"Denshion::CDAudioManager - interruption ended with flags %i",flags); + CDLOGINFO(@"Denshion::CDAudioManager - interruption ended with flags %i",flags); if (flags == AVAudioSessionInterruptionFlags_ShouldResume) { [self audioSessionResumed]; } @@ -735,14 +725,14 @@ -(void) endInterruptionWithFlags:(NSUInteger)flags { -(void)audioSessionInterrupted { if (!_interrupted) { - CDLOG(@"Denshion::CDAudioManager - Audio session interrupted"); + CDLOGINFO(@"Denshion::CDAudioManager - Audio session interrupted"); _interrupted = YES; // Deactivate the current audio session [self audioSessionSetActive:NO]; if (alcGetCurrentContext() != NULL) { - CDLOG(@"Denshion::CDAudioManager - Setting OpenAL context to NULL"); + CDLOGINFO(@"Denshion::CDAudioManager - Setting OpenAL context to NULL"); ALenum error = AL_NO_ERROR; @@ -760,7 +750,7 @@ -(void)audioSessionInterrupted -(void)audioSessionResumed { if (_interrupted) { - CDLOG(@"Denshion::CDAudioManager - Audio session resumed"); + CDLOGINFO(@"Denshion::CDAudioManager - Audio session resumed"); _interrupted = NO; BOOL activationResult = NO; @@ -779,12 +769,12 @@ -(void)audioSessionResumed [NSThread sleepForTimeInterval:0.5]; activationResult = [self audioSessionSetActive:YES]; activateCount++; - CDLOG(@"Denshion::CDAudioManager - Reactivation attempt %i status = %i",activateCount,activationResult); + CDLOGINFO(@"Denshion::CDAudioManager - Reactivation attempt %i status = %i",activateCount,activationResult); } } if (alcGetCurrentContext() == NULL) { - CDLOG(@"Denshion::CDAudioManager - Restoring OpenAL context"); + CDLOGINFO(@"Denshion::CDAudioManager - Restoring OpenAL context"); ALenum error = AL_NO_ERROR; // Restore open al context alcMakeContextCurrent([soundEngine openALContext]); @@ -854,17 +844,17 @@ -(int) bufferForFile:(NSString*) filePath create:(BOOL) create { if ([freedBuffers count] > 0) { bufferId = [[[freedBuffers lastObject] retain] autorelease]; [freedBuffers removeLastObject]; - CDLOG(@"Denshion::CDBufferManager reusing buffer id %i",[bufferId intValue]); + CDLOGINFO(@"Denshion::CDBufferManager reusing buffer id %i",[bufferId intValue]); } else { bufferId = [[NSNumber alloc] initWithInt:nextBufferId]; [bufferId autorelease]; - CDLOG(@"Denshion::CDBufferManager generating new buffer id %i",[bufferId intValue]); + CDLOGINFO(@"Denshion::CDBufferManager generating new buffer id %i",[bufferId intValue]); nextBufferId++; } if ([soundEngine loadBuffer:[bufferId intValue] filePath:filePath]) { //File successfully loaded - CDLOG(@"Denshion::CDBufferManager buffer loaded %@ %@",bufferId,filePath); + CDLOGINFO(@"Denshion::CDBufferManager buffer loaded %@ %@",bufferId,filePath); [loadedBuffers setObject:bufferId forKey:filePath]; return [bufferId intValue]; } else { diff --git a/libs/CocosDenshion/CDOpenALSupport.m b/libs/CocosDenshion/CDOpenALSupport.m index ab0df8e..26cf782 100644 --- a/libs/CocosDenshion/CDOpenALSupport.m +++ b/libs/CocosDenshion/CDOpenALSupport.m @@ -88,6 +88,8 @@ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF theData = malloc(dataSize); if (theData) { + memset(theData, 0, dataSize); + AudioFileReadBytes(afid, false, 0, &dataSize, theData); if(err == noErr) { @@ -195,6 +197,8 @@ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF theData = malloc(dataSize); if (theData) { + memset(theData, 0, dataSize); + AudioBufferList theDataBuffer; theDataBuffer.mNumberBuffers = 1; theDataBuffer.mBuffers[0].mDataByteSize = dataSize; diff --git a/libs/CocosDenshion/CocosDenshion.h b/libs/CocosDenshion/CocosDenshion.h index bb5c720..638d852 100644 --- a/libs/CocosDenshion/CocosDenshion.h +++ b/libs/CocosDenshion/CocosDenshion.h @@ -103,7 +103,16 @@ because you require OS 2.0 compatibility. #define CD_SAMPLE_RATE_BASIC 8000 #define CD_SAMPLE_RATE_DEFAULT 44100 -#define CD_MSG_BAD_AL_CONTEXT @"cdbadalcontext" +extern NSString * const kCDN_BadAlContext; +extern NSString * const kCDN_AsynchLoadComplete; + +extern float const kCD_PitchDefault; +extern float const kCD_PitchLowerOneOctave; +extern float const kCD_PitchHigherOneOctave; +extern float const kCD_PanDefault; +extern float const kCD_PanFullLeft; +extern float const kCD_PanFullRight; +extern float const kCD_GainDefault; enum bufferState { CD_BS_EMPTY = 0, @@ -198,12 +207,13 @@ typedef struct _sourceInfo { sourceInfo *_sources; sourceGroup *_sourceGroups; ALCcontext *context; - int _sourceGroupTotal; + NSUInteger _sourceGroupTotal; UInt32 _audioSessionCategory; BOOL _handleAudioSession; + ALfloat _preMuteGain; + NSObject *_mutexBufferLoad; BOOL mute_; BOOL enabled_; - ALfloat _preMuteGain; ALenum lastErrorCode_; BOOL functioning_; @@ -224,7 +234,7 @@ typedef struct _sourceInfo { /** Total number of sources available */ @property (readonly) int sourceTotal; /** Total number of source groups that have been defined */ -@property (readonly) int sourceGroupTotal; +@property (readonly) NSUInteger sourceGroupTotal; /** Sets the sample rate for the audio mixer. For best performance this should match the sample rate of your audio content */ +(void) setMixerSampleRate:(Float32) sampleRate; @@ -246,7 +256,7 @@ typedef struct _sourceInfo { /** Stops all playing sounds */ -(void) stopAllSounds; -(void) defineSourceGroups:(NSArray*) sourceGroupDefinitions; --(void) defineSourceGroups:(int[]) sourceGroupDefinitions total:(int) total; +-(void) defineSourceGroups:(int[]) sourceGroupDefinitions total:(NSUInteger) total; -(void) setSourceGroupNonInterruptible:(int) sourceGroupId isNonInterruptible:(BOOL) isNonInterruptible; -(void) setSourceGroupEnabled:(int) sourceGroupId enabled:(BOOL) enabled; -(BOOL) sourceGroupEnabled:(int) sourceGroupId; @@ -344,7 +354,7 @@ typedef struct _sourceInfo { @property (readonly) NSString *filePath; @property (readonly) int soundId; -- (id)init:(int) theSoundId filePath:(NSString *) theFilePath; +- (id)init:(int) theSoundId filePath:(const NSString *) theFilePath; @end /** Interpolation type */ diff --git a/libs/CocosDenshion/CocosDenshion.m b/libs/CocosDenshion/CocosDenshion.m index 3b252fe..6956c3a 100644 --- a/libs/CocosDenshion/CocosDenshion.m +++ b/libs/CocosDenshion/CocosDenshion.m @@ -24,6 +24,10 @@ of this software and associated documentation files (the "Software"), to deal #import "CocosDenshion.h" +ALvoid alBufferDataStaticProc(const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq); +ALvoid alcMacOSXMixerOutputRateProc(const ALdouble value); + + typedef ALvoid AL_APIENTRY (*alBufferDataStaticProcPtr) (const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq); ALvoid alBufferDataStaticProc(const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq) { @@ -54,13 +58,23 @@ ALvoid alcMacOSXMixerOutputRateProc(const ALdouble value) return; } +NSString * const kCDN_BadAlContext = @"kCDN_BadAlContext"; +NSString * const kCDN_AsynchLoadComplete = @"kCDN_AsynchLoadComplete"; +float const kCD_PitchDefault = 1.0f; +float const kCD_PitchLowerOneOctave = 0.5f; +float const kCD_PitchHigherOneOctave = 2.0f; +float const kCD_PanDefault = 0.0f; +float const kCD_PanFullLeft = -1.0f; +float const kCD_PanFullRight = 1.0f; +float const kCD_GainDefault = 1.0f; + @interface CDSoundEngine (PrivateMethods) -(BOOL) _initOpenAL; -(void) _testGetGain; -(void) _dumpSourceGroupsInfo; -(void) _getSourceIndexForSourceGroup; -(void) _freeSourceGroups; --(BOOL) _setUpSourceGroups:(int[]) definitions total:(int) total; +-(BOOL) _setUpSourceGroups:(int[]) definitions total:(NSUInteger) total; @end #pragma mark - @@ -118,7 +132,6 @@ - (void) _testGetGain { ALfloat gainVal; alGetSourcef(testSourceId, AL_GAIN, &gainVal); getGainWorks_ = (gainVal == testValue); - CDLOG(@"Denshion::CDSoundEngine - testing get gain for source %i",getGainWorks_); } //Generate sources one at a time until we fail @@ -129,7 +142,6 @@ -(void) _generateSources { sourceTotal_ = 0; alGetError();//Clear error while (!hasFailed && sourceTotal_ < CD_SOURCE_LIMIT) { - CDLOG(@"Denshion::CDSoundEngine - try to generate source %i",sourceTotal_); alGenSources(1, &(_sources[sourceTotal_].sourceId)); if (alGetError() == AL_NO_ERROR) { //Now try attaching source to null buffer @@ -149,11 +161,9 @@ -(void) _generateSources { for (int i=sourceTotal_; i < CD_SOURCE_LIMIT; i++) { _sources[i].usable = false; } - CDLOG(@"Denshion::CDSoundEngine - total sources %i",sourceTotal_); } -(void) _generateBuffers:(int) startIndex endIndex:(int) endIndex { - CDLOG(@"Denshion::CDSoundEngine - generate buffers %i to %i",startIndex,endIndex); if (_buffers) { alGetError(); for (int i=startIndex; i <= endIndex; i++) { @@ -161,7 +171,6 @@ -(void) _generateBuffers:(int) startIndex endIndex:(int) endIndex { _buffers[i].bufferData = NULL; if (alGetError() == AL_NO_ERROR) { _buffers[i].bufferState = CD_BS_EMPTY; - CDLOG(@"Denshion::CDSoundEngine - buffer created %i",_buffers[i].bufferId); } else { _buffers[i].bufferState = CD_BS_FAILED; CDLOG(@"Denshion::CDSoundEngine - buffer creation failed %i",i); @@ -184,7 +193,7 @@ - (BOOL) _initOpenAL _mixerSampleRate = CD_SAMPLE_RATE_DEFAULT; } alcMacOSXMixerOutputRateProc(_mixerSampleRate); - CDLOG(@"Denshion::CDSoundEngine - mixer output rate set to %0.2f",_mixerSampleRate); + CDLOGINFO(@"Denshion::CDSoundEngine - mixer output rate set to %0.2f",_mixerSampleRate); // Create a new OpenAL Device // Pass NULL to specify the system's default output device @@ -220,11 +229,11 @@ - (void) dealloc { [self stopAllSounds]; - CDLOG(@"Denshion::CDSoundEngine - Deallocing sound engine."); + CDLOGINFO(@"Denshion::CDSoundEngine - Deallocing sound engine."); [self _freeSourceGroups]; // Delete the Sources - CDLOG(@"Denshion::CDSoundEngine - deleting sources."); + CDLOGINFO(@"Denshion::CDSoundEngine - deleting sources."); for (int i=0; i < sourceTotal_; i++) { alSourcei(_sources[i].sourceId, AL_BUFFER, 0);//Detach from current buffer alDeleteSources(1, &(_sources[i].sourceId)); @@ -234,7 +243,7 @@ - (void) dealloc { } // Delete the Buffers - CDLOG(@"Denshion::CDSoundEngine - deleting buffers."); + CDLOGINFO(@"Denshion::CDSoundEngine - deleting buffers."); for (int i=0; i < bufferTotal; i++) { alDeleteBuffers(1, &_buffers[i].bufferId); #ifdef CD_USE_STATIC_BUFFERS @@ -243,42 +252,45 @@ - (void) dealloc { } #endif } - CDLOG(@"Denshion::CDSoundEngine - free buffers."); + CDLOGINFO(@"Denshion::CDSoundEngine - free buffers."); free(_buffers); currentContext = alcGetCurrentContext(); //Get device for active context device = alcGetContextsDevice(currentContext); //Release context - CDLOG(@"Denshion::CDSoundEngine - destroy context."); + CDLOGINFO(@"Denshion::CDSoundEngine - destroy context."); alcDestroyContext(currentContext); //Close device - CDLOG(@"Denshion::CDSoundEngine - close device."); + CDLOGINFO(@"Denshion::CDSoundEngine - close device."); alcCloseDevice(device); - CDLOG(@"Denshion::CDSoundEngine - free sources."); + CDLOGINFO(@"Denshion::CDSoundEngine - free sources."); free(_sources); + //Release mutexes + [_mutexBufferLoad release]; + [super dealloc]; } --(int) sourceGroupTotal { +-(NSUInteger) sourceGroupTotal { return _sourceGroupTotal; } -(void) _freeSourceGroups { - CDLOG(@"Denshion::CDSoundEngine freeing source groups"); + CDLOGINFO(@"Denshion::CDSoundEngine freeing source groups"); if(_sourceGroups) { for (int i=0; i < _sourceGroupTotal; i++) { if (_sourceGroups[i].sourceStatuses) { free(_sourceGroups[i].sourceStatuses); - CDLOG(@"Denshion::CDSoundEngine freed source statuses %i",i); + CDLOGINFO(@"Denshion::CDSoundEngine freed source statuses %i",i); } } free(_sourceGroups); } } --(BOOL) _redefineSourceGroups:(int[]) definitions total:(int) total +-(BOOL) _redefineSourceGroups:(int[]) definitions total:(NSUInteger) total { if (_sourceGroups) { //Stop all sounds @@ -289,7 +301,7 @@ -(BOOL) _redefineSourceGroups:(int[]) definitions total:(int) total return [self _setUpSourceGroups:definitions total:total]; } --(BOOL) _setUpSourceGroups:(int[]) definitions total:(int) total +-(BOOL) _setUpSourceGroups:(int[]) definitions total:(NSUInteger) total { _sourceGroups = (sourceGroup *)malloc( sizeof(_sourceGroups[0]) * total); if(!_sourceGroups) { @@ -314,25 +326,23 @@ -(BOOL) _setUpSourceGroups:(int[]) definitions total:(int) total } } sourceCount += definitions[i]; - CDLOG(@"Denshion::CDSoundEngine - source def %i %i %i",i,_sourceGroups[i].startIndex, _sourceGroups[i].currentIndex); } - [self _dumpSourceGroupsInfo]; return YES; } --(void) defineSourceGroups:(int[]) sourceGroupDefinitions total:(int) total { +-(void) defineSourceGroups:(int[]) sourceGroupDefinitions total:(NSUInteger) total { [self _redefineSourceGroups:sourceGroupDefinitions total:total]; } -(void) defineSourceGroups:(NSArray*) sourceGroupDefinitions { - CDLOG(@"Denshion::CDSoundEngine - source groups defined by NSArray."); - int totalDefs = [sourceGroupDefinitions count]; + CDLOGINFO(@"Denshion::CDSoundEngine - source groups defined by NSArray."); + NSUInteger totalDefs = [sourceGroupDefinitions count]; int* defs = (int *)malloc( sizeof(int) * totalDefs); int currentIndex = 0; for (id currentDef in sourceGroupDefinitions) { if ([currentDef isKindOfClass:[NSNumber class]]) { - defs[currentIndex] = [(NSNumber*)currentDef integerValue]; - CDLOG(@"Denshion::CDSoundEngine - found definition %i.",defs[currentIndex]); + defs[currentIndex] = (int)[(NSNumber*)currentDef integerValue]; + CDLOGINFO(@"Denshion::CDSoundEngine - found definition %i.",defs[currentIndex]); } else { CDLOG(@"Denshion::CDSoundEngine - warning, did not understand source definition."); defs[currentIndex] = 0; @@ -347,6 +357,9 @@ - (id)init { if ((self = [super init])) { + //Create mutexes + _mutexBufferLoad = [[NSObject alloc] init]; + asynchLoadProgress_ = 0.0f; bufferTotal = CD_BUFFERS_START; @@ -437,7 +450,7 @@ - (BOOL) unloadBuffer:(int) soundId #ifdef CD_USE_STATIC_BUFFERS //Free previous data, if alDeleteBuffer has returned without error then no if (_buffers[soundId].bufferData) { - CDLOG(@"Denshion::CDSoundEngine - freeing static data for soundId %i @ %i",soundId,_buffers[soundId].bufferData); + CDLOGINFO(@"Denshion::CDSoundEngine - freeing static data for soundId %i @ %i",soundId,_buffers[soundId].bufferData); free(_buffers[soundId].bufferData);//Free the old data _buffers[soundId].bufferData = NULL; } @@ -452,7 +465,7 @@ - (BOOL) unloadBuffer:(int) soundId } else { //We now have an empty buffer _buffers[soundId].bufferState = CD_BS_EMPTY; - CDLOG(@"Denshion::CDSoundEngine - buffer %i successfully unloaded\n",soundId); + CDLOGINFO(@"Denshion::CDSoundEngine - buffer %i successfully unloaded\n",soundId); return TRUE; } } @@ -490,75 +503,75 @@ -(BOOL) _resizeBuffers:(int) increment { } -(BOOL) loadBufferFromData:(int) soundId soundData:(ALvoid*) soundData format:(ALenum) format size:(ALsizei) size freq:(ALsizei) freq { - - CDLOG(@"Denshion::CDSoundEngine - Loading buffer %i ", soundId); - - if (!functioning_) { - //OpenAL initialisation has previously failed - CDLOG(@"Denshion::CDSoundEngine - Loading buffer failed because sound engine state != functioning"); - return FALSE; - } - - //Ensure soundId is within array bounds otherwise memory corruption will occur - if (soundId < 0) { - CDLOG(@"Denshion::CDSoundEngine - soundId is negative"); - return FALSE; - } - - if (soundId >= bufferTotal) { - //Need to resize the buffers - int requiredIncrement = CD_BUFFERS_INCREMENT; - while (bufferTotal + requiredIncrement < soundId) { - requiredIncrement += CD_BUFFERS_INCREMENT; + + @synchronized(_mutexBufferLoad) { + + if (!functioning_) { + //OpenAL initialisation has previously failed + CDLOG(@"Denshion::CDSoundEngine - Loading buffer failed because sound engine state != functioning"); + return FALSE; } - CDLOG(@"Denshion::CDSoundEngine - attempting to resize buffers by %i for sound %i",requiredIncrement,soundId); - if (![self _resizeBuffers:requiredIncrement]) { - CDLOG(@"Denshion::CDSoundEngine - buffer resize failed"); + + //Ensure soundId is within array bounds otherwise memory corruption will occur + if (soundId < 0) { + CDLOG(@"Denshion::CDSoundEngine - soundId is negative"); return FALSE; - } - } - - if (soundData) - { - if (_buffers[soundId].bufferState != CD_BS_EMPTY) { - CDLOG(@"Denshion::CDSoundEngine - non empty buffer, regenerating"); - if (![self unloadBuffer:soundId]) { - //Deletion of buffer failed, delete buffer routine has set buffer state and lastErrorCode - return NO; + } + + if (soundId >= bufferTotal) { + //Need to resize the buffers + int requiredIncrement = CD_BUFFERS_INCREMENT; + while (bufferTotal + requiredIncrement < soundId) { + requiredIncrement += CD_BUFFERS_INCREMENT; + } + CDLOGINFO(@"Denshion::CDSoundEngine - attempting to resize buffers by %i for sound %i",requiredIncrement,soundId); + if (![self _resizeBuffers:requiredIncrement]) { + CDLOG(@"Denshion::CDSoundEngine - buffer resize failed"); + return FALSE; } } + if (soundData) + { + if (_buffers[soundId].bufferState != CD_BS_EMPTY) { + CDLOGINFO(@"Denshion::CDSoundEngine - non empty buffer, regenerating"); + if (![self unloadBuffer:soundId]) { + //Deletion of buffer failed, delete buffer routine has set buffer state and lastErrorCode + return NO; + } + } + #ifdef CD_DEBUG - //Check that sample rate matches mixer rate and warn if they do not - if (freq != (int)_mixerSampleRate) { - CDLOG(@"Denshion::CDSoundEngine - WARNING sample rate does not match mixer sample rate performance will not be optimal."); - } + //Check that sample rate matches mixer rate and warn if they do not + if (freq != (int)_mixerSampleRate) { + CDLOGINFO(@"Denshion::CDSoundEngine - WARNING sample rate does not match mixer sample rate performance may not be optimal."); + } #endif - + #ifdef CD_USE_STATIC_BUFFERS - alBufferDataStaticProc(_buffers[soundId].bufferId, format, soundData, size, freq); - _buffers[soundId].bufferData = data;//Save the pointer to the new data + alBufferDataStaticProc(_buffers[soundId].bufferId, format, soundData, size, freq); + _buffers[soundId].bufferData = data;//Save the pointer to the new data #else - alBufferData(_buffers[soundId].bufferId, format, soundData, size, freq); + alBufferData(_buffers[soundId].bufferId, format, soundData, size, freq); #endif - if((lastErrorCode_ = alGetError()) != AL_NO_ERROR) { - CDLOG(@"Denshion::CDSoundEngine - error attaching audio to buffer: %x", lastErrorCode_); + if((lastErrorCode_ = alGetError()) != AL_NO_ERROR) { + CDLOG(@"Denshion::CDSoundEngine - error attaching audio to buffer: %x", lastErrorCode_); + _buffers[soundId].bufferState = CD_BS_FAILED; + return FALSE; + } + } else { + CDLOG(@"Denshion::CDSoundEngine Buffer data is null!"); _buffers[soundId].bufferState = CD_BS_FAILED; return FALSE; - } - } else { - CDLOG(@"Denshion::CDSoundEngine Buffer data is null!"); - _buffers[soundId].bufferState = CD_BS_FAILED; - return FALSE; - } - - _buffers[soundId].format = format; - _buffers[soundId].sizeInBytes = size; - _buffers[soundId].frequencyInHertz = freq; - _buffers[soundId].bufferState = CD_BS_LOADED; - CDLOG(@"Denshion::CDSoundEngine - =============== Buffer Loaded ==============="); - return TRUE; - + } + + _buffers[soundId].format = format; + _buffers[soundId].sizeInBytes = size; + _buffers[soundId].frequencyInHertz = freq; + _buffers[soundId].bufferState = CD_BS_LOADED; + CDLOGINFO(@"Denshion::CDSoundEngine Buffer %i loaded format:%i freq:%i size:%i",soundId,format,freq,size); + return TRUE; + }//end mutex } /** @@ -573,7 +586,7 @@ - (BOOL) loadBuffer:(int) soundId filePath:(NSString*) filePath ALsizei size; ALsizei freq; - CDLOG(@"Denshion::CDSoundEngine - Loading openAL buffer %i %@", soundId, filePath); + CDLOGINFO(@"Denshion::CDSoundEngine - Loading openAL buffer %i %@", soundId, filePath); CFURLRef fileURL = nil; NSString *path = [CDUtilities fullPathFromRelativePath:filePath]; @@ -599,10 +612,10 @@ - (BOOL) loadBuffer:(int) soundId filePath:(NSString*) filePath -(BOOL) validateBufferId:(int) soundId { if (soundId < 0 || soundId >= bufferTotal) { - CDLOG(@"Denshion::CDSoundEngine - validateBufferId buffer outside range %i",soundId); + CDLOGINFO(@"Denshion::CDSoundEngine - validateBufferId buffer outside range %i",soundId); return NO; } else if (_buffers[soundId].bufferState != CD_BS_LOADED) { - CDLOG(@"Denshion::CDSoundEngine - validateBufferId invalide buffer state %i",soundId); + CDLOGINFO(@"Denshion::CDSoundEngine - validateBufferId invalide buffer state %i",soundId); return NO; } else { return YES; @@ -734,6 +747,12 @@ -(void) _lockSource:(int) sourceIndex lock:(BOOL) lock { -(int) _getSourceIndexForSourceGroup:(int)sourceGroupId { + //Ensure source group id is valid to prevent memory corruption + if (sourceGroupId < 0 || sourceGroupId >= _sourceGroupTotal) { + CDLOG(@"Denshion::CDSoundEngine invalid source group id %i",sourceGroupId); + return CD_NO_SOURCE; + } + int sourceIndex = -1;//Using -1 to indicate no source found BOOL complete = NO; ALint sourceState = 0; @@ -814,15 +833,15 @@ - (ALuint)playSound:(int) soundId sourceGroupId:(int)sourceGroupId pitch:(float) if (!enabled_ || !functioning_ || _buffers[soundId].bufferState != CD_BS_LOADED || _sourceGroups[sourceGroupId].enabled) { #ifdef CD_DEBUG if (!functioning_) { - CDLOG(@"Denshion::CDSoundEngine - sound playback aborted because sound engine is not functioning"); + CDLOGINFO(@"Denshion::CDSoundEngine - sound playback aborted because sound engine is not functioning"); } else if (_buffers[soundId].bufferState != CD_BS_LOADED) { - CDLOG(@"Denshion::CDSoundEngine - sound playback aborted because buffer %i is not loaded", soundId); + CDLOGINFO(@"Denshion::CDSoundEngine - sound playback aborted because buffer %i is not loaded", soundId); } #endif return CD_MUTE; } - - int sourceIndex = [self _getSourceIndexForSourceGroup:sourceGroupId]; + + int sourceIndex = [self _getSourceIndexForSourceGroup:sourceGroupId];//This method ensures sourceIndex is valid if (sourceIndex != CD_NO_SOURCE) { ALint state; @@ -847,8 +866,8 @@ - (ALuint)playSound:(int) soundId sourceGroupId:(int)sourceGroupId pitch:(float) return source; } else { if (alcGetCurrentContext() == NULL) { - CDLOG(@"Denshion::CDSoundEngine - posting bad OpenAL context message"); - [[NSNotificationCenter defaultCenter] postNotificationName:CD_MSG_BAD_AL_CONTEXT object:nil]; + CDLOGINFO(@"Denshion::CDSoundEngine - posting bad OpenAL context message"); + [[NSNotificationCenter defaultCenter] postNotificationName:kCDN_BadAlContext object:nil]; } return CD_NO_SOURCE; } @@ -911,7 +930,7 @@ -(CDSoundSource *) soundSourceForSound:(int) soundId sourceGroupId:(int) sourceG } -(void) _soundSourcePreRelease:(CDSoundSource *) soundSource { - CDLOG(@"Denshion::CDSoundEngine _soundSourcePreRelease %i",soundSource->_sourceIndex); + CDLOGINFO(@"Denshion::CDSoundEngine _soundSourcePreRelease %i",soundSource->_sourceIndex); //Unlock the sound source's source [self _lockSource:soundSource->_sourceIndex lock:NO]; } @@ -921,7 +940,7 @@ -(void) _soundSourcePreRelease:(CDSoundSource *) soundSource { */ - (void) stopSourceGroup:(int) sourceGroupId { - if (!functioning_ || sourceGroupId >= _sourceGroupTotal) { + if (!functioning_ || sourceGroupId >= _sourceGroupTotal || sourceGroupId < 0) { return; } int sourceCount = _sourceGroups[sourceGroupId].totalSources; @@ -957,6 +976,12 @@ - (void) stopAllSounds { * no free sources available then the play request will be ignored and CD_NO_SOURCE will be returned. */ - (void) setSourceGroupNonInterruptible:(int) sourceGroupId isNonInterruptible:(BOOL) isNonInterruptible { + //Ensure source group id is valid to prevent memory corruption + if (sourceGroupId < 0 || sourceGroupId >= _sourceGroupTotal) { + CDLOG(@"Denshion::CDSoundEngine setSourceGroupNonInterruptible invalid source group id %i",sourceGroupId); + return; + } + if (isNonInterruptible) { _sourceGroups[sourceGroupId].nonInterruptible = true; } else { @@ -972,6 +997,12 @@ - (void) setSourceGroupNonInterruptible:(int) sourceGroupId isNonInterruptible:( * no matter what the source group mute setting is. */ - (void) setSourceGroupEnabled:(int) sourceGroupId enabled:(BOOL) enabled { + //Ensure source group id is valid to prevent memory corruption + if (sourceGroupId < 0 || sourceGroupId >= _sourceGroupTotal) { + CDLOG(@"Denshion::CDSoundEngine setSourceGroupEnabled invalid source group id %i",sourceGroupId); + return; + } + if (enabled) { _sourceGroups[sourceGroupId].enabled = true; [self stopSourceGroup:sourceGroupId]; @@ -993,13 +1024,13 @@ -(ALCcontext *) openALContext { - (void) _dumpSourceGroupsInfo { #ifdef CD_DEBUG - CDLOG(@"-------------- source Group Info --------------"); + CDLOGINFO(@"-------------- source Group Info --------------"); for (int i=0; i < _sourceGroupTotal; i++) { - CDLOG(@"Group: %i start:%i total:%i",i,_sourceGroups[i].startIndex, _sourceGroups[i].totalSources); - CDLOG(@"----- mute:%i nonInterruptible:%i",_sourceGroups[i].enabled, _sourceGroups[i].nonInterruptible); - CDLOG(@"----- Source statuses ----"); + CDLOGINFO(@"Group: %i start:%i total:%i",i,_sourceGroups[i].startIndex, _sourceGroups[i].totalSources); + CDLOGINFO(@"----- mute:%i nonInterruptible:%i",_sourceGroups[i].enabled, _sourceGroups[i].nonInterruptible); + CDLOGINFO(@"----- Source statuses ----"); for (int j=0; j < _sourceGroups[i].totalSources; j++) { - CDLOG(@"Source status:%i index=%i locked=%i",j,_sourceGroups[i].sourceStatuses[j] >> 1, _sourceGroups[i].sourceStatuses[j] & 1); + CDLOGINFO(@"Source status:%i index=%i locked=%i",j,_sourceGroups[i].sourceStatuses[j] >> 1, _sourceGroups[i].sourceStatuses[j] & 1); } } #endif @@ -1030,7 +1061,7 @@ -(id)init:(ALuint) theSourceId sourceIndex:(int) index soundEngine:(CDSoundEngin -(void) dealloc { - CDLOG(@"Denshion::CDSoundSource deallocated %i",self->_sourceIndex); + CDLOGINFO(@"Denshion::CDSoundSource deallocated %i",self->_sourceIndex); //Notify sound engine we are about to release [_engine _soundSourcePreRelease:self]; @@ -1114,8 +1145,8 @@ -(BOOL) play { CDSOUNDSOURCE_UPDATE_LAST_ERROR; if (lastError != AL_NO_ERROR) { if (alcGetCurrentContext() == NULL) { - CDLOG(@"Denshion::CDSoundSource - posting bad OpenAL context message"); - [[NSNotificationCenter defaultCenter] postNotificationName:CD_MSG_BAD_AL_CONTEXT object:nil]; + CDLOGINFO(@"Denshion::CDSoundSource - posting bad OpenAL context message"); + [[NSNotificationCenter defaultCenter] postNotificationName:kCDN_BadAlContext object:nil]; } return NO; } else { @@ -1272,7 +1303,7 @@ -(id) init:(NSArray *)loadRequests soundEngine:(CDSoundEngine *) theSoundEngine } -(void) main { - CDLOG(@"Denshion::CDAsynchBufferLoader - loading buffers"); + CDLOGINFO(@"Denshion::CDAsynchBufferLoader - loading buffers"); [super main]; _soundEngine.asynchLoadProgress = 0.0f; @@ -1287,6 +1318,7 @@ -(void) main { //Completed _soundEngine.asynchLoadProgress = 1.0f; + [[NSNotificationCenter defaultCenter] postNotificationName:kCDN_AsynchLoadComplete object:nil]; } @@ -1307,10 +1339,10 @@ @implementation CDBufferLoadRequest @synthesize filePath, soundId; --(id) init:(int) theSoundId filePath:(NSString *) theFilePath { +-(id) init:(int) theSoundId filePath:(const NSString *) theFilePath { if ((self = [super init])) { soundId = theSoundId; - filePath = theFilePath; + filePath = [theFilePath copy];//TODO: is retain necessary or does copy set retain count [filePath retain]; } return self; @@ -1408,7 +1440,7 @@ -(id) init:(id) theTarget interpolationType:(tCDInterpolationType) type startVal } -(void) dealloc { - CDLOG(@"Denshion::CDPropertyModifier deallocated %@",self); + CDLOGINFO(@"Denshion::CDPropertyModifier deallocated %@",self); [target release]; [interpolator release]; [super dealloc]; diff --git a/libs/CocosDenshion/SimpleAudioEngine.m b/libs/CocosDenshion/SimpleAudioEngine.m index a93f86a..cdff26c 100644 --- a/libs/CocosDenshion/SimpleAudioEngine.m +++ b/libs/CocosDenshion/SimpleAudioEngine.m @@ -147,14 +147,12 @@ -(void) preloadEffect:(NSString*) filePath int soundId = [bufferManager bufferForFile:filePath create:YES]; if (soundId == kCDNoBuffer) { CDLOG(@"Denshion::SimpleAudioEngine sound failed to preload %@",filePath); - } else { - CDLOG(@"Denshion::SimpleAudioEngine preloaded %@",filePath); - } + } } -(void) unloadEffect:(NSString*) filePath { - CDLOG(@"Denshion::SimpleAudioEngine unloadedEffect %@",filePath); + CDLOGINFO(@"Denshion::SimpleAudioEngine unloadedEffect %@",filePath); [bufferManager releaseBufferForFile:filePath]; } @@ -212,7 +210,7 @@ -(CDSoundSource *) soundSourceForFile:(NSString*) filePath { int soundId = [bufferManager bufferForFile:filePath create:YES]; if (soundId != kCDNoBuffer) { CDSoundSource *result = [soundEngine soundSourceForSound:soundId sourceGroupId:0]; - CDLOG(@"Denshion::SimpleAudioEngine sound source created for %@",filePath); + CDLOGINFO(@"Denshion::SimpleAudioEngine sound source created for %@",filePath); return result; } else { return nil; diff --git a/libs/FontLabel/FontLabel.m b/libs/FontLabel/FontLabel.m index 4fc82b0..58975b1 100644 --- a/libs/FontLabel/FontLabel.m +++ b/libs/FontLabel/FontLabel.m @@ -168,12 +168,21 @@ - (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)num if (numberOfLines == 1) { // if numberOfLines == 1 we need to use the version that converts spaces - CGSize size = [self.text sizeWithZFont:self.zFont]; + CGSize size; + if (self.zAttributedText == nil) { + size = [self.text sizeWithZFont:self.zFont]; + } else { + size = [self.zAttributedText size]; + } bounds.size.width = MIN(bounds.size.width, size.width); bounds.size.height = MIN(bounds.size.height, size.height); } else { if (numberOfLines > 0) bounds.size.height = MIN(bounds.size.height, self.zFont.leading * numberOfLines); - bounds.size = [self.text sizeWithZFont:self.zFont constrainedToSize:bounds.size lineBreakMode:self.lineBreakMode]; + if (self.zAttributedText == nil) { + bounds.size = [self.text sizeWithZFont:self.zFont constrainedToSize:bounds.size lineBreakMode:self.lineBreakMode]; + } else { + bounds.size = [self.zAttributedText sizeConstrainedToSize:bounds.size lineBreakMode:self.lineBreakMode]; + } } return bounds; } diff --git a/libs/FontLabel/FontLabelStringDrawing.m b/libs/FontLabel/FontLabelStringDrawing.m index 4f30066..2907372 100644 --- a/libs/FontLabel/FontLabelStringDrawing.m +++ b/libs/FontLabel/FontLabelStringDrawing.m @@ -455,7 +455,8 @@ static CGSize drawOrSizeTextConstrainedToSize(BOOL performDraw, NSString *string READ_GLYPHS(); - NSCharacterSet *alphaCharset = [NSCharacterSet alphanumericCharacterSet]; + NSMutableCharacterSet *alphaCharset = [NSMutableCharacterSet alphanumericCharacterSet]; + [alphaCharset addCharactersInString:@"([{'\"\u2019\u02BC"]; // scan left-to-right looking for newlines or until we hit the width constraint // When we hit a wrapping point, calculate truncation as follows: @@ -518,6 +519,27 @@ static CGSize drawOrSizeTextConstrainedToSize(BOOL performDraw, NSString *string lineAscender = MAX(lineAscender, currentFont.ascender); } unichar c = characters[idx]; + // Mark a wrap point before spaces and after any stretch of non-alpha characters + BOOL markWrap = NO; + if (c == (unichar)' ') { + markWrap = YES; + } else if ([alphaCharset characterIsMember:c]) { + if (!inAlpha) { + markWrap = YES; + inAlpha = YES; + } + } else { + inAlpha = NO; + } + if (markWrap) { + lastWrapCache = (__typeof__(lastWrapCache)){ + .index = idx, + .glyphIndex = glyphIdx, + .currentRunIdx = currentRunIdx, + .lineSize = lineSize + }; + } + // process the line if (c == (unichar)'\n' || c == 0x0085) { // U+0085 is the NEXT_LINE unicode character finishLine = YES; skipCount = 1; @@ -682,26 +704,6 @@ static CGSize drawOrSizeTextConstrainedToSize(BOOL performDraw, NSString *string glyphIdx += skipCount; lineCount++; } else { - // Mark a wrap point before spaces and after any stretch of non-alpha characters - BOOL markWrap = NO; - if (characters[idx] == (unichar)' ') { - markWrap = YES; - } else if ([alphaCharset characterIsMember:characters[idx]]) { - if (!inAlpha) { - markWrap = YES; - inAlpha = YES; - } - } else { - inAlpha = NO; - } - if (markWrap) { - lastWrapCache = (__typeof__(lastWrapCache)){ - .index = idx, - .glyphIndex = glyphIdx, - .currentRunIdx = currentRunIdx, - .lineSize = lineSize - }; - } lineSize.width += advances[glyphIdx]; glyphIdx++; idx++; diff --git a/libs/FontLabel/FontManager.m b/libs/FontLabel/FontManager.m index c961de1..12eac2d 100644 --- a/libs/FontLabel/FontManager.m +++ b/libs/FontLabel/FontManager.m @@ -21,7 +21,6 @@ #import "FontManager.h" #import "ZFont.h" -#import "CCConfiguration.h" static FontManager *sharedFontManager = nil; diff --git a/libs/FontLabel/ZAttributedString.m b/libs/FontLabel/ZAttributedString.m index e1557c0..a4163bc 100644 --- a/libs/FontLabel/ZAttributedString.m +++ b/libs/FontLabel/ZAttributedString.m @@ -67,7 +67,7 @@ - (id)copyWithZone:(NSZone *)zone { } - (id)mutableCopyWithZone:(NSZone *)zone { - return [(ZMutableAttributedString*)[ZMutableAttributedString allocWithZone:zone] initWithAttributedString:self]; + return [(ZMutableAttributedString *)[ZMutableAttributedString allocWithZone:zone] initWithAttributedString:self]; } - (NSUInteger)length { @@ -291,7 +291,7 @@ - (NSDictionary *)attributesAtIndex:(NSUInteger)index longestEffectiveRange:(NSR NSUInteger endRunIndex = runIndex+1; runIndex--; // search backwards - while (true) { + while (1) { if (run.index <= rangeLimit.location) { break; } @@ -349,7 +349,7 @@ - (void)offsetRunsInRange:(NSRange )range byOffset:(NSInteger)offset; @implementation ZMutableAttributedString - (id)copyWithZone:(NSZone *)zone { - return [(ZMutableAttributedString*)[ZAttributedString allocWithZone:zone] initWithAttributedString:self]; + return [(ZAttributedString *)[ZAttributedString allocWithZone:zone] initWithAttributedString:self]; } - (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range { @@ -459,7 +459,8 @@ - (NSRange)rangeOfAttributeRunsForRange:(NSRange)range { if (((ZAttributeRun *)[_attributes lastObject]).index < NSMaxRange(range)) { NSRange subrange = NSMakeRange(first, [_attributes count] - first); if (NSMaxRange(range) < [_buffer length]) { - ZAttributeRun *newRun = [[ZAttributeRun alloc] initWithIndex:NSMaxRange(range) attributes:(NSDictionary*)[[_attributes lastObject] attributes]]; + ZAttributeRun *newRun = [[ZAttributeRun alloc] initWithIndex:NSMaxRange(range) + attributes:(NSDictionary*)[(ZAttributeRun *)[_attributes lastObject] attributes]]; [_attributes addObject:newRun]; [newRun release]; } @@ -483,7 +484,7 @@ - (NSRange)rangeOfAttributeRunsForRange:(NSRange)range { if ([[_attributes objectAtIndex:firstAfter] index] > NSMaxRange(range)) { // the first after is too far after, insert another run! ZAttributeRun *newRun = [[ZAttributeRun alloc] initWithIndex:NSMaxRange(range) - attributes:(NSDictionary*)[[_attributes objectAtIndex:firstAfter-1] attributes]]; + attributes:[(ZAttributeRun *)[_attributes objectAtIndex:firstAfter-1] attributes]]; [_attributes insertObject:newRun atIndex:firstAfter]; [newRun release]; } @@ -536,6 +537,7 @@ + (id)attributeRunWithIndex:(NSUInteger)idx attributes:(NSDictionary *)attrs { } - (id)initWithIndex:(NSUInteger)idx attributes:(NSDictionary *)attrs { + NSParameterAssert(idx >= 0); if ((self = [super init])) { _index = idx; if (attrs == nil) { diff --git a/libs/FontLabel/ZFont.m b/libs/FontLabel/ZFont.m index a81f53b..793b13a 100644 --- a/libs/FontLabel/ZFont.m +++ b/libs/FontLabel/ZFont.m @@ -52,7 +52,6 @@ - (id)initWithCGFont:(CGFontRef)cgFont size:(CGFloat)fontSize { - (id)init { NSAssert(NO, @"-init is not valid for ZFont"); - [self release]; return nil; } diff --git a/libs/TouchJSON/CDataScanner.h b/libs/TouchJSON/CDataScanner.h index a768892..41f68e8 100644 --- a/libs/TouchJSON/CDataScanner.h +++ b/libs/TouchJSON/CDataScanner.h @@ -1,9 +1,9 @@ // // CDataScanner.h -// TouchJSON +// TouchCode // // Created by Jonathan Wight on 04/16/08. -// Copyright (c) 2008 Jonathan Wight +// Copyright 2008 toxicsoftware.com. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -38,15 +38,14 @@ u_int8_t *end; u_int8_t *current; NSUInteger length; - - NSCharacterSet *doubleCharacters; } @property (readwrite, nonatomic, retain) NSData *data; @property (readwrite, nonatomic, assign) NSUInteger scanLocation; +@property (readonly, nonatomic, assign) NSUInteger bytesRemaining; @property (readonly, nonatomic, assign) BOOL isAtEnd; -+ (id)scannerWithData:(NSData *)inData; +- (id)initWithData:(NSData *)inData; - (unichar)currentCharacter; - (unichar)scanCharacter; @@ -60,9 +59,13 @@ - (BOOL)scanUpToCharactersFromSet:(NSCharacterSet *)set intoString:(NSString **)outValue; // inSet must only contain 7-bit ASCII characters - (BOOL)scanNumber:(NSNumber **)outValue; +- (BOOL)scanDecimalNumber:(NSDecimalNumber **)outValue; + +- (BOOL)scanDataOfLength:(NSUInteger)inLength intoData:(NSData **)outData; - (void)skipWhitespace; - (NSString *)remainingString; +- (NSData *)remainingData; @end diff --git a/libs/TouchJSON/CDataScanner.m b/libs/TouchJSON/CDataScanner.m index 44df309..b3cee6f 100644 --- a/libs/TouchJSON/CDataScanner.m +++ b/libs/TouchJSON/CDataScanner.m @@ -1,9 +1,9 @@ // // CDataScanner.m -// TouchJSON +// TouchCode // // Created by Jonathan Wight on 04/16/08. -// Copyright (c) 2008 Jonathan Wight +// Copyright 2008 toxicsoftware.com. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -32,239 +32,309 @@ #import "CDataScanner_Extensions.h" @interface CDataScanner () -@property (readwrite, nonatomic, retain) NSCharacterSet *doubleCharacters; @end #pragma mark - inline static unichar CharacterAtPointer(void *start, void *end) -{ -#pragma unused(end) - -const u_int8_t theByte = *(u_int8_t *)start; -if (theByte & 0x80) - { - // TODO -- UNICODE!!!! (well in theory nothing todo here) - } -const unichar theCharacter = theByte; -return(theCharacter); -} - -@implementation CDataScanner - -@dynamic data; -@dynamic scanLocation; -@dynamic isAtEnd; -@synthesize doubleCharacters; - -+ (id)scannerWithData:(NSData *)inData -{ -CDataScanner *theScanner = [[[self alloc] init] autorelease]; -theScanner.data = inData; -return(theScanner); -} + { + #pragma unused(end) + + const u_int8_t theByte = *(u_int8_t *)start; + if (theByte & 0x80) + { + // TODO -- UNICODE!!!! (well in theory nothing todo here) + } + const unichar theCharacter = theByte; + return(theCharacter); + } + + static NSCharacterSet *sDoubleCharacters = NULL; + + @implementation CDataScanner - (id)init -{ -if ((self = [super init]) != nil) - { - self.doubleCharacters = [NSCharacterSet characterSetWithCharactersInString:@"0123456789eE-."]; - } -return(self); -} + { + if ((self = [super init]) != NULL) + { + } + return(self); + } + +- (id)initWithData:(NSData *)inData; + { + if ((self = [self init]) != NULL) + { + [self setData:inData]; + } + return(self); + } + + + (void)initialize + { + if (sDoubleCharacters == NULL) + { + sDoubleCharacters = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789eE-+."] retain]; + } + } - (void)dealloc -{ -self.data = NULL; -self.doubleCharacters = NULL; -// -[super dealloc]; -} + { + [data release]; + data = NULL; + // + [super dealloc]; + } - (NSUInteger)scanLocation -{ -return(current - start); -} + { + return(current - start); + } + +- (NSUInteger)bytesRemaining + { + return(end - current); + } - (NSData *)data -{ -return(data); -} + { + return(data); + } - (void)setData:(NSData *)inData -{ -if (data != inData) - { - if (data) - { - [data release]; - data = NULL; - } - - if (inData) - { - data = [inData retain]; - // - start = (u_int8_t *)data.bytes; - end = start + data.length; - current = start; - length = data.length; - } + { + if (data != inData) + { + [data release]; + data = [inData retain]; + } + + if (data) + { + start = (u_int8_t *)data.bytes; + end = start + data.length; + current = start; + length = data.length; + } + else + { + start = NULL; + end = NULL; + current = NULL; + length = 0; + } } -} - (void)setScanLocation:(NSUInteger)inScanLocation -{ -current = start + inScanLocation; -} + { + current = start + inScanLocation; + } - (BOOL)isAtEnd -{ -return(self.scanLocation >= length); -} + { + return(self.scanLocation >= length); + } - (unichar)currentCharacter -{ -return(CharacterAtPointer(current, end)); -} + { + return(CharacterAtPointer(current, end)); + } #pragma mark - - (unichar)scanCharacter -{ -const unichar theCharacter = CharacterAtPointer(current++, end); -return(theCharacter); -} + { + const unichar theCharacter = CharacterAtPointer(current++, end); + return(theCharacter); + } - (BOOL)scanCharacter:(unichar)inCharacter -{ -unichar theCharacter = CharacterAtPointer(current, end); -if (theCharacter == inCharacter) - { - ++current; - return(YES); - } -else - return(NO); -} - -- (BOOL)scanUTF8String:(const char *)inString intoString:(NSString **)outValue; -{ -const size_t theLength = strlen(inString); -if ((size_t)(end - current) < theLength) - return(NO); -if (strncmp((char *)current, inString, theLength) == 0) - { - current += theLength; - if (outValue) - *outValue = [NSString stringWithUTF8String:inString]; - return(YES); - } -return(NO); -} + { + unichar theCharacter = CharacterAtPointer(current, end); + if (theCharacter == inCharacter) + { + ++current; + return(YES); + } + else + return(NO); + } + +- (BOOL)scanUTF8String:(const char *)inString intoString:(NSString **)outValue + { + const size_t theLength = strlen(inString); + if ((size_t)(end - current) < theLength) + return(NO); + if (strncmp((char *)current, inString, theLength) == 0) + { + current += theLength; + if (outValue) + *outValue = [NSString stringWithUTF8String:inString]; + return(YES); + } + return(NO); + } - (BOOL)scanString:(NSString *)inString intoString:(NSString **)outValue -{ -if ((size_t)(end - current) < inString.length) - return(NO); -if (strncmp((char *)current, [inString UTF8String], inString.length) == 0) - { - current += inString.length; - if (outValue) - *outValue = inString; - return(YES); - } -return(NO); -} + { + if ((size_t)(end - current) < inString.length) + return(NO); + if (strncmp((char *)current, [inString UTF8String], inString.length) == 0) + { + current += inString.length; + if (outValue) + *outValue = inString; + return(YES); + } + return(NO); + } - (BOOL)scanCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue -{ -u_int8_t *P; -for (P = current; P < end && [inSet characterIsMember:*P] == YES; ++P) - ; - -if (P == current) - { - return(NO); - } - -if (outValue) - { - *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease]; - } - -current = P; - -return(YES); -} + { + u_int8_t *P; + for (P = current; P < end && [inSet characterIsMember:*P] == YES; ++P) + ; -- (BOOL)scanUpToString:(NSString *)inString intoString:(NSString **)outValue -{ -const char *theToken = [inString UTF8String]; -const char *theResult = strnstr((char *)current, theToken, end - current); -if (theResult == NULL) - { - return(NO); - } + if (P == current) + { + return(NO); + } + + if (outValue) + { + *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease]; + } -if (outValue) - { - *outValue = [[[NSString alloc] initWithBytes:current length:theResult - (char *)current encoding:NSUTF8StringEncoding] autorelease]; - } + current = P; -current = (u_int8_t *)theResult; + return(YES); + } -return(YES); -} +- (BOOL)scanUpToString:(NSString *)inString intoString:(NSString **)outValue + { + const char *theToken = [inString UTF8String]; + const char *theResult = strnstr((char *)current, theToken, end - current); + if (theResult == NULL) + { + return(NO); + } + + if (outValue) + { + *outValue = [[[NSString alloc] initWithBytes:current length:theResult - (char *)current encoding:NSUTF8StringEncoding] autorelease]; + } + + current = (u_int8_t *)theResult; + + return(YES); + } - (BOOL)scanUpToCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue -{ -u_int8_t *P; -for (P = current; P < end && [inSet characterIsMember:*P] == NO; ++P) - ; - -if (P == current) - { - return(NO); - } - -if (outValue) - { - *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease]; - } - -current = P; - -return(YES); -} + { + u_int8_t *P; + for (P = current; P < end && [inSet characterIsMember:*P] == NO; ++P) + ; + + if (P == current) + { + return(NO); + } + + if (outValue) + { + *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease]; + } + + current = P; + + return(YES); + } - (BOOL)scanNumber:(NSNumber **)outValue -{ -// Replace all of this with a strtod call -NSString *theString = NULL; -if ([self scanCharactersFromSet:doubleCharacters intoString:&theString]) - { - if (outValue) - *outValue = [NSNumber numberWithDouble:[theString doubleValue]]; // TODO dont use doubleValue - return(YES); - } -return(NO); -} + { + NSString *theString = NULL; + if ([self scanCharactersFromSet:sDoubleCharacters intoString:&theString]) + { + if ([theString rangeOfString:@"."].location != NSNotFound) + { + if (outValue) + { + *outValue = [NSDecimalNumber decimalNumberWithString:theString]; + } + return(YES); + } + else if ([theString rangeOfString:@"-"].location != NSNotFound) + { + if (outValue != NULL) + { + *outValue = [NSNumber numberWithLongLong:[theString longLongValue]]; + } + return(YES); + } + else + { + if (outValue != NULL) + { + *outValue = [NSNumber numberWithUnsignedLongLong:strtoull([theString UTF8String], NULL, 0)]; + } + return(YES); + } + + } + return(NO); + } + +- (BOOL)scanDecimalNumber:(NSDecimalNumber **)outValue; + { + NSString *theString = NULL; + if ([self scanCharactersFromSet:sDoubleCharacters intoString:&theString]) + { + if (outValue) + { + *outValue = [NSDecimalNumber decimalNumberWithString:theString]; + } + return(YES); + } + return(NO); + } + +- (BOOL)scanDataOfLength:(NSUInteger)inLength intoData:(NSData **)outData; + { + if (self.bytesRemaining < inLength) + { + return(NO); + } + + if (outData) + { + *outData = [NSData dataWithBytes:current length:inLength]; + } + + current += inLength; + return(YES); + } + - (void)skipWhitespace -{ -u_int8_t *P; -for (P = current; P < end && (isspace(*P)); ++P) - ; + { + u_int8_t *P; + for (P = current; P < end && (isspace(*P)); ++P) + ; -current = P; -} + current = P; + } - (NSString *)remainingString -{ -NSData *theRemainingData = [NSData dataWithBytes:current length:end - current]; -NSString *theString = [[[NSString alloc] initWithData:theRemainingData encoding:NSUTF8StringEncoding] autorelease]; -return(theString); -} + { + NSData *theRemainingData = [NSData dataWithBytes:current length:end - current]; + NSString *theString = [[[NSString alloc] initWithData:theRemainingData encoding:NSUTF8StringEncoding] autorelease]; + return(theString); + } -@end +- (NSData *)remainingData; + { + NSData *theRemainingData = [NSData dataWithBytes:current length:end - current]; + return(theRemainingData); + } + + @end diff --git a/libs/TouchJSON/Extensions/CDataScanner_Extensions.h b/libs/TouchJSON/Extensions/CDataScanner_Extensions.h index 8c3c8dd..cde1dbb 100644 --- a/libs/TouchJSON/Extensions/CDataScanner_Extensions.h +++ b/libs/TouchJSON/Extensions/CDataScanner_Extensions.h @@ -1,9 +1,9 @@ // // CDataScanner_Extensions.h -// TouchJSON +// TouchCode // // Created by Jonathan Wight on 12/08/2005. -// Copyright (c) 2005 Jonathan Wight +// Copyright 2005 toxicsoftware.com. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -34,4 +34,7 @@ - (BOOL)scanCStyleComment:(NSString **)outComment; - (BOOL)scanCPlusPlusStyleComment:(NSString **)outComment; +- (NSUInteger)lineOfScanLocation; +- (NSDictionary *)userInfoForScanLocation; + @end diff --git a/libs/TouchJSON/Extensions/CDataScanner_Extensions.m b/libs/TouchJSON/Extensions/CDataScanner_Extensions.m index c1a16d9..90dbbda 100644 --- a/libs/TouchJSON/Extensions/CDataScanner_Extensions.m +++ b/libs/TouchJSON/Extensions/CDataScanner_Extensions.m @@ -1,9 +1,9 @@ // -// NSScanner_Extensions.m -// TouchJSON +// CDataScanner_Extensions.m +// TouchCode // // Created by Jonathan Wight on 12/08/2005. -// Copyright (c) 2005 Jonathan Wight +// Copyright 2005 toxicsoftware.com. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -29,7 +29,12 @@ #import "CDataScanner_Extensions.h" -#import "NSCharacterSet_Extensions.h" +#define LF 0x000a // Line Feed +#define FF 0x000c // Form Feed +#define CR 0x000d // Carriage Return +#define NEL 0x0085 // Next Line +#define LS 0x2028 // Line Separator +#define PS 0x2029 // Paragraph Separator @implementation CDataScanner (CDataScanner_Extensions) @@ -59,22 +64,72 @@ - (BOOL)scanCStyleComment:(NSString **)outComment } - (BOOL)scanCPlusPlusStyleComment:(NSString **)outComment -{ -if ([self scanString:@"//" intoString:NULL] == YES) - { - NSString *theComment = NULL; - [self scanUpToCharactersFromSet:[NSCharacterSet linebreaksCharacterSet] intoString:&theComment]; - [self scanCharactersFromSet:[NSCharacterSet linebreaksCharacterSet] intoString:NULL]; + { + if ([self scanString:@"//" intoString:NULL] == YES) + { + unichar theCharacters[] = { LF, FF, CR, NEL, LS, PS, }; + NSCharacterSet *theLineBreaksCharacterSet = [NSCharacterSet characterSetWithCharactersInString:[NSString stringWithCharacters:theCharacters length:sizeof(theCharacters) / sizeof(*theCharacters)]]; - if (outComment != NULL) - *outComment = theComment; + NSString *theComment = NULL; + [self scanUpToCharactersFromSet:theLineBreaksCharacterSet intoString:&theComment]; + [self scanCharactersFromSet:theLineBreaksCharacterSet intoString:NULL]; - return(YES); - } -else - { - return(NO); - } -} + if (outComment != NULL) + *outComment = theComment; + + return(YES); + } + else + { + return(NO); + } + } + +- (NSUInteger)lineOfScanLocation + { + NSUInteger theLine = 0; + for (const u_int8_t *C = start; C < current; ++C) + { + // TODO: JIW What about MS-DOS line endings you bastard! (Also other unicode line endings) + if (*C == '\n' || *C == '\r') + { + ++theLine; + } + } + return(theLine); + } + +- (NSDictionary *)userInfoForScanLocation + { + NSUInteger theLine = 0; + const u_int8_t *theLineStart = start; + for (const u_int8_t *C = start; C < current; ++C) + { + if (*C == '\n' || *C == '\r') + { + theLineStart = C - 1; + ++theLine; + } + } + + NSUInteger theCharacter = current - theLineStart; + + NSRange theStartRange = NSIntersectionRange((NSRange){ .location = MAX((NSInteger)self.scanLocation - 20, 0), .length = 20 + (NSInteger)self.scanLocation - 20 }, (NSRange){ .location = 0, .length = self.data.length }); + NSRange theEndRange = NSIntersectionRange((NSRange){ .location = self.scanLocation, .length = 20 }, (NSRange){ .location = 0, .length = self.data.length }); + + + NSString *theSnippet = [NSString stringWithFormat:@"%@!HERE>!%@", + [[[NSString alloc] initWithData:[self.data subdataWithRange:theStartRange] encoding:NSUTF8StringEncoding] autorelease], + [[[NSString alloc] initWithData:[self.data subdataWithRange:theEndRange] encoding:NSUTF8StringEncoding] autorelease] + ]; + + NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithUnsignedInteger:theLine], @"line", + [NSNumber numberWithUnsignedInteger:theCharacter], @"character", + [NSNumber numberWithUnsignedInteger:self.scanLocation], @"location", + theSnippet, @"snippet", + NULL]; + return(theUserInfo); + } @end diff --git a/libs/TouchJSON/Extensions/NSCharacterSet_Extensions.h b/libs/TouchJSON/Extensions/NSCharacterSet_Extensions.h deleted file mode 100644 index c934a7d..0000000 --- a/libs/TouchJSON/Extensions/NSCharacterSet_Extensions.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// NSCharacterSet_Extensions.h -// TouchJSON -// -// Created by Jonathan Wight on 12/08/2005. -// Copyright (c) 2005 Jonathan Wight -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#import - -@interface NSCharacterSet (NSCharacterSet_Extensions) - -+ (NSCharacterSet *)linebreaksCharacterSet; - -@end diff --git a/libs/TouchJSON/Extensions/NSCharacterSet_Extensions.m b/libs/TouchJSON/Extensions/NSCharacterSet_Extensions.m deleted file mode 100644 index f0306a5..0000000 --- a/libs/TouchJSON/Extensions/NSCharacterSet_Extensions.m +++ /dev/null @@ -1,48 +0,0 @@ -// -// NSCharacterSet_Extensions.m -// TouchJSON -// -// Created by Jonathan Wight on 12/08/2005. -// Copyright (c) 2005 Jonathan Wight -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#import "NSCharacterSet_Extensions.h" - -@implementation NSCharacterSet (NSCharacterSet_Extensions) - -#define LF 0x000a // Line Feed -#define FF 0x000c // Form Feed -#define CR 0x000d // Carriage Return -#define NEL 0x0085 // Next Line -#define LS 0x2028 // Line Separator -#define PS 0x2029 // Paragraph Separator - -+ (NSCharacterSet *)linebreaksCharacterSet -{ -unichar theCharacters[] = { LF, FF, CR, NEL, LS, PS, }; - -return([NSCharacterSet characterSetWithCharactersInString:[NSString stringWithCharacters:theCharacters length:sizeof(theCharacters) / sizeof(*theCharacters)]]); -} - -@end diff --git a/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.h b/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.h index 4d88124..6e611d0 100644 --- a/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.h +++ b/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.h @@ -1,9 +1,9 @@ // // NSDictionary_JSONExtensions.h -// TouchJSON +// TouchCode // // Created by Jonathan Wight on 04/17/08. -// Copyright (c) 2008 Jonathan Wight +// Copyright 2008 toxicsoftware.com. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -32,5 +32,6 @@ @interface NSDictionary (NSDictionary_JSONExtensions) + (id)dictionaryWithJSONData:(NSData *)inData error:(NSError **)outError; ++ (id)dictionaryWithJSONString:(NSString *)inJSON error:(NSError **)outError; @end diff --git a/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.m b/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.m index 005efc6..c0bb43c 100644 --- a/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.m +++ b/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.m @@ -1,9 +1,9 @@ // // NSDictionary_JSONExtensions.m -// TouchJSON +// TouchCode // // Created by Jonathan Wight on 04/17/08. -// Copyright (c) 2008 Jonathan Wight +// Copyright 2008 toxicsoftware.com. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -34,8 +34,14 @@ @implementation NSDictionary (NSDictionary_JSONExtensions) + (id)dictionaryWithJSONData:(NSData *)inData error:(NSError **)outError -{ -return([[CJSONDeserializer deserializer] deserialize:inData error:outError]); -} + { + return([[CJSONDeserializer deserializer] deserialize:inData error:outError]); + } + ++ (id)dictionaryWithJSONString:(NSString *)inJSON error:(NSError **)outError; + { + NSData *theData = [inJSON dataUsingEncoding:NSUTF8StringEncoding]; + return([self dictionaryWithJSONData:theData error:outError]); + } @end diff --git a/libs/TouchJSON/Extensions/NSScanner_Extensions.h b/libs/TouchJSON/Extensions/NSScanner_Extensions.h deleted file mode 100644 index fc8c774..0000000 --- a/libs/TouchJSON/Extensions/NSScanner_Extensions.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// NSScanner_Extensions.h -// CocoaJSON -// -// Created by Jonathan Wight on 12/08/2005. -// Copyright (c) 2005 Jonathan Wight -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#import - -@interface NSScanner (NSScanner_Extensions) - -- (NSString *)remainingString; - -- (unichar)currentCharacter; -- (unichar)scanCharacter; -- (BOOL)scanCharacter:(unichar)inCharacter; -- (void)backtrack:(unsigned)inCount; - -- (BOOL)scanCStyleComment:(NSString **)outComment; -- (BOOL)scanCPlusPlusStyleComment:(NSString **)outComment; - -@end diff --git a/libs/TouchJSON/Extensions/NSScanner_Extensions.m b/libs/TouchJSON/Extensions/NSScanner_Extensions.m deleted file mode 100644 index 981366f..0000000 --- a/libs/TouchJSON/Extensions/NSScanner_Extensions.m +++ /dev/null @@ -1,118 +0,0 @@ -// -// NSScanner_Extensions.m -// CocoaJSON -// -// Created by Jonathan Wight on 12/08/2005. -// Copyright (c) 2005 Jonathan Wight -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#import "NSScanner_Extensions.h" - -#import "NSCharacterSet_Extensions.h" - -@implementation NSScanner (NSScanner_Extensions) - -- (NSString *)remainingString -{ -return([[self string] substringFromIndex:[self scanLocation]]); -} - -- (unichar)currentCharacter -{ -return([[self string] characterAtIndex:[self scanLocation]]); -} - -- (unichar)scanCharacter -{ -unsigned theScanLocation = [self scanLocation]; -unichar theCharacter = [[self string] characterAtIndex:theScanLocation]; -[self setScanLocation:theScanLocation + 1]; -return(theCharacter); -} - -- (BOOL)scanCharacter:(unichar)inCharacter -{ -unsigned theScanLocation = [self scanLocation]; -if ([[self string] characterAtIndex:theScanLocation] == inCharacter) - { - [self setScanLocation:theScanLocation + 1]; - return(YES); - } -else - return(NO); -} - -- (void)backtrack:(unsigned)inCount -{ -unsigned theScanLocation = [self scanLocation]; -if (inCount > theScanLocation) - [NSException raise:NSGenericException format:@"Backtracked too far."]; -[self setScanLocation:theScanLocation - inCount]; -} - -- (BOOL)scanCStyleComment:(NSString **)outComment -{ -if ([self scanString:@"/*" intoString:NULL] == YES) - { - NSString *theComment = NULL; - if ([self scanUpToString:@"*/" intoString:&theComment] == NO) - [NSException raise:NSGenericException format:@"Started to scan a C style comment but it wasn't terminated."]; - - if ([theComment rangeOfString:@"/*"].location != NSNotFound) - [NSException raise:NSGenericException format:@"C style comments should not be nested."]; - - if ([self scanString:@"*/" intoString:NULL] == NO) - [NSException raise:NSGenericException format:@"C style comment did not end correctly."]; - - if (outComment != NULL) - *outComment = theComment; - - return(YES); - } -else - { - return(NO); - } -} - -- (BOOL)scanCPlusPlusStyleComment:(NSString **)outComment -{ -if ([self scanString:@"//" intoString:NULL] == YES) - { - NSString *theComment = NULL; - [self scanUpToCharactersFromSet:[NSCharacterSet linebreaksCharacterSet] intoString:&theComment]; - [self scanCharactersFromSet:[NSCharacterSet linebreaksCharacterSet] intoString:NULL]; - - if (outComment != NULL) - *outComment = theComment; - - return(YES); - } -else - { - return(NO); - } -} - -@end diff --git a/libs/TouchJSON/JSON/CJSONDeserializer.h b/libs/TouchJSON/JSON/CJSONDeserializer.h old mode 100755 new mode 100644 index 7a805f9..0c3ed02 --- a/libs/TouchJSON/JSON/CJSONDeserializer.h +++ b/libs/TouchJSON/JSON/CJSONDeserializer.h @@ -1,9 +1,9 @@ // // CJSONDeserializer.h -// TouchJSON +// TouchCode // // Created by Jonathan Wight on 12/15/2005. -// Copyright (c) 2005 Jonathan Wight +// Copyright 2005 toxicsoftware.com. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -29,31 +29,35 @@ #import -extern NSString *const kJSONDeserializerErrorDomain /* = @"CJSONDeserializerErrorDomain" */; - -@protocol CDeserializerProtocol - -- (id)deserializeAsDictionary:(NSData *)inData error:(NSError **)outError; +#import "CJSONScanner.h" -@end +extern NSString *const kJSONDeserializerErrorDomain /* = @"CJSONDeserializerErrorDomain" */; -#pragma mark - +enum { + kJSONDeserializationOptions_MutableContainers = kJSONScannerOptions_MutableContainers, + kJSONDeserializationOptions_MutableLeaves = kJSONScannerOptions_MutableLeaves, +}; +typedef NSUInteger EJSONDeserializationOptions; -@interface CJSONDeserializer : NSObject { +@class CJSONScanner; +@interface CJSONDeserializer : NSObject { + CJSONScanner *scanner; + EJSONDeserializationOptions options; } -+ (id)deserializer; +@property (readwrite, nonatomic, retain) CJSONScanner *scanner; +/// Object to return instead when a null encountered in the JSON. Defaults to NSNull. Setting to null causes the scanner to skip null values. +@property (readwrite, nonatomic, retain) id nullObject; +/// JSON must be encoded in Unicode (UTF-8, UTF-16 or UTF-32). Use this if you expect to get the JSON in another encoding. +@property (readwrite, nonatomic, assign) NSStringEncoding allowedEncoding; +@property (readwrite, nonatomic, assign) EJSONDeserializationOptions options; -- (id)deserializeAsDictionary:(NSData *)inData error:(NSError **)outError; - -@end - -#pragma mark - - -@interface CJSONDeserializer (CJSONDeserializer_Deprecated) ++ (id)deserializer; -/// You should switch to using deserializeAsDictionary:error: instead. - (id)deserialize:(NSData *)inData error:(NSError **)outError; +- (id)deserializeAsDictionary:(NSData *)inData error:(NSError **)outError; +- (id)deserializeAsArray:(NSData *)inData error:(NSError **)outError; + @end diff --git a/libs/TouchJSON/JSON/CJSONDeserializer.m b/libs/TouchJSON/JSON/CJSONDeserializer.m old mode 100755 new mode 100644 index 1dbb317..27a2d03 --- a/libs/TouchJSON/JSON/CJSONDeserializer.m +++ b/libs/TouchJSON/JSON/CJSONDeserializer.m @@ -1,9 +1,9 @@ // // CJSONDeserializer.m -// TouchJSON +// TouchCode // // Created by Jonathan Wight on 12/15/2005. -// Copyright (c) 2005 Jonathan Wight +// Copyright 2005 toxicsoftware.com. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -34,51 +34,128 @@ NSString *const kJSONDeserializerErrorDomain = @"CJSONDeserializerErrorDomain"; +@interface CJSONDeserializer () +@end + @implementation CJSONDeserializer +@synthesize scanner; +@synthesize options; + + (id)deserializer -{ -return([[[self alloc] init] autorelease]); -} - -- (id)deserializeAsDictionary:(NSData *)inData error:(NSError **)outError; -{ -if (inData == NULL || [inData length] == 0) - { - if (outError) - *outError = [NSError errorWithDomain:kJSONDeserializerErrorDomain code:-1 userInfo:NULL]; - - return(NULL); - } -CJSONScanner *theScanner = [CJSONScanner scannerWithData:inData]; -NSDictionary *theDictionary = NULL; -if ([theScanner scanJSONDictionary:&theDictionary error:outError] == YES) - return(theDictionary); -else - return(NULL); -} + { + return([[[self alloc] init] autorelease]); + } -@end +- (id)init + { + if ((self = [super init]) != NULL) + { + } + return(self); + } + +- (void)dealloc + { + [scanner release]; + scanner = NULL; + // + [super dealloc]; + } + +#pragma mark - + +- (CJSONScanner *)scanner + { + if (scanner == NULL) + { + scanner = [[CJSONScanner alloc] init]; + } + return(scanner); + } + +- (id)nullObject + { + return(self.scanner.nullObject); + } + +- (void)setNullObject:(id)inNullObject + { + self.scanner.nullObject = inNullObject; + } #pragma mark - -@implementation CJSONDeserializer (CJSONDeserializer_Deprecated) +- (NSStringEncoding)allowedEncoding + { + return(self.scanner.allowedEncoding); + } + +- (void)setAllowedEncoding:(NSStringEncoding)inAllowedEncoding + { + self.scanner.allowedEncoding = inAllowedEncoding; + } + +#pragma mark - - (id)deserialize:(NSData *)inData error:(NSError **)outError -{ -if (inData == NULL || [inData length] == 0) - { - if (outError) - *outError = [NSError errorWithDomain:kJSONDeserializerErrorDomain code:-1 userInfo:NULL]; - - return(NULL); - } -CJSONScanner *theScanner = [CJSONScanner scannerWithData:inData]; -id theObject = NULL; -if ([theScanner scanJSONObject:&theObject error:outError] == YES) - return(theObject); -else - return(NULL); -} + { + if (inData == NULL || [inData length] == 0) + { + if (outError) + *outError = [NSError errorWithDomain:kJSONDeserializerErrorDomain code:kJSONScannerErrorCode_NothingToScan userInfo:NULL]; + + return(NULL); + } + if ([self.scanner setData:inData error:outError] == NO) + { + return(NULL); + } + id theObject = NULL; + if ([self.scanner scanJSONObject:&theObject error:outError] == YES) + return(theObject); + else + return(NULL); + } + +- (id)deserializeAsDictionary:(NSData *)inData error:(NSError **)outError + { + if (inData == NULL || [inData length] == 0) + { + if (outError) + *outError = [NSError errorWithDomain:kJSONDeserializerErrorDomain code:kJSONScannerErrorCode_NothingToScan userInfo:NULL]; + + return(NULL); + } + if ([self.scanner setData:inData error:outError] == NO) + { + return(NULL); + } + NSDictionary *theDictionary = NULL; + if ([self.scanner scanJSONDictionary:&theDictionary error:outError] == YES) + return(theDictionary); + else + return(NULL); + } + +- (id)deserializeAsArray:(NSData *)inData error:(NSError **)outError + { + if (inData == NULL || [inData length] == 0) + { + if (outError) + *outError = [NSError errorWithDomain:kJSONDeserializerErrorDomain code:kJSONScannerErrorCode_NothingToScan userInfo:NULL]; + + return(NULL); + } + if ([self.scanner setData:inData error:outError] == NO) + { + return(NULL); + } + NSArray *theArray = NULL; + if ([self.scanner scanJSONArray:&theArray error:outError] == YES) + return(theArray); + else + return(NULL); + } @end diff --git a/libs/TouchJSON/JSON/CJSONScanner.h b/libs/TouchJSON/JSON/CJSONScanner.h index 70d6074..d410893 100644 --- a/libs/TouchJSON/JSON/CJSONScanner.h +++ b/libs/TouchJSON/JSON/CJSONScanner.h @@ -1,9 +1,9 @@ // // CJSONScanner.h -// TouchJSON +// TouchCode // // Created by Jonathan Wight on 12/07/2005. -// Copyright (c) 2005 Jonathan Wight +// Copyright 2005 toxicsoftware.com. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -29,9 +29,27 @@ #import "CDataScanner.h" +enum { + kJSONScannerOptions_MutableContainers = 0x1, + kJSONScannerOptions_MutableLeaves = 0x2, +}; +typedef NSUInteger EJSONScannerOptions; + +/// CDataScanner subclass that understands JSON syntax natively. You should generally use CJSONDeserializer instead of this class. (TODO - this could have been a category?) @interface CJSONScanner : CDataScanner { + BOOL strictEscapeCodes; + id nullObject; + NSStringEncoding allowedEncoding; + EJSONScannerOptions options; } +@property (readwrite, nonatomic, assign) BOOL strictEscapeCodes; +@property (readwrite, nonatomic, retain) id nullObject; +@property (readwrite, nonatomic, assign) NSStringEncoding allowedEncoding; +@property (readwrite, nonatomic, assign) EJSONScannerOptions options; + +- (BOOL)setData:(NSData *)inData error:(NSError **)outError; + - (BOOL)scanJSONObject:(id *)outObject error:(NSError **)outError; - (BOOL)scanJSONDictionary:(NSDictionary **)outDictionary error:(NSError **)outError; - (BOOL)scanJSONArray:(NSArray **)outArray error:(NSError **)outError; @@ -40,4 +58,38 @@ @end -extern NSString *const kJSONScannerErrorDomain /* = @"CJSONScannerErrorDomain" */; +extern NSString *const kJSONScannerErrorDomain /* = @"kJSONScannerErrorDomain" */; + +typedef enum { + + // Fundamental scanning errors + kJSONScannerErrorCode_NothingToScan = -11, + kJSONScannerErrorCode_CouldNotDecodeData = -12, + kJSONScannerErrorCode_CouldNotSerializeData = -13, + kJSONScannerErrorCode_CouldNotSerializeObject = -14, + kJSONScannerErrorCode_CouldNotScanObject = -15, + + // Dictionary scanning + kJSONScannerErrorCode_DictionaryStartCharacterMissing = -101, + kJSONScannerErrorCode_DictionaryKeyScanFailed = -102, + kJSONScannerErrorCode_DictionaryKeyNotTerminated = -103, + kJSONScannerErrorCode_DictionaryValueScanFailed = -104, + kJSONScannerErrorCode_DictionaryKeyValuePairNoDelimiter = -105, + kJSONScannerErrorCode_DictionaryNotTerminated = -106, + + // Array scanning + kJSONScannerErrorCode_ArrayStartCharacterMissing = -201, + kJSONScannerErrorCode_ArrayValueScanFailed = -202, + kJSONScannerErrorCode_ArrayValueIsNull = -203, + kJSONScannerErrorCode_ArrayNotTerminated = -204, + + // String scanning + kJSONScannerErrorCode_StringNotStartedWithBackslash = -301, + kJSONScannerErrorCode_StringUnicodeNotDecoded = -302, + kJSONScannerErrorCode_StringUnknownEscapeCode = -303, + kJSONScannerErrorCode_StringNotTerminated = -304, + + // Number scanning + kJSONScannerErrorCode_NumberNotScannable = -401 + +} EJSONScannerErrorCode; diff --git a/libs/TouchJSON/JSON/CJSONScanner.m b/libs/TouchJSON/JSON/CJSONScanner.m index c9b1d58..c5ffeb4 100644 --- a/libs/TouchJSON/JSON/CJSONScanner.m +++ b/libs/TouchJSON/JSON/CJSONScanner.m @@ -1,9 +1,9 @@ // // CJSONScanner.m -// TouchJSON +// TouchCode // // Created by Jonathan Wight on 12/07/2005. -// Copyright (c) 2005 Jonathan Wight +// Copyright 2005 toxicsoftware.com. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -29,23 +29,22 @@ #import "CJSONScanner.h" -#import "NSCharacterSet_Extensions.h" #import "CDataScanner_Extensions.h" #if !defined(TREAT_COMMENTS_AS_WHITESPACE) #define TREAT_COMMENTS_AS_WHITESPACE 0 #endif // !defined(TREAT_COMMENTS_AS_WHITESPACE) -NSString *const kJSONScannerErrorDomain = @"CJSONScannerErrorDomain"; +NSString *const kJSONScannerErrorDomain = @"kJSONScannerErrorDomain"; inline static int HexToInt(char inCharacter) -{ -int theValues[] = { 0x0 /* 48 '0' */, 0x1 /* 49 '1' */, 0x2 /* 50 '2' */, 0x3 /* 51 '3' */, 0x4 /* 52 '4' */, 0x5 /* 53 '5' */, 0x6 /* 54 '6' */, 0x7 /* 55 '7' */, 0x8 /* 56 '8' */, 0x9 /* 57 '9' */, -1 /* 58 ':' */, -1 /* 59 ';' */, -1 /* 60 '<' */, -1 /* 61 '=' */, -1 /* 62 '>' */, -1 /* 63 '?' */, -1 /* 64 '@' */, 0xa /* 65 'A' */, 0xb /* 66 'B' */, 0xc /* 67 'C' */, 0xd /* 68 'D' */, 0xe /* 69 'E' */, 0xf /* 70 'F' */, -1 /* 71 'G' */, -1 /* 72 'H' */, -1 /* 73 'I' */, -1 /* 74 'J' */, -1 /* 75 'K' */, -1 /* 76 'L' */, -1 /* 77 'M' */, -1 /* 78 'N' */, -1 /* 79 'O' */, -1 /* 80 'P' */, -1 /* 81 'Q' */, -1 /* 82 'R' */, -1 /* 83 'S' */, -1 /* 84 'T' */, -1 /* 85 'U' */, -1 /* 86 'V' */, -1 /* 87 'W' */, -1 /* 88 'X' */, -1 /* 89 'Y' */, -1 /* 90 'Z' */, -1 /* 91 '[' */, -1 /* 92 '\' */, -1 /* 93 ']' */, -1 /* 94 '^' */, -1 /* 95 '_' */, -1 /* 96 '`' */, 0xa /* 97 'a' */, 0xb /* 98 'b' */, 0xc /* 99 'c' */, 0xd /* 100 'd' */, 0xe /* 101 'e' */, 0xf /* 102 'f' */, }; -if (inCharacter >= '0' && inCharacter <= 'f') - return(theValues[inCharacter - '0']); -else - return(-1); -} + { + int theValues[] = { 0x0 /* 48 '0' */, 0x1 /* 49 '1' */, 0x2 /* 50 '2' */, 0x3 /* 51 '3' */, 0x4 /* 52 '4' */, 0x5 /* 53 '5' */, 0x6 /* 54 '6' */, 0x7 /* 55 '7' */, 0x8 /* 56 '8' */, 0x9 /* 57 '9' */, -1 /* 58 ':' */, -1 /* 59 ';' */, -1 /* 60 '<' */, -1 /* 61 '=' */, -1 /* 62 '>' */, -1 /* 63 '?' */, -1 /* 64 '@' */, 0xa /* 65 'A' */, 0xb /* 66 'B' */, 0xc /* 67 'C' */, 0xd /* 68 'D' */, 0xe /* 69 'E' */, 0xf /* 70 'F' */, -1 /* 71 'G' */, -1 /* 72 'H' */, -1 /* 73 'I' */, -1 /* 74 'J' */, -1 /* 75 'K' */, -1 /* 76 'L' */, -1 /* 77 'M' */, -1 /* 78 'N' */, -1 /* 79 'O' */, -1 /* 80 'P' */, -1 /* 81 'Q' */, -1 /* 82 'R' */, -1 /* 83 'S' */, -1 /* 84 'T' */, -1 /* 85 'U' */, -1 /* 86 'V' */, -1 /* 87 'W' */, -1 /* 88 'X' */, -1 /* 89 'Y' */, -1 /* 90 'Z' */, -1 /* 91 '[' */, -1 /* 92 '\' */, -1 /* 93 ']' */, -1 /* 94 '^' */, -1 /* 95 '_' */, -1 /* 96 '`' */, 0xa /* 97 'a' */, 0xb /* 98 'b' */, 0xc /* 99 'c' */, 0xd /* 100 'd' */, 0xe /* 101 'e' */, 0xf /* 102 'f' */, }; + if (inCharacter >= '0' && inCharacter <= 'f') + return(theValues[inCharacter - '0']); + else + return(-1); + } @interface CJSONScanner () - (BOOL)scanNotQuoteCharactersIntoString:(NSString **)outValue; @@ -55,482 +54,623 @@ - (BOOL)scanNotQuoteCharactersIntoString:(NSString **)outValue; @implementation CJSONScanner +@synthesize strictEscapeCodes; +@synthesize nullObject; +@synthesize allowedEncoding; +@synthesize options; + - (id)init -{ -if ((self = [super init]) != nil) - { - } -return(self); -} + { + if ((self = [super init]) != NULL) + { + strictEscapeCodes = NO; + nullObject = [[NSNull null] retain]; + } + return(self); + } - (void)dealloc -{ -// -[super dealloc]; -} + { + [nullObject release]; + nullObject = NULL; + // + [super dealloc]; + } #pragma mark - +- (BOOL)setData:(NSData *)inData error:(NSError **)outError; + { + NSData *theData = inData; + if (theData && theData.length >= 4) + { + // This code is lame, but it works. Because the first character of any JSON string will always be a (ascii) control character we can work out the Unicode encoding by the bit pattern. See section 3 of http://www.ietf.org/rfc/rfc4627.txt + const char *theChars = theData.bytes; + NSStringEncoding theEncoding = NSUTF8StringEncoding; + if (theChars[0] != 0 && theChars[1] == 0) + { + if (theChars[2] != 0 && theChars[3] == 0) + theEncoding = NSUTF16LittleEndianStringEncoding; + else if (theChars[2] == 0 && theChars[3] == 0) + theEncoding = NSUTF32LittleEndianStringEncoding; + } + else if (theChars[0] == 0 && theChars[2] == 0 && theChars[3] != 0) + { + if (theChars[1] == 0) + theEncoding = NSUTF32BigEndianStringEncoding; + else if (theChars[1] != 0) + theEncoding = NSUTF16BigEndianStringEncoding; + } + + NSString *theString = [[NSString alloc] initWithData:theData encoding:theEncoding]; + if (theString == NULL && self.allowedEncoding != 0) + { + theString = [[NSString alloc] initWithData:theData encoding:self.allowedEncoding]; + } + theData = [theString dataUsingEncoding:NSUTF8StringEncoding]; + [theString release]; + } + + if (theData) + { + [super setData:theData]; + return(YES); + } + else + { + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan data. Data wasn't encoded properly?", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_CouldNotDecodeData userInfo:theUserInfo]; + } + return(NO); + } + } + - (void)setData:(NSData *)inData -{ -NSData *theData = inData; -if (theData && theData.length >= 4) - { - // This code is lame, but it works. Because the first character of any JSON string will always be a (ascii) control character we can work out the Unicode encoding by the bit pattern. See section 3 of http://www.ietf.org/rfc/rfc4627.txt - const char *theChars = theData.bytes; - NSStringEncoding theEncoding = NSUTF8StringEncoding; - if (theChars[0] != 0 && theChars[1] == 0) - { - if (theChars[2] != 0 && theChars[3] == 0) - theEncoding = NSUTF16LittleEndianStringEncoding; - else if (theChars[2] == 0 && theChars[3] == 0) - theEncoding = NSUTF32LittleEndianStringEncoding; - } - else if (theChars[0] == 0 && theChars[2] == 0 && theChars[3] != 0) - { - if (theChars[1] == 0) - theEncoding = NSUTF32BigEndianStringEncoding; - else if (theChars[1] != 0) - theEncoding = NSUTF16BigEndianStringEncoding; - } - - if (theEncoding != NSUTF8StringEncoding) - { - NSString *theString = [[NSString alloc] initWithData:theData encoding:theEncoding]; - theData = [theString dataUsingEncoding:NSUTF8StringEncoding]; - [theString release]; - } - } -[super setData:theData]; -} + { + [self setData:inData error:NULL]; + } #pragma mark - - (BOOL)scanJSONObject:(id *)outObject error:(NSError **)outError -{ -[self skipWhitespace]; - -id theObject = NULL; - -const unichar C = [self currentCharacter]; -switch (C) - { - case 't': - if ([self scanUTF8String:"true" intoString:NULL]) - { - theObject = [NSNumber numberWithBool:YES]; - } - break; - case 'f': - if ([self scanUTF8String:"false" intoString:NULL]) - { - theObject = [NSNumber numberWithBool:NO]; - } - break; - case 'n': - if ([self scanUTF8String:"null" intoString:NULL]) - { - theObject = [NSNull null]; - } - break; - case '\"': - case '\'': - [self scanJSONStringConstant:&theObject error:outError]; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - [self scanJSONNumberConstant:&theObject error:outError]; - break; - case '{': - [self scanJSONDictionary:&theObject error:outError]; - break; - case '[': - [self scanJSONArray:&theObject error:outError]; - break; - default: - - break; - } - -if (outObject != NULL) - *outObject = theObject; -return(YES); -} + { + BOOL theResult = YES; + + [self skipWhitespace]; + + id theObject = NULL; + + const unichar C = [self currentCharacter]; + switch (C) + { + case 't': + if ([self scanUTF8String:"true" intoString:NULL]) + { + theObject = [NSNumber numberWithBool:YES]; + } + break; + case 'f': + if ([self scanUTF8String:"false" intoString:NULL]) + { + theObject = [NSNumber numberWithBool:NO]; + } + break; + case 'n': + if ([self scanUTF8String:"null" intoString:NULL]) + { + theObject = self.nullObject; + } + break; + case '\"': + case '\'': + theResult = [self scanJSONStringConstant:&theObject error:outError]; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + theResult = [self scanJSONNumberConstant:&theObject error:outError]; + break; + case '{': + theResult = [self scanJSONDictionary:&theObject error:outError]; + break; + case '[': + theResult = [self scanJSONArray:&theObject error:outError]; + break; + default: + theResult = NO; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan object. Character not a valid JSON character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_CouldNotScanObject userInfo:theUserInfo]; + } + break; + } + + if (outObject != NULL) + *outObject = theObject; + + return(theResult); + } - (BOOL)scanJSONDictionary:(NSDictionary **)outDictionary error:(NSError **)outError -{ -NSUInteger theScanLocation = [self scanLocation]; - -if ([self scanCharacter:'{'] == NO) - { - if (outError) - { - NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: - @"Could not scan dictionary. Dictionary that does not start with '{' character.", NSLocalizedDescriptionKey, - NULL]; - *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:-1 userInfo:theUserInfo]; - } - return(NO); - } - -NSMutableDictionary *theDictionary = [[NSMutableDictionary alloc] init]; - -while ([self currentCharacter] != '}') - { - [self skipWhitespace]; - - if ([self currentCharacter] == '}') - break; - - NSString *theKey = NULL; - if ([self scanJSONStringConstant:&theKey error:outError] == NO) - { - [self setScanLocation:theScanLocation]; - if (outError) - { - NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: - @"Could not scan dictionary. Failed to scan a key.", NSLocalizedDescriptionKey, - NULL]; - *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:-2 userInfo:theUserInfo]; - } - [theDictionary release]; - return(NO); - } - - [self skipWhitespace]; - - if ([self scanCharacter:':'] == NO) - { - [self setScanLocation:theScanLocation]; - if (outError) - { - NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: - @"Could not scan dictionary. Key was not terminated with a ':' character.", NSLocalizedDescriptionKey, - NULL]; - *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:-3 userInfo:theUserInfo]; - } - [theDictionary release]; - return(NO); - } - - id theValue = NULL; - if ([self scanJSONObject:&theValue error:outError] == NO) - { - [self setScanLocation:theScanLocation]; - if (outError) - { - NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: - @"Could not scan dictionary. Failed to scan a value.", NSLocalizedDescriptionKey, - NULL]; - *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:-4 userInfo:theUserInfo]; - } - [theDictionary release]; - return(NO); - } - - [theDictionary setValue:theValue forKey:theKey]; - - [self skipWhitespace]; - if ([self scanCharacter:','] == NO) - { - if ([self currentCharacter] != '}') - { - [self setScanLocation:theScanLocation]; - if (outError) - { - NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: - @"Could not scan dictionary. Key value pairs not delimited with a ',' character.", NSLocalizedDescriptionKey, - NULL]; - *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:-5 userInfo:theUserInfo]; - } - [theDictionary release]; - return(NO); - } - break; - } - else - { - [self skipWhitespace]; - if ([self currentCharacter] == '}') - break; - } - } - -if ([self scanCharacter:'}'] == NO) - { - [self setScanLocation:theScanLocation]; - if (outError) - { - NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: - @"Could not scan dictionary. Dictionary not terminated by a '}' character.", NSLocalizedDescriptionKey, - NULL]; - *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:-6 userInfo:theUserInfo]; - } - [theDictionary release]; - return(NO); - } - -if (outDictionary != NULL) - *outDictionary = [[theDictionary copy] autorelease]; - -[theDictionary release]; - -return(YES); -} + { + NSUInteger theScanLocation = [self scanLocation]; + + [self skipWhitespace]; + + if ([self scanCharacter:'{'] == NO) + { + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan dictionary. Dictionary that does not start with '{' character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryStartCharacterMissing userInfo:theUserInfo]; + } + return(NO); + } + + NSMutableDictionary *theDictionary = [[NSMutableDictionary alloc] init]; + + while ([self currentCharacter] != '}') + { + [self skipWhitespace]; + + if ([self currentCharacter] == '}') + break; + + NSString *theKey = NULL; + if ([self scanJSONStringConstant:&theKey error:outError] == NO) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan dictionary. Failed to scan a key.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryKeyScanFailed userInfo:theUserInfo]; + } + [theDictionary release]; + return(NO); + } + + [self skipWhitespace]; + + if ([self scanCharacter:':'] == NO) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan dictionary. Key was not terminated with a ':' character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryKeyNotTerminated userInfo:theUserInfo]; + } + [theDictionary release]; + return(NO); + } + + id theValue = NULL; + if ([self scanJSONObject:&theValue error:outError] == NO) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan dictionary. Failed to scan a value.", NSLocalizedDescriptionKey, + NULL]; + + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryValueScanFailed userInfo:theUserInfo]; + } + [theDictionary release]; + return(NO); + } + + if (theValue == NULL && self.nullObject == NULL) + { + // If the value is a null and nullObject is also null then we're skipping this key/value pair. + } + else + { + [theDictionary setValue:theValue forKey:theKey]; + } + + [self skipWhitespace]; + if ([self scanCharacter:','] == NO) + { + if ([self currentCharacter] != '}') + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan dictionary. Key value pairs not delimited with a ',' character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryKeyValuePairNoDelimiter userInfo:theUserInfo]; + } + [theDictionary release]; + return(NO); + } + break; + } + else + { + [self skipWhitespace]; + if ([self currentCharacter] == '}') + break; + } + } + + if ([self scanCharacter:'}'] == NO) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan dictionary. Dictionary not terminated by a '}' character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryNotTerminated userInfo:theUserInfo]; + } + [theDictionary release]; + return(NO); + } + + if (outDictionary != NULL) + { + if (self.options & kJSONScannerOptions_MutableContainers) + { + *outDictionary = [theDictionary autorelease]; + } + else + { + *outDictionary = [[theDictionary copy] autorelease]; + [theDictionary release]; + } + } + else + { + [theDictionary release]; + } + + return(YES); + } - (BOOL)scanJSONArray:(NSArray **)outArray error:(NSError **)outError -{ -NSUInteger theScanLocation = [self scanLocation]; - -if ([self scanCharacter:'['] == NO) - { - if (outError) - { - NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: - @"Could not scan array. Array not started by a '{' character.", NSLocalizedDescriptionKey, - NULL]; - *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:-7 userInfo:theUserInfo]; - } - return(NO); - } - -NSMutableArray *theArray = [[NSMutableArray alloc] init]; - -[self skipWhitespace]; -while ([self currentCharacter] != ']') - { - NSString *theValue = NULL; - if ([self scanJSONObject:&theValue error:outError] == NO) - { - [self setScanLocation:theScanLocation]; - if (outError) - { - NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: - @"Could not scan array. Could not scan a value.", NSLocalizedDescriptionKey, - NULL]; - *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:-8 userInfo:theUserInfo]; - } - [theArray release]; - return(NO); - } - - [theArray addObject:theValue]; - - [self skipWhitespace]; - if ([self scanCharacter:','] == NO) - { - [self skipWhitespace]; - if ([self currentCharacter] != ']') - { - [self setScanLocation:theScanLocation]; - if (outError) - { - NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: - @"Could not scan array. Array not terminated by a ']' character.", NSLocalizedDescriptionKey, - NULL]; - *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:-9 userInfo:theUserInfo]; - } - [theArray release]; - return(NO); - } - - break; - } - [self skipWhitespace]; - } - -[self skipWhitespace]; - -if ([self scanCharacter:']'] == NO) - { - [self setScanLocation:theScanLocation]; - if (outError) - { - NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: - @"Could not scan array. Array not terminated by a ']' character.", NSLocalizedDescriptionKey, - NULL]; - *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:-10 userInfo:theUserInfo]; - } - [theArray release]; - return(NO); - } - -if (outArray != NULL) - *outArray = [[theArray copy] autorelease]; - -[theArray release]; - -return(YES); -} + { + NSUInteger theScanLocation = [self scanLocation]; + + [self skipWhitespace]; + + if ([self scanCharacter:'['] == NO) + { + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan array. Array not started by a '[' character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayStartCharacterMissing userInfo:theUserInfo]; + } + return(NO); + } + + NSMutableArray *theArray = [[NSMutableArray alloc] init]; + + [self skipWhitespace]; + while ([self currentCharacter] != ']') + { + NSString *theValue = NULL; + if ([self scanJSONObject:&theValue error:outError] == NO) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan array. Could not scan a value.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayValueScanFailed userInfo:theUserInfo]; + } + [theArray release]; + return(NO); + } + + if (theValue == NULL) + { + if (self.nullObject != NULL) + { + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan array. Value is NULL.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayValueIsNull userInfo:theUserInfo]; + } + [theArray release]; + return(NO); + } + } + else + { + [theArray addObject:theValue]; + } + + [self skipWhitespace]; + if ([self scanCharacter:','] == NO) + { + [self skipWhitespace]; + if ([self currentCharacter] != ']') + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan array. Array not terminated by a ']' character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayNotTerminated userInfo:theUserInfo]; + } + [theArray release]; + return(NO); + } + + break; + } + [self skipWhitespace]; + } + + [self skipWhitespace]; + + if ([self scanCharacter:']'] == NO) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan array. Array not terminated by a ']' character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayNotTerminated userInfo:theUserInfo]; + } + [theArray release]; + return(NO); + } + + if (outArray != NULL) + { + if (self.options & kJSONScannerOptions_MutableContainers) + { + *outArray = [theArray autorelease]; + } + else + { + *outArray = [[theArray copy] autorelease]; + [theArray release]; + } + } + else + { + [theArray release]; + } + return(YES); + } - (BOOL)scanJSONStringConstant:(NSString **)outStringConstant error:(NSError **)outError -{ -NSUInteger theScanLocation = [self scanLocation]; - -[self skipWhitespace]; // TODO - i want to remove this method. But breaks unit tests. - -NSMutableString *theString = [[NSMutableString alloc] init]; - -if ([self scanCharacter:'"'] == NO) - { - [self setScanLocation:theScanLocation]; - if (outError) - { - NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: - @"Could not scan string constant. String not started by a '\"' character.", NSLocalizedDescriptionKey, - NULL]; - *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:-11 userInfo:theUserInfo]; - } - [theString release]; - return(NO); - } - -while ([self scanCharacter:'"'] == NO) - { - NSString *theStringChunk = NULL; - if ([self scanNotQuoteCharactersIntoString:&theStringChunk]) - { - [theString appendString:theStringChunk]; - } - - if ([self scanCharacter:'\\'] == YES) - { - unichar theCharacter = [self scanCharacter]; - switch (theCharacter) - { - case '"': - case '\\': - case '/': - break; - case 'b': - theCharacter = '\b'; - break; - case 'f': - theCharacter = '\f'; - break; - case 'n': - theCharacter = '\n'; - break; - case 'r': - theCharacter = '\r'; - break; - case 't': - theCharacter = '\t'; - break; - case 'u': - { - theCharacter = 0; - - int theShift; - for (theShift = 12; theShift >= 0; theShift -= 4) - { - const int theDigit = HexToInt([self scanCharacter]); - if (theDigit == -1) - { - [self setScanLocation:theScanLocation]; - if (outError) - { - NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: - @"Could not scan string constant. Unicode character could not be decoded.", NSLocalizedDescriptionKey, - NULL]; - *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:-12 userInfo:theUserInfo]; - } - [theString release]; - return(NO); - } - theCharacter |= (theDigit << theShift); - } - } - break; - default: - { - [self setScanLocation:theScanLocation]; - if (outError) - { - NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: - @"Could not scan string constant. Unknown escape code.", NSLocalizedDescriptionKey, - NULL]; - *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:-13 userInfo:theUserInfo]; - } - [theString release]; - return(NO); - } - break; - } - CFStringAppendCharacters((CFMutableStringRef)theString, &theCharacter, 1); - } - } - -if (outStringConstant != NULL) - *outStringConstant = [[theString copy] autorelease]; - -[theString release]; - -return(YES); -} + { + NSUInteger theScanLocation = [self scanLocation]; + + [self skipWhitespace]; + + NSMutableString *theString = [[NSMutableString alloc] init]; + + if ([self scanCharacter:'"'] == NO) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan string constant. String not started by a '\"' character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_StringNotStartedWithBackslash userInfo:theUserInfo]; + } + [theString release]; + return(NO); + } + + while ([self scanCharacter:'"'] == NO) + { + NSString *theStringChunk = NULL; + if ([self scanNotQuoteCharactersIntoString:&theStringChunk]) + { + CFStringAppend((CFMutableStringRef)theString, (CFStringRef)theStringChunk); + } + else if ([self scanCharacter:'\\'] == YES) + { + unichar theCharacter = [self scanCharacter]; + switch (theCharacter) + { + case '"': + case '\\': + case '/': + break; + case 'b': + theCharacter = '\b'; + break; + case 'f': + theCharacter = '\f'; + break; + case 'n': + theCharacter = '\n'; + break; + case 'r': + theCharacter = '\r'; + break; + case 't': + theCharacter = '\t'; + break; + case 'u': + { + theCharacter = 0; + + int theShift; + for (theShift = 12; theShift >= 0; theShift -= 4) + { + const int theDigit = HexToInt([self scanCharacter]); + if (theDigit == -1) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan string constant. Unicode character could not be decoded.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_StringUnicodeNotDecoded userInfo:theUserInfo]; + } + [theString release]; + return(NO); + } + theCharacter |= (theDigit << theShift); + } + } + break; + default: + { + if (strictEscapeCodes == YES) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan string constant. Unknown escape code.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_StringUnknownEscapeCode userInfo:theUserInfo]; + } + [theString release]; + return(NO); + } + } + break; + } + CFStringAppendCharacters((CFMutableStringRef)theString, &theCharacter, 1); + } + else + { + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan string constant. No terminating double quote character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_StringNotTerminated userInfo:theUserInfo]; + } + [theString release]; + return(NO); + } + } + + if (outStringConstant != NULL) + { + if (self.options & kJSONScannerOptions_MutableLeaves) + { + *outStringConstant = [theString autorelease]; + } + else + { + *outStringConstant = [[theString copy] autorelease]; + [theString release]; + } + } + else + { + [theString release]; + } + + return(YES); + } - (BOOL)scanJSONNumberConstant:(NSNumber **)outNumberConstant error:(NSError **)outError -{ -NSNumber *theNumber = NULL; -if ([self scanNumber:&theNumber] == YES) - { - if (outNumberConstant != NULL) - *outNumberConstant = theNumber; - return(YES); - } -else - { - if (outError) - { - NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: - @"Could not scan number constant.", NSLocalizedDescriptionKey, - NULL]; - *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:-14 userInfo:theUserInfo]; - } - return(NO); - } -} + { + NSNumber *theNumber = NULL; + + [self skipWhitespace]; + + if ([self scanNumber:&theNumber] == YES) + { + if (outNumberConstant != NULL) + *outNumberConstant = theNumber; + return(YES); + } + else + { + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan number constant.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_NumberNotScannable userInfo:theUserInfo]; + } + return(NO); + } + } #if TREAT_COMMENTS_AS_WHITESPACE - (void)skipWhitespace -{ -[super skipWhitespace]; -[self scanCStyleComment:NULL]; -[self scanCPlusPlusStyleComment:NULL]; -[super skipWhitespace]; -} + { + [super skipWhitespace]; + [self scanCStyleComment:NULL]; + [self scanCPlusPlusStyleComment:NULL]; + [super skipWhitespace]; + } #endif // TREAT_COMMENTS_AS_WHITESPACE #pragma mark - - (BOOL)scanNotQuoteCharactersIntoString:(NSString **)outValue -{ -u_int8_t *P; -for (P = current; P < end && *P != '\"' && *P != '\\'; ++P) - ; - -if (P == current) - { - return(NO); - } - -if (outValue) - { - *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease]; - } - -current = P; - -return(YES); -} + { + u_int8_t *P; + for (P = current; P < end && *P != '\"' && *P != '\\'; ++P) + ; + + if (P == current) + { + return(NO); + } + + if (outValue) + { + *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease]; + } + + current = P; + + return(YES); + } @end diff --git a/libs/TouchJSON/JSON/CJSONSerializer.h b/libs/TouchJSON/JSON/CJSONSerializer.h index b858bf1..748a85c 100644 --- a/libs/TouchJSON/JSON/CJSONSerializer.h +++ b/libs/TouchJSON/JSON/CJSONSerializer.h @@ -1,9 +1,9 @@ // // CJSONSerializer.h -// TouchJSON +// TouchCode // // Created by Jonathan Wight on 12/07/2005. -// Copyright (c) 2005 Jonathan Wight +// Copyright 2005 toxicsoftware.com. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -34,12 +34,20 @@ + (id)serializer; -- (NSString *)serializeObject:(id)inObject; +- (BOOL)isValidJSONObject:(id)inObject; -- (NSString *)serializeNull:(NSNull *)inNull; -- (NSString *)serializeNumber:(NSNumber *)inNumber; -- (NSString *)serializeString:(NSString *)inString; -- (NSString *)serializeArray:(NSArray *)inArray; -- (NSString *)serializeDictionary:(NSDictionary *)inDictionary; +/// Take any JSON compatible object (generally NSNull, NSNumber, NSString, NSArray and NSDictionary) and produce an NSData containing the serialized JSON. +- (NSData *)serializeObject:(id)inObject error:(NSError **)outError; + +- (NSData *)serializeNull:(NSNull *)inNull error:(NSError **)outError; +- (NSData *)serializeNumber:(NSNumber *)inNumber error:(NSError **)outError; +- (NSData *)serializeString:(NSString *)inString error:(NSError **)outError; +- (NSData *)serializeArray:(NSArray *)inArray error:(NSError **)outError; +- (NSData *)serializeDictionary:(NSDictionary *)inDictionary error:(NSError **)outError; @end + +typedef enum { + CJSONSerializerErrorCouldNotSerializeDataType = -1, + CJSONSerializerErrorCouldNotSerializeObject = -1 +} CJSONSerializerError; diff --git a/libs/TouchJSON/JSON/CJSONSerializer.m b/libs/TouchJSON/JSON/CJSONSerializer.m index 7511e11..952b3c2 100644 --- a/libs/TouchJSON/JSON/CJSONSerializer.m +++ b/libs/TouchJSON/JSON/CJSONSerializer.m @@ -1,9 +1,9 @@ // // CJSONSerializer.m -// TouchJSON +// TouchCode // // Created by Jonathan Wight on 12/07/2005. -// Copyright (c) 2005 Jonathan Wight +// Copyright 2005 toxicsoftware.com. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -29,156 +29,314 @@ #import "CJSONSerializer.h" +#import "JSONRepresentation.h" + +static NSData *kNULL = NULL; +static NSData *kFalse = NULL; +static NSData *kTrue = NULL; + @implementation CJSONSerializer ++ (void)initialize + { + NSAutoreleasePool *thePool = [[NSAutoreleasePool alloc] init]; + + if (self == [CJSONSerializer class]) + { + if (kNULL == NULL) + kNULL = [[NSData alloc] initWithBytesNoCopy:(void *)"null" length:4 freeWhenDone:NO]; + if (kFalse == NULL) + kFalse = [[NSData alloc] initWithBytesNoCopy:(void *)"false" length:5 freeWhenDone:NO]; + if (kTrue == NULL) + kTrue = [[NSData alloc] initWithBytesNoCopy:(void *)"true" length:4 freeWhenDone:NO]; + + [thePool release]; + } + } + + (id)serializer -{ -return([[[self alloc] init] autorelease]); -} - -- (NSString *)serializeObject:(id)inObject; -{ -NSString *theResult = @""; - -if ([inObject isKindOfClass:[NSNull class]]) - { - theResult = [self serializeNull:inObject]; - } -else if ([inObject isKindOfClass:[NSNumber class]]) - { - theResult = [self serializeNumber:inObject]; - } -else if ([inObject isKindOfClass:[NSString class]]) - { - theResult = [self serializeString:inObject]; - } -else if ([inObject isKindOfClass:[NSArray class]]) - { - theResult = [self serializeArray:inObject]; - } -else if ([inObject isKindOfClass:[NSDictionary class]]) - { - theResult = [self serializeDictionary:inObject]; - } -else if ([inObject isKindOfClass:[NSData class]]) - { - NSString *theString = [[[NSString alloc] initWithData:inObject encoding:NSUTF8StringEncoding] autorelease]; - theResult = [self serializeString:theString]; - } -else - { - [NSException raise:NSGenericException format:@"Cannot serialize data of type '%@'", NSStringFromClass([inObject class])]; - } -if (theResult == NULL) - [NSException raise:NSGenericException format:@"Could not serialize object '%@'", inObject]; -return(theResult); -} - -- (NSString *)serializeNull:(NSNull *)inNull -{ -#pragma unused (inNull) -return(@"null"); -} - -- (NSString *)serializeNumber:(NSNumber *)inNumber -{ -NSString *theResult = NULL; -switch (CFNumberGetType((CFNumberRef)inNumber)) - { - case kCFNumberCharType: - { - int theValue = [inNumber intValue]; - if (theValue == 0) - theResult = @"false"; - else if (theValue == 1) - theResult = @"true"; - else - theResult = [inNumber stringValue]; - } - break; - case kCFNumberSInt8Type: - case kCFNumberSInt16Type: - case kCFNumberSInt32Type: - case kCFNumberSInt64Type: - case kCFNumberFloat32Type: - case kCFNumberFloat64Type: - case kCFNumberShortType: - case kCFNumberIntType: - case kCFNumberLongType: - case kCFNumberLongLongType: - case kCFNumberFloatType: - case kCFNumberDoubleType: - case kCFNumberCFIndexType: - default: - theResult = [inNumber stringValue]; - break; - } -return(theResult); -} - -- (NSString *)serializeString:(NSString *)inString -{ -NSMutableString *theMutableCopy = [[inString mutableCopy] autorelease]; -[theMutableCopy replaceOccurrencesOfString:@"\\" withString:@"\\\\" options:0 range:NSMakeRange(0, [theMutableCopy length])]; -[theMutableCopy replaceOccurrencesOfString:@"\"" withString:@"\\\"" options:0 range:NSMakeRange(0, [theMutableCopy length])]; -[theMutableCopy replaceOccurrencesOfString:@"/" withString:@"\\/" options:0 range:NSMakeRange(0, [theMutableCopy length])]; -[theMutableCopy replaceOccurrencesOfString:@"\b" withString:@"\\b" options:0 range:NSMakeRange(0, [theMutableCopy length])]; -[theMutableCopy replaceOccurrencesOfString:@"\f" withString:@"\\f" options:0 range:NSMakeRange(0, [theMutableCopy length])]; -[theMutableCopy replaceOccurrencesOfString:@"\n" withString:@"\\n" options:0 range:NSMakeRange(0, [theMutableCopy length])]; -[theMutableCopy replaceOccurrencesOfString:@"\n" withString:@"\\n" options:0 range:NSMakeRange(0, [theMutableCopy length])]; -[theMutableCopy replaceOccurrencesOfString:@"\t" withString:@"\\t" options:0 range:NSMakeRange(0, [theMutableCopy length])]; -/* - case 'u': - { - theCharacter = 0; - - int theShift; - for (theShift = 12; theShift >= 0; theShift -= 4) - { - int theDigit = HexToInt([self scanCharacter]); - if (theDigit == -1) - { - [self setScanLocation:theScanLocation]; - return(NO); - } - theCharacter |= (theDigit << theShift); - } - } -*/ -return([NSString stringWithFormat:@"\"%@\"", theMutableCopy]); -} - -- (NSString *)serializeArray:(NSArray *)inArray -{ -NSMutableString *theString = [NSMutableString string]; - -NSEnumerator *theEnumerator = [inArray objectEnumerator]; -id theValue = NULL; -while ((theValue = [theEnumerator nextObject]) != NULL) - { - [theString appendString:[self serializeObject:theValue]]; - if (theValue != [inArray lastObject]) - [theString appendString:@","]; - } -return([NSString stringWithFormat:@"[%@]", theString]); -} - -- (NSString *)serializeDictionary:(NSDictionary *)inDictionary -{ -NSMutableString *theString = [NSMutableString string]; - -NSArray *theKeys = [inDictionary allKeys]; -NSEnumerator *theEnumerator = [theKeys objectEnumerator]; -NSString *theKey = NULL; -while ((theKey = [theEnumerator nextObject]) != NULL) - { - id theValue = [inDictionary objectForKey:theKey]; - - [theString appendFormat:@"%@:%@", [self serializeString:theKey], [self serializeObject:theValue]]; - if (theKey != [theKeys lastObject]) - [theString appendString:@","]; - } -return([NSString stringWithFormat:@"{%@}", theString]); -} + { + return([[[self alloc] init] autorelease]); + } + +- (BOOL)isValidJSONObject:(id)inObject + { + if ([inObject isKindOfClass:[NSNull class]]) + { + return(YES); + } + else if ([inObject isKindOfClass:[NSNumber class]]) + { + return(YES); + } + else if ([inObject isKindOfClass:[NSString class]]) + { + return(YES); + } + else if ([inObject isKindOfClass:[NSArray class]]) + { + return(YES); + } + else if ([inObject isKindOfClass:[NSDictionary class]]) + { + return(YES); + } + else if ([inObject isKindOfClass:[NSData class]]) + { + return(YES); + } + else if ([inObject respondsToSelector:@selector(JSONDataRepresentation)]) + { + return(YES); + } + else + { + return(NO); + } + } + +- (NSData *)serializeObject:(id)inObject error:(NSError **)outError + { + NSData *theResult = NULL; + + if ([inObject isKindOfClass:[NSNull class]]) + { + theResult = [self serializeNull:inObject error:outError]; + } + else if ([inObject isKindOfClass:[NSNumber class]]) + { + theResult = [self serializeNumber:inObject error:outError]; + } + else if ([inObject isKindOfClass:[NSString class]]) + { + theResult = [self serializeString:inObject error:outError]; + } + else if ([inObject isKindOfClass:[NSArray class]]) + { + theResult = [self serializeArray:inObject error:outError]; + } + else if ([inObject isKindOfClass:[NSDictionary class]]) + { + theResult = [self serializeDictionary:inObject error:outError]; + } + else if ([inObject isKindOfClass:[NSData class]]) + { + NSString *theString = [[[NSString alloc] initWithData:inObject encoding:NSUTF8StringEncoding] autorelease]; + theResult = [self serializeString:theString error:outError]; + } + else if ([inObject respondsToSelector:@selector(JSONDataRepresentation)]) + { + theResult = [inObject JSONDataRepresentation]; + } + else + { + if (outError) + { + NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithFormat:@"Cannot serialize data of type '%@'", NSStringFromClass([inObject class])], NSLocalizedDescriptionKey, + NULL]; + *outError = [NSError errorWithDomain:@"TODO_DOMAIN" code:CJSONSerializerErrorCouldNotSerializeDataType userInfo:theUserInfo]; + } + return(NULL); + } + if (theResult == NULL) + { + if (outError) + { + NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithFormat:@"Could not serialize object '%@'", inObject], NSLocalizedDescriptionKey, + NULL]; + *outError = [NSError errorWithDomain:@"TODO_DOMAIN" code:CJSONSerializerErrorCouldNotSerializeObject userInfo:theUserInfo]; + } + return(NULL); + } + return(theResult); + } + +- (NSData *)serializeNull:(NSNull *)inNull error:(NSError **)outError + { + #pragma unused (inNull, outError) + return(kNULL); + } + +- (NSData *)serializeNumber:(NSNumber *)inNumber error:(NSError **)outError + { + #pragma unused (outError) + NSData *theResult = NULL; + switch (CFNumberGetType((CFNumberRef)inNumber)) + { + case kCFNumberCharType: + { + int theValue = [inNumber intValue]; + if (theValue == 0) + theResult = kFalse; + else if (theValue == 1) + theResult = kTrue; + else + theResult = [[inNumber stringValue] dataUsingEncoding:NSASCIIStringEncoding]; + } + break; + case kCFNumberFloat32Type: + case kCFNumberFloat64Type: + case kCFNumberFloatType: + case kCFNumberDoubleType: + case kCFNumberSInt8Type: + case kCFNumberSInt16Type: + case kCFNumberSInt32Type: + case kCFNumberSInt64Type: + case kCFNumberShortType: + case kCFNumberIntType: + case kCFNumberLongType: + case kCFNumberLongLongType: + case kCFNumberCFIndexType: + default: + theResult = [[inNumber stringValue] dataUsingEncoding:NSASCIIStringEncoding]; + break; + } + return(theResult); + } + +- (NSData *)serializeString:(NSString *)inString error:(NSError **)outError + { + #pragma unused (outError) + + const char *theUTF8String = [inString UTF8String]; + + NSMutableData *theData = [NSMutableData dataWithLength:strlen(theUTF8String) * 2 + 2]; + + char *theOutputStart = [theData mutableBytes]; + char *OUT = theOutputStart; + + *OUT++ = '"'; + + for (const char *IN = theUTF8String; IN && *IN != '\0'; ++IN) + { + switch (*IN) + { + case '\\': + { + *OUT++ = '\\'; + *OUT++ = '\\'; + } + break; + case '\"': + { + *OUT++ = '\\'; + *OUT++ = '\"'; + } + break; + case '/': + { + *OUT++ = '\\'; + *OUT++ = '/'; + } + break; + case '\b': + { + *OUT++ = '\\'; + *OUT++ = 'b'; + } + break; + case '\f': + { + *OUT++ = '\\'; + *OUT++ = 'f'; + } + break; + case '\n': + { + *OUT++ = '\\'; + *OUT++ = 'n'; + } + break; + case '\r': + { + *OUT++ = '\\'; + *OUT++ = 'r'; + } + break; + case '\t': + { + *OUT++ = '\\'; + *OUT++ = 't'; + } + break; + default: + { + *OUT++ = *IN; + } + break; + } + } + + *OUT++ = '"'; + + theData.length = OUT - theOutputStart; + return(theData); + } + +- (NSData *)serializeArray:(NSArray *)inArray error:(NSError **)outError + { + NSMutableData *theData = [NSMutableData data]; + + [theData appendBytes:"[" length:1]; + + NSEnumerator *theEnumerator = [inArray objectEnumerator]; + id theValue = NULL; + NSUInteger i = 0; + while ((theValue = [theEnumerator nextObject]) != NULL) + { + NSData *theValueData = [self serializeObject:theValue error:outError]; + if (theValueData == NULL) + { + return(NULL); + } + [theData appendData:theValueData]; + if (++i < [inArray count]) + [theData appendBytes:"," length:1]; + } + + [theData appendBytes:"]" length:1]; + + return(theData); + } + +- (NSData *)serializeDictionary:(NSDictionary *)inDictionary error:(NSError **)outError + { + NSMutableData *theData = [NSMutableData data]; + + [theData appendBytes:"{" length:1]; + + NSArray *theKeys = [inDictionary allKeys]; + NSEnumerator *theEnumerator = [theKeys objectEnumerator]; + NSString *theKey = NULL; + while ((theKey = [theEnumerator nextObject]) != NULL) + { + id theValue = [inDictionary objectForKey:theKey]; + + NSData *theKeyData = [self serializeString:theKey error:outError]; + if (theKeyData == NULL) + { + return(NULL); + } + NSData *theValueData = [self serializeObject:theValue error:outError]; + if (theValueData == NULL) + { + return(NULL); + } + + + [theData appendData:theKeyData]; + [theData appendBytes:":" length:1]; + [theData appendData:theValueData]; + + if (theKey != [theKeys lastObject]) + [theData appendData:[@"," dataUsingEncoding:NSASCIIStringEncoding]]; + } + + [theData appendBytes:"}" length:1]; + + return(theData); + } @end diff --git a/libs/TouchJSON/JSON/JSONRepresentation.h b/libs/TouchJSON/JSON/JSONRepresentation.h new file mode 100644 index 0000000..a83d76f --- /dev/null +++ b/libs/TouchJSON/JSON/JSONRepresentation.h @@ -0,0 +1,18 @@ +// +// JSONRepresentation.h +// TouchJSON +// +// Created by Jonathan Wight on 10/15/10. +// Copyright 2010 toxicsoftware.com. All rights reserved. +// + +#import + +@protocol JSONRepresentation + +@optional +- (id)initWithJSONDataRepresentation:(NSData *)inJSONData; + +- (NSData *)JSONDataRepresentation; + +@end diff --git a/libs/cocos2d/CCAction.h b/libs/cocos2d/CCAction.h index 327a251..51bad8e 100644 --- a/libs/cocos2d/CCAction.h +++ b/libs/cocos2d/CCAction.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -51,7 +52,7 @@ enum { @property (nonatomic,readonly,assign) id target; /** The original target, since target can be nil. - Is the target that were used to run the action. Unless you are doing something complex, like ActionManager, you should NOT call this method. + Is the target that were used to run the action. Unless you are doing something complex, like CCActionManager, you should NOT call this method. @since v0.8.2 */ @property (nonatomic,readonly,assign) id originalTarget; @@ -112,8 +113,11 @@ enum { */ @interface CCRepeatForever : CCAction { - CCActionInterval *other; + CCActionInterval *innerAction_; } +/** Inner action */ +@property (nonatomic, readwrite, retain) CCActionInterval *innerAction; + /** creates the action */ +(id) actionWithAction: (CCActionInterval*) action; /** initializes the action */ @@ -123,15 +127,18 @@ enum { /** Changes the speed of an action, making it take longer (speed>1) or less (speed<1) time. Useful to simulate 'slow motion' or 'fast forward' effect. - @warning This action can't be Sequenceable because it is not an IntervalAction + @warning This action can't be Sequenceable because it is not an CCIntervalAction */ @interface CCSpeed : CCAction { - CCActionInterval *other; - float speed; + CCActionInterval *innerAction_; + float speed_; } /** alter the speed of the inner function in runtime */ @property (nonatomic,readwrite) float speed; +/** Inner action of CCSpeed */ +@property (nonatomic, readwrite, retain) CCActionInterval *innerAction; + /** creates the action */ +(id) actionWithAction: (CCActionInterval*) action speed:(float)rate; /** initializes the action */ diff --git a/libs/cocos2d/CCAction.m b/libs/cocos2d/CCAction.m index 8fc3b4c..1649cfb 100644 --- a/libs/cocos2d/CCAction.m +++ b/libs/cocos2d/CCAction.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -121,6 +122,7 @@ - (CCFiniteTimeAction*) reverse #pragma mark - #pragma mark RepeatForever @implementation CCRepeatForever +@synthesize innerAction=innerAction_; +(id) actionWithAction: (CCActionInterval*) action { return [[[self alloc] initWithAction: action] autorelease]; @@ -129,38 +131,39 @@ +(id) actionWithAction: (CCActionInterval*) action -(id) initWithAction: (CCActionInterval*) action { if( (self=[super init]) ) - other = [action retain]; + self.innerAction = action; return self; } -(id) copyWithZone: (NSZone*) zone { - CCAction *copy = [[[self class] allocWithZone: zone] initWithAction:[[other copy] autorelease] ]; + CCAction *copy = [[[self class] allocWithZone: zone] initWithAction:[[innerAction_ copy] autorelease] ]; return copy; } -(void) dealloc { - [other release]; + [innerAction_ release]; [super dealloc]; } -(void) startWithTarget:(id)aTarget { [super startWithTarget:aTarget]; - [other startWithTarget:target_]; + [innerAction_ startWithTarget:target_]; } -(void) step:(ccTime) dt { - [other step: dt]; - if( [other isDone] ) { - ccTime diff = dt + other.duration - other.elapsed; - [other startWithTarget:target_]; + [innerAction_ step: dt]; + if( [innerAction_ isDone] ) { + ccTime diff = innerAction_.elapsed - innerAction_.duration; + [innerAction_ startWithTarget:target_]; - // to prevent jerk. issue #390 - [other step: diff]; + // to prevent jerk. issue #390, 1247 + [innerAction_ step: 0.0f]; + [innerAction_ step: diff]; } } @@ -172,9 +175,8 @@ -(BOOL) isDone - (CCActionInterval *) reverse { - return [CCRepeatForever actionWithAction:[other reverse]]; + return [CCRepeatForever actionWithAction:[innerAction_ reverse]]; } - @end // @@ -183,7 +185,8 @@ - (CCActionInterval *) reverse #pragma mark - #pragma mark Speed @implementation CCSpeed -@synthesize speed; +@synthesize speed=speed_; +@synthesize innerAction=innerAction_; +(id) actionWithAction: (CCActionInterval*) action speed:(float)r { @@ -193,49 +196,49 @@ +(id) actionWithAction: (CCActionInterval*) action speed:(float)r -(id) initWithAction: (CCActionInterval*) action speed:(float)r { if( (self=[super init]) ) { - other = [action retain]; - speed = r; + self.innerAction = action; + speed_ = r; } return self; } -(id) copyWithZone: (NSZone*) zone { - CCAction *copy = [[[self class] allocWithZone: zone] initWithAction:[[other copy] autorelease] speed:speed]; + CCAction *copy = [[[self class] allocWithZone: zone] initWithAction:[[innerAction_ copy] autorelease] speed:speed_]; return copy; } -(void) dealloc { - [other release]; + [innerAction_ release]; [super dealloc]; } -(void) startWithTarget:(id)aTarget { [super startWithTarget:aTarget]; - [other startWithTarget:target_]; + [innerAction_ startWithTarget:target_]; } -(void) stop { - [other stop]; + [innerAction_ stop]; [super stop]; } -(void) step:(ccTime) dt { - [other step: dt * speed]; + [innerAction_ step: dt * speed_]; } -(BOOL) isDone { - return [other isDone]; + return [innerAction_ isDone]; } - (CCActionInterval *) reverse { - return [CCSpeed actionWithAction:[other reverse] speed:speed]; + return [CCSpeed actionWithAction:[innerAction_ reverse] speed:speed_]; } @end @@ -320,8 +323,6 @@ -(id) copyWithZone: (NSZone*) zone -(void) step:(ccTime) dt { -#define CLAMP(x,y,z) MIN(MAX(x,y),z) - if(boundarySet) { // whole map fits inside a single screen, no need to modify the position - unless map boundaries are increased @@ -329,12 +330,10 @@ -(void) step:(ccTime) dt return; CGPoint tempPos = ccpSub( halfScreenSize, followedNode_.position); - [target_ setPosition:ccp(CLAMP(tempPos.x,leftBoundary,rightBoundary), CLAMP(tempPos.y,bottomBoundary,topBoundary))]; + [target_ setPosition:ccp(clampf(tempPos.x,leftBoundary,rightBoundary), clampf(tempPos.y,bottomBoundary,topBoundary))]; } else - [target_ setPosition:ccpSub( halfScreenSize, followedNode_.position )]; - -#undef CLAMP + [target_ setPosition:ccpSub( halfScreenSize, followedNode_.position )]; } diff --git a/libs/cocos2d/CCActionCamera.h b/libs/cocos2d/CCActionCamera.h index 131c084..1ea83a7 100644 --- a/libs/cocos2d/CCActionCamera.h +++ b/libs/cocos2d/CCActionCamera.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/libs/cocos2d/CCActionCamera.m b/libs/cocos2d/CCActionCamera.m index 5134c6f..4dafc4e 100644 --- a/libs/cocos2d/CCActionCamera.m +++ b/libs/cocos2d/CCActionCamera.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/libs/cocos2d/CCActionGrid.h b/libs/cocos2d/CCActionGrid.h index 13b6bc7..6b31179 100644 --- a/libs/cocos2d/CCActionGrid.h +++ b/libs/cocos2d/CCActionGrid.h @@ -87,8 +87,8 @@ /** CCAccelDeccelAmplitude action */ @interface CCAccelDeccelAmplitude : CCActionInterval { - float rate; - CCActionInterval *other; + float rate_; + CCActionInterval *other_; } /** amplitude rate */ @@ -106,8 +106,8 @@ /** CCAccelAmplitude action */ @interface CCAccelAmplitude : CCActionInterval { - float rate; - CCActionInterval *other; + float rate_; + CCActionInterval *other_; } /** amplitude rate */ @@ -125,8 +125,8 @@ /** CCDeccelAmplitude action */ @interface CCDeccelAmplitude : CCActionInterval { - float rate; - CCActionInterval *other; + float rate_; + CCActionInterval *other_; } /** amplitude rate */ @@ -156,7 +156,7 @@ /** CCReuseGrid action */ @interface CCReuseGrid : CCActionInstant { - int t; + int t_; } /** creates an action with the number of times that the current grid will be reused */ +(id) actionWithTimes: (int) times; diff --git a/libs/cocos2d/CCActionGrid.m b/libs/cocos2d/CCActionGrid.m index b2d8f98..638e27d 100644 --- a/libs/cocos2d/CCActionGrid.m +++ b/libs/cocos2d/CCActionGrid.m @@ -120,7 +120,7 @@ -(ccVertex3F)originalVertex:(ccGridSize)pos -(void)setVertex:(ccGridSize)pos vertex:(ccVertex3F)vertex { CCGrid3D *g = (CCGrid3D *)[target_ grid]; - return [g setVertex:pos vertex:vertex]; + [g setVertex:pos vertex:vertex]; } @end @@ -183,7 +183,7 @@ -(CGFloat)getAmplitudeRate @implementation CCAccelDeccelAmplitude -@synthesize rate; +@synthesize rate=rate_; +(id)actionWithAction:(CCAction*)action duration:(ccTime)d { @@ -194,8 +194,8 @@ -(id)initWithAction:(CCAction *)action duration:(ccTime)d { if ( (self = [super initWithDuration:d]) ) { - rate = 1.0f; - other = [action retain]; + rate_ = 1.0f; + other_ = (CCActionInterval*)[action retain]; } return self; @@ -203,14 +203,14 @@ -(id)initWithAction:(CCAction *)action duration:(ccTime)d -(void)dealloc { - [other release]; + [other_ release]; [super dealloc]; } -(void)startWithTarget:(id)aTarget { [super startWithTarget:aTarget]; - [other startWithTarget:target_]; + [other_ startWithTarget:target_]; } -(void) update: (ccTime) time @@ -223,13 +223,13 @@ -(void) update: (ccTime) time f = 1 - f; } - [other setAmplitudeRate:powf(f, rate)]; - [other update:time]; + [other_ setAmplitudeRate:powf(f, rate_)]; + [other_ update:time]; } - (CCActionInterval*) reverse { - return [CCAccelDeccelAmplitude actionWithAction:[other reverse] duration:duration_]; + return [CCAccelDeccelAmplitude actionWithAction:[other_ reverse] duration:duration_]; } @end @@ -241,7 +241,7 @@ - (CCActionInterval*) reverse @implementation CCAccelAmplitude -@synthesize rate; +@synthesize rate=rate_; +(id)actionWithAction:(CCAction*)action duration:(ccTime)d { @@ -252,8 +252,8 @@ -(id)initWithAction:(CCAction *)action duration:(ccTime)d { if ( (self = [super initWithDuration:d]) ) { - rate = 1.0f; - other = [action retain]; + rate_ = 1.0f; + other_ = (CCActionInterval*)[action retain]; } return self; @@ -261,25 +261,25 @@ -(id)initWithAction:(CCAction *)action duration:(ccTime)d -(void)dealloc { - [other release]; + [other_ release]; [super dealloc]; } -(void)startWithTarget:(id)aTarget { [super startWithTarget:aTarget]; - [other startWithTarget:target_]; + [other_ startWithTarget:target_]; } -(void) update: (ccTime) time { - [other setAmplitudeRate:powf(time, rate)]; - [other update:time]; + [other_ setAmplitudeRate:powf(time, rate_)]; + [other_ update:time]; } - (CCActionInterval*) reverse { - return [CCAccelAmplitude actionWithAction:[other reverse] duration:self.duration]; + return [CCAccelAmplitude actionWithAction:[other_ reverse] duration:self.duration]; } @end @@ -291,7 +291,7 @@ - (CCActionInterval*) reverse @implementation CCDeccelAmplitude -@synthesize rate; +@synthesize rate=rate_; +(id)actionWithAction:(CCAction*)action duration:(ccTime)d { @@ -302,8 +302,8 @@ -(id)initWithAction:(CCAction *)action duration:(ccTime)d { if ( (self = [super initWithDuration:d]) ) { - rate = 1.0f; - other = [action retain]; + rate_ = 1.0f; + other_ = (CCActionInterval*)[action retain]; } return self; @@ -311,25 +311,25 @@ -(id)initWithAction:(CCAction *)action duration:(ccTime)d -(void)dealloc { - [other release]; + [other_ release]; [super dealloc]; } -(void)startWithTarget:(id)aTarget { [super startWithTarget:aTarget]; - [other startWithTarget:target_]; + [other_ startWithTarget:target_]; } -(void) update: (ccTime) time { - [other setAmplitudeRate:powf((1-time), rate)]; - [other update:time]; + [other_ setAmplitudeRate:powf((1-time), rate_)]; + [other_ update:time]; } - (CCActionInterval*) reverse { - return [CCDeccelAmplitude actionWithAction:[other reverse] duration:self.duration]; + return [CCDeccelAmplitude actionWithAction:[other_ reverse] duration:self.duration]; } @end @@ -369,7 +369,7 @@ +(id)actionWithTimes:(int)times -(id)initWithTimes:(int)times { if ( (self = [super init]) ) - t = times; + t_ = times; return self; } @@ -380,7 +380,7 @@ -(void)startWithTarget:(id)aTarget CCNode *myTarget = (CCNode*) [self target]; if ( myTarget.grid && myTarget.grid.active ) - myTarget.grid.reuseGrid += t; + myTarget.grid.reuseGrid += t_; } @end diff --git a/libs/cocos2d/CCActionInstant.h b/libs/cocos2d/CCActionInstant.h index 40eb15f..5a1bc2d 100644 --- a/libs/cocos2d/CCActionInstant.h +++ b/libs/cocos2d/CCActionInstant.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -96,6 +97,10 @@ id targetCallback_; SEL selector_; } + +/** Target that will be called */ +@property (nonatomic, readwrite, retain) id targetCallback; + /** creates the action with the callback */ +(id) actionWithTarget: (id) t selector:(SEL) s; /** initializes the action with the callback */ @@ -139,6 +144,9 @@ typedef void (*CC_CALLBACK_ND)(id, SEL, id, void *); { id object_; } +/** object to be passed as argument */ +@property (nonatomic, readwrite, retain) id object; + /** creates the action with the callback and the object to pass as an argument */ +(id) actionWithTarget: (id) t selector:(SEL) s object:(id)object; /** initializes the action with the callback and the object to pass as an argument */ diff --git a/libs/cocos2d/CCActionInstant.m b/libs/cocos2d/CCActionInstant.m index 2b9072c..e7f6fad 100644 --- a/libs/cocos2d/CCActionInstant.m +++ b/libs/cocos2d/CCActionInstant.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -235,6 +236,9 @@ -(void) startWithTarget:(id)aTarget #pragma mark CCCallFunc @implementation CCCallFunc + +@synthesize targetCallback = targetCallback_; + +(id) actionWithTarget: (id) t selector:(SEL) s { return [[[self alloc] initWithTarget: t selector: s] autorelease]; @@ -243,7 +247,7 @@ +(id) actionWithTarget: (id) t selector:(SEL) s -(id) initWithTarget: (id) t selector:(SEL) s { if( (self=[super init]) ) { - targetCallback_ = [t retain]; + self.targetCallback = t; selector_ = s; } return self; @@ -344,6 +348,7 @@ -(void) execute @end @implementation CCCallFuncO +@synthesize object = object_; +(id) actionWithTarget: (id) t selector:(SEL) s object:(id)object { @@ -353,7 +358,7 @@ +(id) actionWithTarget: (id) t selector:(SEL) s object:(id)object -(id) initWithTarget:(id) t selector:(SEL) s object:(id)object { if( (self=[super initWithTarget:t selector:s] ) ) - object_ = [object retain]; + self.object = object; return self; } diff --git a/libs/cocos2d/CCActionInterval.h b/libs/cocos2d/CCActionInterval.h index 035bd50..5c63137 100644 --- a/libs/cocos2d/CCActionInterval.h +++ b/libs/cocos2d/CCActionInterval.h @@ -1,7 +1,8 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2008-2011 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -69,12 +70,14 @@ then running it again in Reverse mode. */ @interface CCSequence : CCActionInterval { - CCFiniteTimeAction *actions[2]; - ccTime split; - int last; + CCFiniteTimeAction *actions_[2]; + ccTime split_; + int last_; } /** helper contructor to create an array of sequenceable actions */ +(id) actions: (CCFiniteTimeAction*) action1, ... NS_REQUIRES_NIL_TERMINATION; +/** helper contructor to create an array of sequenceable actions given an array */ ++(id) actionsWithArray: (NSArray*) actions; /** creates the action */ +(id) actionOne:(CCFiniteTimeAction*)actionOne two:(CCFiniteTimeAction*)actionTwo; /** initializes the action */ @@ -87,25 +90,33 @@ then running it again in Reverse mode. */ @interface CCRepeat : CCActionInterval { - unsigned int times_; - unsigned int total_; - CCFiniteTimeAction *other_; + NSUInteger times_; + NSUInteger total_; + ccTime nextDt_; + BOOL isActionInstant_; + CCFiniteTimeAction *innerAction_; } -/** creates a CCRepeat action. Times is an unsigned integer between 1 and pow(2,30) */ -+(id) actionWithAction:(CCFiniteTimeAction*)action times: (unsigned int)times; -/** initializes a CCRepeat action. Times is an unsigned integer between 1 and pow(2,30) */ --(id) initWithAction:(CCFiniteTimeAction*)action times: (unsigned int)times; + +/** Inner action */ +@property (nonatomic,readwrite,retain) CCFiniteTimeAction *innerAction; + +/** creates a CCRepeat action. Times is an unsigned integer between 1 and MAX_UINT */ ++(id) actionWithAction:(CCFiniteTimeAction*)action times: (NSUInteger)times; +/** initializes a CCRepeat action. Times is an unsigned integer between 1 and MAX_UINT */ +-(id) initWithAction:(CCFiniteTimeAction*)action times: (NSUInteger)times; @end /** Spawn a new action immediately */ @interface CCSpawn : CCActionInterval { - CCFiniteTimeAction *one; - CCFiniteTimeAction *two; + CCFiniteTimeAction *one_; + CCFiniteTimeAction *two_; } /** helper constructor to create an array of spawned actions */ +(id) actions: (CCFiniteTimeAction*) action1, ... NS_REQUIRES_NIL_TERMINATION; +/** helper contructor to create an array of spawned actions given an array */ ++(id) actionsWithArray: (NSArray*) actions; /** creates the Spawn action */ +(id) actionOne: (CCFiniteTimeAction*) one two:(CCFiniteTimeAction*) two; /** initializes the Spawn action with the 2 actions to spawn */ @@ -118,9 +129,9 @@ then running it again in Reverse mode. */ @interface CCRotateTo : CCActionInterval { - float dstAngle; - float startAngle; - float diffAngle; + float dstAngle_; + float startAngle_; + float diffAngle_; } /** creates the action */ +(id) actionWithDuration:(ccTime)duration angle:(float)angle; @@ -132,8 +143,8 @@ then running it again in Reverse mode. */ @interface CCRotateBy : CCActionInterval { - float angle; - float startAngle; + float angle_; + float startAngle_; } /** creates the action */ +(id) actionWithDuration:(ccTime)duration angle:(float)deltaAngle; @@ -145,9 +156,9 @@ then running it again in Reverse mode. */ @interface CCMoveTo : CCActionInterval { - CGPoint endPosition; - CGPoint startPosition; - CGPoint delta; + CGPoint endPosition_; + CGPoint startPosition_; + CGPoint delta_; } /** creates the action */ +(id) actionWithDuration:(ccTime)duration position:(CGPoint)position; @@ -168,19 +179,47 @@ then running it again in Reverse mode. -(id) initWithDuration: (ccTime)duration position:(CGPoint)deltaPosition; @end +/** Skews a CCNode object to given angles by modifying it's skewX and skewY attributes + @since v1.0 + */ +@interface CCSkewTo : CCActionInterval +{ + float skewX_; + float skewY_; + float startSkewX_; + float startSkewY_; + float endSkewX_; + float endSkewY_; + float deltaX_; + float deltaY_; +} +/** creates the action */ ++(id) actionWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy; +/** initializes the action */ +-(id) initWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy; +@end + +/** Skews a CCNode object by skewX and skewY degrees + @since v1.0 + */ +@interface CCSkewBy : CCSkewTo +{ +} +@end + /** Moves a CCNode object simulating a parabolic jump movement by modifying it's position attribute. */ @interface CCJumpBy : CCActionInterval { - CGPoint startPosition; - CGPoint delta; - ccTime height; - int jumps; + CGPoint startPosition_; + CGPoint delta_; + ccTime height_; + NSUInteger jumps_; } /** creates the action */ -+(id) actionWithDuration: (ccTime)duration position:(CGPoint)position height:(ccTime)height jumps:(int)jumps; ++(id) actionWithDuration: (ccTime)duration position:(CGPoint)position height:(ccTime)height jumps:(NSUInteger)jumps; /** initializes the action */ --(id) initWithDuration: (ccTime)duration position:(CGPoint)position height:(ccTime)height jumps:(int)jumps; +-(id) initWithDuration: (ccTime)duration position:(CGPoint)position height:(ccTime)height jumps:(NSUInteger)jumps; @end /** Moves a CCNode object to a parabolic position simulating a jump movement by modifying it's position attribute. @@ -205,8 +244,8 @@ typedef struct _ccBezierConfig { */ @interface CCBezierBy : CCActionInterval { - ccBezierConfig config; - CGPoint startPosition; + ccBezierConfig config_; + CGPoint startPosition_; } /** creates the action with a duration and a bezier configuration */ @@ -229,14 +268,14 @@ typedef struct _ccBezierConfig { */ @interface CCScaleTo : CCActionInterval { - float scaleX; - float scaleY; - float startScaleX; - float startScaleY; - float endScaleX; - float endScaleY; - float deltaX; - float deltaY; + float scaleX_; + float scaleY_; + float startScaleX_; + float startScaleY_; + float endScaleX_; + float endScaleY_; + float deltaX_; + float deltaY_; } /** creates the action with the same scale factor for X and Y */ +(id) actionWithDuration: (ccTime)duration scale:(float) s; @@ -259,12 +298,12 @@ typedef struct _ccBezierConfig { */ @interface CCBlink : CCActionInterval { - int times; + NSUInteger times_; } /** creates the action */ -+(id) actionWithDuration: (ccTime)duration blinks:(unsigned int)blinks; ++(id) actionWithDuration: (ccTime)duration blinks:(NSUInteger)blinks; /** initilizes the action */ --(id) initWithDuration: (ccTime)duration blinks:(unsigned int)blinks; +-(id) initWithDuration: (ccTime)duration blinks:(NSUInteger)blinks; @end /** Fades In an object that implements the CCRGBAProtocol protocol. It modifies the opacity from 0 to 255. @@ -288,8 +327,8 @@ typedef struct _ccBezierConfig { */ @interface CCFadeTo : CCActionInterval { - GLubyte toOpacity; - GLubyte fromOpacity; + GLubyte toOpacity_; + GLubyte fromOpacity_; } /** creates an action with duration and opactiy */ +(id) actionWithDuration:(ccTime)duration opacity:(GLubyte)opactiy; @@ -303,8 +342,8 @@ typedef struct _ccBezierConfig { */ @interface CCTintTo : CCActionInterval { - ccColor3B to; - ccColor3B from; + ccColor3B to_; + ccColor3B from_; } /** creates an action with duration and color */ +(id) actionWithDuration:(ccTime)duration red:(GLubyte)red green:(GLubyte)green blue:(GLubyte)blue; @@ -317,8 +356,8 @@ typedef struct _ccBezierConfig { */ @interface CCTintBy : CCActionInterval { - GLshort deltaR, deltaG, deltaB; - GLshort fromR, fromG, fromB; + GLshort deltaR_, deltaG_, deltaB_; + GLshort fromR_, fromG_, fromB_; } /** creates an action with duration and color */ +(id) actionWithDuration:(ccTime)duration red:(GLshort)deltaRed green:(GLshort)deltaGreen blue:(GLshort)deltaBlue; @@ -342,7 +381,7 @@ typedef struct _ccBezierConfig { */ @interface CCReverseTime : CCActionInterval { - CCFiniteTimeAction * other; + CCFiniteTimeAction * other_; } /** creates the action */ +(id) actionWithAction: (CCFiniteTimeAction*) action; @@ -356,29 +395,51 @@ typedef struct _ccBezierConfig { /** Animates a sprite given the name of an Animation */ @interface CCAnimate : CCActionInterval { - CCAnimation *animation_; - id origFrame; - BOOL restoreOriginalFrame; + NSMutableArray *splitTimes_; + NSInteger nextFrame_; + CCAnimation *animation_; + id origFrame_; + BOOL restoreOriginalFrame_; } /** animation used for the animage */ @property (readwrite,nonatomic,retain) CCAnimation * animation; /** creates the action with an Animation and will restore the original frame when the animation is over */ -+(id) actionWithAnimation:(CCAnimation*) a; ++(id) actionWithAnimation:(CCAnimation*)animation; /** initializes the action with an Animation and will restore the original frame when the animtion is over */ --(id) initWithAnimation:(CCAnimation*) a; +-(id) initWithAnimation:(CCAnimation*)animation; /** creates the action with an Animation */ -+(id) actionWithAnimation:(CCAnimation*) a restoreOriginalFrame:(BOOL)b; ++(id) actionWithAnimation:(CCAnimation*)animation restoreOriginalFrame:(BOOL)restoreOriginalFrame; /** initializes the action with an Animation */ --(id) initWithAnimation:(CCAnimation*) a restoreOriginalFrame:(BOOL)b; +-(id) initWithAnimation:(CCAnimation*) a restoreOriginalFrame:(BOOL)restoreOriginalFrame; /** creates an action with a duration, animation and depending of the restoreOriginalFrame, it will restore the original frame or not. The 'delay' parameter of the animation will be overrided by the duration parameter. @since v0.99.0 */ -+(id) actionWithDuration:(ccTime)duration animation:(CCAnimation*)animation restoreOriginalFrame:(BOOL)b; ++(id) actionWithDuration:(ccTime)duration animation:(CCAnimation*)animation restoreOriginalFrame:(BOOL)restoreOriginalFrame; /** initializes an action with a duration, animation and depending of the restoreOriginalFrame, it will restore the original frame or not. The 'delay' parameter of the animation will be overrided by the duration parameter. @since v0.99.0 */ --(id) initWithDuration:(ccTime)duration animation:(CCAnimation*)animation restoreOriginalFrame:(BOOL)b; +-(id) initWithDuration:(ccTime)duration animation:(CCAnimation*)animation restoreOriginalFrame:(BOOL)restoreOriginalFrame; +@end + +/** Overrides the target of an action so that it always runs on the target + * specified at action creation rather than the one specified by runAction. + @since 1.1 + */ +@interface CCTargetedAction : CCActionInterval +{ + id forcedTarget_; + CCFiniteTimeAction* action_; +} +/** This is the target that the action will be forced to run with */ +@property(readwrite,nonatomic,retain) id forcedTarget; + +/** Create an action with the specified action and forced target */ ++ (id) actionWithTarget:(id) target action:(CCFiniteTimeAction*) action; + +/** Init an action with the specified action and forced target */ +- (id) initWithTarget:(id) target action:(CCFiniteTimeAction*) action; + @end \ No newline at end of file diff --git a/libs/cocos2d/CCActionInterval.m b/libs/cocos2d/CCActionInterval.m index 148bb0a..d1d9673 100644 --- a/libs/cocos2d/CCActionInterval.m +++ b/libs/cocos2d/CCActionInterval.m @@ -1,7 +1,8 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2008-2011 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +27,7 @@ #import "CCActionInterval.h" +#import "CCActionInstant.h" #import "CCSprite.h" #import "CCSpriteFrame.h" #import "CCAnimation.h" @@ -88,7 +90,7 @@ -(void) step: (ccTime) dt } else elapsed_ += dt; - [self update: MIN(1, elapsed_/duration_)]; + [self update: MIN(1, elapsed_/MAX(duration_,FLT_EPSILON))]; } -(void) startWithTarget:(id)aTarget @@ -111,11 +113,6 @@ - (CCActionInterval*) reverse #pragma mark - #pragma mark Sequence @implementation CCSequence -+(id) actionOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two -{ - return [[[self alloc] initOne:one two:two ] autorelease]; -} - +(id) actions: (CCFiniteTimeAction*) action1, ... { va_list params; @@ -135,47 +132,66 @@ +(id) actions: (CCFiniteTimeAction*) action1, ... return prev; } --(id) initOne: (CCFiniteTimeAction*) one_ two: (CCFiniteTimeAction*) two_ ++(id) actionsWithArray: (NSArray*) actions { - NSAssert( one_!=nil, @"Sequence: argument one must be non-nil"); - NSAssert( two_!=nil, @"Sequence: argument two must be non-nil"); + CCFiniteTimeAction *prev = [actions objectAtIndex:0]; + + for (NSUInteger i = 1; i < [actions count]; i++) + prev = [self actionOne:prev two:[actions objectAtIndex:i]]; + + return prev; +} - CCFiniteTimeAction *one = one_; - CCFiniteTimeAction *two = two_; ++(id) actionOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two +{ + return [[[self alloc] initOne:one two:two ] autorelease]; +} + +-(id) initOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two +{ + NSAssert( one!=nil && two!=nil, @"Sequence: arguments must be non-nil"); + NSAssert( one!=actions_[0] && one!=actions_[1], @"Sequence: re-init using the same parameters is not supported"); + NSAssert( two!=actions_[1] && two!=actions_[0], @"Sequence: re-init using the same parameters is not supported"); ccTime d = [one duration] + [two duration]; - [super initWithDuration: d]; - actions[0] = [one retain]; - actions[1] = [two retain]; + if( (self=[super initWithDuration: d]) ) { + + // XXX: Supports re-init without leaking. Fails if one==one_ || two==two_ + [actions_[0] release]; + [actions_[1] release]; + + actions_[0] = [one retain]; + actions_[1] = [two retain]; + } return self; } -(id) copyWithZone: (NSZone*) zone { - CCAction *copy = [[[self class] allocWithZone:zone] initOne:[[actions[0] copy] autorelease] two:[[actions[1] copy] autorelease] ]; + CCAction *copy = [[[self class] allocWithZone:zone] initOne:[[actions_[0] copy] autorelease] two:[[actions_[1] copy] autorelease] ]; return copy; } -(void) dealloc { - [actions[0] release]; - [actions[1] release]; + [actions_[0] release]; + [actions_[1] release]; [super dealloc]; } -(void) startWithTarget:(id)aTarget { [super startWithTarget:aTarget]; - split = [actions[0] duration] / duration_; - last = -1; + split_ = [actions_[0] duration] / MAX(duration_, FLT_EPSILON); + last_ = -1; } -(void) stop { - [actions[0] stop]; - [actions[1] stop]; + [actions_[0] stop]; + [actions_[1] stop]; [super stop]; } @@ -184,40 +200,40 @@ -(void) update: (ccTime) t int found = 0; ccTime new_t = 0.0f; - if( t >= split ) { + if( t >= split_ ) { found = 1; - if ( split == 1 ) + if ( split_ == 1 ) new_t = 1; else - new_t = (t-split) / (1 - split ); + new_t = (t-split_) / (1 - split_ ); } else { found = 0; - if( split != 0 ) - new_t = t / split; + if( split_ != 0 ) + new_t = t / split_; else new_t = 1; } - if (last == -1 && found==1) { - [actions[0] startWithTarget:target_]; - [actions[0] update:1.0f]; - [actions[0] stop]; + if (last_ == -1 && found==1) { + [actions_[0] startWithTarget:target_]; + [actions_[0] update:1.0f]; + [actions_[0] stop]; } - if (last != found ) { - if( last != -1 ) { - [actions[last] update: 1.0f]; - [actions[last] stop]; + if (last_ != found ) { + if( last_ != -1 ) { + [actions_[last_] update: 1.0f]; + [actions_[last_] stop]; } - [actions[found] startWithTarget:target_]; + [actions_[found] startWithTarget:target_]; } - [actions[found] update: new_t]; - last = found; + [actions_[found] update: new_t]; + last_ = found; } - (CCActionInterval *) reverse { - return [[self class] actionOne: [actions[1] reverse] two: [actions[0] reverse ] ]; + return [[self class] actionOne: [actions_[1] reverse] two: [actions_[0] reverse ] ]; } @end @@ -227,19 +243,24 @@ - (CCActionInterval *) reverse #pragma mark - #pragma mark CCRepeat @implementation CCRepeat -+(id) actionWithAction:(CCFiniteTimeAction*)action times:(unsigned int)times +@synthesize innerAction=innerAction_; + ++(id) actionWithAction:(CCFiniteTimeAction*)action times:(NSUInteger)times { return [[[self alloc] initWithAction:action times:times] autorelease]; } --(id) initWithAction:(CCFiniteTimeAction*)action times:(unsigned int)times +-(id) initWithAction:(CCFiniteTimeAction*)action times:(NSUInteger)times { ccTime d = [action duration] * times; - + if( (self=[super initWithDuration: d ]) ) { times_ = times; - other_ = [action retain]; - + self.innerAction = action; + isActionInstant_ = ([action isKindOfClass:[CCActionInstant class]]) ? YES : NO; + + //a instant action needs to be executed one time less in the update method since it uses startWithTarget to execute the action + if (isActionInstant_) times_ -=1; total_ = 0; } return self; @@ -247,26 +268,27 @@ -(id) initWithAction:(CCFiniteTimeAction*)action times:(unsigned int)times -(id) copyWithZone: (NSZone*) zone { - CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[other_ copy] autorelease] times:times_]; + CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[innerAction_ copy] autorelease] times:times_]; return copy; } -(void) dealloc { - [other_ release]; + [innerAction_ release]; [super dealloc]; } -(void) startWithTarget:(id)aTarget { total_ = 0; + nextDt_ = [innerAction_ duration]/duration_; [super startWithTarget:aTarget]; - [other_ startWithTarget:aTarget]; + [innerAction_ startWithTarget:aTarget]; } -(void) stop { - [other_ stop]; + [innerAction_ stop]; [super stop]; } @@ -275,34 +297,42 @@ -(void) stop // container action like Repeat, Sequence, AccelDeccel, etc.. -(void) update:(ccTime) dt { - ccTime t = dt * times_; - if( t > total_+1 ) { - [other_ update:1.0f]; - total_++; - [other_ stop]; - [other_ startWithTarget:target_]; - - // repeat is over ? - if( total_== times_ ) - // so, set it in the original position - [other_ update:0]; - else { - // no ? start next repeat with the right update - // to prevent jerk (issue #390) - [other_ update: t-total_]; + if (dt >= nextDt_) + { + while (dt > nextDt_ && total_ < times_) + { + + [innerAction_ update:1.0f]; + total_++; + + [innerAction_ stop]; + [innerAction_ startWithTarget:target_]; + nextDt_ += [innerAction_ duration]/duration_; } - - } else { - float r = fmodf(t, 1.0f); + //fix for issue #1288, incorrect end value of repeat + if(dt == 1.0 && total_ < times_) + { + total_++; + } - // fix last repeat position - // else it could be 0. - if( dt== 1.0f) { - r = 1.0f; - total_++; // this is the added line + //don't set a instantaction back or update it, it has no use because it has no duration + if (!isActionInstant_) + { + if (total_ == times_) + { + [innerAction_ update:1]; + [innerAction_ stop]; + }//issue #390 prevent jerk, use right update + else + { + [innerAction_ update:dt - (nextDt_ - innerAction_.duration/duration_)]; + } } - [other_ update: MIN(r,1)]; + } + else + { + [innerAction_ update:fmodf(dt * times_,1.0f)]; } } @@ -313,7 +343,7 @@ -(BOOL) isDone - (CCActionInterval *) reverse { - return [[self class] actionWithAction:[other_ reverse] times:times_]; + return [[self class] actionWithAction:[innerAction_ reverse] times:times_]; } @end @@ -343,70 +373,86 @@ +(id) actions: (CCFiniteTimeAction*) action1, ... return prev; } ++(id) actionsWithArray: (NSArray*) actions +{ + CCFiniteTimeAction *prev = [actions objectAtIndex:0]; + + for (NSUInteger i = 1; i < [actions count]; i++) + prev = [self actionOne:prev two:[actions objectAtIndex:i]]; + + return prev; +} + +(id) actionOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two { return [[[self alloc] initOne:one two:two ] autorelease]; } --(id) initOne: (CCFiniteTimeAction*) one_ two: (CCFiniteTimeAction*) two_ +-(id) initOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two { - NSAssert( one_!=nil, @"Spawn: argument one must be non-nil"); - NSAssert( two_!=nil, @"Spawn: argument two must be non-nil"); + NSAssert( one!=nil && two!=nil, @"Spawn: arguments must be non-nil"); + NSAssert( one!=one_ && one!=two_, @"Spawn: reinit using same parameters is not supported"); + NSAssert( two!=two_ && two!=one_, @"Spawn: reinit using same parameters is not supported"); - ccTime d1 = [one_ duration]; - ccTime d2 = [two_ duration]; + ccTime d1 = [one duration]; + ccTime d2 = [two duration]; - [super initWithDuration: fmaxf(d1,d2)]; + if( (self=[super initWithDuration: MAX(d1,d2)] ) ) { - one = one_; - two = two_; + // XXX: Supports re-init without leaking. Fails if one==one_ || two==two_ + [one_ release]; + [two_ release]; - if( d1 > d2 ) - two = [CCSequence actionOne: two_ two:[CCDelayTime actionWithDuration: (d1-d2)] ]; - else if( d1 < d2) - one = [CCSequence actionOne: one_ two: [CCDelayTime actionWithDuration: (d2-d1)] ]; - - [one retain]; - [two retain]; + one_ = one; + two_ = two; + + if( d1 > d2 ) + two_ = [CCSequence actionOne:two two:[CCDelayTime actionWithDuration: (d1-d2)] ]; + else if( d1 < d2) + one_ = [CCSequence actionOne:one two: [CCDelayTime actionWithDuration: (d2-d1)] ]; + + [one_ retain]; + [two_ retain]; + } return self; } -(id) copyWithZone: (NSZone*) zone { - CCAction *copy = [[[self class] allocWithZone: zone] initOne: [[one copy] autorelease] two: [[two copy] autorelease] ]; + CCAction *copy = [[[self class] allocWithZone: zone] initOne: [[one_ copy] autorelease] two: [[two_ copy] autorelease] ]; return copy; } -(void) dealloc { - [one release]; - [two release]; + [one_ release]; + [two_ release]; [super dealloc]; } -(void) startWithTarget:(id)aTarget { [super startWithTarget:aTarget]; - [one startWithTarget:target_]; - [two startWithTarget:target_]; + [one_ startWithTarget:target_]; + [two_ startWithTarget:target_]; } -(void) stop { - [one stop]; - [two stop]; + [one_ stop]; + [two_ stop]; [super stop]; } -(void) update: (ccTime) t { - [one update:t]; - [two update:t]; + [one_ update:t]; + [two_ update:t]; } - (CCActionInterval *) reverse { - return [[self class] actionOne: [one reverse] two: [two reverse ] ]; + return [[self class] actionOne: [one_ reverse] two: [two_ reverse ] ]; } @end @@ -425,14 +471,14 @@ +(id) actionWithDuration: (ccTime) t angle:(float) a -(id) initWithDuration: (ccTime) t angle:(float) a { if( (self=[super initWithDuration: t]) ) - dstAngle = a; + dstAngle_ = a; return self; } -(id) copyWithZone: (NSZone*) zone { - CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] angle: dstAngle]; + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] angle:dstAngle_]; return copy; } @@ -440,21 +486,21 @@ -(void) startWithTarget:(CCNode *)aTarget { [super startWithTarget:aTarget]; - startAngle = [target_ rotation]; - if (startAngle > 0) - startAngle = fmodf(startAngle, 360.0f); + startAngle_ = [target_ rotation]; + if (startAngle_ > 0) + startAngle_ = fmodf(startAngle_, 360.0f); else - startAngle = fmodf(startAngle, -360.0f); + startAngle_ = fmodf(startAngle_, -360.0f); - diffAngle = dstAngle - startAngle; - if (diffAngle > 180) - diffAngle -= 360; - if (diffAngle < -180) - diffAngle += 360; + diffAngle_ =dstAngle_ - startAngle_; + if (diffAngle_ > 180) + diffAngle_ -= 360; + if (diffAngle_ < -180) + diffAngle_ += 360; } -(void) update: (ccTime) t { - [target_ setRotation: startAngle + diffAngle * t]; + [target_ setRotation: startAngle_ + diffAngle_ * t]; } @end @@ -474,32 +520,32 @@ +(id) actionWithDuration: (ccTime) t angle:(float) a -(id) initWithDuration: (ccTime) t angle:(float) a { if( (self=[super initWithDuration: t]) ) - angle = a; + angle_ = a; return self; } -(id) copyWithZone: (NSZone*) zone { - CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] angle: angle]; + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] angle: angle_]; return copy; } -(void) startWithTarget:(id)aTarget { [super startWithTarget:aTarget]; - startAngle = [target_ rotation]; + startAngle_ = [target_ rotation]; } -(void) update: (ccTime) t { // XXX: shall I add % 360 - [target_ setRotation: (startAngle + angle * t )]; + [target_ setRotation: (startAngle_ +angle_ * t )]; } -(CCActionInterval*) reverse { - return [[self class] actionWithDuration:duration_ angle:-angle]; + return [[self class] actionWithDuration:duration_ angle:-angle_]; } @end @@ -519,27 +565,27 @@ +(id) actionWithDuration: (ccTime) t position: (CGPoint) p -(id) initWithDuration: (ccTime) t position: (CGPoint) p { if( (self=[super initWithDuration: t]) ) - endPosition = p; + endPosition_ = p; return self; } -(id) copyWithZone: (NSZone*) zone { - CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] position: endPosition]; + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] position: endPosition_]; return copy; } -(void) startWithTarget:(CCNode *)aTarget { [super startWithTarget:aTarget]; - startPosition = [(CCNode*)target_ position]; - delta = ccpSub( endPosition, startPosition ); + startPosition_ = [(CCNode*)target_ position]; + delta_ = ccpSub( endPosition_, startPosition_ ); } -(void) update: (ccTime) t { - [target_ setPosition: ccp( (startPosition.x + delta.x * t ), (startPosition.y + delta.y * t ) )]; + [target_ setPosition: ccp( (startPosition_.x + delta_.x * t ), (startPosition_.y + delta_.y * t ) )]; } @end @@ -558,30 +604,133 @@ +(id) actionWithDuration: (ccTime) t position: (CGPoint) p -(id) initWithDuration: (ccTime) t position: (CGPoint) p { if( (self=[super initWithDuration: t]) ) - delta = p; + delta_ = p; return self; } -(id) copyWithZone: (NSZone*) zone { - CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] position: delta]; + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] position: delta_]; return copy; } -(void) startWithTarget:(CCNode *)aTarget { - CGPoint dTmp = delta; + CGPoint dTmp = delta_; [super startWithTarget:aTarget]; - delta = dTmp; + delta_ = dTmp; } -(CCActionInterval*) reverse { - return [[self class] actionWithDuration:duration_ position:ccp( -delta.x, -delta.y)]; + return [[self class] actionWithDuration:duration_ position:ccp( -delta_.x, -delta_.y)]; } @end + +// +// SkewTo +// +#pragma mark - +#pragma mark SkewTo + +@implementation CCSkewTo ++(id) actionWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy +{ + return [[[self alloc] initWithDuration: t skewX:sx skewY:sy] autorelease]; +} + +-(id) initWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy +{ + if( (self=[super initWithDuration:t]) ) { + endSkewX_ = sx; + endSkewY_ = sy; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] skewX:endSkewX_ skewY:endSkewY_]; + return copy; +} + +-(void) startWithTarget:(CCNode *)aTarget +{ + [super startWithTarget:aTarget]; + + startSkewX_ = [target_ skewX]; + + if (startSkewX_ > 0) + startSkewX_ = fmodf(startSkewX_, 180.0f); + else + startSkewX_ = fmodf(startSkewX_, -180.0f); + + deltaX_ = endSkewX_ - startSkewX_; + + if ( deltaX_ > 180 ) { + deltaX_ -= 360; + } + if ( deltaX_ < -180 ) { + deltaX_ += 360; + } + + startSkewY_ = [target_ skewY]; + + if (startSkewY_ > 0) + startSkewY_ = fmodf(startSkewY_, 360.0f); + else + startSkewY_ = fmodf(startSkewY_, -360.0f); + + deltaY_ = endSkewY_ - startSkewY_; + + if ( deltaY_ > 180 ) { + deltaY_ -= 360; + } + if ( deltaY_ < -180 ) { + deltaY_ += 360; + } +} + +-(void) update: (ccTime) t +{ + [target_ setSkewX: (startSkewX_ + deltaX_ * t ) ]; + [target_ setSkewY: (startSkewY_ + deltaY_ * t ) ]; +} + +@end + +// +// CCSkewBy +// +@implementation CCSkewBy + +-(id) initWithDuration:(ccTime)t skewX:(float)deltaSkewX skewY:(float)deltaSkewY +{ + if( (self=[super initWithDuration:t skewX:deltaSkewX skewY:deltaSkewY]) ) { + skewX_ = deltaSkewX; + skewY_ = deltaSkewY; + } + return self; +} + +-(void) startWithTarget:(CCNode *)aTarget +{ + [super startWithTarget:aTarget]; + deltaX_ = skewX_; + deltaY_ = skewY_; + endSkewX_ = startSkewX_ + deltaX_; + endSkewY_ = startSkewY_ + deltaY_; +} + +-(CCActionInterval*) reverse +{ + return [[self class] actionWithDuration:duration_ skewX:-skewX_ skewY:-skewY_]; +} +@end + + // // JumpBy // @@ -589,31 +738,31 @@ -(CCActionInterval*) reverse #pragma mark JumpBy @implementation CCJumpBy -+(id) actionWithDuration: (ccTime) t position: (CGPoint) pos height: (ccTime) h jumps:(int)j ++(id) actionWithDuration: (ccTime) t position: (CGPoint) pos height: (ccTime) h jumps:(NSUInteger)j { return [[[self alloc] initWithDuration: t position: pos height: h jumps:j] autorelease]; } --(id) initWithDuration: (ccTime) t position: (CGPoint) pos height: (ccTime) h jumps:(int)j +-(id) initWithDuration: (ccTime) t position: (CGPoint) pos height: (ccTime) h jumps:(NSUInteger)j { if( (self=[super initWithDuration:t]) ) { - delta = pos; - height = h; - jumps = j; + delta_ = pos; + height_ = h; + jumps_ = j; } return self; } -(id) copyWithZone: (NSZone*) zone { - CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] position: delta height:height jumps:jumps]; + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] position:delta_ height:height_ jumps:jumps_]; return copy; } -(void) startWithTarget:(id)aTarget { [super startWithTarget:aTarget]; - startPosition = [(CCNode*)target_ position]; + startPosition_ = [(CCNode*)target_ position]; } -(void) update: (ccTime) t @@ -625,17 +774,17 @@ -(void) update: (ccTime) t // [target setPosition: ccp( startPosition.x + x, startPosition.y + y )]; // parabolic jump (since v0.8.2) - ccTime frac = fmodf( t * jumps, 1.0f ); - ccTime y = height * 4 * frac * (1 - frac); - y += delta.y * t; - ccTime x = delta.x * t; - [target_ setPosition: ccp( startPosition.x + x, startPosition.y + y )]; + ccTime frac = fmodf( t * jumps_, 1.0f ); + ccTime y = height_ * 4 * frac * (1 - frac); + y += delta_.y * t; + ccTime x = delta_.x * t; + [target_ setPosition: ccp( startPosition_.x + x, startPosition_.y + y )]; } -(CCActionInterval*) reverse { - return [[self class] actionWithDuration:duration_ position: ccp(-delta.x,-delta.y) height: height jumps:jumps]; + return [[self class] actionWithDuration:duration_ position: ccp(-delta_.x,-delta_.y) height:height_ jumps:jumps_]; } @end @@ -649,7 +798,7 @@ @implementation CCJumpTo -(void) startWithTarget:(CCNode *)aTarget { [super startWithTarget:aTarget]; - delta = ccp( delta.x - startPosition.x, delta.y - startPosition.y ); + delta_ = ccp( delta_.x - startPosition_.x, delta_.y - startPosition_.y ); } @end @@ -681,47 +830,47 @@ +(id) actionWithDuration: (ccTime) t bezier:(ccBezierConfig) c -(id) initWithDuration: (ccTime) t bezier:(ccBezierConfig) c { if( (self=[super initWithDuration: t]) ) { - config = c; + config_ = c; } return self; } -(id) copyWithZone: (NSZone*) zone { - CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] bezier: config]; + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] bezier:config_]; return copy; } -(void) startWithTarget:(id)aTarget { [super startWithTarget:aTarget]; - startPosition = [(CCNode*)target_ position]; + startPosition_ = [(CCNode*)target_ position]; } -(void) update: (ccTime) t { float xa = 0; - float xb = config.controlPoint_1.x; - float xc = config.controlPoint_2.x; - float xd = config.endPosition.x; + float xb = config_.controlPoint_1.x; + float xc = config_.controlPoint_2.x; + float xd = config_.endPosition.x; float ya = 0; - float yb = config.controlPoint_1.y; - float yc = config.controlPoint_2.y; - float yd = config.endPosition.y; + float yb = config_.controlPoint_1.y; + float yc = config_.controlPoint_2.y; + float yd = config_.endPosition.y; float x = bezierat(xa, xb, xc, xd, t); float y = bezierat(ya, yb, yc, yd, t); - [target_ setPosition: ccpAdd( startPosition, ccp(x,y))]; + [target_ setPosition: ccpAdd( startPosition_, ccp(x,y))]; } - (CCActionInterval*) reverse { ccBezierConfig r; - r.endPosition = ccpNeg(config.endPosition); - r.controlPoint_1 = ccpAdd(config.controlPoint_2, ccpNeg(config.endPosition)); - r.controlPoint_2 = ccpAdd(config.controlPoint_1, ccpNeg(config.endPosition)); + r.endPosition = ccpNeg(config_.endPosition); + r.controlPoint_1 = ccpAdd(config_.controlPoint_2, ccpNeg(config_.endPosition)); + r.controlPoint_2 = ccpAdd(config_.controlPoint_1, ccpNeg(config_.endPosition)); CCBezierBy *action = [[self class] actionWithDuration:[self duration] bezier:r]; return action; @@ -737,9 +886,9 @@ @implementation CCBezierTo -(void) startWithTarget:(id)aTarget { [super startWithTarget:aTarget]; - config.controlPoint_1 = ccpSub(config.controlPoint_1, startPosition); - config.controlPoint_2 = ccpSub(config.controlPoint_2, startPosition); - config.endPosition = ccpSub(config.endPosition, startPosition); + config_.controlPoint_1 = ccpSub(config_.controlPoint_1, startPosition_); + config_.controlPoint_2 = ccpSub(config_.controlPoint_2, startPosition_); + config_.endPosition = ccpSub(config_.endPosition, startPosition_); } @end @@ -758,8 +907,8 @@ +(id) actionWithDuration: (ccTime) t scale:(float) s -(id) initWithDuration: (ccTime) t scale:(float) s { if( (self=[super initWithDuration: t]) ) { - endScaleX = s; - endScaleY = s; + endScaleX_ = s; + endScaleY_ = s; } return self; } @@ -772,31 +921,31 @@ +(id) actionWithDuration: (ccTime) t scaleX:(float)sx scaleY:(float)sy -(id) initWithDuration: (ccTime) t scaleX:(float)sx scaleY:(float)sy { if( (self=[super initWithDuration: t]) ) { - endScaleX = sx; - endScaleY = sy; + endScaleX_ = sx; + endScaleY_ = sy; } return self; } -(id) copyWithZone: (NSZone*) zone { - CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] scaleX:endScaleX scaleY:endScaleY]; + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] scaleX:endScaleX_ scaleY:endScaleY_]; return copy; } -(void) startWithTarget:(CCNode *)aTarget { [super startWithTarget:aTarget]; - startScaleX = [target_ scaleX]; - startScaleY = [target_ scaleY]; - deltaX = endScaleX - startScaleX; - deltaY = endScaleY - startScaleY; + startScaleX_ = [target_ scaleX]; + startScaleY_ = [target_ scaleY]; + deltaX_ = endScaleX_ - startScaleX_; + deltaY_ = endScaleY_ - startScaleY_; } -(void) update: (ccTime) t { - [target_ setScaleX: (startScaleX + deltaX * t ) ]; - [target_ setScaleY: (startScaleY + deltaY * t ) ]; + [target_ setScaleX: (startScaleX_ + deltaX_ * t ) ]; + [target_ setScaleY: (startScaleY_ + deltaY_ * t ) ]; } @end @@ -809,13 +958,13 @@ @implementation CCScaleBy -(void) startWithTarget:(CCNode *)aTarget { [super startWithTarget:aTarget]; - deltaX = startScaleX * endScaleX - startScaleX; - deltaY = startScaleY * endScaleY - startScaleY; + deltaX_ = startScaleX_ * endScaleX_ - startScaleX_; + deltaY_ = startScaleY_ * endScaleY_ - startScaleY_; } -(CCActionInterval*) reverse { - return [[self class] actionWithDuration:duration_ scaleX: 1/endScaleX scaleY:1/endScaleY]; + return [[self class] actionWithDuration:duration_ scaleX:1/endScaleX_ scaleY:1/endScaleY_]; } @end @@ -825,29 +974,29 @@ -(CCActionInterval*) reverse #pragma mark - #pragma mark Blink @implementation CCBlink -+(id) actionWithDuration: (ccTime) t blinks: (unsigned int) b ++(id) actionWithDuration: (ccTime) t blinks: (NSUInteger) b { return [[[ self alloc] initWithDuration: t blinks: b] autorelease]; } --(id) initWithDuration: (ccTime) t blinks: (unsigned int) b +-(id) initWithDuration: (ccTime) t blinks: (NSUInteger) b { if( (self=[super initWithDuration: t] ) ) - times = b; + times_ = b; return self; } -(id) copyWithZone: (NSZone*) zone { - CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] blinks: times]; + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] blinks: times_]; return copy; } -(void) update: (ccTime) t { if( ! [self isDone] ) { - ccTime slice = 1.0f / times; + ccTime slice = 1.0f / times_; ccTime m = fmodf(t, slice); [target_ setVisible: (m > slice/2) ? YES : NO]; } @@ -856,7 +1005,7 @@ -(void) update: (ccTime) t -(CCActionInterval*) reverse { // return 'self' - return [[self class] actionWithDuration:duration_ blinks: times]; + return [[self class] actionWithDuration:duration_ blinks: times_]; } @end @@ -908,26 +1057,26 @@ +(id) actionWithDuration: (ccTime) t opacity: (GLubyte) o -(id) initWithDuration: (ccTime) t opacity: (GLubyte) o { if( (self=[super initWithDuration: t] ) ) - toOpacity = o; + toOpacity_ = o; return self; } -(id) copyWithZone: (NSZone*) zone { - CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] opacity: toOpacity]; + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] opacity:toOpacity_]; return copy; } -(void) startWithTarget:(CCNode *)aTarget { [super startWithTarget:aTarget]; - fromOpacity = [(id)target_ opacity]; + fromOpacity_ = [(id)target_ opacity]; } -(void) update: (ccTime) t { - [(id)target_ setOpacity: fromOpacity + ( toOpacity - fromOpacity ) * t]; + [(id)target_ setOpacity:fromOpacity_ + ( toOpacity_ - fromOpacity_ ) * t]; } @end @@ -944,15 +1093,15 @@ +(id) actionWithDuration:(ccTime)t red:(GLubyte)r green:(GLubyte)g blue:(GLubyte -(id) initWithDuration: (ccTime) t red:(GLubyte)r green:(GLubyte)g blue:(GLubyte)b { - if( (self=[super initWithDuration: t] ) ) - to = ccc3(r,g,b); + if( (self=[super initWithDuration:t] ) ) + to_ = ccc3(r,g,b); return self; } -(id) copyWithZone: (NSZone*) zone { - CCAction *copy = [(CCTintTo*)[[self class] allocWithZone: zone] initWithDuration: [self duration] red:to.r green:to.g blue:to.b]; + CCAction *copy = [(CCTintTo*)[[self class] allocWithZone: zone] initWithDuration:[self duration] red:to_.r green:to_.g blue:to_.b]; return copy; } @@ -961,13 +1110,13 @@ -(void) startWithTarget:(id)aTarget [super startWithTarget:aTarget]; id tn = (id) target_; - from = [tn color]; + from_ = [tn color]; } -(void) update: (ccTime) t { id tn = (id) target_; - [tn setColor:ccc3(from.r + (to.r - from.r) * t, from.g + (to.g - from.g) * t, from.b + (to.b - from.b) * t)]; + [tn setColor:ccc3(from_.r + (to_.r - from_.r) * t, from_.g + (to_.g - from_.g) * t, from_.b + (to_.b - from_.b) * t)]; } @end @@ -985,16 +1134,16 @@ +(id) actionWithDuration:(ccTime)t red:(GLshort)r green:(GLshort)g blue:(GLshort -(id) initWithDuration:(ccTime)t red:(GLshort)r green:(GLshort)g blue:(GLshort)b { if( (self=[super initWithDuration: t] ) ) { - deltaR = r; - deltaG = g; - deltaB = b; + deltaR_ = r; + deltaG_ = g; + deltaB_ = b; } return self; } -(id) copyWithZone: (NSZone*) zone { - return[(CCTintBy*)[[self class] allocWithZone: zone] initWithDuration: [self duration] red:deltaR green:deltaG blue:deltaB]; + return[(CCTintBy*)[[self class] allocWithZone: zone] initWithDuration: [self duration] red:deltaR_ green:deltaG_ blue:deltaB_]; } -(void) startWithTarget:(id)aTarget @@ -1003,20 +1152,20 @@ -(void) startWithTarget:(id)aTarget id tn = (id) target_; ccColor3B color = [tn color]; - fromR = color.r; - fromG = color.g; - fromB = color.b; + fromR_ = color.r; + fromG_ = color.g; + fromB_ = color.b; } -(void) update: (ccTime) t { id tn = (id) target_; - [tn setColor:ccc3( fromR + deltaR * t, fromG + deltaG * t, fromB + deltaB * t)]; + [tn setColor:ccc3( fromR_ + deltaR_ * t, fromG_ + deltaG_ * t, fromB_ + deltaB_ * t)]; } - (CCActionInterval*) reverse { - return [CCTintBy actionWithDuration:duration_ red:-deltaR green:-deltaG blue:-deltaB]; + return [CCTintBy actionWithDuration:duration_ red:-deltaR_ green:-deltaG_ blue:-deltaB_]; } @end @@ -1052,43 +1201,49 @@ +(id) actionWithAction: (CCFiniteTimeAction*) action -(id) initWithAction: (CCFiniteTimeAction*) action { - if( (self=[super initWithDuration: [action duration]]) ) - other = [action retain]; + NSAssert(action != nil, @"CCReverseTime: action should not be nil"); + NSAssert(action != other_, @"CCReverseTime: re-init doesn't support using the same arguments"); + + if( (self=[super initWithDuration: [action duration]]) ) { + // Don't leak if action is reused + [other_ release]; + other_ = [action retain]; + } return self; } -(id) copyWithZone: (NSZone*) zone { - return [[[self class] allocWithZone: zone] initWithAction:[[other copy] autorelease] ]; + return [[[self class] allocWithZone: zone] initWithAction:[[other_ copy] autorelease] ]; } -(void) dealloc { - [other release]; + [other_ release]; [super dealloc]; } -(void) startWithTarget:(id)aTarget { [super startWithTarget:aTarget]; - [other startWithTarget:target_]; + [other_ startWithTarget:target_]; } -(void) stop { - [other stop]; + [other_ stop]; [super stop]; } -(void) update:(ccTime)t { - [other update:1-t]; + [other_ update:1-t]; } -(CCActionInterval*) reverse { - return [[other copy] autorelease]; + return [[other_ copy] autorelease]; } @end @@ -1096,55 +1251,63 @@ -(CCActionInterval*) reverse // Animate // -#pragma mark - -#pragma mark Animate +#pragma mark - CCAnimate @implementation CCAnimate @synthesize animation = animation_; +(id) actionWithAnimation: (CCAnimation*)anim { - return [[[self alloc] initWithAnimation:anim restoreOriginalFrame:YES] autorelease]; + return [[[self alloc] initWithAnimation:anim restoreOriginalFrame:anim.restoreOriginalFrame] autorelease]; } -+(id) actionWithAnimation: (CCAnimation*)anim restoreOriginalFrame:(BOOL)b ++(id) actionWithAnimation: (CCAnimation*)anim restoreOriginalFrame:(BOOL)restore { - return [[[self alloc] initWithAnimation:anim restoreOriginalFrame:b] autorelease]; + return [[[self alloc] initWithAnimation:anim restoreOriginalFrame:restore] autorelease]; } -+(id) actionWithDuration:(ccTime)duration animation: (CCAnimation*)anim restoreOriginalFrame:(BOOL)b ++(id) actionWithDuration:(ccTime)duration animation: (CCAnimation*)anim restoreOriginalFrame:(BOOL)restore { - return [[[self alloc] initWithDuration:duration animation:anim restoreOriginalFrame:b] autorelease]; + return [[[self alloc] initWithDuration:duration animation:anim restoreOriginalFrame:restore] autorelease]; } -(id) initWithAnimation: (CCAnimation*)anim { NSAssert( anim!=nil, @"Animate: argument Animation must be non-nil"); - return [self initWithAnimation:anim restoreOriginalFrame:YES]; + return [self initWithAnimation:anim restoreOriginalFrame:anim.restoreOriginalFrame]; } --(id) initWithAnimation: (CCAnimation*)anim restoreOriginalFrame:(BOOL) b +-(id) initWithAnimation: (CCAnimation*)anim restoreOriginalFrame:(BOOL)restoreOriginalFrame { NSAssert( anim!=nil, @"Animate: argument Animation must be non-nil"); - - if( (self=[super initWithDuration: [[anim frames] count] * [anim delay]]) ) { - - restoreOriginalFrame = b; - self.animation = anim; - origFrame = nil; - } - return self; + + return [self initWithDuration:anim.duration animation:anim restoreOriginalFrame:restoreOriginalFrame]; } --(id) initWithDuration:(ccTime)aDuration animation: (CCAnimation*)anim restoreOriginalFrame:(BOOL) b +// delegate initializer +-(id) initWithDuration:(ccTime)duration animation: (CCAnimation*)anim restoreOriginalFrame:(BOOL)restoreOriginalFrame { NSAssert( anim!=nil, @"Animate: argument Animation must be non-nil"); - if( (self=[super initWithDuration:aDuration] ) ) { + if( (self=[super initWithDuration:duration] ) ) { - restoreOriginalFrame = b; + nextFrame_ = 0; + restoreOriginalFrame_ = restoreOriginalFrame; self.animation = anim; - origFrame = nil; + origFrame_ = nil; + + splitTimes_ = [[NSMutableArray alloc] initWithCapacity:anim.frames.count]; + + float accumUnitsOfTime = 0; + float newUnitOfTimeValue = duration / anim.totalDelayUnits; + + for( CCAnimationFrame *frame in anim.frames ) { + + NSNumber *value = [NSNumber numberWithFloat: (accumUnitsOfTime * newUnitOfTimeValue) / duration]; + accumUnitsOfTime += frame.delayUnits; + + [splitTimes_ addObject:value]; + } } return self; } @@ -1152,13 +1315,14 @@ -(id) initWithDuration:(ccTime)aDuration animation: (CCAnimation*)anim restoreOr -(id) copyWithZone: (NSZone*) zone { - return [[[self class] allocWithZone: zone] initWithDuration:duration_ animation:animation_ restoreOriginalFrame:restoreOriginalFrame]; + return [[[self class] allocWithZone: zone] initWithDuration:duration_ animation:animation_ restoreOriginalFrame:restoreOriginalFrame_]; } -(void) dealloc { + [splitTimes_ release]; [animation_ release]; - [origFrame release]; + [origFrame_ release]; [super dealloc]; } @@ -1166,18 +1330,20 @@ -(void) startWithTarget:(id)aTarget { [super startWithTarget:aTarget]; CCSprite *sprite = target_; - - [origFrame release]; - - if( restoreOriginalFrame ) - origFrame = [[sprite displayedFrame] retain]; + + [origFrame_ release]; + + if( restoreOriginalFrame_ ) + origFrame_ = [[sprite displayedFrame] retain]; + + nextFrame_ = 0; } -(void) stop { - if( restoreOriginalFrame ) { + if( restoreOriginalFrame_ ) { CCSprite *sprite = target_; - [sprite setDisplayFrame:origFrame]; + [sprite setDisplayFrame:origFrame_]; } [super stop]; @@ -1187,15 +1353,25 @@ -(void) update: (ccTime) t { NSArray *frames = [animation_ frames]; NSUInteger numberOfFrames = [frames count]; + CCSpriteFrame *frameToDisplay = nil; - NSUInteger idx = t * numberOfFrames; - - if( idx >= numberOfFrames ) - idx = numberOfFrames -1; - - CCSprite *sprite = target_; - if (! [sprite isFrameDisplayed: [frames objectAtIndex: idx]] ) - [sprite setDisplayFrame: [frames objectAtIndex:idx]]; + for( NSUInteger i=nextFrame_; i < numberOfFrames; i++ ) { + NSNumber *splitTime = [splitTimes_ objectAtIndex:i]; + + if( [splitTime floatValue] <= t ) { + CCAnimationFrame *frame = [frames objectAtIndex:i]; + frameToDisplay = [frame spriteFrame]; + [(CCSprite*)target_ setDisplayFrame: frameToDisplay]; + + NSDictionary *dict = [frame userInfo]; + if( dict ) + [[NSNotificationCenter defaultCenter] postNotificationName:CCAnimationFrameDisplayedNotification object:target_ userInfo:dict]; + + nextFrame_ = i+1; + + break; + } + } } - (CCActionInterval *) reverse @@ -1206,8 +1382,52 @@ - (CCActionInterval *) reverse for (id element in enumerator) [newArray addObject:[[element copy] autorelease]]; - CCAnimation *newAnim = [CCAnimation animationWithFrames:newArray delay:animation_.delay]; - return [[self class] actionWithDuration:duration_ animation:newAnim restoreOriginalFrame:restoreOriginalFrame]; + CCAnimation *newAnim = [CCAnimation animationWithFrames:newArray delayPerUnit:animation_.delayPerUnit]; + return [[self class] actionWithDuration:duration_ animation:newAnim restoreOriginalFrame:restoreOriginalFrame_]; } @end + +@implementation CCTargetedAction + +@synthesize forcedTarget = forcedTarget_; + ++ (id) actionWithTarget:(id) target action:(CCFiniteTimeAction*) action +{ + return [[ (CCTargetedAction*)[self alloc] initWithTarget:target action:action] autorelease]; +} + +- (id) initWithTarget:(id) targetIn action:(CCFiniteTimeAction*) actionIn +{ + if((self = [super initWithDuration:actionIn.duration])) + { + forcedTarget_ = [targetIn retain]; + action_ = [actionIn retain]; + } + return self; +} + +- (void) dealloc +{ + [forcedTarget_ release]; + [action_ release]; + [super dealloc]; +} + +- (void) startWithTarget:(id)aTarget +{ + [super startWithTarget:forcedTarget_]; + [action_ startWithTarget:forcedTarget_]; +} + +- (void) stop +{ + [action_ stop]; +} + +- (void) update:(ccTime) time +{ + [action_ update:time]; +} + +@end \ No newline at end of file diff --git a/libs/cocos2d/CCActionManager.h b/libs/cocos2d/CCActionManager.h index 476390b..d836287 100644 --- a/libs/cocos2d/CCActionManager.h +++ b/libs/cocos2d/CCActionManager.h @@ -1,9 +1,11 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2008-2010 Ricardo Quesada * Copyright (c) 2009 Valentin Milea * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -26,18 +28,20 @@ #import "CCAction.h" +#import "ccMacros.h" #import "Support/ccCArray.h" #import "Support/uthash.h" typedef struct _hashElement { struct ccArray *actions; - id target; - unsigned int actionIndex; - CCAction *currentAction; + NSUInteger actionIndex; BOOL currentActionSalvaged; BOOL paused; UT_hash_handle hh; + + CC_ARC_UNSAFE_RETAINED id target; + CC_ARC_UNSAFE_RETAINED CCAction *currentAction; } tHashElement; @@ -86,17 +90,17 @@ typedef struct _hashElement */ -(void) removeAction: (CCAction*) action; /** Removes an action given its tag and the target */ --(void) removeActionByTag:(int)tag target:(id)target; +-(void) removeActionByTag:(NSInteger)tag target:(id)target; /** Gets an action given its tag an a target @return the Action the with the given tag */ --(CCAction*) getActionByTag:(int) tag target:(id)target; +-(CCAction*) getActionByTag:(NSInteger) tag target:(id)target; /** Returns the numbers of actions that are running in a certain target * Composable actions are counted as 1 action. Example: * If you are running 1 Sequence of 7 actions, it will return 1. * If you are running 7 Sequences of 2 actions, it will return 7. */ --(int) numberOfRunningActionsInTarget:(id)target; +-(NSUInteger) numberOfRunningActionsInTarget:(id)target; /** Pauses the target: all running actions and newly added actions will be paused. */ @@ -105,14 +109,5 @@ typedef struct _hashElement */ -(void) resumeTarget:(id)target; -/** Resumes the target. All queued actions will be resumed. - @deprecated Use resumeTarget: instead. Will be removed in v1.0. - */ --(void) resumeAllActionsForTarget:(id)target DEPRECATED_ATTRIBUTE; -/** Pauses the target: all running actions and newly added actions will be paused. - */ --(void) pauseAllActionsForTarget:(id)target DEPRECATED_ATTRIBUTE; - - @end diff --git a/libs/cocos2d/CCActionManager.m b/libs/cocos2d/CCActionManager.m index 9a6376f..8bdfbb7 100644 --- a/libs/cocos2d/CCActionManager.m +++ b/libs/cocos2d/CCActionManager.m @@ -1,9 +1,11 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2008-2010 Ricardo Quesada * Copyright (c) 2009 Valentin Milea * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -132,12 +134,6 @@ -(void) removeActionAtIndex:(NSUInteger)index hashElement:(tHashElement*)element #pragma mark ActionManager - Pause / Resume -// XXX DEPRECATED. REMOVE IN 1.0 --(void) pauseAllActionsForTarget:(id)target -{ - [self pauseTarget:target]; -} - -(void) pauseTarget:(id)target { tHashElement *element = NULL; @@ -148,12 +144,6 @@ -(void) pauseTarget:(id)target // CCLOG(@"cocos2d: pauseAllActions: Target not found"); } -// XXX DEPRECATED. REMOVE IN 1.0 --(void) resumeAllActionsForTarget:(id)target -{ - [self resumeTarget:target]; -} - -(void) resumeTarget:(id)target { tHashElement *element = NULL; @@ -243,7 +233,7 @@ -(void) removeAction: (CCAction*) action // } } --(void) removeActionByTag:(int) aTag target:(id)target +-(void) removeActionByTag:(NSInteger)aTag target:(id)target { NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag"); NSAssert( target != nil, @"Target should be ! nil"); @@ -256,19 +246,18 @@ -(void) removeActionByTag:(int) aTag target:(id)target for( NSUInteger i = 0; i < limit; i++) { CCAction *a = element->actions->arr[i]; - if( a.tag == aTag && [a originalTarget]==target) - return [self removeActionAtIndex:i hashElement:element]; + if( a.tag == aTag && [a originalTarget]==target) { + [self removeActionAtIndex:i hashElement:element]; + break; + } } -// CCLOG(@"cocos2d: removeActionByTag: Action not found!"); + } -// else { -// CCLOG(@"cocos2d: removeActionByTag: Target not found!"); -// } } #pragma mark ActionManager - get --(CCAction*) getActionByTag:(int)aTag target:(id)target +-(CCAction*) getActionByTag:(NSInteger)aTag target:(id)target { NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag"); @@ -293,7 +282,7 @@ -(CCAction*) getActionByTag:(int)aTag target:(id)target return nil; } --(int) numberOfRunningActionsInTarget:(id) target +-(NSUInteger) numberOfRunningActionsInTarget:(id) target { tHashElement *element = NULL; HASH_FIND_INT(targets, &target, element); diff --git a/libs/cocos2d/CCActionTiledGrid.h b/libs/cocos2d/CCActionTiledGrid.h index 5d88b16..d66132d 100644 --- a/libs/cocos2d/CCActionTiledGrid.h +++ b/libs/cocos2d/CCActionTiledGrid.h @@ -64,7 +64,7 @@ @interface CCShuffleTiles : CCTiledGrid3DAction { int seed; - int tilesCount; + NSUInteger tilesCount; int *tilesOrder; void *tiles; } @@ -124,7 +124,7 @@ @interface CCTurnOffTiles : CCTiledGrid3DAction { int seed; - int tilesCount; + NSUInteger tilesCount; int *tilesOrder; } diff --git a/libs/cocos2d/CCActionTiledGrid.m b/libs/cocos2d/CCActionTiledGrid.m index 4513866..75965ec 100644 --- a/libs/cocos2d/CCActionTiledGrid.m +++ b/libs/cocos2d/CCActionTiledGrid.m @@ -210,12 +210,12 @@ -(void)dealloc [super dealloc]; } --(void)shuffle:(int*)array count:(int)len +-(void)shuffle:(int*)array count:(NSUInteger)len { - int i; + NSInteger i; for( i = len - 1; i >= 0; i-- ) { - int j = rand() % (i+1); + NSInteger j = rand() % (i+1); int v = array[i]; array[i] = array[j]; array[j] = v; @@ -226,7 +226,7 @@ -(ccGridSize)getDelta:(ccGridSize)pos { CGPoint pos2; - int idx = pos.x * gridSize_.y + pos.y; + NSInteger idx = pos.x * gridSize_.y + pos.y; pos2.x = tilesOrder[idx] / (int)gridSize_.y; pos2.y = tilesOrder[idx] % (int)gridSize_.y; @@ -475,12 +475,12 @@ -(void)dealloc [super dealloc]; } --(void)shuffle:(int*)array count:(int)len +-(void)shuffle:(int*)array count:(NSUInteger)len { - int i; + NSInteger i; for( i = len - 1; i >= 0; i-- ) { - int j = rand() % (i+1); + NSInteger j = rand() % (i+1); int v = array[i]; array[i] = array[j]; array[j] = v; diff --git a/libs/cocos2d/CCAnimation.h b/libs/cocos2d/CCAnimation.h index 86c089c..4a93cb2 100644 --- a/libs/cocos2d/CCAnimation.h +++ b/libs/cocos2d/CCAnimation.h @@ -2,17 +2,18 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada - * + * Copyright (c) 2011 Zynga Inc. + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -24,107 +25,126 @@ */ #import +#ifdef __CC_PLATFORM_IOS +#import +#endif // IPHONE @class CCSpriteFrame; @class CCTexture2D; +@class CCSpriteFrame; + +/** CCAnimationFrame + A frame of the animation. It contains information like: + - sprite frame name + - # of delay units. + - offset + + @since v1.1 + */ +@interface CCAnimationFrame : NSObject +{ + CCSpriteFrame* spriteFrame_; + float delayUnits_; + NSDictionary *userInfo_; +} +/** CCSpriteFrameName to be used */ +@property (nonatomic, readwrite, retain) CCSpriteFrame* spriteFrame; + +/** how many units of time the frame takes */ +@property (nonatomic, readwrite) float delayUnits; + +/** A CCAnimationFrameDisplayedNotification notification will be broadcasted when the frame is displayed with this dictionary as UserInfo. If UserInfo is nil, then no notification will be broadcasted. */ +@property (nonatomic, readwrite, retain) NSDictionary *userInfo; + +/** initializes the animation frame with a spriteframe, number of delay units and a notification user info */ +-(id) initWithSpriteFrame:(CCSpriteFrame*)spriteFrame delayUnits:(float)delayUnits userInfo:(NSDictionary*)userInfo; +@end /** A CCAnimation object is used to perform animations on the CCSprite objects. - The CCAnimation object contains CCSpriteFrame objects, and a possible delay between the frames. + The CCAnimation object contains CCAnimationFrame objects, and a possible delay between the frames. You can animate a CCAnimation object by using the CCAnimate action. Example: - [sprite runAction:[CCAnimate actionWithAnimation:animation]]; + [sprite runAction:[CCAnimate actionWithAnimation:animation]]; */ @interface CCAnimation : NSObject { - NSString *name_; - float delay_; - NSMutableArray *frames_; + float totalDelayUnits_; + float delayPerUnit_; + float duration_; + NSMutableArray *frames_; + BOOL restoreOriginalFrame_; } -/** name of the animation */ -@property (nonatomic,readwrite,retain) NSString *name; -/** delay between frames in seconds. */ -@property (nonatomic,readwrite,assign) float delay; -/** array of frames */ +/** total Delay units of the CCAnimation. */ +@property (nonatomic, readonly) float totalDelayUnits; +/** Delay in seconds of the "delay unit" */ +@property (nonatomic, readwrite) float delayPerUnit; +/** duration in seconds of the whole animation. It is the result of totalDelayUnits * delayPerUnit */ +@property (nonatomic,readonly) float duration; +/** array of CCAnimationFrames */ @property (nonatomic,readwrite,retain) NSMutableArray *frames; +/** whether or not it shall restore the original frame when the animation finishes */ +@property (nonatomic,readwrite) BOOL restoreOriginalFrame; /** Creates an animation @since v0.99.5 */ +(id) animation; -/** Creates an animation with frames. +/** Creates an animation with an array of CCSpriteFrame. + The frames will be created with one "delay unit". @since v0.99.5 */ -+(id) animationWithFrames:(NSArray*)frames; ++(id) animationWithFrames:(NSArray*)arrayOfSpriteFrameNames; -/* Creates an animation with frames and a delay between frames. +/* Creates an animation with an array of CCSpriteFrame and a delay between frames in seconds. + The frames will be added with one "delay unit". @since v0.99.5 */ -+(id) animationWithFrames:(NSArray*)frames delay:(float)delay; ++(id) animationWithFrames:(NSArray*)arrayOfSpriteFrameNames delay:(float)delay; -/** Creates a CCAnimation with a name - @since v0.99.3 - @deprecated Will be removed in 1.0.1. Use "animation" instead. +/* Creates an animation with an array of CCAnimationFrame and the delay per units in seconds. + @since v2.0 */ -+(id) animationWithName:(NSString*)name DEPRECATED_ATTRIBUTE; ++(id) animationWithFrames:(NSArray*)arrayOfAnimationFrames delayPerUnit:(float)delayPerUnit; -/** Creates a CCAnimation with a name and frames - @since v0.99.3 - @deprecated Will be removed in 1.0.1. Use "animationWithFrames" instead. - */ -+(id) animationWithName:(NSString*)name frames:(NSArray*)frames DEPRECATED_ATTRIBUTE; - -/** Creates a CCAnimation with a name and delay between frames. */ -+(id) animationWithName:(NSString*)name delay:(float)delay DEPRECATED_ATTRIBUTE; - -/** Creates a CCAnimation with a name, delay and an array of CCSpriteFrames. */ -+(id) animationWithName:(NSString*)name delay:(float)delay frames:(NSArray*)frames DEPRECATED_ATTRIBUTE; - -/** Initializes a CCAnimation with frames. +/** Initializes a CCAnimation with an array of CCSpriteFrame. + The frames will be added with one "delay unit". @since v0.99.5 -*/ --(id) initWithFrames:(NSArray*)frames; + */ +-(id) initWithFrames:(NSArray*)arrayOfSpriteFrameNames; -/** Initializes a CCAnimation with frames and a delay between frames +/** Initializes a CCAnimation with an array of CCSpriteFrames and a delay between frames in seconds. + The frames will be added with one "delay unit". @since v0.99.5 */ --(id) initWithFrames:(NSArray *)frames delay:(float)delay; +-(id) initWithFrames:(NSArray *)arrayOfSpriteFrameNames delay:(float)delay; -/** Initializes a CCAnimation with a name - @since v0.99.3 - @deprecated Will be removed in 1.0.1. Use "init" instead. +/* Initializes an animation with an array of CCAnimationFrame and the delay per units in seconds. + @since v2.0 */ --(id) initWithName:(NSString*)name DEPRECATED_ATTRIBUTE; +-(id) initWithFrames:(NSArray*)arrayOfAnimationFrames delayPerUnit:(float)delayPerUnit; -/** Initializes a CCAnimation with a name and frames - @since v0.99.3 - @deprecated Will be removed in 1.0.1. Use "initWithFrames" instead. +/** Adds a CCSpriteFrame to a CCAnimation. + The frame will be added with one "delay unit". */ --(id) initWithName:(NSString*)name frames:(NSArray*)frames DEPRECATED_ATTRIBUTE; - -/** Initializes a CCAnimation with a name and delay between frames. - @deprecated Will be removed in 1.0.1. Use "initWithFrames:nil delay:delay" instead. -*/ --(id) initWithName:(NSString*)name delay:(float)delay DEPRECATED_ATTRIBUTE; - -/** Initializes a CCAnimation with a name, delay and an array of CCSpriteFrames. - @deprecated Will be removed in 1.0.1. Use "initWithFrames:frames delay:delay" instead. -*/ --(id) initWithName:(NSString*)name delay:(float)delay frames:(NSArray*)frames DEPRECATED_ATTRIBUTE; - -/** Adds a frame to a CCAnimation. */ -(void) addFrame:(CCSpriteFrame*)frame; +/** Adds a CCSpriteFrame to a CCAnimation. + delay is in seconds +*/ +-(void) addFrame:(CCSpriteFrame*)frame delay:(float) delay; /** Adds a frame with an image filename. Internally it will create a CCSpriteFrame and it will add it. + The frame will be added with one "delay unit". Added to facilitate the migration from v0.8 to v0.9. */ -(void) addFrameWithFilename:(NSString*)filename; /** Adds a frame with a texture and a rect. Internally it will create a CCSpriteFrame and it will add it. + The frame will be added with one "delay unit". Added to facilitate the migration from v0.8 to v0.9. */ -(void) addFrameWithTexture:(CCTexture2D*)texture rect:(CGRect)rect; diff --git a/libs/cocos2d/CCAnimation.m b/libs/cocos2d/CCAnimation.m index bb8480c..99fc421 100644 --- a/libs/cocos2d/CCAnimation.m +++ b/libs/cocos2d/CCAnimation.m @@ -2,17 +2,18 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada - * + * Copyright (c) 2011 Zynga Inc. + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -29,42 +30,68 @@ #import "CCTexture2D.h" #import "CCTextureCache.h" -@implementation CCAnimation -@synthesize name = name_, delay = delay_, frames = frames_; +#pragma mark - CCAnimationFrame +@implementation CCAnimationFrame -+(id) animation +@synthesize spriteFrame = spriteFrame_, delayUnits = delayUnits_, userInfo=userInfo_; + +-(id) initWithSpriteFrame:(CCSpriteFrame *)spriteFrame delayUnits:(float)delayUnits userInfo:(NSDictionary*)userInfo { - return [[[self alloc] init] autorelease]; + if( (self=[super init]) ) { + self.spriteFrame = spriteFrame; + self.delayUnits = delayUnits; + self.userInfo = userInfo; + } + + return self; } -+(id) animationWithFrames:(NSArray*)frames +-(void) dealloc +{ + CCLOGINFO( @"cocos2d: deallocing %@", self); + + [spriteFrame_ release]; + [userInfo_ release]; + + [super dealloc]; +} + +-(id) copyWithZone: (NSZone*) zone { - return [[[self alloc] initWithFrames:frames] autorelease]; + CCAnimationFrame *copy = [[[self class] allocWithZone: zone] initWithSpriteFrame:[[spriteFrame_ copy] autorelease] delayUnits:delayUnits_ userInfo:[[userInfo_ copy] autorelease] ]; + return copy; } -+(id) animationWithFrames:(NSArray*)frames delay:(float)delay +-(NSString*) description { - return [[[self alloc] initWithFrames:frames delay:delay] autorelease]; + return [NSString stringWithFormat:@"<%@ = %08X | SpriteFrame = %08X, delayUnits = %0.2f >", [self class], self, spriteFrame_, delayUnits_ ]; } +@end -+(id) animationWithName:(NSString*)name + +#pragma mark - CCAnimation + +@implementation CCAnimation +@synthesize frames = frames_, duration=duration_, totalDelayUnits=totalDelayUnits_, delayPerUnit=delayPerUnit_, restoreOriginalFrame=restoreOriginalFrame_; + ++(id) animation { - return [[[self alloc] initWithName:name] autorelease]; + return [[[self alloc] init] autorelease]; } -+(id) animationWithName:(NSString*)name frames:(NSArray*)frames ++(id) animationWithFrames:(NSArray*)frames { - return [[[self alloc] initWithName:name frames:frames] autorelease]; + return [[[self alloc] initWithFrames:frames] autorelease]; } -+(id) animationWithName:(NSString*)aname delay:(float)d frames:(NSArray*)array ++(id) animationWithFrames:(NSArray*)frames delay:(float)delay { - return [[[self alloc] initWithName:aname delay:d frames:array] autorelease]; + return [[[self alloc] initWithFrames:frames delay:delay] autorelease]; } -+(id) animationWithName:(NSString*)aname delay:(float)d ++(id) animationWithFrames:(NSArray*)arrayOfAnimationFrames delayPerUnit:(float)delayPerUnit { - return [[[self alloc] initWithName:aname delay:d] autorelease]; + return [[[self alloc] initWithFrames:arrayOfAnimationFrames delayPerUnit:delayPerUnit] autorelease]; } -(id) init @@ -81,57 +108,78 @@ -(id) initWithFrames:(NSArray*)array delay:(float)delay { if( (self=[super init]) ) { - delay_ = delay; - self.frames = [NSMutableArray arrayWithArray:array]; + self.frames = [NSMutableArray arrayWithCapacity:[array count]]; + duration_ = [array count] * delay; + + for( CCSpriteFrame *frame in array ) { + CCAnimationFrame *animFrame = [[CCAnimationFrame alloc] initWithSpriteFrame:frame delayUnits:1 userInfo:nil]; + + [self.frames addObject:animFrame]; + [animFrame release]; + totalDelayUnits_++; + } + + delayPerUnit_ = delay; } return self; } --(id) initWithName:(NSString*)name -{ - return [self initWithName:name delay:0 frames:nil]; -} - --(id) initWithName:(NSString*)name frames:(NSArray*)frames +-(id) initWithFrames:(NSArray*)arrayOfAnimationFrames delayPerUnit:(float)delayPerUnit { - return [self initWithName:name delay:0 frames:frames]; -} - --(id) initWithName:(NSString*)t delay:(float)d -{ - return [self initWithName:t delay:d frames:nil]; -} - --(id) initWithName:(NSString*)name delay:(float)delay frames:(NSArray*)array -{ - if( (self=[super init]) ) { - - delay_ = delay; - self.name = name; - self.frames = [NSMutableArray arrayWithArray:array]; + if( ( self=[super init]) ) { + delayPerUnit_ = delayPerUnit; + self.frames = [NSMutableArray arrayWithArray:arrayOfAnimationFrames]; + duration_ = 0; + for( CCAnimationFrame *animFrame in frames_ ) { + duration_ += animFrame.delayUnits * delayPerUnit; + totalDelayUnits_ += animFrame.delayUnits; + } } return self; } - (NSString*) description { - return [NSString stringWithFormat:@"<%@ = %08X | frames=%d, delay:%f>", [self class], self, + return [NSString stringWithFormat:@"<%@ = %08X | frames=%d, totalDelayUnits=%d, delayPerUnit=%f>", [self class], self, [frames_ count], - delay_ + totalDelayUnits_, + delayPerUnit_ ]; } -(void) dealloc { CCLOGINFO( @"cocos2d: deallocing %@",self); - [name_ release]; + [frames_ release]; [super dealloc]; } -(void) addFrame:(CCSpriteFrame*)frame { - [frames_ addObject:frame]; + CCAnimationFrame *animFrame = [[CCAnimationFrame alloc] initWithSpriteFrame:frame delayUnits:1 userInfo:nil]; + [frames_ addObject:animFrame]; + [animFrame release]; + + // update duration + duration_ += delayPerUnit_; + totalDelayUnits_++; +} + +-(void) addFrame:(CCSpriteFrame*)frame delay:(float) delay +{ + if ([frames_ count] == 0) + { + delayPerUnit_ = delay; + } + + float delayUnits = delay / delayPerUnit_; + totalDelayUnits_+= delayUnits; + duration_ += delay; + + CCAnimationFrame *animFrame = [[CCAnimationFrame alloc] initWithSpriteFrame:frame delayUnits:delayUnits userInfo:nil]; + [frames_ addObject:animFrame]; + [animFrame release]; } -(void) addFrameWithFilename:(NSString*)filename @@ -139,14 +187,15 @@ -(void) addFrameWithFilename:(NSString*)filename CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:filename]; CGRect rect = CGRectZero; rect.size = texture.contentSize; - CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:texture rect:rect]; - [frames_ addObject:frame]; + CCSpriteFrame *spriteFrame = [CCSpriteFrame frameWithTexture:texture rect:rect]; + + [self addFrame:spriteFrame]; } -(void) addFrameWithTexture:(CCTexture2D*)texture rect:(CGRect)rect { CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:texture rect:rect]; - [frames_ addObject:frame]; + [self addFrame:frame]; } @end diff --git a/libs/cocos2d/CCAnimationCache.h b/libs/cocos2d/CCAnimationCache.h index 3a9b8ae..674c07a 100644 --- a/libs/cocos2d/CCAnimationCache.h +++ b/libs/cocos2d/CCAnimationCache.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,10 +28,8 @@ @class CCAnimation; -/** Singleton that manages the Animations. +/** Singleton that manages the CCAnimation objects. It saves in a cache the animations. You should use this class if you want to save your animations in a cache. - - Before v0.99.5, the recommend way was to save them on the CCSprite. Since v0.99.5, you should use this class instead. @since v0.99.5 */ @@ -60,4 +59,16 @@ */ -(CCAnimation*) animationByName:(NSString*)name; +/** Adds an animation from an NSDictionary + Make sure that the frames were previously loaded in the CCSpriteFrameCache. + @since v1.1 + */ +-(void)addAnimationsWithDictionary:(NSDictionary *)dictionary; + +/** Adds an animation from a plist file. + Make sure that the frames were previously loaded in the CCSpriteFrameCache. + @since v1.1 + */ +-(void)addAnimationsWithFile:(NSString *)plist; + @end diff --git a/libs/cocos2d/CCAnimationCache.m b/libs/cocos2d/CCAnimationCache.m index 003bc63..ab698c8 100644 --- a/libs/cocos2d/CCAnimationCache.m +++ b/libs/cocos2d/CCAnimationCache.m @@ -2,17 +2,21 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2010 Ricardo Quesada - * + * Copyright (c) 2011 Zynga Inc. + * + * Copyright (c) 2011 John Wordsworth + * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -23,10 +27,12 @@ * */ -#import "ccMacros.h" #import "CCAnimationCache.h" +#import "ccMacros.h" +#import "CCSpriteFrameCache.h" #import "CCAnimation.h" #import "CCSprite.h" +#import "Support/CCFileUtils.h" @implementation CCAnimationCache @@ -39,7 +45,7 @@ + (CCAnimationCache *)sharedAnimationCache { if (!sharedAnimationCache_) sharedAnimationCache_ = [[CCAnimationCache alloc] init]; - + return sharedAnimationCache_; } @@ -97,4 +103,149 @@ -(CCAnimation*) animationByName:(NSString*)name return [animations_ objectForKey:name]; } -@end +#pragma mark CCAnimationCache - from file + +-(void) parseVersion1:(NSDictionary*)animations +{ + NSArray* animationNames = [animations allKeys]; + CCSpriteFrameCache *frameCache = [CCSpriteFrameCache sharedSpriteFrameCache]; + + for( NSString *name in animationNames ) { + NSDictionary* animationDict = [animations objectForKey:name]; + NSArray *frameNames = [animationDict objectForKey:@"frames"]; + NSNumber *delay = [animationDict objectForKey:@"delay"]; + CCAnimation* animation = nil; + + if ( frameNames == nil ) { + CCLOG(@"cocos2d: CCAnimationCache: Animation '%@' found in dictionary without any frames - cannot add to animation cache.", name); + continue; + } + + NSMutableArray *frames = [NSMutableArray arrayWithCapacity:[frameNames count]]; + + for( NSString *frameName in frameNames ) { + CCSpriteFrame *spriteFrame = [frameCache spriteFrameByName:frameName]; + + if ( ! spriteFrame ) { + CCLOG(@"cocos2d: CCAnimationCache: Animation '%@' refers to frame '%@' which is not currently in the CCSpriteFrameCache. This frame will not be added to the animation.", name, frameName); + + continue; + } + + CCAnimationFrame *animFrame = [[CCAnimationFrame alloc] initWithSpriteFrame:spriteFrame delayUnits:1 userInfo:nil]; + [frames addObject:animFrame]; + [animFrame release]; + } + + if ( [frames count] == 0 ) { + CCLOG(@"cocos2d: CCAnimationCache: None of the frames for animation '%@' were found in the CCSpriteFrameCache. Animation is not being added to the Animation Cache.", name); + continue; + } else if ( [frames count] != [frameNames count] ) { + CCLOG(@"cocos2d: CCAnimationCache: An animation in your dictionary refers to a frame which is not in the CCSpriteFrameCache. Some or all of the frames for the animation '%@' may be missing.", name); + } + + animation = [CCAnimation animationWithFrames:frames delayPerUnit:[delay floatValue]]; + + [[CCAnimationCache sharedAnimationCache] addAnimation:animation name:name]; + } +} + +-(void) parseVersion2:(NSDictionary*)animations +{ + NSArray* animationNames = [animations allKeys]; + CCSpriteFrameCache *frameCache = [CCSpriteFrameCache sharedSpriteFrameCache]; + + for( NSString *name in animationNames ) + { + NSDictionary* animationDict = [animations objectForKey:name]; + + // BOOL loop = [[animationDict objectForKey:@"loop"] boolValue]; + BOOL restoreOriginalFrame = [[animationDict objectForKey:@"restoreOriginalFrame"] boolValue]; + + NSArray *frameArray = [animationDict objectForKey:@"frames"]; + + + if ( frameArray == nil ) { + CCLOG(@"cocos2d: CCAnimationCache: Animation '%@' found in dictionary without any frames - cannot add to animation cache.", name); + continue; + } + + // Array of AnimationFrames + NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:[frameArray count]]; + + for( NSDictionary *entry in frameArray ) { + NSString *spriteFrameName = [entry objectForKey:@"spriteframe"]; + CCSpriteFrame *spriteFrame = [frameCache spriteFrameByName:spriteFrameName]; + + if( ! spriteFrame ) { + CCLOG(@"cocos2d: CCAnimationCache: Animation '%@' refers to frame '%@' which is not currently in the CCSpriteFrameCache. This frame will not be added to the animation.", name, spriteFrameName); + + continue; + } + + float delayUnits = [[entry objectForKey:@"delayUnits"] floatValue]; + NSDictionary *userInfo = [entry objectForKey:@"notification"]; + + CCAnimationFrame *animFrame = [[CCAnimationFrame alloc] initWithSpriteFrame:spriteFrame delayUnits:delayUnits userInfo:userInfo]; + + [array addObject:animFrame]; + [animFrame release]; + } + + float delayPerUnit = [[animationDict objectForKey:@"delayPerUnit"] floatValue]; + CCAnimation *animation = [[CCAnimation alloc] initWithFrames:array delayPerUnit:delayPerUnit]; + [array release]; + + [animation setRestoreOriginalFrame:restoreOriginalFrame]; + + [[CCAnimationCache sharedAnimationCache] addAnimation:animation name:name]; + [animation release]; + } +} + +-(void)addAnimationsWithDictionary:(NSDictionary *)dictionary +{ + NSDictionary *animations = [dictionary objectForKey:@"animations"]; + + if ( animations == nil ) { + CCLOG(@"cocos2d: CCAnimationCache: No animations were found in provided dictionary."); + return; + } + + NSUInteger version = 1; + NSDictionary *properties = [dictionary objectForKey:@"properties"]; + if( properties ) + version = [[properties objectForKey:@"format"] intValue]; + + NSArray *spritesheets = [properties objectForKey:@"spritesheets"]; + for( NSString *name in spritesheets ) + [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:name]; + + switch (version) { + case 1: + [self parseVersion1:animations]; + break; + case 2: + [self parseVersion2:animations]; + break; + default: + NSAssert(NO, @"Invalid animation format"); + } +} + + +/** Read an NSDictionary from a plist file and parse it automatically for animations */ +-(void)addAnimationsWithFile:(NSString *)plist +{ + NSAssert( plist, @"Invalid texture file name"); + + NSString *path = [CCFileUtils fullPathFromRelativePath:plist]; + NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; + + NSAssert1( dict, @"CCAnimationCache: File could not be found: %@", plist); + + + [self addAnimationsWithDictionary:dict]; +} + +@end \ No newline at end of file diff --git a/libs/cocos2d/CCAtlasNode.h b/libs/cocos2d/CCAtlasNode.h index 145586f..c805812 100644 --- a/libs/cocos2d/CCAtlasNode.h +++ b/libs/cocos2d/CCAtlasNode.h @@ -2,6 +2,8 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -42,14 +44,17 @@ CCTextureAtlas *textureAtlas_; // chars per row - int itemsPerRow_; + NSUInteger itemsPerRow_; // chars per column - int itemsPerColumn_; + NSUInteger itemsPerColumn_; // width of each char - int itemWidth_; + NSUInteger itemWidth_; // height of each char - int itemHeight_; + NSUInteger itemHeight_; + + // quads to draw + NSUInteger quadsToDraw_; // blend function ccBlendFunc blendFunc_; @@ -72,12 +77,14 @@ /** conforms to CCRGBAProtocol protocol */ @property (nonatomic,readwrite) ccColor3B color; +/** how many quads to draw */ +@property (nonatomic,readwrite) NSUInteger quadsToDraw; /** creates a CCAtlasNode with an Atlas file the width and height of each item measured in points and the quantity of items to render*/ -+(id) atlasWithTileFile:(NSString*)tile tileWidth:(int)w tileHeight:(int)h itemsToRender: (int) c; ++(id) atlasWithTileFile:(NSString*)tile tileWidth:(NSUInteger)w tileHeight:(NSUInteger)h itemsToRender: (NSUInteger) c; /** initializes an CCAtlasNode with an Atlas file the width and height of each item measured in points and the quantity of items to render*/ --(id) initWithTileFile:(NSString*)tile tileWidth:(int)w tileHeight:(int)h itemsToRender: (int) c; +-(id) initWithTileFile:(NSString*)tile tileWidth:(NSUInteger)w tileHeight:(NSUInteger)h itemsToRender: (NSUInteger) c; /** updates the Atlas (indexed vertex array). * Shall be overriden in subclasses diff --git a/libs/cocos2d/CCAtlasNode.m b/libs/cocos2d/CCAtlasNode.m index 840fead..328f672 100644 --- a/libs/cocos2d/CCAtlasNode.m +++ b/libs/cocos2d/CCAtlasNode.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -37,14 +38,15 @@ @implementation CCAtlasNode @synthesize textureAtlas = textureAtlas_; @synthesize blendFunc = blendFunc_; +@synthesize quadsToDraw = quadsToDraw_; #pragma mark CCAtlasNode - Creation & Init -+(id) atlasWithTileFile:(NSString*)tile tileWidth:(int)w tileHeight:(int)h itemsToRender: (int) c ++(id) atlasWithTileFile:(NSString*)tile tileWidth:(NSUInteger)w tileHeight:(NSUInteger)h itemsToRender: (NSUInteger) c { return [[[self alloc] initWithTileFile:tile tileWidth:w tileHeight:h itemsToRender:c] autorelease]; } --(id) initWithTileFile:(NSString*)tile tileWidth:(int)w tileHeight:(int)h itemsToRender: (int) c +-(id) initWithTileFile:(NSString*)tile tileWidth:(NSUInteger)w tileHeight:(NSUInteger)h itemsToRender: (NSUInteger) c { if( (self=[super init]) ) { @@ -60,8 +62,9 @@ -(id) initWithTileFile:(NSString*)tile tileWidth:(int)w tileHeight:(int)h itemsT // double retain to avoid the autorelease pool // also, using: self.textureAtlas supports re-initialization without leaking - self.textureAtlas = [[CCTextureAtlas alloc] initWithFile:tile capacity:c]; - [textureAtlas_ release]; + CCTextureAtlas *atlas = [[CCTextureAtlas alloc] initWithFile:tile capacity:c]; + self.textureAtlas = atlas; + [atlas release]; if( ! textureAtlas_ ) { CCLOG(@"cocos2d: Could not initialize CCAtlasNode. Invalid Texture"); @@ -74,6 +77,8 @@ -(id) initWithTileFile:(NSString*)tile tileWidth:(int)w tileHeight:(int)h itemsT [self calculateMaxItems]; + self.quadsToDraw = c; + } return self; } @@ -102,6 +107,8 @@ -(void) updateAtlasValues #pragma mark CCAtlasNode - draw - (void) draw { + [super draw]; + // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY // Unneeded states: GL_COLOR_ARRAY @@ -113,7 +120,7 @@ - (void) draw if( newBlend ) glBlendFunc( blendFunc_.src, blendFunc_.dst ); - [textureAtlas_ drawQuads]; + [textureAtlas_ drawNumberOfQuads:quadsToDraw_ fromIndex:0]; if( newBlend ) glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST); diff --git a/libs/cocos2d/CCCamera.h b/libs/cocos2d/CCCamera.h index 387c854..19a7712 100644 --- a/libs/cocos2d/CCCamera.h +++ b/libs/cocos2d/CCCamera.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/libs/cocos2d/CCCamera.m b/libs/cocos2d/CCCamera.m index 3841ab3..1ef6655 100644 --- a/libs/cocos2d/CCCamera.m +++ b/libs/cocos2d/CCCamera.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/libs/cocos2d/CCCompatibility.h b/libs/cocos2d/CCCompatibility.h deleted file mode 100644 index b1b578e..0000000 --- a/libs/cocos2d/CCCompatibility.h +++ /dev/null @@ -1,224 +0,0 @@ - -/* - * cocos2d for iPhone: http://www.cocos2d-iphone.org - * - * Copyright (c) 2008-2010 Ricardo Quesada - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -// AUTOMATICALLY GENERATED. DO NOT EDIT - - -#import -#import "cocos2d.h" - -#if CC_COMPATIBILITY_WITH_0_8 - -DEPRECATED_ATTRIBUTE @interface AccelAmplitude : CCAccelAmplitude {} @end -DEPRECATED_ATTRIBUTE @interface AccelDeccelAmplitude : CCAccelDeccelAmplitude {} @end -DEPRECATED_ATTRIBUTE @interface Action : CCAction {} @end -DEPRECATED_ATTRIBUTE @interface ActionManager : CCActionManager {} @end -DEPRECATED_ATTRIBUTE @interface Animate : CCAnimate {} @end -DEPRECATED_ATTRIBUTE @interface Animation : CCAnimation {} @end -DEPRECATED_ATTRIBUTE @interface AtlasAnimation : CCAnimation {} @end -DEPRECATED_ATTRIBUTE @interface AtlasNode : CCAtlasNode {} @end -DEPRECATED_ATTRIBUTE @interface AtlasSprite : CCSprite {} @end -DEPRECATED_ATTRIBUTE @interface AtlasSpriteFrame : CCSpriteFrame {} @end -DEPRECATED_ATTRIBUTE @interface AtlasSpriteManager : CCSpriteSheet {} @end -DEPRECATED_ATTRIBUTE @interface BezierBy : CCBezierBy {} @end -DEPRECATED_ATTRIBUTE @interface BezierTo : CCBezierTo {} @end -DEPRECATED_ATTRIBUTE @interface BitmapFontAtlas : CCBitmapFontAtlas {} @end -DEPRECATED_ATTRIBUTE @interface BitmapFontConfiguration : CCBitmapFontConfiguration {} @end -DEPRECATED_ATTRIBUTE @interface Blink : CCBlink {} @end -DEPRECATED_ATTRIBUTE @interface CallFunc : CCCallFunc {} @end -DEPRECATED_ATTRIBUTE @interface CallFuncN : CCCallFuncN {} @end -DEPRECATED_ATTRIBUTE @interface CallFuncND : CCCallFuncND {} @end -DEPRECATED_ATTRIBUTE @interface Camera : CCCamera {} @end -DEPRECATED_ATTRIBUTE @interface CameraAction : CCCameraAction {} @end -DEPRECATED_ATTRIBUTE @interface CocosNode : CCNode {} @end -DEPRECATED_ATTRIBUTE @interface ColorLayer : CCColorLayer {} @end -DEPRECATED_ATTRIBUTE @interface DeccelAmplitude : CCDeccelAmplitude {} @end -DEPRECATED_ATTRIBUTE @interface DelayTime : CCDelayTime {} @end -DEPRECATED_ATTRIBUTE @interface Director : CCDirector {} @end -DEPRECATED_ATTRIBUTE @interface DisplayLinkDirector : CCDisplayLinkDirector {} @end -DEPRECATED_ATTRIBUTE @interface EaseAction : CCEaseAction {} @end -DEPRECATED_ATTRIBUTE @interface EaseBackIn : CCEaseBackIn {} @end -DEPRECATED_ATTRIBUTE @interface EaseBackInOut : CCEaseBackInOut {} @end -DEPRECATED_ATTRIBUTE @interface EaseBackOut : CCEaseBackOut {} @end -DEPRECATED_ATTRIBUTE @interface EaseBounce : CCEaseBounce {} @end -DEPRECATED_ATTRIBUTE @interface EaseBounceIn : CCEaseBounceIn {} @end -DEPRECATED_ATTRIBUTE @interface EaseBounceInOut : CCEaseBounceInOut {} @end -DEPRECATED_ATTRIBUTE @interface EaseBounceOut : CCEaseBounceOut {} @end -DEPRECATED_ATTRIBUTE @interface EaseElastic : CCEaseElastic {} @end -DEPRECATED_ATTRIBUTE @interface EaseElasticIn : CCEaseElasticIn {} @end -DEPRECATED_ATTRIBUTE @interface EaseElasticInOut : CCEaseElasticInOut {} @end -DEPRECATED_ATTRIBUTE @interface EaseElasticOut : CCEaseElasticOut {} @end -DEPRECATED_ATTRIBUTE @interface EaseExponentialIn : CCEaseExponentialIn {} @end -DEPRECATED_ATTRIBUTE @interface EaseExponentialInOut : CCEaseExponentialInOut {} @end -DEPRECATED_ATTRIBUTE @interface EaseExponentialOut : CCEaseExponentialOut {} @end -DEPRECATED_ATTRIBUTE @interface EaseIn : CCEaseIn {} @end -DEPRECATED_ATTRIBUTE @interface EaseInOut : CCEaseInOut {} @end -DEPRECATED_ATTRIBUTE @interface EaseOut : CCEaseOut {} @end -DEPRECATED_ATTRIBUTE @interface EaseRateAction : CCEaseRateAction {} @end -DEPRECATED_ATTRIBUTE @interface EaseSineIn : CCEaseSineIn {} @end -DEPRECATED_ATTRIBUTE @interface EaseSineInOut : CCEaseSineInOut {} @end -DEPRECATED_ATTRIBUTE @interface EaseSineOut : CCEaseSineOut {} @end -DEPRECATED_ATTRIBUTE @interface FadeBLTransition : CCTransitionFadeBL {} @end -DEPRECATED_ATTRIBUTE @interface FadeDownTransition : CCTransitionFadeDown {} @end -DEPRECATED_ATTRIBUTE @interface FadeIn : CCFadeIn {} @end -DEPRECATED_ATTRIBUTE @interface FadeOut : CCFadeOut {} @end -DEPRECATED_ATTRIBUTE @interface FadeOutBLTiles : CCFadeOutBLTiles {} @end -DEPRECATED_ATTRIBUTE @interface FadeOutDownTiles : CCFadeOutDownTiles {} @end -DEPRECATED_ATTRIBUTE @interface FadeOutTRTiles : CCFadeOutTRTiles {} @end -DEPRECATED_ATTRIBUTE @interface FadeOutUpTiles : CCFadeOutUpTiles {} @end -DEPRECATED_ATTRIBUTE @interface FadeTRTransition : CCTransitionFadeTR {} @end -DEPRECATED_ATTRIBUTE @interface FadeTo : CCFadeTo {} @end -DEPRECATED_ATTRIBUTE @interface FadeTransition : CCTransitionFade {} @end -DEPRECATED_ATTRIBUTE @interface FadeUpTransition : CCTransitionFadeUp {} @end -DEPRECATED_ATTRIBUTE @interface FastDirector : CCFastDirector {} @end -DEPRECATED_ATTRIBUTE @interface FiniteTimeAction : CCFiniteTimeAction {} @end -DEPRECATED_ATTRIBUTE @interface FlipAngularTransition : CCTransitionFlipAngular {} @end -DEPRECATED_ATTRIBUTE @interface FlipX3D : CCFlipX3D {} @end -DEPRECATED_ATTRIBUTE @interface FlipXTransition : CCTransitionFlipX {} @end -DEPRECATED_ATTRIBUTE @interface FlipY3D : CCFlipY3D {} @end -DEPRECATED_ATTRIBUTE @interface FlipYTransition : CCTransitionFlipY {} @end -DEPRECATED_ATTRIBUTE @interface Grabber : CCGrabber {} @end -DEPRECATED_ATTRIBUTE @interface Grid3D : CCGrid3D {} @end -DEPRECATED_ATTRIBUTE @interface Grid3DAction : CCGrid3DAction {} @end -DEPRECATED_ATTRIBUTE @interface GridAction : CCGridAction {} @end -DEPRECATED_ATTRIBUTE @interface GridBase : CCGridBase {} @end -DEPRECATED_ATTRIBUTE @interface Hide : CCHide {} @end -DEPRECATED_ATTRIBUTE @interface InstantAction : CCInstantAction {} @end -DEPRECATED_ATTRIBUTE @interface IntervalAction : CCIntervalAction {} @end -DEPRECATED_ATTRIBUTE @interface JumpBy : CCJumpBy {} @end -DEPRECATED_ATTRIBUTE @interface JumpTiles3D : CCJumpTiles3D {} @end -DEPRECATED_ATTRIBUTE @interface JumpTo : CCJumpTo {} @end -DEPRECATED_ATTRIBUTE @interface JumpZoomTransition : CCTransitionJumpZoom {} @end -DEPRECATED_ATTRIBUTE @interface Label : CCLabel {} @end -DEPRECATED_ATTRIBUTE @interface LabelAtlas : CCLabelAtlas {} @end -DEPRECATED_ATTRIBUTE @interface Layer : CCLayer {} @end -DEPRECATED_ATTRIBUTE @interface Lens3D : CCLens3D {} @end -DEPRECATED_ATTRIBUTE @interface Liquid : CCLiquid {} @end -DEPRECATED_ATTRIBUTE @interface Menu : CCMenu {} @end -DEPRECATED_ATTRIBUTE @interface MenuItem : CCMenuItem {} @end -DEPRECATED_ATTRIBUTE @interface MenuItemAtlasFont : CCMenuItemAtlasFont {} @end -DEPRECATED_ATTRIBUTE @interface MenuItemFont : CCMenuItemFont {} @end -DEPRECATED_ATTRIBUTE @interface MenuItemImage : CCMenuItemImage {} @end -DEPRECATED_ATTRIBUTE @interface MenuItemLabel : CCMenuItemLabel {} @end -DEPRECATED_ATTRIBUTE @interface MenuItemSprite : CCMenuItemSprite {} @end -DEPRECATED_ATTRIBUTE @interface MenuItemToggle : CCMenuItemToggle {} @end -DEPRECATED_ATTRIBUTE @interface MotionStreak : CCMotionStreak {} @end -DEPRECATED_ATTRIBUTE @interface MoveBy : CCMoveBy {} @end -DEPRECATED_ATTRIBUTE @interface MoveInBTransition : CCTransitionMoveInB {} @end -DEPRECATED_ATTRIBUTE @interface MoveInLTransition : CCTransitionMoveInL {} @end -DEPRECATED_ATTRIBUTE @interface MoveInRTransition : CCTransitionMoveInR {} @end -DEPRECATED_ATTRIBUTE @interface MoveInTTransition : CCTransitionMoveInT {} @end -DEPRECATED_ATTRIBUTE @interface MoveTo : CCMoveTo {} @end -DEPRECATED_ATTRIBUTE @interface MultiplexLayer : CCMultiplexLayer {} @end -DEPRECATED_ATTRIBUTE @interface OrbitCamera : CCOrbitCamera {} @end -DEPRECATED_ATTRIBUTE @interface OrientedTransitionScene : CCTransitionSceneOriented {} @end -DEPRECATED_ATTRIBUTE @interface PVRTexture : CCPVRTexture {} @end -DEPRECATED_ATTRIBUTE @interface PageTurn3D : CCPageTurn3D {} @end -DEPRECATED_ATTRIBUTE @interface PageTurnTransition : CCPageTurnTransition {} @end -DEPRECATED_ATTRIBUTE @interface ParallaxNode : CCParallaxNode {} @end -DEPRECATED_ATTRIBUTE @interface ParticleExplosion : CCParticleExplosion {} @end -DEPRECATED_ATTRIBUTE @interface ParticleFire : CCParticleFire {} @end -DEPRECATED_ATTRIBUTE @interface ParticleFireworks : CCParticleFireworks {} @end -DEPRECATED_ATTRIBUTE @interface ParticleFlower : CCParticleFlower {} @end -DEPRECATED_ATTRIBUTE @interface ParticleGalaxy : CCParticleGalaxy {} @end -DEPRECATED_ATTRIBUTE @interface ParticleMeteor : CCParticleMeteor {} @end -DEPRECATED_ATTRIBUTE @interface ParticleRain : CCParticleRain {} @end -DEPRECATED_ATTRIBUTE @interface ParticleSmoke : CCParticleSmoke {} @end -DEPRECATED_ATTRIBUTE @interface ParticleSnow : CCParticleSnow {} @end -DEPRECATED_ATTRIBUTE @interface ParticleSpiral : CCParticleSpiral {} @end -DEPRECATED_ATTRIBUTE @interface ParticleSun : CCParticleSun {} @end -DEPRECATED_ATTRIBUTE @interface ParticleSystem : CCParticleSystem {} @end -DEPRECATED_ATTRIBUTE @interface Place : CCPlace {} @end -DEPRECATED_ATTRIBUTE @interface PointParticleSystem : CCPointParticleSystem {} @end -DEPRECATED_ATTRIBUTE @interface QuadParticleSystem : CCQuadParticleSystem {} @end -DEPRECATED_ATTRIBUTE @interface RenderTexture : CCRenderTexture {} @end -DEPRECATED_ATTRIBUTE @interface Repeat : CCRepeat {} @end -DEPRECATED_ATTRIBUTE @interface RepeatForever : CCRepeatForever {} @end -DEPRECATED_ATTRIBUTE @interface ReuseGrid : CCReuseGrid {} @end -DEPRECATED_ATTRIBUTE @interface ReverseTime : CCReverseTime {} @end -DEPRECATED_ATTRIBUTE @interface Ribbon : CCRibbon {} @end -DEPRECATED_ATTRIBUTE @interface RibbonSegment : CCRibbonSegment {} @end -DEPRECATED_ATTRIBUTE @interface Ripple3D : CCRipple3D {} @end -DEPRECATED_ATTRIBUTE @interface RotateBy : CCRotateBy {} @end -DEPRECATED_ATTRIBUTE @interface RotateTo : CCRotateTo {} @end -DEPRECATED_ATTRIBUTE @interface RotoZoomTransition : CCTransitionRotoZoom {} @end -DEPRECATED_ATTRIBUTE @interface ScaleBy : CCScaleBy {} @end -DEPRECATED_ATTRIBUTE @interface ScaleTo : CCScaleTo {} @end -DEPRECATED_ATTRIBUTE @interface Scene : CCScene {} @end -DEPRECATED_ATTRIBUTE @interface Scheduler : CCScheduler {} @end -DEPRECATED_ATTRIBUTE @interface Sequence : CCSequence {} @end -DEPRECATED_ATTRIBUTE @interface Shaky3D : CCShaky3D {} @end -DEPRECATED_ATTRIBUTE @interface ShakyTiles3D : CCShakyTiles3D {} @end -DEPRECATED_ATTRIBUTE @interface ShatteredTiles3D : CCShatteredTiles3D {} @end -DEPRECATED_ATTRIBUTE @interface Show : CCShow {} @end -DEPRECATED_ATTRIBUTE @interface ShrinkGrowTransition : CCTransitionShrinkGrow {} @end -DEPRECATED_ATTRIBUTE @interface ShuffleTiles : CCShuffleTiles {} @end -DEPRECATED_ATTRIBUTE @interface SlideInBTransition : CCTransitionSlideInB {} @end -DEPRECATED_ATTRIBUTE @interface SlideInLTransition : CCTransitionSlideInL {} @end -DEPRECATED_ATTRIBUTE @interface SlideInRTransition : CCTransitionSlideInR {} @end -DEPRECATED_ATTRIBUTE @interface SlideInTTransition : CCTransitionSlideInT {} @end -DEPRECATED_ATTRIBUTE @interface Spawn : CCSpawn {} @end -DEPRECATED_ATTRIBUTE @interface Speed : CCSpeed {} @end -DEPRECATED_ATTRIBUTE @interface SplitCols : CCSplitCols {} @end -DEPRECATED_ATTRIBUTE @interface SplitColsTransition : CCTransitionSplitCols {} @end -DEPRECATED_ATTRIBUTE @interface SplitRows : CCSplitRows {} @end -DEPRECATED_ATTRIBUTE @interface SplitRowsTransition : CCTransitionSplitRows {} @end -DEPRECATED_ATTRIBUTE @interface Sprite : CCSprite {} @end -DEPRECATED_ATTRIBUTE @interface StandardTouchHandler : CCStandardTouchHandler {} @end -DEPRECATED_ATTRIBUTE @interface StopGrid : CCStopGrid {} @end -DEPRECATED_ATTRIBUTE @interface TMXLayer : CCTMXLayer {} @end -DEPRECATED_ATTRIBUTE @interface TMXLayerInfo : CCTMXLayerInfo {} @end -DEPRECATED_ATTRIBUTE @interface TMXMapInfo : CCTMXMapInfo {} @end -DEPRECATED_ATTRIBUTE @interface TMXTiledMap : CCTMXTiledMap {} @end -DEPRECATED_ATTRIBUTE @interface TMXTilesetInfo : CCTMXTilesetInfo {} @end -DEPRECATED_ATTRIBUTE @interface TargetedTouchHandler : CCTargetedTouchHandler {} @end -DEPRECATED_ATTRIBUTE @interface Texture2D : CCTexture2D {} @end -DEPRECATED_ATTRIBUTE @interface TextureAtlas : CCTextureAtlas {} @end -DEPRECATED_ATTRIBUTE @interface TextureMgr : CCTextureCache {} @end -DEPRECATED_ATTRIBUTE @interface TextureNode : CCSprite {} @end -DEPRECATED_ATTRIBUTE @interface ThreadedFastDirector : CCThreadedFastDirector {} @end -DEPRECATED_ATTRIBUTE @interface TileMapAtlas : CCTileMapAtlas {} @end -DEPRECATED_ATTRIBUTE @interface TiledGrid3D : CCTiledGrid3D {} @end -DEPRECATED_ATTRIBUTE @interface TiledGrid3DAction : CCTiledGrid3DAction {} @end -DEPRECATED_ATTRIBUTE @interface Timer : CCTimer {} @end -DEPRECATED_ATTRIBUTE @interface TimerDirector : CCTimerDirector {} @end -DEPRECATED_ATTRIBUTE @interface TintBy : CCTintBy {} @end -DEPRECATED_ATTRIBUTE @interface TintTo : CCTintTo {} @end -DEPRECATED_ATTRIBUTE @interface ToggleVisibility : CCToggleVisibility {} @end -DEPRECATED_ATTRIBUTE @interface TouchDispatcher : CCTouchDispatcher {} @end -DEPRECATED_ATTRIBUTE @interface TouchHandler : CCTouchHandler {} @end -DEPRECATED_ATTRIBUTE @interface TransitionScene : CCTransitionScene {} @end -DEPRECATED_ATTRIBUTE @interface TurnOffTiles : CCTurnOffTiles {} @end -DEPRECATED_ATTRIBUTE @interface TurnOffTilesTransition : CCTransitionTurnOffTiles {} @end -DEPRECATED_ATTRIBUTE @interface Twirl : CCTwirl {} @end -DEPRECATED_ATTRIBUTE @interface Waves : CCWaves {} @end -DEPRECATED_ATTRIBUTE @interface Waves3D : CCWaves3D {} @end -DEPRECATED_ATTRIBUTE @interface WavesTiles3D : CCWavesTiles3D {} @end -DEPRECATED_ATTRIBUTE @interface ZoomFlipAngularTransition : CCTransitionZoomFlipAngular {} @end -DEPRECATED_ATTRIBUTE @interface ZoomFlipXTransition : CCTransitionZoomFlipX {} @end -DEPRECATED_ATTRIBUTE @interface ZoomFlipYTransition : CCTransitionZoomFlipY {} @end - -#endif // CC_COMPATIBILITY_WITH_0_8 diff --git a/libs/cocos2d/CCCompatibility.m b/libs/cocos2d/CCCompatibility.m deleted file mode 100644 index 93d0e53..0000000 --- a/libs/cocos2d/CCCompatibility.m +++ /dev/null @@ -1,596 +0,0 @@ - -/* - * cocos2d for iPhone: http://www.cocos2d-iphone.org - * - * Copyright (c) 2008-2010 Ricardo Quesada - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -// AUTOMATICALLY GENERATED. DO NOT EDIT - -#include "CCCompatibility.h" -#if CC_COMPATIBILITY_WITH_0_8 -@implementation AccelAmplitude -@end - -@implementation AccelDeccelAmplitude -@end - -@implementation Action -@end - -@implementation ActionManager -@end - -@implementation Animate -@end - -@implementation Animation -@end - -@implementation AtlasAnimation -@end - -@implementation AtlasNode -@end - -@implementation AtlasSprite -@end - -@implementation AtlasSpriteFrame -@end - -@implementation AtlasSpriteManager -@end - -@implementation BezierBy -@end - -@implementation BezierTo -@end - -@implementation BitmapFontAtlas -@end - -@implementation BitmapFontConfiguration -@end - -@implementation Blink -@end - -@implementation CallFunc -@end - -@implementation CallFuncN -@end - -@implementation CallFuncND -@end - -@implementation Camera -@end - -@implementation CameraAction -@end - -@implementation CocosNode -@end - -@implementation ColorLayer -@end - -@implementation DeccelAmplitude -@end - -@implementation DelayTime -@end - -@implementation Director -@end - -@implementation DisplayLinkDirector -@end - -@implementation EaseAction -@end - -@implementation EaseBackIn -@end - -@implementation EaseBackInOut -@end - -@implementation EaseBackOut -@end - -@implementation EaseBounce -@end - -@implementation EaseBounceIn -@end - -@implementation EaseBounceInOut -@end - -@implementation EaseBounceOut -@end - -@implementation EaseElastic -@end - -@implementation EaseElasticIn -@end - -@implementation EaseElasticInOut -@end - -@implementation EaseElasticOut -@end - -@implementation EaseExponentialIn -@end - -@implementation EaseExponentialInOut -@end - -@implementation EaseExponentialOut -@end - -@implementation EaseIn -@end - -@implementation EaseInOut -@end - -@implementation EaseOut -@end - -@implementation EaseRateAction -@end - -@implementation EaseSineIn -@end - -@implementation EaseSineInOut -@end - -@implementation EaseSineOut -@end - -@implementation FadeBLTransition -@end - -@implementation FadeDownTransition -@end - -@implementation FadeIn -@end - -@implementation FadeOut -@end - -@implementation FadeOutBLTiles -@end - -@implementation FadeOutDownTiles -@end - -@implementation FadeOutTRTiles -@end - -@implementation FadeOutUpTiles -@end - -@implementation FadeTRTransition -@end - -@implementation FadeTo -@end - -@implementation FadeTransition -@end - -@implementation FadeUpTransition -@end - -@implementation FastDirector -@end - -@implementation FiniteTimeAction -@end - -@implementation FlipAngularTransition -@end - -@implementation FlipX3D -@end - -@implementation FlipXTransition -@end - -@implementation FlipY3D -@end - -@implementation FlipYTransition -@end - -@implementation Grabber -@end - -@implementation Grid3D -@end - -@implementation Grid3DAction -@end - -@implementation GridAction -@end - -@implementation GridBase -@end - -@implementation Hide -@end - -@implementation InstantAction -@end - -@implementation IntervalAction -@end - -@implementation JumpBy -@end - -@implementation JumpTiles3D -@end - -@implementation JumpTo -@end - -@implementation JumpZoomTransition -@end - -@implementation Label -@end - -@implementation LabelAtlas -@end - -@implementation Layer -@end - -@implementation Lens3D -@end - -@implementation Liquid -@end - -@implementation Menu -@end - -@implementation MenuItem -@end - -@implementation MenuItemAtlasFont -@end - -@implementation MenuItemFont -@end - -@implementation MenuItemImage -@end - -@implementation MenuItemLabel -@end - -@implementation MenuItemSprite -@end - -@implementation MenuItemToggle -@end - -@implementation MotionStreak -@end - -@implementation MoveBy -@end - -@implementation MoveInBTransition -@end - -@implementation MoveInLTransition -@end - -@implementation MoveInRTransition -@end - -@implementation MoveInTTransition -@end - -@implementation MoveTo -@end - -@implementation MultiplexLayer -@end - -@implementation OrbitCamera -@end - -@implementation OrientedTransitionScene -@end - -@implementation PVRTexture -@end - -@implementation PageTurn3D -@end - -@implementation PageTurnTransition -@end - -@implementation ParallaxNode -@end - -@implementation ParticleExplosion -@end - -@implementation ParticleFire -@end - -@implementation ParticleFireworks -@end - -@implementation ParticleFlower -@end - -@implementation ParticleGalaxy -@end - -@implementation ParticleMeteor -@end - -@implementation ParticleRain -@end - -@implementation ParticleSmoke -@end - -@implementation ParticleSnow -@end - -@implementation ParticleSpiral -@end - -@implementation ParticleSun -@end - -@implementation ParticleSystem -@end - -@implementation Place -@end - -@implementation PointParticleSystem -@end - -@implementation QuadParticleSystem -@end - -@implementation RenderTexture -@end - -@implementation Repeat -@end - -@implementation RepeatForever -@end - -@implementation ReuseGrid -@end - -@implementation ReverseTime -@end - -@implementation Ribbon -@end - -@implementation RibbonSegment -@end - -@implementation Ripple3D -@end - -@implementation RotateBy -@end - -@implementation RotateTo -@end - -@implementation RotoZoomTransition -@end - -@implementation ScaleBy -@end - -@implementation ScaleTo -@end - -@implementation Scene -@end - -@implementation Scheduler -@end - -@implementation Sequence -@end - -@implementation Shaky3D -@end - -@implementation ShakyTiles3D -@end - -@implementation ShatteredTiles3D -@end - -@implementation Show -@end - -@implementation ShrinkGrowTransition -@end - -@implementation ShuffleTiles -@end - -@implementation SlideInBTransition -@end - -@implementation SlideInLTransition -@end - -@implementation SlideInRTransition -@end - -@implementation SlideInTTransition -@end - -@implementation Spawn -@end - -@implementation Speed -@end - -@implementation SplitCols -@end - -@implementation SplitColsTransition -@end - -@implementation SplitRows -@end - -@implementation SplitRowsTransition -@end - -@implementation Sprite -@end - -@implementation StandardTouchHandler -@end - -@implementation StopGrid -@end - -@implementation TMXLayer -@end - -@implementation TMXLayerInfo -@end - -@implementation TMXMapInfo -@end - -@implementation TMXTiledMap -@end - -@implementation TMXTilesetInfo -@end - -@implementation TargetedTouchHandler -@end - -@implementation Texture2D -@end - -@implementation TextureAtlas -@end - -@implementation TextureMgr -@end - -@implementation TextureNode -@end - -@implementation ThreadedFastDirector -@end - -@implementation TileMapAtlas -@end - -@implementation TiledGrid3D -@end - -@implementation TiledGrid3DAction -@end - -@implementation Timer -@end - -@implementation TimerDirector -@end - -@implementation TintBy -@end - -@implementation TintTo -@end - -@implementation ToggleVisibility -@end - -@implementation TouchDispatcher -@end - -@implementation TouchHandler -@end - -@implementation TransitionScene -@end - -@implementation TurnOffTiles -@end - -@implementation TurnOffTilesTransition -@end - -@implementation Twirl -@end - -@implementation Waves -@end - -@implementation Waves3D -@end - -@implementation WavesTiles3D -@end - -@implementation ZoomFlipAngularTransition -@end - -@implementation ZoomFlipXTransition -@end - -@implementation ZoomFlipYTransition -@end - - -#endif // CC_COMPATIBILITY_WITH_0_8 diff --git a/libs/cocos2d/CCConfiguration.h b/libs/cocos2d/CCConfiguration.h index 11bd120..04e1b55 100644 --- a/libs/cocos2d/CCConfiguration.h +++ b/libs/cocos2d/CCConfiguration.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,6 +40,11 @@ enum { kCCiOSVersion_4_0 = 0x04000000, kCCiOSVersion_4_0_1 = 0x04000100, kCCiOSVersion_4_1 = 0x04010000, + kCCiOSVersion_4_2 = 0x04020000, + kCCiOSVersion_4_3 = 0x04030000, + kCCiOSVersion_4_3_1 = 0x04030100, + kCCiOSVersion_4_3_2 = 0x04030200, + kCCiOSVersion_4_3_3 = 0x04030300, kCCMacVersion_10_5 = 0x0a050000, kCCMacVersion_10_6 = 0x0a060000, diff --git a/libs/cocos2d/CCConfiguration.m b/libs/cocos2d/CCConfiguration.m index e70bed1..d51cd58 100644 --- a/libs/cocos2d/CCConfiguration.m +++ b/libs/cocos2d/CCConfiguration.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/libs/cocos2d/CCDirector.h b/libs/cocos2d/CCDirector.h index fd36364..ddcd08d 100644 --- a/libs/cocos2d/CCDirector.h +++ b/libs/cocos2d/CCDirector.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -88,6 +89,8 @@ and when to execute the Scenes. BOOL displayFPS_; NSUInteger frames_; + NSUInteger totalFrames_; + ccTime accumDt_; ccTime frameRate_; #if CC_DIRECTOR_FAST_FPS @@ -134,7 +137,7 @@ and when to execute the Scenes. /* the cocos2d running thread */ NSThread *runningThread_; - + // profiler #if CC_ENABLE_PROFILERS ccTime accumDtForProfiler_; @@ -163,6 +166,8 @@ and when to execute the Scenes. @since v0.8.2 */ @property (nonatomic,readwrite) ccDirectorProjection projection; +/** How many frames were called since the director started */ +@property (nonatomic,readonly) NSUInteger totalFrames; /** Whether or not the replaced scene will receive the cleanup message. If the new scene is pushed, then the old scene won't receive the "cleanup" message. @@ -282,7 +287,7 @@ and when to execute the Scenes. // Memory Helper /** Removes all the cocos2d data that was cached automatically. - It will purge the CCTextureCache, CCBitmapFont cache. + It will purge the CCTextureCache, CCLabelBMFont cache. IMPORTANT: The CCSpriteFrameCache won't be purged. If you want to purge it, you have to purge it manually. @since v0.99.3 */ diff --git a/libs/cocos2d/CCDirector.m b/libs/cocos2d/CCDirector.m index 35425fe..ce0e78e 100644 --- a/libs/cocos2d/CCDirector.m +++ b/libs/cocos2d/CCDirector.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -85,6 +86,7 @@ @implementation CCDirector @synthesize runningThread = runningThread_; @synthesize notificationNode = notificationNode_; @synthesize projectionDelegate = projectionDelegate_; +@synthesize totalFrames = totalFrames_; // // singleton stuff // @@ -137,7 +139,7 @@ - (id) init // FPS displayFPS_ = NO; - frames_ = 0; + totalFrames_ = frames_ = 0; // paused ? isPaused_ = NO; @@ -217,6 +219,12 @@ -(void) calculateDeltaTime dt = (now.tv_sec - lastUpdate_.tv_sec) + (now.tv_usec - lastUpdate_.tv_usec) / 1000000.0f; dt = MAX(0,dt); } + +#ifdef DEBUG + // If we are debugging our code, prevent big delta time + if( dt > 0.2f ) + dt = 1/60.0f; +#endif lastUpdate_ = now; } @@ -226,7 +234,7 @@ -(void) calculateDeltaTime -(void) purgeCachedData { [CCLabelBMFont purgeCachedData]; - [CCTextureCache purgeSharedTextureCache]; + [[CCTextureCache sharedTextureCache] removeUnusedTextures]; } #pragma mark Director - Scene OpenGL Helper @@ -262,7 +270,7 @@ - (void) setDepthTest: (BOOL) on ccglClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); +// glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); } else glDisable( GL_DEPTH_TEST ); } @@ -505,7 +513,7 @@ -(void) showFPS [FPSLabel_ setString:str]; [str release]; } - + [FPSLabel_ draw]; } #else @@ -523,7 +531,7 @@ -(void) showFPS } NSString *str = [NSString stringWithFormat:@"%.2f",frameRate_]; - CCTexture2D *texture = [[CCTexture2D alloc] initWithString:str dimensions:CGSizeMake(100,30) alignment:UITextAlignmentLeft fontName:@"Arial" fontSize:24]; + CCTexture2D *texture = [[CCTexture2D alloc] initWithString:str dimensions:CGSizeMake(100,30) alignment:CCTextAlignmentLeft fontName:@"Arial" fontSize:24]; // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY @@ -543,6 +551,7 @@ -(void) showFPS } #endif + - (void) showProfilers { #if CC_ENABLE_PROFILERS accumDtForProfiler_ += dt; diff --git a/libs/cocos2d/CCDrawingPrimitives.h b/libs/cocos2d/CCDrawingPrimitives.h index 1dbd9a5..a1d7634 100644 --- a/libs/cocos2d/CCDrawingPrimitives.h +++ b/libs/cocos2d/CCDrawingPrimitives.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -49,7 +50,7 @@ extern "C" { - ccDrawCubicBezier You can change the color, width and other property by calling the - glColor4ub(), glLineWitdh(), glPointSize(). + glColor4ub(), glLineWidth(), glPointSize(). @warning These functions draws the Line, Point, Polygon, immediately. They aren't batched. If you are going to make a game that depends on these primitives, I suggest creating a batch. */ @@ -66,12 +67,32 @@ void ccDrawPoints( const CGPoint *points, NSUInteger numberOfPoints ); /** draws a line given the origin and destination point measured in points. */ void ccDrawLine( CGPoint origin, CGPoint destination ); +/** draws multiple lines in one draw call + @since 1.1 + */ +void ccDrawLines( CGPoint* points, NSUInteger numberOfPoints ); + +/** draws a rectangle given the origin and destination point measured in points. */ +void ccDrawRect( CGPoint origin, CGPoint destination ); + +/** draws a solid rectangle given the origin and destination point measured in points. + @since 1.1 + */ +void ccDrawSolidRect( CGPoint origin, CGPoint destination ); + /** draws a poligon given a pointer to CGPoint coordiantes and the number of vertices measured in points. The polygon can be closed or open */ void ccDrawPoly( const CGPoint *vertices, NSUInteger numOfVertices, BOOL closePolygon ); -/** draws a circle given the center, radius and number of segments measured in points */ +/** draws a solid poligon given a pointer to CGPoint coordiantes and the number of vertices measured in points. + The polygon can be closed or open + @since 1.1 + */ +void ccDrawSolidPoly( const CGPoint *vertices, NSUInteger numOfVertices, BOOL closePolygon ); + +/** draws a circle given the center, radius and number of segments measured in points + */ void ccDrawCircle( CGPoint center, float radius, float angle, NSUInteger segments, BOOL drawLineToCenter); /** draws a quad bezier path measured in points. diff --git a/libs/cocos2d/CCDrawingPrimitives.m b/libs/cocos2d/CCDrawingPrimitives.m index 1e26a6f..d3d9322 100644 --- a/libs/cocos2d/CCDrawingPrimitives.m +++ b/libs/cocos2d/CCDrawingPrimitives.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -68,14 +69,14 @@ void ccDrawPoints( const CGPoint *points, NSUInteger numberOfPoints ) // points ? if( CC_CONTENT_SCALE_FACTOR() != 1 ) { for( NSUInteger i=0; i 0 ) { - int numQuads = gridSize_.x * gridSize_.y; + NSInteger numQuads = gridSize_.x * gridSize_.y; memcpy(originalVertices, vertices, numQuads*12*sizeof(GLfloat)); reuseGrid_--; diff --git a/libs/cocos2d/CCLabelAtlas.h b/libs/cocos2d/CCLabelAtlas.h index d30fb38..7a1fe9a 100644 --- a/libs/cocos2d/CCLabelAtlas.h +++ b/libs/cocos2d/CCLabelAtlas.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -36,7 +37,7 @@ - CCLabelAtlas "characters" have a fixed height and width - CCLabelAtlas "characters" can be anything you want since they are taken from an image file - A more flexible class is CCBitmapFontAtlas. It supports variable width characters and it also has a nice editor. + A more flexible class is CCLabelBMFont. It supports variable width characters and it also has a nice editor. */ @interface CCLabelAtlas : CCAtlasNode { @@ -44,18 +45,13 @@ NSString *string_; // the first char in the charmap - char mapStartChar; + unsigned char mapStartChar_; } /** creates the CCLabelAtlas with a string, a char map file(the atlas), the width and height of each element in points and the starting char of the atlas */ -+(id) labelWithString:(NSString*) string charMapFile: (NSString*) charmapfile itemWidth:(int)w itemHeight:(int)h startCharMap:(char)c; - -/** creates the CCLabelAtlas with a string, a char map file(the atlas), the width and height of each element in points and the starting char of the atlas. - @deprecated Will be removed in 1.0.1. Use "labelWithString:" instead - */ -+(id) labelAtlasWithString:(NSString*) string charMapFile: (NSString*) charmapfile itemWidth:(int)w itemHeight:(int)h startCharMap:(char)c DEPRECATED_ATTRIBUTE; ++(id) labelWithString:(NSString*) string charMapFile: (NSString*) charmapfile itemWidth:(NSUInteger)w itemHeight:(NSUInteger)h startCharMap:(unsigned char)c; /** initializes the CCLabelAtlas with a string, a char map file(the atlas), the width and height in points of each element and the starting char of the atlas */ --(id) initWithString:(NSString*) string charMapFile: (NSString*) charmapfile itemWidth:(int)w itemHeight:(int)h startCharMap:(char)c; +-(id) initWithString:(NSString*) string charMapFile: (NSString*) charmapfile itemWidth:(NSUInteger)w itemHeight:(NSUInteger)h startCharMap:(unsigned char)c; @end diff --git a/libs/cocos2d/CCLabelAtlas.m b/libs/cocos2d/CCLabelAtlas.m index 98ba04e..a8d4f43 100644 --- a/libs/cocos2d/CCLabelAtlas.m +++ b/libs/cocos2d/CCLabelAtlas.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,24 +36,17 @@ @implementation CCLabelAtlas #pragma mark CCLabelAtlas - Creation & Init -+(id) labelWithString:(NSString*)string charMapFile:(NSString*)charmapfile itemWidth:(int)w itemHeight:(int)h startCharMap:(char)c ++(id) labelWithString:(NSString*)string charMapFile:(NSString*)charmapfile itemWidth:(NSUInteger)w itemHeight:(NSUInteger)h startCharMap:(unsigned char)c { return [[[self alloc] initWithString:string charMapFile:charmapfile itemWidth:w itemHeight:h startCharMap:c] autorelease]; } -// XXX DEPRECATED. Remove it in 1.0.1 -+(id) labelAtlasWithString:(NSString*) string charMapFile: (NSString*) charmapfile itemWidth:(int)w itemHeight:(int)h startCharMap:(char)c -{ - return [self labelWithString:string charMapFile:charmapfile itemWidth:w itemHeight:h startCharMap:c]; -} - - --(id) initWithString:(NSString*) theString charMapFile: (NSString*) charmapfile itemWidth:(int)w itemHeight:(int)h startCharMap:(char)c +-(id) initWithString:(NSString*) theString charMapFile: (NSString*) charmapfile itemWidth:(NSUInteger)w itemHeight:(NSUInteger)h startCharMap:(unsigned char)c { if ((self=[super initWithTileFile:charmapfile tileWidth:w tileHeight:h itemsToRender:[theString length] ]) ) { - mapStartChar = c; + mapStartChar_ = c; [self setString: theString]; } @@ -70,18 +64,18 @@ -(void) dealloc -(void) updateAtlasValues { - int n = [string_ length]; + NSUInteger n = [string_ length]; ccV3F_C4B_T2F_Quad quad; - const char *s = [string_ UTF8String]; + const unsigned char *s = (unsigned char*) [string_ UTF8String]; CCTexture2D *texture = [textureAtlas_ texture]; float textureWide = [texture pixelsWide]; float textureHigh = [texture pixelsHigh]; for( NSUInteger i=0; i textureAtlas_.totalQuads ) - [textureAtlas_ resizeCapacity: newString.length]; + NSUInteger len = [newString length]; + if( len > textureAtlas_.capacity ) + [textureAtlas_ resizeCapacity:len]; [string_ release]; string_ = [newString copy]; [self updateAtlasValues]; CGSize s; - s.width = [string_ length] * itemWidth_; + s.width = len * itemWidth_; s.height = itemHeight_; [self setContentSizeInPixels:s]; + + self.quadsToDraw = len; } -(NSString*) string @@ -146,44 +143,21 @@ -(NSString*) string return string_; } -#pragma mark CCLabelAtlas - draw +#pragma mark CCLabelAtlas - DebugDraw -// XXX: overriding draw from AtlasNode +#if CC_LABELATLAS_DEBUG_DRAW - (void) draw { - // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY - // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY - // Unneeded states: GL_COLOR_ARRAY - glDisableClientState(GL_COLOR_ARRAY); + [super draw]; - glColor4ub( color_.r, color_.g, color_.b, opacity_); - - BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST; - if( newBlend ) - glBlendFunc( blendFunc_.src, blendFunc_.dst ); - - [textureAtlas_ drawNumberOfQuads: string_.length]; - - if( newBlend ) - glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST); - - // is this chepear than saving/restoring color state ? - // XXX: There is no need to restore the color to (255,255,255,255). Objects should use the color - // XXX: that they need -// glColor4ub( 255, 255, 255, 255); - - // Restore Default GL state. Enable GL_COLOR_ARRAY - glEnableClientState(GL_COLOR_ARRAY); - - -#if CC_LABELATLAS_DEBUG_DRAW CGSize s = [self contentSize]; CGPoint vertices[4]={ ccp(0,0),ccp(s.width,0), ccp(s.width,s.height),ccp(0,s.height), }; ccDrawPoly(vertices, 4, YES); -#endif // CC_LABELATLAS_DEBUG_DRAW } +#endif // CC_LABELATLAS_DEBUG_DRAW + @end diff --git a/libs/cocos2d/CCLabelBMFont.h b/libs/cocos2d/CCLabelBMFont.h index 38b32dc..1db3ad0 100644 --- a/libs/cocos2d/CCLabelBMFont.h +++ b/libs/cocos2d/CCLabelBMFont.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,12 +25,12 @@ * Portions of this code are based and inspired on: * http://www.71squared.co.uk/2009/04/iphone-game-programming-tutorial-4-bitmap-font-class * by Michael Daley - - * Use any of these editors to generate bitmap font atlas: - * http://www.n4te.com/hiero/hiero.jnlp - * http://slick.cokeandcode.com/demos/hiero.jnlp - * http://www.angelcode.com/products/bmfont/ - * + * + * Use any of these editors to generate BMFonts: + * http://glyphdesigner.71squared.com/ (Commercial, Mac OS X) + * http://www.n4te.com/hiero/hiero.jnlp (Free, Java) + * http://slick.cokeandcode.com/demos/hiero.jnlp (Free, Java) + * http://www.angelcode.com/products/bmfont/ (Free, Windows only) */ #import "CCSpriteBatchNode.h" @@ -51,6 +52,8 @@ typedef struct _BMFontDef { int yOffset; //! The amount to move the current position after drawing the character (in pixels) int xAdvance; + // Enable Hash Table + UT_hash_handle hh; } ccBMFontDef; /** @struct ccBMFontPadding @@ -68,20 +71,15 @@ typedef struct _BMFontPadding { int bottom; } ccBMFontPadding; -enum { - // how many characters are supported - kCCBMFontMaxChars = 2048, //256, -}; - /** CCBMFontConfiguration has parsed configuration of the the .fnt file @since v0.8 */ @interface CCBMFontConfiguration : NSObject { -// XXX: Creating a public interface so that the bitmapFontArray[] is accesible + // XXX: Creating a public interface so that the bitmapFontArray[] is accesible @public // The characters building up the font - ccBMFontDef BMFontArray_[kCCBMFontMaxChars]; + ccBMFontDef *BMFontHash_; // FNTConfig: Common Height NSUInteger commonHeight_; @@ -91,7 +89,7 @@ enum { // atlas name NSString *atlasName_; - + // values for kerning struct _KerningHashElement *kerningDictionary_; } @@ -104,30 +102,30 @@ enum { /** CCLabelBMFont is a subclass of CCSpriteBatchNode - + Features: - Treats each character like a CCSprite. This means that each individual character can be: - - rotated - - scaled - - translated - - tinted - - chage the opacity + - rotated + - scaled + - translated + - tinted + - chage the opacity - It can be used as part of a menu item. - anchorPoint can be used to align the "label" - Supports AngelCode text format Limitations: - - All inner characters are using an anchorPoint of (0.5f, 0.5f) and it is not recommend to change it - because it might affect the rendering + - All inner characters are using an anchorPoint of (0.5f, 0.5f) and it is not recommend to change it + because it might affect the rendering CCLabelBMFont implements the protocol CCLabelProtocol, like CCLabel and CCLabelAtlas. CCLabelBMFont has the flexibility of CCLabel, the speed of CCLabelAtlas and all the features of CCSprite. If in doubt, use CCLabelBMFont instead of CCLabelAtlas / CCLabel. Supported editors: - - http://www.n4te.com/hiero/hiero.jnlp - - http://slick.cokeandcode.com/demos/hiero.jnlp - - http://www.angelcode.com/products/bmfont/ + - http://www.n4te.com/hiero/hiero.jnlp + - http://slick.cokeandcode.com/demos/hiero.jnlp + - http://www.angelcode.com/products/bmfont/ @since v0.8 */ @@ -136,9 +134,16 @@ enum { { // string to render NSString *string_; + + // initial string without line breaks + NSString *initialString_; + // max width until a line break is added + float width_; + // alignment of all lines + CCTextAlignment alignment_; CCBMFontConfiguration *configuration_; - + // texture RGBA GLubyte opacity_; ccColor3B color_; @@ -151,6 +156,10 @@ enum { */ +(void) purgeCachedData; +@property (nonatomic,copy,readonly) NSString *initialString; +@property (nonatomic,assign,readonly) float width; +@property (nonatomic,assign,readonly) CCTextAlignment alignment; + /** conforms to CCRGBAProtocol protocol */ @property (nonatomic,readwrite) GLubyte opacity; /** conforms to CCRGBAProtocol protocol */ @@ -159,31 +168,26 @@ enum { /** creates a BMFont label with an initial string and the FNT file */ +(id) labelWithString:(NSString*)string fntFile:(NSString*)fntFile; - -/** creates a BMFont label with an initial string and the FNT file - @deprecated Will be removed in 1.0.1. Use "labelWithString" instead. - */ -+(id) bitmapFontAtlasWithString:(NSString*)string fntFile:(NSString*)fntFile DEPRECATED_ATTRIBUTE; +/** creates a BMFont label with an initial string, the FNT file, width, and alignment option */ ++(id) labelWithString:(NSString*)string fntFile:(NSString*)fntFile width:(float)width alignment:(CCTextAlignment)alignment; /** init a BMFont label with an initial string and the FNT file */ -(id) initWithString:(NSString*)string fntFile:(NSString*)fntFile; +/** init a BMFont label with an initial string and the FNT file, width, and alignment option*/ +-(id) initWithString:(NSString*)string fntFile:(NSString*)fntFile width:(float)width alignment:(CCTextAlignment)alignment; /** updates the font chars based on the string to render */ -(void) createFontChars; + +- (void)setWidth:(float)width; +- (void)setAlignment:(CCTextAlignment)alignment; @end /** Free function that parses a FNT file a place it on the cache -*/ + */ CCBMFontConfiguration * FNTConfigLoadFile( NSString *file ); /** Purges the FNT config cache */ void FNTConfigRemoveCache( void ); - -/** CCBitmapFontAtlas - @deprecated Use CCLabelBMFont instead. Will be removed 1.0.1 - */ -DEPRECATED_ATTRIBUTE @interface CCBitmapFontAtlas : CCLabelBMFont -@end - diff --git a/libs/cocos2d/CCLabelBMFont.m b/libs/cocos2d/CCLabelBMFont.m index 67e168e..147fc32 100644 --- a/libs/cocos2d/CCLabelBMFont.m +++ b/libs/cocos2d/CCLabelBMFont.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,13 +27,15 @@ * by Michael Daley * * - * Use any of these editors to generate bitmap font atlas: - * http://www.n4te.com/hiero/hiero.jnlp - * http://slick.cokeandcode.com/demos/hiero.jnlp - * http://www.angelcode.com/products/bmfont/ + * Use any of these editors to generate BMFonts: + * http://glyphdesigner.71squared.com/ (Commercial, Mac OS X) + * http://www.n4te.com/hiero/hiero.jnlp (Free, Java) + * http://slick.cokeandcode.com/demos/hiero.jnlp (Free, Java) + * http://www.angelcode.com/products/bmfont/ (Free, Windows only) */ #import "ccConfig.h" +#import "ccMacros.h" #import "CCLabelBMFont.h" #import "CCSprite.h" #import "CCDrawingPrimitives.h" @@ -82,15 +85,19 @@ void FNTConfigRemoveCache( void ) @interface CCBMFontConfiguration (Private) -(void) parseConfigFile:(NSString*)controlFile; --(void) parseCharacterDefinition:(NSString*)line charDef:(ccBMFontDef*)characterDefinition; +-(void) parseCharacterDefinition:(NSString*)line; -(void) parseInfoArguments:(NSString*)line; -(void) parseCommonArguments:(NSString*)line; -(void) parseImageFileName:(NSString*)line fntFile:(NSString*)fntFile; -(void) parseKerningCapacity:(NSString*)line; -(void) parseKerningEntry:(NSString*)line; -(void) purgeKerningDictionary; +-(void) purgeBMFontHash; @end +#pragma mark - +#pragma mark CCBMFontConfiguration + @implementation CCBMFontConfiguration +(id) configurationWithFNTFile:(NSString*)FNTfile @@ -101,9 +108,9 @@ +(id) configurationWithFNTFile:(NSString*)FNTfile -(id) initWithFNTfile:(NSString*)fntFile { if((self=[super init])) { - + BMFontHash_ = NULL; kerningDictionary_ = NULL; - + [self parseConfigFile:fntFile]; } return self; @@ -113,6 +120,7 @@ - (void) dealloc { CCLOGINFO( @"cocos2d: deallocing %@", self); [self purgeKerningDictionary]; + [self purgeBMFontHash]; [atlasName_ release]; [super dealloc]; } @@ -136,10 +144,24 @@ -(void) purgeKerningDictionary } } +-(void) purgeBMFontHash +{ + ccBMFontDef *current; + + while(BMFontHash_) { + current = BMFontHash_; + HASH_DEL(BMFontHash_,current); + free(current); + } +} + - (void)parseConfigFile:(NSString*)fntFile { NSString *fullpath = [CCFileUtils fullPathFromRelativePath:fntFile]; - NSString *contents = [NSString stringWithContentsOfFile:fullpath encoding:NSUTF8StringEncoding error:nil]; + NSError *error; + NSString *contents = [NSString stringWithContentsOfFile:fullpath encoding:NSUTF8StringEncoding error:&error]; + + NSAssert1( contents, @"cocos2d: Error parsing FNTfile: %@", error); // Move all lines in the string, which are denoted by \n, into an array @@ -157,7 +179,7 @@ - (void)parseConfigFile:(NSString*)fntFile if([line hasPrefix:@"info face"]) { // XXX: info parsing is incomplete // Not needed for the Hiero editors, but needed for the AngelCode editor -// [self parseInfoArguments:line]; + // [self parseInfoArguments:line]; } // Check to see if the start of the line is something we are interested in else if([line hasPrefix:@"common lineHeight"]) { @@ -170,12 +192,7 @@ - (void)parseConfigFile:(NSString*)fntFile // Ignore this line } else if([line hasPrefix:@"char"]) { - // Parse the current line and create a new CharDef - ccBMFontDef characterDefinition; - [self parseCharacterDefinition:line charDef:&characterDefinition]; - - // Add the CharDef returned to the charArray - BMFontArray_[ characterDefinition.charID ] = characterDefinition; + [self parseCharacterDefinition:line]; } else if([line hasPrefix:@"kernings count"]) { [self parseKerningCapacity:line]; @@ -191,7 +208,7 @@ - (void)parseConfigFile:(NSString*)fntFile -(void) parseImageFileName:(NSString*)line fntFile:(NSString*)fntFile { NSString *propertyValue = nil; - + // Break the values for this line up using = NSArray *values = [line componentsSeparatedByString:@"="]; @@ -203,18 +220,18 @@ -(void) parseImageFileName:(NSString*)line fntFile:(NSString*)fntFile // page ID. Sanity check propertyValue = [nse nextObject]; - NSAssert( [propertyValue intValue] == 0, @"XXX: BitmapFontAtlas only supports 1 page"); + NSAssert( [propertyValue intValue] == 0, @"XXX: LabelBMFont only supports 1 page"); // file propertyValue = [nse nextObject]; NSArray *array = [propertyValue componentsSeparatedByString:@"\""]; propertyValue = [array objectAtIndex:1]; - NSAssert(propertyValue,@"BitmapFontAtlas file could not be found"); + NSAssert(propertyValue,@"LabelBMFont file could not be found"); // Supports subdirectories NSString *dir = [fntFile stringByDeletingLastPathComponent]; atlasName_ = [dir stringByAppendingPathComponent:propertyValue]; - + [atlasName_ retain]; } @@ -237,22 +254,22 @@ -(void) parseInfoArguments:(NSString*)line // size (ignore) [nse nextObject]; - + // bold (ignore) [nse nextObject]; - + // italic (ignore) [nse nextObject]; // charset (ignore) [nse nextObject]; - + // unicode (ignore) [nse nextObject]; - + // strechH (ignore) [nse nextObject]; - + // smooth (ignore) [nse nextObject]; @@ -272,7 +289,7 @@ -(void) parseInfoArguments:(NSString*)line // padding right propertyValue = [paddingEnum nextObject]; padding_.right = [propertyValue intValue]; - + // padding bottom propertyValue = [paddingEnum nextObject]; padding_.bottom = [propertyValue intValue]; @@ -283,7 +300,7 @@ -(void) parseInfoArguments:(NSString*)line CCLOG(@"cocos2d: padding: %d,%d,%d,%d", padding_.left, padding_.top, padding_.right, padding_.bottom); } - + // spacing (ignore) [nse nextObject]; } @@ -323,8 +340,11 @@ -(void) parseCommonArguments:(NSString*)line // packed (ignore) What does this mean ?? } -- (void)parseCharacterDefinition:(NSString*)line charDef:(ccBMFontDef*)characterDefinition -{ +- (void)parseCharacterDefinition:(NSString*)line +{ + ccBMFontDef *characterDefinition = NULL; + characterDefinition = calloc(sizeof(ccBMFontDef),1); + // Break the values for this line up using = NSArray *values = [line componentsSeparatedByString:@"="]; NSEnumerator *nse = [values objectEnumerator]; @@ -337,8 +357,7 @@ - (void)parseCharacterDefinition:(NSString*)line charDef:(ccBMFontDef*)character propertyValue = [nse nextObject]; propertyValue = [propertyValue substringToIndex: [propertyValue rangeOfString: @" "].location]; characterDefinition->charID = [propertyValue intValue]; - NSAssert(characterDefinition->charID < kCCBMFontMaxChars, @"BitmpaFontAtlas: CharID bigger than supported"); - + // Character x propertyValue = [nse nextObject]; characterDefinition->rect.origin.x = [propertyValue intValue]; @@ -360,28 +379,31 @@ - (void)parseCharacterDefinition:(NSString*)line charDef:(ccBMFontDef*)character // Character xadvance propertyValue = [nse nextObject]; characterDefinition->xAdvance = [propertyValue intValue]; + + // Add the CharDef returned to the charHash + HASH_ADD_INT(BMFontHash_, charID, characterDefinition); } -(void) parseKerningCapacity:(NSString*) line { // When using uthash there is not need to parse the capacity. - -// NSAssert(!kerningDictionary, @"dictionary already initialized"); -// -// // Break the values for this line up using = -// NSArray *values = [line componentsSeparatedByString:@"="]; -// NSEnumerator *nse = [values objectEnumerator]; -// NSString *propertyValue; -// -// // We need to move past the first entry in the array before we start assigning values -// [nse nextObject]; -// -// // count -// propertyValue = [nse nextObject]; -// int capacity = [propertyValue intValue]; -// -// if( capacity != -1 ) -// kerningDictionary = ccHashSetNew(capacity, targetSetEql); + + // NSAssert(!kerningDictionary, @"dictionary already initialized"); + // + // // Break the values for this line up using = + // NSArray *values = [line componentsSeparatedByString:@"="]; + // NSEnumerator *nse = [values objectEnumerator]; + // NSString *propertyValue; + // + // // We need to move past the first entry in the array before we start assigning values + // [nse nextObject]; + // + // // count + // propertyValue = [nse nextObject]; + // int capacity = [propertyValue intValue]; + // + // if( capacity != -1 ) + // kerningDictionary = ccHashSetNew(capacity, targetSetEql); } -(void) parseKerningEntry:(NSString*) line @@ -404,7 +426,7 @@ -(void) parseKerningEntry:(NSString*) line // second propertyValue = [nse nextObject]; int amount = [propertyValue intValue]; - + tKerningHashElement *element = calloc( sizeof( *element ), 1 ); element->amount = amount; element->key = (first<<16) | (second&0xffff); @@ -421,67 +443,231 @@ -(NSString*) atlasNameFromFntFile:(NSString*)fntFile; -(int) kerningAmountForFirst:(unichar)first second:(unichar)second; +-(void) updateLabel; +-(void) setString:(NSString*) newString fromUpdate:(bool)fromUpdate; + @end +#pragma mark - +#pragma mark CCLabelBMFont + @implementation CCLabelBMFont +@synthesize initialString = initialString_, width = width_, alignment = alignment_; @synthesize opacity = opacity_, color = color_; -#pragma mark BitmapFontAtlas - Purge Cache + +#pragma mark LabelBMFont - Purge Cache +(void) purgeCachedData { FNTConfigRemoveCache(); } -#pragma mark BitmapFontAtlas - Creation & Init +#pragma mark LabelBMFont - Creation & Init +(id) labelWithString:(NSString *)string fntFile:(NSString *)fntFile { return [[[self alloc] initWithString:string fntFile:fntFile] autorelease]; } -// XXX - deprecated - Will be removed in 1.0.1 -+(id) bitmapFontAtlasWithString:(NSString*)string fntFile:(NSString*)fntFile ++(id) labelWithString:(NSString*)string fntFile:(NSString*)fntFile width:(float)width alignment:(CCTextAlignment)alignment { - return [self labelWithString:string fntFile:fntFile]; + return [[[self alloc] initWithString:string fntFile:fntFile width:width alignment:alignment] autorelease]; } -(id) initWithString:(NSString*)theString fntFile:(NSString*)fntFile +{ + return [self initWithString:theString fntFile:fntFile width:-1 alignment:CCTextAlignmentLeft]; +} + +-(id) initWithString:(NSString*)theString fntFile:(NSString*)fntFile width:(float)width alignment:(CCTextAlignment)alignment { [configuration_ release]; // allow re-init - + configuration_ = FNTConfigLoadFile(fntFile); [configuration_ retain]; - - NSAssert( configuration_, @"Error creating config for BitmapFontAtlas"); - + + NSAssert( configuration_, @"Error creating config for LabelBMFont"); + if ((self=[super initWithFile:configuration_->atlasName_ capacity:[theString length]])) { - + + initialString_ = [theString copy]; + width_ = width; + alignment_ = alignment; + opacity_ = 255; color_ = ccWHITE; - + contentSize_ = CGSizeZero; opacityModifyRGB_ = [[textureAtlas_ texture] hasPremultipliedAlpha]; - + anchorPoint_ = ccp(0.5f, 0.5f); - + + + [self setString:theString]; + + [self updateLabel]; } - + return self; } -(void) dealloc { [string_ release]; + [initialString_ release], initialString_ = nil; [configuration_ release]; [super dealloc]; } -#pragma mark BitmapFontAtlas - Atlas generation +#pragma mark LabelBMFont - Alignment + +- (void)updateLabel { + + [self setString:initialString_ fromUpdate:YES]; + + if (width_ > 0){ + //Step 1: Make multiline + + NSString *multilineString = @"", *lastWord = @""; + int line = 1, i = 0; + NSUInteger stringLength = [self.string length]; + float startOfLine = -1, startOfWord = -1; + int skip = 0; + //Go through each character and insert line breaks as necessary + for (int j = 0; j < [children_ count]; j++) { + CCSprite *characterSprite; + + while(!(characterSprite = (CCSprite *)[self getChildByTag:j+skip])) + skip++; + + if (!characterSprite.visible) continue; + + if (i >= stringLength || i < 0) + break; + + unichar character = [self.string characterAtIndex:i]; + + if (startOfWord == -1) + startOfWord = characterSprite.position.x - characterSprite.contentSize.width/2; + if (startOfLine == -1) + startOfLine = startOfWord; + + //Character is a line break + //Put lastWord on the current line and start a new line + //Reset lastWord + if ([[NSCharacterSet newlineCharacterSet] characterIsMember:character]) { + lastWord = [[lastWord stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] stringByAppendingFormat:@"%C", character]; + multilineString = [multilineString stringByAppendingString:lastWord]; + lastWord = @""; + startOfWord = -1; + line++; + startOfLine = -1; + i++; + + //CCLabelBMFont do not have a character for new lines, so do NOT "continue;" in the for loop. Process the next character + if (i >= stringLength || i < 0) + break; + character = [self.string characterAtIndex:i]; + + if (startOfWord == -1) + startOfWord = characterSprite.position.x - characterSprite.contentSize.width/2; + if (startOfLine == -1) + startOfLine = startOfWord; + } + + //Character is a whitespace + //Put lastWord on current line and continue on current line + //Reset lastWord + if ([[NSCharacterSet whitespaceCharacterSet] characterIsMember:character]) { + lastWord = [lastWord stringByAppendingFormat:@"%C", character]; + multilineString = [multilineString stringByAppendingString:lastWord]; + lastWord = @""; + startOfWord = -1; + i++; + continue; + } + + //Character is out of bounds + //Do not put lastWord on current line. Add "\n" to current line to start a new line + //Append to lastWord + if (characterSprite.position.x + characterSprite.contentSize.width/2 - startOfLine > self.width) { + lastWord = [lastWord stringByAppendingFormat:@"%C", character]; + NSString *trimmedString = [multilineString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + multilineString = [trimmedString stringByAppendingString:@"\n"]; + line++; + startOfLine = -1; + i++; + continue; + } else { + //Character is normal + //Append to lastWord + lastWord = [lastWord stringByAppendingFormat:@"%C", character]; + i++; + continue; + } + } + + multilineString = [multilineString stringByAppendingFormat:@"%@", lastWord]; + + [self setString:multilineString fromUpdate:YES]; + } + + //Step 2: Make alignment + + if (self.alignment != CCTextAlignmentLeft) { + + int i = 0; + //Number of spaces skipped + int lineNumber = 0; + //Go through line by line + for (NSString *lineString in [string_ componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]]) { + int lineWidth = 0; + + //Find index of last character in this line + NSInteger index = i + [lineString length] - 1 + lineNumber; + if (index < 0) + continue; + + //Find position of last character on the line + CCSprite *lastChar = (CCSprite *)[self getChildByTag:index]; + + lineWidth = lastChar.position.x + lastChar.contentSize.width/2; + + //Figure out how much to shift each character in this line horizontally + float shift = 0; + switch (self.alignment) { + case CCTextAlignmentCenter: + shift = self.contentSize.width/2 - lineWidth/2; + break; + case CCTextAlignmentRight: + shift = self.contentSize.width - lineWidth; + default: + break; + } + + if (shift != 0) { + int j = 0; + //For each character, shift it so that the line is center aligned + for (j = 0; j < [lineString length]; j++) { + index = i + j + lineNumber; + if (index < 0) + continue; + CCSprite *characterSprite = (CCSprite *)[self getChildByTag:index]; + characterSprite.position = ccpAdd(characterSprite.position, ccp(shift, 0)); + } + } + i += [lineString length]; + lineNumber++; + } + } +} + +#pragma mark LabelBMFont - Atlas generation -(int) kerningAmountForFirst:(unichar)first second:(unichar)second { @@ -494,28 +680,28 @@ -(int) kerningAmountForFirst:(unichar)first second:(unichar)second if(element) ret = element->amount; } - + return ret; } -(void) createFontChars { - int nextFontPositionX = 0; - int nextFontPositionY = 0; + NSInteger nextFontPositionX = 0; + NSInteger nextFontPositionY = 0; unichar prev = -1; - int kerningAmount = 0; + NSInteger kerningAmount = 0; CGSize tmpSize = CGSizeZero; - - int longestLine = 0; - int totalHeight = 0; + + NSInteger longestLine = 0; + NSUInteger totalHeight = 0; - int quantityOfLines = 1; - + NSUInteger quantityOfLines = 1; + NSUInteger stringLen = [string_ length]; if( ! stringLen ) return; - + // quantity of lines NEEDS to be calculated before parsing the lines, // since the Y position needs to be calcualted before hand for(NSUInteger i=0; i < stringLen-1;i++) { @@ -527,78 +713,93 @@ -(void) createFontChars totalHeight = configuration_->commonHeight_ * quantityOfLines; nextFontPositionY = -(configuration_->commonHeight_ - configuration_->commonHeight_*quantityOfLines); - for(NSUInteger i=0; icommonHeight_; continue; } - + kerningAmount = [self kerningAmountForFirst:prev second:c]; - ccBMFontDef fontDef = configuration_->BMFontArray_[c]; - - CGRect rect = fontDef.rect; - - CCSprite *fontChar; - - fontChar = (CCSprite*) [self getChildByTag:i]; - if( ! fontChar ) { - fontChar = [[CCSprite alloc] initWithBatchNode:self rectInPixels:rect]; - [self addChild:fontChar z:0 tag:i]; - [fontChar release]; - } - else { - // reusing fonts - [fontChar setTextureRectInPixels:rect rotated:NO untrimmedSize:rect.size]; - - // restore to default in case they were modified - fontChar.visible = YES; - fontChar.opacity = 255; - } - - float yOffset = configuration_->commonHeight_ - fontDef.yOffset; - fontChar.positionInPixels = ccp( (float)nextFontPositionX + fontDef.xOffset + fontDef.rect.size.width*0.5f + kerningAmount, - (float)nextFontPositionY + yOffset - rect.size.height*0.5f ); - - // update kerning - nextFontPositionX += configuration_->BMFontArray_[c].xAdvance + kerningAmount; - prev = c; - - // Apply label properties - [fontChar setOpacityModifyRGB:opacityModifyRGB_]; - // Color MUST be set before opacity, since opacity might change color if OpacityModifyRGB is on - [fontChar setColor:color_]; - - // only apply opacity if it is different than 255 ) - // to prevent modifying the color too (issue #610) - if( opacity_ != 255 ) - [fontChar setOpacity: opacity_]; - - if (longestLine < nextFontPositionX) - longestLine = nextFontPositionX; - } - - tmpSize.width = longestLine; - tmpSize.height = totalHeight; - - [self setContentSizeInPixels:tmpSize]; + ccBMFontDef *fontDef = NULL; + unsigned int charKey = c; + HASH_FIND_INT(configuration_->BMFontHash_,&charKey,fontDef); + + if(fontDef) { + CGRect rect = fontDef->rect; + + CCSprite *fontChar; + + fontChar = (CCSprite*) [self getChildByTag:i]; + if( ! fontChar ) { + fontChar = [[CCSprite alloc] initWithBatchNode:self rectInPixels:rect]; + [self addChild:fontChar z:0 tag:i]; + [fontChar release]; + } + else { + // reusing fonts + [fontChar setTextureRectInPixels:rect rotated:NO untrimmedSize:rect.size]; + + // restore to default in case they were modified + fontChar.visible = YES; + fontChar.opacity = 255; + } + + float yOffset = configuration_->commonHeight_ - fontDef->yOffset; + fontChar.positionInPixels = ccp( (float)nextFontPositionX + fontDef->xOffset + fontDef->rect.size.width*0.5f + kerningAmount, (float)nextFontPositionY + yOffset - rect.size.height*0.5f ); + + // update kerning + nextFontPositionX += fontDef->xAdvance + kerningAmount; + prev = c; + + // Apply label properties + [fontChar setOpacityModifyRGB:opacityModifyRGB_]; + // Color MUST be set before opacity, since opacity might change color if OpacityModifyRGB is on + [fontChar setColor:color_]; + + // only apply opacity if it is different than 255 ) + // to prevent modifying the color too (issue #610) + if( opacity_ != 255 ) + [fontChar setOpacity: opacity_]; + + if (longestLine < nextFontPositionX) + longestLine = nextFontPositionX; + + tmpSize.width = longestLine; + tmpSize.height = totalHeight; + + [self setContentSizeInPixels:tmpSize]; + } + } } -#pragma mark BitmapFontAtlas - CCLabelProtocol protocol +#pragma mark LabelBMFont - CCLabelProtocol protocol - (void) setString:(NSString*) newString -{ - [string_ release]; - string_ = [newString copy]; - - CCNode *child; - CCARRAY_FOREACH(children_, child) - child.visible = NO; +{ + [self setString:newString fromUpdate:NO]; +} +- (void) setString:(NSString*) newString fromUpdate:(bool)fromUpdate +{ + if (fromUpdate) { + [string_ release]; + string_ = [newString copy]; + } else { + [initialString_ release]; + initialString_ = [newString copy]; + } + + CCSprite *child; + CCARRAY_FOREACH(children_, child) + child.visible = NO; + [self createFontChars]; + + if (!fromUpdate) + [self updateLabel]; } -(NSString*) string @@ -611,7 +812,7 @@ -(void) setCString:(char*)label [self setString:[NSString stringWithUTF8String:label]]; } -#pragma mark BitmapFontAtlas - CCRGBAProtocol protocol +#pragma mark LabelBMFont - CCRGBAProtocol protocol -(void) setColor:(ccColor3B)color { @@ -619,16 +820,16 @@ -(void) setColor:(ccColor3B)color CCSprite *child; CCARRAY_FOREACH(children_, child) - [child setColor:color_]; + [child setColor:color_]; } -(void) setOpacity:(GLubyte)opacity { opacity_ = opacity; - + id child; CCARRAY_FOREACH(children_, child) - [child setOpacity:opacity_]; + [child setOpacity:opacity_]; } -(void) setOpacityModifyRGB:(BOOL)modify { @@ -636,7 +837,7 @@ -(void) setOpacityModifyRGB:(BOOL)modify id child; CCARRAY_FOREACH(children_, child) - [child setOpacityModifyRGB:modify]; + [child setOpacityModifyRGB:modify]; } -(BOOL) doesOpacityModifyRGB @@ -644,7 +845,7 @@ -(BOOL) doesOpacityModifyRGB return opacityModifyRGB_; } -#pragma mark BitmapFontAtlas - AnchorPoint +#pragma mark LabelBMFont - AnchorPoint -(void) setAnchorPoint:(CGPoint)point { if( ! CGPointEqualToPoint(point, anchorPoint_) ) { @@ -653,11 +854,23 @@ -(void) setAnchorPoint:(CGPoint)point } } -#pragma mark BitmapFontAtlas - Debug draw -#if CC_BITMAPFONTATLAS_DEBUG_DRAW +#pragma mark LabelBMFont - Alignment +- (void)setWidth:(float)width { + width_ = width; + [self updateLabel]; +} + +- (void)setAlignment:(CCTextAlignment)alignment { + alignment_ = alignment; + [self updateLabel]; +} + +#pragma mark LabelBMFont - Debug draw +#if CC_LABELBMFONT_DEBUG_DRAW -(void) draw { [super draw]; + CGSize s = [self contentSize]; CGPoint vertices[4]={ ccp(0,0),ccp(s.width,0), @@ -665,5 +878,5 @@ -(void) draw }; ccDrawPoly(vertices, 4, YES); } -#endif // CC_BITMAPFONTATLAS_DEBUG_DRAW +#endif // CC_LABELBMFONT_DEBUG_DRAW @end diff --git a/libs/cocos2d/CCLabelTTF.h b/libs/cocos2d/CCLabelTTF.h index 66cdda7..8e48ce1 100644 --- a/libs/cocos2d/CCLabelTTF.h +++ b/libs/cocos2d/CCLabelTTF.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,7 +34,7 @@ * * All features from CCTextureNode are valid in CCLabel * - * CCLabel objects are slow. Consider using CCLabelAtlas or CCBitmapFontAtlas instead. + * CCLabel objects are slow. Consider using CCLabelAtlas or CCLabelBMFont instead. */ @interface CCLabelTTF : CCSprite @@ -42,13 +43,28 @@ CCTextAlignment alignment_; NSString * fontName_; CGFloat fontSize_; + CCLineBreakMode lineBreakMode_; NSString *string_; } +/** creates a CCLabel from a fontname, alignment, dimension in points, line break mode, and font size in points. + Supported lineBreakModes: + - iOS: all UILineBreakMode supported modes + - Mac: Only NSLineBreakByWordWrapping is supported. + @since v1.0 + */ ++ (id) labelWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode fontName:(NSString*)name fontSize:(CGFloat)size; /** creates a CCLabel from a fontname, alignment, dimension in points and font size in points*/ + (id) labelWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size; /** creates a CCLabel from a fontname and font size in points*/ + (id) labelWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size; +/** initializes the CCLabel with a font name, alignment, dimension in points, line brea mode and font size in points. + Supported lineBreakModes: + - iOS: all UILineBreakMode supported modes + - Mac: Only NSLineBreakByWordWrapping is supported. + @since v1.0 + */ +- (id) initWithString:(NSString*)str dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode fontName:(NSString*)name fontSize:(CGFloat)size; /** initializes the CCLabel with a font name, alignment, dimension in points and font size in points */ - (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size; /** initializes the CCLabel with a font name and font size in points */ diff --git a/libs/cocos2d/CCLabelTTF.m b/libs/cocos2d/CCLabelTTF.m index 5760a20..e20124b 100644 --- a/libs/cocos2d/CCLabelTTF.m +++ b/libs/cocos2d/CCLabelTTF.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -43,6 +44,11 @@ - (id) init return nil; } ++ (id) labelWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode fontName:(NSString*)name fontSize:(CGFloat)size; +{ + return [[[self alloc] initWithString: string dimensions:dimensions alignment:alignment lineBreakMode:lineBreakMode fontName:name fontSize:size]autorelease]; +} + + (id) labelWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size { return [[[self alloc] initWithString: string dimensions:dimensions alignment:alignment fontName:name fontSize:size]autorelease]; @@ -54,7 +60,7 @@ + (id) labelWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFl } -- (id) initWithString:(NSString*)str dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size +- (id) initWithString:(NSString*)str dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode fontName:(NSString*)name fontSize:(CGFloat)size { if( (self=[super init]) ) { @@ -62,12 +68,18 @@ - (id) initWithString:(NSString*)str dimensions:(CGSize)dimensions alignment:(CC alignment_ = alignment; fontName_ = [name retain]; fontSize_ = size * CC_CONTENT_SCALE_FACTOR(); + lineBreakMode_ = lineBreakMode; [self setString:str]; } return self; } +- (id) initWithString:(NSString*)str dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size +{ + return [self initWithString:str dimensions:dimensions alignment:alignment lineBreakMode:CCLineBreakModeWordWrap fontName:name fontSize:size]; +} + - (id) initWithString:(NSString*)str fontName:(NSString*)name fontSize:(CGFloat)size { if( (self=[super init]) ) { @@ -95,9 +107,27 @@ - (void) setString:(NSString*)str tex = [[CCTexture2D alloc] initWithString:str dimensions:dimensions_ alignment:alignment_ + lineBreakMode:lineBreakMode_ fontName:fontName_ fontSize:fontSize_]; +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) { + if( CC_CONTENT_SCALE_FACTOR() == 2 ) + [tex setResolutionType:kCCResolutioniPadRetinaDisplay]; + else + [tex setResolutionType:kCCResolutioniPad]; + } + // iPhone ? + else + { + if( CC_CONTENT_SCALE_FACTOR() == 2 ) + [tex setResolutionType:kCCResolutioniPhoneRetinaDisplay]; + else + [tex setResolutionType:kCCResolutioniPhone]; + } +#endif + [self setTexture:tex]; [tex release]; @@ -115,11 +145,14 @@ - (void) dealloc { [string_ release]; [fontName_ release]; + [super dealloc]; } - (NSString*) description { - return [NSString stringWithFormat:@"<%@ = %08X | FontName = %@, FontSize = %.1f>", [self class], self, fontName_, fontSize_]; + // XXX: string_, fontName_ can't be displayed here, since they might be already released + + return [NSString stringWithFormat:@"<%@ = %08X | FontSize = %.1f>", [self class], self, fontSize_]; } @end diff --git a/libs/cocos2d/CCLayer.h b/libs/cocos2d/CCLayer.h index 9c02f37..3082a70 100644 --- a/libs/cocos2d/CCLayer.h +++ b/libs/cocos2d/CCLayer.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -36,9 +37,9 @@ #import "CCProtocols.h" #import "CCNode.h" -// -// CCLayer -// +#pragma mark - +#pragma mark CCLayer + /** CCLayer is a subclass of CCNode that implements the TouchEventsDelegate protocol. All features from CCNode are valid, plus the following new features: @@ -70,7 +71,7 @@ You can enable / disable touch events with this property. Only the touches of this node will be affected. This "method" is not propagated to it's children. - Valid only on iOS. Not valid on Mac. + Valid on iOS and Mac OS X v10.6 and later. @since v0.8.1 */ @@ -87,10 +88,11 @@ #elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) -@interface CCLayer : CCNode +@interface CCLayer : CCNode { BOOL isMouseEnabled_; BOOL isKeyboardEnabled_; + BOOL isTouchEnabled_; } /** whether or not it will receive mouse events. @@ -105,6 +107,12 @@ */ @property (nonatomic, readwrite) BOOL isKeyboardEnabled; +/** whether or not it will receive touch events. + + Valid on iOS and Mac OS X v10.6 and later. + */ +@property (nonatomic, readwrite) BOOL isTouchEnabled; + /** priority of the mouse event delegate. Default 0. Override this method to set another priority. @@ -121,14 +129,22 @@ */ -(NSInteger) keyboardDelegatePriority; +/** priority of the touch event delegate. + Default 0. + Override this method to set another priority. + + Valind only Mac. Not valid on iOS + */ +-(NSInteger) touchDelegatePriority; + #endif // mac @end -// -// CCLayerColor -// +#pragma mark - +#pragma mark CCLayerColor + /** CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol. All features from CCLayer are valid, plus the following new features: @@ -139,8 +155,8 @@ { GLubyte opacity_; ccColor3B color_; - GLfloat squareVertices[4 * 2]; - GLubyte squareColors[4 * 4]; + ccVertex2F squareVertices_[4]; + ccColor4B squareColors_[4]; ccBlendFunc blendFunc_; } @@ -150,7 +166,9 @@ /** creates a CCLayer with color. Width and height are the window size. */ + (id) layerWithColor: (ccColor4B)color; -/** initializes a CCLayer with color, width and height in Points */ +/** initializes a CCLayer with color, width and height in Points. + This is the designated initializer. + */ - (id) initWithColor:(ccColor4B)color width:(GLfloat)w height:(GLfloat)h; /** initializes a CCLayer with color. Width and height are the window size. */ - (id) initWithColor:(ccColor4B)color; @@ -172,34 +190,27 @@ @property (nonatomic,readwrite) ccBlendFunc blendFunc; @end -/** CCColorLayer - It is the same as CCLayerColor. - - @deprecated Use CCLayerColor instead. This class will be removed in v1.0.1 - */ -DEPRECATED_ATTRIBUTE @interface CCColorLayer : CCLayerColor -@end - +#pragma mark - +#pragma mark CCLayerGradient -// -// CCLayerGradient -// /** CCLayerGradient is a subclass of CCLayerColor that draws gradients across the background. All features from CCLayerColor are valid, plus the following new features: - direction - final color + - interpolation mode Color is interpolated between the startColor and endColor along the given vector (starting at the origin, ending at the terminus). If no vector is supplied, it defaults to (0, -1) -- a fade from top to bottom. - Given the nature of - the interpolation, you will not see either the start or end color for + If 'compressedInterpolation' is disabled, you will not see either the start or end color for non-cardinal vectors; a smooth gradient implying both end points will be still be drawn, however. + If ' compressedInterpolation' is enabled (default mode) you will see both the start and end colors of the gradient. + @since v0.99.5 */ @interface CCLayerGradient : CCLayerColor @@ -208,6 +219,7 @@ the background. GLubyte startOpacity_; GLubyte endOpacity_; CGPoint vector_; + BOOL compressedInterpolation_; } /** Creates a full-screen CCLayer with a gradient between start and end. */ @@ -221,9 +233,7 @@ the background. - (id) initWithColor: (ccColor4B) start fadingTo: (ccColor4B) end alongVector: (CGPoint) v; /** The starting color. */ -- (ccColor3B) startColor; -- (void) setStartColor:(ccColor3B)colors; - +@property (nonatomic, readwrite) ccColor3B startColor; /** The ending color. */ @property (nonatomic, readwrite) ccColor3B endColor; /** The starting opacity. */ @@ -232,18 +242,25 @@ the background. @property (nonatomic, readwrite) GLubyte endOpacity; /** The vector along which to fade color. */ @property (nonatomic, readwrite) CGPoint vector; - +/** Whether or not the interpolation will be compressed in order to display all the colors of the gradient both in canonical and non canonical vectors + Default: YES + */ +@property (nonatomic, readwrite) BOOL compressedInterpolation; + @end -/** CCMultipleLayer is a CCLayer with the ability to multiplex it's children. +#pragma mark - +#pragma mark CCLayerMultiplex + +/** CCLayerMultiplex is a CCLayer with the ability to multiplex it's children. Features: - It supports one or more children - Only one children will be active a time */ -@interface CCMultiplexLayer : CCLayer +@interface CCLayerMultiplex : CCLayer { - unsigned int enabledLayer; - NSMutableArray *layers; + unsigned int enabledLayer_; + NSMutableArray *layers_; } /** creates a CCMultiplexLayer with one or more layers using a variable argument list. */ @@ -259,3 +276,4 @@ the background. */ -(void) switchToAndReleaseMe: (unsigned int) n; @end + diff --git a/libs/cocos2d/CCLayer.m b/libs/cocos2d/CCLayer.m index 6604bb8..4ae5665 100644 --- a/libs/cocos2d/CCLayer.m +++ b/libs/cocos2d/CCLayer.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -55,8 +56,9 @@ -(id) init [self setContentSize:s]; self.isRelativeAnchorPoint = NO; -#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED isTouchEnabled_ = NO; + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED isAccelerometerEnabled_ = NO; #elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) isMouseEnabled_ = NO; @@ -113,7 +115,7 @@ -(void) setIsTouchEnabled:(BOOL)enabled #elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) -#pragma mark CCLayer - Mouse & Keyboard events +#pragma mark CCLayer - Mouse, Keyboard & Touch events -(NSInteger) mouseDelegatePriority { @@ -163,6 +165,29 @@ -(void) setIsKeyboardEnabled:(BOOL)enabled } } +-(NSInteger) touchDelegatePriority +{ + return 0; +} + +-(BOOL) isTouchEnabled +{ + return isTouchEnabled_; +} + +-(void) setIsTouchEnabled:(BOOL)enabled +{ + if( isTouchEnabled_ != enabled ) { + isTouchEnabled_ = enabled; + if( isRunning_ ) { + if( enabled ) + [[CCEventDispatcher sharedDispatcher] addTouchDelegate:self priority:[self touchDelegatePriority]]; + else + [[CCEventDispatcher sharedDispatcher] removeTouchDelegate:self]; + } + } +} + #endif // Mac @@ -182,6 +207,10 @@ -(void) onEnter if( isKeyboardEnabled_) [[CCEventDispatcher sharedDispatcher] addKeyboardDelegate:self priority:[self keyboardDelegatePriority]]; + + if( isTouchEnabled_) + [[CCEventDispatcher sharedDispatcher] addTouchDelegate:self priority:[self touchDelegatePriority]]; + #endif // then iterate over all the children @@ -216,6 +245,10 @@ -(void) onExit if( isKeyboardEnabled_ ) [[CCEventDispatcher sharedDispatcher] removeKeyboardDelegate:self]; + + if( isTouchEnabled_ ) + [[CCEventDispatcher sharedDispatcher] removeTouchDelegate:self]; + #endif [super onExit]; @@ -254,6 +287,13 @@ + (id) layerWithColor:(ccColor4B)color return [[(CCLayerColor*)[self alloc] initWithColor:color] autorelease]; } +-(id) init +{ + CGSize s = [[CCDirector sharedDirector] winSize]; + return [self initWithColor:ccc4(0,0,0,0) width:s.width height:s.height]; +} + +// Designated initializer - (id) initWithColor:(ccColor4B)color width:(GLfloat)w height:(GLfloat) h { if( (self=[super init]) ) { @@ -266,8 +306,10 @@ - (id) initWithColor:(ccColor4B)color width:(GLfloat)w height:(GLfloat) h color_.b = color.b; opacity_ = color.a; - for (NSUInteger i = 0; i= rowColumns) { diff --git a/libs/cocos2d/CCMenuItem.h b/libs/cocos2d/CCMenuItem.h index ca07b5e..2437394 100644 --- a/libs/cocos2d/CCMenuItem.h +++ b/libs/cocos2d/CCMenuItem.h @@ -1,7 +1,8 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2008-2011 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,15 +31,17 @@ @class CCSprite; -#define kItemSize 32 +#define kCCItemSize 32 +#pragma mark - +#pragma mark CCMenuItem /** CCMenuItem base class * * Subclass CCMenuItem (or any subclass) to create your custom CCMenuItem objects. */ @interface CCMenuItem : CCNode { - NSInvocation *invocation; + NSInvocation *invocation_; #if NS_BLOCKS_AVAILABLE // used for menu items using a block void (^block_)(id sender); @@ -89,6 +92,9 @@ -(BOOL) isEnabled; @end +#pragma mark - +#pragma mark CCMenuItemLabel + /** An abstract class for "label" CCMenuItemLabel items Any CCNode that supports the CCLabelProtocol protocol can be added. Supported nodes: @@ -110,6 +116,9 @@ /** Label that is rendered. It can be any CCNode that implements the CCLabelProtocol */ @property (nonatomic,readwrite,assign) CCNode* label; +/** creates a CCMenuItemLabel with a Label. Target and selector will be nill */ ++(id) itemWithLabel:(CCNode*)label; + /** creates a CCMenuItemLabel with a Label, target and selector */ +(id) itemWithLabel:(CCNode*)label target:(id)target selector:(SEL)selector; @@ -137,6 +146,9 @@ -(void) setIsEnabled: (BOOL)enabled; @end +#pragma mark - +#pragma mark CCMenuItemAtlasFont + /** A CCMenuItemAtlasFont Helper class that creates a MenuItemLabel class with a LabelAtlas */ @@ -167,22 +179,27 @@ @end +#pragma mark - +#pragma mark CCMenuItemFont + /** A CCMenuItemFont Helper class that creates a CCMenuItemLabel class with a Label */ @interface CCMenuItemFont : CCMenuItemLabel { + NSUInteger fontSize_; + NSString *fontName_; } -/** set font size */ -+(void) setFontSize: (int) s; +/** set default font size */ ++(void) setFontSize: (NSUInteger) s; -/** get font size */ -+(int) fontSize; +/** get default font size */ ++(NSUInteger) fontSize; -/** set the font name */ +/** set default font name */ +(void) setFontName: (NSString*) n; -/** get the font name */ +/** get default font name */ +(NSString*) fontName; /** creates a menu item from a string without target/selector. To be used with CCMenuItemToggle */ @@ -194,6 +211,18 @@ /** initializes a menu item from a string with a target/selector */ -(id) initFromString: (NSString*) value target:(id) r selector:(SEL) s; +/** set font size */ +-(void) setFontSize: (NSUInteger) s; + +/** get font size */ +-(NSUInteger) fontSize; + +/** set the font name */ +-(void) setFontName: (NSString*) n; + +/** get the font name */ +-(NSString*) fontName; + #if NS_BLOCKS_AVAILABLE /** creates a menu item from a string with the specified block. The block will be "copied". @@ -207,6 +236,9 @@ #endif @end +#pragma mark - +#pragma mark CCMenuItemSprite + /** CCMenuItemSprite accepts CCNode objects as items. The images has 3 different states: - unselected image @@ -255,6 +287,9 @@ @end +#pragma mark - +#pragma mark CCMenuItemImage + /** CCMenuItemImage accepts images as items. The images has 3 different states: - unselected image @@ -291,7 +326,8 @@ #endif @end - +#pragma mark - +#pragma mark CCMenuItemToggle /** A CCMenuItemToggle A simple container class that "toggles" it's inner items diff --git a/libs/cocos2d/CCMenuItem.m b/libs/cocos2d/CCMenuItem.m index 304702e..c371f8c 100644 --- a/libs/cocos2d/CCMenuItem.m +++ b/libs/cocos2d/CCMenuItem.m @@ -1,7 +1,8 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2008-2011 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,19 +30,15 @@ #import "CCActionInterval.h" #import "CCSprite.h" #import "Support/CGPointExtension.h" +#import "CCBlockSupport.h" -static int _fontSize = kItemSize; + static NSUInteger _fontSize = kCCItemSize; static NSString *_fontName = @"Marker Felt"; static BOOL _fontNameRelease = NO; -enum { - kCurrentItem = 0xc0c05001, -}; - -enum { - kZoomActionTag = 0xc0c05002, -}; +const uint32_t kCurrentItem = 0xc0c05001; +const uint32_t kZoomActionTag = 0xc0c05002; #pragma mark - @@ -72,16 +69,16 @@ -(id) initWithTarget:(id) rec selector:(SEL) cb if( rec && cb ) { sig = [rec methodSignatureForSelector:cb]; - invocation = nil; - invocation = [NSInvocation invocationWithMethodSignature:sig]; - [invocation setTarget:rec]; - [invocation setSelector:cb]; + invocation_ = nil; + invocation_ = [NSInvocation invocationWithMethodSignature:sig]; + [invocation_ setTarget:rec]; + [invocation_ setSelector:cb]; #if NS_BLOCKS_AVAILABLE if ([sig numberOfArguments] == 3) #endif - [invocation setArgument:&self atIndex:2]; + [invocation_ setArgument:&self atIndex:2]; - [invocation retain]; + [invocation_ retain]; } isEnabled_ = YES; @@ -106,7 +103,7 @@ -(id) initWithBlock:(void(^)(id sender))block { -(void) dealloc { - [invocation release]; + [invocation_ release]; #if NS_BLOCKS_AVAILABLE [block_ release]; @@ -128,7 +125,7 @@ -(void) unselected -(void) activate { if(isEnabled_) - [invocation invoke]; + [invocation_ invoke]; } -(void) setIsEnabled: (BOOL)enabled @@ -163,6 +160,11 @@ +(id) itemWithLabel:(CCNode*)label target:(id)ta return [[[self alloc] initWithLabel:label target:target selector:selector] autorelease]; } ++(id) itemWithLabel:(CCNode*)label +{ + return [[[self alloc] initWithLabel:label target:nil selector:NULL] autorelease]; +} + -(id) initWithLabel:(CCNode*)label target:(id)target selector:(SEL)selector { if( (self=[super initWithTarget:target selector:selector]) ) { @@ -226,8 +228,13 @@ -(void) selected // subclass to change the default action if(isEnabled_) { [super selected]; - [self stopActionByTag:kZoomActionTag]; - originalScale_ = self.scale; + + CCAction *action = [self getActionByTag:kZoomActionTag]; + if( action ) + [self stopAction:action]; + else + originalScale_ = self.scale; + CCAction *zoomAction = [CCScaleTo actionWithDuration:0.1f scale:originalScale_ * 1.2f]; zoomAction.tag = kZoomActionTag; [self runAction:zoomAction]; @@ -330,12 +337,12 @@ -(void) dealloc @implementation CCMenuItemFont -+(void) setFontSize: (int) s ++(void) setFontSize: (NSUInteger) s { _fontSize = s; } -+(int) fontSize ++(NSUInteger) fontSize { return _fontSize; } @@ -368,7 +375,10 @@ -(id) initFromString: (NSString*) value target:(id) rec selector:(SEL) cb { NSAssert( [value length] != 0, @"Value length must be greater than 0"); - CCLabelTTF *label = [CCLabelTTF labelWithString:value fontName:_fontName fontSize:_fontSize]; + fontName_ = [_fontName copy]; + fontSize_ = _fontSize; + + CCLabelTTF *label = [CCLabelTTF labelWithString:value fontName:fontName_ fontSize:fontSize_]; if((self=[super initWithLabel:label target:rec selector:cb]) ) { // do something ? @@ -377,12 +387,45 @@ -(id) initFromString: (NSString*) value target:(id) rec selector:(SEL) cb return self; } +-(void) recreateLabel +{ + CCLabelTTF *label = [CCLabelTTF labelWithString:[label_ string] fontName:fontName_ fontSize:fontSize_]; + self.label = label; +} + +-(void) setFontSize: (NSUInteger) size +{ + fontSize_ = size; + [self recreateLabel]; +} + +-(NSUInteger) fontSize +{ + return fontSize_; +} + +-(void) setFontName: (NSString*) fontName +{ + if (fontName_) + [fontName_ release]; + + fontName_ = [fontName copy]; + [self recreateLabel]; +} + +-(NSString*) fontName +{ + return fontName_; +} + #if NS_BLOCKS_AVAILABLE -+(id) itemFromString: (NSString*) value block:(void(^)(id sender))block { ++(id) itemFromString: (NSString*) value block:(void(^)(id sender))block +{ return [[[self alloc] initFromString:value block:block] autorelease]; } --(id) initFromString: (NSString*) value block:(void(^)(id sender))block { +-(id) initFromString: (NSString*) value block:(void(^)(id sender))block +{ block_ = [block copy]; return [self initFromString:value target:block_ selector:@selector(ccCallbackBlockWithSender:)]; } @@ -680,7 +723,10 @@ -(void)setSelectedIndex:(NSUInteger)index { if( index != selectedIndex_ ) { selectedIndex_=index; - [self removeChildByTag:kCurrentItem cleanup:NO]; + CCMenuItem *currentItem = (CCMenuItem*)[self getChildByTag:kCurrentItem]; + if( currentItem ) { + [currentItem removeFromParentAndCleanup:NO]; + } CCMenuItem *item = [subItems_ objectAtIndex:selectedIndex_]; [self addChild:item z:0 tag:kCurrentItem]; diff --git a/libs/cocos2d/CCMotionStreak.m b/libs/cocos2d/CCMotionStreak.m index 698cc59..42737b9 100644 --- a/libs/cocos2d/CCMotionStreak.m +++ b/libs/cocos2d/CCMotionStreak.m @@ -54,8 +54,8 @@ -(id)initWithFade:(float)fade minSeg:(float)seg image:(NSString*)path width:(flo ribbon_ = [CCRibbon ribbonWithWidth:width_ image:path length:length color:color fade:fade]; [self addChild:ribbon_]; - // update ribbon position - [self scheduleUpdate]; + // update ribbon position. Use schedule:interval and not scheduleUpdated. issue #1075 + [self schedule:@selector(update:) interval:0]; } return self; } diff --git a/libs/cocos2d/CCNode.h b/libs/cocos2d/CCNode.h index d6faaf5..353c3bd 100644 --- a/libs/cocos2d/CCNode.h +++ b/libs/cocos2d/CCNode.h @@ -1,8 +1,10 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2008-2010 Ricardo Quesada * Copyright (c) 2009 Valentin Milea + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -105,6 +107,9 @@ enum { // position of the node CGPoint position_; CGPoint positionInPixels_; + + // skew angles + float skewX_, skewY_; // is visible BOOL visible_; @@ -154,10 +159,14 @@ enum { // Is running BOOL isRunning_; + + //used to preserve sequence while sorting children with the same zOrder + NSUInteger orderOfArrival_; // To reduce memory, place BOOLs that are not properties here: BOOL isTransformDirty_:1; BOOL isInverseDirty_:1; + BOOL isReorderChildDirty_:1; #if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX BOOL isTransformGLDirty_:1; #endif @@ -174,6 +183,20 @@ enum { @since v0.8 */ @property (nonatomic,readwrite) float vertexZ; + +/** The X skew angle of the node in degrees. + This angle describes the shear distortion in the X direction. + Thus, it is the angle between the Y axis and the left edge of the shape + The default skewX angle is 0. Positive values distort the node in a CW direction. + */ +@property(nonatomic,readwrite,assign) float skewX; + +/** The Y skew angle of the node in degrees. + This angle describes the shear distortion in the Y direction. + Thus, it is the angle between the X axis and the bottom edge of the shape + The default skewY angle is 0. Positive values distort the node in a CCW direction. + */ +@property(nonatomic,readwrite,assign) float skewY; /** The rotation (angle) of the node in degrees. 0 is the default rotation angle. Positive values rotate node CW. */ @property(nonatomic,readwrite,assign) float rotation; /** The scale factor of the node. 1.0 is the default scale factor. It modifies the X and Y scale at the same time. */ @@ -236,6 +259,9 @@ enum { /** A custom user data pointer */ @property(nonatomic,readwrite,assign) void *userData; +/** used internally for zOrder sorting, don't change this manually */ +@property(nonatomic,readwrite) NSUInteger orderOfArrival; + // initializators /** allocates and initializes a node. The node will be created as "autorelease". @@ -259,10 +285,14 @@ enum { -(void) onEnterTransitionDidFinish; /** callback that is called every time the CCNode leaves the 'stage'. If the CCNode leaves the 'stage' with a transition, this callback is called when the transition finishes. - During onExit you can't a "sister/brother" node. + During onExit you can't access a sibling node. */ -(void) onExit; +/** callback that is called every time the CCNode leaves the 'stage'. + If the CCNode leaves the 'stage' with a transition, this callback is called when the transition starts. + */ +-(void) onExitTransitionDidStart; // composition: ADD @@ -276,13 +306,13 @@ enum { If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately. @since v0.7.1 */ --(void) addChild: (CCNode*)node z:(int)z; +-(void) addChild: (CCNode*)node z:(NSInteger)z; /** Adds a child to the container with z order and tag. If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately. @since v0.7.1 */ --(void) addChild: (CCNode*)node z:(int)z tag:(int)tag; +-(void) addChild: (CCNode*)node z:(NSInteger)z tag:(NSInteger)tag; // composition: REMOVE @@ -300,7 +330,7 @@ enum { /** Removes a child from the container by tag value. It will also cleanup all running actions depending on the cleanup parameter @since v0.7.1 */ --(void) removeChildByTag:(int) tag cleanup:(BOOL)cleanup; +-(void) removeChildByTag:(NSInteger) tag cleanup:(BOOL)cleanup; /** Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter. @since v0.7.1 @@ -312,12 +342,16 @@ enum { @return returns a CCNode object @since v0.7.1 */ --(CCNode*) getChildByTag:(int) tag; +-(CCNode*) getChildByTag:(NSInteger) tag; /** Reorders a child according to a new z value. * The child MUST be already added. */ --(void) reorderChild:(CCNode*)child z:(int)zOrder; +-(void) reorderChild:(CCNode*)child z:(NSInteger)zOrder; + +/** performance improvement, Sort the children array once before drawing, instead of every time when a child is added or reordered + don't call this manually unless a child added needs to be removed in the same frame */ +- (void) sortAllChildren; /** Stops all running actions and schedulers @since v0.8 @@ -386,18 +420,18 @@ enum { /** Removes an action from the running action list given its tag @since v0.7.1 */ --(void) stopActionByTag:(int) tag; +-(void) stopActionByTag:(NSInteger) tag; /** Gets an action from the running action list given its tag @since v0.7.1 @return the Action the with the given tag */ --(CCAction*) getActionByTag:(int) tag; +-(CCAction*) getActionByTag:(NSInteger) tag; /** Returns the numbers of actions that are running plus the ones that are schedule to run (actions in actionsToAdd and actions arrays). * Composable actions are counted as 1 action. Example: * If you are running 1 Sequence of 7 actions, it will return 1. * If you are running 7 Sequences of 2 actions, it will return 7. */ --(int) numberOfRunningActions; +-(NSUInteger) numberOfRunningActions; // timers @@ -418,7 +452,7 @@ enum { @since v0.99.3 */ --(void) scheduleUpdateWithPriority:(int)priority; +-(void) scheduleUpdateWithPriority:(NSInteger)priority; /* unschedules the "update" method. @@ -438,6 +472,17 @@ enum { If the selector is already scheduled, then the interval parameter will be updated without scheduling it again. */ -(void) schedule: (SEL) s interval:(ccTime)seconds; +/** + repeat will execute the action repeat + 1 times, for a continues action use kCCRepeatForever + delay is the amount of time the action will wait before execution + */ +-(void) schedule:(SEL)selector interval:(ccTime)interval repeat: (uint) repeat delay:(ccTime) delay; + +/** + Schedules a selector that runs only once, with a delay of 0 or larger +*/ +- (void) scheduleOnce:(SEL) selector delay:(ccTime) delay; + /** unschedules a custom selector.*/ -(void) unschedule: (SEL) s; diff --git a/libs/cocos2d/CCNode.m b/libs/cocos2d/CCNode.m index 5392905..3daf0bf 100644 --- a/libs/cocos2d/CCNode.m +++ b/libs/cocos2d/CCNode.m @@ -1,8 +1,10 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2008-2010 Ricardo Quesada * Copyright (c) 2009 Valentin Milea + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -48,13 +50,16 @@ #define RENDER_IN_SUBPIXEL (NSInteger) #endif +// XXX: Yes, nodes might have a sort problem once per year +static NSUInteger globalOrderOfArrival = 0; + @interface CCNode () // lazy allocs -(void) childrenAlloc; // helper that reorder a child --(void) insertChild:(CCNode*)child z:(int)z; +-(void) insertChild:(CCNode*)child z:(NSInteger)z; // used internally to alter the zOrder variable. DON'T call this method manually --(void) _setZOrder:(int) z; +-(void) _setZOrder:(NSInteger) z; -(void) detachChild:(CCNode *)child cleanup:(BOOL)doCleanup; @end @@ -69,16 +74,37 @@ @implementation CCNode @synthesize vertexZ = vertexZ_; @synthesize isRunning = isRunning_; @synthesize userData = userData_; +@synthesize orderOfArrival = orderOfArrival_; #pragma mark CCNode - Transform related properties @synthesize rotation = rotation_, scaleX = scaleX_, scaleY = scaleY_; +@synthesize skewX = skewX_, skewY = skewY_; @synthesize position = position_, positionInPixels = positionInPixels_; @synthesize anchorPoint = anchorPoint_, anchorPointInPixels = anchorPointInPixels_; @synthesize contentSize = contentSize_, contentSizeInPixels = contentSizeInPixels_; @synthesize isRelativeAnchorPoint = isRelativeAnchorPoint_; // getters synthesized, setters explicit + +-(void) setSkewX:(float)newSkewX +{ + skewX_ = newSkewX; + isTransformDirty_ = isInverseDirty_ = YES; +#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX + isTransformGLDirty_ = YES; +#endif +} + +-(void) setSkewY:(float)newSkewY +{ + skewY_ = newSkewY; + isTransformDirty_ = isInverseDirty_ = YES; +#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX + isTransformGLDirty_ = YES; +#endif +} + -(void) setRotation: (float)newRotation { rotation_ = newRotation; @@ -209,6 +235,11 @@ -(void) setVertexZ:(float)vertexZ vertexZ_ = vertexZ * CC_CONTENT_SCALE_FACTOR(); } +-(float) vertexZ +{ + return vertexZ_ / CC_CONTENT_SCALE_FACTOR(); +} + -(float) scale { NSAssert( scaleX_ == scaleY_, @"CCNode#scale. ScaleX != ScaleY. Don't know which one to return"); @@ -237,6 +268,7 @@ -(id) init isRunning_ = NO; + skewX_ = skewY_ = 0.0f; rotation_ = 0.0f; scaleX_ = scaleY_ = 1.0f; positionInPixels_ = position_ = CGPointZero; @@ -251,7 +283,7 @@ -(id) init #if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX isTransformGLDirty_ = YES; #endif - + isReorderChildDirty_ = NO; vertexZ_ = 0; grid_ = nil; @@ -273,6 +305,8 @@ -(id) init //initialize parent to nil parent_ = nil; + + orderOfArrival_=0; } return self; @@ -337,7 +371,7 @@ -(CCCamera*) camera return camera_; } --(CCNode*) getChildByTag:(int) aTag +-(CCNode*) getChildByTag:(NSInteger) aTag { NSAssert( aTag != kCCNodeTagInvalid, @"Invalid tag"); @@ -354,7 +388,7 @@ -(CCNode*) getChildByTag:(int) aTag * If a class want's to extend the 'addChild' behaviour it only needs * to override this method */ --(void) addChild: (CCNode*) child z:(int)z tag:(int) aTag +-(void) addChild: (CCNode*) child z:(NSInteger)z tag:(NSInteger) aTag { NSAssert( child != nil, @"Argument must be non-nil"); NSAssert( child.parent == nil, @"child already added. It can't be added again"); @@ -368,13 +402,16 @@ -(void) addChild: (CCNode*) child z:(int)z tag:(int) aTag [child setParent: self]; + //CCDirector.sharedDirector->getorderOfArrival + [child setOrderOfArrival: globalOrderOfArrival++]; + if( isRunning_ ) { [child onEnter]; [child onEnterTransitionDidFinish]; } } --(void) addChild: (CCNode*) child z:(int)z +-(void) addChild: (CCNode*) child z:(NSInteger)z { NSAssert( child != nil, @"Argument must be non-nil"); [self addChild:child z:z tag:child.tag]; @@ -405,7 +442,7 @@ -(void) removeChild: (CCNode*)child cleanup:(BOOL)cleanup [self detachChild:child cleanup:cleanup]; } --(void) removeChildByTag:(int)aTag cleanup:(BOOL)cleanup +-(void) removeChildByTag:(NSInteger)aTag cleanup:(BOOL)cleanup { NSAssert( aTag != kCCNodeTagInvalid, @"Invalid tag"); @@ -427,7 +464,10 @@ -(void) removeAllChildrenWithCleanup:(BOOL)cleanup // -1st do onExit // -2nd cleanup if (isRunning_) + { + [c onExitTransitionDidStart]; [c onExit]; + } if (cleanup) [c cleanup]; @@ -445,7 +485,10 @@ -(void) detachChild:(CCNode *)child cleanup:(BOOL)doCleanup // -1st do onExit // -2nd cleanup if (isRunning_) + { + [child onExitTransitionDidStart]; [child onExit]; + } // If you don't do cleanup, the child's actions will not get removed and the // its scheduledSelectors_ dict will not get released! @@ -459,45 +502,56 @@ -(void) detachChild:(CCNode *)child cleanup:(BOOL)doCleanup } // used internally to alter the zOrder variable. DON'T call this method manually --(void) _setZOrder:(int) z +-(void) _setZOrder:(NSInteger) z { zOrder_ = z; } // helper used by reorderChild & add --(void) insertChild:(CCNode*)child z:(int)z +-(void) insertChild:(CCNode*)child z:(NSInteger)z { - NSUInteger index=0; - CCNode *a = [children_ lastObject]; - - // quick comparison to improve performance - if (!a || a.zOrder <= z) - [children_ addObject:child]; - - else - { - CCARRAY_FOREACH(children_, a) { - if ( a.zOrder > z ) { - [children_ insertObject:child atIndex:index]; - break; - } - index++; - } - } + isReorderChildDirty_=YES; + ccArrayAppendObjectWithResize(children_->data, child); [child _setZOrder:z]; } --(void) reorderChild:(CCNode*) child z:(int)z +-(void) reorderChild:(CCNode*) child z:(NSInteger)z { NSAssert( child != nil, @"Child must be non-nil"); - [child retain]; - [children_ removeObject:child]; - - [self insertChild:child z:z]; - - [child release]; + isReorderChildDirty_=YES; + [child setOrderOfArrival: globalOrderOfArrival++]; + [child _setZOrder:z]; +} + +- (void) sortAllChildren +{ + if (isReorderChildDirty_) + { + NSInteger i,j,length=children_->data->num; + CCNode ** x=children_->data->arr; + CCNode *tempItem; + + //insertion sort + for(i=1; i=0 && ( tempItem.zOrder< x[j].zOrder || ( tempItem.zOrder == x[j].zOrder && tempItem.orderOfArrival < x[j].orderOfArrival ) ) ) + { + x[j+1] = x[j]; + j = j-1; + } + x[j+1] = tempItem; + } + + //don't need to check children recursively, that's done in visit of each child + + isReorderChildDirty_=NO; + } } #pragma mark CCNode Draw @@ -525,6 +579,7 @@ -(void) visit [self transform]; if(children_) { + [self sortAllChildren]; ccArray *arrayData = children_->data; NSUInteger i = 0; @@ -549,6 +604,8 @@ -(void) visit } else [self draw]; + orderOfArrival_=0; + if ( grid_ && grid_.active) [grid_ afterDraw:self]; @@ -618,6 +675,14 @@ -(void) transform // scale if (scaleX_ != 1.0f || scaleY_ != 1.0f) glScalef( scaleX_, scaleY_, 1.0f ); + + // skew + if ( (skewX_ != 0.0f) || (skewY_ != 0.0f) ) { + CGAffineTransform skewMatrix = CGAffineTransformMake( 1.0f, tanf(CC_DEGREES_TO_RADIANS(skewY_)), tanf(CC_DEGREES_TO_RADIANS(skewX_)), 1.0f, 0.0f, 0.0f ); + GLfloat glMatrix[16]; + CGAffineToGL(&skewMatrix, glMatrix); + glMultMatrixf(glMatrix); + } if ( camera_ && !(grid_ && grid_.active) ) [camera_ locate]; @@ -647,6 +712,11 @@ -(void) onEnterTransitionDidFinish [children_ makeObjectsPerformSelector:@selector(onEnterTransitionDidFinish)]; } +-(void) onExitTransitionDidStart +{ + [children_ makeObjectsPerformSelector:@selector(onExitTransitionDidStart)]; +} + -(void) onExit { [self pauseSchedulerAndActions]; @@ -675,19 +745,19 @@ -(void) stopAction: (CCAction*) action [[CCActionManager sharedManager] removeAction:action]; } --(void) stopActionByTag:(int)aTag +-(void) stopActionByTag:(NSInteger)aTag { NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag"); [[CCActionManager sharedManager] removeActionByTag:aTag target:self]; } --(CCAction*) getActionByTag:(int) aTag +-(CCAction*) getActionByTag:(NSInteger) aTag { NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag"); return [[CCActionManager sharedManager] getActionByTag:aTag target:self]; } --(int) numberOfRunningActions +-(NSUInteger) numberOfRunningActions { return [[CCActionManager sharedManager] numberOfRunningActionsInTarget:self]; } @@ -699,7 +769,7 @@ -(void) scheduleUpdate [self scheduleUpdateWithPriority:0]; } --(void) scheduleUpdateWithPriority:(int)priority +-(void) scheduleUpdateWithPriority:(NSInteger)priority { [[CCScheduler sharedScheduler] scheduleUpdateForTarget:self priority:priority paused:!isRunning_]; } @@ -711,15 +781,25 @@ -(void) unscheduleUpdate -(void) schedule:(SEL)selector { - [self schedule:selector interval:0]; + [self schedule:selector interval:0 repeat:kCCRepeatForever delay:0]; } -(void) schedule:(SEL)selector interval:(ccTime)interval +{ + [self schedule:selector interval:interval repeat:kCCRepeatForever delay:0]; +} + +-(void) schedule:(SEL)selector interval:(ccTime)interval repeat: (uint) repeat delay:(ccTime) delay { NSAssert( selector != nil, @"Argument must be non-nil"); NSAssert( interval >=0, @"Arguemnt must be positive"); - [[CCScheduler sharedScheduler] scheduleSelector:selector forTarget:self interval:interval paused:!isRunning_]; + [[CCScheduler sharedScheduler] scheduleSelector:selector forTarget:self interval:interval paused:!isRunning_ repeat:repeat delay:delay]; +} + +- (void) scheduleOnce:(SEL) selector delay:(ccTime) delay +{ + [self schedule:selector interval:0.f repeat:0 delay:delay]; } -(void) unschedule:(SEL)selector @@ -757,7 +837,7 @@ - (CGAffineTransform)nodeToParentTransform if ( !isRelativeAnchorPoint_ && !CGPointEqualToPoint(anchorPointInPixels_, CGPointZero) ) transform_ = CGAffineTransformTranslate(transform_, anchorPointInPixels_.x, anchorPointInPixels_.y); - + if( ! CGPointEqualToPoint(positionInPixels_, CGPointZero) ) transform_ = CGAffineTransformTranslate(transform_, positionInPixels_.x, positionInPixels_.y); @@ -766,10 +846,17 @@ - (CGAffineTransform)nodeToParentTransform if( ! (scaleX_ == 1 && scaleY_ == 1) ) transform_ = CGAffineTransformScale(transform_, scaleX_, scaleY_); + + if( skewX_ != 0 || skewY_ != 0 ) { + // create a skewed coordinate system + CGAffineTransform skew = CGAffineTransformMake(1.0f, tanf(CC_DEGREES_TO_RADIANS(skewY_)), tanf(CC_DEGREES_TO_RADIANS(skewX_)), 1.0f, 0.0f, 0.0f); + // apply the skew to the transform + transform_ = CGAffineTransformConcat(skew, transform_); + } if( ! CGPointEqualToPoint(anchorPointInPixels_, CGPointZero) ) transform_ = CGAffineTransformTranslate(transform_, -anchorPointInPixels_.x, -anchorPointInPixels_.y); - + isTransformDirty_ = NO; } diff --git a/libs/cocos2d/CCParallaxNode.h b/libs/cocos2d/CCParallaxNode.h index c41b304..5728eb1 100644 --- a/libs/cocos2d/CCParallaxNode.h +++ b/libs/cocos2d/CCParallaxNode.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -44,6 +45,6 @@ It returns self, so you can chain several addChilds. @since v0.8 */ --(void) addChild: (CCNode*)node z:(int)z parallaxRatio:(CGPoint)c positionOffset:(CGPoint)positionOffset; +-(void) addChild: (CCNode*)node z:(NSInteger)z parallaxRatio:(CGPoint)c positionOffset:(CGPoint)positionOffset; @end diff --git a/libs/cocos2d/CCParallaxNode.m b/libs/cocos2d/CCParallaxNode.m index 20f573c..d4cda39 100644 --- a/libs/cocos2d/CCParallaxNode.m +++ b/libs/cocos2d/CCParallaxNode.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,9 +34,9 @@ @interface CGPointObject : NSObject CGPoint offset_; CCNode *child_; // weak ref } -@property (readwrite) CGPoint ratio; -@property (readwrite) CGPoint offset; -@property (readwrite,assign) CCNode *child; +@property (nonatomic,readwrite) CGPoint ratio; +@property (nonatomic,readwrite) CGPoint offset; +@property (nonatomic,readwrite,assign) CCNode *child; +(id) pointWithCGPoint:(CGPoint)point offset:(CGPoint)offset; -(id) initWithCGPoint:(CGPoint)point offset:(CGPoint)offset; @end @@ -80,12 +81,12 @@ - (void) dealloc [super dealloc]; } --(void) addChild:(CCNode*)child z:(int)z tag:(int)tag +-(void) addChild:(CCNode*)child z:(NSInteger)z tag:(NSInteger)tag { NSAssert(NO,@"ParallaxNode: use addChild:z:parallaxRatio:positionOffset instead"); } --(void) addChild: (CCNode*) child z:(int)z parallaxRatio:(CGPoint)ratio positionOffset:(CGPoint)offset +-(void) addChild: (CCNode*) child z:(NSInteger)z parallaxRatio:(CGPoint)ratio positionOffset:(CGPoint)offset { NSAssert( child != nil, @"Argument must be non-nil"); CGPointObject *obj = [CGPointObject pointWithCGPoint:ratio offset:offset]; diff --git a/libs/cocos2d/CCParticleBatchNode.h b/libs/cocos2d/CCParticleBatchNode.h new file mode 100644 index 0000000..021592f --- /dev/null +++ b/libs/cocos2d/CCParticleBatchNode.h @@ -0,0 +1,130 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (C) 2009 Matt Oswald + * + * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Copyright (c) 2011 Marco Tillemans + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCNode.h" +@class CCTextureAtlas; +@class CCParticleSystem; + +//don't use lazy sorting for particle systems +@interface CCNode (extension) +-(void) setZOrder:(NSUInteger) z; +@end + +/** CCParticleBatchNode is like a batch node: if it contains children, it will draw them in 1 single OpenGL call + * (often known as "batch draw"). + * + * A CCParticleBatchNode can reference one and only one texture (one image file, one texture atlas). + * Only the CCParticleSystems that are contained in that texture can be added to the CCSpriteBatchNode. + * All CCParticleSystems added to a CCSpriteBatchNode are drawn in one OpenGL ES draw call. + * If the CCParticleSystems are not added to a CCParticleBatchNode then an OpenGL ES draw call will be needed for each one, which is less efficient. + * + * + * Limitations: + * - At the moment only CCParticleSystemQuad is supported + * - All systems need to be drawn with the same parameters, blend function, aliasing, texture + * + * Most efficient usage + * - Initialize the ParticleBatchNode with the texture and enough capacity for all the particle systems + * - Initialize all particle systems and add them as child to the batch node + * @since v1.1 + */ + +@interface CCParticleBatchNode : CCNode { + + CCTextureAtlas *textureAtlas_; + ccBlendFunc blendFunc_; + + BOOL useQuad_; //YES childs are quad particle systems, NO childs are point particle systems + + BOOL reorderDirty_; //YES if one of the childs is reordered +} + +/** the texture atlas used for drawing the quads */ +@property (nonatomic, retain) CCTextureAtlas* textureAtlas; +/** the blend function used for drawing the quads */ +@property (nonatomic, readwrite) ccBlendFunc blendFunc; + +/** initializes the particle system with CCTexture2D, a default capacity of 500, quad particle system and normal blending */ ++(id)particleBatchNodeWithTexture:(CCTexture2D *)tex; + +/** initializes the particle system with CCTexture2D, + a capacity of particles, which particle system to use and a choice between normal or additive blending +*/ ++(id)particleBatchNodeWithTexture:(CCTexture2D *)tex capacity:(NSUInteger) capacity useQuad:(BOOL) useQuad additiveBlending:(BOOL) additive; + +/** initializes the particle system with the name of a file on disk (for a list of supported formats look at the CCTexture2D class), + a default capacity of 500 particles, quad particle system and normal blending + */ ++(id)particleBatchNodeWithFile:(NSString*) imageFile; + +/** initializes the particle system with the name of a file on disk (for a list of supported formats look at the CCTexture2D class), + a capacity of particles, which particle system to use and a choice between normal or additive blending + */ ++(id)particleBatchNodeWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity useQuad:(BOOL) useQuad additiveBlending:(BOOL) additive; + +/** extracts texture data from a plist and puts the texture in the texture cache. Use it before loading the batch node */ ++(BOOL) extractTextureFromPlist:(NSString*) plistFile; + +/** initializes the particle system with CCTexture2D, + a capacity of particles, which particle system to use and a choice between normal or additive blending + */ +-(id)initWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity useQuad:(BOOL) useQuad additiveBlending:(BOOL) additive; + +/** initializes the particle system with the name of a file on disk (for a list of supported formats look at the CCTexture2D class), + a capacity of particles, which particle system to use and a choice between normal or additive blending + */ +-(id)initWithFile:(NSString *)fileImage capacity:(NSUInteger)capacity useQuad:(BOOL) useQuad additiveBlending:(BOOL) additive; + +/** only CCParticleSystemQuad is supported for the moment */ +-(void) addChild:(CCParticleSystem*)child z:(NSInteger)z tag:(NSInteger) aTag; + +/** helper method for addChild, adds room to texture atlas for particles of child */ +-(void) insertChild:(CCParticleSystem*) pSystem inAtlasAtIndex:(NSUInteger)index; + +/** helper method for removeChild, removes child's particles from texture atlas */ +-(void) removeChildFromAtlas:(CCParticleSystem*) pSystem cleanup:(BOOL) doCleanUp; + +/** disables a particle by inserting a 0'd quad into the texture atlas */ +-(void) disableParticle:(NSUInteger) particleIndex; + +/** switch between multiplied and premultiplied blending modes */ +-(void) switchBlendingBetweenMultipliedAndPreMultiplied; + +/** set a additive blending mode */ +-(void) additiveBlending; + +/** set a normal blending mode, taking premultiplied / non premultiplied into account */ +-(void) normalBlending; + +/** conforming to CCTextureProtocol */ +-(void) updateBlendFunc; +-(void) setTexture:(CCTexture2D*)texture; +-(CCTexture2D*) texture; +@end diff --git a/libs/cocos2d/CCParticleBatchNode.m b/libs/cocos2d/CCParticleBatchNode.m new file mode 100644 index 0000000..e85dc94 --- /dev/null +++ b/libs/cocos2d/CCParticleBatchNode.m @@ -0,0 +1,537 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (C) 2009 Matt Oswald + * + * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Copyright (c) 2011 Marco Tillemans + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCParticleBatchNode.h" +#import "CCTextureCache.h" +#import "CCTextureAtlas.h" +#import "ccConfig.h" +#import "ccMacros.h" +#import "CCGrid.h" +#import "Support/CGPointExtension.h" +#import "CCParticleSystem.h" +#import "CCParticleSystem.h" +#import "CCParticleSystemPoint.h" + +#import "Support/base64.h" +#import "Support/ZipUtils.h" +#import "Support/CCFileUtils.h" + +#define kDefaultCapacity 500 + +//need to set z-order manualy, because fast reordering of childs would be complexer / slower +@implementation CCNode (extension) +-(void) setZOrder:(NSUInteger) z +{ + zOrder_ = z; +} +@end + +@interface CCParticleBatchNode (private) +-(void) updateAllAtlasIndexes; +-(void) increaseAtlasCapacityTo:(NSUInteger) quantity; +-(NSUInteger) searchNewPositionInChildrenForZ:(NSInteger) z; +-(NSUInteger) addChildHelper: (CCNode*) child z:(NSInteger)z tag:(NSInteger) aTag; +-(void) moveSystem:(CCParticleSystem*) system toNewIndex:(NSUInteger) newIndex; +@end + +@implementation CCParticleBatchNode + +@synthesize textureAtlas = textureAtlas_; +@synthesize blendFunc = blendFunc_; + ++(BOOL) extractTextureFromPlist:(NSString*) plistFile +{ + NSString *path = [CCFileUtils fullPathFromRelativePath:plistFile]; + NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; + + NSAssert( dict != nil, @"ParticleBatchNode: plist file not found"); + + NSString *textureName = [dict valueForKey:@"textureFileName"]; + + CCTexture2D *tex = [[CCTextureCache sharedTextureCache] addImage:textureName]; + + if( !tex ) + { + NSString *textureData = [dict valueForKey:@"textureImageData"]; + NSAssert( textureData, @"CCuseQuad: Couldn't load texture"); + + // if it fails, try to get it from the base64-gzipped data + unsigned char *buffer = NULL; + int len = base64Decode((unsigned char*)[textureData UTF8String], (unsigned int)[textureData length], &buffer); + NSAssert( buffer != NULL, @"CCuseQuad: error decoding textureImageData"); + + unsigned char *deflated = NULL; + NSUInteger deflatedLen = ccInflateMemory(buffer, len, &deflated); + free( buffer ); + + NSAssert( deflated != NULL, @"CCuseQuad: error ungzipping textureImageData"); + NSData *data = [[NSData alloc] initWithBytes:deflated length:deflatedLen]; + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + UIImage *image = [[UIImage alloc] initWithData:data]; +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + NSBitmapImageRep *image = [[NSBitmapImageRep alloc] initWithData:data]; +#endif + + free(deflated); deflated = NULL; + + tex = [ [CCTextureCache sharedTextureCache] addCGImage:[image CGImage] forKey:textureName]; + [data release]; + [image release]; + } + if (tex) return YES; + else return NO; +} + +/* + * creation with CCTexture2D + */ ++(id)particleBatchNodeWithTexture:(CCTexture2D *)tex +{ + return [[[self alloc] initWithTexture:tex capacity:kDefaultCapacity useQuad:YES additiveBlending:NO] autorelease]; +} + ++(id)particleBatchNodeWithTexture:(CCTexture2D *)tex capacity:(NSUInteger) capacity useQuad:(BOOL) useQuad additiveBlending:(BOOL) additive +{ + return [[[self alloc] initWithTexture:tex capacity:capacity useQuad:YES additiveBlending:additive] autorelease]; +} + +/* + * creation with File Image + */ ++(id)particleBatchNodeWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity useQuad:(BOOL) useQuad additiveBlending:(BOOL) additive +{ + return [[[self alloc] initWithFile:fileImage capacity:capacity useQuad:useQuad additiveBlending:additive] autorelease]; +} + ++(id)particleBatchNodeWithFile:(NSString*) imageFile +{ + return [[[self alloc] initWithFile:imageFile capacity:kDefaultCapacity useQuad:YES additiveBlending:NO] autorelease]; +} + +/* + * init with CCTexture2D + */ +-(id)initWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity useQuad:(BOOL) useQuad additiveBlending:(BOOL) additive +{ + if (self = [super init]) + { + useQuad_ = useQuad; + reorderDirty_ = NO; + + //TODO initialize point atlas here + if (useQuad_) textureAtlas_ = [[CCTextureAtlas alloc] initWithTexture:tex capacity:capacity]; + + if (additive) [self additiveBlending]; + else [self normalBlending]; + + // no lazy alloc in this node + children_ = [[CCArray alloc] initWithCapacity:5]; + } + + return self; +} + +/* + * init with FileImage + */ +-(id)initWithFile:(NSString *)fileImage capacity:(NSUInteger)capacity useQuad:(BOOL) useQuad additiveBlending:(BOOL) additive +{ + CCTexture2D *tex = [[CCTextureCache sharedTextureCache] addImage:fileImage]; + return [self initWithTexture:tex capacity:capacity useQuad:useQuad additiveBlending:additive]; +} + +-(NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %08X | Tag = %i>", [self class], self, tag_ ]; +} + +-(void)dealloc +{ + [textureAtlas_ release]; + [super dealloc]; +} + +#pragma mark CCParticleBatchNode - composition + +// override visit. +// Don't call visit on it's children +-(void) visit +{ + + // CAREFUL: + // This visit is almost identical to CocosNode#visit + // with the exception that it doesn't call visit on it's children + // + // The alternative is to have a void CCSprite#visit, but + // although this is less mantainable, is faster + // + if (!visible_) + return; + + glPushMatrix(); + + if ( grid_ && grid_.active) { + [grid_ beforeDraw]; + [self transformAncestors]; + } + + //update of particle system is called before reordering is done, data in texture atlas is not up to date yet, need to set quads again according to new atlasIndexes + if (reorderDirty_) + { + [children_ makeObjectsPerformSelector:@selector(updateWithNoTime)]; + reorderDirty_ = NO; + } + [self transform]; + + [self draw]; + + if ( grid_ && grid_.active) + [grid_ afterDraw:self]; + + glPopMatrix(); +} + +// override addChild: +-(void) addChild:(CCParticleSystem*)child z:(NSInteger)z tag:(NSInteger) aTag +{ + NSAssert( child != nil, @"Argument must be non-nil"); + NSAssert( [child isKindOfClass:[CCParticleSystem class]], @"CCParticleBatchNode only supports CCQuadParticleSystems as children"); + + if (useQuad_) + { + NSAssert( child.texture.name == textureAtlas_.texture.name, @"CCParticleSystem is not using the same texture id"); + } + + //no lazy sorting, so don't call super addChild, call helper instead + NSUInteger pos = [self addChildHelper:child z:z tag:aTag]; + + //get new atlasIndex + NSUInteger atlasIndex; + + if (pos != 0) + atlasIndex = [[children_ objectAtIndex:pos-1] atlasIndex]+[[children_ objectAtIndex:pos-1] totalParticles]; + else + atlasIndex = 0; + + [child useBatchNode:self]; + + [self insertChild:child inAtlasAtIndex:atlasIndex]; +} + +//don't use lazy sorting, reordering the particle systems quads afterwards would be too complex +//XXX research whether lazy sorting + freeing current quads and calloc a new block with size of capacity would be faster +//XXX or possibly using vertexZ for reordering, that would be fastest +//this helper is almost equivalent to CCNode's addChild, but doesn't make use of the lazy sorting +-(NSUInteger) addChildHelper: (CCNode*) child z:(NSInteger)z tag:(NSInteger) aTag +{ + NSAssert( child != nil, @"Argument must be non-nil"); + NSAssert( child.parent == nil, @"child already added. It can't be added again"); + + if( ! children_ ) + children_ = [[CCArray alloc] initWithCapacity:4]; + + //don't use a lazy insert + NSUInteger pos = [self searchNewPositionInChildrenForZ:z]; + + [children_ insertObject:child atIndex:pos]; + + child.tag = aTag; + [child setZOrder:z]; + + [child setParent: self]; + + if( isRunning_ ) { + [child onEnter]; + [child onEnterTransitionDidFinish]; + } + return pos; +} + +// override reorderChild +-(void) reorderChild:(CCParticleSystem*)child z:(NSInteger)z +{ + NSAssert( child != nil, @"Child must be non-nil"); + NSAssert( [children_ containsObject:child], @"Child doesn't belong to Sprite" ); + + if( z == child.zOrder ) + return; + + if ([children_ count] == 1) [child setZOrder:z]; + else + { + reorderDirty_ = YES; + [child retain]; + + NSUInteger oldPos = [children_ indexOfObject:child]; + + //only remove the child, not the scheduled update + [children_ removeObject:child]; + + NSUInteger pos = [self searchNewPositionInChildrenForZ:z]; + + if (pos != oldPos) + { + NSUInteger newIndex; + if (pos == [children_ count]) + newIndex = textureAtlas_.totalQuads; + else + newIndex = [[children_ objectAtIndex:MIN([children_ count]-1,pos)] atlasIndex]; + + //to correctly move the quads, the new index needs to be the left border of where the quads will be placed + if (z > child.zOrder) + newIndex -= child.totalParticles; + + //move quads in textureAtlas + [self moveSystem:child toNewIndex:newIndex]; + } + [children_ insertObject:child atIndex:pos]; + + [child release]; + + //renew atlasIndexes of children + [self updateAllAtlasIndexes]; + } +} + +-(NSUInteger) searchNewPositionInChildrenForZ: (NSInteger) z +{ + int i = 0; + NSUInteger count = [children_ count]; + CCNode* child; + + while (i < count) + { + child = [children_ objectAtIndex:i]; + if (child.zOrder > z) return MAX(0,(i-1)); + + i++; + } + + if (z >= 0) return MAX(0,count); + else return 0; +} + +// override removeChild: +-(void)removeChild: (CCParticleSystem*) child cleanup:(BOOL) doCleanup +{ + // explicit nil handling + if (child == nil) + return; + + NSAssert([children_ containsObject:child], @"CCParticleBatchNode doesn't contain the sprite. Can't remove it"); + + // cleanup before removing, issue 1316 clean before calling super + [self removeChildFromAtlas:child cleanup:doCleanup]; + + [super removeChild:child cleanup:doCleanup]; + + [self updateAllAtlasIndexes]; +} + +-(void)removeChildAtIndex:(NSUInteger)index cleanup:(BOOL) doCleanup +{ + [self removeChild:(CCParticleSystem *)[children_ objectAtIndex:index] cleanup:doCleanup]; +} + +-(void)removeAllChildrenWithCleanup:(BOOL)doCleanup +{ + [children_ makeObjectsPerformSelector:@selector(useSelfRender)]; + + [super removeAllChildrenWithCleanup:doCleanup]; + + [textureAtlas_ removeAllQuads]; +} + +#pragma mark CCParticleBatchNode - draw +-(void) draw +{ + //don't call super draw, it's empty + //[super draw]; + + if( textureAtlas_.totalQuads == 0 ) + return; + + // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY + // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY + // Unneeded states: - + + BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST; + if( newBlend ) + glBlendFunc( blendFunc_.src, blendFunc_.dst ); + + [textureAtlas_ drawQuads]; + if( newBlend ) + glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST); +} + +#pragma mark CCParticleBatchNode - private + +-(void) increaseAtlasCapacityTo:(NSUInteger) quantity +{ + CCLOG(@"cocos2d: CCParticleBatchNode: resizing TextureAtlas capacity from [%lu] to [%lu].", + (long)textureAtlas_.capacity, + (long)quantity); + + if( ! [textureAtlas_ resizeCapacity:quantity] ) { + // serious problems + CCLOG(@"cocos2d: WARNING: Not enough memory to resize the atlas"); + NSAssert(NO,@"XXX: CCParticleBatchNode #increaseAtlasCapacity SHALL handle this assert"); + } +} + +-(void) moveSystem:(CCParticleSystem*) system toNewIndex:(NSUInteger) newIndex +{ + [textureAtlas_ insertQuadsFromIndex:system.atlasIndex amount:system.totalParticles atIndex:newIndex]; +} + +//sets a 0'd quad into the quads array +-(void) disableParticle:(NSUInteger) particleIndex +{ + ccV3F_C4B_T2F_Quad* quad = &((textureAtlas_.quads)[particleIndex]); + quad->br.vertices.x = quad->br.vertices.y = quad->tr.vertices.x = quad->tr.vertices.y = quad->tl.vertices.x = quad->tl.vertices.y = quad->bl.vertices.x = quad->bl.vertices.y = 0.0f; +} + +#pragma mark CCParticleBatchNode - add / remove / reorder helper methods + +// add child helper +-(void) insertChild:(CCParticleSystem*) pSystem inAtlasAtIndex:(NSUInteger)index +{ + pSystem.atlasIndex = index; + + if(textureAtlas_.totalQuads + pSystem.totalParticles > textureAtlas_.capacity) + { + [self increaseAtlasCapacityTo:textureAtlas_.totalQuads + pSystem.totalParticles]; + + //after a realloc empty quads of textureAtlas can be filled with gibberish (realloc doesn't perform calloc), insert empty quads to prevent it + [textureAtlas_ fillWithEmptyQuadsFromIndex:textureAtlas_.capacity - pSystem.totalParticles amount:pSystem.totalParticles]; + } + + if (useQuad_) + { + //make room for quads, not necessary for last child + if (pSystem.atlasIndex+pSystem.totalParticles != textureAtlas_.totalQuads) [textureAtlas_ moveQuadsFromIndex:index to:index+pSystem.totalParticles]; + + //increase totalParticles here for new particles, update method of particlesystem will fill the quads + [textureAtlas_ increaseTotalQuadsWith:pSystem.totalParticles]; + + [pSystem batchNodeInitialization]; + } + + [self updateAllAtlasIndexes]; +} + +// remove child helper +-(void) removeChildFromAtlas:(CCParticleSystem*) pSystem cleanup:(BOOL) doCleanUp +{ + [textureAtlas_ removeQuadsAtIndex:pSystem.atlasIndex amount:pSystem.totalParticles]; + + //after memove of data, empty the quads at the end of array + [textureAtlas_ fillWithEmptyQuadsFromIndex:textureAtlas_.totalQuads amount:pSystem.totalParticles]; + + //with no cleanup the particle system could be reused for self rendering + if (!doCleanUp) [pSystem useSelfRender]; + +} + +//rebuild atlas indexes +-(void) updateAllAtlasIndexes +{ + CCParticleSystem* child; + uint index = 0; + + CCARRAY_FOREACH(children_,child) + { + child.atlasIndex = index; + index += child.totalParticles; + } +} + +#pragma mark CCParticleBatchNode - CocosNodeTexture protocol + +-(void) additiveBlending +{ + blendFunc_.src = GL_SRC_ALPHA; + blendFunc_.dst = GL_ONE; +} + +-(void) normalBlending +{ + if( ! [textureAtlas_.texture hasPremultipliedAlpha] ) { + blendFunc_.src = GL_SRC_ALPHA; + blendFunc_.dst = GL_ONE_MINUS_SRC_ALPHA; + } + else + { + blendFunc_.src = GL_ONE; + blendFunc_.dst = GL_ONE_MINUS_SRC_ALPHA; + } +} + +-(void) switchBlendingBetweenMultipliedAndPreMultiplied +{ + if (blendFunc_.src == GL_ONE) + { + blendFunc_.src = GL_SRC_ALPHA; + blendFunc_.dst = GL_ONE_MINUS_SRC_ALPHA; + } + else + { + blendFunc_.src = GL_ONE; + blendFunc_.dst = GL_ONE_MINUS_SRC_ALPHA; + } +} + +-(void) updateBlendFunc +{ + if( ! [textureAtlas_.texture hasPremultipliedAlpha] ) { + blendFunc_.src = GL_SRC_ALPHA; + blendFunc_.dst = GL_ONE_MINUS_SRC_ALPHA; + } +} + +-(void) setTexture:(CCTexture2D*)texture +{ + textureAtlas_.texture = texture; + + // If the new texture has No premultiplied alpha, AND the blendFunc hasn't been changed, then update it + if( texture && ! [texture hasPremultipliedAlpha] && ( blendFunc_.src == CC_BLEND_SRC && blendFunc_.dst == CC_BLEND_DST ) ) + { + blendFunc_.src = GL_SRC_ALPHA; + blendFunc_.dst = GL_ONE_MINUS_SRC_ALPHA; + } +} + +-(CCTexture2D*) texture +{ + return textureAtlas_.texture; +} + +@end \ No newline at end of file diff --git a/libs/cocos2d/CCParticleExamples.h b/libs/cocos2d/CCParticleExamples.h index b28fca9..f859b48 100644 --- a/libs/cocos2d/CCParticleExamples.h +++ b/libs/cocos2d/CCParticleExamples.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,82 +30,68 @@ #import "CCParticleSystemPoint.h" #import "CCParticleSystemQuad.h" -// build each architecture with the optimal particle system - -// ARMv7, Mac or Simulator use "Quad" particle -#if defined(__ARM_NEON__) || defined(__MAC_OS_X_VERSION_MAX_ALLOWED) || TARGET_IPHONE_SIMULATOR - #define ARCH_OPTIMAL_PARTICLE_SYSTEM CCParticleSystemQuad - -// ARMv6 use "Point" particle -#elif __arm__ - #define ARCH_OPTIMAL_PARTICLE_SYSTEM CCParticleSystemPoint -#else - #error(unknown architecture) -#endif - - //! A fire particle system -@interface CCParticleFire: ARCH_OPTIMAL_PARTICLE_SYSTEM +@interface CCParticleFire: CCParticleSystemQuad { } @end //! A fireworks particle system -@interface CCParticleFireworks : ARCH_OPTIMAL_PARTICLE_SYSTEM +@interface CCParticleFireworks : CCParticleSystemQuad { } @end //! A sun particle system -@interface CCParticleSun : ARCH_OPTIMAL_PARTICLE_SYSTEM +@interface CCParticleSun : CCParticleSystemQuad { } @end //! A galaxy particle system -@interface CCParticleGalaxy : ARCH_OPTIMAL_PARTICLE_SYSTEM +@interface CCParticleGalaxy : CCParticleSystemQuad { } @end //! A flower particle system -@interface CCParticleFlower : ARCH_OPTIMAL_PARTICLE_SYSTEM +@interface CCParticleFlower : CCParticleSystemQuad { } @end //! A meteor particle system -@interface CCParticleMeteor : ARCH_OPTIMAL_PARTICLE_SYSTEM +@interface CCParticleMeteor : CCParticleSystemQuad { } @end //! An spiral particle system -@interface CCParticleSpiral : ARCH_OPTIMAL_PARTICLE_SYSTEM +@interface CCParticleSpiral : CCParticleSystemQuad { } @end //! An explosion particle system -@interface CCParticleExplosion : ARCH_OPTIMAL_PARTICLE_SYSTEM +@interface CCParticleExplosion : CCParticleSystemQuad { } @end //! An smoke particle system -@interface CCParticleSmoke : ARCH_OPTIMAL_PARTICLE_SYSTEM +@interface CCParticleSmoke : CCParticleSystemQuad { } @end //! An snow particle system -@interface CCParticleSnow : ARCH_OPTIMAL_PARTICLE_SYSTEM +@interface CCParticleSnow : CCParticleSystemQuad { } @end //! A rain particle system -@interface CCParticleRain : ARCH_OPTIMAL_PARTICLE_SYSTEM +@interface CCParticleRain : CCParticleSystemQuad { } @end diff --git a/libs/cocos2d/CCParticleExamples.m b/libs/cocos2d/CCParticleExamples.m index c3b8f8f..38c8b46 100644 --- a/libs/cocos2d/CCParticleExamples.m +++ b/libs/cocos2d/CCParticleExamples.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,7 +40,7 @@ -(id) init return [self initWithTotalParticles:1500]; } --(id) initWithTotalParticles:(int)p +-(id) initWithTotalParticles:(NSUInteger)p { if( (self=[super initWithTotalParticles:p]) ) { // duration @@ -116,7 +117,7 @@ -(id) init return [self initWithTotalParticles:250]; } --(id) initWithTotalParticles:(int) p +-(id) initWithTotalParticles:(NSUInteger) p { if( (self=[super initWithTotalParticles:p]) ) { @@ -196,7 +197,7 @@ -(id) init return [self initWithTotalParticles:350]; } --(id) initWithTotalParticles:(int) p +-(id) initWithTotalParticles:(NSUInteger) p { if( (self=[super initWithTotalParticles:p]) ) { @@ -276,7 +277,7 @@ -(id) init return [self initWithTotalParticles:200]; } --(id) initWithTotalParticles:(int)p +-(id) initWithTotalParticles:(NSUInteger)p { if( (self=[super initWithTotalParticles:p]) ) { @@ -359,7 +360,7 @@ -(id) init return [self initWithTotalParticles:250]; } --(id) initWithTotalParticles:(int) p +-(id) initWithTotalParticles:(NSUInteger) p { if( (self=[super initWithTotalParticles:p]) ) { @@ -442,7 +443,7 @@ -(id) init return [self initWithTotalParticles:150]; } --(id) initWithTotalParticles:(int) p +-(id) initWithTotalParticles:(NSUInteger) p { if( (self=[super initWithTotalParticles:p]) ) { @@ -525,7 +526,7 @@ -(id) init return [self initWithTotalParticles:500]; } --(id) initWithTotalParticles:(int) p +-(id) initWithTotalParticles:(NSUInteger) p { if( (self=[super initWithTotalParticles:p]) ) { @@ -608,7 +609,7 @@ -(id) init return [self initWithTotalParticles:700]; } --(id) initWithTotalParticles:(int)p +-(id) initWithTotalParticles:(NSUInteger)p { if( (self=[super initWithTotalParticles:p]) ) { @@ -690,7 +691,7 @@ -(id) init return [self initWithTotalParticles:200]; } --(id) initWithTotalParticles:(int) p +-(id) initWithTotalParticles:(NSUInteger) p { if( (self=[super initWithTotalParticles:p]) ) { @@ -766,7 +767,7 @@ -(id) init return [self initWithTotalParticles:700]; } --(id) initWithTotalParticles:(int)p +-(id) initWithTotalParticles:(NSUInteger)p { if( (self=[super initWithTotalParticles:p]) ) { @@ -848,7 +849,7 @@ -(id) init return [self initWithTotalParticles:1000]; } --(id) initWithTotalParticles:(int)p +-(id) initWithTotalParticles:(NSUInteger)p { if( (self=[super initWithTotalParticles:p]) ) { diff --git a/libs/cocos2d/CCParticleSystem.h b/libs/cocos2d/CCParticleSystem.h index e87961d..47f69d1 100644 --- a/libs/cocos2d/CCParticleSystem.h +++ b/libs/cocos2d/CCParticleSystem.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,11 +30,29 @@ #import "ccTypes.h" #import "ccConfig.h" +@class CCParticleBatchNode; #if CC_ENABLE_PROFILERS @class CCProfilingTimer; + #endif //* @enum + +/** @typedef tCCParticleAnimationType + possible types of particle animations + */ +typedef enum { + /** New particles play the animation in a loop. */ + kCCParticleAnimationTypeLoop = 0, + /** New particles play the animation in a loop with a random starting frame. */ + kCCParticleAnimationTypeLoopWithRandomStartFrame, + /** New particles play the animation once. */ + kCCParticleAnimationTypeOnce, + /** New particles choose a single random frame from the animation. */ + kCCParticleAnimationTypeRandomFrame + +} tCCParticleAnimationType; + enum { /** The Particle emitter lives forever */ kCCParticleDurationInfinity = -1, @@ -86,6 +105,7 @@ enum { */ typedef struct sCCParticle { CGPoint pos; + float z; CGPoint startPos; ccColor4F color; @@ -98,6 +118,8 @@ typedef struct sCCParticle { float deltaRotation; ccTime timeToLive; + + NSUInteger atlasIndex; union { // Mode A: gravity, direction, radial accel, tangential accel @@ -115,6 +137,11 @@ typedef struct sCCParticle { float deltaRadius; } B; } mode; + + // animation + ccTime elapsed; + ccTime split; + NSUInteger currentFrame; }tCCParticle; @@ -236,6 +263,11 @@ typedef void (*CC_UPDATE_PARTICLE_IMP)(id, SEL, tCCParticle*, CGPoint); // end size of variance float endSizeVar; + float startScale; + float startScaleVar; + float endScale; + float endScaleVar; + // How many seconds will the particle live float life; // Life variance @@ -259,17 +291,13 @@ typedef void (*CC_UPDATE_PARTICLE_IMP)(id, SEL, tCCParticle*, CGPoint); // end angle ariance float endSpinVar; - // Array of particles tCCParticle *particles; // Maximum particles NSUInteger totalParticles; // Count of active particles NSUInteger particleCount; - - // color modulate -// BOOL colorModulate; - + // How many particles can be emitted per second float emissionRate; float emitCounter; @@ -292,6 +320,23 @@ typedef void (*CC_UPDATE_PARTICLE_IMP)(id, SEL, tCCParticle*, CGPoint); CC_UPDATE_PARTICLE_IMP updateParticleImp; SEL updateParticleSel; + //for batching + CCParticleBatchNode *batchNode_; + BOOL useBatchNode_; + //index of system in batch node array + NSUInteger atlasIndex_; + //YES if scaled or rotated + BOOL transformSystemDirty_; + + // animation + BOOL useAnimation_; + NSUInteger totalFrameCount_; + + //contains offset positions for vertex and precalculated texture coordinates + ccAnimationFrameData *animationFrameData_; + tCCParticleAnimationType animationType_; + + // profiling #if CC_ENABLE_PROFILERS CCProfilingTimer* _profilingTimer; @@ -353,6 +398,22 @@ typedef void (*CC_UPDATE_PARTICLE_IMP)(id, SEL, tCCParticle*, CGPoint); @property (nonatomic,readwrite,assign) float endSize; /** end size variance in pixels of each particle */ @property (nonatomic,readwrite,assign) float endSizeVar; +/** start scale in pixels of each particle. Only used by animation + @since 1.1 + */ +@property (nonatomic,readwrite,assign) float startScale; +/** scale variance in pixels of each particle. Only used by animation + @since 1.1 + */ +@property (nonatomic,readwrite,assign) float startScaleVar; +/** end scale in pixels of each particle. Only used by animation + @since 1.1 + */ +@property (nonatomic,readwrite,assign) float endScale; +/** end scale variance in pixels of each particle. Only used by animation + @since 1.1 + */ +@property (nonatomic,readwrite,assign) float endScaleVar; /** start color of each particle */ @property (nonatomic,readwrite,assign) ccColor4F startColor; /** start color variance of each particle */ @@ -399,7 +460,19 @@ typedef void (*CC_UPDATE_PARTICLE_IMP)(id, SEL, tCCParticle*, CGPoint); - kCCParticleModeRadius: uses radius movement + rotation */ @property (nonatomic,readwrite) NSInteger emitterMode; +/** Index of first particle in texture atlas of batch node + @since 1.1 + */ +@property (nonatomic,readwrite) NSUInteger atlasIndex; +/** YES if a particle batchnode is used for rendering, NO for self rendering + @since 1.1 + */ +@property (nonatomic,readonly) BOOL useBatchNode; +/** animation type, once, loop from beginning, random frame, or loop with random start frame + @since 1.1 + */ +@property (nonatomic,readwrite) tCCParticleAnimationType animationType; /** creates an initializes a CCParticleSystem from a plist file. This plist files can be creted manually or with Particle Designer: http://particledesigner.71squared.com/ @@ -419,8 +492,8 @@ typedef void (*CC_UPDATE_PARTICLE_IMP)(id, SEL, tCCParticle*, CGPoint); */ -(id) initWithDictionary:(NSDictionary*)dictionary; -//! Initializes a system with a fixed number of particles --(id) initWithTotalParticles:(int) numberOfParticles; +//! Initializes a system with a fixed number of particles and whether a batchnode is used for rendering +-(id) initWithTotalParticles:(NSUInteger) numberOfParticles; //! Add a particle to the emitter -(BOOL) addParticle; //! Initializes a particle @@ -440,5 +513,13 @@ typedef void (*CC_UPDATE_PARTICLE_IMP)(id, SEL, tCCParticle*, CGPoint); //! called in every loop. -(void) update: (ccTime) dt; -@end +-(void) updateWithNoTime; + +//switch to self rendering +-(void) useSelfRender; +//switch to batch node rendering +-(void) useBatchNode:(CCParticleBatchNode*) batchNode; +//used internally by CCParticleBathNode +-(void) batchNodeInitialization; +@end \ No newline at end of file diff --git a/libs/cocos2d/CCParticleSystem.m b/libs/cocos2d/CCParticleSystem.m index 1ee46da..bbe512f 100644 --- a/libs/cocos2d/CCParticleSystem.m +++ b/libs/cocos2d/CCParticleSystem.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -50,9 +51,12 @@ #import "Support/CCProfiling.h" #endif #import "CCParticleSystem.h" +#import "CCParticleBatchNode.h" #import "CCTextureCache.h" +#import "CCTextureAtlas.h" #import "ccMacros.h" + // support #import "Support/OpenGL_Internal.h" #import "Support/CGPointExtension.h" @@ -60,6 +64,7 @@ #import "Support/ZipUtils.h" #import "Support/CCFileUtils.h" + @implementation CCParticleSystem @synthesize active, duration; @synthesize sourcePosition, posVar; @@ -72,11 +77,15 @@ @implementation CCParticleSystem @synthesize totalParticles; @synthesize startSize, startSizeVar; @synthesize endSize, endSizeVar; +@synthesize startScale, startScaleVar; +@synthesize endScale, endScaleVar; @synthesize blendFunc = blendFunc_; @synthesize positionType = positionType_; @synthesize autoRemoveOnFinish = autoRemoveOnFinish_; @synthesize emitterMode = emitterMode_; - +@synthesize atlasIndex = atlasIndex_; +@synthesize useBatchNode = useBatchNode_; +@synthesize animationType=animationType_; +(id) particleWithFile:(NSString*) plistFile { @@ -102,8 +111,9 @@ -(id) initWithDictionary:(NSDictionary *)dictionary { NSUInteger maxParticles = [[dictionary valueForKey:@"maxParticles"] intValue]; // self, not super - if ((self=[self initWithTotalParticles:maxParticles] ) ) { - + + if ((self=[self initWithTotalParticles:maxParticles] ) ) + { // angle angle = [[dictionary valueForKey:@"angle"] floatValue]; angleVar = [[dictionary valueForKey:@"angleVariance"] floatValue]; @@ -148,7 +158,6 @@ -(id) initWithDictionary:(NSDictionary *)dictionary endSize = [[dictionary valueForKey:@"finishParticleSize"] floatValue]; endSizeVar = [[dictionary valueForKey:@"finishParticleSizeVariance"] floatValue]; - // position float x = [[dictionary valueForKey:@"sourcePositionx"] floatValue]; float y = [[dictionary valueForKey:@"sourcePositiony"] floatValue]; @@ -156,6 +165,20 @@ -(id) initWithDictionary:(NSDictionary *)dictionary posVar.x = [[dictionary valueForKey:@"sourcePositionVariancex"] floatValue]; posVar.y = [[dictionary valueForKey:@"sourcePositionVariancey"] floatValue]; + // Spinning + startSpin = [[dictionary valueForKey:@"rotationStart"] floatValue]; + startSpinVar = [[dictionary valueForKey:@"rotationStartVariance"] floatValue]; + endSpin = [[dictionary valueForKey:@"rotationEnd"] floatValue]; + endSpinVar = [[dictionary valueForKey:@"rotationEndVariance"] floatValue]; + + //v2 additions + if ([dictionary valueForKey:@"version"] && [[dictionary valueForKey:@"version"] intValue] == 2) + { + startScale = [[dictionary valueForKey:@"startScale"] floatValue]; + startScaleVar = [[dictionary valueForKey:@"startScaleVar"] floatValue]; + endScale = [[dictionary valueForKey:@"endScale"] floatValue]; + endScaleVar = [[dictionary valueForKey:@"endScaleVar"] floatValue]; + } emitterMode_ = [[dictionary valueForKey:@"emitterType"] intValue]; @@ -185,7 +208,6 @@ -(id) initWithDictionary:(NSDictionary *)dictionary mode.A.tangentialAccelVar = tmp ? [tmp floatValue] : 0; } - // or Mode B: radius movement else if( emitterMode_ == kCCParticleModeRadius ) { float maxRadius = [[dictionary valueForKey:@"maxRadius"] floatValue]; @@ -210,49 +232,55 @@ -(id) initWithDictionary:(NSDictionary *)dictionary // emission Rate emissionRate = totalParticles/life; + //don't get the internal texture if a batchNode is used + if (!batchNode_) + { // texture // Try to get the texture from the cache - NSString *textureName = [dictionary valueForKey:@"textureFileName"]; - - self.texture = [[CCTextureCache sharedTextureCache] addImage:textureName]; - - NSString *textureData = [dictionary valueForKey:@"textureImageData"]; - - if ( ! texture_ && textureData) { + NSString *textureName = [dictionary valueForKey:@"textureFileName"]; + + CCTexture2D *tex = [[CCTextureCache sharedTextureCache] addImage:textureName]; - // if it fails, try to get it from the base64-gzipped data - unsigned char *buffer = NULL; - NSUInteger len = base64Decode((unsigned char*)[textureData UTF8String], [textureData length], &buffer); - NSAssert( buffer != NULL, @"CCParticleSystem: error decoding textureImageData"); + if( tex ) + [self setTexture:tex]; + else { - unsigned char *deflated = NULL; - NSUInteger deflatedLen = ccInflateMemory(buffer, len, &deflated); - free( buffer ); + NSString *textureData = [dictionary valueForKey:@"textureImageData"]; + NSAssert( textureData, @"CCParticleSystem: Couldn't load texture"); + + // if it fails, try to get it from the base64-gzipped data + unsigned char *buffer = NULL; + int len = base64Decode((unsigned char*)[textureData UTF8String], (unsigned int)[textureData length], &buffer); + NSAssert( buffer != NULL, @"CCParticleSystem: error decoding textureImageData"); + + unsigned char *deflated = NULL; + NSUInteger deflatedLen = ccInflateMemory(buffer, len, &deflated); + free( buffer ); + + NSAssert( deflated != NULL, @"CCParticleSystem: error ungzipping textureImageData"); + NSData *data = [[NSData alloc] initWithBytes:deflated length:deflatedLen]; - NSAssert( deflated != NULL, @"CCParticleSystem: error ungzipping textureImageData"); - NSData *data = [[NSData alloc] initWithBytes:deflated length:deflatedLen]; - #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED - UIImage *image = [[UIImage alloc] initWithData:data]; + UIImage *image = [[UIImage alloc] initWithData:data]; #elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) - NSBitmapImageRep *image = [[NSBitmapImageRep alloc] initWithData:data]; + NSBitmapImageRep *image = [[NSBitmapImageRep alloc] initWithData:data]; #endif + + free(deflated); deflated = NULL; + + [self setTexture: [ [CCTextureCache sharedTextureCache] addCGImage:[image CGImage] forKey:textureName]]; + [data release]; + [image release]; + } - free(deflated); deflated = NULL; - - self.texture = [[CCTextureCache sharedTextureCache] addCGImage:[image CGImage] forKey:textureName]; - [data release]; - [image release]; + NSAssert( [self texture] != NULL, @"CCParticleSystem: error loading the texture"); } + } - NSAssert( [self texture] != NULL, @"CCParticleSystem: error loading the texture"); - - } - return self; } --(id) initWithTotalParticles:(int) numberOfParticles +-(id) initWithTotalParticles:(NSUInteger) numberOfParticles { if( (self=[super init]) ) { @@ -266,6 +294,14 @@ -(id) initWithTotalParticles:(int) numberOfParticles return nil; } + if (batchNode_) + { + for (int i = 0; i < totalParticles; i++) + { + particles[i].atlasIndex=i; + } + } + // default, active active = YES; @@ -277,11 +313,7 @@ -(id) initWithTotalParticles:(int) numberOfParticles // by default be in mode A: emitterMode_ = kCCParticleModeGravity; - - // default: modulate - // XXX: not used - // colorModulate = YES; - + autoRemoveOnFinish_ = NO; // profiling @@ -292,12 +324,19 @@ -(id) initWithTotalParticles:(int) numberOfParticles // Optimization: compile udpateParticle method updateParticleSel = @selector(updateQuadWithParticle:newPosition:); updateParticleImp = (CC_UPDATE_PARTICLE_IMP) [self methodForSelector:updateParticleSel]; + + //for batchNode + transformSystemDirty_ = NO; + + // animation + useAnimation_ = NO; + totalFrameCount_ = 0; + animationFrameData_ = NULL; + animationType_ = kCCParticleAnimationTypeLoop; // udpate after action in run! [self scheduleUpdateWithPriority:1]; - } - return self; } @@ -305,6 +344,9 @@ -(void) dealloc { free( particles ); + if (animationFrameData_) + free(animationFrameData_); + [texture_ release]; // profiling #if CC_ENABLE_PROFILERS @@ -329,29 +371,32 @@ -(BOOL) addParticle -(void) initParticle: (tCCParticle*) particle { - + //CGPoint currentPosition = position_; // timeToLive // no negative life. prevent division by 0 - particle->timeToLive = MAX(0, life + lifeVar * CCRANDOM_MINUS1_1() ); + particle->timeToLive = life + lifeVar * CCRANDOM_MINUS1_1(); + particle->timeToLive = MAX(0, particle->timeToLive); // position particle->pos.x = sourcePosition.x + posVar.x * CCRANDOM_MINUS1_1(); - particle->pos.x *= CC_CONTENT_SCALE_FACTOR(); particle->pos.y = sourcePosition.y + posVar.y * CCRANDOM_MINUS1_1(); + + //CCLOG(@"particle pos %f %f n pos %f %f",particle->pos.x,particle->pos.y, position_.x,position_.y); + particle->pos.x *= CC_CONTENT_SCALE_FACTOR(); particle->pos.y *= CC_CONTENT_SCALE_FACTOR(); // Color ccColor4F start; - start.r = MIN(1, MAX(0, startColor.r + startColorVar.r * CCRANDOM_MINUS1_1() ) ); - start.g = MIN(1, MAX(0, startColor.g + startColorVar.g * CCRANDOM_MINUS1_1() ) ); - start.b = MIN(1, MAX(0, startColor.b + startColorVar.b * CCRANDOM_MINUS1_1() ) ); - start.a = MIN(1, MAX(0, startColor.a + startColorVar.a * CCRANDOM_MINUS1_1() ) ); + start.r = clampf( startColor.r + startColorVar.r * CCRANDOM_MINUS1_1(), 0, 1); + start.g = clampf( startColor.g + startColorVar.g * CCRANDOM_MINUS1_1(), 0, 1); + start.b = clampf( startColor.b + startColorVar.b * CCRANDOM_MINUS1_1(), 0, 1); + start.a = clampf( startColor.a + startColorVar.a * CCRANDOM_MINUS1_1(), 0, 1); ccColor4F end; - end.r = MIN(1, MAX(0, endColor.r + endColorVar.r * CCRANDOM_MINUS1_1() ) ); - end.g = MIN(1, MAX(0, endColor.g + endColorVar.g * CCRANDOM_MINUS1_1() ) ); - end.b = MIN(1, MAX(0, endColor.b + endColorVar.b * CCRANDOM_MINUS1_1() ) ); - end.a = MIN(1, MAX(0, endColor.a + endColorVar.a * CCRANDOM_MINUS1_1() ) ); + end.r = clampf( endColor.r + endColorVar.r * CCRANDOM_MINUS1_1(), 0, 1); + end.g = clampf( endColor.g + endColorVar.g * CCRANDOM_MINUS1_1(), 0, 1); + end.b = clampf( endColor.b + endColorVar.b * CCRANDOM_MINUS1_1(), 0, 1); + end.a = clampf( endColor.a + endColorVar.a * CCRANDOM_MINUS1_1(), 0, 1); particle->color = start; particle->deltaColor.r = (end.r - start.r) / particle->timeToLive; @@ -360,19 +405,38 @@ -(void) initParticle: (tCCParticle*) particle particle->deltaColor.a = (end.a - start.a) / particle->timeToLive; // size - float startS = MAX(0, startSize + startSizeVar * CCRANDOM_MINUS1_1() ); // no negative size - startS *= CC_CONTENT_SCALE_FACTOR(); - - particle->size = startS; - if( endSize == kCCParticleStartSizeEqualToEndSize ) - particle->deltaSize = 0; - else { - float endS = endSize + endSizeVar * CCRANDOM_MINUS1_1(); - endS = MAX(0, endS); - endS *= CC_CONTENT_SCALE_FACTOR(); - particle->deltaSize = (endS - startS) / particle->timeToLive; + //to limit increase in byte size of particle, size is used as scale during animation + if (useAnimation_) + { + float startS = startScale + startScaleVar * CCRANDOM_MINUS1_1(); + startS = MAX(0, startS); // No negative value + + particle->size = startS; + if( endScale == kCCParticleStartSizeEqualToEndSize ) + particle->deltaSize = 0; + else { + float endS = endScale + endScaleVar * CCRANDOM_MINUS1_1(); + endS = MAX(0, endS); // No negative values + particle->deltaSize = (endS - startS) / particle->timeToLive; + } + } + else + { + float startS = startSize + startSizeVar * CCRANDOM_MINUS1_1(); + startS = MAX(0, startS); // No negative value + startS *= CC_CONTENT_SCALE_FACTOR(); + + particle->size = startS; + if( endSize == kCCParticleStartSizeEqualToEndSize ) + particle->deltaSize = 0; + else { + float endS = endSize + endSizeVar * CCRANDOM_MINUS1_1(); + endS = MAX(0, endS); // No negative values + endS *= CC_CONTENT_SCALE_FACTOR(); + particle->deltaSize = (endS - startS) / particle->timeToLive; + } + } - // rotation float startA = startSpin + startSpinVar * CCRANDOM_MINUS1_1(); float endA = endSpin + endSpinVar * CCRANDOM_MINUS1_1(); @@ -430,6 +494,29 @@ -(void) initParticle: (tCCParticle*) particle particle->mode.B.angle = a; particle->mode.B.degreesPerSecond = CC_DEGREES_TO_RADIANS(mode.B.rotatePerSecond + mode.B.rotatePerSecondVar * CCRANDOM_MINUS1_1()); } + + particle->z=vertexZ_; + + // animation + if (useAnimation_) + { + particle->split = 0; + particle->elapsed = 0; + + switch (animationType_) { + default: + case kCCParticleAnimationTypeOnce: + case kCCParticleAnimationTypeLoop: { + particle->currentFrame = 0; + break; + } + case kCCParticleAnimationTypeRandomFrame: + case kCCParticleAnimationTypeLoopWithRandomStartFrame: { + particle->currentFrame = (NSUInteger) roundf((CCRANDOM_0_1() * (totalFrameCount_ -1))); + break; + } + } + } } -(void) stopSystem @@ -447,6 +534,7 @@ -(void) resetSystem tCCParticle *p = &particles[particleIdx]; p->timeToLive = 0; } + } -(BOOL) isFull @@ -459,12 +547,15 @@ -(void) update: (ccTime) dt { if( active && emissionRate ) { float rate = 1.0f / emissionRate; - emitCounter += dt; + + //issue #1201, prevent bursts of particles, due to too high emitCounter + if (particleCount < totalParticles) emitCounter += dt; + while( particleCount < totalParticles && emitCounter > rate ) { [self addParticle]; emitCounter -= rate; } - + elapsed += dt; if(duration != -1 && duration < elapsed) [self stopSystem]; @@ -472,113 +563,189 @@ -(void) update: (ccTime) dt particleIdx = 0; - #if CC_ENABLE_PROFILERS CCProfilingBeginTimingBlock(_profilingTimer); #endif + + CGPoint currentPosition; + //if (useBatchNode_) currentPosition = [self.parent convertToWorldSpace:self.position]; + //else + currentPosition = CGPointZero; - - CGPoint currentPosition = CGPointZero; if( positionType_ == kCCPositionTypeFree ) { currentPosition = [self convertToWorldSpace:CGPointZero]; currentPosition.x *= CC_CONTENT_SCALE_FACTOR(); currentPosition.y *= CC_CONTENT_SCALE_FACTOR(); } else if( positionType_ == kCCPositionTypeRelative ) { + //currentPosition = [self convertToWorldSpace:CGPointZero]; currentPosition = position_; currentPosition.x *= CC_CONTENT_SCALE_FACTOR(); currentPosition.y *= CC_CONTENT_SCALE_FACTOR(); } - while( particleIdx < particleCount ) + if (visible_) { - tCCParticle *p = &particles[particleIdx]; - - // life - p->timeToLive -= dt; - - if( p->timeToLive > 0 ) { + while( particleIdx < particleCount ) + { + tCCParticle *p = &particles[particleIdx]; - // Mode A: gravity, direction, tangential accel & radial accel - if( emitterMode_ == kCCParticleModeGravity ) { - CGPoint tmp, radial, tangential; + // life + p->timeToLive -= dt; + + if( p->timeToLive > 0 ) { - radial = CGPointZero; - // radial acceleration - if(p->pos.x || p->pos.y) - radial = ccpNormalize(p->pos); + if (useAnimation_) { + switch (animationType_) { + default: + case kCCParticleAnimationTypeLoopWithRandomStartFrame: + case kCCParticleAnimationTypeLoop: + { + p->elapsed += dt; + while (p->elapsed >= p->split) { + + p->currentFrame++; + if (p->currentFrame >= totalFrameCount_) + { + p->currentFrame = 0; + p->elapsed = p->elapsed - p->split; + p->split = 0.f; + } + p->split+=animationFrameData_[p->currentFrame].delay; + + } + break; + } + case kCCParticleAnimationTypeOnce: + { + //stop after one iteration + if (p->currentFrame != totalFrameCount_) + { + p->elapsed += dt; + while (p->elapsed >= p->split) { + + p->currentFrame++; + if (p->currentFrame >= totalFrameCount_) + { + p->currentFrame = totalFrameCount_; + break; + } + p->split+=animationFrameData_[p->currentFrame].delay; + } + } + break; + } + case kCCParticleAnimationTypeRandomFrame: + { + // frame does not change in random mode + break; + } + } + } - tangential = radial; - radial = ccpMult(radial, p->mode.A.radialAccel); + // Mode A: gravity, direction, tangential accel & radial accel + if( emitterMode_ == kCCParticleModeGravity ) { + CGPoint tmp, radial, tangential; + + radial = CGPointZero; + // radial acceleration + if(p->pos.x || p->pos.y) + radial = ccpNormalize(p->pos); + + tangential = radial; + radial = ccpMult(radial, p->mode.A.radialAccel); + + // tangential acceleration + float newy = tangential.x; + tangential.x = -tangential.y; + tangential.y = newy; + tangential = ccpMult(tangential, p->mode.A.tangentialAccel); + + // (gravity + radial + tangential) * dt + tmp = ccpAdd( ccpAdd( radial, tangential), mode.A.gravity); + tmp = ccpMult( tmp, dt); + p->mode.A.dir = ccpAdd( p->mode.A.dir, tmp); + tmp = ccpMult(p->mode.A.dir, dt); + p->pos = ccpAdd( p->pos, tmp ); + } - // tangential acceleration - float newy = tangential.x; - tangential.x = -tangential.y; - tangential.y = newy; - tangential = ccpMult(tangential, p->mode.A.tangentialAccel); + // Mode B: radius movement + else { + // Update the angle and radius of the particle. + p->mode.B.angle += p->mode.B.degreesPerSecond * dt; + p->mode.B.radius += p->mode.B.deltaRadius * dt; + + p->pos.x = - cosf(p->mode.B.angle) * p->mode.B.radius; + p->pos.y = - sinf(p->mode.B.angle) * p->mode.B.radius; + } - // (gravity + radial + tangential) * dt - tmp = ccpAdd( ccpAdd( radial, tangential), mode.A.gravity); - tmp = ccpMult( tmp, dt); - p->mode.A.dir = ccpAdd( p->mode.A.dir, tmp); - tmp = ccpMult(p->mode.A.dir, dt); - p->pos = ccpAdd( p->pos, tmp ); - } - - // Mode B: radius movement - else { - // Update the angle and radius of the particle. - p->mode.B.angle += p->mode.B.degreesPerSecond * dt; - p->mode.B.radius += p->mode.B.deltaRadius * dt; + // color + p->color.r += (p->deltaColor.r * dt); + p->color.g += (p->deltaColor.g * dt); + p->color.b += (p->deltaColor.b * dt); + p->color.a += (p->deltaColor.a * dt); - p->pos.x = - cosf(p->mode.B.angle) * p->mode.B.radius; - p->pos.y = - sinf(p->mode.B.angle) * p->mode.B.radius; - } - - // color - p->color.r += (p->deltaColor.r * dt); - p->color.g += (p->deltaColor.g * dt); - p->color.b += (p->deltaColor.b * dt); - p->color.a += (p->deltaColor.a * dt); - - // size - p->size += (p->deltaSize * dt); - p->size = MAX( 0, p->size ); - - // angle - p->rotation += (p->deltaRotation * dt); - - // - // update values in quad - // - - CGPoint newPos; - - if( positionType_ == kCCPositionTypeFree || positionType_ == kCCPositionTypeRelative ) { - CGPoint diff = ccpSub( currentPosition, p->startPos ); - newPos = ccpSub(p->pos, diff); + // size + p->size += (p->deltaSize * dt); + p->size = MAX( 0, p->size ); + + // angle + p->rotation += (p->deltaRotation * dt); + + // + // update values in quad + // + + CGPoint newPos; + + if( positionType_ == kCCPositionTypeFree || positionType_ == kCCPositionTypeRelative ) + { + CGPoint diff = ccpSub( currentPosition, p->startPos ); + newPos = ccpSub(p->pos, diff); + } else + newPos = p->pos; + + //translate newPos to correct position, since matrix transform isn't performed in batchnode + //don't update the particle with the new position information, it will interfere with the radius and tangential calculations + if (useBatchNode_) + { + newPos.x += positionInPixels_.x; + newPos.y += positionInPixels_.y; + } + + p->z = vertexZ_; - } else - newPos = p->pos; + updateParticleImp(self, updateParticleSel, p, newPos); + + // update particle counter + particleIdx++; - - updateParticleImp(self, updateParticleSel, p, newPos); - - // update particle counter - particleIdx++; - - } else { - // life < 0 - if( particleIdx != particleCount-1 ) - particles[particleIdx] = particles[particleCount-1]; - particleCount--; - - if( particleCount == 0 && autoRemoveOnFinish_ ) { - [self unscheduleUpdate]; - [parent_ removeChild:self cleanup:YES]; - return; + } else { + // life < 0 + NSUInteger currentIndex = p->atlasIndex; + + if( particleIdx != particleCount-1 ) + particles[particleIdx] = particles[particleCount-1]; + + if (useBatchNode_) + { + //disable the switched particle + [batchNode_ disableParticle:(atlasIndex_+currentIndex)]; + + //switch indexes + particles[particleCount-1].atlasIndex = currentIndex; + } + + particleCount--; + + if( particleCount == 0 && autoRemoveOnFinish_ ) { + [self unscheduleUpdate]; + [parent_ removeChild:self cleanup:YES]; + return; + } } - } + }//while + transformSystemDirty_ = NO; } #if CC_ENABLE_PROFILERS @@ -586,10 +753,15 @@ -(void) update: (ccTime) dt #endif #ifdef CC_USES_VBO - [self postStep]; + if (!useBatchNode_) [self postStep]; #endif } +-(void) updateWithNoTime +{ + [self update:0.0f]; +} + -(void) updateQuadWithParticle:(tCCParticle*)particle newPosition:(CGPoint)pos; { // should be overriden @@ -604,7 +776,6 @@ -(void) postStep -(void) setTexture:(CCTexture2D*) texture { - [texture_ release]; texture_ = [texture retain]; // If the new texture has No premultiplied alpha, AND the blendFunc hasn't been changed, then update it @@ -790,6 +961,54 @@ -(float) rotatePerSecondVar NSAssert( emitterMode_ == kCCParticleModeRadius, @"Particle Mode should be Radius"); return mode.B.rotatePerSecondVar; } -@end + +#pragma mark ParticleSystem - methods for batchNode rendering + +-(void) useSelfRender +{ + useBatchNode_ = NO; +} + +-(void) useBatchNode:(CCParticleBatchNode*) batchNode +{ + batchNode_ = batchNode; + useBatchNode_ = YES; + + //each particle needs a unique index + for (NSUInteger i = 0; i < totalParticles; i++) + { + particles[i].atlasIndex=i; + } +} + +-(void) batchNodeInitialization +{//override this +} + +//don't use a transform matrix, this is faster +-(void) setScale:(float) s +{ + transformSystemDirty_ = YES; + [super setScale:s]; +} + +-(void) setRotation: (float)newRotation +{ + transformSystemDirty_ = YES; + [super setRotation:newRotation]; +} + +-(void) setScaleX: (float)newScaleX +{ + transformSystemDirty_ = YES; + [super setScaleX:newScaleX]; +} + +-(void) setScaleY: (float)newScaleY +{ + transformSystemDirty_ = YES; + [super setScaleY:newScaleY]; +} +@end \ No newline at end of file diff --git a/libs/cocos2d/CCParticleSystemPoint.h b/libs/cocos2d/CCParticleSystemPoint.h index 029ad41..f0918fe 100644 --- a/libs/cocos2d/CCParticleSystemPoint.h +++ b/libs/cocos2d/CCParticleSystemPoint.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/libs/cocos2d/CCParticleSystemPoint.m b/libs/cocos2d/CCParticleSystemPoint.m index f789f04..0894d2b 100644 --- a/libs/cocos2d/CCParticleSystemPoint.m +++ b/libs/cocos2d/CCParticleSystemPoint.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -41,7 +42,7 @@ @implementation CCParticleSystemPoint --(id) initWithTotalParticles:(int) numberOfParticles +-(id) initWithTotalParticles:(NSUInteger) numberOfParticles { if( (self=[super initWithTotalParticles:numberOfParticles]) ) { @@ -81,7 +82,8 @@ -(void) updateQuadWithParticle:(tCCParticle*)p newPosition:(CGPoint)newPos // place vertices and colos in array vertices[particleIdx].pos = (ccVertex2F) {newPos.x, newPos.y}; vertices[particleIdx].size = p->size; - vertices[particleIdx].colors = p->color; + ccColor4B color = { p->color.r*255, p->color.g*255, p->color.b*255, p->color.a*255 }; + vertices[particleIdx].color = color; } -(void) postStep @@ -95,6 +97,8 @@ -(void) postStep -(void) draw { + [super draw]; + if (particleIdx==0) return; @@ -115,7 +119,7 @@ -(void) draw glVertexPointer(2,GL_FLOAT, kPointSize, 0); - glColorPointer(4, GL_FLOAT, kPointSize, (GLvoid*) offsetof(ccPointSprite, colors) ); + glColorPointer(4, GL_UNSIGNED_BYTE, kPointSize, (GLvoid*) offsetof(ccPointSprite, color) ); glEnableClientState(GL_POINT_SIZE_ARRAY_OES); glPointSizePointerOES(GL_FLOAT, kPointSize, (GLvoid*) offsetof(ccPointSprite, size) ); @@ -123,8 +127,8 @@ -(void) draw int offset = (int)vertices; glVertexPointer(2,GL_FLOAT, kPointSize, (GLvoid*) offset); - int diff = offsetof(ccPointSprite, colors); - glColorPointer(4, GL_FLOAT, kPointSize, (GLvoid*) (offset+diff)); + int diff = offsetof(ccPointSprite, color); + glColorPointer(4, GL_UNSIGNED_BYTE, kPointSize, (GLvoid*) (offset+diff)); glEnableClientState(GL_POINT_SIZE_ARRAY_OES); diff = offsetof(ccPointSprite, size); diff --git a/libs/cocos2d/CCParticleSystemQuad.h b/libs/cocos2d/CCParticleSystemQuad.h index eea9edd..baeb4f1 100644 --- a/libs/cocos2d/CCParticleSystemQuad.h +++ b/libs/cocos2d/CCParticleSystemQuad.h @@ -1,8 +1,10 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2008-2010 Ricardo Quesada * Copyright (c) 2009 Leonardo Kasperavičius + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,6 +31,7 @@ #import "ccConfig.h" @class CCSpriteFrame; +@class CCAnimation; /** CCParticleSystemQuad is a subclass of CCParticleSystem @@ -42,17 +45,38 @@ - On 3rd gen iPhone and iPads: It is MUCH faster than CCParticleSystemPoint - It consumes more RAM and more GPU memory than CCParticleSystemPoint - It supports subrects + - It supports batched rendering since 1.1 @since v0.8 */ @interface CCParticleSystemQuad : CCParticleSystem { - ccV2F_C4F_T2F_Quad *quads_; // quads to be rendered + ccV3F_C4B_T2F_Quad *quads_; // quads to be rendered GLushort *indices_; // indices + CGRect textureRect_; #if CC_USES_VBO GLuint quadsID_; // VBO id #endif + + CGPoint particleAnchorPoint_; + CCAnimation *animation_; } +@property (nonatomic, readwrite) ccV3F_C4B_T2F_Quad* quads; +/** animation that holds the sprite frames + @since 1.1 + */ +@property (nonatomic, retain) CCAnimation* animation; + +/** create system with properties from plist, batchnode and rect on the sprite sheet + use nil for batchNode to not use batch rendering + if rect is (0.0f,0.0f,0.0f,0.0f) the whole texture width and height will be used +*/ ++(id) particleWithFile:(NSString*) plistFile batchNode:(CCParticleBatchNode*) batchNode rect:(CGRect) rect; + +-(id) initWithFile:(NSString *)plistFile batchNode:(CCParticleBatchNode*) batchNode rect:(CGRect) rect; + +-(id) initWithTotalParticles:(NSUInteger)numberOfParticles batchNode:(CCParticleBatchNode*) batchNode rect:(CGRect) rect; + /** initialices the indices for the vertices */ -(void) initIndices; @@ -61,14 +85,24 @@ /** Sets a new CCSpriteFrame as particle. WARNING: this method is experimental. Use setTexture:withRect instead. + uses the texture and the rect of the spriteframe to call setTexture:Rect: @since v0.99.4 */ --(void)setDisplayFrame:(CCSpriteFrame*)spriteFrame; +-(void) setDisplayFrame:(CCSpriteFrame*)spriteFrame; /** Sets a new texture with a rect. The rect is in Points. @since v0.99.4 */ -(void) setTexture:(CCTexture2D *)texture withRect:(CGRect)rect; -@end +/** sets a animation that will be used for each particle, default particle anchorpoint of (0.5,0.5) + @since 1.1 + */ +-(void) setAnimation:(CCAnimation*) anim; +/** sets a animation that will be used for each particle, and the anchor point for each particle + Note, offsets of sprite frames are not used + @since 1.1 + */ +-(void) setAnimation:(CCAnimation*) anim withAnchorPoint:(CGPoint) particleAP; +@end \ No newline at end of file diff --git a/libs/cocos2d/CCParticleSystemQuad.m b/libs/cocos2d/CCParticleSystemQuad.m index 219f2cc..7c2c591 100644 --- a/libs/cocos2d/CCParticleSystemQuad.m +++ b/libs/cocos2d/CCParticleSystemQuad.m @@ -1,8 +1,10 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2008-2010 Ricardo Quesada * Copyright (c) 2009 Leonardo Kasperavičius + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,21 +36,71 @@ #import "CCTextureCache.h" #import "ccMacros.h" #import "CCSpriteFrame.h" +#import "CCParticleBatchNode.h" +#import "CCTextureAtlas.h" +#import "CCAnimation.h" // support #import "Support/OpenGL_Internal.h" #import "Support/CGPointExtension.h" +@interface CCParticleSystemQuad (private) +-(id) initializeParticleSystemWithBatchNode:(CCParticleBatchNode*) batchNode rect:(CGRect) rect; +@end + @implementation CCParticleSystemQuad +@synthesize quads=quads_; +@synthesize animation=animation_; ++(id) particleWithFile:(NSString*) plistFile batchNode:(CCParticleBatchNode*) batchNode rect:(CGRect) rect +{ + return [[[self alloc] initWithFile:plistFile batchNode:batchNode rect:rect] autorelease]; +} + +-(id) initWithFile:(NSString *)plistFile batchNode:(CCParticleBatchNode*) batchNode rect:(CGRect) rect +{ + batchNode_ = batchNode; + textureRect_ = rect; + return [super initWithFile:plistFile]; +} -// overriding the init method --(id) initWithTotalParticles:(int) numberOfParticles +// overriding the init method, this is the base initializer +-(id) initWithTotalParticles:(NSUInteger)numberOfParticles batchNode:(CCParticleBatchNode*) batchNode rect:(CGRect) rect { - // base initialization + batchNode_ = batchNode; + textureRect_ = rect; + + //first super then self if( (self=[super initWithTotalParticles:numberOfParticles]) ) { + if ([self initializeParticleSystemWithBatchNode:batchNode rect:rect]==nil) return nil; + } + + return self; +} + +-(id) initWithTotalParticles:(NSUInteger) numberOfParticles +{ + CCParticleBatchNode* batchNode = nil; + CGRect rect = CGRectMake(0.0f,0.0f,0.0f,0.0f); + if (batchNode_) + { + batchNode = batchNode_; + rect = textureRect_; + } + return [self initWithTotalParticles:numberOfParticles batchNode:batchNode rect:rect]; +} + +-(id) initializeParticleSystemWithBatchNode:(CCParticleBatchNode*) batchNode rect:(CGRect) rect +{ + if (rect.size.width == 0.f && rect.size.height == 0.f && batchNode != nil) + { + rect.size = CGSizeMake([batchNode.textureAtlas.texture pixelsWide], [batchNode.textureAtlas.texture pixelsHigh]); + } - // allocating data space + // allocating data space + if (batchNode == nil) + { + quads_ = calloc( sizeof(quads_[0]) * totalParticles, 1 ); indices_ = calloc( sizeof(indices_[0]) * totalParticles * 6, 1 ); @@ -64,10 +116,10 @@ -(id) initWithTotalParticles:(int) numberOfParticles } // initialize only once the texCoords and the indices - [self initTexCoordsWithRect:CGRectMake(0, 0, [texture_ pixelsWide], [texture_ pixelsHigh])]; + [self initTexCoordsWithRect:rect]; [self initIndices]; - -#if CC_USES_VBO + + #if CC_USES_VBO // create the VBO buffer glGenBuffers(1, &quadsID_); @@ -75,65 +127,113 @@ -(id) initWithTotalParticles:(int) numberOfParticles glBindBuffer(GL_ARRAY_BUFFER, quadsID_); glBufferData(GL_ARRAY_BUFFER, sizeof(quads_[0])*totalParticles, quads_,GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); -#endif + #endif + + useBatchNode_ = NO; } + else { + quads_ = NULL; + indices_ = NULL; - return self; + batchNode_ = batchNode; + + //can't use setTexture here since system isn't added to batchnode yet + texture_ = [batchNode.textureAtlas.texture retain]; + textureRect_ = rect; + + useBatchNode_ = YES; + } + + particleAnchorPoint_ = ccp(0.5f,0.5f); + animation_ = nil; + + return [NSNumber numberWithInt:1]; } -(void) dealloc { - free(quads_); - free(indices_); + if (quads_) free(quads_); + if (indices_) free(indices_); #if CC_USES_VBO - glDeleteBuffers(1, &quadsID_); + if (!useBatchNode_) glDeleteBuffers(1, &quadsID_); #endif + [animation_ release]; [super dealloc]; } -// rect is in Points coordinates. +// pointRect is in Points coordinates. -(void) initTexCoordsWithRect:(CGRect)pointRect { - // convert to Tex coords + textureRect_ = pointRect; - CGRect rect = CGRectMake( - pointRect.origin.x * CC_CONTENT_SCALE_FACTOR(), - pointRect.origin.y * CC_CONTENT_SCALE_FACTOR(), - pointRect.size.width * CC_CONTENT_SCALE_FACTOR(), - pointRect.size.height * CC_CONTENT_SCALE_FACTOR() ); - - GLfloat wide = [texture_ pixelsWide]; - GLfloat high = [texture_ pixelsHigh]; + if (texture_) + { + // convert to pixels coords + CGRect rect = CGRectMake( + pointRect.origin.x * CC_CONTENT_SCALE_FACTOR(), + pointRect.origin.y * CC_CONTENT_SCALE_FACTOR(), + pointRect.size.width * CC_CONTENT_SCALE_FACTOR(), + pointRect.size.height * CC_CONTENT_SCALE_FACTOR() ); + + GLfloat wide = [texture_ pixelsWide]; + GLfloat high = [texture_ pixelsHigh]; + #if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL - GLfloat left = (rect.origin.x*2+1) / (wide*2); - GLfloat bottom = (rect.origin.y*2+1) / (high*2); - GLfloat right = left + (rect.size.width*2-2) / (wide*2); - GLfloat top = bottom + (rect.size.height*2-2) / (high*2); + GLfloat left = (rect.origin.x*2+1) / (wide*2); + GLfloat bottom = (rect.origin.y*2+1) / (high*2); + GLfloat right = left + (rect.size.width*2-2) / (wide*2); + GLfloat top = bottom + (rect.size.height*2-2) / (high*2); #else - GLfloat left = rect.origin.x / wide; - GLfloat bottom = rect.origin.y / high; - GLfloat right = left + rect.size.width / wide; - GLfloat top = bottom + rect.size.height / high; + GLfloat left = rect.origin.x / wide; + GLfloat bottom = rect.origin.y / high; + GLfloat right = left + rect.size.width / wide; + GLfloat top = bottom + rect.size.height / high; #endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL // Important. Texture in cocos2d are inverted, so the Y component should be inverted - CC_SWAP( top, bottom); - - for(NSUInteger i=0; ibl.colors = p->color; - quad->br.colors = p->color; - quad->tl.colors = p->color; - quad->tr.colors = p->color; + ccV3F_C4B_T2F_Quad *quad; + + if (useBatchNode_) + { + ccV3F_C4B_T2F_Quad *batchQuads = [[batchNode_ textureAtlas] quads]; + quad = &(batchQuads[atlasIndex_+p->atlasIndex]); + } + else quad = &(quads_[particleIdx]); + + ccColor4B color = { p->color.r*255, p->color.g*255, p->color.b*255, p->color.a*255}; + quad->bl.colors = color; + quad->br.colors = color; + quad->tl.colors = color; + quad->tr.colors = color; // vertices - GLfloat size_2 = p->size/2; - if( p->rotation ) { - GLfloat x1 = -size_2; - GLfloat y1 = -size_2; + GLfloat pos1x, pos1y, pos2x, pos2y; + if (useAnimation_) + { + //p->size = scale + ccAnimationFrameData frameData = animationFrameData_[p->currentFrame]; + + pos1x = (-particleAnchorPoint_.x * frameData.size.width) * p->size; + pos1y = (-particleAnchorPoint_.y * frameData.size.height) * p->size; + pos2x = ((1.f - particleAnchorPoint_.x) * frameData.size.width) * p->size; + pos2y = ((1.f - particleAnchorPoint_.y) * frameData.size.height) * p->size; + + // set the texture coordinates to the (new) frame + quad->tl.texCoords = frameData.texCoords.tl; + quad->tr.texCoords = frameData.texCoords.tr; + quad->bl.texCoords = frameData.texCoords.bl; + quad->br.texCoords = frameData.texCoords.br; + + } + else + { + float size2 = p->size/2.f; + pos1x = -size2;//leftside x + pos1y = -size2; //bottom side y + pos2x = size2; //rightside x + pos2y = size2; //topside y + } + + GLfloat r; + + //positionTypeFree doesn't react to transformations of parent + if (useBatchNode_ && positionType_!=kCCPositionTypeFree) + {//transformation need to be applied to quad manually + + pos1x = pos1x * scaleX_; + pos1y = pos1y * scaleY_; + + pos2x = pos2x * scaleX_; + pos2y = pos2y * scaleY_; + + r = (GLfloat)-CC_DEGREES_TO_RADIANS(p->rotation+rotation_); + } + else + r = (GLfloat)-CC_DEGREES_TO_RADIANS(p->rotation); + + //don't transform particles if type is free + if (useBatchNode_ ) + { + GLfloat x1 = pos1x; + GLfloat y1 = pos1y; + + GLfloat x2 = pos2x; + GLfloat y2 = pos2y; + GLfloat x = newPos.x; + GLfloat y = newPos.y; + + GLfloat cr = cosf(r); + GLfloat sr = sinf(r); + GLfloat cr2 = cosf(r); + GLfloat sr2 = sinf(r); + GLfloat ax = x1 * cr - y1 * sr2 + x; + GLfloat ay = x1 * sr + y1 * cr2 + y; + GLfloat bx = x2 * cr - y1 * sr2 + x; + GLfloat by = x2 * sr + y1 * cr2 + y; + GLfloat cx = x2 * cr - y2 * sr2 + x; + GLfloat cy = x2 * sr + y2 * cr2 + y; + GLfloat dx = x1 * cr - y2 * sr2 + x; + GLfloat dy = x1 * sr + y2 * cr2 + y; + + // bottom-left + quad->bl.vertices.x = ax; + quad->bl.vertices.y = ay; + quad->bl.vertices.z = p->z; + + // bottom-right vertex: + quad->br.vertices.x = bx; + quad->br.vertices.y = by; + quad->br.vertices.z = p->z; + + // top-left vertex: + quad->tl.vertices.x = dx; + quad->tl.vertices.y = dy; + quad->tl.vertices.z = p->z; + // top-right vertex: + quad->tr.vertices.x = cx; + quad->tr.vertices.y = cy; + quad->tr.vertices.z = p->z; + } + else if( p->rotation) { + GLfloat x1 = pos1x; + GLfloat y1 = pos1y; + + GLfloat x2 = pos2x; + GLfloat y2 = pos2y; - GLfloat x2 = size_2; - GLfloat y2 = size_2; GLfloat x = newPos.x; GLfloat y = newPos.y; - GLfloat r = (GLfloat)-CC_DEGREES_TO_RADIANS(p->rotation); GLfloat cr = cosf(r); GLfloat sr = sinf(r); + GLfloat ax = x1 * cr - y1 * sr + x; GLfloat ay = x1 * sr + y1 * cr + y; GLfloat bx = x2 * cr - y1 * sr + x; @@ -227,20 +421,20 @@ -(void) updateQuadWithParticle:(tCCParticle*)p newPosition:(CGPoint)newPos quad->tr.vertices.y = cy; } else { // bottom-left vertex: - quad->bl.vertices.x = newPos.x - size_2; - quad->bl.vertices.y = newPos.y - size_2; + quad->bl.vertices.x = newPos.x + pos1x; + quad->bl.vertices.y = newPos.y + pos1y; // bottom-right vertex: - quad->br.vertices.x = newPos.x + size_2; - quad->br.vertices.y = newPos.y - size_2; + quad->br.vertices.x = newPos.x + pos2x; + quad->br.vertices.y = newPos.y + pos1y; // top-left vertex: - quad->tl.vertices.x = newPos.x - size_2; - quad->tl.vertices.y = newPos.y + size_2; + quad->tl.vertices.x = newPos.x + pos1x; + quad->tl.vertices.y = newPos.y + pos2y; // top-right vertex: - quad->tr.vertices.x = newPos.x + size_2; - quad->tr.vertices.y = newPos.y + size_2; + quad->tr.vertices.x = newPos.x + pos2x; + quad->tr.vertices.y = newPos.y + pos2y; } } @@ -256,6 +450,10 @@ -(void) postStep // overriding draw method -(void) draw { + [super draw]; + + NSAssert(!useBatchNode_,@"draw should not be called when added to a particleBatchNode"); + // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY // Unneeded states: - @@ -267,25 +465,25 @@ -(void) draw #if CC_USES_VBO glBindBuffer(GL_ARRAY_BUFFER, quadsID_); - glVertexPointer(2,GL_FLOAT, kQuadSize, 0); + glVertexPointer(3,GL_FLOAT, kQuadSize, 0); - glColorPointer(4, GL_FLOAT, kQuadSize, (GLvoid*) offsetof(ccV2F_C4F_T2F,colors) ); + glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*) offsetof(ccV3F_C4B_T2F,colors) ); - glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*) offsetof(ccV2F_C4F_T2F,texCoords) ); + glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*) offsetof(ccV3F_C4B_T2F,texCoords) ); #else // vertex array list NSUInteger offset = (NSUInteger) quads_; // vertex - NSUInteger diff = offsetof( ccV2F_C4F_T2F, vertices); + NSUInteger diff = offsetof( ccV3F_C4B_T2F, vertices); glVertexPointer(2,GL_FLOAT, kQuadSize, (GLvoid*) (offset+diff) ); // color - diff = offsetof( ccV2F_C4F_T2F, colors); - glColorPointer(4, GL_FLOAT, kQuadSize, (GLvoid*)(offset + diff)); + diff = offsetof( ccV3F_C4B_T2F, colors); + glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*)(offset + diff)); // tex coords - diff = offsetof( ccV2F_C4F_T2F, texCoords); + diff = offsetof( ccV3F_C4B_T2F, texCoords); glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*)(offset + diff)); #endif // ! CC_USES_VBO @@ -295,7 +493,7 @@ -(void) draw glBlendFunc( blendFunc_.src, blendFunc_.dst ); NSAssert( particleIdx == particleCount, @"Abnormal error in particle quad"); - glDrawElements(GL_TRIANGLES, particleIdx*6, GL_UNSIGNED_SHORT, indices_); + glDrawElements(GL_TRIANGLES, (GLsizei) particleIdx*6, GL_UNSIGNED_SHORT, indices_); // restore blend state if( newBlend ) @@ -309,6 +507,160 @@ -(void) draw // - } -@end +-(void) useSelfRender +{ + if (useBatchNode_) + { + [self initializeParticleSystemWithBatchNode:nil rect:textureRect_]; + useBatchNode_ = NO; + } +} + +-(void) batchNodeInitialization +{ + [self initTexCoordsWithRect:textureRect_]; +} + +-(void) useBatchNode:(CCParticleBatchNode*) batchNode +{ + if (!useBatchNode_) + { + [super useBatchNode:batchNode]; + + if (quads_) free(quads_); + quads_ = NULL; + + if (indices_) free(indices_); + indices_ = NULL; + +#if CC_USES_VBO + glDeleteBuffers(1, &quadsID_); +#endif + } +} + +-(void) setAnimation:(CCAnimation*)anim +{ + [self setAnimation:anim withAnchorPoint:ccp(0.5f,0.5f)]; +} +// animation +-(void) setAnimation:(CCAnimation*)anim withAnchorPoint:(CGPoint) particleAP +{ + NSAssert (anim != nil,@"animation is nil"); + + [anim retain]; + [animation_ release]; + animation_ = anim; + + particleAnchorPoint_ = particleAP; + + + NSArray* frames = animation_.frames; + + if ([frames count] == 0) + { + useAnimation_ = NO; + CCLOG(@"no frames in animation"); + return; + } + + CCSpriteFrame *frame = [[frames objectAtIndex:0] spriteFrame]; + if ([frame offsetInPixels].x != 0.f || [frame offsetInPixels].y != 0.f) + { + CCLOG(@"Particle animation, offset will not be taken into account"); + } + + if (batchNode_) + { + NSAssert (batchNode_.texture.name == texture_.name,@"CCParticleSystemQuad can only use a animation with the same texture as the batchnode"); + } + else + { + CCSpriteFrame* frame = ([[frames objectAtIndex:0] spriteFrame]); + self.texture = frame.texture; + } + + totalFrameCount_ = [frames count]; + + if (animationFrameData_) + { + free(animationFrameData_); + animationFrameData_ = NULL; + } + + // allocate memory for an array that will store data of the animation in the easies usable way for fast per frame updates of the particle system + animationFrameData_ = malloc( sizeof(animationFrameData_[0]) * totalFrameCount_ ); + + useAnimation_ = YES; + + //same as CCAnimate + float newUnitOfTimeValue = animation_.duration / animation_.totalDelayUnits; + + for (int i = 0; i < totalFrameCount_; i++) { + + CCAnimationFrame *animationFrame = [frames objectAtIndex:i]; + CCSpriteFrame* frame = animationFrame.spriteFrame; + + CGRect rect = [frame rectInPixels]; + + animationFrameData_[i].delay = newUnitOfTimeValue * animationFrame.delayUnits; + animationFrameData_[i].size = rect.size; + + // now calculate the texture coordinates for the frame + float left,right,top,bottom; + ccT2F_Quad quad; + GLfloat atlasWidth = (GLfloat)texture_.pixelsWide; + GLfloat atlasHeight = (GLfloat)texture_.pixelsHigh; + + if(frame.rotated){ +#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL + left = (2*rect.origin.x+1)/(2*atlasWidth); + right = left+(rect.size.height*2-2)/(2*atlasWidth); + top = (2*rect.origin.y+1)/(2*atlasHeight); + bottom = top+(rect.size.width*2-2)/(2*atlasHeight); +#else + left = rect.origin.x/atlasWidth; + right = left+(rect.size.height/atlasWidth); + top = rect.origin.y/atlasHeight; + bottom = top+(rect.size.width/atlasHeight); +#endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL + + quad.bl.u = left; + quad.bl.v = top; + quad.br.u = left; + quad.br.v = bottom; + quad.tl.u = right; + quad.tl.v = top; + quad.tr.u = right; + quad.tr.v = bottom; + + } else { +#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL + left = (2*rect.origin.x+1)/(2*atlasWidth); + right = left + (rect.size.width*2-2)/(2*atlasWidth); + top = (2*rect.origin.y+1)/(2*atlasHeight); + bottom = top + (rect.size.height*2-2)/(2*atlasHeight); +#else + left = rect.origin.x/atlasWidth; + right = left + rect.size.width/atlasWidth; + top = rect.origin.y/atlasHeight; + bottom = top + rect.size.height/atlasHeight; +#endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL + + quad.bl.u = left; + quad.bl.v = bottom; + quad.br.u = right; + quad.br.v = bottom; + quad.tl.u = left; + quad.tl.v = top; + quad.tr.u = right; + quad.tr.v = top; + } + + animationFrameData_[i].texCoords = quad; + + } // for +} +@end \ No newline at end of file diff --git a/libs/cocos2d/CCProgressTimer.h b/libs/cocos2d/CCProgressTimer.h index 6661a6f..9a07f2f 100644 --- a/libs/cocos2d/CCProgressTimer.h +++ b/libs/cocos2d/CCProgressTimer.h @@ -57,7 +57,7 @@ typedef enum { CCSprite *sprite_; int vertexDataCount_; - ccV2F_C4F_T2F *vertexData_; + ccV2F_C4B_T2F *vertexData_; } /** Change the percentage to change progress. */ diff --git a/libs/cocos2d/CCProgressTimer.m b/libs/cocos2d/CCProgressTimer.m index 20c66c6..4e697b2 100644 --- a/libs/cocos2d/CCProgressTimer.m +++ b/libs/cocos2d/CCProgressTimer.m @@ -87,14 +87,8 @@ -(void)dealloc -(void)setPercentage:(float) percentage { - if(percentage_ != percentage){ - if(percentage_ < 0.f) - percentage_ = 0.f; - else if(percentage > 100.0f) - percentage_ = 100.f; - else - percentage_ = percentage; - + if(percentage_ != percentage) { + percentage_ = clampf( percentage, 0, 100); [self updateProgress]; } } @@ -148,16 +142,18 @@ -(ccVertex2F)vertexFromTexCoord:(CGPoint) texCoord ret.y = tmp.y; return ret; } --(void)updateColor { - ccColor4F color = ccc4FFromccc3B(sprite_.color); + +-(void)updateColor +{ + GLubyte op = sprite_.opacity; + ccColor3B c3b = sprite_.color; + + ccColor4B color = { c3b.r, c3b.g, c3b.b, op }; if([sprite_.texture hasPremultipliedAlpha]){ - float op = sprite_.opacity/255.f; - color.r *= op; - color.g *= op; - color.b *= op; - color.a = op; - } else - color.a = sprite_.opacity/255.f; + color.r *= op/255; + color.g *= op/255; + color.b *= op/255; + } if(vertexData_){ for (int i=0; i < vertexDataCount_; ++i) { @@ -295,7 +291,7 @@ -(void)updateRadial if(!vertexData_) { vertexDataCount_ = index + 3; - vertexData_ = malloc(vertexDataCount_ * sizeof(ccV2F_C4F_T2F)); + vertexData_ = malloc(vertexDataCount_ * sizeof(ccV2F_C4B_T2F)); NSAssert( vertexData_, @"CCProgressTimer. Not enough memory"); [self updateColor]; @@ -362,13 +358,14 @@ -(void)updateBar CGPoint tMax = ccp(sprite_.texture.maxS,sprite_.texture.maxT); unsigned char vIndexes[2] = {0,0}; + unsigned char index = 0; // We know vertex data is always equal to the 4 corners // If we don't have vertex data then we create it here and populate // the side of the bar vertices that won't ever change. if (!vertexData_) { vertexDataCount_ = kProgressTextureCoordsCount; - vertexData_ = malloc(vertexDataCount_ * sizeof(ccV2F_C4F_T2F)); + vertexData_ = malloc(vertexDataCount_ * sizeof(ccV2F_C4B_T2F)); NSAssert( vertexData_, @"CCProgressTimer. Not enough memory"); if(type_ == kCCProgressTimerTypeHorizontalBarLR){ @@ -385,7 +382,7 @@ -(void)updateBar vertexData_[vIndexes[1] = 2].texCoords = (ccTex2F){tMax.x, 0}; } - unsigned char index = vIndexes[0]; + index = vIndexes[0]; vertexData_[index].vertices = [self vertexFromTexCoord:ccp(vertexData_[index].texCoords.u, vertexData_[index].texCoords.v)]; index = vIndexes[1]; @@ -393,13 +390,13 @@ -(void)updateBar if (sprite_.flipY || sprite_.flipX) { if (sprite_.flipX) { - unsigned char index = vIndexes[0]; + index = vIndexes[0]; vertexData_[index].texCoords.u = tMax.x - vertexData_[index].texCoords.u; index = vIndexes[1]; vertexData_[index].texCoords.u = tMax.x - vertexData_[index].texCoords.u; } if(sprite_.flipY){ - unsigned char index = vIndexes[0]; + index = vIndexes[0]; vertexData_[index].texCoords.v = tMax.y - vertexData_[index].texCoords.v; index = vIndexes[1]; vertexData_[index].texCoords.v = tMax.y - vertexData_[index].texCoords.v; @@ -423,20 +420,20 @@ -(void)updateBar vertexData_[vIndexes[1] = 3].texCoords = (ccTex2F){tMax.x, tMax.y*alpha}; } - unsigned char index = vIndexes[0]; + index = vIndexes[0]; vertexData_[index].vertices = [self vertexFromTexCoord:ccp(vertexData_[index].texCoords.u, vertexData_[index].texCoords.v)]; index = vIndexes[1]; vertexData_[index].vertices = [self vertexFromTexCoord:ccp(vertexData_[index].texCoords.u, vertexData_[index].texCoords.v)]; if (sprite_.flipY || sprite_.flipX) { if (sprite_.flipX) { - unsigned char index = vIndexes[0]; + index = vIndexes[0]; vertexData_[index].texCoords.u = tMax.x - vertexData_[index].texCoords.u; index = vIndexes[1]; vertexData_[index].texCoords.u = tMax.x - vertexData_[index].texCoords.u; } if(sprite_.flipY){ - unsigned char index = vIndexes[0]; + index = vIndexes[0]; vertexData_[index].texCoords.v = tMax.y - vertexData_[index].texCoords.v; index = vIndexes[1]; vertexData_[index].texCoords.v = tMax.y - vertexData_[index].texCoords.v; @@ -462,6 +459,8 @@ -(CGPoint)boundaryTexCoord:(char)index -(void)draw { + [super draw]; + if(!vertexData_)return; if(!sprite_)return; ccBlendFunc blendFunc = sprite_.blendFunc; @@ -473,9 +472,9 @@ -(void)draw // Replaced [texture_ drawAtPoint:CGPointZero] with my own vertexData // Everything above me and below me is copied from CCTextureNode's draw glBindTexture(GL_TEXTURE_2D, sprite_.texture.name); - glVertexPointer(2, GL_FLOAT, sizeof(ccV2F_C4F_T2F), &vertexData_[0].vertices); - glTexCoordPointer(2, GL_FLOAT, sizeof(ccV2F_C4F_T2F), &vertexData_[0].texCoords); - glColorPointer(4, GL_FLOAT, sizeof(ccV2F_C4F_T2F), &vertexData_[0].colors); + glVertexPointer(2, GL_FLOAT, sizeof(ccV2F_C4B_T2F), &vertexData_[0].vertices); + glTexCoordPointer(2, GL_FLOAT, sizeof(ccV2F_C4B_T2F), &vertexData_[0].texCoords); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ccV2F_C4B_T2F), &vertexData_[0].colors); if(type_ == kCCProgressTimerTypeRadialCCW || type_ == kCCProgressTimerTypeRadialCW){ glDrawArrays(GL_TRIANGLE_FAN, 0, vertexDataCount_); } else if (type_ == kCCProgressTimerTypeHorizontalBarLR || diff --git a/libs/cocos2d/CCProtocols.h b/libs/cocos2d/CCProtocols.h index f40c1ab..f7043fc 100644 --- a/libs/cocos2d/CCProtocols.h +++ b/libs/cocos2d/CCProtocols.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -121,4 +122,4 @@ @since v0.99.5 */ -(void) updateProjection; -@end \ No newline at end of file +@end diff --git a/libs/cocos2d/CCRenderTexture.h b/libs/cocos2d/CCRenderTexture.h old mode 100755 new mode 100644 index 10500f4..5af73fa --- a/libs/cocos2d/CCRenderTexture.h +++ b/libs/cocos2d/CCRenderTexture.h @@ -49,6 +49,8 @@ enum the render texture to your scene and treat it like any other CocosNode. There are also functions for saving the render texture to disk in PNG or JPG format. + + @since v0.8.1 */ @interface CCRenderTexture : CCNode @@ -59,8 +61,6 @@ enum CCSprite* sprite_; GLenum pixelFormat_; - GLfloat clearColor_[4]; - } /** The CCSprite being used. @@ -98,8 +98,14 @@ enum -(BOOL)saveBuffer:(NSString*)name; /** saves the texture into a file. The format can be JPG or PNG */ -(BOOL)saveBuffer:(NSString*)name format:(int)format; -/* get buffer as UIImage, can only save a render buffer which has a RGBA8888 pixel format */ +/** get buffer as UIImage, can only save a render buffer which has a RGBA8888 pixel format */ -(NSData*)getUIImageAsDataFromBuffer:(int) format; +/** get buffer as UIImage + In rare cases getUIImageFromBuffer produces artifacts, a workaround for this is + NSData *imageData = [renderer getUIImageAsDataFromBuffer:kCCImageFormatPNG]; + UIImage *image = [UIImage imageWithData:imageData]; + */ +-(UIImage *)getUIImageFromBuffer; #endif // __IPHONE_OS_VERSION_MAX_ALLOWED diff --git a/libs/cocos2d/CCRenderTexture.m b/libs/cocos2d/CCRenderTexture.m old mode 100755 new mode 100644 index 42e5f7b..83ca652 --- a/libs/cocos2d/CCRenderTexture.m +++ b/libs/cocos2d/CCRenderTexture.m @@ -28,12 +28,7 @@ #import "CCDirector.h" #import "ccMacros.h" #import "Support/ccUtils.h" - -@interface CCRenderTexture (private) - -- (void) saveGLstate; -- (void) restoreGLstate; -@end +#import "Support/CCFileUtils.h" @implementation CCRenderTexture @@ -113,60 +108,53 @@ -(void)dealloc [super dealloc]; } - -(void)begin { - // issue #878 save opengl state - [self saveGLstate]; - - CC_DISABLE_DEFAULT_GL_STATES(); // Save the current matrix glPushMatrix(); CGSize texSize = [texture_ contentSizeInPixels]; - - // Calculate the adjustment ratios based on the old and new projections - CGSize size = [[CCDirector sharedDirector] displaySizeInPixels]; - float widthRatio = size.width / texSize.width; - float heightRatio = size.height / texSize.height; - - // Adjust the orthographic propjection and viewport - ccglOrtho((float)-1.0 / widthRatio, (float)1.0 / widthRatio, (float)-1.0 / heightRatio, (float)1.0 / heightRatio, -1,1); - glViewport(0, 0, texSize.width, texSize.height); - - glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &oldFBO_); - ccglBindFramebuffer(CC_GL_FRAMEBUFFER, fbo_);//Will direct drawing to the frame buffer created above - - CC_ENABLE_DEFAULT_GL_STATES(); -} - --(void)beginWithClear:(float)r g:(float)g b:(float)b a:(float)a -{ - // issue #878 save opengl state - [self saveGLstate]; - - CC_DISABLE_DEFAULT_GL_STATES(); - // Save the current matrix - glPushMatrix(); - CGSize texSize = [texture_ contentSizeInPixels]; // Calculate the adjustment ratios based on the old and new projections CGSize size = [[CCDirector sharedDirector] displaySizeInPixels]; float widthRatio = size.width / texSize.width; float heightRatio = size.height / texSize.height; + // Adjust the orthographic propjection and viewport ccglOrtho((float)-1.0 / widthRatio, (float)1.0 / widthRatio, (float)-1.0 / heightRatio, (float)1.0 / heightRatio, -1,1); glViewport(0, 0, texSize.width, texSize.height); + glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &oldFBO_); ccglBindFramebuffer(CC_GL_FRAMEBUFFER, fbo_);//Will direct drawing to the frame buffer created above + // Issue #1145 + // There is no need to enable the default GL states here + // but since CCRenderTexture is mostly used outside the "render" loop + // these states needs to be enabled. + // Since this bug was discovered in API-freeze (very close of 1.0 release) + // This bug won't be fixed to prevent incompatibilities with code. + // + // If you understand the above mentioned message, then you can comment the following line + // and enable the gl states manually, in case you need them. + CC_ENABLE_DEFAULT_GL_STATES(); +} + +-(void)beginWithClear:(float)r g:(float)g b:(float)b a:(float)a +{ + [self begin]; + + // save clear color + GLfloat clearColor[4]; + glGetFloatv(GL_COLOR_CLEAR_VALUE,clearColor); + glClearColor(r, g, b, a); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - CC_ENABLE_DEFAULT_GL_STATES(); + + // restore clear color + glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); } -(void)end @@ -176,29 +164,14 @@ -(void)end glPopMatrix(); CGSize size = [[CCDirector sharedDirector] displaySizeInPixels]; glViewport(0, 0, size.width, size.height); - [self restoreGLstate]; - } -(void)clear:(float)r g:(float)g b:(float)b a:(float)a { - [self begin]; - glClearColor(r, g, b, a); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - + [self beginWithClear:r g:g b:b a:a]; [self end]; } --(void) saveGLstate -{ - glGetFloatv(GL_COLOR_CLEAR_VALUE,clearColor_); -} - -- (void) restoreGLstate -{ - glClearColor(clearColor_[0], clearColor_[1], clearColor_[2], clearColor_[3]); -} - #pragma mark RenderTexture - Save Image #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED @@ -209,15 +182,71 @@ -(BOOL)saveBuffer:(NSString*)name -(BOOL)saveBuffer:(NSString*)fileName format:(int)format { - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:fileName]; + NSString *fullPath = [CCFileUtils fullPathFromRelativePath:fileName]; NSData *data = [self getUIImageAsDataFromBuffer:format]; return [data writeToFile:fullPath atomically:YES]; } +/* get buffer as UIImage */ +-(UIImage *)getUIImageFromBuffer +{ + NSAssert(pixelFormat_ == kCCTexture2DPixelFormat_RGBA8888,@"only RGBA8888 can be saved as image"); + + CGSize s = [texture_ contentSizeInPixels]; + int tx = s.width; + int ty = s.height; + + int bitsPerComponent = 8; + int bitsPerPixel = 4 * 8; + int bytesPerPixel = bitsPerPixel / 8; + int bytesPerRow = bytesPerPixel * tx; + NSInteger myDataLength = bytesPerRow * ty; + + GLubyte *buffer = malloc(sizeof(GLubyte)*myDataLength); + GLubyte *pixels = malloc(sizeof(GLubyte)*myDataLength); + + if( ! (buffer && pixels) ) { + CCLOG(@"cocos2d: CCRenderTexture#getUIImageFromBuffer: not enough memory"); + free(buffer); + free(pixels); + return nil; + } + + [self begin]; + glReadPixels(0,0,tx,ty,GL_RGBA,GL_UNSIGNED_BYTE, buffer); + [self end]; + + // flip image + int x,y; + + for(y = 0; y creationTime[0] = seg->creationTime[seg->end - 1]; - int v = (seg->end-1)*6; - int c = (seg->end-1)*4; + NSUInteger v = (seg->end-1)*6; + NSUInteger c = (seg->end-1)*4; newSeg->verts[0] = seg->verts[v]; newSeg->verts[1] = seg->verts[v+1]; newSeg->verts[2] = seg->verts[v+2]; @@ -224,8 +224,8 @@ -(void)addPointAt:(CGPoint)location width:(float)w seg->end++; } - int v = seg->end*6; - int c = seg->end*4; + NSUInteger v = seg->end*6; + NSUInteger c = seg->end*4; // add new vertex seg->creationTime[seg->end] = curTime_; seg->verts[v] = p1.x; @@ -251,6 +251,8 @@ -(void)addPointAt:(CGPoint)location width:(float)w -(void) draw { + [super draw]; + if ([segments_ count] > 0) { // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY @@ -345,10 +347,10 @@ -(void)draw:(float)curTime fadeTime:(float)fadeTime color:(ccColor4B)color { // generate alpha/color for each point glEnableClientState(GL_COLOR_ARRAY); - uint i = begin; + NSUInteger i = begin; for (; i < end; ++i) { - int idx = i*8; + NSUInteger idx = i*8; colors[idx] = r; colors[idx+1] = g; colors[idx+2] = b; @@ -372,7 +374,7 @@ -(void)draw:(float)curTime fadeTime:(float)fadeTime color:(ccColor4B)color } glVertexPointer(3, GL_FLOAT, 0, &verts[begin*6]); glTexCoordPointer(2, GL_FLOAT, 0, &coords[begin*4]); - glDrawArrays(GL_TRIANGLE_STRIP, 0, (end - begin) * 2); + glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei) (end - begin) * 2); } else finished = YES; diff --git a/libs/cocos2d/CCScene.h b/libs/cocos2d/CCScene.h index eedc985..1d104bc 100644 --- a/libs/cocos2d/CCScene.h +++ b/libs/cocos2d/CCScene.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/libs/cocos2d/CCScene.m b/libs/cocos2d/CCScene.m index e1716bb..e991d6e 100644 --- a/libs/cocos2d/CCScene.m +++ b/libs/cocos2d/CCScene.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/libs/cocos2d/CCScheduler.h b/libs/cocos2d/CCScheduler.h index 94e381f..be635f7 100644 --- a/libs/cocos2d/CCScheduler.h +++ b/libs/cocos2d/CCScheduler.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,12 +40,16 @@ typedef void (*TICK_IMP)(id, SEL, ccTime); TICK_IMP impMethod; ccTime elapsed; + BOOL runForever; + BOOL useDelay; + uint nTimesExecuted; + uint repeat; //0 = once, 1 is 2 x executed + ccTime delay; @public // optimization ccTime interval; SEL selector; } - /** interval in seconds */ @property (nonatomic,readwrite,assign) ccTime interval; @@ -60,9 +65,9 @@ typedef void (*TICK_IMP)(id, SEL, ccTime); */ -(id) initWithTarget:(id) t selector:(SEL)s; -/** Initializes a timer with a target, a selector and an interval in seconds. +/** Initializes a timer with a target, a selector, an interval in seconds, repeat in number of times to repeat, delay in seconds */ --(id) initWithTarget:(id) t selector:(SEL)s interval:(ccTime)seconds; +-(id) initWithTarget:(id)t selector:(SEL)s interval:(ccTime) seconds repeat:(uint) r delay:(ccTime) d; /** triggers the timer */ @@ -110,6 +115,8 @@ struct _hashUpdateEntry; // Optimization TICK_IMP impMethod; SEL updateSelector; + + BOOL updateHashLocked; // If true unschedule will not remove anything from a hash. Elements will only be marked for deletion. } /** Modifies the time of all scheduled callbacks. @@ -138,9 +145,14 @@ struct _hashUpdateEntry; If paused is YES, then it won't be called until it is resumed. If 'interval' is 0, it will be called every frame, but if so, it recommened to use 'scheduleUpdateForTarget:' instead. If the selector is already scheduled, then only the interval parameter will be updated without re-scheduling it again. - - @since v0.99.3 + repeat let the action be repeated repeat + 1 times, use kCCRepeatForever to let the action run continiously + delay is the amount of time the action will wait before it'll start + + @since v0.99.3, repeat and delay added in v1.1 */ +-(void) scheduleSelector:(SEL)selector forTarget:(id)target interval:(ccTime)interval paused:(BOOL)paused repeat: (uint) repeat delay: (ccTime) delay; + +/** calls scheduleSelector with kCCRepeatForever and a 0 delay */ -(void) scheduleSelector:(SEL)selector forTarget:(id)target interval:(ccTime)interval paused:(BOOL)paused; /** Schedules the 'update' selector for a given target with a given priority. @@ -148,7 +160,7 @@ struct _hashUpdateEntry; The lower the priority, the earlier it is called. @since v0.99.3 */ --(void) scheduleUpdateForTarget:(id)target priority:(int)priority paused:(BOOL)paused; +-(void) scheduleUpdateForTarget:(id)target priority:(NSInteger)priority paused:(BOOL)paused; /** Unshedules a selector for a given target. If you want to unschedule the "update", use unscheudleUpdateForTarget. @@ -188,25 +200,9 @@ struct _hashUpdateEntry; */ -(void) resumeTarget:(id)target; - -/** schedules a Timer. - It will be fired in every frame. - - @deprecated Use scheduleSelector:forTarget:interval:paused instead. Will be removed in 1.0 - */ --(void) scheduleTimer: (CCTimer*) timer DEPRECATED_ATTRIBUTE; - -/** unschedules an already scheduled Timer - - @deprecated Use unscheduleSelector:forTarget. Will be removed in v1.0 +/** Returns whether or not the target is paused + @since v1.0.0 */ --(void) unscheduleTimer: (CCTimer*) timer DEPRECATED_ATTRIBUTE; +-(BOOL) isTargetPaused:(id)target; -/** unschedule all timers. - You should NEVER call this method, unless you know what you are doing. - - @deprecated Use scheduleAllSelectors instead. Will be removed in 1.0 - @since v0.8 - */ --(void) unscheduleAllTimers DEPRECATED_ATTRIBUTE; @end diff --git a/libs/cocos2d/CCScheduler.m b/libs/cocos2d/CCScheduler.m index 8111ffb..3e8ee60 100644 --- a/libs/cocos2d/CCScheduler.m +++ b/libs/cocos2d/CCScheduler.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -40,11 +41,11 @@ typedef struct _listEntry { struct _listEntry *prev, *next; - TICK_IMP impMethod; - id target; // not retained (retained by hashUpdateEntry) - int priority; - BOOL paused; - + TICK_IMP impMethod; + id target; // not retained (retained by hashUpdateEntry) + NSInteger priority; + BOOL paused; + BOOL markedForDeletion; // selector will no longer be called and entry will be removed at end of the next tick } tListEntry; typedef struct _hashUpdateEntry @@ -88,20 +89,20 @@ -(id) init +(id) timerWithTarget:(id)t selector:(SEL)s { - return [[[self alloc] initWithTarget:t selector:s] autorelease]; + return [[[self alloc] initWithTarget:t selector:s interval:0 repeat:kCCRepeatForever delay:0] autorelease]; } +(id) timerWithTarget:(id)t selector:(SEL)s interval:(ccTime) i { - return [[[self alloc] initWithTarget:t selector:s interval:i] autorelease]; + return [[[self alloc] initWithTarget:t selector:s interval:i repeat:kCCRepeatForever delay:0] autorelease]; } -(id) initWithTarget:(id)t selector:(SEL)s { - return [self initWithTarget:t selector:s interval:0]; + return [self initWithTarget:t selector:s interval:0 repeat:kCCRepeatForever delay: 0]; } --(id) initWithTarget:(id)t selector:(SEL)s interval:(ccTime) seconds +-(id) initWithTarget:(id)t selector:(SEL)s interval:(ccTime) seconds repeat:(uint) r delay:(ccTime) d { if( (self=[super init]) ) { #if COCOS2D_DEBUG @@ -115,10 +116,16 @@ -(id) initWithTarget:(id)t selector:(SEL)s interval:(ccTime) seconds impMethod = (TICK_IMP) [t methodForSelector:s]; elapsed = -1; interval = seconds; + repeat = r; + delay = d; + useDelay = (delay > 0) ? YES : NO; + repeat = r; + runForever = (repeat == kCCRepeatForever) ? YES : NO; } return self; } + - (NSString*) description { return [NSString stringWithFormat:@"<%@ = %08X | target:%@ selector:(%@)>", [self class], self, [target class], NSStringFromSelector(selector)]; @@ -133,12 +140,50 @@ -(void) dealloc -(void) update: (ccTime) dt { if( elapsed == - 1) + { elapsed = 0; + nTimesExecuted = 0; + } else - elapsed += dt; - if( elapsed >= interval ) { - impMethod(target, selector, elapsed); - elapsed = 0; + { + if (runForever && !useDelay) + {//standard timer usage + elapsed += dt; + if( elapsed >= interval ) { + impMethod(target, selector, elapsed); + elapsed = 0; + + } + } + else + {//advanced usage + elapsed += dt; + if (useDelay) + { + if( elapsed >= delay ) + { + impMethod(target, selector, elapsed); + elapsed = elapsed - delay; + nTimesExecuted+=1; + useDelay = NO; + } + } + else + { + if (elapsed >= interval) + { + impMethod(target, selector, elapsed); + elapsed = 0; + nTimesExecuted += 1; + + } + } + + if (nTimesExecuted > repeat) + {//unschedule timer + [[CCScheduler sharedScheduler] unscheduleSelector:selector forTarget:target]; + } + } } } @end @@ -198,6 +243,7 @@ - (id) init currentTarget = nil; currentTargetSalvaged = NO; hashForSelectors = nil; + updateHashLocked = NO; } return self; @@ -225,22 +271,12 @@ -(void) removeHashElement:(tHashSelectorEntry*)element free(element); } --(void) scheduleTimer: (CCTimer*) t -{ - NSAssert(NO, @"Not implemented. Use scheduleSelector:forTarget:"); -} - --(void) unscheduleTimer: (CCTimer*) t +-(void) scheduleSelector:(SEL)selector forTarget:(id)target interval:(ccTime)interval paused:(BOOL)paused { - NSAssert(NO, @"Not implemented. Use unscheduleSelector:forTarget:"); + [self scheduleSelector:selector forTarget:target interval:interval paused:paused repeat:kCCRepeatForever delay:0.0f]; } --(void) unscheduleAllTimers -{ - NSAssert(NO, @"Not implemented. Use unscheduleAllSelectors"); -} - --(void) scheduleSelector:(SEL)selector forTarget:(id)target interval:(ccTime)interval paused:(BOOL)paused +-(void) scheduleSelector:(SEL)selector forTarget:(id)target interval:(ccTime)interval paused:(BOOL)paused repeat:(uint) repeat delay:(ccTime) delay { NSAssert( selector != nil, @"Argument selector must be non-nil"); NSAssert( target != nil, @"Argument target must be non-nil"); @@ -252,10 +288,10 @@ -(void) scheduleSelector:(SEL)selector forTarget:(id)target interval:(ccTime)int element = calloc( sizeof( *element ), 1 ); element->target = [target retain]; HASH_ADD_INT( hashForSelectors, target, element ); - + // Is this the 1st element ? Then set the pause level to all the selectors of this target element->paused = paused; - + } else NSAssert( element->paused == paused, @"CCScheduler. Trying to schedule a selector with a pause value different than the target"); @@ -275,7 +311,7 @@ -(void) scheduleSelector:(SEL)selector forTarget:(id)target interval:(ccTime)int ccArrayEnsureExtraCapacity(element->timers, 1); } - CCTimer *timer = [[CCTimer alloc] initWithTarget:target selector:selector interval:interval]; + CCTimer *timer = [[CCTimer alloc] initWithTarget:target selector:selector interval:interval repeat:repeat delay:delay]; ccArrayAppendObject(element->timers, timer); [timer release]; } @@ -329,7 +365,7 @@ -(void) unscheduleSelector:(SEL)selector forTarget:(id)target #pragma mark CCScheduler - Update Specific --(void) priorityIn:(tListEntry**)list target:(id)target priority:(int)priority paused:(BOOL)paused +-(void) priorityIn:(tListEntry**)list target:(id)target priority:(NSInteger)priority paused:(BOOL)paused { tListEntry *listElement = malloc( sizeof(*listElement) ); @@ -338,7 +374,7 @@ -(void) priorityIn:(tListEntry**)list target:(id)target priority:(int)priority p listElement->paused = paused; listElement->impMethod = (TICK_IMP) [target methodForSelector:updateSelector]; listElement->next = listElement->prev = NULL; - + listElement->markedForDeletion = NO; // empty list ? if( ! *list ) { @@ -384,6 +420,7 @@ -(void) appendIn:(tListEntry**)list target:(id)target paused:(BOOL)paused listElement->target = target; listElement->paused = paused; + listElement->markedForDeletion = NO; listElement->impMethod = (TICK_IMP) [target methodForSelector:updateSelector]; DL_APPEND(*list, listElement); @@ -397,13 +434,20 @@ -(void) appendIn:(tListEntry**)list target:(id)target paused:(BOOL)paused HASH_ADD_INT(hashForUpdates, target, hashElement ); } --(void) scheduleUpdateForTarget:(id)target priority:(int)priority paused:(BOOL)paused +-(void) scheduleUpdateForTarget:(id)target priority:(NSInteger)priority paused:(BOOL)paused { -#if COCOS2D_DEBUG >= 1 tHashUpdateEntry * hashElement = NULL; HASH_FIND_INT(hashForUpdates, &target, hashElement); - NSAssert( hashElement == NULL, @"CCScheduler: You can't re-schedule an 'update' selector'. Unschedule it first"); + if(hashElement) + { +#if COCOS2D_DEBUG >= 1 + NSAssert( hashElement->entry->markedForDeletion, @"CCScheduler: You can't re-schedule an 'update' selector'. Unschedule it first"); #endif + // TODO : check if priority has changed! + + hashElement->entry->markedForDeletion = NO; + return; + } // most of the updates are going to be 0, that's way there // is an special list for updates with priority 0 @@ -417,6 +461,23 @@ -(void) scheduleUpdateForTarget:(id)target priority:(int)priority paused:(BOOL)p [self priorityIn:&updatesPos target:target priority:priority paused:paused]; } +- (void) removeUpdateFromHash:(tListEntry*)entry +{ + tHashUpdateEntry * element = NULL; + + HASH_FIND_INT(hashForUpdates, &entry->target, element); + if( element ) { + // list entry + DL_DELETE( *element->list, element->entry ); + free( element->entry ); + + // hash entry + [element->target release]; + HASH_DEL( hashForUpdates, element); + free(element); + } +} + -(void) unscheduleUpdateForTarget:(id)target { if( target == nil ) @@ -424,16 +485,20 @@ -(void) unscheduleUpdateForTarget:(id)target tHashUpdateEntry * element = NULL; HASH_FIND_INT(hashForUpdates, &target, element); - if( element ) { - - // list entry - DL_DELETE( *element->list, element->entry ); - free( element->entry ); - - // hash entry - [element->target release]; - HASH_DEL( hashForUpdates, element); - free(element); + if( element ) { + if(updateHashLocked) + element->entry->markedForDeletion = YES; + else + [self removeUpdateFromHash:element->entry]; + +// // list entry +// DL_DELETE( *element->list, element->entry ); +// free( element->entry ); +// +// // hash entry +// [element->target release]; +// HASH_DEL( hashForUpdates, element); +// free(element); } } @@ -527,10 +592,27 @@ -(void) pauseTarget:(id)target } +-(BOOL) isTargetPaused:(id)target +{ + NSAssert( target != nil, @"target must be non nil" ); + + // Custom selectors + tHashSelectorEntry *element = NULL; + HASH_FIND_INT(hashForSelectors, &target, element); + if( element ) + { + return element->paused; + } + return NO; // should never get here + +} + #pragma mark CCScheduler - Main Loop -(void) tick: (ccTime) dt { + updateHashLocked = YES; + if( timeScale_ != 1.0f ) dt *= timeScale_; @@ -539,19 +621,21 @@ -(void) tick: (ccTime) dt // updates with priority < 0 DL_FOREACH_SAFE( updatesNeg, entry, tmp ) { - if( ! entry->paused ) + if( ! entry->paused && !entry->markedForDeletion ) entry->impMethod( entry->target, updateSelector, dt ); } // updates with priority == 0 DL_FOREACH_SAFE( updates0, entry, tmp ) { - if( ! entry->paused ) + if( ! entry->paused && !entry->markedForDeletion ) + { entry->impMethod( entry->target, updateSelector, dt ); + } } // updates with priority > 0 DL_FOREACH_SAFE( updatesPos, entry, tmp ) { - if( ! entry->paused ) + if( ! entry->paused && !entry->markedForDeletion ) entry->impMethod( entry->target, updateSelector, dt ); } @@ -590,8 +674,33 @@ -(void) tick: (ccTime) dt [self removeHashElement:currentTarget]; } + // delete all updates that are morked for deletion + // updates with priority < 0 + DL_FOREACH_SAFE( updatesNeg, entry, tmp ) { + if(entry->markedForDeletion ) + { + [self removeUpdateFromHash:entry]; + } + } + + // updates with priority == 0 + DL_FOREACH_SAFE( updates0, entry, tmp ) { + if(entry->markedForDeletion ) + { + [self removeUpdateFromHash:entry]; + } + } + + // updates with priority > 0 + DL_FOREACH_SAFE( updatesPos, entry, tmp ) { + if(entry->markedForDeletion ) + { + [self removeUpdateFromHash:entry]; + } + } + + updateHashLocked = NO; currentTarget = nil; } - @end diff --git a/libs/cocos2d/CCSprite.h b/libs/cocos2d/CCSprite.h index 8b35176..cf21862 100644 --- a/libs/cocos2d/CCSprite.h +++ b/libs/cocos2d/CCSprite.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,17 +30,12 @@ #import "CCTextureAtlas.h" @class CCSpriteBatchNode; -@class CCSpriteSheet; -@class CCSpriteSheetInternalOnly; @class CCSpriteFrame; @class CCAnimation; #pragma mark CCSprite -enum { - /// CCSprite invalid index on the CCSpriteBatchode - CCSpriteIndexNotInitialized = 0xffffffff, -}; +#define CCSpriteIndexNotInitialized 0xffffffff /// CCSprite invalid index on the CCSpriteBatchode /** Whether or not an CCSprite will rotate, scale or translate with it's parent. @@ -54,9 +50,11 @@ typedef enum { CC_HONOR_PARENT_TRANSFORM_ROTATE = 1 << 1, //! Scale with it's parent CC_HONOR_PARENT_TRANSFORM_SCALE = 1 << 2, + //! Skew with it's parent + CC_HONOR_PARENT_TRANSFORM_SKEW = 1 << 3, //! All possible transformation enabled. Default value. - CC_HONOR_PARENT_TRANSFORM_ALL = CC_HONOR_PARENT_TRANSFORM_TRANSLATE | CC_HONOR_PARENT_TRANSFORM_ROTATE | CC_HONOR_PARENT_TRANSFORM_SCALE, + CC_HONOR_PARENT_TRANSFORM_ALL = CC_HONOR_PARENT_TRANSFORM_TRANSLATE | CC_HONOR_PARENT_TRANSFORM_ROTATE | CC_HONOR_PARENT_TRANSFORM_SCALE | CC_HONOR_PARENT_TRANSFORM_SKEW, } ccHonorParentTransform; @@ -130,21 +128,19 @@ typedef enum { // image is flipped BOOL flipX_; BOOL flipY_; - - - // Animations that belong to the sprite - NSMutableDictionary *animations_; - + @public - // used internally. + // used internally void (*updateMethod)(id, SEL); + void (*sortMethod)(id, SEL); + } /** whether or not the Sprite needs to be updated in the Atlas */ @property (nonatomic,readwrite) BOOL dirty; /** the quad (tex coords, vertex coords and color) information */ @property (nonatomic,readonly) ccV3F_C4B_T2F_Quad quad; -/** The index used on the TextureATlas. Don't modify this value unless you know what you are doing */ +/** The index used on the TextureAtlas. Don't modify this value unless you know what you are doing */ @property (nonatomic,readwrite) NSUInteger atlasIndex; /** returns the rect of the CCSprite in points */ @property (nonatomic,readonly) CGRect textureRect; @@ -224,11 +220,6 @@ typedef enum { */ +(id) spriteWithFile:(NSString*)filename rect:(CGRect)rect; -/** Creates an sprite with a CGImageRef. - @deprecated Use spriteWithCGImage:key: instead. Will be removed in v1.0 final - */ -+(id) spriteWithCGImage: (CGImageRef)image DEPRECATED_ATTRIBUTE; - /** Creates an sprite with a CGImageRef and a key. The key is used by the CCTextureCache to know if a texture was already created with this CGImage. For example, a valid key is: @"sprite_frame_01". @@ -242,8 +233,6 @@ typedef enum { */ +(id) spriteWithBatchNode:(CCSpriteBatchNode*)batchNode rect:(CGRect)rect; -+(id) spriteWithSpriteSheet:(CCSpriteSheetInternalOnly*)spritesheet rect:(CGRect)rect DEPRECATED_ATTRIBUTE; - /** Initializes an sprite with a texture. The rect used will be the size of the texture. @@ -278,11 +267,6 @@ typedef enum { */ -(id) initWithFile:(NSString*)filename rect:(CGRect)rect; -/** Initializes an sprite with a CGImageRef - @deprecated Use spriteWithCGImage:key: instead. Will be removed in v1.0 final - */ --(id) initWithCGImage: (CGImageRef)image DEPRECATED_ATTRIBUTE; - /** Initializes an sprite with a CGImageRef and a key The key is used by the CCTextureCache to know if a texture was already created with this CGImage. For example, a valid key is: @"sprite_frame_01". @@ -291,12 +275,11 @@ typedef enum { */ -(id) initWithCGImage:(CGImageRef)image key:(NSString*)key; -/** Initializes an sprite with an CCSpriteSheet and a rect in points +/** Initializes an sprite with an CCSpriteBatchNode and a rect in points */ -(id) initWithBatchNode:(CCSpriteBatchNode*)batchNode rect:(CGRect)rect; --(id) initWithSpriteSheet:(CCSpriteSheetInternalOnly*)spritesheet rect:(CGRect)rect DEPRECATED_ATTRIBUTE; -/** Initializes an sprite with an CCSpriteSheet and a rect in pixels +/** Initializes an sprite with an CCSpriteBatchNode and a rect in pixels @since v0.99.5 */ -(id) initWithBatchNode:(CCSpriteBatchNode*)batchNode rectInPixels:(CGRect)rect; @@ -325,7 +308,6 @@ typedef enum { @since v0.99.0 */ -(void) useBatchNode:(CCSpriteBatchNode*)batchNode; --(void) useSpriteSheetRender:(CCSpriteSheetInternalOnly*)spriteSheet DEPRECATED_ATTRIBUTE; #pragma mark CCSprite - Frames @@ -341,27 +323,10 @@ typedef enum { #pragma mark CCSprite - Animation -/** changes the display frame based on an animation and an index. - @deprecated Will be removed in 1.0.1. Use setDisplayFrameWithAnimationName:index instead - */ --(void) setDisplayFrame: (NSString*) animationName index:(int) frameIndex DEPRECATED_ATTRIBUTE; - /** changes the display frame with animation name and index. The animation name will be get from the CCAnimationCache @since v0.99.5 */ -(void) setDisplayFrameWithAnimationName:(NSString*)animationName index:(int) frameIndex; -/** returns an Animation given it's name. - - @deprecated Use CCAnimationCache instead. Will be removed in 1.0.1 - */ --(CCAnimation*)animationByName: (NSString*) animationName DEPRECATED_ATTRIBUTE; - -/** adds an Animation to the Sprite. - - @deprecated Use CCAnimationCache instead. Will be removed in 1.0.1 - */ --(void) addAnimation: (CCAnimation*) animation DEPRECATED_ATTRIBUTE; - @end diff --git a/libs/cocos2d/CCSprite.m b/libs/cocos2d/CCSprite.m index 7875782..12f9907 100644 --- a/libs/cocos2d/CCSprite.m +++ b/libs/cocos2d/CCSprite.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,7 +28,6 @@ #import "ccConfig.h" #import "CCSpriteBatchNode.h" -#import "CCSpriteSheet.h" #import "CCSprite.h" #import "CCSpriteFrame.h" #import "CCSpriteFrameCache.h" @@ -51,15 +51,19 @@ CGPoint pos; // position x and y CGPoint scale; // scale x and y float rotation; + CGPoint skew; // skew x and y CGPoint ap; // anchor point in pixels BOOL visible; }; +static SEL selSortMethod = NULL; + @interface CCSprite (Private) -(void)updateTextureCoords:(CGRect)rect; -(void)updateBlendFunc; -(void) initAnimationDictionary; -(void) getTransformValues:(struct transformValues_*)tv; // optimization +-(void) setReorderChildDirtyRecursively; @end @implementation CCSprite @@ -105,15 +109,11 @@ +(id)spriteWithSpriteFrame:(CCSpriteFrame*)spriteFrame +(id)spriteWithSpriteFrameName:(NSString*)spriteFrameName { CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:spriteFrameName]; + + NSAssert1(frame!=nil, @"Invalid spriteFrameName: %@", spriteFrameName); return [self spriteWithSpriteFrame:frame]; } -// XXX: deprecated -+(id)spriteWithCGImage:(CGImageRef)image -{ - return [[[self alloc] initWithCGImage:image] autorelease]; -} - +(id)spriteWithCGImage:(CGImageRef)image key:(NSString*)key { return [[[self alloc] initWithCGImage:image key:key] autorelease]; @@ -123,10 +123,6 @@ +(id) spriteWithBatchNode:(CCSpriteBatchNode*)batchNode rect:(CGRect)rect { return [[[self alloc] initWithBatchNode:batchNode rect:rect] autorelease]; } -+(id) spriteWithSpriteSheet:(CCSpriteSheetInternalOnly*)spritesheet rect:(CGRect)rect // XXX DEPRECATED -{ - return [self spriteWithBatchNode:spritesheet rect:rect]; -} -(id) init { @@ -134,7 +130,7 @@ -(id) init dirty_ = recursiveDirty_ = NO; // by default use "Self Render". - // if the sprite is added to an SpriteSheet, then it will automatically switch to "SpriteSheet Render" + // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render" [self useSelfRender]; opacityModifyRGB_ = YES; @@ -152,9 +148,6 @@ -(id) init flipY_ = flipX_ = NO; - // lazy alloc - animations_ = nil; - // default transform anchor: center anchorPoint_ = ccp(0.5f, 0.5f); @@ -180,6 +173,10 @@ -(id) init // updateMethod selector updateMethod = (__typeof__(updateMethod))[self methodForSelector:@selector(updateTransform)]; + + // sortMethod selector + selSortMethod = @selector(sortAllChildren); + sortMethod = (__typeof__(sortMethod))[self methodForSelector:selSortMethod]; } return self; @@ -250,21 +247,6 @@ -(id)initWithSpriteFrameName:(NSString*)spriteFrameName return [self initWithSpriteFrame:frame]; } -// XXX: deprecated -- (id) initWithCGImage: (CGImageRef)image -{ - NSAssert(image!=nil, @"Invalid CGImageRef for sprite"); - - // XXX: possible bug. See issue #349. New API should be added - NSString *key = [NSString stringWithFormat:@"%08X",(unsigned long)image]; - CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addCGImage:image forKey:key]; - - CGRect rect = CGRectZero; - rect.size = texture.contentSize; - - return [self initWithTexture:texture rect:rect]; -} - - (id) initWithCGImage:(CGImageRef)image key:(NSString*)key { NSAssert(image!=nil, @"Invalid CGImageRef for sprite"); @@ -295,11 +277,6 @@ -(id) initWithBatchNode:(CCSpriteBatchNode*)batchNode rectInPixels:(CGRect)rect return ret; } --(id) initWithSpriteSheet:(CCSpriteSheetInternalOnly*)spritesheet rect:(CGRect)rect // XXX DEPRECATED -{ - return [self initWithBatchNode:spritesheet rect:rect]; -} - - (NSString*) description { return [NSString stringWithFormat:@"<%@ = %08X | Rect = (%.2f,%.2f,%.2f,%.2f) | tag = %i | atlasIndex = %i>", [self class], self, @@ -312,7 +289,6 @@ - (NSString*) description - (void) dealloc { [texture_ release]; - [animations_ release]; [super dealloc]; } @@ -340,15 +316,6 @@ -(void) useBatchNode:(CCSpriteBatchNode*)batchNode textureAtlas_ = [batchNode textureAtlas]; // weak ref batchNode_ = batchNode; // weak ref } --(void) useSpriteSheetRender:(CCSpriteSheetInternalOnly*)spriteSheet // XXX DEPRECATED -{ - [self useBatchNode:spriteSheet]; -} - --(void) initAnimationDictionary -{ - animations_ = [[NSMutableDictionary alloc] initWithCapacity:2]; -} -(void)setTextureRect:(CGRect)rect { @@ -377,7 +344,7 @@ -(void)setTextureRectInPixels:(CGRect)rect rotated:(BOOL)rotated untrimmedSize:( offsetPositionInPixels_.y = relativeOffsetInPixels.y + (contentSizeInPixels_.height - rectInPixels_.size.height) / 2; - // rendering using SpriteSheet + // rendering using batch node if( usesBatchNode_ ) { // update dirty_, don't update recursiveDirty_ dirty_ = YES; @@ -492,10 +459,16 @@ -(void)updateTransform float radians = -CC_DEGREES_TO_RADIANS(rotation_); float c = cosf(radians); float s = sinf(radians); - + matrix = CGAffineTransformMake( c * scaleX_, s * scaleX_, -s * scaleY_, c * scaleY_, positionInPixels_.x, positionInPixels_.y); + if( skewX_ || skewY_ ) { + CGAffineTransform skewMatrix = CGAffineTransformMake(1.0f, tanf(CC_DEGREES_TO_RADIANS(skewY_)), + tanf(CC_DEGREES_TO_RADIANS(skewX_)), 1.0f, + 0.0f, 0.0f); + matrix = CGAffineTransformConcat(skewMatrix, matrix); + } matrix = CGAffineTransformTranslate(matrix, -anchorPointInPixels_.x, -anchorPointInPixels_.y); @@ -523,7 +496,7 @@ -(void)updateTransform } CGAffineTransform newMatrix = CGAffineTransformIdentity; - // 2nd: Translate, Rotate, Scale + // 2nd: Translate, Skew, Rotate, Scale if( prevHonor & CC_HONOR_PARENT_TRANSFORM_TRANSLATE ) newMatrix = CGAffineTransformTranslate(newMatrix, tv.pos.x, tv.pos.y); if( prevHonor & CC_HONOR_PARENT_TRANSFORM_ROTATE ) @@ -531,6 +504,11 @@ -(void)updateTransform if( prevHonor & CC_HONOR_PARENT_TRANSFORM_SCALE ) { newMatrix = CGAffineTransformScale(newMatrix, tv.scale.x, tv.scale.y); } + if ( prevHonor & CC_HONOR_PARENT_TRANSFORM_SKEW ) { + CGAffineTransform skew = CGAffineTransformMake(1.0f, tanf(CC_DEGREES_TO_RADIANS(tv.skew.y)), tanf(CC_DEGREES_TO_RADIANS(tv.skew.x)), 1.0f, 0.0f, 0.0f); + // apply the skew to the transform + newMatrix = CGAffineTransformConcat(skew, newMatrix); + } // 3rd: Translate anchor point newMatrix = CGAffineTransformTranslate(newMatrix, -tv.ap.x, -tv.ap.y); @@ -590,6 +568,8 @@ -(void) getTransformValues:(struct transformValues_*) tv tv->scale.x = scaleX_; tv->scale.y = scaleY_; tv->rotation = rotation_; + tv->skew.x = skewX_; + tv->skew.y = skewY_; tv->ap = anchorPointInPixels_; tv->visible = visible_; } @@ -598,6 +578,8 @@ -(void) getTransformValues:(struct transformValues_*) tv -(void) draw { + [super draw]; + NSAssert(!usesBatchNode_, @"If CCSprite is being rendered by CCSpriteBatchNode, CCSprite#draw SHOULD NOT be called"); // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY @@ -630,61 +612,76 @@ -(void) draw if( newBlend ) glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST); -#if CC_SPRITE_DEBUG_DRAW - CGSize s = [self contentSize]; +#if CC_SPRITE_DEBUG_DRAW == 1 + // draw bounding box CGPoint vertices[4]={ - ccp(0,0),ccp(s.width,0), - ccp(s.width,s.height),ccp(0,s.height), + ccp(quad_.tl.vertices.x,quad_.tl.vertices.y), + ccp(quad_.bl.vertices.x,quad_.bl.vertices.y), + ccp(quad_.br.vertices.x,quad_.br.vertices.y), + ccp(quad_.tr.vertices.x,quad_.tr.vertices.y), }; ccDrawPoly(vertices, 4, YES); -#endif // CC_TEXTURENODE_DEBUG_DRAW +#elif CC_SPRITE_DEBUG_DRAW == 2 + // draw texture box + CGSize s = self.textureRect.size; + CGPoint offsetPix = self.offsetPositionInPixels; + CGPoint vertices[4] = { + ccp(offsetPix.x,offsetPix.y), ccp(offsetPix.x+s.width,offsetPix.y), + ccp(offsetPix.x+s.width,offsetPix.y+s.height), ccp(offsetPix.x,offsetPix.y+s.height) + }; + ccDrawPoly(vertices, 4, YES); +#endif // CC_SPRITE_DEBUG_DRAW } #pragma mark CCSprite - CCNode overrides --(void) addChild:(CCSprite*)child z:(int)z tag:(int) aTag +-(void) addChild:(CCSprite*)child z:(NSInteger)z tag:(NSInteger) aTag { NSAssert( child != nil, @"Argument must be non-nil"); - - [super addChild:child z:z tag:aTag]; - if( usesBatchNode_ ) { NSAssert( [child isKindOfClass:[CCSprite class]], @"CCSprite only supports CCSprites as children when using CCSpriteBatchNode"); NSAssert( child.texture.name == textureAtlas_.texture.name, @"CCSprite is not using the same texture id"); - NSUInteger index = [batchNode_ atlasIndexForChild:child atZ:z]; - [batchNode_ insertChild:child inAtlasAtIndex:index]; + if( atlasIndex_ != CCSpriteIndexNotInitialized) { + //put it in descendants array of batch node only if not already added in descendants + [batchNode_ appendChild:child]; + } + if (!isReorderChildDirty_) [self setReorderChildDirtyRecursively]; } - + //CCNode already sets isReorderChildDirty_ so this needs to be after batchNode check + [super addChild:child z:z tag:aTag]; hasChildren_ = YES; } --(void) reorderChild:(CCSprite*)child z:(int)z +-(void) reorderChild:(CCSprite*)child z:(NSInteger)z { NSAssert( child != nil, @"Child must be non-nil"); NSAssert( [children_ containsObject:child], @"Child doesn't belong to Sprite" ); if( z == child.zOrder ) return; - - if( usesBatchNode_ ) { - // XXX: Instead of removing/adding, it is more efficient to reorder manually - [child retain]; - [self removeChild:child cleanup:NO]; - [self addChild:child z:z]; - [child release]; + + if( usesBatchNode_ ) + { + if (!isReorderChildDirty_) + { + [self setReorderChildDirtyRecursively]; + [batchNode_ reorderBatch:YES]; + } } - - else - [super reorderChild:child z:z]; + + [super reorderChild:child z:z]; } -(void)removeChild: (CCSprite *)sprite cleanup:(BOOL)doCleanup { - if( usesBatchNode_ ) - [batchNode_ removeSpriteFromAtlas:sprite]; - + if( usesBatchNode_ ) { + if( atlasIndex_ != CCSpriteIndexNotInitialized) { + [batchNode_ removeSpriteFromAtlas:sprite]; + } + } + [super removeChild:sprite cleanup:doCleanup]; hasChildren_ = ( [children_ count] > 0 ); @@ -703,12 +700,61 @@ -(void)removeAllChildrenWithCleanup:(BOOL)doCleanup hasChildren_ = NO; } +- (void) sortAllChildren +{ + if (isReorderChildDirty_) + { + NSInteger i,j,length=children_->data->num; + CCNode ** x=children_->data->arr; + CCNode * tempItem; + + //insertion sort + for(i=1; i=0 && ( tempItem.zOrder < x[j].zOrder || ( tempItem.zOrder == x[j].zOrder && tempItem.orderOfArrival < x[j].orderOfArrival ) ) ) + { + x[j+1] = x[j]; + j = j-1; + } + x[j+1] = tempItem; + } + + if (usesBatchNode_) + { + //sorted now check all children recursively + CCSprite *child; + // fast dispatch + CCARRAY_FOREACH(children_, child) child->sortMethod(child,selSortMethod); + } + + isReorderChildDirty_=NO; + } +} + // // CCNode property overloads // used only when parent is CCSpriteBatchNode // #pragma mark CCSprite - property overloads +-(void) setReorderChildDirtyRecursively +{ + //only set parents flag the first time + if (!isReorderChildDirty_) + { + isReorderChildDirty_=YES; + CCNode* node=(CCNode*) parent_; + while ( node!=nil && node!=batchNode_) + { + [(CCSprite*) node setReorderChildDirtyRecursively]; + node=node.parent; + } + } +} -(void) setDirtyRecursively:(BOOL)b { @@ -748,6 +794,18 @@ -(void)setRotation:(float)rot SET_DIRTY_RECURSIVELY(); } +-(void)setSkewX:(float)sx +{ + [super setSkewX:sx]; + SET_DIRTY_RECURSIVELY(); +} + +-(void)setSkewY:(float)sy +{ + [super setSkewY:sy]; + SET_DIRTY_RECURSIVELY(); +} + -(void)setScaleX:(float) sx { [super setScaleX:sx]; @@ -794,7 +852,7 @@ -(void)setFlipX:(BOOL)b { if( flipX_ != b ) { flipX_ = b; - [self setTextureRectInPixels:rectInPixels_ rotated:rectRotated_ untrimmedSize:rectInPixels_.size]; + [self setTextureRectInPixels:rectInPixels_ rotated:rectRotated_ untrimmedSize:contentSizeInPixels_]; } } -(BOOL) flipX @@ -806,7 +864,7 @@ -(void) setFlipY:(BOOL)b { if( flipY_ != b ) { flipY_ = b; - [self setTextureRectInPixels:rectInPixels_ rotated:rectRotated_ untrimmedSize:rectInPixels_.size]; + [self setTextureRectInPixels:rectInPixels_ rotated:rectRotated_ untrimmedSize:contentSizeInPixels_]; } } -(BOOL) flipY @@ -869,9 +927,9 @@ -(void) setColor:(ccColor3B)color3 color_ = colorUnmodified_ = color3; if( opacityModifyRGB_ ){ - color_.r = color3.r * opacity_/255; - color_.g = color3.g * opacity_/255; - color_.b = color3.b * opacity_/255; + color_.r = color3.r * opacity_/255.0f; + color_.g = color3.g * opacity_/255.0f; + color_.b = color3.b * opacity_/255.0f; } [self updateColor]; @@ -908,20 +966,6 @@ -(void) setDisplayFrame:(CCSpriteFrame*)frame [self setTextureRectInPixels:frame.rectInPixels rotated:frame.rotated untrimmedSize:frame.originalSizeInPixels]; } -// XXX deprecated --(void) setDisplayFrame: (NSString*) animationName index:(int) frameIndex -{ - if( ! animations_ ) - [self initAnimationDictionary]; - - CCAnimation *a = [animations_ objectForKey: animationName]; - CCSpriteFrame *frame = [[a frames] objectAtIndex:frameIndex]; - - NSAssert( frame, @"CCSprite#setDisplayFrame. Invalid frame"); - - [self setDisplayFrame:frame]; -} - -(void) setDisplayFrameWithAnimationName: (NSString*) animationName index:(int) frameIndex { NSAssert( animationName, @"CCSprite#setDisplayFrameWithAnimationName. animationName must not be nil"); @@ -946,23 +990,12 @@ -(BOOL) isFrameDisplayed:(CCSpriteFrame*)frame } -(CCSpriteFrame*) displayedFrame -{ - return [CCSpriteFrame frameWithTexture:self.texture rect:rect_]; -} - --(void) addAnimation: (CCAnimation*) anim -{ - // lazy alloc - if( ! animations_ ) - [self initAnimationDictionary]; - - [animations_ setObject:anim forKey:[anim name]]; -} - --(CCAnimation*)animationByName: (NSString*) animationName -{ - NSAssert( animationName != nil, @"animationName parameter must be non nil"); - return [animations_ objectForKey:animationName]; +{ + return [CCSpriteFrame frameWithTexture:texture_ + rectInPixels:rectInPixels_ + rotated:rectRotated_ + offset:unflippedOffsetPositionFromCenter_ + originalSize:contentSizeInPixels_]; } #pragma mark CCSprite - CocosNodeTexture protocol diff --git a/libs/cocos2d/CCSpriteBatchNode.h b/libs/cocos2d/CCSpriteBatchNode.h index 61111c2..0df663d 100644 --- a/libs/cocos2d/CCSpriteBatchNode.h +++ b/libs/cocos2d/CCSpriteBatchNode.h @@ -1,8 +1,10 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2009-2010 Ricardo Quesada * Copyright (C) 2009 Matt Oswald + * + * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -56,6 +58,11 @@ // all descendants: chlidren, gran children, etc... CCArray *descendants_; + + @private + + void (*updateAtlasIndexMethod_)(id, SEL,CCSprite*,NSInteger*); + } /** returns the TextureAtlas that is used */ @@ -71,27 +78,23 @@ The capacity will be increased in 33% in runtime if it run out of space. */ +(id)batchNodeWithTexture:(CCTexture2D *)tex; -+(id)spriteSheetWithTexture:(CCTexture2D *)tex DEPRECATED_ATTRIBUTE; /** creates a CCSpriteBatchNode with a texture2d and capacity of children. The capacity will be increased in 33% in runtime if it run out of space. */ +(id)batchNodeWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity; -+(id)spriteSheetWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity DEPRECATED_ATTRIBUTE; /** creates a CCSpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) with a default capacity of 29 children. The capacity will be increased in 33% in runtime if it run out of space. The file will be loaded using the TextureMgr. */ +(id)batchNodeWithFile:(NSString*) fileImage; -+(id)spriteSheetWithFile:(NSString*) fileImage DEPRECATED_ATTRIBUTE; /** creates a CCSpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) and capacity of children. The capacity will be increased in 33% in runtime if it run out of space. The file will be loaded using the TextureMgr. */ +(id)batchNodeWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity; -+(id)spriteSheetWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity DEPRECATED_ATTRIBUTE; /** initializes a CCSpriteBatchNode with a texture2d and capacity of children. The capacity will be increased in 33% in runtime if it run out of space. @@ -105,25 +108,6 @@ -(void) increaseAtlasCapacity; -/** creates an sprite with a rect in the CCSpriteBatchNode. - It's the same as: - - create an standard CCSsprite - - set the usingSpriteSheet = YES - - set the textureAtlas to the same texture Atlas as the CCSpriteBatchNode - @deprecated Use [CCSprite spriteWithBatchNode:rect:] instead; - */ --(CCSprite*) createSpriteWithRect:(CGRect)rect DEPRECATED_ATTRIBUTE; - -/** initializes a previously created sprite with a rect. This sprite will have the same texture as the CCSpriteBatchNode. - It's the same as: - - initialize an standard CCSsprite - - set the usingBatchNode = YES - - set the textureAtlas to the same texture Atlas as the CCSpriteBatchNode - @since v0.99.0 - @deprecated Use [CCSprite initWithBatchNode:rect:] instead; -*/ --(void) initSprite:(CCSprite*)sprite rect:(CGRect)rect DEPRECATED_ATTRIBUTE; - /** removes a child given a certain index. It will also cleanup the running actions depending on the cleanup parameter. @warning Removing a child from a CCSpriteBatchNode is very slow */ @@ -135,9 +119,12 @@ -(void)removeChild: (CCSprite *)sprite cleanup:(BOOL)doCleanup; -(void) insertChild:(CCSprite*)child inAtlasAtIndex:(NSUInteger)index; +-(void) appendChild:(CCSprite*)sprite; -(void) removeSpriteFromAtlas:(CCSprite*)sprite; -(NSUInteger) rebuildIndexInOrder:(CCSprite*)parent atlasIndex:(NSUInteger)index; --(NSUInteger) atlasIndexForChild:(CCSprite*)sprite atZ:(int)z; +-(NSUInteger) atlasIndexForChild:(CCSprite*)sprite atZ:(NSInteger)z; +/* Sprites use this to start sortChildren, don't call this manually */ +- (void) reorderBatch:(BOOL) reorder; @end diff --git a/libs/cocos2d/CCSpriteBatchNode.m b/libs/cocos2d/CCSpriteBatchNode.m index 28fb082..ebce133 100644 --- a/libs/cocos2d/CCSpriteBatchNode.m +++ b/libs/cocos2d/CCSpriteBatchNode.m @@ -1,8 +1,10 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2009-2010 Ricardo Quesada * Copyright (C) 2009 Matt Oswald + * + * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,9 +41,14 @@ #pragma mark CCSpriteBatchNode static SEL selUpdate = NULL; +static SEL selUpdateAtlasIndex =NULL; +static SEL selSortMethod =NULL; @interface CCSpriteBatchNode (private) -(void) updateBlendFunc; +-(void) updateAtlasIndex:(CCSprite*) sprite currentIndex:(NSInteger*) curIndex; +-(void) swap:(NSInteger) oldIndex withNewIndex:(NSInteger) newIndex; + @end @implementation CCSpriteBatchNode @@ -55,6 +62,8 @@ +(void) initialize { if ( self == [CCSpriteBatchNode class] ) { selUpdate = @selector(updateTransform); + selUpdateAtlasIndex = @selector(updateAtlasIndex:currentIndex:); + selSortMethod = @selector(sortAllChildren); } } /* @@ -64,19 +73,11 @@ +(id)batchNodeWithTexture:(CCTexture2D *)tex { return [[[self alloc] initWithTexture:tex capacity:defaultCapacity] autorelease]; } -+(id)spriteSheetWithTexture:(CCTexture2D *)tex // XXX DEPRECATED -{ - return [self batchNodeWithTexture:tex]; -} +(id)batchNodeWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity { return [[[self alloc] initWithTexture:tex capacity:capacity] autorelease]; } -+(id)spriteSheetWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity // XXX DEPRECATED -{ - return [self batchNodeWithTexture:tex capacity:capacity]; -} /* * creation with File Image @@ -85,20 +86,11 @@ +(id)batchNodeWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity { return [[[self alloc] initWithFile:fileImage capacity:capacity] autorelease]; } -+(id)spriteSheetWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity // XXX DEPRECATED -{ - return [self batchNodeWithFile:fileImage capacity:capacity]; -} +(id)batchNodeWithFile:(NSString*) imageFile { return [[[self alloc] initWithFile:imageFile capacity:defaultCapacity] autorelease]; } -+(id)spriteSheetWithFile:(NSString*) imageFile // XXX DEPRECATED -{ - return [self batchNodeWithFile:imageFile]; -} - /* * init with CCTexture2D @@ -116,6 +108,8 @@ -(id)initWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity // no lazy alloc in this node children_ = [[CCArray alloc] initWithCapacity:capacity]; descendants_ = [[CCArray alloc] initWithCapacity:capacity]; + + updateAtlasIndexMethod_ = (__typeof__(updateAtlasIndexMethod_)) [self methodForSelector:selUpdateAtlasIndex]; } return self; @@ -167,34 +161,21 @@ -(void) visit [self transformAncestors]; } + [self sortAllChildren]; [self transform]; - [self draw]; + orderOfArrival_=0; + if ( grid_ && grid_.active) [grid_ afterDraw:self]; glPopMatrix(); } -// XXX deprecated --(CCSprite*) createSpriteWithRect:(CGRect)rect -{ - CCSprite *sprite = [CCSprite spriteWithTexture:textureAtlas_.texture rect:rect]; - [sprite useBatchNode:self]; - - return sprite; -} - -// XXX deprecated --(void) initSprite:(CCSprite*)sprite rect:(CGRect)rect -{ - [sprite initWithTexture:textureAtlas_.texture rect:rect]; - [sprite useBatchNode:self]; -} // override addChild: --(void) addChild:(CCSprite*)child z:(int)z tag:(int) aTag +-(void) addChild:(CCSprite*)child z:(NSInteger)z tag:(NSInteger) aTag { NSAssert( child != nil, @"Argument must be non-nil"); NSAssert( [child isKindOfClass:[CCSprite class]], @"CCSpriteBatchNode only supports CCSprites as children"); @@ -202,12 +183,11 @@ -(void) addChild:(CCSprite*)child z:(int)z tag:(int) aTag [super addChild:child z:z tag:aTag]; - NSUInteger index = [self atlasIndexForChild:child atZ:z]; - [self insertChild:child inAtlasAtIndex:index]; + [self appendChild:child]; } // override reorderChild --(void) reorderChild:(CCSprite*)child z:(int)z +-(void) reorderChild:(CCSprite*)child z:(NSInteger)z { NSAssert( child != nil, @"Child must be non-nil"); NSAssert( [children_ containsObject:child], @"Child doesn't belong to Sprite" ); @@ -215,11 +195,8 @@ -(void) reorderChild:(CCSprite*)child z:(int)z if( z == child.zOrder ) return; - // XXX: Instead of removing/adding, it is more efficient to reorder manually - [child retain]; - [self removeChild:child cleanup:NO]; - [self addChild:child z:z]; - [child release]; + //set the z-order and sort later + [super reorderChild:child z:z]; } // override removeChild: @@ -245,17 +222,145 @@ -(void)removeChildAtIndex:(NSUInteger)index cleanup:(BOOL)doCleanup -(void)removeAllChildrenWithCleanup:(BOOL)doCleanup { // Invalidate atlas index. issue #569 - [children_ makeObjectsPerformSelector:@selector(useSelfRender)]; - + // useSelfRender should be performed on all descendants. issue #1216 + [descendants_ makeObjectsPerformSelector:@selector(useSelfRender)]; + [super removeAllChildrenWithCleanup:doCleanup]; - + [descendants_ removeAllObjects]; [textureAtlas_ removeAllQuads]; } +//override sortAllChildren +- (void) sortAllChildren +{ + if (isReorderChildDirty_) + { + NSInteger i,j,length=children_->data->num; + CCNode ** x=children_->data->arr; + CCNode *tempItem; + CCSprite *child; + + //insertion sort + for(i=1; i=0 && ( tempItem.zOrder < x[j].zOrder || ( tempItem.zOrder == x[j].zOrder && tempItem.orderOfArrival < x[j].orderOfArrival ) ) ) + { + x[j+1] = x[j]; + j--; + } + + x[j+1] = tempItem; + } + + //sorted now check all children + if ([children_ count] > 0) + { + //first sort all children recursively based on zOrder + CCARRAY_FOREACH(children_, child) child->sortMethod(child,selSortMethod); + + NSInteger index=0; + + //fast dispatch, give every child a new atlasIndex based on their relative zOrder (keep parent -> child relations intact) and at the same time reorder descedants and the quads to the right index + CCARRAY_FOREACH(children_, child) updateAtlasIndexMethod_(self,selUpdateAtlasIndex,child,&index); + } + + isReorderChildDirty_=NO; + } +} + +-(void) updateAtlasIndex:(CCSprite*) sprite currentIndex:(NSInteger*) curIndex +{ + CCArray *array = [sprite children]; + NSUInteger count = [array count]; + NSInteger oldIndex; + + if( count == 0 ) + { + oldIndex=sprite.atlasIndex; + sprite.atlasIndex=*curIndex; + sprite.orderOfArrival=0; + if (oldIndex!=*curIndex) + [self swap:oldIndex withNewIndex:*curIndex]; + (*curIndex)++; + } + else + { + BOOL needNewIndex=YES; + + if (((CCSprite*) (array->data->arr[0])).zOrder >= 0) + {//all children are in front of the parent + oldIndex=sprite.atlasIndex; + sprite.atlasIndex=*curIndex; + sprite.orderOfArrival=0; + if (oldIndex!=*curIndex) + [self swap:oldIndex withNewIndex:*curIndex]; + (*curIndex)++; + + needNewIndex=NO; + } + + CCSprite* child; + CCARRAY_FOREACH(array,child) + { + if (needNewIndex && child.zOrder >= 0) + { + oldIndex=sprite.atlasIndex; + sprite.atlasIndex=*curIndex; + sprite.orderOfArrival=0; + if (oldIndex!=*curIndex) + [self swap:oldIndex withNewIndex:*curIndex]; + (*curIndex)++; + needNewIndex=NO; + + } + //fast dispatch + updateAtlasIndexMethod_(self,selUpdateAtlasIndex,child,curIndex); + } + + if (needNewIndex) + {//all children have a zOrder < 0) + oldIndex=sprite.atlasIndex; + sprite.atlasIndex=*curIndex; + sprite.orderOfArrival=0; + if (oldIndex!=*curIndex) + [self swap:oldIndex withNewIndex:*curIndex]; + (*curIndex)++; + } + } +} + +- (void) swap:(NSInteger) oldIndex withNewIndex:(NSInteger) newIndex +{ + id* x=descendants_->data->arr; + ccV3F_C4B_T2F_Quad* quads=textureAtlas_.quads; + + id tempItem=x[oldIndex]; + ccV3F_C4B_T2F_Quad tempItemQuad=quads[oldIndex]; + + //update the index of other swapped item + ((CCSprite*) x[newIndex]).atlasIndex=oldIndex; + + x[oldIndex]=x[newIndex]; + quads[oldIndex]=quads[newIndex]; + x[newIndex]=tempItem; + quads[newIndex]=tempItemQuad; +} + +- (void) reorderBatch:(BOOL) reorder +{ + isReorderChildDirty_=reorder; +} + #pragma mark CCSpriteBatchNode - draw -(void) draw { + [super draw]; + // Optimization: Fast Dispatch if( textureAtlas_.totalQuads == 0 ) return; @@ -275,13 +380,14 @@ -(void) draw child->updateMethod(child, selUpdate); #if CC_SPRITEBATCHNODE_DEBUG_DRAW - //Issue #528 - CGRect rect = [child boundingBox]; + //Issue #528, 1069 + ccV3F_C4B_T2F_Quad *quads = [textureAtlas_ quads]; + ccV3F_C4B_T2F_Quad *quad= &(quads[child.atlasIndex]); CGPoint vertices[4]={ - ccp(rect.origin.x,rect.origin.y), - ccp(rect.origin.x+rect.size.width,rect.origin.y), - ccp(rect.origin.x+rect.size.width,rect.origin.y+rect.size.height), - ccp(rect.origin.x,rect.origin.y+rect.size.height), + ccp(quad->tl.vertices.x,quad->tl.vertices.y), + ccp(quad->bl.vertices.x,quad->bl.vertices.y), + ccp(quad->br.vertices.x,quad->br.vertices.y), + ccp(quad->tr.vertices.x,quad->tr.vertices.y), }; ccDrawPoly(vertices, 4, YES); #endif // CC_SPRITEBATCHNODE_DEBUG_DRAW @@ -309,15 +415,15 @@ -(void) increaseAtlasCapacity // this is likely computationally expensive NSUInteger quantity = (textureAtlas_.capacity + 1) * 4 / 3; - CCLOG(@"cocos2d: CCSpriteBatchNode: resizing TextureAtlas capacity from [%u] to [%u].", - (unsigned int)textureAtlas_.capacity, - (unsigned int)quantity); + CCLOG(@"cocos2d: CCSpriteBatchNode: resizing TextureAtlas capacity from [%lu] to [%lu].", + (long)textureAtlas_.capacity, + (long)quantity); if( ! [textureAtlas_ resizeCapacity:quantity] ) { // serious problems CCLOG(@"cocos2d: WARNING: Not enough memory to resize the atlas"); - NSAssert(NO,@"XXX: SpriteSheet#increaseAtlasCapacity SHALL handle this assert"); + NSAssert(NO,@"XXX: CCSpriteBatchNode#increaseAtlasCapacity SHALL handle this assert"); } } @@ -367,7 +473,7 @@ -(NSUInteger) lowestAtlasIndexInChild:(CCSprite*)sprite } --(NSUInteger)atlasIndexForChild:(CCSprite*)sprite atZ:(int)z +-(NSUInteger)atlasIndexForChild:(CCSprite*)sprite atZ:(NSInteger)z { CCArray *brothers = [[sprite parent] children]; NSUInteger childIndex = [brothers indexOfObject:sprite]; @@ -441,11 +547,38 @@ -(void) insertChild:(CCSprite*)sprite inAtlasAtIndex:(NSUInteger)index // add children recursively CCARRAY_FOREACH(sprite.children, child){ - NSUInteger index = [self atlasIndexForChild:child atZ: child.zOrder]; - [self insertChild:child inAtlasAtIndex:index]; + NSUInteger idx = [self atlasIndexForChild:child atZ: child.zOrder]; + [self insertChild:child inAtlasAtIndex:idx]; } } +// addChild helper, faster than insertChild +-(void) appendChild:(CCSprite*)sprite +{ + isReorderChildDirty_=YES; + [sprite useBatchNode:self]; + [sprite setDirty: YES]; + + if(textureAtlas_.totalQuads == textureAtlas_.capacity) + [self increaseAtlasCapacity]; + + ccArray *descendantsData = descendants_->data; + + ccArrayAppendObjectWithResize(descendantsData, sprite); + + NSUInteger index=descendantsData->num-1; + + sprite.atlasIndex=index; + + ccV3F_C4B_T2F_Quad quad = [sprite quad]; + [textureAtlas_ insertQuad:&quad atIndex:index]; + + // add children recursively + CCSprite* child; + CCARRAY_FOREACH(sprite.children, child) [self appendChild:child]; +} + + // remove child helper -(void) removeSpriteFromAtlas:(CCSprite*)sprite { diff --git a/libs/cocos2d/CCSpriteFrame.h b/libs/cocos2d/CCSpriteFrame.h index ce8c1cf..983aeed 100644 --- a/libs/cocos2d/CCSpriteFrame.h +++ b/libs/cocos2d/CCSpriteFrame.h @@ -1,7 +1,8 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2008-2011 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -46,10 +47,10 @@ CGSize originalSizeInPixels_; CCTexture2D *texture_; } -/** rect of the frame in points */ +/** rect of the frame in points. If it is updated, then rectInPixels will be updated too. */ @property (nonatomic,readwrite) CGRect rect; -/** rect of the frame in pixels */ +/** rect of the frame in pixels. If it is updated, then rect (points) will be udpated too. */ @property (nonatomic,readwrite) CGRect rectInPixels; /** whether or not the rect of the frame is rotated ( x = x+width, y = y+height, width = height, height = width ) */ diff --git a/libs/cocos2d/CCSpriteFrame.m b/libs/cocos2d/CCSpriteFrame.m index 952d9aa..e9ebd04 100644 --- a/libs/cocos2d/CCSpriteFrame.m +++ b/libs/cocos2d/CCSpriteFrame.m @@ -1,7 +1,8 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2008-2011 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,7 +30,6 @@ #import "ccMacros.h" @implementation CCSpriteFrame -@synthesize rect = rect_, rectInPixels=rectInPixels_; @synthesize rotated = rotated_, offsetInPixels = offsetInPixels_, texture = texture_; @synthesize originalSizeInPixels=originalSizeInPixels_; @@ -64,12 +64,14 @@ -(id) initWithTexture:(CCTexture2D*)texture rectInPixels:(CGRect)rect rotated:(B - (NSString*) description { - return [NSString stringWithFormat:@"<%@ = %08X | TextureName=%d, Rect = (%.2f,%.2f,%.2f,%.2f)>", [self class], self, + return [NSString stringWithFormat:@"<%@ = %08X | TextureName=%d, Rect = (%.2f,%.2f,%.2f,%.2f)> rotated:%d", [self class], self, texture_.name, rect_.origin.x, rect_.origin.y, rect_.size.width, - rect_.size.height]; + rect_.size.height, + rotated_ + ]; } - (void) dealloc @@ -84,4 +86,26 @@ -(id) copyWithZone: (NSZone*) zone CCSpriteFrame *copy = [[[self class] allocWithZone: zone] initWithTexture:texture_ rectInPixels:rectInPixels_ rotated:rotated_ offset:offsetInPixels_ originalSize:originalSizeInPixels_]; return copy; } + +-(CGRect) rect +{ + return rect_; +} + +-(CGRect) rectInPixels +{ + return rectInPixels_; +} + +-(void) setRect:(CGRect)rect +{ + rect_ = rect; + rectInPixels_ = CC_RECT_POINTS_TO_PIXELS( rect_ ); +} + +-(void) setRectInPixels:(CGRect)rectInPixels +{ + rectInPixels_ = rectInPixels; + rect_ = CC_RECT_PIXELS_TO_POINTS(rectInPixels); +} @end diff --git a/libs/cocos2d/CCSpriteFrameCache.h b/libs/cocos2d/CCSpriteFrameCache.h index b50a6a0..67504d8 100644 --- a/libs/cocos2d/CCSpriteFrameCache.h +++ b/libs/cocos2d/CCSpriteFrameCache.h @@ -1,9 +1,13 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2008-2010 Ricardo Quesada * Copyright (c) 2009 Jason Booth + * * Copyright (c) 2009 Robert J Payne + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -123,11 +127,4 @@ */ -(CCSpriteFrame*) spriteFrameByName:(NSString*)name; -/** Creates an sprite with the name of an sprite frame. - The created sprite will contain the texture, rect and offset of the sprite frame. - It returns an autorelease object. - @deprecated use [CCSprite spriteWithSpriteFrameName:name]. This method will be removed on final v0.9 - */ --(CCSprite*) createSpriteWithFrameName:(NSString*)name DEPRECATED_ATTRIBUTE; - @end diff --git a/libs/cocos2d/CCSpriteFrameCache.m b/libs/cocos2d/CCSpriteFrameCache.m index 514ab97..e46204a 100644 --- a/libs/cocos2d/CCSpriteFrameCache.m +++ b/libs/cocos2d/CCSpriteFrameCache.m @@ -1,9 +1,12 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2008-2010 Ricardo Quesada * Copyright (c) 2009 Jason Booth + * * Copyright (c) 2009 Robert J Payne + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -116,7 +119,7 @@ -(void) addSpriteFramesWithDictionary:(NSDictionary*)dictionary texture:(CCTextu // add real frames for(NSString *frameDictKey in framesDict) { NSDictionary *frameDict = [framesDict objectForKey:frameDictKey]; - CCSpriteFrame *spriteFrame; + CCSpriteFrame *spriteFrame=nil; if(format == 0) { float x = [[frameDict objectForKey:@"x"] floatValue]; float y = [[frameDict objectForKey:@"y"] floatValue]; @@ -193,7 +196,7 @@ -(void) addSpriteFramesWithFile:(NSString*)plist texture:(CCTexture2D*)texture NSString *path = [CCFileUtils fullPathFromRelativePath:plist]; NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; - return [self addSpriteFramesWithDictionary:dict texture:texture]; + [self addSpriteFramesWithDictionary:dict texture:texture]; } -(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName @@ -334,11 +337,4 @@ -(CCSpriteFrame*) spriteFrameByName:(NSString*)name return frame; } -#pragma mark CCSpriteFrameCache - sprite creation - --(CCSprite*) createSpriteWithFrameName:(NSString*)name -{ - CCSpriteFrame *frame = [spriteFrames_ objectForKey:name]; - return [CCSprite spriteWithSpriteFrame:frame]; -} @end diff --git a/libs/cocos2d/CCSpriteSheet.h b/libs/cocos2d/CCSpriteSheet.h deleted file mode 100644 index c55f534..0000000 --- a/libs/cocos2d/CCSpriteSheet.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * cocos2d for iPhone: http://www.cocos2d-iphone.org - * - * Copyright (c) 2009-2010 Ricardo Quesada - * Copyright (C) 2009 Matt Oswald - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - - -#import "CCSpriteBatchNode.h" - -#pragma mark CCSpriteSheet - - -/* Added only to prevent GCC compile warnings - Will be removed in v1.1 - */ -@interface CCSpriteSheetInternalOnly : CCSpriteBatchNode -{ -} -@end - -/** CCSpriteSheet is like a batch node: if it contains children, it will draw them in 1 single OpenGL call - * (often known as "batch draw"). - * - * A CCSpriteSheet can reference one and only one texture (one image file, one texture atlas). - * Only the CCSprites that are contained in that texture can be added to the CCSpriteSheet. - * All CCSprites added to a CCSpriteSheet are drawn in one OpenGL ES draw call. - * If the CCSprites are not added to a CCSpriteSheet then an OpenGL ES draw call will be needed for each one, which is less efficient. - * - * - * Limitations: - * - The only object that is accepted as child (or grandchild, grand-grandchild, etc...) is CCSprite or any subclass of CCSprite. eg: particles, labels and layer can't be added to a CCSpriteSheet. - * - Either all its children are Aliased or Antialiased. It can't be a mix. This is because "alias" is a property of the texture, and all the sprites share the same texture. - * - * @since v0.7.1 - * - * @deprecated Use CCSpriteBatchNode instead. This class will be removed in v1.1 - */ -DEPRECATED_ATTRIBUTE @interface CCSpriteSheet : CCSpriteSheetInternalOnly -{ -} -@end diff --git a/libs/cocos2d/CCTMXLayer.h b/libs/cocos2d/CCTMXLayer.h index b7dc2ab..a5b0b47 100644 --- a/libs/cocos2d/CCTMXLayer.h +++ b/libs/cocos2d/CCTMXLayer.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,7 +39,7 @@ /** CCTMXLayer represents the TMX layer. - It is a subclass of CCSpriteSheet. By default the tiles are rendered using a CCTextureAtlas. + It is a subclass of CCSpriteBatchNode. By default the tiles are rendered using a CCTextureAtlas. If you mofify a tile on runtime, then, that tile will become a CCSprite, otherwise no CCSprite objects are created. The benefits of using CCSprite objects as tiles are: - tiles (CCSprite) can be rotated/scaled/moved with a nice API @@ -60,6 +61,10 @@ http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:tiled_maps @since v0.8.1 + + Tiles can have tile flags for additional properties. At the moment only flip horizontal and flip vertical are used. These bit flags are defined in CCTMXXMLParser.h. + + @since 1.1 */ @interface CCTMXLayer : CCSpriteBatchNode { @@ -67,25 +72,23 @@ NSString *layerName_; CGSize layerSize_; CGSize mapTileSize_; - unsigned int *tiles_; - int layerOrientation_; + uint32_t *tiles_; // GID are 32 bit + NSUInteger layerOrientation_; NSMutableArray *properties_; unsigned char opacity_; // TMX Layer supports opacity - unsigned int minGID_; - unsigned int maxGID_; + NSUInteger minGID_; + NSUInteger maxGID_; // Only used when vertexZ is used - int vertexZvalue_; + NSInteger vertexZvalue_; BOOL useAutomaticVertexZ_; float alphaFuncValue_; // used for optimization CCSprite *reusedTile_; ccCArray *atlasIndexArray_; - - } /** name of the layer */ @property (nonatomic,readwrite,retain) NSString *layerName; @@ -94,11 +97,11 @@ /** size of the map's tile (could be differnt from the tile's size) */ @property (nonatomic,readwrite) CGSize mapTileSize; /** pointer to the map of tiles */ -@property (nonatomic,readwrite) unsigned int *tiles; +@property (nonatomic,readwrite) uint32_t *tiles; /** Tilset information for the layer */ @property (nonatomic,readwrite,retain) CCTMXTilesetInfo *tileset; /** Layer orientation, which is the same as the map orientation */ -@property (nonatomic,readwrite) int layerOrientation; +@property (nonatomic,readwrite) NSUInteger layerOrientation; /** properties from the layer. They can be added using Tiled */ @property (nonatomic,readwrite,retain) NSMutableArray *properties; @@ -126,13 +129,28 @@ if it returns 0, it means that the tile is empty. This method requires the the tile map has not been previously released (eg. don't call [layer releaseMap]) */ --(unsigned int) tileGIDAt:(CGPoint)tileCoordinate; +-(uint32_t) tileGIDAt:(CGPoint)tileCoordinate; + +/** returns the tile gid at a given tile coordinate and includes the tile flags when flag is YES + if it returns 0, it means that the tile is empty. + This method requires the the tile map has not been previously released (eg. don't call [layer releaseMap]) + */ +-(uint32_t) tileGIDAt:(CGPoint)pos withFlags:(BOOL) flags; /** sets the tile gid (gid = tile global id) at a given tile coordinate. The Tile GID can be obtained by using the method "tileGIDAt" or by using the TMX editor -> Tileset Mgr +1. If a tile is already placed at that position, then it will be removed. */ --(void) setTileGID:(unsigned int)gid at:(CGPoint)tileCoordinate; +-(void) setTileGID:(uint32_t)gid at:(CGPoint)tileCoordinate; + +/** sets the tile gid (gid = tile global id) at a given tile coordinate. + The Tile GID can be obtained by using the method "tileGIDAt" or by using the TMX editor -> Tileset Mgr +1. + If a tile is already placed at that position, then it will be removed. + + Use withFlags if the tile flags need to be changed as well + */ + +-(void) setTileGID:(uint32_t)gid at:(CGPoint)pos withFlags:(BOOL) flags; /** removes a tile at given tile coordinate */ -(void) removeTileAt:(CGPoint)tileCoordinate; @@ -149,5 +167,5 @@ /** CCTMXLayer doesn't support adding a CCSprite manually. @warning addchild:z:tag: is not supported on CCTMXLayer. Instead of setTileGID:at:/tileAt: */ --(void) addChild: (CCNode*)node z:(int)z tag:(int)tag; +-(void) addChild: (CCNode*)node z:(NSInteger)z tag:(NSInteger)tag; @end diff --git a/libs/cocos2d/CCTMXLayer.m b/libs/cocos2d/CCTMXLayer.m index 887af20..d925605 100644 --- a/libs/cocos2d/CCTMXLayer.m +++ b/libs/cocos2d/CCTMXLayer.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,22 +36,28 @@ #import "CCTextureCache.h" #import "Support/CGPointExtension.h" + #pragma mark - #pragma mark CCSpriteBatchNode Extension +@interface CCSpriteBatchNode (TMXTiledMapExtensions) +-(id) addSpriteWithoutQuad:(CCSprite*)child z:(NSUInteger)z tag:(NSInteger)aTag; +-(void) addQuadFromSprite:(CCSprite*)sprite quadIndex:(NSUInteger)index; +@end + /* IMPORTANT XXX IMPORTNAT: - * These 2 methods can't be part of CCTMXLayer since they call [super add...], and CCSpriteSheet#add SHALL not be called + * These 2 methods can't be part of CCTMXLayer since they call [super add...], and CCSpriteBatchNode#add SHALL not be called */ @implementation CCSpriteBatchNode (TMXTiledMapExtension) /* Adds a quad into the texture atlas but it won't be added into the children array. This method should be called only when you are dealing with very big AtlasSrite and when most of the CCSprite won't be updated. - For example: a tile map (CCTMXMap) or a label with lots of characgers (BitmapFontAtlas) + For example: a tile map (CCTMXMap) or a label with lots of characgers (CCLabelBMFont) */ --(void) addQuadFromSprite:(CCSprite*)sprite quadIndex:(unsigned int)index +-(void) addQuadFromSprite:(CCSprite*)sprite quadIndex:(NSUInteger)index { NSAssert( sprite != nil, @"Argument must be non-nil"); - NSAssert( [sprite isKindOfClass:[CCSprite class]], @"CCSpriteSheet only supports CCSprites as children"); + NSAssert( [sprite isKindOfClass:[CCSprite class]], @"CCSpriteBatchNode only supports CCSprites as children"); while(index >= textureAtlas_.capacity || textureAtlas_.capacity == textureAtlas_.totalQuads ) @@ -75,10 +82,10 @@ -(void) addQuadFromSprite:(CCSprite*)sprite quadIndex:(unsigned int)index /* This is the opposite of "addQuadFromSprite. It add the sprite to the children and descendants array, but it doesn't update add it to the texture atlas */ --(id) addSpriteWithoutQuad:(CCSprite*)child z:(unsigned int)z tag:(int)aTag +-(id) addSpriteWithoutQuad:(CCSprite*)child z:(NSUInteger)z tag:(NSInteger)aTag { NSAssert( child != nil, @"Argument must be non-nil"); - NSAssert( [child isKindOfClass:[CCSprite class]], @"CCSpriteSheet only supports CCSprites as children"); + NSAssert( [child isKindOfClass:[CCSprite class]], @"CCSpriteBatchNode only supports CCSprites as children"); // quad index is Z [child setAtlasIndex:z]; @@ -95,6 +102,9 @@ -(id) addSpriteWithoutQuad:(CCSprite*)child z:(unsigned int)z tag:(int)aTag // IMPORTANT: Call super, and not self. Avoid adding it to the texture atlas array [super addChild:child z:z tag:aTag]; + + //#issue 1262 don't use lazy sorting, tiles are added as quads not as sprites, so sprites need to be added in order + [self reorderBatch:NO]; return self; } @end @@ -103,7 +113,10 @@ -(id) addSpriteWithoutQuad:(CCSprite*)child z:(unsigned int)z tag:(int)aTag #pragma mark - #pragma mark CCTMXLayer -@interface CCTMXLayer (Private) +int compareInts (const void * a, const void * b); + + +@interface CCTMXLayer () -(CGPoint) positionForIsoAt:(CGPoint)pos; -(CGPoint) positionForOrthoAt:(CGPoint)pos; -(CGPoint) positionForHexAt:(CGPoint)pos; @@ -111,20 +124,15 @@ -(CGPoint) positionForHexAt:(CGPoint)pos; -(CGPoint) calculateLayerOffset:(CGPoint)offset; /* optimization methos */ --(CCSprite*) appendTileForGID:(unsigned int)gid at:(CGPoint)pos; --(CCSprite*) insertTileForGID:(unsigned int)gid at:(CGPoint)pos; --(CCSprite*) updateTileForGID:(unsigned int)gid at:(CGPoint)pos; +-(CCSprite*) appendTileForGID:(uint32_t)gid at:(CGPoint)pos; +-(CCSprite*) insertTileForGID:(uint32_t)gid at:(CGPoint)pos; +-(CCSprite*) updateTileForGID:(uint32_t)gid at:(CGPoint)pos; /* The layer recognizes some special properties, like cc_vertez */ -(void) parseInternalProperties; +- (void) setupTileSprite:(CCSprite*) sprite position:(CGPoint)pos withGID:(uint32_t)gid; --(int) vertexZForPos:(CGPoint)pos; - -// adding quad from sprite --(void)addQuadFromSprite:(CCSprite*)sprite quadIndex:(unsigned int)index; - -// adds an sprite without the quad --(id)addSpriteWithoutQuad:(CCSprite*)child z:(int)z tag:(int)aTag; +-(NSInteger) vertexZForPos:(CGPoint)pos; // index -(NSUInteger) atlasIndexForExistantZ:(NSUInteger)z; @@ -242,11 +250,11 @@ -(void) setupTiles // Parse cocos2d properties [self parseInternalProperties]; - for( unsigned int y=0; y < layerSize_.height; y++ ) { - for( unsigned int x=0; x < layerSize_.width; x++ ) { + for( NSUInteger y=0; y < layerSize_.height; y++ ) { + for( NSUInteger x=0; x < layerSize_.width; x++ ) { - unsigned int pos = x + layerSize_.width * y; - unsigned int gid = tiles_[ pos ]; + NSUInteger pos = x + layerSize_.width * y; + uint32_t gid = tiles_[ pos ]; // gid are stored in little endian. // if host is big endian, then swap @@ -260,6 +268,8 @@ -(void) setupTiles // Optimization: update min and max GID rendered by the layer minGID_ = MIN(gid, minGID_); maxGID_ = MAX(gid, maxGID_); +// minGID_ = MIN((gid & kFlippedMask), minGID_); +// maxGID_ = MAX((gid & kFlippedMask), maxGID_); } } } @@ -299,7 +309,7 @@ -(CCSprite*) tileAt:(CGPoint)pos NSAssert( tiles_ && atlasIndexArray_, @"TMXLayer: the tiles map has been released"); CCSprite *tile = nil; - unsigned int gid = [self tileGIDAt:pos]; + uint32_t gid = [self tileGIDAt:pos]; // if GID == 0, then no tile is present if( gid ) { @@ -315,7 +325,7 @@ -(CCSprite*) tileAt:(CGPoint)pos tile.anchorPoint = CGPointZero; [tile setOpacity:opacity_]; - unsigned int indexForZ = [self atlasIndexForExistantZ:z]; + NSUInteger indexForZ = [self atlasIndexForExistantZ:z]; [self addSpriteWithoutQuad:tile z:indexForZ tag:z]; [tile release]; } @@ -323,18 +333,48 @@ -(CCSprite*) tileAt:(CGPoint)pos return tile; } --(unsigned int) tileGIDAt:(CGPoint)pos +-(uint32_t) tileGIDAt:(CGPoint)pos +{ + return [self tileGIDAt:pos withFlags:NO]; +} + +-(uint32_t) tileGIDAt:(CGPoint)pos withFlags:(BOOL) flags { NSAssert( pos.x < layerSize_.width && pos.y < layerSize_.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position"); NSAssert( tiles_ && atlasIndexArray_, @"TMXLayer: the tiles map has been released"); - int idx = pos.x + pos.y * layerSize_.width; - return tiles_[ idx ]; + NSInteger idx = pos.x + pos.y * layerSize_.width; + + // Bits on the far end of the 32-bit global tile ID are used for tile flags + // issue1264, flipped tiles can be changed dynamically + if (flags) + return (tiles_[ idx ]); + else + return (tiles_[ idx ] & kFlippedMask); } #pragma mark CCTMXLayer - adding helper methods --(CCSprite*) insertTileForGID:(unsigned int)gid at:(CGPoint)pos +- (void) setupTileSprite:(CCSprite*) sprite position:(CGPoint)pos withGID:(uint32_t)gid +{ + [sprite setPositionInPixels: [self positionAt:pos]]; + [sprite setVertexZ: [self vertexZForPos:pos]]; + sprite.anchorPoint = CGPointZero; + [sprite setOpacity:opacity_]; + + //issue 1264, flip can be undone as well + if (gid & kFlippedHorizontallyFlag) + sprite.flipX = YES; + else + sprite.flipX = NO; + + if (gid & kFlippedVerticallyFlag) + sprite.flipY = YES; + else + sprite.flipY = NO; +} + +-(CCSprite*) insertTileForGID:(uint32_t)gid at:(CGPoint)pos { CGRect rect = [tileset_ rectForGID:gid]; @@ -345,10 +385,7 @@ -(CCSprite*) insertTileForGID:(unsigned int)gid at:(CGPoint)pos else [reusedTile_ initWithBatchNode:self rectInPixels:rect]; - [reusedTile_ setPositionInPixels: [self positionAt:pos]]; - [reusedTile_ setVertexZ: [self vertexZForPos:pos]]; - reusedTile_.anchorPoint = CGPointZero; - [reusedTile_ setOpacity:opacity_]; + [self setupTileSprite:reusedTile_ position:pos withGID:gid]; // get atlas index NSUInteger indexForZ = [self atlasIndexForNewZ:z]; @@ -362,7 +399,7 @@ -(CCSprite*) insertTileForGID:(unsigned int)gid at:(CGPoint)pos // update possible children CCSprite *sprite; CCARRAY_FOREACH(children_, sprite) { - unsigned int ai = [sprite atlasIndex]; + NSUInteger ai = [sprite atlasIndex]; if( ai >= indexForZ) [sprite setAtlasIndex: ai+1]; } @@ -372,7 +409,7 @@ -(CCSprite*) insertTileForGID:(unsigned int)gid at:(CGPoint)pos return reusedTile_; } --(CCSprite*) updateTileForGID:(unsigned int)gid at:(CGPoint)pos +-(CCSprite*) updateTileForGID:(uint32_t)gid at:(CGPoint)pos { CGRect rect = [tileset_ rectForGID:gid]; @@ -383,13 +420,10 @@ -(CCSprite*) updateTileForGID:(unsigned int)gid at:(CGPoint)pos else [reusedTile_ initWithBatchNode:self rectInPixels:rect]; - [reusedTile_ setPositionInPixels: [self positionAt:pos]]; - [reusedTile_ setVertexZ: [self vertexZForPos:pos]]; - reusedTile_.anchorPoint = CGPointZero; - [reusedTile_ setOpacity:opacity_]; + [self setupTileSprite:reusedTile_ position:pos withGID:gid]; // get atlas index - unsigned int indexForZ = [self atlasIndexForExistantZ:z]; + NSUInteger indexForZ = [self atlasIndexForExistantZ:z]; [reusedTile_ setAtlasIndex:indexForZ]; [reusedTile_ setDirty:YES]; @@ -402,7 +436,7 @@ -(CCSprite*) updateTileForGID:(unsigned int)gid at:(CGPoint)pos // used only when parsing the map. useless after the map was parsed // since lot's of assumptions are no longer true --(CCSprite*) appendTileForGID:(unsigned int)gid at:(CGPoint)pos +-(CCSprite*) appendTileForGID:(uint32_t)gid at:(CGPoint)pos { CGRect rect = [tileset_ rectForGID:gid]; @@ -413,10 +447,7 @@ -(CCSprite*) appendTileForGID:(unsigned int)gid at:(CGPoint)pos else [reusedTile_ initWithBatchNode:self rectInPixels:rect]; - [reusedTile_ setPositionInPixels: [self positionAt:pos]]; - [reusedTile_ setVertexZ: [self vertexZForPos:pos]]; - reusedTile_.anchorPoint = CGPointZero; - [reusedTile_ setOpacity:opacity_]; + [self setupTileSprite:reusedTile_ position:pos withGID:gid]; // optimization: // The difference between appendTileForGID and insertTileforGID is that append is faster, since @@ -465,17 +496,21 @@ -(NSUInteger)atlasIndexForNewZ:(NSUInteger)z } #pragma mark CCTMXLayer - adding / remove tiles +-(void) setTileGID:(uint32_t)gid at:(CGPoint)pos +{ + [self setTileGID:gid at:pos withFlags:NO]; +} --(void) setTileGID:(unsigned int)gid at:(CGPoint)pos +-(void) setTileGID:(uint32_t)gid at:(CGPoint)pos withFlags:(BOOL) flags { NSAssert( pos.x < layerSize_.width && pos.y < layerSize_.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position"); NSAssert( tiles_ && atlasIndexArray_, @"TMXLayer: the tiles map has been released"); NSAssert( gid == 0 || gid >= tileset_.firstGid, @"TMXLayer: invalid gid" ); - unsigned int currentGID = [self tileGIDAt:pos]; + uint32_t currentGID = [self tileGIDAt:pos withFlags:flags]; - if( currentGID != gid ) { - + if (currentGID != gid) + { // setting gid=0 is equal to remove the tile if( gid == 0 ) [self removeTileAt:pos]; @@ -487,11 +522,15 @@ -(void) setTileGID:(unsigned int)gid at:(CGPoint)pos // modifying an existing tile with a non-empty tile else { - unsigned int z = pos.x + pos.y * layerSize_.width; - id sprite = [self getChildByTag:z]; + NSUInteger z = pos.x + pos.y * layerSize_.width; + CCSprite *sprite = (CCSprite *)[self getChildByTag:z]; if( sprite ) { CGRect rect = [tileset_ rectForGID:gid]; [sprite setTextureRectInPixels:rect rotated:NO untrimmedSize:rect.size]; + + if (flags) + [self setupTileSprite:sprite position:[sprite position] withGID:gid]; + tiles_[z] = gid; } else [self updateTileForGID:gid at:pos]; @@ -499,7 +538,7 @@ -(void) setTileGID:(unsigned int)gid at:(CGPoint)pos } } --(void) addChild: (CCNode*)node z:(int)z tag:(int)tag +-(void) addChild: (CCNode*)node z:(NSInteger)z tag:(NSInteger)tag { NSAssert(NO, @"addChild: is not supported on CCTMXLayer. Instead use setTileGID:at:/tileAt:"); } @@ -512,7 +551,7 @@ -(void) removeChild:(CCSprite*)sprite cleanup:(BOOL)cleanup NSAssert( [children_ containsObject:sprite], @"Tile does not belong to TMXLayer"); - unsigned int atlasIndex = [sprite atlasIndex]; + NSUInteger atlasIndex = [sprite atlasIndex]; NSUInteger zz = (NSUInteger) atlasIndexArray_->arr[atlasIndex]; tiles_[zz] = 0; ccCArrayRemoveValueAtIndex(atlasIndexArray_, atlasIndex); @@ -524,12 +563,12 @@ -(void) removeTileAt:(CGPoint)pos NSAssert( pos.x < layerSize_.width && pos.y < layerSize_.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position"); NSAssert( tiles_ && atlasIndexArray_, @"TMXLayer: the tiles map has been released"); - unsigned int gid = [self tileGIDAt:pos]; + uint32_t gid = [self tileGIDAt:pos]; if( gid ) { - unsigned int z = pos.x + pos.y * layerSize_.width; - unsigned atlasIndex = [self atlasIndexForExistantZ:z]; + NSUInteger z = pos.x + pos.y * layerSize_.width; + NSUInteger atlasIndex = [self atlasIndexForExistantZ:z]; // remove tile from GID map tiles_[z] = 0; @@ -545,9 +584,8 @@ -(void) removeTileAt:(CGPoint)pos [textureAtlas_ removeQuadAtIndex:atlasIndex]; // update possible children - CCSprite *sprite; CCARRAY_FOREACH(children_, sprite) { - unsigned int ai = [sprite atlasIndex]; + NSUInteger ai = [sprite atlasIndex]; if( ai >= atlasIndex) { [sprite setAtlasIndex: ai-1]; } @@ -624,10 +662,10 @@ -(CGPoint) positionForHexAt:(CGPoint)pos return xy; } --(int) vertexZForPos:(CGPoint)pos +-(NSInteger) vertexZForPos:(CGPoint)pos { - int ret = 0; - unsigned int maxVal = 0; + NSInteger ret = 0; + NSUInteger maxVal = 0; if( useAutomaticVertexZ_ ) { switch( layerOrientation_ ) { case CCTMXOrientationIso: diff --git a/libs/cocos2d/CCTMXObjectGroup.h b/libs/cocos2d/CCTMXObjectGroup.h index f2a3f2c..02feadf 100644 --- a/libs/cocos2d/CCTMXObjectGroup.h +++ b/libs/cocos2d/CCTMXObjectGroup.h @@ -1,9 +1,11 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2010 Ricardo Quesada * Copyright (c) 2010 Neophit * + * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -28,7 +30,7 @@ * */ -#import "CCSpriteSheet.h" +#import "CCNode.h" @class CCTMXObjectGroup; diff --git a/libs/cocos2d/CCTMXObjectGroup.m b/libs/cocos2d/CCTMXObjectGroup.m index c0c0537..648cda4 100644 --- a/libs/cocos2d/CCTMXObjectGroup.m +++ b/libs/cocos2d/CCTMXObjectGroup.m @@ -1,9 +1,11 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2010 Ricardo Quesada * Copyright (c) 2010 Neophit * + * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -30,6 +32,7 @@ #import "CCTMXObjectGroup.h" #import "CCTMXXMLParser.h" +#import "ccMacros.h" #import "Support/CGPointExtension.h" diff --git a/libs/cocos2d/CCTMXTiledMap.h b/libs/cocos2d/CCTMXTiledMap.h index 3ae0153..225edb6 100644 --- a/libs/cocos2d/CCTMXTiledMap.h +++ b/libs/cocos2d/CCTMXTiledMap.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,7 +28,7 @@ * */ -#import "CCSpriteSheet.h" +#import "CCNode.h" @class CCTMXLayer; @@ -75,7 +76,7 @@ enum - It only supports the XML format (the JSON format is not supported) Technical description: - Each layer is created using an CCTMXLayer (subclass of CCSpriteSheet). If you have 5 layers, then 5 CCTMXLayer will be created, + Each layer is created using an CCTMXLayer (subclass of CCSpriteBatchNode). If you have 5 layers, then 5 CCTMXLayer will be created, unless the layer visibility is off. In that case, the layer won't be created at all. You can obtain the layers (CCTMXLayer objects) at runtime by: - [map getChildByTag: tag_number]; // 0=1st layer, 1=2nd layer, 2=3rd layer, etc... @@ -121,20 +122,21 @@ enum /** creates a TMX Tiled Map with a TMX file.*/ +(id) tiledMapWithTMXFile:(NSString*)tmxFile; +/** initializes a TMX Tiled Map with a TMX formatted XML string and a path to TMX resources */ ++(id) tiledMapWithXML:(NSString*)tmxString resourcePath:(NSString*)resourcePath; + /** initializes a TMX Tiled Map with a TMX file */ -(id) initWithTMXFile:(NSString*)tmxFile; +/** initializes a TMX Tiled Map with a TMX formatted XML string and a path to TMX resources */ +-(id) initWithXML:(NSString*)tmxString resourcePath:(NSString*)resourcePath; + /** return the TMXLayer for the specific layer */ -(CCTMXLayer*) layerNamed:(NSString *)layerName; /** return the TMXObjectGroup for the secific group */ -(CCTMXObjectGroup*) objectGroupNamed:(NSString *)groupName; -/** return the TMXObjectGroup for the secific group - @deprecated Use map#objectGroupNamed instead - */ --(CCTMXObjectGroup*) groupNamed:(NSString *)groupName DEPRECATED_ATTRIBUTE; - /** return the value for the specific property name */ -(id) propertyNamed:(NSString *)propertyName; diff --git a/libs/cocos2d/CCTMXTiledMap.m b/libs/cocos2d/CCTMXTiledMap.m index 70838a2..1bce7d6 100644 --- a/libs/cocos2d/CCTMXTiledMap.m +++ b/libs/cocos2d/CCTMXTiledMap.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,7 +33,6 @@ #import "CCTMXLayer.h" #import "CCTMXObjectGroup.h" #import "CCSprite.h" -#import "CCSpriteSheet.h" #import "CCTextureCache.h" #import "Support/CGPointExtension.h" @@ -43,6 +43,7 @@ @interface CCTMXTiledMap (Private) -(id) parseLayer:(CCTMXLayerInfo*)layer map:(CCTMXMapInfo*)mapInfo; -(CCTMXTilesetInfo*) tilesetForLayer:(CCTMXLayerInfo*)layerInfo map:(CCTMXMapInfo*)mapInfo; +-(void) buildWithMapInfo:(CCTMXMapInfo*)mapInfo; @end @implementation CCTMXTiledMap @@ -57,6 +58,55 @@ +(id) tiledMapWithTMXFile:(NSString*)tmxFile return [[[self alloc] initWithTMXFile:tmxFile] autorelease]; } ++(id) tiledMapWithXML:(NSString*)tmxString resourcePath:(NSString*)resourcePath +{ + return [[[self alloc] initWithXML:tmxString resourcePath:resourcePath] autorelease]; +} + +-(void) buildWithMapInfo:(CCTMXMapInfo*)mapInfo +{ + mapSize_ = mapInfo.mapSize; + tileSize_ = mapInfo.tileSize; + mapOrientation_ = mapInfo.orientation; + objectGroups_ = [mapInfo.objectGroups retain]; + properties_ = [mapInfo.properties retain]; + tileProperties_ = [mapInfo.tileProperties retain]; + + int idx=0; + + for( CCTMXLayerInfo *layerInfo in mapInfo.layers ) { + + if( layerInfo.visible ) { + CCNode *child = [self parseLayer:layerInfo map:mapInfo]; + [self addChild:child z:idx tag:idx]; + + // update content size with the max size + CGSize childSize = [child contentSize]; + CGSize currentSize = [self contentSize]; + currentSize.width = MAX( currentSize.width, childSize.width ); + currentSize.height = MAX( currentSize.height, childSize.height ); + [self setContentSize:currentSize]; + + idx++; + } + } +} + +-(id) initWithXML:(NSString*)tmxString resourcePath:(NSString*)resourcePath +{ + if ((self=[super init])) { + + [self setContentSize:CGSizeZero]; + + CCTMXMapInfo *mapInfo = [CCTMXMapInfo formatWithXML:tmxString resourcePath:resourcePath]; + + NSAssert( [mapInfo.tilesets count] != 0, @"TMXTiledMap: Map not found. Please check the filename."); + [self buildWithMapInfo:mapInfo]; + } + + return self; +} + -(id) initWithTMXFile:(NSString*)tmxFile { NSAssert(tmxFile != nil, @"TMXTiledMap: tmx file should not bi nil"); @@ -68,32 +118,7 @@ -(id) initWithTMXFile:(NSString*)tmxFile CCTMXMapInfo *mapInfo = [CCTMXMapInfo formatWithTMXFile:tmxFile]; NSAssert( [mapInfo.tilesets count] != 0, @"TMXTiledMap: Map not found. Please check the filename."); - - mapSize_ = mapInfo.mapSize; - tileSize_ = mapInfo.tileSize; - mapOrientation_ = mapInfo.orientation; - objectGroups_ = [mapInfo.objectGroups retain]; - properties_ = [mapInfo.properties retain]; - tileProperties_ = [mapInfo.tileProperties retain]; - - int idx=0; - - for( CCTMXLayerInfo *layerInfo in mapInfo.layers ) { - - if( layerInfo.visible ) { - CCNode *child = [self parseLayer:layerInfo map:mapInfo]; - [self addChild:child z:idx tag:idx]; - - // update content size with the max size - CGSize childSize = [child contentSize]; - CGSize currentSize = [self contentSize]; - currentSize.width = MAX( currentSize.width, childSize.width ); - currentSize.height = MAX( currentSize.height, childSize.height ); - [self setContentSize:currentSize]; - - idx++; - } - } + [self buildWithMapInfo:mapInfo]; } return self; @@ -123,7 +148,6 @@ -(id) parseLayer:(CCTMXLayerInfo*)layerInfo map:(CCTMXMapInfo*)mapInfo -(CCTMXTilesetInfo*) tilesetForLayer:(CCTMXLayerInfo*)layerInfo map:(CCTMXMapInfo*)mapInfo { - CCTMXTilesetInfo *tileset = nil; CFByteOrder o = CFByteOrderGetCurrent(); CGSize size = layerInfo.layerSize; @@ -146,7 +170,7 @@ -(CCTMXTilesetInfo*) tilesetForLayer:(CCTMXLayerInfo*)layerInfo map:(CCTMXMapInf // Optimization: quick return // if the layer is invalid (more than 1 tileset per layer) an assert will be thrown later - if( gid >= tileset.firstGid ) + if( (gid & kFlippedMask) >= tileset.firstGid ) return tileset; } } @@ -155,7 +179,7 @@ -(CCTMXTilesetInfo*) tilesetForLayer:(CCTMXLayerInfo*)layerInfo map:(CCTMXMapInf // If all the tiles are 0, return empty tileset CCLOG(@"cocos2d: Warning: TMX Layer '%@' has no tiles", layerInfo.name); - return tileset; + return nil; } @@ -185,12 +209,6 @@ -(CCTMXObjectGroup*) objectGroupNamed:(NSString *)groupName return nil; } -// XXX deprecated --(CCTMXObjectGroup*) groupNamed:(NSString *)groupName -{ - return [self objectGroupNamed:groupName]; -} - -(id) propertyNamed:(NSString *)propertyName { return [properties_ valueForKey:propertyName]; diff --git a/libs/cocos2d/CCTMXXMLParser.h b/libs/cocos2d/CCTMXXMLParser.h index 5c25a73..18021c9 100644 --- a/libs/cocos2d/CCTMXXMLParser.h +++ b/libs/cocos2d/CCTMXXMLParser.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -43,6 +44,7 @@ enum { TMXLayerAttribNone = 1 << 0, TMXLayerAttribBase64 = 1 << 1, TMXLayerAttribGzip = 1 << 2, + TMXLayerAttribZlib = 1 << 3, }; enum { @@ -54,6 +56,11 @@ enum { TMXPropertyTile }; +// Bits on the far end of the 32-bit global tile ID (GID's) are used for tile flags +#define kFlippedHorizontallyFlag 0x80000000 +#define kFlippedVerticallyFlag 0x40000000 +#define kFlippedMask ~(kFlippedHorizontallyFlag|kFlippedVerticallyFlag) + /* CCTMXLayerInfo contains the information about the layers like: - Layer name - Layer size @@ -157,6 +164,9 @@ enum { // tmx filename NSString *filename_; + // tmx resource path + NSString *resources_; + // map orientation int orientation_; @@ -188,13 +198,22 @@ enum { @property (nonatomic,readwrite,retain) NSMutableArray *layers; @property (nonatomic,readwrite,retain) NSMutableArray *tilesets; @property (nonatomic,readwrite,retain) NSString *filename; +@property (nonatomic,readwrite,retain) NSString *resources; @property (nonatomic,readwrite,retain) NSMutableArray *objectGroups; @property (nonatomic,readwrite,retain) NSMutableDictionary *properties; @property (nonatomic,readwrite,retain) NSMutableDictionary *tileProperties; /** creates a TMX Format with a tmx file */ +(id) formatWithTMXFile:(NSString*)tmxFile; -/** initializes a TMX format witha tmx file */ + +/** creates a TMX Format with an XML string and a TMX resource path */ ++(id) formatWithXML:(NSString*)tmxString resourcePath:(NSString*)resourcePath; + +/** initializes a TMX format with a tmx file */ -(id) initWithTMXFile:(NSString*)tmxFile; + +/** initializes a TMX format with an XML string and a TMX resource path */ +-(id) initWithXML:(NSString*)tmxString resourcePath:(NSString*)resourcePath; + @end diff --git a/libs/cocos2d/CCTMXXMLParser.m b/libs/cocos2d/CCTMXXMLParser.m index 550f537..cc7d460 100644 --- a/libs/cocos2d/CCTMXXMLParser.m +++ b/libs/cocos2d/CCTMXXMLParser.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -96,6 +97,7 @@ -(CGRect) rectForGID:(unsigned int)gid CGRect rect; rect.size = tileSize_; + gid &= kFlippedMask; gid = gid - firstGid_; int max_x = (imageSize_.width - margin_*2 + spacing_) / (tileSize_.width + spacing_); @@ -114,12 +116,15 @@ -(CGRect) rectForGID:(unsigned int)gid @interface CCTMXMapInfo (Private) /* initalises parsing of an XML file, either a tmx (Map) file or tsx (Tileset) file */ -(void) parseXMLFile:(NSString *)xmlFilename; +/* initalises parsing of an XML string, either a tmx (Map) string or tsx (Tileset) string */ +- (void) parseXMLString:(NSString *)xmlString; +/* handles the work of parsing for parseXMLFile: and parseXMLString: */ +- (NSError*) parseXMLData:(NSData*)data; @end - @implementation CCTMXMapInfo -@synthesize orientation = orientation_, mapSize = mapSize_, layers = layers_, tilesets = tilesets_, tileSize = tileSize_, filename = filename_, objectGroups = objectGroups_, properties = properties_; +@synthesize orientation = orientation_, mapSize = mapSize_, layers = layers_, tilesets = tilesets_, tileSize = tileSize_, filename = filename_, resources = resources_, objectGroups = objectGroups_, properties = properties_; @synthesize tileProperties = tileProperties_; +(id) formatWithTMXFile:(NSString*)tmxFile @@ -127,33 +132,53 @@ +(id) formatWithTMXFile:(NSString*)tmxFile return [[[self alloc] initWithTMXFile:tmxFile] autorelease]; } ++(id) formatWithXML:(NSString*)tmxString resourcePath:(NSString*)resourcePath +{ + return [[[self alloc] initWithXML:tmxString resourcePath:resourcePath] autorelease]; +} + +- (void) internalInit:(NSString*)tmxFileName resourcePath:(NSString*)resourcePath +{ + self.tilesets = [NSMutableArray arrayWithCapacity:4]; + self.layers = [NSMutableArray arrayWithCapacity:4]; + self.filename = tmxFileName; + self.resources = resourcePath; + self.objectGroups = [NSMutableArray arrayWithCapacity:4]; + self.properties = [NSMutableDictionary dictionaryWithCapacity:5]; + self.tileProperties = [NSMutableDictionary dictionaryWithCapacity:5]; + + // tmp vars + currentString = [[NSMutableString alloc] initWithCapacity:1024]; + storingCharacters = NO; + layerAttribs = TMXLayerAttribNone; + parentElement = TMXPropertyNone; +} + +-(id) initWithXML:(NSString *)tmxString resourcePath:(NSString*)resourcePath +{ + if( (self=[super init])) { + [self internalInit:nil resourcePath:resourcePath]; + [self parseXMLString:tmxString]; + } + return self; +} + -(id) initWithTMXFile:(NSString*)tmxFile { if( (self=[super init])) { - - self.tilesets = [NSMutableArray arrayWithCapacity:4]; - self.layers = [NSMutableArray arrayWithCapacity:4]; - self.filename = tmxFile; - self.objectGroups = [NSMutableArray arrayWithCapacity:4]; - self.properties = [NSMutableDictionary dictionaryWithCapacity:5]; - self.tileProperties = [NSMutableDictionary dictionaryWithCapacity:5]; - - // tmp vars - currentString = [[NSMutableString alloc] initWithCapacity:1024]; - storingCharacters = NO; - layerAttribs = TMXLayerAttribNone; - parentElement = TMXPropertyNone; - + [self internalInit:tmxFile resourcePath:nil]; [self parseXMLFile:filename_]; } return self; } + - (void) dealloc { CCLOGINFO(@"cocos2d: deallocing %@", self); [tilesets_ release]; [layers_ release]; [filename_ release]; + [resources_ release]; [currentString release]; [objectGroups_ release]; [properties_ release]; @@ -161,21 +186,32 @@ - (void) dealloc [super dealloc]; } -- (void) parseXMLFile:(NSString *)xmlFilename +- (void) parseXMLData:(NSData*)data { - NSURL *url = [NSURL fileURLWithPath:[CCFileUtils fullPathFromRelativePath:xmlFilename] ]; - NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:url]; - + NSXMLParser *parser = [[[NSXMLParser alloc] initWithData:data] autorelease]; + // we'll do the parsing [parser setDelegate:self]; [parser setShouldProcessNamespaces:NO]; [parser setShouldReportNamespacePrefixes:NO]; [parser setShouldResolveExternalEntities:NO]; [parser parse]; + + NSAssert1( ![parser parserError], @"Error parsing TMX data: %@.", [NSString stringWithCharacters:[data bytes] length:[data length]] ); +} - NSAssert1( ! [parser parserError], @"Error parsing file: %@.", xmlFilename ); +- (void) parseXMLString:(NSString *)xmlString +{ + NSData* data = [xmlString dataUsingEncoding:NSUTF8StringEncoding]; + [self parseXMLData:data]; + +} - [parser release]; +- (void) parseXMLFile:(NSString *)xmlFilename +{ + NSURL *url = [NSURL fileURLWithPath:[CCFileUtils fullPathFromRelativePath:xmlFilename] ]; + NSData *data = [NSData dataWithContentsOfURL:url]; + [self parseXMLData:data]; } // the XML parser calls here with all the elements @@ -209,6 +245,8 @@ -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName name if (externalTilesetFilename) { // Tileset file will be relative to the map file. So we need to convert it to an absolute path NSString *dir = [filename_ stringByDeletingLastPathComponent]; // Directory of map file + if (!dir) + dir = resources_; externalTilesetFilename = [dir stringByAppendingPathComponent:externalTilesetFilename]; // Append path to tileset file [self parseXMLFile:externalTilesetFilename]; @@ -283,7 +321,9 @@ -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName name // build full path NSString *imagename = [attributeDict valueForKey:@"source"]; - NSString *path = [filename_ stringByDeletingLastPathComponent]; + NSString *path = [filename_ stringByDeletingLastPathComponent]; + if (!path) + path = resources_; tileset.sourceImage = [path stringByAppendingPathComponent:imagename]; } else if([elementName isEqualToString:@"data"]) { @@ -296,11 +336,14 @@ -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName name if( [compression isEqualToString:@"gzip"] ) layerAttribs |= TMXLayerAttribGzip; - - NSAssert( !compression || [compression isEqualToString:@"gzip"], @"TMX: unsupported compression method" ); + + else if( [compression isEqualToString:@"zlib"] ) + layerAttribs |= TMXLayerAttribZlib; + + NSAssert( !compression || [compression isEqualToString:@"gzip"] || [compression isEqualToString:@"zlib"], @"TMX: unsupported compression method" ); } - NSAssert( layerAttribs != TMXLayerAttribNone, @"TMX tile map: Only base64 and/or gzip maps are supported" ); + NSAssert( layerAttribs != TMXLayerAttribNone, @"TMX tile map: Only base64 and/or gzip/zlib maps are supported" ); } else if([elementName isEqualToString:@"object"]) { @@ -387,15 +430,22 @@ - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName names CCTMXLayerInfo *layer = [layers_ lastObject]; unsigned char *buffer; - len = base64Decode((unsigned char*)[currentString UTF8String], [currentString length], &buffer); + len = base64Decode((unsigned char*)[currentString UTF8String], (unsigned int) [currentString length], &buffer); if( ! buffer ) { CCLOG(@"cocos2d: TiledMap: decode data error"); return; } - if( layerAttribs & TMXLayerAttribGzip ) { + if( layerAttribs & (TMXLayerAttribGzip | TMXLayerAttribZlib) ) { unsigned char *deflated; - ccInflateMemory(buffer, len, &deflated); + CGSize s = [layer layerSize]; + int sizeHint = s.width * s.height * sizeof(uint32_t); + + int inflatedLen = ccInflateMemoryWithHint(buffer, len, &deflated, sizeHint); + NSAssert( inflatedLen == sizeHint, @"CCTMXXMLParser: Hint failed!"); + + inflatedLen = (int)&inflatedLen; // XXX: to avoid warings in compiler + free( buffer ); if( ! deflated ) { diff --git a/libs/cocos2d/CCTexture2D.h b/libs/cocos2d/CCTexture2D.h index 7f606f5..97461c6 100644 --- a/libs/cocos2d/CCTexture2D.h +++ b/libs/cocos2d/CCTexture2D.h @@ -68,6 +68,8 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. #import // for NSObject +#import "ccTypes.h" + #import "Platforms/CCGL.h" // OpenGL stuff #import "Platforms/CCNS.h" // Next-Step stuff @@ -82,24 +84,25 @@ typedef enum { kCCTexture2DPixelFormat_RGBA8888, //! 16-bit texture without Alpha channel kCCTexture2DPixelFormat_RGB565, + //! 24-bit texture without Alpha channel + kCCTexture2DPixelFormat_RGB888, //! 8-bit textures used as masks kCCTexture2DPixelFormat_A8, + //! 8-bit intensity texture + kCCTexture2DPixelFormat_I8, + //! 16-bit textures used as masks + kCCTexture2DPixelFormat_AI88, //! 16-bit textures: RGBA4444 kCCTexture2DPixelFormat_RGBA4444, //! 16-bit textures: RGB5A1 kCCTexture2DPixelFormat_RGB5A1, + //! 4-bit PVRTC-compressed texture: PVRTC4 + kCCTexture2DPixelFormat_PVRTC4, + //! 2-bit PVRTC-compressed texture: PVRTC2 + kCCTexture2DPixelFormat_PVRTC2, //! Default texture format: RGBA8888 kCCTexture2DPixelFormat_Default = kCCTexture2DPixelFormat_RGBA8888, - - // backward compatibility stuff - kTexture2DPixelFormat_Automatic = kCCTexture2DPixelFormat_Automatic, - kTexture2DPixelFormat_RGBA8888 = kCCTexture2DPixelFormat_RGBA8888, - kTexture2DPixelFormat_RGB565 = kCCTexture2DPixelFormat_RGB565, - kTexture2DPixelFormat_A8 = kCCTexture2DPixelFormat_A8, - kTexture2DPixelFormat_RGBA4444 = kCCTexture2DPixelFormat_RGBA4444, - kTexture2DPixelFormat_RGB5A1 = kCCTexture2DPixelFormat_RGB5A1, - kTexture2DPixelFormat_Default = kCCTexture2DPixelFormat_Default } CCTexture2DPixelFormat; @@ -121,6 +124,11 @@ typedef enum { GLfloat maxS_, maxT_; BOOL hasPremultipliedAlpha_; + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + ccResolutionType resolutionType_; +#endif + } /** Intializes with a texture2d with data */ - (id) initWithData:(const void*)data pixelFormat:(CCTexture2DPixelFormat)pixelFormat pixelsWide:(NSUInteger)width pixelsHigh:(NSUInteger)height contentSize:(CGSize)size; @@ -149,8 +157,22 @@ typedef enum { /** whether or not the texture has their Alpha premultiplied */ @property(nonatomic,readonly) BOOL hasPremultipliedAlpha; +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +/** Returns the resolution type of the texture. + Is it a RetinaDisplay texture, an iPad texture or an standard texture ? + Only valid on iOS. Not valid on OS X. + + Should be a readonly property. It is readwrite as a hack. + + @since v1.1 + */ +@property (nonatomic, readwrite) ccResolutionType resolutionType; +#endif + /** returns the content size of the texture in points */ -(CGSize) contentSize; + + @end /** @@ -171,7 +193,8 @@ Note that RGBA type textures will have their alpha premultiplied - use the blend @interface CCTexture2D (Image) /** Initializes a texture from a UIImage object */ #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED -- (id) initWithImage:(UIImage *)uiImage; +- (id) initWithImage:(UIImage *)uiImage resolutionType:(ccResolutionType)resolution; +- (id) initWithImage:(UIImage *)uiImage DEPRECATED_ATTRIBUTE; #elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) - (id) initWithImage:(CGImageRef)cgImage; #endif @@ -182,6 +205,13 @@ Extensions to make it easy to create a CCTexture2D object from a string of text. Note that the generated textures are of type A8 - use the blending mode (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). */ @interface CCTexture2D (Text) +/** Initializes a texture from a string with dimensions, alignment, line break mode, font name and font size + Supported lineBreakModes: + - iOS: all UILineBreakMode supported modes + - Mac: Only NSLineBreakByWordWrapping is supported. + @since v1.0 + */ +- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode fontName:(NSString*)name fontSize:(CGFloat)size; /** Initializes a texture from a string with dimensions, alignment, font name and font size */ - (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size; /** Initializes a texture from a string with font name and font size */ @@ -197,9 +227,11 @@ Note that the generated textures are of type A8 - use the blending mode (GL_SRC_ /** Initializes a texture from a PVR Texture Compressed (PVRTC) buffer * * IMPORTANT: This method is only defined on iOS. It is not supported on the Mac version. + * + * @deprecated Use initWithPVRFile instead. Will be removed in 2.0 */ #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED --(id) initWithPVRTCData: (const void*)data level:(int)level bpp:(int)bpp hasAlpha:(BOOL)hasAlpha length:(int)length; +-(id) initWithPVRTCData: (const void*)data level:(int)level bpp:(int)bpp hasAlpha:(BOOL)hasAlpha length:(int)length pixelFormat:(CCTexture2DPixelFormat)pixelFormat; #endif // __IPHONE_OS_VERSION_MAX_ALLOWED /** Initializes a texture from a PVR file. @@ -300,6 +332,11 @@ typedef struct _ccTexParams { @since v0.8 */ +(CCTexture2DPixelFormat) defaultAlphaPixelFormat; + +/** returns the bits-per-pixel of the in-memory OpenGL texture + @since v1.0 + */ +-(NSUInteger) bitsPerPixelForFormat; @end diff --git a/libs/cocos2d/CCTexture2D.m b/libs/cocos2d/CCTexture2D.m index 4fe1568..9f16de4 100644 --- a/libs/cocos2d/CCTexture2D.m +++ b/libs/cocos2d/CCTexture2D.m @@ -1,70 +1,73 @@ /* - -===== IMPORTANT ===== - -This is sample code demonstrating API, technology or techniques in development. -Although this sample code has been reviewed for technical accuracy, it is not -final. Apple is supplying this information to help you plan for the adoption of -the technologies and programming interfaces described herein. This information -is subject to change, and software implemented based on this sample code should -be tested with final operating system software and final documentation. Newer -versions of this sample code may be provided with future seeds of the API or -technology. For information about updates to this and other developer -documentation, view the New & Updated sidebars in subsequent documentationd -seeds. - -===================== - -File: Texture2D.m -Abstract: Creates OpenGL 2D textures from images or text. - -Version: 1.6 - -Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. -("Apple") in consideration of your agreement to the following terms, and your -use, installation, modification or redistribution of this Apple software -constitutes acceptance of these terms. If you do not agree with these terms, -please do not use, install, modify or redistribute this Apple software. - -In consideration of your agreement to abide by the following terms, and subject -to these terms, Apple grants you a personal, non-exclusive license, under -Apple's copyrights in this original Apple software (the "Apple Software"), to -use, reproduce, modify and redistribute the Apple Software, with or without -modifications, in source and/or binary forms; provided that if you redistribute -the Apple Software in its entirety and without modifications, you must retain -this notice and the following text and disclaimers in all such redistributions -of the Apple Software. -Neither the name, trademarks, service marks or logos of Apple Inc. may be used -to endorse or promote products derived from the Apple Software without specific -prior written permission from Apple. Except as expressly stated in this notice, -no other rights or licenses, express or implied, are granted by Apple herein, -including but not limited to any patent rights that may be infringed by your -derivative works or by other works in which the Apple Software may be -incorporated. - -The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO -WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED -WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN -COMBINATION WITH YOUR PRODUCTS. - -IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR -DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF -CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Copyright (C) 2008 Apple Inc. All Rights Reserved. - -*/ + + ===== IMPORTANT ===== + + This is sample code demonstrating API, technology or techniques in development. + Although this sample code has been reviewed for technical accuracy, it is not + final. Apple is supplying this information to help you plan for the adoption of + the technologies and programming interfaces described herein. This information + is subject to change, and software implemented based on this sample code should + be tested with final operating system software and final documentation. Newer + versions of this sample code may be provided with future seeds of the API or + technology. For information about updates to this and other developer + documentation, view the New & Updated sidebars in subsequent documentationd + seeds. + + ===================== + + File: Texture2D.m + Abstract: Creates OpenGL 2D textures from images or text. + + Version: 1.6 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under + Apple's copyrights in this original Apple software (the "Apple Software"), to + use, reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions + of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. may be used + to endorse or promote products derived from the Apple Software without specific + prior written permission from Apple. Except as expressly stated in this notice, + no other rights or licenses, express or implied, are granted by Apple herein, + including but not limited to any patent rights that may be infringed by your + derivative works or by other works in which the Apple Software may be + incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR + DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF + CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF + APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2008 Apple Inc. All Rights Reserved. + + */ /* * Support for RGBA_4_4_4_4 and RGBA_5_5_5_1 was copied from: * https://devforums.apple.com/message/37855#37855 by a1studmuffin */ +/* + * Added many additions for cocos2d + */ #import @@ -76,8 +79,10 @@ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #import "ccConfig.h" #import "ccMacros.h" #import "CCConfiguration.h" -#import "Support/ccUtils.h" #import "CCTexturePVR.h" +#import "Support/ccUtils.h" +#import "Support/CCFileUtils.h" + #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && CC_FONT_LABEL_SUPPORT // FontLabel support @@ -86,8 +91,8 @@ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #endif// CC_FONT_LABEL_SUPPORT -// For Labels use 32-bit textures on iPhone 3GS / iPads since A8 textures are very slow -#if defined(__ARM_NEON__) && CC_USE_RGBA32_LABELS_ON_NEON_ARCH +// For Labels use 16-bit textures on iPhone 3GS / iPads since A8 textures are very slow +#if (defined(__ARM_NEON__) || TARGET_IPHONE_SIMULATOR) && CC_USE_LA88_LABELS_ON_NEON_ARCH #define USE_TEXT_WITH_A8_TEXTURES 0 #else @@ -109,12 +114,18 @@ @implementation CCTexture2D @synthesize contentSizeInPixels = size_, pixelFormat = format_, pixelsWide = width_, pixelsHigh = height_, name = name_, maxS = maxS_, maxT = maxT_; @synthesize hasPremultipliedAlpha = hasPremultipliedAlpha_; +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +@synthesize resolutionType = resolutionType_; +#endif + + - (id) initWithData:(const void*)data pixelFormat:(CCTexture2DPixelFormat)pixelFormat pixelsWide:(NSUInteger)width pixelsHigh:(NSUInteger)height contentSize:(CGSize)size { if((self = [super init])) { + glPixelStorei(GL_UNPACK_ALIGNMENT,1); glGenTextures(1, &name_); glBindTexture(GL_TEXTURE_2D, name_); - + [self setAntiAliasTexParameters]; // Specify OpenGL texture image @@ -122,34 +133,41 @@ - (id) initWithData:(const void*)data pixelFormat:(CCTexture2DPixelFormat)pixelF switch(pixelFormat) { case kCCTexture2DPixelFormat_RGBA8888: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei) width, (GLsizei) height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); break; case kCCTexture2DPixelFormat_RGBA4444: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei) width, (GLsizei) height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); break; case kCCTexture2DPixelFormat_RGB5A1: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, data); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei) width, (GLsizei) height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, data); break; case kCCTexture2DPixelFormat_RGB565: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei) width, (GLsizei) height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); + break; + case kCCTexture2DPixelFormat_AI88: + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, (GLsizei) width, (GLsizei) height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data); break; case kCCTexture2DPixelFormat_A8: - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, (GLsizei) width, (GLsizei) height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data); break; default: [NSException raise:NSInternalInconsistencyException format:@""]; } - + size_ = size; width_ = width; height_ = height; format_ = pixelFormat; maxS_ = size.width / (float)width; maxT_ = size.height / (float)height; - + hasPremultipliedAlpha_ = NO; - } + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + resolutionType_ = kCCResolutionUnknown; +#endif + } return self; } @@ -187,6 +205,7 @@ -(CGSize) contentSize return ret; } + @end #pragma mark - @@ -194,7 +213,16 @@ -(CGSize) contentSize @implementation CCTexture2D (Image) #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +// XXX deprecated. To be removed in 2.0 - (id) initWithImage:(UIImage *)uiImage +{ + return [self initWithImage:uiImage resolutionType:kCCResolutionUnknown]; +} +#endif + + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +- (id) initWithImage:(UIImage *)uiImage resolutionType:(ccResolutionType)resolution #elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) - (id) initWithImage:(CGImageRef)CGImage #endif @@ -222,24 +250,24 @@ - (id) initWithImage:(CGImageRef)CGImage } CCConfiguration *conf = [CCConfiguration sharedConfiguration]; - + #if CC_TEXTURE_NPOT_SUPPORT if( [conf supportsNPOT] ) { POTWide = CGImageGetWidth(CGImage); POTHigh = CGImageGetHeight(CGImage); - + } else #endif { POTWide = ccNextPOT(CGImageGetWidth(CGImage)); POTHigh = ccNextPOT(CGImageGetHeight(CGImage)); } - + NSUInteger maxTextureSize = [conf maxTextureSize]; if( POTHigh > maxTextureSize || POTWide > maxTextureSize ) { - CCLOG(@"cocos2d: WARNING: Image (%d x %d) is bigger than the supported %d x %d", - (unsigned int)POTWide, (unsigned int)POTHigh, - (unsigned int)maxTextureSize, (unsigned int)maxTextureSize); + CCLOG(@"cocos2d: WARNING: Image (%lu x %lu) is bigger than the supported %ld x %ld", + (long)POTWide, (long)POTHigh, + (long)maxTextureSize, (long)maxTextureSize); [self release]; return nil; } @@ -249,7 +277,7 @@ - (id) initWithImage:(CGImageRef)CGImage size_t bpp = CGImageGetBitsPerComponent(CGImage); colorSpace = CGImageGetColorSpace(CGImage); - + if(colorSpace) { if(hasAlpha || bpp >= 8) pixelFormat = defaultAlphaPixelFormat_; @@ -264,7 +292,7 @@ - (id) initWithImage:(CGImageRef)CGImage } imageSize = CGSizeMake(CGImageGetWidth(CGImage), CGImageGetHeight(CGImage)); - + // Create the bitmap graphics context switch(pixelFormat) { @@ -274,11 +302,11 @@ - (id) initWithImage:(CGImageRef)CGImage colorSpace = CGColorSpaceCreateDeviceRGB(); data = malloc(POTHigh * POTWide * 4); info = hasAlpha ? kCGImageAlphaPremultipliedLast : kCGImageAlphaNoneSkipLast; -// info = kCGImageAlphaPremultipliedLast; // issue #886. This patch breaks BMP images. + // info = kCGImageAlphaPremultipliedLast; // issue #886. This patch breaks BMP images. context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, 4 * POTWide, colorSpace, info | kCGBitmapByteOrder32Big); CGColorSpaceRelease(colorSpace); break; - + case kCCTexture2DPixelFormat_RGB565: colorSpace = CGColorSpaceCreateDeviceRGB(); data = malloc(POTHigh * POTWide * 4); @@ -354,6 +382,10 @@ - (id) initWithImage:(CGImageRef)CGImage CGContextRelease(context); [self releaseData:data]; +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + resolutionType_ = resolution; +#endif + return self; } @end @@ -365,7 +397,7 @@ @implementation CCTexture2D (Text) #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED -- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment font:(id)uifont +- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode font:(id)uifont { NSAssert( uifont, @"Invalid font"); @@ -375,17 +407,15 @@ - (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment: CGContextRef context; CGColorSpaceRef colorSpace; - + #if USE_TEXT_WITH_A8_TEXTURES - colorSpace = CGColorSpaceCreateDeviceGray(); data = calloc(POTHigh, POTWide); - context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, POTWide, colorSpace, kCGImageAlphaNone); #else - colorSpace = CGColorSpaceCreateDeviceRGB(); - data = calloc(POTHigh, POTWide * 4); - context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, 4 * POTWide, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); + data = calloc(POTHigh, POTWide * 2); #endif - + + colorSpace = CGColorSpaceCreateDeviceGray(); + context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, POTWide, colorSpace, kCGImageAlphaNone); CGColorSpaceRelease(colorSpace); if( ! context ) { @@ -399,77 +429,78 @@ - (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment: CGContextScaleCTM(context, 1.0f, -1.0f); //NOTE: NSString draws in UIKit referential i.e. renders upside-down compared to CGBitmapContext referential UIGraphicsPushContext(context); - + // normal fonts if( [uifont isKindOfClass:[UIFont class] ] ) - [string drawInRect:CGRectMake(0, 0, dimensions.width, dimensions.height) withFont:uifont lineBreakMode:UILineBreakModeWordWrap alignment:alignment]; + [string drawInRect:CGRectMake(0, 0, dimensions.width, dimensions.height) withFont:uifont lineBreakMode:lineBreakMode alignment:alignment]; #if CC_FONT_LABEL_SUPPORT else // ZFont class - [string drawInRect:CGRectMake(0, 0, dimensions.width, dimensions.height) withZFont:uifont lineBreakMode:UILineBreakModeWordWrap alignment:alignment]; + [string drawInRect:CGRectMake(0, 0, dimensions.width, dimensions.height) withZFont:uifont lineBreakMode:lineBreakMode alignment:alignment]; #endif UIGraphicsPopContext(); #if USE_TEXT_WITH_A8_TEXTURES self = [self initWithData:data pixelFormat:kCCTexture2DPixelFormat_A8 pixelsWide:POTWide pixelsHigh:POTHigh contentSize:dimensions]; -#else - self = [self initWithData:data pixelFormat:kCCTexture2DPixelFormat_RGBA8888 pixelsWide:POTWide pixelsHigh:POTHigh contentSize:dimensions]; -#endif + +#else // ! USE_TEXT_WITH_A8_TEXTURES + NSUInteger textureSize = POTWide*POTHigh; + unsigned short *la88_data = (unsigned short*)data; + for(int i = textureSize-1; i>=0; i--) //Convert A8 to AI88 + la88_data[i] = (data[i] << 8) | 0xff; + + self = [self initWithData:data pixelFormat:kCCTexture2DPixelFormat_AI88 pixelsWide:POTWide pixelsHigh:POTHigh contentSize:dimensions]; +#endif // ! USE_TEXT_WITH_A8_TEXTURES + CGContextRelease(context); [self releaseData:data]; - + return self; } - + + + #elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) - (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment attributedString:(NSAttributedString*)stringWithAttributes -{ - NSAssert( stringWithAttributes, @"Invalid stringWithAttributes"); - - NSUInteger POTWide = ccNextPOT(dimensions.width); - NSUInteger POTHigh = ccNextPOT(dimensions.height); - unsigned char* data; +{ + NSAssert(stringWithAttributes, @"Invalid stringWithAttributes"); + + // get nearest power of two + NSSize POTSize = NSMakeSize(ccNextPOT(dimensions.width), ccNextPOT(dimensions.height)); + // get string dimensions NSSize realDimensions = [stringWithAttributes size]; - - //Alignment - float xPadding = 0; // Mac crashes if the width or height is 0 - if( realDimensions.width > 0 && realDimensions.height > 0 ) { - switch (alignment) { - case CCTextAlignmentLeft: xPadding = 0; break; - case CCTextAlignmentCenter: xPadding = (dimensions.width-realDimensions.width)/2.0f; break; - case CCTextAlignmentRight: xPadding = dimensions.width-realDimensions.width; break; - default: break; - } - - //Disable antialias + if (realDimensions.width > 0 && realDimensions.height > 0) + { + // Disable antialias [[NSGraphicsContext currentContext] setShouldAntialias:NO]; - NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(POTWide, POTHigh)]; + NSImage *image = [[NSImage alloc] initWithSize:POTSize]; [image lockFocus]; + + [stringWithAttributes drawInRect:NSMakeRect(0, POTSize.height - dimensions.height, dimensions.width, dimensions.height)]; //POTSize.width, POTSize.height)]; - [stringWithAttributes drawAtPoint:NSMakePoint(xPadding, POTHigh-dimensions.height)]; // draw at offset position - - NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect (0.0f, 0.0f, POTWide, POTHigh)]; + NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0.0f, 0.0f, POTSize.width, POTSize.height)]; [image unlockFocus]; + + unsigned char *data = (unsigned char *) [bitmap bitmapData]; // Use the same buffer to improve the performance. - data = (unsigned char*) [bitmap bitmapData]; //Use the same buffer to improve the performance. - - NSUInteger textureSize = POTWide*POTHigh; - for(int i = 0; iwrapS == GL_CLAMP_TO_EDGE && texParams->wrapT == GL_CLAMP_TO_EDGE), @"GL_CLAMP_TO_EDGE should be used in NPOT textures"); - glBindTexture( GL_TEXTURE_2D, self.name ); + glBindTexture( GL_TEXTURE_2D, name_ ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texParams->minFilter ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texParams->magFilter ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texParams->wrapS ); @@ -750,5 +820,49 @@ +(CCTexture2DPixelFormat) defaultAlphaPixelFormat { return defaultAlphaPixelFormat_; } + +-(NSUInteger) bitsPerPixelForFormat +{ + NSUInteger ret=0; + + switch (format_) { + case kCCTexture2DPixelFormat_RGBA8888: + ret = 32; + break; + case kCCTexture2DPixelFormat_RGB565: + ret = 16; + break; + case kCCTexture2DPixelFormat_RGB888: + ret = 24; + break; + case kCCTexture2DPixelFormat_A8: + ret = 8; + break; + case kCCTexture2DPixelFormat_RGBA4444: + ret = 16; + break; + case kCCTexture2DPixelFormat_RGB5A1: + ret = 16; + break; + case kCCTexture2DPixelFormat_PVRTC4: + ret = 4; + break; + case kCCTexture2DPixelFormat_PVRTC2: + ret = 2; + break; + case kCCTexture2DPixelFormat_I8: + ret = 8; + break; + case kCCTexture2DPixelFormat_AI88: + ret = 16; + break; + default: + ret = -1; + NSAssert1(NO , @"bitsPerPixelForFormat: %ld, unrecognised pixel format", (long)format_); + CCLOG(@"bitsPerPixelForFormat: %ld, cannot give useful result", (long)format_); + break; + } + return ret; +} @end diff --git a/libs/cocos2d/CCTextureAtlas.h b/libs/cocos2d/CCTextureAtlas.h index 51f09ea..6b4e79a 100644 --- a/libs/cocos2d/CCTextureAtlas.h +++ b/libs/cocos2d/CCTextureAtlas.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -48,6 +49,7 @@ CCTexture2D *texture_; #if CC_USES_VBO GLuint buffersVBO_[2]; //0: vertex 1: indices + BOOL dirty_; //indicates whether or not the array buffer of the VBO needs to be updated #endif // CC_USES_VBO } @@ -98,39 +100,84 @@ */ -(void) insertQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger)index; +/** Inserts a c array of quads at a given index + index must be between 0 and the atlas capacity - 1 + this method doesn't enlarge the array when amount + index > totalQuads + @since v1.1 +*/ +-(void) insertQuads:(ccV3F_C4B_T2F_Quad*)quads atIndex:(NSUInteger)index amount:(NSUInteger) amount; + /** Removes the quad that is located at a certain index and inserts it at a new index This operation is faster than removing and inserting in a quad in 2 different steps @since v0.7.2 */ -(void) insertQuadFromIndex:(NSUInteger)fromIndex atIndex:(NSUInteger)newIndex; +/** Inserts a amount of quads from oldIndex at newIndex, while moving quads at newIndex - oldIndex back accordingly + @since v1.1 + */ +-(void) insertQuadsFromIndex:(NSUInteger)oldIndex amount:(NSUInteger) amount atIndex:(NSUInteger)newIndex; + /** removes a quad at a given index number. The capacity remains the same, but the total number of quads to be drawn is reduced in 1 @since v0.7.2 */ -(void) removeQuadAtIndex:(NSUInteger) index; +/** removes a amount of quads starting from index + @since 1.1 + */ +- (void) removeQuadsAtIndex:(NSUInteger) index amount:(NSUInteger) amount; + /** removes all Quads. The TextureAtlas capacity remains untouched. No memory is freed. The total number of quads to be drawn will be 0 @since v0.7.2 */ -(void) removeAllQuads; - -/** resize the capacity of the Texture Atlas. +/** resize the capacity of the CCTextureAtlas. * The new capacity can be lower or higher than the current one * It returns YES if the resize was successful. * If it fails to resize the capacity it will return NO with a new capacity of 0. */ -(BOOL) resizeCapacity: (NSUInteger) n; +/** + Used internally by CCParticleBatchNode + don't use this unless you know what you're doing + @since 1.1 +*/ +- (void) increaseTotalQuadsWith:(NSUInteger) amount; + +/** + Moves quads from index till totalQuads to the newIndex + Used internally by CCParticleBatchNode + This method doesn't enlarge the array if newIndex + quads to be moved > capacity + @since 1.1 +*/ +- (void) moveQuadsFromIndex:(NSUInteger) index to:(NSUInteger) newIndex; + +/** + Ensures that after a realloc quads are still empty + Used internally by CCParticleBatchNode + @since 1.1 +*/ +- (void) fillWithEmptyQuadsFromIndex:(NSUInteger) index amount:(NSUInteger) amount; /** draws n quads * n can't be greater than the capacity of the Atlas */ + -(void) drawNumberOfQuads: (NSUInteger) n; +/** draws n quads from an index (offset). + n + start can't be greater than the capacity of the atlas + + @since v1.0 + */ +-(void) drawNumberOfQuads: (NSUInteger) n fromIndex: (NSUInteger) start; + /** draws all the Atlas's Quads */ -(void) drawQuads; diff --git a/libs/cocos2d/CCTextureAtlas.m b/libs/cocos2d/CCTextureAtlas.m index da70593..d72e2bd 100644 --- a/libs/cocos2d/CCTextureAtlas.m +++ b/libs/cocos2d/CCTextureAtlas.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,6 +30,8 @@ #import "ccMacros.h" #import "CCTexture2D.h" #import "CCTextureCache.h" +#import "CGPointExtension.h" +#import "CCDrawingPrimitives.h" @interface CCTextureAtlas (Private) @@ -61,7 +64,7 @@ -(id) initWithFile:(NSString*)file capacity:(NSUInteger)n CCTexture2D *tex = [[CCTextureCache sharedTextureCache] addImage:file]; if( tex ) return [self initWithTexture:tex capacity:n]; - + // else { CCLOG(@"cocos2d: Could not open file: %@", file); @@ -73,16 +76,19 @@ -(id) initWithFile:(NSString*)file capacity:(NSUInteger)n -(id) initWithTexture:(CCTexture2D*)tex capacity:(NSUInteger)n { if( (self=[super init]) ) { - + capacity_ = n; totalQuads_ = 0; // retained in property self.texture = tex; + // Re-initialization is not allowed + NSAssert(quads_==nil && indices_==nil, @"CCTextureAtlas re-initialization is not allowed"); + quads_ = calloc( sizeof(quads_[0]) * capacity_, 1 ); indices_ = calloc( sizeof(indices_[0]) * capacity_ * 6, 1 ); - + if( ! ( quads_ && indices_) ) { CCLOG(@"cocos2d: CCTextureAtlas: not enough memory"); if( quads_ ) @@ -91,19 +97,20 @@ -(id) initWithTexture:(CCTexture2D*)tex capacity:(NSUInteger)n free(indices_); return nil; } - + #if CC_USES_VBO // initial binding - glGenBuffers(2, &buffersVBO_[0]); + glGenBuffers(2, &buffersVBO_[0]); + dirty_ = YES; #endif // CC_USES_VBO [self initIndices]; } - + return self; } -- (NSString*) description +-(NSString*) description { return [NSString stringWithFormat:@"<%@ = %08X | totalQuads = %i>", [self class], self, totalQuads_]; } @@ -114,12 +121,12 @@ -(void) dealloc free(quads_); free(indices_); - + #if CC_USES_VBO glDeleteBuffers(2, buffersVBO_); #endif // CC_USES_VBO - - + + [texture_ release]; [super dealloc]; @@ -139,7 +146,7 @@ -(void) initIndices indices_[i*6+0] = i*4+0; indices_[i*6+1] = i*4+1; indices_[i*6+2] = i*4+2; - + // inverted index. issue #179 indices_[i*6+3] = i*4+3; indices_[i*6+4] = i*4+2; @@ -149,7 +156,7 @@ -(void) initIndices // indices_[i*6+5] = i*4+1; #endif } - + #if CC_USES_VBO glBindBuffer(GL_ARRAY_BUFFER, buffersVBO_[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(quads_[0]) * capacity_, quads_, GL_DYNAMIC_DRAW); @@ -162,15 +169,27 @@ -(void) initIndices #pragma mark TextureAtlas - Update, Insert, Move & Remove +-(ccV3F_C4B_T2F_Quad *) quads +{ + //if someone accesses the quads directly, presume that changes will be made +#if CC_USES_VBO + dirty_ = YES; +#endif + return quads_; +} + -(void) updateQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger) n { NSAssert(n < capacity_, @"updateQuadWithTexture: Invalid index"); - + totalQuads_ = MAX( n+1, totalQuads_); - + quads_[n] = *quad; -} +#if CC_USES_VBO + dirty_ = YES; +#endif +} -(void) insertQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger)index { @@ -188,8 +207,43 @@ -(void) insertQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger)index memmove( &quads_[index+1],&quads_[index], sizeof(quads_[0]) * remaining ); quads_[index] = *quad; + +#if CC_USES_VBO + dirty_ = YES; +#endif } +-(void) insertQuads:(ccV3F_C4B_T2F_Quad*)quads atIndex:(NSUInteger)index amount:(NSUInteger) amount +{ + NSAssert(index + amount <= capacity_, @"insertQuadWithTexture: Invalid index + amount"); + + totalQuads_+= amount; + + NSAssert( totalQuads_ <= capacity_, @"invalid totalQuads"); + + // issue #575. index can be > totalQuads + NSInteger remaining = (totalQuads_-1) - index - amount; + + // last object doesn't need to be moved + if( remaining > 0) + // tex coordinates + memmove( &quads_[index+amount],&quads_[index], sizeof(quads_[0]) * remaining ); + + + + NSUInteger max = index + amount; + NSInteger j = 0; + for (NSInteger i = index; i < max ; i++) + { + quads_[index] = quads[j]; + index++; + j++; + } + +#if CC_USES_VBO + dirty_ = YES; +#endif +} -(void) insertQuadFromIndex:(NSUInteger)oldIndex atIndex:(NSUInteger)newIndex { @@ -199,7 +253,7 @@ -(void) insertQuadFromIndex:(NSUInteger)oldIndex atIndex:(NSUInteger)newIndex if( oldIndex == newIndex ) return; - NSUInteger howMany = abs( oldIndex - newIndex); + NSUInteger howMany = labs( oldIndex - newIndex); NSUInteger dst = oldIndex; NSUInteger src = oldIndex + 1; if( oldIndex > newIndex) { @@ -211,21 +265,79 @@ -(void) insertQuadFromIndex:(NSUInteger)oldIndex atIndex:(NSUInteger)newIndex ccV3F_C4B_T2F_Quad quadsBackup = quads_[oldIndex]; memmove( &quads_[dst],&quads_[src], sizeof(quads_[0]) * howMany ); quads_[newIndex] = quadsBackup; + +#if CC_USES_VBO + dirty_ = YES; +#endif } --(void) removeQuadAtIndex:(NSUInteger) index +-(void) insertQuadsFromIndex:(NSUInteger)oldIndex amount:(NSUInteger) amount atIndex:(NSUInteger)newIndex { - NSAssert(index < totalQuads_, @"removeQuadAtIndex: Invalid index"); + NSAssert(newIndex + amount <= totalQuads_, @"insertQuadFromIndex:atIndex: Invalid index"); + NSAssert(oldIndex < totalQuads_, @"insertQuadFromIndex:atIndex: Invalid index"); - NSUInteger remaining = (totalQuads_-1) - index; + if( oldIndex == newIndex ) + return; + + //create buffer + size_t quadSize = sizeof(ccV3F_C4B_T2F_Quad); + ccV3F_C4B_T2F_Quad *tempQuads = malloc(quadSize*amount); + memcpy(tempQuads,&quads_[oldIndex],quadSize*amount); + if (newIndex < oldIndex) + { + //move quads from newIndex to newIndex + amount to make room for buffer + memmove(&quads_[newIndex],&quads_[newIndex+amount],(oldIndex-newIndex)*quadSize); + } + else + {//move quads above back + memmove(&quads_[oldIndex],&quads_[oldIndex+amount],(newIndex-oldIndex)*quadSize); + } + memcpy(&quads_[newIndex],tempQuads,amount*quadSize); + free(tempQuads); + +#if CC_USES_VBO + dirty_ = YES; +#endif +} + +-(void) removeQuadAtIndex:(NSUInteger) index +{ + NSAssert(index < totalQuads_, @"removeQuadAtIndex: Invalid index"); + + NSUInteger remaining = (totalQuads_-1) - index; + + // last object doesn't need to be moved if( remaining ) - // tex coordinates memmove( &quads_[index],&quads_[index+1], sizeof(quads_[0]) * remaining ); - + totalQuads_--; + +#if CC_USES_VBO + dirty_ = YES; +#endif +} + +-(void) removeQuadsAtIndex:(NSUInteger) index amount:(NSUInteger) amount +{ + NSAssert(index + amount <= totalQuads_, @"removeQuadAtIndex: index + amount out of bounds"); + + if (index + amount > totalQuads_) + amount = totalQuads_ - index; + + NSUInteger remaining = (totalQuads_) - (index + amount); + + totalQuads_-= amount; + + // last object doesn't need to be moved + if ( remaining ) + memmove( &quads_[index],&quads_[index+amount], sizeof(quads_[0]) * remaining ); + +#if CC_USES_VBO + dirty_ = YES; +#endif } -(void) removeAllQuads @@ -246,98 +358,129 @@ -(BOOL) resizeCapacity: (NSUInteger) newCapacity void * tmpQuads = realloc( quads_, sizeof(quads_[0]) * capacity_ ); void * tmpIndices = realloc( indices_, sizeof(indices_[0]) * capacity_ * 6 ); - + if( ! ( tmpQuads && tmpIndices) ) { CCLOG(@"cocos2d: CCTextureAtlas: not enough memory"); if( tmpQuads ) free(tmpQuads); else free(quads_); - + if( tmpIndices ) free(tmpIndices); else free(indices_); - + indices_ = nil; quads_ = nil; capacity_ = totalQuads_ = 0; return NO; } - + quads_ = tmpQuads; indices_ = tmpIndices; [self initIndices]; +#if CC_USES_VBO + dirty_ = YES; +#endif return YES; } +#pragma mark TextureAtlas - CCParticleBatchNode Specific + +-(void) fillWithEmptyQuadsFromIndex:(NSUInteger) index amount:(NSUInteger) amount +{ + ccV3F_C4B_T2F_Quad quad; + bzero( &quad, sizeof(quad) ); + + NSUInteger to = index + amount; + for (NSInteger i = index ; i < to ; i++) + { + quads_[i] = quad; + } + +} +-(void) increaseTotalQuadsWith:(NSUInteger) amount +{ + totalQuads_ += amount; +} + +-(void) moveQuadsFromIndex:(NSUInteger) index to:(NSUInteger) newIndex +{ + NSAssert(newIndex + (totalQuads_ - index) <= capacity_, @"moveQuadsFromIndex move is out of bounds"); + + memmove(quads_ + newIndex,quads_ + index, (totalQuads_ - index) * sizeof(quads_[0])); +} + #pragma mark TextureAtlas - Drawing -(void) drawQuads { - return [self drawNumberOfQuads: totalQuads_]; + [self drawNumberOfQuads: totalQuads_ fromIndex:0]; } -(void) drawNumberOfQuads: (NSUInteger) n { + [self drawNumberOfQuads:n fromIndex:0]; +} + +-(void) drawNumberOfQuads: (NSUInteger) n fromIndex: (NSUInteger) start +{ // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY // Unneeded states: - - + glBindTexture(GL_TEXTURE_2D, [texture_ name]); #define kQuadSize sizeof(quads_[0].bl) - - #if CC_USES_VBO glBindBuffer(GL_ARRAY_BUFFER, buffersVBO_[0]); - + // XXX: update is done in draw... perhaps it should be done in a timer - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(quads_[0]) * n, quads_); - + if (dirty_) { + glBufferSubData(GL_ARRAY_BUFFER, sizeof(quads_[0])*start, sizeof(quads_[0]) * n , &quads_[start] ); + dirty_ = NO; + } + // vertices glVertexPointer(3, GL_FLOAT, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, vertices)); - + // colors glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, colors)); - + // tex coords glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, texCoords)); - + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffersVBO_[1]); #if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP - glDrawElements(GL_TRIANGLE_STRIP, n*6, GL_UNSIGNED_SHORT, (GLvoid*)0); + glDrawElements(GL_TRIANGLE_STRIP, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(indices_[0])) ); #else - glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, (GLvoid*)0); + glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(indices_[0])) ); #endif // CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP - + glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - #else // ! CC_USES_VBO - - NSUInteger offset = (NSUInteger)quads_; + NSUInteger offset = (NSUInteger)quads_; // vertex NSUInteger diff = offsetof( ccV3F_C4B_T2F, vertices); glVertexPointer(3, GL_FLOAT, kQuadSize, (GLvoid*) (offset + diff) ); - // color diff = offsetof( ccV3F_C4B_T2F, colors); glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*)(offset + diff)); - + // tex coords diff = offsetof( ccV3F_C4B_T2F, texCoords); glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*)(offset + diff)); - + #if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP - glDrawElements(GL_TRIANGLE_STRIP, n*6, GL_UNSIGNED_SHORT, indices_); + glDrawElements(GL_TRIANGLE_STRIP, n*6, GL_UNSIGNED_SHORT, indices_ + start * 6 ); #else - glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, indices_); + glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, indices_ + start * 6 ); #endif - + #endif // CC_USES_VBO } - @end diff --git a/libs/cocos2d/CCTextureCache.h b/libs/cocos2d/CCTextureCache.h index dbf138e..0d40489 100644 --- a/libs/cocos2d/CCTextureCache.h +++ b/libs/cocos2d/CCTextureCache.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -122,6 +123,8 @@ * hasAlpha: whether or not the image contains alpha channel * * IMPORTANT: This method is only defined on iOS. It is not supported on the Mac version. + * + * @deprecated Will be removed in 2.0. Use addPVRImage instead. */ #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED -(CCTexture2D*) addPVRTCImage:(NSString*)fileimage bpp:(int)bpp hasAlpha:(BOOL)alpha width:(int)w; @@ -137,3 +140,12 @@ @end +@interface CCTextureCache (Debug) +/** Output to CCLOG the current contents of this CCTextureCache + * This will attempt to calculate the size of each texture, and the total texture memory in use + * + * @since v1.0 + */ +-(void) dumpCachedTextureInfo; + +@end diff --git a/libs/cocos2d/CCTextureCache.m b/libs/cocos2d/CCTextureCache.m index 6510497..c752027 100644 --- a/libs/cocos2d/CCTextureCache.m +++ b/libs/cocos2d/CCTextureCache.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,6 +35,7 @@ #import "Support/CCFileUtils.h" #import "CCDirector.h" #import "ccConfig.h" +#import "ccTypes.h" // needed for CCCallFuncO in Mac-display_link version #import "CCActionManager.h" @@ -52,9 +54,9 @@ @interface CCAsyncObject : NSObject id target_; id data_; } -@property (readwrite,assign) SEL selector; -@property (readwrite,retain) id target; -@property (readwrite,retain) id data; +@property (nonatomic,readwrite,assign) SEL selector; +@property (nonatomic,readwrite,retain) id target; +@property (nonatomic,readwrite,retain) id data; @end @implementation CCAsyncObject @@ -120,7 +122,7 @@ - (NSString*) description -(void) dealloc { - CCLOG(@"cocos2d: deallocing %@", self); + CCLOGINFO(@"cocos2d: deallocing %@", self); [textures_ release]; [dictLock_ release]; @@ -217,7 +219,9 @@ -(void) addImageAsync: (NSString*)path target:(id)target selector:(SEL)selector CCTexture2D * tex; - path = ccRemoveHDSuffixFromFile(path); +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + path = [CCFileUtils removeSuffixFromFile:path]; +#endif if( (tex=[textures_ objectForKey: path] ) ) { [target performSelector:selector withObject:tex]; @@ -246,7 +250,9 @@ -(CCTexture2D*) addImage: (NSString*) path [dictLock_ lock]; // remove possible -HD suffix to prevent caching the same image twice (issue #1040) - path = ccRemoveHDSuffixFromFile( path ); +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + path = [CCFileUtils removeSuffixFromFile: path]; +#endif tex=[textures_ objectForKey: path]; @@ -267,11 +273,12 @@ -(CCTexture2D*) addImage: (NSString*) path ) { // convert jpg to png before loading the texture - NSString *fullpath = [CCFileUtils fullPathFromRelativePath: path ]; + ccResolutionType resolution; + NSString *fullpath = [CCFileUtils fullPathFromRelativePath: path resolutionType:&resolution]; UIImage *jpg = [[UIImage alloc] initWithContentsOfFile:fullpath]; UIImage *png = [[UIImage alloc] initWithData:UIImagePNGRepresentation(jpg)]; - tex = [ [CCTexture2D alloc] initWithImage: png ]; + tex = [ [CCTexture2D alloc] initWithImage:png resolutionType:resolution]; [png release]; [jpg release]; @@ -280,16 +287,17 @@ -(CCTexture2D*) addImage: (NSString*) path else CCLOG(@"cocos2d: Couldn't add image:%@ in CCTextureCache", path); - [tex release]; + // autorelease prevents possible crash in multithreaded environments + [tex autorelease]; } else { - // prevents overloading the autorelease pool - NSString *fullpath = [CCFileUtils fullPathFromRelativePath: path ]; + ccResolutionType resolution; + NSString *fullpath = [CCFileUtils fullPathFromRelativePath:path resolutionType:&resolution]; UIImage *image = [ [UIImage alloc] initWithContentsOfFile: fullpath ]; - tex = [ [CCTexture2D alloc] initWithImage: image ]; + tex = [ [CCTexture2D alloc] initWithImage:image resolutionType:resolution]; [image release]; if( tex ) @@ -297,7 +305,8 @@ -(CCTexture2D*) addImage: (NSString*) path else CCLOG(@"cocos2d: Couldn't add image:%@ in CCTextureCache", path); - [tex release]; + // autorelease prevents possible crash in multithreaded environments + [tex autorelease]; } // Only in Mac @@ -317,7 +326,8 @@ -(CCTexture2D*) addImage: (NSString*) path else CCLOG(@"cocos2d: Couldn't add image:%@ in CCTextureCache", path); - [tex release]; + // autorelease prevents possible crash in multithreaded environments + [tex autorelease]; } #endif // __MAC_OS_X_VERSION_MAX_ALLOWED @@ -343,7 +353,7 @@ -(CCTexture2D*) addCGImage: (CGImageRef) imageref forKey: (NSString *)key #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED // prevents overloading the autorelease pool UIImage *image = [[UIImage alloc] initWithCGImage:imageref]; - tex = [[CCTexture2D alloc] initWithImage: image]; + tex = [[CCTexture2D alloc] initWithImage:image resolutionType:kCCResolutionUnknown]; [image release]; #elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) @@ -408,6 +418,7 @@ - (CCTexture2D *)textureForKey:(NSString *)key @implementation CCTextureCache (PVRSupport) #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +// XXX deprecated -(CCTexture2D*) addPVRTCImage:(NSString*)path bpp:(int)bpp hasAlpha:(BOOL)alpha width:(int)w { NSAssert(path != nil, @"TextureCache: fileimage MUST not be nill"); @@ -416,7 +427,7 @@ -(CCTexture2D*) addPVRTCImage:(NSString*)path bpp:(int)bpp hasAlpha:(BOOL)alpha CCTexture2D * tex; // remove possible -HD suffix to prevent caching the same image twice (issue #1040) - path = ccRemoveHDSuffixFromFile( path ); + path = [CCFileUtils removeSuffixFromFile: path]; if( (tex=[textures_ objectForKey: path] ) ) { return tex; @@ -426,7 +437,7 @@ -(CCTexture2D*) addPVRTCImage:(NSString*)path bpp:(int)bpp hasAlpha:(BOOL)alpha NSString *fullpath = [CCFileUtils fullPathFromRelativePath:path]; NSData *nsdata = [[NSData alloc] initWithContentsOfFile:fullpath]; - tex = [[CCTexture2D alloc] initWithPVRTCData:[nsdata bytes] level:0 bpp:bpp hasAlpha:alpha length:w]; + tex = [[CCTexture2D alloc] initWithPVRTCData:[nsdata bytes] level:0 bpp:bpp hasAlpha:alpha length:w pixelFormat:bpp==2?kCCTexture2DPixelFormat_PVRTC2:kCCTexture2DPixelFormat_PVRTC4]; if( tex ) [textures_ setObject: tex forKey:path]; else @@ -445,16 +456,15 @@ -(CCTexture2D*) addPVRImage:(NSString*)path CCTexture2D * tex; // remove possible -HD suffix to prevent caching the same image twice (issue #1040) - path = ccRemoveHDSuffixFromFile( path ); +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + path = [CCFileUtils removeSuffixFromFile: path]; +#endif if( (tex=[textures_ objectForKey: path] ) ) { return tex; } - // Split up directory and filename - NSString *fullpath = [CCFileUtils fullPathFromRelativePath:path]; - - tex = [[CCTexture2D alloc] initWithPVRFile: fullpath]; + tex = [[CCTexture2D alloc] initWithPVRFile: path]; if( tex ) [textures_ setObject: tex forKey:path]; else @@ -464,3 +474,31 @@ -(CCTexture2D*) addPVRImage:(NSString*)path } @end + + +@implementation CCTextureCache (Debug) + +-(void) dumpCachedTextureInfo +{ + NSUInteger count = 0; + NSUInteger totalBytes = 0; + for (NSString* texKey in textures_) { + CCTexture2D* tex = [textures_ objectForKey:texKey]; + NSUInteger bpp = [tex bitsPerPixelForFormat]; + // Each texture takes up width * height * bytesPerPixel bytes. + NSUInteger bytes = tex.pixelsWide * tex.pixelsHigh * bpp / 8; + totalBytes += bytes; + count++; + CCLOG( @"cocos2d: \"%@\" rc=%lu id=%lu %lu x %lu @ %ld bpp => %lu KB", + texKey, + (long)[tex retainCount], + (long)tex.name, + (long)tex.pixelsWide, + (long)tex.pixelsHigh, + (long)bpp, + (long)bytes / 1024 ); + } + CCLOG( @"cocos2d: CCTextureCache dumpDebugInfo: %ld textures, for %lu KB (%.2f MB)", (long)count, (long)totalBytes / 1024, totalBytes / (1024.0f*1024.0f)); +} + +@end diff --git a/libs/cocos2d/CCTexturePVR.h b/libs/cocos2d/CCTexturePVR.h index c8a8e75..66f8286 100644 --- a/libs/cocos2d/CCTexturePVR.h +++ b/libs/cocos2d/CCTexturePVR.h @@ -48,9 +48,8 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. #import #import "Platforms/CCGL.h" -#import "CCTextureCache.h" #import "CCTexture2D.h" -#import "ccCArray.h" + #pragma mark - #pragma mark CCTexturePVR @@ -98,20 +97,30 @@ enum { // cocos2d integration BOOL retainName_; + CCTexture2DPixelFormat format_; } +/** initializes a CCTexturePVR with a path */ - (id)initWithContentsOfFile:(NSString *)path; +/** initializes a CCTexturePVR with an URL */ - (id)initWithContentsOfURL:(NSURL *)url; +/** creates and initializes a CCTexturePVR with a path */ + (id)pvrTextureWithContentsOfFile:(NSString *)path; +/** creates and initializes a CCTexturePVR with an URL */ + (id)pvrTextureWithContentsOfURL:(NSURL *)url; +/** texture id name */ @property (nonatomic,readonly) GLuint name; +/** texture width */ @property (nonatomic,readonly) uint32_t width; +/** texture height */ @property (nonatomic,readonly) uint32_t height; +/** whether or not the texture has alpha */ @property (nonatomic,readonly) BOOL hasAlpha; // cocos2d integration @property (nonatomic,readwrite) BOOL retainName; +@property (nonatomic,readonly) CCTexture2DPixelFormat format; @end diff --git a/libs/cocos2d/CCTexturePVR.m b/libs/cocos2d/CCTexturePVR.m index 9f0e73f..0878f54 100644 --- a/libs/cocos2d/CCTexturePVR.m +++ b/libs/cocos2d/CCTexturePVR.m @@ -67,32 +67,46 @@ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #import "Support/ccUtils.h" #import "Support/CCFileUtils.h" #import "Support/ZipUtils.h" +#import "Support/OpenGL_Internal.h" #pragma mark - #pragma mark CCTexturePVR #define PVR_TEXTURE_FLAG_TYPE_MASK 0xff -#define PVR_TEXTURE_FLAG_FLIPPED_MASK 0x10000 + +// Values taken from PVRTexture.h from http://www.imgtec.com +enum { + kPVRTextureFlagMipmap = (1<<8), // has mip map levels + kPVRTextureFlagTwiddle = (1<<9), // is twiddled + kPVRTextureFlagBumpmap = (1<<10), // has normals encoded for a bump map + kPVRTextureFlagTiling = (1<<11), // is bordered for tiled pvr + kPVRTextureFlagCubemap = (1<<12), // is a cubemap/skybox + kPVRTextureFlagFalseMipCol = (1<<13), // are there false coloured MIP levels + kPVRTextureFlagVolume = (1<<14), // is this a volume texture + kPVRTextureFlagAlpha = (1<<15), // v2.1 is there transparency info in the texture + kPVRTextureFlagVerticalFlip = (1<<16), // v2.1 is the texture vertically flipped +}; + static char gPVRTexIdentifier[4] = "PVR!"; enum { - kPVRTextureFlagTypeRGBA_4444= 0x10, - kPVRTextureFlagTypeRGBA_5551, - kPVRTextureFlagTypeRGBA_8888, - kPVRTextureFlagTypeRGB_565, - kPVRTextureFlagTypeRGB_555, // unsupported - kPVRTextureFlagTypeRGB_888, // unsupported - kPVRTextureFlagTypeI_8, - kPVRTextureFlagTypeAI_88, - kPVRTextureFlagTypePVRTC_2, - kPVRTextureFlagTypePVRTC_4, - kPVRTextureFlagTypeBGRA_8888, - kPVRTextureFlagTypeA_8, + kPVRTexturePixelTypeRGBA_4444= 0x10, + kPVRTexturePixelTypeRGBA_5551, + kPVRTexturePixelTypeRGBA_8888, + kPVRTexturePixelTypeRGB_565, + kPVRTexturePixelTypeRGB_555, // unsupported + kPVRTexturePixelTypeRGB_888, + kPVRTexturePixelTypeI_8, + kPVRTexturePixelTypeAI_88, + kPVRTexturePixelTypePVRTC_2, + kPVRTexturePixelTypePVRTC_4, + kPVRTexturePixelTypeBGRA_8888, + kPVRTexturePixelTypeA_8, }; -static const uint32_t tableFormats[][6] = { +static const uint32_t tableFormats[][7] = { // - PVR texture format // - OpenGL internal format @@ -100,18 +114,20 @@ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE // - OpenGL type // - bpp // - compressed - { kPVRTextureFlagTypeRGBA_4444, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 16, NO }, - { kPVRTextureFlagTypeRGBA_5551, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 16, NO }, - { kPVRTextureFlagTypeRGBA_8888, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 32, NO }, - { kPVRTextureFlagTypeRGB_565, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 16, NO }, - { kPVRTextureFlagTypeI_8, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 8, NO }, - { kPVRTextureFlagTypeAI_88, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 16, NO }, + // - Cocos2d texture format constant + { kPVRTexturePixelTypeRGBA_4444, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 16, NO, kCCTexture2DPixelFormat_RGBA4444 }, + { kPVRTexturePixelTypeRGBA_5551, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 16, NO, kCCTexture2DPixelFormat_RGB5A1 }, + { kPVRTexturePixelTypeRGBA_8888, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 32, NO, kCCTexture2DPixelFormat_RGBA8888 }, + { kPVRTexturePixelTypeRGB_565, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 16, NO, kCCTexture2DPixelFormat_RGB565 }, + { kPVRTexturePixelTypeRGB_888, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, 24, NO, kCCTexture2DPixelFormat_RGB888 }, + { kPVRTexturePixelTypeA_8, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, 8, NO, kCCTexture2DPixelFormat_A8 }, + { kPVRTexturePixelTypeI_8, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 8, NO, kCCTexture2DPixelFormat_I8 }, + { kPVRTexturePixelTypeAI_88, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 16, NO, kCCTexture2DPixelFormat_AI88 }, #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED - { kPVRTextureFlagTypePVRTC_2, GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, -1, -1, 2, YES }, - { kPVRTextureFlagTypePVRTC_4, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, -1, -1, 4, YES }, + { kPVRTexturePixelTypePVRTC_2, GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, -1, -1, 2, YES, kCCTexture2DPixelFormat_PVRTC2 }, + { kPVRTexturePixelTypePVRTC_4, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, -1, -1, 4, YES, kCCTexture2DPixelFormat_PVRTC4 }, #endif // iphone only - { kPVRTextureFlagTypeBGRA_8888, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE, 32, NO }, - { kPVRTextureFlagTypeA_8, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, 8, NO }, + { kPVRTexturePixelTypeBGRA_8888, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE, 32, NO, kCCTexture2DPixelFormat_RGBA8888 }, }; #define MAX_TABLE_ELEMENTS (sizeof(tableFormats) / sizeof(tableFormats[0])) @@ -122,6 +138,7 @@ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE kCCInternalOpenGLType, kCCInternalBPP, kCCInternalCompressedImage, + kCCInternalCCTexture2DPixelFormat, }; typedef struct _PVRTexHeader @@ -151,9 +168,10 @@ @implementation CCTexturePVR // cocos2d integration @synthesize retainName = retainName_; +@synthesize format = format_; -- (BOOL)unpackPVRData:(unsigned char*)data PVRLen:(unsigned int)len +- (BOOL)unpackPVRData:(unsigned char*)data PVRLen:(NSUInteger)len { BOOL success = FALSE; PVRTexHeader *header = NULL; @@ -176,14 +194,17 @@ - (BOOL)unpackPVRData:(unsigned char*)data PVRLen:(unsigned int)len return FALSE; } + CCConfiguration *configuration = [CCConfiguration sharedConfiguration]; + flags = CFSwapInt32LittleToHost(header->flags); formatFlags = flags & PVR_TEXTURE_FLAG_TYPE_MASK; - BOOL flipped = flags & PVR_TEXTURE_FLAG_FLIPPED_MASK; + BOOL flipped = flags & kPVRTextureFlagVerticalFlip; if( flipped ) CCLOG(@"cocos2d: WARNING: Image is flipped. Regenerate it using PVRTexTool"); - - if( header->width != ccNextPOT(header->width) || header->height != ccNextPOT(header->height) ) { - CCLOG(@"cocos2d: WARNING: PVR NPOT textures are not supported. Regenerate it."); + + if( ! [configuration supportsNPOT] && + ( header->width != ccNextPOT(header->width) || header->height != ccNextPOT(header->height ) ) ) { + CCLOG(@"cocos2d: ERROR: Loding an NPOT texture (%dx%d) but is not supported on this device", header->width, header->height); return FALSE; } @@ -202,24 +223,24 @@ - (BOOL)unpackPVRData:(unsigned char*)data PVRLen:(unsigned int)len dataLength = CFSwapInt32LittleToHost(header->dataLength); bytes = ((uint8_t *)data) + sizeof(PVRTexHeader); + format_ = tableFormats[tableFormatIndex_][kCCInternalCCTexture2DPixelFormat]; + bpp = tableFormats[tableFormatIndex_][kCCInternalBPP]; // Calculate the data size for each texture level and respect the minimum number of blocks while (dataOffset < dataLength) { switch (formatFlags) { - case kPVRTextureFlagTypePVRTC_2: + case kPVRTexturePixelTypePVRTC_2: blockSize = 8 * 4; // Pixel by pixel block size for 2bpp widthBlocks = width / 8; heightBlocks = height / 4; - bpp = 2; break; - case kPVRTextureFlagTypePVRTC_4: + case kPVRTexturePixelTypePVRTC_4: blockSize = 4 * 4; // Pixel by pixel block size for 4bpp widthBlocks = width / 4; heightBlocks = height / 4; - bpp = 4; break; - case kPVRTextureFlagTypeBGRA_8888: + case kPVRTexturePixelTypeBGRA_8888: if( ! [[CCConfiguration sharedConfiguration] supportsBGRA8888] ) { CCLOG(@"cocos2d: TexturePVR. BGRA8888 not supported on this device"); return FALSE; @@ -228,7 +249,6 @@ - (BOOL)unpackPVRData:(unsigned char*)data PVRLen:(unsigned int)len blockSize = 1; widthBlocks = width; heightBlocks = height; - bpp = tableFormats[ tableFormatIndex_][ kCCInternalBPP]; break; } @@ -239,16 +259,16 @@ - (BOOL)unpackPVRData:(unsigned char*)data PVRLen:(unsigned int)len heightBlocks = 2; dataSize = widthBlocks * heightBlocks * ((blockSize * bpp) / 8); - float packetLenght = (dataLength-dataOffset); - packetLenght = packetLenght > dataSize ? dataSize : packetLenght; + float packetLength = (dataLength-dataOffset); + packetLength = packetLength > dataSize ? dataSize : packetLength; mipmaps_[numberOfMipmaps_].address = bytes+dataOffset; - mipmaps_[numberOfMipmaps_].len = packetLenght; + mipmaps_[numberOfMipmaps_].len = packetLength; numberOfMipmaps_++; NSAssert( numberOfMipmaps_ < CC_PVRMIPMAP_MAX, @"TexturePVR: Maximum number of mimpaps reached. Increate the CC_PVRMIPMAP_MAX value"); - dataOffset += packetLenght; + dataOffset += packetLength; width = MAX(width >> 1, 1); height = MAX(height >> 1, 1); @@ -260,7 +280,7 @@ - (BOOL)unpackPVRData:(unsigned char*)data PVRLen:(unsigned int)len } if( ! success ) - CCLOG(@"cocos2d: WARNING: Unssupported PVR Pixel Format: 0x%2x", formatFlags); + CCLOG(@"cocos2d: WARNING: Unsupported PVR Pixel Format: 0x%2x. Re-encode it with a OpenGL pixel format variant", formatFlags); return success; } @@ -268,8 +288,8 @@ - (BOOL)unpackPVRData:(unsigned char*)data PVRLen:(unsigned int)len - (BOOL)createGLTexture { - NSUInteger width = width_; - NSUInteger height = height_; + GLsizei width = width_; + GLsizei height = height_; GLenum err; if (numberOfMipmaps_ > 0) @@ -277,12 +297,15 @@ - (BOOL)createGLTexture if (name_ != 0) glDeleteTextures(1, &name_); + glPixelStorei(GL_UNPACK_ALIGNMENT,1); glGenTextures(1, &name_); glBindTexture(GL_TEXTURE_2D, name_); } + CHECK_GL_ERROR(); // clean possible GL error + // Generate textures with mipmaps - for (NSUInteger i=0; i < numberOfMipmaps_; i++) + for (GLint i=0; i < numberOfMipmaps_; i++) { GLenum internalFormat = tableFormats[tableFormatIndex_][kCCInternalOpenGLInternalFormat]; GLenum format = tableFormats[tableFormatIndex_][kCCInternalOpenGLFormat]; @@ -303,12 +326,12 @@ - (BOOL)createGLTexture glTexImage2D(GL_TEXTURE_2D, i, internalFormat, width, height, 0, format, type, data); if( i > 0 && (width != height || ccNextPOT(width) != width ) ) - CCLOG(@"cocos2d: TexturePVR. WARNING. Mipmap level %lu is not squared. Texture won't render correctly. width=%lu != height=%lu", i, width, height); + CCLOG(@"cocos2d: TexturePVR. WARNING. Mipmap level %u is not squared. Texture won't render correctly. width=%u != height=%u", i, width, height); err = glGetError(); if (err != GL_NO_ERROR) { - CCLOG(@"cocos2d: TexturePVR: Error uploading compressed texture level: %u . glError: 0x%04X", (unsigned int)i, err); + CCLOG(@"cocos2d: TexturePVR: Error uploading compressed texture level: %u . glError: 0x%04X", i, err); return FALSE; } @@ -325,7 +348,7 @@ - (id)initWithContentsOfFile:(NSString *)path if((self = [super init])) { unsigned char *pvrdata = NULL; - int pvrlen = 0; + NSInteger pvrlen = 0; NSString *lowerCase = [path lowercaseString]; if ( [lowerCase hasSuffix:@".ccz"]) @@ -359,7 +382,6 @@ - (id)initWithContentsOfFile:(NSString *)path } free(pvrdata); - } return self; diff --git a/libs/cocos2d/CCTileMapAtlas.h b/libs/cocos2d/CCTileMapAtlas.h index e4b60e2..102ae46 100644 --- a/libs/cocos2d/CCTileMapAtlas.h +++ b/libs/cocos2d/CCTileMapAtlas.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/libs/cocos2d/CCTileMapAtlas.m b/libs/cocos2d/CCTileMapAtlas.m index 378ad03..aef6fe0 100644 --- a/libs/cocos2d/CCTileMapAtlas.m +++ b/libs/cocos2d/CCTileMapAtlas.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,7 +32,7 @@ @interface CCTileMapAtlas (Private) -(void) loadTGAfile:(NSString*)file; -(void) calculateItemsToRender; --(void) updateAtlasValueAt:(ccGridSize)pos withValue:(ccColor3B)value withIndex:(int)idx; +-(void) updateAtlasValueAt:(ccGridSize)pos withValue:(ccColor3B)value withIndex:(NSUInteger)idx; @end @@ -154,12 +155,12 @@ -(ccColor3B) tileAt:(ccGridSize) pos return value; } --(void) updateAtlasValueAt:(ccGridSize)pos withValue:(ccColor3B)value withIndex:(int)idx +-(void) updateAtlasValueAt:(ccGridSize)pos withValue:(ccColor3B)value withIndex:(NSUInteger)idx { ccV3F_C4B_T2F_Quad quad; - int x = pos.x; - int y = pos.y; + NSInteger x = pos.x; + NSInteger y = pos.y; float row = (value.r % itemsPerRow_); float col = (value.r / itemsPerRow_); diff --git a/libs/cocos2d/CCTransition.h b/libs/cocos2d/CCTransition.h index 619a8a3..e37d3e8 100644 --- a/libs/cocos2d/CCTransition.h +++ b/libs/cocos2d/CCTransition.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/libs/cocos2d/CCTransition.m b/libs/cocos2d/CCTransition.m index 61f96b7..8cca825 100644 --- a/libs/cocos2d/CCTransition.m +++ b/libs/cocos2d/CCTransition.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -45,9 +46,8 @@ #import "Platforms/Mac/CCEventDispatcher.h" #endif -enum { - kSceneFade = 0xFADEFADE, -}; +const uint32_t kSceneFade = 0xFADEFADE; + @interface CCTransitionScene (Private) -(void) sceneOrder; @@ -93,6 +93,8 @@ -(void) sceneOrder -(void) draw { + [super draw]; + if( inSceneOnTop_ ) { [outScene_ visit]; [inScene_ visit]; @@ -152,8 +154,12 @@ -(void) hideOutShowIn -(void) onEnter { [super onEnter]; + + // outScene_ should not receive the onExit callback + // only the onExitTransitionDidStart + [outScene_ onExitTransitionDidStart]; + [inScene_ onEnter]; - // outScene_ should not receive the onEnter callback } // custom onExit @@ -162,7 +168,7 @@ -(void) onExit [super onExit]; [outScene_ onExit]; - // inScene_ should not receive the onExit callback + // inScene_ should not receive the onEnter callback // only the onEnterTransitionDidFinish [inScene_ onEnterTransitionDidFinish]; } diff --git a/libs/cocos2d/Platforms/CCGL.h b/libs/cocos2d/Platforms/CCGL.h index 9dc3e9b..0725f89 100644 --- a/libs/cocos2d/Platforms/CCGL.h +++ b/libs/cocos2d/Platforms/CCGL.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/libs/cocos2d/Platforms/CCNS.h b/libs/cocos2d/Platforms/CCNS.h index a8d5e0a..c595a18 100644 --- a/libs/cocos2d/Platforms/CCNS.h +++ b/libs/cocos2d/Platforms/CCNS.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -42,6 +43,14 @@ #define CCTextAlignmentCenter UITextAlignmentCenter #define CCTextAlignmentLeft UITextAlignmentLeft #define CCTextAlignmentRight UITextAlignmentRight +#define CCLineBreakMode UILineBreakMode +#define CCLineBreakModeWordWrap UILineBreakModeWordWrap +#define CCLineBreakModeCharacterWrap UILineBreakModeCharacterWrap +#define CCLineBreakModeClip UILineBreakModeClip +#define CCLineBreakModeHeadTruncation UILineBreakModeHeadTruncation +#define CCLineBreakModeTailTruncation UILineBreakModeTailTruncation +#define CCLineBreakModeMiddleTruncation UILineBreakModeMiddleTruncation + #elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) @@ -56,6 +65,13 @@ #define CCTextAlignmentCenter NSCenterTextAlignment #define CCTextAlignmentLeft NSLeftTextAlignment #define CCTextAlignmentRight NSRightTextAlignment +#define CCLineBreakMode NSLineBreakMode +#define CCLineBreakModeWordWrap NSLineBreakByWordWrapping +#define CCLineBreakModeClip -1 +#define CCLineBreakModeHeadTruncation -1 +#define CCLineBreakModeTailTruncation -1 +#define CCLineBreakModeMiddleTruncation -1 + #endif diff --git a/libs/cocos2d/Platforms/Mac/CCDirectorMac.h b/libs/cocos2d/Platforms/Mac/CCDirectorMac.h index 1df12d3..0d623b4 100644 --- a/libs/cocos2d/Platforms/Mac/CCDirectorMac.h +++ b/libs/cocos2d/Platforms/Mac/CCDirectorMac.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -52,13 +53,14 @@ enum { BOOL isFullScreen_; int resizeMode_; CGPoint winOffset_; - CGSize originalWinSize_; + CGSize originalWinSize_; - MacGLView *fullScreenGLView_; NSWindow *fullScreenWindow_; - + // cache - MacGLView *windowGLView_; + NSWindow *windowGLView_; + NSView *superViewGLView_; + NSRect originalWinRect_; // Original size and position } // whether or not the view is in fullscreen mode @@ -67,6 +69,8 @@ enum { // resize mode: with or without scaling @property (nonatomic, readwrite) int resizeMode; +@property (nonatomic, readwrite) CGSize originalWinSize; + /** Sets the view in fullscreen or window mode */ - (void) setFullScreen:(BOOL)fullscreen; diff --git a/libs/cocos2d/Platforms/Mac/CCDirectorMac.m b/libs/cocos2d/Platforms/Mac/CCDirectorMac.m index 531646d..0095cdb 100644 --- a/libs/cocos2d/Platforms/Mac/CCDirectorMac.m +++ b/libs/cocos2d/Platforms/Mac/CCDirectorMac.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -65,6 +66,7 @@ -(CGPoint) convertEventToGL:(NSEvent*)event @implementation CCDirectorMac @synthesize isFullScreen = isFullScreen_; +@synthesize originalWinSize = originalWinSize_; -(id) init { @@ -72,7 +74,7 @@ -(id) init isFullScreen_ = NO; resizeMode_ = kCCDirectorResize_AutoScale; - fullScreenGLView_ = nil; + originalWinSize_ = CGSizeZero; fullScreenWindow_ = nil; windowGLView_ = nil; winOffset_ = CGPointZero; @@ -83,7 +85,7 @@ -(id) init - (void) dealloc { - [fullScreenGLView_ release]; + [superViewGLView_ release]; [fullScreenWindow_ release]; [windowGLView_ release]; [super dealloc]; @@ -96,58 +98,68 @@ - (void) setFullScreen:(BOOL)fullscreen { // Mac OS X 10.6 and later offer a simplified mechanism to create full-screen contexts #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5 - - if( isFullScreen_ != fullscreen ) { - - isFullScreen_ = fullscreen; - if( fullscreen ) { - - // create the fullscreen view/window - NSRect mainDisplayRect, viewRect; - - // Create a screen-sized window on the display you want to take over - // Note, mainDisplayRect has a non-zero origin if the key window is on a secondary display - mainDisplayRect = [[NSScreen mainScreen] frame]; - fullScreenWindow_ = [[NSWindow alloc] initWithContentRect:mainDisplayRect - styleMask:NSBorderlessWindowMask - backing:NSBackingStoreBuffered - defer:YES]; - - // Set the window level to be above the menu bar - [fullScreenWindow_ setLevel:NSMainMenuWindowLevel+1]; - - // Perform any other window configuration you desire - [fullScreenWindow_ setOpaque:YES]; - [fullScreenWindow_ setHidesOnDeactivate:YES]; - - // Create a view with a double-buffered OpenGL context and attach it to the window - // By specifying the non-fullscreen context as the shareContext, we automatically inherit the OpenGL objects (textures, etc) it has defined - viewRect = NSMakeRect(0.0, 0.0, mainDisplayRect.size.width, mainDisplayRect.size.height); - - fullScreenGLView_ = [[MacGLView alloc] initWithFrame:viewRect shareContext:[openGLView_ openGLContext]]; - - [fullScreenWindow_ setContentView:fullScreenGLView_]; - - // Show the window - [fullScreenWindow_ makeKeyAndOrderFront:self]; - - [self setOpenGLView:fullScreenGLView_]; - - } else { - - [fullScreenWindow_ release]; - [fullScreenGLView_ release]; - fullScreenWindow_ = nil; - fullScreenGLView_ = nil; - - [[windowGLView_ openGLContext] makeCurrentContext]; - [self setOpenGLView:windowGLView_]; - - } - - [openGLView_ setNeedsDisplay:YES]; - } + if (isFullScreen_ == fullscreen) return; + + if( fullscreen ) { + originalWinRect_ = [openGLView_ frame]; + + // Cache normal window and superview of openGLView + if(!windowGLView_) + windowGLView_ = [[openGLView_ window] retain]; + + [superViewGLView_ release]; + superViewGLView_ = [[openGLView_ superview] retain]; + + + // Get screen size + NSRect displayRect = [[NSScreen mainScreen] frame]; + + // Create a screen-sized window on the display you want to take over + fullScreenWindow_ = [[MacWindow alloc] initWithFrame:displayRect fullscreen:YES]; + + // Remove glView from window + [openGLView_ removeFromSuperview]; + + // Set new frame + [openGLView_ setFrame:displayRect]; + + // Attach glView to fullscreen window + [fullScreenWindow_ setContentView:openGLView_]; + + // Show the fullscreen window + [fullScreenWindow_ makeKeyAndOrderFront:self]; + [fullScreenWindow_ makeMainWindow]; + + } else { + + // Remove glView from fullscreen window + [openGLView_ removeFromSuperview]; + + // Release fullscreen window + [fullScreenWindow_ release]; + fullScreenWindow_ = nil; + + // Attach glView to superview + [superViewGLView_ addSubview:openGLView_]; + + // Set new frame + [openGLView_ setFrame:originalWinRect_]; + + // Show the window + [windowGLView_ makeKeyAndOrderFront:self]; + [windowGLView_ makeMainWindow]; + } + isFullScreen_ = fullscreen; + + [openGLView_ retain]; // Retain +1 + + // re-configure glView + [self setOpenGLView:openGLView_]; + + [openGLView_ release]; // Retain -1 + + [openGLView_ setNeedsDisplay:YES]; #else #error Full screen is not supported for Mac OS 10.5 or older yet #error If you don't want FullScreen support, you can safely remove these 2 lines @@ -159,8 +171,8 @@ -(void) setOpenGLView:(MacGLView *)view [super setOpenGLView:view]; // cache the NSWindow and NSOpenGLView created from the NIB - if( ! isFullScreen_ && ! windowGLView_) { - windowGLView_ = [view retain]; + if( !isFullScreen_ && CGSizeEqualToSize(originalWinSize_, CGSizeZero)) + { originalWinSize_ = winSizeInPixels_; } } @@ -173,16 +185,11 @@ -(int) resizeMode -(void) setResizeMode:(int)mode { if( mode != resizeMode_ ) { + resizeMode_ = mode; - [openGLView_ setNeedsDisplay: YES]; - - [self setProjection:projection_]; - - if( mode == kCCDirectorResize_AutoScale ) { - originalWinSize_ = winSizeInPixels_; - CCLOG(@"cocos2d: Warning. Switching back to AutoScale might break some stuff. Experimental stuff"); - } + [self setProjection:projection_]; + [openGLView_ setNeedsDisplay: YES]; } } @@ -214,7 +221,7 @@ -(void) setProjection:(ccDirectorProjection)projection offset = winOffset_; } - + switch (projection) { case kCCDirectorProjection2D: glViewport(offset.x, offset.y, widthAspect, heightAspect); @@ -260,6 +267,7 @@ -(CGSize) winSize { if( resizeMode_ == kCCDirectorResize_AutoScale ) return originalWinSize_; + return winSizeInPixels_; } @@ -308,7 +316,7 @@ - (CVReturn) getFrameForTime:(const CVTimeStamp*)outputTime [self drawScene]; [[CCEventDispatcher sharedDispatcher] dispatchQueuedEvents]; - [[NSRunLoop currentRunLoop] run]; + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:nil]; [pool release]; @@ -438,9 +446,11 @@ - (void) drawScene CC_DISABLE_DEFAULT_GL_STATES(); glPopMatrix(); - + + totalFrames_++; + [[openGLView_ openGLContext] flushBuffer]; - CGLUnlockContext([[openGLView_ openGLContext] CGLContextObj]); + CGLUnlockContext([[openGLView_ openGLContext] CGLContextObj]); } // set the event dispatcher @@ -454,9 +464,13 @@ -(void) setOpenGLView:(MacGLView *)view [openGLView_ setEventDelegate: eventDispatcher]; [eventDispatcher setDispatchEvents: YES]; + // Enable Touches. Default no. + // Only available on OS X 10.6+ +#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5 [view setAcceptsTouchEvents:NO]; // [view setAcceptsTouchEvents:YES]; +#endif // Synchronize buffer swaps with vertical refresh rate diff --git a/libs/cocos2d/Platforms/Mac/CCEventDispatcher.h b/libs/cocos2d/Platforms/Mac/CCEventDispatcher.h index b52f8d1..06889e8 100644 --- a/libs/cocos2d/Platforms/Mac/CCEventDispatcher.h +++ b/libs/cocos2d/Platforms/Mac/CCEventDispatcher.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -156,6 +157,36 @@ -(BOOL) ccFlagsChanged:(NSEvent*)event; @end +#pragma mark - +#pragma mark CCTouchEventDelegate + +/** CCTouchEventDelegate protocol. + Implement it in your node to receive any of touch events + */ +@protocol CCTouchEventDelegate +@optional +/** called when the "touchesBegan" event is received. + Return YES to avoid propagating the event to other delegates. + */ +- (BOOL)ccTouchesBeganWithEvent:(NSEvent *)event; + +/** called when the "touchesMoved" event is received. + Return YES to avoid propagating the event to other delegates. + */ +- (BOOL)ccTouchesMovedWithEvent:(NSEvent *)event; + +/** called when the "touchesEnded" event is received. + Return YES to avoid propagating the event to other delegates. + */ +- (BOOL)ccTouchesEndedWithEvent:(NSEvent *)event; + +/** called when the "touchesCancelled" event is received. + Return YES to avoid propagating the event to other delegates. + */ +- (BOOL)ccTouchesCancelledWithEvent:(NSEvent *)event; + +@end + #pragma mark - #pragma mark CCEventDispatcher @@ -177,6 +208,7 @@ struct _listEntry; struct _listEntry *keyboardDelegates_; struct _listEntry *mouseDelegates_; + struct _listEntry *touchDelegates_; } @property (nonatomic, readwrite) BOOL dispatchEvents; @@ -219,7 +251,19 @@ struct _listEntry; #pragma mark CCEventDispatcher - Touches -// XXX +/** Adds a Touch delegate to the dispatcher's list. + Delegates with a lower priority value will be called before higher priority values. + All the events will be propgated to all the delegates, unless the one delegate returns YES. + + IMPORTANT: The delegate will be retained. + */ +- (void)addTouchDelegate:(id)delegate priority:(NSInteger)priority; + +/** Removes a touch delegate */ +- (void)removeTouchDelegate:(id) delegate; + +/** Removes all touch delegates, releasing all the delegates */ +- (void)removeAllTouchDelegates; #pragma mark CCEventDispatcher - Dispatch Events diff --git a/libs/cocos2d/Platforms/Mac/CCEventDispatcher.m b/libs/cocos2d/Platforms/Mac/CCEventDispatcher.m index b726665..1d1740e 100644 --- a/libs/cocos2d/Platforms/Mac/CCEventDispatcher.m +++ b/libs/cocos2d/Platforms/Mac/CCEventDispatcher.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -48,7 +49,12 @@ kCCImplementsScrollWheel = 1 << 10, kCCImplementsMouseEntered = 1 << 11, kCCImplementsMouseExited = 1 << 12, - + + kCCImplementsTouchesBegan = 1 << 13, + kCCImplementsTouchesMoved = 1 << 14, + kCCImplementsTouchesEnded = 1 << 15, + kCCImplementsTouchesCancelled = 1 << 16, + // keyboard kCCImplementsKeyUp = 1 << 0, kCCImplementsKeyDown = 1 << 1, @@ -112,6 +118,7 @@ -(id) init // delegates keyboardDelegates_ = NULL; mouseDelegates_ = NULL; + touchDelegates_ = NULL; #if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD eventQueueCount = 0; @@ -250,6 +257,29 @@ -(void) removeAllKeyboardDelegates [self removeAllDelegatesFromList:&keyboardDelegates_]; } +-(void) addTouchDelegate:(id) delegate priority:(NSInteger)priority +{ + NSUInteger flags = 0; + + flags |= ( [delegate respondsToSelector:@selector(ccTouchesBeganWithEvent:)] ? kCCImplementsTouchesBegan : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccTouchesMovedWithEvent:)] ? kCCImplementsTouchesMoved : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccTouchesEndedWithEvent:)] ? kCCImplementsTouchesEnded : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccTouchesCancelledWithEvent:)] ? kCCImplementsTouchesCancelled : 0 ); + + [self addDelegate:delegate priority:priority flags:flags list:&touchDelegates_]; +} + +-(void) removeTouchDelegate:(id) delegate +{ + [self removeDelegate:delegate fromList:&touchDelegates_]; +} + +-(void) removeAllTouchDelegates +{ + [self removeAllDelegatesFromList:&touchDelegates_]; +} + + #pragma mark CCEventDispatcher - Mouse events // // Mouse events @@ -504,7 +534,7 @@ - (void)flagsChanged:(NSEvent *)event tListEntry *entry, *tmp; DL_FOREACH_SAFE( keyboardDelegates_, entry, tmp ) { - if ( entry->flags & kCCImplementsKeyUp ) { + if ( entry->flags & kCCImplementsFlagsChanged ) { void *swallows = [entry->delegate performSelector:@selector(ccFlagsChanged:) withObject:event]; if( swallows ) break; @@ -518,32 +548,65 @@ - (void)flagsChanged:(NSEvent *)event - (void)touchesBeganWithEvent:(NSEvent *)event { - if (dispatchEvents_ ) { - NSLog(@"Touch Events: Not supported yet"); - } + if( dispatchEvents_ ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( touchDelegates_, entry, tmp ) { + if ( entry->flags & kCCImplementsTouchesBegan) { + void *swallows = [entry->delegate performSelector:@selector(ccTouchesBeganWithEvent:) withObject:event]; + if( swallows ) + break; + } + } + } } - (void)touchesMovedWithEvent:(NSEvent *)event { - if (dispatchEvents_ ) { - NSLog(@"Touch Events: Not supported yet"); - } + if( dispatchEvents_ ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( touchDelegates_, entry, tmp ) { + if ( entry->flags & kCCImplementsTouchesMoved) { + void *swallows = [entry->delegate performSelector:@selector(ccTouchesMovedWithEvent:) withObject:event]; + if( swallows ) + break; + } + } + } } - (void)touchesEndedWithEvent:(NSEvent *)event { - if (dispatchEvents_ ) { - NSLog(@"Touch Events: Not supported yet"); - } + if( dispatchEvents_ ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( touchDelegates_, entry, tmp ) { + if ( entry->flags & kCCImplementsTouchesEnded) { + void *swallows = [entry->delegate performSelector:@selector(ccTouchesEndedWithEvent:) withObject:event]; + if( swallows ) + break; + } + } + } } - (void)touchesCancelledWithEvent:(NSEvent *)event { - if (dispatchEvents_ ) { - NSLog(@"Touch Events: Not supported yet"); - } + if( dispatchEvents_ ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( touchDelegates_, entry, tmp ) { + if ( entry->flags & kCCImplementsTouchesCancelled) { + void *swallows = [entry->delegate performSelector:@selector(ccTouchesCancelledWithEvent:) withObject:event]; + if( swallows ) + break; + } + } + } } + #pragma mark CCEventDispatcher - queue events #if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD @@ -551,28 +614,32 @@ -(void) queueEvent:(NSEvent*)event selector:(SEL)selector { NSAssert( eventQueueCount < QUEUE_EVENT_MAX, @"CCEventDispatcher: recompile. Increment QUEUE_EVENT_MAX value"); - eventQueue[eventQueueCount].selector = selector; - eventQueue[eventQueueCount].event = [event copy]; - - eventQueueCount++; + @synchronized (self) { + eventQueue[eventQueueCount].selector = selector; + eventQueue[eventQueueCount].event = [event copy]; + + eventQueueCount++; + } } -(void) dispatchQueuedEvents { - for( int i=0; i < eventQueueCount; i++ ) { - SEL sel = eventQueue[i].selector; - NSEvent *event = eventQueue[i].event; - - [self performSelector:sel withObject:event]; + @synchronized (self) { + for( int i=0; i < eventQueueCount; i++ ) { + SEL sel = eventQueue[i].selector; + NSEvent *event = eventQueue[i].event; + + [self performSelector:sel withObject:event]; + + [event release]; + } - [event release]; + eventQueueCount = 0; } - - eventQueueCount = 0; } #endif // CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD @end -#endif // __MAC_OS_X_VERSION_MAX_ALLOWED \ No newline at end of file +#endif // __MAC_OS_X_VERSION_MAX_ALLOWED diff --git a/libs/cocos2d/Platforms/Mac/MacGLView.h b/libs/cocos2d/Platforms/Mac/MacGLView.h index 8d04b8e..8099273 100644 --- a/libs/cocos2d/Platforms/Mac/MacGLView.h +++ b/libs/cocos2d/Platforms/Mac/MacGLView.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/libs/cocos2d/Platforms/Mac/MacGLView.m b/libs/cocos2d/Platforms/Mac/MacGLView.m index c29045d..a041dc8 100644 --- a/libs/cocos2d/Platforms/Mac/MacGLView.m +++ b/libs/cocos2d/Platforms/Mac/MacGLView.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -71,7 +72,7 @@ - (id) initWithFrame:(NSRect)frameRect shareContext:(NSOpenGLContext*)context if (!pixelFormat) NSLog(@"No OpenGL pixel format"); - if (self = [super initWithFrame:frameRect pixelFormat:[pixelFormat autorelease]]) { + if( (self = [super initWithFrame:frameRect pixelFormat:[pixelFormat autorelease]]) ) { if( context ) [self setOpenGLContext:context]; @@ -238,4 +239,4 @@ - (void)touchesCancelledWithEvent:(NSEvent *)theEvent @end -#endif // __MAC_OS_X_VERSION_MAX_ALLOWED \ No newline at end of file +#endif // __MAC_OS_X_VERSION_MAX_ALLOWED diff --git a/libs/cocos2d/CCSpriteSheet.m b/libs/cocos2d/Platforms/Mac/MacWindow.h similarity index 71% rename from libs/cocos2d/CCSpriteSheet.m rename to libs/cocos2d/Platforms/Mac/MacWindow.h index fccc143..716fe9b 100644 --- a/libs/cocos2d/CCSpriteSheet.m +++ b/libs/cocos2d/Platforms/Mac/MacWindow.h @@ -1,8 +1,7 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2009-2010 Ricardo Quesada - * Copyright (C) 2009 Matt Oswald + * Copyright (c) 2010 Ricardo Quesada * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -21,17 +20,23 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. - * */ +// Only compile this code on Mac. These files should not be included on your iOS project. +// But in case they are included, it won't be compiled. +#import +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) -#import "CCSpriteSheet.h" +#import -#pragma mark - -#pragma mark CCSpriteSheet -@implementation CCSpriteSheetInternalOnly -@end +@interface MacWindow : NSWindow +{ +} +- (id) initWithFrame:(NSRect)frame fullscreen:(BOOL)fullscreen; -@implementation CCSpriteSheet @end + + +#endif // __MAC_OS_X_VERSION_MAX_ALLOWED \ No newline at end of file diff --git a/libs/cocos2d/Platforms/Mac/MacWindow.m b/libs/cocos2d/Platforms/Mac/MacWindow.m new file mode 100644 index 0000000..28736a3 --- /dev/null +++ b/libs/cocos2d/Platforms/Mac/MacWindow.m @@ -0,0 +1,70 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Only compile this code on Mac. These files should not be included on your iOS project. +// But in case they are included, it won't be compiled. +#import +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + +#import "MacWindow.h" + + +@implementation MacWindow + +- (id) initWithFrame:(NSRect)frame fullscreen:(BOOL)fullscreen +{ + int styleMask = fullscreen ? NSBackingStoreBuffered : ( NSTitledWindowMask | NSClosableWindowMask ); + self = [self initWithContentRect:frame + styleMask:styleMask + backing:NSBackingStoreBuffered + defer:YES]; + + if (self != nil) + { + if(fullscreen) + { + [self setLevel:NSMainMenuWindowLevel+1]; + [self setHidesOnDeactivate:YES]; + [self setHasShadow:NO]; + } + + [self setAcceptsMouseMovedEvents:NO]; + [self setOpaque:YES]; + } + return self; +} + +- (BOOL) canBecomeKeyWindow +{ + return YES; +} + +- (BOOL) canBecomeMainWindow +{ + return YES; +} +@end + +#endif // __MAC_OS_X_VERSION_MAX_ALLOWED diff --git a/libs/cocos2d/Platforms/iOS/CCDirectorIOS.h b/libs/cocos2d/Platforms/iOS/CCDirectorIOS.h old mode 100755 new mode 100644 index 7126d0d..4d57e8c --- a/libs/cocos2d/Platforms/iOS/CCDirectorIOS.h +++ b/libs/cocos2d/Platforms/iOS/CCDirectorIOS.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -50,45 +51,6 @@ typedef enum { CCDeviceOrientationLandscapeRight = kCCDeviceOrientationLandscapeRight, } ccDeviceOrientation; -/** @typedef tPixelFormat - Possible Pixel Formats for the OpenGL View. - - @deprecated Will be removed in v1.0 - */ -typedef enum { - /** RGB565 pixel format. No alpha. 16-bit. (Default) */ - kCCPixelFormatRGB565, - /** RGBA format. 32-bit. Needed for some 3D effects. It is not as fast as the RGB565 format. */ - kCCPixelFormatRGBA8888, - /** default pixel format */ - kCCPixelFormatDefault = kCCPixelFormatRGB565, - - // backward compatibility stuff - kPixelFormatRGB565 = kCCPixelFormatRGB565, - kRGB565 = kCCPixelFormatRGB565, - kPixelFormatRGBA8888 = kCCPixelFormatRGBA8888, - kRGBA8 = kCCPixelFormatRGBA8888, -} tPixelFormat; - -/** @typedef tDepthBufferFormat - Possible DepthBuffer Formats for the OpenGLView. - Use 16 or 24 bit depth buffers if you are going to use real 3D objects. - - @deprecated Will be removed in v1.0 - */ -typedef enum { - /// A Depth Buffer of 0 bits will be used (default) - kCCDepthBufferNone, - /// A depth buffer of 16 bits will be used - kCCDepthBuffer16, - /// A depth buffer of 24 bits will be used - kCCDepthBuffer24, - - // backward compatibility stuff - kDepthBuffer16 = kCCDepthBuffer16, - kDepthBuffer24 = kCCDepthBuffer24, -} tDepthBufferFormat; - /** @typedef ccDirectorType Possible Director Types. @since v0.8.2 @@ -177,8 +139,7 @@ typedef enum { This is the recommened way to enable Retina Display. @since v0.99.5 */ --(BOOL) enableRetinaDisplay:(BOOL)yes; - +-(BOOL) enableRetinaDisplay:(BOOL)enable; /** returns the content scale factor */ -(CGFloat) contentScaleFactor; @@ -218,56 +179,7 @@ typedef enum { /* contentScaleFactor could be simulated */ BOOL isContentScaleSupported_; - tPixelFormat pixelFormat_; // Deprecated. Will be removed in 1.0 - tDepthBufferFormat depthBufferFormat_; // Deprecated. Will be removed in 1.0 } - -// iPhone Specific - -/** Pixel format used to create the context */ -@property (nonatomic,readonly) tPixelFormat pixelFormat DEPRECATED_ATTRIBUTE; - -/** Uses a new pixel format for the EAGLView. - Call this class method before attaching it to a UIView - Default pixel format: kRGB565. Supported pixel formats: kRGBA8 and kRGB565 - - @deprecated Set the pixel format when creating the EAGLView. This method will be removed in v1.0 - */ --(void) setPixelFormat: (tPixelFormat)p DEPRECATED_ATTRIBUTE; - -/** Change depth buffer format of the render buffer. - Call this class method before attaching it to a UIWindow/UIView - Default depth buffer: 0 (none). Supported: kCCDepthBufferNone, kCCDepthBuffer16, and kCCDepthBuffer24 - - @deprecated Set the depth buffer format when creating the EAGLView. This method will be removed in v1.0 - */ --(void) setDepthBufferFormat: (tDepthBufferFormat)db DEPRECATED_ATTRIBUTE; - -// Integration with UIKit -/** detach the cocos2d view from the view/window */ --(BOOL)detach DEPRECATED_ATTRIBUTE; - -/** attach in UIWindow using the full frame. - It will create a EAGLView. - - @deprecated set setOpenGLView instead. Will be removed in v1.0 - */ --(BOOL)attachInWindow:(UIWindow *)window DEPRECATED_ATTRIBUTE; - -/** attach in UIView using the full frame. - It will create a EAGLView. - - @deprecated set setOpenGLView instead. Will be removed in v1.0 - */ --(BOOL)attachInView:(UIView *)view DEPRECATED_ATTRIBUTE; - -/** attach in UIView using the given frame. - It will create a EAGLView and use it. - - @deprecated set setOpenGLView instead. Will be removed in v1.0 - */ --(BOOL)attachInView:(UIView *)view withFrame:(CGRect)frame DEPRECATED_ATTRIBUTE; - @end /** FastDirector is a Director that triggers the main loop as fast as possible. @@ -281,7 +193,7 @@ typedef enum { { BOOL isRunning; - NSAutoreleasePool *autoreleasePool; + id autoreleasePool; } -(void) mainLoop; @end diff --git a/libs/cocos2d/Platforms/iOS/CCDirectorIOS.m b/libs/cocos2d/Platforms/iOS/CCDirectorIOS.m old mode 100755 new mode 100644 index a97e2e1..26f55c4 --- a/libs/cocos2d/Platforms/iOS/CCDirectorIOS.m +++ b/libs/cocos2d/Platforms/iOS/CCDirectorIOS.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -110,26 +111,16 @@ + (BOOL) setDirectorType:(ccDirectorType)type #pragma mark CCDirectorIOS @interface CCDirectorIOS () --(BOOL)isOpenGLAttached; --(BOOL)initOpenGLViewWithView:(UIView *)view withFrame:(CGRect)rect; - -(void) updateContentScaleFactor; @end @implementation CCDirectorIOS -@synthesize pixelFormat=pixelFormat_; - - (id) init { if( (self=[super init]) ) { - - // default values - pixelFormat_ = kCCPixelFormatDefault; // DEPRECATED. Will be removed in 1.0 - depthBufferFormat_ = 0; // DEPRECATED. Will be removed in 1.0 - // portrait mode default deviceOrientation_ = CCDeviceOrientationPortrait; @@ -192,7 +183,9 @@ - (void) drawScene glPopMatrix(); - [openGLView_ swapBuffers]; + totalFrames_++; + + [openGLView_ swapBuffers]; } -(void) setProjection:(ccDirectorProjection)projection @@ -210,17 +203,28 @@ -(void) setProjection:(ccDirectorProjection)projection break; case kCCDirectorProjection3D: + { + float zeye = [self getZEye]; + glViewport(0, 0, size.width, size.height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - gluPerspective(60, (GLfloat)size.width/size.height, 0.5f, 1500.0f); - + // accommodate iPad retina while keep backward compatibility + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad && + [[UIScreen mainScreen] scale] > 1.0 ) + { + gluPerspective(60, (GLfloat)size.width/size.height, zeye-size.height/2, zeye+size.height/2 ); + } else { + gluPerspective(60, (GLfloat)size.width/size.height, 0.5f, 1500); + } + glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - gluLookAt( size.width/2, size.height/2, [self getZEye], + gluLookAt( size.width/2, size.height/2, zeye, size.width/2, size.height/2, 0, - 0.0f, 1.0f, 0.0f); + 0.0f, 1.0f, 0.0f); break; + } case kCCDirectorProjectionCustom: if( projectionDelegate_ ) @@ -235,166 +239,8 @@ -(void) setProjection:(ccDirectorProjection)projection projection_ = projection; } -#pragma mark Director Scene iPhone Specific - --(void) setPixelFormat: (tPixelFormat) format -{ - NSAssert( ! [self isOpenGLAttached], @"Can't change the pixel format after the director was initialized" ); - pixelFormat_ = format; -} - --(void) setDepthBufferFormat: (tDepthBufferFormat) format -{ - NSAssert( ! [self isOpenGLAttached], @"Can't change the depth buffer format after the director was initialized"); - depthBufferFormat_ = format; -} - #pragma mark Director Integration with a UIKit view -// is the view currently attached --(BOOL)isOpenGLAttached -{ - return ([openGLView_ superview]!=nil); -} - -// XXX: deprecated --(BOOL)detach -{ - NSAssert([self isOpenGLAttached], @"FATAL: Director: Can't detach the OpenGL View, because it is not attached. Attach it first."); - - // remove from the superview - [openGLView_ removeFromSuperview]; - - NSAssert(![self isOpenGLAttached], @"FATAL: Director: Can't detach the OpenGL View, it is still attached to the superview."); - - - return YES; -} - -// XXX: Deprecated method --(BOOL)attachInWindow:(UIWindow *)window -{ - if([self initOpenGLViewWithView:window withFrame:[window bounds]]) - { - return YES; - } - - return NO; -} - -// XXX: Deprecated method --(BOOL)attachInView:(UIView *)view -{ - if([self initOpenGLViewWithView:view withFrame:[view bounds]]) - { - return YES; - } - - return NO; -} - -// XXX: Deprecated method --(BOOL)attachInView:(UIView *)view withFrame:(CGRect)frame -{ - if([self initOpenGLViewWithView:view withFrame:frame]) - { - return YES; - } - - return NO; -} - -// XXX: Deprecated method --(BOOL)initOpenGLViewWithView:(UIView *)view withFrame:(CGRect)rect -{ - NSAssert( ! [self isOpenGLAttached], @"FATAL: Can't re-attach the OpenGL View, because it is already attached. Detach it first"); - - // check if the view is not initialized - if(!openGLView_) - { - // define the pixel format - NSString *pFormat = nil; - GLuint depthFormat = 0; - - if(pixelFormat_==kCCPixelFormatRGBA8888) - pFormat = kEAGLColorFormatRGBA8; - else if(pixelFormat_== kCCPixelFormatRGB565) - pFormat = kEAGLColorFormatRGB565; - else { - CCLOG(@"cocos2d: Director: Unknown pixel format."); - } - - if(depthBufferFormat_ == kCCDepthBuffer16) - depthFormat = GL_DEPTH_COMPONENT16_OES; - else if(depthBufferFormat_ == kCCDepthBuffer24) - depthFormat = GL_DEPTH_COMPONENT24_OES; - else if(depthBufferFormat_ == kCCDepthBufferNone) - depthFormat = 0; - else { - CCLOG(@"cocos2d: Director: Unknown buffer depth."); - } - - // alloc and init the opengl view - openGLView_ = [[EAGLView alloc] initWithFrame:rect - pixelFormat:pFormat - depthFormat:depthFormat - preserveBackbuffer:NO - sharegroup:nil - multiSampling:NO - numberOfSamples:0]; - - // check if the view was alloced and initialized - NSAssert( openGLView_, @"FATAL: Could not alloc and init the OpenGL view. "); - - // opaque by default (faster) - openGLView_.opaque = YES; - } - else - { - // set the (new) frame of the glview - [openGLView_ setFrame:rect]; - } - - winSizeInPoints_ = rect.size; - winSizeInPixels_ = CGSizeMake(winSizeInPoints_.width * __ccContentScaleFactor, winSizeInPoints_.height * __ccContentScaleFactor); - - - // set the touch delegate of the glview to self - [openGLView_ setTouchDelegate: [CCTouchDispatcher sharedDispatcher]]; - - - // check if the superview has touchs enabled and enable it in our view - if([view isUserInteractionEnabled]) - { - [openGLView_ setUserInteractionEnabled:YES]; - [[CCTouchDispatcher sharedDispatcher] setDispatchEvents: YES]; - } - else - { - [openGLView_ setUserInteractionEnabled:NO]; - [[CCTouchDispatcher sharedDispatcher] setDispatchEvents: NO]; - } - - // check if multi touches are enabled and set them - if([view isMultipleTouchEnabled]) - { - [openGLView_ setMultipleTouchEnabled:YES]; - } - else - { - [openGLView_ setMultipleTouchEnabled:NO]; - } - - // add the glview to his (new) superview - [view addSubview:openGLView_]; - - - NSAssert( [self isOpenGLAttached], @"FATAL: Director: Could not attach OpenGL view"); - - [self setGLDefaultValues]; - return YES; -} - -(void) setOpenGLView:(EAGLView *)view { if( view != openGLView_ ) { @@ -445,7 +291,10 @@ -(void) updateContentScaleFactor isContentScaleSupported_ = YES; } else - CCLOG(@"cocos2d: 'setContentScaleFactor:' is not supported on this device"); + { + CCLOG(@"cocos2d: WARNING: calling setContentScaleFactor on iOS < 4. Using fallback mechanism"); + isContentScaleSupported_ = NO; + } } -(BOOL) enableRetinaDisplay:(BOOL)enabled @@ -506,9 +355,6 @@ -(CGPoint)convertToGL:(CGPoint)uiPoint ret.y = newX; break; } - -// if( __ccContentScaleFactor != 1 && isContentScaleSupported_ ) -// ret = ccpMult(ret, __ccContentScaleFactor); return ret; } @@ -533,8 +379,6 @@ -(CGPoint)convertToUI:(CGPoint)glPoint uiPoint = ccp(winSize.width-glPoint.y, winSize.height-glPoint.x); break; } - - uiPoint = ccpMult(uiPoint, 1/__ccContentScaleFactor); return uiPoint; } @@ -576,7 +420,7 @@ - (void) setDeviceOrientation:(ccDeviceOrientation) orientation [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationPortrait animated:NO]; break; case CCDeviceOrientationPortraitUpsideDown: - [[UIApplication sharedApplication] setStatusBarOrientation: UIDeviceOrientationPortraitUpsideDown animated:NO]; + [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationPortraitUpsideDown animated:NO]; break; case CCDeviceOrientationLandscapeLeft: [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationLandscapeRight animated:NO]; @@ -714,6 +558,8 @@ - (id) init - (void) startAnimation { + NSAssert( isRunning == NO, @"isRunning must be NO. Calling startAnimation twice?"); + // XXX: // XXX: release autorelease objects created // XXX: between "use fast director" and "runWithScene" @@ -800,7 +646,8 @@ - (id) init - (void) startAnimation { - + NSAssert( isRunning == NO, @"isRunning must be NO. Calling startAnimation twice?"); + if ( gettimeofday( &lastUpdate_, NULL) != 0 ) { CCLOG(@"cocos2d: ThreadedFastDirector: Error on gettimeofday"); } @@ -861,6 +708,8 @@ - (void)setAnimationInterval:(NSTimeInterval)interval - (void) startAnimation { + NSAssert( displayLink == nil, @"displayLink must be nil. Calling startAnimation twice?"); + if ( gettimeofday( &lastUpdate_, NULL) != 0 ) { CCLOG(@"cocos2d: DisplayLinkDirector: Error on gettimeofday"); } diff --git a/libs/cocos2d/Platforms/iOS/CCTouchDispatcher.h b/libs/cocos2d/Platforms/iOS/CCTouchDispatcher.h index b692c6d..0be9f13 100644 --- a/libs/cocos2d/Platforms/iOS/CCTouchDispatcher.h +++ b/libs/cocos2d/Platforms/iOS/CCTouchDispatcher.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2009 Valentin Milea + * Copyright (c) 2011 Samuel J. Grabski * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,12 +26,17 @@ // Only compile this code on iOS. These files should NOT be included on your Mac project. // But in case they are included, it won't be compiled. + #import #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED #import "CCTouchDelegateProtocol.h" #import "EAGLView.h" +#import "CCArray.h" // CCArray +#import "../../ccMacros.h" // CCLOG + +#define CC_UNUSED_ARGUMENT 0 typedef enum { @@ -41,7 +47,6 @@ typedef enum kCCTouchSelectorAllBits = ( kCCTouchSelectorBeganBit | kCCTouchSelectorMovedBit | kCCTouchSelectorEndedBit | kCCTouchSelectorCancelledBit), } ccTouchSelectorFlag; - enum { kCCTouchBegan, kCCTouchMoved, @@ -57,12 +62,111 @@ struct ccTouchHandlerHelperData { ccTouchSelectorFlag type; }; +/** typedef enum ccSortingAlgorithm @since v1.1.0 */ +typedef enum{ + kCCAlgInsertionSort = 0, // Insertion Sort is the default algorithm used + kCCAlgQSort, // C qsort + kCCAlgMergeLSort, // mergeLSort + kCCDoNotSort // do not sort +}ccSortingAlgorithm; + +/** typedef struct ccActionToDo @since v1.1.0 */ +typedef struct{ + int targetedRemoval; + int standardRemoval; + // + BOOL processStandardHandlersFirstFlag; + BOOL processStandardHandlersFirstArg; // order of processing + // + BOOL sortingAlgorithmFlag; + ccSortingAlgorithm sortingAlgorithmArg; // sorting algorithm type + // + BOOL reversePriorityFlag; + BOOL reversePriorityArg; // reverse priority + // + BOOL usersComparatorFlag; + int(*usersComparatorArg)(const void *, const void *); // new user comparator function + // + int targetedPriority; + int standardPriority; + // + BOOL targetedDebugLogFlag; + int targetedDebugLogArg; + // + BOOL standardDebugLogFlag; + int standardDebugLogArg; +}ccActionToDo; // All critical operations should be only done only when event processing is finished + +/** typedef enum ccDispatcherDelegateType @since v1.1.0 */ +typedef enum { + kCCTargeted, + kCCStandard +}ccDispatcherDelegateType; + +/** typedef enum ccHandlerFieldName @since v1.1.0 */ +typedef enum { + kCCDelegate = 0, // use with care + // real fields - their values can be accessed using 'retrieveField' function + kCCPriority, // use to change priorities + kCCTag, // use to change tag(s) + kCCDisable, // use to disable delegate(s) + kCCRemove, // use to remove delegate(s) + kCCSwallowsTouches, + // special virtual fields - use it if you understand its purpose + kCCPriorityToDo, // use to prepare change of priority, do the actual sorting by calling 'sortDelegates:' function + // useful for compound priority changes + kCCRemoveToDo, // use to mark delegates for removal, do actual removal by calling 'removeToDoDelegates:' function + // useful for compound removals + // kCC*ToDo fields are designed to work with 'setField' and 'setDelegatesField' functions + // + kCCNotRemoved, // do an action only for the delegates which are not marked for removal + kCCNone, // no field is searched for evaluation + kCCDebug, // prints debug info to console +}ccHandlerFieldName; + +/** typedef enum ccOperators @since v1.1.0 */ +typedef enum{ + kCCFALSE = 0, // always false + kCCTRUE, // always true + // One argument operators use with arg1; arg2 not used + kCCNEQ,//(v != arg1) + kCCEQ, //(v == arg1) + kCCGE, //(v >= arg1) + kCCGT, //(v > arg1) + kCCLE, //(v <= arg1) + kCCLT, //(v < arg1) + // And + kCCGEAndLE, // very useful (one closed range) (v >= arg1) && (v <= arg2); (arg1 <= arg2) + kCCGEAndLT, // one range (arg1 < arg2) + kCCGTAndLE, // one range (arg1 < arg2) + kCCGTAndLT, // very useful (one open range) (v > arg1) && (v < arg2); (arg1+1 < arg2) + kCCLEAndGE, // one inverted endpoints range (v <= arg1) && (v>= arg2); (arg1 >= arg2) + kCCLEAndGT, // one inverted endpoints range (arg1 > arg2) + kCCLTAndGE, // one inverted endpoints range (arg1 > arg2) + kCCLTAndGT, // one inverted endpoints range (arg1 > arg2+1) + // Or + kCCGEOrLE, // inverted endpoints values (arg1 > arg2) + kCCGEOrLT, // inverted endpoints values (arg1 > arg2) + kCCGTOrLE, // inverted endpoints values (arg1 > arg2) + kCCGTOrLT, // inverted endpoints values (arg1 > arg2) + kCCLEOrGE, // whole domain if arg1==arg2 (== kTRUE); two ranges (v <= arg1) && (v>= arg2); (arg1 < arg2) + kCCLEOrGT, // two ranges + kCCLTOrGE, // two ranges + kCCLTOrGT, // two ranges +}ccOperators; + +typedef enum +{ + kCCAddTargetedHandler, + kCCAddStandardHandler, +}ccHandlersToDoType; + /** CCTouchDispatcher. Singleton that handles all the touch events. The dispatcher dispatches events to the registered TouchHandlers. There are 2 different type of touch handlers: - - Standard Touch Handlers - - Targeted Touch Handlers + - Standard Touch Handlers + - Targeted Touch Handlers The Standard Touch Handlers work like the CocoaTouch touch handler: a set of touches is passed to the delegate. On the other hand, the Targeted Touch Handlers only receive 1 touch at the time, and they can "swallow" touches (avoid the propagation of the event). @@ -70,33 +174,41 @@ struct ccTouchHandlerHelperData { Firstly, the dispatcher sends the received touches to the targeted touches. These touches can be swallowed by the Targeted Touch Handlers. If there are still remaining touches, then the remaining touches will be sent to the Standard Touch Handlers. - @since v0.8.0 + + The above processing order can be reversed by setting 'processStandardHandlersFirst' to YES. + @since v1.1.0 */ @interface CCTouchDispatcher : NSObject { - NSMutableArray *targetedHandlers; - NSMutableArray *standardHandlers; - - BOOL locked; - BOOL toAdd; - BOOL toRemove; - NSMutableArray *handlersToAdd; - NSMutableArray *handlersToRemove; - BOOL toQuit; - - BOOL dispatchEvents; + CCArray *targetedHandlers; + CCArray *standardHandlers; + CCArray *handlersToDo; + + BOOL dispatchEvents; // default is YES; + BOOL processStandardHandlersFirst; // default is NO; + BOOL locked; // do not disturb, executing touch callbacks + + ccActionToDo actionToDo; // outstanding processing to do + + ccSortingAlgorithm sortingAlgorithm; // default kAlgInsertionSort + int(* usersComparator)(const void *, const void *); // user's comparator for sorting default NULL // 4, 1 for each type of event struct ccTouchHandlerHelperData handlerHelperData[kCCTouchMax]; +@private + unsigned int targetedHandlersCount; + unsigned int standardHandlersCount; + BOOL needsMutableSet; + id mutableTouches; + struct ccTouchHandlerHelperData helper; } /** singleton of the CCTouchDispatcher */ + (CCTouchDispatcher*)sharedDispatcher; /** Whether or not the events are going to be dispatched. Default: YES */ -@property (nonatomic,readwrite, assign) BOOL dispatchEvents; - +@property (nonatomic,readwrite,assign) BOOL dispatchEvents; /** Adds a standard touch delegate to the dispatcher's list. See StandardTouchDelegate description. IMPORTANT: The delegate will be retained. @@ -114,9 +226,349 @@ struct ccTouchHandlerHelperData { /** Removes all touch delegates, releasing all the delegates */ -(void) removeAllDelegates; /** Changes the priority of a previously added delegate. The lower the number, - the higher the priority */ + the higher the priority + @since v1.0 + depreciated in v1.1 use: + - (int) setPriority:(int)newValue delegate:(id)delegate delay:(BOOL)yesOrNo type:(ccDispatcherDelegateType)type; + */ -(void) setPriority:(int) priority forDelegate:(id) delegate; +// ------------------------------------------------------------------- +// @since v1.1.0: +//-------------------------------------------------------------------- + +//---------------------------------- +// adding delegates with tags +//---------------------------------- + +/** Adds a standard touch delegate to the dispatcher's list. + in addition to priority, tag and disabled flag can be specified. + 'doNotSort' prevents sorting delegates after the addition of a new one. + Events will be distributed to the delegates in the same order as delegates were added. + See StandardTouchDelegate description. + IMPORTANT: The delegate will be retained. + @since v1.1.0 + */ +- (void) addStandardDelegate:(id) delegate priority:(int)priority + tag:(int)aTag disable:(int)yesOrNo doNotSort:(int)YN; +/** Adds a targeted touch delegate to the dispatcher's list. + in addition to swallowsTouches or priority, tag and disable flag can be specified. + 'doNoSort' prevents sorting delegates after adding a new one. + Events will be distributed to the delegates in the same order as delegates were added. + See TargetedTouchDelegate description. + IMPORTANT: The delegate will be retained. + @since v1.1.0 + */ +- (void) addTargetedDelegate:(id) delegate priority:(int)priority swallowsTouches:(BOOL)swallowsTouches + tag:(int)aTag disable:(int)yesOrNo doNotSort:(int)YN; + +//--------------------------------------------------------------------- +// safe touch call-back getters and setters for internal control fields +//--------------------------------------------------------------------- + +/** As per default targeted handlers are executed first + If needed this order can be reversed: + @since v1.1.0 + */ +-(void) setProcessStandardHandlersFirst:(BOOL)yesOrNo; + +/** gets - current/requested - order of processing + @return whether or not standard handlers are processed first in the event loop + @since v1.1.0 + */ +-(BOOL) processStandardHandlersFirst; + +/** get locked state of the dispatcher. It returns YES when called from touch callback function. + @since v1.1.0 + */ +-(BOOL) locked; + +/** set sorting algorithm + @since v1.1.0 + */ +- (void) setSortingAlgorithm:(ccSortingAlgorithm)alg; + +/** get - current/requested - sortingAlgorithm + + @since v1.1.0 + */ +- (ccSortingAlgorithm) sortingAlgorithm; + +/** set reverse/normal order of priorities + This operation will NOT force resorting + Call sorting yourself via: sortDelegates:(ccDispatcherDelegateType)type; + */ +- (void) setReversePriority:(BOOL)yesNo; +/** get - current/requested 'reversePriority' + @since v1.1.0 + */ +- (BOOL) reversePriority; + +/** User can sets his own order of handling touches by supplying comparator functions. + 'setUsersComparator' sets new comparator for the sorting algorithms. + This operation will NOT force resorting. To do sorting use: sortDelegates:(ccDispatcherDelegateType)type; + 'reversePriority' parameter has NO bearing when user supplies his own comparator + @since v1.1.0 + */ +- (void) setUsersComparator:(int(*)(const void *, const void *))comparator; + +/** get - current/requested - usersComparator + @since v1.1.0 + */ +- (int(*)(const void *, const void *)) usersComparator; + +//-------------------------------------------- +// debug +//-------------------------------------------- + +/** prints debug info about handlers. If format = 1, info about delegate is added. + If 'after' = YES, the debug log is printed after all callback requests to the touch dispatcher + have been processed. In this case the return value is equal to -1. + If requested outside a touch callback it returns the number of the handlers' objects of the given type. + It is equal to the count of the printed handlers. + @since v1.1.0 + */ +- (int) printDebugLog:(int)format afterEvents:(BOOL)after type:(ccDispatcherDelegateType)type; + +//-------------------------------------------- +// priority sort +//-------------------------------------------- +//-------------------------------------------- +/** sorts delegates of the given type according to the following factors: + - sortingAlgorithm + - reversePriority + - comparator + + This function is also useful when priority is changed without sorting by the following functions used with kCCPriorityToDo field: + setField:kCCPriorityToDo ... or/and setDelegatesField:kCCPriorityToDo ... + Regardless, delegates will be sorted at the end of the callback event processing loop if required. + + @since v1.1.0 + */ +- (void) sortDelegates:(ccDispatcherDelegateType)type; +//-------------------------------------------- + +//--------------------------------- +// counting delegates +//--------------------------------- + +/** returns number of delegates of the given type + User's callback safe: delegates in the process of being removed are not counted. + @since v1.1.0 + */ +- (int) countDelegatesUsage:(ccDispatcherDelegateType)type; + +/** checks if the touch delegate is already added to the dispatcher's list of the given type + It may be important since any attempt to add two identical delegates triggers the 'NSAssert'. + User's callback safe: + It returns 0 if delegate does not exist or is marked for removal or >0 if delegate is added. + If delegate is marked for removal adding the same delegate is safe. + @since v1.1.0 + */ +- (int) countDelegateUsage:(id) delegate type:(ccDispatcherDelegateType)type; + +/** returns number of delegates with the specified tag + User's callback safe: delegates in the process of being removed are not counted. + */ +- (int) countTagUsage:(int)tagValue type:(ccDispatcherDelegateType)type; + +/** returns number of delegates with the specified priority + User's callback safe: delegates in the process of being removed are not counted. + @since v1.1.0 + */ +- (int) countPriorityUsage:(int)priorityValue type:(ccDispatcherDelegateType)type; + +/** returns number of delegates with the specified disable value ((Use: YES or NO) + User's callback safe: delegates in the process of being removed are not counted. + @since v1.1.0 + */ +- (int) countDisableUsage:(int)disableValue type:(ccDispatcherDelegateType)type; + +/** returns number of delegates with the specified value for given field + User's callback safe: delegates in the process of being removed are not counted. + Notice: It is generic functions covering all sugar 'countThisFieldUsage()' functions + @since v1.1.0 + */ +- (int) countFieldUsage:(ccHandlerFieldName)field fieldValue:(int)value type:(ccDispatcherDelegateType)type; + +//---------------------------------- +// retrieval of the field value +// --------------------------------- + +/** returns priority of the delegate or if the delegate does not exist, returns NSNotFound + @since v1.1.0 + */ +- (int) retrievePriorityField:(id) delegate type:(ccDispatcherDelegateType)type; + +/** returns tag of the delegate or if the delegate does not exist, returns NSNotFound + @since v1.1.0 + */ +- (int) retrieveTagField:(id) delegate type:(ccDispatcherDelegateType)type; + +/** returns value of the disable field or if the delegate does not exist, returns NSNotFound + @since v1.1.0 + */ +-(int) retrieveDisableField:(id) delegate type:(ccDispatcherDelegateType)type; + +/** returns value of the field or if the delegate does not exist, returns NSNotFound + Notice: It is generic functions covering all sugar 'retrieve*Field(.)' functions + @since v1.1.0 + */ +- (int) retrieveField:(ccHandlerFieldName)field delegate:(id)delegate type:(ccDispatcherDelegateType)type; + +//-------------------------------- +// disabling of the delegate(s) +//-------------------------------- + +/** disables/enables already added touch delegate + @since v1.1.0 + */ +- (int) disableDelegate:(id) delegate disable:(int)yesOrNo type:(ccDispatcherDelegateType)type; + +/** disables/enables all delegates of the given type + returns number of disabled delegates + @since v1.1.0 + */ +- (int) disableAllDelegates:(int)yesOrNo type:(ccDispatcherDelegateType)type; +/** disables/enables already added touch delegates of the given type + with specified tag. (That allows for fast and selective disabling/enabling of delegates. + Otherwise, delegates would have to be removed and added again to the list) + returns number of disabled delegates + @since v1.1.0 + */ +- (int) disableDelegatesWithTag:(int)aTag disable:(int)yesOrNo type:(ccDispatcherDelegateType)type; +/** disables/enables already added targeted touch delegates of the given type + with specified priority (including those marked for removal). + returns number of disabled delegates + @since v1.1.0 + */ +- (int) disableDelegatesWithPriority:(int)aPriority disable:(int)yesOrNo type:(ccDispatcherDelegateType)type; + +/** inside the event loop, delegates marked for removal still receive touches (default) + 'disableRemovedDelegates' disables/enables delegates marked for removal inside the event loop. + Use it inside the touch callback function if you do not want removed delegates to be active + during event loop. + returns number of disabled delegates (including those marked for removal) + @since v1.1.0 + */ +- (int) disableRemovedDelegates:(int)yesOrNo type:(ccDispatcherDelegateType)type; + +/** generic function to disable/enable delegates when a specific field contains a certain value. + The content of the field is evaluated against arg1 and arg2 using (ccOperators)op. + @since v1.1.0 + */ +- (int) disableDelegatesWithField:(ccHandlerFieldName)fieldName arg1:(int)leftEndPoint arg2:(int)rightEndPoint operator:(ccOperators)op +disable:(int)yesOrNo type:(ccDispatcherDelegateType)type; + +//--------------------------------- +// removal of the delegate/s +//--------------------------------- +// Note: removal cannot be undone. If you need an already removed delegate then add it again. + +/** Removes the delegate of the given type, releasing the delegate + If delay: is set to YES the removal is delayed until removeToDoDelegates:type is called or current/first + event loop ends. + @since v1.1.0 + */ +- (int) removeDelegate:(id) delegate delay:(BOOL)yesOrNO type:(ccDispatcherDelegateType)type; + +/** removes all delegates of the given type + returns number of delegates removed + @since v1.1.0 + */ +- (int) removeAllDelegates:(ccDispatcherDelegateType)type; + +/** removes all delegates of the given type with specified tag + returns number of delegates removed + If delay: is set to YES the removal is delayed until removeToDoDelegates:type is called or current/first + event loop ends. + @since v1.1.0 + */ +- (int) removeDelegatesWithTag:(int)tag delay:(BOOL)yesOrNO type:(ccDispatcherDelegateType)type; + +/** removes all delegates of the given type with specified priority + returns number of delegates removed + If delay: is set to YES the removal is delayed until removeToDoDelegates:type is called or current/first + event loop ends. + @since v1.1.0 + */ +- (int) removeDelegatesWithPriority:(int)priority delay:(BOOL)yesOrNO type:(ccDispatcherDelegateType)type; + +/** removes all delegates of the given type marked for removal by the following functions used with kCCRemoveToDo field: + setField:kCCRemoveToDo ... or/and setDelegatesField:kCCRemoveToDo ... or remove* functions with delay:YES + If 'removeToDoDelegates' is not used all marked delegates will be removed at the end of the first event processing loop. + returns number of delegates removed. + If function is called in the touch callback it returns -1. (Delegates will be removed at the end of the event loop) + @since v1.1.0 + */ +- (int) removeToDoDelegates:(ccDispatcherDelegateType)type; + +/** power function: covers all 'removeDelegates*' functions. Removes delegates of the given type + for which a given field contains desired value. + The value of the field is evaluated against arg1 and arg2 using (ccOperators)op. + @since v1.1.0 + */ +- (int) removeDelegatesWithField:(ccHandlerFieldName)fieldName + arg1:(int)leftEndPoint arg2:(int)rightEndPoint operator:(ccOperators)op delay:(BOOL)yesOrNO type:(ccDispatcherDelegateType)type; + +//------------------------------------------------------------------------- +// setting the value of a specific field to a new value for a given delegate +//------------------------------------------------------------------------- + +/** Changes the priority of the previously added delegate. + If the new value is different from the old one, it will commence sorting of the delegates. + returns the number of delegates which changed priority. Removed delegates are not counted. + If delay: is set to YES, sorting is delayed until 'sortDelegates:type' is called or the current/first + event loop ends. + @since v1.1.0 + */ +- (int) setPriority:(int)newValue delegate:(id)delegate delay:(BOOL)yesOrNo type:(ccDispatcherDelegateType)type; + +/** setRemove == removeDelegate + If delay: is set to YES then the removal is delayed until removeToDoDelegates:type is called or current/first + event loop ends. + @since v1.1.0 + */ +- (int) setRemove:(id)delegate delay:(BOOL)yesOrNo type:(ccDispatcherDelegateType)type; + +/** set a new tag for delegate + @since v1.1.0 + */ +- (int) setTag:(int)newValue delegate:(id)delegate type:(ccDispatcherDelegateType)type; +/** setDisable == disableDelegate - disable/enable delegate + @since v1.1.0 + */ +- (int) setDisable:(int)newValue delegate:(id)delegate type:(ccDispatcherDelegateType)type; + +/** generic power function: sets value of the specific field to a new value. + @return number of affected delegates. It returns 0 if delegate is not found. It returns less than 0 for an error. + @since v1.1.0 + */ +- (int) setField:(ccHandlerFieldName)field newValue:(int)newValue delegate:(id)delegate type:(ccDispatcherDelegateType)type; + +//------------------------------------------------------------------------------------------------ +// setting a new value for a specific field in delegate(s) which is conditional on the value of a certain field in the delegate +//------------------------------------------------------------------------------------------------ +/** sets new priority for all delegates with the given tag + If delay: is set to YES sorting is delayed until sortDelegates:type; is called or the current/first + event loop ends. + @since v1.1.0 + */ +- (int) setPriorityForTag:(int)tag newPriority:(int)value delay:(BOOL)yesOrNO type:(ccDispatcherDelegateType)type; +/** sets new tag for all delegates with the given priority + @since v1.1.0 + */ +- (int) setTagForPriority:(int)priority newTag:(int)value type:(ccDispatcherDelegateType)type; + +/** 'Only For Eagles' - generic power function - allows changes for delegates with the specific field value + The content of the field is evaluated against arg1 and arg2 using (ccOperators)op. + It returns number of affected delegates. + @since v1.1.0 + */ +- (int) setDelegatesField:(ccHandlerFieldName)field newValue:(int)newValue + ifField:(ccHandlerFieldName)fieldToSearch arg1:(int)leftEndPoint arg2:(int)rightEndPoint operator:(ccOperators)op +type:(ccDispatcherDelegateType)type; +//----------------------------------------------------------------------------------------------- @end #endif // __IPHONE_OS_VERSION_MAX_ALLOWED diff --git a/libs/cocos2d/Platforms/iOS/CCTouchDispatcher.m b/libs/cocos2d/Platforms/iOS/CCTouchDispatcher.m index 46e433e..0665cc7 100644 --- a/libs/cocos2d/Platforms/iOS/CCTouchDispatcher.m +++ b/libs/cocos2d/Platforms/iOS/CCTouchDispatcher.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2009 Valentin Milea + * Copyright (c) 2011 Samuel J. Grabski * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,20 +24,43 @@ * */ -// Only compile this code on iOS. These files should NOT be included on your Mac project. -// But in case they are included, it won't be compiled. #import #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED - #import "CCTouchDispatcher.h" #import "CCTouchHandler.h" +#include // qsort + +/** @since v1.1.0 */ +@interface CCHandlersToDo : NSObject // treat as private +{ +@private + ccHandlersToDoType type_; + CCTouchHandler *handler_; + int arg_; +} + +@property(nonatomic,readwrite,assign) ccHandlersToDoType type; +@property(nonatomic,readwrite,retain) CCTouchHandler *handler; +@property(nonatomic,readwrite,assign) int arg; + +@end + +static BOOL reversePriority; // default is NO; +static NSComparisonResult sortByPriority(const void * first, const void * second); +static BOOL eval(int v, ccOperators op, int arg); +static ccOperators calcOp1(ccOperators compOp); +static BOOL isItAnd(ccOperators compOp); +static ccOperators calcOp3(ccOperators compOp); +static BOOL evaluate(int v, ccOperators op1, int v1, BOOL useAnd, ccOperators op3, int v2); @implementation CCTouchDispatcher @synthesize dispatchEvents; +#define CC_SEARCH_NOT_SUCCESSFUL NSNotFound + static CCTouchDispatcher *sharedDispatcher = nil; +(CCTouchDispatcher*) sharedDispatcher @@ -60,24 +84,31 @@ +(id) allocWithZone:(NSZone *)zone -(id) init { if((self = [super init])) { - - dispatchEvents = YES; - targetedHandlers = [[NSMutableArray alloc] initWithCapacity:8]; - standardHandlers = [[NSMutableArray alloc] initWithCapacity:4]; + + locked = NO; + dispatchEvents = YES; + int capacity = 30; - handlersToAdd = [[NSMutableArray alloc] initWithCapacity:8]; - handlersToRemove = [[NSMutableArray alloc] initWithCapacity:8]; + targetedHandlers = [[CCArray alloc] initWithCapacity:capacity]; + standardHandlers = [[CCArray alloc] initWithCapacity:capacity]; + handlersToDo = [[CCArray alloc] initWithCapacity:capacity]; + + actionToDo.targetedRemoval = actionToDo.standardRemoval = 0; + actionToDo.processStandardHandlersFirstFlag = NO; + actionToDo.processStandardHandlersFirstArg = processStandardHandlersFirst = NO; + actionToDo.sortingAlgorithmFlag = NO; + actionToDo.sortingAlgorithmArg = sortingAlgorithm = kCCAlgInsertionSort; + actionToDo.reversePriorityFlag = actionToDo.reversePriorityArg = reversePriority = NO; + actionToDo.usersComparatorFlag = NO; + actionToDo.usersComparatorArg = usersComparator = NULL; + actionToDo.targetedPriority = actionToDo.standardPriority = 0; + actionToDo.targetedDebugLogFlag = actionToDo.standardDebugLogFlag = NO; + actionToDo.targetedDebugLogArg = actionToDo.standardDebugLogArg = 0; - toRemove = NO; - toAdd = NO; - toQuit = NO; - locked = NO; - handlerHelperData[kCCTouchBegan] = (struct ccTouchHandlerHelperData) {@selector(ccTouchesBegan:withEvent:),@selector(ccTouchBegan:withEvent:),kCCTouchSelectorBeganBit}; handlerHelperData[kCCTouchMoved] = (struct ccTouchHandlerHelperData) {@selector(ccTouchesMoved:withEvent:),@selector(ccTouchMoved:withEvent:),kCCTouchSelectorMovedBit}; handlerHelperData[kCCTouchEnded] = (struct ccTouchHandlerHelperData) {@selector(ccTouchesEnded:withEvent:),@selector(ccTouchEnded:withEvent:),kCCTouchSelectorEndedBit}; - handlerHelperData[kCCTouchCancelled] = (struct ccTouchHandlerHelperData) {@selector(ccTouchesCancelled:withEvent:),@selector(ccTouchCancelled:withEvent:),kCCTouchSelectorCancelledBit}; - + handlerHelperData[kCCTouchCancelled] = (struct ccTouchHandlerHelperData) {@selector(ccTouchesCancelled:withEvent:),@selector(ccTouchCancelled:withEvent:),kCCTouchSelectorCancelledBit}; } return self; @@ -87,8 +118,7 @@ -(void) dealloc { [targetedHandlers release]; [standardHandlers release]; - [handlersToAdd release]; - [handlersToRemove release]; + [handlersToDo release]; [super dealloc]; } @@ -96,142 +126,1285 @@ -(void) dealloc // handlers management // -#pragma mark TouchDispatcher - Add Hanlder +#pragma mark - +#pragma mark - Changing priority of the added handlers --(void) forceAddHandler:(CCTouchHandler*)handler array:(NSMutableArray*)array -{ - NSUInteger i = 0; +static NSComparisonResult sortByPriority(const void * first, const void * second) +{ + id fId = ((id *) first)[0]; // Lord, Have Mercy on Us! + id sId = ((id *) second)[0]; // Amen. - for( CCTouchHandler *h in array ) { - if( h.priority < handler.priority ) - i++; - - NSAssert( h.delegate != handler.delegate, @"Delegate already added to touch dispatcher."); + CCTouchHandler *f = (CCTouchHandler*) fId; + CCTouchHandler *s = (CCTouchHandler*) sId; + + int fP = f.priority; + int sP = s.priority; + + if (fP == sP) return NSOrderedSame; + + if (reversePriority){ + if (fP > sP) // if p1 > p2 > p3 order: p1,p2,p3 + return NSOrderedAscending; + else + return NSOrderedDescending; + } + else{ // default + if (fP < sP) // if p1 < p2 < p3 order: p1,p2,p3 + return NSOrderedAscending; + else + return NSOrderedDescending; } - [array insertObject:handler atIndex:i]; } --(void) addStandardDelegate:(id) delegate priority:(int)priority +-(void) rearrangeHandlers:(CCArray *)array { - CCTouchHandler *handler = [CCStandardTouchHandler handlerWithDelegate:delegate priority:priority]; - if( ! locked ) { - [self forceAddHandler:handler array:standardHandlers]; - } else { - [handlersToAdd addObject:handler]; - toAdd = YES; + if ( usersComparator ){ + switch (sortingAlgorithm) { + default: + case kCCAlgInsertionSort: + [array insertionSortUsingCFuncComparator:usersComparator]; + case kCCAlgQSort: + [array qsortUsingCFuncComparator:usersComparator]; + break; + case kCCAlgMergeLSort: + [array mergesortLUsingCFuncComparator:usersComparator]; + break; + case kCCDoNotSort: + break; + } + } + else{ + switch (sortingAlgorithm) { + default: + case kCCAlgInsertionSort: + [array insertionSortUsingCFuncComparator:sortByPriority]; + break; + case kCCAlgQSort: + [array qsortUsingCFuncComparator:sortByPriority]; + break; + case kCCAlgMergeLSort: + [array mergesortLUsingCFuncComparator:sortByPriority]; + break; + case kCCDoNotSort: + break; + } } } --(void) addTargetedDelegate:(id) delegate priority:(int)priority swallowsTouches:(BOOL)swallowsTouches -{ - CCTouchHandler *handler = [CCTargetedTouchHandler handlerWithDelegate:delegate priority:priority swallowsTouches:swallowsTouches]; - if( ! locked ) { - [self forceAddHandler:handler array:targetedHandlers]; - } else { - [handlersToAdd addObject:handler]; - toAdd = YES; +- (void) forceSetPriority +{ + if (actionToDo.targetedPriority){ + [self rearrangeHandlers:targetedHandlers]; + actionToDo.targetedPriority = 0; } + if (actionToDo.standardPriority){ + [self rearrangeHandlers:standardHandlers]; + actionToDo.standardPriority = 0; + } } -#pragma mark TouchDispatcher - removeDelegate +#pragma mark TouchDispatcher - arrayForType --(void) forceRemoveDelegate:(id)delegate +-(CCArray *) arrayForType:(ccDispatcherDelegateType)delegateType { - // XXX: remove it from both handlers ??? + CCArray *array; - for( CCTouchHandler *handler in targetedHandlers ) { - if( handler.delegate == delegate ) { - [targetedHandlers removeObject:handler]; + switch (delegateType){ + default: + case kCCTargeted: + array = targetedHandlers; + break; + case kCCStandard: + array = standardHandlers; break; + } + return array; +} +//----------------------------------------------------------- + +// removes all delegates of the given type +-(int) forceRemoveAllObjects:(ccDispatcherDelegateType) delegateType +{ + CCArray *array = [self arrayForType:delegateType]; + int numberOfObjectsRemoved = [array count]; + + [array removeAllObjects]; + + return numberOfObjectsRemoved; +} + +#pragma mark TouchDispatcher - removeAllDelegates + +-(int) removeAllDelegates:(ccDispatcherDelegateType) type +{ + if ( locked ) { + return ( [self removeDelegatesWithField:kCCNotRemoved arg1:CC_UNUSED_ARGUMENT arg2:CC_UNUSED_ARGUMENT operator:kCCTRUE delay:YES type:type] ); + } + else { + return ( [self forceRemoveAllObjects:type] ); + } +} + +#pragma mark TouchDispatcher - removeAllDelegates + +-(void) removeAllDelegates // since: v0.8.0 +{ + [self removeAllDelegates:kCCTargeted]; + [self removeAllDelegates:kCCStandard]; +} + +#pragma mark TouchDispatcher - forceRemoveOfMarkedHandlers + +-(void) forceRemoveOfMarkedHandlers:(ccDispatcherDelegateType)delegateType nrOfObjects:(int)nrOfObjects +{ // fast removal in one pass + int counter = 0; + CCTouchHandler *handler; + + CCArray *array = [self arrayForType:delegateType]; + ccArray *arrayData = array->data; + + for (int i = arrayData->num - 1; i>=0; --i) { + + handler = arrayData->arr[i]; // get handler + + if (handler.remove){ + + ccArrayRemoveObjectAtIndex(arrayData,i); // remove it + + //--- this works well if there is more smaller removals than the big ones + counter++; + if (counter >= nrOfObjects) + break; + //--- } + } +} + +#pragma mark TouchDispatcher - forceRemoveMarkedDelegates + +-(void) forceRemoveMarkedDelegates +{ + if ( actionToDo.targetedRemoval ) { + [self forceRemoveOfMarkedHandlers:kCCTargeted nrOfObjects:actionToDo.targetedRemoval]; + actionToDo.targetedRemoval = 0; + } + + if ( actionToDo.standardRemoval ) { + [self forceRemoveOfMarkedHandlers:kCCStandard nrOfObjects:actionToDo.standardRemoval]; + actionToDo.standardRemoval = 0; + } +} +//--- +#pragma mark TouchDispatcher - toDoAddType + +-(ccHandlersToDoType) toDoAddType:(ccDispatcherDelegateType)type +{ + ccHandlersToDoType toDo; + switch(type) { + default: + case kCCTargeted: + toDo = kCCAddTargetedHandler; + break; + case kCCStandard: + toDo = kCCAddStandardHandler; + break; + } + return toDo; +} + +-(void) debugLog:(ccDispatcherDelegateType)delegateType nr:(int)nr handler:(CCTouchHandler *) h formatType:(int)format +{ + switch (delegateType) { + + case kCCTargeted: + switch (format){ + case 1: + CCLOG(@"N%3d Targ priority%4d tag%4d dis%2d rem%2d swallow%2d enabledSelectors %02X handlersFirst%d revPrio%d sortAlgo%d usersComp%p del %@", + nr, h.priority, h.tag, h.disable, h.remove, ((CCTargetedTouchHandler*)h).swallowsTouches, + ((CCTargetedTouchHandler*)h).enabledSelectors, + processStandardHandlersFirst, reversePriority, sortingAlgorithm, usersComparator, + h.delegate); + break; + default: + case 0: + CCLOG(@"N%3d Targ priority%4d tag%4d dis%2d rem%2d swallow%2d enabledSelectors %02X handlersFirst%d revPrio%d sortAlgo%d usersComp%p", + nr, h.priority, h.tag, h.disable, h.remove,((CCTargetedTouchHandler*)h).swallowsTouches, + ((CCTargetedTouchHandler*)h).enabledSelectors, + processStandardHandlersFirst, reversePriority, sortingAlgorithm, usersComparator); + break; + } + break; + + case kCCStandard: + switch (format){ + case 1: + CCLOG(@"N%3d Stnd pri%4d tag%4d dis%2d rem%2d handlersFirst%d revPrio%d sortAlgo%d usersComp%p del %@", + nr, h.priority, h.tag, h.disable, h.remove, + processStandardHandlersFirst, reversePriority, sortingAlgorithm, usersComparator, + h.delegate); + break; + default: + case 0: + CCLOG(@"N%3d Stnd pri%4d tag%4d dis%2d rem%2d handlersFirst%d revPrio%d sortAlgo%d usersComp%p", + nr, h.priority, h.tag, h.disable, h.remove, + processStandardHandlersFirst, reversePriority, sortingAlgorithm, usersComparator); + break; + } + break; + } // switch (delegateType) +} + +-(void) debugLog:(ccHandlersToDoType)type nr:(int)cnr handlerToDo:(CCHandlersToDo *)h formatType:(int)format +{ + switch (type) { + + case kCCAddTargetedHandler: + switch (format) { + case 1: + CCLOG(@"C%3d Trg pri%4d tag%4d dis%2d rem%2d swl%2d eS %02X hF%d rP%d sA%d uC%p %@", + cnr, h.handler.priority, h.handler.tag, h.handler.disable, h.handler.remove, + ((CCTargetedTouchHandler *) h.handler).swallowsTouches, + ((CCTargetedTouchHandler *) h.handler).enabledSelectors, + processStandardHandlersFirst,reversePriority, sortingAlgorithm, usersComparator, + h.handler.delegate); + break; + default: + case 0: + CCLOG(@"C%3d Trg pri%4d tag%4d dis%2d rem%2d swl%2d eS %02X hF%d rP%d sA%d uC%p", + cnr, h.handler.priority, h.handler.tag, h.handler.disable, h.handler.remove, + ((CCTargetedTouchHandler *) h.handler).swallowsTouches, + ((CCTargetedTouchHandler *) h.handler).enabledSelectors, + processStandardHandlersFirst, reversePriority, sortingAlgorithm, usersComparator); + break; + } + break; + + case kCCAddStandardHandler: + switch (format) { + case 1: + CCLOG(@"C%3d Stn pri%4d tag%4d dis%2d rem%2d hF%d rP%d sA%d uC%p %@", + cnr, h.handler.priority, h.handler.tag, h.handler.disable, h.handler.remove, + processStandardHandlersFirst, reversePriority, sortingAlgorithm, usersComparator, + h.handler.delegate); + break; + default: + case 0: + CCLOG(@"C%3d Stn pri%4d tag%4d dis%2d rem%2d hF%d rP%d sA%d uC%p", + cnr, h.handler.priority, h.handler.tag, h.handler.disable, h.handler.remove, + processStandardHandlersFirst, reversePriority, sortingAlgorithm, usersComparator); + break; + } + break; + } //switch (type) +} + +#pragma mark - +#pragma mark - alterTouchHandler + +-(void) fieldToAlter:(ccHandlerFieldName)fieldToAlter withValue:(int)v forHandler:(CCTouchHandler *)h type:(ccDispatcherDelegateType)delegateType action:(int *)a +{ + switch ( fieldToAlter ) { + case kCCDelegate: + break; + case kCCPriority: + case kCCPriorityToDo: + if ( h.priority != v ){ + if (!h.remove) { // otherwise no need it is gone soon + h.priority = v; + (*a)++; + } + } + break; + case kCCTag: + h.tag = v; + (*a)++;; + break; + case kCCDisable: + h.disable = v; + (*a)++; + break; + case kCCRemove: + case kCCRemoveToDo: + if (!h.remove) { // one way only, no undo of course + if (v) { + h.remove = YES; + (*a)++; + } + } + break; + case kCCSwallowsTouches: + if(delegateType == kCCTargeted){ + ((CCTargetedTouchHandler *) h).swallowsTouches = (BOOL)(v!=0); + (*a)++; + } + break; + case kCCNotRemoved: + if (!h.remove) + (*a)++; + break; + case kCCNone: // just counting all objects + (*a)++; + break; + case kCCDebug: + (*a)++; + [self debugLog:delegateType nr:(*a) handler:h formatType:v]; + break; + } +} + +-(void) fieldToAlter:(ccHandlerFieldName)fieldToAlter withValue:(int)v forToDoHandler:(CCHandlersToDo *)hToDo action:(int *)c +{ + switch ( fieldToAlter ){ + case kCCDelegate: + break; + case kCCPriority: + case kCCPriorityToDo: + if (hToDo.handler.priority != v ){ + if (!hToDo.handler.remove){ + hToDo.handler.priority = v; + (*c)++; + } + } + break; + case kCCTag: + hToDo.handler.tag = v; + (*c)++; + break; + case kCCDisable: + hToDo.handler.disable = v; + (*c)++; + break; + case kCCRemove: + case kCCRemoveToDo: + if (!hToDo.handler.remove) { + if ( v ) { // one way only, no undo of course + hToDo.handler.remove = YES; + (*c)++; + } + } + break; + case kCCSwallowsTouches: + if (hToDo.type == kCCAddTargetedHandler) { + ((CCTargetedTouchHandler *) hToDo.handler).swallowsTouches = (BOOL)(v!=0); + (*c)++; + } + break; + case kCCNotRemoved: + if (!hToDo.handler.remove) + (*c)++; + break; + case kCCNone: // counting all objects + (*c)++; + break; + case kCCDebug: + (*c)++; + [self debugLog:hToDo.type nr:(*c) handlerToDo:hToDo formatType:v]; + break; + } +} + +- (void) sortDelegates:(ccDispatcherDelegateType)type; // API +{ + switch(type){ + case kCCTargeted: actionToDo.targetedPriority = YES; break; + case kCCStandard: actionToDo.standardPriority = YES; break; } - for( CCTouchHandler *handler in standardHandlers ) { - if( handler.delegate == delegate ) { - [standardHandlers removeObject:handler]; + if (!locked) { // sorting can be done now (if not it will be done in the 'processCallbackRequestsToTheDispatcher' + [self forceSetPriority];} // priority flags are cleared here +} + +- (int) removeToDoDelegates:(ccDispatcherDelegateType)type; // API +{ + int ret = -1; + + if (!locked) { // removal can be done now (if not it will be done in the 'processCallbackRequestsToTheDispatcher' + + switch ( type ) { + case kCCTargeted: + ret = actionToDo.targetedRemoval; + [self forceRemoveOfMarkedHandlers:kCCTargeted nrOfObjects:actionToDo.targetedRemoval]; + actionToDo.targetedRemoval = 0; // removal flags are cleared here + break; + case kCCStandard: + ret = actionToDo.standardRemoval; + [self forceRemoveOfMarkedHandlers:kCCStandard nrOfObjects:actionToDo.standardRemoval]; + actionToDo.standardRemoval = 0; // removal flags are cleared here + break; + } + } + + return ret; +} + +-(void) actionProcessing:(ccHandlerFieldName)fieldToAlter type:(ccDispatcherDelegateType)delegateType action:(int)action +{ + switch(fieldToAlter) + { + case kCCDelegate: break; - } + case kCCPriority: + if (action) { + [self sortDelegates:delegateType]; + } + break; + case kCCPriorityToDo: + if (action) { + switch( delegateType ){ + case kCCTargeted: actionToDo.targetedPriority = YES; break; + case kCCStandard: actionToDo.standardPriority = YES; break; + } + }// sort will be done at the end of all callbacks or when 'sortDelegates' is issued + break; + case kCCTag: + break; + case kCCDisable: + break; + case kCCRemove: + if (action) { + switch ( delegateType ) { + case kCCTargeted: actionToDo.targetedRemoval += action; break; // accumulate number of removals + case kCCStandard: actionToDo.standardRemoval += action; break; // accumulate number of removals + } + if (!locked) { //removal can be done now; no accumulation from other remove calls + [self removeToDoDelegates:delegateType]; // removal flags are cleared here + } + } + break; + case kCCRemoveToDo: + if (action) { + switch ( delegateType ) { + case kCCTargeted: actionToDo.targetedRemoval += action; break; // accumulate number of removals + case kCCStandard: actionToDo.standardRemoval += action; break; // accumulate number of removals + } + } // removal will be done at the end of all callbacks or + break; + case kCCSwallowsTouches: + break; + case kCCNotRemoved: + break; + case kCCNone: + break; + case kCCDebug: + break; + } +} + +static BOOL eval(int v, ccOperators op, int arg) +{ + switch(op){ + case kCCFALSE: return NO; break; + case kCCTRUE: return YES; break; + case kCCNEQ: return (v != arg); break; + case kCCEQ: return (v == arg); break; + case kCCGE: return (v >= arg); break; + case kCCGT: return (v > arg); break; + case kCCLE: return (v <= arg); break; + case kCCLT: return (v < arg); break; + default: return NO; break; + } +} + +static ccOperators calcOp1(ccOperators compOp) +{ + switch(compOp){ // fast parsing does not depend on the order of 'ccOperators' + case kCCFALSE:case kCCTRUE:case kCCNEQ:case kCCEQ:case kCCGE:case kCCGT:case kCCLE:case kCCLT:return compOp;break; + case kCCGEAndLE:case kCCGEAndLT:case kCCGEOrLE:case kCCGEOrLT:return kCCGE;break; + case kCCGTAndLE:case kCCGTAndLT:case kCCGTOrLE:case kCCGTOrLT:return kCCGT;break; + case kCCLEAndGE:case kCCLEAndGT:case kCCLEOrGE:case kCCLEOrGT:return kCCLE;break; + case kCCLTAndGE:case kCCLTAndGT:case kCCLTOrGE:case kCCLTOrGT:return kCCLT;break; + default: return kCCFALSE; break; + } +} + +static BOOL isItAnd(ccOperators compOp) +{ + switch(compOp){ // fast parsing does not depend on the order of 'ccOperators' + case kCCFALSE:case kCCTRUE:case kCCNEQ:case kCCEQ:case kCCGE:case kCCGT:case kCCLE:case kCCLT:return NO;break; + case kCCGEAndLE:case kCCGEAndLT:case kCCGTAndLE:case kCCGTAndLT: + case kCCLEAndGE:case kCCLEAndGT:case kCCLTAndGE:case kCCLTAndGT:return YES;break; + case kCCGEOrLE:case kCCGEOrLT:case kCCGTOrLE:case kCCGTOrLT: + case kCCLEOrGE:case kCCLEOrGT:case kCCLTOrGE:case kCCLTOrGT:return NO;break; + default:return NO;break; + } +} + +static ccOperators calcOp3(ccOperators compOp) +{ + switch(compOp){ // fast parsing does not depend on the order of 'ccOperators' + case kCCFALSE:case kCCTRUE:case kCCNEQ:case kCCEQ:case kCCGE:case kCCGT:case kCCLE:case kCCLT:return kCCTRUE;break; + case kCCLEAndGE:case kCCLTAndGE:case kCCLEOrGE:case kCCLTOrGE:return kCCGE;break; + case kCCLEAndGT:case kCCLTAndGT:case kCCLEOrGT:case kCCLTOrGT:return kCCGT;break; + case kCCGEAndLE:case kCCGTAndLE:case kCCGEOrLE:case kCCGTOrLE:return kCCLE;break; + case kCCGEAndLT:case kCCGTAndLT:case kCCGEOrLT:case kCCGTOrLT:return kCCLT;break; + default:return kCCTRUE;break; } } --(void) removeDelegate:(id) delegate +static BOOL evaluate(int v, ccOperators op1, int v1, BOOL useAnd, ccOperators op3, int v2) { - if( delegate == nil ) + BOOL result1 = eval(v,op1,v1); + if (op3 == kCCTRUE) return result1; + + BOOL result3 = eval(v,op3,v2); + if (useAnd) return (result1 && result3); + else return (result1 || result3); // use OR +} + +// magic function: +-(int) alterTouchHandler:(ccDispatcherDelegateType)dType delegate:(id)delegate + fieldToSearch:(ccHandlerFieldName)searchField + arg1:(int)v1 + arg2:(int)v2 + operator:(ccOperators)op + fieldToAlter:(ccHandlerFieldName)fieldToAlter withValue:(int)nV +{ + int action = 0; // number of objects affected + + if ( (searchField == kCCDelegate) && (delegate == nil) ) { + return -1; // NSAssert(delegate != nil, @"Got nil touch delegate!"); + } + + ccOperators op1 = calcOp1(op); + BOOL useAnd = isItAnd(op); // if false use OR operator + ccOperators op3 = calcOp3(op); + + CCArray *array = [self arrayForType:dType]; // array for given handler's type + ccHandlersToDoType hToDoType = [self toDoAddType:dType]; + + CCTouchHandler *h; + CCARRAY_FOREACH(array, h) { + switch(searchField) { + case kCCDelegate: + if( h.delegate == delegate ) { + [self fieldToAlter:fieldToAlter withValue:nV forHandler:h type:dType action:&action]; + break; // delegate has been found + } + break; + case kCCPriority: + case kCCPriorityToDo: + if ( evaluate(h.priority, op1, v1, useAnd, op3, v2) ) { + [self fieldToAlter:fieldToAlter withValue:nV forHandler:h type:dType action:&action]; + } + break; + case kCCTag: + if ( evaluate(h.tag, op1, v1, useAnd, op3, v2) ) { + [self fieldToAlter:fieldToAlter withValue:nV forHandler:h type:dType action:&action]; + } + break; + case kCCDisable: + if ( evaluate(h.disable, op1, v1, useAnd, op3, v2) ) { + [self fieldToAlter:fieldToAlter withValue:nV forHandler:h type:dType action:&action]; + } + break; + case kCCRemove: + case kCCRemoveToDo: + if ( evaluate(h.remove, op1, v1, useAnd, op3, v2) ) { + [self fieldToAlter:fieldToAlter withValue:nV forHandler:h type:dType action:&action]; + } + break; + case kCCSwallowsTouches: + if ( dType == kCCTargeted ) { + if ( evaluate( ((CCTargetedTouchHandler*)h).swallowsTouches, op1, v1, useAnd, op3, v2) ) { + [self fieldToAlter:fieldToAlter withValue:nV forHandler:h type:dType action:&action]; + } + } + break; + case kCCNotRemoved: + if (!h.remove) + [self fieldToAlter:fieldToAlter withValue:nV forHandler:h type:dType action:&action]; + break; + case kCCNone: // for any value (for all value) no conditions checked + [self fieldToAlter:fieldToAlter withValue:nV forHandler:h type:dType action:&action]; + break; + case kCCDebug: + action++; [self debugLog:dType nr:action handler:h formatType:nV]; + break; + default: + CCLOG(@"alterTouchHandler:You must be kidding!"); + break; + + }// search + }//ccarray + + // handlersToDo array should be empty if we are NOT 'locked' + int callback = 0; // number of object affected in the callback ToDo array + CCHandlersToDo *hToDo; + CCARRAY_FOREACH(handlersToDo, hToDo) { + if ( hToDo.type != hToDoType ) // kCCAddTargetedHandler, kCCAddStandardHandler + continue; + switch(searchField) { + case kCCDelegate: + if( hToDo.handler.delegate == delegate ) { + [self fieldToAlter:fieldToAlter withValue:nV forToDoHandler:hToDo action:&callback]; + }// notice: all delegates are searched + break; + case kCCPriority: + case kCCPriorityToDo: + if ( evaluate(hToDo.handler.priority, op1, v1, useAnd, op3, v2) ) { + [self fieldToAlter:fieldToAlter withValue:nV forToDoHandler:hToDo action:&callback]; + } + break; + case kCCTag: + if ( evaluate(hToDo.handler.tag, op1, v1, useAnd, op3, v2) ) { + [self fieldToAlter:fieldToAlter withValue:nV forToDoHandler:hToDo action:&callback]; + } + break; + case kCCDisable: + if ( evaluate(hToDo.handler.disable, op1, v1, useAnd, op3, v2) ) { + [self fieldToAlter:fieldToAlter withValue:nV forToDoHandler:hToDo action:&callback]; + } + break; + case kCCRemove: + case kCCRemoveToDo: + if ( evaluate(hToDo.handler.remove, op1, v1, useAnd, op3, v2) ) { + [self fieldToAlter:fieldToAlter withValue:nV forToDoHandler:hToDo action:&callback]; + } + break; + case kCCSwallowsTouches: + if ( hToDo.type == kCCAddTargetedHandler ) { + if ( evaluate(((CCTargetedTouchHandler*)hToDo.handler).swallowsTouches, op1, v1, useAnd, op3, v2) ) { + [self fieldToAlter:fieldToAlter withValue:nV forToDoHandler:hToDo action:&callback]; + } + } + break; + case kCCNotRemoved: + if (!hToDo.handler.remove) + [self fieldToAlter:fieldToAlter withValue:nV forToDoHandler:hToDo action:&callback]; + break; + case kCCNone: // for any value (for all value) no conditions checked + [self fieldToAlter:fieldToAlter withValue:nV forToDoHandler:hToDo action:&callback]; + break; + case kCCDebug: + callback++; [self debugLog:hToDoType nr:callback handlerToDo:hToDo formatType:nV]; + break; + } // search + }//ccarray + + [self actionProcessing:fieldToAlter type:dType action:action]; + + return (action + callback); // number of handlers affected +} + +#pragma mark - +#pragma mark - Add Handlers + +-(void) forceAddHandler:(CCTouchHandler*)handler doNotSort:(int)doNotSort type:(ccDispatcherDelegateType)delegateType +{ + if (handler.remove) return; // if handler is marked for removal do not add it to the array + + CCArray *array = [self arrayForType:delegateType]; + + if ( doNotSort ) { + NSAssert( [array containsObject:handler] != YES, @"Delegate already added to touch dispatcher!"); + [array addObject:handler]; // add at the end return; + } - if( ! locked ) { - [self forceRemoveDelegate:delegate]; - } else { - [handlersToRemove addObject:delegate]; - toRemove = YES; + NSUInteger i = 0; + CCTouchHandler *h; + CCARRAY_FOREACH(array, h){ // search all array + + if ( usersComparator ) { + if ( usersComparator( & h, & handler ) == NSOrderedAscending ){ + i++; + } + } + else { + if (reversePriority) { // Descending order. Priority list looks like: 10, 5, 1 - 5, - 10, - 20 + + if ( h.priority > handler.priority ) { + i++; // count elements which have greater priority than given one + } + } + else{ // DEFAULT: Ascending order + if ( h.priority < handler.priority ) { // Priority list looks like: - 20, - 10, -5 , 1 , 5, 10 + i++; // count elements which have lesser priority than given one + } + } + } + + NSAssert( h.delegate != handler.delegate, @"Delegate already added to touch dispatcher."); } + + [array insertObject:handler atIndex:i]; // insert } -#pragma mark TouchDispatcher - removeAllDelegates +-(void) safelyAddHandler:(CCTouchHandler*)handler doNotSort:(int)yesOrNo type:(ccDispatcherDelegateType)delegateType +{ + ccHandlersToDoType toDoType = [self toDoAddType:delegateType]; + + CCHandlersToDo *todo = [[CCHandlersToDo alloc] init]; // autorelease could be used + + todo.type = toDoType; + todo.handler = handler; + todo.arg = yesOrNo; + + [handlersToDo addObject:todo]; + [todo release]; todo = nil; // no need when autorelease done +} --(void) forceRemoveAllDelegates -{ - [standardHandlers removeAllObjects]; - [targetedHandlers removeAllObjects]; +-(void) add:(id) handler doNotSort:(int)yesOrNo type:(ccDispatcherDelegateType) delegateType +{ + if (handler == nil ) + return; + + if ( locked ) { + [self safelyAddHandler:handler doNotSort:yesOrNo type:delegateType]; // safe in to do loop + } + else { + [self forceAddHandler:handler doNotSort:yesOrNo type:delegateType]; + } +} + +//---------------------- +// adding a delegate +//---------------------- + +-(void) addStandardDelegate:(id) delegate priority:(int)priority tag:(int)aTag disable:(int)yesOrNo doNotSort:(int)YN +{ + [self add:[CCStandardTouchHandler handlerWithDelegate:delegate priority:priority tag:aTag disable:yesOrNo] doNotSort:YN type:kCCStandard]; } --(void) removeAllDelegates + +-(void) addStandardDelegate:(id) delegate priority:(int)priority { - if( ! locked ) - [self forceRemoveAllDelegates]; - else - toQuit = YES; + [self addStandardDelegate:(id) delegate priority:priority tag:0 disable:NO doNotSort:NO]; } -#pragma mark Changing priority of added handlers +-(void) addTargetedDelegate:(id) delegate priority:(int)priority swallowsTouches:(BOOL)swallowsTouches tag:(int)aTag disable:(int)yesOrNo doNotSort:(int)YN +{ + [self add:[CCTargetedTouchHandler handlerWithDelegate:delegate priority:priority swallowsTouches:swallowsTouches tag:aTag disable:yesOrNo] doNotSort:YN type:kCCTargeted]; +} --(void) setPriority:(int) priority forDelegate:(id) delegate +-(void) addTargetedDelegate:(id) delegate priority:(int)priority swallowsTouches:(BOOL)swallowsTouches { - NSAssert(NO, @"Set priority no implemented yet. Don't forget to report this bug!"); -// if( delegate == nil ) -// [NSException raise:NSInvalidArgumentException format:@"Got nil touch delegate"]; -// -// CCTouchHandler *handler = nil; -// for( handler in touchHandlers ) -// if( handler.delegate == delegate ) break; -// -// if( handler == nil ) -// [NSException raise:NSInvalidArgumentException format:@"Touch delegate not found"]; -// -// if( handler.priority != priority ) { -// handler.priority = priority; -// -// [handler retain]; -// [touchHandlers removeObject:handler]; -// [self addHandler:handler]; -// [handler release]; -// } + [self addTargetedDelegate:delegate priority:priority swallowsTouches:swallowsTouches tag:0 disable:NO doNotSort:NO]; } +//---------------------------------------------------------------------- +// safe touch call-back getters and setters for internal control fields +//---------------------------------------------------------------------- +// API - touch callbacks safe +-(BOOL) locked +{ + return locked; +} + +- (void) setProcessStandardHandlersFirst:(BOOL)yesOrNo +{ + if (locked){ + actionToDo.processStandardHandlersFirstFlag = YES; + actionToDo.processStandardHandlersFirstArg = yesOrNo; + } + else{ + processStandardHandlersFirst = yesOrNo; + } +} +/* get - current/requested - order of processing */ +- (BOOL) processStandardHandlersFirst +{ + if (locked){ + if (actionToDo.processStandardHandlersFirstFlag){ + return actionToDo.processStandardHandlersFirstArg; + } + else{ + return processStandardHandlersFirst; + } + } + return processStandardHandlersFirst; +} // -// dispatch events -// --(void) touches:(NSSet*)touches withEvent:(UIEvent*)event withTouchType:(unsigned int)idx; +- (void) setSortingAlgorithm:(ccSortingAlgorithm)alg { - NSAssert(idx < 4, @"Invalid idx value"); + if (locked){ + actionToDo.sortingAlgorithmFlag = YES; + actionToDo.sortingAlgorithmArg = alg; + } + else{ + sortingAlgorithm = alg; + } +} +/* get - current/requested - sortingAlgorithm */ +- (ccSortingAlgorithm) sortingAlgorithm +{ + if (locked){ + if (actionToDo.sortingAlgorithmFlag){ + return actionToDo.sortingAlgorithmArg; + } + else{ + return sortingAlgorithm; + } + } + return sortingAlgorithm; +} + +- (void) setReversePriority:(BOOL)yesNo +{ + if (locked){ + actionToDo.reversePriorityFlag = YES; + actionToDo.reversePriorityArg = yesNo; + } + else{ + reversePriority = yesNo; + } +} +/* get - current/requested - reversePriority */ +- (BOOL) reversePriority +{ // it is up to user to call the sort at his convenience + if (locked){ + if (actionToDo.reversePriorityFlag){ + return actionToDo.reversePriorityArg; + } + else{ + return reversePriority; + } + } + return reversePriority; +} + +- (void) setUsersComparator:(int(*)(const void *, const void *))comparator; +{ // it is up to user to call the sort at his convenience + if (locked){ + actionToDo.usersComparatorFlag = YES; + actionToDo.usersComparatorArg = comparator; + } + else{ + usersComparator = comparator; + } +} +/* get - current/requested usersComparator */ +- (int(*)(const void *, const void *)) usersComparator +{ + if (locked){ + if (actionToDo.usersComparatorFlag){ + return actionToDo.usersComparatorArg; + } + else{ + return usersComparator; + } + } + return usersComparator; +} - id mutableTouches; - locked = YES; +#pragma mark TouchDispatcher - retrieveField + +// returns value of the field or NSNotFound when delegate does not exist +- (int) retrieveField:(ccHandlerFieldName)field delegate:(id)delegate type:(ccDispatcherDelegateType)delegateType // power function +{ + NSAssert(delegate != nil, @"Got nil touch delegate!"); - // optimization to prevent a mutable copy when it is not necessary - unsigned int targetedHandlersCount = [targetedHandlers count]; - unsigned int standardHandlersCount = [standardHandlers count]; - BOOL needsMutableSet = (targetedHandlersCount && standardHandlersCount); + BOOL notFound = YES; + int value = CC_SEARCH_NOT_SUCCESSFUL; + + CCArray *array = [self arrayForType:delegateType]; + ccHandlersToDoType type = [self toDoAddType:delegateType]; - mutableTouches = (needsMutableSet ? [touches mutableCopy] : touches); + CCTouchHandler *handler; + CCARRAY_FOREACH(array, handler) { + + if ( handler.delegate == delegate ) { + + notFound = NO; + + switch ( field ) { + case kCCDelegate: + value = YES; + break; + case kCCPriority: + case kCCPriorityToDo: + value = handler.priority; + break; + case kCCTag: + value = handler.tag; + break; + case kCCDisable: + value = handler.disable; + break; + case kCCRemove: + case kCCRemoveToDo: + value = handler.remove; + break; + case kCCSwallowsTouches: + if(delegateType == kCCTargeted){ + value = ((CCTargetedTouchHandler *) handler).swallowsTouches;} + break; + default: + break; + + } + break; // break the loop if delegate had been found + }//if + }//ccarray + + CCHandlersToDo *handlerToDo; + CCARRAY_FOREACH(handlersToDo, handlerToDo) { + + if( handlerToDo.handler.delegate == delegate ) { + + if ( handlerToDo.type == type ) { + + notFound = NO; + + switch ( field ){ + case kCCDelegate: + value = YES; + break; + case kCCPriority: + case kCCPriorityToDo: + value = handlerToDo.handler.priority; + break; + case kCCTag: + value = handlerToDo.handler.tag; + break; + case kCCDisable: + value = handlerToDo.handler.disable; + break; + case kCCRemove: + case kCCRemoveToDo: + value = handlerToDo.handler.remove; + break; + case kCCSwallowsTouches: + if(type == kCCAddTargetedHandler){ + value = ((CCTargetedTouchHandler *) handlerToDo.handler).swallowsTouches;} + break; + default: + break; + } + }//if + }//if + }//ccarray + + if (notFound) CCLOG(@"TouchHandler:delegate not found!"); + return value; +} - struct ccTouchHandlerHelperData helper = handlerHelperData[idx]; - // - // process the target handlers 1st - // +//--------------------------------- +// counting delegates +//--------------------------------- + +- (int) countDelegatesUsage:(ccDispatcherDelegateType)type +{ + return ([self alterTouchHandler:type delegate:nil + fieldToSearch:kCCNone arg1:CC_UNUSED_ARGUMENT arg2:CC_UNUSED_ARGUMENT operator:kCCTRUE fieldToAlter:kCCNotRemoved withValue:CC_UNUSED_ARGUMENT]); +} + +-(int) countDelegateUsage:(id)delegate type:(ccDispatcherDelegateType)type +{ + return ([self alterTouchHandler:type delegate:delegate + fieldToSearch:kCCDelegate arg1:CC_UNUSED_ARGUMENT arg2:CC_UNUSED_ARGUMENT operator:kCCTRUE fieldToAlter:kCCNotRemoved withValue:CC_UNUSED_ARGUMENT]); +} + +-(int) countTagUsage:(int)tag type:(ccDispatcherDelegateType)type +{ + return ([self alterTouchHandler:type delegate:nil + fieldToSearch:kCCTag arg1:tag arg2:tag operator:kCCEQ fieldToAlter:kCCNotRemoved withValue:CC_UNUSED_ARGUMENT]); +} + +- (int) countPriorityUsage:(int)priority type:(ccDispatcherDelegateType)type +{ + return ([self alterTouchHandler:type delegate:nil + fieldToSearch:kCCPriority arg1:priority arg2:priority operator:kCCEQ fieldToAlter:kCCNotRemoved withValue:CC_UNUSED_ARGUMENT]); +} + +- (int) countDisableUsage:(int)aDisable type:(ccDispatcherDelegateType)type +{ + return ([self alterTouchHandler:type delegate:nil + fieldToSearch:kCCDisable arg1:aDisable arg2:aDisable operator:kCCEQ fieldToAlter:kCCNotRemoved withValue:CC_UNUSED_ARGUMENT]); +} + +- (int) countFieldUsage:(ccHandlerFieldName)field fieldValue:(int)value type:(ccDispatcherDelegateType)type // power function +{ + return ([self alterTouchHandler:type delegate:nil + fieldToSearch:field arg1:value arg2:value operator:kCCEQ fieldToAlter:kCCNotRemoved withValue:CC_UNUSED_ARGUMENT]); +} + +//------------------------------------------------------------------------------- +// retrieval of the field value +// Function returns value of the field or NSNotFound when delegate does not exist +// ------------------------------------------------------------------------------ + +// helper functions based on the generic 'retrieveField' function + +-(int) retrievePriorityField:(id)delegate type:(ccDispatcherDelegateType)type +{ + return ( [self retrieveField:kCCPriority delegate:delegate type:type] ); +} +// returns value of the field or NSNotFound when delegate does not exist +-(int) retrieveTagField:(id)delegate type:(ccDispatcherDelegateType)type +{ + return ( [self retrieveField:kCCTag delegate:delegate type:type] ); +} +// returns value of the field or NSNotFound when delegate does not exist +-(int) retrieveDisableField:(id)delegate type:(ccDispatcherDelegateType)type +{ + return ( [self retrieveField:kCCDisable delegate:delegate type:type] ); +} + +//-------------------------------- +// disabling of the delegate/s +//-------------------------------- + +#pragma mark - +#pragma mark - disable/enable particular touch delegate or group + +- (int) disableDelegate:(id)delegate disable:(int)yesOrNo type:(ccDispatcherDelegateType)type +{ + return ( [self alterTouchHandler:type delegate:delegate fieldToSearch:kCCDelegate + arg1:CC_UNUSED_ARGUMENT arg2:CC_UNUSED_ARGUMENT operator:kCCTRUE fieldToAlter:kCCDisable withValue:yesOrNo] ); +} + +-(int) disableAllDelegates:(int)yesOrNo type:(ccDispatcherDelegateType)type +{ + return ( [self alterTouchHandler:type delegate:nil fieldToSearch:kCCNone + arg1:CC_UNUSED_ARGUMENT arg2:CC_UNUSED_ARGUMENT operator:kCCTRUE fieldToAlter:kCCDisable withValue:yesOrNo]); +} + +- (int) disableDelegatesWithTag:(int)tag disable:(int) yesOrNo type:(ccDispatcherDelegateType)type +{ + return ( [self alterTouchHandler:type delegate:nil fieldToSearch:kCCTag + arg1:tag arg2:tag operator:kCCEQ fieldToAlter:kCCDisable withValue:yesOrNo] ); +} + +- (int) disableDelegatesWithPriority:(int) priority disable:(int) yesOrNo type:(ccDispatcherDelegateType)type +{ + return ( [self alterTouchHandler:type delegate:nil fieldToSearch:kCCPriority + arg1:priority arg2:priority operator:kCCEQ fieldToAlter:kCCDisable withValue:yesOrNo] ); +} + +-(int) disableRemovedDelegates:(int)yesOrNo type:(ccDispatcherDelegateType)type +{ + return ( [self alterTouchHandler:type delegate:nil fieldToSearch:kCCRemove + arg1:YES arg2:YES operator:kCCEQ fieldToAlter:kCCDisable withValue:yesOrNo] ); +} + +- (int) disableDelegatesWithField:(ccHandlerFieldName)fieldName arg1:(int)leftEndPoint arg2:(int)rightEndPoint operator:(ccOperators)op + disable:(int)yesOrNo type:(ccDispatcherDelegateType)type +{ + return ( [self alterTouchHandler:type delegate:nil fieldToSearch:fieldName + arg1:leftEndPoint arg2:rightEndPoint operator:op fieldToAlter:kCCDisable withValue:yesOrNo] ); +} + +//--------------------------------- +// removal of the delegate/s +//--------------------------------- +#pragma mark - +#pragma mark - removeDelegate + +-(void) removeDelegate:(id) delegate // since v0.8.0 +{ + [self removeDelegate:delegate delay:NO type:kCCTargeted]; + [self removeDelegate:delegate delay:NO type:kCCStandard]; +} + +-(int) removeDelegate:(id)delegate delay:(BOOL)yesOrNo type:(ccDispatcherDelegateType)delegateType +{ + ccHandlerFieldName r = kCCRemove; if (yesOrNo) r = kCCRemoveToDo; + return ([self alterTouchHandler:delegateType delegate:delegate fieldToSearch:kCCDelegate + arg1:CC_UNUSED_ARGUMENT arg2:CC_UNUSED_ARGUMENT operator:kCCTRUE fieldToAlter:r withValue:YES]); +} + +- (int) removeDelegatesWithTag:(int)tag delay:(BOOL)yesOrNo type:(ccDispatcherDelegateType)delegateType +{ + ccHandlerFieldName r = kCCRemove; if (yesOrNo) r = kCCRemoveToDo; + return ([self alterTouchHandler:delegateType delegate:nil fieldToSearch:kCCTag + arg1:tag arg2:tag operator:kCCEQ fieldToAlter:r withValue:YES]); +} + +- (int) removeDelegatesWithPriority:(int)priority delay:(BOOL)yesOrNo type:(ccDispatcherDelegateType)delegateType +{ + ccHandlerFieldName r = kCCRemove; if (yesOrNo) r = kCCRemoveToDo; + return ([self alterTouchHandler:delegateType delegate:nil fieldToSearch:kCCPriority + arg1:priority arg2:priority operator:kCCEQ fieldToAlter:r withValue:YES]); +} + +// Only For Eagles - Power API Function +- (int) removeDelegatesWithField:(ccHandlerFieldName)fieldToSearch arg1:(int)leftV arg2:(int)rightV operator:(ccOperators)op + delay:(BOOL)yesOrNo type:(ccDispatcherDelegateType)delegateType +{ + if (fieldToSearch == kCCDelegate) return -1; // user cannot search this field + + ccHandlerFieldName r = kCCRemove; if (yesOrNo) r = kCCRemoveToDo; + return ([self alterTouchHandler:delegateType delegate:nil fieldToSearch:fieldToSearch + arg1:leftV arg2:rightV operator:op fieldToAlter:r withValue:YES]); +} + +//------------------------------------ +// setting value for a delegate field +//------------------------------------ + +-(void) setPriority:(int)priority forDelegate:(id)delegate /** since v1.0 obsolete */ +{ + [self setPriority:priority delegate:delegate delay:NO type:kCCTargeted]; + [self setPriority:priority delegate:delegate delay:NO type:kCCStandard]; +} + +-(int) setPriority:(int)newValue delegate:(id)delegate delay:(BOOL)yesOrNo type:(ccDispatcherDelegateType)type; +{ + ccHandlerFieldName p = kCCPriority; if (yesOrNo) p = kCCPriorityToDo; + return [self alterTouchHandler:type delegate:delegate fieldToSearch:kCCDelegate + arg1:CC_UNUSED_ARGUMENT arg2:CC_UNUSED_ARGUMENT operator:kCCTRUE fieldToAlter:p withValue:newValue]; +} + +- (int) setTag:(int)newValue delegate:(id)delegate type:(ccDispatcherDelegateType)type +{ + return [self alterTouchHandler:type delegate:delegate fieldToSearch:kCCDelegate + arg1:CC_UNUSED_ARGUMENT arg2:CC_UNUSED_ARGUMENT operator:kCCTRUE fieldToAlter:kCCTag withValue:newValue]; +} + +- (int) setDisable:(int)newValue delegate:(id)delegate type:(ccDispatcherDelegateType)type +{ + return [self alterTouchHandler:type delegate:delegate fieldToSearch:kCCDelegate + arg1:CC_UNUSED_ARGUMENT arg2:CC_UNUSED_ARGUMENT operator:kCCTRUE fieldToAlter:kCCDisable withValue:newValue]; +} + +- (int) setRemove:(id)delegate delay:(BOOL)yesOrNo type:(ccDispatcherDelegateType)type +{ + ccHandlerFieldName r = kCCRemove; if (yesOrNo) r = kCCRemoveToDo; + return [self alterTouchHandler:type delegate:delegate fieldToSearch:kCCDelegate + arg1:CC_UNUSED_ARGUMENT arg2:CC_UNUSED_ARGUMENT operator:kCCTRUE fieldToAlter:r withValue:YES]; +} + +// generic power function +- (int) setField:(ccHandlerFieldName)field newValue:(int)newValue delegate:(id)delegate type:(ccDispatcherDelegateType)type +{ + return ([self alterTouchHandler:type delegate:delegate fieldToSearch:kCCDelegate + arg1:CC_UNUSED_ARGUMENT arg2:CC_UNUSED_ARGUMENT operator:kCCTRUE fieldToAlter:field withValue:newValue]); +} + +//------------------------------------------------------------------------------------------------ +// setting new value for a delegates specific field conditional on the value of other(same) field +//------------------------------------------------------------------------------------------------ +- (int) setTagForPriority:(int)priority newTag:(int)value type:(ccDispatcherDelegateType)delegateType +{ + return ([self alterTouchHandler:delegateType delegate:nil + fieldToSearch:kCCPriority arg1:priority arg2:priority operator:kCCEQ fieldToAlter:kCCTag withValue:value]); +} + +- (int) setPriorityForTag:(int)tag newPriority:(int)value delay:(BOOL)yesOrNo type:(ccDispatcherDelegateType)delegateType +{ + ccHandlerFieldName p = kCCPriority; if (yesOrNo) p = kCCPriorityToDo; + return ([self alterTouchHandler:delegateType delegate:nil + fieldToSearch:kCCTag arg1:tag arg2:tag operator:kCCEQ fieldToAlter:p withValue:value]); +} + +/** Only For Eagles - Power Functions: */ +-(int) setDelegatesField:(ccHandlerFieldName)field newValue:(int)newValue + ifField:(ccHandlerFieldName)fieldToSearch arg1:(int)leftEndPoint arg2:(int)rightEndPoint operator:(ccOperators)op + type:(ccDispatcherDelegateType)type +{ + return ([self alterTouchHandler:type delegate:nil fieldToSearch:fieldToSearch + arg1:leftEndPoint arg2:rightEndPoint operator:op fieldToAlter:field withValue:newValue]); +} +//------------------------------------------------------------------------------------------------ + +- (int) printDebugLog:(int)format type:(ccDispatcherDelegateType)type // API +{ + int count = 0; + switch(type){ + case kCCTargeted: + count = [self setDelegatesField:kCCDebug newValue:format ifField:kCCNone + arg1:CC_UNUSED_ARGUMENT arg2:CC_UNUSED_ARGUMENT operator:kCCTRUE type:type]; + break; + case kCCStandard: + count = [self setDelegatesField:kCCDebug newValue:format ifField:kCCNone + arg1:CC_UNUSED_ARGUMENT arg2:CC_UNUSED_ARGUMENT operator:kCCTRUE type:type]; + break; + } + return count; +} + +- (int) printDebugLog:(int)format afterEvents:(BOOL)after type:(ccDispatcherDelegateType)type; // API +{ + if (!after || !locked) { + return ( [self printDebugLog:format type:type] ); + } + // after && locked + + switch(type){ + case kCCTargeted: actionToDo.targetedDebugLogFlag = YES; actionToDo.targetedDebugLogArg = format; break; + case kCCStandard: actionToDo.standardDebugLogFlag = YES; actionToDo.standardDebugLogArg = format; break; + } + return -1; +} + +-(void) processCallbackRequestsToTheDispatcher +{ + // check if we need to change the order of processing: + if (actionToDo.processStandardHandlersFirstFlag) { + processStandardHandlersFirst = actionToDo.processStandardHandlersFirstArg; + actionToDo.processStandardHandlersFirstFlag = NO; + } + // check if we need to change the sortingAlgorithm + if (actionToDo.sortingAlgorithmFlag) { + sortingAlgorithm = actionToDo.sortingAlgorithmArg; + actionToDo.sortingAlgorithmFlag = NO; + } + // check if we need to change the priority order + if (actionToDo.reversePriorityFlag){ + reversePriority = actionToDo.reversePriorityArg; + actionToDo.reversePriorityFlag = NO; + } + // check if we need to change the user's 'usersComparator' + if (actionToDo.usersComparatorFlag){ + usersComparator = actionToDo.usersComparatorArg; + actionToDo.usersComparatorFlag = NO; + } + + // -- handle priority change -- + [self forceSetPriority]; + //----------------------------- + + // print debug log + if (actionToDo.targetedDebugLogFlag){ + [self printDebugLog:actionToDo.targetedDebugLogArg type:kCCTargeted]; + actionToDo.targetedDebugLogFlag = NO; + } + if (actionToDo.standardDebugLogFlag){ + [self printDebugLog:actionToDo.standardDebugLogArg type:kCCStandard]; + actionToDo.standardDebugLogFlag = NO; + } +} + +#pragma mark TouchDispatcher - safeProcessing + +-(void) safeProcessing // process messages to the Dispatcher sent by user's touch callbacks +{ + // -- remove marked for removal delegates -- + [self forceRemoveMarkedDelegates]; + //------------------------------------------ + + CCHandlersToDo *todo; + CCARRAY_FOREACH(handlersToDo, todo) { + switch (todo.type) { + case kCCAddTargetedHandler: + [self forceAddHandler:todo.handler doNotSort:todo.arg type:kCCTargeted]; + break; + case kCCAddStandardHandler: + [self forceAddHandler:todo.handler doNotSort:todo.arg type:kCCStandard]; + break; + default: + break; + } + } + [handlersToDo removeAllObjects]; + + // -- process deleyed requests from user's touch callbacks -- + [self processCallbackRequestsToTheDispatcher]; + //------------------------------------------------------------ +} + +#pragma mark - +#pragma mark TouchDispatcher - Process Targeted Handlers + +- (void) processTargetedHandlers:(NSSet*)touches withEvent:(UIEvent*)event withTouchType:(unsigned int)idx +{ + CCTargetedTouchHandler *handler; if( targetedHandlersCount > 0 ) { for( UITouch *touch in touches ) { - for(CCTargetedTouchHandler *handler in targetedHandlers) { + CCARRAY_FOREACH(targetedHandlers, handler) { // speed is critical here + + if ( handler.disable ) continue; // handlers marked for removal are serviced BOOL claimed = NO; if( idx == kCCTouchBegan ) { @@ -249,7 +1422,7 @@ -(void) touches:(NSSet*)touches withEvent:(UIEvent*)event withTouchType:(unsigne if( helper.type & (kCCTouchSelectorCancelledBit | kCCTouchSelectorEndedBit) ) [handler.claimedTouches removeObject:touch]; } - + if( claimed && handler.swallowsTouches ) { if( needsMutableSet ) [mutableTouches removeObject:touch]; @@ -257,46 +1430,59 @@ -(void) touches:(NSSet*)touches withEvent:(UIEvent*)event withTouchType:(unsigne } } } - } - - // - // process standard handlers 2nd - // + } +} + +#pragma mark TouchDispatcher - Process Standard Handlers + +- (void) processStandardHandlers:(UIEvent*)event +{ + CCTouchHandler *handler; if( standardHandlersCount > 0 && [mutableTouches count]>0 ) { - for( CCTouchHandler *handler in standardHandlers ) { + CCARRAY_FOREACH(standardHandlers, handler) { + if ( handler.disable ) continue; // handlers marked for removal are serviced (default) if( handler.enabledSelectors & helper.type ) [handler.delegate performSelector:helper.touchesSel withObject:mutableTouches withObject:event]; } - } - if( needsMutableSet ) - [mutableTouches release]; + } +} + +#pragma mark TouchDispatcher - touches - dispatch events! + +-(void) touches:(NSSet*)touches withEvent:(UIEvent*)event withTouchType:(unsigned int)idx +{ + NSAssert(idx < 4, @"Invalid idx value"); + + locked = YES; // processing of the touch callbacks is in progress + + // optimization to prevent a mutable copy when it is not necessary + targetedHandlersCount = [targetedHandlers count]; + standardHandlersCount = [standardHandlers count]; + needsMutableSet = (targetedHandlersCount && standardHandlersCount); + + mutableTouches = (needsMutableSet ? [touches mutableCopy] : touches); // copy is expensive + + helper = handlerHelperData[idx]; // - // Optimization. To prevent a [handlers copy] which is expensive - // the add/removes/quit is done after the iterations + // processing touches // - locked = NO; - if( toRemove ) { - toRemove = NO; - for( id delegate in handlersToRemove ) - [self forceRemoveDelegate:delegate]; - [handlersToRemove removeAllObjects]; - } - if( toAdd ) { - toAdd = NO; - for( CCTouchHandler *handler in handlersToAdd ) { - Class targetedClass = [CCTargetedTouchHandler class]; - if( [handler isKindOfClass:targetedClass] ) - [self forceAddHandler:handler array:targetedHandlers]; - else - [self forceAddHandler:handler array:standardHandlers]; - } - [handlersToAdd removeAllObjects]; + if ( processStandardHandlersFirst ) { + [self processStandardHandlers:event]; + [self processTargetedHandlers:touches withEvent:event withTouchType:idx]; } - if( toQuit ) { - toQuit = NO; - [self forceRemoveAllDelegates]; + else{ // this is the default order of the event processing + [self processTargetedHandlers:touches withEvent:event withTouchType:idx]; + [self processStandardHandlers:event]; } + + if ( needsMutableSet ) + [mutableTouches release]; + + locked = NO; // processing of the touch callbacks is done + + // all critical operations are done after touch callback processing loop is finished + [self safeProcessing]; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event @@ -304,6 +1490,7 @@ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event if( dispatchEvents ) [self touches:touches withEvent:event withTouchType:kCCTouchBegan]; } + - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { if( dispatchEvents ) @@ -321,6 +1508,24 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event if( dispatchEvents ) [self touches:touches withEvent:event withTouchType:kCCTouchCancelled]; } + +@end + + +#pragma mark - +#pragma mark CCHandlersToDo + +@implementation CCHandlersToDo + +@synthesize type = type_; +@synthesize handler = handler_; +@synthesize arg = arg_; + +-(void) dealloc +{ + [handler_ release]; + [super dealloc]; +} @end #endif // __IPHONE_OS_VERSION_MAX_ALLOWED diff --git a/libs/cocos2d/Platforms/iOS/CCTouchHandler.h b/libs/cocos2d/Platforms/iOS/CCTouchHandler.h index 31a3e36..5b7b207 100644 --- a/libs/cocos2d/Platforms/iOS/CCTouchHandler.h +++ b/libs/cocos2d/Platforms/iOS/CCTouchHandler.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2009 Valentin Milea + * Copyright (c) 2011 Samuel J. Grabski * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -41,17 +42,27 @@ /** CCTouchHandler Object than contains the delegate and priority of the event handler. -*/ + */ @interface CCTouchHandler : NSObject { id delegate; int priority; + int tag; // similar to CCNode tag + int disable; // allows fast disabling: default NO, enabled + BOOL remove; // if (!=0) object marked for removal (allows fast removal) ccTouchSelectorFlag enabledSelectors_; } /** delegate */ @property(nonatomic, readwrite, retain) id delegate; /** priority */ -@property(nonatomic, readwrite) int priority; // default 0 +@property(nonatomic, readwrite) int priority; // default 0 +/** tag */ +@property(nonatomic, readwrite) int tag; // default 0 +/** disable */ +@property(nonatomic, readwrite) int disable; // default 0; NO +/** remove */ +@property(nonatomic, readwrite) BOOL remove; // default NO + /** enabled selectors */ @property(nonatomic,readwrite) ccTouchSelectorFlag enabledSelectors; @@ -59,6 +70,11 @@ + (id)handlerWithDelegate:(id)aDelegate priority:(int)priority; /** initializes a TouchHandler with a delegate and a priority */ - (id)initWithDelegate:(id)aDelegate priority:(int)priority; + +/** allocates a TouchHandler with a delegate, priority, tag and a disable flag */ ++ (id)handlerWithDelegate:(id)aDelegate priority:(int)aPriority tag:(int)aTag disable:(int)yesOrNo; +/** initializes a TouchHandler with a delegate, priority tag and a disable flag */ +- (id)initWithDelegate:(id)aDelegate priority:(int)aPriority tag:(int)aTag disable:(int)yesOrNo; @end /** CCStandardTouchHandler @@ -83,11 +99,23 @@ /** MutableSet that contains the claimed touches */ @property(nonatomic, readonly) NSMutableSet *claimedTouches; -/** allocates a TargetedTouchHandler with a delegate, a priority and whether or not it swallows touches or not */ +/** allocates a TargetedTouchHandler with a delegate, a priority and whether or not it swallows touches or not + tag = 0; disabled = NO + */ + (id)handlerWithDelegate:(id) aDelegate priority:(int)priority swallowsTouches:(BOOL)swallowsTouches; +/** allocates a TargetedTouchHandler with a delegate, a priority and whether or not it swallows touches or not + allows to set tag and disabled flag + */ ++ (id)handlerWithDelegate:(id) aDelegate priority:(int)priority swallowsTouches:(BOOL)swallowsTouches + tag:(int)aTag disable:(int)yesOrNo; /** initializes a TargetedTouchHandler with a delegate, a priority and whether or not it swallows touches or not */ - (id)initWithDelegate:(id) aDelegate priority:(int)priority swallowsTouches:(BOOL)swallowsTouches; +/** initializes a TargetedTouchHandler with a delegate, a priority and whether or not it swallows touches or not + allows to set tag and disabled flag + */ +- (id)initWithDelegate:(id) aDelegate priority:(int)priority swallowsTouches:(BOOL)swallowsTouches + tag:(int)aTag disable:(int)yesOrNo; @end #endif // __IPHONE_OS_VERSION_MAX_ALLOWED diff --git a/libs/cocos2d/Platforms/iOS/CCTouchHandler.m b/libs/cocos2d/Platforms/iOS/CCTouchHandler.m index a52103b..233417b 100644 --- a/libs/cocos2d/Platforms/iOS/CCTouchHandler.m +++ b/libs/cocos2d/Platforms/iOS/CCTouchHandler.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2009 Valentin Milea + * Copyright (c) 2011 Samuel J. Grabski * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -43,27 +44,38 @@ #pragma mark TouchHandler @implementation CCTouchHandler -@synthesize delegate, priority; -@synthesize enabledSelectors=enabledSelectors_; +@synthesize delegate, priority, tag, disable, remove; +@synthesize enabledSelectors = enabledSelectors_; ++ (id)handlerWithDelegate:(id) aDelegate priority:(int)aPriority tag:(int)aTag disable:(int)yesOrNo +{ + return [[[self alloc] initWithDelegate:aDelegate priority:aPriority tag:aTag disable:yesOrNo] autorelease]; +} + (id)handlerWithDelegate:(id) aDelegate priority:(int)aPriority { - return [[[self alloc] initWithDelegate:aDelegate priority:aPriority] autorelease]; + return [[[self alloc] initWithDelegate:aDelegate priority:aPriority tag:0 disable:NO] autorelease]; } -- (id)initWithDelegate:(id) aDelegate priority:(int)aPriority +- (id)initWithDelegate:(id) aDelegate priority:(int)aPriority tag:(int)aTag disable:(int)yesOrNo { NSAssert(aDelegate != nil, @"Touch delegate may not be nil"); if ((self = [super init])) { self.delegate = aDelegate; priority = aPriority; + tag = aTag; + disable = yesOrNo; + remove = NO; enabledSelectors_ = 0; } return self; } +- (id)initWithDelegate:(id) aDelegate priority:(int)aPriority{ + return ( [self initWithDelegate:aDelegate priority:aPriority tag:0 disable:NO] ); +} + - (void)dealloc { CCLOGINFO(@"cocos2d: deallocing %@", self); [delegate release]; @@ -74,20 +86,26 @@ - (void)dealloc { #pragma mark - #pragma mark StandardTouchHandler @implementation CCStandardTouchHandler --(id) initWithDelegate:(id)del priority:(int)pri + +-(id) initWithDelegate:(id)aDelegate priority:(int)aPriority tag:(int)aTag disable:(int)yesOrNo { - if( (self=[super initWithDelegate:del priority:pri]) ) { - if( [del respondsToSelector:@selector(ccTouchesBegan:withEvent:)] ) + if( (self=[super initWithDelegate:aDelegate priority:aPriority tag:aTag disable:yesOrNo]) ) { + if( [aDelegate respondsToSelector:@selector(ccTouchesBegan:withEvent:)] ) enabledSelectors_ |= kCCTouchSelectorBeganBit; - if( [del respondsToSelector:@selector(ccTouchesMoved:withEvent:)] ) + if( [aDelegate respondsToSelector:@selector(ccTouchesMoved:withEvent:)] ) enabledSelectors_ |= kCCTouchSelectorMovedBit; - if( [del respondsToSelector:@selector(ccTouchesEnded:withEvent:)] ) + if( [aDelegate respondsToSelector:@selector(ccTouchesEnded:withEvent:)] ) enabledSelectors_ |= kCCTouchSelectorEndedBit; - if( [del respondsToSelector:@selector(ccTouchesCancelled:withEvent:)] ) + if( [aDelegate respondsToSelector:@selector(ccTouchesCancelled:withEvent:)] ) enabledSelectors_ |= kCCTouchSelectorCancelledBit; } return self; } + +-(id) initWithDelegate:(id)aDelegate priority:(int)aPriority +{ + return ([self initWithDelegate:aDelegate priority:aPriority tag:0 disable:NO]); +} @end #pragma mark - @@ -101,14 +119,18 @@ @implementation CCTargetedTouchHandler @synthesize swallowsTouches, claimedTouches; -+ (id)handlerWithDelegate:(id)aDelegate priority:(int)priority swallowsTouches:(BOOL)swallow ++ (id)handlerWithDelegate:(id)aDelegate priority:(int)aPriority swallowsTouches:(BOOL)swallow tag:(int)aTag disable:(int)yesOrNo { - return [[[self alloc] initWithDelegate:aDelegate priority:priority swallowsTouches:swallow] autorelease]; + return [[[self alloc] initWithDelegate:aDelegate priority:aPriority swallowsTouches:swallow tag:aTag disable:yesOrNo] autorelease]; +} ++ (id)handlerWithDelegate:(id)aDelegate priority:(int)aPriority swallowsTouches:(BOOL)swallow +{ + return [[[self alloc] initWithDelegate:aDelegate priority:aPriority swallowsTouches:swallow tag:0 disable:NO] autorelease]; } -- (id)initWithDelegate:(id)aDelegate priority:(int)aPriority swallowsTouches:(BOOL)swallow +- (id)initWithDelegate:(id)aDelegate priority:(int)aPriority swallowsTouches:(BOOL)swallow tag:(int)aTag disable:(int)yesOrNo { - if ((self = [super initWithDelegate:aDelegate priority:aPriority])) { + if ((self = [super initWithDelegate:aDelegate priority:aPriority tag:aTag disable:yesOrNo ])) { claimedTouches = [[NSMutableSet alloc] initWithCapacity:2]; swallowsTouches = swallow; @@ -125,11 +147,15 @@ - (id)initWithDelegate:(id)aDelegate priority:(int)aPriority swallowsTouches:(BO return self; } +- (id)initWithDelegate:(id)aDelegate priority:(int)aPriority swallowsTouches:(BOOL)swallow +{ + return( [self initWithDelegate:aDelegate priority:aPriority swallowsTouches:swallow tag:0 disable:NO] ); +} + - (void)dealloc { [claimedTouches release]; [super dealloc]; } @end - #endif // __IPHONE_OS_VERSION_MAX_ALLOWED \ No newline at end of file diff --git a/libs/cocos2d/Platforms/iOS/EAGLView.h b/libs/cocos2d/Platforms/iOS/EAGLView.h old mode 100755 new mode 100644 index fd41c5e..3b6c2f3 --- a/libs/cocos2d/Platforms/iOS/EAGLView.h +++ b/libs/cocos2d/Platforms/iOS/EAGLView.h @@ -152,4 +152,4 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. - (CGRect) convertRectFromViewToSurface:(CGRect)rect; @end -#endif // __IPHONE_OS_VERSION_MAX_ALLOWED \ No newline at end of file +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED diff --git a/libs/cocos2d/Platforms/iOS/EAGLView.m b/libs/cocos2d/Platforms/iOS/EAGLView.m old mode 100755 new mode 100644 index 39dcdb6..5303828 --- a/libs/cocos2d/Platforms/iOS/EAGLView.m +++ b/libs/cocos2d/Platforms/iOS/EAGLView.m @@ -185,7 +185,6 @@ -(BOOL) setupSurfaceWithSharegroup:(EAGLSharegroup*)sharegroup return NO; context_ = [renderer_ context]; - [context_ renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:eaglLayer]; discardFramebufferSupported_ = [[CCConfiguration sharedConfiguration] supportsDiscardFramebuffer]; @@ -203,16 +202,17 @@ - (void) dealloc - (void) layoutSubviews { - [renderer_ resizeFromLayer:(CAEAGLLayer*)self.layer]; + [renderer_ resizeFromLayer:(CAEAGLLayer*)self.layer]; + size_ = [renderer_ backingSize]; // Issue #914 #924 CCDirector *director = [CCDirector sharedDirector]; [director reshapeProjection:size_]; - + // Avoid flicker. Issue #350 [director performSelectorOnMainThread:@selector(drawScene) withObject:nil waitUntilDone:YES]; -} +} - (void) swapBuffers { @@ -259,9 +259,8 @@ - (void) swapBuffers } #endif // __IPHONE_4_0 - if(![context_ presentRenderbuffer:GL_RENDERBUFFER_OES]) - CCLOG(@"cocos2d: Failed to swap renderbuffer in %s\n", __FUNCTION__); + CCLOG(@"cocos2d: Failed to swap renderbuffer in %s\n", __FUNCTION__); #if COCOS2D_DEBUG CHECK_GL_ERROR(); @@ -339,4 +338,4 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event @end -#endif // __IPHONE_OS_VERSION_MAX_ALLOWED \ No newline at end of file +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED diff --git a/libs/cocos2d/Platforms/iOS/ES1Renderer.h b/libs/cocos2d/Platforms/iOS/ES1Renderer.h old mode 100755 new mode 100644 index d5ce292..4135326 --- a/libs/cocos2d/Platforms/iOS/ES1Renderer.h +++ b/libs/cocos2d/Platforms/iOS/ES1Renderer.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -49,14 +50,14 @@ unsigned int pixelFormat_; // The OpenGL ES names for the framebuffer and renderbuffer used to render to this view - GLuint defaultFramebuffer_; - GLuint colorRenderbuffer_; + GLuint defaultFrameBuffer_; + GLuint colorRenderBuffer_; GLuint depthBuffer_; //buffers for MSAA - GLuint msaaFramebuffer_; - GLuint msaaColorbuffer_; + GLuint msaaFrameBuffer_; + GLuint msaaColorBuffer_; EAGLContext *context_; } @@ -66,6 +67,10 @@ - (BOOL)resizeFromLayer:(CAEAGLLayer *)layer; +- (unsigned int) colorRenderBuffer; +- (unsigned int) defaultFrameBuffer; +- (unsigned int) msaaFrameBuffer; +- (unsigned int) msaaColorBuffer; @end #endif // __IPHONE_OS_VERSION_MAX_ALLOWED diff --git a/libs/cocos2d/Platforms/iOS/ES1Renderer.m b/libs/cocos2d/Platforms/iOS/ES1Renderer.m old mode 100755 new mode 100644 index 73a5814..b56b75e --- a/libs/cocos2d/Platforms/iOS/ES1Renderer.m +++ b/libs/cocos2d/Platforms/iOS/ES1Renderer.m @@ -1,29 +1,30 @@ /* - * cocos2d for iPhone: http://www.cocos2d-iphone.org - * - * Copyright (c) 2010 Ricardo Quesada - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * - * File autogenerated with Xcode. Adapted for cocos2d needs. - */ +* cocos2d for iPhone: http://www.cocos2d-iphone.org +* +* Copyright (c) 2010 Ricardo Quesada +* Copyright (c) 2011 Zynga Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +* +* +* File autogenerated with Xcode. Adapted for cocos2d needs. +*/ // Only compile this code on iOS. These files should NOT be included on your Mac project. // But in case they are included, it won't be compiled. @@ -41,7 +42,6 @@ - (GLenum) convertPixelFormat:(int) pixelFormat; @end - @implementation ES1Renderer @synthesize context=context_; @@ -58,117 +58,154 @@ - (id) initWithDepthFormat:(unsigned int)depthFormat withPixelFormat:(unsigned i { context_ = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1 sharegroup:sharegroup]; } - - if (!context_ || ![EAGLContext setCurrentContext:context_]) - { - [self release]; - return nil; - } - - // Create default framebuffer object. The backing will be allocated for the current layer in -resizeFromLayer - glGenFramebuffersOES(1, &defaultFramebuffer_); - NSAssert( defaultFramebuffer_, @"Can't create default frame buffer"); - glGenRenderbuffersOES(1, &colorRenderbuffer_); - NSAssert( colorRenderbuffer_, @"Can't create default render buffer"); - - glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer_); - glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer_); - glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer_); - - depthFormat_ = depthFormat; - if( depthFormat_ ) { -// glGenRenderbuffersOES(1, &depthBuffer_); -// glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthBuffer_); -// glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthFormat_, 100, 100); -// glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthBuffer_); - - // default buffer -// glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer_); + if (!context_ || ![EAGLContext setCurrentContext:context_]) + { + [self release]; + return nil; } + backingWidth_ = backingHeight_ = 0; + depthBuffer_ = colorRenderBuffer_ = defaultFrameBuffer_ = msaaColorBuffer_ = msaaFrameBuffer_ = 0; + + depthFormat_ = depthFormat; + pixelFormat_ = pixelFormat; - multiSampling_ = multiSampling; + multiSampling_ = multiSampling; + if (multiSampling_) { GLint maxSamplesAllowed; glGetIntegerv(GL_MAX_SAMPLES_APPLE, &maxSamplesAllowed); samplesToUse_ = MIN(maxSamplesAllowed,requestedSamples); - - /* Create the MSAA framebuffer (offscreen) */ - glGenFramebuffersOES(1, &msaaFramebuffer_); - glBindFramebufferOES(GL_FRAMEBUFFER_OES, msaaFramebuffer_); - } - - CHECK_GL_ERROR(); + + //[self createFrameBuffer:(CAEAGLLayer*) self.layer]; } return self; } -- (BOOL)resizeFromLayer:(CAEAGLLayer *)layer -{ - // Allocate color buffer backing based on the current layer size +- (void) destroyFrameBuffer +{ +// Tear down GL + if(defaultFrameBuffer_) + { + glDeleteFramebuffersOES(1, &defaultFrameBuffer_); + defaultFrameBuffer_ = 0; + } - glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer_); + if(colorRenderBuffer_) + { + glDeleteRenderbuffersOES(1, &colorRenderBuffer_); + colorRenderBuffer_ = 0; + } - if (![context_ renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:layer]) + if( depthBuffer_ ) + { + glDeleteRenderbuffersOES(1, &depthBuffer_); + depthBuffer_ = 0; + } + + if ( msaaColorBuffer_) { - CCLOG(@"failed to call context"); + glDeleteRenderbuffersOES(1, &msaaColorBuffer_); + msaaColorBuffer_ = 0; } + + if ( msaaFrameBuffer_) + { + glDeleteRenderbuffersOES(1, &msaaFrameBuffer_); + msaaFrameBuffer_ = 0; + } +} - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth_); - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight_); - - CCLOG(@"cocos2d: surface size: %dx%d", (int)backingWidth_, (int)backingHeight_); +- (void) createFrameBuffer:(CAEAGLLayer *)layer +{ + glGenFramebuffersOES(1, &defaultFrameBuffer_); + glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFrameBuffer_); + + NSAssert( defaultFrameBuffer_, @"Can't create default frame buffer"); + + glGenRenderbuffersOES(1, &colorRenderBuffer_); + glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderBuffer_); + + NSAssert( colorRenderBuffer_, @"Can't create default render buffer"); + + + // Create default framebuffer object. The backing will be allocated for the current layer in -resizeFromLayer + if (![context_ renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:layer]) + { + CCLOG(@"failed to call context"); + } + + glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderBuffer_); + + glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth_); + glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight_); + if (multiSampling_) { /* Create the offscreen MSAA color buffer. - After rendering, the contents of this will be blitted into ColorRenderbuffer */ + After rendering, the contents of this will be blitted into ColorRenderbuffer */ + + glGenFramebuffersOES(1, &msaaFrameBuffer_); + glBindFramebufferOES(GL_FRAMEBUFFER_OES, msaaFrameBuffer_); + + glGenRenderbuffersOES(1, &msaaColorBuffer_); + glBindRenderbufferOES(GL_RENDERBUFFER_OES, msaaColorBuffer_); - //msaaFrameBuffer needs to be binded - glBindFramebufferOES(GL_FRAMEBUFFER_OES, msaaFramebuffer_); - glGenRenderbuffersOES(1, &msaaColorbuffer_); - glBindRenderbufferOES(GL_RENDERBUFFER_OES, msaaColorbuffer_); glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, samplesToUse_,pixelFormat_ , backingWidth_, backingHeight_); - glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, msaaColorbuffer_); - + + glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, msaaColorBuffer_); + if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) - { CCLOG(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); - return NO; - } } - - if (depthFormat_) + + if (depthFormat_) { - if( ! depthBuffer_ ) - glGenRenderbuffersOES(1, &depthBuffer_); - + glGenRenderbuffersOES(1, &depthBuffer_); glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthBuffer_); + if( multiSampling_ ) glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, samplesToUse_, depthFormat_,backingWidth_, backingHeight_); else glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthFormat_, backingWidth_, backingHeight_); + glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthBuffer_); // bind color buffer - glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer_); + glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderBuffer_); + } - - glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer_); - + + glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFrameBuffer_); + if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) - { CCLOG(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); - return NO; - } CHECK_GL_ERROR(); +} - return YES; +- (BOOL)resizeFromLayer:(CAEAGLLayer *)layer +{ + //issue #1254, destroy and recreate OpenGL buffers completely + if (colorRenderBuffer_) + { + [self destroyFrameBuffer]; + [self createFrameBuffer:layer]; + + CCLOG(@"cocos2d: surface size: %dx%d, resizing buffers", (int)backingWidth_, (int)backingHeight_); + } + else + {//first time + [self createFrameBuffer:layer]; + CCLOG(@"cocos2d: surface size: %dx%d", (int)backingWidth_, (int)backingHeight_); + } + + return YES; } -(CGSize) backingSize @@ -186,37 +223,8 @@ - (void)dealloc { CCLOGINFO(@"cocos2d: deallocing %@", self); - // Tear down GL - if(defaultFramebuffer_) - { - glDeleteFramebuffersOES(1, &defaultFramebuffer_); - defaultFramebuffer_ = 0; - } + [self destroyFrameBuffer]; - if(colorRenderbuffer_) - { - glDeleteRenderbuffersOES(1, &colorRenderbuffer_); - colorRenderbuffer_ = 0; - } - - if( depthBuffer_ ) - { - glDeleteRenderbuffersOES(1, &depthBuffer_); - depthBuffer_ = 0; - } - - if ( msaaColorbuffer_) - { - glDeleteRenderbuffersOES(1, &msaaColorbuffer_); - msaaColorbuffer_ = 0; - } - - if ( msaaFramebuffer_) - { - glDeleteRenderbuffersOES(1, &msaaFramebuffer_); - msaaFramebuffer_ = 0; - } - // Tear down context if ([EAGLContext currentContext] == context_) [EAGLContext setCurrentContext:nil]; @@ -229,24 +237,24 @@ - (void)dealloc - (unsigned int) colorRenderBuffer { - return colorRenderbuffer_; + return colorRenderBuffer_; } - (unsigned int) defaultFrameBuffer { - return defaultFramebuffer_; + return defaultFrameBuffer_; } - (unsigned int) msaaFrameBuffer { - return msaaFramebuffer_; + return msaaFrameBuffer_; } - (unsigned int) msaaColorBuffer { - return msaaColorbuffer_; + return msaaColorBuffer_; } @end -#endif // __IPHONE_OS_VERSION_MAX_ALLOWED +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED \ No newline at end of file diff --git a/libs/cocos2d/Platforms/iOS/ESRenderer.h b/libs/cocos2d/Platforms/iOS/ESRenderer.h old mode 100755 new mode 100644 index ff54ccb..e612eee --- a/libs/cocos2d/Platforms/iOS/ESRenderer.h +++ b/libs/cocos2d/Platforms/iOS/ESRenderer.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/libs/cocos2d/Platforms/iOS/glu.c b/libs/cocos2d/Platforms/iOS/glu.c old mode 100755 new mode 100644 diff --git a/libs/cocos2d/Support/CCArray.h b/libs/cocos2d/Support/CCArray.h index 77c0863..1f10cf5 100644 --- a/libs/cocos2d/Support/CCArray.h +++ b/libs/cocos2d/Support/CCArray.h @@ -1,7 +1,7 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2010 Abstraction Works. http://www.abstractionworks.com + * Copyright (c) 2010 ForzeField Studios S.L. http://forzefield.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,9 +39,9 @@ #define CCARRAY_FOREACH(__array__, __object__) \ if (__array__ && __array__->data->num > 0) \ -for(id *arr = __array__->data->arr, *end = __array__->data->arr + __array__->data->num-1; \ - arr <= end && ((__object__ = *arr) != nil || true); \ - arr++) +for(const CC_ARC_UNSAFE_RETAINED id *__arr__ = __array__->data->arr, *end = __array__->data->arr + __array__->data->num-1; \ + __arr__ <= end && ((__object__ = *__arr__) != nil || true); \ + __arr__++) @interface CCArray : NSObject { @@ -59,22 +59,29 @@ for(id *arr = __array__->data->arr, *end = __array__->data->arr + __array__->dat - (id) initWithNSArray:(NSArray*)otherArray; +// Querying an Array + - (NSUInteger) count; - (NSUInteger) capacity; - (NSUInteger) indexOfObject:(id)object; - (id) objectAtIndex:(NSUInteger)index; -- (id) lastObject; -- (id) randomObject; - (BOOL) containsObject:(id)object; +- (id) randomObject; +- (id) lastObject; +- (NSArray*) getNSArray; +/** @since 1.1 */ +- (BOOL) isEqualToArray:(CCArray*)otherArray; -#pragma mark Adding Objects + +// Adding Objects - (void) addObject:(id)object; - (void) addObjectsFromArray:(CCArray*)otherArray; - (void) addObjectsFromNSArray:(NSArray*)otherArray; - (void) insertObject:(id)object atIndex:(NSUInteger)index; -#pragma mark Removing Objects + +// Removing Objects - (void) removeLastObject; - (void) removeObject:(id)object; @@ -84,9 +91,29 @@ for(id *arr = __array__->data->arr, *end = __array__->data->arr + __array__->dat - (void) fastRemoveObject:(id)object; - (void) fastRemoveObjectAtIndex:(NSUInteger)index; + +// Rearranging Content + +- (void) exchangeObject:(id)object1 withObject:(id)object2; +- (void) exchangeObjectAtIndex:(NSUInteger)index1 withObjectAtIndex:(NSUInteger)index2; +/** @since 1.1 */ +- (void) replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject; +- (void) reverseObjects; +- (void) reduceMemoryFootprint; + +// Sorting Array +/** all since @1.1 */ +- (void) qsortUsingCFuncComparator:(int(*)(const void *, const void *))comparator; // c qsort is used for sorting +- (void) insertionSortUsingCFuncComparator:(int(*)(const void *, const void *))comparator; // insertion sort +- (void) mergesortLUsingCFuncComparator:(int(*)(const void *, const void *))comparator; // mergesort +- (void) insertionSort:(SEL)selector; // It sorts source array in ascending order +- (void) sortUsingFunction:(NSInteger (*)(id, id, void *))compare context:(void *)context; + +// Sending Messages to Elements + - (void) makeObjectsPerformSelector:(SEL)aSelector; - (void) makeObjectsPerformSelector:(SEL)aSelector withObject:(id)object; - -- (NSArray*) getNSArray; +/** @since 1.1 */ +- (void) makeObjectPerformSelectorWithArrayObjects:(id)object selector:(SEL)aSelector; @end diff --git a/libs/cocos2d/Support/CCArray.m b/libs/cocos2d/Support/CCArray.m index 7866ccd..7ebe2c4 100644 --- a/libs/cocos2d/Support/CCArray.m +++ b/libs/cocos2d/Support/CCArray.m @@ -1,7 +1,7 @@ /* * cocos2d for iPhone: http://www.cocos2d-iphone.org * - * Copyright (c) 2010 Abstraction Works. http://www.abstractionworks.com + * Copyright (c) 2010 ForzeField Studios S.L. http://forzefield.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,7 +25,6 @@ #import "CCArray.h" #import "../ccMacros.h" - @implementation CCArray + (id) array @@ -81,19 +80,14 @@ - (id) initWithNSArray:(NSArray*)otherArray return self; } - - - (id) initWithCoder:(NSCoder*)coder { self = [self initWithNSArray:[coder decodeObjectForKey:@"nsarray"]]; return self; } -- (void)encodeWithCoder:(NSCoder *)coder -{ - [coder encodeObject:[self getNSArray] forKey:@"nsarray"]; -} +#pragma mark Querying an Array - (NSUInteger) count { @@ -112,13 +106,16 @@ - (NSUInteger) indexOfObject:(id)object - (id) objectAtIndex:(NSUInteger)index { - if( index >= data->num ) - [NSException raise:NSRangeException - format: @"index out of range in objectAtIndex(%d)", data->num ]; + NSAssert2( index < data->num, @"index out of range in objectAtIndex(%d), index %i", data->num, index ); return data->arr[index]; } +- (BOOL) containsObject:(id)object +{ + return ccArrayContainsObject(data, object); +} + - (id) lastObject { if( data->num > 0 ) @@ -132,11 +129,23 @@ - (id) randomObject return data->arr[(int)(data->num*CCRANDOM_0_1())]; } -- (BOOL) containsObject:(id)object +- (NSArray*) getNSArray { - return ccArrayContainsObject(data, object); + return [NSArray arrayWithObjects:data->arr count:data->num]; } +- (BOOL) isEqualToArray:(CCArray*)otherArray { + for (int i = 0; i< [self count]; i++) + { + if (![[self objectAtIndex:i] isEqual: [otherArray objectAtIndex:i]]) + { + return NO; + } + } + return YES; +} + + #pragma mark Adding Objects - (void) addObject:(id)object @@ -161,16 +170,8 @@ - (void) insertObject:(id)object atIndex:(NSUInteger)index ccArrayInsertObjectAtIndex(data, object, index); } -#pragma mark Removing Objects - -- (void) removeLastObject -{ - if( data->num == 0 ) - [NSException raise:NSRangeException - format: @"no objects added"]; - ccArrayRemoveObjectAtIndex(data, data->num-1); -} +#pragma mark Removing Objects - (void) removeObject:(id)object { @@ -182,26 +183,79 @@ - (void) removeObjectAtIndex:(NSUInteger)index ccArrayRemoveObjectAtIndex(data, index); } +- (void) fastRemoveObject:(id)object +{ + ccArrayFastRemoveObject(data, object); +} + +- (void) fastRemoveObjectAtIndex:(NSUInteger)index +{ + ccArrayFastRemoveObjectAtIndex(data, index); +} + - (void) removeObjectsInArray:(CCArray*)otherArray { ccArrayRemoveArray(data, otherArray->data); } +- (void) removeLastObject +{ + NSAssert( data->num > 0, @"no objects added" ); + + ccArrayRemoveObjectAtIndex(data, data->num-1); +} + - (void) removeAllObjects { ccArrayRemoveAllObjects(data); } -- (void) fastRemoveObjectAtIndex:(NSUInteger)index + +#pragma mark Rearranging Content + +- (void) exchangeObject:(id)object1 withObject:(id)object2 { - ccArrayFastRemoveObjectAtIndex(data, index); + NSUInteger index1 = ccArrayGetIndexOfObject(data, object1); + if(index1 == NSNotFound) return; + NSUInteger index2 = ccArrayGetIndexOfObject(data, object2); + if(index2 == NSNotFound) return; + + ccArraySwapObjectsAtIndexes(data, index1, index2); } -- (void) fastRemoveObject:(id)object +- (void) exchangeObjectAtIndex:(NSUInteger)index1 withObjectAtIndex:(NSUInteger)index2 { - ccArrayFastRemoveObject(data, object); + ccArraySwapObjectsAtIndexes(data, index1, index2); +} + +- (void) replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject { + ccArrayInsertObjectAtIndex(data, anObject, index); + ccArrayRemoveObjectAtIndex(data, index+1); } +- (void) reverseObjects +{ + if (data->num > 1) + { + //floor it since in case of a oneven number the number of swaps stays the same + int count = (int) floorf(data->num/2.f); + NSUInteger maxIndex = data->num - 1; + + for (int i = 0; i < count ; i++) + { + ccArraySwapObjectsAtIndexes(data, i, maxIndex); + maxIndex--; + } + } +} + +- (void) reduceMemoryFootprint +{ + ccArrayShrink(data); +} + +#pragma mark Sending Messages to Elements + - (void) makeObjectsPerformSelector:(SEL)aSelector { ccArrayMakeObjectsPerformSelector(data, aSelector); @@ -212,11 +266,13 @@ - (void) makeObjectsPerformSelector:(SEL)aSelector withObject:(id)object ccArrayMakeObjectsPerformSelectorWithObject(data, aSelector, object); } -- (NSArray*) getNSArray -{ - return [NSArray arrayWithObjects:data->arr count:data->num]; +- (void) makeObjectPerformSelectorWithArrayObjects:(id)object selector:(SEL)aSelector +{ + ccArrayMakeObjectPerformSelectorWithArrayObjects(data, aSelector, object); } +#pragma mark CCArray - NSFastEnumeration protocol + - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len { if(state->state == 1) return 0; @@ -227,19 +283,148 @@ - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state object return data->num; } +#pragma mark CCArray - sorting + +/** @since 1.1 */ +#pragma mark - +#pragma mark CCArray insertionSortUsingCFuncComparator + +- (void) insertionSortUsingCFuncComparator:(int(*)(const void *, const void *))comparator +{ + insertionSort(data, comparator); +} + +#pragma mark CCArray qsortUsingCFuncComparator + +- (void) qsortUsingCFuncComparator:(int(*)(const void *, const void *))comparator { + + // stable c qsort is used - cost of sorting: best n*log(n), average n*log(n) + // qsort(void *, size_t, size_t, int (*)(const void *arg1, const void *arg2)); + + qsort(data->arr, data->num, sizeof (id), comparator); +} + +#pragma mark CCArray mergesortLUsingCFuncComparator + +- (void) mergesortLUsingCFuncComparator:(int(*)(const void *, const void *))comparator +{ + mergesortL(data, sizeof (id), comparator); +} + +#pragma mark CCArray insertionSort with (SEL)selector + +- (void) insertionSort:(SEL)selector // It sorts source array in ascending order +{ + NSInteger i,j,length = data->num; + + id * x = data->arr; + id temp; + + // insertion sort + for(i=1; i0 && ( (int)([x[j-1] performSelector:selector withObject:x[j]]) == NSOrderedDescending) ) + { + temp = x[j]; + x[j] = x[j-1]; + x[j-1] = temp; + j--; + } + } +} + +static inline NSInteger selectorCompare(id object1,id object2,void *userData){ + SEL selector=userData; + + return (NSInteger)[object1 performSelector:selector withObject:object2]; +} + +-(void)sortUsingSelector:(SEL)selector { + [self sortUsingFunction:selectorCompare context:selector]; +} + +#pragma mark CCArray sortUsingFunction + +// using a comparison function +-(void)sortUsingFunction:(NSInteger (*)(id, id, void *))compare context:(void *)context +{ + NSInteger h, i, j, k, l, m, n = [self count]; + id A, *B = NSZoneMalloc(NULL,(n/2 + 1) * sizeof(id)); + + // to prevent retain counts from temporarily hitting zero. + for(i=0;i= 0; m -= h + h) + { + l = m - h + 1; + if (l < 0) + l = 0; + + for (i = 0, j = l; j <= m; i++, j++) + B[i] = [self objectAtIndex:j]; + + for (i = 0, k = l; k < j && j <= m + h; k++) + { + A = [self objectAtIndex:j]; + if (compare(A, B[i], context) == NSOrderedDescending) + [self replaceObjectAtIndex:k withObject:B[i++]]; + else + { + [self replaceObjectAtIndex:k withObject:A]; + j++; + } + } + + while (k < j) + [self replaceObjectAtIndex:k++ withObject:B[i++]]; + } + } + + for(i=0;i = ( ", [self class], self]; + + for( id obj in self) + [ret appendFormat:@"%@, ",obj]; + + [ret appendString:@")"]; + + return ret; } @end diff --git a/libs/cocos2d/Support/CCFileUtils.h b/libs/cocos2d/Support/CCFileUtils.h index 4cf4218..ddf4162 100644 --- a/libs/cocos2d/Support/CCFileUtils.h +++ b/libs/cocos2d/Support/CCFileUtils.h @@ -2,17 +2,18 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada - * + * Copyright (c) 2011 Zynga Inc. + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -25,7 +26,7 @@ #import - +#import "../ccTypes.h" /** Helper class to handle file operations */ @interface CCFileUtils : NSObject @@ -34,28 +35,98 @@ /** Returns the fullpath of an filename. - If this method is when Retina Display is enabled, then the - Retina Display suffix will be appended to the file (See ccConfig.h). + If in RetinaDisplay mode, and a RetinaDisplay file is found, it will return that path. + If in iPad mode, and an iPad file is found, it will return that path. + + Examples: - If the Retina Display image doesn't exist, then it will return the "non-Retina Display" image + * In iPad mode: "image.png" -> "/full/path/image-ipad.png" (in case the -ipad file exists) + * In RetinaDisplay mode: "image.png" -> "/full/path/image-hd.png" (in case the -hd file exists) */ +(NSString*) fullPathFromRelativePath:(NSString*) relPath; -@end -/** loads a file into memory. - the caller should release the allocated buffer. + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + +/** Returns the fullpath of an filename including the resolution of the image. + + If in RetinaDisplay mode, and a RetinaDisplay file is found, it will return that path. + If in iPad mode, and an iPad file is found, it will return that path. + + Examples: + + * In iPad mode: "image.png" -> "/full/path/image-ipad.png" (in case the -ipad file exists) + * In RetinaDisplay mode: "image.png" -> "/full/path/image-hd.png" (in case the -hd file exists) + + If an iPad file is found, it will set resolution type to kCCResolutioniPad + If a RetinaDisplay file is found, it will set resolution type to kCCResolutionRetinaDisplay + + */ ++(NSString*) fullPathFromRelativePath:(NSString*)relPath resolutionType:(ccResolutionType*)resolutionType; + + +/** removes the suffix from a path + * On RetinaDisplay it will remove the -hd suffix + * On iPad it will remove the -ipad suffix + * On iPhone it will remove the (empty) suffix + Only valid on iOS. Not valid for OS X. - @returns the size of the allocated buffer @since v0.99.5 */ -int ccLoadFileIntoMemory(const char *filename, unsigned char **out); ++(NSString *)removeSuffixFromFile:(NSString*) path; +/** Sets the iPhone RetinaDisplay suffix to load resources. + By default it is "-hd". + Only valid on iOS. Not valid for OS X. + + @since v1.1 + */ ++(void) setiPhoneRetinaDisplaySuffix:(NSString*)suffix; -/** removes the HD suffix from a path +/** Sets the iPad suffix to load resources. + By default it is "". + Only valid on iOS. Not valid for OS X. - @returns NSString * without the HD suffix + + */ ++(void) setiPadSuffix:(NSString*)suffix; + +/** Sets the iPad Retina Display suffix to load resources. + By default it is "-ipadhd". + Only valid on iOS. Not valid for OS X. + + @since v1.1 + */ ++(void) setiPadRetinaDisplaySuffix:(NSString*)suffix; + +/** Returns whether or not a given filename exists with the iPad suffix. + Only available on iOS. Not supported on OS X. + @since v1.1 + */ ++(BOOL) iPadFileExistsAtPath:(NSString*)filename; + +/** Returns whether or not a given filename exists with the iPad RetinaDisplay suffix. + Only available on iOS. Not supported on OS X. + + */ ++(BOOL) iPadRetinaDisplayFileExistsAtPath:(NSString*)filename; + +/** Returns whether or not a given path exists with the iPhone RetinaDisplay suffix. + Only available on iOS. Not supported on OS X. + @since v1.1 + */ ++(BOOL) iPhoneRetinaDisplayFileExistsAtPath:(NSString*)filename; + +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED + +@end + +/** loads a file into memory. + the caller should release the allocated buffer. + + @returns the size of the allocated buffer @since v0.99.5 */ -NSString *ccRemoveHDSuffixFromFile( NSString *path ); +NSInteger ccLoadFileIntoMemory(const char *filename, unsigned char **out); diff --git a/libs/cocos2d/Support/CCFileUtils.m b/libs/cocos2d/Support/CCFileUtils.m index d728ee3..41ba507 100644 --- a/libs/cocos2d/Support/CCFileUtils.m +++ b/libs/cocos2d/Support/CCFileUtils.m @@ -2,17 +2,18 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada - * + * Copyright (c) 2011 Zynga Inc. + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -24,70 +25,62 @@ */ -#import #import "CCFileUtils.h" #import "../CCConfiguration.h" #import "../ccMacros.h" #import "../ccConfig.h" +#import "../ccTypes.h" static NSFileManager *__localFileManager=nil; -// -int ccLoadFileIntoMemory(const char *filename, unsigned char **out) -{ - assert( out ); - assert( &*out ); +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + +static NSString *__suffixiPhoneRetinaDisplay =@"-hd"; +static NSString *__suffixiPad =@"-ipad"; +static NSString *__suffixiPadRetinaDisplay =@"-ipadhd"; + +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED + - int size = 0; +NSString *ccRemoveSuffixFromPath( NSString *suffix, NSString *path); + +// +NSInteger ccLoadFileIntoMemory(const char *filename, unsigned char **out) +{ + NSCAssert( out, @"ccLoadFileIntoMemory: invalid 'out' parameter"); + NSCAssert( &*out, @"ccLoadFileIntoMemory: invalid 'out' parameter"); + + size_t size = 0; FILE *f = fopen(filename, "rb"); - if( !f ) { + if( !f ) { *out = NULL; return -1; - } - + } + fseek(f, 0, SEEK_END); size = ftell(f); fseek(f, 0, SEEK_SET); - + *out = malloc(size); - int read = fread(*out, 1, size, f); - if( read != size ) { + size_t read = fread(*out, 1, size, f); + if( read != size ) { free(*out); *out = NULL; return -1; } - + fclose(f); - + return size; } -NSString *ccRemoveHDSuffixFromFile( NSString *path ) -{ -#if CC_IS_RETINA_DISPLAY_SUPPORTED - - if( CC_CONTENT_SCALE_FACTOR() == 2 ) { - - NSString *name = [path lastPathComponent]; - - // check if path already has the suffix. - if( [name rangeOfString:CC_RETINA_DISPLAY_FILENAME_SUFFIX].location != NSNotFound ) { - - CCLOG(@"cocos2d: Filename(%@) contains %@ suffix. Removing it. See cocos2d issue #1040", path, CC_RETINA_DISPLAY_FILENAME_SUFFIX); - - NSString *newLastname = [name stringByReplacingOccurrencesOfString:CC_RETINA_DISPLAY_FILENAME_SUFFIX withString:@""]; - - NSString *pathWithoutLastname = [path stringByDeletingLastPathComponent]; - return [pathWithoutLastname stringByAppendingPathComponent:newLastname]; - } - } - -#endif // CC_IS_RETINA_DISPLAY_SUPPORTED - - return path; - -} +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +@interface CCFileUtils() ++(NSString *) removeSuffix:(NSString*)suffix fromPath:(NSString*)path; ++(BOOL) fileExistsAtPath:(NSString*)string withSuffix:(NSString*)suffix; +@end +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED @implementation CCFileUtils @@ -97,72 +90,231 @@ +(void) initialize __localFileManager = [[NSFileManager alloc] init]; } -+(NSString*) getDoubleResolutionImage:(NSString*)path ++(NSString*) getPath:(NSString*)path forSuffix:(NSString*)suffix { -#if CC_IS_RETINA_DISPLAY_SUPPORTED + // quick return + if( ! suffix || [suffix length] == 0 ) + return path; + + NSString *pathWithoutExtension = [path stringByDeletingPathExtension]; + NSString *name = [pathWithoutExtension lastPathComponent]; + + // check if path already has the suffix. + if( [name rangeOfString:suffix].location != NSNotFound ) { + + CCLOG(@"cocos2d: WARNING Filename(%@) already has the suffix %@. Using it.", name, suffix); + return path; + } + + + NSString *extension = [path pathExtension]; + + if( [extension isEqualToString:@"ccz"] || [extension isEqualToString:@"gz"] ) + { + // All ccz / gz files should be in the format filename.xxx.ccz + // so we need to pull off the .xxx part of the extension as well + extension = [NSString stringWithFormat:@"%@.%@", [pathWithoutExtension pathExtension], extension]; + pathWithoutExtension = [pathWithoutExtension stringByDeletingPathExtension]; + } + + + NSString *newName = [pathWithoutExtension stringByAppendingString:suffix]; + newName = [newName stringByAppendingPathExtension:extension]; + + if( [__localFileManager fileExistsAtPath:newName] ) + return newName; + + CCLOG(@"cocos2d: CCFileUtils: Warning file not found: %@", [newName lastPathComponent] ); + + return nil; +} - if( CC_CONTENT_SCALE_FACTOR() == 2 ) ++(NSString*) fullPathFromRelativePath:(NSString*)relPath resolutionType:(ccResolutionType*)resolutionType +{ + NSAssert(relPath != nil, @"CCFileUtils: Invalid path"); + + NSString *fullpath = nil; + + // only if it is not an absolute path + if( ! [relPath isAbsolutePath] ) { + + // pathForResource also searches in .lproj directories. issue #1230 + NSString *file = [relPath lastPathComponent]; + NSString *imageDirectory = [relPath stringByDeletingLastPathComponent]; + + fullpath = [[NSBundle mainBundle] pathForResource:file + ofType:nil + inDirectory:imageDirectory]; + + + } + + if (fullpath == nil) + fullpath = relPath; + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + + NSString *ret = nil; + + // iPad? + if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - - NSString *pathWithoutExtension = [path stringByDeletingPathExtension]; - NSString *name = [pathWithoutExtension lastPathComponent]; - - // check if path already has the suffix. - if( [name rangeOfString:CC_RETINA_DISPLAY_FILENAME_SUFFIX].location != NSNotFound ) { - - CCLOG(@"cocos2d: WARNING Filename(%@) already has the suffix %@. Using it.", name, CC_RETINA_DISPLAY_FILENAME_SUFFIX); - return path; + // Retina Display ? + if( CC_CONTENT_SCALE_FACTOR() == 2 ) { + ret = [self getPath:fullpath forSuffix:__suffixiPadRetinaDisplay]; + *resolutionType = kCCResolutioniPadRetinaDisplay; } - - - NSString *extension = [path pathExtension]; - - if( [extension isEqualToString:@"ccz"] || [extension isEqualToString:@"gz"] ) + else { - // All ccz / gz files should be in the format filename.xxx.ccz - // so we need to pull off the .xxx part of the extension as well - extension = [NSString stringWithFormat:@"%@.%@", [pathWithoutExtension pathExtension], extension]; - pathWithoutExtension = [pathWithoutExtension stringByDeletingPathExtension]; + ret = [self getPath:fullpath forSuffix:__suffixiPad]; + *resolutionType = kCCResolutioniPad; + } - - - NSString *retinaName = [pathWithoutExtension stringByAppendingString:CC_RETINA_DISPLAY_FILENAME_SUFFIX]; - retinaName = [retinaName stringByAppendingPathExtension:extension]; + } + // iPhone ? + else + { + // Retina Display ? + if( CC_CONTENT_SCALE_FACTOR() == 2 ) { + ret = [self getPath:fullpath forSuffix:__suffixiPhoneRetinaDisplay]; + *resolutionType = kCCResolutioniPhoneRetinaDisplay; + } + } + + // If it is iPhone Non RetinaDisplay, or if the previous "getPath" failed, then use iPhone images. + if( ret == nil ) + { + *resolutionType = kCCResolutioniPhone; + ret = fullpath; + } + + return ret; + +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + + *resolutionType = kCCResolutioniPhone; + + return fullpath; + +#endif // __CC_PLATFORM_MAC + + return nil; +} + ++(NSString*) fullPathFromRelativePath:(NSString*) relPath +{ + ccResolutionType ignore; + return [self fullPathFromRelativePath:relPath resolutionType:&ignore]; +} + +#pragma mark CCFileUtils - Suffix (iOS only) + - if( [__localFileManager fileExistsAtPath:retinaName] ) - return retinaName; +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED - CCLOG(@"cocos2d: CCFileUtils: Warning HD file not found: %@", [retinaName lastPathComponent] ); ++(NSString *) removeSuffix:(NSString*)suffix fromPath:(NSString*)path +{ + // quick return + if( ! suffix || [suffix length] == 0 ) + return path; + + NSString *name = [path lastPathComponent]; + + // check if path already has the suffix. + if( [name rangeOfString:suffix].location != NSNotFound ) { + + CCLOGINFO(@"cocos2d: Filename(%@) contains %@ suffix. Removing it. See cocos2d issue #1040", path, suffix); + + NSString *newLastname = [name stringByReplacingOccurrencesOfString:suffix withString:@""]; + + NSString *pathWithoutLastname = [path stringByDeletingLastPathComponent]; + return [pathWithoutLastname stringByAppendingPathComponent:newLastname]; } - -#endif // CC_IS_RETINA_DISPLAY_SUPPORTED - + return path; } -+(NSString*) fullPathFromRelativePath:(NSString*) relPath ++(NSString*) removeSuffixFromFile:(NSString*) path { - NSAssert(relPath != nil, @"CCFileUtils: Invalid path"); + NSString *ret = nil; + + if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) + { + if( CC_CONTENT_SCALE_FACTOR() == 2 ) + ret = [self removeSuffix:__suffixiPadRetinaDisplay fromPath:path]; + else + ret = [self removeSuffix:__suffixiPad fromPath:path]; + } + else + { + if( CC_CONTENT_SCALE_FACTOR() == 2 ) + ret = [self removeSuffix:__suffixiPhoneRetinaDisplay fromPath:path]; + else + ret = path; + } + + return ret; +} + ++(void) setiPhoneRetinaDisplaySuffix:(NSString*)suffix +{ + [__suffixiPhoneRetinaDisplay release]; + __suffixiPhoneRetinaDisplay = [suffix copy]; +} ++(void) setiPadSuffix:(NSString*)suffix +{ + [__suffixiPad release]; + __suffixiPad = [suffix copy]; +} + ++(void) setiPadRetinaDisplaySuffix:(NSString*)suffix +{ + [__suffixiPadRetinaDisplay release]; + __suffixiPadRetinaDisplay = [suffix copy]; +} + ++(BOOL) fileExistsAtPath:(NSString*)relPath withSuffix:(NSString*)suffix +{ NSString *fullpath = nil; - + // only if it is not an absolute path - if( ! [relPath isAbsolutePath] ) - { + if( ! [relPath isAbsolutePath] ) { + // pathForResource also searches in .lproj directories. issue #1230 NSString *file = [relPath lastPathComponent]; NSString *imageDirectory = [relPath stringByDeletingLastPathComponent]; - + fullpath = [[NSBundle mainBundle] pathForResource:file ofType:nil inDirectory:imageDirectory]; + } - + if (fullpath == nil) fullpath = relPath; - - fullpath = [self getDoubleResolutionImage:fullpath]; - - return fullpath; + + NSString *path = [self getPath:fullpath forSuffix:suffix]; + + return ( path != nil ); } ++(BOOL) iPhoneRetinaDisplayFileExistsAtPath:(NSString*)path +{ + return [self fileExistsAtPath:path withSuffix:__suffixiPhoneRetinaDisplay]; +} + ++(BOOL) iPadFileExistsAtPath:(NSString*)path +{ + return [self fileExistsAtPath:path withSuffix:__suffixiPad]; +} + ++(BOOL) iPadRetinaDisplayFileExistsAtPath:(NSString*)path +{ + return [self fileExistsAtPath:path withSuffix:__suffixiPadRetinaDisplay]; +} + + +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED + + @end diff --git a/libs/cocos2d/Support/CGPointExtension.h b/libs/cocos2d/Support/CGPointExtension.h index 5193d3f..96edeb7 100644 --- a/libs/cocos2d/Support/CGPointExtension.h +++ b/libs/cocos2d/Support/CGPointExtension.h @@ -2,6 +2,7 @@ * http://www.cocos2d-iphone.org * * Copyright (c) 2007 Scott Lembcke + * * Copyright (c) 2010 Lam Pham * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -316,6 +317,18 @@ BOOL ccpLineIntersect(CGPoint p1, CGPoint p2, CGPoint p3, CGPoint p4, float *s, float *t); +/* + ccpSegmentIntersect returns YES if Segment A-B intersects with segment C-D + @since v1.0.0 + */ +BOOL ccpSegmentIntersect(CGPoint A, CGPoint B, CGPoint C, CGPoint D); + +/* + ccpIntersectPoint returns the intersection point of line A-B, C-D + @since v1.0.0 + */ +CGPoint ccpIntersectPoint(CGPoint A, CGPoint B, CGPoint C, CGPoint D); + #ifdef __cplusplus } #endif diff --git a/libs/cocos2d/Support/CGPointExtension.m b/libs/cocos2d/Support/CGPointExtension.m index 04fff86..b06859d 100644 --- a/libs/cocos2d/Support/CGPointExtension.m +++ b/libs/cocos2d/Support/CGPointExtension.m @@ -2,6 +2,7 @@ * http://www.cocos2d-iphone.org * * Copyright (c) 2007 Scott Lembcke + * * Copyright (c) 2010 Lam Pham * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -84,7 +85,8 @@ CGPoint ccpFromSize(CGSize s) return ccp(s.width, s.height); } -CGPoint ccpCompOp(CGPoint p, float (*opFunc)(float)){ +CGPoint ccpCompOp(CGPoint p, float (*opFunc)(float)) +{ return ccp(opFunc(p.x), opFunc(p.y)); } @@ -103,59 +105,87 @@ CGPoint ccpCompMult(CGPoint a, CGPoint b) float ccpAngleSigned(CGPoint a, CGPoint b) { - CGPoint a2 = ccpNormalize(a); CGPoint b2 = ccpNormalize(b); + CGPoint a2 = ccpNormalize(a); + CGPoint b2 = ccpNormalize(b); float angle = atan2f(a2.x * b2.y - a2.y * b2.x, ccpDot(a2, b2)); if( fabs(angle) < kCGPointEpsilon ) return 0.f; return angle; } -CGPoint ccpRotateByAngle(CGPoint v, CGPoint pivot, float angle) { +CGPoint ccpRotateByAngle(CGPoint v, CGPoint pivot, float angle) +{ CGPoint r = ccpSub(v, pivot); - float t = r.x; float cosa = cosf(angle), sina = sinf(angle); - r.x = t*cosa - r.y*sina; - r.y = t*sina + r.y*cosa; - r = ccpAdd(r, pivot); + float t = r.x; + r.x = t*cosa - r.y*sina + pivot.x; + r.y = t*sina + r.y*cosa + pivot.y; return r; } -BOOL ccpLineIntersect(CGPoint p1, CGPoint p2, - CGPoint p3, CGPoint p4, - float *s, float *t){ - CGPoint p13, p43, p21; - float d1343, d4321, d1321, d4343, d2121; - float numer, denom; - - p13 = ccpSub(p1, p3); - - p43 = ccpSub(p4, p3); - - //Roughly equal to zero but with an epsilon deviation for float - //correction - if (ccpFuzzyEqual(p43, CGPointZero, kCGPointEpsilon)) - return false; - - p21 = ccpSub(p2, p1); - - //Roughly equal to zero - if (ccpFuzzyEqual(p21,CGPointZero, kCGPointEpsilon)) - return false; - - d1343 = ccpDot(p13, p43); - d4321 = ccpDot(p43, p21); - d1321 = ccpDot(p13, p21); - d4343 = ccpDot(p43, p43); - d2121 = ccpDot(p21, p21); - - denom = d2121 * d4343 - d4321 * d4321; - if (fabs(denom) < kCGPointEpsilon) - return false; - numer = d1343 * d4321 - d1321 * d4343; - - *s = numer / denom; - *t = (d1343 + d4321 *(*s)) / d4343; - - return true; + +BOOL ccpSegmentIntersect(CGPoint A, CGPoint B, CGPoint C, CGPoint D) +{ + float S, T; + + if( ccpLineIntersect(A, B, C, D, &S, &T ) + && (S >= 0.0f && S <= 1.0f && T >= 0.0f && T <= 1.0f) ) + return YES; + + return NO; +} + +CGPoint ccpIntersectPoint(CGPoint A, CGPoint B, CGPoint C, CGPoint D) +{ + float S, T; + + if( ccpLineIntersect(A, B, C, D, &S, &T) ) { + // Point of intersection + CGPoint P; + P.x = A.x + S * (B.x - A.x); + P.y = A.y + S * (B.y - A.y); + return P; + } + + return CGPointZero; +} + +BOOL ccpLineIntersect(CGPoint A, CGPoint B, + CGPoint C, CGPoint D, + float *S, float *T) +{ + // FAIL: Line undefined + if ( (A.x==B.x && A.y==B.y) || (C.x==D.x && C.y==D.y) ) return NO; + + const float BAx = B.x - A.x; + const float BAy = B.y - A.y; + const float DCx = D.x - C.x; + const float DCy = D.y - C.y; + const float ACx = A.x - C.x; + const float ACy = A.y - C.y; + + const float denom = DCy*BAx - DCx*BAy; + + *S = DCx*ACy - DCy*ACx; + *T = BAx*ACy - BAy*ACx; + + if (denom == 0) { + if (*S == 0 || *T == 0) { + // Lines incident + return YES; + } + // Lines parallel and not incident + return NO; + } + + *S = *S / denom; + *T = *T / denom; + + // Point of intersection + // CGPoint P; + // P.x = A.x + *S * (B.x - A.x); + // P.y = A.y + *S * (B.y - A.y); + + return YES; } float ccpAngle(CGPoint a, CGPoint b) @@ -164,4 +194,3 @@ float ccpAngle(CGPoint a, CGPoint b) if( fabs(angle) < kCGPointEpsilon ) return 0.f; return angle; } - diff --git a/libs/cocos2d/Support/TGAlib.m b/libs/cocos2d/Support/TGAlib.m index b574d59..11303b4 100644 --- a/libs/cocos2d/Support/TGAlib.m +++ b/libs/cocos2d/Support/TGAlib.m @@ -11,6 +11,8 @@ #import "TGAlib.h" +void tgaLoadRLEImageData(FILE *file, tImageTGA *info); +void tgaFlipImage( tImageTGA *info ); // load the image header fields. We only keep those that matter! void tgaLoadHeader(FILE *file, tImageTGA *info) { diff --git a/libs/cocos2d/Support/ZipUtils.h b/libs/cocos2d/Support/ZipUtils.h index 8179e4c..363f911 100644 --- a/libs/cocos2d/Support/ZipUtils.h +++ b/libs/cocos2d/Support/ZipUtils.h @@ -47,12 +47,25 @@ extern "C" { * Inflates either zlib or gzip deflated memory. The inflated memory is * expected to be freed by the caller. * + * It will allocate 256k for the destination buffer. If it is not enought it will multiply the previous buffer size per 2, until there is enough memory. * @returns the length of the deflated buffer * @since v0.8.1 */ int ccInflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out); +/** + * Inflates either zlib or gzip deflated memory. The inflated memory is + * expected to be freed by the caller. + * + * outLenghtHint is assumed to be the needed room to allocate the inflated buffer. + * + * @returns the length of the deflated buffer + * + @since v1.0.0 + */ +int ccInflateMemoryWithHint(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int outLenghtHint ); + /** inflates a GZip file into memory * diff --git a/libs/cocos2d/Support/ZipUtils.m b/libs/cocos2d/Support/ZipUtils.m index 198ab4f..33446e5 100644 --- a/libs/cocos2d/Support/ZipUtils.m +++ b/libs/cocos2d/Support/ZipUtils.m @@ -29,13 +29,12 @@ // Should buffer factor be 1.5 instead of 2 ? #define BUFFER_INC_FACTOR (2) -static int inflateMemory_(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int *outLength) +static int inflateMemoryWithHint(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int *outLength, unsigned int outLenghtHint ) { /* ret value */ int err = Z_OK; - /* 256k initial decompress buffer */ - int bufferSize = 256 * 1024; + int bufferSize = outLenghtHint; *out = (unsigned char*) malloc(bufferSize); z_stream d_stream; /* decompression stream */ @@ -87,27 +86,27 @@ static int inflateMemory_(unsigned char *in, unsigned int inLength, unsigned cha } } - + *outLength = bufferSize - d_stream.avail_out; err = inflateEnd(&d_stream); return err; } -int ccInflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out) +int ccInflateMemoryWithHint(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int outLengthHint ) { unsigned int outLength = 0; - int err = inflateMemory_(in, inLength, out, &outLength); + int err = inflateMemoryWithHint(in, inLength, out, &outLength, outLengthHint ); if (err != Z_OK || *out == NULL) { if (err == Z_MEM_ERROR) CCLOG(@"cocos2d: ZipUtils: Out of memory while decompressing map data!"); - + else if (err == Z_VERSION_ERROR) CCLOG(@"cocos2d: ZipUtils: Incompatible zlib version!"); - + else if (err == Z_DATA_ERROR) CCLOG(@"cocos2d: ZipUtils: Incorrect zlib compressed data!"); - + else CCLOG(@"cocos2d: ZipUtils: Unknown error while decompressing map data!"); @@ -119,13 +118,19 @@ int ccInflateMemory(unsigned char *in, unsigned int inLength, unsigned char **ou return outLength; } +int ccInflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out) +{ + // 256k for hint + return ccInflateMemoryWithHint(in, inLength, out, 256 * 1024 ); +} + int ccInflateGZipFile(const char *path, unsigned char **out) { int len; unsigned int offset = 0; - assert( out ); - assert( &*out ); + NSCAssert( out, @"ccInflateGZipFile: invalid 'out' parameter"); + NSCAssert( &*out, @"ccInflateGZipFile: invalid 'out' parameter"); gzFile inFile = gzopen(path, "rb"); if( inFile == NULL ) { @@ -134,7 +139,7 @@ int ccInflateGZipFile(const char *path, unsigned char **out) } /* 512k initial decompress buffer */ - unsigned int bufferSize = 512 * 1024; + int bufferSize = 512 * 1024; unsigned int totalBufferSize = bufferSize; *out = malloc( bufferSize ); @@ -182,14 +187,15 @@ int ccInflateGZipFile(const char *path, unsigned char **out) int ccInflateCCZFile(const char *path, unsigned char **out) { - assert( out ); - assert( &*out ); + NSCAssert( out, @"ccInflateCCZFile: invalid 'out' parameter"); + NSCAssert( &*out, @"ccInflateCCZFile: invalid 'out' parameter"); // load file into memory unsigned char *compressed = NULL; - int fileLen = ccLoadFileIntoMemory( path, &compressed ); + NSInteger fileLen = ccLoadFileIntoMemory( path, &compressed ); if( fileLen < 0 ) { CCLOG(@"cocos2d: Error loading CCZ compressed file"); + return -1; } struct CCZHeader *header = (struct CCZHeader*) compressed; @@ -243,4 +249,4 @@ int ccInflateCCZFile(const char *path, unsigned char **out) return len; -} \ No newline at end of file +} diff --git a/libs/cocos2d/Support/base64.c b/libs/cocos2d/Support/base64.c index 7a8f65a..9aa52a6 100644 --- a/libs/cocos2d/Support/base64.c +++ b/libs/cocos2d/Support/base64.c @@ -7,8 +7,12 @@ #include #include +#include "base64.h" + unsigned char alphabet[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +int _base64Decode( unsigned char *input, unsigned int input_len, unsigned char *output, unsigned int *output_len ); + int _base64Decode( unsigned char *input, unsigned int input_len, unsigned char *output, unsigned int *output_len ) { static char inalphabet[256], decoder[256]; diff --git a/libs/cocos2d/Support/ccCArray.h b/libs/cocos2d/Support/ccCArray.h index 7e38976..a9bc066 100644 --- a/libs/cocos2d/Support/ccCArray.h +++ b/libs/cocos2d/Support/ccCArray.h @@ -21,7 +21,7 @@ /** @file - Based on Chipmunk cpArray. + arrd on Chipmunk cpArray. ccArray is a faster alternative to NSMutableArray, it does pretty much the same thing (stores NSObjects and retains/releases them appropriately). It's faster because: @@ -43,6 +43,7 @@ #import #import +#import "../ccMacros.h" #pragma mark - #pragma mark ccArray for Objects @@ -51,10 +52,15 @@ #define CCARRAYDATA_FOREACH(__array__, __object__) \ __object__=__array__->arr[0]; for(NSUInteger i=0, num=__array__->num; iarr[i]) \ +#if defined(__has_feature) && __has_feature(objc_arc) + typedef __strong id CCARRAY_ID; +#else + typedef id CCARRAY_ID; +#endif typedef struct ccArray { NSUInteger num, max; - id *arr; + CCARRAY_ID *arr; } ccArray; /** Allocates and initializes a new array with specified capacity */ @@ -64,7 +70,7 @@ static inline ccArray* ccArrayNew(NSUInteger capacity) { ccArray *arr = (ccArray*)malloc( sizeof(ccArray) ); arr->num = 0; - arr->arr = (id*) malloc( capacity * sizeof(id) ); + arr->arr = (CCARRAY_ID *)calloc(capacity, sizeof(id)); arr->max = capacity; return arr; @@ -87,7 +93,10 @@ static inline void ccArrayFree(ccArray *arr) static inline void ccArrayDoubleCapacity(ccArray *arr) { arr->max *= 2; - arr->arr = (id*) realloc( arr->arr, arr->max * sizeof(id) ); + CCARRAY_ID *newArr = (CCARRAY_ID *)realloc( arr->arr, arr->max * sizeof(id) ); + // will fail when there's not enough memory + NSCAssert(newArr != NULL, @"ccArrayDoubleCapacity failed. Not enough memory"); + arr->arr = newArr; } /** Increases array capacity such that max >= num + extra. */ @@ -97,11 +106,36 @@ static inline void ccArrayEnsureExtraCapacity(ccArray *arr, NSUInteger extra) ccArrayDoubleCapacity(arr); } +/** shrinks the array so the memory footprint corresponds with the number of items */ +static inline void ccArrayShrink(ccArray *arr) +{ + NSUInteger newSize; + + //only resize when necessary + if (arr->max > arr->num && !(arr->num==0 && arr->max==1)) + { + if (arr->num!=0) + { + newSize=arr->num; + arr->max=arr->num; + } + else + {//minimum capacity of 1, with 0 elements the array would be free'd by realloc + newSize=1; + arr->max=1; + } + + arr->arr = (CCARRAY_ID *) realloc(arr->arr,newSize * sizeof(id) ); + NSCAssert(arr->arr!=NULL,@"could not reallocate the memory"); + } +} + /** Returns index of first occurence of object, NSNotFound if object not found. */ static inline NSUInteger ccArrayGetIndexOfObject(ccArray *arr, id object) { for( NSUInteger i = 0; i < arr->num; i++) if( arr->arr[i] == object ) return i; + return NSNotFound; } @@ -114,7 +148,7 @@ static inline BOOL ccArrayContainsObject(ccArray *arr, id object) /** Appends an object. Bahaviour undefined if array doesn't have enough capacity. */ static inline void ccArrayAppendObject(ccArray *arr, id object) { - arr->arr[arr->num] = [object retain]; + arr->arr[arr->num] = CC_ARC_RETAIN(object); arr->num++; } @@ -140,37 +174,50 @@ static inline void ccArrayAppendArrayWithResize(ccArray *arr, ccArray *plusArr) ccArrayAppendArray(arr, plusArr); } +/** Inserts an object at index */ static inline void ccArrayInsertObjectAtIndex(ccArray *arr, id object, NSUInteger index) { NSCAssert(index<=arr->num, @"Invalid index. Out of bounds"); ccArrayEnsureExtraCapacity(arr, 1); - int remaining = arr->num - index; + NSUInteger remaining = arr->num - index; if( remaining > 0) - memmove(&arr->arr[index+1], &arr->arr[index], sizeof(id) * remaining ); + memmove((void *)&arr->arr[index+1], (void *)&arr->arr[index], sizeof(id) * remaining ); - arr->arr[index] = [object retain]; + arr->arr[index] = CC_ARC_RETAIN(object); arr->num++; } +/** Swaps two objects */ +static inline void ccArraySwapObjectsAtIndexes(ccArray *arr, NSUInteger index1, NSUInteger index2) +{ + NSCAssert(index1 < arr->num, @"(1) Invalid index. Out of bounds"); + NSCAssert(index2 < arr->num, @"(2) Invalid index. Out of bounds"); + + id object1 = arr->arr[index1]; + + arr->arr[index1] = arr->arr[index2]; + arr->arr[index2] = object1; +} + /** Removes all objects from arr */ static inline void ccArrayRemoveAllObjects(ccArray *arr) { while( arr->num > 0 ) - [arr->arr[--arr->num] release]; + CC_ARC_RELEASE(arr->arr[--arr->num]); } /** Removes object at specified index and pushes back all subsequent objects. Behaviour undefined if index outside [0, num-1]. */ static inline void ccArrayRemoveObjectAtIndex(ccArray *arr, NSUInteger index) { - [arr->arr[index] release]; + CC_ARC_RELEASE(arr->arr[index]); arr->num--; - int remaining = arr->num - index; + NSUInteger remaining = arr->num - index; if(remaining>0) - memmove(&arr->arr[index], &arr->arr[index+1], remaining * sizeof(id)); + memmove((void *)&arr->arr[index], (void *)&arr->arr[index+1], remaining * sizeof(id)); } /** Removes object at specified index and fills the gap with the last object, @@ -178,7 +225,7 @@ static inline void ccArrayRemoveObjectAtIndex(ccArray *arr, NSUInteger index) Behaviour undefined if index outside [0, num-1]. */ static inline void ccArrayFastRemoveObjectAtIndex(ccArray *arr, NSUInteger index) { - [arr->arr[index] release]; + CC_ARC_RELEASE(arr->arr[index]); NSUInteger last = --arr->num; arr->arr[index] = arr->arr[last]; } @@ -215,7 +262,7 @@ static inline void ccArrayFullRemoveArray(ccArray *arr, ccArray *minusArr) for( NSUInteger i = 0; i < arr->num; i++) { if( ccArrayContainsObject(minusArr, arr->arr[i]) ) { - [arr->arr[i] release]; + CC_ARC_RELEASE(arr->arr[i]); back++; } else arr->arr[i - back] = arr->arr[i]; @@ -228,13 +275,28 @@ static inline void ccArrayFullRemoveArray(ccArray *arr, ccArray *minusArr) static inline void ccArrayMakeObjectsPerformSelector(ccArray *arr, SEL sel) { for( NSUInteger i = 0; i < arr->num; i++) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" [arr->arr[i] performSelector:sel]; +#pragma clang diagnostic pop } static inline void ccArrayMakeObjectsPerformSelectorWithObject(ccArray *arr, SEL sel, id object) { for( NSUInteger i = 0; i < arr->num; i++) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" [arr->arr[i] performSelector:sel withObject:object]; +#pragma clang diagnostic pop +} + +static inline void ccArrayMakeObjectPerformSelectorWithArrayObjects(ccArray *arr, SEL sel, id object) +{ + for( NSUInteger i = 0; i < arr->num; i++) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [object performSelector:sel withObject:arr->arr[i]]; +#pragma clang diagnostic pop } @@ -252,7 +314,7 @@ static inline ccCArray* ccCArrayNew(NSUInteger capacity) { ccCArray *arr = (ccCArray*)malloc( sizeof(ccCArray) ); arr->num = 0; - arr->arr = (id*) malloc( capacity * sizeof(id) ); + arr->arr = (CCARRAY_ID *) malloc( capacity * sizeof(id) ); arr->max = capacity; return arr; @@ -272,55 +334,55 @@ static inline void ccCArrayFree(ccCArray *arr) /** Doubles C array capacity */ static inline void ccCArrayDoubleCapacity(ccCArray *arr) { - return ccArrayDoubleCapacity(arr); + ccArrayDoubleCapacity(arr); } /** Increases array capacity such that max >= num + extra. */ static inline void ccCArrayEnsureExtraCapacity(ccCArray *arr, NSUInteger extra) { - return ccArrayEnsureExtraCapacity(arr,extra); + ccArrayEnsureExtraCapacity(arr,extra); } /** Returns index of first occurence of value, NSNotFound if value not found. */ -static inline NSUInteger ccCArrayGetIndexOfValue(ccCArray *arr, void* value) +static inline NSUInteger ccCArrayGetIndexOfValue(ccCArray *arr, CCARRAY_ID value) { for( NSUInteger i = 0; i < arr->num; i++) - if( arr->arr[i] == value ) return i; + if( [arr->arr[i] isEqual:value] ) return i; return NSNotFound; } /** Returns a Boolean value that indicates whether value is present in the C array. */ -static inline BOOL ccCArrayContainsValue(ccCArray *arr, void* value) +static inline BOOL ccCArrayContainsValue(ccCArray *arr, CCARRAY_ID value) { return ccCArrayGetIndexOfValue(arr, value) != NSNotFound; } /** Inserts a value at a certain position. Behaviour undefined if aray doesn't have enough capacity */ -static inline void ccCArrayInsertValueAtIndex( ccCArray *arr, void *value, NSUInteger index) +static inline void ccCArrayInsertValueAtIndex( ccCArray *arr, CCARRAY_ID value, NSUInteger index) { - assert( index < arr->max ); + NSCAssert( index < arr->max, @"ccCArrayInsertValueAtIndex: invalid index"); - int remaining = arr->num - index; + NSUInteger remaining = arr->num - index; // last Value doesn't need to be moved if( remaining > 0) { // tex coordinates - memmove( &arr->arr[index+1],&arr->arr[index], sizeof(void*) * remaining ); + memmove((void *)&arr->arr[index+1], (void *)&arr->arr[index], sizeof(void*) * remaining ); } arr->num++; - arr->arr[index] = (id) value; + arr->arr[index] = value; } /** Appends an value. Bahaviour undefined if array doesn't have enough capacity. */ -static inline void ccCArrayAppendValue(ccCArray *arr, void* value) +static inline void ccCArrayAppendValue(ccCArray *arr, CCARRAY_ID value) { arr->arr[arr->num] = (id) value; arr->num++; } /** Appends an value. Capacity of arr is increased if needed. */ -static inline void ccCArrayAppendValueWithResize(ccCArray *arr, void* value) +static inline void ccCArrayAppendValueWithResize(ccCArray *arr, CCARRAY_ID value) { ccCArrayEnsureExtraCapacity(arr, 1); ccCArrayAppendValue(arr, value); @@ -371,7 +433,7 @@ static inline void ccCArrayFastRemoveValueAtIndex(ccCArray *arr, NSUInteger inde /** Searches for the first occurance of value and removes it. If value is not found the function has no effect. @since v0.99.4 */ -static inline void ccCArrayRemoveValue(ccCArray *arr, void* value) +static inline void ccCArrayRemoveValue(ccCArray *arr, CCARRAY_ID value) { NSUInteger index = ccCArrayGetIndexOfValue(arr, value); if (index != NSNotFound) @@ -403,4 +465,90 @@ static inline void ccCArrayFullRemoveArray(ccCArray *arr, ccCArray *minusArr) arr->num -= back; } -#endif // CC_ARRAY_H \ No newline at end of file + +//used by mergesortL +static inline void pointerswap(void* a, void* b, size_t width) +{ + void* tmp; + tmp = *(void**)a; + *(void**)a = *(void**)b; + *(void**)b = tmp; +} + +// iterative mergesort arrd on +// http://www.inf.fh-flensburg.de/lang/algorithmen/sortieren/merge/mergiter.htm +static inline int mergesortL(ccCArray* array, size_t width, int (*compar)(const void *, const void *)) +{ + CCARRAY_ID *arr = array->arr; + NSInteger i,j,k,s,m,n= array->num; + + CCARRAY_ID *B = (CCARRAY_ID*) malloc((n/2 + 1) * width); + for (s = 1; s < n; s += s) + { + for (m = n-1-s; m >= 0; m -= s+s) + { + NSInteger lo = MAX(m-(s+1),0); + NSInteger hi = m+s; + + j = lo; + + if (m-j > 0) + { + memcpy(B, &arr[j], (m-j) * width); + } + + i = 0; + j = m; + k = lo; + + while (knum; + + CCARRAY_ID *x = arr->arr; + id temp; + + // insertion sort + for(i=1; i0 && ( comparator( &x[j-1], &x[j] ) == NSOrderedDescending) ) + { + temp = x[j]; + x[j] = x[j-1]; + x[j-1] = temp; + j--; + } + } +} + +#endif // CC_ARRAY_H diff --git a/libs/cocos2d/Support/ccUtils.c b/libs/cocos2d/Support/ccUtils.c index a509494..39786ec 100644 --- a/libs/cocos2d/Support/ccUtils.c +++ b/libs/cocos2d/Support/ccUtils.c @@ -8,7 +8,7 @@ */ #include "ccUtils.h" -unsigned int ccNextPOT(unsigned int x) +unsigned long ccNextPOT(unsigned long x) { x = x - 1; x = x | (x >> 1); diff --git a/libs/cocos2d/Support/ccUtils.h b/libs/cocos2d/Support/ccUtils.h index 552b268..783fc54 100644 --- a/libs/cocos2d/Support/ccUtils.h +++ b/libs/cocos2d/Support/ccUtils.h @@ -24,6 +24,6 @@ @since v0.99.5 */ -unsigned int ccNextPOT( unsigned int value ); +unsigned long ccNextPOT( unsigned long value ); #endif // ! __CC_UTILS_H diff --git a/libs/cocos2d/Support/uthash.h b/libs/cocos2d/Support/uthash.h index 3a404dc..a4bdc18 100644 --- a/libs/cocos2d/Support/uthash.h +++ b/libs/cocos2d/Support/uthash.h @@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. when compiling c++ source) this code uses whatever method is needed or, for VS2008 where neither is available, uses casting workarounds. */ #ifdef _MSC_VER /* MS compiler */ -#if _MSC_VER >= 1600 && __cplusplus /* VS2010 or newer in C++ mode */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ #define DECLTYPE(x) (decltype(x)) #else /* VS2008 or older (or VS2010 in C mode) */ #define NO_DECLTYPE @@ -62,11 +62,11 @@ typedef unsigned int uint32_t; #include /* uint32_t */ #endif -#define UTHASH_VERSION 1.9 +#define UTHASH_VERSION 1.9.3 #define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */ #define uthash_malloc(sz) malloc(sz) /* malloc fcn */ -#define uthash_free(ptr) free(ptr) /* free fcn */ +#define uthash_free(ptr,sz) free(ptr) /* free fcn */ #define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ #define uthash_expand_fyi(tbl) /* can be defined to log expands */ @@ -106,7 +106,7 @@ do { #define HASH_BLOOM_FREE(tbl) \ do { \ - uthash_free((tbl)->bloom_bv); \ + uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ } while (0); #define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8))) @@ -194,9 +194,10 @@ do { unsigned _hd_bkt; \ struct UT_hash_handle *_hd_hh_del; \ if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \ - uthash_free((head)->hh.tbl->buckets ); \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ head = NULL; \ } else { \ _hd_hh_del = &((delptr)->hh); \ @@ -233,6 +234,10 @@ do { HASH_FIND(hh,head,findint,sizeof(int),out) #define HASH_ADD_INT(head,intfield,add) \ HASH_ADD(hh,head,intfield,sizeof(int),add) +#define HASH_FIND_PTR(head,findptr,out) \ + HASH_FIND(hh,head,findptr,sizeof(void *),out) +#define HASH_ADD_PTR(head,ptrfield,add) \ + HASH_ADD(hh,head,ptrfield,sizeof(void *),add) #define HASH_DEL(head,delptr) \ HASH_DELETE(hh,head,delptr) @@ -321,7 +326,7 @@ do { #define HASH_BER(key,keylen,num_bkts,hashv,bkt) \ do { \ unsigned _hb_keylen=keylen; \ - char *_hb_key=(char*)key; \ + char *_hb_key=(char*)(key); \ (hashv) = 0; \ while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \ bkt = (hashv) & (num_bkts-1); \ @@ -333,7 +338,7 @@ do { #define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \ do { \ unsigned _sx_i; \ - char *_hs_key=(char*)key; \ + char *_hs_key=(char*)(key); \ hashv = 0; \ for(_sx_i=0; _sx_i < keylen; _sx_i++) \ hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ @@ -343,7 +348,7 @@ do { #define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \ do { \ unsigned _fn_i; \ - char *_hf_key=(char*)key; \ + char *_hf_key=(char*)(key); \ hashv = 2166136261UL; \ for(_fn_i=0; _fn_i < keylen; _fn_i++) \ hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \ @@ -353,7 +358,7 @@ do { #define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \ do { \ unsigned _ho_i; \ - char *_ho_key=(char*)key; \ + char *_ho_key=(char*)(key); \ hashv = 0; \ for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ hashv += _ho_key[_ho_i]; \ @@ -382,7 +387,7 @@ do { #define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \ do { \ unsigned _hj_i,_hj_j,_hj_k; \ - char *_hj_key=(char*)key; \ + char *_hj_key=(char*)(key); \ hashv = 0xfeedbeef; \ _hj_i = _hj_j = 0x9e3779b9; \ _hj_k = keylen; \ @@ -433,7 +438,7 @@ do { #endif #define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \ do { \ - char *_sfh_key=(char*)key; \ + char *_sfh_key=(char*)(key); \ uint32_t _sfh_tmp, _sfh_len = keylen; \ \ int _sfh_rem = _sfh_len & 3; \ @@ -498,7 +503,7 @@ do { const unsigned int _mur_m = 0x5bd1e995; \ const int _mur_r = 24; \ hashv = 0xcafebabe ^ keylen; \ - char *_mur_key = (char *)key; \ + char *_mur_key = (char *)(key); \ uint32_t _mur_tmp, _mur_len = keylen; \ \ for (;_mur_len >= 4; _mur_len-=4) { \ @@ -531,8 +536,8 @@ do { do { \ const unsigned int _mur_m = 0x5bd1e995; \ const int _mur_r = 24; \ - hashv = 0xcafebabe ^ keylen; \ - char *_mur_key = (char *)key; \ + hashv = 0xcafebabe ^ (keylen); \ + char *_mur_key = (char *)(key); \ uint32_t _mur_len = keylen; \ int _mur_align = (int)_mur_key & 3; \ \ @@ -732,9 +737,9 @@ do { _he_thh = _he_hh_nxt; \ } \ } \ + uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ tbl->num_buckets *= 2; \ tbl->log2_num_buckets++; \ - uthash_free( tbl->buckets ); \ tbl->buckets = _he_new_buckets; \ tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \ (tbl->ineff_expands+1) : 0; \ @@ -875,15 +880,26 @@ do { #define HASH_CLEAR(hh,head) \ do { \ if (head) { \ - uthash_free((head)->hh.tbl->buckets ); \ - uthash_free((head)->hh.tbl); \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ (head)=NULL; \ } \ } while(0) +#ifdef NO_DECLTYPE +#define HASH_ITER(hh,head,el,tmp) \ +for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \ + el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL)) +#else +#define HASH_ITER(hh,head,el,tmp) \ +for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \ + el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL)) +#endif + /* obtain a count of items in the hash */ #define HASH_COUNT(head) HASH_CNT(hh,head) -#define HASH_CNT(hh,head) (head?(head->hh.tbl->num_items):0) +#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0) typedef struct UT_hash_bucket { struct UT_hash_handle *hh_head; diff --git a/libs/cocos2d/Support/utlist.h b/libs/cocos2d/Support/utlist.h index 99cc6f8..34c725b 100644 --- a/libs/cocos2d/Support/utlist.h +++ b/libs/cocos2d/Support/utlist.h @@ -24,7 +24,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef UTLIST_H #define UTLIST_H -#define UTLIST_VERSION 1.9 +#define UTLIST_VERSION 1.9.1 /* * This file contains macros to manipulate singly and doubly-linked lists. @@ -61,19 +61,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. As decltype is only available in newer compilers (VS2010 or gcc 4.3+ when compiling c++ code), this code uses whatever method is needed or, for VS2008 where neither is available, uses casting workarounds. */ - -#ifndef DECLTYPE #ifdef _MSC_VER /* MS compiler */ -#if _MSC_VER >= 1600 && __cplusplus /* VS2010 and newer in C++ mode */ -#define DECLTYPE(x) decltype(x) +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define LDECLTYPE(x) decltype(x) #else /* VS2008 or older (or VS2010 in C mode) */ #define NO_DECLTYPE -#define DECLTYPE(x) char* +#define LDECLTYPE(x) char* #endif #else /* GNU, Sun and other compilers */ -#define DECLTYPE(x) __typeof(x) +#define LDECLTYPE(x) __typeof(x) #endif -#endif // DECLTYPE /* for VS2008 we use some workarounds to get around the lack of decltype, * namely, we always reassign our tmp variable to the list head if we need @@ -102,12 +99,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ #define LL_SORT(list, cmp) \ do { \ - DECLTYPE(list) _ls_p; \ - DECLTYPE(list) _ls_q; \ - DECLTYPE(list) _ls_e; \ - DECLTYPE(list) _ls_tail; \ - DECLTYPE(list) _ls_oldhead; \ - DECLTYPE(list) _tmp; \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + LDECLTYPE(list) _ls_oldhead; \ + LDECLTYPE(list) _tmp; \ int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ if (list) { \ _ls_insize = 1; \ @@ -158,12 +155,12 @@ do { #define DL_SORT(list, cmp) \ do { \ - DECLTYPE(list) _ls_p; \ - DECLTYPE(list) _ls_q; \ - DECLTYPE(list) _ls_e; \ - DECLTYPE(list) _ls_tail; \ - DECLTYPE(list) _ls_oldhead; \ - DECLTYPE(list) _tmp; \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + LDECLTYPE(list) _ls_oldhead; \ + LDECLTYPE(list) _tmp; \ int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ if (list) { \ _ls_insize = 1; \ @@ -216,13 +213,13 @@ do { #define CDL_SORT(list, cmp) \ do { \ - DECLTYPE(list) _ls_p; \ - DECLTYPE(list) _ls_q; \ - DECLTYPE(list) _ls_e; \ - DECLTYPE(list) _ls_tail; \ - DECLTYPE(list) _ls_oldhead; \ - DECLTYPE(list) _tmp; \ - DECLTYPE(list) _tmp2; \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + LDECLTYPE(list) _ls_oldhead; \ + LDECLTYPE(list) _tmp; \ + LDECLTYPE(list) _tmp2; \ int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ if (list) { \ _ls_insize = 1; \ @@ -295,7 +292,7 @@ do { #define LL_APPEND(head,add) \ do { \ - DECLTYPE(head) _tmp; \ + LDECLTYPE(head) _tmp; \ (add)->next=NULL; \ if (head) { \ _tmp = head; \ @@ -308,7 +305,7 @@ do { #define LL_DELETE(head,del) \ do { \ - DECLTYPE(head) _tmp; \ + LDECLTYPE(head) _tmp; \ if ((head) == (del)) { \ (head)=(head)->next; \ } else { \ diff --git a/libs/cocos2d/ccConfig.h b/libs/cocos2d/ccConfig.h index 5ab8e6e..a853c88 100644 --- a/libs/cocos2d/ccConfig.h +++ b/libs/cocos2d/ccConfig.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -41,7 +42,7 @@ The "correct" way to prevent artifacts is by using the spritesheet-artifact-fixer.py or a similar tool. Affected nodes: - - CCSprite / CCSpriteBatchNode and subclasses: CCBitmapFontAtlas, CCTMXTiledMap + - CCSprite / CCSpriteBatchNode and subclasses: CCLabelBMFont, CCTMXTiledMap - CCLabelAtlas - CCQuadParticleSystem - CCTileMap @@ -50,7 +51,9 @@ @since v0.99.5 */ +#ifndef CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL #define CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL 0 +#endif /** @def CC_FONT_LABEL_SUPPORT @@ -62,7 +65,13 @@ Only valid for cocos2d-ios. Not supported on cocos2d-mac */ +#ifndef CC_FONT_LABEL_SUPPORT +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED #define CC_FONT_LABEL_SUPPORT 1 +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) +#define CC_FONT_LABEL_SUPPORT 0 +#endif +#endif /** @def CC_DIRECTOR_FAST_FPS If enabled, then the FPS will be drawn using CCLabelAtlas (fast rendering). @@ -71,7 +80,9 @@ To enable set it to a value different than 0. Enabled by default. */ +#ifndef CC_DIRECTOR_FAST_FPS #define CC_DIRECTOR_FAST_FPS 1 +#endif /** @def CC_DIRECTOR_FPS_INTERVAL Senconds between FPS updates. @@ -80,7 +91,9 @@ Default value: 0.1f */ +#ifndef CC_DIRECTOR_FPS_INTERVAL #define CC_DIRECTOR_FPS_INTERVAL (0.1f) +#endif /** @def CC_DIRECTOR_DISPATCH_FAST_EVENTS If enabled, and only when it is used with CCFastDirector, the main loop will wait 0.04 seconds to @@ -92,7 +105,9 @@ @warning This feature is experimental */ +#ifndef CC_DIRECTOR_DISPATCH_FAST_EVENTS #define CC_DIRECTOR_DISPATCH_FAST_EVENTS 0 +#endif /** @def CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD If enabled, cocos2d-mac will run on the Display Link thread. If disabled cocos2d-mac will run in its own thread. @@ -105,7 +120,9 @@ Only valid for cocos2d-mac. Not supported on cocos2d-ios. */ +#ifndef CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD #define CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD 1 +#endif /** @def CC_COCOSNODE_RENDER_SUBPIXEL If enabled, the CCNode objects (CCSprite, CCLabel,etc) will be able to render in subpixels. @@ -113,7 +130,9 @@ To enable set it to 1. Enabled by default. */ +#ifndef CC_COCOSNODE_RENDER_SUBPIXEL #define CC_COCOSNODE_RENDER_SUBPIXEL 1 +#endif /** @def CC_SPRITEBATCHNODE_RENDER_SUBPIXEL If enabled, the CCSprite objects rendered with CCSpriteBatchNode will be able to render in subpixels. @@ -121,10 +140,10 @@ To enable set it to 1. Enabled by default. */ +#ifndef CC_SPRITEBATCHNODE_RENDER_SUBPIXEL #define CC_SPRITEBATCHNODE_RENDER_SUBPIXEL 1 +#endif - -#if defined(__ARM_NEON__) || TARGET_IPHONE_SIMULATOR || defined(__MAC_OS_X_VERSION_MAX_ALLOWED) /** @def CC_USES_VBO If enabled, batch nodes (texture atlas and particle system) will use VBO instead of vertex list (VBO is recommended by Apple) @@ -134,10 +153,13 @@ @since v0.99.5 */ +#ifndef CC_USES_VBO +#if defined(__ARM_NEON__) || TARGET_IPHONE_SIMULATOR || defined(__MAC_OS_X_VERSION_MAX_ALLOWED) #define CC_USES_VBO 1 #else #define CC_USES_VBO 0 #endif +#endif /** @def CC_NODE_TRANSFORM_USING_AFFINE_MATRIX If enabled, CCNode will transform the nodes using a cached Affine matrix. @@ -146,12 +168,14 @@ Using the translate/rotate/scale requires 5 GL calls. But computing the Affine matrix is relative expensive. But according to performance tests, Affine matrix performs better. - This parameter doesn't affect SpriteSheet nodes. + This parameter doesn't affect CCSpriteBatchNode nodes. To enable set it to a value different than 0. Enabled by default. */ +#ifndef CC_NODE_TRANSFORM_USING_AFFINE_MATRIX #define CC_NODE_TRANSFORM_USING_AFFINE_MATRIX 1 +#endif /** @def CC_OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA If most of your imamges have pre-multiplied alpha, set it to 1 (if you are going to use .PNG/.JPG file images). @@ -161,7 +185,9 @@ @since v0.99.5 */ +#ifndef CC_OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA #define CC_OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA 1 +#endif /** @def CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP Use GL_TRIANGLE_STRIP instead of GL_TRIANGLES when rendering the texture atlas. @@ -170,8 +196,9 @@ To enable set it to a value different than 0. Disabled by default. */ +#ifndef CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP #define CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP 0 - +#endif /** @def CC_TEXTURE_NPOT_SUPPORT If enabled, NPOT textures will be used where available. Only 3rd gen (and newer) devices support NPOT textures. @@ -181,76 +208,74 @@ To enable set it to a value different than 0. Disabled by default. + This value governs only the PNG, GIF, BMP, images. + This value DOES NOT govern the PVR (PVR.GZ, PVR.CCZ) files. If NPOT PVR is loaded, then it will create an NPOT texture ignoring this value. + + @deprecated This value will be removed in 1.1 and NPOT textures will be loaded by default if the device supports it. + @since v0.99.2 */ +#ifndef CC_TEXTURE_NPOT_SUPPORT #define CC_TEXTURE_NPOT_SUPPORT 0 +#endif -/** @def CC_RETINA_DISPLAY_SUPPORT - If enabled, cocos2d supports retina display. - For performance reasons, it's recommended disable it in games without retina display support, like iPad only games. - - To enable set it to 1. Use 0 to disable it. Enabled by default. - - @since v0.99.5 - */ -#define CC_RETINA_DISPLAY_SUPPORT 1 - -/** @def CC_RETINA_DISPLAY_FILENAME_SUFFIX - It's the suffix that will be appended to the files in order to load "retina display" images. - - On an iPhone4 with Retina Display support enabled, the file @"sprite-hd.png" will be loaded instead of @"sprite.png". - If the file doesn't exist it will use the non-retina display image. - - Platforms: Only used on Retina Display devices like iPhone 4. - - @since v0.99.5 - */ -#define CC_RETINA_DISPLAY_FILENAME_SUFFIX @"-hd" - -/** @def CC_USE_RGBA32_LABELS_ON_NEON_ARCH - If enabled, it will use RGBA8888 (32-bit textures) on Neon devices for CCLabelTTF objects. +/** @def CC_USE_LA88_LABELS_ON_NEON_ARCH + If enabled, it will use LA88 (16-bit textures) on Neon devices for CCLabelTTF objects. If it is disabled, or if it is used on another architecture it will use A8 (8-bit textures). - On Neon devices, RGBA8888 textures are 6% faster than A8 textures, but then will consule 4x memory. + On Neon devices, LA88 textures are 6% faster than A8 textures, but then will consume 2x memory. This feature is disabled by default. Platforms: Only used on ARM Neon architectures like iPhone 3GS or newer and iPad. - + @since v0.99.5 */ -#define CC_USE_RGBA32_LABELS_ON_NEON_ARCH 0 +#ifndef CC_USE_LA88_LABELS_ON_NEON_ARCH +#define CC_USE_LA88_LABELS_ON_NEON_ARCH 0 +#endif /** @def CC_SPRITE_DEBUG_DRAW If enabled, all subclasses of CCSprite will draw a bounding box Useful for debugging purposes only. It is recommened to leave it disabled. - To enable set it to a value different than 0. Disabled by default. + To enable set it to a value different than 0. Disabled by default: + 0 -- disabled + 1 -- draw bounding box + 2 -- draw texture box */ +#ifndef CC_SPRITE_DEBUG_DRAW #define CC_SPRITE_DEBUG_DRAW 0 +#endif /** @def CC_SPRITEBATCHNODE_DEBUG_DRAW - If enabled, all subclasses of CCSprite that are rendered using an CCSpriteSheet draw a bounding box. + If enabled, all subclasses of CCSprite that are rendered using an CCSpriteBatchNode draw a bounding box. Useful for debugging purposes only. It is recommened to leave it disabled. To enable set it to a value different than 0. Disabled by default. */ +#ifndef CC_SPRITEBATCHNODE_DEBUG_DRAW #define CC_SPRITEBATCHNODE_DEBUG_DRAW 0 +#endif -/** @def CC_BITMAPFONTATLAS_DEBUG_DRAW - If enabled, all subclasses of BitmapFontAtlas will draw a bounding box +/** @def CC_LABELBMFONT_DEBUG_DRAW + If enabled, all subclasses of CCLabelBMFont will draw a bounding box Useful for debugging purposes only. It is recommened to leave it disabled. To enable set it to a value different than 0. Disabled by default. */ -#define CC_BITMAPFONTATLAS_DEBUG_DRAW 0 +#ifndef CC_LABELBMFONT_DEBUG_DRAW +#define CC_LABELBMFONT_DEBUG_DRAW 0 +#endif -/** @def CC_LABELATLAS_DEBUG_DRAW - If enabled, all subclasses of LabeltAtlas will draw a bounding box +/** @def CC_LABELBMFONT_DEBUG_DRAW + If enabled, all subclasses of CCLabeltAtlas will draw a bounding box Useful for debugging purposes only. It is recommened to leave it disabled. To enable set it to a value different than 0. Disabled by default. */ +#ifndef CC_LABELATLAS_DEBUG_DRAW #define CC_LABELATLAS_DEBUG_DRAW 0 +#endif /** @def CC_ENABLE_PROFILERS If enabled, will activate various profilers withing cocos2d. This statistical data will be output to the console @@ -259,33 +284,6 @@ To enable set it to a value different than 0. Disabled by default. */ +#ifndef CC_ENABLE_PROFILERS #define CC_ENABLE_PROFILERS 0 - -/** @def CC_COMPATIBILITY_WITH_0_8 - Enable it if you want to support v0.8 compatbility. - Basically, classes without namespaces will work. - It is recommended to disable compatibility once you have migrated your game to v0.9 to avoid class name polution - - To enable set it to a value different than 0. Disabled by default. - */ -#define CC_COMPATIBILITY_WITH_0_8 0 - - -// -// DON'T edit this macro. -// -#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED - -#if CC_RETINA_DISPLAY_SUPPORT -#define CC_IS_RETINA_DISPLAY_SUPPORTED 1 -#else -#define CC_IS_RETINA_DISPLAY_SUPPORTED 0 #endif - -#elif __MAC_OS_X_VERSION_MAX_ALLOWED - -#define CC_IS_RETINA_DISPLAY_SUPPORTED 0 - -#endif - - diff --git a/libs/cocos2d/ccMacros.h b/libs/cocos2d/ccMacros.h index 117066d..fb03ed4 100644 --- a/libs/cocos2d/ccMacros.h +++ b/libs/cocos2d/ccMacros.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -93,6 +94,7 @@ simple macro that swaps 2 variables */ #define CC_RADIANS_TO_DEGREES(__ANGLE__) ((__ANGLE__) * 57.29577951f) // PI * 180 +#define kCCRepeatForever UINT_MAX -1 /** @def CC_BLEND_SRC default gl blend src function. Compatible with premultiplied alpha images. */ @@ -127,8 +129,8 @@ default gl blend src function. Compatible with premultiplied alpha images. */ #define CC_DISABLE_DEFAULT_GL_STATES() { \ glDisable(GL_TEXTURE_2D); \ - glDisableClientState(GL_COLOR_ARRAY); \ glDisableClientState(GL_TEXTURE_COORD_ARRAY); \ + glDisableClientState(GL_COLOR_ARRAY); \ glDisableClientState(GL_VERTEX_ARRAY); \ } @@ -149,6 +151,9 @@ default gl blend src function. Compatible with premultiplied alpha images. @since v0.99.4 */ + +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED + #define CC_DIRECTOR_INIT() \ do { \ window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; \ @@ -170,6 +175,28 @@ do { \ [window addSubview:__glView]; \ [window makeKeyAndVisible]; \ } while(0) + + +#elif __MAC_OS_X_VERSION_MAX_ALLOWED + +#import "Platforms/Mac/MacWindow.h" + +#define CC_DIRECTOR_INIT(__WINSIZE__) \ +do { \ + NSRect frameRect = NSMakeRect(0, 0, (__WINSIZE__).width, (__WINSIZE__).height); \ + self.window = [[MacWindow alloc] initWithFrame:frameRect fullscreen:NO]; \ + self.glView = [[MacGLView alloc] initWithFrame:frameRect shareContext:nil]; \ + [self.window setContentView:self.glView]; \ + CCDirector *__director = [CCDirector sharedDirector]; \ + [__director setDisplayFPS:NO]; \ + [__director setOpenGLView:self.glView]; \ + [(CCDirectorMac*)__director setOriginalWinSize:__WINSIZE__]; \ + [self.window makeMainWindow]; \ + [self.window makeKeyAndOrderFront:self]; \ +} while(0) + +#endif + /** @def CC_DIRECTOR_END Stops and removes the director from memory. @@ -186,7 +213,9 @@ do { \ } while(0) -#if CC_IS_RETINA_DISPLAY_SUPPORTED + + +#if __IPHONE_OS_VERSION_MAX_ALLOWED /****************************/ /** RETINA DISPLAY ENABLED **/ @@ -214,7 +243,7 @@ do { \ CGRectMake( (__points__).origin.x * CC_CONTENT_SCALE_FACTOR(), (__points__).origin.y * CC_CONTENT_SCALE_FACTOR(), \ (__points__).size.width * CC_CONTENT_SCALE_FACTOR(), (__points__).size.height * CC_CONTENT_SCALE_FACTOR() ) -#else // retina disabled +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) /*****************************/ /** RETINA DISPLAY DISABLED **/ @@ -224,4 +253,25 @@ do { \ #define CC_RECT_PIXELS_TO_POINTS(__pixels__) __pixels__ #define CC_RECT_POINTS_TO_PIXELS(__points__) __points__ -#endif // CC_IS_RETINA_DISPLAY_SUPPORTED +#endif // __MAC_OS_X_VERSION_MAX_ALLOWED + +/*****************/ +/** ARC Macros **/ +/*****************/ +#if defined(__has_feature) && __has_feature(objc_arc) +// ARC (used for inline functions) +#define CC_ARC_RETAIN(value) value +#define CC_ARC_RELEASE(value) value = 0 +#define CC_ARC_UNSAFE_RETAINED __unsafe_unretained + +#else +// No ARC +#define CC_ARC_RETAIN(value) [value retain] +#define CC_ARC_RELEASE(value) [value release] +#define CC_ARC_UNSAFE_RETAINED +#endif + +/*******************/ +/** Notifications **/ +/*******************/ +#define CCAnimationFrameDisplayedNotification @"CCAnimationFrameDisplayedNotification" diff --git a/libs/cocos2d/ccTypes.h b/libs/cocos2d/ccTypes.h index 65a73dd..3863603 100644 --- a/libs/cocos2d/ccTypes.h +++ b/libs/cocos2d/ccTypes.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -102,6 +103,12 @@ typedef struct _ccColor4F { GLfloat b; GLfloat a; } ccColor4F; +//! helper that creates a ccColor4f type +static inline ccColor4F +ccc4f(const GLfloat r, const GLfloat g, const GLfloat b, const GLfloat a) +{ + return (ccColor4F){r, g, b, a}; +} /** Returns a ccColor4F from a ccColor3B. Alpha will be 1. @since v0.99.1 @@ -159,7 +166,7 @@ typedef struct _ccTex2F { typedef struct _ccPointSprite { ccVertex2F pos; // 8 bytes - ccColor4F colors; // 16 bytes + ccColor4B color; // 4 bytes GLfloat size; // 4 bytes } ccPointSprite; @@ -195,6 +202,17 @@ ccg(const NSInteger x, const NSInteger y) return v; } +//! a Point with a vertex point, a tex coord point and a color 4B +typedef struct _ccV2F_C4B_T2F +{ + //! vertices (2F) + ccVertex2F vertices; + //! colors (4B) + ccColor4B colors; + //! tex coords (2F) + ccTex2F texCoords; +} ccV2F_C4B_T2F; + //! a Point with a vertex point, a tex coord point and a color 4F typedef struct _ccV2F_C4F_T2F { @@ -221,6 +239,19 @@ typedef struct _ccV3F_C4B_T2F ccTex2F texCoords; // 8 byts } ccV3F_C4B_T2F; +//! 4 ccVertex2FTex2FColor4B Quad +typedef struct _ccV2F_C4B_T2F_Quad +{ + //! bottom left + ccV2F_C4B_T2F bl; + //! bottom right + ccV2F_C4B_T2F br; + //! top left + ccV2F_C4B_T2F tl; + //! top right + ccV2F_C4B_T2F tr; +} ccV2F_C4B_T2F_Quad; + //! 4 ccVertex3FTex2FColor4B typedef struct _ccV3F_C4B_T2F_Quad { @@ -256,7 +287,46 @@ typedef struct _ccBlendFunc GLenum dst; } ccBlendFunc; +//! ccResolutionType +typedef enum +{ + //! Unknonw resolution type + kCCResolutionUnknown, + //! iPhone resolution type + kCCResolutioniPhone, + //! RetinaDisplay resolution type + kCCResolutioniPhoneRetinaDisplay, + //! iPad resolution type + kCCResolutioniPad, + //! iPad Retina Display resolution type + kCCResolutioniPadRetinaDisplay, + +} ccResolutionType; + //! delta time type //! if you want more resolution redefine it as a double typedef float ccTime; //typedef double ccTime; + +// types for animation in particle systems + +// texture coordinates for a quad +typedef struct _ccT2F_Quad +{ + //! bottom left + ccTex2F bl; + //! bottom right + ccTex2F br; + //! top left + ccTex2F tl; + //! top right + ccTex2F tr; +} ccT2F_Quad; + +// struct that holds the size in pixels, texture coordinates and delays for animated CCParticleSystemQuad +typedef struct +{ + ccT2F_Quad texCoords; + ccTime delay; + CGSize size; +} ccAnimationFrameData; diff --git a/libs/cocos2d/cocos2d.h b/libs/cocos2d/cocos2d.h index 96a0e9c..6b0b17a 100644 --- a/libs/cocos2d/cocos2d.h +++ b/libs/cocos2d/cocos2d.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,8 +39,8 @@ */ // 0x00 HI ME LO -// 00 00 99 05 -#define COCOS2D_VERSION 0x00009905 +// 00 01 01 00 +#define COCOS2D_VERSION 0x00010100 #import @@ -66,7 +67,6 @@ #import "CCAnimationCache.h" #import "CCSprite.h" #import "CCSpriteFrame.h" -#import "CCSpriteSheet.h" #import "CCSpriteBatchNode.h" #import "CCSpriteFrameCache.h" @@ -78,6 +78,7 @@ #import "CCParticleSystemPoint.h" #import "CCParticleSystemQuad.h" #import "CCParticleExamples.h" +#import "CCParticleBatchNode.h" #import "CCTexture2D.h" #import "CCTexturePVR.h" @@ -151,10 +152,6 @@ #endif // CC_ENABLE_PROFILERS -// compatibility with v0.8 -#import "CCCompatibility.h" - - // free functions NSString * cocos2dVersion(void); diff --git a/libs/cocos2d/cocos2d.m b/libs/cocos2d/cocos2d.m index 619d367..6d5ab2a 100644 --- a/libs/cocos2d/cocos2d.m +++ b/libs/cocos2d/cocos2d.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,8 +25,8 @@ #import - -static NSString *version = @"cocos2d v0.99.5"; +#import "cocos2d.h" +static NSString *version = @"cocos2d v1.1.0-beta2b"; NSString *cocos2dVersion() { diff --git a/libs/cocoslive/CLScoreServerPost.h b/libs/cocoslive/CLScoreServerPost.h index 3954fa4..7bcaa51 100644 --- a/libs/cocoslive/CLScoreServerPost.h +++ b/libs/cocoslive/CLScoreServerPost.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/libs/cocoslive/CLScoreServerPost.m b/libs/cocoslive/CLScoreServerPost.m index e5a0388..43ee7b2 100644 --- a/libs/cocoslive/CLScoreServerPost.m +++ b/libs/cocoslive/CLScoreServerPost.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,6 +29,8 @@ #import "ccMacros.h" // free function used to sort +NSInteger alphabeticSort(id string1, id string2, void *reverse); + NSInteger alphabeticSort(id string1, id string2, void *reverse) { if ((NSInteger *)reverse == NO) @@ -135,7 +138,7 @@ -(BOOL) submitScore: (NSDictionary*)dict forUpdate:(BOOL)isUpdate // create the connection with the request // and start loading the data - self.connection=[[NSURLConnection alloc] initWithRequest:post delegate:self]; + self.connection=[NSURLConnection connectionWithRequest:post delegate:self]; if ( ! connection_) return NO; diff --git a/libs/cocoslive/CLScoreServerRequest.h b/libs/cocoslive/CLScoreServerRequest.h index 5428b23..61a5d7f 100644 --- a/libs/cocoslive/CLScoreServerRequest.h +++ b/libs/cocoslive/CLScoreServerRequest.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/libs/cocoslive/CLScoreServerRequest.m b/libs/cocoslive/CLScoreServerRequest.m index 2e6bc76..8c1c44f 100644 --- a/libs/cocoslive/CLScoreServerRequest.m +++ b/libs/cocoslive/CLScoreServerRequest.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,7 +31,7 @@ // local imports #import "CLScoreServerPost.h" #import "CLScoreServerRequest.h" -#import "ccMacros.h" +#import "../cocos2d/ccMacros.h" @implementation CLScoreServerRequest @@ -104,7 +105,7 @@ -(BOOL) requestScores:(tQueryType)type // create the connection with the request // and start loading the data - self.connection=[[NSURLConnection alloc] initWithRequest:request delegate:self]; + self.connection=[NSURLConnection connectionWithRequest:request delegate:self]; if (! connection_) return NO; @@ -166,7 +167,7 @@ -(BOOL) requestRankForScore:(int)score andCategory:(NSString*)category { // create the connection with the request // and start loading the data - self.connection=[[NSURLConnection alloc] initWithRequest:request delegate:self]; + self.connection=[NSURLConnection connectionWithRequest:request delegate:self]; if (! connection_) return NO; diff --git a/libs/cocoslive/cocoslive.h b/libs/cocoslive/cocoslive.h index 2c7dfe4..15dbe1a 100644 --- a/libs/cocoslive/cocoslive.h +++ b/libs/cocoslive/cocoslive.h @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,4 +40,4 @@ // free functions -NSString * cocos2dVersion(void); +NSString * cocosLiveVersion(void); diff --git a/libs/cocoslive/cocoslive.m b/libs/cocoslive/cocoslive.m index 2883659..613a9d7 100644 --- a/libs/cocoslive/cocoslive.m +++ b/libs/cocoslive/cocoslive.m @@ -2,6 +2,7 @@ * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +27,8 @@ #import +#import "cocoslive.h" + static NSString *version = @"cocoslive v0.3.2"; NSString *cocosLiveVersion()