public Vector2?Parse(JsonReader reader, float scale) { JsonToken token = reader.Peek(); if (token == JsonToken.StartArray) { return(JsonUtils.JsonToPoint(reader, scale)); } if (token == JsonToken.StartObject) { return(JsonUtils.JsonToPoint(reader, scale)); } if (token == JsonToken.Integer || token == JsonToken.Float) { // This is the case where the static value for a property is an array of numbers. // We begin the array to see if we have an array of keyframes but it's just an array // of static numbers instead. var point = new Vector2(reader.NextDouble() * scale, reader.NextDouble() * scale); while (reader.HasNext()) { reader.SkipValue(); } return(point); } throw new System.ArgumentException("Cannot convert json to point. Next token is " + token); }
public static AnimatablePathValue Parse(JsonReader reader, LottieComposition composition) { List <Keyframe <Vector2?> > keyframes = new List <Keyframe <Vector2?> >(); if (reader.Peek() == JsonToken.StartArray) { reader.BeginArray(); while (reader.HasNext()) { keyframes.Add(PathKeyframeParser.Parse(reader, composition)); } reader.EndArray(); KeyframesParser.SetEndFrames <Keyframe <Vector2?>, Vector2?>(keyframes); } else { keyframes.Add(new Keyframe <Vector2?>(JsonUtils.JsonToPoint(reader, Utils.Utils.DpScale()))); } return(new AnimatablePathValue(keyframes)); }
public Vector2?Parse(JsonReader reader, float scale) { return(JsonUtils.JsonToPoint(reader, scale)); }
/// <summary> /// beginObject will already be called on the keyframe so it can be differentiated with /// a non animated value. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="composition"></param> /// <param name="reader"></param> /// <param name="scale"></param> /// <param name="valueParser"></param> /// <returns></returns> private static Keyframe <T> ParseKeyframe <T>(LottieComposition composition, JsonReader reader, float scale, IValueParser <T> valueParser) { Vector2? cp1 = null; Vector2? cp2 = null; float startFrame = 0; T startValue = default(T); T endValue = default(T); bool hold = false; IInterpolator interpolator; // Only used by PathKeyframe Vector2?pathCp1 = null; Vector2?pathCp2 = null; reader.BeginObject(); while (reader.HasNext()) { switch (reader.NextName()) { case "t": startFrame = reader.NextDouble(); break; case "s": startValue = valueParser.Parse(reader, scale); break; case "e": endValue = valueParser.Parse(reader, scale); break; case "o": cp1 = JsonUtils.JsonToPoint(reader, scale); break; case "i": cp2 = JsonUtils.JsonToPoint(reader, scale); break; case "h": hold = reader.NextInt() == 1; break; case "to": pathCp1 = JsonUtils.JsonToPoint(reader, scale); break; case "ti": pathCp2 = JsonUtils.JsonToPoint(reader, scale); break; default: reader.SkipValue(); break; } } reader.EndObject(); if (hold) { endValue = startValue; // TODO: create a HoldInterpolator so progress changes don't invalidate. interpolator = LinearInterpolator; } else if (cp1 != null && cp2 != null) { cp1 = new Vector2(MiscUtils.Clamp(cp1.Value.X, -scale, scale), MiscUtils.Clamp(cp1.Value.Y, -MaxCpValue, MaxCpValue)); cp2 = new Vector2(MiscUtils.Clamp(cp2.Value.X, -scale, scale), MiscUtils.Clamp(cp2.Value.Y, -MaxCpValue, MaxCpValue)); int hash = Utils.Utils.HashFor(cp1.Value.X, cp1.Value.Y, cp2.Value.X, cp2.Value.Y); if (GetInterpolator(hash, out var interpolatorRef) == false || interpolatorRef.TryGetTarget(out interpolator) == false) { interpolator = new PathInterpolator(cp1.Value.X / scale, cp1.Value.Y / scale, cp2.Value.X / scale, cp2.Value.Y / scale); try { PutInterpolator(hash, new WeakReference <IInterpolator>(interpolator)); } catch { // It is not clear why but SparseArrayCompat sometimes fails with this: // https://github.com/airbnb/lottie-android/issues/452 // Because this is not a critical operation, we can safely just ignore it. // I was unable to repro this to attempt a proper fix. } } } else { interpolator = LinearInterpolator; } var keyframe = new Keyframe <T>(composition, startValue, endValue, interpolator, startFrame, null) { PathCp1 = pathCp1, PathCp2 = pathCp2 }; return(keyframe); }