Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Usage of Setter #1152

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/Beutl.Engine/Graphics/FilterEffects/FilterEffect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,30 @@ public virtual Rect TransformBounds(Rect bounds)
{
return bounds;
}

public FilterEffect CreateDelegatedInstance()
{
return new Delegated(this);
}

private sealed class Delegated : FilterEffect
{
private readonly FilterEffect _filterEffect;

public Delegated(FilterEffect filterEffect)
{
_filterEffect = filterEffect;
_filterEffect.Invalidated += (s, e) => RaiseInvalidated(e);
}

public override void ApplyTo(FilterEffectContext context)
{
_filterEffect.ApplyTo(context);
}

public override Rect TransformBounds(Rect bounds)
{
return _filterEffect.TransformBounds(bounds);
}
}
}
101 changes: 26 additions & 75 deletions src/Beutl.ProjectSystem/Operation/DecorateOperator.cs
Original file line number Diff line number Diff line change
@@ -1,100 +1,51 @@
using Beutl.Animation;
using System.Runtime.CompilerServices;
using Beutl.Graphics;
using Beutl.Graphics.Effects;
using Beutl.Graphics.Transformation;
using Beutl.Styling;

namespace Beutl.Operation;

public sealed class DecorateOperator : StylingOperator
public sealed class DecorateOperator() : PublishOperator<DrawableDecorator>([
(Drawable.TransformProperty, () => new TransformGroup()),
(Drawable.TransformOriginProperty, RelativePoint.Center),
(Drawable.FilterEffectProperty, () => new FilterEffectGroup()),
(Drawable.BlendModeProperty, BlendMode.SrcOver)
])
{
private readonly List<IStyleInstance> _instances = [];

public Setter<ITransform?> Transform { get; set; } =
new(Drawable.TransformProperty, new TransformGroup());

public Setter<RelativePoint> TransformOrigin { get; set; } =
new(Drawable.TransformOriginProperty, RelativePoint.Center);

public Setter<FilterEffect?> FilterEffect { get; set; } =
new(Drawable.FilterEffectProperty, new FilterEffectGroup());

public Setter<BlendMode> BlendMode { get; set; } =
new(Drawable.BlendModeProperty, Graphics.BlendMode.SrcOver);
private readonly ConditionalWeakTable<Drawable, DrawableDecorator> _bag = [];

public override void Evaluate(OperatorEvaluationContext context)
{
if (IsEnabled)
if (!IsEnabled) return;

Value.ApplyAnimations(context.Clock);
for (int i = 0; i < context.FlowRenderables.Count; i++)
{
int j = 0;
for (int i = 0; i < context.FlowRenderables.Count; i++)
if (context.FlowRenderables[i] is not Drawable drawable) continue;
var decorator = _bag.GetValue(drawable, d => new DrawableDecorator { Child = d });
decorator.Child = drawable;
context.FlowRenderables[i] = decorator;

decorator.Transform = (Value.Transform as IMutableTransform)?.ToImmutable() ?? Value.Transform;
decorator.TransformOrigin = Value.TransformOrigin;
decorator.BlendMode = Value.BlendMode;
if (Value.FilterEffect is null)
{
if (context.FlowRenderables[i] is not Drawable drawable) continue;
IStyleInstance instance = GetInstance(j, drawable);

if (instance is { Target: DrawableDecorator decorator })
{
while (drawable.BatchUpdate)
{
drawable.EndBatchUpdate();
}

ApplyStyle(instance, context.Clock);
context.FlowRenderables[i] = decorator;
j++;
}
else
{
context.FlowRenderables.RemoveAt(i);
i--;
}
decorator.FilterEffect = null;
}
}
}

private void ApplyStyle(IStyleInstance instance, IClock clock)
{
instance.Begin();
instance.Apply(clock);
instance.End();
}

private IStyleInstance GetInstance(int index, Drawable value)
{
IStyleInstance? instance;
if (index < _instances.Count)
{
instance = _instances[index];
if (instance.Target is DrawableDecorator dec)
else
{
dec.Child = value;
decorator.FilterEffect ??= Value.FilterEffect.CreateDelegatedInstance();
}
}
else
{
instance = Style.Instance(new DrawableDecorator { Child = value });
_instances.Add(instance);
}

return instance;
}

protected override Style OnInitializeStyle(Func<IList<ISetter>> setters)
{
var style = new Style<DrawableDecorator>();
style.Setters.AddRange(setters());
return style;
}

public override void Exit()
{
base.Exit();
foreach (IStyleInstance instance in _instances)
foreach (var entry in _bag)
{
if (instance.Target is DrawableDecorator dec)
{
dec.Child = null;
}
entry.Value.Child = null;
}
}
}
Loading