コード例 #1
0
        public static Sn.Matrix3x2 CreateMatrixFromTransform(LayerContext context, Transform transform)
        {
            if (transform is null)
            {
                return(Sn.Matrix3x2.Identity);
            }

            if (transform.IsAnimated)
            {
                // TODO - report an issue. We can't handle an animated transform.
                // TODO - we could handle it if the only thing that is animated is the Opacity.
            }

            var anchor   = ConvertTo.Vector2(transform.Anchor.InitialValue);
            var position = ConvertTo.Vector2(transform.Position.InitialValue);
            var scale    = ConvertTo.Vector2(transform.ScalePercent.InitialValue / 100.0);
            var rotation = (float)transform.Rotation.InitialValue.Radians;

            // Calculate the matrix that is equivalent to the properties.
            var combinedMatrix =
                Sn.Matrix3x2.CreateScale(scale, anchor) *
                Sn.Matrix3x2.CreateRotation(rotation, anchor) *
                Sn.Matrix3x2.CreateTranslation(position + anchor);

            return(combinedMatrix);
        }
コード例 #2
0
ファイル: SolidLayers.cs プロジェクト: mezstd/Lottie-Windows
            internal override Visual?GetVisualRoot(CompositionContext context)
            {
                // Translate the SolidLayer to a Visual.
                if (_context.Layer.IsHidden || _context.Layer.Transform.Opacity.IsAlways(LottieData.Opacity.Transparent))
                {
                    // The layer does not render anything. Nothing to translate. This can happen when someone
                    // creates a solid layer to act like a Null layer.
                    return(null);
                }

                if (!Transforms.TryCreateContainerVisualTransformChain(_context, out var containerRootNode, out var containerContentNode))
                {
                    // The layer is never visible.
                    return(null);
                }

                var rectangle = context.ObjectFactory.CreateSpriteVisual();

                rectangle.Size = ConvertTo.Vector2(_context.Layer.Width, _context.Layer.Height);

                containerContentNode.Children.Add(rectangle);

                var layerHasMasks = false;

#if !NoClipping
                layerHasMasks = _context.Layer.Masks.Any();
#endif
                rectangle.Brush = Brushes.CreateNonAnimatedColorBrush(_context, _context.Layer.Color);

                rectangle.SetDescription(context, () => "SolidLayerRectangle");

                var result = layerHasMasks
                    ? Masks.TranslateAndApplyMasksForLayer(_context, containerRootNode)
                    : containerRootNode;

                Describe(context, result);

                return(result);
            }
コード例 #3
0
        public static CompositionShape TranslateEllipseContent(ShapeContext context, Ellipse shapeContent)
        {
            // An ellipse is represented as a SpriteShape with a CompositionEllipseGeometry.
            var compositionSpriteShape = context.ObjectFactory.CreateSpriteShape();

            compositionSpriteShape.SetDescription(context, () => shapeContent.Name);

            var compositionEllipseGeometry = context.ObjectFactory.CreateEllipseGeometry();

            compositionEllipseGeometry.SetDescription(context, () => $"{shapeContent.Name}.EllipseGeometry");

            compositionSpriteShape.Geometry = compositionEllipseGeometry;

            var position = Optimizer.TrimAnimatable(context, shapeContent.Position);

            if (position.IsAnimated)
            {
                Animate.Vector2(context, position, compositionEllipseGeometry, "Center");
            }
            else
            {
                compositionEllipseGeometry.Center = ConvertTo.Vector2(position.InitialValue);
            }

            // Ensure that the diameter is expressed in a form that has only one easing per channel.
            var diameter = AnimatableVector3Rewriter.EnsureOneEasingPerChannel(shapeContent.Diameter);

            if (diameter is AnimatableXYZ diameterXYZ)
            {
                var diameterX = Optimizer.TrimAnimatable(context, diameterXYZ.X);
                var diameterY = Optimizer.TrimAnimatable(context, diameterXYZ.Y);
                if (diameterX.IsAnimated)
                {
                    Animate.ScaledScalar(context, diameterX, 0.5, compositionEllipseGeometry, $"{nameof(CompositionEllipseGeometry.Radius)}.X");
                }

                if (diameterY.IsAnimated)
                {
                    Animate.ScaledScalar(context, diameterY, 0.5, compositionEllipseGeometry, $"{nameof(CompositionEllipseGeometry.Radius)}.Y");
                }

                if (!diameterX.IsAnimated || !diameterY.IsAnimated)
                {
                    compositionEllipseGeometry.Radius = ConvertTo.Vector2(diameter.InitialValue) * 0.5F;
                }
            }
            else
            {
                var diameter3 = Optimizer.TrimAnimatable <Vector3>(context, (AnimatableVector3)diameter);
                if (diameter3.IsAnimated)
                {
                    Animate.ScaledVector2(context, diameter3, 0.5, compositionEllipseGeometry, nameof(CompositionEllipseGeometry.Radius));
                }
                else
                {
                    compositionEllipseGeometry.Radius = ConvertTo.Vector2(diameter.InitialValue) * 0.5F;
                }
            }

            Shapes.TranslateAndApplyShapeContext(
                context,
                compositionSpriteShape,
                reverseDirection: shapeContent.DrawingDirection == DrawingDirection.Reverse);

            return(compositionSpriteShape);
        }
