mirror of
https://github.com/DarthAffe/CUE.NET.git
synced 2026-11-11 04:56:44 +00:00
Refactored to do everything based on LEDs.
This will adapt the devices and reduces the importance of the "special case keyboard"
This commit is contained in:
1 parent
bfe51add66
commit
5a018d0743
24 files changed
+847
-894
No files matched your search
@@ -2,14 +2,21 @@
|
||||
// ReSharper disable UnusedMethodReturnValue.Global
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CUE.NET.Brushes;
|
||||
using CUE.NET.Devices.Generic.Enums;
|
||||
using CUE.NET.Devices.Generic.EventArgs;
|
||||
using CUE.NET.Devices.Keyboard.Enums;
|
||||
using CUE.NET.Effects;
|
||||
using CUE.NET.Groups;
|
||||
using CUE.NET.Helper;
|
||||
using CUE.NET.Native;
|
||||
|
||||
namespace CUE.NET.Devices.Generic
|
||||
@@ -21,6 +28,16 @@ namespace CUE.NET.Devices.Generic
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private CancellationTokenSource _updateTokenSource;
|
||||
private CancellationToken _updateToken;
|
||||
private Task _updateTask;
|
||||
private DateTime _lastUpdate = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of attached ledgroups.
|
||||
/// </summary>
|
||||
protected LinkedList<ILedGroup> LedGroups { get; } = new LinkedList<ILedGroup>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets generic information provided by CUE for the device.
|
||||
/// </summary>
|
||||
@@ -45,15 +62,65 @@ namespace CUE.NET.Devices.Generic
|
||||
/// </summary>
|
||||
public float UpdateFrequency { get; set; } = 1f / 30f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the rectangle containing all LEDs of the device.
|
||||
/// </summary>
|
||||
public RectangleF DeviceRectangle { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a dictionary containing all LEDs of the device.
|
||||
/// </summary>
|
||||
protected Dictionary<int, CorsairLed> Leds { get; } = new Dictionary<int, CorsairLed>();
|
||||
protected Dictionary<CorsairLedId, CorsairLed> LedMapping { get; } = new Dictionary<CorsairLedId, CorsairLed>();
|
||||
|
||||
private CancellationTokenSource _updateTokenSource;
|
||||
private CancellationToken _updateToken;
|
||||
private Task _updateTask;
|
||||
private DateTime _lastUpdate = DateTime.Now;
|
||||
/// <summary>
|
||||
/// Gets a read-only collection containing the LEDs of the device.
|
||||
/// </summary>
|
||||
public IEnumerable<CorsairLed> Leds => new ReadOnlyCollection<CorsairLed>(LedMapping.Values.ToList());
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the background brush of the keyboard.
|
||||
/// </summary>
|
||||
public IBrush Brush { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the z-index of the background brush of the keyboard.<br />
|
||||
/// This value has absolutely no effect.
|
||||
/// </summary>
|
||||
public int ZIndex { get; set; } = 0;
|
||||
|
||||
#region Indexers
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="CorsairLed" /> with the specified ID.
|
||||
/// </summary>
|
||||
/// <param name="ledId">The ID of the LED to get.</param>
|
||||
/// <returns>The LED with the specified ID or null if no LED is found.</returns>
|
||||
public CorsairLed this[CorsairLedId ledId]
|
||||
{
|
||||
get
|
||||
{
|
||||
CorsairLed key;
|
||||
return LedMapping.TryGetValue(ledId, out key) ? key : null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="CorsairLed" /> at the given physical location.
|
||||
/// </summary>
|
||||
/// <param name="location">The point to get the location from.</param>
|
||||
/// <returns>The LED at the given point or null if no location is found.</returns>
|
||||
public CorsairLed this[PointF location] => LedMapping.Values.FirstOrDefault(x => x.LedRectangle.Contains(location));
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="CorsairLed" /> inside the given rectangle.
|
||||
/// </summary>
|
||||
/// <param name="referenceRect">The rectangle to check.</param>
|
||||
/// <param name="minOverlayPercentage">The minimal percentage overlay a location must have with the <see cref="Rectangle" /> to be taken into the list.</param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<CorsairLed> this[RectangleF referenceRect, float minOverlayPercentage = 0.5f] => LedMapping.Values
|
||||
.Where(x => RectangleHelper.CalculateIntersectPercentage(x.LedRectangle, referenceRect) >= minOverlayPercentage);
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -96,6 +163,10 @@ namespace CUE.NET.Devices.Generic
|
||||
{
|
||||
this.DeviceInfo = info;
|
||||
|
||||
// ReSharper disable once VirtualMemberCallInConstructor - I know, but I need this ...
|
||||
InitializeLeds();
|
||||
DeviceRectangle = RectangleHelper.CreateRectangleFromRectangles(((IEnumerable<CorsairLed>)this).Select(x => x.LedRectangle));
|
||||
|
||||
CheckUpdateLoop();
|
||||
}
|
||||
|
||||
@@ -103,18 +174,20 @@ namespace CUE.NET.Devices.Generic
|
||||
|
||||
#region Methods
|
||||
|
||||
protected abstract void InitializeLeds();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the LED-Object with the specified id.
|
||||
/// </summary>
|
||||
/// <param name="ledId">The LED-Id to initialize.</param>
|
||||
/// <param name="ledRectangle">The rectangle representing the position of the LED to initialize.</param>
|
||||
/// <returns></returns>
|
||||
protected CorsairLed InitializeLed(int ledId, RectangleF ledRectangle)
|
||||
protected CorsairLed InitializeLed(CorsairLedId ledId, RectangleF ledRectangle)
|
||||
{
|
||||
if (!Leds.ContainsKey(ledId))
|
||||
if (!LedMapping.ContainsKey(ledId))
|
||||
{
|
||||
CorsairLed led = new CorsairLed(ledRectangle);
|
||||
Leds.Add(ledId, led);
|
||||
CorsairLed led = new CorsairLed(ledId, ledRectangle);
|
||||
LedMapping.Add(ledId, led);
|
||||
return led;
|
||||
}
|
||||
|
||||
@@ -175,12 +248,22 @@ namespace CUE.NET.Devices.Generic
|
||||
{
|
||||
OnUpdating();
|
||||
|
||||
// Update effects
|
||||
foreach (ILedGroup ledGroup in LedGroups)
|
||||
ledGroup.UpdateEffects();
|
||||
|
||||
// Render brushes
|
||||
Render(this);
|
||||
foreach (ILedGroup ledGroup in LedGroups.OrderBy(x => x.ZIndex))
|
||||
Render(ledGroup);
|
||||
|
||||
// Device-specific updates
|
||||
DeviceUpdate();
|
||||
|
||||
ICollection<LedUpateRequest> ledsToUpdate = (flushLeds ? Leds : Leds.Where(x => x.Value.IsDirty)).Select(x => new LedUpateRequest(x.Key, x.Value.RequestedColor)).ToList();
|
||||
|
||||
foreach (CorsairLed led in Leds.Values)
|
||||
led.Update();
|
||||
// Send LEDs to SDK
|
||||
ICollection<LedUpateRequest> ledsToUpdate = (flushLeds ? LedMapping : LedMapping.Where(x => x.Value.IsDirty)).Select(x => new LedUpateRequest(x.Key, x.Value.RequestedColor)).ToList();
|
||||
foreach (LedUpateRequest updateRequest in ledsToUpdate)
|
||||
LedMapping[updateRequest.LedId].Update();
|
||||
|
||||
UpdateLeds(ledsToUpdate);
|
||||
|
||||
@@ -190,7 +273,82 @@ namespace CUE.NET.Devices.Generic
|
||||
/// <summary>
|
||||
/// Performs device specific updates.
|
||||
/// </summary>
|
||||
protected abstract void DeviceUpdate();
|
||||
protected virtual void DeviceUpdate()
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Attaches the given ledgroup.
|
||||
/// </summary>
|
||||
/// <param name="ledGroup">The ledgroup to attach.</param>
|
||||
/// <returns><c>true</c> if the ledgroup could be attached; otherwise, <c>false</c>.</returns>
|
||||
public bool AttachLedGroup(ILedGroup ledGroup)
|
||||
{
|
||||
lock (LedGroups)
|
||||
{
|
||||
if (ledGroup == null || LedGroups.Contains(ledGroup)) return false;
|
||||
|
||||
LedGroups.AddLast(ledGroup);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detaches the given ledgroup.
|
||||
/// </summary>
|
||||
/// <param name="ledGroup">The ledgroup to detached.</param>
|
||||
/// <returns><c>true</c> if the ledgroup could be detached; otherwise, <c>false</c>.</returns>
|
||||
public bool DetachLedGroup(ILedGroup ledGroup)
|
||||
{
|
||||
lock (LedGroups)
|
||||
{
|
||||
if (ledGroup == null) return false;
|
||||
|
||||
LinkedListNode<ILedGroup> node = LedGroups.Find(ledGroup);
|
||||
if (node == null) return false;
|
||||
|
||||
LedGroups.Remove(node);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders a ledgroup.
|
||||
/// </summary>
|
||||
/// <param name="ledGroup">The led group to render.</param>
|
||||
// ReSharper disable once MemberCanBeMadeStatic.Local - idc
|
||||
protected virtual void Render(ILedGroup ledGroup)
|
||||
{
|
||||
IList<CorsairLed> leds = ledGroup.GetLeds().ToList();
|
||||
IBrush brush = ledGroup.Brush;
|
||||
|
||||
try
|
||||
{
|
||||
switch (brush.BrushCalculationMode)
|
||||
{
|
||||
case BrushCalculationMode.Relative:
|
||||
RectangleF brushRectangle = RectangleHelper.CreateRectangleFromRectangles(leds.Select(x => x.LedRectangle));
|
||||
float offsetX = -brushRectangle.X;
|
||||
float offsetY = -brushRectangle.Y;
|
||||
brushRectangle.X = 0;
|
||||
brushRectangle.Y = 0;
|
||||
brush.PerformRender(brushRectangle, leds.Select(x => new BrushRenderTarget(x.Id, x.LedRectangle.GetCenter(offsetX, offsetY))));
|
||||
break;
|
||||
case BrushCalculationMode.Absolute:
|
||||
brush.PerformRender(DeviceRectangle, leds.Select(x => new BrushRenderTarget(x.Id, x.LedRectangle.GetCenter())));
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
brush.UpdateEffects();
|
||||
brush.PerformFinalize();
|
||||
|
||||
foreach (KeyValuePair<BrushRenderTarget, Color> renders in brush.RenderedTargets)
|
||||
this[renders.Key.LedId].Color = renders.Value;
|
||||
}
|
||||
// ReSharper disable once CatchAllClause
|
||||
catch (Exception ex) { OnException(ex); }
|
||||
}
|
||||
|
||||
private void UpdateLeds(ICollection<LedUpateRequest> updateRequests)
|
||||
{
|
||||
@@ -207,7 +365,7 @@ namespace CUE.NET.Devices.Generic
|
||||
{
|
||||
_CorsairLedColor color = new _CorsairLedColor
|
||||
{
|
||||
ledId = ledUpdateRequest.LedId,
|
||||
ledId = (int)ledUpdateRequest.LedId,
|
||||
r = ledUpdateRequest.Color.R,
|
||||
g = ledUpdateRequest.Color.G,
|
||||
b = ledUpdateRequest.Color.B
|
||||
@@ -228,10 +386,49 @@ namespace CUE.NET.Devices.Generic
|
||||
/// </summary>
|
||||
internal void ResetLeds()
|
||||
{
|
||||
foreach (CorsairLed led in Leds.Values)
|
||||
foreach (CorsairLed led in LedMapping.Values)
|
||||
led.Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list containing all LEDs of this group.
|
||||
/// </summary>
|
||||
/// <returns>The list containing all LEDs of this group.</returns>
|
||||
public IEnumerable<CorsairLed> GetLeds()
|
||||
{
|
||||
return Leds;
|
||||
}
|
||||
|
||||
#region Effects
|
||||
|
||||
/// <summary>
|
||||
/// NOT IMPLEMENTED: Effects can't be applied directly to the device. Add it to the Brush or create a keygroup instead.
|
||||
/// </summary>
|
||||
public void UpdateEffects()
|
||||
{
|
||||
throw new NotSupportedException("Effects can't be applied directly to the device. Add it to the Brush or create a keygroup instead.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// NOT IMPLEMENTED: Effects can't be applied directly to the device. Add it to the Brush or create a keygroup instead.
|
||||
/// </summary>
|
||||
/// <param name="effect">The effect to add.</param>
|
||||
public void AddEffect(IEffect<ILedGroup> effect)
|
||||
{
|
||||
throw new NotSupportedException("Effects can't be applied directly to the device. Add it to the Brush or create a keygroup instead.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// NOT IMPLEMENTED: Effects can't be applied directly to the device. Add it to the Brush or create a keygroup instead.
|
||||
/// </summary>
|
||||
/// <param name="effect">The effect to remove.</param>
|
||||
public void RemoveEffect(IEffect<ILedGroup> effect)
|
||||
{
|
||||
throw new NotSupportedException("Effects can't be applied directly to the device. Add it to the Brush or create a keygroup instead.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region EventCaller
|
||||
|
||||
/// <summary>
|
||||
@@ -313,6 +510,28 @@ namespace CUE.NET.Devices.Generic
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEnumerable
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerator that iterates over all LEDs of the device.
|
||||
/// </summary>
|
||||
/// <returns>An enumerator for all LEDs of the device.</returns>
|
||||
public IEnumerator<CorsairLed> GetEnumerator()
|
||||
{
|
||||
return LedMapping.Values.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerator that iterates over all LEDs of the device.
|
||||
/// </summary>
|
||||
/// <returns>An enumerator for all LEDs of the device.</returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
|
||||
|
||||
using System.Drawing;
|
||||
using CUE.NET.Devices.Generic.Enums;
|
||||
using CUE.NET.Helper;
|
||||
|
||||
namespace CUE.NET.Devices.Generic
|
||||
@@ -13,7 +14,9 @@ namespace CUE.NET.Devices.Generic
|
||||
public class CorsairLed
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
|
||||
public CorsairLedId Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a rectangle representing the physical location of the led.
|
||||
/// </summary>
|
||||
@@ -24,11 +27,6 @@ namespace CUE.NET.Devices.Generic
|
||||
/// </summary>
|
||||
public bool IsDirty => RequestedColor != _color;
|
||||
|
||||
/// <summary>
|
||||
/// Indicate whether the Color of the LED was set since the last update.
|
||||
/// </summary>
|
||||
public bool IsUpdated { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Color the LED should be set to on the next update.
|
||||
/// </summary>
|
||||
@@ -36,7 +34,7 @@ namespace CUE.NET.Devices.Generic
|
||||
|
||||
private Color _color = Color.Transparent;
|
||||
/// <summary>
|
||||
/// Gets the current color of the LED. Sets the <see cref="RequestedColor" /> for the next update and mark the LED as <see cref="IsUpdated" />.
|
||||
/// Gets the current color of the LED. Sets the <see cref="RequestedColor" /> for the next update. />.
|
||||
/// </summary>
|
||||
public Color Color
|
||||
{
|
||||
@@ -44,10 +42,7 @@ namespace CUE.NET.Devices.Generic
|
||||
set
|
||||
{
|
||||
if (!IsLocked)
|
||||
{
|
||||
RequestedColor = RequestedColor.Blend(value);
|
||||
IsUpdated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,9 +58,11 @@ namespace CUE.NET.Devices.Generic
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CorsairLed"/> class.
|
||||
/// </summary>
|
||||
/// <param name="ledRectangle">The rectangle representing the physical location of the led.</param>
|
||||
internal CorsairLed(RectangleF ledRectangle)
|
||||
/// <param name="id">The ID of the LED</param>
|
||||
/// <param name="ledRectangle">The rectangle representing the physical location of the LED.</param>
|
||||
internal CorsairLed(CorsairLedId id, RectangleF ledRectangle)
|
||||
{
|
||||
this.Id = id;
|
||||
this.LedRectangle = ledRectangle;
|
||||
}
|
||||
|
||||
@@ -79,7 +76,6 @@ namespace CUE.NET.Devices.Generic
|
||||
internal void Update()
|
||||
{
|
||||
_color = RequestedColor;
|
||||
IsUpdated = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -89,7 +85,6 @@ namespace CUE.NET.Devices.Generic
|
||||
{
|
||||
_color = Color.Transparent;
|
||||
RequestedColor = Color.Transparent;
|
||||
IsUpdated = false;
|
||||
IsLocked = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
|
||||
|
||||
using System.Drawing;
|
||||
using CUE.NET.Devices.Generic.Enums;
|
||||
|
||||
namespace CUE.NET.Devices.Generic
|
||||
{
|
||||
@@ -15,7 +16,7 @@ namespace CUE.NET.Devices.Generic
|
||||
/// <summary>
|
||||
/// Gets the id of the led to update.
|
||||
/// </summary>
|
||||
public int LedId { get; }
|
||||
public CorsairLedId LedId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the requested color of the led.
|
||||
@@ -31,7 +32,7 @@ namespace CUE.NET.Devices.Generic
|
||||
/// </summary>
|
||||
/// <param name="ledId">The id of the led to update.</param>
|
||||
/// <param name="color">The requested color of the led.</param>
|
||||
public LedUpateRequest(int ledId, Color color)
|
||||
public LedUpateRequest(CorsairLedId ledId, Color color)
|
||||
{
|
||||
this.LedId = ledId;
|
||||
this.Color = color;
|
||||
|
||||
Reference in new issue
Block a user