diff --git a/src/Artemis.Core/RGB.NET/BitmapBrush.cs b/src/Artemis.Core/RGB.NET/BitmapBrush.cs index f0f2276fe..166bbe509 100644 --- a/src/Artemis.Core/RGB.NET/BitmapBrush.cs +++ b/src/Artemis.Core/RGB.NET/BitmapBrush.cs @@ -10,6 +10,7 @@ namespace Artemis.Core.RGB.NET public class BitmapBrush : AbstractDecoratable, IBrush, IDisposable { private readonly PluginSetting _sampleSizeSetting; + private object _disposeLock; #region Constructors @@ -17,6 +18,7 @@ namespace Artemis.Core.RGB.NET { _sampleSizeSetting = sampleSizeSetting; Scale = scale; + _disposeLock = new object(); } #endregion @@ -55,20 +57,27 @@ namespace Artemis.Core.RGB.NET /// public virtual void PerformRender(Rectangle rectangle, IEnumerable renderTargets) { - if (RenderedRectangle != rectangle || RenderedScale != Scale) - Bitmap = null; + lock (_disposeLock) + { + // Can happen during surface change + if (IsDisposed) + return; - RenderedRectangle = rectangle; - RenderedScale = Scale; - RenderedTargets.Clear(); + if (RenderedRectangle != rectangle || RenderedScale != Scale) + Bitmap = null; - if (Bitmap == null) - CreateBitmap(RenderedRectangle); + RenderedRectangle = rectangle; + RenderedScale = Scale; + RenderedTargets.Clear(); - if (_sampleSizeSetting.Value == 1) - TakeCenter(renderTargets); - else - TakeSamples(renderTargets); + if (Bitmap == null) + CreateBitmap(RenderedRectangle); + + if (_sampleSizeSetting.Value == 1) + TakeCenter(renderTargets); + else + TakeSamples(renderTargets); + } } private void TakeCenter(IEnumerable renderTargets) @@ -140,9 +149,15 @@ namespace Artemis.Core.RGB.NET public void Dispose() { - Bitmap?.Dispose(); + lock (_disposeLock) + { + Bitmap?.Dispose(); + IsDisposed = true; + } } + public bool IsDisposed { get; set; } + #endregion } } \ No newline at end of file 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 e8a33bc36..9db002c81 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupView.xaml @@ -85,7 +85,7 @@ - + @@ -105,7 +105,12 @@ - + Effect diff --git a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/Artemis.Plugins.LayerEffects.Filter.csproj b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/Artemis.Plugins.LayerEffects.Filter.csproj index 9b626a5f3..d29a8e43a 100644 --- a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/Artemis.Plugins.LayerEffects.Filter.csproj +++ b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/Artemis.Plugins.LayerEffects.Filter.csproj @@ -36,6 +36,7 @@ - + \ No newline at end of file diff --git a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/BlurEffect.cs b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/BlurEffect.cs new file mode 100644 index 000000000..c7bf0cd25 --- /dev/null +++ b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/BlurEffect.cs @@ -0,0 +1,37 @@ +using Artemis.Core.Plugins.LayerEffect.Abstract; +using SkiaSharp; + +namespace Artemis.Plugins.LayerEffects.Filter +{ + public class BlurEffect : LayerEffect + { + public override void EnableLayerEffect() + { + } + + public override void DisableLayerEffect() + { + } + + public override void Update(double deltaTime) + { + } + + 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 + ); + } + + public override void PostProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint) + { + } + + private void UpdateFilterType() + { + } + } +} \ No newline at end of file diff --git a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/BlurEffectProperties.cs b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/BlurEffectProperties.cs new file mode 100644 index 000000000..5f9f54986 --- /dev/null +++ b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/BlurEffectProperties.cs @@ -0,0 +1,25 @@ +using Artemis.Core.Models.Profile; +using Artemis.Core.Models.Profile.LayerProperties.Attributes; +using Artemis.Core.Models.Profile.LayerProperties.Types; + +namespace Artemis.Plugins.LayerEffects.Filter +{ + public class BlurEffectProperties : LayerPropertyGroup + { + [PropertyDescription(Description = "The amount of blur to apply")] + public SKSizeLayerProperty BlurAmount { get; set; } + + + protected override void PopulateDefaults() + { + } + + protected override void OnPropertiesInitialized() + { + } + + private void UpdateVisibility() + { + } + } +} \ No newline at end of file diff --git a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/DilateEffect.cs b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/DilateEffect.cs new file mode 100644 index 000000000..411a63d75 --- /dev/null +++ b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/DilateEffect.cs @@ -0,0 +1,33 @@ +using Artemis.Core.Plugins.LayerEffect.Abstract; +using SkiaSharp; + +namespace Artemis.Plugins.LayerEffects.Filter +{ + public class DilateEffect : LayerEffect + { + public override void EnableLayerEffect() + { + } + + public override void DisableLayerEffect() + { + } + + public override void Update(double deltaTime) + { + } + + public override void PreProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint) + { + paint.ImageFilter = SKImageFilter.CreateDilate( + (int) Properties.DilateRadius.CurrentValue.Width, + (int) Properties.DilateRadius.CurrentValue.Height, + paint.ImageFilter + ); + } + + public override void PostProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint) + { + } + } +} \ No newline at end of file diff --git a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/DilateEffectProperties.cs b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/DilateEffectProperties.cs new file mode 100644 index 000000000..3b3cfa502 --- /dev/null +++ b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/DilateEffectProperties.cs @@ -0,0 +1,20 @@ +using Artemis.Core.Models.Profile; +using Artemis.Core.Models.Profile.LayerProperties.Attributes; +using Artemis.Core.Models.Profile.LayerProperties.Types; + +namespace Artemis.Plugins.LayerEffects.Filter +{ + public class DilateEffectProperties : LayerPropertyGroup + { + [PropertyDescription(Description = "The amount of dilation to apply")] + public SKSizeLayerProperty DilateRadius { get; set; } + + protected override void PopulateDefaults() + { + } + + protected override void OnPropertiesInitialized() + { + } + } +} \ No newline at end of file diff --git a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/ErodeEffect.cs b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/ErodeEffect.cs new file mode 100644 index 000000000..d532aac3a --- /dev/null +++ b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/ErodeEffect.cs @@ -0,0 +1,33 @@ +using Artemis.Core.Plugins.LayerEffect.Abstract; +using SkiaSharp; + +namespace Artemis.Plugins.LayerEffects.Filter +{ + public class ErodeEffect : LayerEffect + { + public override void EnableLayerEffect() + { + } + + public override void DisableLayerEffect() + { + } + + public override void Update(double deltaTime) + { + } + + public override void PreProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint) + { + paint.ImageFilter = SKImageFilter.CreateErode( + (int) Properties.ErodeRadius.CurrentValue.Width, + (int) Properties.ErodeRadius.CurrentValue.Height, + paint.ImageFilter + ); + } + + public override void PostProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint) + { + } + } +} \ No newline at end of file diff --git a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/ErodeEffectProperties.cs b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/ErodeEffectProperties.cs new file mode 100644 index 000000000..4a643c858 --- /dev/null +++ b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/ErodeEffectProperties.cs @@ -0,0 +1,20 @@ +using Artemis.Core.Models.Profile; +using Artemis.Core.Models.Profile.LayerProperties.Attributes; +using Artemis.Core.Models.Profile.LayerProperties.Types; + +namespace Artemis.Plugins.LayerEffects.Filter +{ + public class ErodeEffectProperties : LayerPropertyGroup + { + [PropertyDescription(Description = "The amount of erode to apply")] + public SKSizeLayerProperty ErodeRadius { get; set; } + + protected override void PopulateDefaults() + { + } + + protected override void OnPropertiesInitialized() + { + } + } +} \ 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 deleted file mode 100644 index cd4774b86..000000000 --- a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/FilterEffect.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using Artemis.Core.Plugins.LayerEffect.Abstract; -using Artemis.UI.Shared.Utilities; -using SkiaSharp; - -namespace Artemis.Plugins.LayerEffects.Filter -{ - public class FilterEffect : LayerEffect - { - public override void EnableLayerEffect() - { - Properties.FilterType.BaseValueChanged += (sender, args) => UpdateFilterType(); - - UpdateFilterType(); - } - - private void UpdateFilterType() - { - if (HasBeenRenamed) - return; - - Name = EnumUtilities.HumanizeValue(Properties.FilterType); - } - - public override void DisableLayerEffect() - { - } - - public override void Update(double deltaTime) - { - } - - public override void PreProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint) - { - if (Properties.FilterType == FilterType.Blur) - { - paint.ImageFilter = SKImageFilter.CreateBlur( - Properties.BlurAmount.CurrentValue.Width, - Properties.BlurAmount.CurrentValue.Height, - paint.ImageFilter - ); - } - else if (Properties.FilterType == FilterType.Dilate) - { - paint.ImageFilter = SKImageFilter.CreateDilate( - (int) Properties.DilateRadius.CurrentValue.Width, - (int) Properties.DilateRadius.CurrentValue.Height, - paint.ImageFilter - ); - } - else if (Properties.FilterType == FilterType.Erode) - { - paint.ImageFilter = SKImageFilter.CreateErode( - (int) Properties.ErodeRadius.CurrentValue.Width, - (int) Properties.ErodeRadius.CurrentValue.Height, - paint.ImageFilter - ); - } - else if (Properties.FilterType == FilterType.Erode) - { - paint.ImageFilter = SKImageFilter.CreateErode( - (int) Properties.ErodeRadius.CurrentValue.Width, - (int) Properties.ErodeRadius.CurrentValue.Height, - paint.ImageFilter - ); - } - else if (Properties.FilterType == FilterType.DropShadow) - { - paint.ImageFilter = SKImageFilter.CreateDropShadow( - Properties.ShadowOffset.CurrentValue.X, - Properties.ShadowOffset.CurrentValue.Y, - Properties.ShadowBlurAmount.CurrentValue.Width, - Properties.ShadowBlurAmount.CurrentValue.Height, Properties.ShadowColor, - SKDropShadowImageFilterShadowMode.DrawShadowAndForeground, - paint.ImageFilter - ); - } - } - - public override void PostProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint) - { - } - } -} \ No newline at end of file diff --git a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/FilterEffectProperties.cs b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/FilterEffectProperties.cs deleted file mode 100644 index 5f70b13ed..000000000 --- a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/FilterEffectProperties.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using Artemis.Core.Models.Profile; -using Artemis.Core.Models.Profile.LayerProperties.Attributes; -using Artemis.Core.Models.Profile.LayerProperties.Types; -using SkiaSharp; - -namespace Artemis.Plugins.LayerEffects.Filter -{ - public class FilterEffectProperties : LayerPropertyGroup - { - [PropertyDescription] - public EnumLayerProperty FilterType { get; set; } - - [PropertyDescription(Description = "The amount of blur to apply")] - public SKSizeLayerProperty BlurAmount { get; set; } - - [PropertyDescription(Description = "The amount of dilation to apply")] - public SKSizeLayerProperty DilateRadius { get; set; } - - [PropertyDescription(Description = "The amount of erode to apply")] - public SKSizeLayerProperty ErodeRadius { get; set; } - - [PropertyDescription(Description = "The offset of the shadow")] - public SKPointLayerProperty ShadowOffset { get; set; } - - [PropertyDescription(Description = "The amount of blur to apply to the shadow")] - public SKSizeLayerProperty ShadowBlurAmount { get; set; } - - [PropertyDescription(Description = "The color of the shadow")] - public SKColorLayerProperty ShadowColor { get; set; } - - protected override void PopulateDefaults() - { - ShadowBlurAmount.DefaultValue = new SKSize(5, 5); - ShadowColor.DefaultValue = new SKColor(50, 50, 50); - } - - protected override void OnPropertiesInitialized() - { - FilterType.BaseValueChanged += (sender, args) => UpdateVisibility(); - UpdateVisibility(); - } - - private void UpdateVisibility() - { - BlurAmount.IsHidden = FilterType != Filter.FilterType.Blur; - DilateRadius.IsHidden = FilterType != Filter.FilterType.Dilate; - ErodeRadius.IsHidden = FilterType != Filter.FilterType.Erode; - ShadowOffset.IsHidden = FilterType != Filter.FilterType.DropShadow; - ShadowBlurAmount.IsHidden = FilterType != Filter.FilterType.DropShadow; - ShadowColor.IsHidden = FilterType != Filter.FilterType.DropShadow; - } - } - - public enum FilterType - { - Blur, - Dilate, - Erode, - DropShadow, - } -} \ No newline at end of file diff --git a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/FilterEffectProvider.cs b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/FilterEffectProvider.cs index 436aad3a8..ca1fe61d1 100644 --- a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/FilterEffectProvider.cs +++ b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/FilterEffectProvider.cs @@ -6,7 +6,11 @@ namespace Artemis.Plugins.LayerEffects.Filter { public override void EnablePlugin() { - AddLayerEffectDescriptor("Filter", "A layer effect providing different types of filters", "ImageFilterFrames"); + AddLayerEffectDescriptor("Blur", "A layer effect providing a blur filter effect", "BlurOn"); + AddLayerEffectDescriptor("Dilate", "A layer effect providing a dilation filter effect", "EyePlus"); + AddLayerEffectDescriptor("Erode", "A layer effect providing an erode filter effect", "EyeMinus"); + AddLayerEffectDescriptor("Glow", "A layer effect providing a glow filter effect", "BoxShadow"); + AddLayerEffectDescriptor("Gray-scale", "A layer effect providing a gray-scale filter effect", "InvertColors"); } public override void DisablePlugin() diff --git a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/GlowEffect.cs b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/GlowEffect.cs new file mode 100644 index 000000000..636c21bab --- /dev/null +++ b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/GlowEffect.cs @@ -0,0 +1,36 @@ +using Artemis.Core.Plugins.LayerEffect.Abstract; +using SkiaSharp; + +namespace Artemis.Plugins.LayerEffects.Filter +{ + public class GlowEffect : LayerEffect + { + public override void EnableLayerEffect() + { + } + + public override void DisableLayerEffect() + { + } + + public override void Update(double deltaTime) + { + } + + public override void PreProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint) + { + paint.ImageFilter = SKImageFilter.CreateDropShadow( + Properties.GlowOffset.CurrentValue.X, + Properties.GlowOffset.CurrentValue.Y, + Properties.GlowBlurAmount.CurrentValue.Width, + Properties.GlowBlurAmount.CurrentValue.Height, Properties.GlowColor, + SKDropShadowImageFilterShadowMode.DrawShadowAndForeground, + paint.ImageFilter + ); + } + + public override void PostProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint) + { + } + } +} \ No newline at end of file diff --git a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/GlowEffectProperties.cs b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/GlowEffectProperties.cs new file mode 100644 index 000000000..5aace96bd --- /dev/null +++ b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/GlowEffectProperties.cs @@ -0,0 +1,29 @@ +using Artemis.Core.Models.Profile; +using Artemis.Core.Models.Profile.LayerProperties.Attributes; +using Artemis.Core.Models.Profile.LayerProperties.Types; +using SkiaSharp; + +namespace Artemis.Plugins.LayerEffects.Filter +{ + public class GlowEffectProperties : LayerPropertyGroup + { + [PropertyDescription(Description = "The offset of the glow")] + public SKPointLayerProperty GlowOffset { get; set; } + + [PropertyDescription(Description = "The amount of blur to apply to the glow")] + public SKSizeLayerProperty GlowBlurAmount { get; set; } + + [PropertyDescription(Description = "The color of the glow")] + public SKColorLayerProperty GlowColor { get; set; } + + protected override void PopulateDefaults() + { + GlowBlurAmount.DefaultValue = new SKSize(25, 25); + GlowColor.DefaultValue = new SKColor(255, 255, 255); + } + + protected override void OnPropertiesInitialized() + { + } + } +} \ No newline at end of file diff --git a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/GrayScaleEffect.cs b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/GrayScaleEffect.cs new file mode 100644 index 000000000..5e7657118 --- /dev/null +++ b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/GrayScaleEffect.cs @@ -0,0 +1,35 @@ +using Artemis.Core.Plugins.LayerEffect.Abstract; +using SkiaSharp; + +namespace Artemis.Plugins.LayerEffects.Filter +{ + public class GrayScaleEffect : LayerEffect + { + public override void EnableLayerEffect() + { + } + + public override void DisableLayerEffect() + { + } + + public override void Update(double deltaTime) + { + } + + public override void PreProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint) + { + paint.ImageFilter = SKImageFilter.CreateColorFilter(SKColorFilter.CreateColorMatrix(new[] + { + 0.21f, 0.72f, 0.07f, 0, 0, + 0.21f, 0.72f, 0.07f, 0, 0, + 0.21f, 0.72f, 0.07f, 0, 0, + 0, 0, 0, 1, 0 + }), paint.ImageFilter); + } + + public override void PostProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint) + { + } + } +} \ No newline at end of file diff --git a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/GrayScaleEffectProperties.cs b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/GrayScaleEffectProperties.cs new file mode 100644 index 000000000..a9bace0b3 --- /dev/null +++ b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/GrayScaleEffectProperties.cs @@ -0,0 +1,20 @@ +using Artemis.Core.Models.Profile; +using Artemis.Core.Models.Profile.LayerProperties.Attributes; +using Artemis.Core.Models.Profile.LayerProperties.Types; + +namespace Artemis.Plugins.LayerEffects.Filter +{ + public class GrayScaleEffectProperties : LayerPropertyGroup + { + [PropertyDescription(Name = "Gray-scale strength (NYI)")] + public FloatLayerProperty GrayScaleStrength { get; set; } + + protected override void PopulateDefaults() + { + } + + protected override void OnPropertiesInitialized() + { + } + } +} \ No newline at end of file