1
0
mirror of https://github.com/DarthAffe/RGB.NET.git synced 2025-12-13 01:58:30 +00:00

Fixed some stuff to get Corsair-Devices working

This commit is contained in:
Darth Affe 2017-01-26 20:14:38 +01:00
parent 7f6c8e6a70
commit 05c0633348
18 changed files with 308 additions and 35 deletions

View File

@ -0,0 +1,110 @@
// ReSharper disable VirtualMemberNeverOverriden.Global
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable VirtualMemberNeverOverridden.Global
using System.Collections.Generic;
using System.Linq;
namespace RGB.NET.Core
{
/// <summary>
/// Represents a basic brush.
/// </summary>
public abstract class AbstractBrush : AbstractEffectTarget<IBrush>, IBrush
{
#region Properties & Fields
/// <inheritdoc />
public BrushCalculationMode BrushCalculationMode { get; set; } = BrushCalculationMode.Relative;
/// <inheritdoc />
public double Brightness { get; set; }
/// <inheritdoc />
public double Opacity { get; set; }
/// <inheritdoc />
public IList<IColorCorrection> ColorCorrections { get; } = new List<IColorCorrection>();
/// <inheritdoc />
public Rectangle RenderedRectangle { get; protected set; }
/// <inheritdoc />
public Dictionary<BrushRenderTarget, Color> RenderedTargets { get; } = new Dictionary<BrushRenderTarget, Color>();
/// <inheritdoc />
protected override IBrush EffectTarget => this;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="AbstractBrush"/> class.
/// </summary>
/// <param name="brightness">The overall percentage brightness of the brush. (default: 1.0)</param>
/// <param name="opacity">The overall percentage opacity of the brush. (default: 1.0)</param>
protected AbstractBrush(double brightness = 1, double opacity = 1)
{
this.Brightness = brightness;
this.Opacity = opacity;
}
#endregion
#region Methods
/// <summary>
/// Performas the render pass of the brush and calculates the raw colors for all requested points.
/// </summary>
/// <param name="rectangle">The rectangle in which the brush should be drawn.</param>
/// <param name="renderTargets">The targets (keys/points) of which the color should be calculated.</param>
public virtual void PerformRender(Rectangle rectangle, IEnumerable<BrushRenderTarget> renderTargets)
{
RenderedRectangle = rectangle;
RenderedTargets.Clear();
foreach (BrushRenderTarget point in renderTargets)
RenderedTargets[point] = new Color(GetColorAtPoint(rectangle, point)); // Clone the color, we don't want to have reference issues here and brushes might return the same color multiple times!
}
/// <summary>
/// Performs the finalize pass of the brush and calculates the final colors for all previously calculated points.
/// </summary>
public virtual void PerformFinalize()
{
List<BrushRenderTarget> renderTargets = RenderedTargets.Keys.ToList();
foreach (BrushRenderTarget renderTarget in renderTargets)
FinalizeColor(RenderedTargets[renderTarget]); // Cloning here again shouldn't be needed since we did this above.
}
/// <summary>
/// Gets the color at an specific point assuming the brush is drawn into the given rectangle.
/// </summary>
/// <param name="rectangle">The rectangle in which the brush should be drawn.</param>
/// <param name="renderTarget">The target (key/point) from which the color should be taken.</param>
/// <returns>The color at the specified point.</returns>
protected abstract Color GetColorAtPoint(Rectangle rectangle, BrushRenderTarget renderTarget);
/// <summary>
/// Finalizes the color by appliing the overall brightness and opacity.<br/>
/// This method should always be the last call of a <see cref="GetColorAtPoint" /> implementation.
/// If you overwrite this method please make sure that you never return the same color-object twice to prevent reference-issues!
/// </summary>
/// <param name="color">The color to finalize.</param>
/// <returns>The finalized color.</returns>
protected virtual void FinalizeColor(Color color)
{
foreach (IColorCorrection colorCorrection in ColorCorrections)
colorCorrection.ApplyTo(color);
// Since we use HSV to calculate there is no way to make a color 'brighter' than 100%
// Be carefull with the naming: Since we use HSV the correct term is 'value' but outside we call it 'brightness'
// THIS IS NOT A HSB CALCULATION!!!
color.Value *= Brightness <= 0 ? 0 : (Brightness >= 1.0 ? 1.0 : Brightness);
color.A = (byte)(color.A * (Opacity <= 0 ? 0 : (Opacity >= 1.0 ? 1.0 : Opacity)));
}
#endregion
}
}

