diff options
Diffstat (limited to 'libs/cocos2d/CCSpriteFrameCache.m')
-rwxr-xr-x | libs/cocos2d/CCSpriteFrameCache.m | 347 |
1 files changed, 347 insertions, 0 deletions
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 @@ | |||
1 | /* | ||
2 | * cocos2d for iPhone: http://www.cocos2d-iphone.org | ||
3 | * | ||
4 | * Copyright (c) 2009 Jason Booth | ||
5 | * | ||
6 | * Copyright (c) 2009 Robert J Payne | ||
7 | * | ||
8 | * Copyright (c) 2008-2010 Ricardo Quesada | ||
9 | * Copyright (c) 2011 Zynga Inc. | ||
10 | * | ||
11 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
12 | * of this software and associated documentation files (the "Software"), to deal | ||
13 | * in the Software without restriction, including without limitation the rights | ||
14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
15 | * copies of the Software, and to permit persons to whom the Software is | ||
16 | * furnished to do so, subject to the following conditions: | ||
17 | * | ||
18 | * The above copyright notice and this permission notice shall be included in | ||
19 | * all copies or substantial portions of the Software. | ||
20 | * | ||
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
27 | * THE SOFTWARE. | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | /* | ||
32 | * To create sprite frames and texture atlas, use this tool: | ||
33 | * http://zwoptex.zwopple.com/ | ||
34 | */ | ||
35 | |||
36 | #import "Platforms/CCNS.h" | ||
37 | #import "ccMacros.h" | ||
38 | #import "CCTextureCache.h" | ||
39 | #import "CCSpriteFrameCache.h" | ||
40 | #import "CCSpriteFrame.h" | ||
41 | #import "CCSprite.h" | ||
42 | #import "Support/CCFileUtils.h" | ||
43 | |||
44 | |||
45 | @implementation CCSpriteFrameCache | ||
46 | |||
47 | #pragma mark CCSpriteFrameCache - Alloc, Init & Dealloc | ||
48 | |||
49 | static CCSpriteFrameCache *sharedSpriteFrameCache_=nil; | ||
50 | |||
51 | + (CCSpriteFrameCache *)sharedSpriteFrameCache | ||
52 | { | ||
53 | if (!sharedSpriteFrameCache_) | ||
54 | sharedSpriteFrameCache_ = [[CCSpriteFrameCache alloc] init]; | ||
55 | |||
56 | return sharedSpriteFrameCache_; | ||
57 | } | ||
58 | |||
59 | +(id)alloc | ||
60 | { | ||
61 | NSAssert(sharedSpriteFrameCache_ == nil, @"Attempted to allocate a second instance of a singleton."); | ||
62 | return [super alloc]; | ||
63 | } | ||
64 | |||
65 | +(void)purgeSharedSpriteFrameCache | ||
66 | { | ||
67 | [sharedSpriteFrameCache_ release]; | ||
68 | sharedSpriteFrameCache_ = nil; | ||
69 | } | ||
70 | |||
71 | -(id) init | ||
72 | { | ||
73 | if( (self=[super init]) ) { | ||
74 | spriteFrames_ = [[NSMutableDictionary alloc] initWithCapacity: 100]; | ||
75 | spriteFramesAliases_ = [[NSMutableDictionary alloc] initWithCapacity:10]; | ||
76 | } | ||
77 | |||
78 | return self; | ||
79 | } | ||
80 | |||
81 | - (NSString*) description | ||
82 | { | ||
83 | return [NSString stringWithFormat:@"<%@ = %08X | num of sprite frames = %i>", [self class], self, [spriteFrames_ count]]; | ||
84 | } | ||
85 | |||
86 | -(void) dealloc | ||
87 | { | ||
88 | CCLOGINFO(@"cocos2d: deallocing %@", self); | ||
89 | |||
90 | [spriteFrames_ release]; | ||
91 | [spriteFramesAliases_ release]; | ||
92 | [super dealloc]; | ||
93 | } | ||
94 | |||
95 | #pragma mark CCSpriteFrameCache - loading sprite frames | ||
96 | |||
97 | -(void) addSpriteFramesWithDictionary:(NSDictionary*)dictionary texture:(CCTexture2D*)texture | ||
98 | { | ||
99 | /* | ||
100 | Supported Zwoptex Formats: | ||
101 | ZWTCoordinatesFormatOptionXMLLegacy = 0, // Flash Version | ||
102 | ZWTCoordinatesFormatOptionXML1_0 = 1, // Desktop Version 0.0 - 0.4b | ||
103 | ZWTCoordinatesFormatOptionXML1_1 = 2, // Desktop Version 1.0.0 - 1.0.1 | ||
104 | ZWTCoordinatesFormatOptionXML1_2 = 3, // Desktop Version 1.0.2+ | ||
105 | */ | ||
106 | NSDictionary *metadataDict = [dictionary objectForKey:@"metadata"]; | ||
107 | NSDictionary *framesDict = [dictionary objectForKey:@"frames"]; | ||
108 | |||
109 | int format = 0; | ||
110 | |||
111 | // get the format | ||
112 | if(metadataDict != nil) | ||
113 | format = [[metadataDict objectForKey:@"format"] intValue]; | ||
114 | |||
115 | // check the format | ||
116 | NSAssert( format >= 0 && format <= 3, @"cocos2d: WARNING: format is not supported for CCSpriteFrameCache addSpriteFramesWithDictionary:texture:"); | ||
117 | |||
118 | |||
119 | // add real frames | ||
120 | for(NSString *frameDictKey in framesDict) { | ||
121 | NSDictionary *frameDict = [framesDict objectForKey:frameDictKey]; | ||
122 | CCSpriteFrame *spriteFrame; | ||
123 | if(format == 0) { | ||
124 | float x = [[frameDict objectForKey:@"x"] floatValue]; | ||
125 | float y = [[frameDict objectForKey:@"y"] floatValue]; | ||
126 | float w = [[frameDict objectForKey:@"width"] floatValue]; | ||
127 | float h = [[frameDict objectForKey:@"height"] floatValue]; | ||
128 | float ox = [[frameDict objectForKey:@"offsetX"] floatValue]; | ||
129 | float oy = [[frameDict objectForKey:@"offsetY"] floatValue]; | ||
130 | int ow = [[frameDict objectForKey:@"originalWidth"] intValue]; | ||
131 | int oh = [[frameDict objectForKey:@"originalHeight"] intValue]; | ||
132 | // check ow/oh | ||
133 | if(!ow || !oh) | ||
134 | CCLOG(@"cocos2d: WARNING: originalWidth/Height not found on the CCSpriteFrame. AnchorPoint won't work as expected. Regenerate the .plist"); | ||
135 | |||
136 | // abs ow/oh | ||
137 | ow = abs(ow); | ||
138 | oh = abs(oh); | ||
139 | // create frame | ||
140 | |||
141 | spriteFrame = [[CCSpriteFrame alloc] initWithTexture:texture | ||
142 | rectInPixels:CGRectMake(x, y, w, h) | ||
143 | rotated:NO | ||
144 | offset:CGPointMake(ox, oy) | ||
145 | originalSize:CGSizeMake(ow, oh)]; | ||
146 | } else if(format == 1 || format == 2) { | ||
147 | CGRect frame = CCRectFromString([frameDict objectForKey:@"frame"]); | ||
148 | BOOL rotated = NO; | ||
149 | |||
150 | // rotation | ||
151 | if(format == 2) | ||
152 | rotated = [[frameDict objectForKey:@"rotated"] boolValue]; | ||
153 | |||
154 | CGPoint offset = CCPointFromString([frameDict objectForKey:@"offset"]); | ||
155 | CGSize sourceSize = CCSizeFromString([frameDict objectForKey:@"sourceSize"]); | ||
156 | |||
157 | // create frame | ||
158 | spriteFrame = [[CCSpriteFrame alloc] initWithTexture:texture | ||
159 | rectInPixels:frame | ||
160 | rotated:rotated | ||
161 | offset:offset | ||
162 | originalSize:sourceSize]; | ||
163 | } else if(format == 3) { | ||
164 | // get values | ||
165 | CGSize spriteSize = CCSizeFromString([frameDict objectForKey:@"spriteSize"]); | ||
166 | CGPoint spriteOffset = CCPointFromString([frameDict objectForKey:@"spriteOffset"]); | ||
167 | CGSize spriteSourceSize = CCSizeFromString([frameDict objectForKey:@"spriteSourceSize"]); | ||
168 | CGRect textureRect = CCRectFromString([frameDict objectForKey:@"textureRect"]); | ||
169 | BOOL textureRotated = [[frameDict objectForKey:@"textureRotated"] boolValue]; | ||
170 | |||
171 | // get aliases | ||
172 | NSArray *aliases = [frameDict objectForKey:@"aliases"]; | ||
173 | for(NSString *alias in aliases) { | ||
174 | if( [spriteFramesAliases_ objectForKey:alias] ) | ||
175 | CCLOG(@"cocos2d: WARNING: an alias with name %@ already exists",alias); | ||
176 | |||
177 | [spriteFramesAliases_ setObject:frameDictKey forKey:alias]; | ||
178 | } | ||
179 | |||
180 | // create frame | ||
181 | spriteFrame = [[CCSpriteFrame alloc] initWithTexture:texture | ||
182 | rectInPixels:CGRectMake(textureRect.origin.x, textureRect.origin.y, spriteSize.width, spriteSize.height) | ||
183 | rotated:textureRotated | ||
184 | offset:spriteOffset | ||
185 | originalSize:spriteSourceSize]; | ||
186 | } | ||
187 | |||
188 | // add sprite frame | ||
189 | [spriteFrames_ setObject:spriteFrame forKey:frameDictKey]; | ||
190 | [spriteFrame release]; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | -(void) addSpriteFramesWithFile:(NSString*)plist texture:(CCTexture2D*)texture | ||
195 | { | ||
196 | NSString *path = [CCFileUtils fullPathFromRelativePath:plist]; | ||
197 | NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; | ||
198 | |||
199 | [self addSpriteFramesWithDictionary:dict texture:texture]; | ||
200 | } | ||
201 | |||
202 | -(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName | ||
203 | { | ||
204 | NSAssert( textureFileName, @"Invalid texture file name"); | ||
205 | CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:textureFileName]; | ||
206 | |||
207 | if( texture ) | ||
208 | [self addSpriteFramesWithFile:plist texture:texture]; | ||
209 | else | ||
210 | CCLOG(@"cocos2d: CCSpriteFrameCache: couldn't load texture file. File not found: %@", textureFileName); | ||
211 | } | ||
212 | |||
213 | -(void) addSpriteFramesWithFile:(NSString*)plist | ||
214 | { | ||
215 | NSString *path = [CCFileUtils fullPathFromRelativePath:plist]; | ||
216 | NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; | ||
217 | |||
218 | NSString *texturePath = nil; | ||
219 | NSDictionary *metadataDict = [dict objectForKey:@"metadata"]; | ||
220 | if( metadataDict ) | ||
221 | // try to read texture file name from meta data | ||
222 | texturePath = [metadataDict objectForKey:@"textureFileName"]; | ||
223 | |||
224 | |||
225 | if( texturePath ) | ||
226 | { | ||
227 | // build texture path relative to plist file | ||
228 | NSString *textureBase = [plist stringByDeletingLastPathComponent]; | ||
229 | texturePath = [textureBase stringByAppendingPathComponent:texturePath]; | ||
230 | } else { | ||
231 | // build texture path by replacing file extension | ||
232 | texturePath = [plist stringByDeletingPathExtension]; | ||
233 | texturePath = [texturePath stringByAppendingPathExtension:@"png"]; | ||
234 | |||
235 | CCLOG(@"cocos2d: CCSpriteFrameCache: Trying to use file '%@' as texture", texturePath); | ||
236 | } | ||
237 | |||
238 | CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:texturePath]; | ||
239 | |||
240 | if( texture ) | ||
241 | [self addSpriteFramesWithDictionary:dict texture:texture]; | ||
242 | |||
243 | else | ||
244 | CCLOG(@"cocos2d: CCSpriteFrameCache: Couldn't load texture"); | ||
245 | } | ||
246 | |||
247 | -(void) addSpriteFrame:(CCSpriteFrame*)frame name:(NSString*)frameName | ||
248 | { | ||
249 | [spriteFrames_ setObject:frame forKey:frameName]; | ||
250 | } | ||
251 | |||
252 | #pragma mark CCSpriteFrameCache - removing | ||
253 | |||
254 | -(void) removeSpriteFrames | ||
255 | { | ||
256 | [spriteFrames_ removeAllObjects]; | ||
257 | [spriteFramesAliases_ removeAllObjects]; | ||
258 | } | ||
259 | |||
260 | -(void) removeUnusedSpriteFrames | ||
261 | { | ||
262 | NSArray *keys = [spriteFrames_ allKeys]; | ||
263 | for( id key in keys ) { | ||
264 | id value = [spriteFrames_ objectForKey:key]; | ||
265 | if( [value retainCount] == 1 ) { | ||
266 | CCLOG(@"cocos2d: CCSpriteFrameCache: removing unused frame: %@", key); | ||
267 | [spriteFrames_ removeObjectForKey:key]; | ||
268 | } | ||
269 | } | ||
270 | } | ||
271 | |||
272 | -(void) removeSpriteFrameByName:(NSString*)name | ||
273 | { | ||
274 | // explicit nil handling | ||
275 | if( ! name ) | ||
276 | return; | ||
277 | |||
278 | // Is this an alias ? | ||
279 | NSString *key = [spriteFramesAliases_ objectForKey:name]; | ||
280 | |||
281 | if( key ) { | ||
282 | [spriteFrames_ removeObjectForKey:key]; | ||
283 | [spriteFramesAliases_ removeObjectForKey:name]; | ||
284 | |||
285 | } else | ||
286 | [spriteFrames_ removeObjectForKey:name]; | ||
287 | } | ||
288 | |||
289 | - (void) removeSpriteFramesFromFile:(NSString*) plist | ||
290 | { | ||
291 | NSString *path = [CCFileUtils fullPathFromRelativePath:plist]; | ||
292 | NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; | ||
293 | |||
294 | [self removeSpriteFramesFromDictionary:dict]; | ||
295 | } | ||
296 | |||
297 | - (void) removeSpriteFramesFromDictionary:(NSDictionary*) dictionary | ||
298 | { | ||
299 | NSDictionary *framesDict = [dictionary objectForKey:@"frames"]; | ||
300 | NSMutableArray *keysToRemove=[NSMutableArray array]; | ||
301 | |||
302 | for(NSString *frameDictKey in framesDict) | ||
303 | { | ||
304 | if ([spriteFrames_ objectForKey:frameDictKey]!=nil) | ||
305 | [keysToRemove addObject:frameDictKey]; | ||
306 | } | ||
307 | [spriteFrames_ removeObjectsForKeys:keysToRemove]; | ||
308 | } | ||
309 | |||
310 | - (void) removeSpriteFramesFromTexture:(CCTexture2D*) texture | ||
311 | { | ||
312 | NSMutableArray *keysToRemove=[NSMutableArray array]; | ||
313 | |||
314 | for (NSString *spriteFrameKey in spriteFrames_) | ||
315 | { | ||
316 | if ([[spriteFrames_ valueForKey:spriteFrameKey] texture] == texture) | ||
317 | [keysToRemove addObject:spriteFrameKey]; | ||
318 | |||
319 | } | ||
320 | [spriteFrames_ removeObjectsForKeys:keysToRemove]; | ||
321 | } | ||
322 | |||
323 | #pragma mark CCSpriteFrameCache - getting | ||
324 | |||
325 | -(CCSpriteFrame*) spriteFrameByName:(NSString*)name | ||
326 | { | ||
327 | CCSpriteFrame *frame = [spriteFrames_ objectForKey:name]; | ||
328 | if( ! frame ) { | ||
329 | // try alias dictionary | ||
330 | NSString *key = [spriteFramesAliases_ objectForKey:name]; | ||
331 | frame = [spriteFrames_ objectForKey:key]; | ||
332 | |||
333 | if( ! frame ) | ||
334 | CCLOG(@"cocos2d: CCSpriteFrameCache: Frame '%@' not found", name); | ||
335 | } | ||
336 | |||
337 | return frame; | ||
338 | } | ||
339 | |||
340 | #pragma mark CCSpriteFrameCache - sprite creation | ||
341 | |||
342 | -(CCSprite*) createSpriteWithFrameName:(NSString*)name | ||
343 | { | ||
344 | CCSpriteFrame *frame = [spriteFrames_ objectForKey:name]; | ||
345 | return [CCSprite spriteWithSpriteFrame:frame]; | ||
346 | } | ||
347 | @end | ||