RSS

(root)/iphone/common : /source/ElAnimation.m (revision 96)

To get this branch, use:
bzr branch /browse/iphone/common
Line Revision Contents
1 25
//
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 27
	NSMutableDictionary*		queuedAnimations;
38 25
	NSTimeInterval				lastTime;
39 27
40 25
	mach_timebase_info_data_t	timebase;
41
	uint64_t					machTimingStart;
42
}
43
+ (ElAnimationController*) sharedController;
44
45 27
- (void) queueAnimation: (ElAnimation*) anim forKey: (id) key atBeginning: (BOOL) atBegin cancelPending: (BOOL) cancelPending;
46 25
- (NSTimeInterval) now;
47 65
- (NSTimeInterval) currentTime;
48 25
49
@end;
50
51
52
@implementation ElAnimation
53
54 27
- (void) queueForKey: (NSString*) key atBeginning: (BOOL) atBeginning cancelPending: (BOOL) cancelPending;
55 25
{
56 27
	[[ElAnimationController sharedController] queueAnimation: self forKey: key atBeginning: atBeginning cancelPending: cancelPending];
57 25
}
58
59
- (BOOL) animateForTime: (NSTimeInterval) time delta: (NSTimeInterval) deltaTime
60
{
61
	if (time > startTime + duration)
62
		return NO;
63
	else
64
		return YES;
65
}
66
67
+ (NSTimeInterval) now
68
{
69
	return [[ElAnimationController sharedController] now];
70
}
71
72 65
+ (NSTimeInterval) currentTime
73
{
74
	return [[ElAnimationController sharedController] currentTime];
75
}
76
77 27
- (void) setStartTime: (NSTimeInterval) time
78
{
79
	startTime = time;
80
}
81
- (NSTimeInterval) startTime
82
{
83
	return startTime;
84
}
85
86
+ (ElAnimation*) delayedAnimationWithDelay: (float) seconds
87
{
88 94
	ElAnimation* anim = [[ElAnimation alloc] init];
89 27
	[anim setDuration: seconds];
90
	return anim;
91
}
92
93
@synthesize duration, interpolation;
94 25
95
@end
96
97
@implementation ElFloatAnimation
98
99
- (BOOL) animateForTime: (NSTimeInterval) time delta: (NSTimeInterval) delta
100
{
101
	BOOL result = [super animateForTime: time delta: delta];
102
103
	double t = fclamp((time - startTime)/duration, 0.0, 1.0);
104
	
105
	float y = 0.0;
106
	switch (interpolation)
107
	{
108
		case kElLinearInterpolation:
109
			y = linearInterpolation(startValue, endValue, t);
110
			break;
111
		case kElEaseInInterpolation:
112
			y = easyInInterpolation(startValue, endValue, t);
113
			break;
114
		case kElEaseOutInterpolation:
115
			y = easyOutInterpolation(startValue, endValue, t);
116
			break;
117
		case kElSmoothInterpolation:
118
			y = smoothInterpolation(startValue, endValue, t);
119
			break;
120
	}
121
	
122
	[target setValue: [NSNumber numberWithFloat: y] forKey: property];
123
124
	return result;
125
}
126
127
@synthesize startValue, endValue, target, property;
128
129
@end
130
131 94
132
133 43
@implementation ElV3Animation
134
135
- (BOOL) animateForTime: (NSTimeInterval) time delta: (NSTimeInterval) delta
136
{
137
	BOOL result = [super animateForTime: time delta: delta];
138
139
	double t = fclamp((time - startTime)/duration, 0.0, 1.0);
140
	
141
	v3 y = vcreate(0.0f, 0.0f, 0.0f);
142
	switch (interpolation)
143
	{
144
		case kElLinearInterpolation:
145
			y.v.x = linearInterpolation(startv.v.x, endv.v.x, t);
146
			y.v.y = linearInterpolation(startv.v.y, endv.v.y, t);
147
			y.v.z = linearInterpolation(startv.v.z, endv.v.z, t);
148
			break;
149
		case kElEaseInInterpolation:
150
			y.v.x = easyInInterpolation(startv.v.x, endv.v.x, t);
151
			y.v.y = easyInInterpolation(startv.v.y, endv.v.y, t);
152
			y.v.z = easyInInterpolation(startv.v.z, endv.v.z, t);
153
			break;
154
		case kElEaseOutInterpolation:
155
			y.v.x = easyOutInterpolation(startv.v.x, endv.v.x, t);
156
			y.v.y = easyOutInterpolation(startv.v.y, endv.v.y, t);
157
			y.v.z = easyOutInterpolation(startv.v.z, endv.v.z, t);
158
			break;
159
		case kElSmoothInterpolation:
160
			y.v.x = smoothInterpolation(startv.v.x, endv.v.x, t);
161
			y.v.y = smoothInterpolation(startv.v.y, endv.v.y, t);
162
			y.v.z = smoothInterpolation(startv.v.z, endv.v.z, t);
163
			break;
164
	}
165
	
166 94
	assert(0);
167
//	[target performSelector: setter withObject: (void*)&y];
168 43
169
	return result;
170
}
171
172
173
@synthesize startv, endv, target, setter;
174
175
@end
176
177 65
@interface NSObject (ElCGPositionAnimation)
178
- (void) setPosition: (CGPoint) p;
179
@end
180
181
@implementation ElCGPositionAnimation
182
183
- (BOOL) animateForTime: (NSTimeInterval) time delta: (NSTimeInterval) delta
184
{
185
	BOOL result = [super animateForTime: time delta: delta];
186
187
	double t = fclamp((time - startTime)/duration, 0.0, 1.0);
188
	
189
	CGPoint y = CGPointZero;
190
	switch (interpolation)
191
	{
192
		case kElLinearInterpolation:
193
			y.x = linearInterpolation(startPoint.x, endPoint.x, t);
194
			y.y = linearInterpolation(startPoint.y, endPoint.y, t);
195
			break;
196
		case kElEaseInInterpolation:
197
			y.x = easyInInterpolation(startPoint.x, endPoint.x, t);
198
			y.y = easyInInterpolation(startPoint.y, endPoint.y, t);
199
			break;
200
		case kElEaseOutInterpolation:
201
			y.x = easyOutInterpolation(startPoint.x, endPoint.x, t);
202
			y.y = easyOutInterpolation(startPoint.y, endPoint.y, t);
203
			break;
204
		case kElSmoothInterpolation:
205
			y.x = smoothInterpolation(startPoint.x, endPoint.x, t);
206
			y.y = smoothInterpolation(startPoint.y, endPoint.y, t);
207
			break;
208
	}
209
	
210
	[target setPosition: y];
211
212
	return result;
213
}
214
215
@synthesize startPoint, endPoint, target;
216
217
@end
218
219 43
220 25
@implementation ElAnimationController
221
222
- (id) init
223
{
224
	if (!(self = [super init]))
225
		return nil;
226
227 27
	queuedAnimations = [[NSMutableDictionary alloc] init];
228 25
229
	mach_timebase_info(&timebase);
230
	machTimingStart = mach_absolute_time();
231
232
	return self;
233
}
234
235
- (NSTimeInterval) currentTime
236
{
237
	uint64_t mtime = mach_absolute_time();
238
	
239
	uint64_t elapsed = mtime - machTimingStart;
240
	
241
	return (NSTimeInterval)((elapsed*timebase.numer)/timebase.denom)*1e-9;
242
}
243
244
+ (id) sharedController
245
{
246
	static ElAnimationController* sharedController = nil;
247
	if (!sharedController)
248
		sharedController = [[ElAnimationController alloc] init];
249
	return sharedController;
250
}
251
252
- (void) timerCallback
253
{
254
	NSTimeInterval time = [self currentTime];
255
	NSTimeInterval delta = time - lastTime;
256
	
257
//	NSLog(@"%f %f", time, delta);
258
	
259 27
	NSMutableArray* keysToRemove = [NSMutableArray array];
260
	for (id key in queuedAnimations)
261 25
	{
262 27
		NSMutableArray* animArray = [queuedAnimations objectForKey: key];
263
		if (![animArray count])
264
		{
265
			[keysToRemove addObject: key];
266
			continue;
267
		}
268
		
269
		ElAnimation* anim = [animArray objectAtIndex: 0];
270
		
271
		if ([anim startTime] == 0.0)
272
			[anim setStartTime: lastTime];
273
			
274
		[anim animateForTime: time delta: delta];
275
276
		if ([anim startTime] + [anim duration] < time)
277
		{
278
			[animArray removeObjectAtIndex: 0];
279
			//NSLog(@"dequeued animation");
280
		}
281 25
	}
282 27
	[queuedAnimations removeObjectsForKeys: keysToRemove];
283 25
	lastTime = time;
284
}
285
286 27
- (void) queueAnimation: (ElAnimation*) anim forKey: (id) key atBeginning: (BOOL) atBeginning cancelPending: (BOOL) cancelPending
287 25
{
288
	static NSTimer* animationTimer = nil;
289
	if (!animationTimer)
290
	{
291
		animationTimer = [NSTimer scheduledTimerWithTimeInterval: 0.01 target: self selector: @selector(timerCallback) userInfo: nil repeats: YES];
292
		lastTime = [self currentTime];
293
	}
294
	
295 27
	if (!key)
296
		key = [NSNull null];
297
	
298
	NSMutableArray* animArray = [queuedAnimations objectForKey: key];
299
	if (!animArray)
300
	{
301
		animArray = [NSMutableArray array];
302
		[queuedAnimations setObject: animArray forKey: key];
303
	}
304
	
305
	if (!cancelPending && !atBeginning)
306
		[animArray addObject: anim];
307
	else if (cancelPending && !atBeginning)
308
	{
309
		if ([animArray count] > 1)
310
			[animArray removeObjectsInRange: (NSRange){1, [animArray count]-1}];
311
		[animArray addObject: anim];
312
	}
313
	else if (!cancelPending && atBeginning)
314
	{
315
		if ([animArray count])
316
			[animArray replaceObjectAtIndex: 0 withObject: anim];
317
		else
318
			[animArray addObject: anim];
319
	}
320
	else
321
	{
322
		[animArray removeAllObjects];
323
		[animArray addObject: anim];
324
	}
325 25
}
326
327
- (NSTimeInterval) now
328
{
329
	return lastTime;
330
}
331
332
@end
333
334 28
NSString*	AnimationAbsoluteTimeKey = @"animationAbsoluteTime";
335
NSString*	AnimationPassedTimeKey	= @"animationPassedTime";
336
NSString*	AnimationDeltaTimeKey	= @"animationDeltaTime";
337
NSString*	AnimationUserInfoKey	= @"animationUserInfo";
338
339
@implementation ElCallbackAnimation
340
341
- (BOOL) animateForTime: (NSTimeInterval) time delta: (NSTimeInterval) delta
342
{
343
	BOOL result = [super animateForTime: time delta: delta];
344
345
	NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithDouble: time], AnimationAbsoluteTimeKey, [NSNumber numberWithDouble: time - startTime], AnimationPassedTimeKey, [NSNumber numberWithDouble: delta], AnimationDeltaTimeKey, userInfo, AnimationUserInfoKey, nil];
346
347
	
348
	[target performSelector: callback withObject: dict];
349
350
	return result;
351
}
352
353
354
@synthesize target, userInfo, callback;
355
356
@end

Loggerhead 1.17 is a web-based interface for Bazaar branches