RSS

(root)/iphone/tappity : 60 : common/source/ElAnimation.m

To get this branch, use:
bzr branch /browse/iphone/tappity

« back to all changes in this revision

Viewing changes to common/source/ElAnimation.m

Dömötör Gulyás
2010-01-18 09:01:40
Revision ID: dognotdog@gmail.com-20100118080140-g8bc7z6dp9ilr8rt
made tappity a standalone tree

Show diffs side-by-side

added added

removed removed

1
 
//
2
 
//  ElAnimation.m
3
 
//  Jigs
4
 
//
5
 
//  Created by döme on 11.08.2009.
6
 
//  Copyright 2009 __MyCompanyName__. All rights reserved.
7
 
//
8
 
 
9
 
#import "ElAnimation.h"
10
 
 
11
 
#import <mach/mach_time.h>
12
 
#import "geometry.h"
13
 
 
14
 
float linearInterpolation(float a, float b, float t)
15
 
{
16
 
        return a + t*(b-a);
17
 
}
18
 
 
19
 
float easyOutInterpolation(float a, float b, float t)
20
 
{
21
 
        return a + t*t*(b-a);
22
 
}
23
 
 
24
 
float easyInInterpolation(float a, float b, float t)
25
 
{
26
 
        float x = t-1.0f;
27
 
        return a + (1.0f - x*x)*(b-a);
28
 
}
29
 
 
30
 
float smoothInterpolation(float a, float b, float t)
31
 
{
32
 
        return a + (3*t*t - 2*t*t*t)*(b-a);
33
 
}
34
 
 
35
 
@interface ElAnimationController : NSObject
36
 
{
37
 
        NSMutableDictionary*            queuedAnimations;
38
 
        NSTimeInterval                          lastTime;
39
 
 
40
 
        mach_timebase_info_data_t       timebase;
41
 
        uint64_t                                        machTimingStart;
42
 
}
43
 
+ (ElAnimationController*) sharedController;
44
 
 
45
 
- (void) queueAnimation: (ElAnimation*) anim forKey: (id) key atBeginning: (BOOL) atBegin cancelPending: (BOOL) cancelPending;
46
 
- (NSTimeInterval) now;
47
 
 
48
 
@end;
49
 
 
50
 
 
51
 
@implementation ElAnimation
52
 
 
53
 
- (void) queueForKey: (NSString*) key atBeginning: (BOOL) atBeginning cancelPending: (BOOL) cancelPending;
54
 
{
55
 
        [[ElAnimationController sharedController] queueAnimation: self forKey: key atBeginning: atBeginning cancelPending: cancelPending];
56
 
}
57
 
 
58
 
- (BOOL) animateForTime: (NSTimeInterval) time delta: (NSTimeInterval) deltaTime
59
 
{
60
 
        if (time > startTime + duration)
61
 
                return NO;
62
 
        else
63
 
                return YES;
64
 
}
65
 
 
66
 
+ (NSTimeInterval) now
67
 
{
68
 
        return [[ElAnimationController sharedController] now];
69
 
}
70
 
 
71
 
- (void) setStartTime: (NSTimeInterval) time
72
 
{
73
 
        startTime = time;
74
 
}
75
 
- (NSTimeInterval) startTime
76
 
{
77
 
        return startTime;
78
 
}
79
 
 
80
 
+ (ElAnimation*) delayedAnimationWithDelay: (float) seconds
81
 
{
82
 
        ElAnimation* anim = [[[ElAnimation alloc] init] autorelease];
83
 
        [anim setDuration: seconds];
84
 
        return anim;
85
 
}
86
 
 
87
 
@synthesize duration, interpolation;
88
 
 
89
 
@end
90
 
 
91
 
@implementation ElFloatAnimation
92
 
 
93
 
- (BOOL) animateForTime: (NSTimeInterval) time delta: (NSTimeInterval) delta
94
 
{
95
 
        BOOL result = [super animateForTime: time delta: delta];
96
 
 
97
 
        double t = fclamp((time - startTime)/duration, 0.0, 1.0);
98
 
        
99
 
        float y = 0.0;
100
 
        switch (interpolation)
101
 
        {
102
 
                case kElLinearInterpolation:
103
 
                        y = linearInterpolation(startValue, endValue, t);
104
 
                        break;
105
 
                case kElEaseInInterpolation:
106
 
                        y = easyInInterpolation(startValue, endValue, t);
107
 
                        break;
108
 
                case kElEaseOutInterpolation:
109
 
                        y = easyOutInterpolation(startValue, endValue, t);
110
 
                        break;
111
 
                case kElSmoothInterpolation:
112
 
                        y = smoothInterpolation(startValue, endValue, t);
113
 
                        break;
114
 
        }
115
 
        
116
 
        [target setValue: [NSNumber numberWithFloat: y] forKey: property];
117
 
 
118
 
        return result;
119
 
}
120
 
 
121
 
