diff --git a/flare_dart/lib/actor_artboard.dart b/flare_dart/lib/actor_artboard.dart index 0ccf2d6..99f64e9 100644 --- a/flare_dart/lib/actor_artboard.dart +++ b/flare_dart/lib/actor_artboard.dart @@ -286,10 +286,10 @@ class ActorArtboard { // layers won't be known before this. for (int i = 1; i < componentCount; i++) { ActorComponent c = components[i]; - if (c is ActorDrawable && c.layerEffectRenderer == null) { + if (c is ActorDrawable && c.layerEffectRenderParent == null) { _drawableNodes.add(c); } - if (c is ActorLayerEffectRenderer && c.layerEffectRenderer == null) { + if (c is ActorLayerEffectRenderer && c.layerEffectRenderParent == null) { _effectRenderers.add(c); } } diff --git a/flare_dart/lib/actor_drawable.dart b/flare_dart/lib/actor_drawable.dart index 719f391..72807c1 100644 --- a/flare_dart/lib/actor_drawable.dart +++ b/flare_dart/lib/actor_drawable.dart @@ -85,15 +85,7 @@ abstract class ActorDrawable extends ActorNode { } } } - - ActorLayerEffectRenderer _layerEffectRenderer; - ActorLayerEffectRenderer get layerEffectRenderer => _layerEffectRenderer; - set layerEffectRenderer(ActorLayerEffectRenderer value) { - if (_layerEffectRenderer == value) { - return; - } - _layerEffectRenderer?.removeDrawable(this); - _layerEffectRenderer = value; - _layerEffectRenderer?.addDrawable(this); - } + /// If this is set the drawable belongs to a layer. We store a reference to + /// the parent node that contains the layer. + ActorNode layerEffectRenderParent; } diff --git a/flare_dart/lib/actor_layer_effect_renderer.dart b/flare_dart/lib/actor_layer_effect_renderer.dart index e7e0bf3..f5fb563 100644 --- a/flare_dart/lib/actor_layer_effect_renderer.dart +++ b/flare_dart/lib/actor_layer_effect_renderer.dart @@ -4,6 +4,7 @@ import 'package:flare_dart/math/aabb.dart'; import 'actor_artboard.dart'; import 'actor_blur.dart'; +import 'actor_component.dart'; import 'actor_drawable.dart'; import 'actor_inner_shadow.dart'; import 'actor_mask.dart'; @@ -27,16 +28,6 @@ class ActorLayerEffectRenderer extends ActorDrawable { List get dropShadows => _dropShadows; List get innerShadows => _innerShadows; - bool addDrawable(ActorDrawable drawable) { - if (_drawables.contains(drawable)) { - return false; - } - _drawables.add(drawable); - return true; - } - - bool removeDrawable(ActorDrawable drawable) => _drawables.remove(drawable); - void sortDrawables() { _drawables .sort((ActorDrawable a, ActorDrawable b) => a.drawOrder - b.drawOrder); @@ -80,20 +71,37 @@ class ActorLayerEffectRenderer extends ActorDrawable { parent.children.whereType().toList(growable: false); } + @override + void resolveComponentIndices(List components) { + super.resolveComponentIndices(components); + parent.findLayerEffect(); + } + @override void completeResolve() { super.completeResolve(); - // When we complete resolve we find all the children and mark their layers. - // Alternative way to do this is to have each drawable check for parent - // layers when the parent changes. That would be more effective if nodes - // were to get moved around at runtime. + _drawables.clear(); + parent?.all((node) { - if (node is ActorDrawable && node != this) { - node.layerEffectRenderer = this; + if (node == this) { + // don't recurse into this renderer + return false; + } else if (node is ActorNode && + node.layerEffect != null && + node.layerEffect != this) { + _drawables.add(node.layerEffect); + // don't recurse further into nodes that are drawing to layers + return false; + } + if (node is ActorDrawable) { + _drawables.add(node); } return true; }); + + _drawables.forEach(_computeLayerNode); + sortDrawables(); computeMasks(); findEffects(); @@ -101,31 +109,28 @@ class ActorLayerEffectRenderer extends ActorDrawable { void computeMasks() { _renderMasks.clear(); - var maskSearch = parent; - var masks = []; - - while (maskSearch != null) { - masks += - maskSearch.children.whereType().toList(growable: false); - maskSearch = maskSearch.parent; - } + var masks = parent.children.whereType().toList(growable: false); for (final mask in masks) { var renderMask = ActorLayerEffectRendererMask(mask); mask.source?.all((child) { + if (child == parent) { + // recursive mask was selected + return false; + } if (child is ActorDrawable) { - if (child.layerEffectRenderer != null && - child.layerEffectRenderer != this) { + if (child == this) { + return false; + } else if (child.layerEffect != null) { // Layer effect is direct discendant of this layer, so we want to // draw it with the other drawables in this layer. - renderMask.drawables.add(child.layerEffectRenderer); + renderMask.drawables.add(child.layerEffect); // Don't iterate if child has further layer effect return false; } else { renderMask.drawables.add(child); } } - return true; }); @@ -135,3 +140,15 @@ class ActorLayerEffectRenderer extends ActorDrawable { } } } + +void _computeLayerNode(ActorDrawable drawable) { + ActorNode parent = drawable; + while (parent != null) { + if (parent.layerEffect != null) { + drawable.layerEffectRenderParent = parent; + return; + } + parent = parent.parent; + } + drawable.layerEffectRenderParent = null; +} diff --git a/flare_dart/lib/actor_node.dart b/flare_dart/lib/actor_node.dart index 5153f67..abc6a02 100644 --- a/flare_dart/lib/actor_node.dart +++ b/flare_dart/lib/actor_node.dart @@ -33,6 +33,7 @@ class ActorNode extends ActorComponent { double _opacity = 1.0; double _renderOpacity = 1.0; ActorLayerEffectRenderer _layerEffect; + ActorLayerEffectRenderer get layerEffect => _layerEffect; bool _overrideWorldTransform = false; bool _isCollapsedVisibility = false;