Exemplo n.º 1
0
 public Layer(List <IContentModel> shapes, LottieComposition composition, string layerName, long layerId, LayerType layerType, long parentId, string refId, List <Mask> masks, AnimatableTransform transform, int solidWidth, int solidHeight, Color solidColor, float timeStretch, float startFrame, int preCompWidth, int preCompHeight, AnimatableTextFrame text, AnimatableTextProperties textProperties, List <Keyframe <float?> > inOutKeyframes, MatteType matteType, AnimatableFloatValue timeRemapping)
 {
     _shapes        = shapes;
     _composition   = composition;
     Name           = layerName;
     Id             = layerId;
     _layerType     = layerType;
     ParentId       = parentId;
     RefId          = refId;
     Masks          = masks;
     Transform      = transform;
     SolidWidth     = solidWidth;
     SolidHeight    = solidHeight;
     SolidColor     = solidColor;
     TimeStretch    = timeStretch;
     StartFrame     = startFrame;
     PreCompWidth   = preCompWidth;
     PreCompHeight  = preCompHeight;
     Text           = text;
     TextProperties = textProperties;
     InOutKeyframes = inOutKeyframes;
     _matteType     = matteType;
     TimeRemapping  = timeRemapping;
 }
Exemplo n.º 2
0
        internal BaseStrokeContent(ILottieDrawable lottieDrawable, BaseLayer layer, SKStrokeCap cap, SKStrokeJoin join, float miterLimit, AnimatableIntegerValue opacity, AnimatableFloatValue width, List <AnimatableFloatValue> dashPattern, AnimatableFloatValue offset)
        {
            _lottieDrawable = lottieDrawable;
            _layer          = layer;

            Paint.Style       = SKPaintStyle.Stroke;
            Paint.StrokeCap   = cap;
            Paint.StrokeJoin  = join;
            Paint.StrokeMiter = miterLimit;

            _opacityAnimation = opacity.CreateAnimation();
            _widthAnimation   = width.CreateAnimation();

            if (offset == null)
            {
                _dashPatternOffsetAnimation = null;
            }
            else
            {
                _dashPatternOffsetAnimation = offset.CreateAnimation();
            }
            _dashPatternAnimations = new List <IBaseKeyframeAnimation <float?, float?> >(dashPattern.Count);
            _dashPatternValues     = new float[dashPattern.Count];

            for (var i = 0; i < dashPattern.Count; i++)
            {
                _dashPatternAnimations.Add(dashPattern[i].CreateAnimation());
            }

            layer.AddAnimation(_opacityAnimation);
            layer.AddAnimation(_widthAnimation);
            for (var i = 0; i < _dashPatternAnimations.Count; i++)
            {
                layer.AddAnimation(_dashPatternAnimations[i]);
            }
            if (_dashPatternOffsetAnimation != null)
            {
                layer.AddAnimation(_dashPatternOffsetAnimation);
            }

            _opacityAnimation.ValueChanged += OnValueChanged;
            _widthAnimation.ValueChanged   += OnValueChanged;

            for (var i = 0; i < dashPattern.Count; i++)
            {
                _dashPatternAnimations[i].ValueChanged += OnValueChanged;
            }
            if (_dashPatternOffsetAnimation != null)
            {
                _dashPatternOffsetAnimation.ValueChanged += OnValueChanged;
            }
        }
Exemplo n.º 3
0
 public RectangleShape(string name, IAnimatableValue <Vector2?, Vector2?> position, AnimatablePointValue size, AnimatableFloatValue cornerRadius)
 {
     Name          = name;
     _position     = position;
     _size         = size;
     _cornerRadius = cornerRadius;
 }
Exemplo n.º 4
0
        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));
        }
Exemplo n.º 5
0
 public ShapeTrimPath(string name, Type type, AnimatableFloatValue start, AnimatableFloatValue end, AnimatableFloatValue offset)
 {
     Name    = name;
     _type   = type;
     _start  = start;
     _end    = end;
     _offset = offset;
 }
Exemplo n.º 6
0
        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>();

            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;

                default:
                    reader.SkipValue();
                    break;
                }
            }

            return(new ShapeStroke(name, offset, lineDashPattern, color, opacity, width, capType, joinType, miterLimit));
        }
 public AnimatableTextProperties(AnimatableColorValue color, AnimatableColorValue stroke, AnimatableFloatValue strokeWidth, AnimatableFloatValue tracking)
 {
     _color       = color;
     _stroke      = stroke;
     _strokeWidth = strokeWidth;
     _tracking    = tracking;
 }
        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));
        }
Exemplo n.º 9
0
 public ShapeStroke(string name, AnimatableFloatValue offset, List <AnimatableFloatValue> lineDashPattern, AnimatableColorValue color, AnimatableIntegerValue opacity, AnimatableFloatValue width, LineCapType capType, LineJoinType joinType, float miterLimit, bool hidden)
 {
     Name            = name;
     DashOffset      = offset;
     LineDashPattern = lineDashPattern;
     Color           = color;
     Opacity         = opacity;
     Width           = width;
     CapType         = capType;
     JoinType        = joinType;
     MiterLimit      = miterLimit;
     IsHidden        = hidden;
 }
Exemplo n.º 10
0
 public GradientStroke(string name, GradientType gradientType, AnimatableGradientColorValue gradientColor, AnimatableIntegerValue opacity, AnimatablePointValue startPoint, AnimatablePointValue endPoint, AnimatableFloatValue width, ShapeStroke.LineCapType capType, ShapeStroke.LineJoinType joinType, float miterLimit, List <AnimatableFloatValue> lineDashPattern, AnimatableFloatValue dashOffset)
 {
     Name            = name;
     GradientType    = gradientType;
     GradientColor   = gradientColor;
     Opacity         = opacity;
     StartPoint      = startPoint;
     EndPoint        = endPoint;
     Width           = width;
     CapType         = capType;
     JoinType        = joinType;
     MiterLimit      = miterLimit;
     LineDashPattern = lineDashPattern;
     DashOffset      = dashOffset;
 }
Exemplo n.º 11
0
 public RectangleShape(string name, IAnimatableValue <Vector2?, Vector2?> position, AnimatablePointValue size, AnimatableFloatValue cornerRadius)
 {
     Name         = name;
     Position     = position;
     Size         = size;
     CornerRadius = cornerRadius;
     IsHidden     = hidden;
 }
Exemplo n.º 12
0
 public ShapeTrimPath(string name, Type type, AnimatableFloatValue start, AnimatableFloatValue end, AnimatableFloatValue offset, bool hidden)
 {
     Name     = name;
     _type    = type;
     Start    = start;
     End      = end;
     Offset   = offset;
     IsHidden = hidden;
 }
Exemplo n.º 13
0
 public GradientFill(string name, GradientType gradientType, PathFillType fillType,
                     AnimatableGradientColorValue gradientColor, AnimatableIntegerValue opacity, AnimatablePointValue startPoint,
                     AnimatablePointValue endPoint, AnimatableFloatValue highlightLength, AnimatableFloatValue highlightAngle)
 {
     GradientType    = gradientType;
     FillType        = fillType;
     GradientColor   = gradientColor;
     Opacity         = opacity;
     StartPoint      = startPoint;
     EndPoint        = endPoint;
     Name            = name;
     HighlightLength = highlightLength;
     HighlightAngle  = highlightAngle;
 }
        internal static GradientFill Parse(JsonReader reader, LottieComposition composition)
        {
            string name = null;
            AnimatableGradientColorValue color   = null;
            AnimatableIntegerValue       opacity = null;
            var gradientType = GradientType.Linear;
            AnimatablePointValue startPoint = null;
            AnimatablePointValue endPoint   = null;
            var fillType = PathFillType.EvenOdd;
            AnimatableFloatValue highlightAngle  = null;
            AnimatableFloatValue highlightLength = null;

            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 "r":
                    fillType = reader.NextInt() == 1 ? PathFillType.Winding : PathFillType.EvenOdd;
                    break;

                case "h":
                    highlightLength = AnimatableValueParser.ParseFloat(reader, composition);
                    break;

                case "a":
                    highlightAngle = AnimatableValueParser.ParseFloat(reader, composition);
                    break;

                default:
                    reader.SkipValue();
                    break;
                }
            }

            return(new GradientFill(
                       name, gradientType, fillType, color, opacity, startPoint, endPoint, highlightLength, highlightAngle));
        }
        /// <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 <Vector?, Vector?> ParseSplitPath(JsonReader reader,
                                                                           LottieComposition composition)
        {
            AnimatablePathValue  pathAnimation = null;
            AnimatableFloatValue xAnimation    = null;
            AnimatableFloatValue yAnimation    = null;

            var 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));
        }
Exemplo n.º 16
0
 public PolystarShape(string name, Type type, AnimatableFloatValue points, IAnimatableValue <Vector2?, Vector2?> position, AnimatableFloatValue rotation, AnimatableFloatValue innerRadius, AnimatableFloatValue outerRadius, AnimatableFloatValue innerRoundedness, AnimatableFloatValue outerRoundedness, bool hidden)
 {
     Name             = name;
     _type            = type;
     Points           = points;
     Position         = position;
     Rotation         = rotation;
     InnerRadius      = innerRadius;
     OuterRadius      = outerRadius;
     InnerRoundedness = innerRoundedness;
     OuterRoundedness = outerRoundedness;
     IsHidden         = hidden;
 }
Exemplo n.º 17
0
        public static Layer Parse(JsonReader reader, LottieComposition composition)
        {
            // This should always be set by After Effects. However, if somebody wants to minify
            // and optimize their json, the name isn't critical for most cases so it can be removed.
            string layerName = "UNSET";

            Layer.LayerType layerType   = Layer.LayerType.Unknown;
            string          refId       = null;
            long            layerId     = 0;
            int             solidWidth  = 0;
            int             solidHeight = 0;
            Color           solidColor;
            int             preCompWidth  = 0;
            int             preCompHeight = 0;
            long            parentId      = -1;
            float           timeStretch   = 1f;
            float           startFrame    = 0f;
            float           inFrame       = 0f;
            float           outFrame      = 0f;
            string          cl            = null;
            bool            hidden        = false;

            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;

                case "hd":
                    hidden = reader.NextBoolean();
                    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, hidden));
        }
Exemplo n.º 18
0
        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;

            var 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);
                    if (rotation.Keyframes.Count == 0)
                    {
                        rotation.Keyframes.Add(new Keyframe <float?>(composition, 0f, 0f, null, 0f, composition.EndFrame));
                    }
                    else if (rotation.Keyframes[0].StartValue == null)
                    {
                        rotation.Keyframes[0] = new Keyframe <float?>(composition, 0f, 0f, null, 0f, composition.EndFrame);
                    }
                    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));
        }
Exemplo n.º 19
0
            internal static Layer NewInstance(JsonObject json, LottieComposition composition)
            {
                var layerName = json.GetNamedString("nm");
                var refId     = json.GetNamedString("refId", string.Empty);

                if (layerName.EndsWith(".ai") || json.GetNamedString("cl", "").Equals("ai"))
                {
                    composition.AddWarning("Convert your Illustrator layers to shape layers.");
                }

                var       layerId     = (long)json.GetNamedNumber("ind");
                var       solidWidth  = 0;
                var       solidHeight = 0;
                Color     solidColor;
                var       preCompWidth  = 0;
                var       preCompHeight = 0;
                LayerType layerType;
                var       layerTypeInt = (int)json.GetNamedNumber("ty", -1);

                if (layerTypeInt < (int)LayerType.Unknown)
                {
                    layerType = (LayerType)layerTypeInt;
                }
                else
                {
                    layerType = LayerType.Unknown;
                }

                if (layerType == LayerType.Text && !Utils.Utils.IsAtLeastVersion(composition, 4, 8, 0))
                {
                    layerType = LayerType.Unknown;
                    composition.AddWarning("Text is only supported on bodymovin >= 4.8.0");
                }

                var parentId = (long)json.GetNamedNumber("parent", -1);

                if (layerType == LayerType.Solid)
                {
                    solidWidth  = (int)(json.GetNamedNumber("sw") * composition.DpScale);
                    solidHeight = (int)(json.GetNamedNumber("sh") * composition.DpScale);
                    solidColor  = Utils.Utils.GetSolidColorBrush(json.GetNamedString("sc"));
                    Debug.WriteLine("\tSolid=" + string.Format("{0:X}", solidColor) + " " + solidWidth + "x" + solidHeight + " " + composition.Bounds, Tag);
                }

                var transform      = AnimatableTransform.Factory.NewInstance(json.GetNamedObject("ks"), composition);
                var matteType      = (MatteType)(int)json.GetNamedNumber("tt", 0);
                var masks          = new List <Mask>();
                var inOutKeyframes = new List <IKeyframe <float?> >();
                var jsonMasks      = json.GetNamedArray("masksProperties", null);

                if (jsonMasks != null)
                {
                    for (var i = 0; i < jsonMasks.Count; i++)
                    {
                        var mask = Mask.Factory.NewMask(jsonMasks[i].GetObject(), composition);
                        masks.Add(mask);
                    }
                }

                var shapes     = new List <IContentModel>();
                var shapesJson = json.GetNamedArray("shapes", null);

                if (shapesJson != null)
                {
                    for (var i = 0; i < shapesJson.Count; i++)
                    {
                        var shape = ShapeGroup.ShapeItemWithJson(shapesJson[i].GetObject(), composition);
                        if (shape != null)
                        {
                            shapes.Add(shape);
                        }
                    }
                }

                AnimatableTextFrame      text           = null;
                AnimatableTextProperties textProperties = null;
                var textJson = json.GetNamedObject("t", null);

                if (textJson != null)
                {
                    text = AnimatableTextFrame.Factory.NewInstance(textJson.GetNamedObject("d", null), composition);
                    var namedArray     = textJson.GetNamedArray("a", null);
                    var propertiesJson = namedArray?.Count > 0 ? namedArray.GetObjectAt(0) : null;
                    textProperties = AnimatableTextProperties.Factory.NewInstance(propertiesJson, composition);
                }

                if (json.ContainsKey("ef"))
                {
                    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.");
                }

                var timeStretch   = (float)json.GetNamedNumber("sr", 1.0);
                var startFrame    = (float)json.GetNamedNumber("st");
                var frames        = composition.DurationFrames;
                var startProgress = startFrame / frames;

                if (layerType == LayerType.PreComp)
                {
                    preCompWidth  = (int)(json.GetNamedNumber("w") * composition.DpScale);
                    preCompHeight = (int)(json.GetNamedNumber("h") * composition.DpScale);
                }

                // 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.
                var inFrame  = (float)json.GetNamedNumber("ip") / timeStretch;
                var outFrame = (float)json.GetNamedNumber("op") / timeStretch;

                // Before the in frame
                if (inFrame > 0)
                {
                    var 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 + 1;
                var visibleKeyframe = new Keyframe <float?>(composition, 1f, 1f, null, inFrame, outFrame);

                inOutKeyframes.Add(visibleKeyframe);

                var outKeyframe = new Keyframe <float?>(composition, 0f, 0f, null, outFrame, float.MaxValue);

                inOutKeyframes.Add(outKeyframe);

                AnimatableFloatValue timeRemapping = null;

                if (json.ContainsKey("tm"))
                {
                    timeRemapping = AnimatableFloatValue.Factory.NewInstance(json.GetNamedObject("tm", null), composition, false);
                }

                return(new Layer(shapes, composition, layerName, layerId, layerType, parentId, refId, masks, transform, solidWidth, solidHeight, solidColor, timeStretch, startProgress, preCompWidth, preCompHeight, text, textProperties, inOutKeyframes, matteType, timeRemapping));
            }