View File

@ -70,9 +70,11 @@ namespace RGB.NET.Core
DeviceUpdate();
// Send LEDs to SDK
IEnumerable<Led> ledsToUpdate = flushLeds ? LedMapping.Values : LedMapping.Values.Where(x => x.IsDirty);
IEnumerable<Led> ledsToUpdate = (flushLeds ? LedMapping.Values : LedMapping.Values.Where(x => x.IsDirty)).ToList();
foreach (Led ledToUpdate in ledsToUpdate)
ledToUpdate.Update();
UpdateLeds(ledsToUpdate);
}
/// <summary>
@ -81,6 +83,11 @@ namespace RGB.NET.Core
protected virtual void DeviceUpdate()
{ }
/// <summary>
/// Sends all the updated <see cref="Led"/> to the device.
/// </summary>
protected abstract void UpdateLeds(IEnumerable<Led> ledsToUpdate);
/// <summary>
/// Initializes the <see cref="Led"/> with the specified id.
/// </summary>

View File

@ -0,0 +1,49 @@
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable UnusedAutoPropertyAccessor.Global
using System;
namespace RGB.NET.Core
{
/// <summary>
/// Represents the information supplied with an <see cref="RGBSurface.SurfaceLayoutChanged"/>-event.
/// </summary>
public class SurfaceLayoutChangedEventArgs : EventArgs
{
#region Properties & Fields
/// <summary>
/// Gets the <see cref="IRGBDevice"/> that caused the change. Returns null if the change isn't caused by a <see cref="IRGBDevice"/>.
/// </summary>
public IRGBDevice Device { get; }
/// <summary>
/// Gets a value indicating if the event is caused by the addition of a new <see cref="IRGBDevice"/> to the <see cref="RGBSurface"/>.
/// </summary>
public bool DeviceAdded { get; }
/// <summary>
/// Gets a value indicating if the event is caused by a changed location of one of the devices on the <see cref="RGBSurface"/>.
/// </summary>
public bool DeviceLocationChanged { get; }
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="SurfaceLayoutChangedEventArgs"/> class.
/// </summary>
/// <param name="device">The <see cref="IRGBDevice"/> that caused the change</param>
/// <param name="deviceAdded">A value indicating if the event is caused by the addition of a new <see cref="IRGBDevice"/> to the <see cref="RGBSurface"/>.</param>
/// <param name="deviceLocationChanged">A value indicating if the event is caused by a changed location of one of the devices on the <see cref="RGBSurface"/>.</param>
public SurfaceLayoutChangedEventArgs(IRGBDevice device, bool deviceAdded, bool deviceLocationChanged)
{
this.Device = device;
this.DeviceAdded = deviceAdded;
this.DeviceLocationChanged = deviceLocationChanged;
}
#endregion
}
}

View File

