diff --git a/CUE.NET.csproj b/CUE.NET.csproj
index 9cd2868..61448c7 100644
--- a/CUE.NET.csproj
+++ b/CUE.NET.csproj
@@ -63,8 +63,10 @@
-
-
+
+
+
+
diff --git a/Devices/Keyboard/Brushes/GradientStop.cs b/Devices/Keyboard/Brushes/GradientStop.cs
new file mode 100644
index 0000000..761eb05
--- /dev/null
+++ b/Devices/Keyboard/Brushes/GradientStop.cs
@@ -0,0 +1,26 @@
+using System.Drawing;
+
+namespace CUE.NET.Devices.Keyboard.Brushes
+{
+ public class GradientStop
+ {
+
+ #region Properties & Fields
+
+ public float Offset { get; set; }
+
+ public Color Color { get; set; }
+
+ #endregion
+
+ #region Constructors
+
+ public GradientStop(float offset, Color color)
+ {
+ this.Offset = offset;
+ this.Color = color;
+ }
+
+ #endregion
+ }
+}
diff --git a/Devices/Keyboard/ColorBrushes/IBrush.cs b/Devices/Keyboard/Brushes/IBrush.cs
similarity index 73%
rename from Devices/Keyboard/ColorBrushes/IBrush.cs
rename to Devices/Keyboard/Brushes/IBrush.cs
index e90c6dd..7e23773 100644
--- a/Devices/Keyboard/ColorBrushes/IBrush.cs
+++ b/Devices/Keyboard/Brushes/IBrush.cs
@@ -1,6 +1,6 @@
using System.Drawing;
-namespace CUE.NET.Devices.Keyboard.ColorBrushes
+namespace CUE.NET.Devices.Keyboard.Brushes
{
public interface IBrush
{
diff --git a/Devices/Keyboard/Brushes/LinearGradientBrush.cs b/Devices/Keyboard/Brushes/LinearGradientBrush.cs
new file mode 100644
index 0000000..31a169a
--- /dev/null
+++ b/Devices/Keyboard/Brushes/LinearGradientBrush.cs
@@ -0,0 +1,132 @@
+// ReSharper disable CollectionNeverUpdated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable ReturnTypeCanBeEnumerable.Global
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+
+namespace CUE.NET.Devices.Keyboard.Brushes
+{
+ public class LinearGradientBrush : 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 IList GradientStops { get; } = new List();
+
+ #endregion
+
+ #region Constructor
+
+ public LinearGradientBrush()
+ { }
+
+ public LinearGradientBrush(PointF startPoint, PointF endPoint, params GradientStop[] gradientStops)
+ {
+ 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);
+ }
+
+ #endregion
+
+ #region Methods
+
+ public Color GetColorAtPoint(RectangleF rectangle, PointF point)
+ {
+ if (!GradientStops.Any()) return Color.Transparent;
+ if (GradientStops.Count == 1) return GradientStops.First().Color;
+
+ // Taken from https://dotupdate.wordpress.com/2008/01/28/find-the-color-of-a-point-in-a-lineargradientbrush/
+
+ float x3 = point.X;
+ float y3 = point.Y;
+
+ float x1 = StartPoint.X * rectangle.Width;
+ float y1 = StartPoint.Y * rectangle.Height;
+ PointF p1 = new PointF(x1, y1); // Starting point
+
+ float x2 = EndPoint.X * rectangle.Width;
+ float y2 = EndPoint.Y * rectangle.Height;
+ PointF p2 = new PointF(x2, y2); //End point
+
+ // Calculate intersecting points
+ PointF p4;
+
+ if (y1.Equals(y2)) // Horizontal case
+ p4 = new PointF(x3, y1);
+
+ else if (x1.Equals(x2)) // Vertical case
+ p4 = new PointF(x1, y3);
+
+ else // Diagnonal case
+ {
+ float m = (y2 - y1) / (x2 - x1);
+ float m2 = -1 / m;
+ float b = y1 - m * x1;
+ float c = y3 - m2 * x3;
+
+ float x4 = (c - b) / (m - m2);
+ float y4 = m * x4 + b;
+ p4 = new PointF(x4, y4);
+ }
+
+ // Calculate distances relative to the vector start
+ float d4 = Dist(p4, p1, p2);
+ float d2 = Dist(p2, p1, p2);
+
+ float x = d4 / d2;
+
+ // Clip the input if before or after the max/min offset values
+ float max = GradientStops.Max(n => n.Offset);
+ if (x > max)
+ x = max;
+
+ float min = GradientStops.Min(n => n.Offset);
+ if (x < min)
+ x = min;
+
+ // Find gradient stops that surround the input value
+ GradientStop gs0 = GradientStops.Where(n => n.Offset <= x).OrderBy(n => n.Offset).Last();
+ GradientStop gs1 = GradientStops.Where(n => n.Offset >= x).OrderBy(n => n.Offset).First();
+
+ float y = 0f;
+ if (!gs0.Offset.Equals(gs1.Offset))
+ y = ((x - gs0.Offset) / (gs1.Offset - gs0.Offset));
+
+ byte colA = (byte)((gs1.Color.A - gs0.Color.A) * y + gs0.Color.A);
+ byte colR = (byte)((gs1.Color.R - gs0.Color.R) * y + gs0.Color.R);
+ byte colG = (byte)((gs1.Color.G - gs0.Color.G) * y + gs0.Color.G);
+ byte colB = (byte)((gs1.Color.B - gs0.Color.B) * y + gs0.Color.B);
+ return Color.FromArgb(colA, colR, colG, colB);
+ }
+
+ // Taken from 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 with origin po and pointing to pf
+ ///
+ private float Dist(PointF px, PointF po, PointF pf)
+ {
+ float d = (float)Math.Sqrt((px.Y - po.Y) * (px.Y - po.Y) + (px.X - po.X) * (px.X - po.X));
+
+ return (((px.Y < po.Y) && (pf.Y > po.Y)) ||
+ ((px.Y > po.Y) && (pf.Y < po.Y)) ||
+ ((px.Y.Equals(po.Y)) && (px.X < po.X) && (pf.X > po.X)) ||
+ ((px.Y.Equals(po.Y)) && (px.X > po.X) && (pf.X < po.X)))
+ ? -d : d;
+ }
+
+ #endregion
+ }
+}
diff --git a/Devices/Keyboard/ColorBrushes/SolidColorBrush.cs b/Devices/Keyboard/Brushes/SolidColorBrush.cs
similarity index 92%
rename from Devices/Keyboard/ColorBrushes/SolidColorBrush.cs
rename to Devices/Keyboard/Brushes/SolidColorBrush.cs
index 66057cf..148f949 100644
--- a/Devices/Keyboard/ColorBrushes/SolidColorBrush.cs
+++ b/Devices/Keyboard/Brushes/SolidColorBrush.cs
@@ -1,6 +1,6 @@
using System.Drawing;
-namespace CUE.NET.Devices.Keyboard.ColorBrushes
+namespace CUE.NET.Devices.Keyboard.Brushes
{
public class SolidColorBrush : IBrush
{
diff --git a/Devices/Keyboard/CorsairKeyboard.cs b/Devices/Keyboard/CorsairKeyboard.cs
index b0be27b..27fa6a0 100644
--- a/Devices/Keyboard/CorsairKeyboard.cs
+++ b/Devices/Keyboard/CorsairKeyboard.cs
@@ -6,7 +6,7 @@ using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using CUE.NET.Devices.Generic;
-using CUE.NET.Devices.Keyboard.ColorBrushes;
+using CUE.NET.Devices.Keyboard.Brushes;
using CUE.NET.Devices.Keyboard.Enums;
using CUE.NET.Devices.Keyboard.Keys;
using CUE.NET.Helper;
diff --git a/Devices/Keyboard/Keys/BaseKeyGroup.cs b/Devices/Keyboard/Keys/BaseKeyGroup.cs
index 1eca0de..bb39884 100644
--- a/Devices/Keyboard/Keys/BaseKeyGroup.cs
+++ b/Devices/Keyboard/Keys/BaseKeyGroup.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
-using CUE.NET.Devices.Keyboard.ColorBrushes;
+using CUE.NET.Devices.Keyboard.Brushes;
using CUE.NET.Devices.Keyboard.Extensions;
namespace CUE.NET.Devices.Keyboard.Keys
diff --git a/Devices/Keyboard/Keys/IKeyGroup.cs b/Devices/Keyboard/Keys/IKeyGroup.cs
index e962bee..4fbc569 100644
--- a/Devices/Keyboard/Keys/IKeyGroup.cs
+++ b/Devices/Keyboard/Keys/IKeyGroup.cs
@@ -1,5 +1,5 @@
using System.Collections.Generic;
-using CUE.NET.Devices.Keyboard.ColorBrushes;
+using CUE.NET.Devices.Keyboard.Brushes;
namespace CUE.NET.Devices.Keyboard.Keys
{
diff --git a/Examples/SimpleDevTest/Program.cs b/Examples/SimpleDevTest/Program.cs
index b3685b2..687ac9e 100644
--- a/Examples/SimpleDevTest/Program.cs
+++ b/Examples/SimpleDevTest/Program.cs
@@ -5,7 +5,7 @@ using System.Threading.Tasks;
using CUE.NET;
using CUE.NET.Devices.Generic.Enums;
using CUE.NET.Devices.Keyboard;
-using CUE.NET.Devices.Keyboard.ColorBrushes;
+using CUE.NET.Devices.Keyboard.Brushes;
using CUE.NET.Devices.Keyboard.Enums;
using CUE.NET.Devices.Keyboard.Extensions;
using CUE.NET.Devices.Keyboard.Keys;
@@ -18,6 +18,7 @@ namespace SimpleDevTest
public static void Main(string[] args)
{
Console.WriteLine("Press any key to exit ...");
+ Console.WriteLine();
Task.Factory.StartNew(
() =>
{
@@ -35,6 +36,11 @@ namespace SimpleDevTest
if (keyboard == null)
throw new WrapperException("No keyboard found");
+
+ // ---------------------------------------------------------------------------
+ // First we'll look at some basic coloring
+
+ Console.WriteLine("Basic color-test ...");
// Ink all numbers on the keypad except the '5' purple, we want that to be gray
ListKeyGroup purpleGroup = new RectangleKeyGroup(keyboard, CorsairKeyboardKeyId.Keypad7, CorsairKeyboardKeyId.Keypad3)
{ Brush = new SolidColorBrush(Color.Purple) }
@@ -63,27 +69,68 @@ namespace SimpleDevTest
// Update the keyboard to show the configured colors, (your CUE settings defines the rest)
keyboard.UpdateLeds();
- // Wait 5 sec
- for (int i = 5; i > 0; i--)
+ Wait(3);
+
+ // Remove all the groups we created above to clear the keyboard
+ purpleGroup.Detach();
+ whiteGroup.Detach();
+ yellowGroup.Detach();
+
+
+ // ---------------------------------------------------------------------------
+ // Next we add a nice linear gradient brush over the keyboard and play around with the offset of one stop
+
+ Console.WriteLine("gradient-brush-test");
+
+ // 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));
+
+ // ... and add it as the keyboard background
+ keyboard.Brush = linearBrush;
+
+ // Move the brush from left to right
+ for (float offset = 0; offset <= 1f; offset += 0.02f)
{
- Console.WriteLine(i);
- Thread.Sleep(1000);
+ moveableStop.Offset = offset;
+ keyboard.UpdateLeds();
+ Thread.Sleep(100);
}
+ // And back to center
+ for (float offset = 1f; offset >= 0.5f; offset -= 0.02f)
+ {
+ moveableStop.Offset = offset;
+ keyboard.UpdateLeds();
+ Thread.Sleep(100);
+ }
+
+ // "Rotate" the brush (this is of course not the best implementation for this but you see the point)
+ for (float rotateX = 0, rotateY = 0; rotateX <= 1f; rotateX += 0.02f, rotateY = 0.04f)
+ {
+ if (rotateY > 1f)
+ rotateY = 1f - (rotateY - 1f);
+
+ linearBrush.StartPoint = new PointF(rotateX, rotateY);
+ linearBrush.EndPoint = new PointF(1f - rotateX, 1f - rotateY);
+
+ keyboard.UpdateLeds();
+ Thread.Sleep(100);
+ }
+
+ Wait(2);
+
// ---------------------------------------------------------------------------
// Now let us move some points random over the keyboard
// Something like this could become some sort of effect
// Initialize needed stuff
- const float SPEED = 4f; // mm/tick
+ const float SPEED = 6f; // mm/tick
Random random = new Random();
- // Remove all the groups we created above to clear the keyboard
- purpleGroup.Detach();
- whiteGroup.Detach();
- yellowGroup.Detach();
-
// Flash whole keyboard three times to ... well ... just to make it happen
for (int i = 0; i < 3; i++)
{
@@ -168,6 +215,15 @@ namespace SimpleDevTest
Thread.Sleep(1000); // Don't exit after exception
}
+ private static void Wait(int sec)
+ {
+ for (int i = sec; i > 0; i--)
+ {
+ Console.WriteLine(i);
+ Thread.Sleep(1000);
+ }
+ }
+
private static PointF Interpolate(PointF p1, PointF p2, float length)
{
float distance = (float)(Math.Sqrt(Math.Pow(p2.X - p1.X, 2) + Math.Pow(p2.Y - p1.Y, 2)));
diff --git a/Helper/ColorHelper.cs b/Helper/ColorHelper.cs
index 7ba2140..16be988 100644
--- a/Helper/ColorHelper.cs
+++ b/Helper/ColorHelper.cs
@@ -49,8 +49,8 @@ namespace CUE.NET.Helper
private static byte GetIntColorFromFloat(float f)
{
- float calcF = (float)Math.Max(0.0, Math.Min(1.0, f));
- return (byte)(calcF == 1.0 ? 255 : calcF * 256.0);
+ float calcF = (float)Math.Max(0f, Math.Min(1f, f));
+ return (byte)(calcF.Equals(1f) ? 255 : calcF * 256.0);
}
}
}