diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index 099a29e7c..4d613d614 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -17,6 +17,8 @@ namespace Artemis.Core.Models.Profile { private readonly List _layerElements; private List _leds; + private SKBitmap _renderBitmap; + private SKCanvas _renderCanvas; public Layer(Profile profile, ProfileElement parent, string name) { @@ -70,33 +72,28 @@ namespace Artemis.Core.Models.Profile foreach (var layerElement in LayerElements) layerElement.RenderPreProcess(surface, canvas); - using (var bitmap = new SKBitmap(new SKImageInfo((int) RenderRectangle.Width, (int) RenderRectangle.Height))) - using (var layerCanvas = new SKCanvas(bitmap)) + _renderCanvas.Clear(); + foreach (var layerElement in LayerElements) + layerElement.Render(surface, _renderCanvas); + + var baseShader = SKShader.CreateBitmap(_renderBitmap, SKShaderTileMode.Repeat, SKShaderTileMode.Repeat, SKMatrix.MakeTranslation(RenderRectangle.Left, RenderRectangle.Top)); + foreach (var layerElement in LayerElements) { - layerCanvas.Clear(); + var newBaseShader = layerElement.RenderPostProcess(surface, _renderBitmap, baseShader); + if (newBaseShader == null) + continue; - foreach (var layerElement in LayerElements) - layerElement.Render(surface, layerCanvas); + // Dispose the old base shader if the layer element provided a new one + if (!ReferenceEquals(baseShader, newBaseShader)) + baseShader.Dispose(); - var baseShader = SKShader.CreateBitmap(bitmap, SKShaderTileMode.Repeat, SKShaderTileMode.Repeat, SKMatrix.MakeTranslation(RenderRectangle.Left, RenderRectangle.Top)); - foreach (var layerElement in LayerElements) - { - var newBaseShader = layerElement.RenderPostProcess(surface, bitmap, baseShader); - if (newBaseShader == null) - continue; - - // Dispose the old base shader if the layer element provided a new one - if (!ReferenceEquals(baseShader, newBaseShader)) - baseShader.Dispose(); - - baseShader = newBaseShader; - } - - //canvas.ClipPath(RenderPath); - canvas.DrawRect(RenderRectangle, new SKPaint {Shader = baseShader, FilterQuality = SKFilterQuality.Low}); - baseShader.Dispose(); + baseShader = newBaseShader; } + canvas.ClipPath(RenderPath); + canvas.DrawRect(RenderRectangle, new SKPaint {Shader = baseShader, FilterQuality = SKFilterQuality.Low}); + baseShader.Dispose(); + canvas.Restore(); } @@ -188,7 +185,7 @@ namespace Artemis.Core.Models.Profile _leds = leds; CalculateRenderProperties(); } - + internal void CalculateRenderProperties() { if (!Leds.Any()) @@ -208,6 +205,13 @@ namespace Artemis.Core.Models.Profile path.AddRect(artemisLed.AbsoluteRenderRectangle); RenderPath = path; + + var oldBitmap = _renderBitmap; + var oldCanvas = _renderCanvas; + _renderBitmap = new SKBitmap(new SKImageInfo((int) RenderRectangle.Width, (int) RenderRectangle.Height)); + _renderCanvas = new SKCanvas(_renderBitmap); + oldBitmap?.Dispose(); + oldCanvas?.Dispose(); OnRenderPropertiesUpdated(); } diff --git a/src/Artemis.Core/Services/RgbService.cs b/src/Artemis.Core/Services/RgbService.cs index 5f6719938..fc2445c71 100644 --- a/src/Artemis.Core/Services/RgbService.cs +++ b/src/Artemis.Core/Services/RgbService.cs @@ -57,7 +57,7 @@ namespace Artemis.Core.Services _logger.Warning("RgbDevice provider {deviceProvider} has no devices", deviceProvider.GetType().Name); return; } - + foreach (var surfaceDevice in deviceProvider.Devices) { if (!_loadedDevices.Contains(surfaceDevice)) diff --git a/src/Artemis.Plugins.LayerElements.Noise/Artemis.Plugins.LayerElements.Noise.csproj b/src/Artemis.Plugins.LayerElements.Noise/Artemis.Plugins.LayerElements.Noise.csproj new file mode 100644 index 000000000..c2585910e --- /dev/null +++ b/src/Artemis.Plugins.LayerElements.Noise/Artemis.Plugins.LayerElements.Noise.csproj @@ -0,0 +1,101 @@ + + + + + Debug + AnyCPU + {7F4C7AB0-4C9B-452D-AFED-34544C903DEF} + Library + Properties + Artemis.Plugins.LayerElements.Noise + Artemis.Plugins.LayerElements.Noise + v4.7.2 + 512 + true + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + ..\packages\SkiaSharp.1.68.1\lib\net45\SkiaSharp.dll + + + ..\packages\Stylet.1.3.0\lib\net45\Stylet.dll + + + + ..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll + + + + ..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll + + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + + + + + + + + + + + + + + + + + + + MSBuild:Compile + Designer + + + + + + + PreserveNewest + + + + + {9b811f9b-86b9-4771-87af-72bae7078a36} + Artemis.Core + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElement.cs b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElement.cs new file mode 100644 index 000000000..8480880d4 --- /dev/null +++ b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElement.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Artemis.Core.Models.Profile; +using Artemis.Core.Models.Surface; +using Artemis.Core.Plugins.LayerElement; +using SkiaSharp; + +namespace Artemis.Plugins.LayerElements.Noise +{ + public class NoiseLayerElement : LayerElement + { + private SKShader _shader; + private List _testColors; + private SKPaint _paint; + + public NoiseLayerElement(Layer layer, Guid guid, NoiseLayerElementSettings settings, LayerElementDescriptor descriptor) : base(layer, guid, settings, descriptor) + { + Settings = settings; + + _testColors = new List(); + for (var i = 0; i < 9; i++) + { + if (i != 8) + _testColors.Add(SKColor.FromHsv(i * 32, 100, 100)); + else + _testColors.Add(SKColor.FromHsv(0, 100, 100)); + } + + CreateShader(); + Layer.RenderPropertiesUpdated += (sender, args) => CreateShader(); + Settings.PropertyChanged += (sender, args) => CreateShader(); + } + + private void CreateShader() + { + var shader = SKShader.CreatePerlinNoiseFractalNoise(1, 1, 1, 1); + + var oldShader = _shader; + var oldPaint = _paint; + _shader = shader; + _paint = new SKPaint {Shader = _shader, FilterQuality = SKFilterQuality.Low}; + oldShader?.Dispose(); + oldPaint?.Dispose(); + } + + public new NoiseLayerElementSettings Settings { get; } + + public override LayerElementViewModel GetViewModel() + { + return new NoiseLayerElementViewModel(this); + } + + public override void Render(ArtemisSurface surface, SKCanvas canvas) + { + canvas.DrawRect(Layer.AbsoluteRenderRectangle, _paint); + } + } +} \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementProvider.cs b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementProvider.cs new file mode 100644 index 000000000..30e9dba29 --- /dev/null +++ b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementProvider.cs @@ -0,0 +1,25 @@ +using Artemis.Core.Plugins.LayerElement; +using Artemis.Core.Plugins.Models; + +namespace Artemis.Plugins.LayerElements.Noise +{ + public class NoiseLayerElementProvider : LayerElementProvider + { + public NoiseLayerElementProvider(PluginInfo pluginInfo) : base(pluginInfo) + { + AddLayerElementDescriptor("Noise", "A brush of that shows a perlin noise", "Brush"); + } + + public override void EnablePlugin() + { + } + + public override void DisablePlugin() + { + } + + public override void Dispose() + { + } + } +} \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementSettings.cs b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementSettings.cs new file mode 100644 index 000000000..d21103516 --- /dev/null +++ b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementSettings.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.ComponentModel; +using Artemis.Core.Plugins.LayerElement; +using SkiaSharp; + +namespace Artemis.Plugins.LayerElements.Noise +{ + public class NoiseLayerElementSettings : LayerElementSettings + { + private BrushType _brushType; + private List _colors; + + public NoiseLayerElementSettings() + { + BrushType = BrushType.Solid; + Colors = new List(); + } + + public BrushType BrushType + { + get => _brushType; + set => SetAndNotify(ref _brushType, value); + } + + public List Colors + { + get => _colors; + set => SetAndNotify(ref _colors, value); + } + } + + public enum BrushType + { + [Description("Solid")] + Solid, + + [Description("Linear Gradient")] + LinearGradient, + + [Description("Radial Gradient")] + RadialGradient, + + [Description("Sweep Gradient")] + SweepGradient + } +} \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementView.xaml b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementView.xaml new file mode 100644 index 000000000..c2f752827 --- /dev/null +++ b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementView.xaml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Setting title + Setting subtitle + + + + + + + + + + + + + + + + + + + Setting title + Setting subtitle + + + + + + + + + + + + + + + + + + + Setting title + Setting subtitle + + + + + + + + + + + + + + + + + + + Setting title + Setting subtitle + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementViewModel.cs b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementViewModel.cs new file mode 100644 index 000000000..9d081dd9b --- /dev/null +++ b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementViewModel.cs @@ -0,0 +1,14 @@ +using Artemis.Core.Plugins.LayerElement; + +namespace Artemis.Plugins.LayerElements.Noise +{ + public class NoiseLayerElementViewModel : LayerElementViewModel + { + public NoiseLayerElementViewModel(NoiseLayerElement layerElement) : base(layerElement) + { + LayerElement = layerElement; + } + + public new NoiseLayerElement LayerElement { get; } + } +} \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerElements.Noise/Properties/AssemblyInfo.cs b/src/Artemis.Plugins.LayerElements.Noise/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..b4c93e2c5 --- /dev/null +++ b/src/Artemis.Plugins.LayerElements.Noise/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Artemis.Plugins.LayerElements.Noise")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Artemis.Plugins.LayerElements.Noise")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("7f4c7ab0-4c9b-452d-afed-34544c903def")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Artemis.Plugins.LayerElements.Noise/app.config b/src/Artemis.Plugins.LayerElements.Noise/app.config new file mode 100644 index 000000000..6c8c160bb --- /dev/null +++ b/src/Artemis.Plugins.LayerElements.Noise/app.config @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerElements.Noise/packages.config b/src/Artemis.Plugins.LayerElements.Noise/packages.config new file mode 100644 index 000000000..f09586bad --- /dev/null +++ b/src/Artemis.Plugins.LayerElements.Noise/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerElements.Noise/plugin.json b/src/Artemis.Plugins.LayerElements.Noise/plugin.json new file mode 100644 index 000000000..ad1c2a5c1 --- /dev/null +++ b/src/Artemis.Plugins.LayerElements.Noise/plugin.json @@ -0,0 +1,10 @@ +{ + "Guid": "61cbbf01-8d69-4ede-a972-f3f269da66d9", + "Name": "Noise layer elements", + "Version": { + "Major": 1, + "Minor": 0, + "Build": 0 + }, + "Main": "Artemis.Plugins.LayerElements.Noise.dll" +} \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElement.cs b/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElement.cs index cc25b86de..0e3f570f0 100644 --- a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElement.cs +++ b/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElement.cs @@ -12,6 +12,7 @@ namespace Artemis.Plugins.LayerElements.Brush { private SKShader _shader; private List _testColors; + private SKPaint _paint; public BrushLayerElement(Layer layer, Guid guid, BrushLayerElementSettings settings, LayerElementDescriptor descriptor) : base(layer, guid, settings, descriptor) { @@ -52,11 +53,13 @@ namespace Artemis.Plugins.LayerElements.Brush default: throw new ArgumentOutOfRangeException(); } - - var oldShader = _shader; - _shader = shader; + var oldShader = _shader; + var oldPaint = _paint; + _shader = shader; + _paint = new SKPaint {Shader = _shader, FilterQuality = SKFilterQuality.Low}; oldShader?.Dispose(); + oldPaint?.Dispose(); } public new BrushLayerElementSettings Settings { get; } @@ -68,10 +71,7 @@ namespace Artemis.Plugins.LayerElements.Brush public override void Render(ArtemisSurface surface, SKCanvas canvas) { - using (var paint = new SKPaint {Shader = _shader, FilterQuality = SKFilterQuality.Low}) - { - canvas.DrawRect(Layer.AbsoluteRenderRectangle, paint); - } + canvas.DrawRect(Layer.AbsoluteRenderRectangle, _paint); } } } \ No newline at end of file diff --git a/src/Artemis.sln b/src/Artemis.sln index 437dd44f4..ddd50d604 100644 --- a/src/Artemis.sln +++ b/src/Artemis.sln @@ -7,6 +7,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.UI", "Artemis.UI\Ar ProjectSection(ProjectDependencies) = postProject {E592F239-FAA0-4840-9C85-46E5867D06D5} = {E592F239-FAA0-4840-9C85-46E5867D06D5} {0F288A66-6EB0-4589-8595-E33A3A3EAEA2} = {0F288A66-6EB0-4589-8595-E33A3A3EAEA2} + {7F4C7AB0-4C9B-452D-AFED-34544C903DEF} = {7F4C7AB0-4C9B-452D-AFED-34544C903DEF} {235A45C7-24AD-4F47-B9D4-CD67E610A04D} = {235A45C7-24AD-4F47-B9D4-CD67E610A04D} {6FE5DED5-D62E-4811-985F-644124FCEEFE} = {6FE5DED5-D62E-4811-985F-644124FCEEFE} {A779B2F8-C253-4C4B-8634-6EB8F594E96D} = {A779B2F8-C253-4C4B-8634-6EB8F594E96D} @@ -28,6 +29,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.Plugins.Devices.Log EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.Plugins.LayerElements.Animations", "Artemis.Plugins.LayerElements.Animations\Artemis.Plugins.LayerElements.Animations.csproj", "{6FE5DED5-D62E-4811-985F-644124FCEEFE}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.Plugins.LayerElements.Noise", "Artemis.Plugins.LayerElements.Noise\Artemis.Plugins.LayerElements.Noise.csproj", "{7F4C7AB0-4C9B-452D-AFED-34544C903DEF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -100,6 +103,14 @@ Global {6FE5DED5-D62E-4811-985F-644124FCEEFE}.Release|Any CPU.Build.0 = Release|Any CPU {6FE5DED5-D62E-4811-985F-644124FCEEFE}.Release|x64.ActiveCfg = Release|Any CPU {6FE5DED5-D62E-4811-985F-644124FCEEFE}.Release|x64.Build.0 = Release|Any CPU + {7F4C7AB0-4C9B-452D-AFED-34544C903DEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7F4C7AB0-4C9B-452D-AFED-34544C903DEF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F4C7AB0-4C9B-452D-AFED-34544C903DEF}.Debug|x64.ActiveCfg = Debug|Any CPU + {7F4C7AB0-4C9B-452D-AFED-34544C903DEF}.Debug|x64.Build.0 = Debug|Any CPU + {7F4C7AB0-4C9B-452D-AFED-34544C903DEF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7F4C7AB0-4C9B-452D-AFED-34544C903DEF}.Release|Any CPU.Build.0 = Release|Any CPU + {7F4C7AB0-4C9B-452D-AFED-34544C903DEF}.Release|x64.ActiveCfg = Release|Any CPU + {7F4C7AB0-4C9B-452D-AFED-34544C903DEF}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -110,6 +121,7 @@ Global {A779B2F8-C253-4C4B-8634-6EB8F594E96D} = {E830A02B-A7E5-4A6B-943F-76B0A542630C} {235A45C7-24AD-4F47-B9D4-CD67E610A04D} = {E830A02B-A7E5-4A6B-943F-76B0A542630C} {6FE5DED5-D62E-4811-985F-644124FCEEFE} = {E830A02B-A7E5-4A6B-943F-76B0A542630C} + {7F4C7AB0-4C9B-452D-AFED-34544C903DEF} = {E830A02B-A7E5-4A6B-943F-76B0A542630C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C203080A-4473-4CC2-844B-F552EA43D66A}