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>
ILayerPropertyKeyframe? AddKeyframeEntity(KeyframeEntity keyframeEntity);
/// <summary>
/// Overrides the property value with the default value
/// </summary>
void ApplyDefaultValue();
/// <summary>
/// Updates the layer properties internal state
/// </summary>

View File

@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
using Artemis.Storage.Entities.Profile;
using Newtonsoft.Json;
@ -39,6 +38,107 @@ namespace Artemis.Core
_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 />
public PropertyDescriptionAttribute PropertyDescription { get; internal set; }
@ -62,28 +162,6 @@ namespace Artemis.Core
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 />
public void Dispose()
{
@ -91,7 +169,38 @@ namespace Artemis.Core
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
@ -195,22 +304,25 @@ namespace Artemis.Core
ReapplyUpdate();
}
/// <summary>
/// Overrides the property value with the default value
/// </summary>
public void ApplyDefaultValue(TimeSpan? time)
/// <inheritdoc />
public void ApplyDefaultValue()
{
if (_disposed)
throw new ObjectDisposedException("LayerProperty");
string json = CoreJson.SerializeObject(DefaultValue, true);
SetCurrentValue(CoreJson.DeserializeObject<T>(json)!, time);
KeyframesEnabled = false;
SetCurrentValue(CoreJson.DeserializeObject<T>(json)!, null);
}
private void ReapplyUpdate()
{
ProfileElement.Timeline.ClearDelta();
Update(ProfileElement.Timeline);
// Create a timeline with the same position but a delta of zero
Timeline temporaryTimeline = new();
temporaryTimeline.Override(ProfileElement.Timeline.Position, false);
temporaryTimeline.ClearDelta();
Update(temporaryTimeline);
OnCurrentValueSet();
}
@ -440,10 +552,10 @@ namespace Artemis.Core
if (_disposed)
throw new ObjectDisposedException("LayerProperty");
foreach (IDataBindingRegistration dataBindingRegistration in _dataBindingRegistrations)
foreach (IDataBindingRegistration dataBindingRegistration in _dataBindingRegistrations)
dataBindingRegistration.ClearDataBinding();
_dataBindingRegistrations.Clear();
OnDataBindingPropertiesCleared();
}
@ -593,7 +705,7 @@ namespace Artemis.Core
throw new ArtemisCoreException("Layer property is not yet initialized");
if (!IsLoadedFromStorage)
ApplyDefaultValue(null);
ApplyDefaultValue();
else
try
{
@ -657,123 +769,5 @@ namespace Artemis.Core
}
#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();
}
/// <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>
/// Called before property group is activated to allow you to populate <see cref="LayerProperty{T}.DefaultValue" /> on
/// the properties you want
@ -145,6 +170,27 @@ namespace Artemis.Core
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)
{
if (path == null) throw new ArgumentNullException(nameof(path));
@ -209,6 +255,17 @@ namespace Artemis.Core
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)
{
string path = $"{Path}.{propertyInfo.Name}";
@ -266,67 +323,11 @@ namespace Artemis.Core
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 />
public void Dispose()
{
Dispose(true);
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",
"FeatureId": null,
"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,
"KeyframeEntities": {
"$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",
"FeatureId": "Artemis.Plugins.LayerBrushes.Noise.NoiseBrushProvider-61cbbf01",
"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,
"KeyframeEntities": {
"$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",
"FeatureId": null,
"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,
"KeyframeEntities": {
"$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",
"FeatureId": "Artemis.Plugins.LayerBrushes.Color.ColorBrushProvider-92a9d6ba",
"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,
"KeyframeEntities": {
"$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",
"FeatureId": null,
"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,
"KeyframeEntities": {
"$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",
"FeatureId": "Artemis.Plugins.LayerBrushes.Color.ColorBrushProvider-92a9d6ba",
"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,
"KeyframeEntities": {
"$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
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);
}
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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@ using LiteDB;
namespace Artemis.Storage.Migrations
{
public class M10BetterDataBindings : IStorageMigration
public class M0010BetterDataBindings : IStorageMigration
{
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.Linq;
using System.Windows;
using System.Windows.Controls.Primitives;
using Artemis.Core;
using Artemis.Core.Modules;
using Artemis.Core.Services;
@ -20,7 +19,6 @@ namespace Artemis.UI.Shared.Services
{
internal class ProfileEditorService : IProfileEditorService
{
private readonly ICoreService _coreService;
private readonly IKernel _kernel;
private readonly ILogger _logger;
private readonly IProfileService _profileService;
@ -29,6 +27,7 @@ namespace Artemis.UI.Shared.Services
private readonly object _selectedProfileElementLock = new();
private readonly object _selectedProfileLock = new();
private TimeSpan _currentTime;
private bool _doTick;
private int _pixelsPerSecond;
public ProfileEditorService(IKernel kernel, ILogger logger, IProfileService profileService, ICoreService coreService, IRgbService rgbService)
@ -36,16 +35,63 @@ namespace Artemis.UI.Shared.Services
_kernel = kernel;
_logger = logger;
_profileService = profileService;
_coreService = coreService;
_rgbService = rgbService;
_registeredPropertyEditors = new List<PropertyInputRegistration>();
coreService.FrameRendered += CoreServiceOnFrameRendered;
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)
{
_coreService.FrameRendered -= CoreServiceOnFrameRendered;
if (!_doTick) return;
_doTick = false;
Execute.PostToUIThread(OnProfilePreviewUpdated);
}
@ -73,6 +119,26 @@ namespace Artemis.UI.Shared.Services
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 bool Playing { get; set; }
@ -351,19 +417,14 @@ namespace Artemis.UI.Shared.Services
.ToList();
}
private void Tick()
{
if (SelectedProfile == null)
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);
_coreService.FrameRendered += CoreServiceOnFrameRendered;
}
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;
#region Copy/paste
@ -444,70 +505,5 @@ namespace Artemis.UI.Shared.Services
}
#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
{
private readonly BaseLayerBrush _layerBrush;
private ILayerBrushPreset _selectedPreset;
public LayerBrushPresetViewModel(BaseLayerBrush layerBrush)
{
_layerBrush = layerBrush;
Presets = new BindableCollection<ILayerBrushPreset>();
Presets.AddRange(layerBrush.Presets);
}
@ -29,6 +31,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Dialogs
public void SelectPreset(ILayerBrushPreset preset)
{
_layerBrush.BaseProperties?.ResetAllLayerProperties();
preset.Apply();
Execute.OnUIThreadAsync(async () =>
{

View File

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

View File

@ -321,7 +321,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
dataBindingRegistration.GetDataBinding()?.UpdateWithDelta(delta);
// TODO: Only update when there are data bindings
_profileEditorService.UpdateProfilePreview();
if (!_profileEditorService.Playing)
_profileEditorService.UpdateProfilePreview();
}
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)
{
if (SelectedLeds == null)
if (SelectedLeds == null || !SelectedLeds.Any())
return;
using SKPaint highlightPaint = new() {Color = SKColors.White};

View File

@ -25,5 +25,23 @@ namespace Artemis.UI.Screens.StartupWizard.Steps
StartupWizardViewModel startupWizardViewModel = (StartupWizardViewModel) Parent;
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
}
}