@ -3,7 +3,7 @@
namespace RGB.NET.Core
{
/// <summary>
/// Represents a generic ledgroup.
/// Represents a generic <see cref="AbstractLedGroup"/>.
/// </summary>
public abstract class AbstractLedGroup : AbstractEffectTarget<ILedGroup>, ILedGroup
{
@ -22,11 +22,33 @@ namespace RGB.NET.Core
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="AbstractLedGroup"/> class.
/// </summary>
/// <param name="autoAttach">Specifies whether this <see cref="AbstractLedGroup"/> should be automatically attached or not.</param>
protected AbstractLedGroup(bool autoAttach)
{
if (autoAttach)
RGBSurface.AttachLedGroup(this);
}
#endregion
#region Methods
/// <inheritdoc />
public abstract IEnumerable<Led> GetLeds();
/// <inheritdoc />
public virtual void OnAttach()
{ }
/// <inheritdoc />
public virtual void OnDetach()
{ }
#endregion
}
}

View File

@ -25,5 +25,15 @@ namespace RGB.NET.Core
/// </summary>
/// <returns>The list containing all <see cref="Led"/> of this <see cref="ILedGroup"/>.</returns>
IEnumerable<Led> GetLeds();
/// <summary>
/// Called when the <see cref="ILedId"/> is attached to the <see cref="RGBSurface"/>.
/// </summary>
void OnAttach();
/// <summary>
/// Called when the <see cref="ILedId"/> is detached from the <see cref="RGBSurface"/>.
/// </summary>
void OnDetach();
}
}

View File

@ -278,9 +278,9 @@ namespace RGB.NET.Core
if (color.A == 255)
{
A = color.A;
R = color.A;
G = color.A;
B = color.A;
R = color.R;
G = color.G;
B = color.B;
}
else
{

View File

@ -5,6 +5,11 @@
/// </summary>
public interface ILedId
{
/// <summary>
/// Gets the <see cref="IRGBDevice"/> the <see cref="ILedId"/> belongs to.
/// </summary>
IRGBDevice Device { get; }
/// <summary>
/// Gets a value indicating if this <see cref="ILedId"/> is valid.
/// </summary>

View File

@ -59,7 +59,8 @@ namespace RGB.NET.Core
{
if (!IsLocked)
{
RequestedColor.Blend(value);
// DarthAffe 26.01.2017: DON'T USE THE PROPERTY HERE! Working on the copy doesn't work!
_requestedColor.Blend(value);
// ReSharper disable ExplicitCallerInfoArgument
OnPropertyChanged(nameof(RequestedColor));

View File

@ -42,6 +42,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Brushes\AbstractBrush.cs" />
<Compile Include="Brushes\BrushCalculationMode.cs" />
<Compile Include="Brushes\BrushRenderTarget.cs" />
<Compile Include="Brushes\IBrush.cs" />
@ -55,6 +56,7 @@
<Compile Include="Effects\IEffect.cs" />
<Compile Include="Effects\IEffectTarget.cs" />
<Compile Include="Events\ExceptionEventArgs.cs" />
<Compile Include="Events\SurfaceLayoutChangedEventArgs.cs" />
<Compile Include="Events\UpdatedEventArgs.cs" />
<Compile Include="Events\UpdatingEventArgs.cs" />
<Compile Include="Exceptions\EffectException.cs" />

View File

@ -19,7 +19,7 @@ namespace RGB.NET.Core
private static IList<IRGBDeviceProvider> _deviceProvider = new List<IRGBDeviceProvider>();
private static IList<IRGBDevice> _devices = new List<IRGBDevice>();
// ReSharper disable InconsistentNaming
private static readonly LinkedList<ILedGroup> _ledGroups = new LinkedList<ILedGroup>();
@ -38,6 +38,11 @@ namespace RGB.NET.Core
/// </summary>
public static Rectangle SurfaceRectangle => new Rectangle(_surfaceRectangle);
/// <summary>
/// Gets a list of all <see cref="Led"/> on this <see cref="RGBSurface"/>.
/// </summary>
public static IEnumerable<Led> Leds => _devices.SelectMany(x => x);
#endregion
#region Constructors
@ -141,6 +146,8 @@ namespace RGB.NET.Core
if (_ledGroups.Contains(ledGroup)) return false;
_ledGroups.AddLast(ledGroup);
ledGroup.OnAttach();
return true;
}
}
@ -160,6 +167,8 @@ namespace RGB.NET.Core
if (node == null) return false;
_ledGroups.Remove(node);
node.Value.OnDetach();
return true;
}
}

