From 9cd57b731ab1c666d4a1cb725538fdc137763d12 Mon Sep 17 00:00:00 2001 From: Starla Insigna Date: Sat, 30 Jul 2011 11:19:14 -0400 Subject: Initial commit (version 0.2.1) --- libs/cocos2d/CCSpriteFrameCache.m | 347 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 347 insertions(+) create mode 100755 libs/cocos2d/CCSpriteFrameCache.m (limited to 'libs/cocos2d/CCSpriteFrameCache.m') diff --git a/libs/cocos2d/CCSpriteFrameCache.m b/libs/cocos2d/CCSpriteFrameCache.m new file mode 100755 index 0000000..f154c3d --- /dev/null +++ b/libs/cocos2d/CCSpriteFrameCache.m @@ -0,0 +1,347 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * 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 + * 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. + * + */ + +/* + * To create sprite frames and texture atlas, use this tool: + * http://zwoptex.zwopple.com/ + */ + +#import "Platforms/CCNS.h" +#import "ccMacros.h" +#import "CCTextureCache.h" +#import "CCSpriteFrameCache.h" +#import "CCSpriteFrame.h" +#import "CCSprite.h" +#import "Support/CCFileUtils.h" + + +@implementation CCSpriteFrameCache + +#pragma mark CCSpriteFrameCache - Alloc, Init & Dealloc + +static CCSpriteFrameCache *sharedSpriteFrameCache_=nil; + ++ (CCSpriteFrameCache *)sharedSpriteFrameCache +{ + if (!sharedSpriteFrameCache_) + sharedSpriteFrameCache_ = [[CCSpriteFrameCache alloc] init]; + + return sharedSpriteFrameCache_; +} + ++(id)alloc +{ + NSAssert(sharedSpriteFrameCache_ == nil, @"Attempted to allocate a second instance of a singleton."); + return [super alloc]; +} + ++(void)purgeSharedSpriteFrameCache +{ + [sharedSpriteFrameCache_ release]; + sharedSpriteFrameCache_ = nil; +} + +-(id) init +{ + if( (self=[super init]) ) { + spriteFrames_ = [[NSMutableDictionary alloc] initWithCapacity: 100]; + spriteFramesAliases_ = [[NSMutableDictionary alloc] initWithCapacity:10]; + } + + return self; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %08X | num of sprite frames = %i>", [self class], self, [spriteFrames_ count]]; +} + +-(void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + + [spriteFrames_ release]; + [spriteFramesAliases_ release]; + [super dealloc]; +} + +#pragma mark CCSpriteFrameCache - loading sprite frames + +-(void) addSpriteFramesWithDictionary:(NSDictionary*)dictionary texture:(CCTexture2D*)texture +{ + /* + Supported Zwoptex Formats: + ZWTCoordinatesFormatOptionXMLLegacy = 0, // Flash Version + ZWTCoordinatesFormatOptionXML1_0 = 1, // Desktop Version 0.0 - 0.4b + ZWTCoordinatesFormatOptionXML1_1 = 2, // Desktop Version 1.0.0 - 1.0.1 + ZWTCoordinatesFormatOptionXML1_2 = 3, // Desktop Version 1.0.2+ + */ + NSDictionary *metadataDict = [dictionary objectForKey:@"metadata"]; + NSDictionary *framesDict = [dictionary objectForKey:@"frames"]; + + int format = 0; + + // get the format + if(metadataDict != nil) + format = [[metadataDict objectForKey:@"format"] intValue]; + + // check the format + NSAssert( format >= 0 && format <= 3, @"cocos2d: WARNING: format is not supported for CCSpriteFrameCache addSpriteFramesWithDictionary:texture:"); + + + // add real frames + for(NSString *frameDictKey in framesDict) { + NSDictionary *frameDict = [framesDict objectForKey:frameDictKey]; + CCSpriteFrame *spriteFrame; + if(format == 0) { + float x = [[frameDict objectForKey:@"x"] floatValue]; + float y = [[frameDict objectForKey:@"y"] floatValue]; + float w = [[frameDict objectForKey:@"width"] floatValue]; + float h = [[frameDict objectForKey:@"height"] floatValue]; + float ox = [[frameDict objectForKey:@"offsetX"] floatValue]; + float oy = [[frameDict objectForKey:@"offsetY"] floatValue]; + int ow = [[frameDict objectForKey:@"originalWidth"] intValue]; + int oh = [[frameDict objectForKey:@"originalHeight"] intValue]; + // check ow/oh + if(!ow || !oh) + CCLOG(@"cocos2d: WARNING: originalWidth/Height not found on the CCSpriteFrame. AnchorPoint won't work as expected. Regenerate the .plist"); + + // abs ow/oh + ow = abs(ow); + oh = abs(oh); + // create frame + + spriteFrame = [[CCSpriteFrame alloc] initWithTexture:texture + rectInPixels:CGRectMake(x, y, w, h) + rotated:NO + offset:CGPointMake(ox, oy) + originalSize:CGSizeMake(ow, oh)]; + } else if(format == 1 || format == 2) { + CGRect frame = CCRectFromString([frameDict objectForKey:@"frame"]); + BOOL rotated = NO; + + // rotation + if(format == 2) + rotated = [[frameDict objectForKey:@"rotated"] boolValue]; + + CGPoint offset = CCPointFromString([frameDict objectForKey:@"offset"]); + CGSize sourceSize = CCSizeFromString([frameDict objectForKey:@"sourceSize"]); + + // create frame + spriteFrame = [[CCSpriteFrame alloc] initWithTexture:texture + rectInPixels:frame + rotated:rotated + offset:offset + originalSize:sourceSize]; + } else if(format == 3) { + // get values + CGSize spriteSize = CCSizeFromString([frameDict objectForKey:@"spriteSize"]); + CGPoint spriteOffset = CCPointFromString([frameDict objectForKey:@"spriteOffset"]); + CGSize spriteSourceSize = CCSizeFromString([frameDict objectForKey:@"spriteSourceSize"]); + CGRect textureRect = CCRectFromString([frameDict objectForKey:@"textureRect"]); + BOOL textureRotated = [[frameDict objectForKey:@"textureRotated"] boolValue]; + + // get aliases + NSArray *aliases = [frameDict objectForKey:@"aliases"]; + for(NSString *alias in aliases) { + if( [spriteFramesAliases_ objectForKey:alias] ) + CCLOG(@"cocos2d: WARNING: an alias with name %@ already exists",alias); + + [spriteFramesAliases_ setObject:frameDictKey forKey:alias]; + } + + // create frame + spriteFrame = [[CCSpriteFrame alloc] initWithTexture:texture + rectInPixels:CGRectMake(textureRect.origin.x, textureRect.origin.y, spriteSize.width, spriteSize.height) + rotated:textureRotated + offset:spriteOffset + originalSize:spriteSourceSize]; + } + + // add sprite frame + [spriteFrames_ setObject:spriteFrame forKey:frameDictKey]; + [spriteFrame release]; + } +} + +-(void) addSpriteFramesWithFile:(NSString*)plist texture:(CCTexture2D*)texture +{ + NSString *path = [CCFileUtils fullPathFromRelativePath:plist]; + NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; + + [self addSpriteFramesWithDictionary:dict texture:texture]; +} + +-(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName +{ + NSAssert( textureFileName, @"Invalid texture file name"); + CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:textureFileName]; + + if( texture ) + [self addSpriteFramesWithFile:plist texture:texture]; + else + CCLOG(@"cocos2d: CCSpriteFrameCache: couldn't load texture file. File not found: %@", textureFileName); +} + +-(void) addSpriteFramesWithFile:(NSString*)plist +{ + NSString *path = [CCFileUtils fullPathFromRelativePath:plist]; + NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; + + NSString *texturePath = nil; + NSDictionary *metadataDict = [dict objectForKey:@"metadata"]; + if( metadataDict ) + // try to read texture file name from meta data + texturePath = [metadataDict objectForKey:@"textureFileName"]; + + + if( texturePath ) + { + // build texture path relative to plist file + NSString *textureBase = [plist stringByDeletingLastPathComponent]; + texturePath = [textureBase stringByAppendingPathComponent:texturePath]; + } else { + // build texture path by replacing file extension + texturePath = [plist stringByDeletingPathExtension]; + texturePath = [texturePath stringByAppendingPathExtension:@"png"]; + + CCLOG(@"cocos2d: CCSpriteFrameCache: Trying to use file '%@' as texture", texturePath); + } + + CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:texturePath]; + + if( texture ) + [self addSpriteFramesWithDictionary:dict texture:texture]; + + else + CCLOG(@"cocos2d: CCSpriteFrameCache: Couldn't load texture"); +} + +-(void) addSpriteFrame:(CCSpriteFrame*)frame name:(NSString*)frameName +{ + [spriteFrames_ setObject:frame forKey:frameName]; +} + +#pragma mark CCSpriteFrameCache - removing + +-(void) removeSpriteFrames +{ + [spriteFrames_ removeAllObjects]; + [spriteFramesAliases_ removeAllObjects]; +} + +-(void) removeUnusedSpriteFrames +{ + NSArray *keys = [spriteFrames_ allKeys]; + for( id key in keys ) { + id value = [spriteFrames_ objectForKey:key]; + if( [value retainCount] == 1 ) { + CCLOG(@"cocos2d: CCSpriteFrameCache: removing unused frame: %@", key); + [spriteFrames_ removeObjectForKey:key]; + } + } +} + +-(void) removeSpriteFrameByName:(NSString*)name +{ + // explicit nil handling + if( ! name ) + return; + + // Is this an alias ? + NSString *key = [spriteFramesAliases_ objectForKey:name]; + + if( key ) { + [spriteFrames_ removeObjectForKey:key]; + [spriteFramesAliases_ removeObjectForKey:name]; + + } else + [spriteFrames_ removeObjectForKey:name]; +} + +- (void) removeSpriteFramesFromFile:(NSString*) plist +{ + NSString *path = [CCFileUtils fullPathFromRelativePath:plist]; + NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; + + [self removeSpriteFramesFromDictionary:dict]; +} + +- (void) removeSpriteFramesFromDictionary:(NSDictionary*) dictionary +{ + NSDictionary *framesDict = [dictionary objectForKey:@"frames"]; + NSMutableArray *keysToRemove=[NSMutableArray array]; + + for(NSString *frameDictKey in framesDict) + { + if ([spriteFrames_ objectForKey:frameDictKey]!=nil) + [keysToRemove addObject:frameDictKey]; + } + [spriteFrames_ removeObjectsForKeys:keysToRemove]; +} + +- (void) removeSpriteFramesFromTexture:(CCTexture2D*) texture +{ + NSMutableArray *keysToRemove=[NSMutableArray array]; + + for (NSString *spriteFrameKey in spriteFrames_) + { + if ([[spriteFrames_ valueForKey:spriteFrameKey] texture] == texture) + [keysToRemove addObject:spriteFrameKey]; + + } + [spriteFrames_ removeObjectsForKeys:keysToRemove]; +} + +#pragma mark CCSpriteFrameCache - getting + +-(CCSpriteFrame*) spriteFrameByName:(NSString*)name +{ + CCSpriteFrame *frame = [spriteFrames_ objectForKey:name]; + if( ! frame ) { + // try alias dictionary + NSString *key = [spriteFramesAliases_ objectForKey:name]; + frame = [spriteFrames_ objectForKey:key]; + + if( ! frame ) + CCLOG(@"cocos2d: CCSpriteFrameCache: Frame '%@' not found", name); + } + + return frame; +} + +#pragma mark CCSpriteFrameCache - sprite creation + +-(CCSprite*) createSpriteWithFrameName:(NSString*)name +{ + CCSpriteFrame *frame = [spriteFrames_ objectForKey:name]; + return [CCSprite spriteWithSpriteFrame:frame]; +} +@end -- cgit 1.4.1