Skip to content

Commit

Permalink
Mark layers after drawables are computed.
Browse files Browse the repository at this point in the history
  • Loading branch information
luigi-rosso committed Dec 16, 2019
1 parent 0e815f5 commit e1c9972
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 41 deletions.
4 changes: 2 additions & 2 deletions flare_dart/lib/actor_artboard.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
14 changes: 3 additions & 11 deletions flare_dart/lib/actor_drawable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
73 changes: 45 additions & 28 deletions flare_dart/lib/actor_layer_effect_renderer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -27,16 +28,6 @@ class ActorLayerEffectRenderer extends ActorDrawable {
List<ActorDropShadow> get dropShadows => _dropShadows;
List<ActorInnerShadow> 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);
Expand Down Expand Up @@ -80,52 +71,66 @@ class ActorLayerEffectRenderer extends ActorDrawable {
parent.children.whereType<ActorInnerShadow>().toList(growable: false);
}

@override
void resolveComponentIndices(List<ActorComponent> 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();
}

void computeMasks() {
_renderMasks.clear();
var maskSearch = parent;
var masks = <ActorMask>[];

while (maskSearch != null) {
masks +=
maskSearch.children.whereType<ActorMask>().toList(growable: false);
maskSearch = maskSearch.parent;
}
var masks = parent.children.whereType<ActorMask>().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;
});

Expand All @@ -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;
}
1 change: 1 addition & 0 deletions flare_dart/lib/actor_node.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit e1c9972

Please sign in to comment.