Added keyframe creation outside the timeline

Added existing shape moving
This commit is contained in:
SpoinkyNL committed 2020-01-13 22:11:25 +01:00
1 parent a138ec916d
commit 7ddf816ca5
22 files changed
+178 -148

No files matched your search

@@ -21,68 +21,82 @@ namespace Artemis.Core.Models.Profile.LayerProperties
Name = name;
Description = description;
Type = type;
CanUseKeyframes = true;
Children = new List<BaseLayerProperty>();
BaseKeyframes = new List<BaseKeyframe>();
}
/// <summary>
/// The layer this property applies to
/// Gets the layer this property applies to
/// </summary>
public Layer Layer { get; }
/// <summary>
/// The parent property of this property.
/// Gets the parent property of this property.
/// </summary>
public BaseLayerProperty Parent { get; }
/// <summary>
/// The child properties of this property.
/// Gets or sets the child properties of this property.
/// <remarks>If the layer has children it cannot contain a value or keyframes.</remarks>
/// </summary>
public List<BaseLayerProperty> Children { get; set; }
/// <summary>
/// A unique identifier for this property, a layer may not contain two properties with the same ID.
/// Gets or sets a unique identifier for this property, a layer may not contain two properties with the same ID.
/// </summary>
public string Id { get; set; }
/// <summary>
/// The user-friendly name for this property, shown in the UI.
/// Gets or sets the user-friendly name for this property, shown in the UI.
/// </summary>
public string Name { get; set; }
/// <summary>
/// The user-friendly description for this property, shown in the UI.
/// Gets or sets the user-friendly description for this property, shown in the UI.
/// </summary>
public string Description { get; set; }
/// <summary>
/// Whether to expand this property by default, this is useful for important parent properties.
/// Gets or sets whether to expand this property by default, this is useful for important parent properties.
/// </summary>
public bool ExpandByDefault { get; set; }
/// <summary>
/// An optional input prefix to show before input elements in the UI.
/// Gets or sets the an optional input prefix to show before input elements in the UI.
/// </summary>
public string InputPrefix { get; set; }
/// <summary>
/// An optional input affix to show behind input elements in the UI.
/// Gets or sets an optional input affix to show behind input elements in the UI.
/// </summary>
public string InputAffix { get; set; }
/// <summary>
/// The type of value this layer property contains.
/// Gets or sets whether this property can use keyframes, True by default.
/// </summary>
public Type Type { get; set; }
public bool CanUseKeyframes { get; set; }
/// <summary>
/// A list of keyframes defining different values of the property in time, this list contains the untyped
/// Gets or sets whether this property is using keyframes.
/// </summary>
public bool IsUsingKeyframes { get; set; }
/// <summary>
/// Gets the type of value this layer property contains.
/// </summary>
public Type Type { get; protected set; }
/// <summary>
/// Gets a list of keyframes defining different values of the property in time, this list contains the untyped
/// <see cref="BaseKeyframe" />.
/// </summary>
public IReadOnlyCollection<BaseKeyframe> UntypedKeyframes => BaseKeyframes.AsReadOnly();
/// <summary>
/// Gets or sets the keyframe engine instance of this property
/// </summary>
public KeyframeEngine KeyframeEngine { get; set; }
protected List<BaseKeyframe> BaseKeyframes { get; set; }
@@ -113,6 +127,7 @@ namespace Artemis.Core.Models.Profile.LayerProperties
propertyEntity.ValueType = Type.Name;
propertyEntity.Value = JsonConvert.SerializeObject(BaseValue);
propertyEntity.IsUsingKeyframes = IsUsingKeyframes;
propertyEntity.KeyframeEntities.Clear();
foreach (var baseKeyframe in BaseKeyframes)
@@ -129,6 +144,7 @@ namespace Artemis.Core.Models.Profile.LayerProperties
internal void ApplyToProperty(PropertyEntity propertyEntity)
{
BaseValue = DeserializePropertyValue(propertyEntity.Value);
IsUsingKeyframes = propertyEntity.IsUsingKeyframes;
BaseKeyframes.Clear();
foreach (var keyframeEntity in propertyEntity.KeyframeEntities.OrderBy(e => e.Position))
@@ -170,6 +186,33 @@ namespace Artemis.Core.Models.Profile.LayerProperties
BaseKeyframes.Clear();
}
/// <summary>
/// Gets the current value using the regular value or keyframes.
/// </summary>
/// <param name="value">The value to set.</param>
/// <param name="time">
/// An optional time to set the value add, if provided and property is using keyframes the value will be set to an new
/// or existing keyframe.
/// </param>
public void SetCurrentValue(object value, TimeSpan? time)
{
if (value != null && value.GetType() != Type)
throw new ArtemisCoreException($"Cannot set value of type {value.GetType()} on property {this}, expected type is {Type}.");
if (time == null || !CanUseKeyframes || !IsUsingKeyframes)
BaseValue = value;
else
{
// If on a keyframe, update the keyframe
var currentKeyframe = UntypedKeyframes.FirstOrDefault(k => k.Position == time.Value);
// Create a new keyframe if none found
if (currentKeyframe == null)
currentKeyframe = CreateNewKeyframe(time.Value);
currentKeyframe.BaseValue = value;
}
}
internal void SortKeyframes()
{
BaseKeyframes = BaseKeyframes.OrderBy(k => k.Position).ToList();
@@ -1,4 +1,5 @@
using System.Collections.ObjectModel;
using System;
using System.Collections.ObjectModel;
using System.Linq;
namespace Artemis.Core.Models.Profile.LayerProperties
@@ -10,7 +11,7 @@ namespace Artemis.Core.Models.Profile.LayerProperties
}
/// <summary>
/// The value of the property without any keyframes applied
/// Gets or sets the value of the property without any keyframes applied
/// </summary>
public T Value
{
@@ -19,12 +20,12 @@ namespace Artemis.Core.Models.Profile.LayerProperties
}
/// <summary>
/// The value of the property with keyframes applied
/// Gets the value of the property with keyframes applied
/// </summary>
public T CurrentValue => KeyframeEngine != null ? (T) KeyframeEngine.GetCurrentValue() : Value;
/// <summary>
/// A list of keyframes defining different values of the property in time, this list contains the strongly typed
/// Gets a list of keyframes defining different values of the property in time, this list contains the strongly typed
/// <see cref="Keyframe{T}" />
/// </summary>
public ReadOnlyCollection<Keyframe<T>> Keyframes => BaseKeyframes.Cast<Keyframe<T>>().ToList().AsReadOnly();
@@ -50,7 +51,7 @@ namespace Artemis.Core.Models.Profile.LayerProperties
}
/// <summary>
/// Gets the current value using the keyframes
/// Gets the current value using the regular value or if present, keyframes
/// </summary>
/// <returns></returns>
public T GetCurrentValue()
@@ -1,4 +1,5 @@
using System.Linq;
using System;
using System.Linq;
using Artemis.Storage.Entities.Profile;
using SkiaSharp;
@@ -41,13 +42,14 @@ namespace Artemis.Core.Models.Profile.LayerShapes
/// <summary>
/// Updates Position and Size using the provided unscaled rectangle
/// </summary>
/// <param name="rect">An unscaled rectangle where 1px = 1mm</param>
public void SetFromUnscaledRectangle(SKRect rect)
/// <param name="rect">An unscaled rectangle which is relative to the layer (1.0 being full width/height, 0.5 being half).</param>
/// <param name="time">An optional timespan to indicate where to set the properties, if null the properties' base values will be used.</param>
public void SetFromUnscaledRectangle(SKRect rect, TimeSpan? time)
{
if (!Layer.Leds.Any())
{
Layer.PositionProperty.Value = SKPoint.Empty;
Layer.SizeProperty.Value = SKSize.Empty;
Layer.PositionProperty.SetCurrentValue(SKPoint.Empty, time);
Layer.SizeProperty.SetCurrentValue(SKSize.Empty, time);
return;
}
@@ -56,10 +58,9 @@ 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;
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);
Layer.PositionProperty.SetCurrentValue(new SKPoint((float) (100f / width * (rect.Left - x)) / 100f, (float) (100f / height * (rect.Top - y)) / 100f), time);
Layer.SizeProperty.SetCurrentValue(new SKSize((float) (100f / width * rect.Width) / 100f, (float) (100f / height * rect.Height) / 100f), time);
// TODO: Update keyframes
CalculateRenderProperties(Layer.PositionProperty.CurrentValue, Layer.SizeProperty.CurrentValue);
}