1
0
mirror of https://github.com/DarthAffe/CUE.NET.git synced 2025-12-13 09:08:34 +00:00

Improved the led update mechanism

This commit is contained in:
unknown 2015-09-20 12:16:24 +02:00
parent 61b712d026
commit 4e1a1d11bd
9 changed files with 112 additions and 45 deletions

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using CUE.NET.Native; using CUE.NET.Native;
@ -35,9 +36,19 @@ namespace CUE.NET.Devices.Generic
return Leds[ledId]; return Leds[ledId];
} }
public virtual void UpdateLeds(bool fullUpdate = false) public virtual void UpdateLeds(bool forceUpdate = false)
{ {
IList<KeyValuePair<int, CorsairLed>> ledsToUpdate = (fullUpdate ? Leds : Leds.Where(x => x.Value.IsDirty)).ToList(); IList<KeyValuePair<int, CorsairLed>> ledsToUpdate = (forceUpdate ? Leds : Leds.Where(x => x.Value.IsDirty)).ToList();
foreach (CorsairLed led in Leds.Values)
led.Update();
UpdateLeds(ledsToUpdate);
}
private static void UpdateLeds(ICollection<KeyValuePair<int, CorsairLed>> ledsToUpdate)
{
ledsToUpdate = ledsToUpdate.Where(x => x.Value.Color != Color.Transparent).ToList();
if (!ledsToUpdate.Any()) if (!ledsToUpdate.Any())
return; // CUE seems to crash if 'CorsairSetLedsColors' is called with a zero length array return; // CUE seems to crash if 'CorsairSetLedsColors' is called with a zero length array

View File

@ -6,21 +6,27 @@ namespace CUE.NET.Devices.Generic
{ {
#region Properties & Fields #region Properties & Fields
public bool IsDirty { get; private set; } = false; public bool IsDirty => RequestedColor != _color;
public bool IsUpdated { get; private set; }
private Color _color = Color.Black; public Color RequestedColor { get; private set; } = Color.Transparent;
private Color _color = Color.Transparent;
public Color Color public Color Color
{ {
get { return _color; } get { return _color; }
set set
{ {
if (_color != value) if (!IsLocked)
IsDirty = true; {
RequestedColor = value;
_color = value; IsUpdated = true;
}
} }
} }
public bool IsLocked { get; set; } = false;
//TODO DarthAffe 19.09.2015: Add effects and stuff //TODO DarthAffe 19.09.2015: Add effects and stuff
#endregion #endregion
@ -30,5 +36,15 @@ namespace CUE.NET.Devices.Generic
internal CorsairLed() { } internal CorsairLed() { }
#endregion #endregion
#region Methods
internal void Update()
{
_color = RequestedColor;
IsUpdated = false;
}
#endregion
} }
} }

View File

@ -13,8 +13,7 @@ namespace CUE.NET.Devices.Generic
/// Device type. /// Device type.
/// </summary> /// </summary>
public CorsairDeviceType Type { get; } public CorsairDeviceType Type { get; }
//TODO DarthAffe 17.09.2015: This could be an Enum
/// <summary> /// <summary>
/// Device model (like “K95RGB”). /// Device model (like “K95RGB”).
/// </summary> /// </summary>

View File

@ -4,6 +4,6 @@
{ {
IDeviceInfo DeviceInfo { get; } IDeviceInfo DeviceInfo { get; }
void UpdateLeds(bool fullUpdate = false); void UpdateLeds(bool forceUpdate = false);
} }
} }

View File