- (void) dealloc
122
 
{
123
 
        [target release];
124
 
        [super dealloc];
125
 
}
126
 
 
127
 
@synthesize startValue, endValue, target, property;
128
 
 
129
 
@end
130
 
 
131
 
@implementation ElV3Animation
132
 
 
133
 
- (BOOL) animateForTime: (NSTimeInterval) time delta: (NSTimeInterval) delta
134
 
{
135
 
        BOOL result = [super animateForTime: time delta: delta];
136
 
 
137
 
        double t = fclamp((time - startTime)/duration, 0.0, 1.0);
138
 
        
139
 
        v3 y = vcreate(0.0f, 0.0f, 0.0f);
140
 
        switch (interpolation)
141
 
        {
142
 
                case kElLinearInterpolation:
143
 
                        y.v.x = linearInterpolation(startv.v.x, endv.v.x, t);
144
 
                        y.v.y = linearInterpolation(startv.v.y, endv.v.y, t);
145
 
                        y.v.z = linearInterpolation(startv.v.z, endv.v.z, t);
146
 
                        break;
147
 
                case kElEaseInInterpolation:
148
 
                        y.v.x = easyInInterpolation(startv.v.x, endv.v.x, t);
149
 
                        y.v.y = easyInInterpolation(startv.v.y, endv.v.y, t);
150
 
                        y.v.z = easyInInterpolation(startv.v.z, endv.v.z, t);
151
 
                        break;
152
 
                case kElEaseOutInterpolation:
153
 
                        y.v.x = easyOutInterpolation(startv.v.x, endv.v.x, t);
154
 
                        y.v.y = easyOutInterpolation(startv.v.y, endv.v.y, t);
155
 
                        y.v.z = easyOutInterpolation(startv.v.z, endv.v.z, t);
156
 
                        break;
157
 
                case kElSmoothInterpolation:
158
 
                        y.v.x = smoothInterpolation(startv.v.x, endv.v.x, t);
159
 
                        y.v.y = smoothInterpolation(startv.v.y, endv.v.y, t);
160
 
                        y.v.z = smoothInterpolation(startv.v.z, endv.v.z, t);
161
 
                        break;
162
 
        }
163
 
        
164
 
        [target performSelector: setter withObject: (void*)&y];
165
 
 
166
 
        return result;
167
 
}
168
 
 
169
 
- (void) dealloc
170
 
{
171
 
        [target release];
172
 
        [super dealloc];
173
 
}
174
 
 
175
 
@synthesize startv, endv, target, setter;
176
 
 
177
 
@end
178
 
 
179
 
 
180
 
@implementation ElAnimationController
181
 
 
182
 
- (id) init
183
 
{
184
 
        if (!(self = [super init]))
185
 
                return nil;
186
 
 
187
 
        queuedAnimations = [[NSMutableDictionary alloc] init];
188
 
 
189
 
        mach_timebase_info(&timebase);
190
 
        machTimingStart = mach_absolute_time();
191
 
 
192
 
        return self;
193
 
}
194
 
 
195
 
- (NSTimeInterval) currentTime
196
 
{
197
 
        uint64_t mtime = mach_absolute_time();
198
 
        
199
 
        uint64_t elapsed = mtime - machTimingStart;
200
 
        
201
 
        return (NSTimeInterval)((elapsed*timebase.numer)/timebase.denom)*1e-9;
202
 
}
203
 
 
204
 
+ (id) sharedController
205
 
{
206
 
        static ElAnimationController* sharedController = nil;
207
 
        if (!sharedController)
208
 
                sharedController = [[ElAnimationController alloc] init];
209
 
        return sharedController;
210
 
}
211
 
 
212
 
- (void) timerCallback
213
 
