diff --git a/CUE.NET.csproj b/CUE.NET.csproj
index a122d31..b7c90ac 100644
--- a/CUE.NET.csproj
+++ b/CUE.NET.csproj
@@ -46,10 +46,14 @@
-
+
+
+
+
-
+
+
@@ -75,6 +79,7 @@
+
diff --git a/Devices/Keyboard/Brushes/Gradient/AbstractGradient.cs b/Devices/Keyboard/Brushes/Gradient/AbstractGradient.cs
new file mode 100644
index 0000000..dfe056b
--- /dev/null
+++ b/Devices/Keyboard/Brushes/Gradient/AbstractGradient.cs
@@ -0,0 +1,47 @@
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+
+namespace CUE.NET.Devices.Keyboard.Brushes.Gradient
+{
+ public abstract class AbstractGradient : IGradient
+ {
+ #region Properties & Fields
+
+ public IList GradientStops { get; } = new List();
+
+ #endregion
+
+ #region Constructors
+
+ public AbstractGradient()
+ { }
+
+ public AbstractGradient(params GradientStop[] gradientStops)
+ {
+ foreach (GradientStop gradientStop in gradientStops)
+ GradientStops.Add(gradientStop);
+ }
+
+ #endregion
+
+ #region Methods
+
+ protected float ClipOffset(float offset)
+ {
+ float max = GradientStops.Max(n => n.Offset);
+ if (offset > max)
+ return max;
+
+ float min = GradientStops.Min(n => n.Offset);
+ if (offset < min)
+ return min;
+
+ return offset;
+ }
+
+ public abstract Color GetColor(float offset);
+
+ #endregion
+ }
+}
diff --git a/Devices/Keyboard/Brushes/GradientStop.cs b/Devices/Keyboard/Brushes/Gradient/GradientStop.cs
similarity index 88%
rename from Devices/Keyboard/Brushes/GradientStop.cs
rename to Devices/Keyboard/Brushes/Gradient/GradientStop.cs
index 48e428c..89bd03a 100644
--- a/Devices/Keyboard/Brushes/GradientStop.cs
+++ b/Devices/Keyboard/Brushes/Gradient/GradientStop.cs
@@ -1,6 +1,6 @@
using System.Drawing;
-namespace CUE.NET.Devices.Keyboard.Brushes
+namespace CUE.NET.Devices.Keyboard.Brushes.Gradient
{
public class GradientStop
{
diff --git a/Devices/Keyboard/Brushes/Gradient/IGradient.cs b/Devices/Keyboard/Brushes/Gradient/IGradient.cs
new file mode 100644
index 0000000..b5cc9ff
--- /dev/null
+++ b/Devices/Keyboard/Brushes/Gradient/IGradient.cs
@@ -0,0 +1,9 @@
+using System.Drawing;
+
+namespace CUE.NET.Devices.Keyboard.Brushes.Gradient
+{
+ public interface IGradient
+ {
+ Color GetColor(float offset);
+ }
+}
diff --git a/Devices/Keyboard/Brushes/Gradient/LinearGradient.cs b/Devices/Keyboard/Brushes/Gradient/LinearGradient.cs
new file mode 100644
index 0000000..5af52db
--- /dev/null
+++ b/Devices/Keyboard/Brushes/Gradient/LinearGradient.cs
@@ -0,0 +1,45 @@
+using System.Drawing;
+using System.Linq;
+
+namespace CUE.NET.Devices.Keyboard.Brushes.Gradient
+{
+ public class LinearGradient : AbstractGradient
+ {
+ #region Constructors
+
+ public LinearGradient()
+ { }
+
+ public LinearGradient(params GradientStop[] gradientStops)
+ : base(gradientStops)
+ { }
+
+ #endregion
+
+ #region Methods
+
+ public override Color GetColor(float offset)
+ {
+ if (!GradientStops.Any()) return Color.Transparent;
+ if (GradientStops.Count == 1) return GradientStops.First().Color;
+
+ offset = ClipOffset(offset);
+
+ GradientStop gsBefore = GradientStops.Where(n => n.Offset <= offset).OrderBy(n => n.Offset).Last();
+ GradientStop gsAfter = GradientStops.Where(n => n.Offset >= offset).OrderBy(n => n.Offset).First();
+
+ float blendFactor = 0f;
+ if (!gsBefore.Offset.Equals(gsAfter.Offset))
+ blendFactor = ((offset - gsBefore.Offset) / (gsAfter.Offset - gsBefore.Offset));
+
+ byte colA = (byte)((gsAfter.Color.A - gsBefore.Color.A) * blendFactor + gsBefore.Color.A);
+ byte colR = (byte)((gsAfter.Color.R - gsBefore.Color.R) * blendFactor + gsBefore.Color.R);
+ byte colG = (byte)((gsAfter.Color.G - gsBefore.Color.G) * blendFactor + gsBefore.Color.G);
+ byte colB = (byte)((gsAfter.Color.B - gsBefore.Color.B) * blendFactor + gsBefore.Color.B);
+
+ return Color.FromArgb(colA, colR, colG, colB);
+ }
+
+ #endregion
+ }
+}
diff --git a/Devices/Keyboard/Brushes/Gradient/RainbowGradient.cs b/Devices/Keyboard/Brushes/Gradient/RainbowGradient.cs
new file mode 100644
index 0000000..b777955
--- /dev/null
+++ b/Devices/Keyboard/Brushes/Gradient/RainbowGradient.cs
@@ -0,0 +1,40 @@
+// ReSharper disable MemberCanBePrivate.Global
+
+using System.Drawing;
+using CUE.NET.Helper;
+
+namespace CUE.NET.Devices.Keyboard.Brushes.Gradient
+{
+ public class RainbowGradient : IGradient
+ {
+ #region Properties & Fields
+
+ public float StartHue { get; set; }
+ public float EndHue { get; set; }
+
+ #endregion
+
+ #region Constructors
+
+ public RainbowGradient(float startHue = 0f, float endHue = 360f)
+ {
+ this.StartHue = startHue;
+ this.EndHue = endHue;
+ }
+
+ #endregion
+
+ #region Methods
+
+ #endregion
+
+ public Color GetColor(float offset)
+ {
+ float range = EndHue - StartHue;
+ float hue = (StartHue + (range * offset)) % 360f;
+ if (hue < 0)
+ hue += 360;
+ return ColorHelper.ColorFromHSV(hue, 1f, 1f);
+ }
+ }
+}
diff --git a/Devices/Keyboard/Brushes/LinearGradientBrush.cs b/Devices/Keyboard/Brushes/LinearGradientBrush.cs
index 172db0d..729d969 100644
--- a/Devices/Keyboard/Brushes/LinearGradientBrush.cs
+++ b/Devices/Keyboard/Brushes/LinearGradientBrush.cs
@@ -2,9 +2,8 @@
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable ReturnTypeCanBeEnumerable.Global
-using System.Collections.Generic;
using System.Drawing;
-using System.Linq;
+using CUE.NET.Devices.Keyboard.Brushes.Gradient;
using CUE.NET.Helper;
namespace CUE.NET.Devices.Keyboard.Brushes
@@ -15,7 +14,7 @@ namespace CUE.NET.Devices.Keyboard.Brushes
public PointF StartPoint { get; set; } = new PointF(0f, 0.5f);
public PointF EndPoint { get; set; } = new PointF(1f, 0.5f);
- public IList GradientStops { get; } = new List();
+ public IGradient Gradient { get; set; }
#endregion
@@ -24,19 +23,16 @@ namespace CUE.NET.Devices.Keyboard.Brushes
public LinearGradientBrush()
{ }
- public LinearGradientBrush(PointF startPoint, PointF endPoint, params GradientStop[] gradientStops)
+ public LinearGradientBrush(IGradient gradient)
+ {
+ this.Gradient = gradient;
+ }
+
+ public LinearGradientBrush(PointF startPoint, PointF endPoint, IGradient gradient)
{
this.StartPoint = startPoint;
this.EndPoint = endPoint;
-
- foreach (GradientStop gradientStop in gradientStops)
- GradientStops.Add(gradientStop);
- }
-
- public LinearGradientBrush(params GradientStop[] gradientStops)
- {
- foreach (GradientStop gradientStop in gradientStops)
- GradientStops.Add(gradientStop);
+ this.Gradient = gradient;
}
#endregion
@@ -45,37 +41,13 @@ namespace CUE.NET.Devices.Keyboard.Brushes
public override Color GetColorAtPoint(RectangleF rectangle, PointF point)
{
- if (!GradientStops.Any()) return Color.Transparent;
- if (GradientStops.Count == 1) return GradientStops.First().Color;
+ if (Gradient == null) return Color.Transparent;
PointF startPoint = new PointF(StartPoint.X * rectangle.Width, StartPoint.Y * rectangle.Height);
PointF endPoint = new PointF(EndPoint.X * rectangle.Width, EndPoint.Y * rectangle.Height);
- float offset = GradientHelper.CalculateGradientOffset(startPoint, endPoint, point);
-
- // Clip the input if before or after the max/min offset values
- float max = GradientStops.Max(n => n.Offset);
- if (offset > max)
- offset = max;
-
- float min = GradientStops.Min(n => n.Offset);
- if (offset < min)
- offset = min;
-
- // Find gradient stops that surround the input value
- GradientStop gsBefore = GradientStops.Where(n => n.Offset <= offset).OrderBy(n => n.Offset).Last();
- GradientStop gsAfter = GradientStops.Where(n => n.Offset >= offset).OrderBy(n => n.Offset).First();
-
- float blendFactor = 0f;
- if (!gsBefore.Offset.Equals(gsAfter.Offset))
- blendFactor = ((offset - gsBefore.Offset) / (gsAfter.Offset - gsBefore.Offset));
-
- byte colA = (byte)((gsAfter.Color.A - gsBefore.Color.A) * blendFactor + gsBefore.Color.A);
- byte colR = (byte)((gsAfter.Color.R - gsBefore.Color.R) * blendFactor + gsBefore.Color.R);
- byte colG = (byte)((gsAfter.Color.G - gsBefore.Color.G) * blendFactor + gsBefore.Color.G);
- byte colB = (byte)((gsAfter.Color.B - gsBefore.Color.B) * blendFactor + gsBefore.Color.B);
-
- return FinalizeColor(Color.FromArgb(colA, colR, colG, colB));
+ float offset = GradientHelper.CalculateLinearGradientOffset(startPoint, endPoint, point);
+ return FinalizeColor(Gradient.GetColor(offset));
}
#endregion
diff --git a/Devices/Keyboard/Brushes/RadialGradientBrush.cs b/Devices/Keyboard/Brushes/RadialGradientBrush.cs
new file mode 100644
index 0000000..57cca44
--- /dev/null
+++ b/Devices/Keyboard/Brushes/RadialGradientBrush.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Drawing;
+using CUE.NET.Devices.Keyboard.Brushes.Gradient;
+using CUE.NET.Helper;
+
+namespace CUE.NET.Devices.Keyboard.Brushes
+{
+ public class RadialGradientBrush : AbstractBrush
+ {
+ #region Properties & Fields
+
+ public PointF Center { get; set; } = new PointF(0.5f, 0.5f);
+ public IGradient Gradient { get; set; }
+
+ #endregion
+
+ #region Constructors
+
+ public RadialGradientBrush()
+ { }
+
+ public RadialGradientBrush(IGradient gradient)
+ {
+ this.Gradient = gradient;
+ }
+
+ public RadialGradientBrush(PointF center, IGradient gradient)
+ {
+ this.Center = center;
+ this.Gradient = gradient;
+ }
+
+ #endregion
+
+ #region Methods
+
+ public override Color GetColorAtPoint(RectangleF rectangle, PointF point)
+ {
+ PointF centerPoint = new PointF(rectangle.X + rectangle.Width * Center.X, rectangle.Y + rectangle.Height * Center.Y);
+
+ // Calculate the distance to the farthest point from the center as reference (this has to be a corner)
+ float refDistance = (float)Math.Max(Math.Max(Math.Max(GradientHelper.CalculateDistance(rectangle.Location, centerPoint),
+ GradientHelper.CalculateDistance(new PointF(rectangle.X + rectangle.Width, rectangle.Y), centerPoint)),
+ GradientHelper.CalculateDistance(new PointF(rectangle.X, rectangle.Y + rectangle.Height), centerPoint)),
+ GradientHelper.CalculateDistance(new PointF(rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height), centerPoint));
+
+ float distance = GradientHelper.CalculateDistance(point, centerPoint);
+ float offset = distance / refDistance;
+ return FinalizeColor(Gradient.GetColor(offset));
+ }
+
+ #endregion
+ }
+}
diff --git a/Devices/Keyboard/Brushes/RainbowBrush.cs b/Devices/Keyboard/Brushes/RainbowBrush.cs
deleted file mode 100644
index 813d443..0000000
--- a/Devices/Keyboard/Brushes/RainbowBrush.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-// ReSharper disable MemberCanBePrivate.Global
-
-using System.Drawing;
-using CUE.NET.Helper;
-
-namespace CUE.NET.Devices.Keyboard.Brushes
-{
- public class RainbowBrush : AbstractBrush
- {
- #region Properties & Fields
-
- public PointF StartPoint { get; set; } = new PointF(0f, 0.5f);
- public PointF EndPoint { get; set; } = new PointF(1f, 0.5f);
- public float StartHue { get; set; }
- public float EndHue { get; set; }
-
- #endregion
-
- #region Constructors
-
- public RainbowBrush(float startHue = 0f, float endHue = 360f)
- {
- this.StartHue = startHue;
- this.EndHue = endHue;
- }
-
- public RainbowBrush(PointF startPoint, PointF endPoint, float startHue = 0f, float endHue = 360f)
- {
- this.StartPoint = startPoint;
- this.EndPoint = endPoint;
- this.StartHue = startHue;
- this.EndHue = endHue;
- }
-
- #endregion
-
- #region Methods
-
- public override Color GetColorAtPoint(RectangleF rectangle, PointF point)
- {
- PointF startPoint = new PointF(StartPoint.X * rectangle.Width, StartPoint.Y * rectangle.Height);
- PointF endPoint = new PointF(EndPoint.X * rectangle.Width, EndPoint.Y * rectangle.Height);
-
- float offset = GradientHelper.CalculateGradientOffset(startPoint, endPoint, point);
- float range = EndHue - StartHue;
-
- float hue = (StartHue + (range * offset)) % 360f;
- return FinalizeColor(ColorHelper.ColorFromHSV(hue, 1f, 1f));
- }
-
- #endregion
- }
-}
diff --git a/Devices/Keyboard/Brushes/RandomColorBrush.cs b/Devices/Keyboard/Brushes/RandomColorBrush.cs
new file mode 100644
index 0000000..c8ff304
--- /dev/null
+++ b/Devices/Keyboard/Brushes/RandomColorBrush.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Drawing;
+using CUE.NET.Helper;
+
+namespace CUE.NET.Devices.Keyboard.Brushes
+{
+ //TODO DarthAffe 30.09.2015: Like this the brush seems kinda useless. Think about making it cool.
+ public class RandomColorBrush : AbstractBrush
+ {
+ #region Properties & Fields
+
+ private Random _random = new Random();
+
+ #endregion
+
+ #region Methods
+
+ public override Color GetColorAtPoint(RectangleF rectangle, PointF point)
+ {
+ return FinalizeColor(ColorHelper.ColorFromHSV((float)_random.NextDouble() * 360f, 1, 1));
+ }
+
+ #endregion
+ }
+}
diff --git a/Examples/SimpleDevTest/Program.cs b/Examples/SimpleDevTest/Program.cs
index fdcaf38..04495bf 100644
--- a/Examples/SimpleDevTest/Program.cs
+++ b/Examples/SimpleDevTest/Program.cs
@@ -6,6 +6,7 @@ using CUE.NET;
using CUE.NET.Devices.Generic.Enums;
using CUE.NET.Devices.Keyboard;
using CUE.NET.Devices.Keyboard.Brushes;
+using CUE.NET.Devices.Keyboard.Brushes.Gradient;
using CUE.NET.Devices.Keyboard.Enums;
using CUE.NET.Devices.Keyboard.Extensions;
using CUE.NET.Devices.Keyboard.Keys;
@@ -87,7 +88,7 @@ namespace SimpleDevTest
GradientStop moveableStop = new GradientStop(0, Color.FromArgb(0, 255, 0));
// Create a basic (by default horizontal) brush ...
- LinearGradientBrush linearBrush = new LinearGradientBrush(new GradientStop(0, Color.Blue), moveableStop, new GradientStop(1f, Color.White));
+ LinearGradientBrush linearBrush = new LinearGradientBrush(new LinearGradient(new GradientStop(0, Color.Blue), moveableStop, new GradientStop(1f, Color.White)));
// ... and add it as the keyboard background
keyboard.Brush = linearBrush;
@@ -129,17 +130,17 @@ namespace SimpleDevTest
Console.WriteLine("rainbow-test");
// Create an simple horizontal rainbow containing two times the full spectrum
- RainbowBrush rainbowBrush = new RainbowBrush(0, 720);
+ RainbowGradient rainbowGradient = new RainbowGradient(0, 720);
// Add the rainbow to the keyboard and perform an initial update
- keyboard.Brush = rainbowBrush;
+ keyboard.Brush = new LinearGradientBrush(rainbowGradient);
keyboard.UpdateLeds();
// Let the rainbow move around for 10 secs
for (int i = 0; i < 100; i++)
{
- rainbowBrush.StartHue += 10f;
- rainbowBrush.EndHue += 10f;
+ rainbowGradient.StartHue += 10f;
+ rainbowGradient.EndHue += 10f;
keyboard.UpdateLeds();
Thread.Sleep(100);
}
diff --git a/Helper/GradientHelper.cs b/Helper/GradientHelper.cs
index 8b866f0..54dac67 100644
--- a/Helper/GradientHelper.cs
+++ b/Helper/GradientHelper.cs
@@ -1,4 +1,6 @@
-using System;
+// ReSharper disable MemberCanBePrivate.Global
+
+using System;
using System.Drawing;
namespace CUE.NET.Helper
@@ -6,7 +8,7 @@ namespace CUE.NET.Helper
public static class GradientHelper
{
// Based on https://dotupdate.wordpress.com/2008/01/28/find-the-color-of-a-point-in-a-lineargradientbrush/
- public static float CalculateGradientOffset(PointF startPoint, PointF endPoint, PointF point)
+ public static float CalculateLinearGradientOffset(PointF startPoint, PointF endPoint, PointF point)
{
PointF intersectingPoint;
if (startPoint.Y.Equals(endPoint.Y)) // Horizontal case
@@ -39,9 +41,9 @@ namespace CUE.NET.Helper
///
/// Returns the signed magnitude of a point on a vector
///
- private static float CalculateDistance(PointF point, PointF origin, PointF direction)
+ public static float CalculateDistance(PointF point, PointF origin, PointF direction)
{
- float distance = (float)Math.Sqrt((point.Y - origin.Y) * (point.Y - origin.Y) + (point.X - origin.X) * (point.X - origin.X));
+ float distance = CalculateDistance(point, origin);
return (((point.Y < origin.Y) && (direction.Y > origin.Y)) ||
((point.Y > origin.Y) && (direction.Y < origin.Y)) ||
@@ -49,5 +51,10 @@ namespace CUE.NET.Helper
((point.Y.Equals(origin.Y)) && (point.X > origin.X) && (direction.X < origin.X)))
? -distance : distance;
}
+
+ public static float CalculateDistance(PointF point1, PointF point2)
+ {
+ return (float)Math.Sqrt((point1.Y - point2.Y) * (point1.Y - point2.Y) + (point1.X - point2.X) * (point1.X - point2.X));
+ }
}
}