5
// Created by döme on 11.08.2009.
6
// Copyright 2009 __MyCompanyName__. All rights reserved.
9
#import "ElAnimation.h"
11
#import <mach/mach_time.h>
14
float linearInterpolation(float a, float b, float t)
19
float easyOutInterpolation(float a, float b, float t)
24
float easyInInterpolation(float a, float b, float t)
27
return a + (1.0f - x*x)*(b-a);
30
float smoothInterpolation(float a, float b, float t)
32
return a + (3*t*t - 2*t*t*t)*(b-a);
35
@interface ElAnimationController : NSObject
37
NSMutableDictionary* queuedAnimations;
38
NSTimeInterval lastTime;
40
mach_timebase_info_data_t timebase;
41
uint64_t machTimingStart;
43
+ (ElAnimationController*) sharedController;
45
- (void) queueAnimation: (ElAnimation*) anim forKey: (id) key atBeginning: (BOOL) atBegin cancelPending: (BOOL) cancelPending;
46
- (NSTimeInterval) now;
51
@implementation ElAnimation
53
- (void) queueForKey: (NSString*) key atBeginning: (BOOL) atBeginning cancelPending: (BOOL) cancelPending;
55
[[ElAnimationController sharedController] queueAnimation: self forKey: key atBeginning: atBeginning cancelPending: cancelPending];
58
- (BOOL) animateForTime: (NSTimeInterval) time delta: (NSTimeInterval) deltaTime
60
if (time > startTime + duration)
66
+ (NSTimeInterval) now
68
return [[ElAnimationController sharedController] now];
71
- (void) setStartTime: (NSTimeInterval) time
75
- (NSTimeInterval) startTime
80
+ (ElAnimation*) delayedAnimationWithDelay: (float) seconds
82
ElAnimation* anim = [[[ElAnimation alloc] init] autorelease];
83
[anim setDuration: seconds];
87
@synthesize duration, interpolation;
91
@implementation ElFloatAnimation
93
- (BOOL) animateForTime: (NSTimeInterval) time delta: (NSTimeInterval) delta
95
BOOL result = [super animateForTime: time delta: delta];
97
double t = fclamp((time - startTime)/duration, 0.0, 1.0);
100
switch (interpolation)
102
case kElLinearInterpolation:
103
y = linearInterpolation(startValue, endValue, t);
105
case kElEaseInInterpolation:
106
y = easyInInterpolation(startValue, endValue, t);
108
case kElEaseOutInterpolation:
109
y = easyOutInterpolation(startValue, endValue, t);
111
case kElSmoothInterpolation:
112
y = smoothInterpolation(startValue, endValue, t);
116
[target setValue: [NSNumber numberWithFloat: y] forKey: property];
127
@synthesize startValue, endValue, target, property;
131
@implementation ElV3Animation
133
- (BOOL) animateForTime: (NSTimeInterval) time delta: (NSTimeInterval) delta
135
BOOL result = [super animateForTime: time delta: delta];
137
double t = fclamp((time - startTime)/duration, 0.0, 1.0);
139
v3 y = vcreate(0.0f, 0.0f, 0.0f);
140
switch (interpolation)
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);
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);
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);
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);
164
[target performSelector: setter withObject: (void*)&y];
175
@synthesize startv, endv, target, setter;
180
@implementation ElAnimationController
184
if (!(self = [super init]))
187
queuedAnimations = [[NSMutableDictionary alloc] init];
189
mach_timebase_info(&timebase);
190
machTimingStart = mach_absolute_time();
195
- (NSTimeInterval) currentTime
197
uint64_t mtime = mach_absolute_time();
199
uint64_t elapsed = mtime - machTimingStart;
201
return (NSTimeInterval)((elapsed*timebase.numer)/timebase.denom)*1e-9;
204
+ (id) sharedController
206
static ElAnimationController* sharedController = nil;
207
if (!sharedController)
208
sharedController = [[ElAnimationController alloc] init];
209
return sharedController;
212
- (void) timerCallback
214
NSTimeInterval time = [self currentTime];
215
NSTimeInterval delta = time - lastTime;
217
// NSLog(@"%f %f", time, delta);
219
NSMutableArray* keysToRemove = [NSMutableArray array];
220
for (id key in queuedAnimations)
222
NSMutableArray* animArray = [queuedAnimations objectForKey: key];
223
if (![animArray count])
225
[keysToRemove addObject: key];
229
ElAnimation* anim = [animArray objectAtIndex: 0];
231
if ([anim startTime] == 0.0)
232
[anim setStartTime: lastTime];
234
[anim animateForTime: time delta: delta];
236
if ([anim startTime] + [anim duration] < time)
238
[animArray removeObjectAtIndex: 0];
239
//NSLog(@"dequeued animation");
242
[queuedAnimations removeObjectsForKeys: keysToRemove];
246
- (void) queueAnimation: (ElAnimation*) anim forKey: (id) key atBeginning: (BOOL) atBeginning cancelPending: (BOOL) cancelPending
248
static NSTimer* animationTimer = nil;
251
animationTimer = [NSTimer scheduledTimerWithTimeInterval: 0.01 target: self selector: @selector(timerCallback) userInfo: nil repeats: YES];
252
lastTime = [self currentTime];
258
NSMutableArray* animArray = [queuedAnimations objectForKey: key];
261
animArray = [NSMutableArray array];
262
[queuedAnimations setObject: animArray forKey: key];
265
if (!cancelPending && !atBeginning)
266
[animArray addObject: anim];
267
else if (cancelPending && !atBeginning)
269
if ([animArray count] > 1)
270
[animArray removeObjectsInRange: (NSRange){1, [animArray count]-1}];
271
[animArray addObject: anim];
273
else if (!cancelPending && atBeginning)
275
if ([animArray count])
276
[animArray replaceObjectAtIndex: 0 withObject: anim];
278
[animArray addObject: anim];
282
[animArray removeAllObjects];
283
[animArray addObject: anim];
287
- (NSTimeInterval) now
294
NSString* AnimationAbsoluteTimeKey = @"animationAbsoluteTime";
295
NSString* AnimationPassedTimeKey = @"animationPassedTime";
296
NSString* AnimationDeltaTimeKey = @"animationDeltaTime";
297
NSString* AnimationUserInfoKey = @"animationUserInfo";
299
@implementation ElCallbackAnimation
301
- (BOOL) animateForTime: (NSTimeInterval) time delta: (NSTimeInterval) delta
303
BOOL result = [super animateForTime: time delta: delta];
305
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithDouble: time], AnimationAbsoluteTimeKey, [NSNumber numberWithDouble: time - startTime], AnimationPassedTimeKey, [NSNumber numberWithDouble: delta], AnimationDeltaTimeKey, userInfo, AnimationUserInfoKey, nil];
308
[target performSelector: callback withObject: dict];
320
@synthesize target, userInfo, callback;