internal static RectangleShape Parse(JsonReader reader, LottieComposition composition) { string name = null; IAnimatableValue <Vector2?, Vector2?> position = null; AnimatablePointValue size = null; AnimatableFloatValue roundedness = null; while (reader.HasNext()) { switch (reader.NextName()) { case "nm": name = reader.NextString(); break; case "p": position = AnimatablePathValueParser.ParseSplitPath(reader, composition); break; case "s": size = AnimatableValueParser.ParsePoint(reader, composition); break; case "r": roundedness = AnimatableValueParser.ParseFloat(reader, composition); break; default: reader.SkipValue(); break; } } return(new RectangleShape(name, position, size, roundedness)); }
internal static Repeater Parse(JsonReader reader, LottieComposition composition) { string name = null; AnimatableFloatValue copies = null; AnimatableFloatValue offset = null; AnimatableTransform transform = null; while (reader.HasNext()) { switch (reader.NextName()) { case "nm": name = reader.NextString(); break; case "c": copies = AnimatableValueParser.ParseFloat(reader, composition, false); break; case "o": offset = AnimatableValueParser.ParseFloat(reader, composition, false); break; case "tr": transform = AnimatableTransformParser.Parse(reader, composition); break; default: reader.SkipValue(); break; } } return(new Repeater(name, copies, offset, transform)); }
/// <summary> /// Returns either an <see cref="AnimatablePathValue"/> or an <see cref="AnimatableSplitDimensionPathValue"/>. /// </summary> /// <param name="reader"></param> /// <param name="composition"></param> /// <returns></returns> internal static IAnimatableValue <Vector2?, Vector2?> ParseSplitPath(JsonReader reader, LottieComposition composition) { AnimatablePathValue pathAnimation = null; AnimatableFloatValue xAnimation = null; AnimatableFloatValue yAnimation = null; bool hasExpressions = false; reader.BeginObject(); while (reader.Peek() != JsonToken.EndObject) { switch (reader.NextName()) { case "k": pathAnimation = Parse(reader, composition); break; case "x": if (reader.Peek() == JsonToken.String) { hasExpressions = true; reader.SkipValue(); } else { xAnimation = AnimatableValueParser.ParseFloat(reader, composition); } break; case "y": if (reader.Peek() == JsonToken.String) { hasExpressions = true; reader.SkipValue(); } else { yAnimation = AnimatableValueParser.ParseFloat(reader, composition); } break; default: reader.SkipValue(); break; } } reader.EndObject(); if (hasExpressions) { composition.AddWarning("Lottie doesn't support expressions."); } if (pathAnimation != null) { return(pathAnimation); } return(new AnimatableSplitDimensionPathValue(xAnimation, yAnimation)); }
internal static ShapeTrimPath Parse(JsonReader reader, LottieComposition composition) { string name = null; ShapeTrimPath.Type type = ShapeTrimPath.Type.Simultaneously; AnimatableFloatValue start = null; AnimatableFloatValue end = null; AnimatableFloatValue offset = null; bool hidden = false; while (reader.HasNext()) { switch (reader.NextName()) { case "s": start = AnimatableValueParser.ParseFloat(reader, composition, false); break; case "e": end = AnimatableValueParser.ParseFloat(reader, composition, false); break; case "o": offset = AnimatableValueParser.ParseFloat(reader, composition, false); break; case "nm": name = reader.NextString(); break; case "m": type = (ShapeTrimPath.Type)reader.NextInt(); break; case "hd": hidden = reader.NextBoolean(); break; default: reader.SkipValue(); break; } } return(new ShapeTrimPath(name, type, start, end, offset, hidden)); }
private static AnimatableTextProperties ParseAnimatableTextProperties(JsonReader reader, LottieComposition composition) { AnimatableColorValue color = null; AnimatableColorValue stroke = null; AnimatableFloatValue strokeWidth = null; AnimatableFloatValue tracking = null; reader.BeginObject(); while (reader.HasNext()) { switch (reader.NextName()) { case "fc": color = AnimatableValueParser.ParseColor(reader, composition); break; case "sc": stroke = AnimatableValueParser.ParseColor(reader, composition); break; case "sw": strokeWidth = AnimatableValueParser.ParseFloat(reader, composition); break; case "t": tracking = AnimatableValueParser.ParseFloat(reader, composition); break; default: reader.SkipValue(); break; } } reader.EndObject(); return(new AnimatableTextProperties(color, stroke, strokeWidth, tracking)); }
internal static ShapeStroke Parse(JsonReader reader, LottieComposition composition) { string name = null; AnimatableColorValue color = null; AnimatableFloatValue width = null; AnimatableIntegerValue opacity = null; ShapeStroke.LineCapType capType = ShapeStroke.LineCapType.Unknown; ShapeStroke.LineJoinType joinType = ShapeStroke.LineJoinType.Round; AnimatableFloatValue offset = null; float miterLimit = 0f; List <AnimatableFloatValue> lineDashPattern = new List <AnimatableFloatValue>(); bool hidden = false; while (reader.HasNext()) { switch (reader.NextName()) { case "nm": name = reader.NextString(); break; case "c": color = AnimatableValueParser.ParseColor(reader, composition); break; case "w": width = AnimatableValueParser.ParseFloat(reader, composition); break; case "o": opacity = AnimatableValueParser.ParseInteger(reader, composition); break; case "lc": capType = (ShapeStroke.LineCapType)(reader.NextInt() - 1); break; case "lj": joinType = (ShapeStroke.LineJoinType)(reader.NextInt() - 1); break; case "ml": miterLimit = reader.NextDouble(); break; case "d": reader.BeginArray(); while (reader.HasNext()) { String n = null; AnimatableFloatValue val = null; reader.BeginObject(); while (reader.HasNext()) { switch (reader.NextName()) { case "n": n = reader.NextString(); break; case "v": val = AnimatableValueParser.ParseFloat(reader, composition); break; default: reader.SkipValue(); break; } } reader.EndObject(); switch (n) { case "o": offset = val; break; case "d": case "g": lineDashPattern.Add(val); break; } } reader.EndArray(); if (lineDashPattern.Count == 1) { // If there is only 1 value then it is assumed to be equal parts on and off. lineDashPattern.Add(lineDashPattern[0]); } break; case "hd": hidden = reader.NextBoolean(); break; default: reader.SkipValue(); break; } } return(new ShapeStroke(name, offset, lineDashPattern, color, opacity, width, capType, joinType, miterLimit, hidden)); }
public static Layer Parse(JsonReader reader, LottieComposition composition) { string layerName = null; Layer.LayerType layerType = Layer.LayerType.Unknown; string refId = null; long layerId = 0; int solidWidth = 0; int solidHeight = 0; Color solidColor = Color.Transparent; int preCompWidth = 0; int preCompHeight = 0; long parentId = -1; float timeStretch = 1f; float startFrame = 0f; float inFrame = 0f; float outFrame = 0f; string cl = null; Layer.MatteType matteType = Layer.MatteType.None; AnimatableTransform transform = null; AnimatableTextFrame text = null; AnimatableTextProperties textProperties = null; AnimatableFloatValue timeRemapping = null; List <Mask> masks = new List <Mask>(); List <IContentModel> shapes = new List <IContentModel>(); reader.BeginObject(); while (reader.HasNext()) { switch (reader.NextName()) { case "nm": layerName = reader.NextString(); break; case "ind": layerId = reader.NextInt(); break; case "refId": refId = reader.NextString(); break; case "ty": int layerTypeInt = reader.NextInt(); if (layerTypeInt < (int)Layer.LayerType.Unknown) { layerType = (Layer.LayerType)layerTypeInt; } else { layerType = Layer.LayerType.Unknown; } break; case "parent": parentId = reader.NextInt(); break; case "sw": solidWidth = (int)(reader.NextInt() * Utils.Utils.DpScale()); break; case "sh": solidHeight = (int)(reader.NextInt() * Utils.Utils.DpScale()); break; case "sc": solidColor = Utils.Utils.GetSolidColorBrush(reader.NextString()); break; case "ks": transform = AnimatableTransformParser.Parse(reader, composition); break; case "tt": matteType = (Layer.MatteType)reader.NextInt(); break; case "masksProperties": reader.BeginArray(); while (reader.HasNext()) { masks.Add(MaskParser.Parse(reader, composition)); } reader.EndArray(); break; case "shapes": reader.BeginArray(); while (reader.HasNext()) { var shape = ContentModelParser.Parse(reader, composition); if (shape != null) { shapes.Add(shape); } } reader.EndArray(); break; case "t": reader.BeginObject(); while (reader.HasNext()) { switch (reader.NextName()) { case "d": text = AnimatableValueParser.ParseDocumentData(reader, composition); break; case "a": reader.BeginArray(); if (reader.HasNext()) { textProperties = AnimatableTextPropertiesParser.Parse(reader, composition); } while (reader.HasNext()) { reader.SkipValue(); } reader.EndArray(); break; default: reader.SkipValue(); break; } } reader.EndObject(); break; case "ef": reader.BeginArray(); List <string> effectNames = new List <string>(); while (reader.HasNext()) { reader.BeginObject(); while (reader.HasNext()) { switch (reader.NextName()) { case "nm": effectNames.Add(reader.NextString()); break; default: reader.SkipValue(); break; } } reader.EndObject(); } reader.EndArray(); composition.AddWarning("Lottie doesn't support layer effects. If you are using them for " + " fills, strokes, trim paths etc. then try adding them directly as contents " + " in your shape. Found: " + effectNames); break; case "sr": timeStretch = reader.NextDouble(); break; case "st": startFrame = reader.NextDouble(); break; case "w": preCompWidth = (int)(reader.NextInt() * Utils.Utils.DpScale()); break; case "h": preCompHeight = (int)(reader.NextInt() * Utils.Utils.DpScale()); break; case "ip": inFrame = reader.NextDouble(); break; case "op": outFrame = reader.NextDouble(); break; case "tm": timeRemapping = AnimatableValueParser.ParseFloat(reader, composition, false); break; case "cl": cl = reader.NextString(); break; default: reader.SkipValue(); break; } } reader.EndObject(); // Bodymovin pre-scales the in frame and out frame by the time stretch. However, that will // cause the stretch to be double counted since the in out animation gets treated the same // as all other animations and will have stretch applied to it again. inFrame /= timeStretch; outFrame /= timeStretch; List <Keyframe <float?> > inOutKeyframes = new List <Keyframe <float?> >(); // Before the in frame if (inFrame > 0) { Keyframe <float?> preKeyframe = new Keyframe <float?>(composition, 0f, 0f, null, 0f, inFrame); inOutKeyframes.Add(preKeyframe); } // The + 1 is because the animation should be visible on the out frame itself. outFrame = (outFrame > 0 ? outFrame : composition.EndFrame); Keyframe <float?> visibleKeyframe = new Keyframe <float?>(composition, 1f, 1f, null, inFrame, outFrame); inOutKeyframes.Add(visibleKeyframe); Keyframe <float?> outKeyframe = new Keyframe <float?>(composition, 0f, 0f, null, outFrame, float.MaxValue); inOutKeyframes.Add(outKeyframe); if (layerName.EndsWith(".ai") || "ai".Equals(cl)) { composition.AddWarning("Convert your Illustrator layers to shape layers."); } return(new Layer(shapes, composition, layerName, layerId, layerType, parentId, refId, masks, transform, solidWidth, solidHeight, solidColor, timeStretch, startFrame, preCompWidth, preCompHeight, text, textProperties, inOutKeyframes, matteType, timeRemapping)); }
internal static PolystarShape Parse(JsonReader reader, LottieComposition composition) { string name = null; PolystarShape.Type type = PolystarShape.Type.Polygon; AnimatableFloatValue points = null; IAnimatableValue <Vector2?, Vector2?> position = null; AnimatableFloatValue rotation = null; AnimatableFloatValue outerRadius = null; AnimatableFloatValue outerRoundedness = null; AnimatableFloatValue innerRadius = null; AnimatableFloatValue innerRoundedness = null; while (reader.HasNext()) { switch (reader.NextName()) { case "nm": name = reader.NextString(); break; case "sy": type = (PolystarShape.Type)reader.NextInt(); break; case "pt": points = AnimatableValueParser.ParseFloat(reader, composition, false); break; case "p": position = AnimatablePathValueParser.ParseSplitPath(reader, composition); break; case "r": rotation = AnimatableValueParser.ParseFloat(reader, composition, false); break; case "or": outerRadius = AnimatableValueParser.ParseFloat(reader, composition); break; case "os": outerRoundedness = AnimatableValueParser.ParseFloat(reader, composition, false); break; case "ir": innerRadius = AnimatableValueParser.ParseFloat(reader, composition); break; case "is": innerRoundedness = AnimatableValueParser.ParseFloat(reader, composition, false); break; default: reader.SkipValue(); break; } } return(new PolystarShape(name, type, points, position, rotation, innerRadius, outerRadius, innerRoundedness, outerRoundedness)); }
internal static GradientStroke Parse(JsonReader reader, LottieComposition composition) { string name = null; AnimatableGradientColorValue color = null; AnimatableIntegerValue opacity = null; var gradientType = GradientType.Linear; AnimatablePointValue startPoint = null; AnimatablePointValue endPoint = null; AnimatableFloatValue width = null; var capType = ShapeStroke.LineCapType.Unknown; var joinType = ShapeStroke.LineJoinType.Round; AnimatableFloatValue offset = null; var miterLimit = 0f; var lineDashPattern = new List <AnimatableFloatValue>(); while (reader.HasNext()) { switch (reader.NextName()) { case "nm": name = reader.NextString(); break; case "g": var points = -1; reader.BeginObject(); while (reader.HasNext()) { switch (reader.NextName()) { case "p": points = reader.NextInt(); break; case "k": color = AnimatableValueParser.ParseGradientColor(reader, composition, points); break; default: reader.SkipValue(); break; } } reader.EndObject(); break; case "o": opacity = AnimatableValueParser.ParseInteger(reader, composition); break; case "t": gradientType = reader.NextInt() == 1 ? GradientType.Linear : GradientType.Radial; break; case "s": startPoint = AnimatableValueParser.ParsePoint(reader, composition); break; case "e": endPoint = AnimatableValueParser.ParsePoint(reader, composition); break; case "w": width = AnimatableValueParser.ParseFloat(reader, composition); break; case "lc": capType = (ShapeStroke.LineCapType)(reader.NextInt() - 1); break; case "lj": joinType = (ShapeStroke.LineJoinType)(reader.NextInt() - 1); break; case "ml": miterLimit = reader.NextDouble(); break; case "d": reader.BeginArray(); while (reader.HasNext()) { string n = null; AnimatableFloatValue val = null; reader.BeginObject(); while (reader.HasNext()) { switch (reader.NextName()) { case "n": n = reader.NextString(); break; case "v": val = AnimatableValueParser.ParseFloat(reader, composition); break; default: reader.SkipValue(); break; } } reader.EndObject(); if (n.Equals("o")) { offset = val; } else if (n.Equals("d") || n.Equals("g")) { lineDashPattern.Add(val); } } reader.EndArray(); if (lineDashPattern.Count == 1) { // If there is only 1 value then it is assumed to be equal parts on and off. lineDashPattern.Add(lineDashPattern[0]); } break; default: reader.SkipValue(); break; } } return(new GradientStroke( name, gradientType, color, opacity, startPoint, endPoint, width, capType, joinType, miterLimit, lineDashPattern, offset)); }
public static AnimatableTransform Parse(JsonReader reader, LottieComposition composition) { AnimatablePathValue anchorPoint = null; IAnimatableValue <Vector2?, Vector2?> position = null; AnimatableScaleValue scale = null; AnimatableFloatValue rotation = null; AnimatableIntegerValue opacity = null; AnimatableFloatValue startOpacity = null; AnimatableFloatValue endOpacity = null; bool isObject = reader.Peek() == JsonToken.StartObject; if (isObject) { reader.BeginObject(); } while (reader.HasNext()) { switch (reader.NextName()) { case "a": reader.BeginObject(); while (reader.HasNext()) { if (reader.NextName().Equals("k")) { anchorPoint = AnimatablePathValueParser.Parse(reader, composition); } else { reader.SkipValue(); } } reader.EndObject(); break; case "p": position = AnimatablePathValueParser.ParseSplitPath(reader, composition); break; case "s": scale = AnimatableValueParser.ParseScale(reader, composition); break; case "rz": composition.AddWarning("Lottie doesn't support 3D layers."); rotation = AnimatableValueParser.ParseFloat(reader, composition, false); break; case "r": rotation = AnimatableValueParser.ParseFloat(reader, composition, false); break; case "o": opacity = AnimatableValueParser.ParseInteger(reader, composition); break; case "so": startOpacity = AnimatableValueParser.ParseFloat(reader, composition, false); break; case "eo": endOpacity = AnimatableValueParser.ParseFloat(reader, composition, false); break; default: reader.SkipValue(); break; } } if (isObject) { reader.EndObject(); } if (anchorPoint == null) { // Cameras don't have an anchor point property. Although we don't support them, at least // we won't crash. Debug.WriteLine("Layer has no transform property. You may be using an unsupported layer type such as a camera.", LottieLog.Tag); anchorPoint = new AnimatablePathValue(); } if (scale == null) { // Somehow some community animations don't have scale in the transform. scale = new AnimatableScaleValue(new ScaleXy(1f, 1f)); } if (opacity == null) { // Repeaters have start/end opacity instead of opacity opacity = new AnimatableIntegerValue(); } return(new AnimatableTransform( anchorPoint, position, scale, rotation, opacity, startOpacity, endOpacity)); }