@ -51,6 +51,10 @@ namespace CUE.NET.Devices.Keyboard
} }
public IEnumerable<CorsairKey> Keys => new ReadOnlyCollection<CorsairKey>(_keys.Values.ToList()); public IEnumerable<CorsairKey> Keys => new ReadOnlyCollection<CorsairKey>(_keys.Values.ToList());
public Color Color { get; set; } = Color.Transparent;
private readonly IList<IKeyGroup> _keyGroups = new List<IKeyGroup>();
#endregion #endregion
@ -69,10 +73,38 @@ namespace CUE.NET.Devices.Keyboard
#region Methods #region Methods
public void SetColor(Color color) public override void UpdateLeds(bool forceUpdate = false)
{ {
foreach (CorsairKey key in this) // Apply all KeyGroups first
key.Led.Color = color; // Update only 'clean' leds, manual set should always override groups
IEnumerable<CorsairKey> cleanKeys = this.Where(x => !x.Led.IsUpdated).ToList();
if (Color != Color.Transparent)
foreach (CorsairKey key in cleanKeys)
key.Led.Color = Color;
//TODO DarthAffe 20.09.2015: Add some sort of priority
foreach (IKeyGroup keyGroup in _keyGroups)
foreach (CorsairKey key in keyGroup.Keys.Where(key => cleanKeys.Contains(key)))
key.Led.Color = keyGroup.Color;
// Perform 'real' update
base.UpdateLeds(forceUpdate);
}
public void AttachKeyGroup(IKeyGroup keyGroup)
{
if (keyGroup == null) return;
if (!_keyGroups.Contains(keyGroup))
_keyGroups.Add(keyGroup);
}
public void DetachKeyGroup(IKeyGroup keyGroup)
{
if (keyGroup == null) return;
_keyGroups.Remove(keyGroup);
} }
private void InitializeKeys() private void InitializeKeys()
@ -83,9 +115,11 @@ namespace CUE.NET.Devices.Keyboard
for (int i = 0; i < nativeLedPositions.numberOfLed; i++) for (int i = 0; i < nativeLedPositions.numberOfLed; i++)
{ {
_CorsairLedPosition ledPosition = Marshal.PtrToStructure<_CorsairLedPosition>(ptr); _CorsairLedPosition ledPosition = Marshal.PtrToStructure<_CorsairLedPosition>(ptr);
_keys.Add(ledPosition.ledId, new CorsairKey(ledPosition.ledId, GetLed((int)ledPosition.ledId), CorsairLed led = GetLed((int)ledPosition.ledId);
_keys.Add(ledPosition.ledId, new CorsairKey(ledPosition.ledId, led,
//TODO DarthAffe 19.09.2015: Is something like RectangleD needed? I don't think so ... //TODO DarthAffe 19.09.2015: Is something like RectangleD needed? I don't think so ...
new RectangleF((float)ledPosition.left, (float)ledPosition.top, (float)ledPosition.width, (float)ledPosition.height))); new RectangleF((float)ledPosition.left, (float)ledPosition.top, (float)ledPosition.width, (float)ledPosition.height)));
ptr = new IntPtr(ptr.ToInt64() + structSize); ptr = new IntPtr(ptr.ToInt64() + structSize);
} }
} }

View File

@ -13,25 +13,24 @@ namespace CUE.NET.Devices.Keyboard.Keys
public IEnumerable<CorsairKey> Keys => new ReadOnlyCollection<CorsairKey>(GroupKeys); public IEnumerable<CorsairKey> Keys => new ReadOnlyCollection<CorsairKey>(GroupKeys);
protected IList<CorsairKey> GroupKeys { get; } = new List<CorsairKey>(); protected IList<CorsairKey> GroupKeys { get; } = new List<CorsairKey>();
public Color Color { get; set; } = Color.Transparent;
#endregion #endregion
#region Constructors #region Constructors
protected BaseKeyGroup(CorsairKeyboard keyboard) protected BaseKeyGroup(CorsairKeyboard keyboard, bool autoAttach = true)
{ {
this.Keyboard = keyboard; this.Keyboard = keyboard;
if (autoAttach)
keyboard.AttachKeyGroup(this);
} }
#endregion #endregion
#region Methods #region Methods
public virtual void SetColor(Color color)
{
foreach (CorsairKey key in GroupKeys)
key.Led.Color = color;
}
public void MergeKeys(IKeyGroup groupToMerge) public void MergeKeys(IKeyGroup groupToMerge)
{ {
foreach (CorsairKey key in groupToMerge.Keys) foreach (CorsairKey key in groupToMerge.Keys)

View File

@ -7,6 +7,6 @@ namespace CUE.NET.Devices.Keyboard.Keys
{ {
IEnumerable<CorsairKey> Keys { get; } IEnumerable<CorsairKey> Keys { get; }
void SetColor(Color color); Color Color { get; set; }
} }
} }

