1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Brush presets - Reset properties to default before applying preset

Layer properties - Disable keyframes when resetting to default
Device dialogs - Only dim unselected LEDs if a LED is selected
Migrations - Renamed to stay in order 
Migrations - Added migration for color gradients
This commit is contained in:
Robert 2021-04-06 20:56:18 +02:00
parent 2bc882c814
commit 60df649eb0
22 changed files with 376 additions and 319 deletions

View File

@ -59,6 +59,11 @@ namespace Artemis.Core
/// <returns>If succeeded the resulting keyframe, otherwise <see langword="null" /></returns> /// <returns>If succeeded the resulting keyframe, otherwise <see langword="null" /></returns>
ILayerPropertyKeyframe? AddKeyframeEntity(KeyframeEntity keyframeEntity); ILayerPropertyKeyframe? AddKeyframeEntity(KeyframeEntity keyframeEntity);
/// <summary>
/// Overrides the property value with the default value
/// </summary>
void ApplyDefaultValue();
/// <summary> /// <summary>
/// Updates the layer properties internal state /// Updates the layer properties internal state
/// </summary> /// </summary>

View File

@ -2,7 +2,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Linq.Expressions;
using Artemis.Storage.Entities.Profile; using Artemis.Storage.Entities.Profile;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -39,6 +38,107 @@ namespace Artemis.Core
_keyframes = new List<LayerPropertyKeyframe<T>>(); _keyframes = new List<LayerPropertyKeyframe<T>>();
} }
/// <summary>
/// Releases the unmanaged resources used by the object and optionally releases the managed resources.
/// </summary>
/// <param name="disposing">
/// <see langword="true" /> to release both managed and unmanaged resources;
/// <see langword="false" /> to release only unmanaged resources.
/// </param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_disposed = true;
foreach (IDataBinding dataBinding in _dataBindings)
dataBinding.Dispose();
Disposed?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Invokes the <see cref="Updated" /> event
/// </summary>
protected virtual void OnUpdated()
{
Updated?.Invoke(this, new LayerPropertyEventArgs(this));
}
/// <summary>
/// Invokes the <see cref="CurrentValueSet" /> event
/// </summary>
protected virtual void OnCurrentValueSet()
{
CurrentValueSet?.Invoke(this, new LayerPropertyEventArgs(this));
LayerPropertyGroup.OnLayerPropertyOnCurrentValueSet(new LayerPropertyEventArgs(this));
}
/// <summary>
/// Invokes the <see cref="VisibilityChanged" /> event
/// </summary>
protected virtual void OnVisibilityChanged()
{
VisibilityChanged?.Invoke(this, new LayerPropertyEventArgs(this));
}
/// <summary>
/// Invokes the <see cref="KeyframesToggled" /> event
/// </summary>
protected virtual void OnKeyframesToggled()
{
KeyframesToggled?.Invoke(this, new LayerPropertyEventArgs(this));
}
/// <summary>
/// Invokes the <see cref="KeyframeAdded" /> event
/// </summary>
protected virtual void OnKeyframeAdded()
{
KeyframeAdded?.Invoke(this, new LayerPropertyEventArgs(this));
}
/// <summary>
/// Invokes the <see cref="KeyframeRemoved" /> event
/// </summary>
protected virtual void OnKeyframeRemoved()
{
KeyframeRemoved?.Invoke(this, new LayerPropertyEventArgs(this));
}
/// <summary>
/// Invokes the <see cref="DataBindingPropertyRegistered" /> event
/// </summary>
protected virtual void OnDataBindingPropertyRegistered()
{
DataBindingPropertyRegistered?.Invoke(this, new LayerPropertyEventArgs(this));
}
/// <summary>
/// Invokes the <see cref="DataBindingDisabled" /> event
/// </summary>
protected virtual void OnDataBindingPropertiesCleared()
{
DataBindingPropertiesCleared?.Invoke(this, new LayerPropertyEventArgs(this));
}
/// <summary>
/// Invokes the <see cref="DataBindingEnabled" /> event
/// </summary>
protected virtual void OnDataBindingEnabled(LayerPropertyEventArgs e)
{
DataBindingEnabled?.Invoke(this, e);
}
/// <summary>
/// Invokes the <see cref="DataBindingDisabled" /> event
/// </summary>
protected virtual void OnDataBindingDisabled(LayerPropertyEventArgs e)
{
DataBindingDisabled?.Invoke(this, e);
}
/// <inheritdoc /> /// <inheritdoc />
public PropertyDescriptionAttribute PropertyDescription { get; internal set; } public PropertyDescriptionAttribute PropertyDescription { get; internal set; }
@ -62,28 +162,6 @@ namespace Artemis.Core
OnUpdated(); OnUpdated();
} }
#region IDisposable
/// <summary>
/// Releases the unmanaged resources used by the object and optionally releases the managed resources.
/// </summary>
/// <param name="disposing">
/// <see langword="true" /> to release both managed and unmanaged resources;
/// <see langword="false" /> to release only unmanaged resources.
/// </param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_disposed = true;
foreach (IDataBinding dataBinding in _dataBindings)
dataBinding.Dispose();
Disposed?.Invoke(this, EventArgs.Empty);
}
}
/// <inheritdoc /> /// <inheritdoc />
public void Dispose() public void Dispose()
{ {
@ -91,7 +169,38 @@ namespace Artemis.Core
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
#endregion /// <inheritdoc />
public event EventHandler? Disposed;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? Updated;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? CurrentValueSet;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? VisibilityChanged;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? KeyframesToggled;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? KeyframeAdded;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? KeyframeRemoved;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? DataBindingPropertyRegistered;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? DataBindingPropertiesCleared;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? DataBindingEnabled;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? DataBindingDisabled;
#region Hierarchy #region Hierarchy
@ -195,22 +304,25 @@ namespace Artemis.Core
ReapplyUpdate(); ReapplyUpdate();
} }
/// <summary> /// <inheritdoc />
/// Overrides the property value with the default value public void ApplyDefaultValue()
/// </summary>
public void ApplyDefaultValue(TimeSpan? time)
{ {
if (_disposed) if (_disposed)
throw new ObjectDisposedException("LayerProperty"); throw new ObjectDisposedException("LayerProperty");
string json = CoreJson.SerializeObject(DefaultValue, true); string json = CoreJson.SerializeObject(DefaultValue, true);
SetCurrentValue(CoreJson.DeserializeObject<T>(json)!, time); KeyframesEnabled = false;
SetCurrentValue(CoreJson.DeserializeObject<T>(json)!, null);
} }
private void ReapplyUpdate() private void ReapplyUpdate()
{ {
ProfileElement.Timeline.ClearDelta(); // Create a timeline with the same position but a delta of zero
Update(ProfileElement.Timeline); Timeline temporaryTimeline = new();
temporaryTimeline.Override(ProfileElement.Timeline.Position, false);
temporaryTimeline.ClearDelta();
Update(temporaryTimeline);
OnCurrentValueSet(); OnCurrentValueSet();
} }
@ -440,10 +552,10 @@ namespace Artemis.Core
if (_disposed) if (_disposed)
throw new ObjectDisposedException("LayerProperty"); throw new ObjectDisposedException("LayerProperty");
foreach (IDataBindingRegistration dataBindingRegistration in _dataBindingRegistrations) foreach (IDataBindingRegistration dataBindingRegistration in _dataBindingRegistrations)
dataBindingRegistration.ClearDataBinding(); dataBindingRegistration.ClearDataBinding();
_dataBindingRegistrations.Clear(); _dataBindingRegistrations.Clear();
OnDataBindingPropertiesCleared(); OnDataBindingPropertiesCleared();
} }
@ -593,7 +705,7 @@ namespace Artemis.Core
throw new ArtemisCoreException("Layer property is not yet initialized"); throw new ArtemisCoreException("Layer property is not yet initialized");
if (!IsLoadedFromStorage) if (!IsLoadedFromStorage)
ApplyDefaultValue(null); ApplyDefaultValue();
else else
try try
{ {
@ -657,123 +769,5 @@ namespace Artemis.Core
} }
#endregion #endregion
#region Events
/// <inheritdoc />
public event EventHandler? Disposed;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? Updated;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? CurrentValueSet;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? VisibilityChanged;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? KeyframesToggled;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? KeyframeAdded;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? KeyframeRemoved;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? DataBindingPropertyRegistered;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? DataBindingPropertiesCleared;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? DataBindingEnabled;
/// <inheritdoc />
public event EventHandler<LayerPropertyEventArgs>? DataBindingDisabled;
/// <summary>
/// Invokes the <see cref="Updated" /> event
/// </summary>
protected virtual void OnUpdated()
{
Updated?.Invoke(this, new LayerPropertyEventArgs(this));
}
/// <summary>
/// Invokes the <see cref="CurrentValueSet" /> event
/// </summary>
protected virtual void OnCurrentValueSet()
{
CurrentValueSet?.Invoke(this, new LayerPropertyEventArgs(this));
LayerPropertyGroup.OnLayerPropertyOnCurrentValueSet(new LayerPropertyEventArgs(this));
}
/// <summary>
/// Invokes the <see cref="VisibilityChanged" /> event
/// </summary>
protected virtual void OnVisibilityChanged()
{
VisibilityChanged?.Invoke(this, new LayerPropertyEventArgs(this));
}
/// <summary>
/// Invokes the <see cref="KeyframesToggled" /> event
/// </summary>
protected virtual void OnKeyframesToggled()
{
KeyframesToggled?.Invoke(this, new LayerPropertyEventArgs(this));
}
/// <summary>
/// Invokes the <see cref="KeyframeAdded" /> event
/// </summary>
protected virtual void OnKeyframeAdded()
{
KeyframeAdded?.Invoke(this, new LayerPropertyEventArgs(this));
}
/// <summary>
/// Invokes the <see cref="KeyframeRemoved" /> event
/// </summary>
protected virtual void OnKeyframeRemoved()
{
KeyframeRemoved?.Invoke(this, new LayerPropertyEventArgs(this));
}
/// <summary>
/// Invokes the <see cref="DataBindingPropertyRegistered" /> event
/// </summary>
protected virtual void OnDataBindingPropertyRegistered()
{
DataBindingPropertyRegistered?.Invoke(this, new LayerPropertyEventArgs(this));
}
/// <summary>
/// Invokes the <see cref="DataBindingDisabled" /> event
/// </summary>
protected virtual void OnDataBindingPropertiesCleared()
{
DataBindingPropertiesCleared?.Invoke(this, new LayerPropertyEventArgs(this));
}
/// <summary>
/// Invokes the <see cref="DataBindingEnabled" /> event
/// </summary>
protected virtual void OnDataBindingEnabled(LayerPropertyEventArgs e)
{
DataBindingEnabled?.Invoke(this, e);
}
/// <summary>
/// Invokes the <see cref="DataBindingDisabled" /> event
/// </summary>
protected virtual void OnDataBindingDisabled(LayerPropertyEventArgs e)
{
DataBindingDisabled?.Invoke(this, e);
}
#endregion
} }
} }

