Skip to content

Instantly share code, notes, and snippets.

@CastIrony
Created April 30, 2010 16:19
Show Gist options
  • Save CastIrony/385419 to your computer and use it in GitHub Desktop.
Save CastIrony/385419 to your computer and use it in GitHub Desktop.
#import "Common.h"
@interface AnimatedFloat : NSObject
{
float _startValue;
NSTimeInterval _startTime;
BOOL _hasStarted;
float _endValue;
NSTimeInterval _endTime;
BOOL _hasEnded;
AnimationCurve _curve;
}
@property (nonatomic, assign) float startValue;
@property (nonatomic, assign) NSTimeInterval startTime;
@property (nonatomic, readonly) BOOL hasStarted;
@property (nonatomic, assign) float endValue;
@property (nonatomic, assign) NSTimeInterval endTime;
@property (nonatomic, readonly) BOOL hasEnded;
@property (nonatomic, assign) AnimationCurve curve;
@property (nonatomic, assign) float value;
+(id)withValue:(float)value;
+(id)withStartValue:(float)startValue endValue:(float)endValue speed:(float)speed;
+(id)withStartValue:(float)startValue endValue:(float)endValue forTime:(NSTimeInterval)time;
-(NSString*)description;
@end
#import "AnimatedFloat.h"
@interface AnimatedFloat ()
@property (nonatomic, assign) BOOL hasStarted;
@property (nonatomic, assign) BOOL hasEnded;
@end
@implementation AnimatedFloat
@synthesize startValue = _startValue;
@synthesize startTime = _startTime;
@synthesize hasStarted = _hasStarted;
@synthesize endValue = _endValue;
@synthesize endTime = _endTime;
@synthesize hasEnded = _hasEnded;
@synthesize curve = _curve;
@dynamic value;
-(id)initWithStartValue:(float)startValue endValue:(float)endValue startTime:(NSTimeInterval)startTime endTime:(NSTimeInterval)endTime
{
self = [super init];
if(self)
{
_startValue = startValue;
_startTime = startTime;
_endValue = endValue;
_endTime = startTime + TIMESCALE * (endTime - startTime);
_hasStarted = NO;
_hasEnded = NO;
_curve = AnimationLinear;
}
return self;
}
+(id)withValue:(float)value
{
NSTimeInterval now = CFAbsoluteTimeGetCurrent();
return [[[AnimatedFloat alloc] initWithStartValue:value endValue:value startTime:now endTime:now] autorelease];
}
+(id)withStartValue:(float)startValue endValue:(float)endValue speed:(float)speed
{
NSTimeInterval now = CFAbsoluteTimeGetCurrent();
if(speed == 0)
{
return [[[AnimatedFloat alloc] initWithStartValue:startValue endValue:endValue startTime:now endTime:now] autorelease];
}
else
{
return [[[AnimatedFloat alloc] initWithStartValue:startValue endValue:endValue startTime:now endTime:now + absf(endValue, startValue) / speed] autorelease];
}
}
+(id)withStartValue:(float)startValue endValue:(float)endValue forTime:(NSTimeInterval)timeInterval
{
NSTimeInterval now = CFAbsoluteTimeGetCurrent();
return [[[AnimatedFloat alloc] initWithStartValue:startValue endValue:endValue startTime:now endTime:now + timeInterval] autorelease];
}
-(NSString*)description
{
return [NSString stringWithFormat:@"[%f5] -> [%f5]", _startValue, _endValue];
}
-(float)value
{
NSTimeInterval now = CFAbsoluteTimeGetCurrent();
if(now > self.startTime && !self.hasStarted)
{
// You can perform some post-start action here
self.hasStarted = YES;
}
if(now > self.endTime && !self.hasEnded)
{
// You can perform some post-end action here
self.hasEnded = YES;
}
if(now < self.startTime) { return self.startValue; }
if(now > self.endTime) { return self.endValue; }
float delta = (now - self.startTime) / (self.endTime - self.startTime);
float proportion = delta;
if(self.curve == AnimationEaseIn) { proportion = (3 * delta - delta * delta * delta) / 2; }
if(self.curve == AnimationEaseOut) { proportion = (3 * delta * delta - delta * delta * delta) / 2; }
if(self.curve == AnimationEaseInOut) { proportion = (3 * delta * delta - 2 * delta * delta * delta); }
return (1.0 - proportion) * self.startValue + (proportion) * self.endValue;
}
-(void)setValue:(float)value
{
NSTimeInterval now = CFAbsoluteTimeGetCurrent();
self.startTime = now;
self.endTime = now;
self.startValue = value;
self.endValue = value;
self.hasStarted = YES;
self.hasEnded = YES;
}
@end
#import "Common.h"
@interface AnimatedVector3D : NSObject
{
Vector3D _startValue;
NSTimeInterval _startTime;
BOOL _hasStarted;
Vector3D _endValue;
NSTimeInterval _endTime;
BOOL _hasEnded;
AnimationCurve _curve;
}
@property (nonatomic, assign) Vector3D startValue;
@property (nonatomic, assign) NSTimeInterval startTime;
@property (nonatomic, readonly) BOOL hasStarted;
@property (nonatomic, assign) Vector3D endValue;
@property (nonatomic, assign) NSTimeInterval endTime;
@property (nonatomic, readonly) BOOL hasEnded;
@property (nonatomic, assign) AnimationCurve curve;
@property (nonatomic, assign) Vector3D value;
+(id)withValue:(Vector3D)value;
+(id)withStartValue:(Vector3D)startValue endValue:(Vector3D)endValue speed:(float)speed;
+(id)withStartValue:(Vector3D)startValue endValue:(Vector3D)endValue forTime:(NSTimeInterval)time;
-(NSString*)description;
@end
#import "AnimatedVector3D.h"
@interface AnimatedVector3D ()
@property (nonatomic, assign) BOOL hasStarted;
@property (nonatomic, assign) BOOL hasEnded;
@end
@implementation AnimatedVector3D
@synthesize startValue = _startValue;
@synthesize startTime = _startTime;
@synthesize hasStarted = _hasStarted;
@synthesize endValue = _endValue;
@synthesize endTime = _endTime;
@synthesize hasEnded = _hasEnded;
@synthesize curve = _curve;
@dynamic value;
-(id)initWithStartValue:(Vector3D)startValue endValue:(Vector3D)endValue startTime:(NSTimeInterval)startTime endTime:(NSTimeInterval)endTime
{
self = [super init];
if(self)
{
_startValue = startValue;
_startTime = startTime;
_endValue = endValue;
_endTime = startTime + TIMESCALE * (endTime - startTime);
_hasStarted = NO;
_hasEnded = NO;
_curve = AnimationLinear;
}
return self;
}
+(id)withValue:(Vector3D)value
{
NSTimeInterval now = CFAbsoluteTimeGetCurrent();
return [[[AnimatedVector3D alloc] initWithStartValue:value endValue:value startTime:now endTime:now] autorelease];
}
+(id)withStartValue:(Vector3D)startValue endValue:(Vector3D)endValue speed:(float)speed
{
NSTimeInterval now = CFAbsoluteTimeGetCurrent();
if(speed == 0)
{
return [[[AnimatedVector3D alloc] initWithStartValue:startValue endValue:endValue startTime:now endTime:now] autorelease];
}
else
{
Vector3D difference = Vector3DMakeWithStartAndEndPoints(startValue, endValue);
float length = Vector3DMagnitude(difference);
return [[[AnimatedVector3D alloc] initWithStartValue:startValue endValue:endValue startTime:now endTime:now + length / abs(speed)] autorelease];
}
}
+(id)withStartValue:(Vector3D)startValue endValue:(Vector3D)endValue forTime:(NSTimeInterval)timeInterval
{
NSTimeInterval now = CFAbsoluteTimeGetCurrent();
return [[[AnimatedVector3D alloc] initWithStartValue:startValue endValue:endValue startTime:now endTime:now + timeInterval] autorelease];
}
-(NSString*)description
{
return [NSString stringWithFormat:@"[%f5, %f5, %f5] -> [%f5, %f5, %f5]", _startValue.x, _startValue.y, _startValue.z, _endValue.x, _endValue.y, _endValue.z];
}
-(Vector3D)value
{
NSTimeInterval now = CFAbsoluteTimeGetCurrent();
if(now > self.startTime && !self.hasStarted)
{
// You can perform some post-start action here
self.hasStarted = YES;
}
if(now > self.endTime && !self.hasEnded)
{
// You can perform some post-end action here
self.hasEnded = YES;
}
if(now < self.startTime) { return self.startValue; }
if(now > self.endTime) { return self.endValue; }
float delta = (now - self.startTime) / (self.endTime - self.startTime);
float delta2 = delta * delta;
float delta3 = delta * delta2;
float proportion = delta;
if(self.curve == AnimationEaseIn) { proportion = (3 * delta - delta3) / 2; }
if(self.curve == AnimationEaseOut) { proportion = (3 * delta2 - delta3) / 2; }
if(self.curve == AnimationEaseInOut) { proportion = (3 * delta2 - 2 * delta3); }
return Vector3DInterpolate(self.startValue, self.endValue, proportion);
}
-(void)setValue:(Vector3D)value
{
NSTimeInterval now = CFAbsoluteTimeGetCurrent();
self.startTime = now;
self.endTime = now;
self.startValue = value;
self.endValue = value;
self.hasStarted = YES;
self.hasEnded = YES;
}
@end
#define TIMESCALE 1
enum
{
AnimationEaseInOut,
AnimationEaseIn,
AnimationEaseOut,
AnimationLinear
}
typedef AnimationCurve;
static inline float absf(float float1, float float2)
{
return float1 < float2 ? float2 - float1 : float1 - float2;
}
typedef struct
{
float x;
float y;
float z;
} Vector3D;
static inline Vector3D Vector3DMake(float inX, float inY, float inZ)
{
Vector3D ret;
ret.x = inX;
ret.y = inY;
ret.z = inZ;
return ret;
}
static inline Vector3D Vector3DInterpolate(Vector3D startValue, Vector3D endValue, float proportion)
{
return Vector3DMake((1.0 - proportion) * startValue.x + (proportion) * endValue.x,
(1.0 - proportion) * startValue.y + (proportion) * endValue.y,
(1.0 - proportion) * startValue.z + (proportion) * endValue.z);
}
static inline float Vector3DMagnitude(Vector3D vector)
{
return sqrtf((vector.x * vector.x) + (vector.y * vector.y) + (vector.z * vector.z));
}
static inline Vector3D Vector3DMakeWithStartAndEndPoints(Vector3D start, Vector3D end)
{
Vector3D ret;
ret.x = end.x - start.x;
ret.y = end.y - start.y;
ret.z = end.z - start.z;
return ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment