Ejemplo n.º 1
0
        internal ShapeLayer(LottieDrawable lottieDrawable, Layer layerModel) : base(lottieDrawable, layerModel)
        {
            var shapeGroup = new ShapeGroup(layerModel.Name, layerModel.Shapes);

            _contentGroup = new ContentGroup(lottieDrawable, this, shapeGroup);
            _contentGroup.SetContents(new List <IContent>(), new List <IContent>());
        }
Ejemplo n.º 2
0
            internal static FontCharacter NewInstance(JsonObject json, LottieComposition composition)
            {
                var character             = json.GetNamedString("ch").ElementAt(0);
                var size                  = (int)json.GetNamedNumber("size", 0);
                var width                 = json.GetNamedNumber("w", 0);
                var style                 = json.GetNamedString("style", "");
                var fontFamily            = json.GetNamedString("fFamily", "");
                var shapesJson            = json.GetNamedObject("data", null)?.GetNamedArray("shapes", null);
                IList <ShapeGroup> shapes = new List <ShapeGroup>();

                if (shapesJson != null)
                {
                    shapes = new List <ShapeGroup>(shapesJson.Count);
                    for (uint i = 0; i < shapesJson.Count; i++)
                    {
                        shapes.Add((ShapeGroup)ShapeGroup.ShapeItemWithJson(shapesJson.GetObjectAt(i), composition));
                    }
                }
                return(new FontCharacter(shapes, character, size, width, style, fontFamily));
            }
Ejemplo n.º 3
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;
                }

                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.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);
                IList <object> shapes    = new List <object>();
                IList <Mask>   masks     = new List <Mask>();
                IList <IKeyframe <float?> > 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 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);
                        }
                    }
                }

                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);
                }

                var inFrame  = (float)json.GetNamedNumber("ip");
                var outFrame = (float)json.GetNamedNumber("op");

                // 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);

                if (outFrame <= composition.DurationFrames)
                {
                    var outKeyframe = new Keyframe <float?>(composition, 0f, 0f, null, outFrame, composition.EndFrame);
                    inOutKeyframes.Add(outKeyframe);
                }

                return(new Layer(shapes, composition, layerName, layerId, layerType, parentId, refId, masks, transform, solidWidth, solidHeight, solidColor, timeStretch, startProgress, preCompWidth, preCompHeight, inOutKeyframes, matteType));
            }
Ejemplo n.º 4
0
 internal ContentGroup(LottieDrawable lottieDrawable, BaseLayer layer, ShapeGroup shapeGroup)
     : this(lottieDrawable, layer, shapeGroup.Name,
            ContentsFromModels(lottieDrawable, layer, shapeGroup.Items),
            FindTransform(shapeGroup.Items))
 {
 }
Ejemplo n.º 5
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.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.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));
            }
Ejemplo n.º 6
0
        internal ContentGroup(LottieDrawable lottieDrawable, BaseLayer layer, ShapeGroup shapeGroup)
        {
            Name = shapeGroup.Name;
            var items = shapeGroup.Items;

            if (items.Count == 0)
            {
                return;
            }

            if (items[items.Count - 1] is AnimatableTransform animatableTransform)
            {
                _transformAnimation = animatableTransform.CreateAnimation();

                _transformAnimation.AddAnimationsToLayer(layer);
                _transformAnimation.ValueChanged += (sender, args) =>
                {
                    lottieDrawable.InvalidateSelf();
                };
            }

            for (var i = 0; i < items.Count; i++)
            {
                var item = items[i];
                if (item is ShapeFill)
                {
                    _contents.Add(new FillContent(lottieDrawable, layer, (ShapeFill)item));
                }
                else if (item is GradientFill)
                {
                    _contents.Add(new GradientFillContent(lottieDrawable, layer, (GradientFill)item));
                }
                else if (item is ShapeStroke)
                {
                    _contents.Add(new StrokeContent(lottieDrawable, layer, (ShapeStroke)item));
                }
                else if (item is GradientStroke)
                {
                    _contents.Add(new GradientStrokeContent(lottieDrawable, layer, (GradientStroke)item));
                }
                else if (item is ShapeGroup)
                {
                    _contents.Add(new ContentGroup(lottieDrawable, layer, (ShapeGroup)item));
                }
                else if (item is RectangleShape)
                {
                    _contents.Add(new RectangleContent(lottieDrawable, layer, (RectangleShape)item));
                }
                else if (item is CircleShape)
                {
                    _contents.Add(new EllipseContent(lottieDrawable, layer, (CircleShape)item));
                }
                else if (item is ShapePath)
                {
                    _contents.Add(new ShapeContent(lottieDrawable, layer, (ShapePath)item));
                }
                else if (item is PolystarShape)
                {
                    _contents.Add(new PolystarContent(lottieDrawable, layer, (PolystarShape)item));
                }
                else if (item is ShapeTrimPath)
                {
                    _contents.Add(new TrimPathContent(layer, (ShapeTrimPath)item));
                }
                else
                {
                    if (item is MergePaths mergePaths)
                    {
                        if (lottieDrawable.EnableMergePathsForKitKatAndAbove())
                        {
                            _contents.Add(new MergePathsContent(mergePaths));
                        }
                        else
                        {
                            Debug.WriteLine("Animation contains merge paths but they are disabled.", Tag);
                        }
                    }
                }
            }

            IList <IContent>  contentsToRemove         = new List <IContent>();
            MergePathsContent currentMergePathsContent = null;

            for (var i = _contents.Count - 1; i >= 0; i--)
            {
                var content = _contents[i];
                if (content is MergePathsContent mergePathsContent)
                {
                    currentMergePathsContent = mergePathsContent;
                }
                if (currentMergePathsContent != null && content != currentMergePathsContent)
                {
                    currentMergePathsContent.AddContentIfNeeded(content);
                    contentsToRemove.Add(content);
                }
            }

            for (var i = _contents.Count - 1; i >= 0; i--)
            {
                if (contentsToRemove.Contains(_contents[i]))
                {
                    _contents.RemoveAt(i);
                }
            }
        }