diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj index 5a94be1b2..a6bc2a87c 100644 --- a/src/Artemis.Core/Artemis.Core.csproj +++ b/src/Artemis.Core/Artemis.Core.csproj @@ -26,6 +26,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Artemis.Core/Models/Profile/Folder.cs b/src/Artemis.Core/Models/Profile/Folder.cs index 48b8bbe6a..732a581d7 100644 --- a/src/Artemis.Core/Models/Profile/Folder.cs +++ b/src/Artemis.Core/Models/Profile/Folder.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; -using Artemis.Core.Models.Profile.LayerShapes; +using Artemis.Core.Plugins.LayerEffect.Abstract; using Artemis.Storage.Entities.Profile; using SkiaSharp; @@ -8,6 +10,8 @@ namespace Artemis.Core.Models.Profile { public sealed class Folder : ProfileElement { + private readonly List _layerEffects; + public Folder(Profile profile, ProfileElement parent, string name) { FolderEntity = new FolderEntity(); @@ -16,6 +20,7 @@ namespace Artemis.Core.Models.Profile Profile = profile; Parent = parent; Name = name; + _layerEffects = new List(); } internal Folder(Profile profile, ProfileElement parent, FolderEntity folderEntity) @@ -27,6 +32,7 @@ namespace Artemis.Core.Models.Profile Parent = parent; Name = folderEntity.Name; Order = folderEntity.Order; + _layerEffects = new List(); // TODO: Load conditions @@ -45,6 +51,11 @@ namespace Artemis.Core.Models.Profile internal FolderEntity FolderEntity { get; set; } + /// + /// Gets a read-only collection of the layer effects on this layer + /// + public ReadOnlyCollection LayerEffects => _layerEffects.AsReadOnly(); + public override void Update(double deltaTime) { // Iterate the children in reverse because that's how they must be rendered too diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index cf1bdf273..4c72f6010 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; +using Artemis.Core.Annotations; using Artemis.Core.Extensions; using Artemis.Core.Models.Profile.LayerProperties; using Artemis.Core.Models.Profile.LayerProperties.Attributes; @@ -23,6 +24,7 @@ namespace Artemis.Core.Models.Profile public sealed class Layer : ProfileElement { private readonly List _expandedPropertyGroups; + private readonly List _layerEffects; private LayerShape _layerShape; private List _leds; private SKPath _path; @@ -38,6 +40,7 @@ namespace Artemis.Core.Models.Profile General = new LayerGeneralProperties {IsCorePropertyGroup = true}; Transform = new LayerTransformProperties {IsCorePropertyGroup = true}; + _layerEffects = new List(); _leds = new List(); _expandedPropertyGroups = new List(); @@ -56,6 +59,7 @@ namespace Artemis.Core.Models.Profile General = new LayerGeneralProperties {IsCorePropertyGroup = true}; Transform = new LayerTransformProperties {IsCorePropertyGroup = true}; + _layerEffects = new List(); _leds = new List(); _expandedPropertyGroups = new List(); _expandedPropertyGroups.AddRange(layerEntity.ExpandedPropertyGroups); @@ -65,6 +69,11 @@ namespace Artemis.Core.Models.Profile internal LayerEntity LayerEntity { get; set; } + /// + /// Gets a read-only collection of the layer effects on this layer + /// + public ReadOnlyCollection LayerEffects => _layerEffects.AsReadOnly(); + /// /// A collection of all the LEDs this layer is assigned to. /// @@ -116,11 +125,6 @@ namespace Artemis.Core.Models.Profile /// public BaseLayerBrush LayerBrush { get; internal set; } - /// - /// The layer effect that will apply pre- and/or post-processing to the layer - /// - public BaseLayerEffect LayerEffect { get; set; } - public override string ToString() { return $"[Layer] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}"; @@ -155,7 +159,22 @@ namespace Artemis.Core.Models.Profile General.ApplyToEntity(); Transform.ApplyToEntity(); LayerBrush?.BaseProperties.ApplyToEntity(); - LayerEffect?.BaseProperties.ApplyToEntity(); + + // Effects + LayerEntity.LayerEffects.Clear(); + foreach (var layerEffect in LayerEffects) + { + var layerEffectEntity = new LayerEffectEntity() + { + PluginGuid = layerEffect.PluginInfo.Guid, + EffectType = layerEffect.GetType().Name, + Name = layerEffect.Name, + HasBeenRenamed = layerEffect.HasBeenRenamed, + Order = layerEffect.Order + }; + LayerEntity.LayerEffects.Add(layerEffectEntity); + layerEffect.BaseProperties.ApplyToEntity(); + } // LEDs LayerEntity.Leds.Clear(); @@ -226,18 +245,21 @@ namespace Artemis.Core.Models.Profile General.Override(TimeSpan.Zero); Transform.Override(TimeSpan.Zero); LayerBrush.BaseProperties.Override(TimeSpan.Zero); - LayerEffect?.BaseProperties?.Override(TimeSpan.Zero); + foreach (var baseLayerEffect in LayerEffects) + baseLayerEffect.BaseProperties?.Override(TimeSpan.Zero); } else { General.Update(deltaTime); Transform.Update(deltaTime); LayerBrush.BaseProperties.Update(deltaTime); - LayerEffect?.BaseProperties?.Update(deltaTime); + foreach (var baseLayerEffect in LayerEffects) + baseLayerEffect.BaseProperties?.Update(deltaTime); } LayerBrush.Update(deltaTime); - LayerEffect?.Update(deltaTime); + foreach (var baseLayerEffect in LayerEffects) + baseLayerEffect.Update(deltaTime); } public void OverrideProgress(TimeSpan timeOverride) @@ -245,7 +267,8 @@ namespace Artemis.Core.Models.Profile General.Override(timeOverride); Transform.Override(timeOverride); LayerBrush?.BaseProperties?.Override(timeOverride); - LayerEffect?.BaseProperties?.Override(timeOverride); + foreach (var baseLayerEffect in LayerEffects) + baseLayerEffect.BaseProperties?.Override(timeOverride); } /// @@ -266,7 +289,8 @@ namespace Artemis.Core.Models.Profile paint.BlendMode = General.BlendMode.CurrentValue; paint.Color = new SKColor(0, 0, 0, (byte) (Transform.Opacity.CurrentValue * 2.55f)); - LayerEffect?.PreProcess(canvas, canvasInfo, Path, paint); + foreach (var baseLayerEffect in LayerEffects) + baseLayerEffect.PreProcess(canvas, canvasInfo, Path, paint); if (!LayerBrush.SupportsTransformation) SimpleRender(canvas, canvasInfo, paint); @@ -275,7 +299,8 @@ namespace Artemis.Core.Models.Profile else if (General.FillType.CurrentValue == LayerFillType.Clip) ClipRender(canvas, canvasInfo, paint); - LayerEffect?.PostProcess(canvas, canvasInfo, Path, paint); + foreach (var baseLayerEffect in LayerEffects) + baseLayerEffect.PostProcess(canvas, canvasInfo, Path, paint); } canvas.Restore(); @@ -382,6 +407,10 @@ namespace Artemis.Core.Models.Profile #endregion + #region Effect management + + #endregion + #region LED management /// @@ -423,36 +452,6 @@ namespace Artemis.Core.Models.Profile CalculateRenderProperties(); } - internal void Deactivate() - { - DeactivateLayerBrush(); - DeactivateLayerEffect(); - } - - internal void DeactivateLayerBrush() - { - if (LayerBrush == null) - return; - - var brush = LayerBrush; - LayerBrush = null; - brush.Dispose(); - - LayerEntity.PropertyEntities.RemoveAll(p => p.PluginGuid == brush.PluginInfo.Guid && p.Path.StartsWith("LayerBrush.")); - } - - internal void DeactivateLayerEffect() - { - if (LayerEffect == null) - return; - - var effect = LayerEffect; - LayerEffect = null; - effect.Dispose(); - - LayerEntity.PropertyEntities.RemoveAll(p => p.PluginGuid == effect.PluginInfo.Guid && p.Path.StartsWith("LayerEffect.")); - } - internal void PopulateLeds(ArtemisSurface surface) { var leds = new List(); @@ -473,12 +472,80 @@ namespace Artemis.Core.Models.Profile #endregion + #region Activation + + internal void Deactivate() + { + DeactivateLayerBrush(); + var layerEffects = new List(LayerEffects); + foreach (var baseLayerEffect in layerEffects) + DeactivateLayerEffect(baseLayerEffect); + } + + private void DeactivateLayerBrush() + { + if (LayerBrush == null) + return; + + var brush = LayerBrush; + LayerBrush = null; + brush.Dispose(); + } + + private void DeactivateLayerEffect([NotNull] BaseLayerEffect effect) + { + if (effect == null) throw new ArgumentNullException(nameof(effect)); + + // Remove the effect from the layer and dispose it + _layerEffects.Remove(effect); + effect.Dispose(); + } + + internal void RemoveLayerBrush() + { + if (LayerBrush == null) + return; + + var brush = LayerBrush; + DeactivateLayerBrush(); + LayerEntity.PropertyEntities.RemoveAll(p => p.PluginGuid == brush.PluginInfo.Guid && p.Path.StartsWith("LayerBrush.")); + } + + internal void RemoveLayerEffect([NotNull] BaseLayerEffect effect) + { + if (effect == null) throw new ArgumentNullException(nameof(effect)); + + DeactivateLayerEffect(effect); + + // Clean up properties + LayerEntity.PropertyEntities.RemoveAll(p => p.PluginGuid == effect.PluginInfo.Guid && p.Path.StartsWith(effect.PropertyRootPath)); + + // Update the order on the remaining effects + var index = 0; + foreach (var baseLayerEffect in LayerEffects.OrderBy(e => e.Order)) + { + baseLayerEffect.UpdateOrder(index + 1); + index++; + } + + OnLayerEffectsUpdated(); + } + + internal void AddLayerEffect([NotNull] BaseLayerEffect effect) + { + if (effect == null) throw new ArgumentNullException(nameof(effect)); + _layerEffects.Add(effect); + OnLayerEffectsUpdated(); + } + + #endregion + #region Events public event EventHandler RenderPropertiesUpdated; public event EventHandler ShapePropertiesUpdated; public event EventHandler LayerBrushUpdated; - public event EventHandler LayerEffectUpdated; + public event EventHandler LayerEffectsUpdated; private void OnRenderPropertiesUpdated() { @@ -495,9 +562,9 @@ namespace Artemis.Core.Models.Profile LayerBrushUpdated?.Invoke(this, EventArgs.Empty); } - internal void OnLayerEffectUpdated() + internal void OnLayerEffectsUpdated() { - LayerEffectUpdated?.Invoke(this, EventArgs.Empty); + LayerEffectsUpdated?.Invoke(this, EventArgs.Empty); } #endregion diff --git a/src/Artemis.Core/Models/Profile/LayerEffectReference.cs b/src/Artemis.Core/Models/Profile/LayerEffectReference.cs deleted file mode 100644 index b0aa157a0..000000000 --- a/src/Artemis.Core/Models/Profile/LayerEffectReference.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using Artemis.Core.Plugins.LayerEffect; - -namespace Artemis.Core.Models.Profile -{ - /// - /// A reference to a - /// - public class LayerEffectReference - { - /// - /// The GUID of the plugin the effect descriptor resides in - /// - public Guid EffectPluginGuid { get; set; } - - /// - /// The full type name of the effect descriptor - /// - public string EffectType { get; set; } - } -} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerGeneralProperties.cs b/src/Artemis.Core/Models/Profile/LayerGeneralProperties.cs index a2e3cf51b..fe819758d 100644 --- a/src/Artemis.Core/Models/Profile/LayerGeneralProperties.cs +++ b/src/Artemis.Core/Models/Profile/LayerGeneralProperties.cs @@ -17,10 +17,7 @@ namespace Artemis.Core.Models.Profile [PropertyDescription(Name = "Brush type", Description = "The type of brush to use for this layer")] public LayerBrushReferenceLayerProperty BrushReference { get; set; } - - [PropertyDescription(Name = "Effect type", Description = "The type of effect to use for this layer")] - public LayerEffectReferenceLayerProperty EffectReference { get; set; } - + protected override void PopulateDefaults() { ShapeType.DefaultValue = LayerShapeType.Rectangle; diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/Types/LayerEffectReferenceLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/Types/LayerEffectReferenceLayerProperty.cs deleted file mode 100644 index 6162ce42e..000000000 --- a/src/Artemis.Core/Models/Profile/LayerProperties/Types/LayerEffectReferenceLayerProperty.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Artemis.Core.Exceptions; - -namespace Artemis.Core.Models.Profile.LayerProperties.Types -{ - /// - /// A special layer property used to configure the selected layer effect - /// - public class LayerEffectReferenceLayerProperty : LayerProperty - { - internal LayerEffectReferenceLayerProperty() - { - KeyframesSupported = false; - } - - protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased) - { - throw new ArtemisCoreException("Layer effect references do not support keyframes."); - } - - public static implicit operator LayerEffectReference(LayerEffectReferenceLayerProperty p) => p.CurrentValue; - } -} \ 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 d2e849fbe..7c027d696 100644 --- a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs +++ b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs @@ -233,7 +233,14 @@ namespace Artemis.Core.Models.Profile private void InitializeProperty(Layer layer, string path, BaseLayerProperty instance) { - var pluginGuid = IsCorePropertyGroup || instance.IsCoreProperty ? Constants.CorePluginInfo.Guid : layer.LayerBrush.PluginInfo.Guid; + Guid pluginGuid; + if (IsCorePropertyGroup || instance.IsCoreProperty) + pluginGuid = Constants.CorePluginInfo.Guid; + else if (instance.Parent.LayerBrush != null) + pluginGuid = instance.Parent.LayerBrush.PluginInfo.Guid; + else + pluginGuid = instance.Parent.LayerEffect.PluginInfo.Guid; + var entity = layer.LayerEntity.PropertyEntities.FirstOrDefault(p => p.PluginGuid == pluginGuid && p.Path == path); var fromStorage = true; if (entity == null) @@ -273,5 +280,20 @@ namespace Artemis.Core.Models.Profile } #endregion + + public void UpdateOrder(int oldOrder) + { + // Expanded state is tied to the path so save it before changing the path + var expanded = Layer.IsPropertyGroupExpanded(this); + Layer.SetPropertyGroupExpanded(this, false); + + Path = Path.Replace($"LayerEffect.{oldOrder}.", $"LayerEffect.{LayerEffect.Order}."); + // Restore the expanded state with the new path + Layer.SetPropertyGroupExpanded(this, expanded); + + // Update children + foreach (var layerPropertyGroup in LayerPropertyGroups) + layerPropertyGroup.UpdateOrder(oldOrder); + } } } \ No newline at end of file diff --git a/src/Artemis.Core/Plugins/Abstract/LayerBrushProvider.cs b/src/Artemis.Core/Plugins/Abstract/LayerBrushProvider.cs index 966cfe431..5a87c0e1d 100644 --- a/src/Artemis.Core/Plugins/Abstract/LayerBrushProvider.cs +++ b/src/Artemis.Core/Plugins/Abstract/LayerBrushProvider.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Collections.ObjectModel; using Artemis.Core.Plugins.Exceptions; using Artemis.Core.Plugins.LayerBrush; @@ -17,6 +18,7 @@ namespace Artemis.Core.Plugins.Abstract protected LayerBrushProvider() { _layerBrushDescriptors = new List(); + PluginDisabled += OnPluginDisabled; } /// @@ -42,5 +44,10 @@ namespace Artemis.Core.Plugins.Abstract _layerBrushDescriptors.Add(new LayerBrushDescriptor(displayName, description, icon, typeof(T), this)); } + + private void OnPluginDisabled(object sender, EventArgs e) + { + _layerBrushDescriptors.Clear(); + } } } \ No newline at end of file diff --git a/src/Artemis.Core/Plugins/Abstract/LayerEffectProvider.cs b/src/Artemis.Core/Plugins/Abstract/LayerEffectProvider.cs index 86140bfb8..2d2d0a188 100644 --- a/src/Artemis.Core/Plugins/Abstract/LayerEffectProvider.cs +++ b/src/Artemis.Core/Plugins/Abstract/LayerEffectProvider.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Collections.ObjectModel; using Artemis.Core.Plugins.Exceptions; using Artemis.Core.Plugins.LayerEffect; @@ -17,6 +18,7 @@ namespace Artemis.Core.Plugins.Abstract protected LayerEffectProvider() { _layerEffectDescriptors = new List(); + PluginDisabled += OnPluginDisabled; } /// @@ -42,5 +44,10 @@ namespace Artemis.Core.Plugins.Abstract _layerEffectDescriptors.Add(new LayerEffectDescriptor(displayName, description, icon, typeof(T), this)); } + + private void OnPluginDisabled(object sender, EventArgs e) + { + _layerEffectDescriptors.Clear(); + } } } \ No newline at end of file diff --git a/src/Artemis.Core/Plugins/LayerBrush/Abstract/BaseLayerBrush.cs b/src/Artemis.Core/Plugins/LayerBrush/Abstract/BaseLayerBrush.cs index f983fe4ac..84113e5f1 100644 --- a/src/Artemis.Core/Plugins/LayerBrush/Abstract/BaseLayerBrush.cs +++ b/src/Artemis.Core/Plugins/LayerBrush/Abstract/BaseLayerBrush.cs @@ -4,13 +4,14 @@ using Artemis.Core.Plugins.Exceptions; using Artemis.Core.Plugins.Models; using Artemis.Core.Services.Interfaces; using SkiaSharp; +using Stylet; namespace Artemis.Core.Plugins.LayerBrush.Abstract { /// /// For internal use only, please use or or instead /// - public abstract class BaseLayerBrush : IDisposable + public abstract class BaseLayerBrush : PropertyChangedBase, IDisposable { private bool _supportsTransformation = true; @@ -48,7 +49,7 @@ namespace Artemis.Core.Plugins.LayerBrush.Abstract get => _supportsTransformation; protected set { - if (BrushType == LayerBrushType.RgbNet) + if (value && BrushType == LayerBrushType.RgbNet) throw new ArtemisPluginException(PluginInfo, "An RGB.NET brush cannot support transformation"); _supportsTransformation = value; } diff --git a/src/Artemis.Core/Plugins/LayerEffect/Abstract/BaseLayerEffect.cs b/src/Artemis.Core/Plugins/LayerEffect/Abstract/BaseLayerEffect.cs index 96909b9a6..2c01cbc6d 100644 --- a/src/Artemis.Core/Plugins/LayerEffect/Abstract/BaseLayerEffect.cs +++ b/src/Artemis.Core/Plugins/LayerEffect/Abstract/BaseLayerEffect.cs @@ -3,13 +3,14 @@ using Artemis.Core.Models.Profile; using Artemis.Core.Plugins.Models; using Artemis.Core.Services.Interfaces; using SkiaSharp; +using Stylet; namespace Artemis.Core.Plugins.LayerEffect.Abstract { /// /// For internal use only, please use instead /// - public abstract class BaseLayerEffect : IDisposable + public abstract class BaseLayerEffect : PropertyChangedBase, IDisposable { /// /// Gets the layer this effect is applied to @@ -21,6 +22,22 @@ namespace Artemis.Core.Plugins.LayerEffect.Abstract /// public Folder Folder { get; internal set; } + /// + /// The name which appears in the editor + /// + public string Name { get; set; } + + /// + /// Gets or sets whether the effect has been renamed by the user, if true consider refraining from changing the name + /// programatically + /// + public bool HasBeenRenamed { get; set; } + + /// + /// Gets the order in which this effect appears in the update loop and editor + /// + public int Order { get; internal set; } + /// /// Gets the descriptor of this effect /// @@ -36,6 +53,8 @@ namespace Artemis.Core.Plugins.LayerEffect.Abstract /// public virtual LayerPropertyGroup BaseProperties => null; + internal string PropertyRootPath => $"LayerEffect.{Order}.{GetType().Name}."; + public void Dispose() { DisableLayerEffect(); @@ -67,6 +86,16 @@ namespace Artemis.Core.Plugins.LayerEffect.Abstract /// public abstract void PostProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint); + public void UpdateOrder(int newOrder) + { + if (newOrder == Order) + return; + + var oldOrder = Order; + Order = newOrder; + BaseProperties.UpdateOrder(oldOrder); + } + internal void InternalPreProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint) { // Move the canvas to the top-left of the render path diff --git a/src/Artemis.Core/Plugins/LayerEffect/Abstract/LayerEffect.cs b/src/Artemis.Core/Plugins/LayerEffect/Abstract/LayerEffect.cs index 2f82d6ead..662310ff9 100644 --- a/src/Artemis.Core/Plugins/LayerEffect/Abstract/LayerEffect.cs +++ b/src/Artemis.Core/Plugins/LayerEffect/Abstract/LayerEffect.cs @@ -39,7 +39,7 @@ namespace Artemis.Core.Plugins.LayerEffect.Abstract { Properties = Activator.CreateInstance(); Properties.LayerEffect = this; - Properties.InitializeProperties(layerService, Layer, "LayerEffect."); + Properties.InitializeProperties(layerService, Layer, PropertyRootPath); PropertiesInitialized = true; EnableLayerEffect(); diff --git a/src/Artemis.Core/Services/Interfaces/ILayerService.cs b/src/Artemis.Core/Services/Interfaces/ILayerService.cs index 8132471aa..f30c1ded8 100644 --- a/src/Artemis.Core/Services/Interfaces/ILayerService.cs +++ b/src/Artemis.Core/Services/Interfaces/ILayerService.cs @@ -3,13 +3,14 @@ using Artemis.Core.Plugins.LayerBrush; using Artemis.Core.Plugins.LayerBrush.Abstract; using Artemis.Core.Plugins.LayerEffect; using Artemis.Core.Plugins.LayerEffect.Abstract; +using Artemis.Storage.Entities.Profile; namespace Artemis.Core.Services.Interfaces { public interface ILayerService : IArtemisService { /// - /// Creates a new layer + /// Creates a new layer /// /// /// @@ -28,11 +29,20 @@ namespace Artemis.Core.Services.Interfaces /// /// Instantiates and adds the described by the provided - /// - /// to the . + /// to the . /// /// The layer to instantiate the effect for + void InstantiateLayerEffects(Layer layer); + + /// + /// Adds the described by the provided to the + /// . + /// + /// The layer to instantiate the effect for + /// /// - BaseLayerEffect InstantiateLayerEffect(Layer layer); + BaseLayerEffect AddLayerEffect(Layer layer, LayerEffectDescriptor layerEffectDescriptor); + + void RemoveLayerEffect(BaseLayerEffect layerEffect); } } \ No newline at end of file diff --git a/src/Artemis.Core/Services/LayerService.cs b/src/Artemis.Core/Services/LayerService.cs index fefdafb71..21a8f7586 100644 --- a/src/Artemis.Core/Services/LayerService.cs +++ b/src/Artemis.Core/Services/LayerService.cs @@ -1,13 +1,17 @@ using System.Collections.Generic; using System.Linq; +using System.Windows.Documents; using Artemis.Core.Exceptions; using Artemis.Core.Models.Profile; using Artemis.Core.Plugins.Abstract; using Artemis.Core.Plugins.LayerBrush; using Artemis.Core.Plugins.LayerBrush.Abstract; +using Artemis.Core.Plugins.LayerEffect; using Artemis.Core.Plugins.LayerEffect.Abstract; using Artemis.Core.Services.Interfaces; +using Artemis.Storage.Entities.Profile; using Ninject; +using Ninject.Injection; using Ninject.Parameters; using Serilog; @@ -37,14 +41,15 @@ namespace Artemis.Core.Services // With the properties loaded, the layer brush and effect can be instantiated InstantiateLayerBrush(layer); - InstantiateLayerEffect(layer); + InstantiateLayerEffects(layer); return layer; } public BaseLayerBrush InstantiateLayerBrush(Layer layer) { - layer.DeactivateLayerBrush(); + if (layer.LayerBrush != null) + throw new ArtemisCoreException("Layer already has an instantiated layer brush"); var descriptorReference = layer.General.BrushReference?.CurrentValue; if (descriptorReference == null) @@ -58,46 +63,72 @@ namespace Artemis.Core.Services if (descriptor == null) return null; - + var brush = (BaseLayerBrush) _kernel.Get(descriptor.LayerBrushType); brush.Layer = layer; brush.Descriptor = descriptor; - layer.LayerBrush = brush; - brush.Initialize(this); brush.Update(0); + + layer.LayerBrush = brush; layer.OnLayerBrushUpdated(); return brush; } - public BaseLayerEffect InstantiateLayerEffect(Layer layer) + public void InstantiateLayerEffects(Layer layer) { - layer.DeactivateLayerEffect(); + if (layer.LayerEffects.Any()) + throw new ArtemisCoreException("Layer already has instantiated layer effects"); - var descriptorReference = layer.General.EffectReference?.CurrentValue; - if (descriptorReference == null) - return null; + foreach (var layerEntityLayerEffect in layer.LayerEntity.LayerEffects.OrderByDescending(e => e.Order)) + { + // Get a matching descriptor + var layerEffectProviders = _pluginService.GetPluginsOfType(); + var descriptors = layerEffectProviders.SelectMany(l => l.LayerEffectDescriptors).ToList(); + var descriptor = descriptors.FirstOrDefault(d => d.LayerEffectProvider.PluginInfo.Guid == layerEntityLayerEffect.PluginGuid && + d.LayerEffectType.Name == layerEntityLayerEffect.EffectType); - // Get a matching descriptor - var layerEffectProviders = _pluginService.GetPluginsOfType(); - var descriptors = layerEffectProviders.SelectMany(l => l.LayerEffectDescriptors).ToList(); - var descriptor = descriptors.FirstOrDefault(d => d.LayerEffectProvider.PluginInfo.Guid == descriptorReference.EffectPluginGuid && - d.LayerEffectType.Name == descriptorReference.EffectType); + if (descriptor == null) + continue; - if (descriptor == null) - return null; + var effect = (BaseLayerEffect) _kernel.Get(descriptor.LayerEffectType); + effect.Layer = layer; + effect.Order = layerEntityLayerEffect.Order; + effect.Name = layerEntityLayerEffect.Name; + effect.Descriptor = descriptor; + effect.Initialize(this); + effect.Update(0); - var effect = (BaseLayerEffect)_kernel.Get(descriptor.LayerEffectType); + layer.AddLayerEffect(effect); + _logger.Debug("Added layer effect with root path {rootPath}", effect.PropertyRootPath); + } + + layer.OnLayerEffectsUpdated(); + } + + public BaseLayerEffect AddLayerEffect(Layer layer, LayerEffectDescriptor layerEffectDescriptor) + { + var effect = (BaseLayerEffect) _kernel.Get(layerEffectDescriptor.LayerEffectType); effect.Layer = layer; - effect.Descriptor = descriptor; - layer.LayerEffect = effect; + effect.Order = layer.LayerEffects.Count + 1; + effect.Descriptor = layerEffectDescriptor; effect.Initialize(this); effect.Update(0); - layer.OnLayerEffectUpdated(); + layer.AddLayerEffect(effect); + _logger.Debug("Added layer effect with root path {rootPath}", effect.PropertyRootPath); + + layer.OnLayerEffectsUpdated(); return effect; } + + public void RemoveLayerEffect(BaseLayerEffect layerEffect) + { + // // Make sure the group is collapsed or the effect that gets this effect's order gets expanded + // layerEffect.Layer.SetPropertyGroupExpanded(layerEffect.BaseProperties, false); + layerEffect.Layer.RemoveLayerEffect(layerEffect); + } } } \ 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 f694508ae..d06ab2951 100644 --- a/src/Artemis.Core/Services/Storage/ProfileService.cs +++ b/src/Artemis.Core/Services/Storage/ProfileService.cs @@ -179,10 +179,8 @@ namespace Artemis.Core.Services.Storage // Only instantiate brushes for layers without an existing brush/effect instance foreach (var layer in profile.GetAllLayers()) { - if (layer.LayerBrush == null) - _layerService.InstantiateLayerBrush(layer); - if (layer.LayerEffect == null) - _layerService.InstantiateLayerEffect(layer); + _layerService.InstantiateLayerBrush(layer); + _layerService.InstantiateLayerEffects(layer); } } diff --git a/src/Artemis.Storage/Entities/Profile/LayerEffectEntity.cs b/src/Artemis.Storage/Entities/Profile/LayerEffectEntity.cs new file mode 100644 index 000000000..ce7239258 --- /dev/null +++ b/src/Artemis.Storage/Entities/Profile/LayerEffectEntity.cs @@ -0,0 +1,13 @@ +using System; + +namespace Artemis.Storage.Entities.Profile +{ + public class LayerEffectEntity + { + public Guid PluginGuid { get; set; } + public string EffectType { get; set; } + public string Name { get; set; } + public bool HasBeenRenamed { get; set; } + public int Order { get; set; } + } +} \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/Profile/LayerEntity.cs b/src/Artemis.Storage/Entities/Profile/LayerEntity.cs index d3ab661bd..f721480c2 100644 --- a/src/Artemis.Storage/Entities/Profile/LayerEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/LayerEntity.cs @@ -12,6 +12,7 @@ namespace Artemis.Storage.Entities.Profile Leds = new List(); PropertyEntities = new List(); Condition = new List(); + LayerEffects = new List(); ExpandedPropertyGroups = new List(); } @@ -24,6 +25,7 @@ namespace Artemis.Storage.Entities.Profile public List Leds { get; set; } public List PropertyEntities { get; set; } public List Condition { get; set; } + public List LayerEffects { get; set; } public List ExpandedPropertyGroups { get; set; } [BsonRef("ProfileEntity")] @@ -31,4 +33,6 @@ namespace Artemis.Storage.Entities.Profile public Guid ProfileId { get; set; } } + + } \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj b/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj index 4714f8226..d003a657a 100644 --- a/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj +++ b/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj @@ -20,6 +20,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj index 0b3b09ceb..e461d9c69 100644 --- a/src/Artemis.UI/Artemis.UI.csproj +++ b/src/Artemis.UI/Artemis.UI.csproj @@ -8,7 +8,7 @@ Artemis en-US Adds third-party support for RGB keyboards to games. - Copyright © Robert Beekman - 2019 + Copyright © Robert Beekman - 2020 1.0.0.0 2.0.0.0 true @@ -117,6 +117,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Artemis.UI/Behaviors/MouseBehaviour.cs b/src/Artemis.UI/Behaviors/MouseBehaviour.cs new file mode 100644 index 000000000..806822804 --- /dev/null +++ b/src/Artemis.UI/Behaviors/MouseBehaviour.cs @@ -0,0 +1,39 @@ +using System.Windows; +using System.Windows.Input; + +namespace Artemis.UI.Behaviors +{ + public class MouseBehaviour + { + public static readonly DependencyProperty MouseUpCommandProperty = + DependencyProperty.RegisterAttached("MouseUpCommand", typeof(ICommand), + typeof(MouseBehaviour), new FrameworkPropertyMetadata( + MouseUpCommandChanged)); + + public static void SetMouseUpCommand(UIElement element, ICommand value) + { + element.SetValue(MouseUpCommandProperty, value); + } + + public static ICommand GetMouseUpCommand(UIElement element) + { + return (ICommand) element.GetValue(MouseUpCommandProperty); + } + + private static void MouseUpCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var element = (FrameworkElement) d; + + element.MouseUp += element_MouseUp; + } + + private static void element_MouseUp(object sender, MouseButtonEventArgs e) + { + var element = (FrameworkElement) sender; + + var command = GetMouseUpCommand(element); + + command.Execute(e); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Ninject/Factories/IVMFactory.cs b/src/Artemis.UI/Ninject/Factories/IVMFactory.cs index 1da8ef7dc..911a49d05 100644 --- a/src/Artemis.UI/Ninject/Factories/IVMFactory.cs +++ b/src/Artemis.UI/Ninject/Factories/IVMFactory.cs @@ -1,11 +1,18 @@ using Artemis.Core.Models.Profile; +using Artemis.Core.Models.Profile.LayerProperties.Attributes; using Artemis.Core.Models.Surface; using Artemis.Core.Plugins.Abstract; using Artemis.UI.Screens.Module; using Artemis.UI.Screens.Module.ProfileEditor; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.LayerEffects; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree; using Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem; using Artemis.UI.Screens.Module.ProfileEditor.Visualization; using Artemis.UI.Screens.Settings.Tabs.Devices; +using Stylet; namespace Artemis.UI.Ninject.Factories { @@ -43,4 +50,14 @@ namespace Artemis.UI.Ninject.Factories { ProfileLayerViewModel Create(Layer layer); } + + public interface ILayerPropertyVmFactory : IVmFactory + { + LayerPropertyGroupViewModel LayerPropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, PropertyGroupDescriptionAttribute propertyGroupDescription); + TreeViewModel TreeViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection layerPropertyGroups); + EffectsViewModel EffectsViewModel(LayerPropertiesViewModel layerPropertiesViewModel); + TimelineViewModel TimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection layerPropertyGroups); + TreePropertyGroupViewModel TreePropertyGroupViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel); + TimelinePropertyGroupViewModel TimelinePropertyGroupViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel); + } } \ No newline at end of file diff --git a/src/Artemis.UI/PropertyInput/EffectPropertyInputView.xaml b/src/Artemis.UI/PropertyInput/EffectPropertyInputView.xaml deleted file mode 100644 index cd29f5b29..000000000 --- a/src/Artemis.UI/PropertyInput/EffectPropertyInputView.xaml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Artemis.UI/PropertyInput/EffectPropertyInputViewModel.cs b/src/Artemis.UI/PropertyInput/EffectPropertyInputViewModel.cs deleted file mode 100644 index 841e97ed7..000000000 --- a/src/Artemis.UI/PropertyInput/EffectPropertyInputViewModel.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Artemis.Core.Events; -using Artemis.Core.Models.Profile; -using Artemis.Core.Models.Profile.LayerProperties; -using Artemis.Core.Plugins.Abstract; -using Artemis.Core.Plugins.LayerEffect; -using Artemis.Core.Services.Interfaces; -using Artemis.UI.Shared.PropertyInput; -using Artemis.UI.Shared.Services.Interfaces; - -namespace Artemis.UI.PropertyInput -{ - public class EffectPropertyInputViewModel : PropertyInputViewModel - { - private readonly ILayerService _layerService; - private readonly IPluginService _pluginService; - - public EffectPropertyInputViewModel(LayerProperty layerProperty, IProfileEditorService profileEditorService, - ILayerService layerService, IPluginService pluginService) : base(layerProperty, profileEditorService) - { - _layerService = layerService; - _pluginService = pluginService; - - _pluginService.PluginEnabled += PluginServiceOnPluginLoaded; - _pluginService.PluginDisabled += PluginServiceOnPluginLoaded; - UpdateEnumValues(); - } - - public List Descriptors { get; set; } - - public LayerEffectDescriptor SelectedDescriptor - { - get => Descriptors.FirstOrDefault(d => d.LayerEffectProvider.PluginInfo.Guid == InputValue?.EffectPluginGuid && d.LayerEffectType.Name == InputValue?.EffectType); - set => SetEffectByDescriptor(value); - } - - public void UpdateEnumValues() - { - var layerEffectProviders = _pluginService.GetPluginsOfType(); - Descriptors = layerEffectProviders.SelectMany(l => l.LayerEffectDescriptors).ToList(); - NotifyOfPropertyChange(nameof(SelectedDescriptor)); - } - - - public override void Dispose() - { - _pluginService.PluginEnabled -= PluginServiceOnPluginLoaded; - _pluginService.PluginDisabled -= PluginServiceOnPluginLoaded; - base.Dispose(); - } - - protected override void OnInputValueApplied() - { - _layerService.InstantiateLayerEffect(LayerProperty.Layer); - } - - private void SetEffectByDescriptor(LayerEffectDescriptor value) - { - InputValue = new LayerEffectReference {EffectPluginGuid = value.LayerEffectProvider.PluginInfo.Guid, EffectType = value.LayerEffectType.Name}; - } - - private void PluginServiceOnPluginLoaded(object sender, PluginEventArgs e) - { - UpdateEnumValues(); - } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/RenameView.xaml similarity index 94% rename from src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameView.xaml rename to src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/RenameView.xaml index e93b00e78..8b8aeb136 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/RenameView.xaml @@ -1,4 +1,4 @@ - - Rename profile element + + - /// Interaction logic for ProfileElementRenameView.xaml + /// Interaction logic for RenameView.xaml /// - public partial class ProfileElementRenameView : UserControl + public partial class RenameView : UserControl { - public ProfileElementRenameView() + public RenameView() { InitializeComponent(); } diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/RenameViewModel.cs similarity index 71% rename from src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameViewModel.cs rename to src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/RenameViewModel.cs index 10794d99b..ad8b97bdf 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/RenameViewModel.cs @@ -6,13 +6,15 @@ using Stylet; namespace Artemis.UI.Screens.Module.ProfileEditor.Dialogs { - public class ProfileElementRenameViewModel : DialogViewModelBase + public class RenameViewModel : DialogViewModelBase { - public ProfileElementRenameViewModel(IModelValidator validator, ProfileElement profileElement) : base(validator) + public RenameViewModel(IModelValidator validator, string subject, string currentName) : base(validator) { - ElementName = profileElement.Name; + Subject = subject; + ElementName = currentName; } + public string Subject { get; } public string ElementName { get; set; } public async Task Accept() @@ -31,7 +33,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Dialogs } } - public class ProfileElementRenameViewModelValidator : AbstractValidator + public class ProfileElementRenameViewModelValidator : AbstractValidator { public ProfileElementRenameViewModelValidator() { diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerEffects/EffectsView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerEffects/EffectsView.xaml new file mode 100644 index 000000000..0e006d289 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerEffects/EffectsView.xaml @@ -0,0 +1,51 @@ + + + + + + + Looks like you have no effects installed or enabled! + + + Effects will apply some sort of post- or pre-processing to layers or even entire folders. + Think of things like blur, black & white but also audio visualization etc. + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerEffects/EffectsViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerEffects/EffectsViewModel.cs new file mode 100644 index 000000000..74fd252fa --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerEffects/EffectsViewModel.cs @@ -0,0 +1,50 @@ +using System.Linq; +using Artemis.Core.Plugins.Abstract; +using Artemis.Core.Plugins.LayerEffect; +using Artemis.Core.Services.Interfaces; +using Stylet; + +namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.LayerEffects +{ + public class EffectsViewModel : PropertyChangedBase + { + private readonly ILayerService _layerService; + private readonly IPluginService _pluginService; + + public EffectsViewModel(LayerPropertiesViewModel layerPropertiesViewModel, IPluginService pluginService, ILayerService layerService) + { + _pluginService = pluginService; + _layerService = layerService; + LayerPropertiesViewModel = layerPropertiesViewModel; + LayerEffectDescriptors = new BindableCollection(); + } + + public LayerPropertiesViewModel LayerPropertiesViewModel { get; } + + public BindableCollection LayerEffectDescriptors { get; set; } + public bool HasLayerEffectDescriptors => LayerEffectDescriptors.Any(); + + public LayerEffectDescriptor SelectedLayerEffectDescriptor + { + get => null; + set => AddLayerEffect(value); + } + + public void PopulateDescriptors() + { + var layerBrushProviders = _pluginService.GetPluginsOfType(); + + if (LayerEffectDescriptors.Any()) + LayerEffectDescriptors.Clear(); + LayerEffectDescriptors.AddRange(layerBrushProviders.SelectMany(l => l.LayerEffectDescriptors)); + + NotifyOfPropertyChange(nameof(HasLayerEffectDescriptors)); + } + + private void AddLayerEffect(LayerEffectDescriptor value) + { + if (LayerPropertiesViewModel.SelectedLayer != null && value != null) + _layerService.AddLayerEffect(LayerPropertiesViewModel.SelectedLayer, value); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml index 3beff72c3..151366d0f 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml @@ -1,21 +1,21 @@  + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties" + xmlns:s="https://github.com/canton7/Stylet" + xmlns:timeline="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:behaviors="clr-namespace:Artemis.UI.Behaviors" + xmlns:Converters="clr-namespace:Artemis.UI.Converters" x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.LayerPropertiesView" + mc:Ignorable="d" + d:DesignHeight="450" + d:DesignWidth="800" + d:DataContext="{d:DesignInstance {x:Type local:LayerPropertiesViewModel}}" + behaviors:InputBindingBehavior.PropagateInputBindingsToWindow="True"> - + - - Effect -  + + Effect + - + + + + + Margin="0 5" + Visibility="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Name, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" /> + - + + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupViewModel.cs index fcf625ceb..a1b90b712 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupViewModel.cs @@ -1,14 +1,50 @@ -using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract; +using System.Collections.Generic; +using Artemis.Core.Services.Interfaces; +using Artemis.UI.Screens.Module.ProfileEditor.Dialogs; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract; +using Artemis.UI.Shared.Services.Interfaces; namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree { public class TreePropertyGroupViewModel { - public TreePropertyGroupViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel) + private readonly IProfileEditorService _profileEditorService; + private readonly ILayerService _layerService; + private readonly IDialogService _dialogService; + + public TreePropertyGroupViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel, + IProfileEditorService profileEditorService, ILayerService layerService, IDialogService dialogService) { - LayerPropertyGroupViewModel = (LayerPropertyGroupViewModel)layerPropertyBaseViewModel; + _profileEditorService = profileEditorService; + _layerService = layerService; + _dialogService = dialogService; + LayerPropertyGroupViewModel = (LayerPropertyGroupViewModel) layerPropertyBaseViewModel; } public LayerPropertyGroupViewModel LayerPropertyGroupViewModel { get; } + + public async void RenameEffect() + { + var result = await _dialogService.ShowDialogAt( + "PropertyTreeDialogHost", + new Dictionary + { + {"subject", "effect"}, + {"currentName", LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Name} + } + ); + if (result is string newName) + { + LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Name = newName; + LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.HasBeenRenamed = true; + _profileEditorService.UpdateSelectedProfile(true); + } + } + + public void DeleteEffect() + { + _layerService.RemoveLayerEffect(LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect); + _profileEditorService.UpdateSelectedProfile(true); + } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreeViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreeViewModel.cs index b67f62e94..6d356518c 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreeViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreeViewModel.cs @@ -1,12 +1,11 @@ -using System.Linq; -using System.Windows; +using System.Windows; using System.Windows.Controls; using System.Windows.Input; using Stylet; namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree { - public class TreeViewModel + public class TreeViewModel : PropertyChangedBase { private readonly LayerPropertiesViewModel _layerPropertiesViewModel; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs index 6209223da..fce6b0e02 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs @@ -130,8 +130,12 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem // ReSharper disable once UnusedMember.Global - Called from view public async Task RenameElement() { - var result = await _dialogService.ShowDialog( - new Dictionary {{"profileElement", ProfileElement}} + var result = await _dialogService.ShowDialog( + new Dictionary + { + {"subject", ProfileElement is Folder ? "folder" : "layer"}, + {"currentName", ProfileElement.Name} + } ); if (result is string newName) { diff --git a/src/Artemis.UI/Services/LayerEditorService.cs b/src/Artemis.UI/Services/LayerEditorService.cs index 1dc03c6fe..3ad8008f2 100644 --- a/src/Artemis.UI/Services/LayerEditorService.cs +++ b/src/Artemis.UI/Services/LayerEditorService.cs @@ -30,7 +30,6 @@ namespace Artemis.UI.Services { _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(BrushPropertyInputViewModel)); _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(ColorGradientPropertyInputViewModel)); - _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(EffectPropertyInputViewModel)); _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(FloatPropertyInputViewModel)); _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(IntPropertyInputViewModel)); _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(SKColorPropertyInputViewModel)); diff --git a/src/Plugins/Artemis.Plugins.LayerBrushes.Color/Artemis.Plugins.LayerBrushes.Color.csproj b/src/Plugins/Artemis.Plugins.LayerBrushes.Color/Artemis.Plugins.LayerBrushes.Color.csproj index 852df1340..69f924a12 100644 --- a/src/Plugins/Artemis.Plugins.LayerBrushes.Color/Artemis.Plugins.LayerBrushes.Color.csproj +++ b/src/Plugins/Artemis.Plugins.LayerBrushes.Color/Artemis.Plugins.LayerBrushes.Color.csproj @@ -37,7 +37,6 @@ - + \ No newline at end of file diff --git a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/FilterEffect.cs b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/FilterEffect.cs index 4db0869f4..ef4d12b2a 100644 --- a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/FilterEffect.cs +++ b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/FilterEffect.cs @@ -1,4 +1,5 @@ -using Artemis.Core.Plugins.LayerEffect.Abstract; +using System; +using Artemis.Core.Plugins.LayerEffect.Abstract; using SkiaSharp; namespace Artemis.Plugins.LayerEffects.Filter @@ -7,8 +8,15 @@ namespace Artemis.Plugins.LayerEffects.Filter { public override void EnableLayerEffect() { + Properties.BlurAmount.BaseValueChanged += BlurAmountOnBaseValueChanged; } - + + private void BlurAmountOnBaseValueChanged(object? sender, EventArgs e) + { + if (!HasBeenRenamed) + Name = "Blur"; + } + public override void DisableLayerEffect() { } @@ -19,6 +27,7 @@ namespace Artemis.Plugins.LayerEffects.Filter public override void PreProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint) { + paint.ImageFilter = SKImageFilter.CreateBlur(Properties.BlurAmount.CurrentValue.Width, Properties.BlurAmount.CurrentValue.Height, paint.ImageFilter); }