View File

@ -7,23 +7,29 @@ namespace RGB.NET.Core
#region EventHandler
/// <summary>
/// Represents the event-handler of the <see cref="RGBSurface.Exception"/>-event.
/// Represents the event-handler of the <see cref="Exception"/>-event.
/// </summary>
/// <param name="args">The arguments provided by the event.</param>
public delegate void ExceptionEventHandler(ExceptionEventArgs args);
/// <summary>
/// Represents the event-handler of the <see cref="RGBSurface.Updating"/>-event.
/// Represents the event-handler of the <see cref="Updating"/>-event.
/// </summary>
/// <param name="args">The arguments provided by the event.</param>
public delegate void UpdatingEventHandler(UpdatingEventArgs args);
/// <summary>
/// Represents the event-handler of the <see cref="RGBSurface.Updated"/>-event.
/// Represents the event-handler of the <see cref="Updated"/>-event.
/// </summary>
/// <param name="args">The arguments provided by the event.</param>
public delegate void UpdatedEventHandler(UpdatedEventArgs args);
/// <summary>
/// Represents the event-handler of the <see cref="SurfaceLayoutChanged"/>-event.
/// </summary>
/// <param name="args"></param>
public delegate void SurfaceLayoutChangedEventHandler(SurfaceLayoutChangedEventArgs args);
#endregion
#region Events
@ -45,6 +51,11 @@ namespace RGB.NET.Core
/// </summary>
public static event UpdatedEventHandler Updated;
/// <summary>
/// Occurs when the layout of this <see cref="RGBSurface"/> changed.
/// </summary>
public static event SurfaceLayoutChangedEventHandler SurfaceLayoutChanged;
// ReSharper restore EventNeverSubscribedTo.Global
#endregion

View File

@ -16,6 +16,7 @@ namespace RGB.NET.Core
{
if (_deviceProvider.Contains(deviceProvider) || _deviceProvider.Any(x => x.GetType() == deviceProvider.GetType())) return;
IRGBDevice addedDevice = null;
if (deviceProvider.IsInitialized || deviceProvider.Initialize())
{
_deviceProvider.Add(deviceProvider);
@ -24,18 +25,27 @@ namespace RGB.NET.Core
{
if (_devices.Contains(device)) continue;
addedDevice = device;
device.PropertyChanged += DeviceOnPropertyChanged;
_devices.Add(device);
}
}
UpdateSurfaceRectangle();
if (addedDevice != null)
{
UpdateSurfaceRectangle();
SurfaceLayoutChanged?.Invoke(new SurfaceLayoutChangedEventArgs(addedDevice, true, false));
}
}
private static void DeviceOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
if (string.Equals(propertyChangedEventArgs.PropertyName, nameof(IRGBDevice.Location)))
{
SurfaceLayoutChanged?.Invoke(new SurfaceLayoutChangedEventArgs(sender as IRGBDevice, false, true));
UpdateSurfaceRectangle();
}
}
#endregion

View File

