From 7a50249335e815b2dcabc47236b903f14dcb618a Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Thu, 18 Jun 2020 19:09:40 +0200 Subject: [PATCH 1/2] Core - Render each profile element in its own bitmap Layer effects - Removed now redundant CreateShapeClip --- .../Models/Profile/EffectProfileElement.cs | 64 ++++----- src/Artemis.Core/Models/Profile/Folder.cs | 45 +++++-- src/Artemis.Core/Models/Profile/Layer.cs | 122 +++++++----------- .../Models/Profile/LayerShapes/Ellipse.cs | 2 +- .../Models/Profile/LayerShapes/Rectangle.cs | 2 +- src/Artemis.Core/Models/Profile/Profile.cs | 4 +- .../Models/Profile/ProfileElement.cs | 2 +- .../Plugins/Abstract/ProfileModule.cs | 3 +- .../Plugins/LayerBrush/Abstract/LayerBrush.cs | 5 - .../LayerEffect/Abstract/BaseLayerEffect.cs | 59 --------- .../BlurEffect.cs | 5 +- .../DilateEffect.cs | 11 +- .../GlowEffect.cs | 9 +- 13 files changed, 126 insertions(+), 207 deletions(-) diff --git a/src/Artemis.Core/Models/Profile/EffectProfileElement.cs b/src/Artemis.Core/Models/Profile/EffectProfileElement.cs index a157ab952..93e0e7ab6 100644 --- a/src/Artemis.Core/Models/Profile/EffectProfileElement.cs +++ b/src/Artemis.Core/Models/Profile/EffectProfileElement.cs @@ -5,21 +5,39 @@ using System.Linq; using Artemis.Core.Annotations; using Artemis.Core.Plugins.LayerEffect.Abstract; using Artemis.Storage.Entities.Profile; -using SkiaSharp; namespace Artemis.Core.Models.Profile { public abstract class EffectProfileElement : PropertiesProfileElement { + protected List _layerEffects; internal abstract EffectsEntity EffectsEntity { get; } - protected List _layerEffects; - /// /// Gets a read-only collection of the layer effects on this entity /// public ReadOnlyCollection LayerEffects => _layerEffects.AsReadOnly(); - + + protected void ApplyLayerEffectsToEntity() + { + EffectsEntity.LayerEffects.Clear(); + foreach (var layerEffect in LayerEffects) + { + var layerEffectEntity = new LayerEffectEntity + { + Id = layerEffect.EntityId, + PluginGuid = layerEffect.PluginInfo.Guid, + EffectType = layerEffect.GetType().Name, + Name = layerEffect.Name, + Enabled = layerEffect.Enabled, + HasBeenRenamed = layerEffect.HasBeenRenamed, + Order = layerEffect.Order + }; + EffectsEntity.LayerEffects.Add(layerEffectEntity); + layerEffect.BaseProperties.ApplyToEntity(); + } + } + internal void RemoveLayerEffect([NotNull] BaseLayerEffect effect) { if (effect == null) throw new ArgumentNullException(nameof(effect)); @@ -53,44 +71,6 @@ namespace Artemis.Core.Models.Profile effect.Dispose(); } - internal SKPath CreateShapeClip() - { - var shapeClip = new SKPath(); - if (Path == null) - return shapeClip; - - if (Parent is EffectProfileElement effectParent) - shapeClip = shapeClip.Op(effectParent.CreateShapeClip(), SKPathOp.Union); - - foreach (var baseLayerEffect in LayerEffects.Where(e => e.Enabled)) - { - var effectClip = baseLayerEffect.InternalCreateShapeClip(Path); - shapeClip = shapeClip.Op(effectClip, SKPathOp.Difference); - } - - return shapeClip; - } - - protected void ApplyLayerEffectsToEntity() - { - EffectsEntity.LayerEffects.Clear(); - foreach (var layerEffect in LayerEffects) - { - var layerEffectEntity = new LayerEffectEntity - { - Id = layerEffect.EntityId, - PluginGuid = layerEffect.PluginInfo.Guid, - EffectType = layerEffect.GetType().Name, - Name = layerEffect.Name, - Enabled = layerEffect.Enabled, - HasBeenRenamed = layerEffect.HasBeenRenamed, - Order = layerEffect.Order - }; - EffectsEntity.LayerEffects.Add(layerEffectEntity); - layerEffect.BaseProperties.ApplyToEntity(); - } - } - #region Events public event EventHandler LayerEffectsUpdated; diff --git a/src/Artemis.Core/Models/Profile/Folder.cs b/src/Artemis.Core/Models/Profile/Folder.cs index e87fc0378..a14ed2872 100644 --- a/src/Artemis.Core/Models/Profile/Folder.cs +++ b/src/Artemis.Core/Models/Profile/Folder.cs @@ -9,6 +9,8 @@ namespace Artemis.Core.Models.Profile { public sealed class Folder : EffectProfileElement { + private SKBitmap _folderBitmap; + public Folder(Profile profile, ProfileElement parent, string name) { FolderEntity = new FolderEntity(); @@ -74,7 +76,7 @@ namespace Artemis.Core.Models.Profile } } - public override void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint) + public override void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo) { if (!Enabled) return; @@ -82,28 +84,44 @@ namespace Artemis.Core.Models.Profile if (Path == null) return; - canvas.Save(); - canvas.ClipPath(Path); + if (_folderBitmap == null) + _folderBitmap = new SKBitmap(new SKImageInfo((int) Path.Bounds.Width, (int) Path.Bounds.Height)); + else if (_folderBitmap.Info.Width != (int) Path.Bounds.Width || _folderBitmap.Info.Height != (int) Path.Bounds.Height) + { + _folderBitmap.Dispose(); + _folderBitmap = new SKBitmap(new SKImageInfo((int) Path.Bounds.Width, (int) Path.Bounds.Height)); + } - // Clone the paint so that any changes are confined to the current group - var groupPaint = paint.Clone(); + using var folderCanvas = new SKCanvas(_folderBitmap); + using var folderPaint = new SKPaint(); + folderCanvas.Clear(); + + var folderPath = new SKPath(Path); + folderPath.Transform(SKMatrix.MakeTranslation(folderPath.Bounds.Left * -1, folderPath.Bounds.Top * -1)); - // Pre-processing only affects other pre-processors and the brushes - canvas.Save(); foreach (var baseLayerEffect in LayerEffects.Where(e => e.Enabled)) - baseLayerEffect.InternalPreProcess(canvas, canvasInfo, new SKPath(Path), groupPaint); + baseLayerEffect.PreProcess(folderCanvas, _folderBitmap.Info, folderPath, folderPaint); // Iterate the children in reverse because the first layer must be rendered last to end up on top for (var index = Children.Count - 1; index > -1; index--) { var profileElement = Children[index]; - profileElement.Render(deltaTime, canvas, canvasInfo, groupPaint); + profileElement.Render(deltaTime, folderCanvas, _folderBitmap.Info); } - // Restore the canvas as to not be affected by pre-processors - canvas.Restore(); + var targetLocation = Path.Bounds.Location; + if (Parent is Folder parentFolder) + targetLocation -= parentFolder.Path.Bounds.Location; + + canvas.Save(); + + var clipPath = new SKPath(folderPath); + clipPath.Transform(SKMatrix.MakeTranslation(targetLocation.X, targetLocation.Y)); + canvas.ClipPath(clipPath); + foreach (var baseLayerEffect in LayerEffects.Where(e => e.Enabled)) - baseLayerEffect.InternalPostProcess(canvas, canvasInfo, new SKPath(Path), groupPaint); + baseLayerEffect.PostProcess(canvas, canvasInfo, folderPath, folderPaint); + canvas.DrawBitmap(_folderBitmap, targetLocation, folderPaint); canvas.Restore(); } @@ -186,6 +204,9 @@ namespace Artemis.Core.Models.Profile internal void Deactivate() { + _folderBitmap?.Dispose(); + _folderBitmap = null; + var layerEffects = new List(LayerEffects); foreach (var baseLayerEffect in layerEffects) DeactivateLayerEffect(baseLayerEffect); diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index 55273c538..f05e0130f 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -25,6 +25,7 @@ namespace Artemis.Core.Models.Profile { private LayerShape _layerShape; private List _leds; + private SKBitmap _layerBitmap; internal Layer(Profile profile, ProfileElement parent, string name) { @@ -225,7 +226,7 @@ namespace Artemis.Core.Models.Profile } /// - public override void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint) + public override void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo) { if (!Enabled) return; @@ -237,77 +238,86 @@ namespace Artemis.Core.Models.Profile if (LayerBrush?.BaseProperties?.PropertiesInitialized == false || LayerBrush?.BrushType != LayerBrushType.Regular) return; - canvas.Save(); - canvas.ClipPath(Path); + if (_layerBitmap == null) + _layerBitmap = new SKBitmap(new SKImageInfo((int)Path.Bounds.Width, (int)Path.Bounds.Height)); + else if (_layerBitmap.Info.Width != (int)Path.Bounds.Width || _layerBitmap.Info.Height != (int)Path.Bounds.Height) + { + _layerBitmap.Dispose(); + _layerBitmap = new SKBitmap(new SKImageInfo((int)Path.Bounds.Width, (int)Path.Bounds.Height)); + } - paint.BlendMode = General.BlendMode.CurrentValue; - paint.Color = new SKColor(0, 0, 0, (byte) (Transform.Opacity.CurrentValue * 2.55f)); + using var layerCanvas = new SKCanvas(_layerBitmap); + using var layerPaint = new SKPaint + { + FilterQuality = SKFilterQuality.Low, + BlendMode = General.BlendMode.CurrentValue, + Color = new SKColor(0, 0, 0, (byte) (Transform.Opacity.CurrentValue * 2.55f)) + }; + layerCanvas.Clear(); - // Pre-processing only affects other pre-processors and the brushes - canvas.Save(); + var layerPath = new SKPath(Path); + layerPath.Transform(SKMatrix.MakeTranslation(layerPath.Bounds.Left * -1, layerPath.Bounds.Top * -1)); + foreach (var baseLayerEffect in LayerEffects.Where(e => e.Enabled)) - baseLayerEffect.InternalPreProcess(canvas, canvasInfo, new SKPath(Path), paint); + baseLayerEffect.PreProcess(layerCanvas, _layerBitmap.Info, layerPath, layerPaint); - // Shape clip must be determined before commiting to any rendering - var shapeClip = CreateShapeClip(); - if (!shapeClip.IsEmpty) - ExcludePathFromTranslation(shapeClip); + layerCanvas.ClipPath(layerPath); if (!LayerBrush.SupportsTransformation) - SimpleRender(canvas, canvasInfo, paint, shapeClip); + SimpleRender(layerCanvas, _layerBitmap.Info, layerPaint, layerPath); else if (General.FillType.CurrentValue == LayerFillType.Stretch) - StretchRender(canvas, canvasInfo, paint, shapeClip); + StretchRender(layerCanvas, _layerBitmap.Info, layerPaint, layerPath); else if (General.FillType.CurrentValue == LayerFillType.Clip) - ClipRender(canvas, canvasInfo, paint, shapeClip); + ClipRender(layerCanvas, _layerBitmap.Info, layerPaint, layerPath); - // Restore the canvas as to not be affected by pre-processors - canvas.Restore(); foreach (var baseLayerEffect in LayerEffects.Where(e => e.Enabled)) - baseLayerEffect.InternalPostProcess(canvas, canvasInfo, new SKPath(Path), paint); + baseLayerEffect.PostProcess(layerCanvas, _layerBitmap.Info, layerPath, layerPaint); - canvas.Restore(); + var targetLocation = new SKPoint(0, 0); + if (Parent is Folder parentFolder) + targetLocation = Path.Bounds.Location - parentFolder.Path.Bounds.Location; + + canvas.DrawBitmap(_layerBitmap, targetLocation, layerPaint); } - private void SimpleRender(SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint, SKPath shapeClip) + private void SimpleRender(SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint, SKPath layerPath) { - var path = LayerShape.Path.Op(shapeClip, SKPathOp.Difference); - LayerBrush.InternalRender(canvas, canvasInfo, path, paint); + LayerBrush.InternalRender(canvas, canvasInfo, new SKPath(LayerShape.Path), paint); } - private void StretchRender(SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint, SKPath shapeClip) + private void StretchRender(SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint, SKPath layerPath) { // Apply transformations var sizeProperty = Transform.Scale.CurrentValue; var rotationProperty = Transform.Rotation.CurrentValue; - var anchorPosition = GetLayerAnchorPosition(); + var anchorPosition = GetLayerAnchorPosition(layerPath); var anchorProperty = Transform.AnchorPoint.CurrentValue; // Translation originates from the unscaled center of the shape and is tied to the anchor - var x = anchorPosition.X - Bounds.MidX - anchorProperty.X * Bounds.Width; - var y = anchorPosition.Y - Bounds.MidY - anchorProperty.Y * Bounds.Height; + var x = anchorPosition.X - layerPath.Bounds.MidX - anchorProperty.X * layerPath.Bounds.Width; + var y = anchorPosition.Y - layerPath.Bounds.MidY - anchorProperty.Y * layerPath.Bounds.Height; // Apply these before translation because anchorPosition takes translation into account canvas.RotateDegrees(rotationProperty, anchorPosition.X, anchorPosition.Y); canvas.Scale(sizeProperty.Width / 100f, sizeProperty.Height / 100f, anchorPosition.X, anchorPosition.Y); canvas.Translate(x, y); - - var path = LayerShape.Path.Op(shapeClip, SKPathOp.Difference); - LayerBrush.InternalRender(canvas, canvasInfo, path, paint); + + LayerBrush.InternalRender(canvas, canvasInfo, new SKPath(LayerShape.Path), paint); } - private void ClipRender(SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint, SKPath shapeClip) + private void ClipRender(SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint, SKPath layerPath) { // Apply transformation var sizeProperty = Transform.Scale.CurrentValue; var rotationProperty = Transform.Rotation.CurrentValue; - var anchorPosition = GetLayerAnchorPosition(); + var anchorPosition = GetLayerAnchorPosition(layerPath); var anchorProperty = Transform.AnchorPoint.CurrentValue; // Translation originates from the unscaled center of the shape and is tied to the anchor - var x = anchorPosition.X - Bounds.MidX - anchorProperty.X * Bounds.Width; - var y = anchorPosition.Y - Bounds.MidY - anchorProperty.Y * Bounds.Height; + var x = anchorPosition.X - layerPath.Bounds.MidX - anchorProperty.X * layerPath.Bounds.Width; + var y = anchorPosition.Y - layerPath.Bounds.MidY - anchorProperty.Y * layerPath.Bounds.Height; var clipPath = new SKPath(LayerShape.Path); clipPath.Transform(SKMatrix.MakeTranslation(x, y)); @@ -329,7 +339,6 @@ namespace Artemis.Core.Models.Profile var renderPath = new SKPath(); renderPath.AddRect(boundsRect); - renderPath = renderPath.Op(shapeClip, SKPathOp.Difference); LayerBrush.InternalRender(canvas, canvasInfo, renderPath, paint); } @@ -357,54 +366,20 @@ namespace Artemis.Core.Models.Profile OnRenderPropertiesUpdated(); } - internal SKPoint GetLayerAnchorPosition() + internal SKPoint GetLayerAnchorPosition(SKPath layerPath) { var positionProperty = Transform.Position.CurrentValue; // Start at the center of the shape - var position = new SKPoint(Bounds.MidX, Bounds.MidY); + var position = new SKPoint(layerPath.Bounds.MidX, layerPath.Bounds.MidY); // Apply translation - position.X += positionProperty.X * Bounds.Width; - position.Y += positionProperty.Y * Bounds.Height; + position.X += positionProperty.X * layerPath.Bounds.Width; + position.Y += positionProperty.Y * layerPath.Bounds.Height; return position; } - - /// - /// Excludes the provided path from the translations applied to the layer by applying translations that cancel the - /// layer translations out - /// - /// - public void ExcludePathFromTranslation(SKPath path) - { - var sizeProperty = Transform.Scale.CurrentValue; - var rotationProperty = Transform.Rotation.CurrentValue; - - var anchorPosition = GetLayerAnchorPosition(); - var anchorProperty = Transform.AnchorPoint.CurrentValue; - - // Translation originates from the unscaled center of the shape and is tied to the anchor - var x = anchorPosition.X - Bounds.MidX - anchorProperty.X * Bounds.Width; - var y = anchorPosition.Y - Bounds.MidY - anchorProperty.Y * Bounds.Height; - - var reversedXScale = 1f / (sizeProperty.Width / 100f); - var reversedYScale = 1f / (sizeProperty.Height / 100f); - - if (General.FillType == LayerFillType.Stretch) - { - path.Transform(SKMatrix.MakeRotationDegrees(rotationProperty * -1, anchorPosition.X, anchorPosition.Y)); - path.Transform(SKMatrix.MakeScale(reversedXScale, reversedYScale, anchorPosition.X, anchorPosition.Y)); - path.Transform(SKMatrix.MakeTranslation(x * -1, y * -1)); - } - else - { - path.Transform(SKMatrix.MakeRotationDegrees(rotationProperty * -1, anchorPosition.X, anchorPosition.Y)); - path.Transform(SKMatrix.MakeTranslation(x * -1, y * -1)); - } - } - #endregion #region LED management @@ -472,6 +447,9 @@ namespace Artemis.Core.Models.Profile internal void Deactivate() { + _layerBitmap?.Dispose(); + _layerBitmap = null; + DeactivateLayerBrush(); var layerEffects = new List(LayerEffects); foreach (var baseLayerEffect in layerEffects) diff --git a/src/Artemis.Core/Models/Profile/LayerShapes/Ellipse.cs b/src/Artemis.Core/Models/Profile/LayerShapes/Ellipse.cs index 62e30a9fa..58a9f5d85 100644 --- a/src/Artemis.Core/Models/Profile/LayerShapes/Ellipse.cs +++ b/src/Artemis.Core/Models/Profile/LayerShapes/Ellipse.cs @@ -11,7 +11,7 @@ namespace Artemis.Core.Models.Profile.LayerShapes public override void CalculateRenderProperties() { var path = new SKPath(); - path.AddOval(Layer.Bounds); + path.AddOval(SKRect.Create(Layer.Bounds.Width, Layer.Bounds.Height)); Path = path; } } diff --git a/src/Artemis.Core/Models/Profile/LayerShapes/Rectangle.cs b/src/Artemis.Core/Models/Profile/LayerShapes/Rectangle.cs index 71783bfc1..21d914636 100644 --- a/src/Artemis.Core/Models/Profile/LayerShapes/Rectangle.cs +++ b/src/Artemis.Core/Models/Profile/LayerShapes/Rectangle.cs @@ -11,7 +11,7 @@ namespace Artemis.Core.Models.Profile.LayerShapes public override void CalculateRenderProperties() { var path = new SKPath(); - path.AddRect(Layer.Bounds); + path.AddRect(SKRect.Create(Layer.Bounds.Width, Layer.Bounds.Height)); Path = path; } } diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs index 082666b41..560be8fd8 100644 --- a/src/Artemis.Core/Models/Profile/Profile.cs +++ b/src/Artemis.Core/Models/Profile/Profile.cs @@ -57,7 +57,7 @@ namespace Artemis.Core.Models.Profile } } - public override void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint) + public override void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo) { lock (this) { @@ -65,7 +65,7 @@ namespace Artemis.Core.Models.Profile throw new ArtemisCoreException($"Cannot render inactive profile: {this}"); foreach (var profileElement in Children) - profileElement.Render(deltaTime, canvas, canvasInfo, paint); + profileElement.Render(deltaTime, canvas, canvasInfo); } } diff --git a/src/Artemis.Core/Models/Profile/ProfileElement.cs b/src/Artemis.Core/Models/Profile/ProfileElement.cs index 4a050ce99..231d5bec8 100644 --- a/src/Artemis.Core/Models/Profile/ProfileElement.cs +++ b/src/Artemis.Core/Models/Profile/ProfileElement.cs @@ -49,7 +49,7 @@ namespace Artemis.Core.Models.Profile /// /// Renders the element /// - public abstract void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint); + public abstract void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo); public List GetAllFolders() { diff --git a/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs b/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs index d9445bb66..1d34f53d0 100644 --- a/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs +++ b/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs @@ -26,8 +26,7 @@ namespace Artemis.Core.Plugins.Abstract lock (this) { // Render the profile - using var paint = new SKPaint {FilterQuality = SKFilterQuality.Low}; - ActiveProfile?.Render(deltaTime, canvas, canvasInfo, paint); + ActiveProfile?.Render(deltaTime, canvas, canvasInfo); } } diff --git a/src/Artemis.Core/Plugins/LayerBrush/Abstract/LayerBrush.cs b/src/Artemis.Core/Plugins/LayerBrush/Abstract/LayerBrush.cs index ac02786a9..545fac339 100644 --- a/src/Artemis.Core/Plugins/LayerBrush/Abstract/LayerBrush.cs +++ b/src/Artemis.Core/Plugins/LayerBrush/Abstract/LayerBrush.cs @@ -24,11 +24,6 @@ namespace Artemis.Core.Plugins.LayerBrush.Abstract internal override void InternalRender(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint) { - // Move the canvas to the top-left of the render path - canvas.Translate(path.Bounds.Left, path.Bounds.Top); - // Pass the render path to the layer brush positioned at 0,0 - path.Transform(SKMatrix.MakeTranslation(path.Bounds.Left * -1, path.Bounds.Top * -1)); - Render(canvas, canvasInfo, path, paint); } diff --git a/src/Artemis.Core/Plugins/LayerEffect/Abstract/BaseLayerEffect.cs b/src/Artemis.Core/Plugins/LayerEffect/Abstract/BaseLayerEffect.cs index 45fb497d8..e33d799f6 100644 --- a/src/Artemis.Core/Plugins/LayerEffect/Abstract/BaseLayerEffect.cs +++ b/src/Artemis.Core/Plugins/LayerEffect/Abstract/BaseLayerEffect.cs @@ -99,65 +99,6 @@ namespace Artemis.Core.Plugins.LayerEffect.Abstract /// The paint this layer/folder used to render public abstract void PostProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath renderBounds, SKPaint paint); - /// - /// Allows you to return a clip that is applied to the layer shape (or in case of a folder, all layer shapes in the - /// folder). - /// - /// To avoid breaking other effects, use this instead of applying a clip to the entire canvas if you want to limit - /// where shapes may render - /// - /// - /// The bounds this layer/folder rendered in - /// - public virtual SKPath CreateShapeClip(SKPath renderBounds) - { - return new SKPath(); - } - - internal void InternalPreProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint) - { - var x = path.Bounds.Left; - var y = path.Bounds.Top; - // Move the canvas to the top-left of the render path - canvas.Translate(x, y); - - // Pass the render path to the layer effect positioned at 0,0 - path.Transform(SKMatrix.MakeTranslation(x * -1, y * -1)); - - PreProcess(canvas, canvasInfo, path, paint); - - // Move the canvas back - canvas.Translate(x * -1, y * -1); - } - - internal void InternalPostProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint) - { - var x = path.Bounds.Left; - var y = path.Bounds.Top; - // Move the canvas to the top-left of the render path - canvas.Translate(x, y); - - // Pass the render path to the layer effect positioned at 0,0 - path.Transform(SKMatrix.MakeTranslation(x * -1, y * -1)); - - PostProcess(canvas, canvasInfo, path, paint); - - // Move the canvas back - canvas.Translate(x * -1, y * -1); - } - - internal virtual SKPath InternalCreateShapeClip(SKPath path) - { - var x = path.Bounds.Left; - var y = path.Bounds.Top; - - path.Transform(SKMatrix.MakeTranslation(x * -1, y * -1)); - var shapeClip = CreateShapeClip(path); - if (!shapeClip.IsEmpty) - shapeClip.Transform(SKMatrix.MakeTranslation(x, y)); - return shapeClip; - } - // Not only is this needed to initialize properties on the layer effects, it also prevents implementing anything // but LayerEffect outside the core internal abstract void Initialize(ILayerService layerService); diff --git a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/BlurEffect.cs b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/BlurEffect.cs index 978c4ca6e..eeea51b60 100644 --- a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/BlurEffect.cs +++ b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/BlurEffect.cs @@ -39,12 +39,13 @@ namespace Artemis.Plugins.LayerEffects.Filter public override void PreProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath renderBounds, SKPaint paint) { - if (_imageFilter != null) - paint.ImageFilter = SKImageFilter.CreateMerge(paint.ImageFilter, _imageFilter); + } public override void PostProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath renderBounds, SKPaint paint) { + if (_imageFilter != null) + paint.ImageFilter = SKImageFilter.CreateMerge(paint.ImageFilter, _imageFilter); } private void UpdateFilterType() diff --git a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/DilateEffect.cs b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/DilateEffect.cs index 6d232bd92..70c392d44 100644 --- a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/DilateEffect.cs +++ b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/DilateEffect.cs @@ -18,6 +18,13 @@ namespace Artemis.Plugins.LayerEffects.Filter } public override void PreProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath renderBounds, SKPaint paint) + { + var visualizationPath = new SKPath(); + visualizationPath.AddOval(SKRect.Create(0, 0, renderBounds.Bounds.Width / 2, renderBounds.Bounds.Height / 2)); + canvas.ClipPath(visualizationPath); + } + + public override void PostProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath renderBounds, SKPaint paint) { paint.ImageFilter = SKImageFilter.CreateDilate( (int) Properties.DilateRadius.CurrentValue.Width, @@ -25,9 +32,5 @@ namespace Artemis.Plugins.LayerEffects.Filter paint.ImageFilter ); } - - public override void PostProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath renderBounds, SKPaint paint) - { - } } } \ No newline at end of file diff --git a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/GlowEffect.cs b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/GlowEffect.cs index b3db29c1b..214c390db 100644 --- a/src/Plugins/Artemis.Plugins.LayerEffects.Filter/GlowEffect.cs +++ b/src/Plugins/Artemis.Plugins.LayerEffects.Filter/GlowEffect.cs @@ -18,6 +18,11 @@ namespace Artemis.Plugins.LayerEffects.Filter } public override void PreProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath renderBounds, SKPaint paint) + { + + } + + public override void PostProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath renderBounds, SKPaint paint) { paint.ImageFilter = SKImageFilter.CreateDropShadow( Properties.GlowOffset.CurrentValue.X, @@ -28,9 +33,5 @@ namespace Artemis.Plugins.LayerEffects.Filter paint.ImageFilter ); } - - public override void PostProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath renderBounds, SKPaint paint) - { - } } } \ No newline at end of file From e0951ca0f5517fdc0cd6e6f22303b0495e5b6161 Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Thu, 18 Jun 2020 19:55:59 +0200 Subject: [PATCH 2/2] Slight folder performance tweak --- src/Artemis.Core/Models/Profile/Folder.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Artemis.Core/Models/Profile/Folder.cs b/src/Artemis.Core/Models/Profile/Folder.cs index a14ed2872..0a3ff7fb8 100644 --- a/src/Artemis.Core/Models/Profile/Folder.cs +++ b/src/Artemis.Core/Models/Profile/Folder.cs @@ -78,12 +78,9 @@ namespace Artemis.Core.Models.Profile public override void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo) { - if (!Enabled) + if (!Enabled || Path == null || !Children.Any(c => c.Enabled)) return; - - if (Path == null) - return; - + if (_folderBitmap == null) _folderBitmap = new SKBitmap(new SKImageInfo((int) Path.Bounds.Width, (int) Path.Bounds.Height)); else if (_folderBitmap.Info.Width != (int) Path.Bounds.Width || _folderBitmap.Info.Height != (int) Path.Bounds.Height)