From d1e026770913f5c1d7f09199b2686598b440f9d6 Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 8 Jan 2020 20:36:27 +0100 Subject: [PATCH] Started work on the keyframe engine to tie everything together! --- src/Artemis.Core/Artemis.Core.csproj | 5 ++ .../KeyframeEngines/FloatKeyframeEngine.cs | 18 +++++ .../KeyframeEngines/IntKeyframeEngine.cs | 18 +++++ .../Profile/KeyframeEngines/KeyframeEngine.cs | 65 ++++++++++++++++++ .../KeyframeEngines/SKPointKeyframeEngine.cs | 19 ++++++ .../KeyframeEngines/SKSizeKeyframeEngine.cs | 19 ++++++ src/Artemis.Core/Models/Profile/Layer.cs | 13 ++-- .../LayerProperties/BaseLayerProperty.cs | 27 ++++++-- .../Profile/LayerProperties/LayerProperty.cs | 20 +++++- .../Models/Profile/LayerShapes/Ellipse.cs | 4 +- .../Models/Profile/LayerShapes/Fill.cs | 4 +- .../Models/Profile/LayerShapes/LayerShape.cs | 67 ++++--------------- .../Models/Profile/LayerShapes/Polygon.cs | 2 +- .../Models/Profile/LayerShapes/Rectangle.cs | 4 +- .../Plugins/Models/PluginSetting.cs | 7 +- .../Entities/Profile/ShapeEntity.cs | 5 -- .../LayerProperties/LayerPropertiesView.xaml | 2 +- .../LayerPropertiesViewModel.cs | 2 +- .../LayerProperties/LayerPropertyViewModel.cs | 19 +++++- .../FloatPropertyInputViewModel.cs | 16 +++++ .../IntPropertyInputViewModel.cs | 16 +++++ .../PropertyInput/PropertyInputViewModel.cs | 33 +++++++++ .../SKPointPropertyInputViewModel.cs | 16 +++++ .../SKSizePropertyInputViewModel.cs | 16 +++++ .../PropertyTree/PropertyTreeChildView.xaml | 4 +- .../PropertyTreeChildViewModel.cs | 20 +----- .../PropertyTree/PropertyTreeView.xaml | 4 +- .../PropertyTrackKeyframeViewModel.cs | 1 - 28 files changed, 339 insertions(+), 107 deletions(-) create mode 100644 src/Artemis.Core/Models/Profile/KeyframeEngines/FloatKeyframeEngine.cs create mode 100644 src/Artemis.Core/Models/Profile/KeyframeEngines/IntKeyframeEngine.cs create mode 100644 src/Artemis.Core/Models/Profile/KeyframeEngines/KeyframeEngine.cs create mode 100644 src/Artemis.Core/Models/Profile/KeyframeEngines/SKPointKeyframeEngine.cs create mode 100644 src/Artemis.Core/Models/Profile/KeyframeEngines/SKSizeKeyframeEngine.cs diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj index b57dbfde5..d25e4455b 100644 --- a/src/Artemis.Core/Artemis.Core.csproj +++ b/src/Artemis.Core/Artemis.Core.csproj @@ -149,6 +149,11 @@ + + + + + diff --git a/src/Artemis.Core/Models/Profile/KeyframeEngines/FloatKeyframeEngine.cs b/src/Artemis.Core/Models/Profile/KeyframeEngines/FloatKeyframeEngine.cs new file mode 100644 index 000000000..75272488b --- /dev/null +++ b/src/Artemis.Core/Models/Profile/KeyframeEngines/FloatKeyframeEngine.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using Artemis.Core.Models.Profile.LayerProperties; + +namespace Artemis.Core.Models.Profile.KeyframeEngines +{ + /// + public class FloatKeyframeEngine : KeyframeEngine + { + public sealed override List CompatibleTypes { get; } = new List {typeof(float)}; + + public override object GetCurrentValue() + { + // Nothing fancy for now, just return the base value + return ((LayerProperty) LayerProperty).Value; + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/KeyframeEngines/IntKeyframeEngine.cs b/src/Artemis.Core/Models/Profile/KeyframeEngines/IntKeyframeEngine.cs new file mode 100644 index 000000000..e387e071e --- /dev/null +++ b/src/Artemis.Core/Models/Profile/KeyframeEngines/IntKeyframeEngine.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using Artemis.Core.Models.Profile.LayerProperties; + +namespace Artemis.Core.Models.Profile.KeyframeEngines +{ + /// + public class IntKeyframeEngine : KeyframeEngine + { + public sealed override List CompatibleTypes { get; } = new List {typeof(int)}; + + public override object GetCurrentValue() + { + // Nothing fancy for now, just return the base value + return ((LayerProperty) LayerProperty).Value; + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/KeyframeEngines/KeyframeEngine.cs b/src/Artemis.Core/Models/Profile/KeyframeEngines/KeyframeEngine.cs new file mode 100644 index 000000000..a6a6d00d1 --- /dev/null +++ b/src/Artemis.Core/Models/Profile/KeyframeEngines/KeyframeEngine.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using Artemis.Core.Exceptions; +using Artemis.Core.Models.Profile.LayerProperties; + +namespace Artemis.Core.Models.Profile.KeyframeEngines +{ + public abstract class KeyframeEngine + { + /// + /// Indicates whether has been called. + /// + public bool Initialized { get; private set; } + + /// + /// The layer property this keyframe engine applies to. + /// + public BaseLayerProperty LayerProperty { get; set; } + + /// + /// The keyframe progress in milliseconds. + /// + public double Progress { get; set; } + + /// + /// The types this keyframe engine supports. + /// + public abstract List CompatibleTypes { get; } + + /// + /// Associates the keyframe engine with the provided layer property. + /// + /// + public void Initialize(BaseLayerProperty layerProperty) + { + if (Initialized) + throw new ArtemisCoreException("Cannot initialize the same keyframe engine twice"); + if (!CompatibleTypes.Contains(layerProperty.Type)) + throw new ArtemisCoreException($"This property engine does not support the provided type {layerProperty.Type.Name}"); + + LayerProperty = layerProperty; + Initialized = true; + } + + /// + /// Updates the engine's progress + /// + /// + public void Update(double deltaTime) + { + if (!Initialized) + return; + + Progress += deltaTime; + + // LayerProperty determines what's next: reset, stop, continue + } + + /// + /// Gets the current value, if the progress is in between two keyframes the value will be interpolated + /// + /// + public abstract object GetCurrentValue(); + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/KeyframeEngines/SKPointKeyframeEngine.cs b/src/Artemis.Core/Models/Profile/KeyframeEngines/SKPointKeyframeEngine.cs new file mode 100644 index 000000000..15801bf3c --- /dev/null +++ b/src/Artemis.Core/Models/Profile/KeyframeEngines/SKPointKeyframeEngine.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using Artemis.Core.Models.Profile.LayerProperties; +using SkiaSharp; + +namespace Artemis.Core.Models.Profile.KeyframeEngines +{ + /// + public class SKPointKeyframeEngine : KeyframeEngine + { + public sealed override List CompatibleTypes { get; } = new List {typeof(SKPoint)}; + + public override object GetCurrentValue() + { + // Nothing fancy for now, just return the base value + return ((LayerProperty) LayerProperty).Value; + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/KeyframeEngines/SKSizeKeyframeEngine.cs b/src/Artemis.Core/Models/Profile/KeyframeEngines/SKSizeKeyframeEngine.cs new file mode 100644 index 000000000..7bc7a1f7a --- /dev/null +++ b/src/Artemis.Core/Models/Profile/KeyframeEngines/SKSizeKeyframeEngine.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using Artemis.Core.Models.Profile.LayerProperties; +using SkiaSharp; + +namespace Artemis.Core.Models.Profile.KeyframeEngines +{ + /// + public class SKSizeKeyframeEngine : KeyframeEngine + { + public sealed override List CompatibleTypes { get; } = new List {typeof(SKSize)}; + + public override object GetCurrentValue() + { + // Nothing fancy for now, just return the base value + return ((LayerProperty) LayerProperty).Value; + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index 019148c7e..37346bcef 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -128,9 +128,9 @@ namespace Artemis.Core.Models.Profile public LayerProperty PositionProperty { get; private set; } /// - /// The scale property of this layer, also found in + /// The size property of this layer, also found in /// - public LayerProperty ScaleProperty { get; private set; } + public LayerProperty SizeProperty { get; private set; } /// /// The rotation property of this layer, also found in @@ -304,12 +304,12 @@ namespace Artemis.Core.Models.Profile var transformProperty = new LayerProperty(this, null, "Core.Transform", "Transform", "The default properties collection every layer has, allows you to transform the shape."); AnchorPointProperty = new LayerProperty(this, transformProperty, "Core.AnchorPoint", "Anchor Point", "The point at which the shape is attached to its position."); PositionProperty = new LayerProperty(this, transformProperty, "Core.Position", "Position", "The position of the shape."); - ScaleProperty = new LayerProperty(this, transformProperty, "Core.Scale", "Scale", "The scale of the shape.") {InputAffix = "%"}; + SizeProperty = new LayerProperty(this, transformProperty, "Core.Size", "Size", "The size of the shape.") {InputAffix = "%"}; RotationProperty = new LayerProperty(this, transformProperty, "Core.Rotation", "Rotation", "The rotation of the shape in degrees.") {InputAffix = "°"}; OpacityProperty = new LayerProperty(this, transformProperty, "Core.Opacity", "Opacity", "The opacity of the shape.") {InputAffix = "%"}; transformProperty.Children.Add(AnchorPointProperty); transformProperty.Children.Add(PositionProperty); - transformProperty.Children.Add(ScaleProperty); + transformProperty.Children.Add(SizeProperty); transformProperty.Children.Add(RotationProperty); transformProperty.Children.Add(OpacityProperty); @@ -345,7 +345,10 @@ namespace Artemis.Core.Models.Profile path.AddRect(artemisLed.AbsoluteRenderRectangle); Path = path; - LayerShape?.CalculateRenderProperties(); + // This is called here so that the shape's render properties are up to date when other code + // responds to OnRenderPropertiesUpdated + LayerShape?.CalculateRenderProperties(PositionProperty.GetCurrentValue(), SizeProperty.GetCurrentValue()); + OnRenderPropertiesUpdated(); } diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs index b65a6f1a7..b48bdbf60 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Artemis.Core.Exceptions; +using Artemis.Core.Models.Profile.KeyframeEngines; namespace Artemis.Core.Models.Profile.LayerProperties { @@ -67,12 +68,16 @@ namespace Artemis.Core.Models.Profile.LayerProperties /// public Type Type { get; set; } - protected List BaseKeyframes { get; set; } /// - /// A list of keyframes defining different values of the property in time, this list contains the untyped . + /// A list of keyframes defining different values of the property in time, this list contains the untyped + /// . /// public IReadOnlyCollection UntypedKeyframes => BaseKeyframes.AsReadOnly(); + public KeyframeEngine KeyframeEngine { get; set; } + + protected List BaseKeyframes { get; set; } + protected object BaseValue { get => _baseValue; @@ -80,11 +85,14 @@ namespace Artemis.Core.Models.Profile.LayerProperties { if (value != null && value.GetType() != Type) throw new ArtemisCoreException($"Cannot set value of type {value.GetType()} on property {this}, expected type is {Type}."); - _baseValue = value; + if (!Equals(_baseValue, value)) + { + _baseValue = value; + OnValueChanged(); + } } } - public void ApplyToEntity() { // Big o' TODO @@ -94,5 +102,16 @@ namespace Artemis.Core.Models.Profile.LayerProperties { return $"{nameof(Id)}: {Id}, {nameof(Name)}: {Name}, {nameof(Description)}: {Description}"; } + + #region Events + + public event EventHandler ValueChanged; + + protected virtual void OnValueChanged() + { + ValueChanged?.Invoke(this, EventArgs.Empty); + } + + #endregion } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs index 4141deac3..70a3530d2 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs @@ -9,14 +9,18 @@ namespace Artemis.Core.Models.Profile.LayerProperties { } + /// + /// The value of the property without any keyframes applied + /// public T Value { - get => (T) BaseValue; + get => BaseValue != null ? (T) BaseValue : default; set => BaseValue = value; } /// - /// A list of keyframes defining different values of the property in time, this list contains the strongly typed + /// A list of keyframes defining different values of the property in time, this list contains the strongly typed + /// /// public ReadOnlyCollection> Keyframes => BaseKeyframes.Cast>().ToList().AsReadOnly(); @@ -45,5 +49,17 @@ namespace Artemis.Core.Models.Profile.LayerProperties { BaseKeyframes.Clear(); } + + /// + /// Gets the current value using the keyframes + /// + /// + public T GetCurrentValue() + { + if (KeyframeEngine == null) + return Value; + + return (T) KeyframeEngine.GetCurrentValue(); + } } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerShapes/Ellipse.cs b/src/Artemis.Core/Models/Profile/LayerShapes/Ellipse.cs index 32f0e082f..fa25cf18d 100644 --- a/src/Artemis.Core/Models/Profile/LayerShapes/Ellipse.cs +++ b/src/Artemis.Core/Models/Profile/LayerShapes/Ellipse.cs @@ -13,11 +13,11 @@ namespace Artemis.Core.Models.Profile.LayerShapes { } - public override void CalculateRenderProperties() + public override void CalculateRenderProperties(SKPoint shapePosition, SKSize shapeSize) { var width = Layer.AbsoluteRectangle.Width; var height = Layer.AbsoluteRectangle.Height; - var rect = SKRect.Create(Position.X * width, Position.Y * height, Size.Width * width, Size.Height * height); + var rect = SKRect.Create(shapePosition.X * width, shapePosition.Y * height, shapeSize.Width * width, shapeSize.Height * height); var path = new SKPath(); path.AddOval(rect); diff --git a/src/Artemis.Core/Models/Profile/LayerShapes/Fill.cs b/src/Artemis.Core/Models/Profile/LayerShapes/Fill.cs index ace6d87dd..078137b62 100644 --- a/src/Artemis.Core/Models/Profile/LayerShapes/Fill.cs +++ b/src/Artemis.Core/Models/Profile/LayerShapes/Fill.cs @@ -1,4 +1,5 @@ using Artemis.Storage.Entities.Profile; +using SkiaSharp; namespace Artemis.Core.Models.Profile.LayerShapes { @@ -12,8 +13,9 @@ namespace Artemis.Core.Models.Profile.LayerShapes { } - public override void CalculateRenderProperties() + public override void CalculateRenderProperties(SKPoint shapePosition, SKSize shapeSize) { + // TODO: Scale the path? Not sure if desirable RenderPath = Layer.Path; RenderRectangle = Layer.Path.GetRect(); } diff --git a/src/Artemis.Core/Models/Profile/LayerShapes/LayerShape.cs b/src/Artemis.Core/Models/Profile/LayerShapes/LayerShape.cs index 00ade6057..074908089 100644 --- a/src/Artemis.Core/Models/Profile/LayerShapes/LayerShape.cs +++ b/src/Artemis.Core/Models/Profile/LayerShapes/LayerShape.cs @@ -6,9 +6,6 @@ namespace Artemis.Core.Models.Profile.LayerShapes { public abstract class LayerShape { - private SKPoint _position; - private SKSize _size; - protected LayerShape(Layer layer) { Layer = layer; @@ -17,48 +14,13 @@ namespace Artemis.Core.Models.Profile.LayerShapes protected LayerShape(Layer layer, ShapeEntity shapeEntity) { Layer = layer; - Anchor = new SKPoint(shapeEntity.Anchor?.X ?? 0, shapeEntity.Anchor?.Y ?? 0); - Position = new SKPoint(shapeEntity.Position?.X ?? 0, shapeEntity.Position?.Y ?? 0); - Size = new SKSize(shapeEntity.Width, shapeEntity.Height); } - /// /// The layer this shape is attached to /// public Layer Layer { get; set; } - /// - /// At which position the shape is attached to the layer - /// - public SKPoint Anchor { get; set; } - - /// - /// The position of the shape - /// - public SKPoint Position - { - get => _position; - set - { - _position = value; - Layer.CalculateRenderProperties(); - } - } - - /// - /// The size of the shape - /// - public SKSize Size - { - get => _size; - set - { - _size = value; - Layer.CalculateRenderProperties(); - } - } - /// /// A render rectangle relative to the layer /// @@ -69,17 +31,11 @@ namespace Artemis.Core.Models.Profile.LayerShapes /// public SKPath RenderPath { get; protected set; } - public abstract void CalculateRenderProperties(); + public abstract void CalculateRenderProperties(SKPoint shapePosition, SKSize shapeSize); public virtual void ApplyToEntity() { - Layer.LayerEntity.ShapeEntity = new ShapeEntity - { - Anchor = new ShapePointEntity {X = Anchor.X, Y = Anchor.Y}, - Position = new ShapePointEntity {X = Position.X, Y = Position.Y}, - Width = Size.Width, - Height = Size.Height - }; + Layer.LayerEntity.ShapeEntity = new ShapeEntity(); } /// @@ -90,8 +46,8 @@ namespace Artemis.Core.Models.Profile.LayerShapes { if (!Layer.Leds.Any()) { - Position = SKPoint.Empty; - Size = SKSize.Empty; + Layer.PositionProperty.Value = SKPoint.Empty; + Layer.SizeProperty.Value = SKSize.Empty; return; } @@ -100,8 +56,11 @@ namespace Artemis.Core.Models.Profile.LayerShapes var width = Layer.Leds.Max(l => l.RgbLed.AbsoluteLedRectangle.Location.X + l.RgbLed.AbsoluteLedRectangle.Size.Width) - x; var height = Layer.Leds.Max(l => l.RgbLed.AbsoluteLedRectangle.Location.Y + l.RgbLed.AbsoluteLedRectangle.Size.Height) - y; - Position = new SKPoint((float) (100f / width * (rect.Left - x)) / 100f, (float) (100f / height * (rect.Top - y)) / 100f); - Size = new SKSize((float) (100f / width * rect.Width) / 100f, (float) (100f / height * rect.Height) / 100f); + Layer.PositionProperty.Value = new SKPoint((float) (100f / width * (rect.Left - x)) / 100f, (float) (100f / height * (rect.Top - y)) / 100f); + Layer.SizeProperty.Value = new SKSize((float) (100f / width * rect.Width) / 100f, (float) (100f / height * rect.Height) / 100f); + + // TODO: Update keyframes + CalculateRenderProperties(Layer.PositionProperty.Value, Layer.SizeProperty.Value); } public SKRect GetUnscaledRectangle() @@ -115,10 +74,10 @@ namespace Artemis.Core.Models.Profile.LayerShapes var height = Layer.Leds.Max(l => l.RgbLed.AbsoluteLedRectangle.Location.Y + l.RgbLed.AbsoluteLedRectangle.Size.Height) - y; return SKRect.Create( - (float) (x + width * Position.X), - (float) (y + height * Position.Y), - (float) (width * Size.Width), - (float) (height * Size.Height) + (float) (x + width * Layer.PositionProperty.Value.X), + (float) (y + height * Layer.PositionProperty.Value.Y), + (float) (width * Layer.SizeProperty.Value.Width), + (float) (height * Layer.SizeProperty.Value.Height) ); } } diff --git a/src/Artemis.Core/Models/Profile/LayerShapes/Polygon.cs b/src/Artemis.Core/Models/Profile/LayerShapes/Polygon.cs index a5c230259..f8d432ea8 100644 --- a/src/Artemis.Core/Models/Profile/LayerShapes/Polygon.cs +++ b/src/Artemis.Core/Models/Profile/LayerShapes/Polygon.cs @@ -25,7 +25,7 @@ namespace Artemis.Core.Models.Profile.LayerShapes /// public List RenderPoints => Points.Select(p => new SKPoint(p.X * Layer.AbsoluteRectangle.Width, p.Y * Layer.AbsoluteRectangle.Height)).ToList(); - public override void CalculateRenderProperties() + public override void CalculateRenderProperties(SKPoint shapePosition, SKSize shapeSize) { var path = new SKPath(); path.AddPoly(RenderPoints.ToArray()); diff --git a/src/Artemis.Core/Models/Profile/LayerShapes/Rectangle.cs b/src/Artemis.Core/Models/Profile/LayerShapes/Rectangle.cs index 7c74e8879..adffbccbb 100644 --- a/src/Artemis.Core/Models/Profile/LayerShapes/Rectangle.cs +++ b/src/Artemis.Core/Models/Profile/LayerShapes/Rectangle.cs @@ -13,11 +13,11 @@ namespace Artemis.Core.Models.Profile.LayerShapes { } - public override void CalculateRenderProperties() + public override void CalculateRenderProperties(SKPoint shapePosition, SKSize shapeSize) { var width = Layer.AbsoluteRectangle.Width; var height = Layer.AbsoluteRectangle.Height; - var rect = SKRect.Create(Position.X * width, Position.Y * height, Size.Width * width, Size.Height * height); + var rect = SKRect.Create(shapePosition.X * width, shapePosition.Y * height, shapeSize.Width * width, shapeSize.Height * height); var path = new SKPath(); path.AddRect(rect); path.Transform(SKMatrix.MakeTranslation(Layer.Rectangle.Left, Layer.Rectangle.Top)); diff --git a/src/Artemis.Core/Plugins/Models/PluginSetting.cs b/src/Artemis.Core/Plugins/Models/PluginSetting.cs index 8f64bc71b..2d6da3c0f 100644 --- a/src/Artemis.Core/Plugins/Models/PluginSetting.cs +++ b/src/Artemis.Core/Plugins/Models/PluginSetting.cs @@ -43,8 +43,11 @@ namespace Artemis.Core.Plugins.Models get => _value; set { - _value = value; - OnSettingChanged(); + if (!Equals(_value, value)) + { + _value = value; + OnSettingChanged(); + } } } diff --git a/src/Artemis.Storage/Entities/Profile/ShapeEntity.cs b/src/Artemis.Storage/Entities/Profile/ShapeEntity.cs index 4427b4354..fc415ab80 100644 --- a/src/Artemis.Storage/Entities/Profile/ShapeEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/ShapeEntity.cs @@ -5,11 +5,6 @@ namespace Artemis.Storage.Entities.Profile public class ShapeEntity { public ShapeEntityType Type { get; set; } - public ShapePointEntity Anchor { get; set; } - public float Width { get; set; } - public float Height { get; set; } - public ShapePointEntity Position { get; set; } - public List Points { get; set; } } diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml index e916c15e2..70a77f0e9 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml @@ -61,7 +61,7 @@ - + _keyframesEnabled; + set + { + _keyframesEnabled = value; + UpdateKeyframes(); + } + } + + private void UpdateKeyframes() + { + } + public PropertyInputViewModel GetPropertyInputViewModel() { var match = _kernel.Get>().FirstOrDefault(p => p.CompatibleTypes.Contains(LayerProperty.Type)); diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/FloatPropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/FloatPropertyInputViewModel.cs index e2a9bbdfa..f25212a72 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/FloatPropertyInputViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/FloatPropertyInputViewModel.cs @@ -1,10 +1,26 @@ using System; using System.Collections.Generic; +using Artemis.Core.Models.Profile.LayerProperties; namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyInput { public class FloatPropertyInputViewModel : PropertyInputViewModel { public sealed override List CompatibleTypes { get; } = new List {typeof(float)}; + + protected override void UpdateBaseValue(object value) + { + throw new NotImplementedException(); + } + + protected override void UpdateKeyframeValue(BaseKeyframe keyframe, object value) + { + throw new NotImplementedException(); + } + + protected override void CreateKeyframeForValue(object value) + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/IntPropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/IntPropertyInputViewModel.cs index b1a2df52c..4effe5539 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/IntPropertyInputViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/IntPropertyInputViewModel.cs @@ -1,10 +1,26 @@ using System; using System.Collections.Generic; +using Artemis.Core.Models.Profile.LayerProperties; namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyInput { public class IntPropertyInputViewModel : PropertyInputViewModel { public sealed override List CompatibleTypes { get; } = new List {typeof(int)}; + + protected override void UpdateBaseValue(object value) + { + throw new NotImplementedException(); + } + + protected override void UpdateKeyframeValue(BaseKeyframe keyframe, object value) + { + throw new NotImplementedException(); + } + + protected override void CreateKeyframeForValue(object value) + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/PropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/PropertyInputViewModel.cs index 1b0ab7268..528c05458 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/PropertyInputViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/PropertyInputViewModel.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Linq; +using Artemis.Core.Models.Profile.LayerProperties; using Artemis.UI.Exceptions; using Stylet; @@ -12,6 +14,12 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P public abstract List CompatibleTypes { get; } public LayerPropertyViewModel LayerPropertyViewModel { get; private set; } + public object InputValue + { + get => LayerPropertyViewModel.LayerProperty.KeyframeEngine.GetCurrentValue(); + set => UpdateInputValue(value); + } + public void Initialize(LayerPropertyViewModel layerPropertyViewModel) { if (Initialized) @@ -20,7 +28,32 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P throw new ArtemisUIException($"This input VM does not support the provided type {layerPropertyViewModel.LayerProperty.Type.Name}"); LayerPropertyViewModel = layerPropertyViewModel; + Update(); + Initialized = true; } + + public void Update() + { + NotifyOfPropertyChange(() => InputValue); + } + + private void UpdateInputValue(object value) + { + // If keyframes are disabled, update the base value + if (!LayerPropertyViewModel.KeyframesEnabled) + { + UpdateBaseValue(value); + return; + } + + // If on a keyframe, update the keyframe TODO: Make decisions.. + // var currentKeyframe = LayerPropertyViewModel.LayerProperty.UntypedKeyframes.FirstOrDefault(k => k.Position == LayerPropertyViewModel.) + // Otherwise, add a new keyframe at the current position + } + + protected abstract void UpdateBaseValue(object value); + protected abstract void UpdateKeyframeValue(BaseKeyframe keyframe, object value); + protected abstract void CreateKeyframeForValue(object value); } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKPointPropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKPointPropertyInputViewModel.cs index 189d21481..0977a9bf7 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKPointPropertyInputViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKPointPropertyInputViewModel.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Artemis.Core.Models.Profile.LayerProperties; using SkiaSharp; namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyInput @@ -7,5 +8,20 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P public class SKPointPropertyInputViewModel : PropertyInputViewModel { public sealed override List CompatibleTypes { get; } = new List {typeof(SKPoint)}; + + protected override void UpdateBaseValue(object value) + { + throw new NotImplementedException(); + } + + protected override void UpdateKeyframeValue(BaseKeyframe keyframe, object value) + { + throw new NotImplementedException(); + } + + protected override void CreateKeyframeForValue(object value) + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKSizePropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKSizePropertyInputViewModel.cs index ae184a64f..3b35a67b3 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKSizePropertyInputViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKSizePropertyInputViewModel.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Artemis.Core.Models.Profile.LayerProperties; using SkiaSharp; namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyInput @@ -7,5 +8,20 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P public class SKSizePropertyInputViewModel : PropertyInputViewModel { public sealed override List CompatibleTypes { get; } = new List {typeof(SKSize)}; + + protected override void UpdateBaseValue(object value) + { + throw new NotImplementedException(); + } + + protected override void UpdateKeyframeValue(BaseKeyframe keyframe, object value) + { + throw new NotImplementedException(); + } + + protected override void CreateKeyframeForValue(object value) + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeChildView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeChildView.xaml index b54b1c412..69fba2633 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeChildView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeChildView.xaml @@ -36,8 +36,8 @@ ToolTip="{Binding LayerPropertyViewModel.LayerProperty.Description}" HorizontalAlignment="Left" /> - - + +