diff --git a/CUE.NET.csproj b/CUE.NET.csproj
index 61448c7..8a536c0 100644
--- a/CUE.NET.csproj
+++ b/CUE.NET.csproj
@@ -66,6 +66,7 @@
+
@@ -91,6 +92,7 @@
+
diff --git a/Devices/Keyboard/Brushes/LinearGradientBrush.cs b/Devices/Keyboard/Brushes/LinearGradientBrush.cs
index 8751c40..7ab8482 100644
--- a/Devices/Keyboard/Brushes/LinearGradientBrush.cs
+++ b/Devices/Keyboard/Brushes/LinearGradientBrush.cs
@@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
+using CUE.NET.Helper;
namespace CUE.NET.Devices.Keyboard.Brushes
{
@@ -48,36 +49,10 @@ namespace CUE.NET.Devices.Keyboard.Brushes
if (!GradientStops.Any()) return Color.Transparent;
if (GradientStops.Count == 1) return GradientStops.First().Color;
- // Based on https://dotupdate.wordpress.com/2008/01/28/find-the-color-of-a-point-in-a-lineargradientbrush/
-
PointF startPoint = new PointF(StartPoint.X * rectangle.Width, StartPoint.Y * rectangle.Height);
PointF endPoint = new PointF(EndPoint.X * rectangle.Width, EndPoint.Y * rectangle.Height);
- PointF intersectingPoint;
- if (startPoint.Y.Equals(endPoint.Y)) // Horizontal case
- intersectingPoint = new PointF(point.X, startPoint.Y);
-
- else if (startPoint.X.Equals(endPoint.X)) // Vertical case
- intersectingPoint = new PointF(startPoint.X, point.Y);
-
- else // Diagnonal case
- {
- float slope = (endPoint.Y - startPoint.Y) / (endPoint.X - startPoint.X);
- float orthogonalSlope = -1 / slope;
-
- float startYIntercept = startPoint.Y - slope * startPoint.X;
- float pointYIntercept = point.Y - orthogonalSlope * point.X;
-
- float intersectingPointX = (pointYIntercept - startYIntercept) / (slope - orthogonalSlope);
- float intersectingPointY = slope * intersectingPointX + startYIntercept;
- intersectingPoint = new PointF(intersectingPointX, intersectingPointY);
- }
-
- // Calculate distances relative to the vector start
- float intersectDistance = CalculateDistance(intersectingPoint, startPoint, endPoint);
- float gradientLength = CalculateDistance(endPoint, startPoint, endPoint);
-
- float offset = intersectDistance / gradientLength;
+ 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);
@@ -103,21 +78,6 @@ namespace CUE.NET.Devices.Keyboard.Brushes
return Color.FromArgb(colA, colR, colG, colB);
}
- // Based on https://dotupdate.wordpress.com/2008/01/28/find-the-color-of-a-point-in-a-lineargradientbrush/
- ///
- /// Returns the signed magnitude of a point on a vector
- ///
- private 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));
-
- return (((point.Y < origin.Y) && (direction.Y > origin.Y)) ||
- ((point.Y > origin.Y) && (direction.Y < origin.Y)) ||
- ((point.Y.Equals(origin.Y)) && (point.X < origin.X) && (direction.X > origin.X)) ||
- ((point.Y.Equals(origin.Y)) && (point.X > origin.X) && (direction.X < origin.X)))
- ? -distance : distance;
- }
-
#endregion
}
}
diff --git a/Devices/Keyboard/Brushes/RainbowBrush.cs b/Devices/Keyboard/Brushes/RainbowBrush.cs
new file mode 100644
index 0000000..9bb0481
--- /dev/null
+++ b/Devices/Keyboard/Brushes/RainbowBrush.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Drawing;
+using CUE.NET.Helper;
+
+namespace CUE.NET.Devices.Keyboard.Brushes
+{
+ public class RainbowBrush : IBrush
+ {
+ #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 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 progress = (StartHue + (range * offset)) / 360f;
+
+ float div = (Math.Abs(progress % 1) * 6);
+ int value = (int)((div % 1) * 255);
+
+ switch ((int)div)
+ {
+ case 0:
+ return Color.FromArgb(255, 255, value, 0);
+ case 1:
+ return Color.FromArgb(255, 255 - value, 255, 0);
+ case 2:
+ return Color.FromArgb(255, 0, 255, value);
+ case 3:
+ return Color.FromArgb(255, 0, 255 - value, 255);
+ case 4:
+ return Color.FromArgb(255, value, 0, 255);
+ case 5:
+ return Color.FromArgb(255, 255, 0, 255 - value);
+ default:
+ return Color.Transparent;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Examples/SimpleDevTest/Program.cs b/Examples/SimpleDevTest/Program.cs
index 687ac9e..aa661a8 100644
--- a/Examples/SimpleDevTest/Program.cs
+++ b/Examples/SimpleDevTest/Program.cs
@@ -85,8 +85,8 @@ namespace SimpleDevTest
// Create our gradient stop to play with
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.Red));
+ // Create a basic (by default horizontal) brush ...
+ LinearGradientBrush linearBrush = new LinearGradientBrush(new GradientStop(0, Color.Blue), moveableStop, new GradientStop(1f, Color.White));
// ... and add it as the keyboard background
keyboard.Brush = linearBrush;
@@ -122,6 +122,29 @@ namespace SimpleDevTest
Wait(2);
+ // ---------------------------------------------------------------------------
+ // Time for an even better brush: rainbow
+
+ Console.WriteLine("rainbow-test");
+
+ // Create an simple horizontal rainbow containing two times the full spectrum
+ RainbowBrush rainbowBrush = new RainbowBrush(0, 720);
+
+ // Add the rainbow to the keyboard and perform an initial update
+ keyboard.Brush = rainbowBrush;
+ keyboard.UpdateLeds();
+
+ // Let the rainbow move around for 10 secs
+ for (int i = 0; i < 100; i++)
+ {
+ rainbowBrush.StartHue += 10f;
+ rainbowBrush.EndHue += 10f;
+ keyboard.UpdateLeds();
+ Thread.Sleep(100);
+ }
+
+ Wait(2);
+
// ---------------------------------------------------------------------------
// Now let us move some points random over the keyboard
diff --git a/Helper/GradientHelper.cs b/Helper/GradientHelper.cs
new file mode 100644
index 0000000..8b866f0
--- /dev/null
+++ b/Helper/GradientHelper.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Drawing;
+
+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)
+ {
+ PointF intersectingPoint;
+ if (startPoint.Y.Equals(endPoint.Y)) // Horizontal case
+ intersectingPoint = new PointF(point.X, startPoint.Y);
+
+ else if (startPoint.X.Equals(endPoint.X)) // Vertical case
+ intersectingPoint = new PointF(startPoint.X, point.Y);
+
+ else // Diagnonal case
+ {
+ float slope = (endPoint.Y - startPoint.Y) / (endPoint.X - startPoint.X);
+ float orthogonalSlope = -1 / slope;
+
+ float startYIntercept = startPoint.Y - slope * startPoint.X;
+ float pointYIntercept = point.Y - orthogonalSlope * point.X;
+
+ float intersectingPointX = (pointYIntercept - startYIntercept) / (slope - orthogonalSlope);
+ float intersectingPointY = slope * intersectingPointX + startYIntercept;
+ intersectingPoint = new PointF(intersectingPointX, intersectingPointY);
+ }
+
+ // Calculate distances relative to the vector start
+ float intersectDistance = CalculateDistance(intersectingPoint, startPoint, endPoint);
+ float gradientLength = CalculateDistance(endPoint, startPoint, endPoint);
+
+ return intersectDistance / gradientLength;
+ }
+
+ // Based on https://dotupdate.wordpress.com/2008/01/28/find-the-color-of-a-point-in-a-lineargradientbrush/
+ ///
+ /// Returns the signed magnitude of a point on a vector
+ ///
+ private 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));
+
+ return (((point.Y < origin.Y) && (direction.Y > origin.Y)) ||
+ ((point.Y > origin.Y) && (direction.Y < origin.Y)) ||
+ ((point.Y.Equals(origin.Y)) && (point.X < origin.X) && (direction.X > origin.X)) ||
+ ((point.Y.Equals(origin.Y)) && (point.X > origin.X) && (direction.X < origin.X)))
+ ? -distance : distance;
+ }
+ }
+}