1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2026-01-02 10:43:31 +00:00

Core - Added ways for the core to easily access brush properties

%*/@ me, dealing with generic types in APIs is tricky
This commit is contained in:
Robert 2020-04-29 19:45:13 +02:00
parent 660324c980
commit e97fc046f5
7 changed files with 145 additions and 41 deletions

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using Artemis.Core.Extensions; using Artemis.Core.Extensions;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.Core.Models.Profile.LayerProperties.Attributes; using Artemis.Core.Models.Profile.LayerProperties.Attributes;
using Artemis.Core.Models.Profile.LayerShapes; using Artemis.Core.Models.Profile.LayerShapes;
using Artemis.Core.Models.Surface; using Artemis.Core.Models.Surface;
@ -180,13 +181,28 @@ namespace Artemis.Core.Models.Profile
/// <inheritdoc /> /// <inheritdoc />
public override void Update(double deltaTime) public override void Update(double deltaTime)
{ {
if (LayerBrush == null)
return;
General.Update(deltaTime); General.Update(deltaTime);
Transform.Update(deltaTime); Transform.Update(deltaTime);
LayerBrush.UpdateProperties(deltaTime);
LayerBrush?.UpdateProperties(deltaTime); var properties = new List<BaseLayerProperty>(General.GetAllLayerProperties());
// TODO: Find the last keyframe and if required, reset the properties 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);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -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 namespace Artemis.Core.Models.Profile.LayerProperties
{ {
/// <summary>
/// For internal use only, to implement your own layer property type, extend <see cref="LayerProperty{T}"/> instead.
/// </summary>
public abstract class BaseLayerProperty public abstract class BaseLayerProperty
{ {
/// <summary> /// <summary>
/// Used to declare that this property doesn't belong to a plugin and should use the core plugin GUID /// Used to declare that this property doesn't belong to a plugin and should use the core plugin GUID
/// </summary> /// </summary>
internal bool IsCoreProperty { get; set; } internal bool IsCoreProperty { get; set; }
internal PropertyEntity PropertyEntity { get; set; }
internal LayerPropertyGroup LayerPropertyGroup { get; set; }
/// <summary>
/// Gets whether keyframes are supported on this property
/// </summary>
public bool KeyframesSupported { get; protected set; }
/// <summary>
/// Gets or sets whether keyframes are enabled on this property, has no effect if <see cref="KeyframesSupported" /> is
/// False
/// </summary>
public bool KeyframesEnabled { get; set; }
/// <summary>
/// Gets or sets whether the property is hidden in the UI
/// </summary>
public bool IsHidden { get; set; }
/// <summary>
/// Indicates whether the BaseValue was loaded from storage, useful to check whether a default value must be applied
/// </summary>
public bool IsLoadedFromStorage { get; internal set; }
/// <summary>
/// Gets the total progress on the timeline
/// </summary>
public TimeSpan TimelineProgress { get; internal set; }
/// <summary> /// <summary>
/// Applies the provided property entity to the layer property by deserializing the JSON base value and keyframe values /// 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
/// <see cref="ApplyToLayerProperty" /> /// <see cref="ApplyToLayerProperty" />
/// </summary> /// </summary>
internal abstract void ApplyToEntity(); internal abstract void ApplyToEntity();
internal abstract List<TimeSpan> GetKeyframePositions();
internal abstract TimeSpan GetLastKeyframePosition();
} }
} }

View File

@ -54,37 +54,11 @@ namespace Artemis.Core.Models.Profile.LayerProperties
internal set => _currentValue = value; internal set => _currentValue = value;
} }
/// <summary>
/// Gets whether keyframes are supported on this property
/// </summary>
public bool KeyframesSupported { get; internal set; }
/// <summary>
/// Gets or sets whether keyframes are enabled on this property, has no effect if <see cref="KeyframesSupported" /> is
/// False
/// </summary>
public bool KeyframesEnabled { get; set; }
/// <summary>
/// Gets or sets whether the property is hidden in the UI
/// </summary>
public bool IsHidden { get; set; }
/// <summary>
/// Indicates whether the BaseValue was loaded from storage, useful to check whether a default value must be applied
/// </summary>
public bool IsLoadedFromStorage { get; internal set; }
/// <summary> /// <summary>
/// Gets a read-only list of all the keyframes on this layer property /// Gets a read-only list of all the keyframes on this layer property
/// </summary> /// </summary>
public IReadOnlyList<LayerPropertyKeyframe<T>> Keyframes => _keyframes.AsReadOnly(); public IReadOnlyList<LayerPropertyKeyframe<T>> Keyframes => _keyframes.AsReadOnly();
/// <summary>
/// Gets the total progress on the timeline
/// </summary>
public TimeSpan TimelineProgress { get; private set; }
/// <summary> /// <summary>
/// Gets the current keyframe in the timeline according to the current progress /// Gets the current keyframe in the timeline according to the current progress
/// </summary> /// </summary>
@ -95,9 +69,6 @@ namespace Artemis.Core.Models.Profile.LayerProperties
/// </summary> /// </summary>
public LayerPropertyKeyframe<T> NextKeyframe { get; protected set; } public LayerPropertyKeyframe<T> NextKeyframe { get; protected set; }
internal PropertyEntity PropertyEntity { get; set; }
internal LayerPropertyGroup LayerPropertyGroup { get; set; }
/// <summary> /// <summary>
/// Adds a keyframe to the layer property /// Adds a keyframe to the layer property
/// </summary> /// </summary>
@ -232,6 +203,16 @@ namespace Artemis.Core.Models.Profile.LayerProperties
})); }));
} }
internal override List<TimeSpan> GetKeyframePositions()
{
return Keyframes.Select(k => k.Position).ToList();
}
internal override TimeSpan GetLastKeyframePosition()
{
return Keyframes.LastOrDefault()?.Position ?? TimeSpan.Zero;
}
#region Events #region Events
public event EventHandler Updated; public event EventHandler Updated;