コード例 #4
0
ファイル: Effects.cs プロジェクト: admariner/Lottie-Windows
        public static Visual ApplyGaussianBlur(
            LayerContext context,
            Visual source,
            GaussianBlurEffect gaussianBlurEffect)
        {
            Debug.Assert(gaussianBlurEffect.IsEnabled, "Precondition");
            Debug.Assert(context is PreCompLayerContext || context is ShapeLayerContext, "Precondition");

            var factory = context.ObjectFactory;

            if (!factory.IsUapApiAvailable(nameof(CompositionVisualSurface), versionDependentFeatureDescription: "Gaussian blur"))
            {
                // The effect can't be displayed on the targeted version.
                return(source);
            }

            // Gaussian blur:
            // +--------------+
            // | SpriteVisual | -- Has the final composited result.
            // +--------------+
            //     ^
            //     |
            // +--------------+
            // | EffectBrush  | -- Composition effect brush allows the composite effect result to be used as a brush.
            // +--------------+
            //     ^
            //     |
            // +--------------------+
            // | GaussianBlurEffect |
            // +--------------------+
            //     ^ Source
            //     |
            // +--------------+
            // | SurfaceBrush | -- Surface brush that will paint with the output of the VisualSurface
            // +--------------+    that has the source visual assigned to it.
            //      ^ CompositionEffectSourceParameter("source")
            //      |
            // +---------------+
            // | VisualSurface | -- The visual surface captures the renderable contents of its source visual.
            // +---------------+
            //      ^
            //      |
            //  +--------+
            //  | Visual | -- The layer translated to a Visual.
            //  +--------+
            var size = context.CompositionContext.Size;

            if (context is PreCompLayerContext)
            {
                size = ConvertTo.Vector2(((PreCompLayerContext)context).Layer.Width, ((PreCompLayerContext)context).Layer.Height);
            }

            // Build from the bottom up.
            var visualSurface = factory.CreateVisualSurface();

            visualSurface.SourceVisual = source;
            visualSurface.SourceSize   = size;

            var surfaceBrush = factory.CreateSurfaceBrush(visualSurface);

            var effect = new WinCompData.Mgce.GaussianBlurEffect();

            var blurriness = Optimizer.TrimAnimatable(context, gaussianBlurEffect.Blurriness);

            if (blurriness.IsAnimated)
            {
                context.Issues.AnimatedLayerEffectParameters("Gaussian blur");
            }

            effect.BlurAmount = ConvertTo.Float(blurriness.InitialValue / 10.0);

            // We only support HorizontalAndVertical blur dimension.
            var blurDimensions            = Optimizer.TrimAnimatable(context, gaussianBlurEffect.BlurDimensions);
            var unsupportedBlurDimensions = blurDimensions
                                            .KeyFrames
                                            .Select(kf => kf.Value)
                                            .Distinct()
                                            .Where(v => v.Value != BlurDimension.HorizontalAndVertical).ToArray();

            foreach (var value in unsupportedBlurDimensions)
            {
                context.Issues.UnsupportedLayerEffectParameter("gaussian blur", "blur dimension", value.Value.ToString());
            }

            effect.Source = new CompositionEffectSourceParameter("source");

            var effectBrush = factory.CreateEffectFactory(effect).CreateBrush();

            effectBrush.SetSourceParameter("source", surfaceBrush);

            var result = factory.CreateSpriteVisual();

            result.Brush = effectBrush;
            result.Size  = size;

            return(result);
        }
