summary refs log tree commit diff stats
path: root/libs/cocos2d/CCNotifications.m
diff options
context:
space:
mode:
Diffstat (limited to 'libs/cocos2d/CCNotifications.m')
-rwxr-xr-xlibs/cocos2d/CCNotifications.m494
1 files changed, 494 insertions, 0 deletions
diff --git a/libs/cocos2d/CCNotifications.m b/libs/cocos2d/CCNotifications.m new file mode 100755 index 0000000..235a6a0 --- /dev/null +++ b/libs/cocos2d/CCNotifications.m
@@ -0,0 +1,494 @@
1/*
2 * CCNotifications
3 *
4 * Copyright (c) 2010 ForzeField Studios S.L.
5 * http://forzefield.com
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import "CCNotifications.h"
29#import "CCArray.h"
30#import "notificationDesign.h"
31
32
33@implementation ccNotificationData
34@synthesize title = title_;
35@synthesize message = message_;
36@synthesize media = media_;
37@synthesize mediaType = mediaType_;
38@synthesize tag = tag_;
39@synthesize animated = animated_;
40
41
42- (void) dealloc
43{
44 [self setTitle:nil];
45 [self setMessage:nil];
46 [self setMedia:nil];
47 [super dealloc];
48}
49
50
51@end
52
53@interface CCNotifications (Private)
54
55- (void) _updateAnimationIn;
56- (void) _updateAnimationOut;
57- (CCActionInterval*) _animation:(char)type time:(ccTime)time;
58- (void) _showNotification;
59- (void) _addNotificationToArray:(ccNotificationData*)data cached:(BOOL)isCached;
60- (void) _startScheduler;
61- (void) _hideNotification;
62- (void) _hideNotificationScheduler;
63- (void) registerWithTouchDispatcher;
64- (void) _setState:(char)states;
65
66@end
67
68
69@implementation CCNotifications
70@synthesize position = position_;
71@synthesize notificationDesign = template_;
72@synthesize animationIn = animationIn_;
73@synthesize animationOut = animationOut_;
74@synthesize delegate = delegate_;
75@synthesize showingTime = showingTime_;
76@synthesize currentNotification = currentNotification_;
77
78static CCNotifications *sharedManager;
79
80+ (CCNotifications *)sharedManager
81{
82 if (!sharedManager)
83 sharedManager = [[CCNotifications alloc] init];
84
85 return sharedManager;
86}
87
88+ (id) alloc
89{
90 NSAssert(sharedManager == nil, @"Attempted to allocate a second instance of a singleton.");
91 return [super alloc];
92}
93
94+ (id) systemWithTemplate:(CCNode <CCNotificationDesignProtocol> *)notifications
95{
96 NSAssert(sharedManager == nil, @"Attempted to allocate a second instance of a singleton. You should use setTemplate");
97 sharedManager = [[CCNotifications alloc] initWithTemplate:notifications];
98
99 return sharedManager;
100}
101
102+ (void) purgeSharedManager
103{
104 [sharedManager release];
105}
106
107- (id) init
108{
109 CCNode <CCNotificationDesignProtocol> *templates = [[[CCNotificationDefaultDesign alloc] init] autorelease];
110 self = [self initWithTemplate:templates];
111 return self;
112}
113
114- (id) initWithTemplate:(CCNode <CCNotificationDesignProtocol> *)templates
115{
116 if( (self = [super init]) ) {
117 self.notificationDesign = templates;
118
119 delegate_ = nil;
120 state_ = kCCNotificationStateHide;
121 typeAnimationIn_ = kCCNotificationAnimationMovement;
122 typeAnimationOut_ = kCCNotificationAnimationMovement;
123 timeAnimationIn_ = 0.0f;
124 timeAnimationOut_ = 0.0f;
125
126 cachedNotifications_ = [[CCArray alloc] initWithCapacity:4];
127
128 //Default settings
129 showingTime_ = 4.0f;
130 position_ = kCCNotificationPositionTop;
131
132 [self setAnimation:kCCNotificationAnimationMovement time:0.5f];
133 //[self setAnimationIn:kCCNotificationAnimationMovement time:0.5f];
134 //[self setAnimationOut:kCCNotificationAnimationScale time:0.5f];
135 }
136 return self;
137}
138
139- (void) _setState:(char)states
140{
141 if(state_==states) return;
142 state_ = states;
143
144 if([delegate_ respondsToSelector:@selector(notification:newState:)])
145 [delegate_ notification:currentNotification_ newState:state_];
146
147 if([delegate_ respondsToSelector:@selector(notificationChangeState:tag:)])
148 [delegate_ notificationChangeState:state_ tag:[currentNotification_ tag]];
149}
150
151- (void) setPosition:(char)positions
152{
153 position_ = positions;
154 [self updateAnimations];
155}
156
157- (void) setNotificationDesign:(CCNode <CCNotificationDesignProtocol>*) templates
158{
159 if(state_!=kCCNotificationStateHide)
160 [template_ stopAllActions];
161
162 if(state_==kCCNotificationStateShowing)
163 {
164#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
165 [[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
166#endif
167 [[CCScheduler sharedScheduler] unscheduleSelector:@selector(_hideNotificationScheduler) forTarget:self];
168 }
169
170 [templates retain];
171 [template_ release];
172 template_ = templates;
173 [template_ setVisible:NO];
174 [template_ setIsRelativeAnchorPoint:YES];
175
176 [self _setState:kCCNotificationStateHide];
177}
178#pragma mark Notification Actions
179
180- (CCActionInterval*) _animation:(char)type time:(ccTime)time
181{
182 CCActionInterval *action = nil;
183 switch (type){
184 case kCCNotificationAnimationMovement:
185 if(position_==kCCNotificationPositionBottom)
186 action = [CCMoveBy actionWithDuration:time position:ccp(0, template_.contentSize.height)];
187
188 else if(position_ == kCCNotificationPositionTop)
189 action = [CCMoveBy actionWithDuration:time position:ccp(0, -template_.contentSize.height)];
190
191 break;
192 case kCCNotificationAnimationScale:
193 action = [CCScaleBy actionWithDuration:time scale:(1.0f-KNOTIFICATIONMIN_SCALE)/KNOTIFICATIONMIN_SCALE];
194
195 break;
196 default: break;
197 }
198 return action;
199}
200
201- (void) _updateAnimationIn
202{
203 self.animationIn = [CCSequence actionOne:[self _animation:typeAnimationIn_ time:timeAnimationIn_] two:[CCCallFunc actionWithTarget:self selector:@selector(_startScheduler)]];
204}
205
206- (void) _updateAnimationOut
207{
208 CCActionInterval *tempAction = [self _animation:typeAnimationOut_ time:timeAnimationOut_];
209 self.animationOut = [CCSequence actionOne:[tempAction reverse] two:[CCCallFunc actionWithTarget:self selector:@selector(_hideNotification)]];
210}
211
212- (void) updateAnimations
213{
214 [self _updateAnimationIn];
215 [self _updateAnimationOut];
216}
217
218- (void) setAnimationIn:(char)type time:(ccTime)time
219{
220 typeAnimationIn_ = type;
221 timeAnimationIn_ = time;
222 [self _updateAnimationIn];
223}
224
225- (void) setAnimationOut:(char)type time:(ccTime)time
226{
227 typeAnimationOut_ = type;
228 timeAnimationOut_ = time;
229 [self _updateAnimationOut];
230}
231
232- (void) setAnimation:(char)type time:(ccTime)time
233{
234 typeAnimationIn_ = typeAnimationOut_ = type;
235 timeAnimationIn_ = timeAnimationOut_ = time;
236 [self updateAnimations];
237}
238
239#pragma mark Notification steps
240
241- (void) _startScheduler
242{
243#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
244 [self registerWithTouchDispatcher];
245#endif
246 [self _setState:kCCNotificationStateShowing];
247 [template_ stopAllActions];
248 [[CCScheduler sharedScheduler] scheduleSelector:@selector(_hideNotificationScheduler) forTarget:self interval:showingTime_ paused:NO];
249}
250
251- (void) _hideNotification
252{
253 [self _setState:kCCNotificationStateHide];
254 [template_ setVisible:NO];
255 [template_ stopAllActions];
256 [template_ onExit];
257
258 //Release current notification
259 [cachedNotifications_ removeObject:currentNotification_];
260 self.currentNotification = nil;
261
262 //Check next notification
263 [self _showNotification];
264}
265
266- (void) _hideNotificationScheduler
267{
268#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
269 [[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
270#endif
271 [[CCScheduler sharedScheduler] unscheduleSelector:@selector(_hideNotificationScheduler) forTarget:self];
272 if([currentNotification_ animated])
273 {
274 [self _setState:kCCNotificationStateAnimationOut];
275 [template_ runAction:animationOut_];
276 }else
277 [self _hideNotification];
278}
279
280#pragma mark Manager Notifications
281
282- (void) _addNotificationToArray:(ccNotificationData*)data cached:(BOOL)isCached
283{
284 if(isCached)
285 {
286 [cachedNotifications_ addObject:data];
287 if([cachedNotifications_ count]==1)
288 [self _showNotification];
289 }else{
290 if(currentNotification_)
291 {
292 [cachedNotifications_ removeObject:currentNotification_];
293 }
294 [cachedNotifications_ insertObject:data atIndex:0];
295 [self _showNotification];
296 }
297}
298
299- (ccNotificationData*) addWithTitle:(NSString*)title message:(NSString*)message image:(NSString*)image tag:(int)tag animate:(BOOL)animate waitUntilDone:(BOOL)isCached
300{
301 ccNotificationData *data = [[ccNotificationData alloc] init];
302 data.title = title;
303 data.message = message;
304 data.media = image;
305 data.mediaType = kCCNotificationMediaPath;
306 data.tag = tag;
307 data.animated = animate;
308
309 [self _addNotificationToArray:data cached:isCached];
310 [data release];
311 return data;
312}
313
314- (ccNotificationData*) addWithTitle:(NSString*)title message:(NSString*)message texture:(CCTexture2D*)texture tag:(int)tag animate:(BOOL)animate waitUntilDone:(BOOL)isCached
315{
316 ccNotificationData *data = [[ccNotificationData alloc] init];
317 data.title = title;
318 data.message = message;
319 data.media = texture;
320 data.mediaType = kCCNotificationMediaTexture;
321 data.tag = tag;
322 data.animated = animate;
323
324 [self _addNotificationToArray:data cached:isCached];
325 [data release];
326 return data;
327}
328
329- (ccNotificationData*) addWithTitle:(NSString*)title message:(NSString*)message image:(NSString*)image tag:(int)tag animate:(BOOL)animate
330{
331 return [self addWithTitle:title message:message image:image tag:tag animate:animate waitUntilDone:YES];
332}
333
334- (ccNotificationData*) addWithTitle:(NSString*)title message:(NSString*)message texture:(CCTexture2D*)texture tag:(int)tag animate:(BOOL)animate
335{
336 return [self addWithTitle:title message:message texture:texture tag:tag animate:animate waitUntilDone:YES];
337}
338
339/* Fast methods */
340
341- (ccNotificationData*) addWithTitle:(NSString*)title message:(NSString*)message image:(NSString*)image
342{
343 return [self addWithTitle:title message:message image:image tag:-1 animate:YES waitUntilDone:YES];
344}
345
346- (ccNotificationData*) addWithTitle:(NSString*)title message:(NSString*)message texture:(CCTexture2D*)texture
347{
348 return [self addWithTitle:title message:message texture:texture tag:-1 animate:YES waitUntilDone:YES];
349}
350
351/* Deprecated */
352- (void) addSafelyWithTitle:(NSString*)title message:(NSString*)message image:(NSString*)image tag:(int)tag animate:(BOOL)animate
353{
354 [self addWithTitle:title message:message image:image tag:tag animate:animate waitUntilDone:YES];
355}
356
357- (void) _showNotification
358{
359 if([cachedNotifications_ count]==0) return;
360 //Get notification data
361 self.currentNotification = [cachedNotifications_ objectAtIndex:0];
362
363 //Stop system
364 if(state_==kCCNotificationStateShowing)
365 {
366#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
367 [[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
368#else
369 [[CCEventDispatcher sharedDispatcher] removeMouseDelegate:self];
370#endif
371 }
372
373 if(state_!=kCCNotificationStateHide)
374 {
375 [self _setState:kCCNotificationStateHide];
376
377 [template_ setVisible:NO];
378 [template_ stopAllActions];
379 [template_ onExit];
380 [[CCScheduler sharedScheduler] unscheduleSelector:@selector(_hideNotificationScheduler) forTarget:self];
381 }
382
383 //Get variables
384 CCTexture2D *texture = (currentNotification_.media) ? ((currentNotification_.mediaType==kCCNotificationMediaTexture) ? (CCTexture2D*)currentNotification_.media : [[CCTextureCache sharedTextureCache] addImage:(NSString*)currentNotification_.media]) : nil;
385
386 //Prepare template
387 [template_ setVisible:NO];
388 [template_ stopAllActions];
389 [template_ onExit];
390
391 //Prepare animation
392 CGSize winSize = CGSizeMake(480,320);
393 if(currentNotification_.animated)
394 {
395 if(position_==kCCNotificationPositionBottom){
396 [template_ setAnchorPoint:ccp(0.5f, 0)];
397 switch (typeAnimationIn_) {
398 case kCCNotificationAnimationMovement:
399 [template_ setScale:1.0f];
400 [template_ setPosition:ccp(winSize.width/2.0f, -template_.contentSize.height)];
401
402 break;
403 case kCCNotificationAnimationScale:
404 [template_ setScale:KNOTIFICATIONMIN_SCALE];
405 [template_ setPosition:ccp(winSize.width/2.0f, 0)];
406
407 break;
408 default: return;
409 }
410
411 }else if(position_==kCCNotificationPositionTop)
412 {
413 [template_ setAnchorPoint:ccp(0.5f, 1)];
414 switch (typeAnimationIn_){
415 case kCCNotificationAnimationMovement:
416 [template_ setScale:1.0f];
417 [template_ setPosition:ccp(winSize.width/2.0f, winSize.height+template_.contentSize.height)];
418
419 break;
420 case kCCNotificationAnimationScale:
421 [template_ setScale:KNOTIFICATIONMIN_SCALE];
422 [template_ setPosition:ccp(winSize.width/2.0f, winSize.height)];
423
424 break;
425 default: return;
426 }
427 }
428 [self _setState:kCCNotificationStateAnimationIn];
429 [template_ onEnter];
430 [template_ runAction:animationIn_];
431
432 }else{
433 if(position_==kCCNotificationPositionBottom)
434 {
435 [template_ setAnchorPoint:ccp(0.5f, 0)];
436 [template_ setPosition:ccp(winSize.width/2.0f, 0)];
437 }else if(position_==kCCNotificationPositionTop)
438 {
439 [template_ setAnchorPoint:ccp(0.5f, 1)];
440 [template_ setPosition:ccp(winSize.width/2.0f, winSize.height)];
441 }
442 [self _startScheduler];
443 }
444
445 //Update template
446 [template_ setTitle:[currentNotification_ title] message:[currentNotification_ message] texture:texture];
447 [template_ setVisible:YES];
448}
449
450#pragma mark Touch Events
451
452#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
453- (void) registerWithTouchDispatcher
454{
455 [[CCTouchDispatcher sharedDispatcher] addStandardDelegate:self priority:INT_MIN];
456}
457
458- (void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
459{
460 UITouch *touch = [touches anyObject];
461 CGPoint point = [[CCDirector sharedDirector] convertToGL:[touch locationInView:[touch view]]];
462 CGRect rect = [template_ boundingBox];
463 if(CGRectContainsPoint(rect, point))
464 if([delegate_ respondsToSelector:@selector(touched:)] && [delegate_ touched:[currentNotification_ tag]])
465 [self _hideNotificationScheduler];
466}
467#endif
468
469#pragma mark Other methods
470
471- (void) visit
472{
473 [template_ visit];
474}
475
476- (NSString*) description
477{
478 return [NSString stringWithFormat:@"<%@ = %08X>", [self class], self];
479}
480
481-(void) dealloc
482{
483 CCLOG(@"cocos2d: deallocing %@", self);
484
485 sharedManager = nil;
486 [cachedNotifications_ release];
487 [self setCurrentNotification:nil];
488 [self setNotificationDesign:nil];
489 [self setDelegate:nil];
490 [self setAnimationIn:nil];
491 [self setAnimationOut:nil];
492 [super dealloc];
493}
494@end \ No newline at end of file