mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-31 09:43:46 +00:00
Added layer properties and keyframes to persistent storage
This commit is contained in:
parent
d1e0267709
commit
e8570a6dd9
@ -264,22 +264,76 @@ namespace Artemis.Core.Models.Profile
|
|||||||
CalculateRenderProperties();
|
CalculateRenderProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Properties
|
internal void CalculateRenderProperties()
|
||||||
|
|
||||||
public void AddLayerProperty<T>(LayerProperty<T> layerProperty)
|
|
||||||
{
|
{
|
||||||
if (_properties.ContainsKey(layerProperty.Id))
|
if (!Leds.Any())
|
||||||
throw new ArtemisCoreException($"Duplicate property ID detected. Layer already contains a property with ID {layerProperty.Id}.");
|
{
|
||||||
|
Rectangle = SKRect.Empty;
|
||||||
_properties.Add(layerProperty.Id, layerProperty);
|
AbsoluteRectangle = SKRect.Empty;
|
||||||
|
Path = new SKPath();
|
||||||
|
OnRenderPropertiesUpdated();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddLayerProperty(BaseLayerProperty layerProperty)
|
// Determine to top-left and bottom-right
|
||||||
|
var minX = Leds.Min(l => l.AbsoluteRenderRectangle.Left);
|
||||||
|
var minY = Leds.Min(l => l.AbsoluteRenderRectangle.Top);
|
||||||
|
var maxX = Leds.Max(l => l.AbsoluteRenderRectangle.Right);
|
||||||
|
var maxY = Leds.Max(l => l.AbsoluteRenderRectangle.Bottom);
|
||||||
|
|
||||||
|
Rectangle = SKRect.Create(minX, minY, maxX - minX, maxY - minY);
|
||||||
|
AbsoluteRectangle = SKRect.Create(0, 0, maxX - minX, maxY - minY);
|
||||||
|
|
||||||
|
var path = new SKPath {FillType = SKPathFillType.Winding};
|
||||||
|
foreach (var artemisLed in Leds)
|
||||||
|
path.AddRect(artemisLed.AbsoluteRenderRectangle);
|
||||||
|
|
||||||
|
Path = path;
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"[Layer] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}";
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the provided layer property to the layer.
|
||||||
|
/// If found, the last stored base value and keyframes will be applied to the provided property.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of value of the layer property</typeparam>
|
||||||
|
/// <param name="layerProperty">The property to apply to the layer</param>
|
||||||
|
/// <returns>True if an existing value was found and applied, otherwise false.</returns>
|
||||||
|
public bool AddLayerProperty<T>(LayerProperty<T> layerProperty)
|
||||||
|
{
|
||||||
|
return AddLayerProperty((BaseLayerProperty) layerProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the provided layer property to the layer.
|
||||||
|
/// If found, the last stored base value and keyframes will be applied to the provided property.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="layerProperty">The property to apply to the layer</param>
|
||||||
|
/// <returns>True if an existing value was found and applied, otherwise false.</returns>
|
||||||
|
public bool AddLayerProperty(BaseLayerProperty layerProperty)
|
||||||
{
|
{
|
||||||
if (_properties.ContainsKey(layerProperty.Id))
|
if (_properties.ContainsKey(layerProperty.Id))
|
||||||
throw new ArtemisCoreException($"Duplicate property ID detected. Layer already contains a property with ID {layerProperty.Id}.");
|
throw new ArtemisCoreException($"Duplicate property ID detected. Layer already contains a property with ID {layerProperty.Id}.");
|
||||||
|
|
||||||
|
var propertyEntity = LayerEntity.PropertyEntities.FirstOrDefault(p => p.Id == layerProperty.Id && p.ValueType == layerProperty.Type.Name);
|
||||||
|
// TODO: Catch serialization exceptions and log them
|
||||||
|
if (propertyEntity != null)
|
||||||
|
layerProperty.ApplyToProperty(propertyEntity);
|
||||||
|
|
||||||
_properties.Add(layerProperty.Id, layerProperty);
|
_properties.Add(layerProperty.Id, layerProperty);
|
||||||
|
return propertyEntity != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -320,44 +374,6 @@ namespace Artemis.Core.Models.Profile
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
internal void CalculateRenderProperties()
|
|
||||||
{
|
|
||||||
if (!Leds.Any())
|
|
||||||
{
|
|
||||||
Rectangle = SKRect.Empty;
|
|
||||||
AbsoluteRectangle = SKRect.Empty;
|
|
||||||
Path = new SKPath();
|
|
||||||
OnRenderPropertiesUpdated();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine to top-left and bottom-right
|
|
||||||
var minX = Leds.Min(l => l.AbsoluteRenderRectangle.Left);
|
|
||||||
var minY = Leds.Min(l => l.AbsoluteRenderRectangle.Top);
|
|
||||||
var maxX = Leds.Max(l => l.AbsoluteRenderRectangle.Right);
|
|
||||||
var maxY = Leds.Max(l => l.AbsoluteRenderRectangle.Bottom);
|
|
||||||
|
|
||||||
Rectangle = SKRect.Create(minX, minY, maxX - minX, maxY - minY);
|
|
||||||
AbsoluteRectangle = SKRect.Create(0, 0, maxX - minX, maxY - minY);
|
|
||||||
|
|
||||||
var path = new SKPath {FillType = SKPathFillType.Winding};
|
|
||||||
foreach (var artemisLed in Leds)
|
|
||||||
path.AddRect(artemisLed.AbsoluteRenderRectangle);
|
|
||||||
|
|
||||||
Path = path;
|
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"[Layer] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}";
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
|
|
||||||
public event EventHandler RenderPropertiesUpdated;
|
public event EventHandler RenderPropertiesUpdated;
|
||||||
|
|||||||
@ -4,7 +4,7 @@ namespace Artemis.Core.Models.Profile.LayerProperties
|
|||||||
{
|
{
|
||||||
public class BaseKeyframe
|
public class BaseKeyframe
|
||||||
{
|
{
|
||||||
protected BaseKeyframe(Layer layer, BaseLayerProperty property)
|
protected internal BaseKeyframe(Layer layer, BaseLayerProperty property)
|
||||||
{
|
{
|
||||||
Layer = layer;
|
Layer = layer;
|
||||||
BaseProperty = property;
|
BaseProperty = property;
|
||||||
@ -14,6 +14,6 @@ namespace Artemis.Core.Models.Profile.LayerProperties
|
|||||||
public TimeSpan Position { get; set; }
|
public TimeSpan Position { get; set; }
|
||||||
|
|
||||||
protected BaseLayerProperty BaseProperty { get; }
|
protected BaseLayerProperty BaseProperty { get; }
|
||||||
protected object BaseValue { get; set; }
|
protected internal object BaseValue { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,7 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Artemis.Core.Exceptions;
|
using Artemis.Core.Exceptions;
|
||||||
using Artemis.Core.Models.Profile.KeyframeEngines;
|
using Artemis.Core.Models.Profile.KeyframeEngines;
|
||||||
|
using Artemis.Storage.Entities.Profile;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Artemis.Core.Models.Profile.LayerProperties
|
namespace Artemis.Core.Models.Profile.LayerProperties
|
||||||
{
|
{
|
||||||
@ -9,7 +12,7 @@ namespace Artemis.Core.Models.Profile.LayerProperties
|
|||||||
{
|
{
|
||||||
private object _baseValue;
|
private object _baseValue;
|
||||||
|
|
||||||
protected BaseLayerProperty(Layer layer, BaseLayerProperty parent, string id, string name, string description, Type type)
|
protected internal BaseLayerProperty(Layer layer, BaseLayerProperty parent, string id, string name, string description, Type type)
|
||||||
{
|
{
|
||||||
Layer = layer;
|
Layer = layer;
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
@ -78,7 +81,7 @@ namespace Artemis.Core.Models.Profile.LayerProperties
|
|||||||
|
|
||||||
protected List<BaseKeyframe> BaseKeyframes { get; set; }
|
protected List<BaseKeyframe> BaseKeyframes { get; set; }
|
||||||
|
|
||||||
protected object BaseValue
|
protected internal object BaseValue
|
||||||
{
|
{
|
||||||
get => _baseValue;
|
get => _baseValue;
|
||||||
set
|
set
|
||||||
@ -93,9 +96,36 @@ namespace Artemis.Core.Models.Profile.LayerProperties
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ApplyToEntity()
|
internal void ApplyToEntity()
|
||||||
{
|
{
|
||||||
// Big o' TODO
|
var propertyEntity = Layer.LayerEntity.PropertyEntities.FirstOrDefault(p => p.Id == Id);
|
||||||
|
if (propertyEntity == null)
|
||||||
|
{
|
||||||
|
propertyEntity = new PropertyEntity {Id = Id};
|
||||||
|
Layer.LayerEntity.PropertyEntities.Add(propertyEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
propertyEntity.ValueType = Type.Name;
|
||||||
|
propertyEntity.Value = JsonConvert.SerializeObject(BaseValue);
|
||||||
|
|
||||||
|
propertyEntity.KeyframeEntities.Clear();
|
||||||
|
foreach (var baseKeyframe in BaseKeyframes)
|
||||||
|
{
|
||||||
|
propertyEntity.KeyframeEntities.Add(new KeyframeEntity
|
||||||
|
{
|
||||||
|
Position = baseKeyframe.Position,
|
||||||
|
Value = JsonConvert.SerializeObject(baseKeyframe.BaseValue)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ApplyToProperty(PropertyEntity propertyEntity)
|
||||||
|
{
|
||||||
|
BaseValue = DeserializePropertyValue(propertyEntity.Value);
|
||||||
|
|
||||||
|
BaseKeyframes.Clear();
|
||||||
|
foreach (var keyframeEntity in propertyEntity.KeyframeEntities)
|
||||||
|
BaseKeyframes.Add(new BaseKeyframe(Layer, this) {BaseValue = DeserializePropertyValue(keyframeEntity.Value)});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
@ -103,6 +133,13 @@ namespace Artemis.Core.Models.Profile.LayerProperties
|
|||||||
return $"{nameof(Id)}: {Id}, {nameof(Name)}: {Name}, {nameof(Description)}: {Description}";
|
return $"{nameof(Id)}: {Id}, {nameof(Name)}: {Name}, {nameof(Description)}: {Description}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object DeserializePropertyValue(string value)
|
||||||
|
{
|
||||||
|
if (value == "null")
|
||||||
|
return Type.IsValueType ? Activator.CreateInstance(Type) : null;
|
||||||
|
return JsonConvert.DeserializeObject(value, Type);
|
||||||
|
}
|
||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
|
|
||||||
public event EventHandler<EventArgs> ValueChanged;
|
public event EventHandler<EventArgs> ValueChanged;
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
|
||||||
using LiteDB;
|
using LiteDB;
|
||||||
|
|
||||||
namespace Artemis.Storage.Entities.Profile
|
namespace Artemis.Storage.Entities.Profile
|
||||||
@ -10,6 +9,7 @@ namespace Artemis.Storage.Entities.Profile
|
|||||||
public LayerEntity()
|
public LayerEntity()
|
||||||
{
|
{
|
||||||
Leds = new List<LedEntity>();
|
Leds = new List<LedEntity>();
|
||||||
|
PropertyEntities = new List<PropertyEntity>();
|
||||||
Condition = new List<ProfileConditionEntity>();
|
Condition = new List<ProfileConditionEntity>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,6 +20,7 @@ namespace Artemis.Storage.Entities.Profile
|
|||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
public List<LedEntity> Leds { get; set; }
|
public List<LedEntity> Leds { get; set; }
|
||||||
|
public List<PropertyEntity> PropertyEntities { get; set; }
|
||||||
public List<ProfileConditionEntity> Condition { get; set; }
|
public List<ProfileConditionEntity> Condition { get; set; }
|
||||||
|
|
||||||
public ShapeEntity ShapeEntity { get; set; }
|
public ShapeEntity ShapeEntity { get; set; }
|
||||||
@ -27,6 +28,7 @@ namespace Artemis.Storage.Entities.Profile
|
|||||||
|
|
||||||
[BsonRef("ProfileEntity")]
|
[BsonRef("ProfileEntity")]
|
||||||
public ProfileEntity Profile { get; set; }
|
public ProfileEntity Profile { get; set; }
|
||||||
|
|
||||||
public Guid ProfileId { get; set; }
|
public Guid ProfileId { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
25
src/Artemis.Storage/Entities/Profile/PropertyEntity.cs
Normal file
25
src/Artemis.Storage/Entities/Profile/PropertyEntity.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Artemis.Storage.Entities.Profile
|
||||||
|
{
|
||||||
|
public class PropertyEntity
|
||||||
|
{
|
||||||
|
public PropertyEntity()
|
||||||
|
{
|
||||||
|
KeyframeEntities = new List<KeyframeEntity>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string ValueType { get; set; }
|
||||||
|
public string Value { get; set; }
|
||||||
|
|
||||||
|
public List<KeyframeEntity> KeyframeEntities { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class KeyframeEntity
|
||||||
|
{
|
||||||
|
public TimeSpan Position { get; set; }
|
||||||
|
public string Value { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user