diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj
index afb0d5028..7ab16b561 100644
--- a/src/Artemis.Core/Artemis.Core.csproj
+++ b/src/Artemis.Core/Artemis.Core.csproj
@@ -70,4 +70,9 @@
..\..\..\RGB.NET\bin\netstandard2.0\RGB.NET.Groups.dll
+
+
+ PreserveNewest
+
+
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/Folder.cs b/src/Artemis.Core/Models/Profile/Folder.cs
index 53e25ccf8..0eefa1da7 100644
--- a/src/Artemis.Core/Models/Profile/Folder.cs
+++ b/src/Artemis.Core/Models/Profile/Folder.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Artemis.Core.Plugins.LayerEffect.Abstract;
+using Artemis.Core.Utilities;
using Artemis.Storage.Entities.Profile;
using Artemis.Storage.Entities.Profile.Abstract;
using SkiaSharp;
@@ -61,9 +62,13 @@ namespace Artemis.Core.Models.Profile
internal FolderEntity FolderEntity { get; set; }
internal override RenderElementEntity RenderElementEntity => FolderEntity;
+ public bool IsRootFolder => Parent == Profile;
public override void Update(double deltaTime)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Folder");
+
if (!Enabled)
return;
@@ -89,6 +94,9 @@ namespace Artemis.Core.Models.Profile
public override void OverrideProgress(TimeSpan timeOverride, bool stickToMainSegment)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Folder");
+
if (!Enabled)
return;
@@ -125,6 +133,9 @@ namespace Artemis.Core.Models.Profile
public override void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Folder");
+
if (Path == null || !Enabled || !Children.Any(c => c.Enabled))
return;
@@ -172,6 +183,13 @@ namespace Artemis.Core.Models.Profile
profileElement.Render(deltaTime, folderCanvas, _folderBitmap.Info);
folderCanvas.Restore();
}
+
+ // If required, apply the opacity override of the module to the root folder
+ if (IsRootFolder && Profile.Module.OpacityOverride < 1)
+ {
+ var multiplier = Easings.SineEaseInOut(Profile.Module.OpacityOverride);
+ folderPaint.Color = folderPaint.Color.WithAlpha((byte) (folderPaint.Color.Alpha * multiplier));
+ }
foreach (var baseLayerEffect in LayerEffects.Where(e => e.Enabled))
baseLayerEffect.PostProcess(canvas, canvasInfo, folderPath, folderPaint);
@@ -187,6 +205,9 @@ namespace Artemis.Core.Models.Profile
///
public Folder AddFolder(string name)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Folder");
+
var folder = new Folder(Profile, this, name) {Order = Children.LastOrDefault()?.Order ?? 1};
AddChild(folder);
return folder;
@@ -195,6 +216,9 @@ namespace Artemis.Core.Models.Profile
///
public override void AddChild(ProfileElement child, int? order = null)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Folder");
+
base.AddChild(child, order);
CalculateRenderProperties();
}
@@ -202,6 +226,9 @@ namespace Artemis.Core.Models.Profile
///
public override void RemoveChild(ProfileElement child)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Folder");
+
base.RemoveChild(child);
CalculateRenderProperties();
}
@@ -213,6 +240,9 @@ namespace Artemis.Core.Models.Profile
public void CalculateRenderProperties()
{
+ if (_disposed)
+ throw new ObjectDisposedException("Folder");
+
var path = new SKPath {FillType = SKPathFillType.Winding};
foreach (var child in Children)
{
@@ -234,16 +264,27 @@ namespace Artemis.Core.Models.Profile
if (!disposing)
return;
- _folderBitmap?.Dispose();
foreach (var baseLayerEffect in LayerEffects)
baseLayerEffect.Dispose();
+ _layerEffects.Clear();
+
foreach (var profileElement in Children)
profileElement.Dispose();
+ ChildrenList.Clear();
+
+ _folderBitmap?.Dispose();
+ _folderBitmap = null;
+
+ Profile = null;
+ _disposed = true;
}
internal override void ApplyToEntity()
{
+ if (_disposed)
+ throw new ObjectDisposedException("Folder");
+
FolderEntity.Id = EntityId;
FolderEntity.ParentId = Parent?.EntityId ?? new Guid();
@@ -262,16 +303,6 @@ namespace Artemis.Core.Models.Profile
DisplayConditionGroup?.ApplyToEntity();
}
- internal void Deactivate()
- {
- _folderBitmap?.Dispose();
- _folderBitmap = null;
-
- var layerEffects = new List(LayerEffects);
- foreach (var baseLayerEffect in layerEffects)
- DeactivateLayerEffect(baseLayerEffect);
- }
-
#region Events
public event EventHandler RenderPropertiesUpdated;
diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs
index 0aa341779..fdd212c4f 100644
--- a/src/Artemis.Core/Models/Profile/Layer.cs
+++ b/src/Artemis.Core/Models/Profile/Layer.cs
@@ -126,6 +126,9 @@ namespace Artemis.Core.Models.Profile
///
public override List GetAllKeyframes()
{
+ if (_disposed)
+ throw new ObjectDisposedException("Layer");
+
var keyframes = base.GetAllKeyframes();
foreach (var baseLayerProperty in General.GetAllLayerProperties())
@@ -143,22 +146,36 @@ namespace Artemis.Core.Models.Profile
protected override void Dispose(bool disposing)
{
- if (!disposing)
+ if (!disposing)
return;
- _general?.Dispose();
- _layerBitmap?.Dispose();
+ _disposed = true;
+
+ // Brush first in case it depends on any of the other disposables during it's own disposal
_layerBrush?.Dispose();
- _transform?.Dispose();
+ _layerBrush = null;
foreach (var baseLayerEffect in LayerEffects)
baseLayerEffect.Dispose();
+ _layerEffects.Clear();
+
+ _general?.Dispose();
+ _general = null;
+ _layerBitmap?.Dispose();
+ _layerBitmap = null;
+ _transform?.Dispose();
+ _transform = null;
+
+ Profile = null;
}
#region Storage
internal override void ApplyToEntity()
{
+ if (_disposed)
+ throw new ObjectDisposedException("Layer");
+
// Properties
LayerEntity.Id = EntityId;
LayerEntity.ParentId = Parent?.EntityId ?? new Guid();
@@ -231,6 +248,9 @@ namespace Artemis.Core.Models.Profile
///
public override void Update(double deltaTime)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Layer");
+
if (!Enabled || LayerBrush?.BaseProperties == null || !LayerBrush.BaseProperties.PropertiesInitialized)
return;
@@ -259,6 +279,9 @@ namespace Artemis.Core.Models.Profile
public override void OverrideProgress(TimeSpan timeOverride, bool stickToMainSegment)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Layer");
+
if (!Enabled || LayerBrush?.BaseProperties == null || !LayerBrush.BaseProperties.PropertiesInitialized)
return;
@@ -268,9 +291,7 @@ namespace Artemis.Core.Models.Profile
{
if (!DisplayContinuously)
{
- var position = timeOverride + StartSegmentLength;
- if (position > StartSegmentLength + EndSegmentLength)
- TimelinePosition = StartSegmentLength + EndSegmentLength;
+ TimelinePosition = StartSegmentLength + timeOverride;
}
else
{
@@ -301,6 +322,9 @@ namespace Artemis.Core.Models.Profile
///
public override void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Layer");
+
if (!Enabled || TimelinePosition > TimelineLength)
return;
@@ -424,6 +448,9 @@ namespace Artemis.Core.Models.Profile
internal void CalculateRenderProperties()
{
+ if (_disposed)
+ throw new ObjectDisposedException("Layer");
+
if (!Leds.Any())
Path = new SKPath();
else
@@ -448,6 +475,9 @@ namespace Artemis.Core.Models.Profile
internal SKPoint GetLayerAnchorPosition(SKPath layerPath, bool zeroBased = false)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Layer");
+
var positionProperty = Transform.Position.CurrentValue;
// Start at the center of the shape
@@ -469,6 +499,9 @@ namespace Artemis.Core.Models.Profile
///
public void IncludePathInTranslation(SKPath path, bool zeroBased)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Layer");
+
var sizeProperty = Transform.Scale.CurrentValue;
var rotationProperty = Transform.Rotation.CurrentValue;
@@ -498,6 +531,9 @@ namespace Artemis.Core.Models.Profile
///
public void ExcludePathFromTranslation(SKPath path, bool zeroBased)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Layer");
+
var sizeProperty = Transform.Scale.CurrentValue;
var rotationProperty = Transform.Rotation.CurrentValue;
@@ -531,6 +567,9 @@ namespace Artemis.Core.Models.Profile
/// The number of transformations applied
public int ExcludeCanvasFromTranslation(SKCanvas canvas, bool zeroBased)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Layer");
+
var sizeProperty = Transform.Scale.CurrentValue;
var rotationProperty = Transform.Rotation.CurrentValue;
@@ -568,6 +607,9 @@ namespace Artemis.Core.Models.Profile
/// The LED to add
public void AddLed(ArtemisLed led)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Layer");
+
_leds.Add(led);
CalculateRenderProperties();
}
@@ -578,6 +620,9 @@ namespace Artemis.Core.Models.Profile
/// The LEDs to add
public void AddLeds(IEnumerable leds)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Layer");
+
_leds.AddRange(leds);
CalculateRenderProperties();
}
@@ -588,6 +633,9 @@ namespace Artemis.Core.Models.Profile
/// The LED to remove
public void RemoveLed(ArtemisLed led)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Layer");
+
_leds.Remove(led);
CalculateRenderProperties();
}
@@ -597,12 +645,18 @@ namespace Artemis.Core.Models.Profile
///
public void ClearLeds()
{
+ if (_disposed)
+ throw new ObjectDisposedException("Layer");
+
_leds.Clear();
CalculateRenderProperties();
}
internal void PopulateLeds(ArtemisSurface surface)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Layer");
+
var leds = new List();
// Get the surface LEDs for this layer
@@ -623,17 +677,6 @@ namespace Artemis.Core.Models.Profile
#region Activation
- internal void Deactivate()
- {
- _layerBitmap?.Dispose();
- _layerBitmap = null;
-
- DeactivateLayerBrush();
- var layerEffects = new List(LayerEffects);
- foreach (var baseLayerEffect in layerEffects)
- DeactivateLayerEffect(baseLayerEffect);
- }
-
internal void DeactivateLayerBrush()
{
if (LayerBrush == null)
diff --git a/src/Artemis.Core/Models/Profile/LayerGeneralProperties.cs b/src/Artemis.Core/Models/Profile/LayerGeneralProperties.cs
index 8b1a11b2f..6ce5fa92f 100644
--- a/src/Artemis.Core/Models/Profile/LayerGeneralProperties.cs
+++ b/src/Artemis.Core/Models/Profile/LayerGeneralProperties.cs
@@ -28,5 +28,9 @@ namespace Artemis.Core.Models.Profile
protected override void EnableProperties()
{
}
+
+ protected override void DisableProperties()
+ {
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs
index 009e46301..3c29ea526 100644
--- a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs
+++ b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs
@@ -110,6 +110,8 @@ namespace Artemis.Core.Models.Profile
public void Dispose()
{
DisableProperties();
+ foreach (var layerPropertyGroup in _layerPropertyGroups)
+ layerPropertyGroup.Dispose();
}
///
diff --git a/src/Artemis.Core/Models/Profile/LayerTransformProperties.cs b/src/Artemis.Core/Models/Profile/LayerTransformProperties.cs
index 141d8cfa0..8a6afca51 100644
--- a/src/Artemis.Core/Models/Profile/LayerTransformProperties.cs
+++ b/src/Artemis.Core/Models/Profile/LayerTransformProperties.cs
@@ -30,5 +30,9 @@ namespace Artemis.Core.Models.Profile
protected override void EnableProperties()
{
}
+
+ protected override void DisableProperties()
+ {
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs
index 2394fd43c..b130da1bd 100644
--- a/src/Artemis.Core/Models/Profile/Profile.cs
+++ b/src/Artemis.Core/Models/Profile/Profile.cs
@@ -57,6 +57,8 @@ namespace Artemis.Core.Models.Profile
{
lock (this)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Profile");
if (!IsActivated)
throw new ArtemisCoreException($"Cannot update inactive profile: {this}");
@@ -69,6 +71,8 @@ namespace Artemis.Core.Models.Profile
{
lock (this)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Profile");
if (!IsActivated)
throw new ArtemisCoreException($"Cannot render inactive profile: {this}");
@@ -79,21 +83,26 @@ namespace Artemis.Core.Models.Profile
public Folder GetRootFolder()
{
+ if (_disposed)
+ throw new ObjectDisposedException("Profile");
+
return (Folder) Children.Single();
}
public void ApplyToProfile()
{
+ if (_disposed)
+ throw new ObjectDisposedException("Profile");
+
Name = ProfileEntity.Name;
lock (ChildrenList)
{
- foreach (var folder in GetAllFolders())
- folder.Deactivate();
- foreach (var layer in GetAllLayers())
- layer.Deactivate();
-
+ // Remove the old profile tree
+ foreach (var profileElement in Children)
+ profileElement.Dispose();
ChildrenList.Clear();
+
// Populate the profile starting at the root, the rest is populated recursively
var rootFolder = ProfileEntity.Folders.FirstOrDefault(f => f.ParentId == EntityId);
if (rootFolder == null)
@@ -113,13 +122,21 @@ namespace Artemis.Core.Models.Profile
if (!disposing)
return;
- Deactivate();
+ OnDeactivating();
+
foreach (var profileElement in Children)
profileElement.Dispose();
+ ChildrenList.Clear();
+
+ IsActivated = false;
+ _disposed = true;
}
internal override void ApplyToEntity()
{
+ if (_disposed)
+ throw new ObjectDisposedException("Profile");
+
ProfileEntity.Id = EntityId;
ProfileEntity.PluginGuid = Module.PluginInfo.Guid;
ProfileEntity.Name = Name;
@@ -139,6 +156,8 @@ namespace Artemis.Core.Models.Profile
{
lock (this)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Profile");
if (IsActivated)
return;
@@ -148,25 +167,11 @@ namespace Artemis.Core.Models.Profile
}
}
- internal void Deactivate()
- {
- lock (this)
- {
- if (!IsActivated)
- return;
-
- foreach (var folder in GetAllFolders())
- folder.Deactivate();
- foreach (var layer in GetAllLayers())
- layer.Deactivate();
-
- IsActivated = false;
- OnDeactivated();
- }
- }
-
internal void PopulateLeds(ArtemisSurface surface)
{
+ if (_disposed)
+ throw new ObjectDisposedException("Profile");
+
foreach (var layer in GetAllLayers())
layer.PopulateLeds(surface);
}
@@ -174,7 +179,7 @@ namespace Artemis.Core.Models.Profile
#region Events
///
- /// Occurs when the profile is being activated.
+ /// Occurs when the profile has been activated.
///
public event EventHandler Activated;
@@ -188,7 +193,7 @@ namespace Artemis.Core.Models.Profile
Activated?.Invoke(this, EventArgs.Empty);
}
- private void OnDeactivated()
+ private void OnDeactivating()
{
Deactivated?.Invoke(this, EventArgs.Empty);
}
diff --git a/src/Artemis.Core/Models/Profile/ProfileDescriptor.cs b/src/Artemis.Core/Models/Profile/ProfileDescriptor.cs
index 5dead225a..2ff49ab28 100644
--- a/src/Artemis.Core/Models/Profile/ProfileDescriptor.cs
+++ b/src/Artemis.Core/Models/Profile/ProfileDescriptor.cs
@@ -9,16 +9,16 @@ namespace Artemis.Core.Models.Profile
internal ProfileDescriptor(ProfileModule profileModule, ProfileEntity profileEntity)
{
ProfileModule = profileModule;
- ProfileEntity = profileEntity;
Id = profileEntity.Id;
Name = profileEntity.Name;
+ IsLastActiveProfile = profileEntity.IsActive;
}
-
+
+ public bool IsLastActiveProfile { get; set; }
+
public Guid Id { get; }
public ProfileModule ProfileModule { get; }
public string Name { get; }
-
- internal ProfileEntity ProfileEntity { get; }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/ProfileElement.cs b/src/Artemis.Core/Models/Profile/ProfileElement.cs
index a54fa5dc4..5316a4b69 100644
--- a/src/Artemis.Core/Models/Profile/ProfileElement.cs
+++ b/src/Artemis.Core/Models/Profile/ProfileElement.cs
@@ -22,6 +22,7 @@ namespace Artemis.Core.Models.Profile
GC.SuppressFinalize(this);
}
+ protected bool _disposed;
private bool _enabled;
private Guid _entityId;
private string _name;
@@ -98,6 +99,9 @@ namespace Artemis.Core.Models.Profile
public List GetAllFolders()
{
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
var folders = new List();
foreach (var childFolder in Children.Where(c => c is Folder).Cast())
{
@@ -112,6 +116,9 @@ namespace Artemis.Core.Models.Profile
public List GetAllLayers()
{
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
var layers = new List();
// Add all layers in this element
@@ -131,6 +138,9 @@ namespace Artemis.Core.Models.Profile
/// The order where to place the child (1-based), defaults to the end of the collection
public virtual void AddChild(ProfileElement child, int? order = null)
{
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
lock (ChildrenList)
{
// Add to the end of the list
@@ -169,6 +179,9 @@ namespace Artemis.Core.Models.Profile
/// The profile element to remove
public virtual void RemoveChild(ProfileElement child)
{
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
lock (ChildrenList)
{
ChildrenList.Remove(child);
diff --git a/src/Artemis.Core/Models/Profile/RenderProfileElement.cs b/src/Artemis.Core/Models/Profile/RenderProfileElement.cs
index 77d2b356d..8408a6b31 100644
--- a/src/Artemis.Core/Models/Profile/RenderProfileElement.cs
+++ b/src/Artemis.Core/Models/Profile/RenderProfileElement.cs
@@ -203,8 +203,6 @@ namespace Artemis.Core.Models.Profile
// If we are at the end of the main timeline, wrap around back to the beginning
if (DisplayContinuously && TimelinePosition >= mainSegmentEnd)
TimelinePosition = StartSegmentLength + (mainSegmentEnd - TimelinePosition);
- else if (TimelinePosition >= TimelineLength)
- TimelinePosition = TimelineLength;
}
else
{
diff --git a/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs b/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs
index f2a2d952a..55965ca63 100644
--- a/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs
+++ b/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs
@@ -4,6 +4,7 @@ using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
+using System.Threading.Tasks;
using Artemis.Core.Exceptions;
using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Surface;
@@ -94,6 +95,11 @@ namespace Artemis.Core.Plugins.Abstract
///
public abstract class ProfileModule : Module
{
+ protected ProfileModule()
+ {
+ OpacityOverride = 1;
+ }
+
protected readonly List HiddenPropertiesList = new List();
///
@@ -113,6 +119,10 @@ namespace Artemis.Core.Plugins.Abstract
{
lock (this)
{
+ OpacityOverride = AnimatingProfileChange
+ ? Math.Max(0, OpacityOverride - 0.1)
+ : Math.Min(1, OpacityOverride + 0.1);
+
// Update the profile
if (!IsProfileUpdatingDisabled)
ActiveProfile?.Update(deltaTime);
@@ -129,6 +139,27 @@ namespace Artemis.Core.Plugins.Abstract
}
}
+ internal async Task ChangeActiveProfileAnimated(Profile profile, ArtemisSurface surface)
+ {
+ if (profile != null && profile.Module != this)
+ throw new ArtemisCoreException($"Cannot activate a profile of module {profile.Module} on a module of plugin {PluginInfo}.");
+
+
+ if (profile == ActiveProfile || AnimatingProfileChange)
+ return;
+
+ AnimatingProfileChange = true;
+
+ while (OpacityOverride > 0)
+ await Task.Delay(50);
+
+ ChangeActiveProfile(profile, surface);
+ AnimatingProfileChange = false;
+
+ while (OpacityOverride < 1)
+ await Task.Delay(50);
+ }
+
internal void ChangeActiveProfile(Profile profile, ArtemisSurface surface)
{
if (profile != null && profile.Module != this)
@@ -147,6 +178,16 @@ namespace Artemis.Core.Plugins.Abstract
OnActiveProfileChanged();
}
+ ///
+ /// Overrides the opacity of the root folder
+ ///
+ public double OpacityOverride { get; set; }
+
+ ///
+ /// Indicates whether or not a profile change is being animated
+ ///
+ public bool AnimatingProfileChange { get; private set; }
+
#region Events
public event EventHandler ActiveProfileChanged;
diff --git a/src/Artemis.Core/Plugins/LayerBrush/Abstract/PerLedLayerBrush.cs b/src/Artemis.Core/Plugins/LayerBrush/Abstract/PerLedLayerBrush.cs
index 150a08c3d..758ba6d69 100644
--- a/src/Artemis.Core/Plugins/LayerBrush/Abstract/PerLedLayerBrush.cs
+++ b/src/Artemis.Core/Plugins/LayerBrush/Abstract/PerLedLayerBrush.cs
@@ -52,6 +52,8 @@ namespace Artemis.Core.Plugins.LayerBrush.Abstract
{
var artemisLed = Layer.Leds[index];
var renderPoint = points[index * 2 + 1];
+ if (!float.IsFinite(renderPoint.X) || !float.IsFinite(renderPoint.Y))
+ continue;
// Let the brush determine the color
ledPaint.Color = GetColor(artemisLed, renderPoint);
diff --git a/src/Artemis.Core/Resources/intro-profile.json b/src/Artemis.Core/Resources/intro-profile.json
new file mode 100644
index 000000000..895a03515
--- /dev/null
+++ b/src/Artemis.Core/Resources/intro-profile.json
@@ -0,0 +1,1045 @@
+{
+ "$type": "Artemis.Storage.Entities.Profile.ProfileEntity, Artemis.Storage",
+ "Id": "eb4f487b-475b-408f-a84f-733412d41b44",
+ "PluginGuid": "0de2991a-d7b8-4f61-ae4e-6623849215b5",
+ "Name": "Intro animation",
+ "IsActive": true,
+ "Folders": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.FolderEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": [
+ {
+ "$type": "Artemis.Storage.Entities.Profile.FolderEntity, Artemis.Storage",
+ "Id": "cc21b67c-3485-4dc6-b2af-105fda42a915",
+ "ParentId": "eb4f487b-475b-408f-a84f-733412d41b44",
+ "Order": 1,
+ "Name": "Root folder",
+ "Enabled": true,
+ "Profile": null,
+ "ProfileId": "eb4f487b-475b-408f-a84f-733412d41b44",
+ "StartSegmentLength": "00:00:00",
+ "MainSegmentLength": "00:00:05",
+ "EndSegmentLength": "00:00:00",
+ "DisplayContinuously": true,
+ "AlwaysFinishTimeline": false,
+ "LayerEffects": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.LayerEffectEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ },
+ "PropertyEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ },
+ "ExpandedPropertyGroups": {
+ "$type": "System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib",
+ "$values": []
+ },
+ "RootDisplayCondition": {
+ "$type": "Artemis.Storage.Entities.Profile.DisplayConditionGroupEntity, Artemis.Storage",
+ "BooleanOperator": 0,
+ "Children": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.Abstract.DisplayConditionPartEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ }
+ }
+ ]
+ },
+ "Layers": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.LayerEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": [
+ {
+ "$type": "Artemis.Storage.Entities.Profile.LayerEntity, Artemis.Storage",
+ "Id": "2464a52c-4cec-4f17-87ed-edfe4bfed6f6",
+ "ParentId": "cc21b67c-3485-4dc6-b2af-105fda42a915",
+ "Order": 1,
+ "Name": "Teal layer",
+ "Enabled": true,
+ "Leds": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.LedEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ },
+ "Profile": null,
+ "ProfileId": "eb4f487b-475b-408f-a84f-733412d41b44",
+ "StartSegmentLength": "00:00:00",
+ "MainSegmentLength": "00:00:05",
+ "EndSegmentLength": "00:00:00",
+ "DisplayContinuously": false,
+ "AlwaysFinishTimeline": false,
+ "LayerEffects": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.LayerEffectEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ },
+ "PropertyEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": [
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "General.ShapeType",
+ "Value": "1",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "General.ResizeMode",
+ "Value": "0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "General.BlendMode",
+ "Value": "3",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "General.BrushReference",
+ "Value": "{\"BrushPluginGuid\":\"61cbbf01-8d69-4ede-a972-f3f269da66d9\",\"BrushType\":\"NoiseBrush\"}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.AnchorPoint",
+ "Value": "{\"IsEmpty\":true,\"Length\":0.0,\"LengthSquared\":0.0,\"X\":0.0,\"Y\":0.0}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.Position",
+ "Value": "{\"IsEmpty\":true,\"Length\":0.0,\"LengthSquared\":0.0,\"X\":0.0,\"Y\":0.0}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.Scale",
+ "Value": "{\"IsEmpty\":false,\"Width\":500.0,\"Height\":500.0}",
+ "KeyframesEnabled": true,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": [
+ {
+ "$type": "Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage",
+ "Position": "00:00:02.5000000",
+ "Timeline": 0,
+ "Value": "{\"IsEmpty\":false,\"Width\":300.0,\"Height\":0.0}",
+ "EasingFunction": 3
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage",
+ "Position": "00:00:03.7500000",
+ "Timeline": 0,
+ "Value": "{\"IsEmpty\":false,\"Width\":300.0,\"Height\":400.0}",
+ "EasingFunction": 0
+ }
+ ]
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.Rotation",
+ "Value": "-45.0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.Opacity",
+ "Value": "100.0",
+ "KeyframesEnabled": true,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": [
+ {
+ "$type": "Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage",
+ "Position": "00:00:04",
+ "Timeline": 0,
+ "Value": "100.0",
+ "EasingFunction": 0
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage",
+ "Position": "00:00:04.4000000",
+ "Timeline": 0,
+ "Value": "0.0",
+ "EasingFunction": 0
+ }
+ ]
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "61cbbf01-8d69-4ede-a972-f3f269da66d9",
+ "Path": "LayerBrush.ColorType",
+ "Value": "0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "61cbbf01-8d69-4ede-a972-f3f269da66d9",
+ "Path": "LayerBrush.MainColor",
+ "Value": "\"#ff009688\"",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "61cbbf01-8d69-4ede-a972-f3f269da66d9",
+ "Path": "LayerBrush.SecondaryColor",
+ "Value": "\"#ff00ffe7\"",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "61cbbf01-8d69-4ede-a972-f3f269da66d9",
+ "Path": "LayerBrush.GradientColor",
+ "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}],\"Rotation\":0.0}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "61cbbf01-8d69-4ede-a972-f3f269da66d9",
+ "Path": "LayerBrush.Scale",
+ "Value": "{\"IsEmpty\":false,\"Width\":100.0,\"Height\":100.0}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "61cbbf01-8d69-4ede-a972-f3f269da66d9",
+ "Path": "LayerBrush.Hardness",
+ "Value": "300.0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "61cbbf01-8d69-4ede-a972-f3f269da66d9",
+ "Path": "LayerBrush.ScrollSpeed",
+ "Value": "{\"IsEmpty\":true,\"Length\":0.0,\"LengthSquared\":0.0,\"X\":0.0,\"Y\":0.0}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "61cbbf01-8d69-4ede-a972-f3f269da66d9",
+ "Path": "LayerBrush.AnimationSpeed",
+ "Value": "25.0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ }
+ ]
+ },
+ "ExpandedPropertyGroups": {
+ "$type": "System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib",
+ "$values": [
+ "Transform",
+ "General"
+ ]
+ },
+ "RootDisplayCondition": {
+ "$type": "Artemis.Storage.Entities.Profile.DisplayConditionGroupEntity, Artemis.Storage",
+ "BooleanOperator": 0,
+ "Children": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.Abstract.DisplayConditionPartEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.LayerEntity, Artemis.Storage",
+ "Id": "8d5fa358-88ed-4501-8cb2-fd9c31a34274",
+ "ParentId": "cc21b67c-3485-4dc6-b2af-105fda42a915",
+ "Order": 2,
+ "Name": "RGB layer",
+ "Enabled": true,
+ "Leds": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.LedEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ },
+ "Profile": null,
+ "ProfileId": "eb4f487b-475b-408f-a84f-733412d41b44",
+ "StartSegmentLength": "00:00:00",
+ "MainSegmentLength": "00:00:03.7500000",
+ "EndSegmentLength": "00:00:00",
+ "DisplayContinuously": false,
+ "AlwaysFinishTimeline": false,
+ "LayerEffects": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.LayerEffectEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ },
+ "PropertyEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": [
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "General.ShapeType",
+ "Value": "1",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "General.ResizeMode",
+ "Value": "0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "General.BlendMode",
+ "Value": "3",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "General.BrushReference",
+ "Value": "{\"BrushPluginGuid\":\"92a9d6ba-6f7a-4937-94d5-c1d715b4141a\",\"BrushType\":\"ColorBrush\"}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.AnchorPoint",
+ "Value": "{\"IsEmpty\":true,\"Length\":0.0,\"LengthSquared\":0.0,\"X\":0.0,\"Y\":0.0}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.Position",
+ "Value": "{\"IsEmpty\":false,\"Length\":0.5,\"LengthSquared\":0.25,\"X\":-0.5,\"Y\":-0.0}",
+ "KeyframesEnabled": true,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": [
+ {
+ "$type": "Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage",
+ "Position": "00:00:01.2500000",
+ "Timeline": 0,
+ "Value": "{\"IsEmpty\":false,\"Length\":0.25,\"LengthSquared\":0.0625,\"X\":-0.25,\"Y\":0.0}",
+ "EasingFunction": 0
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage",
+ "Position": "00:00:03.7500000",
+ "Timeline": 0,
+ "Value": "{\"IsEmpty\":false,\"Length\":0.25,\"LengthSquared\":0.0625,\"X\":0.25,\"Y\":0.0}",
+ "EasingFunction": 0
+ }
+ ]
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.Scale",
+ "Value": "{\"IsEmpty\":false,\"Width\":200.0,\"Height\":0.0}",
+ "KeyframesEnabled": true,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": [
+ {
+ "$type": "Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage",
+ "Position": "00:00:01.2500000",
+ "Timeline": 0,
+ "Value": "{\"IsEmpty\":false,\"Width\":150.0,\"Height\":0.0}",
+ "EasingFunction": 5
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage",
+ "Position": "00:00:02.2700000",
+ "Timeline": 0,
+ "Value": "{\"IsEmpty\":false,\"Width\":150.0,\"Height\":100.0}",
+ "EasingFunction": 0
+ }
+ ]
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.Rotation",
+ "Value": "0.0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.Opacity",
+ "Value": "100.0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.GradientType",
+ "Value": "1",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.TileMode",
+ "Value": "0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.Color",
+ "Value": "\"#ffff0000\"",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "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}],\"Rotation\":0.0}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.ColorsMultiplier",
+ "Value": "2",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.LinearGradientRotation",
+ "Value": "0.0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.RadialGradient.CenterOffset",
+ "Value": "{\"IsEmpty\":true,\"Length\":0.0,\"LengthSquared\":0.0,\"X\":0.0,\"Y\":0.0}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.RadialGradient.ResizeMode",
+ "Value": "0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ }
+ ]
+ },
+ "ExpandedPropertyGroups": {
+ "$type": "System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib",
+ "$values": [
+ "Transform",
+ "LayerBrush"
+ ]
+ },
+ "RootDisplayCondition": {
+ "$type": "Artemis.Storage.Entities.Profile.DisplayConditionGroupEntity, Artemis.Storage",
+ "BooleanOperator": 0,
+ "Children": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.Abstract.DisplayConditionPartEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.LayerEntity, Artemis.Storage",
+ "Id": "72a7e56c-0649-4449-8dca-eb937161f228",
+ "ParentId": "cc21b67c-3485-4dc6-b2af-105fda42a915",
+ "Order": 3,
+ "Name": "Exploison layer",
+ "Enabled": true,
+ "Leds": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.LedEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ },
+ "Profile": null,
+ "ProfileId": "eb4f487b-475b-408f-a84f-733412d41b44",
+ "StartSegmentLength": "00:00:00",
+ "MainSegmentLength": "00:00:02.2500000",
+ "EndSegmentLength": "00:00:00",
+ "DisplayContinuously": false,
+ "AlwaysFinishTimeline": false,
+ "LayerEffects": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.LayerEffectEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ },
+ "PropertyEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": [
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "General.ShapeType",
+ "Value": "0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "General.ResizeMode",
+ "Value": "0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "General.BlendMode",
+ "Value": "3",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "General.BrushReference",
+ "Value": "{\"BrushPluginGuid\":\"92a9d6ba-6f7a-4937-94d5-c1d715b4141a\",\"BrushType\":\"ColorBrush\"}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.AnchorPoint",
+ "Value": "{\"IsEmpty\":true,\"Length\":0.0,\"LengthSquared\":0.0,\"X\":0.0,\"Y\":0.0}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.Position",
+ "Value": "{\"IsEmpty\":true,\"Length\":0.0,\"LengthSquared\":0.0,\"X\":0.0,\"Y\":0.0}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.Scale",
+ "Value": "{\"IsEmpty\":false,\"Width\":110.03,\"Height\":340.37}",
+ "KeyframesEnabled": true,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": [
+ {
+ "$type": "Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage",
+ "Position": "00:00:00",
+ "Timeline": 0,
+ "Value": "{\"IsEmpty\":true,\"Width\":0.0,\"Height\":0.0}",
+ "EasingFunction": 6
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage",
+ "Position": "00:00:02",
+ "Timeline": 0,
+ "Value": "{\"IsEmpty\":false,\"Width\":200.0,\"Height\":200.0}",
+ "EasingFunction": 0
+ }
+ ]
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.Rotation",
+ "Value": "0.0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.Opacity",
+ "Value": "100.0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.GradientType",
+ "Value": "2",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.TileMode",
+ "Value": "0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.Color",
+ "Value": "\"#ffff0000\"",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.Colors",
+ "Value": "{\"Stops\":[{\"Color\":\"#00ff0000\",\"Position\":0.0},{\"Color\":\"#ffff8800\",\"Position\":0.492},{\"Color\":\"#ffedff00\",\"Position\":0.905},{\"Color\":\"#00ff0000\",\"Position\":1.0}],\"Rotation\":0.0}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.ColorsMultiplier",
+ "Value": "0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.LinearGradientRotation",
+ "Value": "0.0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.RadialGradient.CenterOffset",
+ "Value": "{\"IsEmpty\":true,\"Length\":0.0,\"LengthSquared\":0.0,\"X\":0.0,\"Y\":0.0}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.RadialGradient.ResizeMode",
+ "Value": "0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ }
+ ]
+ },
+ "ExpandedPropertyGroups": {
+ "$type": "System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib",
+ "$values": [
+ "LayerBrush"
+ ]
+ },
+ "RootDisplayCondition": {
+ "$type": "Artemis.Storage.Entities.Profile.DisplayConditionGroupEntity, Artemis.Storage",
+ "BooleanOperator": 0,
+ "Children": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.Abstract.DisplayConditionPartEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.LayerEntity, Artemis.Storage",
+ "Id": "f046f56f-a236-4ed6-bbd9-b5a4731878cf",
+ "ParentId": "cc21b67c-3485-4dc6-b2af-105fda42a915",
+ "Order": 4,
+ "Name": "Background",
+ "Enabled": true,
+ "Leds": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.LedEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ },
+ "Profile": null,
+ "ProfileId": "eb4f487b-475b-408f-a84f-733412d41b44",
+ "StartSegmentLength": "00:00:00",
+ "MainSegmentLength": "00:00:03.7500000",
+ "EndSegmentLength": "00:00:00",
+ "DisplayContinuously": false,
+ "AlwaysFinishTimeline": false,
+ "LayerEffects": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.LayerEffectEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ },
+ "PropertyEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": [
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "General.ShapeType",
+ "Value": "1",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "General.ResizeMode",
+ "Value": "0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "General.BlendMode",
+ "Value": "3",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "General.BrushReference",
+ "Value": "{\"BrushPluginGuid\":\"92a9d6ba-6f7a-4937-94d5-c1d715b4141a\",\"BrushType\":\"ColorBrush\"}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.AnchorPoint",
+ "Value": "{\"IsEmpty\":true,\"Length\":0.0,\"LengthSquared\":0.0,\"X\":0.0,\"Y\":0.0}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.Position",
+ "Value": "{\"IsEmpty\":true,\"Length\":0.0,\"LengthSquared\":0.0,\"X\":0.0,\"Y\":0.0}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.Scale",
+ "Value": "{\"IsEmpty\":false,\"Width\":100.0,\"Height\":100.0}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.Rotation",
+ "Value": "0.0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ "Path": "Transform.Opacity",
+ "Value": "100.0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.GradientType",
+ "Value": "0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.TileMode",
+ "Value": "0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.Color",
+ "Value": "\"#ff000000\"",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "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}],\"Rotation\":0.0}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.ColorsMultiplier",
+ "Value": "0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.LinearGradientRotation",
+ "Value": "0.0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.RadialGradient.CenterOffset",
+ "Value": "{\"IsEmpty\":true,\"Length\":0.0,\"LengthSquared\":0.0,\"X\":0.0,\"Y\":0.0}",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ },
+ {
+ "$type": "Artemis.Storage.Entities.Profile.PropertyEntity, Artemis.Storage",
+ "PluginGuid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a",
+ "Path": "LayerBrush.RadialGradient.ResizeMode",
+ "Value": "0",
+ "KeyframesEnabled": false,
+ "KeyframeEntities": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.KeyframeEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ }
+ ]
+ },
+ "ExpandedPropertyGroups": {
+ "$type": "System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib",
+ "$values": [
+ "LayerBrush"
+ ]
+ },
+ "RootDisplayCondition": {
+ "$type": "Artemis.Storage.Entities.Profile.DisplayConditionGroupEntity, Artemis.Storage",
+ "BooleanOperator": 0,
+ "Children": {
+ "$type": "System.Collections.Generic.List`1[[Artemis.Storage.Entities.Profile.Abstract.DisplayConditionPartEntity, Artemis.Storage]], System.Private.CoreLib",
+ "$values": []
+ }
+ }
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs
index 1cf8fd5b8..ec0654995 100644
--- a/src/Artemis.Core/Services/CoreService.cs
+++ b/src/Artemis.Core/Services/CoreService.cs
@@ -3,14 +3,17 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
+using System.Threading.Tasks;
using Artemis.Core.Events;
using Artemis.Core.Exceptions;
using Artemis.Core.JsonConverters;
+using Artemis.Core.Models.Profile;
using Artemis.Core.Ninject;
using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Plugins.Models;
using Artemis.Core.Services.Interfaces;
using Artemis.Core.Services.Storage.Interfaces;
+using Artemis.Core.Utilities;
using Artemis.Storage;
using Newtonsoft.Json;
using RGB.NET.Core;
@@ -35,6 +38,7 @@ namespace Artemis.Core.Services
private readonly ISurfaceService _surfaceService;
private List _dataModelExpansions;
private List _modules;
+ private IntroAnimation _introAnimation;
// ReSharper disable once UnusedParameter.Local - Storage migration service is injected early to ensure it runs before anything else
internal CoreService(ILogger logger, StorageMigrationService _, ISettingsService settingsService, IPluginService pluginService,
@@ -90,11 +94,38 @@ namespace Artemis.Core.Services
else
_logger.Information("Initialized without an active surface entity");
+ PlayIntroAnimation();
_profileService.ActivateLastActiveProfiles();
OnInitialized();
}
+ private void PlayIntroAnimation()
+ {
+ FrameRendering += DrawOverlay;
+ _introAnimation = new IntroAnimation(_logger, _profileService, _surfaceService);
+
+ // Draw a white overlay over the device
+ void DrawOverlay(object sender, FrameRenderingEventArgs args)
+ {
+ if (_introAnimation == null)
+ args.Canvas.Clear(new SKColor(0, 0, 0));
+ else
+ _introAnimation.Render(args.DeltaTime, args.Canvas, _rgbService.BitmapBrush.Bitmap.Info);
+ }
+
+ var introLength = _introAnimation.AnimationProfile.GetAllLayers().Max(l => l.TimelineLength);
+
+ // Stop rendering after the profile finishes (take 1 second extra in case of slow updates)
+ Task.Run(async () =>
+ {
+ await Task.Delay(introLength.Add(TimeSpan.FromSeconds(1)));
+ FrameRendering -= DrawOverlay;
+
+ _introAnimation.AnimationProfile?.Dispose();
+ _introAnimation = null;
+ });
+ }
public void SetMainWindowHandle(IntPtr handle)
{
diff --git a/src/Artemis.Core/Services/Interfaces/ICoreService.cs b/src/Artemis.Core/Services/Interfaces/ICoreService.cs
index 34a3969ee..f4e6b7750 100644
--- a/src/Artemis.Core/Services/Interfaces/ICoreService.cs
+++ b/src/Artemis.Core/Services/Interfaces/ICoreService.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
using Artemis.Core.Events;
namespace Artemis.Core.Services.Interfaces
diff --git a/src/Artemis.Core/Services/Storage/Interfaces/IProfileService.cs b/src/Artemis.Core/Services/Storage/Interfaces/IProfileService.cs
index ed087426c..31bd8efcb 100644
--- a/src/Artemis.Core/Services/Storage/Interfaces/IProfileService.cs
+++ b/src/Artemis.Core/Services/Storage/Interfaces/IProfileService.cs
@@ -1,10 +1,14 @@
using System.Collections.Generic;
+using System.Threading.Tasks;
using Artemis.Core.Models.Profile;
using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Services.Interfaces;
namespace Artemis.Core.Services.Storage.Interfaces
{
+ ///
+ /// Provides access to profile storage and is responsible for activating default profiles
+ ///
public interface IProfileService : IArtemisService
{
///
@@ -18,14 +22,14 @@ namespace Artemis.Core.Services.Storage.Interfaces
/// The profile module to create the profile for
/// The name of the new profile
///
- ProfileDescriptor CreateProfile(ProfileModule module, string name);
+ ProfileDescriptor CreateProfileDescriptor(ProfileModule module, string name);
///
/// Gets a descriptor for each profile stored for the given
///
/// The module to return profile descriptors for
///
- List GetProfiles(ProfileModule module);
+ List GetProfileDescriptors(ProfileModule module);
///
/// Writes the profile to persistent storage
@@ -40,30 +44,53 @@ namespace Artemis.Core.Services.Storage.Interfaces
/// The profile to delete
void DeleteProfile(Profile profile);
+ ///
+ /// Permanently deletes the profile described by the provided profile descriptor
+ ///
+ /// The descriptor pointing to the profile to delete
+ void DeleteProfile(ProfileDescriptor profileDescriptor);
+
///
/// Activates the profile described in the given with the currently active surface
///
/// The descriptor describing the profile to activate
Profile ActivateProfile(ProfileDescriptor profileDescriptor);
+ ///
+ /// Asynchronously activates the profile described in the given with the currently
+ /// active surface using a fade animation
+ ///
+ /// The descriptor describing the profile to activate
+ Task ActivateProfileAnimated(ProfileDescriptor profileDescriptor);
+
///
/// Clears the active profile on the given
///
/// The profile module to deactivate the active profile on
void ClearActiveProfile(ProfileModule module);
+ ///
+ /// Asynchronously clears the active profile on the given using a fade animation
+ ///
+ /// The profile module to deactivate the active profile on
+ Task ClearActiveProfileAnimated(ProfileModule module);
+
///
/// Attempts to restore the profile to the state it had before the last call.
///
- ///
- ///
- bool UndoUpdateProfile(Profile selectedProfile, ProfileModule module);
+ ///
+ bool UndoUpdateProfile(Profile profile);
///
/// Attempts to restore the profile to the state it had before the last call.
///
- ///
- ///
- bool RedoUpdateProfile(Profile selectedProfile, ProfileModule module);
+ ///
+ bool RedoUpdateProfile(Profile profile);
+
+ ///
+ /// Prepares the profile for rendering. You should not need to call this, it is exposed for some niche usage in the core
+ ///
+ ///
+ void InstantiateProfile(Profile profile);
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs
index e71830e3e..9212eb87f 100644
--- a/src/Artemis.Core/Services/Storage/ProfileService.cs
+++ b/src/Artemis.Core/Services/Storage/ProfileService.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Threading.Tasks;
using Artemis.Core.Events;
using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Surface;
@@ -15,9 +16,6 @@ using Serilog;
namespace Artemis.Core.Services.Storage
{
- ///
- /// Provides access to profile storage and is responsible for activating default profiles
- ///
public class ProfileService : IProfileService
{
private readonly ILogger _logger;
@@ -51,20 +49,13 @@ namespace Artemis.Core.Services.Storage
}
}
- public List GetProfiles(ProfileModule module)
+ public List GetProfileDescriptors(ProfileModule module)
{
var profileEntities = _profileRepository.GetByPluginGuid(module.PluginInfo.Guid);
return profileEntities.Select(e => new ProfileDescriptor(module, e)).ToList();
}
- public ProfileDescriptor GetLastActiveProfile(ProfileModule module)
- {
- var moduleProfiles = _profileRepository.GetByPluginGuid(module.PluginInfo.Guid);
- var profileEntity = moduleProfiles.FirstOrDefault(p => p.IsActive) ?? moduleProfiles.FirstOrDefault();
- return profileEntity == null ? null : new ProfileDescriptor(module, profileEntity);
- }
-
- public ProfileDescriptor CreateProfile(ProfileModule module, string name)
+ public ProfileDescriptor CreateProfileDescriptor(ProfileModule module, string name)
{
var profileEntity = new ProfileEntity {Id = Guid.NewGuid(), Name = name, PluginGuid = module.PluginInfo.Guid};
return new ProfileDescriptor(module, profileEntity);
@@ -72,31 +63,59 @@ namespace Artemis.Core.Services.Storage
public Profile ActivateProfile(ProfileDescriptor profileDescriptor)
{
- if (profileDescriptor.ProfileModule.ActiveProfile.EntityId == profileDescriptor.Id)
+ if (profileDescriptor.ProfileModule.ActiveProfile?.EntityId == profileDescriptor.Id)
return profileDescriptor.ProfileModule.ActiveProfile;
- var profile = new Profile(profileDescriptor.ProfileModule, profileDescriptor.ProfileEntity);
- InitializeLayerProperties(profile);
- InstantiateLayers(profile);
- InstantiateFolders(profile);
+ var profileEntity = _profileRepository.Get(profileDescriptor.Id);
+ var profile = new Profile(profileDescriptor.ProfileModule, profileEntity);
+ InstantiateProfile(profile);
profileDescriptor.ProfileModule.ChangeActiveProfile(profile, _surfaceService.ActiveSurface);
return profile;
}
+ public async Task ActivateProfileAnimated(ProfileDescriptor profileDescriptor)
+ {
+ if (profileDescriptor.ProfileModule.ActiveProfile?.EntityId == profileDescriptor.Id)
+ return profileDescriptor.ProfileModule.ActiveProfile;
+
+ var profileEntity = _profileRepository.Get(profileDescriptor.Id);
+ var profile = new Profile(profileDescriptor.ProfileModule, profileEntity);
+ InstantiateProfile(profile);
+
+ await profileDescriptor.ProfileModule.ChangeActiveProfileAnimated(profile, _surfaceService.ActiveSurface);
+ return profile;
+ }
+
public void ClearActiveProfile(ProfileModule module)
{
module.ChangeActiveProfile(null, _surfaceService.ActiveSurface);
}
+ public async Task ClearActiveProfileAnimated(ProfileModule module)
+ {
+ await module.ChangeActiveProfileAnimated(null, _surfaceService.ActiveSurface);
+ }
+
public void DeleteProfile(Profile profile)
{
_logger.Debug("Removing profile " + profile);
-
+ // If the given profile is currently active, disable it first (this also disposes it)
+ if (profile.Module.ActiveProfile == profile)
+ profile.Module.ChangeActiveProfile(null, _surfaceService.ActiveSurface);
+ else
+ profile.Dispose();
+
_profileRepository.Remove(profile.ProfileEntity);
}
+ public void DeleteProfile(ProfileDescriptor profileDescriptor)
+ {
+ var profileEntity = _profileRepository.Get(profileDescriptor.Id);
+ _profileRepository.Remove(profileEntity);
+ }
+
public void UpdateProfile(Profile profile, bool includeChildren)
{
_logger.Debug("Updating profile " + profile);
@@ -116,46 +135,73 @@ namespace Artemis.Core.Services.Storage
_profileRepository.Save(profile.ProfileEntity);
}
- public bool UndoUpdateProfile(Profile profile, ProfileModule module)
+ public bool UndoUpdateProfile(Profile profile)
{
- if (!profile.UndoStack.Any())
+ // Keep the profile from being rendered by locking it
+ lock (profile)
{
- _logger.Debug("Undo profile update - Failed, undo stack empty");
- return false;
- }
+ if (!profile.UndoStack.Any())
+ {
+ _logger.Debug("Undo profile update - Failed, undo stack empty");
+ return false;
+ }
- ActivateProfile(module, null);
- var top = profile.UndoStack.Pop();
- var memento = JsonConvert.SerializeObject(profile.ProfileEntity, MementoSettings);
- profile.RedoStack.Push(memento);
- profile.ProfileEntity = JsonConvert.DeserializeObject(top, MementoSettings);
- profile.ApplyToProfile();
- ActivateProfile(module, profile);
+ var top = profile.UndoStack.Pop();
+ var memento = JsonConvert.SerializeObject(profile.ProfileEntity, MementoSettings);
+ profile.RedoStack.Push(memento);
+ profile.ProfileEntity = JsonConvert.DeserializeObject(top, MementoSettings);
+
+ profile.ApplyToProfile();
+ InstantiateProfile(profile);
+ }
_logger.Debug("Undo profile update - Success");
return true;
}
- public bool RedoUpdateProfile(Profile profile, ProfileModule module)
+ public bool RedoUpdateProfile(Profile profile)
{
- if (!profile.RedoStack.Any())
+ // Keep the profile from being rendered by locking it
+ lock (profile)
{
- _logger.Debug("Redo profile update - Failed, redo empty");
- return false;
+ if (!profile.RedoStack.Any())
+ {
+ _logger.Debug("Redo profile update - Failed, redo empty");
+ return false;
+ }
+
+ var top = profile.RedoStack.Pop();
+ var memento = JsonConvert.SerializeObject(profile.ProfileEntity, MementoSettings);
+ profile.UndoStack.Push(memento);
+ profile.ProfileEntity = JsonConvert.DeserializeObject(top, MementoSettings);
+
+ profile.ApplyToProfile();
+ InstantiateProfile(profile);
+
+ _logger.Debug("Redo profile update - Success");
+ return true;
}
-
- ActivateProfile(module, null);
- var top = profile.RedoStack.Pop();
- var memento = JsonConvert.SerializeObject(profile.ProfileEntity, MementoSettings);
- profile.UndoStack.Push(memento);
- profile.ProfileEntity = JsonConvert.DeserializeObject(top, MementoSettings);
- profile.ApplyToProfile();
- ActivateProfile(module, profile);
-
- _logger.Debug("Redo profile update - Success");
- return true;
}
+ public ProfileDescriptor GetLastActiveProfile(ProfileModule module)
+ {
+ var moduleProfiles = _profileRepository.GetByPluginGuid(module.PluginInfo.Guid);
+ var profileEntity = moduleProfiles.FirstOrDefault(p => p.IsActive) ?? moduleProfiles.FirstOrDefault();
+ return profileEntity == null ? null : new ProfileDescriptor(module, profileEntity);
+ }
+
+ public void InstantiateProfile(Profile profile)
+ {
+ profile.PopulateLeds(_surfaceService.ActiveSurface);
+ InitializeLayerProperties(profile);
+ InstantiateLayers(profile);
+ InstantiateFolders(profile);
+ }
+
+ ///
+ /// Initializes the properties on the layers of the given profile
+ ///
+ ///
private void InitializeLayerProperties(Profile profile)
{
foreach (var layer in profile.GetAllLayers())
@@ -167,6 +213,9 @@ namespace Artemis.Core.Services.Storage
}
}
+ ///
+ /// Instantiates all plugin-related classes on the folders of the given profile
+ ///
private void InstantiateFolders(Profile profile)
{
foreach (var folder in profile.GetAllFolders())
@@ -182,6 +231,9 @@ namespace Artemis.Core.Services.Storage
}
}
+ ///
+ /// Instantiates all plugin-related classes on the layers of the given profile
+ ///
private void InstantiateLayers(Profile profile)
{
foreach (var layer in profile.GetAllLayers())
@@ -204,6 +256,10 @@ namespace Artemis.Core.Services.Storage
}
}
+ ///
+ /// Populates all missing LEDs on all currently active profiles
+ ///
+ ///
private void ActiveProfilesPopulateLeds(ArtemisSurface surface)
{
var profileModules = _pluginService.GetPluginsOfType();
@@ -211,6 +267,10 @@ namespace Artemis.Core.Services.Storage
profileModule.ActiveProfile.PopulateLeds(surface);
}
+
+ ///
+ /// Instantiates all missing plugin-related classes on the profile trees of all currently active profiles
+ ///
private void ActiveProfilesInstantiatePlugins()
{
var profileModules = _pluginService.GetPluginsOfType();
@@ -242,8 +302,8 @@ namespace Artemis.Core.Services.Storage
ActiveProfilesInstantiatePlugins();
else if (e.PluginInfo.Instance is ProfileModule profileModule)
{
- var activeProfile = GetActiveProfile(profileModule);
- ActivateProfile(profileModule, activeProfile);
+ var activeProfile = GetLastActiveProfile(profileModule);
+ ActivateProfile(activeProfile);
}
}
diff --git a/src/Artemis.Core/Utilities/IntroAnimation.cs b/src/Artemis.Core/Utilities/IntroAnimation.cs
new file mode 100644
index 000000000..d44860799
--- /dev/null
+++ b/src/Artemis.Core/Utilities/IntroAnimation.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Artemis.Core.Extensions;
+using Artemis.Core.Models.Profile;
+using Artemis.Core.Models.Surface;
+using Artemis.Core.Plugins.Abstract;
+using Artemis.Core.Plugins.Abstract.ViewModels;
+using Artemis.Core.Plugins.LayerBrush;
+using Artemis.Core.Services.Interfaces;
+using Artemis.Core.Services.Storage.Interfaces;
+using Artemis.Storage.Entities.Profile;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Serilog;
+using SkiaSharp;
+
+namespace Artemis.Core.Utilities
+{
+ internal class IntroAnimation
+ {
+ private readonly ILogger _logger;
+ private readonly IProfileService _profileService;
+ private readonly ISurfaceService _surfaceService;
+
+ public IntroAnimation(ILogger logger, IProfileService profileService, ISurfaceService surfaceService)
+ {
+ _logger = logger;
+ _profileService = profileService;
+ _surfaceService = surfaceService;
+ CreateIntroProfile();
+ }
+
+ private void CreateIntroProfile()
+ {
+ try
+ {
+ // Load the intro profile from JSON into a ProfileEntity
+ var json = File.ReadAllText(Path.Combine(Constants.ApplicationFolder, "Resources", "intro-profile.json"));
+ var profileEntity = JsonConvert.DeserializeObject(json);
+ // Inject every LED on the surface into each layer
+ foreach (var profileEntityLayer in profileEntity.Layers)
+ {
+ profileEntityLayer.Leds.AddRange(_surfaceService.ActiveSurface.Devices.SelectMany(d => d.Leds).Select(l => new LedEntity()
+ {
+ DeviceIdentifier = l.Device.RgbDevice.GetDeviceIdentifier(),
+ LedName = l.RgbLed.Id.ToString(),
+ }));
+ }
+
+ var profile = new Profile(new DummyModule(), profileEntity);
+ profile.Activate(_surfaceService.ActiveSurface);
+
+ _profileService.InstantiateProfile(profile);
+ AnimationProfile = profile;
+ }
+ catch (Exception e)
+ {
+ _logger.Warning(e, "Failed to load intro profile");
+ }
+ }
+
+ public Profile AnimationProfile { get; set; }
+
+ public void Render(double deltaTime, SKCanvas canvas, SKImageInfo bitmapInfo)
+ {
+ if (AnimationProfile == null)
+ return;
+
+ AnimationProfile.Update(deltaTime);
+ AnimationProfile.Render(deltaTime, canvas, bitmapInfo);
+ }
+ }
+
+ internal class DummyModule : ProfileModule
+ {
+ public override void EnablePlugin()
+ {
+ }
+
+ public override void DisablePlugin()
+ {
+ }
+
+ public override IEnumerable GetViewModels()
+ {
+ return new List();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/Services/Interfaces/IProfileEditorService.cs b/src/Artemis.UI.Shared/Services/Interfaces/IProfileEditorService.cs
index 67f315c49..4c2fa7b65 100644
--- a/src/Artemis.UI.Shared/Services/Interfaces/IProfileEditorService.cs
+++ b/src/Artemis.UI.Shared/Services/Interfaces/IProfileEditorService.cs
@@ -24,9 +24,9 @@ namespace Artemis.UI.Shared.Services.Interfaces
void ChangeSelectedProfileElement(RenderProfileElement profileElement);
void UpdateSelectedProfileElement();
void UpdateProfilePreview();
- bool UndoUpdateProfile(ProfileModule module);
- bool RedoUpdateProfile(ProfileModule module);
- Module GetCurrentModule();
+ bool UndoUpdateProfile();
+ bool RedoUpdateProfile();
+ ProfileModule GetCurrentModule();
///
/// Occurs when a new profile is selected
diff --git a/src/Artemis.UI.Shared/Services/ProfileEditorService.cs b/src/Artemis.UI.Shared/Services/ProfileEditorService.cs
index fb4c2bb02..ecbd0a28d 100644
--- a/src/Artemis.UI.Shared/Services/ProfileEditorService.cs
+++ b/src/Artemis.UI.Shared/Services/ProfileEditorService.cs
@@ -77,8 +77,9 @@ namespace Artemis.UI.Shared.Services
var profileElementEvent = new ProfileEventArgs(profile, SelectedProfile);
SelectedProfile = profile;
- UpdateProfilePreview();
+
OnSelectedProfileChanged(profileElementEvent);
+ UpdateProfilePreview();
}
}
@@ -88,8 +89,9 @@ namespace Artemis.UI.Shared.Services
{
_logger.Verbose("UpdateSelectedProfile {profile}", SelectedProfile);
_profileService.UpdateProfile(SelectedProfile, true);
- UpdateProfilePreview();
+
OnSelectedProfileChanged(new ProfileEventArgs(SelectedProfile));
+ UpdateProfilePreview();
}
}
@@ -132,13 +134,19 @@ namespace Artemis.UI.Shared.Services
OnProfilePreviewUpdated();
}
- public bool UndoUpdateProfile(ProfileModule module)
+ public bool UndoUpdateProfile()
{
- var undid = _profileService.UndoUpdateProfile(SelectedProfile, module);
+ var undid = _profileService.UndoUpdateProfile(SelectedProfile);
if (!undid)
return false;
+ if (SelectedProfileElement is Folder folder)
+ SelectedProfileElement = SelectedProfile.GetAllFolders().FirstOrDefault(f => f.EntityId == folder.EntityId);
+ else if (SelectedProfileElement is Layer layer)
+ SelectedProfileElement = SelectedProfile.GetAllLayers().FirstOrDefault(l => l.EntityId == layer.EntityId);
+
OnSelectedProfileChanged(new ProfileEventArgs(SelectedProfile, SelectedProfile));
+ OnSelectedProfileElementChanged(new RenderProfileElementEventArgs(SelectedProfileElement));
if (SelectedProfileElement != null)
{
@@ -152,9 +160,9 @@ namespace Artemis.UI.Shared.Services
return true;
}
- public bool RedoUpdateProfile(ProfileModule module)
+ public bool RedoUpdateProfile()
{
- var redid = _profileService.RedoUpdateProfile(SelectedProfile, module);
+ var redid = _profileService.RedoUpdateProfile(SelectedProfile);
if (!redid)
return false;
@@ -248,9 +256,9 @@ namespace Artemis.UI.Shared.Services
return time;
}
- public Module GetCurrentModule()
+ public ProfileModule GetCurrentModule()
{
- return (Module) SelectedProfile?.PluginInfo.Instance;
+ return SelectedProfile?.Module;
}
public event EventHandler ProfileSelected;
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsView.xaml
index 69087f4ce..b8b30d465 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsView.xaml
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsView.xaml
@@ -79,7 +79,7 @@
@@ -96,7 +96,7 @@
@@ -135,7 +135,7 @@
@@ -152,7 +152,7 @@
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs
index 8115186b5..b1195b782 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs
@@ -14,6 +14,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
private RenderProfileElement _renderProfileElement;
private DisplayConditionGroupViewModel _rootGroup;
private int _transitionerIndex;
+ private bool _displayContinuously;
+ private bool _alwaysFinishTimeline;
public DisplayConditionsViewModel(IProfileEditorService profileEditorService, IDisplayConditionsVmFactory displayConditionsVmFactory)
{
@@ -39,15 +41,22 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
set => SetAndNotify(ref _renderProfileElement, value);
}
- public int ConditionBehaviourIndex
+ public bool DisplayContinuously
{
- get => RenderProfileElement != null && RenderProfileElement.AlwaysFinishTimeline ? 0 : 1;
+ get => _displayContinuously;
set
{
- if (RenderProfileElement == null)
- return;
+ if (!SetAndNotify(ref _displayContinuously, value)) return;
+ _profileEditorService.UpdateSelectedProfileElement();
+ }
+ }
- RenderProfileElement.AlwaysFinishTimeline = value == 0;
+ public bool AlwaysFinishTimeline
+ {
+ get => _alwaysFinishTimeline;
+ set
+ {
+ if (!SetAndNotify(ref _alwaysFinishTimeline, value)) return;
_profileEditorService.UpdateSelectedProfileElement();
}
}
@@ -70,9 +79,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
private void ProfileEditorServiceOnProfileElementSelected(object sender, RenderProfileElementEventArgs e)
{
RenderProfileElement = e.RenderProfileElement;
- NotifyOfPropertyChange(nameof(ConditionBehaviourIndex));
NotifyOfPropertyChange(nameof(ConditionBehaviourEnabled));
+ _displayContinuously = RenderProfileElement?.DisplayContinuously ?? false;
+ NotifyOfPropertyChange(nameof(DisplayContinuously));
+ _alwaysFinishTimeline = RenderProfileElement?.AlwaysFinishTimeline ?? false;
+ NotifyOfPropertyChange(nameof(AlwaysFinishTimeline));
+
if (e.RenderProfileElement == null)
{
RootGroup?.Dispose();
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
index 4f9f1d7f3..0a846301d 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
@@ -209,7 +209,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
public List GetAllLayerPropertyGroupViewModels()
{
var groups = LayerPropertyGroups.ToList();
- groups.AddRange(groups.SelectMany(g => g.Children).Where(g => g is LayerPropertyGroupViewModel).Cast());
+ var toAdd = groups.SelectMany(g => g.Children).Where(g => g is LayerPropertyGroupViewModel).Cast().ToList();
+ groups.AddRange(toAdd);
return groups;
}
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs
index c3f85b376..506fb3b80 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs
@@ -9,6 +9,7 @@ using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree;
using Artemis.UI.Shared.Services.Interfaces;
+using Humanizer;
using Ninject;
using Ninject.Parameters;
@@ -42,6 +43,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
TreePropertyGroupViewModel = _layerPropertyVmFactory.TreePropertyGroupViewModel(this);
TimelinePropertyGroupViewModel = _layerPropertyVmFactory.TimelinePropertyGroupViewModel(this);
+ // Generate a fallback name if the description does not contain one
+ if (PropertyGroupDescription.Name == null)
+ {
+ var propertyInfo = LayerPropertyGroup.Parent?.GetType().GetProperties().FirstOrDefault(p => ReferenceEquals(p.GetValue(LayerPropertyGroup.Parent), LayerPropertyGroup));
+ if (propertyInfo != null)
+ PropertyGroupDescription.Name = propertyInfo.Name.Humanize();
+ else
+ PropertyGroupDescription.Name = "Unknown group";
+ }
+
LayerPropertyGroup.VisibilityChanged += LayerPropertyGroupOnVisibilityChanged;
PopulateChildren();
DetermineType();
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupView.xaml
index 55d53b651..6bd0b2e1f 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupView.xaml
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupView.xaml
@@ -21,7 +21,8 @@
Text="{Binding LayerPropertyGroupViewModel.PropertyGroupDescription.Name}"
ToolTip="{Binding LayerPropertyGroupViewModel.PropertyGroupDescription.Description}"
VerticalAlignment="Center"
- Margin="0 5">
+ HorizontalAlignment="Left"
+ Margin="3 5 0 5">