Skip to content

Commit

Permalink
Merge pull request #1152 from b-editor/feat/remove-setter-usage
Browse files Browse the repository at this point in the history
Remove Usage of Setter
  • Loading branch information
yuto-trd authored Nov 15, 2024
2 parents 1b08506 + b4dffee commit 4ba4f3c
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 137 deletions.
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;
}
}
}
80 changes: 20 additions & 60 deletions src/Beutl.ProjectSystem/Operation/GroupOperator.cs
Original file line number Diff line number Diff line change
@@ -1,76 +1,36 @@
using Beutl.Animation;
using Beutl.Graphics;
using Beutl.Graphics;
using Beutl.Graphics.Effects;
using Beutl.Graphics.Rendering;
using Beutl.Graphics.Transformation;
using Beutl.Styling;

namespace Beutl.Operation;

public sealed class GroupOperator : StyledSourcePublisher
public sealed class GroupOperator() : PublishOperator<DrawableGroup>([
(Drawable.TransformProperty, () => new TransformGroup()),
(Drawable.TransformOriginProperty, RelativePoint.Center),
(Drawable.FilterEffectProperty, () => new FilterEffectGroup()),
(Drawable.BlendModeProperty, BlendMode.SrcOver)
])
{
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 Setter<BlendMode>(Drawable.BlendModeProperty, Graphics.BlendMode.SrcOver);

private Renderable? PublishCore(IList<Renderable> value, IClock clock)
public override void Evaluate(OperatorEvaluationContext context)
{
DrawableGroup? renderable = Instance?.Target as DrawableGroup;
var value = Value;
if (!IsEnabled) return;

if (!ReferenceEquals(Style, Instance?.Source) || Instance?.Target == null)
{
renderable = Activator.CreateInstance(Style.TargetType) as DrawableGroup;
if (renderable is ICoreObject coreObj)
{
Instance?.Dispose();
Instance = Style.Instance(coreObj);
}
else
{
renderable = null;
}
}

OnBeforeApplying();
if (Instance != null && IsEnabled)
{
Instance.Begin();
Instance.Apply(clock);
Instance.End();

Drawable[] items = value.OfType<Drawable>().ToArray();
foreach (Drawable item in items)
{
while (item.BatchUpdate)
{
item.EndBatchUpdate();
}
}
renderable!.Children.Replace(items);
}

OnAfterApplying();

return IsEnabled ? renderable : null;
var items = context.FlowRenderables.OfType<Drawable>().ToArray();
context.FlowRenderables.Clear();
value.Children.Replace(items);
context.AddFlowRenderable(value);
}

public override void Evaluate(OperatorEvaluationContext context)
public override void Enter()
{
if (PublishCore(context.FlowRenderables, context.Clock) is Renderable renderable)
{
context.FlowRenderables.Clear();
context.AddFlowRenderable(renderable);
}
base.Enter();
Value.Children.Clear();
}

protected override Style OnInitializeStyle(Func<IList<ISetter>> setters)
public override void Exit()
{
var style = new Style<DrawableGroup>();
style.Setters.AddRange(setters());
return style;
base.Exit();
Value.Children.Clear();
}
}
36 changes: 36 additions & 0 deletions src/Beutl.ProjectSystem/Operation/PublishOperator.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Text.Json.Nodes;
using Beutl.Animation;
using Beutl.Extensibility;
using Beutl.Graphics;
using Beutl.Graphics.Rendering;
using Beutl.Media;
using Beutl.Serialization;
using Beutl.Styling;

namespace Beutl.Operation;

Expand Down Expand Up @@ -35,6 +39,10 @@ public abstract class PublishOperator<T> : SourceOperator
private readonly PropertyWithDefaultValue[] _properties;
private bool _deserializing;

private readonly EvaluationTarget _evaluationTarget =
typeof(T).IsAssignableTo(typeof(Drawable)) ? EvaluationTarget.Graphics
: typeof(T).IsAssignableTo(typeof(Audio.Audio)) ? EvaluationTarget.Audio : EvaluationTarget.Unknown;

static PublishOperator()
{
ValueProperty = ConfigureProperty<T, PublishOperator<T>>(nameof(Value))
Expand All @@ -56,6 +64,8 @@ public T Value
set => SetAndRaise(ValueProperty, ref _value, value);
}

public override EvaluationTarget GetEvaluationTarget() => _evaluationTarget;

public override void Evaluate(OperatorEvaluationContext context)
{
context.AddFlowRenderable(Value);
Expand All @@ -70,6 +80,32 @@ public override void Deserialize(ICoreSerializationContext context)
Debug.Assert(Value != null);
// ReSharper disable once NullCoalescingConditionIsAlwaysNotNullAccordingToAPIContract
Value ??= new T();
// 互換性処理
if (!context.Contains(nameof(Value)))
{
foreach (var prop in _properties)
{
string name = prop.Property.Name;
if (!context.Contains(name)) continue;

JsonNode? propNode = context.GetValue<JsonNode?>(name);
(CoreProperty? _, Optional<object?> value, IAnimation? animation) =
StyleSerializer.ToTuple(propNode, name, typeof(T), context);

if (value.HasValue)
{
Value.SetValue(prop.Property, value.Value);
}

if (animation == null) continue;

var oldAnm = Value.Animations.FirstOrDefault(i => i.Property.Id == prop.Property.Id);
if (oldAnm == null) continue;

Value.Animations.Remove(oldAnm);
Value.Animations.Add(animation);
}
}
}
finally
{
Expand Down
1 change: 1 addition & 0 deletions src/Beutl.ProjectSystem/Operation/StyledSourcePublisher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Beutl.Operation;

[Obsolete("Use PublishOperator instead.")]
public abstract class StyledSourcePublisher : StylingOperator
{
public IStyleInstance? Instance { get; protected set; }
Expand Down
9 changes: 7 additions & 2 deletions src/Beutl.ProjectSystem/Operation/StylingOperator.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using System.Collections;
#pragma warning disable CS0612

using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reactive.Linq;
using System.Reflection;
using System.Text.Json.Nodes;

Expand All @@ -20,13 +21,15 @@

namespace Beutl.Operation;

[Obsolete("Use CorePropertyAdapter instead.")]
public interface ISetterAdapter : IPropertyAdapter
{
ISetter Setter { get; }

IStyle Style { get; }
}

[Obsolete("Use CorePropertyAdapter instead.")]
public sealed class SetterAdapter<T>(Setter<T> setter, Style style) : IAnimatablePropertyAdapter<T>, ISetterAdapter
{
private sealed class AnimationObservable : LightweightObservableBase<IAnimation<T>?>
Expand Down Expand Up @@ -131,6 +134,7 @@ public void SetValue(T? value)
}
}

[Obsolete]
internal static class StylingOperatorPropertyDefinition
{
internal record struct Definition(PropertyInfo Property, Func<object, ISetter> Getter, Action<object, ISetter> Setter);
Expand Down Expand Up @@ -230,6 +234,7 @@ private static Definition[] CreateDefinitions(Type type)
}
}

[Obsolete("Use PublishOperator instead.")]
public abstract class StylingOperator : SourceOperator
{
private Style _style;
Expand Down

0 comments on commit 4ba4f3c

Please sign in to comment.