diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj
index e1b091e70..4a90f4988 100644
--- a/src/Artemis.Core/Artemis.Core.csproj
+++ b/src/Artemis.Core/Artemis.Core.csproj
@@ -110,8 +110,11 @@
..\packages\Serilog.Sinks.File.4.0.0\lib\net45\Serilog.Sinks.File.dll
-
- ..\packages\Stylet.1.2.0\lib\net45\Stylet.dll
+
+ ..\packages\SkiaSharp.1.68.1\lib\net45\SkiaSharp.dll
+
+
+ ..\packages\Stylet.1.3.0\lib\net45\Stylet.dll
@@ -125,20 +128,19 @@
..\packages\System.Diagnostics.DiagnosticSource.4.5.1\lib\net46\System.Diagnostics.DiagnosticSource.dll
-
..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll
-
- ..\packages\System.Numerics.Vectors.4.6.0-preview5.19224.8\lib\net46\System.Numerics.Vectors.dll
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
..\packages\System.Reflection.Metadata.1.7.0-preview8.19405.3\lib\netstandard2.0\System.Reflection.Metadata.dll
- ..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0-preview8.19405.3\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
@@ -156,6 +158,7 @@
+
@@ -189,7 +192,6 @@
-
@@ -230,5 +232,7 @@
+
+
\ No newline at end of file
diff --git a/src/Artemis.Core/Events/FrameRenderedEventArgs.cs b/src/Artemis.Core/Events/FrameRenderedEventArgs.cs
index 144482c9c..d88bb89b7 100644
--- a/src/Artemis.Core/Events/FrameRenderedEventArgs.cs
+++ b/src/Artemis.Core/Events/FrameRenderedEventArgs.cs
@@ -1,18 +1,19 @@
using System;
using System.Drawing;
+using Artemis.Core.RGB.NET;
using RGB.NET.Core;
namespace Artemis.Core.Events
{
public class FrameRenderedEventArgs : EventArgs
{
- public FrameRenderedEventArgs(Bitmap bitmap, RGBSurface rgbSurface)
+ public FrameRenderedEventArgs(GraphicsDecorator graphicsDecorator, RGBSurface rgbSurface)
{
- Bitmap = bitmap;
+ GraphicsDecorator = graphicsDecorator;
RgbSurface = rgbSurface;
}
-
- public Bitmap Bitmap { get; }
+
+ public GraphicsDecorator GraphicsDecorator { get; }
public RGBSurface RgbSurface { get; }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Events/FrameRenderingEventArgs.cs b/src/Artemis.Core/Events/FrameRenderingEventArgs.cs
index 70ed191ac..05d05eff0 100644
--- a/src/Artemis.Core/Events/FrameRenderingEventArgs.cs
+++ b/src/Artemis.Core/Events/FrameRenderingEventArgs.cs
@@ -1,23 +1,23 @@
using System;
using System.Collections.Generic;
-using System.Drawing;
using Artemis.Core.Plugins.Abstract;
using RGB.NET.Core;
+using SkiaSharp;
namespace Artemis.Core.Events
{
public class FrameRenderingEventArgs : EventArgs
{
- public FrameRenderingEventArgs(List modules, Bitmap bitmap, double deltaTime, RGBSurface rgbSurface)
+ public FrameRenderingEventArgs(List modules, SKCanvas canvas, double deltaTime, RGBSurface rgbSurface)
{
Modules = modules;
- Bitmap = bitmap;
+ Canvas = canvas;
DeltaTime = deltaTime;
RgbSurface = rgbSurface;
}
public List Modules { get; }
- public Bitmap Bitmap { get; }
+ public SKCanvas Canvas { get; }
public double DeltaTime { get; }
public RGBSurface RgbSurface { get; }
}
diff --git a/src/Artemis.Core/Extensions/DoubleExtensions.cs b/src/Artemis.Core/Extensions/DoubleExtensions.cs
new file mode 100644
index 000000000..7eda9aa26
--- /dev/null
+++ b/src/Artemis.Core/Extensions/DoubleExtensions.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Artemis.Core.Extensions
+{
+ public static class DoubleExtensions
+ {
+ public static int RoundToInt(this double number)
+ {
+ return (int) Math.Round(number, MidpointRounding.AwayFromZero);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.Core/Extensions/RgbRectangleExtensions.cs b/src/Artemis.Core/Extensions/RgbRectangleExtensions.cs
index bbc3c21e1..3910dc9a0 100644
--- a/src/Artemis.Core/Extensions/RgbRectangleExtensions.cs
+++ b/src/Artemis.Core/Extensions/RgbRectangleExtensions.cs
@@ -1,16 +1,17 @@
-using System.Drawing;
+using RGB.NET.Core;
+using SkiaSharp;
namespace Artemis.Core.Extensions
{
public static class RgbRectangleExtensions
{
- public static Rectangle ToDrawingRectangle(this global::RGB.NET.Core.Rectangle rectangle, double scale)
+ public static SKRect ToSKRect(this Rectangle rectangle, double scale)
{
- return new Rectangle(
- (int) (rectangle.Location.X * scale),
- (int) (rectangle.Location.Y * scale),
- (int) (rectangle.Size.Width * scale),
- (int) (rectangle.Size.Height * scale)
+ return SKRect.Create(
+ (rectangle.Location.X * scale).RoundToInt(),
+ (rectangle.Location.Y * scale).RoundToInt(),
+ (rectangle.Size.Width * scale).RoundToInt(),
+ (rectangle.Size.Height * scale).RoundToInt()
);
}
}
diff --git a/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs b/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs
index 8fec27918..ca259edd1 100644
--- a/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs
+++ b/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
-using System.Drawing;
using System.Linq;
using Artemis.Core.Models.Surface;
+using SkiaSharp;
using Stylet;
namespace Artemis.Core.Models.Profile.Abstract
@@ -45,7 +45,7 @@ namespace Artemis.Core.Models.Profile.Abstract
///
/// Renders the element
///
- public abstract void Render(double deltaTime, ArtemisSurface surface, Graphics graphics);
+ public abstract void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas);
///
/// Applies the profile element's properties to the underlying storage entity
diff --git a/src/Artemis.Core/Models/Profile/Folder.cs b/src/Artemis.Core/Models/Profile/Folder.cs
index 41fde07ae..5d72238ee 100644
--- a/src/Artemis.Core/Models/Profile/Folder.cs
+++ b/src/Artemis.Core/Models/Profile/Folder.cs
@@ -1,9 +1,9 @@
using System;
-using System.Drawing;
using System.Linq;
using Artemis.Core.Models.Profile.Abstract;
using Artemis.Core.Models.Surface;
using Artemis.Storage.Entities.Profile;
+using SkiaSharp;
namespace Artemis.Core.Models.Profile
{
@@ -56,11 +56,11 @@ namespace Artemis.Core.Models.Profile
profileElement.Update(deltaTime);
}
- public override void Render(double deltaTime, ArtemisSurface surface, Graphics graphics)
+ public override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas)
{
// Folders don't render but their children do
foreach (var profileElement in Children)
- profileElement.Render(deltaTime, surface, graphics);
+ profileElement.Render(deltaTime, surface, canvas);
}
public Folder AddFolder(string name)
diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs
index aee7eab8b..15ec80610 100644
--- a/src/Artemis.Core/Models/Profile/Layer.cs
+++ b/src/Artemis.Core/Models/Profile/Layer.cs
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
-using System.Drawing;
-using System.Drawing.Drawing2D;
using System.Linq;
using Artemis.Core.Extensions;
using Artemis.Core.Models.Profile.Abstract;
@@ -10,6 +8,7 @@ using Artemis.Core.Models.Surface;
using Artemis.Core.Plugins.LayerElement;
using Artemis.Storage.Entities.Profile;
using Newtonsoft.Json;
+using SkiaSharp;
namespace Artemis.Core.Models.Profile
{
@@ -50,8 +49,9 @@ namespace Artemis.Core.Models.Profile
public ReadOnlyCollection Leds => _leds.AsReadOnly();
public ReadOnlyCollection LayerElements => _layerElements.AsReadOnly();
- public Rectangle RenderRectangle { get; set; }
- public GraphicsPath RenderPath { get; set; }
+ public SKRect RenderRectangle { get; set; }
+ public SKRect AbsoluteRenderRectangle { get; set; }
+ public SKPath RenderPath { get; set; }
public override void Update(double deltaTime)
{
@@ -59,20 +59,44 @@ namespace Artemis.Core.Models.Profile
layerElement.Update(deltaTime);
}
- public override void Render(double deltaTime, ArtemisSurface surface, Graphics graphics)
+ public override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas)
{
- graphics.SetClip(RenderPath);
+ if (RenderRectangle == null || AbsoluteRenderRectangle == null || RenderPath == null)
+ return;
+
+ canvas.Save();
foreach (var layerElement in LayerElements)
- layerElement.RenderPreProcess(surface, graphics);
+ layerElement.RenderPreProcess(surface, canvas);
- foreach (var layerElement in LayerElements)
- layerElement.Render(surface, graphics);
+ using (var bitmap = new SKBitmap(new SKImageInfo((int) RenderRectangle.Width, (int) RenderRectangle.Height)))
+ using (var layerCanvas = new SKCanvas(bitmap))
+ {
+ layerCanvas.Clear();
- foreach (var layerElement in LayerElements)
- layerElement.RenderPostProcess(surface, graphics);
+ foreach (var layerElement in LayerElements)
+ layerElement.Render(surface, layerCanvas);
- graphics.ResetClip();
+ 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();
+ }
+
+ canvas.Restore();
}
internal override void ApplyToEntity()
@@ -167,21 +191,36 @@ namespace Artemis.Core.Models.Profile
}
// Determine to top-left and bottom-right
- var minX = Leds.Min(l => l.AbsoluteRenderRectangle.X);
- var minY = Leds.Min(l => l.AbsoluteRenderRectangle.Y);
- var maxX = Leds.Max(l => l.AbsoluteRenderRectangle.X + l.AbsoluteRenderRectangle.Width);
- var maxY = Leds.Max(l => l.AbsoluteRenderRectangle.Y + l.AbsoluteRenderRectangle.Height);
+ var minX = Leds.Min(l => l.AbsoluteRenderRectangle.Left);
+ var minY = Leds.Min(l => l.AbsoluteRenderRectangle.Top);
+ var maxX = Leds.Max(l => l.AbsoluteRenderRectangle.Right);
+ var maxY = Leds.Max(l => l.AbsoluteRenderRectangle.Bottom);
- RenderRectangle = new Rectangle(minX, minY, maxX - minX, maxY - minY);
+ RenderRectangle = SKRect.Create(minX, minY, maxX - minX, maxY - minY);
+ AbsoluteRenderRectangle = SKRect.Create(0, 0, maxX - minX, maxY - minY);
+
+ var path = new SKPath {FillType = SKPathFillType.Winding};
+ foreach (var artemisLed in Leds)
+ path.AddRect(artemisLed.AbsoluteRenderRectangle);
- var path = new GraphicsPath();
- path.AddRectangles(Leds.Select(l => l.AbsoluteRenderRectangle).ToArray());
RenderPath = path;
+ OnRenderPropertiesUpdated();
}
public override string ToString()
{
return $"Layer - {nameof(Name)}: {Name}, {nameof(Order)}: {Order}";
}
+
+ #region Events
+
+ public event EventHandler RenderPropertiesUpdated;
+
+ private void OnRenderPropertiesUpdated()
+ {
+ RenderPropertiesUpdated?.Invoke(this, EventArgs.Empty);
+ }
+
+ #endregion
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs
index 2f6f17395..beea80582 100644
--- a/src/Artemis.Core/Models/Profile/Profile.cs
+++ b/src/Artemis.Core/Models/Profile/Profile.cs
@@ -1,11 +1,11 @@
using System;
-using System.Drawing;
using System.Linq;
using Artemis.Core.Exceptions;
using Artemis.Core.Models.Profile.Abstract;
using Artemis.Core.Models.Surface;
using Artemis.Core.Plugins.Models;
using Artemis.Storage.Entities.Profile;
+using SkiaSharp;
namespace Artemis.Core.Models.Profile
{
@@ -56,7 +56,7 @@ namespace Artemis.Core.Models.Profile
}
}
- public override void Render(double deltaTime, ArtemisSurface surface, Graphics graphics)
+ public override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas)
{
lock (this)
{
@@ -64,7 +64,7 @@ namespace Artemis.Core.Models.Profile
throw new ArtemisCoreException($"Cannot render inactive profile: {this}");
foreach (var profileElement in Children)
- profileElement.Render(deltaTime, surface, graphics);
+ profileElement.Render(deltaTime, surface, canvas);
}
}
diff --git a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs
index d276921a6..12fdc8269 100644
--- a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs
+++ b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs
@@ -1,13 +1,12 @@
using System;
using System.Collections.ObjectModel;
-using System.Drawing.Drawing2D;
using System.Linq;
using Artemis.Core.Extensions;
using Artemis.Core.Plugins.Abstract;
using Artemis.Storage.Entities.Surface;
using RGB.NET.Core;
+using SkiaSharp;
using Stylet;
-using Rectangle = System.Drawing.Rectangle;
namespace Artemis.Core.Models.Surface
{
@@ -38,8 +37,8 @@ namespace Artemis.Core.Models.Surface
Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
}
- public Rectangle RenderRectangle { get; private set; }
- public GraphicsPath RenderPath { get; private set; }
+ public SKRect RenderRectangle { get; private set; }
+ public SKPath RenderPath { get; private set; }
public IRGBDevice RgbDevice { get; }
public Plugin Plugin { get; }
@@ -95,11 +94,11 @@ namespace Artemis.Core.Models.Surface
internal void CalculateRenderProperties()
{
- RenderRectangle = new Rectangle(
- (int) Math.Round(RgbDevice.Location.X * Surface.Scale, MidpointRounding.AwayFromZero),
- (int) Math.Round(RgbDevice.Location.Y * Surface.Scale, MidpointRounding.AwayFromZero),
- (int) Math.Round(RgbDevice.DeviceRectangle.Size.Width * Surface.Scale, MidpointRounding.AwayFromZero),
- (int) Math.Round(RgbDevice.DeviceRectangle.Size.Height * Surface.Scale, MidpointRounding.AwayFromZero)
+ RenderRectangle = SKRect.Create(
+ (RgbDevice.Location.X * Surface.Scale).RoundToInt(),
+ (RgbDevice.Location.Y * Surface.Scale).RoundToInt(),
+ (RgbDevice.DeviceRectangle.Size.Width * Surface.Scale).RoundToInt(),
+ (RgbDevice.DeviceRectangle.Size.Height * Surface.Scale).RoundToInt()
);
if (!Leds.Any())
@@ -108,9 +107,10 @@ namespace Artemis.Core.Models.Surface
foreach (var led in Leds)
led.CalculateRenderRectangle();
- var path = new GraphicsPath();
- path.AddRectangles(Leds.Select(l => l.AbsoluteRenderRectangle).ToArray());
- path.FillMode = FillMode.Winding;
+ var path = new SKPath {FillType = SKPathFillType.Winding};
+ foreach (var artemisLed in Leds)
+ path.AddRect(artemisLed.AbsoluteRenderRectangle);
+
RenderPath = path;
}
diff --git a/src/Artemis.Core/Models/Surface/ArtemisLed.cs b/src/Artemis.Core/Models/Surface/ArtemisLed.cs
index fdc6f1162..5b5cb0910 100644
--- a/src/Artemis.Core/Models/Surface/ArtemisLed.cs
+++ b/src/Artemis.Core/Models/Surface/ArtemisLed.cs
@@ -1,7 +1,7 @@
-using System;
+using Artemis.Core.Extensions;
using RGB.NET.Core;
+using SkiaSharp;
using Stylet;
-using Rectangle = System.Drawing.Rectangle;
namespace Artemis.Core.Models.Surface
{
@@ -17,22 +17,22 @@ namespace Artemis.Core.Models.Surface
public Led RgbLed { get; }
public ArtemisDevice Device { get; }
- public Rectangle RenderRectangle { get; private set; }
- public Rectangle AbsoluteRenderRectangle { get; private set; }
+ public SKRect RenderRectangle { get; private set; }
+ public SKRect AbsoluteRenderRectangle { get; private set; }
public void CalculateRenderRectangle()
{
- RenderRectangle = new Rectangle(
- (int) Math.Round(RgbLed.LedRectangle.Location.X * Device.Surface.Scale, MidpointRounding.AwayFromZero),
- (int) Math.Round(RgbLed.LedRectangle.Location.Y * Device.Surface.Scale, MidpointRounding.AwayFromZero),
- (int) Math.Round(RgbLed.LedRectangle.Size.Width * Device.Surface.Scale, MidpointRounding.AwayFromZero),
- (int) Math.Round(RgbLed.LedRectangle.Size.Height * Device.Surface.Scale, MidpointRounding.AwayFromZero)
+ RenderRectangle = SKRect.Create(
+ (RgbLed.LedRectangle.Location.X * Device.Surface.Scale).RoundToInt(),
+ (RgbLed.LedRectangle.Location.Y * Device.Surface.Scale).RoundToInt(),
+ (RgbLed.LedRectangle.Size.Width * Device.Surface.Scale).RoundToInt(),
+ (RgbLed.LedRectangle.Size.Height * Device.Surface.Scale).RoundToInt()
);
- AbsoluteRenderRectangle = new Rectangle(
- (int) Math.Round(RgbLed.AbsoluteLedRectangle.Location.X * Device.Surface.Scale, MidpointRounding.AwayFromZero),
- (int) Math.Round(RgbLed.AbsoluteLedRectangle.Location.Y * Device.Surface.Scale, MidpointRounding.AwayFromZero),
- (int) Math.Round(RgbLed.AbsoluteLedRectangle.Size.Width * Device.Surface.Scale, MidpointRounding.AwayFromZero),
- (int) Math.Round(RgbLed.AbsoluteLedRectangle.Size.Height * Device.Surface.Scale, MidpointRounding.AwayFromZero)
+ AbsoluteRenderRectangle = SKRect.Create(
+ (RgbLed.AbsoluteLedRectangle.Location.X * Device.Surface.Scale).RoundToInt(),
+ (RgbLed.AbsoluteLedRectangle.Location.Y * Device.Surface.Scale).RoundToInt(),
+ (RgbLed.AbsoluteLedRectangle.Size.Width * Device.Surface.Scale).RoundToInt(),
+ (RgbLed.AbsoluteLedRectangle.Size.Height * Device.Surface.Scale).RoundToInt()
);
}
}
diff --git a/src/Artemis.Core/Plugins/Abstract/Module.cs b/src/Artemis.Core/Plugins/Abstract/Module.cs
index 3f085ed03..244e83ce6 100644
--- a/src/Artemis.Core/Plugins/Abstract/Module.cs
+++ b/src/Artemis.Core/Plugins/Abstract/Module.cs
@@ -1,7 +1,7 @@
using System.Collections.Generic;
-using System.Drawing;
using Artemis.Core.Models.Surface;
using Artemis.Core.Plugins.Models;
+using SkiaSharp;
namespace Artemis.Core.Plugins.Abstract
{
@@ -37,8 +37,8 @@ namespace Artemis.Core.Plugins.Abstract
///
/// Time since the last render
/// The RGB Surface to render to
- ///
- public abstract void Render(double deltaTime, ArtemisSurface surface, Graphics graphics);
+ ///
+ public abstract void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas);
///
/// Called when the module's view model is being show, return view models here to create tabs for them
diff --git a/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs b/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs
index 69d4f52ed..10954ed4f 100644
--- a/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs
+++ b/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs
@@ -1,9 +1,9 @@
using System;
-using System.Drawing;
using Artemis.Core.Exceptions;
using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Surface;
using Artemis.Core.Plugins.Models;
+using SkiaSharp;
namespace Artemis.Core.Plugins.Abstract
{
@@ -26,12 +26,12 @@ namespace Artemis.Core.Plugins.Abstract
}
///
- public override void Render(double deltaTime, ArtemisSurface surface, Graphics graphics)
+ public override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas)
{
lock (this)
{
// Render the profile
- ActiveProfile?.Render(deltaTime, surface, graphics);
+ ActiveProfile?.Render(deltaTime, surface, canvas);
}
}
diff --git a/src/Artemis.Core/Plugins/LayerElement/LayerElement.cs b/src/Artemis.Core/Plugins/LayerElement/LayerElement.cs
index b4df0ab4e..2ec7a5d41 100644
--- a/src/Artemis.Core/Plugins/LayerElement/LayerElement.cs
+++ b/src/Artemis.Core/Plugins/LayerElement/LayerElement.cs
@@ -1,6 +1,6 @@
-using System.Drawing;
-using Artemis.Core.Models.Profile;
+using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Surface;
+using SkiaSharp;
namespace Artemis.Core.Plugins.LayerElement
{
@@ -27,21 +27,43 @@ namespace Artemis.Core.Plugins.LayerElement
/// Called before rendering every frame, write your update logic here
///
///
- public abstract void Update(double deltaTime);
+ public virtual void Update(double deltaTime)
+ {
+ }
///
- /// Called before rendering, in the order configured on the layer
+ /// Allows you to perform rendering on the surface before any layer-clipping is applied
+ /// Called before rendering, in the order configured on the layer
///
- public abstract void RenderPreProcess(ArtemisSurface surface, Graphics graphics);
+ /// The surface the layer is rendered on
+ /// The entire surface canvas
+ public virtual void RenderPreProcess(ArtemisSurface surface, SKCanvas canvas)
+ {
+ }
///
- /// Called during rendering, in the order configured on the layer
+ /// The main method of rendering anything to the layer. The provided is specific to the layer
+ /// and matches it's width and height.
+ /// Called during rendering, in the order configured on the layer
///
- public abstract void Render(ArtemisSurface surface, Graphics graphics);
+ /// The surface the layer is rendered on
+ /// The layer canvas
+ public virtual void Render(ArtemisSurface surface, SKCanvas canvas)
+ {
+ }
///
- /// Called after rendering, in the order configured on the layer
+ /// Allows you to modify the used to draw the layer's on the
+ /// .
+ /// Called after rendering, in the order configured on the layer.
///
- public abstract void RenderPostProcess(ArtemisSurface surface, Graphics graphics);
+ /// The surface the layer is rendered on
+ /// The bitmap created from the layer canvas
+ /// The current shader used to draw the bitmap on the surface canvas
+ /// The resulting shader used to draw the bitmap on the surface canvas
+ public virtual SKShader RenderPostProcess(ArtemisSurface surface, SKBitmap bitmap, SKShader shader)
+ {
+ return shader;
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/RGB.NET/DirectBitmap.cs b/src/Artemis.Core/RGB.NET/DirectBitmap.cs
deleted file mode 100644
index 9bc7ddce4..000000000
--- a/src/Artemis.Core/RGB.NET/DirectBitmap.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-using System;
-using System.Drawing;
-using System.Drawing.Imaging;
-using System.Runtime.InteropServices;
-
-namespace Artemis.Core.RGB.NET
-{
- public class DirectBitmap : IDisposable
- {
- public DirectBitmap(int width, int height)
- {
- Width = width;
- Height = height;
- Bits = new int[width * height];
- BitsHandle = GCHandle.Alloc(Bits, GCHandleType.Pinned);
- Bitmap = new Bitmap(width, height, width * 4, PixelFormat.Format32bppPArgb, BitsHandle.AddrOfPinnedObject());
- }
-
- public Bitmap Bitmap { get; }
- public int[] Bits { get; }
- public bool Disposed { get; private set; }
- public int Height { get; }
- public int Width { get; }
-
- protected GCHandle BitsHandle { get; }
-
- public void Dispose()
- {
- if (Disposed) return;
- Disposed = true;
- Bitmap.Dispose();
- BitsHandle.Free();
- }
-
- public void SetPixel(int x, int y, Color colour)
- {
- var index = x + y * Width;
- var col = colour.ToArgb();
-
- Bits[index] = col;
- }
-
- public Color GetPixel(int x, int y)
- {
- var index = x + y * Width;
- if (index >= 0 && index - 1 <= Bits.Length)
- {
- var col = Bits[index];
- var result = Color.FromArgb(col);
-
- return result;
- }
-
- return Color.Black;
- }
- }
-}
\ No newline at end of file
diff --git a/src/Artemis.Core/RGB.NET/GraphicsDecorator.cs b/src/Artemis.Core/RGB.NET/GraphicsDecorator.cs
index 25c126c96..f93cecb82 100644
--- a/src/Artemis.Core/RGB.NET/GraphicsDecorator.cs
+++ b/src/Artemis.Core/RGB.NET/GraphicsDecorator.cs
@@ -1,16 +1,14 @@
using System;
-using System.Drawing;
using System.Linq;
+using Artemis.Core.Extensions;
using RGB.NET.Core;
-using Color = RGB.NET.Core.Color;
-using Rectangle = RGB.NET.Core.Rectangle;
+using SkiaSharp;
namespace Artemis.Core.RGB.NET
{
public class GraphicsDecorator : AbstractDecorator, IBrushDecorator, IDisposable
{
private readonly double _scale;
- private DirectBitmap _bitmap;
public GraphicsDecorator(ILedGroup ledGroup, double scale)
{
@@ -18,27 +16,25 @@ namespace Artemis.Core.RGB.NET
var leds = ledGroup.GetLeds().ToList();
if (!leds.Any())
- _bitmap = null;
- else
- {
- var width = Math.Min(leds.Max(l => l.AbsoluteLedRectangle.Location.X + l.AbsoluteLedRectangle.Size.Width) * scale, 4096);
- var height = Math.Min(leds.Max(l => l.AbsoluteLedRectangle.Location.Y + l.AbsoluteLedRectangle.Size.Height) * scale, 4096);
+ return;
- _bitmap = new DirectBitmap((int) width, (int) height);
- }
+ var width = Math.Min(leds.Max(l => l.AbsoluteLedRectangle.Location.X + l.AbsoluteLedRectangle.Size.Width) * scale, 4096);
+ var height = Math.Min(leds.Max(l => l.AbsoluteLedRectangle.Location.Y + l.AbsoluteLedRectangle.Size.Height) * scale, 4096);
+ Bitmap = new SKBitmap(new SKImageInfo(width.RoundToInt(), height.RoundToInt()));
}
+
+ public SKBitmap Bitmap { get; private set; }
public Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color)
{
+ if (Bitmap == null)
+ return new Color(0, 0, 0);
+
var x = renderTarget.Led.AbsoluteLedRectangle.Center.X * _scale;
var y = renderTarget.Led.AbsoluteLedRectangle.Center.Y * _scale;
- if (_bitmap != null && _bitmap.Width - 1 >= x && _bitmap.Height - 1 >= y)
- {
- var pixel = _bitmap.GetPixel((int) x, (int) y);
- return new Color(pixel.A, pixel.R, pixel.G, pixel.B);
- }
- return new Color(0, 0, 0);
+ var pixel = Bitmap.GetPixel(RoundToInt(x), RoundToInt(y));
+ return new Color(pixel.Alpha, pixel.Red, pixel.Green, pixel.Blue);
}
public override void OnDetached(IDecoratable decoratable)
@@ -48,27 +44,13 @@ namespace Artemis.Core.RGB.NET
public void Dispose()
{
- _bitmap?.Dispose();
- _bitmap = null;
+ Bitmap?.Dispose();
+ Bitmap = null;
}
- public Graphics GetGraphics()
+ private int RoundToInt(double number)
{
- try
- {
- return _bitmap == null ? null : Graphics.FromImage(_bitmap.Bitmap);
- }
- catch (AccessViolationException)
- {
- // ignored
- }
-
- return null;
- }
-
- public Bitmap GetBitmap()
- {
- return _bitmap?.Bitmap;
+ return (int) Math.Round(number, MidpointRounding.AwayFromZero);
}
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs
index 5f099afd9..f784b2c65 100644
--- a/src/Artemis.Core/Services/CoreService.cs
+++ b/src/Artemis.Core/Services/CoreService.cs
@@ -8,7 +8,7 @@ using Artemis.Core.Services.Interfaces;
using Artemis.Core.Services.Storage.Interfaces;
using RGB.NET.Core;
using Serilog;
-using Color = System.Drawing.Color;
+using SkiaSharp;
namespace Artemis.Core.Services
{
@@ -78,26 +78,25 @@ namespace Artemis.Core.Services
module.Update(args.DeltaTime);
}
- // If there is no graphics decorator, skip the frame
- if (_rgbService.GraphicsDecorator == null)
- return;
-
- // Render all active modules
- using (var g = _rgbService.GraphicsDecorator.GetGraphics())
+ // If there is no ready graphics decorator, skip the frame
+ lock (_rgbService.GraphicsDecorator)
{
- // If there are no graphics, skip the frame
- if (g == null)
+ if (_rgbService.GraphicsDecorator?.Bitmap == null)
return;
- g.Clear(Color.Black);
- lock (_modules)
+ // Render all active modules
+ using (var canvas = new SKCanvas(_rgbService.GraphicsDecorator.Bitmap))
{
- foreach (var module in _modules)
- module.Render(args.DeltaTime, _surfaceService.ActiveSurface, g);
+ canvas.Clear(new SKColor(0, 0, 0));
+ lock (_modules)
+ {
+ foreach (var module in _modules)
+ module.Render(args.DeltaTime, _surfaceService.ActiveSurface, canvas);
+ }
+
+ OnFrameRendering(new FrameRenderingEventArgs(_modules, canvas, args.DeltaTime, _rgbService.Surface));
}
}
-
- OnFrameRendering(new FrameRenderingEventArgs(_modules, _rgbService.GraphicsDecorator.GetBitmap(), args.DeltaTime, _rgbService.Surface));
}
catch (Exception e)
{
@@ -107,7 +106,7 @@ namespace Artemis.Core.Services
private void SurfaceOnUpdated(UpdatedEventArgs args)
{
- OnFrameRendered(new FrameRenderedEventArgs(_rgbService.GraphicsDecorator.GetBitmap(), _rgbService.Surface));
+ OnFrameRendered(new FrameRenderedEventArgs(_rgbService.GraphicsDecorator, _rgbService.Surface));
}
protected virtual void OnFrameRendering(FrameRenderingEventArgs e)
diff --git a/src/Artemis.Core/Services/DeviceService.cs b/src/Artemis.Core/Services/DeviceService.cs
index c511a1593..fab36dec0 100644
--- a/src/Artemis.Core/Services/DeviceService.cs
+++ b/src/Artemis.Core/Services/DeviceService.cs
@@ -1,8 +1,8 @@
-using System.Drawing;
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using Artemis.Core.Events;
using Artemis.Core.Models.Surface;
using Artemis.Core.Services.Interfaces;
+using SkiaSharp;
namespace Artemis.Core.Services
{
@@ -25,10 +25,7 @@ namespace Artemis.Core.Services
// Draw a white overlay over the device
void DrawOverlay(object sender, FrameRenderingEventArgs args)
{
- using (var g = Graphics.FromImage(args.Bitmap))
- {
- g.FillPath(new SolidBrush(Color.White), device.RenderPath);
- }
+ args.Canvas.DrawPath(device.RenderPath, new SKPaint {Color = new SKColor(255, 255, 255)});
}
_coreService.FrameRendering += DrawOverlay;
diff --git a/src/Artemis.Core/Services/RgbService.cs b/src/Artemis.Core/Services/RgbService.cs
index 34ef7ff62..5f6719938 100644
--- a/src/Artemis.Core/Services/RgbService.cs
+++ b/src/Artemis.Core/Services/RgbService.cs
@@ -30,6 +30,7 @@ namespace Artemis.Core.Services
_targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 25);
Surface = RGBSurface.Instance;
+ GraphicsDecorator = new GraphicsDecorator(new ListLedGroup(), 1);
// Let's throw these for now
Surface.Exception += SurfaceOnException;
@@ -100,21 +101,22 @@ namespace Artemis.Core.Services
public void UpdateGraphicsDecorator()
{
- // TODO: Create new one first, then clean up the old one for a smoother transition
-
- // Clean up the old background if present
- if (_background != null)
+ lock (GraphicsDecorator)
{
- _background.Brush?.RemoveAllDecorators();
- _background.Detach();
+ // Clean up the old background if present
+ if (_background != null)
+ {
+ _background.Brush?.RemoveAllDecorators();
+ _background.Detach();
+ }
+
+ // Apply the application wide brush and decorator
+ _background = new ListLedGroup(Surface.Leds) {Brush = new SolidColorBrush(new Color(255, 255, 255, 255))};
+ GraphicsDecorator = new GraphicsDecorator(_background, _renderScaleSetting.Value);
+ _background.Brush.RemoveAllDecorators();
+
+ _background.Brush.AddDecorator(GraphicsDecorator);
}
-
- // Apply the application wide brush and decorator
- _background = new ListLedGroup(Surface.Leds) {Brush = new SolidColorBrush(new Color(255, 255, 255, 255))};
- GraphicsDecorator = new GraphicsDecorator(_background, _renderScaleSetting.Value);
- _background.Brush.RemoveAllDecorators();
-
- _background.Brush.AddDecorator(GraphicsDecorator);
}
private void OnDeviceLoaded(DeviceEventArgs e)
diff --git a/src/Artemis.Core/app.config b/src/Artemis.Core/app.config
index 32dcf9823..29342a3c3 100644
--- a/src/Artemis.Core/app.config
+++ b/src/Artemis.Core/app.config
@@ -97,7 +97,7 @@
-
+
diff --git a/src/Artemis.Core/packages.config b/src/Artemis.Core/packages.config
index 2733bfdeb..b00ab366b 100644
--- a/src/Artemis.Core/packages.config
+++ b/src/Artemis.Core/packages.config
@@ -1,5 +1,4 @@
-
@@ -15,13 +14,14 @@
-
+
+
-
+
-
+
\ No newline at end of file
diff --git a/src/Artemis.Plugins.Devices.Corsair/app.config b/src/Artemis.Plugins.Devices.Corsair/app.config
index 9b3e8ff8d..7567ab9a5 100644
--- a/src/Artemis.Plugins.Devices.Corsair/app.config
+++ b/src/Artemis.Plugins.Devices.Corsair/app.config
@@ -13,7 +13,7 @@
-
+
diff --git a/src/Artemis.Plugins.Devices.Logitech/app.config b/src/Artemis.Plugins.Devices.Logitech/app.config
index c8bc187aa..be637eaeb 100644
--- a/src/Artemis.Plugins.Devices.Logitech/app.config
+++ b/src/Artemis.Plugins.Devices.Logitech/app.config
@@ -21,7 +21,7 @@
-
+
diff --git a/src/Artemis.Plugins.LayerElements.Animations/AnimationLayerElementProvider.cs b/src/Artemis.Plugins.LayerElements.Animations/AnimationLayerElementProvider.cs
new file mode 100644
index 000000000..11ed3bf09
--- /dev/null
+++ b/src/Artemis.Plugins.LayerElements.Animations/AnimationLayerElementProvider.cs
@@ -0,0 +1,26 @@
+using Artemis.Core.Plugins.LayerElement;
+using Artemis.Core.Plugins.Models;
+
+namespace Artemis.Plugins.LayerElements.Animations
+{
+ public class AnimationLayerElementProvider : LayerElementProvider
+ {
+ public AnimationLayerElementProvider(PluginInfo pluginInfo) : base(pluginInfo)
+ {
+ AddLayerElementDescriptor("Slide animation", "A sliding animation", "ArrowAll");
+ AddLayerElementDescriptor("Rotation animation", "A rotation animation", "CropRotate");
+ }
+
+ public override void Dispose()
+ {
+ }
+
+ public override void EnablePlugin()
+ {
+ }
+
+ public override void DisablePlugin()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.Plugins.LayerElements.Animations/Artemis.Plugins.LayerElements.Animations.csproj b/src/Artemis.Plugins.LayerElements.Animations/Artemis.Plugins.LayerElements.Animations.csproj
new file mode 100644
index 000000000..d8e14bc49
--- /dev/null
+++ b/src/Artemis.Plugins.LayerElements.Animations/Artemis.Plugins.LayerElements.Animations.csproj
@@ -0,0 +1,92 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {6FE5DED5-D62E-4811-985F-644124FCEEFE}
+ Library
+ Properties
+ Artemis.Plugins.LayerElements.Animations
+ Artemis.Plugins.LayerElements.Animations
+ 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\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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {9b811f9b-86b9-4771-87af-72bae7078a36}
+ Artemis.Core
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
+
+
+ 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}.
+
+
+
+
+ echo Copying plugin to Artemis.UI output directory
+XCOPY "$(TargetDir.TrimEnd('\'))" "$(SolutionDir)\Artemis.UI\$(OutDir)Plugins\$(ProjectName)" /s /q /i /y
+
+
\ No newline at end of file
diff --git a/src/Artemis.Plugins.LayerElements.Animations/Properties/AssemblyInfo.cs b/src/Artemis.Plugins.LayerElements.Animations/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..3bd9cdaa0
--- /dev/null
+++ b/src/Artemis.Plugins.LayerElements.Animations/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.Animations")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Artemis.Plugins.LayerElements.Animations")]
+[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("6fe5ded5-d62e-4811-985f-644124fceefe")]
+
+// 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.Animations/RotationLayerElement.cs b/src/Artemis.Plugins.LayerElements.Animations/RotationLayerElement.cs
new file mode 100644
index 000000000..ade9daa5f
--- /dev/null
+++ b/src/Artemis.Plugins.LayerElements.Animations/RotationLayerElement.cs
@@ -0,0 +1,36 @@
+using Artemis.Core.Models.Profile;
+using Artemis.Core.Models.Surface;
+using Artemis.Core.Plugins.LayerElement;
+using SkiaSharp;
+
+namespace Artemis.Plugins.LayerElements.Animations
+{
+ public class RotationLayerElement : LayerElement
+ {
+ public RotationLayerElement(Layer layer, LayerElementSettings settings, LayerElementDescriptor descriptor) : base(layer, settings, descriptor)
+ {
+ }
+
+ public float Rotation { get; set; }
+
+ public override LayerElementViewModel GetViewModel()
+ {
+ return null;
+ }
+
+ public override void Update(double deltaTime)
+ {
+ Rotation += (float)(deltaTime * 100);
+ if (Rotation > 360)
+ Rotation = 0;
+ }
+
+ public override SKShader RenderPostProcess(ArtemisSurface surface, SKBitmap bitmap, SKShader shader)
+ {
+ var center = new SKPoint(Layer.AbsoluteRenderRectangle.MidX, Layer.AbsoluteRenderRectangle.MidY);
+
+ // TODO Scale so that the rectangle is covered in every rotation, instead of just putting it at 2
+ return SKShader.CreateLocalMatrix(SKShader.CreateLocalMatrix(shader, SKMatrix.MakeScale(2, 2, center.X, center.Y)), SKMatrix.MakeRotationDegrees(Rotation, center.X, center.Y));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.Plugins.LayerElements.Animations/SlideLayerElement.cs b/src/Artemis.Plugins.LayerElements.Animations/SlideLayerElement.cs
new file mode 100644
index 000000000..17f308e93
--- /dev/null
+++ b/src/Artemis.Plugins.LayerElements.Animations/SlideLayerElement.cs
@@ -0,0 +1,33 @@
+using Artemis.Core.Models.Profile;
+using Artemis.Core.Models.Surface;
+using Artemis.Core.Plugins.LayerElement;
+using SkiaSharp;
+
+namespace Artemis.Plugins.LayerElements.Animations
+{
+ public class SlideLayerElement : LayerElement
+ {
+ public SlideLayerElement(Layer layer, LayerElementSettings settings, LayerElementDescriptor descriptor) : base(layer, settings, descriptor)
+ {
+ }
+
+ public int MovePercentage { get; set; }
+
+ public override LayerElementViewModel GetViewModel()
+ {
+ return null;
+ }
+
+ public override void Update(double deltaTime)
+ {
+ MovePercentage++;
+ if (MovePercentage > 100)
+ MovePercentage = 0;
+ }
+
+ public override SKShader RenderPostProcess(ArtemisSurface surface, SKBitmap bitmap, SKShader shader)
+ {
+ return SKShader.CreateLocalMatrix(shader, SKMatrix.MakeTranslation(Layer.RenderRectangle.Width / 100 * MovePercentage * -1, 0));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.Plugins.LayerElements.Animations/app.config b/src/Artemis.Plugins.LayerElements.Animations/app.config
new file mode 100644
index 000000000..03a8d9e5d
--- /dev/null
+++ b/src/Artemis.Plugins.LayerElements.Animations/app.config
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.Plugins.LayerElements.Animations/packages.config b/src/Artemis.Plugins.LayerElements.Animations/packages.config
new file mode 100644
index 000000000..97d48701a
--- /dev/null
+++ b/src/Artemis.Plugins.LayerElements.Animations/packages.config
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.Plugins.LayerElements.Animations/plugin.json b/src/Artemis.Plugins.LayerElements.Animations/plugin.json
new file mode 100644
index 000000000..a5e4bbb6f
--- /dev/null
+++ b/src/Artemis.Plugins.LayerElements.Animations/plugin.json
@@ -0,0 +1,10 @@
+{
+ "Guid": "a3b94380-6592-44f9-8717-3053ca9b4799",
+ "Name": "Animation layer elements",
+ "Version": {
+ "Major": 1,
+ "Minor": 0,
+ "Build": 0
+ },
+ "Main": "Artemis.Plugins.LayerElements.Animations.dll"
+}
\ No newline at end of file
diff --git a/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerElements.Brush.csproj b/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerElements.Brush.csproj
index f39c66274..7ef80e783 100644
--- a/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerElements.Brush.csproj
+++ b/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerElements.Brush.csproj
@@ -13,6 +13,8 @@
512
true
+
+
true
@@ -48,12 +50,28 @@
..\..\..\RGB.NET\bin\net45\RGB.NET.Core.dll
False
-
- ..\packages\Stylet.1.2.0\lib\net45\Stylet.dll
+
+ ..\packages\SkiaSharp.1.68.1\lib\net45\SkiaSharp.dll
+ False
+
+
+ ..\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
+
..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
False
@@ -100,4 +118,11 @@
echo Copying plugin to Artemis.UI output directory
XCOPY "$(TargetDir.TrimEnd('\'))" "$(SolutionDir)\Artemis.UI\$(OutDir)Plugins\$(ProjectName)" /s /q /i /y
+
+
+
+ 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.LayerTypes.Brush/BrushLayerElement.cs b/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElement.cs
index 37153dd13..607ed2f86 100644
--- a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElement.cs
+++ b/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElement.cs
@@ -1,15 +1,42 @@
-using System.Drawing;
+using System.Collections.Generic;
using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Surface;
using Artemis.Core.Plugins.LayerElement;
+using SkiaSharp;
namespace Artemis.Plugins.LayerElements.Brush
{
public class BrushLayerElement : LayerElement
{
+ private SKShader _shader;
+ private List _testColors;
+
public BrushLayerElement(Layer layer, BrushLayerElementSettings settings, LayerElementDescriptor descriptor) : base(layer, settings, descriptor)
{
- Settings = settings ?? new BrushLayerElementSettings {Brush = new SolidBrush(Color.Red)};
+ Settings = settings ?? new BrushLayerElementSettings();
+
+ _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();
+ }
+
+ private void CreateShader()
+ {
+ var center = new SKPoint(Layer.AbsoluteRenderRectangle.MidX, Layer.AbsoluteRenderRectangle.MidY);
+ var shader = SKShader.CreateSweepGradient(center, _testColors.ToArray(), null, SKShaderTileMode.Clamp, 0, 360);
+
+ var oldShader = _shader;
+ _shader = shader;
+
+ oldShader?.Dispose();
}
public new BrushLayerElementSettings Settings { get; }
@@ -19,22 +46,12 @@ namespace Artemis.Plugins.LayerElements.Brush
return new BrushLayerElementViewModel(this);
}
- public override void Update(double deltaTime)
- {
- }
-
- public override void RenderPreProcess(ArtemisSurface surface, Graphics graphics)
- {
- }
-
- public override void Render(ArtemisSurface surface, Graphics graphics)
- {
- if (Settings?.Brush != null)
- graphics.FillRectangle(Settings.Brush, Layer.RenderRectangle);
- }
-
- public override void RenderPostProcess(ArtemisSurface surface, Graphics graphics)
+ public override void Render(ArtemisSurface surface, SKCanvas canvas)
{
+ using (var paint = new SKPaint {Shader = _shader, FilterQuality = SKFilterQuality.Low})
+ {
+ canvas.DrawRect(Layer.AbsoluteRenderRectangle, paint);
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementSettings.cs b/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementSettings.cs
index b274810e8..e2d40a752 100644
--- a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementSettings.cs
+++ b/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementSettings.cs
@@ -1,9 +1,16 @@
-using Artemis.Core.Plugins.LayerElement;
+using System.Collections.Generic;
+using Artemis.Core.Plugins.LayerElement;
+using SkiaSharp;
namespace Artemis.Plugins.LayerElements.Brush
{
public class BrushLayerElementSettings : LayerElementSettings
{
- public System.Drawing.Brush Brush { get; set; }
+ public BrushLayerElementSettings()
+ {
+ Colors = new List();
+ }
+
+ public List Colors { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Plugins.LayerTypes.Brush/app.config b/src/Artemis.Plugins.LayerTypes.Brush/app.config
index 0edb16ded..983b4f4d9 100644
--- a/src/Artemis.Plugins.LayerTypes.Brush/app.config
+++ b/src/Artemis.Plugins.LayerTypes.Brush/app.config
@@ -13,7 +13,7 @@
-
+
diff --git a/src/Artemis.Plugins.LayerTypes.Brush/packages.config b/src/Artemis.Plugins.LayerTypes.Brush/packages.config
index ca0c2406c..66df08a60 100644
--- a/src/Artemis.Plugins.LayerTypes.Brush/packages.config
+++ b/src/Artemis.Plugins.LayerTypes.Brush/packages.config
@@ -1,7 +1,11 @@
-
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj b/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj
index bef9f7b45..af8d5a9fa 100644
--- a/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj
+++ b/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj
@@ -13,6 +13,8 @@
512
true
+
+
true
@@ -42,15 +44,27 @@
False
..\..\..\RGB.NET\bin\net45\RGB.NET.Core.dll
-
- ..\packages\Stylet.1.2.0\lib\net45\Stylet.dll
+
+ ..\packages\SkiaSharp.1.68.1\lib\net45\SkiaSharp.dll
+ False
+
+
+ ..\packages\Stylet.1.3.0\lib\net45\Stylet.dll
+
+ ..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll
+
-
-
- ..\packages\System.Drawing.Common.4.5.0\lib\net461\System.Drawing.Common.dll
- False
+
+ ..\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
..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
@@ -97,4 +111,11 @@
echo Copying plugin to Artemis.UI output directory
XCOPY "$(TargetDir.TrimEnd('\'))" "$(SolutionDir)\Artemis.UI\$(OutDir)Plugins\$(ProjectName)" /s /q /i /y
+
+
+
+ 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.Modules.General/ColorHelpers.cs b/src/Artemis.Plugins.Modules.General/ColorHelpers.cs
index 61e0d063b..df07d6012 100644
--- a/src/Artemis.Plugins.Modules.General/ColorHelpers.cs
+++ b/src/Artemis.Plugins.Modules.General/ColorHelpers.cs
@@ -1,5 +1,4 @@
using System;
-using System.Drawing;
namespace Artemis.Plugins.Modules.General
{
@@ -11,29 +10,5 @@ namespace Artemis.Plugins.Modules.General
{
return Rand.Next(0, 360);
}
-
- public static Color ColorFromHSV(double hue, double saturation, double value)
- {
- var hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
- var f = hue / 60 - Math.Floor(hue / 60);
-
- value = value * 255;
- var v = Convert.ToInt32(value);
- var p = Convert.ToInt32(value * (1 - saturation));
- var q = Convert.ToInt32(value * (1 - f * saturation));
- var t = Convert.ToInt32(value * (1 - (1 - f) * saturation));
-
- if (hi == 0)
- return Color.FromArgb(255, v, t, p);
- if (hi == 1)
- return Color.FromArgb(255, q, v, p);
- if (hi == 2)
- return Color.FromArgb(255, p, v, t);
- if (hi == 3)
- return Color.FromArgb(255, p, q, v);
- if (hi == 4)
- return Color.FromArgb(255, t, p, v);
- return Color.FromArgb(255, v, p, q);
- }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Plugins.Modules.General/GeneralModule.cs b/src/Artemis.Plugins.Modules.General/GeneralModule.cs
index 775ac0455..c732dfd12 100644
--- a/src/Artemis.Plugins.Modules.General/GeneralModule.cs
+++ b/src/Artemis.Plugins.Modules.General/GeneralModule.cs
@@ -1,21 +1,17 @@
using System;
using System.Collections.Generic;
-using System.Drawing;
-using System.Drawing.Drawing2D;
-using System.Linq;
+using System.Diagnostics;
using Artemis.Core.Models.Surface;
using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Plugins.Models;
using Artemis.Core.Services.Storage.Interfaces;
using Artemis.Plugins.Modules.General.ViewModels;
-using RGB.NET.Core;
-using Color = System.Drawing.Color;
+using SkiaSharp;
namespace Artemis.Plugins.Modules.General
{
public class GeneralModule : ProfileModule
{
- private readonly ColorBlend _rainbowColorBlend;
private readonly PluginSettings _settings;
public GeneralModule(PluginInfo pluginInfo, PluginSettings settings, ISurfaceService surfaceService) : base(pluginInfo)
@@ -23,31 +19,25 @@ namespace Artemis.Plugins.Modules.General
_settings = settings;
DisplayName = "General";
ExpandsMainDataModel = true;
- DeviceBrushes = new Dictionary();
+ DeviceShaders = new Dictionary();
+ RainbowColors = new List();
- var testSetting = _settings.GetSetting("TestSetting", DateTime.Now);
-
- Hues = new int[1000];
- for (var i = 0; i < 1000; i++)
- Hues[i] = ColorHelpers.GetRandomHue();
-
- _rainbowColorBlend = new ColorBlend(9);
for (var i = 0; i < 9; i++)
{
- _rainbowColorBlend.Positions[i] = i / 8f;
if (i != 8)
- _rainbowColorBlend.Colors[i] = ColorHelpers.ColorFromHSV(i * 32, 1, 1);
+ RainbowColors.Add(SKColor.FromHsv(i * 32, 100, 100));
else
- _rainbowColorBlend.Colors[i] = ColorHelpers.ColorFromHSV(0, 1, 1);
+ RainbowColors.Add(SKColor.FromHsv(0, 100, 100));
}
- surfaceService.SurfaceConfigurationUpdated += (sender, args) => DeviceBrushes.Clear();
+ surfaceService.SurfaceConfigurationUpdated += (sender, args) => DeviceShaders.Clear();
+ var testSetting = _settings.GetSetting("TestSetting", DateTime.Now);
}
- public int[] Hues { get; set; }
public int MovePercentage { get; set; }
- public Dictionary DeviceBrushes { get; set; }
+ public Dictionary DeviceShaders { get; set; }
+ public List RainbowColors { get; set; }
public override void EnablePlugin()
{
@@ -59,13 +49,6 @@ namespace Artemis.Plugins.Modules.General
public override void Update(double deltaTime)
{
- for (var i = 0; i < Hues.Length; i++)
- {
- Hues[i]++;
- if (Hues[i] > 360)
- Hues[i] = 0;
- }
-
MovePercentage++;
if (MovePercentage > 100)
MovePercentage = 0;
@@ -74,62 +57,46 @@ namespace Artemis.Plugins.Modules.General
}
- public override void Render(double deltaTime, ArtemisSurface surface, Graphics graphics)
+ public override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas)
{
- // Per-device coloring, slower
- // RenderPerDevice(surface, graphics);
+ base.Render(deltaTime, surface, canvas);
+ return;
- // Per-LED coloring, slowest
- // RenderPerLed(surface, graphics);
-
- base.Render(deltaTime, surface, graphics);
- }
-
- public void RenderFullSurface(ArtemisSurface surface, Graphics graphics)
- {
- }
-
- public void RenderPerDevice(ArtemisSurface surface, Graphics graphics)
- {
foreach (var device in surface.Devices)
{
- if (!DeviceBrushes.ContainsKey(device))
- DeviceBrushes.Add(device, new TextureBrush(RenderGradientForDevice(device), WrapMode.Tile));
+ using (var bitmap = new SKBitmap(new SKImageInfo((int) device.RenderRectangle.Width, (int) device.RenderRectangle.Height)))
+ {
+ using (var layerCanvas = new SKCanvas(bitmap))
+ {
+ layerCanvas.Clear();
+ SKShader shader;
+ if (DeviceShaders.ContainsKey(device))
+ shader = DeviceShaders[device];
+ else
+ {
+ shader = SKShader.CreateLinearGradient(
+ new SKPoint(0, 0),
+ new SKPoint(device.RenderRectangle.Width, 0),
+ RainbowColors.ToArray(),
+ null,
+ SKShaderTileMode.Clamp);
+ DeviceShaders.Add(device, shader);
+ }
- var brush = DeviceBrushes[device];
- brush.TranslateTransform((int) Math.Round(device.RenderRectangle.Width / 100.0 * MovePercentage), 0);
- graphics.FillPath(brush, device.RenderPath);
- brush.TranslateTransform((int) Math.Round(device.RenderRectangle.Width / 100.0 * MovePercentage) * -1, 0);
+ using (var paint = new SKPaint {Shader = shader, FilterQuality = SKFilterQuality.Low})
+ {
+ layerCanvas.DrawRect(0, 0, device.RenderRectangle.Width, device.RenderRectangle.Height, paint);
+ }
+ }
- graphics.DrawRectangle(new Pen(Color.Red), device.RenderRectangle);
- }
- }
-
- private Image RenderGradientForDevice(ArtemisDevice device)
- {
- var brush = new LinearGradientBrush(device.RenderRectangle, Color.Black, Color.Black, 0, false)
- {
- InterpolationColors = _rainbowColorBlend
- };
- var bitmap = new Bitmap(device.RenderRectangle.Width, device.RenderRectangle.Height);
- using (var g = Graphics.FromImage(bitmap))
- {
- g.FillRectangle(brush, 0, 0, device.RenderRectangle.Width, device.RenderRectangle.Height);
- }
-
- return bitmap;
- }
-
- public void RenderPerLed(ArtemisSurface surface, Graphics graphics)
- {
- var index = 0;
- foreach (var led in surface.Devices.SelectMany(d => d.Leds))
- {
- if (led.RgbLed.Id == LedId.HeadsetStand1)
- graphics.FillRectangle(new SolidBrush(Color.Red), led.AbsoluteRenderRectangle);
- else
- graphics.FillRectangle(new SolidBrush(ColorHelpers.ColorFromHSV(Hues[index], 1, 1)), led.AbsoluteRenderRectangle);
- index++;
+ using (var bitmapShader = SKShader.CreateBitmap(bitmap, SKShaderTileMode.Repeat, SKShaderTileMode.Repeat))
+ using (var translated = SKShader.CreateLocalMatrix(bitmapShader, SKMatrix.MakeTranslation(device.RenderRectangle.Width / 100 * MovePercentage * -1, 0)))
+ using (var translatedPaint = new SKPaint {Shader = translated, FilterQuality = SKFilterQuality.Low})
+ {
+ // Here we can let each module modify the shader as needed
+ canvas.DrawRect(device.RenderRectangle, translatedPaint);
+ }
+ }
}
}
diff --git a/src/Artemis.Plugins.Modules.General/app.config b/src/Artemis.Plugins.Modules.General/app.config
index 0edb16ded..983b4f4d9 100644
--- a/src/Artemis.Plugins.Modules.General/app.config
+++ b/src/Artemis.Plugins.Modules.General/app.config
@@ -13,7 +13,7 @@
-
+
diff --git a/src/Artemis.Plugins.Modules.General/packages.config b/src/Artemis.Plugins.Modules.General/packages.config
index c5ec6307a..865736c9f 100644
--- a/src/Artemis.Plugins.Modules.General/packages.config
+++ b/src/Artemis.Plugins.Modules.General/packages.config
@@ -1,8 +1,12 @@
-
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/App.config b/src/Artemis.UI/App.config
index 056019794..15f01e053 100644
--- a/src/Artemis.UI/App.config
+++ b/src/Artemis.UI/App.config
@@ -100,7 +100,7 @@
-
+
diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj
index d29501b6e..d9a6e68e6 100644
--- a/src/Artemis.UI/Artemis.UI.csproj
+++ b/src/Artemis.UI/Artemis.UI.csproj
@@ -117,16 +117,38 @@
..\packages\Serilog.2.8.0\lib\net46\Serilog.dll
+
+ ..\packages\SkiaSharp.1.68.1\lib\net45\SkiaSharp.dll
+
+
+ ..\packages\SkiaSharp.Views.Desktop.Common.1.68.1\lib\net45\SkiaSharp.Views.Desktop.Common.dll
+
+
+ ..\packages\SkiaSharp.Views.WPF.1.68.1\lib\net45\SkiaSharp.Views.WPF.dll
+
..\packages\Stylet.1.3.0\lib\net45\Stylet.dll
+
+ ..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll
+
..\packages\System.ComponentModel.Annotations.4.6.0\lib\net461\System.ComponentModel.Annotations.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
+
..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
@@ -420,5 +442,7 @@
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Settings/Debug/DebugViewModel.cs b/src/Artemis.UI/Screens/Settings/Debug/DebugViewModel.cs
index 72d6b088b..7179b8a65 100644
--- a/src/Artemis.UI/Screens/Settings/Debug/DebugViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/Debug/DebugViewModel.cs
@@ -1,12 +1,11 @@
using System;
-using System.Drawing;
-using System.Runtime.InteropServices;
using System.Windows;
-using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Artemis.Core.Events;
using Artemis.Core.Services.Interfaces;
+using SkiaSharp;
+using SkiaSharp.Views.WPF;
using Stylet;
namespace Artemis.UI.Screens.Settings.Debug
@@ -35,12 +34,27 @@ namespace Artemis.UI.Screens.Settings.Debug
private void CoreServiceOnFrameRendered(object sender, FrameRenderedEventArgs e)
{
- if (e.Bitmap == null)
- return;
+ Execute.PostToUIThread(() =>
+ {
+ if (!(CurrentFrame is WriteableBitmap writeableBitmap))
+ {
+ CurrentFrame = e.GraphicsDecorator.Bitmap.ToWriteableBitmap();
+ return;
+ }
- var imageSource = ImageSourceFromBitmap(e.Bitmap);
- imageSource.Freeze();
- Execute.PostToUIThread(() => { CurrentFrame = imageSource; });
+ using (var skiaImage = SKImage.FromPixels(e.GraphicsDecorator.Bitmap.PeekPixels()))
+ {
+ var info = new SKImageInfo(skiaImage.Width, skiaImage.Height);
+ writeableBitmap.Lock();
+ using (var pixmap = new SKPixmap(info, writeableBitmap.BackBuffer, writeableBitmap.BackBufferStride))
+ {
+ skiaImage.ReadPixels(pixmap, 0, 0);
+ }
+
+ writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, info.Width, info.Height));
+ writeableBitmap.Unlock();
+ }
+ });
}
private void CoreServiceOnFrameRendering(object sender, FrameRenderingEventArgs e)
@@ -61,23 +75,5 @@ namespace Artemis.UI.Screens.Settings.Debug
_coreService.FrameRendering -= CoreServiceOnFrameRendering;
base.OnDeactivate();
}
-
- // This is much quicker than saving the bitmap into a memory stream and converting it
- private static ImageSource ImageSourceFromBitmap(Bitmap bmp)
- {
- var handle = bmp.GetHbitmap();
- try
- {
- return Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
- }
- finally
- {
- DeleteObject(handle);
- }
- }
-
- [DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool DeleteObject([In] IntPtr hObject);
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/packages.config b/src/Artemis.UI/packages.config
index 73fe590d2..799e332f9 100644
--- a/src/Artemis.UI/packages.config
+++ b/src/Artemis.UI/packages.config
@@ -1,5 +1,4 @@
-
@@ -17,7 +16,14 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.sln b/src/Artemis.sln
index 71bccf436..437dd44f4 100644
--- a/src/Artemis.sln
+++ b/src/Artemis.sln
@@ -8,6 +8,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.UI", "Artemis.UI\Ar
{E592F239-FAA0-4840-9C85-46E5867D06D5} = {E592F239-FAA0-4840-9C85-46E5867D06D5}
{0F288A66-6EB0-4589-8595-E33A3A3EAEA2} = {0F288A66-6EB0-4589-8595-E33A3A3EAEA2}
{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}
EndProjectSection
EndProject
@@ -25,6 +26,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.Plugins.Devices.Cor
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.Plugins.Devices.Logitech", "Artemis.Plugins.Devices.Logitech\Artemis.Plugins.Devices.Logitech.csproj", "{235A45C7-24AD-4F47-B9D4-CD67E610A04D}"
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
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -89,6 +92,14 @@ Global
{235A45C7-24AD-4F47-B9D4-CD67E610A04D}.Release|Any CPU.Build.0 = Release|Any CPU
{235A45C7-24AD-4F47-B9D4-CD67E610A04D}.Release|x64.ActiveCfg = Release|Any CPU
{235A45C7-24AD-4F47-B9D4-CD67E610A04D}.Release|x64.Build.0 = Release|Any CPU
+ {6FE5DED5-D62E-4811-985F-644124FCEEFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6FE5DED5-D62E-4811-985F-644124FCEEFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6FE5DED5-D62E-4811-985F-644124FCEEFE}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {6FE5DED5-D62E-4811-985F-644124FCEEFE}.Debug|x64.Build.0 = Debug|Any CPU
+ {6FE5DED5-D62E-4811-985F-644124FCEEFE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -98,6 +109,7 @@ Global
{0F288A66-6EB0-4589-8595-E33A3A3EAEA2} = {E830A02B-A7E5-4A6B-943F-76B0A542630C}
{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}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C203080A-4473-4CC2-844B-F552EA43D66A}