View File

@ -121,6 +121,31 @@ namespace Artemis.Core
return result.AsReadOnly(); return result.AsReadOnly();
} }
/// <summary>
/// Applies the default value to all layer properties
/// </summary>
public void ResetAllLayerProperties()
{
foreach (ILayerProperty layerProperty in GetAllLayerProperties())
layerProperty.ApplyDefaultValue();
}
/// <summary>
/// Occurs when the property group has initialized all its children
/// </summary>
public event EventHandler? PropertyGroupInitialized;
/// <summary>
/// Occurs when one of the current value of one of the layer properties in this group changes by some form of input
/// <para>Note: Will not trigger on properties in child groups</para>
/// </summary>
public event EventHandler<LayerPropertyEventArgs>? LayerPropertyOnCurrentValueSet;
/// <summary>
/// Occurs when the <see cref="IsHidden" /> value of the layer property was updated
/// </summary>
public event EventHandler? VisibilityChanged;
/// <summary> /// <summary>
/// Called before property group is activated to allow you to populate <see cref="LayerProperty{T}.DefaultValue" /> on /// Called before property group is activated to allow you to populate <see cref="LayerProperty{T}.DefaultValue" /> on
/// the properties you want /// the properties you want
@ -145,6 +170,27 @@ namespace Artemis.Core
PropertyGroupInitialized?.Invoke(this, EventArgs.Empty); PropertyGroupInitialized?.Invoke(this, EventArgs.Empty);
} }
/// <summary>
/// Releases the unmanaged resources used by the object and optionally releases the managed resources.
/// </summary>
/// <param name="disposing">
/// <see langword="true" /> to release both managed and unmanaged resources;
/// <see langword="false" /> to release only unmanaged resources.
/// </param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_disposed = true;
DisableProperties();
foreach (ILayerProperty layerProperty in _layerProperties)
layerProperty.Dispose();
foreach (LayerPropertyGroup layerPropertyGroup in _layerPropertyGroups)
layerPropertyGroup.Dispose();
}
}
internal void Initialize(RenderProfileElement profileElement, string path, PluginFeature feature) internal void Initialize(RenderProfileElement profileElement, string path, PluginFeature feature)
{ {
if (path == null) throw new ArgumentNullException(nameof(path)); if (path == null) throw new ArgumentNullException(nameof(path));
@ -209,6 +255,17 @@ namespace Artemis.Core
layerPropertyGroup.Update(timeline); layerPropertyGroup.Update(timeline);
} }
internal virtual void OnVisibilityChanged()
{
VisibilityChanged?.Invoke(this, EventArgs.Empty);
}
internal virtual void OnLayerPropertyOnCurrentValueSet(LayerPropertyEventArgs e)
{
Parent?.OnLayerPropertyOnCurrentValueSet(e);
LayerPropertyOnCurrentValueSet?.Invoke(this, e);
}
private void InitializeProperty(PropertyInfo propertyInfo, PropertyDescriptionAttribute propertyDescription) private void InitializeProperty(PropertyInfo propertyInfo, PropertyDescriptionAttribute propertyDescription)
{ {
string path = $"{Path}.{propertyInfo.Name}"; string path = $"{Path}.{propertyInfo.Name}";
@ -266,67 +323,11 @@ namespace Artemis.Core
return entity; return entity;
} }
#region IDisposable
/// <summary>
/// Releases the unmanaged resources used by the object and optionally releases the managed resources.
/// </summary>
/// <param name="disposing">
/// <see langword="true" /> to release both managed and unmanaged resources;
/// <see langword="false" /> to release only unmanaged resources.
/// </param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_disposed = true;
DisableProperties();
foreach (ILayerProperty layerProperty in _layerProperties)
layerProperty.Dispose();
foreach (LayerPropertyGroup layerPropertyGroup in _layerPropertyGroups)
layerPropertyGroup.Dispose();
}
}
/// <inheritdoc /> /// <inheritdoc />
public void Dispose() public void Dispose()
{ {
Dispose(true); Dispose(true);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
#endregion
#region Events
/// <summary>
/// Occurs when the property group has initialized all its children
/// </summary>
public event EventHandler? PropertyGroupInitialized;
/// <summary>
/// Occurs when one of the current value of one of the layer properties in this group changes by some form of input
/// <para>Note: Will not trigger on properties in child groups</para>
/// </summary>
public event EventHandler<LayerPropertyEventArgs>? LayerPropertyOnCurrentValueSet;
/// <summary>
/// Occurs when the <see cref="IsHidden" /> value of the layer property was updated
/// </summary>
public event EventHandler? VisibilityChanged;
internal virtual void OnVisibilityChanged()
{
VisibilityChanged?.Invoke(this, EventArgs.Empty);
}
internal virtual void OnLayerPropertyOnCurrentValueSet(LayerPropertyEventArgs e)
{
Parent?.OnLayerPropertyOnCurrentValueSet(e);
LayerPropertyOnCurrentValueSet?.Invoke(this, e);
}
#endregion
} }
} }

