/// <summary> /// Translates each of the layers in the given <see cref="CompositionContext"/> /// to a <see cref="Visual"/>. /// </summary> /// <returns>The translated layers.</returns> public static Visual[] TranslateLayersToVisuals(CompositionContext context) { var layerTranslators = (from layer in context.Layers.GetLayersBottomToTop() let layerTranslator = CreateTranslatorForLayer(context, layer) where layerTranslator != null select(layerTranslator: layerTranslator, layer: layer)).ToArray(); // Set descriptions on each translate layer so that it's clear where the layer starts. if (context.Translation.AddDescriptions) { foreach (var(layerTranslator, layer) in layerTranslators) { // Add a description if not added already. if (layerTranslator.ShortDescription is null) { layerTranslator.SetDescription(context, $"{layer.Type} layer: {layer.Name}"); } } } // Go through the layers and compose matte layer and layer to be matted into // the resulting visuals. Any layer that is not a matte or matted layer is // simply returned unmodified. var compositionGraphs = Masks.ComposeMattedLayers(context, layerTranslators).ToArray(); // Layers are translated into either a visual tree or a shape tree. Convert the list of Visual and // Shape roots to a list of Visual roots by wrapping the shape trees in ShapeVisuals. return(VisualsAndShapesToVisuals(context, compositionGraphs).ToArray()); }
public static LayerTranslator CreatePreCompLayerTranslator(PreCompLayerContext context) { // TODO - the animations produced inside a PreComp need to be time-mapped. // Create the transform chain. if (!Transforms.TryCreateContainerVisualTransformChain(context, out var rootNode, out var contentsNode)) { // The layer is never visible. return(null); } var result = context.ObjectFactory.CreateContainerVisual(); #if !NoClipping // PreComps must clip to their size. // Create another ContainerVisual to apply clipping to. var clippingNode = context.ObjectFactory.CreateContainerVisual(); contentsNode.Children.Add(clippingNode); contentsNode = clippingNode; contentsNode.Clip = context.ObjectFactory.CreateInsetClip(); contentsNode.Size = context.ChildrenCompositionContext.Size; #endif // Add the translations of each layer to the clipping node. This will recursively // add the tranlation of the layers in nested precomps. var contentsChildren = contentsNode.Children; foreach (var visual in Layers.TranslateLayersToVisuals(context.ChildrenCompositionContext)) { contentsChildren.Add(visual); } // Add mask if the layer has masks. // This must be done after all children are added to the content node. bool layerHasMasks = false; #if !NoClipping layerHasMasks = context.Layer.Masks.Any(); #endif if (layerHasMasks) { var compositedVisual = Masks.TranslateAndApplyMasksForLayer(context, rootNode); result.Children.Add(compositedVisual); } else { result.Children.Add(rootNode); } return(new LayerTranslator.FromVisual(result)); }
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); }