@ -6,15 +6,18 @@ namespace RGB.NET.Devices.Corsair
/// <summary>
/// Represents a Id of a <see cref="Led"/> on a <see cref="CorsairRGBDevice"/>.
/// </summary>
[DebuggerDisplay("{" + nameof(_ledId) + "}")]
[DebuggerDisplay("{" + nameof(LedId) + "}")]
public class CorsairLedId : ILedId
{
#region Properties & Fields
private readonly CorsairLedIds _ledId;
internal readonly CorsairLedIds LedId;
/// <inheritdoc />
public bool IsValid => _ledId != CorsairLedIds.Invalid;
public IRGBDevice Device { get; }
/// <inheritdoc />
public bool IsValid => LedId != CorsairLedIds.Invalid;
#endregion
@ -23,10 +26,12 @@ namespace RGB.NET.Devices.Corsair
/// <summary>
/// Initializes a new instance of the <see cref="CorsairLedId"/> class.
/// </summary>
/// <param name="ledId">The corsair-id of the represented <see cref="Led"/>.</param>
public CorsairLedId(CorsairLedIds ledId)
/// <param name="device">The <see cref="IRGBDevice"/> the <see cref="ILedId"/> belongs to.</param>
/// <param name="ledId">The <see cref="CorsairLedId"/> of the represented <see cref="Led"/>.</param>
public CorsairLedId(IRGBDevice device, CorsairLedIds ledId)
{
this._ledId = ledId;
this.Device = device;
this.LedId = ledId;
}
#endregion
@ -39,7 +44,7 @@ namespace RGB.NET.Devices.Corsair
/// <returns>A string that contains the Id of this <see cref="CorsairLedId"/>. For example "Enter".</returns>
public override string ToString()
{
return _ledId.ToString();
return LedId.ToString();
}
/// <summary>
@ -59,7 +64,7 @@ namespace RGB.NET.Devices.Corsair
if (GetType() != compareLedId.GetType())
return false;
return compareLedId._ledId == _ledId;
return compareLedId.LedId == LedId;
}
/// <summary>
@ -68,7 +73,7 @@ namespace RGB.NET.Devices.Corsair
/// <returns>An integer value that specifies the hash code for this <see cref="CorsairLedId" />.</returns>
public override int GetHashCode()
{
return _ledId.GetHashCode();
return LedId.GetHashCode();
}
#endregion

View File

@ -1,5 +1,9 @@
using System.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using RGB.NET.Core;
using RGB.NET.Devices.Corsair.Native;
namespace RGB.NET.Devices.Corsair
{
@ -51,6 +55,34 @@ namespace RGB.NET.Devices.Corsair
/// </summary>
protected abstract void InitializeLeds();
/// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate)
{
List<Led> leds = ledsToUpdate.Where(x => x.Color.A > 0).ToList();
if (leds.Count > 0) // CUE seems to crash if 'CorsairSetLedsColors' is called with a zero length array
{
int structSize = Marshal.SizeOf(typeof(_CorsairLedColor));
IntPtr ptr = Marshal.AllocHGlobal(structSize * leds.Count);
IntPtr addPtr = new IntPtr(ptr.ToInt64());
foreach (Led led in leds)
{
_CorsairLedColor color = new _CorsairLedColor
{
ledId = (int)((CorsairLedId)led.Id).LedId,
r = led.Color.R,
g = led.Color.G,
b = led.Color.B
};
Marshal.StructureToPtr(color, addPtr, false);
addPtr = new IntPtr(addPtr.ToInt64() + structSize);
}
_CUESDK.CorsairSetLedsColors(leds.Count, ptr);
Marshal.FreeHGlobal(ptr);
}
}
#endregion
}
}

View File

@ -40,8 +40,8 @@ namespace RGB.NET.Devices.Corsair
/// </summary>
protected override void InitializeLeds()
{
InitializeLed(new CorsairLedId(CorsairLedIds.LeftLogo), new Rectangle(0, 0, 10, 10));
InitializeLed(new CorsairLedId(CorsairLedIds.RightLogo), new Rectangle(10, 0, 10, 10));
InitializeLed(new CorsairLedId(this, CorsairLedIds.LeftLogo), new Rectangle(0, 0, 10, 10));
InitializeLed(new CorsairLedId(this, CorsairLedIds.RightLogo), new Rectangle(10, 0, 10, 10));
}
#endregion

View File

