diff --git a/src/Beutl.Engine/Styling/StyleSerializer.cs b/src/Beutl.Engine/Styling/StyleSerializer.cs index 31d4eed55..5849677c5 100644 --- a/src/Beutl.Engine/Styling/StyleSerializer.cs +++ b/src/Beutl.Engine/Styling/StyleSerializer.cs @@ -10,6 +10,20 @@ namespace Beutl.Styling; public static class StyleSerializer { public static ISetter? ToSetter(this JsonNode? json, string name, Type targetType, ICoreSerializationContext context) + { + var (property, value, animation) = ToTuple(json, name, targetType, context); + if (property is null) + return null; + + var helper = (IGenericHelper)typeof(GenericHelper<>) + .MakeGenericType(property.PropertyType)! + .GetField("Instance")! + .GetValue(null)!; + + return helper.InitializeSetter(property, value, animation); + } + + public static (CoreProperty? property, Optional value, IAnimation? animation) ToTuple(JsonNode? json, string name, Type targetType, ICoreSerializationContext context) { JsonNode? animationNode = null; JsonNode? valueNode = null; @@ -26,13 +40,13 @@ public static class StyleSerializer && ownerNode is JsonValue ownerValue && ownerValue.TryGetValue(out string? ownerStr)) { - if (TypeFormat.ToType(ownerStr) is Type ownerType1) + if (TypeFormat.ToType(ownerStr) is { } ownerType1) { ownerType = ownerType1; } else { - return null; + return default; } } @@ -46,12 +60,7 @@ public static class StyleSerializer CoreProperty? property = PropertyRegistry.GetRegistered(ownerType).FirstOrDefault(x => x.Name == name); if (property == null) - return null; - - var helper = (IGenericHelper)typeof(GenericHelper<>) - .MakeGenericType(property.PropertyType) - .GetField("Instance")! - .GetValue(null)!; + return default; Optional value = null; if (valueNode != null) @@ -69,18 +78,29 @@ public static class StyleSerializer } } - return helper.InitializeSetter(property, value, animationNode?.ToAnimation(property, context)); + return (property, value, animationNode?.ToAnimation(property, context)); } public static (string, JsonNode?) ToJson(this ISetter setter, Type targetType, ICoreSerializationContext context) + { + return ToJson( + setter.Property, + setter.Value, + setter.Animation, + targetType, + context + ); + } + + public static (string, JsonNode?) ToJson(CoreProperty property, object? value, IAnimation? animation, Type targetType, ICoreSerializationContext context) { string? owner = null; JsonNode? animationNode = null; - string? name = setter.Property.Name; + string? name = property.Name; - if (!targetType.IsAssignableTo(setter.Property.OwnerType)) + if (!targetType.IsAssignableTo(property.OwnerType)) { - owner = TypeFormat.ToString(setter.Property.OwnerType); + owner = TypeFormat.ToString(property.OwnerType); } // Todo: 互換性維持のために汚くなってる @@ -89,28 +109,28 @@ public static (string, JsonNode?) ToJson(this ISetter setter, Type targetType, I var innerContext = new JsonSerializationContext(targetType, errorNotifier, context, simJson); using (ThreadLocalSerializationContext.Enter(innerContext)) { - setter.Property.RouteSerialize(innerContext, setter.Value); + property.RouteSerialize(innerContext, value); } - JsonNode? value = simJson[name]; + JsonNode? jsonNode = simJson[name]; simJson[name] = null; - if (setter.Animation is { } animation) + if (animation is not null) { - if (animation.Property != setter.Property) + if (animation.Property.Id != property.Id) { - throw new InvalidOperationException("Setter.Animation.Property != Setter.Property"); + throw new InvalidOperationException("Animation.Property != Property"); } animationNode = animation.ToJson(innerContext); } - if (value is JsonValue jsonValue + if (jsonNode is JsonValue jsonValue && owner == null && animationNode == null) { return (name, jsonValue); } - else if (value == null && owner == null && animationNode == null) + else if (jsonNode == null && owner == null && animationNode == null) { return (name, null); } @@ -118,7 +138,7 @@ public static (string, JsonNode?) ToJson(this ISetter setter, Type targetType, I { var json = new JsonObject { - ["Value"] = value + ["Value"] = jsonNode }; if (owner != null) diff --git a/src/Beutl.ProjectSystem/NodeTree/DefaultInputSocket.cs b/src/Beutl.ProjectSystem/NodeTree/DefaultInputSocket.cs new file mode 100644 index 000000000..e5a973e3b --- /dev/null +++ b/src/Beutl.ProjectSystem/NodeTree/DefaultInputSocket.cs @@ -0,0 +1,42 @@ +using Beutl.Media; +using Beutl.Serialization; + +namespace Beutl.NodeTree; + +public sealed class DefaultInputSocket : InputSocket, IDefaultInputSocket +{ + public void SetPropertyAdapter(NodePropertyAdapter property) + { + Property = property; + property.Invalidated += OnAdapterInvalidated; + } + + void IDefaultInputSocket.SetPropertyAdapter(object property) + { + var obj = (NodePropertyAdapter)property; + Property = obj; + obj.Invalidated += OnAdapterInvalidated; + } + + private void OnAdapterInvalidated(object? sender, EventArgs e) + { + RaiseInvalidated(new RenderInvalidatedEventArgs(this)); + } + + public NodePropertyAdapter? GetProperty() + { + return Property as NodePropertyAdapter; + } + + public override void Serialize(ICoreSerializationContext context) + { + base.Serialize(context); + GetProperty()?.Serialize(context); + } + + public override void Deserialize(ICoreSerializationContext context) + { + base.Deserialize(context); + GetProperty()?.Deserialize(context); + } +} diff --git a/src/Beutl.ProjectSystem/NodeTree/NodeItemForSetter.cs b/src/Beutl.ProjectSystem/NodeTree/DefaultNodeItem.cs similarity index 57% rename from src/Beutl.ProjectSystem/NodeTree/NodeItemForSetter.cs rename to src/Beutl.ProjectSystem/NodeTree/DefaultNodeItem.cs index 544581e30..56b86a5d3 100644 --- a/src/Beutl.ProjectSystem/NodeTree/NodeItemForSetter.cs +++ b/src/Beutl.ProjectSystem/NodeTree/DefaultNodeItem.cs @@ -1,26 +1,24 @@ -using System.Text.Json.Nodes; - -using Beutl.Media; +using Beutl.Media; using Beutl.Serialization; namespace Beutl.NodeTree; -public sealed class NodeItemForSetter : NodeItem +public sealed class DefaultNodeItem : NodeItem { - public void SetProperty(SetterAdapter property) + public void SetProperty(NodePropertyAdapter property) { Property = property; - property.Setter.Invalidated += OnSetterInvalidated; + property.Invalidated += OnAdapterInvalidated; } - private void OnSetterInvalidated(object? sender, EventArgs e) + private void OnAdapterInvalidated(object? sender, EventArgs e) { RaiseInvalidated(new RenderInvalidatedEventArgs(this)); } - public SetterAdapter? GetProperty() + public NodePropertyAdapter? GetProperty() { - return Property as SetterAdapter; + return Property as NodePropertyAdapter; } public override void Serialize(ICoreSerializationContext context) diff --git a/src/Beutl.ProjectSystem/NodeTree/IInputSocketForSetter.cs b/src/Beutl.ProjectSystem/NodeTree/IDefaultInputSocket.cs similarity index 67% rename from src/Beutl.ProjectSystem/NodeTree/IInputSocketForSetter.cs rename to src/Beutl.ProjectSystem/NodeTree/IDefaultInputSocket.cs index e75574dba..424adfb1b 100644 --- a/src/Beutl.ProjectSystem/NodeTree/IInputSocketForSetter.cs +++ b/src/Beutl.ProjectSystem/NodeTree/IDefaultInputSocket.cs @@ -1,6 +1,6 @@ namespace Beutl.NodeTree; -internal interface IInputSocketForSetter : IInputSocket +internal interface IDefaultInputSocket : IInputSocket { new int LocalId { get; set; } diff --git a/src/Beutl.ProjectSystem/NodeTree/InputSocketForSetter.cs b/src/Beutl.ProjectSystem/NodeTree/InputSocketForSetter.cs deleted file mode 100644 index 7ca5f4cf2..000000000 --- a/src/Beutl.ProjectSystem/NodeTree/InputSocketForSetter.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Text.Json.Nodes; - -using Beutl.Media; -using Beutl.Serialization; - -namespace Beutl.NodeTree; - -public sealed class InputSocketForSetter : InputSocket, IInputSocketForSetter -{ - public void SetPropertyAdapter(SetterAdapter property) - { - Property = property; - property.Setter.Invalidated += OnSetterInvalidated; - } - - void IInputSocketForSetter.SetPropertyAdapter(object property) - { - var obj = (SetterAdapter)property; - Property = obj; - obj.Setter.Invalidated += OnSetterInvalidated; - } - - private void OnSetterInvalidated(object? sender, EventArgs e) - { - RaiseInvalidated(new RenderInvalidatedEventArgs(this)); - } - - public SetterAdapter? GetProperty() - { - return Property as SetterAdapter; - } - - public override void Serialize(ICoreSerializationContext context) - { - base.Serialize(context); - GetProperty()?.Serialize(context); - } - - public override void Deserialize(ICoreSerializationContext context) - { - base.Deserialize(context); - GetProperty()?.Deserialize(context); - } -} diff --git a/src/Beutl.ProjectSystem/NodeTree/Node.cs b/src/Beutl.ProjectSystem/NodeTree/Node.cs index 1c52615a0..fa56e6d97 100644 --- a/src/Beutl.ProjectSystem/NodeTree/Node.cs +++ b/src/Beutl.ProjectSystem/NodeTree/Node.cs @@ -225,9 +225,8 @@ protected InputSocket CreateInput(CoreProperty property, int localId = if (ValidateLocalId(localId)) throw new InvalidOperationException("An item with the same local-id already exists."); - var setter = new Setter(property); - var adapter = new SetterAdapter(setter, property.OwnerType); - var socket = new InputSocketForSetter() { LocalId = localId }; + var adapter = new NodePropertyAdapter(property, property.OwnerType); + var socket = new DefaultInputSocket { LocalId = localId }; socket.SetPropertyAdapter(adapter); return socket; } @@ -240,9 +239,8 @@ protected IInputSocket CreateInput(CoreProperty property, int localId = -1) throw new InvalidOperationException("An item with the same local-id already exists."); Type propertyType = property.PropertyType; - object setter = Activator.CreateInstance(typeof(Setter<>).MakeGenericType(propertyType), property)!; - object adapter = Activator.CreateInstance(typeof(SetterAdapter<>).MakeGenericType(propertyType), setter, property.OwnerType)!; - var socket = (IInputSocketForSetter)Activator.CreateInstance(typeof(InputSocketForSetter<>).MakeGenericType(propertyType))!; + object adapter = Activator.CreateInstance(typeof(NodePropertyAdapter<>).MakeGenericType(propertyType), property, property.OwnerType)!; + var socket = (IDefaultInputSocket)Activator.CreateInstance(typeof(DefaultInputSocket<>).MakeGenericType(propertyType))!; socket.LocalId = localId; socket.SetPropertyAdapter(adapter); return socket; @@ -255,9 +253,8 @@ protected InputSocket CreateInput(CoreProperty property, int lo if (ValidateLocalId(localId)) throw new InvalidOperationException("An item with the same local-id already exists."); - var setter = new Setter(property); - var adapter = new SetterAdapter(setter, typeof(TOwner)); - var socket = new InputSocketForSetter() { LocalId = localId }; + var adapter = new NodePropertyAdapter(property, typeof(TOwner)); + var socket = new DefaultInputSocket { LocalId = localId }; socket.SetPropertyAdapter(adapter); return socket; } @@ -269,9 +266,9 @@ protected InputSocket CreateInput(CoreProperty property, T value, int l if (ValidateLocalId(localId)) throw new InvalidOperationException("An item with the same local-id already exists."); - var setter = new Setter(property, value); - var adapter = new SetterAdapter(setter, property.OwnerType); - var socket = new InputSocketForSetter() { LocalId = localId }; + var adapter = new NodePropertyAdapter(property, property.OwnerType); + adapter.SetValue(value); + var socket = new DefaultInputSocket { LocalId = localId }; socket.SetPropertyAdapter(adapter); return socket; } @@ -283,9 +280,9 @@ protected InputSocket CreateInput(CoreProperty property, T valu if (ValidateLocalId(localId)) throw new InvalidOperationException("An item with the same local-id already exists."); - var setter = new Setter(property, value); - var adapter = new SetterAdapter(setter, typeof(TOwner)); - var socket = new InputSocketForSetter() { LocalId = localId }; + var adapter = new NodePropertyAdapter(property, typeof(TOwner)); + adapter.SetValue(value); + var socket = new DefaultInputSocket { LocalId = localId }; socket.SetPropertyAdapter(adapter); return socket; } @@ -297,7 +294,7 @@ protected InputSocket CreateInput(string name, int localId = -1) if (ValidateLocalId(localId)) throw new InvalidOperationException("An item with the same local-id already exists."); - return new InputSocketForSetter() + return new DefaultInputSocket { Name = name, LocalId = localId @@ -311,7 +308,7 @@ protected IInputSocket CreateInput(string name, Type type, int localId = -1) if (ValidateLocalId(localId)) throw new InvalidOperationException("An item with the same local-id already exists."); - var socket = (IInputSocketForSetter)Activator.CreateInstance(typeof(InputSocketForSetter<>).MakeGenericType(type))!; + var socket = (IDefaultInputSocket)Activator.CreateInstance(typeof(DefaultInputSocket<>).MakeGenericType(type))!; socket.Name = name; socket.LocalId = localId; return socket; @@ -369,9 +366,8 @@ protected NodeItem CreateProperty(CoreProperty property, int localId = if (ValidateLocalId(localId)) throw new InvalidOperationException("An item with the same local-id already exists."); - var setter = new Setter(property); - var adapter = new SetterAdapter(setter, property.OwnerType); - var socket = new NodeItemForSetter(); + var adapter = new NodePropertyAdapter(property, property.OwnerType); + var socket = new DefaultNodeItem(); socket.SetProperty(adapter); socket.LocalId = localId; return socket; @@ -384,9 +380,9 @@ protected NodeItem CreateProperty(CoreProperty property, T value, int l if (ValidateLocalId(localId)) throw new InvalidOperationException("An item with the same local-id already exists."); - var setter = new Setter(property, value); - var adapter = new SetterAdapter(setter, property.OwnerType); - var socket = new NodeItemForSetter(); + var adapter = new NodePropertyAdapter(property, property.OwnerType); + adapter.SetValue(value); + var socket = new DefaultNodeItem(); socket.SetProperty(adapter); socket.LocalId = localId; return socket; diff --git a/src/Beutl.ProjectSystem/NodeTree/NodePropertyAdapter.cs b/src/Beutl.ProjectSystem/NodeTree/NodePropertyAdapter.cs new file mode 100644 index 000000000..011c9bc5e --- /dev/null +++ b/src/Beutl.ProjectSystem/NodeTree/NodePropertyAdapter.cs @@ -0,0 +1,200 @@ +using System.Text.Json.Nodes; +using Beutl.Animation; +using Beutl.Extensibility; +using Beutl.Media; +using Beutl.Reactive; +using Beutl.Serialization; +using Beutl.Styling; +using Beutl.Validation; +using Reactive.Bindings; + +namespace Beutl.NodeTree; + +public sealed class NodePropertyAdapter : IAnimatablePropertyAdapter +{ + private readonly CorePropertyMetadata _metadata; + private readonly ReactivePropertySlim _rxProperty = new(); + private IAnimation? _animation; + + public NodePropertyAdapter(T? value, CoreProperty property, IAnimation? animation, Type implementedType) + { + Property = property; + Animation = animation; + ImplementedType = implementedType; + ObserveAnimation = new AnimationObservable(this); + _metadata = property.GetMetadata>(implementedType); + _rxProperty.Value = value; + } + + public NodePropertyAdapter(CoreProperty property, Type implementedType) + { + Property = property; + ImplementedType = implementedType; + ObserveAnimation = new AnimationObservable(this); + _metadata = property.GetMetadata>(implementedType); + _rxProperty.Value = _metadata.HasDefaultValue ? _metadata.DefaultValue : default; + } + + private sealed class AnimationObservable(NodePropertyAdapter adapter) : LightweightObservableBase?> + { + private IAnimation? _prevAnimation = adapter.Animation; + + protected override void Subscribed(IObserver?> observer, bool first) + { + base.Subscribed(observer, first); + observer.OnNext(adapter.Animation); + } + + protected override void Deinitialize() + { + adapter.Invalidated -= Setter_Invalidated; + } + + protected override void Initialize() + { + adapter.Invalidated += Setter_Invalidated; + } + + private void Setter_Invalidated(object? sender, EventArgs e) + { + if (_prevAnimation != adapter.Animation) + { + PublishNext(adapter.Animation); + _prevAnimation = adapter.Animation; + } + } + } + + public CoreProperty Property { get; } + + public IAnimation? Animation + { + get => _animation; + set + { + if (_animation != value) + { + if (_animation != null) + { + _animation.Invalidated -= Animation_Invalidated; + } + + _animation = value; + + if (value != null) + { + value.Invalidated += Animation_Invalidated; + } + + Invalidated?.Invoke(this, EventArgs.Empty); + } + } + } + + public IObservable?> ObserveAnimation { get; } + + public Type ImplementedType { get; } + + public Type PropertyType => Property.PropertyType; + + public string DisplayName + { + get + { + CorePropertyMetadata metadata = Property.GetMetadata(ImplementedType); + return metadata.DisplayAttribute?.GetName() ?? Property.Name; + } + } + + public string? Description + { + get + { + CorePropertyMetadata metadata = Property.GetMetadata(ImplementedType); + return metadata.DisplayAttribute?.GetDescription(); + } + } + + public bool IsReadOnly => false; + + CoreProperty IPropertyAdapter.GetCoreProperty() => Property; + + public event EventHandler? Invalidated; + + private void Animation_Invalidated(object? sender, RenderInvalidatedEventArgs e) + { + Invalidated?.Invoke(this, EventArgs.Empty); + } + + private void Value_Invalidated(object? sender, RenderInvalidatedEventArgs e) + { + Invalidated?.Invoke(this, EventArgs.Empty); + } + + public IObservable GetObservable() + { + return _rxProperty; + } + + public T? GetValue() + { + return _rxProperty.Value; + } + + public void SetValue(T? value) + { + if (_metadata.Validator is { } validator) + { + validator.TryCoerce(new ValidationContext(null, Property), ref value); + } + + if (!EqualityComparer.Default.Equals(_rxProperty.Value, value)) + { + if (_rxProperty.Value is IAffectsRender oldValue) + { + oldValue.Invalidated -= Value_Invalidated; + } + + _rxProperty.Value = value; + + Invalidated?.Invoke(this, EventArgs.Empty); + if (value is IAffectsRender newValue) + { + newValue.Invalidated += Value_Invalidated; + } + } + } + + public object? GetDefaultValue() + { + return Property.GetMetadata(ImplementedType).GetDefaultValue(); + } + + public void Serialize(ICoreSerializationContext context) + { + context.SetValue(nameof(Property), Property.Name); + context.SetValue("Target", TypeFormat.ToString(ImplementedType)); + + context.SetValue("Setter", StyleSerializer.ToJson(Property, _rxProperty.Value, Animation, ImplementedType, context).Item2); + } + + public void Deserialize(ICoreSerializationContext context) + { + if (context.GetValue("Setter") is not { } setterNode) + return; + + (CoreProperty? prop, Optional value, IAnimation? animation) = + StyleSerializer.ToTuple(setterNode, Property.Name, ImplementedType, context); + if (prop is null) return; + + if (animation != null) + { + Animation = animation as IAnimation; + } + + if (value is { HasValue: true, Value: T typedValue }) + { + SetValue(typedValue); + } + } +} diff --git a/src/Beutl.ProjectSystem/NodeTree/Nodes/LayerInputNode.cs b/src/Beutl.ProjectSystem/NodeTree/Nodes/LayerInputNode.cs index 48782f717..52ada3e2f 100644 --- a/src/Beutl.ProjectSystem/NodeTree/Nodes/LayerInputNode.cs +++ b/src/Beutl.ProjectSystem/NodeTree/Nodes/LayerInputNode.cs @@ -25,7 +25,7 @@ public interface ILayerInputSocket : IOutputSocket, IAutomaticallyGeneratedSocke public class LayerInputSocket : OutputSocket, ILayerInputSocket, IGroupSocket { - private SetterAdapter? _property; + private NodePropertyAdapter? _property; static LayerInputSocket() { @@ -33,17 +33,17 @@ static LayerInputSocket() public CoreProperty? AssociatedProperty { get; set; } - public void SetProperty(SetterAdapter property) + public void SetProperty(NodePropertyAdapter property) { _property = property; AssociatedProperty = property.Property; - property.Setter.Invalidated += OnSetterInvalidated; + property.Invalidated += OnSetterInvalidated; } void ILayerInputSocket.SetProperty(IPropertyAdapter property) { - SetProperty((SetterAdapter)property); + SetProperty((NodePropertyAdapter)property); } IPropertyAdapter? ILayerInputSocket.GetProperty() @@ -53,8 +53,7 @@ void ILayerInputSocket.SetProperty(IPropertyAdapter property) public void SetupProperty(CoreProperty property) { - var setter = new Setter((CoreProperty)property); - SetProperty(new SetterAdapter(setter, property.OwnerType)); + SetProperty(new NodePropertyAdapter((CoreProperty)property, property.OwnerType)); } private void OnSetterInvalidated(object? sender, EventArgs e) @@ -62,7 +61,7 @@ private void OnSetterInvalidated(object? sender, EventArgs e) RaiseInvalidated(new RenderInvalidatedEventArgs(this)); } - public SetterAdapter? GetProperty() + public NodePropertyAdapter? GetProperty() { return _property; } @@ -71,7 +70,7 @@ public override void PreEvaluate(EvaluationContext context) { if (GetProperty() is { } property) { - if (property is IAnimatablePropertyAdapter { Animation: IAnimation animation }) + if (property is IAnimatablePropertyAdapter { Animation: { } animation }) { Value = animation.GetAnimatedValue(context.Clock); } diff --git a/src/Beutl.ProjectSystem/NodeTree/SetterAdapter.cs b/src/Beutl.ProjectSystem/NodeTree/SetterAdapter.cs deleted file mode 100644 index 9f9e64d0a..000000000 --- a/src/Beutl.ProjectSystem/NodeTree/SetterAdapter.cs +++ /dev/null @@ -1,131 +0,0 @@ -using System.Text.Json.Nodes; - -using Beutl.Animation; -using Beutl.Extensibility; -using Beutl.Reactive; -using Beutl.Serialization; -using Beutl.Styling; - -namespace Beutl.NodeTree; - -public sealed class SetterAdapter(Setter setter, Type implementedType) : IAnimatablePropertyAdapter -{ - private sealed class AnimationObservable : LightweightObservableBase?> - { - private readonly Setter _setter; - private IAnimation? _prevAnimation; - - public AnimationObservable(Setter setter) - { - _setter = setter; - _prevAnimation = setter.Animation; - } - - protected override void Subscribed(IObserver?> observer, bool first) - { - base.Subscribed(observer, first); - observer.OnNext(_setter.Animation); - } - - protected override void Deinitialize() - { - _setter.Invalidated -= Setter_Invalidated; - } - - protected override void Initialize() - { - _setter.Invalidated += Setter_Invalidated; - } - - private void Setter_Invalidated(object? sender, EventArgs e) - { - if (_prevAnimation != _setter.Animation) - { - PublishNext(_setter.Animation); - _prevAnimation = _setter.Animation; - } - } - } - - public CoreProperty Property { get; } = setter.Property; - - public Setter Setter { get; } = setter; - - public IAnimation? Animation - { - get => Setter.Animation; - set => Setter.Animation = value; - } - - public IObservable?> ObserveAnimation { get; } = new AnimationObservable(setter); - - public Type ImplementedType { get; } = implementedType; - - public Type PropertyType => Property.PropertyType; - - public string DisplayName - { - get - { - CorePropertyMetadata metadata = Property.GetMetadata(ImplementedType); - return metadata.DisplayAttribute?.GetName() ?? Property.Name; - } - } - - public string? Description - { - get - { - CorePropertyMetadata metadata = Property.GetMetadata(ImplementedType); - return metadata.DisplayAttribute?.GetDescription(); - } - } - - public bool IsReadOnly => false; - - CoreProperty? IPropertyAdapter.GetCoreProperty() => Property; - - public IObservable GetObservable() - { - return Setter; - } - - public T? GetValue() - { - return Setter.Value; - } - - public void SetValue(T? value) - { - Setter.Value = value; - } - - public object? GetDefaultValue() - { - return Property.GetMetadata(ImplementedType).GetDefaultValue(); - } - - public void Serialize(ICoreSerializationContext context) - { - context.SetValue(nameof(Property), Property.Name); - context.SetValue("Target", TypeFormat.ToString(ImplementedType)); - - context.SetValue(nameof(Setter), StyleSerializer.ToJson(Setter, ImplementedType, context).Item2); - } - - public void Deserialize(ICoreSerializationContext context) - { - if (context.GetValue(nameof(Setter)) is { } setterNode) - { - if (StyleSerializer.ToSetter(setterNode, Property.Name, ImplementedType, context) is Setter setter) - { - if (setter.Animation != null) - { - Setter.Animation = setter.Animation; - } - - Setter.Value = setter.Value; - } - } - } -}