{
214
 
        NSTimeInterval time = [self currentTime];
215
 
        NSTimeInterval delta = time - lastTime;
216
 
        
217
 
//      NSLog(@"%f %f", time, delta);
218
 
        
219
 
        NSMutableArray* keysToRemove = [NSMutableArray array];
220
 
        for (id key in queuedAnimations)
221
 
        {
222
 
                NSMutableArray* animArray = [queuedAnimations objectForKey: key];
223
 
                if (![animArray count])
224
 
                {
225
 
                        [keysToRemove addObject: key];
226
 
                        continue;
227
 
                }
228
 
                
229
 
                ElAnimation* anim = [animArray objectAtIndex: 0];
230
 
                
231
 
                if ([anim startTime] == 0.0)
232
 
                        [anim setStartTime: lastTime];
233
 
                        
234
 
                [anim animateForTime: time delta: delta];
235
 
 
236
 
                if ([anim startTime] + [anim duration] < time)
237
 
                {
238
 
                        [animArray removeObjectAtIndex: 0];
239
 
                        //NSLog(@"dequeued animation");
240
 
                }
241
 
        }
242
 
        [queuedAnimations removeObjectsForKeys: keysToRemove];
243
 
        lastTime = time;
244
 
}
245
 
 
246
 
- (void) queueAnimation: (ElAnimation*) anim forKey: (id) key atBeginning: (BOOL) atBeginning cancelPending: (BOOL) cancelPending
247
 
{
248
 
        static NSTimer* animationTimer = nil;
249
 
        if (!animationTimer)
250
 
        {
251
 
                animationTimer = [NSTimer scheduledTimerWithTimeInterval: 0.01 target: self selector: @selector(timerCallback) userInfo: nil repeats: YES];
252
 
                lastTime = [self currentTime];
253
 
        }
254
 
        
255
 
        if (!key)
256
 
                key = [NSNull null];
257
 
        
258
 
        NSMutableArray* animArray = [queuedAnimations objectForKey: key];
259
 
        if (!animArray)
260
 
        {
261
 
                animArray = [NSMutableArray array];
262
 
                [queuedAnimations setObject: animArray forKey: key];
263
 
        }
264
 
        
265
 
        if (!cancelPending && !atBeginning)
266
 
                [animArray addObject: anim];
267
 
        else if (cancelPending && !atBeginning)
268
 
        {
269
 
                if ([animArray count] > 1)
270
 
                        [animArray removeObjectsInRange: (NSRange){1, [animArray count]-1}];
271
 
                [animArray addObject: anim];
272
 
        }
273
 
        else if (!cancelPending && atBeginning)
274
 
        {
275
 
                if ([animArray count])
276
 
                        [animArray replaceObjectAtIndex: 0 withObject: anim];
277
 
                else
278
 
                        [animArray addObject: anim];
279
 
        }
280
 
        else
281
 
        {
282
 
                [animArray removeAllObjects];
283
 
                [animArray addObject: anim];
284
 
        }
285
 
}
286
 
 
287
 
- (NSTimeInterval) now
288
 
{
289
 
        return lastTime;
290
 
}
291
 
 
292
 
@end
293
 
 
294
 
NSString*       AnimationAbsoluteTimeKey = @"animationAbsoluteTime";
295
 
NSString*       AnimationPassedTimeKey  = @"animationPassedTime";
296
 
NSString*       AnimationDeltaTimeKey   = @"animationDeltaTime";
297
 
NSString*       AnimationUserInfoKey    = @"animationUserInfo";
298
 
 
299
 
@implementation ElCallbackAnimation
300
 
 
301
 
- (BOOL) animateForTime: (NSTimeInterval) time delta: (NSTimeInterval) delta
302
 
{
303
 
        BOOL result = [super animateForTime: time delta: delta];
304
 
 
305
 
        NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithDouble: time], AnimationAbsoluteTimeKey, [NSNumber numberWithDouble: time - startTime], AnimationPassedTimeKey, [NSNumber numberWithDouble: delta], AnimationDeltaTimeKey, userInfo, AnimationUserInfoKey, nil];
306
 
 
307
 
        
308
 
        [target performSelector: callback withObject: dict];
309
 
 
310
 
        return result;
311
 
}
312
 
 
313
 
- (void) dealloc
314
 
{
315
 
        [target release];
316
 
        [userInfo release];
317
 
        [super dealloc];
318
 
}
319
 
 
320
 
@synthesize target, userInfo, callback;
321
 
 
322
 
@end

Loggerhead 1.17 is a web-based interface for Bazaar branches