@ -52,7 +52,7 @@ namespace RGB.NET.Devices.Corsair
for (int i = 0; i < nativeLedPositions.numberOfLed; i++)
{
_CorsairLedPosition ledPosition = (_CorsairLedPosition)Marshal.PtrToStructure(ptr, typeof(_CorsairLedPosition));
InitializeLed(new CorsairLedId(ledPosition.ledId),
InitializeLed(new CorsairLedId(this, ledPosition.ledId),
new Rectangle(ledPosition.left, ledPosition.top, ledPosition.width, ledPosition.height));
ptr = new IntPtr(ptr.ToInt64() + structSize);

View File

@ -44,22 +44,22 @@ namespace RGB.NET.Devices.Corsair
switch (MouseDeviceInfo.PhysicalLayout)
{
case CorsairPhysicalMouseLayout.Zones1:
InitializeLed(new CorsairLedId(CorsairLedIds.B1), new Rectangle(0, 0, 10, 10));
InitializeLed(new CorsairLedId(this, CorsairLedIds.B1), new Rectangle(0, 0, 10, 10));
break;
case CorsairPhysicalMouseLayout.Zones2:
InitializeLed(new CorsairLedId(CorsairLedIds.B1), new Rectangle(0, 0, 10, 10));
InitializeLed(new CorsairLedId(CorsairLedIds.B2), new Rectangle(10, 0, 10, 10));
InitializeLed(new CorsairLedId(this, CorsairLedIds.B1), new Rectangle(0, 0, 10, 10));
InitializeLed(new CorsairLedId(this, CorsairLedIds.B2), new Rectangle(10, 0, 10, 10));
break;
case CorsairPhysicalMouseLayout.Zones3:
InitializeLed(new CorsairLedId(CorsairLedIds.B1), new Rectangle(0, 0, 10, 10));
InitializeLed(new CorsairLedId(CorsairLedIds.B2), new Rectangle(10, 0, 10, 10));
InitializeLed(new CorsairLedId(CorsairLedIds.B3), new Rectangle(20, 0, 10, 10));
InitializeLed(new CorsairLedId(this, CorsairLedIds.B1), new Rectangle(0, 0, 10, 10));
InitializeLed(new CorsairLedId(this, CorsairLedIds.B2), new Rectangle(10, 0, 10, 10));
InitializeLed(new CorsairLedId(this, CorsairLedIds.B3), new Rectangle(20, 0, 10, 10));
break;
case CorsairPhysicalMouseLayout.Zones4:
InitializeLed(new CorsairLedId(CorsairLedIds.B1), new Rectangle(0, 0, 10, 10));
InitializeLed(new CorsairLedId(CorsairLedIds.B2), new Rectangle(10, 0, 10, 10));
InitializeLed(new CorsairLedId(CorsairLedIds.B3), new Rectangle(20, 0, 10, 10));
InitializeLed(new CorsairLedId(CorsairLedIds.B4), new Rectangle(30, 0, 10, 10));
InitializeLed(new CorsairLedId(this, CorsairLedIds.B1), new Rectangle(0, 0, 10, 10));
InitializeLed(new CorsairLedId(this, CorsairLedIds.B2), new Rectangle(10, 0, 10, 10));
InitializeLed(new CorsairLedId(this, CorsairLedIds.B3), new Rectangle(20, 0, 10, 10));
InitializeLed(new CorsairLedId(this, CorsairLedIds.B4), new Rectangle(30, 0, 10, 10));
break;
default:
throw new RGBDeviceException($"Can't initial mouse with layout '{MouseDeviceInfo.PhysicalLayout}'");

View File

@ -62,7 +62,7 @@ namespace RGB.NET.Devices.Corsair
}
foreach (_CorsairLedPosition ledPosition in positions.OrderBy(p => p.ledId))
InitializeLed(new CorsairLedId(ledPosition.ledId),
InitializeLed(new CorsairLedId(this, ledPosition.ledId),
new Rectangle(ledPosition.left, ledPosition.top, ledPosition.width, ledPosition.height));
}