View File

@ -16,20 +16,20 @@ namespace CUE.NET.Devices.Keyboard.Keys
#region Constructors #region Constructors
public RectangleKeyGroup(CorsairKeyboard keyboard, CorsairKeyboardKeyId fromKey, CorsairKeyboardKeyId toKey, float minOverlayPercentage = 0.5f) public RectangleKeyGroup(CorsairKeyboard keyboard, CorsairKeyboardKeyId fromKey, CorsairKeyboardKeyId toKey, float minOverlayPercentage = 0.5f, bool autoAttach = true)
: this(keyboard, keyboard[fromKey], keyboard[toKey], minOverlayPercentage) : this(keyboard, keyboard[fromKey], keyboard[toKey], minOverlayPercentage, autoAttach)
{ } { }
public RectangleKeyGroup(CorsairKeyboard keyboard, CorsairKey fromKey, CorsairKey toKey, float minOverlayPercentage = 0.5f) public RectangleKeyGroup(CorsairKeyboard keyboard, CorsairKey fromKey, CorsairKey toKey, float minOverlayPercentage = 0.5f, bool autoAttach = true)
: this(keyboard, RectangleHelper.CreateRectangleFromRectangles(fromKey.KeyRectangle, toKey.KeyRectangle), minOverlayPercentage) : this(keyboard, RectangleHelper.CreateRectangleFromRectangles(fromKey.KeyRectangle, toKey.KeyRectangle), minOverlayPercentage, autoAttach)
{ } { }
public RectangleKeyGroup(CorsairKeyboard keyboard, PointF fromPoint, PointF toPoint, float minOverlayPercentage = 0.5f) public RectangleKeyGroup(CorsairKeyboard keyboard, PointF fromPoint, PointF toPoint, float minOverlayPercentage = 0.5f, bool autoAttach = true)
: this(keyboard, RectangleHelper.CreateRectangleFromPoints(fromPoint, toPoint), minOverlayPercentage) : this(keyboard, RectangleHelper.CreateRectangleFromPoints(fromPoint, toPoint), minOverlayPercentage, autoAttach)
{ } { }
public RectangleKeyGroup(CorsairKeyboard keyboard, RectangleF requestedRectangle, float minOverlayPercentage = 0.5f) public RectangleKeyGroup(CorsairKeyboard keyboard, RectangleF requestedRectangle, float minOverlayPercentage = 0.5f, bool autoAttach = true)
: base(keyboard) : base(keyboard, autoAttach)
{ {
this.RequestedRectangle = requestedRectangle; this.RequestedRectangle = requestedRectangle;
this.MinOverlayPercentage = minOverlayPercentage; this.MinOverlayPercentage = minOverlayPercentage;

View File

@ -35,8 +35,8 @@ namespace SimpleDevTest
throw new WrapperException("No keyboard found"); throw new WrapperException("No keyboard found");
//Ink all numbers on the keypad purple //Ink all numbers on the keypad purple
RectangleKeyGroup centerGroup = new RectangleKeyGroup(keyboard, CorsairKeyboardKeyId.Keypad7, CorsairKeyboardKeyId.Keypad3); RectangleKeyGroup purpleGroup = new RectangleKeyGroup(keyboard, CorsairKeyboardKeyId.Keypad7, CorsairKeyboardKeyId.Keypad3)
centerGroup.SetColor(Color.Purple); { Color = Color.Purple };
// Ink the Keys 'r', 'g', 'b' in their respective color // Ink the Keys 'r', 'g', 'b' in their respective color
// The char access seems to fail for everything except letters (SDK doesn't return a valid keyId) // The char access seems to fail for everything except letters (SDK doesn't return a valid keyId)
@ -44,17 +44,21 @@ namespace SimpleDevTest
keyboard[CorsairKeyboardKeyId.G].Led.Color = Color.Green; keyboard[CorsairKeyboardKeyId.G].Led.Color = Color.Green;
keyboard['B'].Led.Color = Color.Blue; keyboard['B'].Led.Color = Color.Blue;
// Lock the 'r', 'g', 'b' keys. We want them to stay like this forever
keyboard['R'].Led.IsLocked = true;
keyboard['G'].Led.IsLocked = true;
keyboard['B'].Led.IsLocked = true;
// Ink the letters of 'white' white // Ink the letters of 'white' white
SimpleKeyGroup whiteGroup = new SimpleKeyGroup(keyboard, CorsairKeyboardKeyId.W, CorsairKeyboardKeyId.H, CorsairKeyboardKeyId.I, CorsairKeyboardKeyId.T, CorsairKeyboardKeyId.E); SimpleKeyGroup whiteGroup = new SimpleKeyGroup(keyboard, CorsairKeyboardKeyId.W, CorsairKeyboardKeyId.H, CorsairKeyboardKeyId.I, CorsairKeyboardKeyId.T, CorsairKeyboardKeyId.E)
whiteGroup.SetColor(Color.White); { Color = Color.White };
// Ink the keys '1' to '0' yellow // Ink the keys '1' to '0' yellow
RectangleKeyGroup numberGroup = new RectangleKeyGroup(keyboard, CorsairKeyboardKeyId.D1, CorsairKeyboardKeyId.D0); RectangleKeyGroup yellowGroup = new RectangleKeyGroup(keyboard, CorsairKeyboardKeyId.D1, CorsairKeyboardKeyId.D0)
numberGroup.SetColor(Color.Yellow); { Color = Color.Yellow };
// Update the keyboard to show the configured colors, the parameter 'true' overrides the whole keyboard (default: black), // Update the keyboard to show the configured colors, (your CUE settings defines the rest)
// 'false' (or nothing) overrides only changed keys (your CUE settings defines the rest) - this default behaviour might change soon keyboard.UpdateLeds();
keyboard.UpdateLeds(true);
// Wait 5 sec // Wait 5 sec
for (int i = 5; i > 0; i--) for (int i = 5; i > 0; i--)
@ -72,19 +76,25 @@ namespace SimpleDevTest
const float SPEED = 8f; // mm/tick const float SPEED = 8f; // mm/tick
Random random = new Random(); Random random = new Random();
// Cover whole keyboard as Group to be able to reset (I'll fix this tomorrow) // Remove all the groups we created above to clear the keyboard
keyboard.DetachKeyGroup(purpleGroup);
keyboard.DetachKeyGroup(whiteGroup);
keyboard.DetachKeyGroup(yellowGroup);
// Flash whole keyboard three times to ... well ... just to make it happen // Flash whole keyboard three times to ... well ... just to make it happen
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
keyboard.SetColor(Color.Aquamarine); keyboard.Color = Color.Aquamarine;
keyboard.UpdateLeds(); keyboard.UpdateLeds();
Thread.Sleep(160); Thread.Sleep(160);
keyboard.SetColor(Color.Black); keyboard.Color = Color.Black;
keyboard.UpdateLeds(); keyboard.UpdateLeds();
Thread.Sleep(200); Thread.Sleep(200);
} }
// Set keyboard 'background' to something fancy
keyboard.Color = Color.DarkSlateBlue;
// Spawn our point (rectangle since circles are too hard to calculate :p) in the top-left corner (right over G1 or on ESC depending on your keyboard) // Spawn our point (rectangle since circles are too hard to calculate :p) in the top-left corner (right over G1 or on ESC depending on your keyboard)
RectangleF point = new RectangleF(keyboard.KeyboardRectangle.X, keyboard.KeyboardRectangle.Y, 40, 40); RectangleF point = new RectangleF(keyboard.KeyboardRectangle.X, keyboard.KeyboardRectangle.Y, 40, 40);
// Target of our movement // Target of our movement
@ -98,8 +108,6 @@ namespace SimpleDevTest
else else
point.Location = Interpolate(point.Location, target, SPEED); // It would be better to calculate from the center of our rectangle but the easy way is enough here point.Location = Interpolate(point.Location, target, SPEED); // It would be better to calculate from the center of our rectangle but the easy way is enough here
keyboard.SetColor(Color.Black);
IEnumerable<CorsairKey> keys = keyboard[point, 0.1f]; IEnumerable<CorsairKey> keys = keyboard[point, 0.1f];
if (keys != null) if (keys != null)
foreach (CorsairKey key in keys) foreach (CorsairKey key in keys)