RSS

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

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
48
@end;
49
50
51
@implementation ElAnimation
52
53 27
- (void) queueForKey: (NSString*) key atBeginning: (BOOL) atBeginning cancelPending: (BOOL) cancelPending;
54 25
{
55 27
	[[ElAnimationController sharedController] queueAnimation: self forKey: key atBeginning: atBeginning cancelPending: cancelPending];
56 25
}
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 27
- (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 25
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 27
- (void) dealloc
122
{
123
	[target release];
124
	[super dealloc];
125
}
126 25
127
@synthesize startValue, endValue, target, property;
128
129
@end
130
131 43
@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 25
@implementation ElAnimationController
181
182
- (id) init
183
{
184
	if (!(self = [super init]))
185
		return nil;
186
187 27
	queuedAnimations = [[NSMutableDictionary alloc] init];
188 25
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 27
	NSMutableArray* keysToRemove = [NSMutableArray array];
220
	for (id key in queuedAnimations)
221 25
	{
222 27
		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 25
	}
242 27
	[queuedAnimations removeObjectsForKeys: keysToRemove];
243 25
	lastTime = time;
244
}
245
246 27
- (void) queueAnimation: (ElAnimation*) anim forKey: (id) key atBeginning: (BOOL) atBeginning cancelPending: (BOOL) cancelPending
247 25
{
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 27
	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 25
}
286
287
- (NSTimeInterval) now
288
{
289
	return lastTime;
290
}
291
292
@end
293
294 28
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