コード例 #5
0
ファイル: Effects.cs プロジェクト: admariner/Lottie-Windows
        public static Visual ApplyDropShadow(
            LayerContext context,
            Visual source,
            DropShadowEffect dropShadowEffect)
        {
            if (!context.ObjectFactory.IsUapApiAvailable(nameof(CompositionVisualSurface), versionDependentFeatureDescription: "Drop Shadow"))
            {
                // The effect can't be displayed on the targeted version.
                return(source);
            }

            Debug.Assert(dropShadowEffect.IsEnabled, "Precondition");
            Debug.Assert(context is PreCompLayerContext || context is ShapeLayerContext, "Precondition");

            // Shadow:
            // +------------------+
            // | Container Visual | -- Has the final composited result.
            // +------------------+ <
            //     ^ Child #1        \ Child #2 (original layer)
            //     | (shadow layer)   \
            //     |                   \
            // +---------------------+  \
            // | ApplyGaussianBlur() |   \
            // +---------------------+   +-----------------+
            //     ^                     | ContainerVisual | - Original Visual node.
            //     |                     +-----------------+
            // +----------------+           .
            // | SpriteVisual   |           .
            // +----------------+           .
            //     ^ Source                 .
            //     |                        .
            // +--------------+             .
            // | MaskBrush    |             .
            // +--------------+             .
            //     ^ Source   ^ Mask        . Source
            //     |           \            V
            // +----------+   +---------------+
            // |ColorBrush|   | VisualSurface |
            // +----------+   +---------------+
            GaussianBlurEffect gaussianBlurEffect = new GaussianBlurEffect(
                name: dropShadowEffect.Name + "_blur",
                isEnabled: true,
                blurriness: dropShadowEffect.Softness,
                blurDimensions: new Animatable <Enum <BlurDimension> >(BlurDimension.HorizontalAndVertical),
                repeatEdgePixels: new Animatable <bool>(true),
                forceGpuRendering: true);

            var factory = context.ObjectFactory;
            var size    = context.CompositionContext.Size;

            if (context is PreCompLayerContext)
            {
                size = ConvertTo.Vector2(((PreCompLayerContext)context).Layer.Width, ((PreCompLayerContext)context).Layer.Height);
            }

            var visualSurface = factory.CreateVisualSurface();

            visualSurface.SourceSize   = size;
            visualSurface.SourceVisual = source;

            var maskBrush = factory.CreateMaskBrush();

            var colorBrush = factory.CreateColorBrush(dropShadowEffect.Color.InitialValue);

            var color = Optimizer.TrimAnimatable(context, dropShadowEffect.Color);

            if (color.IsAnimated)
            {
                Animate.Color(context, color, colorBrush, nameof(colorBrush.Color));
            }
            else
            {
                colorBrush.Color = ConvertTo.Color(color.InitialValue);
            }

            maskBrush.Source = colorBrush;
            maskBrush.Mask   = factory.CreateSurfaceBrush(visualSurface);

            var shadowSpriteVisual = factory.CreateSpriteVisual();

            shadowSpriteVisual.Size  = size;
            shadowSpriteVisual.Brush = maskBrush;

            var blurResult = ApplyGaussianBlur(context, shadowSpriteVisual, gaussianBlurEffect);

            var opacity = Optimizer.TrimAnimatable(context, dropShadowEffect.Opacity);

            if (opacity.IsAnimated)
            {
                Animate.Opacity(context, opacity, blurResult, nameof(blurResult.Opacity));
            }
            else
            {
                blurResult.Opacity = (float)opacity.InitialValue.Value;
            }

            // Convert direction and distance to a Vector3.
            var direction = Optimizer.TrimAnimatable(context, dropShadowEffect.Direction);
            var distance  = Optimizer.TrimAnimatable(context, dropShadowEffect.Distance);

            if (direction.IsAnimated)
            {
                if (distance.IsAnimated)
                {
                    // Direction and distance are animated.
                    // NOTE: we could support this in some cases. The worst cases are
                    //       where the keyframes don't line up, and/or the easings are different
                    //       between distance and direction.
                    context.Issues.AnimatedLayerEffectParameters("drop shadow");
                }
                else
                {
                    // Only direction is animated.
                    var distanceValue = distance.InitialValue;
                    var keyFrames     = direction.KeyFrames.Select(
                        kf => new KeyFrame <Vector3>(kf.Frame, VectorFromRotationAndDistance(kf.Value, distanceValue), kf.Easing)).ToArray();
                    var directionAnimation = new TrimmedAnimatable <Vector3>(context, keyFrames[0].Value, keyFrames);
                    Animate.Vector3(context, directionAnimation, blurResult, nameof(blurResult.Offset));
                }
            }
            else if (distance.IsAnimated)
            {
                // Only distance is animated.
                var directionRadians = direction.InitialValue.Radians;
                var keyFrames        = distance.KeyFrames.Select(
                    kf => new KeyFrame <Vector3>(kf.Frame, VectorFromRotationAndDistance(directionRadians, kf.Value), kf.Easing)).ToArray();
                var distanceAnimation = new TrimmedAnimatable <Vector3>(context, keyFrames[0].Value, keyFrames);
                Animate.Vector3(context, distanceAnimation, blurResult, nameof(blurResult.Offset));
            }
            else
            {
                // Direction and distance are both not animated.
                var directionRadians = direction.InitialValue.Radians;
                var distanceValue    = distance.InitialValue;

                blurResult.Offset = ConvertTo.Vector3(VectorFromRotationAndDistance(direction.InitialValue, distance.InitialValue));
            }

            var result = factory.CreateContainerVisual();

            result.Size = size;
            result.Children.Add(blurResult);

            // Check if ShadowOnly can be false
            if (!dropShadowEffect.IsShadowOnly.IsAlways(true))
            {
                // Check if ShadowOnly can be true
                if (!dropShadowEffect.IsShadowOnly.IsAlways(false))
                {
                    var isVisible = FlipBoolAnimatable(dropShadowEffect.IsShadowOnly); // isVisible = !isShadowOnly

                    source.IsVisible = isVisible.InitialValue;
                    if (isVisible.IsAnimated)
                    {
                        Animate.Boolean(
                            context,
                            Optimizer.TrimAnimatable(context, isVisible),
                            source,
                            nameof(blurResult.IsVisible));
                    }
                }

                result.Children.Add(source);
            }

            return(result);
        }