View File

@ -292,7 +292,7 @@
"$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage", "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
"FeatureId": null, "FeatureId": null,
"Path": "LayerBrush.GradientColor", "Path": "LayerBrush.GradientColor",
"Value": "{\"Stops\":[{\"Color\":\"#ff0b4a40\",\"Position\":0.0},{\"Color\":\"#ff00897c\",\"Position\":0.242},{\"Color\":\"#ffffffff\",\"Position\":1.0},{\"Color\":\"#ff00ffe6\",\"Position\":0.67391306}]}", "Value": "[{\"Color\":\"#ff0b4a40\",\"Position\":0.0},{\"Color\":\"#ff00897c\",\"Position\":0.242},{\"Color\":\"#ffffffff\",\"Position\":1.0},{\"Color\":\"#ff00ffe6\",\"Position\":0.67391306}]",
"KeyframesEnabled": false, "KeyframesEnabled": false,
"KeyframeEntities": { "KeyframeEntities": {
"$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib", "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
@ -592,7 +592,7 @@
"$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage", "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
"FeatureId": "Artemis.Plugins.LayerBrushes.Noise.NoiseBrushProvider-61cbbf01", "FeatureId": "Artemis.Plugins.LayerBrushes.Noise.NoiseBrushProvider-61cbbf01",
"Path": "LayerBrush.GradientColor", "Path": "LayerBrush.GradientColor",
"Value": "{\"Stops\":[{\"Color\":\"#ffff0000\",\"Position\":0.0},{\"Color\":\"#ffffbf00\",\"Position\":0.125},{\"Color\":\"#ff7fff00\",\"Position\":0.25},{\"Color\":\"#ff00ff3f\",\"Position\":0.375},{\"Color\":\"#ff00ffff\",\"Position\":0.5},{\"Color\":\"#ff003fff\",\"Position\":0.625},{\"Color\":\"#ff7f00ff\",\"Position\":0.75},{\"Color\":\"#ffff00bf\",\"Position\":0.875},{\"Color\":\"#ffff0000\",\"Position\":1.0}]}", "Value": "[{\"Color\":\"#ffff0000\",\"Position\":0.0},{\"Color\":\"#ffffbf00\",\"Position\":0.125},{\"Color\":\"#ff7fff00\",\"Position\":0.25},{\"Color\":\"#ff00ff3f\",\"Position\":0.375},{\"Color\":\"#ff00ffff\",\"Position\":0.5},{\"Color\":\"#ff003fff\",\"Position\":0.625},{\"Color\":\"#ff7f00ff\",\"Position\":0.75},{\"Color\":\"#ffff00bf\",\"Position\":0.875},{\"Color\":\"#ffff0000\",\"Position\":1.0}]",
"KeyframesEnabled": false, "KeyframesEnabled": false,
"KeyframeEntities": { "KeyframeEntities": {
"$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib", "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
@ -909,7 +909,7 @@
"$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage", "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
"FeatureId": null, "FeatureId": null,
"Path": "LayerBrush.Colors", "Path": "LayerBrush.Colors",
"Value": "{\"Stops\":[{\"Color\":\"#00ff0000\",\"Position\":0.0},{\"Color\":\"#ffffdf00\",\"Position\":0.916},{\"Color\":\"#00ffcd00\",\"Position\":1.0},{\"Color\":\"#fff31900\",\"Position\":0.636},{\"Color\":\"#dbf41500\",\"Position\":0.5461956},{\"Color\":\"#00f60f00\",\"Position\":0.462},{\"Color\":\"#93f60d00\",\"Position\":0.3668478}]}", "Value": "[{\"Color\":\"#00ff0000\",\"Position\":0.0},{\"Color\":\"#ffffdf00\",\"Position\":0.916},{\"Color\":\"#00ffcd00\",\"Position\":1.0},{\"Color\":\"#fff31900\",\"Position\":0.636},{\"Color\":\"#dbf41500\",\"Position\":0.5461956},{\"Color\":\"#00f60f00\",\"Position\":0.462},{\"Color\":\"#93f60d00\",\"Position\":0.3668478}]",
"KeyframesEnabled": false, "KeyframesEnabled": false,
"KeyframeEntities": { "KeyframeEntities": {
"$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib", "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
@ -1164,7 +1164,7 @@
"$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage", "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
"FeatureId": "Artemis.Plugins.LayerBrushes.Color.ColorBrushProvider-92a9d6ba", "FeatureId": "Artemis.Plugins.LayerBrushes.Color.ColorBrushProvider-92a9d6ba",
"Path": "LayerBrush.Colors", "Path": "LayerBrush.Colors",
"Value": "{\"Stops\":[{\"Color\":\"#ffcaff00\",\"Position\":0.709},{\"Color\":\"#ffff0000\",\"Position\":0.902},{\"Color\":\"#ffffffff\",\"Position\":0.5842391},{\"Color\":\"#ffff4100\",\"Position\":0.95108694},{\"Color\":\"#00ff4100\",\"Position\":0.98641306}]}", "Value": "[{\"Color\":\"#ffcaff00\",\"Position\":0.709},{\"Color\":\"#ffff0000\",\"Position\":0.902},{\"Color\":\"#ffffffff\",\"Position\":0.5842391},{\"Color\":\"#ffff4100\",\"Position\":0.95108694},{\"Color\":\"#00ff4100\",\"Position\":0.98641306}]",
"KeyframesEnabled": false, "KeyframesEnabled": false,
"KeyframeEntities": { "KeyframeEntities": {
"$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib", "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
@ -1496,7 +1496,7 @@
"$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage", "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
"FeatureId": null, "FeatureId": null,
"Path": "LayerBrush.Colors", "Path": "LayerBrush.Colors",
"Value": "{\"Stops\":[{\"Color\":\"#ffff0000\",\"Position\":0.0},{\"Color\":\"#ffff8800\",\"Position\":0.125},{\"Color\":\"#ffedff00\",\"Position\":0.25},{\"Color\":\"#ff65ff00\",\"Position\":0.375},{\"Color\":\"#ff00ff22\",\"Position\":0.5},{\"Color\":\"#ff00ffaa\",\"Position\":0.625},{\"Color\":\"#ff00cbff\",\"Position\":0.75},{\"Color\":\"#ff0043ff\",\"Position\":0.875},{\"Color\":\"#ffff0000\",\"Position\":1.0}]}", "Value": "[{\"Color\":\"#ffff0000\",\"Position\":0.0},{\"Color\":\"#ffff8800\",\"Position\":0.125},{\"Color\":\"#ffedff00\",\"Position\":0.25},{\"Color\":\"#ff65ff00\",\"Position\":0.375},{\"Color\":\"#ff00ff22\",\"Position\":0.5},{\"Color\":\"#ff00ffaa\",\"Position\":0.625},{\"Color\":\"#ff00cbff\",\"Position\":0.75},{\"Color\":\"#ff0043ff\",\"Position\":0.875},{\"Color\":\"#ffff0000\",\"Position\":1.0}]",
"KeyframesEnabled": false, "KeyframesEnabled": false,
"KeyframeEntities": { "KeyframeEntities": {
"$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib", "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
@ -1751,7 +1751,7 @@
"$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage", "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
"FeatureId": "Artemis.Plugins.LayerBrushes.Color.ColorBrushProvider-92a9d6ba", "FeatureId": "Artemis.Plugins.LayerBrushes.Color.ColorBrushProvider-92a9d6ba",
"Path": "LayerBrush.Colors", "Path": "LayerBrush.Colors",
"Value": "{\"Stops\":[{\"Color\":\"#ffff0000\",\"Position\":0.0},{\"Color\":\"#ffffbf00\",\"Position\":0.125},{\"Color\":\"#ff7fff00\",\"Position\":0.25},{\"Color\":\"#ff00ff3f\",\"Position\":0.375},{\"Color\":\"#ff00ffff\",\"Position\":0.5},{\"Color\":\"#ff003fff\",\"Position\":0.625},{\"Color\":\"#ff7f00ff\",\"Position\":0.75},{\"Color\":\"#ffff00bf\",\"Position\":0.875},{\"Color\":\"#ffff0000\",\"Position\":1.0}]}", "Value": "[{\"Color\":\"#ffff0000\",\"Position\":0.0},{\"Color\":\"#ffffbf00\",\"Position\":0.125},{\"Color\":\"#ff7fff00\",\"Position\":0.25},{\"Color\":\"#ff00ff3f\",\"Position\":0.375},{\"Color\":\"#ff00ffff\",\"Position\":0.5},{\"Color\":\"#ff003fff\",\"Position\":0.625},{\"Color\":\"#ff7f00ff\",\"Position\":0.75},{\"Color\":\"#ffff00bf\",\"Position\":0.875},{\"Color\":\"#ffff0000\",\"Position\":1.0}]",
"KeyframesEnabled": false, "KeyframesEnabled": false,
"KeyframeEntities": { "KeyframeEntities": {
"$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib", "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",

View File

@ -251,20 +251,16 @@ namespace Artemis.Core.Services
// Draw a white overlay over the device // Draw a white overlay over the device
void DrawOverlay(object? sender, FrameRenderingEventArgs args) void DrawOverlay(object? sender, FrameRenderingEventArgs args)
{ {
if (intro.AnimationProfile.GetAllLayers().All(l => l.Timeline.IsFinished))
{
FrameRendering -= DrawOverlay;
intro.AnimationProfile.Dispose();
}
intro.Render(args.DeltaTime, args.Canvas); intro.Render(args.DeltaTime, args.Canvas);
} }
FrameRendering += DrawOverlay; FrameRendering += DrawOverlay;
// Stop rendering after the profile finishes (take 1 second extra in case of slow updates)
TimeSpan introLength = intro.AnimationProfile.GetAllLayers().Max(l => l.Timeline.Length)!;
Task.Run(async () =>
{
await Task.Delay(introLength.Add(TimeSpan.FromSeconds(1)));
FrameRendering -= DrawOverlay;
intro.AnimationProfile.Dispose();
});
} }
public event EventHandler? Initialized; public event EventHandler? Initialized;

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Artemis.Core.Modules; using Artemis.Core.Modules;

View File

@ -3,7 +3,7 @@ using LiteDB;
namespace Artemis.Storage.Migrations namespace Artemis.Storage.Migrations
{ {
public class M1AttributeBasedPropertiesMigration : IStorageMigration public class M0001AttributeBasedPropertiesMigration : IStorageMigration
{ {
public int UserVersion => 1; public int UserVersion => 1;

View File

@ -5,7 +5,7 @@ using LiteDB;
namespace Artemis.Storage.Migrations namespace Artemis.Storage.Migrations
{ {
public class M2ProfileEntitiesEnabledMigration : IStorageMigration public class M0002ProfileEntitiesEnabledMigration : IStorageMigration
{ {
public int UserVersion => 2; public int UserVersion => 2;

View File

@ -3,7 +3,7 @@ using LiteDB;
namespace Artemis.Storage.Migrations namespace Artemis.Storage.Migrations
{ {
public class M3PluginEntitiesIndexChangesMigration : IStorageMigration public class M0003PluginEntitiesIndexChangesMigration : IStorageMigration
{ {
public int UserVersion => 3; public int UserVersion => 3;

View File

@ -7,7 +7,7 @@ using System.Linq;
namespace Artemis.Storage.Migrations namespace Artemis.Storage.Migrations
{ {
public class M4ProfileSegmentsMigration : IStorageMigration public class M0004ProfileSegmentsMigration : IStorageMigration
{ {
public int UserVersion => 4; public int UserVersion => 4;

View File

@ -3,7 +3,7 @@ using LiteDB;
namespace Artemis.Storage.Migrations namespace Artemis.Storage.Migrations
{ {
public class M5DataBindingTypes : IStorageMigration public class M0005DataBindingTypes : IStorageMigration
{ {
public int UserVersion => 5; public int UserVersion => 5;

View File

@ -4,7 +4,7 @@ using LiteDB;
namespace Artemis.Storage.Migrations namespace Artemis.Storage.Migrations
{ {
public class M6PredicateAbstraction : IStorageMigration public class M0006PredicateAbstraction : IStorageMigration
{ {
public int UserVersion => 6; public int UserVersion => 6;

View File

@ -5,7 +5,7 @@ using LiteDB;
namespace Artemis.Storage.Migrations namespace Artemis.Storage.Migrations
{ {
public class M8PluginFeatures : IStorageMigration public class M0008PluginFeatures : IStorageMigration
{ {
private void Migrate(BsonValue bsonValue, Dictionary<string, string> pluginMap) private void Migrate(BsonValue bsonValue, Dictionary<string, string> pluginMap)
{ {

View File

@ -3,7 +3,7 @@ using LiteDB;
namespace Artemis.Storage.Migrations namespace Artemis.Storage.Migrations
{ {
public class M9DeviceCalibration : IStorageMigration public class M0009DeviceCalibration : IStorageMigration
{ {
public int UserVersion => 9; public int UserVersion => 9;

View File

@ -3,7 +3,7 @@ using LiteDB;
namespace Artemis.Storage.Migrations namespace Artemis.Storage.Migrations
{ {
public class M10BetterDataBindings : IStorageMigration public class M0010BetterDataBindings : IStorageMigration
{ {
private void Migrate(BsonValue bsonValue) private void Migrate(BsonValue bsonValue)
{ {

View File

@ -0,0 +1,42 @@
using Artemis.Storage.Migrations.Interfaces;
using LiteDB;
namespace Artemis.Storage.Migrations
{
public class M0011ColorGradients : IStorageMigration
{
private void Migrate(BsonValue bsonValue)
{
if (!bsonValue.IsDocument || !bsonValue.AsDocument.TryGetValue("PropertyEntities", out BsonValue propertyEntities))
return;
foreach (BsonValue propertyEntity in propertyEntities.AsArray)
{
string valueString = propertyEntity["Value"].AsString;
if (!valueString.StartsWith("{\"Stops\":[{") || !valueString.EndsWith("}]}"))
continue;
valueString = valueString.Replace("{\"Stops\":[{", "[{");
valueString = valueString.Replace("}]}", "}]");
propertyEntity["Value"] = valueString;
}
}
public int UserVersion => 11;
public void Apply(LiteRepository repository)
{
ILiteCollection<BsonDocument> collection = repository.Database.GetCollection("ProfileEntity");
foreach (BsonDocument bsonDocument in collection.FindAll())
{
foreach (BsonValue bsonLayer in bsonDocument["Layers"].AsArray)
Migrate(bsonLayer);
foreach (BsonValue bsonLayer in bsonDocument["Folders"].AsArray)
Migrate(bsonLayer);
collection.Update(bsonDocument);
}
}
}
}

View File

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Controls.Primitives;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.Modules; using Artemis.Core.Modules;
using Artemis.Core.Services; using Artemis.Core.Services;
@ -20,7 +19,6 @@ namespace Artemis.UI.Shared.Services
{ {
internal class ProfileEditorService : IProfileEditorService internal class ProfileEditorService : IProfileEditorService
{ {
private readonly ICoreService _coreService;
private readonly IKernel _kernel; private readonly IKernel _kernel;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IProfileService _profileService; private readonly IProfileService _profileService;
@ -29,6 +27,7 @@ namespace Artemis.UI.Shared.Services
private readonly object _selectedProfileElementLock = new(); private readonly object _selectedProfileElementLock = new();
private readonly object _selectedProfileLock = new(); private readonly object _selectedProfileLock = new();
private TimeSpan _currentTime; private TimeSpan _currentTime;
private bool _doTick;
private int _pixelsPerSecond; private int _pixelsPerSecond;
public ProfileEditorService(IKernel kernel, ILogger logger, IProfileService profileService, ICoreService coreService, IRgbService rgbService) public ProfileEditorService(IKernel kernel, ILogger logger, IProfileService profileService, ICoreService coreService, IRgbService rgbService)
@ -36,16 +35,63 @@ namespace Artemis.UI.Shared.Services
_kernel = kernel; _kernel = kernel;
_logger = logger; _logger = logger;
_profileService = profileService; _profileService = profileService;
_coreService = coreService;
_rgbService = rgbService; _rgbService = rgbService;
_registeredPropertyEditors = new List<PropertyInputRegistration>(); _registeredPropertyEditors = new List<PropertyInputRegistration>();
coreService.FrameRendered += CoreServiceOnFrameRendered;
PixelsPerSecond = 100; PixelsPerSecond = 100;
} }
public event EventHandler? CurrentTimelineChanged;
protected virtual void OnSelectedProfileChanged(ProfileEventArgs e)
{
ProfileSelected?.Invoke(this, e);
}
protected virtual void OnSelectedProfileUpdated(ProfileEventArgs e)
{
SelectedProfileUpdated?.Invoke(this, e);
}
protected virtual void OnSelectedProfileElementChanged(RenderProfileElementEventArgs e)
{
ProfileElementSelected?.Invoke(this, e);
}
protected virtual void OnSelectedProfileElementUpdated(RenderProfileElementEventArgs e)
{
SelectedProfileElementUpdated?.Invoke(this, e);
}
protected virtual void OnCurrentTimeChanged()
{
CurrentTimeChanged?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnCurrentTimelineChanged()
{
CurrentTimelineChanged?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnPixelsPerSecondChanged()
{
PixelsPerSecondChanged?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnProfilePreviewUpdated()
{
ProfilePreviewUpdated?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnSelectedDataBindingChanged()
{
SelectedDataBindingChanged?.Invoke(this, EventArgs.Empty);
}
private void CoreServiceOnFrameRendered(object? sender, FrameRenderedEventArgs e) private void CoreServiceOnFrameRendered(object? sender, FrameRenderedEventArgs e)
{ {
_coreService.FrameRendered -= CoreServiceOnFrameRendered; if (!_doTick) return;
_doTick = false;
Execute.PostToUIThread(OnProfilePreviewUpdated); Execute.PostToUIThread(OnProfilePreviewUpdated);
} }
@ -73,6 +119,26 @@ namespace Artemis.UI.Shared.Services
UpdateProfilePreview(); UpdateProfilePreview();
} }
private void Tick()
{
if (SelectedProfile == null || _doTick)
return;
// Stick to the main segment for any element that is not currently selected
foreach (Folder folder in SelectedProfile.GetAllFolders())
folder.Timeline.Override(CurrentTime, folder.Timeline.PlayMode == TimelinePlayMode.Repeat);
foreach (Layer layer in SelectedProfile.GetAllLayers())
layer.Timeline.Override(CurrentTime, (layer != SelectedProfileElement || layer.Timeline.Length < CurrentTime) && layer.Timeline.PlayMode == TimelinePlayMode.Repeat);
_doTick = true;
}
private void SelectedProfileOnDeactivated(object? sender, EventArgs e)
{
// Execute.PostToUIThread(() => ChangeSelectedProfile(null));
ChangeSelectedProfile(null);
}
public ReadOnlyCollection<PropertyInputRegistration> RegisteredPropertyEditors => _registeredPropertyEditors.AsReadOnly(); public ReadOnlyCollection<PropertyInputRegistration> RegisteredPropertyEditors => _registeredPropertyEditors.AsReadOnly();
public bool Playing { get; set; } public bool Playing { get; set; }
@ -351,19 +417,14 @@ namespace Artemis.UI.Shared.Services
.ToList(); .ToList();
} }
private void Tick() public event EventHandler<ProfileEventArgs>? ProfileSelected;
{ public event EventHandler<ProfileEventArgs>? SelectedProfileUpdated;
if (SelectedProfile == null) public event EventHandler<RenderProfileElementEventArgs>? ProfileElementSelected;
return; public event EventHandler<RenderProfileElementEventArgs>? SelectedProfileElementUpdated;
public event EventHandler? SelectedDataBindingChanged;
// Stick to the main segment for any element that is not currently selected public event EventHandler? CurrentTimeChanged;
foreach (Folder folder in SelectedProfile.GetAllFolders()) public event EventHandler? PixelsPerSecondChanged;
folder.Timeline.Override(CurrentTime, folder.Timeline.PlayMode == TimelinePlayMode.Repeat); public event EventHandler? ProfilePreviewUpdated;
foreach (Layer layer in SelectedProfile.GetAllLayers())
layer.Timeline.Override(CurrentTime, (layer != SelectedProfileElement || layer.Timeline.Length < CurrentTime) && layer.Timeline.PlayMode == TimelinePlayMode.Repeat);
_coreService.FrameRendered += CoreServiceOnFrameRendered;
}
#region Copy/paste #region Copy/paste
@ -444,70 +505,5 @@ namespace Artemis.UI.Shared.Services
} }
#endregion #endregion
#region Events
public event EventHandler<ProfileEventArgs>? ProfileSelected;
public event EventHandler<ProfileEventArgs>? SelectedProfileUpdated;
public event EventHandler<RenderProfileElementEventArgs>? ProfileElementSelected;
public event EventHandler<RenderProfileElementEventArgs>? SelectedProfileElementUpdated;
public event EventHandler? SelectedDataBindingChanged;
public event EventHandler? CurrentTimeChanged;
public event EventHandler? PixelsPerSecondChanged;
public event EventHandler? ProfilePreviewUpdated;
public event EventHandler? CurrentTimelineChanged;
protected virtual void OnSelectedProfileChanged(ProfileEventArgs e)
{
ProfileSelected?.Invoke(this, e);
}
protected virtual void OnSelectedProfileUpdated(ProfileEventArgs e)
{
SelectedProfileUpdated?.Invoke(this, e);
}
protected virtual void OnSelectedProfileElementChanged(RenderProfileElementEventArgs e)
{
ProfileElementSelected?.Invoke(this, e);
}
protected virtual void OnSelectedProfileElementUpdated(RenderProfileElementEventArgs e)
{
SelectedProfileElementUpdated?.Invoke(this, e);
}
protected virtual void OnCurrentTimeChanged()
{
CurrentTimeChanged?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnCurrentTimelineChanged()
{
CurrentTimelineChanged?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnPixelsPerSecondChanged()
{
PixelsPerSecondChanged?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnProfilePreviewUpdated()
{
ProfilePreviewUpdated?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnSelectedDataBindingChanged()
{
SelectedDataBindingChanged?.Invoke(this, EventArgs.Empty);
}
private void SelectedProfileOnDeactivated(object? sender, EventArgs e)
{
// Execute.PostToUIThread(() => ChangeSelectedProfile(null));
ChangeSelectedProfile(null);
}
#endregion
} }
} }

View File

@ -7,10 +7,12 @@ namespace Artemis.UI.Screens.ProfileEditor.Dialogs
{ {
public class LayerBrushPresetViewModel : DialogViewModelBase public class LayerBrushPresetViewModel : DialogViewModelBase
{ {
private readonly BaseLayerBrush _layerBrush;
private ILayerBrushPreset _selectedPreset; private ILayerBrushPreset _selectedPreset;
public LayerBrushPresetViewModel(BaseLayerBrush layerBrush) public LayerBrushPresetViewModel(BaseLayerBrush layerBrush)
{ {
_layerBrush = layerBrush;
Presets = new BindableCollection<ILayerBrushPreset>(); Presets = new BindableCollection<ILayerBrushPreset>();
Presets.AddRange(layerBrush.Presets); Presets.AddRange(layerBrush.Presets);
} }
@ -29,6 +31,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Dialogs
public void SelectPreset(ILayerBrushPreset preset) public void SelectPreset(ILayerBrushPreset preset)
{ {
_layerBrush.BaseProperties?.ResetAllLayerProperties();
preset.Apply(); preset.Apply();
Execute.OnUIThreadAsync(async () => Execute.OnUIThreadAsync(async () =>
{ {

View File

@ -47,7 +47,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
public void ResetToDefault() public void ResetToDefault()
{ {
LayerProperty.ApplyDefaultValue(_profileEditorService.CurrentTime); LayerProperty.ApplyDefaultValue();
_profileEditorService.UpdateSelectedProfileElement(); _profileEditorService.UpdateSelectedProfileElement();
} }

View File

@ -321,7 +321,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
dataBindingRegistration.GetDataBinding()?.UpdateWithDelta(delta); dataBindingRegistration.GetDataBinding()?.UpdateWithDelta(delta);
// TODO: Only update when there are data bindings // TODO: Only update when there are data bindings
_profileEditorService.UpdateProfilePreview(); if (!_profileEditorService.Playing)
_profileEditorService.UpdateProfilePreview();
} }
private void HighlightSelectedLayerOnSettingChanged(object sender, EventArgs e) private void HighlightSelectedLayerOnSettingChanged(object sender, EventArgs e)

View File

@ -94,7 +94,7 @@ namespace Artemis.UI.Screens.Settings.Device
private void CoreServiceOnFrameRendering(object sender, FrameRenderingEventArgs e) private void CoreServiceOnFrameRendering(object sender, FrameRenderingEventArgs e)
{ {
if (SelectedLeds == null) if (SelectedLeds == null || !SelectedLeds.Any())
return; return;
using SKPaint highlightPaint = new() {Color = SKColors.White}; using SKPaint highlightPaint = new() {Color = SKColors.White};

View File

@ -25,5 +25,23 @@ namespace Artemis.UI.Screens.StartupWizard.Steps
StartupWizardViewModel startupWizardViewModel = (StartupWizardViewModel) Parent; StartupWizardViewModel startupWizardViewModel = (StartupWizardViewModel) Parent;
startupWizardViewModel.Continue(); startupWizardViewModel.Continue();
} }
#region Overrides of Screen
/// <inheritdoc />
protected override void OnActivate()
{
_rgbService.IsRenderPaused = true;
base.OnActivate();
}
/// <inheritdoc />
protected override void OnDeactivate()
{
_rgbService.IsRenderPaused = false;
base.OnDeactivate();
}
#endregion
} }
} }