mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-17 02:49:57 +00:00
243 lines
7.4 KiB
Objective-C
243 lines
7.4 KiB
Objective-C
//
|
|
// LOTKeyframe.m
|
|
// Pods
|
|
//
|
|
// Created by brandon_withrow on 7/10/17.
|
|
//
|
|
//
|
|
|
|
#import "LOTKeyframe.h"
|
|
#import "CGGeometry+LOTAdditions.h"
|
|
|
|
@implementation LOTKeyframe
|
|
|
|
- (instancetype)initWithKeyframe:(NSDictionary *)keyframe {
|
|
self = [super init];
|
|
if (self) {
|
|
_keyframeTime = keyframe[@"t"];
|
|
_inTangent = CGPointZero;
|
|
_outTangent = CGPointZero;
|
|
_spatialInTangent = CGPointZero;
|
|
_spatialOutTangent = CGPointZero;
|
|
NSDictionary *timingOutTangent = keyframe[@"o"];
|
|
NSDictionary *timingInTangent = keyframe[@"i"];
|
|
if (timingInTangent) {
|
|
_inTangent = [self _pointFromValueDict:timingInTangent];
|
|
}
|
|
if (timingOutTangent) {
|
|
_outTangent = [self _pointFromValueDict:timingOutTangent];
|
|
}
|
|
if ([keyframe[@"h"] boolValue]) {
|
|
_isHold = YES;
|
|
}
|
|
if (keyframe[@"to"]) {
|
|
NSArray *to = keyframe[@"to"];
|
|
_spatialOutTangent = [self _pointFromValueArray:to];
|
|
}
|
|
if (keyframe[@"ti"]) {
|
|
NSArray *ti = keyframe[@"ti"];
|
|
_spatialInTangent = [self _pointFromValueArray:ti];
|
|
}
|
|
id data = keyframe[@"s"];
|
|
if (data) {
|
|
[self setupOutputWithData:data];
|
|
}
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (instancetype)initWithValue:(id)value {
|
|
self = [super init];
|
|
if (self) {
|
|
_keyframeTime = @0;
|
|
_isHold = YES;
|
|
[self setupOutputWithData:value];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (instancetype)initWithLOTKeyframe:(LOTKeyframe *)keyframe {
|
|
self = [super init];
|
|
if (self) {
|
|
_keyframeTime = [keyframe.keyframeTime copy];
|
|
_inTangent = keyframe.inTangent;
|
|
_outTangent = keyframe.outTangent;
|
|
_spatialInTangent = keyframe.spatialInTangent;
|
|
_spatialOutTangent = keyframe.spatialOutTangent;
|
|
_isHold = keyframe.isHold;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (LOTKeyframe *)copyWithData:(id)data {
|
|
LOTKeyframe *newFrame = [[LOTKeyframe alloc] initWithLOTKeyframe:self];
|
|
[newFrame setData:data];
|
|
return newFrame;
|
|
}
|
|
|
|
- (void)setData:(id)data {
|
|
[self setupOutputWithData:data];
|
|
}
|
|
|
|
- (void)remapValueWithBlock:(CGFloat (^)(CGFloat inValue))remapBlock {
|
|
_floatValue = remapBlock(_floatValue);
|
|
_pointValue = CGPointMake(remapBlock(_pointValue.x), remapBlock(_pointValue.y));
|
|
_sizeValue = CGSizeMake(remapBlock(_sizeValue.width), remapBlock(_sizeValue.height));
|
|
}
|
|
|
|
- (void)setupOutputWithData:(id)data {
|
|
if ([data isKindOfClass:[NSNumber class]]) {
|
|
_floatValue = [(NSNumber*)data floatValue];
|
|
}
|
|
if ([data isKindOfClass:[NSArray class]] &&
|
|
[[(NSArray *)data firstObject] isKindOfClass:[NSNumber class]]) {
|
|
NSArray *numberArray = (NSArray *)data;
|
|
if (numberArray.count > 0) {
|
|
_floatValue = [(NSNumber *)numberArray[0] floatValue];
|
|
}
|
|
if (numberArray.count > 1) {
|
|
_pointValue = CGPointMake(_floatValue = [(NSNumber *)numberArray[0] floatValue],
|
|
_floatValue = [(NSNumber *)numberArray[1] floatValue]);
|
|
_sizeValue = CGSizeMake(_pointValue.x, _pointValue.y);
|
|
}
|
|
if (numberArray.count > 3) {
|
|
_colorValue = [self _colorValueFromArray:numberArray];
|
|
}
|
|
_arrayValue = numberArray;
|
|
} else if ([data isKindOfClass:[NSArray class]] &&
|
|
[[(NSArray *)data firstObject] isKindOfClass:[NSDictionary class]]) {
|
|
_pathData = [[LOTBezierData alloc] initWithData:[(NSArray *)data firstObject]];
|
|
} else if ([data isKindOfClass:[NSDictionary class]]) {
|
|
_pathData = [[LOTBezierData alloc] initWithData:data];
|
|
}
|
|
}
|
|
|
|
- (CGPoint)_pointFromValueArray:(NSArray *)values {
|
|
CGPoint returnPoint = CGPointZero;
|
|
if (values.count > 1) {
|
|
returnPoint.x = [(NSNumber *)values[0] floatValue];
|
|
returnPoint.y = [(NSNumber *)values[1] floatValue];
|
|
}
|
|
return returnPoint;
|
|
}
|
|
|
|
- (CGPoint)_pointFromValueDict:(NSDictionary *)values {
|
|
NSNumber *xValue = @0, *yValue = @0;
|
|
if ([values[@"x"] isKindOfClass:[NSNumber class]]) {
|
|
xValue = values[@"x"];
|
|
} else if ([values[@"x"] isKindOfClass:[NSArray class]]) {
|
|
xValue = values[@"x"][0];
|
|
}
|
|
|
|
if ([values[@"y"] isKindOfClass:[NSNumber class]]) {
|
|
yValue = values[@"y"];
|
|
} else if ([values[@"y"] isKindOfClass:[NSArray class]]) {
|
|
yValue = values[@"y"][0];
|
|
}
|
|
|
|
return CGPointMake([xValue floatValue], [yValue floatValue]);
|
|
}
|
|
|
|
- (UIColor *)_colorValueFromArray:(NSArray<NSNumber *> *)colorArray {
|
|
if (colorArray.count == 4) {
|
|
BOOL shouldUse255 = NO;
|
|
for (NSNumber *number in colorArray) {
|
|
if (number.floatValue > 1) {
|
|
shouldUse255 = YES;
|
|
}
|
|
}
|
|
return [UIColor colorWithRed:colorArray[0].floatValue / (shouldUse255 ? 255.f : 1.f)
|
|
green:colorArray[1].floatValue / (shouldUse255 ? 255.f : 1.f)
|
|
blue:colorArray[2].floatValue / (shouldUse255 ? 255.f : 1.f)
|
|
alpha:colorArray[3].floatValue / (shouldUse255 ? 255.f : 1.f)];
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation LOTKeyframeGroup
|
|
|
|
- (instancetype)initWithData:(id)data {
|
|
self = [super init];
|
|
if (self) {
|
|
if ([data isKindOfClass:[NSDictionary class]] &&
|
|
[(NSDictionary *)data valueForKey:@"k"]) {
|
|
[self buildKeyframesFromData:[(NSDictionary *)data valueForKey:@"k"]];
|
|
} else {
|
|
[self buildKeyframesFromData:data];
|
|
}
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)buildKeyframesFromData:(id)data {
|
|
if ([data isKindOfClass:[NSArray class]] &&
|
|
[[(NSArray *)data firstObject] isKindOfClass:[NSDictionary class]] &&
|
|
[(NSArray *)data firstObject][@"t"]) {
|
|
// Array of Keyframes
|
|
NSArray *keyframes = (NSArray *)data;
|
|
NSMutableArray *keys = [NSMutableArray array];
|
|
NSDictionary *previousFrame = nil;
|
|
for (NSDictionary *keyframe in keyframes) {
|
|
NSMutableDictionary *currentFrame = [NSMutableDictionary dictionary];
|
|
if (keyframe[@"t"]) {
|
|
// Set time
|
|
currentFrame[@"t"] = keyframe[@"t"];
|
|
}
|
|
if (keyframe[@"s"]) {
|
|
// Set Value for Keyframe
|
|
currentFrame[@"s"] = keyframe[@"s"];
|
|
} else if (previousFrame[@"e"]) {
|
|
// Set Value for Keyframe
|
|
currentFrame[@"s"] = previousFrame[@"e"];
|
|
}
|
|
if (keyframe[@"o"]) {
|
|
// Set out tangent
|
|
currentFrame[@"o"] = keyframe[@"o"];
|
|
}
|
|
if (previousFrame[@"i"]) {
|
|
currentFrame[@"i"] = previousFrame[@"i"];
|
|
}
|
|
if (keyframe[@"to"]) {
|
|
// Set out tangent
|
|
currentFrame[@"to"] = keyframe[@"to"];
|
|
}
|
|
if (previousFrame[@"ti"]) {
|
|
currentFrame[@"ti"] = previousFrame[@"ti"];
|
|
}
|
|
if (keyframe[@"h"]) {
|
|
currentFrame[@"h"] = keyframe[@"h"];
|
|
}
|
|
LOTKeyframe *key = [[LOTKeyframe alloc] initWithKeyframe:currentFrame];
|
|
[keys addObject:key];
|
|
previousFrame = keyframe;
|
|
}
|
|
_keyframes = keys;
|
|
|
|
} else {
|
|
LOTKeyframe *key = [[LOTKeyframe alloc] initWithValue:data];
|
|
_keyframes = @[key];
|
|
}
|
|
}
|
|
|
|
-(void)remapKeyframesWithBlock:(CGFloat (^)(CGFloat))remapBlock {
|
|
for (LOTKeyframe *keyframe in _keyframes) {
|
|
[keyframe remapValueWithBlock:remapBlock];
|
|
}
|
|
}
|
|
|
|
@end
|
|
/*
|
|
+KeyFrameObject has
|
|
+ i (PointObject) // Timing curve in tangent
|
|
+ o (PointObject) // Timing curve out tangent
|
|
+ n (array of string) // String representation of timing curve
|
|
+ t (integer) // Keyframe time for start of keyframe
|
|
+ s (float or array of float or PathObject) // The key information
|
|
+ e (float or array of float or PathObject) // The end key information
|
|
+ to (array of float) // For spacial bezier path interpolation, the in tangent
|
|
+ ti (array of float) // For spacial bezier path interpolation, the out tangent
|
|
+ h (integer) // If the keyframe is a Hold keyframe or not
|
|
*/
|