diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs
index 257a63244..19a20ab39 100644
--- a/src/Artemis.Core/Models/Profile/Layer.cs
+++ b/src/Artemis.Core/Models/Profile/Layer.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Artemis.Core.Extensions;
+using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.Core.Models.Profile.LayerProperties.Attributes;
using Artemis.Core.Models.Profile.LayerShapes;
using Artemis.Core.Models.Surface;
@@ -180,13 +181,28 @@ namespace Artemis.Core.Models.Profile
///
public override void Update(double deltaTime)
{
+ if (LayerBrush == null)
+ return;
+
General.Update(deltaTime);
Transform.Update(deltaTime);
+ LayerBrush.UpdateProperties(deltaTime);
- LayerBrush?.UpdateProperties(deltaTime);
- // TODO: Find the last keyframe and if required, reset the properties
+ var properties = new List(General.GetAllLayerProperties());
+ properties.AddRange(Transform.GetAllLayerProperties());
+ properties.AddRange(LayerBrush.GetAllLayerProperties());
- LayerBrush?.Update(deltaTime);
+ // For now, reset all keyframe engines after the last keyframe was hit
+ // This is a placeholder method of repeating the animation until repeat modes are implemented
+ var timeLineEnd = properties.Max(p => p.GetLastKeyframePosition());
+ if (properties.Any(p => p.TimelineProgress >= timeLineEnd))
+ {
+ General.Override(TimeSpan.Zero);
+ Transform.Override(TimeSpan.Zero);
+ LayerBrush.OverrideProperties(TimeSpan.Zero);
+ }
+
+ LayerBrush.Update(deltaTime);
}
///
diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs
index b8daceb02..e27f82c6c 100644
--- a/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs
+++ b/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs
@@ -1,13 +1,46 @@
-using Artemis.Storage.Entities.Profile;
+using System;
+using System.Collections.Generic;
+using Artemis.Storage.Entities.Profile;
namespace Artemis.Core.Models.Profile.LayerProperties
{
+ ///
+ /// For internal use only, to implement your own layer property type, extend instead.
+ ///
public abstract class BaseLayerProperty
{
///
/// Used to declare that this property doesn't belong to a plugin and should use the core plugin GUID
///
internal bool IsCoreProperty { get; set; }
+ internal PropertyEntity PropertyEntity { get; set; }
+ internal LayerPropertyGroup LayerPropertyGroup { get; set; }
+
+ ///
+ /// Gets whether keyframes are supported on this property
+ ///
+ public bool KeyframesSupported { get; protected set; }
+
+ ///
+ /// Gets or sets whether keyframes are enabled on this property, has no effect if is
+ /// False
+ ///
+ public bool KeyframesEnabled { get; set; }
+
+ ///
+ /// Gets or sets whether the property is hidden in the UI
+ ///
+ public bool IsHidden { get; set; }
+
+ ///
+ /// Indicates whether the BaseValue was loaded from storage, useful to check whether a default value must be applied
+ ///
+ public bool IsLoadedFromStorage { get; internal set; }
+
+ ///
+ /// Gets the total progress on the timeline
+ ///
+ public TimeSpan TimelineProgress { get; internal set; }
///
/// Applies the provided property entity to the layer property by deserializing the JSON base value and keyframe values
@@ -21,5 +54,8 @@ namespace Artemis.Core.Models.Profile.LayerProperties
///
///
internal abstract void ApplyToEntity();
+
+ internal abstract List GetKeyframePositions();
+ internal abstract TimeSpan GetLastKeyframePosition();
}
}
\ 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 2b89dfd8d..1ce9a5ec3 100644
--- a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs
+++ b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs
@@ -53,38 +53,12 @@ namespace Artemis.Core.Models.Profile.LayerProperties
get => !KeyframesEnabled || !KeyframesSupported ? BaseValue : _currentValue;
internal set => _currentValue = value;
}
-
- ///
- /// Gets whether keyframes are supported on this property
- ///
- public bool KeyframesSupported { get; internal set; }
-
- ///
- /// Gets or sets whether keyframes are enabled on this property, has no effect if is
- /// False
- ///
- public bool KeyframesEnabled { get; set; }
-
- ///
- /// Gets or sets whether the property is hidden in the UI
- ///
- public bool IsHidden { get; set; }
-
- ///
- /// Indicates whether the BaseValue was loaded from storage, useful to check whether a default value must be applied
- ///
- public bool IsLoadedFromStorage { get; internal set; }
-
+
///
/// Gets a read-only list of all the keyframes on this layer property
///
public IReadOnlyList> Keyframes => _keyframes.AsReadOnly();
-
- ///
- /// Gets the total progress on the timeline
- ///
- public TimeSpan TimelineProgress { get; private set; }
-
+
///
/// Gets the current keyframe in the timeline according to the current progress
///
@@ -94,10 +68,7 @@ namespace Artemis.Core.Models.Profile.LayerProperties
/// Gets the next keyframe in the timeline according to the current progress
///
public LayerPropertyKeyframe NextKeyframe { get; protected set; }
-
- internal PropertyEntity PropertyEntity { get; set; }
- internal LayerPropertyGroup LayerPropertyGroup { get; set; }
-
+
///
/// Adds a keyframe to the layer property
///
@@ -232,6 +203,16 @@ namespace Artemis.Core.Models.Profile.LayerProperties
}));
}
+ internal override List GetKeyframePositions()
+ {
+ return Keyframes.Select(k => k.Position).ToList();
+ }
+
+ internal override TimeSpan GetLastKeyframePosition()
+ {
+ return Keyframes.LastOrDefault()?.Position ?? TimeSpan.Zero;
+ }
+
#region Events
public event EventHandler Updated;
diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/Types/EnumLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/Types/EnumLayerProperty.cs
index 0dbcf3332..63cfbbfd7 100644
--- a/src/Artemis.Core/Models/Profile/LayerProperties/Types/EnumLayerProperty.cs
+++ b/src/Artemis.Core/Models/Profile/LayerProperties/Types/EnumLayerProperty.cs
@@ -1,9 +1,10 @@
-using Artemis.Core.Exceptions;
+using System;
+using Artemis.Core.Exceptions;
namespace Artemis.Core.Models.Profile.LayerProperties.Types
{
- ///
- public class EnumLayerProperty : LayerProperty where T : System.Enum
+ ///
+ public class EnumLayerProperty : LayerProperty where T : Enum
{
public EnumLayerProperty()
{
diff --git a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs
index 60b83d7ca..486b36aa2 100644
--- a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs
+++ b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs
@@ -1,6 +1,9 @@
using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Linq;
using Artemis.Core.Events;
+using Artemis.Core.Exceptions;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.Core.Models.Profile.LayerProperties.Attributes;
using Artemis.Core.Plugins.Exceptions;
@@ -10,13 +13,31 @@ namespace Artemis.Core.Models.Profile
{
public class LayerPropertyGroup
{
+ private ReadOnlyCollection _allLayerProperties;
+
+ protected LayerPropertyGroup()
+ {
+ LayerProperties = new List();
+ LayerPropertyGroups = new List();
+ }
+
public bool PropertiesInitialized { get; private set; }
///
- /// Used to declare that this property group doesn't belong to a plugin and should use the core plugin GUID
+ /// Used to declare that this property group doesn't belong to a plugin and should use the core plugin GUID
///
internal bool IsCorePropertyGroup { get; set; }
+ ///
+ /// A list of all layer properties in this group
+ ///
+ internal List LayerProperties { get; set; }
+
+ ///
+ /// A list of al child groups in this group
+ ///
+ internal List LayerPropertyGroups { get; set; }
+
///
/// Called when all layer properties in this property group have been initialized
///
@@ -26,6 +47,10 @@ namespace Artemis.Core.Models.Profile
internal void InitializeProperties(ILayerService layerService, Layer layer, string path)
{
+ // Doubt this will happen but let's make sure
+ if (PropertiesInitialized)
+ throw new ArtemisCoreException("Layer property group already initialized, wut");
+
// Get all properties with a PropertyDescriptionAttribute
foreach (var propertyInfo in GetType().GetProperties())
{
@@ -38,6 +63,7 @@ namespace Artemis.Core.Models.Profile
var instance = (BaseLayerProperty) Activator.CreateInstance(propertyInfo.PropertyType);
InitializeProperty(layer, path, instance);
propertyInfo.SetValue(this, instance);
+ LayerProperties.Add(instance);
}
else
{
@@ -50,6 +76,7 @@ namespace Artemis.Core.Models.Profile
var instance = (LayerPropertyGroup) Activator.CreateInstance(propertyInfo.PropertyType);
instance.InitializeProperties(layerService, layer, $"{path}{propertyInfo.Name}.");
propertyInfo.SetValue(this, instance);
+ LayerPropertyGroups.Add(instance);
}
}
}
@@ -90,6 +117,25 @@ namespace Artemis.Core.Models.Profile
OnPropertyGroupOverriding(new PropertyGroupUpdatingEventArgs(overrideTime));
}
+ ///
+ /// Recursively gets all layer properties on this group and any subgroups
+ ///
+ ///
+ internal IReadOnlyCollection GetAllLayerProperties()
+ {
+ if (!PropertiesInitialized)
+ return new List();
+ if (_allLayerProperties != null)
+ return _allLayerProperties;
+
+ var result = new List(LayerProperties);
+ foreach (var layerPropertyGroup in LayerPropertyGroups)
+ result.AddRange(layerPropertyGroup.GetAllLayerProperties());
+
+ _allLayerProperties = result.AsReadOnly();
+ return _allLayerProperties;
+ }
+
private void InitializeProperty(Layer layer, string path, BaseLayerProperty instance)
{
var pluginGuid = IsCorePropertyGroup || instance.IsCoreProperty ? Constants.CorePluginInfo.Guid : layer.LayerBrush.PluginInfo.Guid;
diff --git a/src/Artemis.Core/Plugins/LayerBrush/BaseLayerBrush.cs b/src/Artemis.Core/Plugins/LayerBrush/BaseLayerBrush.cs
index 1d831f06f..8e36e0ab3 100644
--- a/src/Artemis.Core/Plugins/LayerBrush/BaseLayerBrush.cs
+++ b/src/Artemis.Core/Plugins/LayerBrush/BaseLayerBrush.cs
@@ -1,5 +1,7 @@
using System;
+using System.Collections.Generic;
using Artemis.Core.Models.Profile;
+using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.Core.Plugins.Models;
using Artemis.Core.Services.Interfaces;
using SkiaSharp;
@@ -66,5 +68,14 @@ namespace Artemis.Core.Plugins.LayerBrush
internal virtual void UpdateProperties(double deltaTime)
{
}
+
+ internal virtual void OverrideProperties(TimeSpan overrideTime)
+ {
+ }
+
+ internal virtual IReadOnlyCollection GetAllLayerProperties()
+ {
+ return new List();
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Plugins/LayerBrush/LayerBrush.cs b/src/Artemis.Core/Plugins/LayerBrush/LayerBrush.cs
index 176c2e062..517322571 100644
--- a/src/Artemis.Core/Plugins/LayerBrush/LayerBrush.cs
+++ b/src/Artemis.Core/Plugins/LayerBrush/LayerBrush.cs
@@ -1,4 +1,7 @@
-using Artemis.Core.Models.Profile;
+using System;
+using System.Collections.Generic;
+using Artemis.Core.Models.Profile;
+using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.Core.Plugins.Exceptions;
using Artemis.Core.Services.Interfaces;
@@ -60,6 +63,16 @@ namespace Artemis.Core.Plugins.LayerBrush
Properties.Update(deltaTime);
}
+ internal override void OverrideProperties(TimeSpan overrideTime)
+ {
+ Properties.Override(overrideTime);
+ }
+
+ internal override IReadOnlyCollection GetAllLayerProperties()
+ {
+ return Properties.GetAllLayerProperties();
+ }
+
#endregion
}
}
\ No newline at end of file