View File

@ -1,9 +1,10 @@
using Artemis.Core.Exceptions; using System;
using Artemis.Core.Exceptions;
namespace Artemis.Core.Models.Profile.LayerProperties.Types namespace Artemis.Core.Models.Profile.LayerProperties.Types
{ {
/// <inheritdoc/> /// <inheritdoc />
public class EnumLayerProperty<T> : LayerProperty<T> where T : System.Enum public class EnumLayerProperty<T> : LayerProperty<T> where T : Enum
{ {
public EnumLayerProperty() public EnumLayerProperty()
{ {

View File

@ -1,6 +1,9 @@
using System; using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using Artemis.Core.Events; using Artemis.Core.Events;
using Artemis.Core.Exceptions;
using Artemis.Core.Models.Profile.LayerProperties; using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.Core.Models.Profile.LayerProperties.Attributes; using Artemis.Core.Models.Profile.LayerProperties.Attributes;
using Artemis.Core.Plugins.Exceptions; using Artemis.Core.Plugins.Exceptions;
@ -10,6 +13,14 @@ namespace Artemis.Core.Models.Profile
{ {
public class LayerPropertyGroup public class LayerPropertyGroup
{ {
private ReadOnlyCollection<BaseLayerProperty> _allLayerProperties;
protected LayerPropertyGroup()
{
LayerProperties = new List<BaseLayerProperty>();
LayerPropertyGroups = new List<LayerPropertyGroup>();
}
public bool PropertiesInitialized { get; private set; } public bool PropertiesInitialized { get; private set; }
/// <summary> /// <summary>
@ -17,6 +28,16 @@ namespace Artemis.Core.Models.Profile
/// </summary> /// </summary>
internal bool IsCorePropertyGroup { get; set; } internal bool IsCorePropertyGroup { get; set; }
/// <summary>
/// A list of all layer properties in this group
/// </summary>
internal List<BaseLayerProperty> LayerProperties { get; set; }
/// <summary>
/// A list of al child groups in this group
/// </summary>
internal List<LayerPropertyGroup> LayerPropertyGroups { get; set; }
/// <summary> /// <summary>
/// Called when all layer properties in this property group have been initialized /// Called when all layer properties in this property group have been initialized
/// </summary> /// </summary>
@ -26,6 +47,10 @@ namespace Artemis.Core.Models.Profile
internal void InitializeProperties(ILayerService layerService, Layer layer, string path) 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 // Get all properties with a PropertyDescriptionAttribute
foreach (var propertyInfo in GetType().GetProperties()) foreach (var propertyInfo in GetType().GetProperties())
{ {
@ -38,6 +63,7 @@ namespace Artemis.Core.Models.Profile
var instance = (BaseLayerProperty) Activator.CreateInstance(propertyInfo.PropertyType); var instance = (BaseLayerProperty) Activator.CreateInstance(propertyInfo.PropertyType);
InitializeProperty(layer, path, instance); InitializeProperty(layer, path, instance);
propertyInfo.SetValue(this, instance); propertyInfo.SetValue(this, instance);
LayerProperties.Add(instance);
} }
else else
{ {
@ -50,6 +76,7 @@ namespace Artemis.Core.Models.Profile
var instance = (LayerPropertyGroup) Activator.CreateInstance(propertyInfo.PropertyType); var instance = (LayerPropertyGroup) Activator.CreateInstance(propertyInfo.PropertyType);
instance.InitializeProperties(layerService, layer, $"{path}{propertyInfo.Name}."); instance.InitializeProperties(layerService, layer, $"{path}{propertyInfo.Name}.");
propertyInfo.SetValue(this, instance); propertyInfo.SetValue(this, instance);
LayerPropertyGroups.Add(instance);
} }
} }
} }
@ -90,6 +117,25 @@ namespace Artemis.Core.Models.Profile
OnPropertyGroupOverriding(new PropertyGroupUpdatingEventArgs(overrideTime)); OnPropertyGroupOverriding(new PropertyGroupUpdatingEventArgs(overrideTime));
} }
/// <summary>
/// Recursively gets all layer properties on this group and any subgroups
/// </summary>
/// <returns></returns>
internal IReadOnlyCollection<BaseLayerProperty> GetAllLayerProperties()
{
if (!PropertiesInitialized)
return new List<BaseLayerProperty>();
if (_allLayerProperties != null)
return _allLayerProperties;
var result = new List<BaseLayerProperty>(LayerProperties);
foreach (var layerPropertyGroup in LayerPropertyGroups)
result.AddRange(layerPropertyGroup.GetAllLayerProperties());
_allLayerProperties = result.AsReadOnly();
return _allLayerProperties;
}
private void InitializeProperty(Layer layer, string path, BaseLayerProperty instance) private void InitializeProperty(Layer layer, string path, BaseLayerProperty instance)
{ {
var pluginGuid = IsCorePropertyGroup || instance.IsCoreProperty ? Constants.CorePluginInfo.Guid : layer.LayerBrush.PluginInfo.Guid; var pluginGuid = IsCorePropertyGroup || instance.IsCoreProperty ? Constants.CorePluginInfo.Guid : layer.LayerBrush.PluginInfo.Guid;

View File

@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic;
using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.Core.Plugins.Models; using Artemis.Core.Plugins.Models;
using Artemis.Core.Services.Interfaces; using Artemis.Core.Services.Interfaces;
using SkiaSharp; using SkiaSharp;
@ -66,5 +68,14 @@ namespace Artemis.Core.Plugins.LayerBrush
internal virtual void UpdateProperties(double deltaTime) internal virtual void UpdateProperties(double deltaTime)
{ {
} }
internal virtual void OverrideProperties(TimeSpan overrideTime)
{
}
internal virtual IReadOnlyCollection<BaseLayerProperty> GetAllLayerProperties()
{
return new List<BaseLayerProperty>();
}
} }
} }

View File

@ -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.Plugins.Exceptions;
using Artemis.Core.Services.Interfaces; using Artemis.Core.Services.Interfaces;
@ -60,6 +63,16 @@ namespace Artemis.Core.Plugins.LayerBrush
Properties.Update(deltaTime); Properties.Update(deltaTime);
} }
internal override void OverrideProperties(TimeSpan overrideTime)
{
Properties.Override(overrideTime);
}
internal override IReadOnlyCollection<BaseLayerProperty> GetAllLayerProperties()
{
return Properties.GetAllLayerProperties();
}
#endregion #endregion
} }
} }