From 13afc29987d01778526ec7c6895fedf68263d395 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Sun, 21 Feb 2021 15:49:05 +0100 Subject: [PATCH 01/22] Reworked rendering --- .../Brushes/ConicalGradientBrush.cs | 121 ------------------ RGB.NET.Brushes/Brushes/IGradientBrush.cs | 17 --- .../Brushes/LinearGradientBrush.cs | 109 ---------------- .../Brushes/RadialGradientBrush.cs | 97 -------------- RGB.NET.Brushes/RGB.NET.Brushes.csproj | 56 -------- .../ColorCorrection/IColorCorrection.cs | 2 +- RGB.NET.Core/Decorators/IBrushDecorator.cs | 2 +- RGB.NET.Core/Devices/AbstractRGBDevice.cs | 3 + RGB.NET.Core/Devices/IRGBDevice.cs | 2 + .../Extensions/RectangleExtensions.cs | 12 +- .../Groups/ListLedGroup.cs | 3 +- RGB.NET.Core/Leds/Led.cs | 12 -- RGB.NET.Core/Positioning/Rectangle.cs | 11 +- RGB.NET.Core/RGB.NET.Core.csproj.DotSettings | 4 + RGB.NET.Core/RGBSurface.cs | 27 ++-- .../{ => Rendering}/Brushes/AbstractBrush.cs | 49 ++----- .../{ => Rendering}/Brushes/IBrush.cs | 28 +--- .../Rendering}/Brushes/SolidColorBrush.cs | 10 +- .../Rendering/Brushes/TextureBrush.cs | 35 +++++ .../RenderMode.cs} | 4 +- .../RenderTarget.cs} | 10 +- .../Rendering/Textures/EmptyTexture.cs | 13 ++ RGB.NET.Core/Rendering/Textures/ITexture.cs | 12 ++ .../Rendering/Textures/PixelTexture.cs | 66 ++++++++++ .../Textures/Sampler/AverageSampler.cs | 77 +++++++++++ .../Rendering/Textures/Sampler/ISampler.cs | 9 ++ RGB.NET.Core/Update/ManualUpdateTrigger.cs | 94 ++++++++++++++ RGB.NET.Decorators/RGB.NET.Decorators.csproj | 57 --------- .../RGB.NET.Groups.csproj.DotSettings | 3 - .../Decorators}/FlashDecorator.cs | 4 +- .../Decorators/IGradientDecorator.cs | 4 +- .../Decorators}/MoveGradientDecorator.cs | 19 ++- .../Groups}/Extensions/LedGroupExtension.cs | 2 +- .../Groups/RectangleLedGroup.cs | 8 +- .../Helper/GradientHelper.cs | 27 ++-- .../RGB.NET.Presets.csproj | 14 +- .../RGB.NET.Presets.csproj.DotSettings | 5 +- .../Textures/AbstractGradientTexture.cs | 42 ++++++ .../Textures/ConicalGradientTexture.cs | 98 ++++++++++++++ .../Textures}/Gradients/AbstractGradient.cs | 11 +- .../Textures}/Gradients/GradientStop.cs | 2 +- .../Textures}/Gradients/IGradient.cs | 4 +- .../Textures}/Gradients/LinearGradient.cs | 10 +- .../Textures}/Gradients/RainbowGradient.cs | 3 +- .../Textures/LinearGradientTexture.cs | 79 ++++++++++++ .../Textures/RadialGradientTexture.cs | 78 +++++++++++ RGB.NET.sln | 19 +-- 47 files changed, 732 insertions(+), 642 deletions(-) delete mode 100644 RGB.NET.Brushes/Brushes/ConicalGradientBrush.cs delete mode 100644 RGB.NET.Brushes/Brushes/IGradientBrush.cs delete mode 100644 RGB.NET.Brushes/Brushes/LinearGradientBrush.cs delete mode 100644 RGB.NET.Brushes/Brushes/RadialGradientBrush.cs delete mode 100644 RGB.NET.Brushes/RGB.NET.Brushes.csproj rename {RGB.NET.Groups => RGB.NET.Core}/Groups/ListLedGroup.cs (99%) rename RGB.NET.Core/{ => Rendering}/Brushes/AbstractBrush.cs (63%) rename RGB.NET.Core/{ => Rendering}/Brushes/IBrush.cs (51%) rename {RGB.NET.Brushes => RGB.NET.Core/Rendering}/Brushes/SolidColorBrush.cs (81%) create mode 100644 RGB.NET.Core/Rendering/Brushes/TextureBrush.cs rename RGB.NET.Core/{Brushes/BrushCalculationMode.cs => Rendering/RenderMode.cs} (79%) rename RGB.NET.Core/{Brushes/BrushRenderTarget.cs => Rendering/RenderTarget.cs} (81%) create mode 100644 RGB.NET.Core/Rendering/Textures/EmptyTexture.cs create mode 100644 RGB.NET.Core/Rendering/Textures/ITexture.cs create mode 100644 RGB.NET.Core/Rendering/Textures/PixelTexture.cs create mode 100644 RGB.NET.Core/Rendering/Textures/Sampler/AverageSampler.cs create mode 100644 RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs create mode 100644 RGB.NET.Core/Update/ManualUpdateTrigger.cs delete mode 100644 RGB.NET.Decorators/RGB.NET.Decorators.csproj delete mode 100644 RGB.NET.Groups/RGB.NET.Groups.csproj.DotSettings rename {RGB.NET.Decorators/Brush => RGB.NET.Presets/Decorators}/FlashDecorator.cs (97%) rename {RGB.NET.Brushes => RGB.NET.Presets}/Decorators/IGradientDecorator.cs (73%) rename {RGB.NET.Decorators/Gradient => RGB.NET.Presets/Decorators}/MoveGradientDecorator.cs (84%) rename {RGB.NET.Groups => RGB.NET.Presets/Groups}/Extensions/LedGroupExtension.cs (98%) rename {RGB.NET.Groups => RGB.NET.Presets}/Groups/RectangleLedGroup.cs (93%) rename {RGB.NET.Brushes => RGB.NET.Presets}/Helper/GradientHelper.cs (76%) rename RGB.NET.Groups/RGB.NET.Groups.csproj => RGB.NET.Presets/RGB.NET.Presets.csproj (82%) rename RGB.NET.Brushes/RGB.NET.Brushes.csproj.DotSettings => RGB.NET.Presets/RGB.NET.Presets.csproj.DotSettings (57%) create mode 100644 RGB.NET.Presets/Textures/AbstractGradientTexture.cs create mode 100644 RGB.NET.Presets/Textures/ConicalGradientTexture.cs rename {RGB.NET.Brushes => RGB.NET.Presets/Textures}/Gradients/AbstractGradient.cs (93%) rename {RGB.NET.Brushes => RGB.NET.Presets/Textures}/Gradients/GradientStop.cs (97%) rename {RGB.NET.Brushes => RGB.NET.Presets/Textures}/Gradients/IGradient.cs (92%) rename {RGB.NET.Brushes => RGB.NET.Presets/Textures}/Gradients/LinearGradient.cs (94%) rename {RGB.NET.Brushes => RGB.NET.Presets/Textures}/Gradients/RainbowGradient.cs (97%) create mode 100644 RGB.NET.Presets/Textures/LinearGradientTexture.cs create mode 100644 RGB.NET.Presets/Textures/RadialGradientTexture.cs diff --git a/RGB.NET.Brushes/Brushes/ConicalGradientBrush.cs b/RGB.NET.Brushes/Brushes/ConicalGradientBrush.cs deleted file mode 100644 index 127ce9c..0000000 --- a/RGB.NET.Brushes/Brushes/ConicalGradientBrush.cs +++ /dev/null @@ -1,121 +0,0 @@ -// ReSharper disable MemberCanBePrivate.Global -// ReSharper disable MemberCanBeProtected.Global -// ReSharper disable ReturnTypeCanBeEnumerable.Global -// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global -// ReSharper disable UnusedMember.Global - -using System; -using RGB.NET.Brushes.Gradients; -using RGB.NET.Core; - -namespace RGB.NET.Brushes -{ - /// - /// - /// - /// Represents a brush drawing a conical gradient. - /// - public class ConicalGradientBrush : AbstractBrush, IGradientBrush - { - #region Properties & Fields - - private float _origin = (float)Math.Atan2(-1, 0); - /// - /// Gets or sets the origin (radian-angle) this is drawn to. (default: -π/2) - /// - public float Origin - { - get => _origin; - set => SetProperty(ref _origin, value); - } - - private Point _center = new(0.5, 0.5); - /// - /// Gets or sets the center (as percentage in the range [0..1]) of the drawn by this . (default: 0.5, 0.5) - /// - public Point Center - { - get => _center; - set => SetProperty(ref _center, value); - } - - private IGradient? _gradient; - /// - /// - /// Gets or sets the gradient drawn by the brush. If null it will default to full transparent. - /// - public IGradient? Gradient - { - get => _gradient; - set => SetProperty(ref _gradient, value); - } - - #endregion - - #region Constructors - - /// - /// - /// Initializes a new instance of the class. - /// - public ConicalGradientBrush() - { } - - /// - /// - /// Initializes a new instance of the class. - /// - /// The drawn by this . - public ConicalGradientBrush(IGradient gradient) - { - this.Gradient = gradient; - } - - /// - /// - /// Initializes a new instance of the class. - /// - /// The center (as percentage in the range [0..1]). - /// The drawn by this . - public ConicalGradientBrush(Point center, IGradient gradient) - { - this.Center = center; - this.Gradient = gradient; - } - - /// - /// - /// Initializes a new instance of the class. - /// - /// The center (as percentage in the range [0..1]). - /// The origin (radian-angle) the is drawn to. - /// The drawn by this . - public ConicalGradientBrush(Point center, float origin, IGradient gradient) - { - this.Center = center; - this.Origin = origin; - this.Gradient = gradient; - } - - #endregion - - #region Methods - - /// - protected override Color GetColorAtPoint(Rectangle rectangle, BrushRenderTarget renderTarget) - { - if (Gradient == null) return Color.Transparent; - - double centerX = rectangle.Size.Width * Center.X; - double centerY = rectangle.Size.Height * Center.Y; - - double angle = Math.Atan2(renderTarget.Point.Y - centerY, renderTarget.Point.X - centerX) - Origin; - if (angle < 0) angle += Math.PI * 2; - double offset = angle / (Math.PI * 2); - - return Gradient.GetColor(offset); - } - - #endregion - } -} diff --git a/RGB.NET.Brushes/Brushes/IGradientBrush.cs b/RGB.NET.Brushes/Brushes/IGradientBrush.cs deleted file mode 100644 index 80522a3..0000000 --- a/RGB.NET.Brushes/Brushes/IGradientBrush.cs +++ /dev/null @@ -1,17 +0,0 @@ -using RGB.NET.Brushes.Gradients; -using RGB.NET.Core; - -namespace RGB.NET.Brushes -{ - /// - /// - /// Represents a basic gradient-brush. - /// - public interface IGradientBrush : IBrush - { - /// - /// Gets the used by this . - /// - IGradient? Gradient { get; } - } -} diff --git a/RGB.NET.Brushes/Brushes/LinearGradientBrush.cs b/RGB.NET.Brushes/Brushes/LinearGradientBrush.cs deleted file mode 100644 index c175068..0000000 --- a/RGB.NET.Brushes/Brushes/LinearGradientBrush.cs +++ /dev/null @@ -1,109 +0,0 @@ -// ReSharper disable CollectionNeverUpdated.Global -// ReSharper disable MemberCanBePrivate.Global -// ReSharper disable MemberCanBeProtected.Global -// ReSharper disable ReturnTypeCanBeEnumerable.Global -// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global -// ReSharper disable UnusedMember.Global - -using RGB.NET.Brushes.Gradients; -using RGB.NET.Brushes.Helper; -using RGB.NET.Core; - -namespace RGB.NET.Brushes -{ - /// - /// - /// - /// Represents a brush drawing a linear gradient. - /// - public class LinearGradientBrush : AbstractBrush, IGradientBrush - { - #region Properties & Fields - - private Point _startPoint = new(0, 0.5); - /// - /// Gets or sets the start (as percentage in the range [0..1]) of the drawn by this . (default: 0.0, 0.5) - /// - public Point StartPoint - { - get => _startPoint; - set => SetProperty(ref _startPoint, value); - } - - private Point _endPoint = new(1, 0.5); - /// - /// Gets or sets the end (as percentage in the range [0..1]) of the drawn by this . (default: 1.0, 0.5) - /// - public Point EndPoint - { - get => _endPoint; - set => SetProperty(ref _endPoint, value); - } - - private IGradient? _gradient; - /// - public IGradient? Gradient - { - get => _gradient; - set => SetProperty(ref _gradient, value); - } - - #endregion - - #region Constructor - - /// - /// - /// Initializes a new instance of the class. - /// - public LinearGradientBrush() - { } - - /// - /// - /// Initializes a new instance of the class. - /// - /// The drawn by this . - public LinearGradientBrush(IGradient gradient) - { - this.Gradient = gradient; - } - /// - /// - /// Initializes a new instance of the class. - /// - /// The start (as percentage in the range [0..1]). - /// The end (as percentage in the range [0..1]). - /// The drawn by this . - public LinearGradientBrush(Point startPoint, Point endPoint, IGradient gradient) - { - this.StartPoint = startPoint; - this.EndPoint = endPoint; - this.Gradient = gradient; - } - - #endregion - - #region Methods - - /// - /// - /// Gets the color at an specific point assuming the brush is drawn into the given rectangle. - /// - /// The rectangle in which the brush should be drawn. - /// The target (key/point) from which the color should be taken. - /// The color at the specified point. - protected override Color GetColorAtPoint(Rectangle rectangle, BrushRenderTarget renderTarget) - { - if (Gradient == null) return Color.Transparent; - - Point startPoint = new(StartPoint.X * rectangle.Size.Width, StartPoint.Y * rectangle.Size.Height); - Point endPoint = new(EndPoint.X * rectangle.Size.Width, EndPoint.Y * rectangle.Size.Height); - - double offset = GradientHelper.CalculateLinearGradientOffset(startPoint, endPoint, renderTarget.Point); - return Gradient.GetColor(offset); - } - - #endregion - } -} diff --git a/RGB.NET.Brushes/Brushes/RadialGradientBrush.cs b/RGB.NET.Brushes/Brushes/RadialGradientBrush.cs deleted file mode 100644 index 9d2ee34..0000000 --- a/RGB.NET.Brushes/Brushes/RadialGradientBrush.cs +++ /dev/null @@ -1,97 +0,0 @@ -// ReSharper disable MemberCanBePrivate.Global -// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global -// ReSharper disable UnusedMember.Global - -using System; -using RGB.NET.Brushes.Gradients; -using RGB.NET.Brushes.Helper; -using RGB.NET.Core; - -namespace RGB.NET.Brushes -{ - /// - /// - /// - /// Represents a brush drawing a radial gradient around a center point. - /// - public class RadialGradientBrush : AbstractBrush, IGradientBrush - { - #region Properties & Fields - - private Point _center = new(0.5, 0.5); - /// - /// Gets or sets the center (as percentage in the range [0..1]) around which the should be drawn. (default: 0.5, 0.5) - /// - public Point Center - { - get => _center; - set => SetProperty(ref _center, value); - } - - private IGradient? _gradient; - /// - public IGradient? Gradient - { - get => _gradient; - set => SetProperty(ref _gradient, value); - } - - #endregion - - #region Constructors - - /// - /// - /// Initializes a new instance of the class. - /// - public RadialGradientBrush() - { } - - /// - /// - /// Initializes a new instance of the class. - /// - /// The gradient drawn by the brush. - public RadialGradientBrush(IGradient gradient) - { - this.Gradient = gradient; - } - - /// - /// - /// Initializes a new instance of the class. - /// - /// The center point (as percentage in the range [0..1]). - /// The gradient drawn by the brush. - public RadialGradientBrush(Point center, IGradient gradient) - { - this.Center = center; - this.Gradient = gradient; - } - - #endregion - - #region Methods - - /// - protected override Color GetColorAtPoint(Rectangle rectangle, BrushRenderTarget renderTarget) - { - if (Gradient == null) return Color.Transparent; - - Point centerPoint = new(rectangle.Location.X + (rectangle.Size.Width * Center.X), rectangle.Location.Y + (rectangle.Size.Height * Center.Y)); - - // Calculate the distance to the farthest point from the center as reference (this has to be a corner) - // ReSharper disable once RedundantCast - never trust this ... - double refDistance = Math.Max(Math.Max(Math.Max(GradientHelper.CalculateDistance(rectangle.Location, centerPoint), - GradientHelper.CalculateDistance(new Point(rectangle.Location.X + rectangle.Size.Width, rectangle.Location.Y), centerPoint)), - GradientHelper.CalculateDistance(new Point(rectangle.Location.X, rectangle.Location.Y + rectangle.Size.Height), centerPoint)), - GradientHelper.CalculateDistance(new Point(rectangle.Location.X + rectangle.Size.Width, rectangle.Location.Y + rectangle.Size.Height), centerPoint)); - - double distance = GradientHelper.CalculateDistance(renderTarget.Point, centerPoint); - double offset = distance / refDistance; - return Gradient.GetColor(offset); - } - - #endregion - } -} diff --git a/RGB.NET.Brushes/RGB.NET.Brushes.csproj b/RGB.NET.Brushes/RGB.NET.Brushes.csproj deleted file mode 100644 index f17e2aa..0000000 --- a/RGB.NET.Brushes/RGB.NET.Brushes.csproj +++ /dev/null @@ -1,56 +0,0 @@ - - - net5.0 - latest - enable - - Darth Affe - Wyrez - en-US - en-US - RGB.NET.Brushes - RGB.NET.Brushes - RGB.NET.Brushes - RGB.NET.Brushes - RGB.NET.Brushes - Brushes-Presets of RGB.NET - Brushes-Presets of RGB.NET, a C# (.NET) library for accessing various RGB-peripherals - Copyright © Darth Affe 2020 - Copyright © Darth Affe 2020 - http://lib.arge.be/icon.png - https://github.com/DarthAffe/RGB.NET - https://raw.githubusercontent.com/DarthAffe/RGB.NET/master/LICENSE - Github - https://github.com/DarthAffe/RGB.NET - True - - - - 0.0.1 - 0.0.1 - 0.0.1 - - ..\bin\ - true - True - True - - - - $(DefineConstants);TRACE;DEBUG - true - full - false - - - - pdbonly - true - $(NoWarn);CS1591;CS1572;CS1573 - $(DefineConstants);RELEASE - - - - - - \ No newline at end of file diff --git a/RGB.NET.Core/ColorCorrection/IColorCorrection.cs b/RGB.NET.Core/ColorCorrection/IColorCorrection.cs index e3e417a..f738f5a 100644 --- a/RGB.NET.Core/ColorCorrection/IColorCorrection.cs +++ b/RGB.NET.Core/ColorCorrection/IColorCorrection.cs @@ -11,6 +11,6 @@ namespace RGB.NET.Core /// Applies the to the given . /// /// The to correct. - Color ApplyTo(Color color); + void ApplyTo(ref Color color); } } diff --git a/RGB.NET.Core/Decorators/IBrushDecorator.cs b/RGB.NET.Core/Decorators/IBrushDecorator.cs index 812af24..f7dca23 100644 --- a/RGB.NET.Core/Decorators/IBrushDecorator.cs +++ b/RGB.NET.Core/Decorators/IBrushDecorator.cs @@ -12,6 +12,6 @@ /// The rectangle in which the should be drawn. /// The target (key/point) from which the should be taken. /// The to be modified. - Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color); + void ManipulateColor(in Rectangle rectangle, in RenderTarget renderTarget, ref Color color); } } diff --git a/RGB.NET.Core/Devices/AbstractRGBDevice.cs b/RGB.NET.Core/Devices/AbstractRGBDevice.cs index b88a3dc..f0083c8 100644 --- a/RGB.NET.Core/Devices/AbstractRGBDevice.cs +++ b/RGB.NET.Core/Devices/AbstractRGBDevice.cs @@ -39,6 +39,9 @@ namespace RGB.NET.Core /// IRGBDeviceInfo IRGBDevice.DeviceInfo => DeviceInfo; + /// + public IList ColorCorrections { get; } = new List(); + /// /// Gets or sets if the device needs to be flushed on every update. /// diff --git a/RGB.NET.Core/Devices/IRGBDevice.cs b/RGB.NET.Core/Devices/IRGBDevice.cs index 15d607e..6a83e50 100644 --- a/RGB.NET.Core/Devices/IRGBDevice.cs +++ b/RGB.NET.Core/Devices/IRGBDevice.cs @@ -20,6 +20,8 @@ namespace RGB.NET.Core /// IRGBDeviceInfo DeviceInfo { get; } + IList ColorCorrections { get; } + #endregion #region Indexer diff --git a/RGB.NET.Core/Extensions/RectangleExtensions.cs b/RGB.NET.Core/Extensions/RectangleExtensions.cs index de09fc0..f14ccff 100644 --- a/RGB.NET.Core/Extensions/RectangleExtensions.cs +++ b/RGB.NET.Core/Extensions/RectangleExtensions.cs @@ -59,7 +59,7 @@ namespace RGB.NET.Core /// /// The intersecting rectangle. /// The percentage of intersection. - public static double CalculateIntersectPercentage(this Rectangle rect, Rectangle intersectingRect) + public static double CalculateIntersectPercentage(this Rectangle rect, in Rectangle intersectingRect) { if (rect.IsEmpty || intersectingRect.IsEmpty) return 0; @@ -72,7 +72,7 @@ namespace RGB.NET.Core /// /// The intersecting /// A new representing the intersection this and the one provided as parameter. - public static Rectangle CalculateIntersection(this Rectangle rect, Rectangle intersectingRectangle) + public static Rectangle CalculateIntersection(this Rectangle rect, in Rectangle intersectingRectangle) { double x1 = Math.Max(rect.Location.X, intersectingRectangle.Location.X); double x2 = Math.Min(rect.Location.X + rect.Size.Width, intersectingRectangle.Location.X + intersectingRectangle.Size.Width); @@ -91,7 +91,7 @@ namespace RGB.NET.Core /// /// The to test. /// true if the rectangle contains the given point; otherwise false. - public static bool Contains(this Rectangle rect, Point point) => rect.Contains(point.X, point.Y); + public static bool Contains(this Rectangle rect, in Point point) => rect.Contains(point.X, point.Y); /// /// Determines if the specified location is contained within this . @@ -107,7 +107,7 @@ namespace RGB.NET.Core /// /// The to test. /// true if the rectangle contains the given rect; otherwise false. - public static bool Contains(this Rectangle rect, Rectangle rect2) => (rect.Location.X <= rect2.Location.X) && ((rect2.Location.X + rect2.Size.Width) <= (rect.Location.X + rect.Size.Width)) + public static bool Contains(this Rectangle rect, in Rectangle rect2) => (rect.Location.X <= rect2.Location.X) && ((rect2.Location.X + rect2.Size.Width) <= (rect.Location.X + rect.Size.Width)) && (rect.Location.Y <= rect2.Location.Y) && ((rect2.Location.Y + rect2.Size.Height) <= (rect.Location.Y + rect.Size.Height)); /// @@ -116,7 +116,7 @@ namespace RGB.NET.Core /// The to move. /// The amount to move. /// The moved rectangle. - public static Rectangle Translate(this Rectangle rect, Point point) => rect.Translate(point.X, point.Y); + public static Rectangle Translate(this Rectangle rect, in Point point) => rect.Translate(point.X, point.Y); /// /// Moves the specified by the given amount. @@ -141,7 +141,7 @@ namespace RGB.NET.Core /// The rotation. /// The origin to rotate around. [0,0] if not set. /// A array of containing the new locations of the corners of the original rectangle. - public static Point[] Rotate(this Rectangle rect, Rotation rotation, Point origin = new()) + public static Point[] Rotate(this Rectangle rect, in Rotation rotation, in Point origin = new()) { Point[] points = { rect.Location, // top left diff --git a/RGB.NET.Groups/Groups/ListLedGroup.cs b/RGB.NET.Core/Groups/ListLedGroup.cs similarity index 99% rename from RGB.NET.Groups/Groups/ListLedGroup.cs rename to RGB.NET.Core/Groups/ListLedGroup.cs index 06d15b8..f4aa007 100644 --- a/RGB.NET.Groups/Groups/ListLedGroup.cs +++ b/RGB.NET.Core/Groups/ListLedGroup.cs @@ -2,9 +2,8 @@ // ReSharper disable UnusedMember.Global using System.Collections.Generic; -using RGB.NET.Core; -namespace RGB.NET.Groups +namespace RGB.NET.Core { /// /// diff --git a/RGB.NET.Core/Leds/Led.cs b/RGB.NET.Core/Leds/Led.cs index 7c39c45..33ea3da 100644 --- a/RGB.NET.Core/Leds/Led.cs +++ b/RGB.NET.Core/Leds/Led.cs @@ -151,18 +151,6 @@ namespace RGB.NET.Core OnPropertyChanged(nameof(Color)); } - /// - /// Resets the back to default. - /// - internal void Reset() - { - _color = Color.Transparent; - RequestedColor = null; - - // ReSharper disable once ExplicitCallerInfoArgument - OnPropertyChanged(nameof(Color)); - } - #endregion #region Operators diff --git a/RGB.NET.Core/Positioning/Rectangle.cs b/RGB.NET.Core/Positioning/Rectangle.cs index cbf80ab..fc94eb9 100644 --- a/RGB.NET.Core/Positioning/Rectangle.cs +++ b/RGB.NET.Core/Positioning/Rectangle.cs @@ -179,7 +179,7 @@ namespace RGB.NET.Core /// true if is a equivalent to this ; otherwise, false. public override bool Equals(object? obj) { - if (!(obj is Rectangle compareRect)) + if (obj is not Rectangle compareRect) return false; if (GetType() != compareRect.GetType()) @@ -222,6 +222,15 @@ namespace RGB.NET.Core /// true if and are not equal; otherwise, false. public static bool operator !=(Rectangle rectangle1, Rectangle rectangle2) => !(rectangle1 == rectangle2); + // DarthAffe 20.02.2021: Used for normalization + public static Rectangle operator /(Rectangle rectangle1, Rectangle rectangle2) + { + double x = rectangle1.Location.X / (rectangle2.Size.Width - rectangle2.Location.X); + double y = rectangle1.Location.Y / (rectangle2.Size.Height - rectangle2.Location.Y); + Size size = rectangle1.Size / rectangle2.Size; + return new Rectangle(new Point(x, y), size); + } + #endregion } } diff --git a/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings b/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings index 8f59663..59c26c0 100644 --- a/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings +++ b/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings @@ -17,6 +17,10 @@ True True True + True + True + True + True True True True \ No newline at end of file diff --git a/RGB.NET.Core/RGBSurface.cs b/RGB.NET.Core/RGBSurface.cs index e45f0f9..417acc5 100644 --- a/RGB.NET.Core/RGBSurface.cs +++ b/RGB.NET.Core/RGBSurface.cs @@ -201,6 +201,7 @@ namespace RGB.NET.Core /// Renders a ledgroup. /// /// The led group to render. + /// Thrown if the of the Brush is not valid. private void Render(ILedGroup ledGroup) { IList leds = ledGroup.GetLeds().ToList(); @@ -208,26 +209,30 @@ namespace RGB.NET.Core if ((brush == null) || !brush.IsEnabled) return; - switch (brush.BrushCalculationMode) + IEnumerable<(RenderTarget renderTarget, Color color)> render; + switch (brush.CalculationMode) { - case BrushCalculationMode.Relative: + case RenderMode.Relative: Rectangle brushRectangle = new(leds.Select(led => led.AbsoluteBoundary)); Point offset = new(-brushRectangle.Location.X, -brushRectangle.Location.Y); brushRectangle = brushRectangle.SetLocation(new Point(0, 0)); - brush.PerformRender(brushRectangle, leds.Select(led => new BrushRenderTarget(led, led.AbsoluteBoundary.Translate(offset)))); + render = brush.Render(brushRectangle, leds.Select(led => new RenderTarget(led, led.AbsoluteBoundary.Translate(offset)))); break; - case BrushCalculationMode.Absolute: - brush.PerformRender(Boundary, leds.Select(led => new BrushRenderTarget(led, led.AbsoluteBoundary))); + case RenderMode.Absolute: + render = brush.Render(Boundary, leds.Select(led => new RenderTarget(led, led.AbsoluteBoundary))); break; default: - throw new ArgumentException(); + throw new ArgumentException($"The CalculationMode '{brush.CalculationMode}' is not valid."); } - //brush.UpdateEffects(); - brush.PerformFinalize(); + foreach ((RenderTarget renderTarget, Color c) in render) + { + Color color = c; + foreach (IColorCorrection colorCorrection in renderTarget.Led.Device.ColorCorrections) + colorCorrection.ApplyTo(ref color); - foreach (KeyValuePair renders in brush.RenderedTargets) - renders.Key.Led.Color = renders.Value; + renderTarget.Led.Color = color; + } } /// @@ -303,7 +308,7 @@ namespace RGB.NET.Core { lock (_devices) { - if (!_devices.Contains(device)) throw new RGBSurfaceException($"The device '{device.DeviceInfo.Manufacturer} {device.DeviceInfo.Model}' isn't not attached to this surface."); + if (!_devices.Contains(device)) throw new RGBSurfaceException($"The device '{device.DeviceInfo.Manufacturer} {device.DeviceInfo.Model}' is not attached to this surface."); device.BoundaryChanged -= DeviceOnBoundaryChanged; device.Surface = null; diff --git a/RGB.NET.Core/Brushes/AbstractBrush.cs b/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs similarity index 63% rename from RGB.NET.Core/Brushes/AbstractBrush.cs rename to RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs index 541b6ac..25e29bf 100644 --- a/RGB.NET.Core/Brushes/AbstractBrush.cs +++ b/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs @@ -20,7 +20,7 @@ namespace RGB.NET.Core public bool IsEnabled { get; set; } = true; /// - public BrushCalculationMode BrushCalculationMode { get; set; } = BrushCalculationMode.Relative; + public RenderMode CalculationMode { get; set; } = RenderMode.Relative; /// public double Brightness { get; set; } @@ -28,15 +28,6 @@ namespace RGB.NET.Core /// public double Opacity { get; set; } - /// - public IList ColorCorrections { get; } = new List(); - - /// - public Rectangle RenderedRectangle { get; protected set; } - - /// - public Dictionary RenderedTargets { get; } = new(); - #endregion #region Constructors @@ -56,17 +47,14 @@ namespace RGB.NET.Core #region Methods - /// - public virtual void PerformRender(Rectangle rectangle, IEnumerable renderTargets) + public IEnumerable<(RenderTarget renderTarget, Color color)> Render(Rectangle rectangle, IEnumerable renderTargets) { - RenderedRectangle = rectangle; - RenderedTargets.Clear(); - - foreach (BrushRenderTarget renderTarget in renderTargets) + foreach (RenderTarget renderTarget in renderTargets) { Color color = GetColorAtPoint(rectangle, renderTarget); - color = ApplyDecorators(rectangle, renderTarget, color); - RenderedTargets[renderTarget] = color; + ApplyDecorators(rectangle, renderTarget, ref color); + FinalizeColor(ref color); + yield return (renderTarget, color); } } @@ -76,22 +64,12 @@ namespace RGB.NET.Core /// The rectangle in which the brush should be drawn. /// The target (key/point) from which the color should be taken. /// The to be modified. - protected virtual Color ApplyDecorators(Rectangle rectangle, BrushRenderTarget renderTarget, Color color) + protected virtual void ApplyDecorators(in Rectangle rectangle, in RenderTarget renderTarget, ref Color color) { lock (Decorators) foreach (IBrushDecorator decorator in Decorators) if (decorator.IsEnabled) - color = decorator.ManipulateColor(rectangle, renderTarget, color); - - return color; - } - - /// - public virtual void PerformFinalize() - { - List renderTargets = RenderedTargets.Keys.ToList(); - foreach (BrushRenderTarget renderTarget in renderTargets) - RenderedTargets[renderTarget] = FinalizeColor(RenderedTargets[renderTarget]); + decorator.ManipulateColor(rectangle, renderTarget, ref color); } /// @@ -100,20 +78,15 @@ namespace RGB.NET.Core /// The rectangle in which the brush should be drawn. /// The target (key/point) from which the color should be taken. /// The color at the specified point. - protected abstract Color GetColorAtPoint(Rectangle rectangle, BrushRenderTarget renderTarget); + protected abstract Color GetColorAtPoint(in Rectangle rectangle, in RenderTarget renderTarget); /// /// Finalizes the color by appliing the overall brightness and opacity.
- /// This method should always be the last call of a implementation. ///
/// The color to finalize. /// The finalized color. - protected virtual Color FinalizeColor(Color color) + protected virtual void FinalizeColor(ref Color color) { - if (ColorCorrections.Count > 0) - foreach (IColorCorrection colorCorrection in ColorCorrections) - color = 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!!! @@ -122,8 +95,6 @@ namespace RGB.NET.Core if (Opacity < 1) color = color.MultiplyA(Opacity.Clamp(0, 1)); - - return color; } #endregion diff --git a/RGB.NET.Core/Brushes/IBrush.cs b/RGB.NET.Core/Rendering/Brushes/IBrush.cs similarity index 51% rename from RGB.NET.Core/Brushes/IBrush.cs rename to RGB.NET.Core/Rendering/Brushes/IBrush.cs index 7d7f2c0..3d2f449 100644 --- a/RGB.NET.Core/Brushes/IBrush.cs +++ b/RGB.NET.Core/Rendering/Brushes/IBrush.cs @@ -19,7 +19,7 @@ namespace RGB.NET.Core /// /// Gets or sets the calculation mode used for the rectangle/points used for color-selection in brushes. /// - BrushCalculationMode BrushCalculationMode { get; set; } + RenderMode CalculationMode { get; set; } /// /// Gets or sets the overall percentage brightness of the . @@ -32,30 +32,10 @@ namespace RGB.NET.Core double Opacity { get; set; } /// - /// Gets a list of used to correct the colors of the . - /// - IList ColorCorrections { get; } - - /// - /// Gets the used in the last render pass. - /// - Rectangle RenderedRectangle { get; } - - /// - /// Gets a dictionary containing all for calculated in the last render pass. - /// - Dictionary RenderedTargets { get; } - - /// - /// Performs the render pass of the and calculates the raw for all requested . + /// Performs the render pass of the and calculates the raw for all requested . /// /// The in which the brush should be drawn. - /// The (keys/points) of which the color should be calculated. - void PerformRender(Rectangle rectangle, IEnumerable renderTargets); - - /// - /// Performs the finalize pass of the and calculates the final for all previously calculated . - /// - void PerformFinalize(); + /// The (keys/points) of which the color should be calculated. + IEnumerable<(RenderTarget renderTarget, Color color)> Render(Rectangle rectangle, IEnumerable renderTargets); } } \ No newline at end of file diff --git a/RGB.NET.Brushes/Brushes/SolidColorBrush.cs b/RGB.NET.Core/Rendering/Brushes/SolidColorBrush.cs similarity index 81% rename from RGB.NET.Brushes/Brushes/SolidColorBrush.cs rename to RGB.NET.Core/Rendering/Brushes/SolidColorBrush.cs index 8bbd68b..aaf9409 100644 --- a/RGB.NET.Brushes/Brushes/SolidColorBrush.cs +++ b/RGB.NET.Core/Rendering/Brushes/SolidColorBrush.cs @@ -1,9 +1,7 @@ // ReSharper disable MemberCanBePrivate.Global // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global -using RGB.NET.Core; - -namespace RGB.NET.Brushes +namespace RGB.NET.Core { /// /// @@ -29,9 +27,9 @@ namespace RGB.NET.Brushes /// /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The drawn by this . + /// The drawn by this . public SolidColorBrush(Color color) { this.Color = color; @@ -42,7 +40,7 @@ namespace RGB.NET.Brushes #region Methods /// - protected override Color GetColorAtPoint(Rectangle rectangle, BrushRenderTarget renderTarget) => Color; + protected override Color GetColorAtPoint(in Rectangle rectangle, in RenderTarget renderTarget) => Color; #endregion diff --git a/RGB.NET.Core/Rendering/Brushes/TextureBrush.cs b/RGB.NET.Core/Rendering/Brushes/TextureBrush.cs new file mode 100644 index 0000000..2ec8f05 --- /dev/null +++ b/RGB.NET.Core/Rendering/Brushes/TextureBrush.cs @@ -0,0 +1,35 @@ +namespace RGB.NET.Core +{ + public class TextureBrush : AbstractBrush + { + #region Properties & Fields + + private ITexture _texture = ITexture.Empty; + public ITexture Texture + { + get => _texture; + set => SetProperty(ref _texture, value); + } + + #endregion + + #region Constructors + + public TextureBrush(ITexture texture) + { + this.Texture = texture; + } + + #endregion + + #region Methods + + protected override Color GetColorAtPoint(in Rectangle rectangle, in RenderTarget renderTarget) + { + Rectangle normalizedRect = renderTarget.Rectangle / rectangle; + return Texture[normalizedRect]; + } + + #endregion + } +} diff --git a/RGB.NET.Core/Brushes/BrushCalculationMode.cs b/RGB.NET.Core/Rendering/RenderMode.cs similarity index 79% rename from RGB.NET.Core/Brushes/BrushCalculationMode.cs rename to RGB.NET.Core/Rendering/RenderMode.cs index 310f563..8908d69 100644 --- a/RGB.NET.Core/Brushes/BrushCalculationMode.cs +++ b/RGB.NET.Core/Rendering/RenderMode.cs @@ -5,7 +5,7 @@ namespace RGB.NET.Core /// /// Contains a list of all brush calculation modes. /// - public enum BrushCalculationMode + public enum RenderMode { /// /// The calculation for will be the rectangle around the the is applied to. @@ -13,7 +13,7 @@ namespace RGB.NET.Core Relative, /// - /// The calculation for will always be the rectangle completly containing all affected . + /// The calculation for will always be the whole . /// Absolute } diff --git a/RGB.NET.Core/Brushes/BrushRenderTarget.cs b/RGB.NET.Core/Rendering/RenderTarget.cs similarity index 81% rename from RGB.NET.Core/Brushes/BrushRenderTarget.cs rename to RGB.NET.Core/Rendering/RenderTarget.cs index e4934e8..4d41827 100644 --- a/RGB.NET.Core/Brushes/BrushRenderTarget.cs +++ b/RGB.NET.Core/Rendering/RenderTarget.cs @@ -6,7 +6,7 @@ namespace RGB.NET.Core /// /// Represents a single target of a brush render. /// - public class BrushRenderTarget + public readonly struct RenderTarget { #region Properties & Fields @@ -23,23 +23,21 @@ namespace RGB.NET.Core /// /// Gets the representing the position to render the target-. /// - public Point Point { get; } + public Point Point => Rectangle.Center; #endregion #region Constructors /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The target-. /// The representing the area to render the target-. - public BrushRenderTarget(Led led, Rectangle rectangle) + public RenderTarget(Led led, Rectangle rectangle) { this.Led = led; this.Rectangle = rectangle; - - this.Point = rectangle.Center; } #endregion diff --git a/RGB.NET.Core/Rendering/Textures/EmptyTexture.cs b/RGB.NET.Core/Rendering/Textures/EmptyTexture.cs new file mode 100644 index 0000000..2998eeb --- /dev/null +++ b/RGB.NET.Core/Rendering/Textures/EmptyTexture.cs @@ -0,0 +1,13 @@ +namespace RGB.NET.Core +{ + internal class EmptyTexture : ITexture + { + #region Properties & Fields + + public Size Size { get; } = new(0, 0); + public Color this[in Point point] => Color.Transparent; + public Color this[in Rectangle rectangle] => Color.Transparent; + + #endregion + } +} diff --git a/RGB.NET.Core/Rendering/Textures/ITexture.cs b/RGB.NET.Core/Rendering/Textures/ITexture.cs new file mode 100644 index 0000000..7d297e1 --- /dev/null +++ b/RGB.NET.Core/Rendering/Textures/ITexture.cs @@ -0,0 +1,12 @@ +namespace RGB.NET.Core +{ + public interface ITexture + { + static ITexture Empty => new EmptyTexture(); + + Size Size { get; } + + Color this[in Point point] { get; } + Color this[in Rectangle rectangle] { get; } + } +} diff --git a/RGB.NET.Core/Rendering/Textures/PixelTexture.cs b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs new file mode 100644 index 0000000..1f4afb6 --- /dev/null +++ b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs @@ -0,0 +1,66 @@ +using System; + +namespace RGB.NET.Core +{ + public sealed class PixelTexture : ITexture + { + #region Properties & Fields + + private readonly int _dataWidth; + private readonly int _dataHeight; + private readonly ReadOnlyMemory _data; + private readonly ISampler _sampler; + + public Size Size { get; } + + public Color this[in Point point] + { + get + { + if (_data.IsEmpty) return Color.Transparent; + + int x = (int)Math.Round(Size.Width * point.X.Clamp(0, 1)); + int y = (int)Math.Round(Size.Height * point.Y.Clamp(0, 1)); + + return _data.Span[(y * _dataWidth) + x]; + } + } + + public Color this[in Rectangle rectangle] + { + get + { + if (_data.IsEmpty) return Color.Transparent; + + int x = (int)Math.Round(Size.Width * rectangle.Location.X.Clamp(0, 1)); + int y = (int)Math.Round(Size.Height * rectangle.Location.Y.Clamp(0, 1)); + int width = (int)Math.Round(Size.Width * rectangle.Size.Width.Clamp(0, 1)); + int height = (int)Math.Round(Size.Height * rectangle.Size.Height.Clamp(0, 1)); + + return _sampler.SampleColor(in _data, x, y, width, height); + } + } + + #endregion + + #region Constructors + + public PixelTexture(int with, int height, ReadOnlyMemory data) + : this(with, height, data, new AverageSampler()) + { } + + public PixelTexture(int with, int height, ReadOnlyMemory data, ISampler sampler) + { + this._data = data; + this._dataWidth = with; + this._dataHeight = height; + this._sampler = sampler; + + if (_data.Length != (with * height)) throw new ArgumentException($"Data-Length {_data.Length} differs from the given size {with}x{height} ({with * height})."); + + Size = new Size(with, height); + } + + #endregion + } +} diff --git a/RGB.NET.Core/Rendering/Textures/Sampler/AverageSampler.cs b/RGB.NET.Core/Rendering/Textures/Sampler/AverageSampler.cs new file mode 100644 index 0000000..92670da --- /dev/null +++ b/RGB.NET.Core/Rendering/Textures/Sampler/AverageSampler.cs @@ -0,0 +1,77 @@ +using System; + +namespace RGB.NET.Core +{ + public class AverageSampler : ISampler + { + #region Properties & Fields + + private Func, int, int, int, int, Color> _sampleMethod = SampleWithoutAlpha; + + private bool _sampleAlpha; + public bool SampleAlpha + { + get => _sampleAlpha; + set + { + _sampleAlpha = value; + _sampleMethod = value ? SampleWithAlpha : SampleWithoutAlpha; + } + } + + #endregion + + #region Methods + + public Color SampleColor(in ReadOnlyMemory data, int x, int y, int width, int height) => _sampleMethod(data, x, y, width, height); + + private static Color SampleWithAlpha(ReadOnlyMemory data, int x, int y, int width, int height) + { + ReadOnlySpan span = data.Span; + + int maxY = y + height; + int count = width * height; + double a = 0, r = 0, g = 0, b = 0; + for (int yPos = y; yPos < maxY; yPos++) + { + ReadOnlySpan line = span.Slice((yPos * width) + x, width); + foreach (Color color in line) + { + a += color.A; + r += color.R; + g += color.G; + b += color.B; + } + } + + if (count == 0) return Color.Transparent; + + return new Color(a / count, r / count, g / count, b / count); + } + + private static Color SampleWithoutAlpha(ReadOnlyMemory data, int x, int y, int width, int height) + { + ReadOnlySpan span = data.Span; + + int maxY = y + height; + int count = width * height; + double r = 0, g = 0, b = 0; + for (int yPos = y; yPos < maxY; yPos++) + { + ReadOnlySpan line = span.Slice((yPos * width) + x, width); + foreach (Color color in line) + { + r += color.R; + g += color.G; + b += color.B; + } + } + + if (count == 0) return Color.Transparent; + + return new Color(r / count, g / count, b / count); + } + + #endregion + } +} diff --git a/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs b/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs new file mode 100644 index 0000000..fd2ea52 --- /dev/null +++ b/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs @@ -0,0 +1,9 @@ +using System; + +namespace RGB.NET.Core +{ + public interface ISampler + { + Color SampleColor(in ReadOnlyMemory data, int x, int y, int width, int height); + } +} diff --git a/RGB.NET.Core/Update/ManualUpdateTrigger.cs b/RGB.NET.Core/Update/ManualUpdateTrigger.cs new file mode 100644 index 0000000..27d18da --- /dev/null +++ b/RGB.NET.Core/Update/ManualUpdateTrigger.cs @@ -0,0 +1,94 @@ +// ReSharper disable MemberCanBePrivate.Global + +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; + +namespace RGB.NET.Core +{ + /// + /// + /// Represents an + /// + public sealed class ManualUpdateTrigger : AbstractUpdateTrigger + { + #region Properties & Fields + + private AutoResetEvent _mutex = new(false); + private Task? UpdateTask { get; set; } + private CancellationTokenSource? UpdateTokenSource { get; set; } + private CancellationToken UpdateToken { get; set; } + + /// + /// Gets the time it took the last update-loop cycle to run. + /// + public double LastUpdateTime { get; private set; } + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// A value indicating if the trigger should automatically right after construction. + public ManualUpdateTrigger() + { + Start(); + } + + #endregion + + #region Methods + + /// + /// Starts the trigger if needed, causing it to performing updates. + /// + private void Start() + { + if (UpdateTask == null) + { + UpdateTokenSource?.Dispose(); + UpdateTokenSource = new CancellationTokenSource(); + UpdateTask = Task.Factory.StartNew(UpdateLoop, (UpdateToken = UpdateTokenSource.Token), TaskCreationOptions.LongRunning, TaskScheduler.Default); + } + } + + /// + /// Stops the trigger if running, causing it to stop performing updates. + /// + private void Stop() + { + if (UpdateTask != null) + { + UpdateTokenSource?.Cancel(); + // ReSharper disable once MethodSupportsCancellation + UpdateTask.Wait(); + UpdateTask.Dispose(); + UpdateTask = null; + } + } + + public void TriggerUpdate() => _mutex.Set(); + + private void UpdateLoop() + { + OnStartup(); + + while (!UpdateToken.IsCancellationRequested) + { + if (_mutex.WaitOne(100)) + { + long preUpdateTicks = Stopwatch.GetTimestamp(); + OnUpdate(); + LastUpdateTime = ((Stopwatch.GetTimestamp() - preUpdateTicks) / 10000.0); + } + } + } + + /// + public override void Dispose() => Stop(); + + #endregion + } +} diff --git a/RGB.NET.Decorators/RGB.NET.Decorators.csproj b/RGB.NET.Decorators/RGB.NET.Decorators.csproj deleted file mode 100644 index f87a519..0000000 --- a/RGB.NET.Decorators/RGB.NET.Decorators.csproj +++ /dev/null @@ -1,57 +0,0 @@ - - - net5.0 - latest - enable - - Darth Affe - Wyrez - en-US - en-US - RGB.NET.Decorators - RGB.NET.Decorators - RGB.NET.Decorators - RGB.NET.Decorators - RGB.NET.Decorators - Decorators-Presets of RGB.NET - Decorators-Presets of RGB.NET, a C# (.NET) library for accessing various RGB-peripherals - Copyright © Darth Affe 2020 - Copyright © Darth Affe 2020 - http://lib.arge.be/icon.png - https://github.com/DarthAffe/RGB.NET - https://raw.githubusercontent.com/DarthAffe/RGB.NET/master/LICENSE - Github - https://github.com/DarthAffe/RGB.NET - True - - - - 0.0.1 - 0.0.1 - 0.0.1 - - ..\bin\ - true - True - True - - - - $(DefineConstants);TRACE;DEBUG - true - full - false - - - - pdbonly - true - $(NoWarn);CS1591;CS1572;CS1573 - $(DefineConstants);RELEASE - - - - - - - \ No newline at end of file diff --git a/RGB.NET.Groups/RGB.NET.Groups.csproj.DotSettings b/RGB.NET.Groups/RGB.NET.Groups.csproj.DotSettings deleted file mode 100644 index b248500..0000000 --- a/RGB.NET.Groups/RGB.NET.Groups.csproj.DotSettings +++ /dev/null @@ -1,3 +0,0 @@ - - True - True \ No newline at end of file diff --git a/RGB.NET.Decorators/Brush/FlashDecorator.cs b/RGB.NET.Presets/Decorators/FlashDecorator.cs similarity index 97% rename from RGB.NET.Decorators/Brush/FlashDecorator.cs rename to RGB.NET.Presets/Decorators/FlashDecorator.cs index 5900851..6bb03ab 100644 --- a/RGB.NET.Decorators/Brush/FlashDecorator.cs +++ b/RGB.NET.Presets/Decorators/FlashDecorator.cs @@ -5,7 +5,7 @@ using System; using RGB.NET.Core; -namespace RGB.NET.Decorators.Brush +namespace RGB.NET.Presets.Decorators { /// /// @@ -85,7 +85,7 @@ namespace RGB.NET.Decorators.Brush #region Methods /// - public Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color) => color.SetA(_currentValue); + public void ManipulateColor(in Rectangle rectangle, in RenderTarget renderTarget, ref Color color) => color = color.SetA(_currentValue); /// protected override void Update(double deltaTime) diff --git a/RGB.NET.Brushes/Decorators/IGradientDecorator.cs b/RGB.NET.Presets/Decorators/IGradientDecorator.cs similarity index 73% rename from RGB.NET.Brushes/Decorators/IGradientDecorator.cs rename to RGB.NET.Presets/Decorators/IGradientDecorator.cs index 86c07de..6f57696 100644 --- a/RGB.NET.Brushes/Decorators/IGradientDecorator.cs +++ b/RGB.NET.Presets/Decorators/IGradientDecorator.cs @@ -1,10 +1,10 @@ using RGB.NET.Core; -namespace RGB.NET.Brushes +namespace RGB.NET.Presets.Decorators { /// /// - /// Represents a basic decorator decorating a . + /// Represents a basic decorator decorating a . /// public interface IGradientDecorator : IDecorator { } diff --git a/RGB.NET.Decorators/Gradient/MoveGradientDecorator.cs b/RGB.NET.Presets/Decorators/MoveGradientDecorator.cs similarity index 84% rename from RGB.NET.Decorators/Gradient/MoveGradientDecorator.cs rename to RGB.NET.Presets/Decorators/MoveGradientDecorator.cs index 52a679b..68a0ef7 100644 --- a/RGB.NET.Decorators/Gradient/MoveGradientDecorator.cs +++ b/RGB.NET.Presets/Decorators/MoveGradientDecorator.cs @@ -1,13 +1,12 @@ -using RGB.NET.Brushes; -using RGB.NET.Brushes.Gradients; -using RGB.NET.Core; +using RGB.NET.Core; +using RGB.NET.Presets.Textures.Gradients; -namespace RGB.NET.Decorators.Gradient +namespace RGB.NET.Presets.Decorators { /// /// /// - /// Represents a decorator which allows to move an by modifying his offset. + /// Represents a decorator which allows to move an by modifying his offset. /// public class MoveGradientDecorator : AbstractUpdateAwareDecorator, IGradientDecorator { @@ -37,13 +36,13 @@ namespace RGB.NET.Decorators.Gradient /// /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The speed of the movement in units per second. - /// The meaning of units differs for the different but 360 units will always be one complete cycle: - /// : 360 unit = 1 offset. - /// : 1 unit = 1 degree. - /// The direction the is moved. + /// The meaning of units differs for the different but 360 units will always be one complete cycle: + /// : 360 unit = 1 offset. + /// : 1 unit = 1 degree. + /// The direction the is moved. /// True leads to an offset-increment (normaly moving to the right), false to an offset-decrement (normaly moving to the left). public MoveGradientDecorator(RGBSurface surface, double speed = 180.0, bool direction = true) : base(surface) diff --git a/RGB.NET.Groups/Extensions/LedGroupExtension.cs b/RGB.NET.Presets/Groups/Extensions/LedGroupExtension.cs similarity index 98% rename from RGB.NET.Groups/Extensions/LedGroupExtension.cs rename to RGB.NET.Presets/Groups/Extensions/LedGroupExtension.cs index 4391131..c9f2677 100644 --- a/RGB.NET.Groups/Extensions/LedGroupExtension.cs +++ b/RGB.NET.Presets/Groups/Extensions/LedGroupExtension.cs @@ -3,7 +3,7 @@ using RGB.NET.Core; -namespace RGB.NET.Groups +namespace RGB.NET.Presets.Groups { /// /// Offers some extensions and helper-methods for related things. diff --git a/RGB.NET.Groups/Groups/RectangleLedGroup.cs b/RGB.NET.Presets/Groups/RectangleLedGroup.cs similarity index 93% rename from RGB.NET.Groups/Groups/RectangleLedGroup.cs rename to RGB.NET.Presets/Groups/RectangleLedGroup.cs index e6c2ae7..b024405 100644 --- a/RGB.NET.Groups/Groups/RectangleLedGroup.cs +++ b/RGB.NET.Presets/Groups/RectangleLedGroup.cs @@ -6,11 +6,11 @@ using System.Collections.Generic; using System.Linq; using RGB.NET.Core; -namespace RGB.NET.Groups +namespace RGB.NET.Presets.Groups { /// /// - /// Represents a containing which physically lay inside a . + /// Represents a containing which physically lay inside a . /// public class RectangleLedGroup : AbstractLedGroup { @@ -114,9 +114,9 @@ namespace RGB.NET.Groups /// /// - /// Gets a list containing all of this . + /// Gets a list containing all of this . /// - /// The list containing all of this . + /// The list containing all of this . public override IList GetLeds() => _ledCache ??= (Surface?.Leds.Where(led => led.AbsoluteBoundary.CalculateIntersectPercentage(Rectangle) >= MinOverlayPercentage).ToList() ?? new List()); private void InvalidateCache() => _ledCache = null; diff --git a/RGB.NET.Brushes/Helper/GradientHelper.cs b/RGB.NET.Presets/Helper/GradientHelper.cs similarity index 76% rename from RGB.NET.Brushes/Helper/GradientHelper.cs rename to RGB.NET.Presets/Helper/GradientHelper.cs index b350af4..32a10c3 100644 --- a/RGB.NET.Brushes/Helper/GradientHelper.cs +++ b/RGB.NET.Presets/Helper/GradientHelper.cs @@ -3,7 +3,7 @@ using System; using RGB.NET.Core; -namespace RGB.NET.Brushes.Helper +namespace RGB.NET.Presets.Helper { /// /// Offers some extensions and helper-methods for gradient related things. @@ -20,13 +20,13 @@ namespace RGB.NET.Brushes.Helper /// The end of the gradient. /// The on the gradient to which the offset is calculated. /// The offset of the on the gradient. - public static double CalculateLinearGradientOffset(Point startPoint, Point endPoint, Point point) + public static double CalculateLinearGradientOffset(in Point startPoint, in Point endPoint, in Point point) { Point intersectingPoint; - if (startPoint.Y.Equals(endPoint.Y)) // Horizontal case + if (startPoint.Y.EqualsInTolerance(endPoint.Y)) // Horizontal case intersectingPoint = new Point(point.X, startPoint.Y); - else if (startPoint.X.Equals(endPoint.X)) // Vertical case + else if (startPoint.X.EqualsInTolerance(endPoint.X)) // Vertical case intersectingPoint = new Point(startPoint.X, point.Y); else // Diagonal case @@ -57,15 +57,15 @@ namespace RGB.NET.Brushes.Helper /// The origin of the vector. /// The direction of the vector. /// The signed magnitude of a on a vector. - public static double CalculateDistance(Point point, Point origin, Point direction) + public static double CalculateDistance(in Point point, in Point origin, in Point direction) { double distance = CalculateDistance(point, origin); - 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; + return (((point.Y < origin.Y) && (direction.Y > origin.Y)) + || ((point.Y > origin.Y) && (direction.Y < origin.Y)) + || ((point.Y.EqualsInTolerance(origin.Y)) && (point.X < origin.X) && (direction.X > origin.X)) + || ((point.Y.EqualsInTolerance(origin.Y)) && (point.X > origin.X) && (direction.X < origin.X))) + ? -distance : distance; } /// @@ -74,7 +74,12 @@ namespace RGB.NET.Brushes.Helper /// The first . /// The second . /// The distance between the two . - public static double CalculateDistance(Point point1, Point point2) => Math.Sqrt(((point1.Y - point2.Y) * (point1.Y - point2.Y)) + ((point1.X - point2.X) * (point1.X - point2.X))); + public static double CalculateDistance(in Point point1, in Point point2) + { + double x = point1.X - point2.X; + double y = point1.Y - point2.Y; + return Math.Sqrt((y * y) + (x * x)); + } #endregion } diff --git a/RGB.NET.Groups/RGB.NET.Groups.csproj b/RGB.NET.Presets/RGB.NET.Presets.csproj similarity index 82% rename from RGB.NET.Groups/RGB.NET.Groups.csproj rename to RGB.NET.Presets/RGB.NET.Presets.csproj index a0251a2..4740b83 100644 --- a/RGB.NET.Groups/RGB.NET.Groups.csproj +++ b/RGB.NET.Presets/RGB.NET.Presets.csproj @@ -8,13 +8,13 @@ Wyrez en-US en-US - RGB.NET.Groups - RGB.NET.Groups - RGB.NET.Groups - RGB.NET.Groups - RGB.NET.Groups - Group-Presets of RGB.NET - Group-Presets of RGB.NET, a C# (.NET) library for accessing various RGB-peripherals + RGB.NET.Presets + RGB.NET.Presets + RGB.NET.Presets + RGB.NET.Presets + RGB.NET.Presets + Presets-Presets of RGB.NET + Presets for RGB.NET, a C# (.NET) library for accessing various RGB-peripherals Copyright © Darth Affe 2020 Copyright © Darth Affe 2020 http://lib.arge.be/icon.png diff --git a/RGB.NET.Brushes/RGB.NET.Brushes.csproj.DotSettings b/RGB.NET.Presets/RGB.NET.Presets.csproj.DotSettings similarity index 57% rename from RGB.NET.Brushes/RGB.NET.Brushes.csproj.DotSettings rename to RGB.NET.Presets/RGB.NET.Presets.csproj.DotSettings index c25ceff..5cecdd9 100644 --- a/RGB.NET.Brushes/RGB.NET.Brushes.csproj.DotSettings +++ b/RGB.NET.Presets/RGB.NET.Presets.csproj.DotSettings @@ -1,3 +1,4 @@  - True - True \ No newline at end of file + False + False + True \ No newline at end of file diff --git a/RGB.NET.Presets/Textures/AbstractGradientTexture.cs b/RGB.NET.Presets/Textures/AbstractGradientTexture.cs new file mode 100644 index 0000000..a724871 --- /dev/null +++ b/RGB.NET.Presets/Textures/AbstractGradientTexture.cs @@ -0,0 +1,42 @@ +using RGB.NET.Core; +using RGB.NET.Presets.Textures.Gradients; + +namespace RGB.NET.Presets.Textures +{ + public abstract class AbstractGradientTexture : AbstractBindable, ITexture + { + #region Properties & Fields + + /// + /// Gets the gradient drawn by the brush. + /// + public IGradient Gradient { get; } + + /// + public Size Size { get; } + + /// + public Color this[in Point point] => GetColor(point); + + /// + public Color this[in Rectangle rectangle] => GetColor(rectangle.Center); + + #endregion + + #region Constructors + + protected AbstractGradientTexture(Size size, IGradient gradient) + { + this.Size = size; + this.Gradient = gradient; + } + + #endregion + + #region Methods + + protected abstract Color GetColor(in Point point); + + #endregion + } +} diff --git a/RGB.NET.Presets/Textures/ConicalGradientTexture.cs b/RGB.NET.Presets/Textures/ConicalGradientTexture.cs new file mode 100644 index 0000000..4b824a2 --- /dev/null +++ b/RGB.NET.Presets/Textures/ConicalGradientTexture.cs @@ -0,0 +1,98 @@ +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable MemberCanBeProtected.Global +// ReSharper disable ReturnTypeCanBeEnumerable.Global +// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global +// ReSharper disable UnusedMember.Global + +using System; +using RGB.NET.Core; +using RGB.NET.Presets.Textures.Gradients; + +namespace RGB.NET.Presets.Textures +{ + /// + /// + /// Represents a brush drawing a conical gradient. + /// + public sealed class ConicalGradientTexture : AbstractGradientTexture + { + #region Constants + + private const double PI2 = Math.PI * 2; + + #endregion + + #region Properties & Fields + + private double _origin = Math.Atan2(-1, 0); + /// + /// Gets or sets the origin (radian-angle) this is drawn to. (default: -π/2) + /// + public double Origin + { + get => _origin; + set => SetProperty(ref _origin, value); + } + + private Point _center = new(0.5, 0.5); + /// + /// Gets or sets the center (as percentage in the range [0..1]) of the drawn by this . (default: 0.5, 0.5) + /// + public Point Center + { + get => _center; + set => SetProperty(ref _center, value); + } + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The drawn by this . + public ConicalGradientTexture(Size size, IGradient gradient) + : base(size, gradient) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The center (as percentage in the range [0..1]). + /// The drawn by this . + public ConicalGradientTexture(Size size, IGradient gradient, Point center) + : base(size, gradient) + { + this.Center = center; + } + + /// + /// Initializes a new instance of the class. + /// + /// The center (as percentage in the range [0..1]). + /// The origin (radian-angle) the is drawn to. + /// The drawn by this . + public ConicalGradientTexture(Size size, IGradient gradient, Point center, float origin) + : base(size, gradient) + { + this.Center = center; + this.Origin = origin; + } + + #endregion + + #region Methods + + protected override Color GetColor(in Point point) + { + double angle = Math.Atan2(point.Y - Center.Y, point.X - Center.X) - Origin; + if (angle < 0) angle += PI2; + double offset = angle / PI2; + + return Gradient.GetColor(offset); + } + + #endregion + } +} diff --git a/RGB.NET.Brushes/Gradients/AbstractGradient.cs b/RGB.NET.Presets/Textures/Gradients/AbstractGradient.cs similarity index 93% rename from RGB.NET.Brushes/Gradients/AbstractGradient.cs rename to RGB.NET.Presets/Textures/Gradients/AbstractGradient.cs index 2a6350b..5271754 100644 --- a/RGB.NET.Brushes/Gradients/AbstractGradient.cs +++ b/RGB.NET.Presets/Textures/Gradients/AbstractGradient.cs @@ -8,8 +8,9 @@ using System.Collections.Specialized; using System.ComponentModel; using System.Linq; using RGB.NET.Core; +using RGB.NET.Presets.Decorators; -namespace RGB.NET.Brushes.Gradients +namespace RGB.NET.Presets.Textures.Gradients { /// /// @@ -97,11 +98,11 @@ namespace RGB.NET.Brushes.Gradients /// protected double ClipOffset(double offset) { - double max = GradientStops.Max(n => n.Offset); + double max = GradientStops.Max(stop => stop.Offset); if (offset > max) return max; - double min = GradientStops.Min(n => n.Offset); + double min = GradientStops.Min(stop => stop.Offset); return offset < min ? min : offset; } @@ -116,11 +117,11 @@ namespace RGB.NET.Brushes.Gradients foreach (GradientStop gradientStop in GradientStops) gradientStop.Offset += offset; - while (GradientStops.All(x => x.Offset > 1)) + while (GradientStops.All(stop => stop.Offset > 1)) foreach (GradientStop gradientStop in GradientStops) gradientStop.Offset -= 1; - while (GradientStops.All(x => x.Offset < 0)) + while (GradientStops.All(stop => stop.Offset < 0)) foreach (GradientStop gradientStop in GradientStops) gradientStop.Offset += 1; } diff --git a/RGB.NET.Brushes/Gradients/GradientStop.cs b/RGB.NET.Presets/Textures/Gradients/GradientStop.cs similarity index 97% rename from RGB.NET.Brushes/Gradients/GradientStop.cs rename to RGB.NET.Presets/Textures/Gradients/GradientStop.cs index 3cb4597..7626bcb 100644 --- a/RGB.NET.Brushes/Gradients/GradientStop.cs +++ b/RGB.NET.Presets/Textures/Gradients/GradientStop.cs @@ -3,7 +3,7 @@ using RGB.NET.Core; -namespace RGB.NET.Brushes.Gradients +namespace RGB.NET.Presets.Textures.Gradients { /// /// Represents a stop on a gradient. diff --git a/RGB.NET.Brushes/Gradients/IGradient.cs b/RGB.NET.Presets/Textures/Gradients/IGradient.cs similarity index 92% rename from RGB.NET.Brushes/Gradients/IGradient.cs rename to RGB.NET.Presets/Textures/Gradients/IGradient.cs index 590ba4c..58824da 100644 --- a/RGB.NET.Brushes/Gradients/IGradient.cs +++ b/RGB.NET.Presets/Textures/Gradients/IGradient.cs @@ -1,9 +1,9 @@ using System; using RGB.NET.Core; +using RGB.NET.Presets.Decorators; -namespace RGB.NET.Brushes.Gradients +namespace RGB.NET.Presets.Textures.Gradients { - /// /// /// Represents a basic gradient. /// diff --git a/RGB.NET.Brushes/Gradients/LinearGradient.cs b/RGB.NET.Presets/Textures/Gradients/LinearGradient.cs similarity index 94% rename from RGB.NET.Brushes/Gradients/LinearGradient.cs rename to RGB.NET.Presets/Textures/Gradients/LinearGradient.cs index f22ec24..716f579 100644 --- a/RGB.NET.Brushes/Gradients/LinearGradient.cs +++ b/RGB.NET.Presets/Textures/Gradients/LinearGradient.cs @@ -5,7 +5,7 @@ using System.ComponentModel; using System.Linq; using RGB.NET.Core; -namespace RGB.NET.Brushes.Gradients +namespace RGB.NET.Presets.Textures.Gradients { /// /// @@ -24,7 +24,7 @@ namespace RGB.NET.Brushes.Gradients /// /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public LinearGradient() { @@ -33,7 +33,7 @@ namespace RGB.NET.Brushes.Gradients /// /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The stops with which the gradient should be initialized. public LinearGradient(params GradientStop[] gradientStops) @@ -44,9 +44,9 @@ namespace RGB.NET.Brushes.Gradients /// /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// Specifies whether the gradient should wrapp or not (see for an example of what this means). + /// Specifies whether the gradient should wrapp or not (see for an example of what this means). /// The stops with which the gradient should be initialized. public LinearGradient(bool wrapGradient, params GradientStop[] gradientStops) : base(wrapGradient, gradientStops) diff --git a/RGB.NET.Brushes/Gradients/RainbowGradient.cs b/RGB.NET.Presets/Textures/Gradients/RainbowGradient.cs similarity index 97% rename from RGB.NET.Brushes/Gradients/RainbowGradient.cs rename to RGB.NET.Presets/Textures/Gradients/RainbowGradient.cs index 2c5c2b6..90c867e 100644 --- a/RGB.NET.Brushes/Gradients/RainbowGradient.cs +++ b/RGB.NET.Presets/Textures/Gradients/RainbowGradient.cs @@ -3,8 +3,9 @@ using System; using RGB.NET.Core; +using RGB.NET.Presets.Decorators; -namespace RGB.NET.Brushes.Gradients +namespace RGB.NET.Presets.Textures.Gradients { /// /// diff --git a/RGB.NET.Presets/Textures/LinearGradientTexture.cs b/RGB.NET.Presets/Textures/LinearGradientTexture.cs new file mode 100644 index 0000000..ae82546 --- /dev/null +++ b/RGB.NET.Presets/Textures/LinearGradientTexture.cs @@ -0,0 +1,79 @@ +// ReSharper disable CollectionNeverUpdated.Global +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable MemberCanBeProtected.Global +// ReSharper disable ReturnTypeCanBeEnumerable.Global +// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global +// ReSharper disable UnusedMember.Global + +using RGB.NET.Core; +using RGB.NET.Presets.Helper; +using RGB.NET.Presets.Textures.Gradients; + +namespace RGB.NET.Presets.Textures +{ + /// + /// + /// Represents a brush drawing a linear gradient. + /// + public sealed class LinearGradientTexture : AbstractGradientTexture + { + #region Properties & Fields + + private Point _startPoint = new(0, 0.5); + /// + /// Gets or sets the start (as percentage in the range [0..1]) of the drawn by this . (default: 0.0, 0.5) + /// + public Point StartPoint + { + get => _startPoint; + set => SetProperty(ref _startPoint, value); + } + + private Point _endPoint = new(1, 0.5); + /// + /// Gets or sets the end (as percentage in the range [0..1]) of the drawn by this . (default: 1.0, 0.5) + /// + public Point EndPoint + { + get => _endPoint; + set => SetProperty(ref _endPoint, value); + } + + #endregion + + #region Constructor + + /// + /// Initializes a new instance of the class. + /// + /// The drawn by this . + public LinearGradientTexture(Size size, IGradient gradient) + : base(size, gradient) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The start (as percentage in the range [0..1]). + /// The end (as percentage in the range [0..1]). + /// The drawn by this . + public LinearGradientTexture(Size size, IGradient gradient, Point startPoint, Point endPoint) + : base(size, gradient) + { + this.StartPoint = startPoint; + this.EndPoint = endPoint; + } + + #endregion + + #region Methods + + protected override Color GetColor(in Point point) + { + double offset = GradientHelper.CalculateLinearGradientOffset(StartPoint, EndPoint, point); + return Gradient.GetColor(offset); + } + + #endregion + } +} diff --git a/RGB.NET.Presets/Textures/RadialGradientTexture.cs b/RGB.NET.Presets/Textures/RadialGradientTexture.cs new file mode 100644 index 0000000..0e335a9 --- /dev/null +++ b/RGB.NET.Presets/Textures/RadialGradientTexture.cs @@ -0,0 +1,78 @@ +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global +// ReSharper disable UnusedMember.Global + +using RGB.NET.Core; +using RGB.NET.Presets.Helper; +using RGB.NET.Presets.Textures.Gradients; + +namespace RGB.NET.Presets.Textures +{ + /// + /// + /// Represents a brush drawing a radial gradient around a center point. + /// + public sealed class RadialGradientTexture : AbstractGradientTexture + { + #region Properties & Fields + + private double _referenceDistance = GradientHelper.CalculateDistance(new Point(0.5, 0.5), new Point(0, 0)); + + private Point _center = new(0.5, 0.5); + /// + /// Gets or sets the center (as percentage in the range [0..1]) around which the should be drawn. (default: 0.5, 0.5) + /// + public Point Center + { + get => _center; + set + { + if (SetProperty(ref _center, value)) + CalculateReferenceDistance(); + } + } + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The gradient drawn by the brush. + public RadialGradientTexture(Size size, IGradient gradient) + : base(size, gradient) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The center point (as percentage in the range [0..1]). + /// The gradient drawn by the brush. + public RadialGradientTexture(Size size, IGradient gradient, Point center) + : base(size, gradient) + { + this.Center = center; + } + + #endregion + + #region Methods + + private void CalculateReferenceDistance() + { + double referenceX = Center.X < 0.5 ? 1 : 0; + double referenceY = Center.Y < 0.5 ? 1 : 0; + _referenceDistance = GradientHelper.CalculateDistance(new Point(referenceX, referenceY), Center); + } + + protected override Color GetColor(in Point point) + { + double distance = GradientHelper.CalculateDistance(point, Center); + double offset = distance / _referenceDistance; + return Gradient.GetColor(offset); + } + + #endregion + } +} diff --git a/RGB.NET.sln b/RGB.NET.sln index 7a1fb70..c9ec688 100644 --- a/RGB.NET.sln +++ b/RGB.NET.sln @@ -5,8 +5,6 @@ VisualStudioVersion = 16.0.29424.173 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Devices", "Devices", "{D13032C6-432E-4F43-8A32-071133C22B16}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Presets", "Presets", "{EBC33090-8494-4DF4-B4B6-64D0E531E93F}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Core", "RGB.NET.Core\RGB.NET.Core.csproj", "{F3ED5768-7251-4347-8D8F-2866313DA658}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Devices.CoolerMaster", "RGB.NET.Devices.CoolerMaster\RGB.NET.Devices.CoolerMaster.csproj", "{E8F927F5-E7CF-464A-B9AE-824C2B29A7D1}" @@ -25,11 +23,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Devices.Novation", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Devices.Razer", "RGB.NET.Devices.Razer\RGB.NET.Devices.Razer.csproj", "{2E162CB7-2C6C-4069-8356-06162F7BE0AA}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Brushes", "RGB.NET.Brushes\RGB.NET.Brushes.csproj", "{B159FB51-5939-490E-A1BA-FB55D4D7ADDF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Decorators", "RGB.NET.Decorators\RGB.NET.Decorators.csproj", "{8725C448-818C-41F7-B23F-F97E062BF233}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Groups", "RGB.NET.Groups\RGB.NET.Groups.csproj", "{6FEBDC9E-909D-4EE2-B003-EDFBEF5FFF40}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Presets", "RGB.NET.Presets\RGB.NET.Presets.csproj", "{B159FB51-5939-490E-A1BA-FB55D4D7ADDF}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Devices.WS281X", "RGB.NET.Devices.WS281X\RGB.NET.Devices.WS281X.csproj", "{0AD382DA-E999-4F74-9658-8D402EE9BF3F}" EndProject @@ -91,14 +85,6 @@ Global {B159FB51-5939-490E-A1BA-FB55D4D7ADDF}.Debug|Any CPU.Build.0 = Debug|Any CPU {B159FB51-5939-490E-A1BA-FB55D4D7ADDF}.Release|Any CPU.ActiveCfg = Release|Any CPU {B159FB51-5939-490E-A1BA-FB55D4D7ADDF}.Release|Any CPU.Build.0 = Release|Any CPU - {8725C448-818C-41F7-B23F-F97E062BF233}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8725C448-818C-41F7-B23F-F97E062BF233}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8725C448-818C-41F7-B23F-F97E062BF233}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8725C448-818C-41F7-B23F-F97E062BF233}.Release|Any CPU.Build.0 = Release|Any CPU - {6FEBDC9E-909D-4EE2-B003-EDFBEF5FFF40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6FEBDC9E-909D-4EE2-B003-EDFBEF5FFF40}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6FEBDC9E-909D-4EE2-B003-EDFBEF5FFF40}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6FEBDC9E-909D-4EE2-B003-EDFBEF5FFF40}.Release|Any CPU.Build.0 = Release|Any CPU {0AD382DA-E999-4F74-9658-8D402EE9BF3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0AD382DA-E999-4F74-9658-8D402EE9BF3F}.Debug|Any CPU.Build.0 = Debug|Any CPU {0AD382DA-E999-4F74-9658-8D402EE9BF3F}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -136,9 +122,6 @@ Global {00BA7E8E-822A-42DA-9EB4-DDBBC7CB0E46} = {D13032C6-432E-4F43-8A32-071133C22B16} {19F701FD-5577-4873-9BE6-6775676FA185} = {D13032C6-432E-4F43-8A32-071133C22B16} {2E162CB7-2C6C-4069-8356-06162F7BE0AA} = {D13032C6-432E-4F43-8A32-071133C22B16} - {B159FB51-5939-490E-A1BA-FB55D4D7ADDF} = {EBC33090-8494-4DF4-B4B6-64D0E531E93F} - {8725C448-818C-41F7-B23F-F97E062BF233} = {EBC33090-8494-4DF4-B4B6-64D0E531E93F} - {6FEBDC9E-909D-4EE2-B003-EDFBEF5FFF40} = {EBC33090-8494-4DF4-B4B6-64D0E531E93F} {0AD382DA-E999-4F74-9658-8D402EE9BF3F} = {D13032C6-432E-4F43-8A32-071133C22B16} {FFDE4387-60F2-47B6-9704-3A57D02B8C64} = {D13032C6-432E-4F43-8A32-071133C22B16} {A3FD5AD7-040A-47CA-A278-53493A25FF8A} = {92D7C263-D4C9-4D26-93E2-93C1F9C2CD16} From b328032df07cc975bd0c0bd3ce599cc68cbcf045 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Mon, 22 Feb 2021 00:46:18 +0100 Subject: [PATCH 02/22] Changed everything to use floats instead of doubles --- .../Color/Behaviors/DefaultColorBehavior.cs | 10 +- RGB.NET.Core/Color/Color.cs | 26 ++-- RGB.NET.Core/Color/HSVColor.cs | 74 ++++----- RGB.NET.Core/Color/RGBColor.cs | 22 +-- RGB.NET.Core/Extensions/MathExtensions.cs | 24 +-- RGB.NET.Core/Extensions/PointExtensions.cs | 6 +- .../Extensions/RectangleExtensions.cs | 26 ++-- RGB.NET.Core/Positioning/Point.cs | 12 +- RGB.NET.Core/Positioning/Rectangle.cs | 38 ++--- RGB.NET.Core/Positioning/Rotation.cs | 36 ++--- RGB.NET.Core/Positioning/Scale.cs | 22 +-- RGB.NET.Core/Positioning/Size.cs | 22 +-- RGB.NET.Core/RGBSurface.cs | 2 +- .../Rendering/Brushes/AbstractBrush.cs | 6 +- RGB.NET.Core/Rendering/Brushes/IBrush.cs | 4 +- .../Textures/Sampler/AverageSampler.cs | 63 ++------ .../Rendering/Textures/Sampler/ISampler.cs | 8 +- .../Helper/NativeExtensions.cs | 8 +- RGB.NET.Layout/DeviceLayout.cs | 8 +- RGB.NET.Layout/IDeviceLayout.cs | 4 +- RGB.NET.Layout/ILedLayout.cs | 8 +- RGB.NET.Layout/LedLayout.cs | 24 +-- RGB.NET.Presets/Decorators/FlashDecorator.cs | 28 ++-- .../Decorators/MoveGradientDecorator.cs | 6 +- RGB.NET.Presets/Helper/GradientHelper.cs | 30 ++-- .../Textures/ConicalGradientTexture.cs | 12 +- .../Textures/Gradients/AbstractGradient.cs | 12 +- .../Textures/Gradients/GradientStop.cs | 6 +- .../Textures/Gradients/IGradient.cs | 4 +- .../Textures/Gradients/LinearGradient.cs | 14 +- .../Textures/Gradients/RainbowGradient.cs | 18 +-- .../Textures/LinearGradientTexture.cs | 6 +- .../Textures/RadialGradientTexture.cs | 12 +- Tests/RGB.NET.Core.Tests/Color/ColorTest.cs | 28 ++-- .../RGB.NET.Core.Tests/Color/HSVColorTest.cs | 134 ++++++++--------- .../RGB.NET.Core.Tests/Color/RGBColorTest.cs | 142 +++++++++--------- 36 files changed, 433 insertions(+), 472 deletions(-) diff --git a/RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs b/RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs index 40b0eec..53289c6 100644 --- a/RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs +++ b/RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs @@ -19,7 +19,7 @@ { if (!(obj is Color)) return false; - (double a, double r, double g, double b) = ((Color)obj).GetRGB(); + (float a, float r, float g, float b) = ((Color)obj).GetRGB(); return color.A.EqualsInTolerance(a) && color.R.EqualsInTolerance(r) && color.G.EqualsInTolerance(g) && color.B.EqualsInTolerance(b); } @@ -50,10 +50,10 @@ if (blendColor.A.EqualsInTolerance(1)) return blendColor; - double resultA = (1.0 - ((1.0 - blendColor.A) * (1.0 - baseColor.A))); - double resultR = (((blendColor.R * blendColor.A) / resultA) + ((baseColor.R * baseColor.A * (1.0 - blendColor.A)) / resultA)); - double resultG = (((blendColor.G * blendColor.A) / resultA) + ((baseColor.G * baseColor.A * (1.0 - blendColor.A)) / resultA)); - double resultB = (((blendColor.B * blendColor.A) / resultA) + ((baseColor.B * baseColor.A * (1.0 - blendColor.A)) / resultA)); + float resultA = (1.0f - ((1.0f - blendColor.A) * (1.0f - baseColor.A))); + float resultR = (((blendColor.R * blendColor.A) / resultA) + ((baseColor.R * baseColor.A * (1.0f - blendColor.A)) / resultA)); + float resultG = (((blendColor.G * blendColor.A) / resultA) + ((baseColor.G * baseColor.A * (1.0f - blendColor.A)) / resultA)); + float resultB = (((blendColor.B * blendColor.A) / resultA) + ((baseColor.B * baseColor.A * (1.0f - blendColor.A)) / resultA)); return new Color(resultA, resultR, resultG, resultB); } diff --git a/RGB.NET.Core/Color/Color.cs b/RGB.NET.Core/Color/Color.cs index e389f19..0948c47 100644 --- a/RGB.NET.Core/Color/Color.cs +++ b/RGB.NET.Core/Color/Color.cs @@ -32,22 +32,22 @@ namespace RGB.NET.Core /// /// Gets the alpha component value of this as percentage in the range [0..1]. /// - public double A { get; } + public float A { get; } /// /// Gets the red component value of this as percentage in the range [0..1]. /// - public double R { get; } + public float R { get; } /// /// Gets the green component value of this as percentage in the range [0..1]. /// - public double G { get; } + public float G { get; } /// /// Gets the blue component value of this as percentage in the range [0..1]. /// - public double B { get; } + public float B { get; } #endregion @@ -106,8 +106,8 @@ namespace RGB.NET.Core /// The red component value of this . /// The green component value of this . /// The blue component value of this . - public Color(double r, double g, double b) - : this(1.0, r, g, b) + public Color(float r, float g, float b) + : this(1.0f, r, g, b) { } /// @@ -117,7 +117,7 @@ namespace RGB.NET.Core /// The red component value of this . /// The green component value of this . /// The blue component value of this . - public Color(double a, byte r, byte g, byte b) + public Color(float a, byte r, byte g, byte b) : this(a, r.GetPercentageFromByteValue(), g.GetPercentageFromByteValue(), b.GetPercentageFromByteValue()) { } @@ -128,7 +128,7 @@ namespace RGB.NET.Core /// The red component value of this . /// The green component value of this . /// The blue component value of this . - public Color(double a, int r, int g, int b) + public Color(float a, int r, int g, int b) : this(a, (byte)r.Clamp(0, byte.MaxValue), (byte)g.Clamp(0, byte.MaxValue), (byte)b.Clamp(0, byte.MaxValue)) { } @@ -139,7 +139,7 @@ namespace RGB.NET.Core /// The red component value of this . /// The green component value of this . /// The blue component value of this . - public Color(int a, double r, double g, double b) + public Color(int a, float r, float g, float b) : this((byte)a.Clamp(0, byte.MaxValue), r, g, b) { } @@ -150,7 +150,7 @@ namespace RGB.NET.Core /// The red component value of this . /// The green component value of this . /// The blue component value of this . - public Color(byte a, double r, double g, double b) + public Color(byte a, float r, float g, float b) : this(a.GetPercentageFromByteValue(), r, g, b) { } @@ -161,7 +161,7 @@ namespace RGB.NET.Core /// The red component value of this . /// The green component value of this . /// The blue component value of this . - public Color(double a, double r, double g, double b) + public Color(float a, float r, float g, float b) { A = a.Clamp(0, 1); R = r.Clamp(0, 1); @@ -269,14 +269,14 @@ namespace RGB.NET.Core /// /// The containing the components. /// The color. - public static implicit operator Color((double r, double g, double b) components) => new(components.r, components.g, components.b); + public static implicit operator Color((float r, float g, float b) components) => new(components.r, components.g, components.b); /// /// Converts a of ARGB-components to a . /// /// The containing the components. /// The color. - public static implicit operator Color((double a, double r, double g, double b) components) => new(components.a, components.r, components.g, components.b); + public static implicit operator Color((float a, float r, float g, float b) components) => new(components.a, components.r, components.g, components.b); #endregion } diff --git a/RGB.NET.Core/Color/HSVColor.cs b/RGB.NET.Core/Color/HSVColor.cs index 741a654..40c89c8 100644 --- a/RGB.NET.Core/Color/HSVColor.cs +++ b/RGB.NET.Core/Color/HSVColor.cs @@ -13,21 +13,21 @@ namespace RGB.NET.Core /// /// /// - public static double GetHue(this Color color) => color.GetHSV().hue; + public static float GetHue(this Color color) => color.GetHSV().hue; /// /// Gets the saturation component value (HSV-color space) of this in the range [0..1]. /// /// /// - public static double GetSaturation(this Color color) => color.GetHSV().saturation; + public static float GetSaturation(this Color color) => color.GetHSV().saturation; /// /// Gets the value component value (HSV-color space) of this in the range [0..1]. /// /// /// - public static double GetValue(this Color color) => color.GetHSV().value; + public static float GetValue(this Color color) => color.GetHSV().value; /// /// Gets the hue, saturation and value component values (HSV-color space) of this . @@ -37,7 +37,7 @@ namespace RGB.NET.Core /// /// /// - public static (double hue, double saturation, double value) GetHSV(this Color color) + public static (float hue, float saturation, float value) GetHSV(this Color color) => CaclulateHSVFromRGB(color.R, color.G, color.B); #endregion @@ -51,9 +51,9 @@ namespace RGB.NET.Core /// The saturation value to add. /// The value value to add. /// The new color after the modification. - public static Color AddHSV(this Color color, double hue = 0, double saturation = 0, double value = 0) + public static Color AddHSV(this Color color, float hue = 0, float saturation = 0, float value = 0) { - (double cHue, double cSaturation, double cValue) = color.GetHSV(); + (float cHue, float cSaturation, float cValue) = color.GetHSV(); return Create(color.A, cHue + hue, cSaturation + saturation, cValue + value); } @@ -64,9 +64,9 @@ namespace RGB.NET.Core /// The saturation value to subtract. /// The value value to subtract. /// The new color after the modification. - public static Color SubtractHSV(this Color color, double hue = 0, double saturation = 0, double value = 0) + public static Color SubtractHSV(this Color color, float hue = 0, float saturation = 0, float value = 0) { - (double cHue, double cSaturation, double cValue) = color.GetHSV(); + (float cHue, float cSaturation, float cValue) = color.GetHSV(); return Create(color.A, cHue - hue, cSaturation - saturation, cValue - value); } @@ -77,9 +77,9 @@ namespace RGB.NET.Core /// The saturation value to multiply. /// The value value to multiply. /// The new color after the modification. - public static Color MultiplyHSV(this Color color, double hue = 1, double saturation = 1, double value = 1) + public static Color MultiplyHSV(this Color color, float hue = 1, float saturation = 1, float value = 1) { - (double cHue, double cSaturation, double cValue) = color.GetHSV(); + (float cHue, float cSaturation, float cValue) = color.GetHSV(); return Create(color.A, cHue * hue, cSaturation * saturation, cValue * value); } @@ -90,9 +90,9 @@ namespace RGB.NET.Core /// The saturation value to divide. /// The value value to divide. /// The new color after the modification. - public static Color DivideHSV(this Color color, double hue = 1, double saturation = 1, double value = 1) + public static Color DivideHSV(this Color color, float hue = 1, float saturation = 1, float value = 1) { - (double cHue, double cSaturation, double cValue) = color.GetHSV(); + (float cHue, float cSaturation, float cValue) = color.GetHSV(); return Create(color.A, cHue / hue, cSaturation / saturation, cValue / value); } @@ -103,9 +103,9 @@ namespace RGB.NET.Core /// The saturation value to set. /// The value value to set. /// The new color after the modification. - public static Color SetHSV(this Color color, double? hue = null, double? saturation = null, double? value = null) + public static Color SetHSV(this Color color, float? hue = null, float? saturation = null, float? value = null) { - (double cHue, double cSaturation, double cValue) = color.GetHSV(); + (float cHue, float cSaturation, float cValue) = color.GetHSV(); return Create(color.A, hue ?? cHue, saturation ?? cSaturation, value ?? cValue); } @@ -120,8 +120,8 @@ namespace RGB.NET.Core /// The saturation component value of this . /// The value component value of this . /// The color created from the values. - public static Color Create(double hue, double saturation, double value) - => Create(1.0, hue, saturation, value); + public static Color Create(float hue, float saturation, float value) + => Create(1.0f, hue, saturation, value); /// /// Creates a new instance of the struct using AHSV-Values. @@ -131,8 +131,8 @@ namespace RGB.NET.Core /// The saturation component value of this . /// The value component value of this . /// The color created from the values. - public static Color Create(byte a, double hue, double saturation, double value) - => Create((double)a / byte.MaxValue, hue, saturation, value); + public static Color Create(byte a, float hue, float saturation, float value) + => Create((float)a / byte.MaxValue, hue, saturation, value); /// /// Creates a new instance of the struct using AHSV-Values. @@ -142,8 +142,8 @@ namespace RGB.NET.Core /// The saturation component value of this . /// The value component value of this . /// The color created from the values. - public static Color Create(int a, double hue, double saturation, double value) - => Create((double)a / byte.MaxValue, hue, saturation, value); + public static Color Create(int a, float hue, float saturation, float value) + => Create((float)a / byte.MaxValue, hue, saturation, value); /// /// Creates a new instance of the struct using AHSV-Values. @@ -153,9 +153,9 @@ namespace RGB.NET.Core /// The saturation component value of this . /// The value component value of this . /// The color created from the values. - public static Color Create(double a, double hue, double saturation, double value) + public static Color Create(float a, float hue, float saturation, float value) { - (double r, double g, double b) = CalculateRGBFromHSV(hue, saturation, value); + (float r, float g, float b) = CalculateRGBFromHSV(hue, saturation, value); return new Color(a, r, g, b); } @@ -163,33 +163,33 @@ namespace RGB.NET.Core #region Helper - private static (double h, double s, double v) CaclulateHSVFromRGB(double r, double g, double b) + private static (float h, float s, float v) CaclulateHSVFromRGB(float r, float g, float b) { if (r.EqualsInTolerance(g) && g.EqualsInTolerance(b)) return (0, 0, r); - double min = Math.Min(Math.Min(r, g), b); - double max = Math.Max(Math.Max(r, g), b); + float min = Math.Min(Math.Min(r, g), b); + float max = Math.Max(Math.Max(r, g), b); - double hue; + float hue; if (max.EqualsInTolerance(min)) hue = 0; else if (max.EqualsInTolerance(r)) // r is max hue = (g - b) / (max - min); else if (max.EqualsInTolerance(g)) // g is max - hue = 2.0 + ((b - r) / (max - min)); + hue = 2.0f + ((b - r) / (max - min)); else // b is max - hue = 4.0 + ((r - g) / (max - min)); + hue = 4.0f + ((r - g) / (max - min)); - hue *= 60.0; + hue *= 60.0f; hue = hue.Wrap(0, 360); - double saturation = max.EqualsInTolerance(0) ? 0 : 1.0 - (min / max); - double value = Math.Max(r, Math.Max(g, b)); + float saturation = max.EqualsInTolerance(0) ? 0 : 1.0f - (min / max); + float value = Math.Max(r, Math.Max(g, b)); return (hue, saturation, value); } - private static (double r, double g, double b) CalculateRGBFromHSV(double h, double s, double v) + private static (float r, float g, float b) CalculateRGBFromHSV(float h, float s, float v) { h = h.Wrap(0, 360); s = s.Clamp(0, 1); @@ -198,12 +198,12 @@ namespace RGB.NET.Core if (s <= 0.0) return (v, v, v); - double hh = h / 60.0; + float hh = h / 60.0f; int i = (int)hh; - double ff = hh - i; - double p = v * (1.0 - s); - double q = v * (1.0 - (s * ff)); - double t = v * (1.0 - (s * (1.0 - ff))); + float ff = hh - i; + float p = v * (1.0f - s); + float q = v * (1.0f - (s * ff)); + float t = v * (1.0f - (s * (1.0f - ff))); return i switch { diff --git a/RGB.NET.Core/Color/RGBColor.cs b/RGB.NET.Core/Color/RGBColor.cs index edb3e1f..17919ec 100644 --- a/RGB.NET.Core/Color/RGBColor.cs +++ b/RGB.NET.Core/Color/RGBColor.cs @@ -49,7 +49,7 @@ namespace RGB.NET.Core /// /// /// - public static (double a, double r, double g, double b) GetRGB(this Color color) + public static (float a, float r, float g, float b) GetRGB(this Color color) => (color.A, color.R, color.G, color.B); #endregion @@ -75,7 +75,7 @@ namespace RGB.NET.Core /// The green value to add. /// The blue value to add. /// The new color after the modification. - public static Color AddRGB(this Color color, double r = 0, double g = 0, double b = 0) + public static Color AddRGB(this Color color, float r = 0, float g = 0, float b = 0) => new(color.A, color.R + r, color.G + g, color.B + b); /// @@ -91,7 +91,7 @@ namespace RGB.NET.Core /// /// The alpha value to add. /// The new color after the modification. - public static Color AddA(this Color color, double a) + public static Color AddA(this Color color, float a) => new(color.A + a, color.R, color.G, color.B); #endregion @@ -115,7 +115,7 @@ namespace RGB.NET.Core /// The green value to subtract. /// The blue value to subtract. /// The new color after the modification. - public static Color SubtractRGB(this Color color, double r = 0, double g = 0, double b = 0) + public static Color SubtractRGB(this Color color, float r = 0, float g = 0, float b = 0) => new(color.A, color.R - r, color.G - g, color.B - b); /// @@ -131,7 +131,7 @@ namespace RGB.NET.Core /// /// The alpha value to subtract. /// The new color after the modification. - public static Color SubtractA(this Color color, double aPercent) + public static Color SubtractA(this Color color, float aPercent) => new(color.A - aPercent, color.R, color.G, color.B); #endregion @@ -145,7 +145,7 @@ namespace RGB.NET.Core /// The green value to multiply. /// The blue value to multiply. /// The new color after the modification. - public static Color MultiplyRGB(this Color color, double r = 1, double g = 1, double b = 1) + public static Color MultiplyRGB(this Color color, float r = 1, float g = 1, float b = 1) => new(color.A, color.R * r, color.G * g, color.B * b); /// @@ -153,7 +153,7 @@ namespace RGB.NET.Core /// /// The alpha value to multiply. /// The new color after the modification. - public static Color MultiplyA(this Color color, double a) + public static Color MultiplyA(this Color color, float a) => new(color.A * a, color.R, color.G, color.B); #endregion @@ -167,7 +167,7 @@ namespace RGB.NET.Core /// The green value to divide. /// The blue value to divide. /// The new color after the modification. - public static Color DivideRGB(this Color color, double r = 1, double g = 1, double b = 1) + public static Color DivideRGB(this Color color, float r = 1, float g = 1, float b = 1) => new(color.A, color.R / r, color.G / g, color.B / b); /// @@ -175,7 +175,7 @@ namespace RGB.NET.Core /// /// The alpha value to divide. /// The new color after the modification. - public static Color DivideA(this Color color, double a) + public static Color DivideA(this Color color, float a) => new(color.A / a, color.R, color.G, color.B); #endregion @@ -209,7 +209,7 @@ namespace RGB.NET.Core /// The green value to set. /// The blue value to set. /// The new color after the modification. - public static Color SetRGB(this Color color, double? r = null, double? g = null, double? b = null) + public static Color SetRGB(this Color color, float? r = null, float? g = null, float? b = null) => new(color.A, r ?? color.R, g ?? color.G, b ?? color.B); /// @@ -224,7 +224,7 @@ namespace RGB.NET.Core /// /// The alpha value to set. /// The new color after the modification. - public static Color SetA(this Color color, double a) => new(a, color.R, color.G, color.B); + public static Color SetA(this Color color, float a) => new(a, color.R, color.G, color.B); #endregion diff --git a/RGB.NET.Core/Extensions/MathExtensions.cs b/RGB.NET.Core/Extensions/MathExtensions.cs index 0a9fb88..d47db3f 100644 --- a/RGB.NET.Core/Extensions/MathExtensions.cs +++ b/RGB.NET.Core/Extensions/MathExtensions.cs @@ -4,16 +4,16 @@ using System.Runtime.CompilerServices; namespace RGB.NET.Core { /// - /// Offers some extensions and helper-methods for the work with doubles + /// Offers some extensions and helper-methods for the work with floats /// - public static class DoubleExtensions + public static class FloatExtensions { #region Constants /// /// Defines the precision RGB.NET processes floating point comparisons in. /// - public const double TOLERANCE = 1E-10; + public const float TOLERANCE = 1E-10f; #endregion @@ -26,7 +26,7 @@ namespace RGB.NET.Core /// The first value to compare. /// true if the difference is smaller than the ; otherwise, false. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool EqualsInTolerance(this double value1, double value2) => Math.Abs(value1 - value2) < TOLERANCE; + public static bool EqualsInTolerance(this float value1, float value2) => Math.Abs(value1 - value2) < TOLERANCE; /// /// Clamps the provided value to be bigger or equal min and smaller or equal max. @@ -36,7 +36,7 @@ namespace RGB.NET.Core /// The higher value of the range the value is clamped to. /// The clamped value. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Clamp(this double value, double min, double max) + public static float Clamp(this float value, float min, float max) { // ReSharper disable ConvertIfStatementToReturnStatement - I'm not sure why, but inlining this statement reduces performance by ~10% if (value < min) return min; @@ -70,9 +70,9 @@ namespace RGB.NET.Core /// The higher value of the range the value is wrapped into. /// The wrapped value. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Wrap(this double value, double min, double max) + public static float Wrap(this float value, float min, float max) { - double range = max - min; + float range = max - min; while (value >= max) value -= range; @@ -84,17 +84,17 @@ namespace RGB.NET.Core } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static byte GetByteValueFromPercentage(this double percentage) + public static byte GetByteValueFromPercentage(this float percentage) { - if (double.IsNaN(percentage)) return 0; + if (float.IsNaN(percentage)) return 0; - percentage = percentage.Clamp(0, 1.0); + percentage = percentage.Clamp(0, 1.0f); return (byte)(percentage >= 1.0 ? 255 : percentage * 256.0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double GetPercentageFromByteValue(this byte value) - => ((double)value) / byte.MaxValue; + public static float GetPercentageFromByteValue(this byte value) + => ((float)value) / byte.MaxValue; #endregion } diff --git a/RGB.NET.Core/Extensions/PointExtensions.cs b/RGB.NET.Core/Extensions/PointExtensions.cs index 9766bf3..00436c1 100644 --- a/RGB.NET.Core/Extensions/PointExtensions.cs +++ b/RGB.NET.Core/Extensions/PointExtensions.cs @@ -13,7 +13,7 @@ namespace RGB.NET.Core /// The x-ammount to move. /// The y-ammount to move. /// The new location of the point. - public static Point Translate(this Point point, double x = 0, double y = 0) => new(point.X + x, point.Y + y); + public static Point Translate(this Point point, float x = 0, float y = 0) => new(point.X + x, point.Y + y); /// /// Rotates the specified by the given amuont around the given origin. @@ -24,8 +24,8 @@ namespace RGB.NET.Core /// The new location of the point. public static Point Rotate(this Point point, Rotation rotation, Point origin = new()) { - double sin = Math.Sin(rotation.Radians); - double cos = Math.Cos(rotation.Radians); + float sin = MathF.Sin(rotation.Radians); + float cos = MathF.Cos(rotation.Radians); point = new Point(point.X - origin.X, point.Y - origin.Y); point = new Point((point.X * cos) - (point.Y * sin), (point.X * sin) + (point.Y * cos)); diff --git a/RGB.NET.Core/Extensions/RectangleExtensions.cs b/RGB.NET.Core/Extensions/RectangleExtensions.cs index f14ccff..634c3f6 100644 --- a/RGB.NET.Core/Extensions/RectangleExtensions.cs +++ b/RGB.NET.Core/Extensions/RectangleExtensions.cs @@ -20,7 +20,7 @@ namespace RGB.NET.Core /// The rectangle to modify. /// The new x-location of the rectangle. /// The modified . - public static Rectangle SetX(this Rectangle rect, double x) => new(new Point(x, rect.Location.Y), rect.Size); + public static Rectangle SetX(this Rectangle rect, float x) => new(new Point(x, rect.Location.Y), rect.Size); /// /// Sets the of the of the given rectangle. @@ -28,7 +28,7 @@ namespace RGB.NET.Core /// The rectangle to modify. /// The new y-location of the rectangle. /// The modified . - public static Rectangle SetY(this Rectangle rect, double y) => new(new Point(rect.Location.X, y), rect.Size); + public static Rectangle SetY(this Rectangle rect, float y) => new(new Point(rect.Location.X, y), rect.Size); /// /// Sets the of the given rectangle. @@ -44,7 +44,7 @@ namespace RGB.NET.Core /// The rectangle to modify. /// The new width of the rectangle. /// The modified . - public static Rectangle SetWidth(this Rectangle rect, double width) => new(rect.Location, new Size(width, rect.Size.Height)); + public static Rectangle SetWidth(this Rectangle rect, float width) => new(rect.Location, new Size(width, rect.Size.Height)); /// /// Sets the of the of the given rectangle. @@ -52,14 +52,14 @@ namespace RGB.NET.Core /// The rectangle to modify. /// The new height of the rectangle. /// The modified . - public static Rectangle SetHeight(this Rectangle rect, double height) => new(rect.Location, new Size(rect.Size.Width, height)); + public static Rectangle SetHeight(this Rectangle rect, float height) => new(rect.Location, new Size(rect.Size.Width, height)); /// /// Calculates the percentage of intersection of a rectangle. /// /// The intersecting rectangle. /// The percentage of intersection. - public static double CalculateIntersectPercentage(this Rectangle rect, in Rectangle intersectingRect) + public static float CalculateIntersectPercentage(this Rectangle rect, in Rectangle intersectingRect) { if (rect.IsEmpty || intersectingRect.IsEmpty) return 0; @@ -74,11 +74,11 @@ namespace RGB.NET.Core /// A new representing the intersection this and the one provided as parameter. public static Rectangle CalculateIntersection(this Rectangle rect, in Rectangle intersectingRectangle) { - double x1 = Math.Max(rect.Location.X, intersectingRectangle.Location.X); - double x2 = Math.Min(rect.Location.X + rect.Size.Width, intersectingRectangle.Location.X + intersectingRectangle.Size.Width); + float x1 = Math.Max(rect.Location.X, intersectingRectangle.Location.X); + float x2 = Math.Min(rect.Location.X + rect.Size.Width, intersectingRectangle.Location.X + intersectingRectangle.Size.Width); - double y1 = Math.Max(rect.Location.Y, intersectingRectangle.Location.Y); - double y2 = Math.Min(rect.Location.Y + rect.Size.Height, intersectingRectangle.Location.Y + intersectingRectangle.Size.Height); + float y1 = Math.Max(rect.Location.Y, intersectingRectangle.Location.Y); + float y2 = Math.Min(rect.Location.Y + rect.Size.Height, intersectingRectangle.Location.Y + intersectingRectangle.Size.Height); if ((x2 >= x1) && (y2 >= y1)) return new Rectangle(x1, y1, x2 - x1, y2 - y1); @@ -99,7 +99,7 @@ namespace RGB.NET.Core /// The X-location to test. /// The Y-location to test. /// true if the rectangle contains the given coordinates; otherwise false. - public static bool Contains(this Rectangle rect, double x, double y) => (rect.Location.X <= x) && (x < (rect.Location.X + rect.Size.Width)) + public static bool Contains(this Rectangle rect, float x, float y) => (rect.Location.X <= x) && (x < (rect.Location.X + rect.Size.Width)) && (rect.Location.Y <= y) && (y < (rect.Location.Y + rect.Size.Height)); /// @@ -125,7 +125,7 @@ namespace RGB.NET.Core /// The x-ammount to move. /// The y-ammount to move. /// The moved rectangle. - public static Rectangle Translate(this Rectangle rect, double x = 0, double y = 0) => new(rect.Location.Translate(x, y), rect.Size); + public static Rectangle Translate(this Rectangle rect, float x = 0, float y = 0) => new(rect.Location.Translate(x, y), rect.Size); /// /// Rotates the specified by the given amuont around the given origin. @@ -150,8 +150,8 @@ namespace RGB.NET.Core new(rect.Location.X, rect.Location.Y + rect.Size.Height), // bottom right }; - double sin = Math.Sin(rotation.Radians); - double cos = Math.Cos(rotation.Radians); + float sin = MathF.Sin(rotation.Radians); + float cos = MathF.Cos(rotation.Radians); for (int i = 0; i < points.Length; i++) { diff --git a/RGB.NET.Core/Positioning/Point.cs b/RGB.NET.Core/Positioning/Point.cs index d546994..aa533f4 100644 --- a/RGB.NET.Core/Positioning/Point.cs +++ b/RGB.NET.Core/Positioning/Point.cs @@ -16,7 +16,7 @@ namespace RGB.NET.Core /// /// Gets a [NaN,NaN]-Point. /// - public static Point Invalid => new(double.NaN, double.NaN); + public static Point Invalid => new(float.NaN, float.NaN); #endregion @@ -25,12 +25,12 @@ namespace RGB.NET.Core /// /// Gets the X-position of this . /// - public double X { get; } + public float X { get; } /// /// Gets the Y-position of this . /// - public double Y { get; } + public float Y { get; } #endregion @@ -41,7 +41,7 @@ namespace RGB.NET.Core /// /// The value used for the X-position. /// The value used for the Y-position. - public Point(double x, double y) + public Point(float x, float y) { this.X = x; this.Y = y; @@ -67,8 +67,8 @@ namespace RGB.NET.Core if (!(obj is Point)) return false; Point comparePoint = (Point)obj; - return ((double.IsNaN(X) && double.IsNaN(comparePoint.X)) || X.EqualsInTolerance(comparePoint.X)) - && ((double.IsNaN(Y) && double.IsNaN(comparePoint.Y)) || Y.EqualsInTolerance(comparePoint.Y)); + return ((float.IsNaN(X) && float.IsNaN(comparePoint.X)) || X.EqualsInTolerance(comparePoint.X)) + && ((float.IsNaN(Y) && float.IsNaN(comparePoint.Y)) || Y.EqualsInTolerance(comparePoint.Y)); } /// diff --git a/RGB.NET.Core/Positioning/Rectangle.cs b/RGB.NET.Core/Positioning/Rectangle.cs index fc94eb9..eddffb5 100644 --- a/RGB.NET.Core/Positioning/Rectangle.cs +++ b/RGB.NET.Core/Positioning/Rectangle.cs @@ -35,7 +35,7 @@ namespace RGB.NET.Core /// Gets a bool indicating if both, the width and the height of the rectangle is greater than zero. /// True if the rectangle has a width or a height of zero; otherwise, false. /// - public bool IsEmpty => (Size.Width <= DoubleExtensions.TOLERANCE) || (Size.Height <= DoubleExtensions.TOLERANCE); + public bool IsEmpty => (Size.Width <= FloatExtensions.TOLERANCE) || (Size.Height <= FloatExtensions.TOLERANCE); #endregion @@ -49,7 +49,7 @@ namespace RGB.NET.Core /// The y-value of the -position of this . /// The width of the of this . /// The height of the of this . - public Rectangle(double x, double y, double width, double height) + public Rectangle(float x, float y, float width, float height) : this(new Point(x, y), new Size(width, height)) { } @@ -70,7 +70,7 @@ namespace RGB.NET.Core this.Location = location; this.Size = size; - Center = new Point(Location.X + (Size.Width / 2.0), Location.Y + (Size.Height / 2.0)); + Center = new Point(Location.X + (Size.Width / 2.0f), Location.Y + (Size.Height / 2.0f)); } /// @@ -91,10 +91,10 @@ namespace RGB.NET.Core public Rectangle(IEnumerable rectangles) { bool hasPoint = false; - double posX = double.MaxValue; - double posY = double.MaxValue; - double posX2 = double.MinValue; - double posY2 = double.MinValue; + float posX = float.MaxValue; + float posY = float.MaxValue; + float posX2 = float.MinValue; + float posY2 = float.MinValue; foreach (Rectangle rectangle in rectangles) { @@ -108,7 +108,7 @@ namespace RGB.NET.Core (Point location, Size size) = hasPoint ? InitializeFromPoints(new Point(posX, posY), new Point(posX2, posY2)) : InitializeFromPoints(new Point(0, 0), new Point(0, 0)); Location = location; Size = size; - Center = new Point(Location.X + (Size.Width / 2.0), Location.Y + (Size.Height / 2.0)); + Center = new Point(Location.X + (Size.Width / 2.0f), Location.Y + (Size.Height / 2.0f)); } /// @@ -131,10 +131,10 @@ namespace RGB.NET.Core : this() { bool hasPoint = false; - double posX = double.MaxValue; - double posY = double.MaxValue; - double posX2 = double.MinValue; - double posY2 = double.MinValue; + float posX = float.MaxValue; + float posY = float.MaxValue; + float posX2 = float.MinValue; + float posY2 = float.MinValue; foreach (Point point in points) { @@ -149,7 +149,7 @@ namespace RGB.NET.Core Location = location; Size = size; - Center = new Point(Location.X + (Size.Width / 2.0), Location.Y + (Size.Height / 2.0)); + Center = new Point(Location.X + (Size.Width / 2.0f), Location.Y + (Size.Height / 2.0f)); } #endregion @@ -158,10 +158,10 @@ namespace RGB.NET.Core private static (Point location, Size size) InitializeFromPoints(Point point1, Point point2) { - double posX = Math.Min(point1.X, point2.X); - double posY = Math.Min(point1.Y, point2.Y); - double width = Math.Max(point1.X, point2.X) - posX; - double height = Math.Max(point1.Y, point2.Y) - posY; + float posX = Math.Min(point1.X, point2.X); + float posY = Math.Min(point1.Y, point2.Y); + float width = Math.Max(point1.X, point2.X) - posX; + float height = Math.Max(point1.Y, point2.Y) - posY; return (new Point(posX, posY), new Size(width, height)); } @@ -225,8 +225,8 @@ namespace RGB.NET.Core // DarthAffe 20.02.2021: Used for normalization public static Rectangle operator /(Rectangle rectangle1, Rectangle rectangle2) { - double x = rectangle1.Location.X / (rectangle2.Size.Width - rectangle2.Location.X); - double y = rectangle1.Location.Y / (rectangle2.Size.Height - rectangle2.Location.Y); + float x = rectangle1.Location.X / (rectangle2.Size.Width - rectangle2.Location.X); + float y = rectangle1.Location.Y / (rectangle2.Size.Height - rectangle2.Location.Y); Size size = rectangle1.Size / rectangle2.Size; return new Rectangle(new Point(x, y), size); } diff --git a/RGB.NET.Core/Positioning/Rotation.cs b/RGB.NET.Core/Positioning/Rotation.cs index 623f64a..d0de9d2 100644 --- a/RGB.NET.Core/Positioning/Rotation.cs +++ b/RGB.NET.Core/Positioning/Rotation.cs @@ -14,9 +14,9 @@ namespace RGB.NET.Core { #region Constants - private const double TWO_PI = Math.PI * 2.0; - private const double RADIANS_DEGREES_CONVERSION = 180.0 / Math.PI; - private const double DEGREES_RADIANS_CONVERSION = Math.PI / 180.0; + private const float TWO_PI = MathF.PI * 2.0f; + private const float RADIANS_DEGREES_CONVERSION = 180.0f / MathF.PI; + private const float DEGREES_RADIANS_CONVERSION = MathF.PI / 180.0f; #endregion @@ -25,12 +25,12 @@ namespace RGB.NET.Core /// /// Gets the angle in degrees. /// - public double Degrees { get; } + public float Degrees { get; } /// /// Gets the angle in radians. /// - public double Radians { get; } + public float Radians { get; } /// /// Gets a bool indicating if the rotation is > 0. @@ -45,13 +45,13 @@ namespace RGB.NET.Core /// Initializes a new instance of the class using the provided values. /// /// The rotation in degrees. - public Rotation(double degrees) + public Rotation(float degrees) : this(degrees, degrees * DEGREES_RADIANS_CONVERSION) { } - private Rotation(double degrees, double radians) + private Rotation(float degrees, float radians) { - this.Degrees = degrees % 360.0; + this.Degrees = degrees % 360.0f; this.Radians = radians % TWO_PI; } @@ -64,14 +64,14 @@ namespace RGB.NET.Core /// /// The angle in degrees. /// The new rotation. - public static Rotation FromDegrees(double degrees) => new(degrees); + public static Rotation FromDegrees(float degrees) => new(degrees); /// /// Creates a new Rotation out of the given radian-angle. /// /// The angle in radians. /// The new rotation. - public static Rotation FromRadians(double radians) => new(radians * RADIANS_DEGREES_CONVERSION, radians); + public static Rotation FromRadians(float radians) => new(radians * RADIANS_DEGREES_CONVERSION, radians); /// /// Tests whether the specified is equivalent to this . @@ -119,7 +119,7 @@ namespace RGB.NET.Core /// The . /// The value to add. /// A new representing the addition of the and the provided value. - public static Rotation operator +(Rotation rotation, double value) => new(rotation.Degrees + value); + public static Rotation operator +(Rotation rotation, float value) => new(rotation.Degrees + value); /// /// Returns a new representing the subtraction of the and the provided value. @@ -127,7 +127,7 @@ namespace RGB.NET.Core /// The . /// The value to substract. /// A new representing the subtraction of the and the provided value. - public static Rotation operator -(Rotation rotation, double value) => new(rotation.Degrees - value); + public static Rotation operator -(Rotation rotation, float value) => new(rotation.Degrees - value); /// /// Returns a new representing the multiplication of the and the provided value. @@ -135,7 +135,7 @@ namespace RGB.NET.Core /// The . /// The value to multiply with. /// A new representing the multiplication of the and the provided value. - public static Rotation operator *(Rotation rotation, double value) => new(rotation.Degrees * value); + public static Rotation operator *(Rotation rotation, float value) => new(rotation.Degrees * value); /// /// Returns a new representing the division of the and the provided value. @@ -143,19 +143,19 @@ namespace RGB.NET.Core /// The . /// The value to device with. /// A new representing the division of the and the provided value. - public static Rotation operator /(Rotation rotation, double value) => value.EqualsInTolerance(0) ? new Rotation(0) : new Rotation(rotation.Degrees / value); + public static Rotation operator /(Rotation rotation, float value) => value.EqualsInTolerance(0) ? new Rotation(0) : new Rotation(rotation.Degrees / value); /// - /// Converts a double to a . + /// Converts a float to a . /// /// The rotation in degrees to convert. - public static implicit operator Rotation(double rotation) => new(rotation); + public static implicit operator Rotation(float rotation) => new(rotation); /// - /// Converts to a double representing the rotation in degrees. + /// Converts to a float representing the rotation in degrees. /// /// The rotatio to convert. - public static implicit operator double(Rotation rotation) => rotation.Degrees; + public static implicit operator float(Rotation rotation) => rotation.Degrees; #endregion } diff --git a/RGB.NET.Core/Positioning/Scale.cs b/RGB.NET.Core/Positioning/Scale.cs index b12af17..1923bf7 100644 --- a/RGB.NET.Core/Positioning/Scale.cs +++ b/RGB.NET.Core/Positioning/Scale.cs @@ -16,12 +16,12 @@ namespace RGB.NET.Core /// /// Gets the horizontal scaling value. /// - public double Horizontal { get; } + public float Horizontal { get; } /// /// Gets the vertical scaling value. /// - public double Vertical { get; } + public float Vertical { get; } #endregion @@ -31,7 +31,7 @@ namespace RGB.NET.Core /// Initializes a new instance of the class using the provided values. /// /// The value used for horizontal and vertical scaling. 0 if not set. - public Scale(double scale = 1.0) : this(scale, scale) + public Scale(float scale = 1.0f) : this(scale, scale) { } /// @@ -39,7 +39,7 @@ namespace RGB.NET.Core /// /// The value used for horizontal scaling. /// The value used for vertical scaling. - public Scale(double horizontal, double vertical) + public Scale(float horizontal, float vertical) { this.Horizontal = horizontal; this.Vertical = vertical; @@ -74,7 +74,7 @@ namespace RGB.NET.Core /// /// The horizontal scaling value. /// The vertical scaling value. - public void Deconstruct(out double horizontalScale, out double verticalScale) + public void Deconstruct(out float horizontalScale, out float verticalScale) { horizontalScale = Horizontal; verticalScale = Vertical; @@ -106,7 +106,7 @@ namespace RGB.NET.Core /// The . /// The value to add. /// A new representing the addition of the and the provided value. - public static Scale operator +(Scale scale, double value) => new(scale.Horizontal + value, scale.Vertical + value); + public static Scale operator +(Scale scale, float value) => new(scale.Horizontal + value, scale.Vertical + value); /// /// Returns a new representing the subtraction of the and the provided value. @@ -114,7 +114,7 @@ namespace RGB.NET.Core /// The . /// The value to substract. /// A new representing the subtraction of the and the provided value. - public static Scale operator -(Scale scale, double value) => new(scale.Horizontal - value, scale.Vertical - value); + public static Scale operator -(Scale scale, float value) => new(scale.Horizontal - value, scale.Vertical - value); /// /// Returns a new representing the multiplication of the and the provided value. @@ -122,7 +122,7 @@ namespace RGB.NET.Core /// The . /// The value to multiply with. /// A new representing the multiplication of the and the provided value. - public static Scale operator *(Scale scale, double value) => new(scale.Horizontal * value, scale.Vertical * value); + public static Scale operator *(Scale scale, float value) => new(scale.Horizontal * value, scale.Vertical * value); /// /// Returns a new representing the division of the and the provided value. @@ -130,14 +130,14 @@ namespace RGB.NET.Core /// The . /// The value to device with. /// A new representing the division of the and the provided value. - public static Scale operator /(Scale scale, double value) => value.EqualsInTolerance(0) ? new Scale(0) : new Scale(scale.Horizontal / value, scale.Vertical / value); + public static Scale operator /(Scale scale, float value) => value.EqualsInTolerance(0) ? new Scale(0) : new Scale(scale.Horizontal / value, scale.Vertical / value); /// - /// Converts a double to a . + /// Converts a float to a . /// /// The scale value to convert. - public static implicit operator Scale(double scale) => new(scale); + public static implicit operator Scale(float scale) => new(scale); #endregion } diff --git a/RGB.NET.Core/Positioning/Size.cs b/RGB.NET.Core/Positioning/Size.cs index 7ed7887..690dc6b 100644 --- a/RGB.NET.Core/Positioning/Size.cs +++ b/RGB.NET.Core/Positioning/Size.cs @@ -16,7 +16,7 @@ namespace RGB.NET.Core /// /// Gets a [NaN,NaN]-Size. /// - public static Size Invalid => new(double.NaN, double.NaN); + public static Size Invalid => new(float.NaN, float.NaN); #endregion @@ -25,12 +25,12 @@ namespace RGB.NET.Core /// /// Gets or sets the width component value of this . /// - public double Width { get; } + public float Width { get; } /// /// Gets or sets the height component value of this . /// - public double Height { get; } + public float Height { get; } #endregion @@ -41,7 +41,7 @@ namespace RGB.NET.Core /// Initializes a new instance of the using the provided size to define a square. /// /// The size used for the component value and the component value. - public Size(double size) + public Size(float size) : this(size, size) { } @@ -50,7 +50,7 @@ namespace RGB.NET.Core /// /// The size used for the component value. /// The size used for the component value. - public Size(double width, double height) + public Size(float width, float height) { this.Width = width; this.Height = height; @@ -75,9 +75,9 @@ namespace RGB.NET.Core { if (!(obj is Size size)) return false; - (double width, double height) = size; - return ((double.IsNaN(Width) && double.IsNaN(width)) || Width.EqualsInTolerance(width)) - && ((double.IsNaN(Height) && double.IsNaN(height)) || Height.EqualsInTolerance(height)); + (float width, float height) = size; + return ((float.IsNaN(Width) && float.IsNaN(width)) || Width.EqualsInTolerance(width)) + && ((float.IsNaN(Height) && float.IsNaN(height)) || Height.EqualsInTolerance(height)); } /// @@ -99,7 +99,7 @@ namespace RGB.NET.Core /// /// The width. /// The height. - public void Deconstruct(out double width, out double height) + public void Deconstruct(out float width, out float height) { width = Width; height = Height; @@ -163,7 +163,7 @@ namespace RGB.NET.Core /// The . /// The factor by which the should be multiplied. /// A new representing the multiplication of the and the provided factor. - public static Size operator *(Size size, double factor) => new(size.Width * factor, size.Height * factor); + public static Size operator *(Size size, float factor) => new(size.Width * factor, size.Height * factor); /// /// Returns a new representing the division of the two provided . @@ -181,7 +181,7 @@ namespace RGB.NET.Core /// The . /// The factor by which the should be divided. /// A new representing the division of the and the provided factor. - public static Size operator /(Size size, double factor) => factor.EqualsInTolerance(0) ? Invalid : new Size(size.Width / factor, size.Height / factor); + public static Size operator /(Size size, float factor) => factor.EqualsInTolerance(0) ? Invalid : new Size(size.Width / factor, size.Height / factor); /// /// Returns a new representing the multiplication of the and the given . diff --git a/RGB.NET.Core/RGBSurface.cs b/RGB.NET.Core/RGBSurface.cs index 417acc5..58208a3 100644 --- a/RGB.NET.Core/RGBSurface.cs +++ b/RGB.NET.Core/RGBSurface.cs @@ -324,7 +324,7 @@ namespace RGB.NET.Core /// public void AlignDevices() { - double posX = 0; + float posX = 0; foreach (IRGBDevice device in Devices) { device.Location += new Point(posX, 0); diff --git a/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs b/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs index 25e29bf..77a39e6 100644 --- a/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs +++ b/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs @@ -23,10 +23,10 @@ namespace RGB.NET.Core public RenderMode CalculationMode { get; set; } = RenderMode.Relative; /// - public double Brightness { get; set; } + public float Brightness { get; set; } /// - public double Opacity { get; set; } + public float Opacity { get; set; } #endregion @@ -37,7 +37,7 @@ namespace RGB.NET.Core /// /// The overall percentage brightness of the brush. (default: 1.0) /// The overall percentage opacity of the brush. (default: 1.0) - protected AbstractBrush(double brightness = 1, double opacity = 1) + protected AbstractBrush(float brightness = 1, float opacity = 1) { this.Brightness = brightness; this.Opacity = opacity; diff --git a/RGB.NET.Core/Rendering/Brushes/IBrush.cs b/RGB.NET.Core/Rendering/Brushes/IBrush.cs index 3d2f449..f2509af 100644 --- a/RGB.NET.Core/Rendering/Brushes/IBrush.cs +++ b/RGB.NET.Core/Rendering/Brushes/IBrush.cs @@ -24,12 +24,12 @@ namespace RGB.NET.Core /// /// Gets or sets the overall percentage brightness of the . /// - double Brightness { get; set; } + float Brightness { get; set; } /// /// Gets or sets the overall percentage opacity of the . /// - double Opacity { get; set; } + float Opacity { get; set; } /// /// Performs the render pass of the and calculates the raw for all requested . diff --git a/RGB.NET.Core/Rendering/Textures/Sampler/AverageSampler.cs b/RGB.NET.Core/Rendering/Textures/Sampler/AverageSampler.cs index 92670da..c9e95ce 100644 --- a/RGB.NET.Core/Rendering/Textures/Sampler/AverageSampler.cs +++ b/RGB.NET.Core/Rendering/Textures/Sampler/AverageSampler.cs @@ -1,75 +1,36 @@ -using System; - -namespace RGB.NET.Core +namespace RGB.NET.Core { public class AverageSampler : ISampler { #region Properties & Fields - private Func, int, int, int, int, Color> _sampleMethod = SampleWithoutAlpha; - - private bool _sampleAlpha; - public bool SampleAlpha - { - get => _sampleAlpha; - set - { - _sampleAlpha = value; - _sampleMethod = value ? SampleWithAlpha : SampleWithoutAlpha; - } - } + public bool SampleAlpha { get; set; } #endregion #region Methods - public Color SampleColor(in ReadOnlyMemory data, int x, int y, int width, int height) => _sampleMethod(data, x, y, width, height); - - private static Color SampleWithAlpha(ReadOnlyMemory data, int x, int y, int width, int height) + public Color SampleColor(int x, int y, int width, int height, GetColor getColor) { - ReadOnlySpan span = data.Span; - + int maxX = x + width; int maxY = y + height; int count = width * height; - double a = 0, r = 0, g = 0, b = 0; + if (count == 0) return Color.Transparent; + + float a = 0, r = 0, g = 0, b = 0; for (int yPos = y; yPos < maxY; yPos++) - { - ReadOnlySpan line = span.Slice((yPos * width) + x, width); - foreach (Color color in line) + for (int xPos = x; xPos < maxX; xPos++) { + Color color = getColor(x, y); a += color.A; r += color.R; g += color.G; b += color.B; } - } - if (count == 0) return Color.Transparent; - - return new Color(a / count, r / count, g / count, b / count); - } - - private static Color SampleWithoutAlpha(ReadOnlyMemory data, int x, int y, int width, int height) - { - ReadOnlySpan span = data.Span; - - int maxY = y + height; - int count = width * height; - double r = 0, g = 0, b = 0; - for (int yPos = y; yPos < maxY; yPos++) - { - ReadOnlySpan line = span.Slice((yPos * width) + x, width); - foreach (Color color in line) - { - r += color.R; - g += color.G; - b += color.B; - } - } - - if (count == 0) return Color.Transparent; - - return new Color(r / count, g / count, b / count); + return SampleAlpha + ? new Color(a / count, r / count, g / count, b / count) + : new Color(r / count, g / count, b / count); } #endregion diff --git a/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs b/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs index fd2ea52..2d9fced 100644 --- a/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs +++ b/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs @@ -1,9 +1,9 @@ -using System; - -namespace RGB.NET.Core +namespace RGB.NET.Core { + public delegate Color GetColor(int x, int y); + public interface ISampler { - Color SampleColor(in ReadOnlyMemory data, int x, int y, int width, int height); + Color SampleColor(int x, int y, int width, int height, GetColor getColorFunc); } } diff --git a/RGB.NET.Devices.Corsair/Helper/NativeExtensions.cs b/RGB.NET.Devices.Corsair/Helper/NativeExtensions.cs index d823f09..3a50788 100644 --- a/RGB.NET.Devices.Corsair/Helper/NativeExtensions.cs +++ b/RGB.NET.Devices.Corsair/Helper/NativeExtensions.cs @@ -8,10 +8,10 @@ namespace RGB.NET.Devices.Corsair internal static Rectangle ToRectangle(this _CorsairLedPosition position) { //HACK DarthAffe 08.07.2018: It seems like corsair introduced a bug here - it's always 0. - double width = position.width < 0.5 ? 10 : position.width; - double height = position.height < 0.5 ? 10 : position.height; - double posX = position.left; - double posY = position.top; + float width = position.width < 0.5f ? 10 : (float)position.width; + float height = position.height < 0.5f ? 10 : (float)position.height; + float posX = (float)position.left; + float posY = (float)position.top; return new Rectangle(posX, posY, width, height); } diff --git a/RGB.NET.Layout/DeviceLayout.cs b/RGB.NET.Layout/DeviceLayout.cs index 2f34028..f4363c8 100644 --- a/RGB.NET.Layout/DeviceLayout.cs +++ b/RGB.NET.Layout/DeviceLayout.cs @@ -59,27 +59,27 @@ namespace RGB.NET.Layout /// Gets or sets the width of the . /// [XmlElement("Width")] - public double Width { get; set; } + public float Width { get; set; } /// /// Gets or sets the height of the . /// [XmlElement("Height")] - public double Height { get; set; } + public float Height { get; set; } /// /// Gets or sets the width of one 'unit' used for the calculation of led positions and sizes. /// [XmlElement("LedUnitWidth")] [DefaultValue(19.0)] - public double LedUnitWidth { get; set; } = 19.0; + public float LedUnitWidth { get; set; } = 19.0f; /// /// Gets or sets the height of one 'unit' used for the calculation of led positions and sizes. /// [XmlElement("LedUnitHeight")] [DefaultValue(19.0)] - public double LedUnitHeight { get; set; } = 19.0; + public float LedUnitHeight { get; set; } = 19.0f; [XmlArray("Leds")] public List InternalLeds { get; set; } = new(); diff --git a/RGB.NET.Layout/IDeviceLayout.cs b/RGB.NET.Layout/IDeviceLayout.cs index c06d9d9..677353c 100644 --- a/RGB.NET.Layout/IDeviceLayout.cs +++ b/RGB.NET.Layout/IDeviceLayout.cs @@ -38,12 +38,12 @@ namespace RGB.NET.Layout /// /// Gets or sets the width of the . /// - double Width { get; } + float Width { get; } /// /// Gets or sets the height of the . /// - double Height { get; } + float Height { get; } /// /// Gets or sets a list of representing all the of the . diff --git a/RGB.NET.Layout/ILedLayout.cs b/RGB.NET.Layout/ILedLayout.cs index 3747a97..5569692 100644 --- a/RGB.NET.Layout/ILedLayout.cs +++ b/RGB.NET.Layout/ILedLayout.cs @@ -22,22 +22,22 @@ namespace RGB.NET.Layout /// /// Gets the x-position of the . /// - double X { get; } + float X { get; } /// /// Gets the y-position of the . /// - double Y { get; } + float Y { get; } /// /// Gets the width of the . /// - double Width { get; } + float Width { get; } /// /// Gets the height of the . /// - double Height { get; } + float Height { get; } object? CustomData { get; } } diff --git a/RGB.NET.Layout/LedLayout.cs b/RGB.NET.Layout/LedLayout.cs index 3bab36c..39af645 100644 --- a/RGB.NET.Layout/LedLayout.cs +++ b/RGB.NET.Layout/LedLayout.cs @@ -83,25 +83,25 @@ namespace RGB.NET.Layout /// Gets the x-position of the . /// [XmlIgnore] - public double X { get; private set; } + public float X { get; private set; } /// /// Gets the y-position of the . /// [XmlIgnore] - public double Y { get; private set; } + public float Y { get; private set; } /// /// Gets the width of the . /// [XmlIgnore] - public double Width { get; private set; } + public float Width { get; private set; } /// /// Gets the height of the . /// [XmlIgnore] - public double Height { get; private set; } + public float Height { get; private set; } #endregion @@ -128,7 +128,7 @@ namespace RGB.NET.Layout Y = GetLocationValue(DescriptiveY, lastLed?.Y ?? 0, Height, lastLed?.Height ?? 0); } - protected virtual double GetLocationValue(string value, double lastValue, double currentSize, double lastSize) + protected virtual float GetLocationValue(string value, float lastValue, float currentSize, float lastSize) { try { @@ -143,21 +143,21 @@ namespace RGB.NET.Layout return lastValue + lastSize; if (value.StartsWith("+", StringComparison.Ordinal)) - return lastValue + lastSize + double.Parse(value[1..], CultureInfo.InvariantCulture); + return lastValue + lastSize + float.Parse(value[1..], CultureInfo.InvariantCulture); if (string.Equals(value, "-", StringComparison.Ordinal)) return lastValue - currentSize; if (value.StartsWith("-", StringComparison.Ordinal)) - return lastValue - currentSize - double.Parse(value[1..], CultureInfo.InvariantCulture); + return lastValue - currentSize - float.Parse(value[1..], CultureInfo.InvariantCulture); if (string.Equals(value, "~", StringComparison.Ordinal)) return (lastValue + lastSize) - currentSize; if (value.StartsWith("~", StringComparison.Ordinal)) - return (lastValue + lastSize) - currentSize - double.Parse(value[1..], CultureInfo.InvariantCulture); + return (lastValue + lastSize) - currentSize - float.Parse(value[1..], CultureInfo.InvariantCulture); - return double.Parse(value, CultureInfo.InvariantCulture); + return float.Parse(value, CultureInfo.InvariantCulture); } catch { @@ -165,7 +165,7 @@ namespace RGB.NET.Layout } } - protected virtual double GetSizeValue(string value, double unitSize) + protected virtual float GetSizeValue(string value, float unitSize) { try { @@ -174,9 +174,9 @@ namespace RGB.NET.Layout value = value.Replace(" ", string.Empty); if (value.EndsWith("mm", StringComparison.OrdinalIgnoreCase)) - return double.Parse(value[..^2], CultureInfo.InvariantCulture); + return float.Parse(value[..^2], CultureInfo.InvariantCulture); - return unitSize * double.Parse(value, CultureInfo.InvariantCulture); + return unitSize * float.Parse(value, CultureInfo.InvariantCulture); } catch { diff --git a/RGB.NET.Presets/Decorators/FlashDecorator.cs b/RGB.NET.Presets/Decorators/FlashDecorator.cs index 6bb03ab..696782a 100644 --- a/RGB.NET.Presets/Decorators/FlashDecorator.cs +++ b/RGB.NET.Presets/Decorators/FlashDecorator.cs @@ -20,46 +20,46 @@ namespace RGB.NET.Presets.Decorators /// Gets or sets the attack-time (in seconds) of the decorator. (default: 0.2)
/// This is close to a synthesizer envelope. (See as reference) ///
- public double Attack { get; set; } = 0.2; + public float Attack { get; set; } = 0.2f; /// /// Gets or sets the decay-time (in seconds) of the decorator. (default: 0)
/// This is close to a synthesizer envelope. (See as reference) ///
- public double Decay { get; set; } = 0; + public float Decay { get; set; } = 0; /// /// Gets or sets the sustain-time (in seconds) of the decorator. (default: 0.3)
/// This is close to a synthesizer envelope. (See as reference)
/// Note that this value for naming reasons represents the time NOT the level. ///
- public double Sustain { get; set; } = 0.3; + public float Sustain { get; set; } = 0.3f; /// /// Gets or sets the release-time (in seconds) of the decorator. (default: 0.2)
/// This is close to a synthesizer envelope. (See as reference) ///
- public double Release { get; set; } = 0.2; + public float Release { get; set; } = 0.2f; /// /// Gets or sets the level to which the oppacity (percentage) should raise in the attack-cycle. (default: 1); /// - public double AttackValue { get; set; } = 1; + public float AttackValue { get; set; } = 1; /// /// Gets or sets the level at which the oppacity (percentage) should stay in the sustain-cycle. (default: 1); /// - public double SustainValue { get; set; } = 1; + public float SustainValue { get; set; } = 1; /// /// Gets or sets the level at which the oppacity (percentage) should stay in the pause-cycle. (default: 0); /// - public double PauseValue { get; set; } = 0; + public float PauseValue { get; set; } = 0; /// /// Gets or sets the interval (in seconds) in which the decorator should repeat (if repetition is enabled). (default: 1) /// - public double Interval { get; set; } = 1; + public float Interval { get; set; } = 1; /// /// Gets or sets the amount of repetitions the decorator should do until it's finished. Zero means infinite. (default: 0) @@ -67,10 +67,10 @@ namespace RGB.NET.Presets.Decorators public int Repetitions { get; set; } = 0; private ADSRPhase _currentPhase; - private double _currentPhaseValue; + private float _currentPhaseValue; private int _repetitionCount; - private double _currentValue; + private float _currentValue; #endregion @@ -90,14 +90,14 @@ namespace RGB.NET.Presets.Decorators /// protected override void Update(double deltaTime) { - _currentPhaseValue -= deltaTime; + _currentPhaseValue -= (float)deltaTime; // Using ifs instead of a switch allows to skip phases with time 0. // ReSharper disable InvertIf if (_currentPhase == ADSRPhase.Attack) if (_currentPhaseValue > 0) - _currentValue = PauseValue + (Math.Min(1, (Attack - _currentPhaseValue) / Attack) * (AttackValue - PauseValue)); + _currentValue = PauseValue + (MathF.Min(1, (Attack - _currentPhaseValue) / Attack) * (AttackValue - PauseValue)); else { _currentPhaseValue = Decay; @@ -106,7 +106,7 @@ namespace RGB.NET.Presets.Decorators if (_currentPhase == ADSRPhase.Decay) if (_currentPhaseValue > 0) - _currentValue = SustainValue + (Math.Min(1, _currentPhaseValue / Decay) * (AttackValue - SustainValue)); + _currentValue = SustainValue + (MathF.Min(1, _currentPhaseValue / Decay) * (AttackValue - SustainValue)); else { _currentPhaseValue = Sustain; @@ -124,7 +124,7 @@ namespace RGB.NET.Presets.Decorators if (_currentPhase == ADSRPhase.Release) if (_currentPhaseValue > 0) - _currentValue = PauseValue + (Math.Min(1, _currentPhaseValue / Release) * (SustainValue - PauseValue)); + _currentValue = PauseValue + (MathF.Min(1, _currentPhaseValue / Release) * (SustainValue - PauseValue)); else { _currentPhaseValue = Interval; diff --git a/RGB.NET.Presets/Decorators/MoveGradientDecorator.cs b/RGB.NET.Presets/Decorators/MoveGradientDecorator.cs index 68a0ef7..5f2280f 100644 --- a/RGB.NET.Presets/Decorators/MoveGradientDecorator.cs +++ b/RGB.NET.Presets/Decorators/MoveGradientDecorator.cs @@ -26,7 +26,7 @@ namespace RGB.NET.Presets.Decorators /// : 360 unit = 1 offset. /// : 1 unit = 1 degree. /// - public double Speed { get; set; } + public float Speed { get; set; } // ReSharper restore MemberCanBePrivate.Global // ReSharper restore AutoPropertyCanBeMadeGetOnly.Global @@ -44,7 +44,7 @@ namespace RGB.NET.Presets.Decorators /// : 1 unit = 1 degree. /// The direction the is moved. /// True leads to an offset-increment (normaly moving to the right), false to an offset-decrement (normaly moving to the left). - public MoveGradientDecorator(RGBSurface surface, double speed = 180.0, bool direction = true) + public MoveGradientDecorator(RGBSurface surface, float speed = 180.0f, bool direction = true) : base(surface) { this.Speed = speed; @@ -58,7 +58,7 @@ namespace RGB.NET.Presets.Decorators /// protected override void Update(double deltaTime) { - double movement = Speed * deltaTime; + float movement = Speed * (float)deltaTime; if (!Direction) movement = -movement; diff --git a/RGB.NET.Presets/Helper/GradientHelper.cs b/RGB.NET.Presets/Helper/GradientHelper.cs index 32a10c3..6254fe5 100644 --- a/RGB.NET.Presets/Helper/GradientHelper.cs +++ b/RGB.NET.Presets/Helper/GradientHelper.cs @@ -20,7 +20,7 @@ namespace RGB.NET.Presets.Helper /// The end of the gradient. /// The on the gradient to which the offset is calculated. /// The offset of the on the gradient. - public static double CalculateLinearGradientOffset(in Point startPoint, in Point endPoint, in Point point) + public static float CalculateLinearGradientOffset(in Point startPoint, in Point endPoint, in Point point) { Point intersectingPoint; if (startPoint.Y.EqualsInTolerance(endPoint.Y)) // Horizontal case @@ -31,20 +31,20 @@ namespace RGB.NET.Presets.Helper else // Diagonal case { - double slope = (endPoint.Y - startPoint.Y) / (endPoint.X - startPoint.X); - double orthogonalSlope = -1 / slope; + float slope = (endPoint.Y - startPoint.Y) / (endPoint.X - startPoint.X); + float orthogonalSlope = -1 / slope; - double startYIntercept = startPoint.Y - (slope * startPoint.X); - double pointYIntercept = point.Y - (orthogonalSlope * point.X); + float startYIntercept = startPoint.Y - (slope * startPoint.X); + float pointYIntercept = point.Y - (orthogonalSlope * point.X); - double intersectingPointX = (pointYIntercept - startYIntercept) / (slope - orthogonalSlope); - double intersectingPointY = (slope * intersectingPointX) + startYIntercept; + float intersectingPointX = (pointYIntercept - startYIntercept) / (slope - orthogonalSlope); + float intersectingPointY = (slope * intersectingPointX) + startYIntercept; intersectingPoint = new Point(intersectingPointX, intersectingPointY); } // Calculate distances relative to the vector start - double intersectDistance = CalculateDistance(intersectingPoint, startPoint, endPoint); - double gradientLength = CalculateDistance(endPoint, startPoint, endPoint); + float intersectDistance = CalculateDistance(intersectingPoint, startPoint, endPoint); + float gradientLength = CalculateDistance(endPoint, startPoint, endPoint); return intersectDistance / gradientLength; } @@ -57,9 +57,9 @@ namespace RGB.NET.Presets.Helper /// The origin of the vector. /// The direction of the vector. /// The signed magnitude of a on a vector. - public static double CalculateDistance(in Point point, in Point origin, in Point direction) + public static float CalculateDistance(in Point point, in Point origin, in Point direction) { - double distance = CalculateDistance(point, origin); + float distance = CalculateDistance(point, origin); return (((point.Y < origin.Y) && (direction.Y > origin.Y)) || ((point.Y > origin.Y) && (direction.Y < origin.Y)) @@ -74,11 +74,11 @@ namespace RGB.NET.Presets.Helper /// The first . /// The second . /// The distance between the two . - public static double CalculateDistance(in Point point1, in Point point2) + public static float CalculateDistance(in Point point1, in Point point2) { - double x = point1.X - point2.X; - double y = point1.Y - point2.Y; - return Math.Sqrt((y * y) + (x * x)); + float x = point1.X - point2.X; + float y = point1.Y - point2.Y; + return MathF.Sqrt((y * y) + (x * x)); } #endregion diff --git a/RGB.NET.Presets/Textures/ConicalGradientTexture.cs b/RGB.NET.Presets/Textures/ConicalGradientTexture.cs index 4b824a2..cf53ae4 100644 --- a/RGB.NET.Presets/Textures/ConicalGradientTexture.cs +++ b/RGB.NET.Presets/Textures/ConicalGradientTexture.cs @@ -18,23 +18,23 @@ namespace RGB.NET.Presets.Textures { #region Constants - private const double PI2 = Math.PI * 2; + private const float PI2 = MathF.PI * 2.0f; #endregion #region Properties & Fields - private double _origin = Math.Atan2(-1, 0); + private float _origin = MathF.Atan2(-1, 0); /// /// Gets or sets the origin (radian-angle) this is drawn to. (default: -π/2) /// - public double Origin + public float Origin { get => _origin; set => SetProperty(ref _origin, value); } - private Point _center = new(0.5, 0.5); + private Point _center = new(0.5f, 0.5f); /// /// Gets or sets the center (as percentage in the range [0..1]) of the drawn by this . (default: 0.5, 0.5) /// @@ -86,9 +86,9 @@ namespace RGB.NET.Presets.Textures protected override Color GetColor(in Point point) { - double angle = Math.Atan2(point.Y - Center.Y, point.X - Center.X) - Origin; + float angle = MathF.Atan2(point.Y - Center.Y, point.X - Center.X) - Origin; if (angle < 0) angle += PI2; - double offset = angle / PI2; + float offset = angle / PI2; return Gradient.GetColor(offset); } diff --git a/RGB.NET.Presets/Textures/Gradients/AbstractGradient.cs b/RGB.NET.Presets/Textures/Gradients/AbstractGradient.cs index 5271754..e52788c 100644 --- a/RGB.NET.Presets/Textures/Gradients/AbstractGradient.cs +++ b/RGB.NET.Presets/Textures/Gradients/AbstractGradient.cs @@ -96,23 +96,23 @@ namespace RGB.NET.Presets.Textures.Gradients ///
/// /// - protected double ClipOffset(double offset) + protected float ClipOffset(float offset) { - double max = GradientStops.Max(stop => stop.Offset); + float max = GradientStops.Max(stop => stop.Offset); if (offset > max) return max; - double min = GradientStops.Min(stop => stop.Offset); + float min = GradientStops.Min(stop => stop.Offset); return offset < min ? min : offset; } /// - public abstract Color GetColor(double offset); + public abstract Color GetColor(float offset); /// - public virtual void Move(double offset) + public virtual void Move(float offset) { - offset /= 360.0; + offset /= 360.0f; foreach (GradientStop gradientStop in GradientStops) gradientStop.Offset += offset; diff --git a/RGB.NET.Presets/Textures/Gradients/GradientStop.cs b/RGB.NET.Presets/Textures/Gradients/GradientStop.cs index 7626bcb..aba665d 100644 --- a/RGB.NET.Presets/Textures/Gradients/GradientStop.cs +++ b/RGB.NET.Presets/Textures/Gradients/GradientStop.cs @@ -12,11 +12,11 @@ namespace RGB.NET.Presets.Textures.Gradients { #region Properties & Fields - private double _offset; + private float _offset; /// /// Gets or sets the percentage offset to place this . This should be inside the range of [0..1] but it's not necessary. /// - public double Offset + public float Offset { get => _offset; set => SetProperty(ref _offset, value); @@ -41,7 +41,7 @@ namespace RGB.NET.Presets.Textures.Gradients ///
/// The percentage offset to place this . /// The of the . - public GradientStop(double offset, Color color) + public GradientStop(float offset, Color color) { this.Offset = offset; this.Color = color; diff --git a/RGB.NET.Presets/Textures/Gradients/IGradient.cs b/RGB.NET.Presets/Textures/Gradients/IGradient.cs index 58824da..1917256 100644 --- a/RGB.NET.Presets/Textures/Gradients/IGradient.cs +++ b/RGB.NET.Presets/Textures/Gradients/IGradient.cs @@ -19,12 +19,12 @@ namespace RGB.NET.Presets.Textures.Gradients ///
/// The percentage offset to take the from. /// The at the specific offset. - Color GetColor(double offset); + Color GetColor(float offset); /// /// Moves the by the provided offset. /// /// The offset the should be moved. - void Move(double offset); + void Move(float offset); } } diff --git a/RGB.NET.Presets/Textures/Gradients/LinearGradient.cs b/RGB.NET.Presets/Textures/Gradients/LinearGradient.cs index 716f579..2aa898e 100644 --- a/RGB.NET.Presets/Textures/Gradients/LinearGradient.cs +++ b/RGB.NET.Presets/Textures/Gradients/LinearGradient.cs @@ -83,7 +83,7 @@ namespace RGB.NET.Presets.Textures.Gradients ///
/// The percentage offset to take the color from. /// The at the specific offset. - public override Color GetColor(double offset) + public override Color GetColor(float offset) { if (GradientStops.Count == 0) return Color.Transparent; if (GradientStops.Count == 1) return GradientStops[0].Color; @@ -93,14 +93,14 @@ namespace RGB.NET.Presets.Textures.Gradients (GradientStop gsBefore, GradientStop gsAfter) = GetEnclosingGradientStops(offset, _orderedGradientStops, WrapGradient); - double blendFactor = 0; + float blendFactor = 0; if (!gsBefore.Offset.Equals(gsAfter.Offset)) blendFactor = ((offset - gsBefore.Offset) / (gsAfter.Offset - gsBefore.Offset)); - double colA = ((gsAfter.Color.A - gsBefore.Color.A) * blendFactor) + gsBefore.Color.A; - double colR = ((gsAfter.Color.R - gsBefore.Color.R) * blendFactor) + gsBefore.Color.R; - double colG = ((gsAfter.Color.G - gsBefore.Color.G) * blendFactor) + gsBefore.Color.G; - double colB = ((gsAfter.Color.B - gsBefore.Color.B) * blendFactor) + gsBefore.Color.B; + float colA = ((gsAfter.Color.A - gsBefore.Color.A) * blendFactor) + gsBefore.Color.A; + float colR = ((gsAfter.Color.R - gsBefore.Color.R) * blendFactor) + gsBefore.Color.R; + float colG = ((gsAfter.Color.G - gsBefore.Color.G) * blendFactor) + gsBefore.Color.G; + float colB = ((gsAfter.Color.B - gsBefore.Color.B) * blendFactor) + gsBefore.Color.B; return new Color(colA, colR, colG, colB); } @@ -112,7 +112,7 @@ namespace RGB.NET.Presets.Textures.Gradients /// The ordered list of to choose from. /// Bool indicating if the gradient should be wrapped or not. /// - protected virtual (GradientStop gsBefore, GradientStop gsAfter) GetEnclosingGradientStops(double offset, LinkedList orderedStops, bool wrap) + protected virtual (GradientStop gsBefore, GradientStop gsAfter) GetEnclosingGradientStops(float offset, LinkedList orderedStops, bool wrap) { LinkedList gradientStops = new(orderedStops); diff --git a/RGB.NET.Presets/Textures/Gradients/RainbowGradient.cs b/RGB.NET.Presets/Textures/Gradients/RainbowGradient.cs index 90c867e..1ec32e2 100644 --- a/RGB.NET.Presets/Textures/Gradients/RainbowGradient.cs +++ b/RGB.NET.Presets/Textures/Gradients/RainbowGradient.cs @@ -17,21 +17,21 @@ namespace RGB.NET.Presets.Textures.Gradients { #region Properties & Fields - private double _startHue; + private float _startHue; /// /// Gets or sets the hue (in degrees) to start from. /// - public double StartHue + public float StartHue { get => _startHue; set => SetProperty(ref _startHue, value); } - private double _endHue; + private float _endHue; /// /// Gets or sets the hue (in degrees) to end the with. /// - public double EndHue + public float EndHue { get => _endHue; set => SetProperty(ref _endHue, value); @@ -53,7 +53,7 @@ namespace RGB.NET.Presets.Textures.Gradients ///
/// The hue (in degrees) to start from (default: 0) /// The hue (in degrees) to end with (default: 360) - public RainbowGradient(double startHue = 0, double endHue = 360) + public RainbowGradient(float startHue = 0, float endHue = 360) { this.StartHue = startHue; this.EndHue = endHue; @@ -71,15 +71,15 @@ namespace RGB.NET.Presets.Textures.Gradients ///
/// The percentage offset to take the color from. /// The color at the specific offset. - public Color GetColor(double offset) + public Color GetColor(float offset) { - double range = EndHue - StartHue; - double hue = StartHue + (range * offset); + float range = EndHue - StartHue; + float hue = StartHue + (range * offset); return HSVColor.Create(hue, 1, 1); } /// - public void Move(double offset) + public void Move(float offset) { // RainbowGradient is calculated inverse offset *= -1; diff --git a/RGB.NET.Presets/Textures/LinearGradientTexture.cs b/RGB.NET.Presets/Textures/LinearGradientTexture.cs index ae82546..d37bf6a 100644 --- a/RGB.NET.Presets/Textures/LinearGradientTexture.cs +++ b/RGB.NET.Presets/Textures/LinearGradientTexture.cs @@ -19,7 +19,7 @@ namespace RGB.NET.Presets.Textures { #region Properties & Fields - private Point _startPoint = new(0, 0.5); + private Point _startPoint = new(0, 0.5f); /// /// Gets or sets the start (as percentage in the range [0..1]) of the drawn by this . (default: 0.0, 0.5) /// @@ -29,7 +29,7 @@ namespace RGB.NET.Presets.Textures set => SetProperty(ref _startPoint, value); } - private Point _endPoint = new(1, 0.5); + private Point _endPoint = new(1, 0.5f); /// /// Gets or sets the end (as percentage in the range [0..1]) of the drawn by this . (default: 1.0, 0.5) /// @@ -70,7 +70,7 @@ namespace RGB.NET.Presets.Textures protected override Color GetColor(in Point point) { - double offset = GradientHelper.CalculateLinearGradientOffset(StartPoint, EndPoint, point); + float offset = GradientHelper.CalculateLinearGradientOffset(StartPoint, EndPoint, point); return Gradient.GetColor(offset); } diff --git a/RGB.NET.Presets/Textures/RadialGradientTexture.cs b/RGB.NET.Presets/Textures/RadialGradientTexture.cs index 0e335a9..b5ff848 100644 --- a/RGB.NET.Presets/Textures/RadialGradientTexture.cs +++ b/RGB.NET.Presets/Textures/RadialGradientTexture.cs @@ -16,9 +16,9 @@ namespace RGB.NET.Presets.Textures { #region Properties & Fields - private double _referenceDistance = GradientHelper.CalculateDistance(new Point(0.5, 0.5), new Point(0, 0)); + private float _referenceDistance = GradientHelper.CalculateDistance(new Point(0.5f, 0.5f), new Point(0, 0)); - private Point _center = new(0.5, 0.5); + private Point _center = new(0.5f, 0.5f); /// /// Gets or sets the center (as percentage in the range [0..1]) around which the should be drawn. (default: 0.5, 0.5) /// @@ -61,15 +61,15 @@ namespace RGB.NET.Presets.Textures private void CalculateReferenceDistance() { - double referenceX = Center.X < 0.5 ? 1 : 0; - double referenceY = Center.Y < 0.5 ? 1 : 0; + float referenceX = Center.X < 0.5f ? 1 : 0; + float referenceY = Center.Y < 0.5f ? 1 : 0; _referenceDistance = GradientHelper.CalculateDistance(new Point(referenceX, referenceY), Center); } protected override Color GetColor(in Point point) { - double distance = GradientHelper.CalculateDistance(point, Center); - double offset = distance / _referenceDistance; + float distance = GradientHelper.CalculateDistance(point, Center); + float offset = distance / _referenceDistance; return Gradient.GetColor(offset); } diff --git a/Tests/RGB.NET.Core.Tests/Color/ColorTest.cs b/Tests/RGB.NET.Core.Tests/Color/ColorTest.cs index bd0fda1..67b5b77 100644 --- a/Tests/RGB.NET.Core.Tests/Color/ColorTest.cs +++ b/Tests/RGB.NET.Core.Tests/Color/ColorTest.cs @@ -221,36 +221,36 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void RGBPercentConstructorTest() { - Core.Color color = new(0.25341, 0.55367, 1); + Core.Color color = new(0.25341f, 0.55367f, 1); - Assert.AreEqual(1, color.A, DoubleExtensions.TOLERANCE, "A is not 1"); - Assert.AreEqual(0.25341, color.R, DoubleExtensions.TOLERANCE, "R is not 0.25341"); - Assert.AreEqual(0.55367, color.G, DoubleExtensions.TOLERANCE, "G is not 0.55367"); - Assert.AreEqual(1, color.B, DoubleExtensions.TOLERANCE, "B is not 1"); + Assert.AreEqual(1, color.A, FloatExtensions.TOLERANCE, "A is not 1"); + Assert.AreEqual(0.25341, color.R, FloatExtensions.TOLERANCE, "R is not 0.25341"); + Assert.AreEqual(0.55367, color.G, FloatExtensions.TOLERANCE, "G is not 0.55367"); + Assert.AreEqual(1, color.B, FloatExtensions.TOLERANCE, "B is not 1"); } [TestMethod] public void ARGBPercentConstructorTest() { - Core.Color color = new(0.3315, 0.25341, 0.55367, 1); + Core.Color color = new(0.3315f, 0.25341f, 0.55367f, 1); - Assert.AreEqual(0.3315, color.A, DoubleExtensions.TOLERANCE, "A is not 0.3315"); - Assert.AreEqual(0.25341, color.R, DoubleExtensions.TOLERANCE, "R is not 0.25341"); - Assert.AreEqual(0.55367, color.G, DoubleExtensions.TOLERANCE, "G is not 0.55367"); - Assert.AreEqual(1, color.B, DoubleExtensions.TOLERANCE, "B is not 1"); + Assert.AreEqual(0.3315f, color.A, FloatExtensions.TOLERANCE, "A is not 0.3315"); + Assert.AreEqual(0.25341f, color.R, FloatExtensions.TOLERANCE, "R is not 0.25341"); + Assert.AreEqual(0.55367f, color.G, FloatExtensions.TOLERANCE, "G is not 0.55367"); + Assert.AreEqual(1, color.B, FloatExtensions.TOLERANCE, "B is not 1"); } [TestMethod] public void RGBPercentConstructorClampTest() { - Core.Color color1 = new(1.1, 1.1, 1.1); + Core.Color color1 = new(1.1f, 1.1f, 1.1f); Assert.AreEqual(1, color1.A, "A is not 1"); Assert.AreEqual(1, color1.R, "R is not 1"); Assert.AreEqual(1, color1.G, "G is not 1"); Assert.AreEqual(1, color1.B, "B is not 1"); - Core.Color color2 = new(-1.0, -1.0, -1.0); + Core.Color color2 = new(-1.0f, -1.0f, -1.0f); Assert.AreEqual(1, color2.A, "A is not 1"); Assert.AreEqual(0, color2.R, "R is not 0"); @@ -261,14 +261,14 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void ARGBPercentConstructorClampTest() { - Core.Color color1 = new(1.1, 1.1, 1.1, 1.1); + Core.Color color1 = new(1.1f, 1.1f, 1.1f, 1.1f); Assert.AreEqual(1, color1.A, "A is not 1"); Assert.AreEqual(1, color1.R, "R is not 1"); Assert.AreEqual(1, color1.G, "G is not 1"); Assert.AreEqual(1, color1.B, "B is not 1"); - Core.Color color2 = new(-1.0, -1.0, -1.0, -1.0); + Core.Color color2 = new(-1.0f, -1.0f, -1.0f, -1.0f); Assert.AreEqual(0, color2.A, "A is not 0"); Assert.AreEqual(0, color2.R, "R is not 0"); diff --git a/Tests/RGB.NET.Core.Tests/Color/HSVColorTest.cs b/Tests/RGB.NET.Core.Tests/Color/HSVColorTest.cs index 823a203..7d365c5 100644 --- a/Tests/RGB.NET.Core.Tests/Color/HSVColorTest.cs +++ b/Tests/RGB.NET.Core.Tests/Color/HSVColorTest.cs @@ -12,55 +12,55 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void AddHueTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); Core.Color result = baseColor.AddHSV(hue: 30); - Assert.AreEqual(HSVColor.Create(210, 0.5, 0.5), result); + Assert.AreEqual(HSVColor.Create(210, 0.5f, 0.5f), result); } [TestMethod] public void AddHueWrapTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); Core.Color result = baseColor.AddHSV(hue: 220); - Assert.AreEqual(HSVColor.Create(40, 0.5, 0.5), result); + Assert.AreEqual(HSVColor.Create(40, 0.5f, 0.5f), result); } [TestMethod] public void AddSaturationTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); - Core.Color result = baseColor.AddHSV(saturation: 0.3); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); + Core.Color result = baseColor.AddHSV(saturation: 0.3f); - Assert.AreEqual(HSVColor.Create(180, 0.8, 0.5), result); + Assert.AreEqual(HSVColor.Create(180, 0.8f, 0.5f), result); } [TestMethod] public void AddSaturationClampTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); - Core.Color result = baseColor.AddHSV(saturation: 0.8); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); + Core.Color result = baseColor.AddHSV(saturation: 0.8f); - Assert.AreEqual(HSVColor.Create(180, 1.0, 0.5), result); + Assert.AreEqual(HSVColor.Create(180, 1.0f, 0.5f), result); } [TestMethod] public void AddValueTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); - Core.Color result = baseColor.AddHSV(value: 0.3); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); + Core.Color result = baseColor.AddHSV(value: 0.3f); - Assert.AreEqual(HSVColor.Create(180, 0.5, 0.8), result); + Assert.AreEqual(HSVColor.Create(180, 0.5f, 0.8f), result); } [TestMethod] public void AddValueClampTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); - Core.Color result = baseColor.AddHSV(value: 0.8); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); + Core.Color result = baseColor.AddHSV(value: 0.8f); - Assert.AreEqual(HSVColor.Create(180, 0.5, 1.0), result); + Assert.AreEqual(HSVColor.Create(180, 0.5f, 1.0f), result); } #endregion @@ -70,55 +70,55 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void SubtractHueTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); Core.Color result = baseColor.SubtractHSV(hue: 30); - Assert.AreEqual(HSVColor.Create(150, 0.5, 0.5), result); + Assert.AreEqual(HSVColor.Create(150, 0.5f, 0.5f), result); } [TestMethod] public void SubtractHueWrapTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); Core.Color result = baseColor.SubtractHSV(hue: 220); - Assert.AreEqual(HSVColor.Create(320, 0.5, 0.5), result); + Assert.AreEqual(HSVColor.Create(320, 0.5f, 0.5f), result); } [TestMethod] public void SubtractSaturationTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); - Core.Color result = baseColor.SubtractHSV(saturation: 0.3); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); + Core.Color result = baseColor.SubtractHSV(saturation: 0.3f); - Assert.AreEqual(HSVColor.Create(180, 0.2, 0.5), result); + Assert.AreEqual(HSVColor.Create(180, 0.2f, 0.5f), result); } [TestMethod] public void SubtractSaturationClampTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); - Core.Color result = baseColor.SubtractHSV(saturation: 0.8); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); + Core.Color result = baseColor.SubtractHSV(saturation: 0.8f); - Assert.AreEqual(HSVColor.Create(180, 0, 0.5), result); + Assert.AreEqual(HSVColor.Create(180, 0, 0.5f), result); } [TestMethod] public void SubtractValueTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); - Core.Color result = baseColor.SubtractHSV(value: 0.3); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); + Core.Color result = baseColor.SubtractHSV(value: 0.3f); - Assert.AreEqual(HSVColor.Create(180, 0.5, 0.2), result); + Assert.AreEqual(HSVColor.Create(180, 0.5f, 0.2f), result); } [TestMethod] public void SubtractValueClampTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); - Core.Color result = baseColor.SubtractHSV(value: .8); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); + Core.Color result = baseColor.SubtractHSV(value: 0.8f); - Assert.AreEqual(HSVColor.Create(180, 0.5, 0), result); + Assert.AreEqual(HSVColor.Create(180, 0.5f, 0), result); } #endregion @@ -128,55 +128,55 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void MultiplyHueTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); - Core.Color result = baseColor.MultiplyHSV(hue: 1.5); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); + Core.Color result = baseColor.MultiplyHSV(hue: 1.5f); - Assert.AreEqual(HSVColor.Create(270, 0.5, 0.5), result); + Assert.AreEqual(HSVColor.Create(270, 0.5f, 0.5f), result); } [TestMethod] public void MultiplyHueWrapTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); Core.Color result = baseColor.MultiplyHSV(hue: 3); - Assert.AreEqual(HSVColor.Create(180, 0.5, 0.5), result); + Assert.AreEqual(HSVColor.Create(180, 0.5f, 0.5f), result); } [TestMethod] public void MultiplySaturationTest() { - Core.Color baseColor = HSVColor.Create(180, 0.2, 0.2); + Core.Color baseColor = HSVColor.Create(180, 0.2f, 0.2f); Core.Color result = baseColor.MultiplyHSV(saturation: 3); - Assert.AreEqual(HSVColor.Create(180, 0.6, 0.2), result); + Assert.AreEqual(HSVColor.Create(180,0.6f, 0.2f), result); } [TestMethod] public void MultiplySaturationClampTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); Core.Color result = baseColor.MultiplyHSV(saturation: 3); - Assert.AreEqual(HSVColor.Create(180, 1.0, 0.5), result); + Assert.AreEqual(HSVColor.Create(180, 1.0f, 0.5f), result); } [TestMethod] public void MultiplyValueTest() { - Core.Color baseColor = HSVColor.Create(180, 0.2, 0.2); + Core.Color baseColor = HSVColor.Create(180, 0.2f, 0.2f); Core.Color result = baseColor.MultiplyHSV(value: 3); - Assert.AreEqual(HSVColor.Create(180, 0.2, 0.6), result); + Assert.AreEqual(HSVColor.Create(180, 0.2f,0.6f), result); } [TestMethod] public void MultiplyValueClampTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); Core.Color result = baseColor.MultiplyHSV(value: 3); - Assert.AreEqual(HSVColor.Create(180, 0.5, 1.0), result); + Assert.AreEqual(HSVColor.Create(180, 0.5f, 1.0f), result); } #endregion @@ -186,28 +186,28 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void DivideHueTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); Core.Color result = baseColor.DivideHSV(hue: 30); - Assert.AreEqual(HSVColor.Create(6, 0.5, 0.5), result); + Assert.AreEqual(HSVColor.Create(6, 0.5f, 0.5f), result); } [TestMethod] public void DivideSaturationTest() { - Core.Color baseColor = HSVColor.Create(180, 0.6, 0.6); + Core.Color baseColor = HSVColor.Create(180,0.6f,0.6f); Core.Color result = baseColor.DivideHSV(saturation: 2); - Assert.AreEqual(HSVColor.Create(180, 0.3, 0.6), result); + Assert.AreEqual(HSVColor.Create(180, 0.3f,0.6f), result); } [TestMethod] public void DivideValueTest() { - Core.Color baseColor = HSVColor.Create(180, 0.6, 0.6); + Core.Color baseColor = HSVColor.Create(180,0.6f,0.6f); Core.Color result = baseColor.DivideHSV(value: 2); - Assert.AreEqual(HSVColor.Create(180, 0.6, 0.3), result); + Assert.AreEqual(HSVColor.Create(180,0.6f, 0.3f), result); } #endregion @@ -217,64 +217,64 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void SetHueTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); Core.Color result = baseColor.SetHSV(hue: 30); - Assert.AreEqual(HSVColor.Create(30, 0.5, 0.5), result); + Assert.AreEqual(HSVColor.Create(30, 0.5f, 0.5f), result); } [TestMethod] public void SetHueWrapTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); Core.Color result = baseColor.SetHSV(hue: 440); - Assert.AreEqual(HSVColor.Create(80, 0.5, 0.5), result); + Assert.AreEqual(HSVColor.Create(80, 0.5f, 0.5f), result); } [TestMethod] public void SetHueWrapNegativeTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); Core.Color result = baseColor.SetHSV(hue: -30); - Assert.AreEqual(HSVColor.Create(330, 0.5, 0.5), result); + Assert.AreEqual(HSVColor.Create(330, 0.5f, 0.5f), result); } [TestMethod] public void SetSaturationTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); - Core.Color result = baseColor.SetHSV(saturation: 0.3); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); + Core.Color result = baseColor.SetHSV(saturation: 0.3f); - Assert.AreEqual(HSVColor.Create(180, 0.3, 0.5), result); + Assert.AreEqual(HSVColor.Create(180, 0.3f, 0.5f), result); } [TestMethod] public void SetSaturationClampTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); Core.Color result = baseColor.SetHSV(saturation: 2); - Assert.AreEqual(HSVColor.Create(180, 1.0, 0.5), result); + Assert.AreEqual(HSVColor.Create(180, 1.0f, 0.5f), result); } [TestMethod] public void SetValueTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); - Core.Color result = baseColor.SetHSV(value: 0.3); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); + Core.Color result = baseColor.SetHSV(value: 0.3f); - Assert.AreEqual(HSVColor.Create(180, 0.5, 0.3), result); + Assert.AreEqual(HSVColor.Create(180, 0.5f, 0.3f), result); } [TestMethod] public void SetValueClampTest() { - Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5); + Core.Color baseColor = HSVColor.Create(180, 0.5f, 0.5f); Core.Color result = baseColor.SetHSV(value: 2); - Assert.AreEqual(HSVColor.Create(180, 0.5, 1.0), result); + Assert.AreEqual(HSVColor.Create(180, 0.5f, 1.0f), result); } #endregion diff --git a/Tests/RGB.NET.Core.Tests/Color/RGBColorTest.cs b/Tests/RGB.NET.Core.Tests/Color/RGBColorTest.cs index 7a9abc9..ea5a1cc 100644 --- a/Tests/RGB.NET.Core.Tests/Color/RGBColorTest.cs +++ b/Tests/RGB.NET.Core.Tests/Color/RGBColorTest.cs @@ -30,19 +30,19 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void BlendUpTest() { - Core.Color baseColor = new(0.0, 0.0, 0.0); - Core.Color blendColor = new(0.5, 1.0, 1.0, 1.0); + Core.Color baseColor = new(0.0f, 0.0f, 0.0f); + Core.Color blendColor = new(0.5f, 1.0f, 1.0f, 1.0f); - Assert.AreEqual(new Core.Color(0.5, 0.5, 0.5), baseColor.Blend(blendColor)); + Assert.AreEqual(new Core.Color(0.5f, 0.5f, 0.5f), baseColor.Blend(blendColor)); } [TestMethod] public void BlendDownTest() { - Core.Color baseColor = new(1.0, 1.0, 1.0); - Core.Color blendColor = new(0.5, 0.0, 0.0, 0.0); + Core.Color baseColor = new(1.0f, 1.0f, 1.0f); + Core.Color blendColor = new(0.5f, 0.0f, 0.0f, 0.0f); - Assert.AreEqual(new Core.Color(0.5, 0.5, 0.5), baseColor.Blend(blendColor)); + Assert.AreEqual(new Core.Color(0.5f, 0.5f, 0.5f), baseColor.Blend(blendColor)); } #endregion @@ -61,10 +61,10 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void AddRGBPercentTest() { - Core.Color baseColor = new(0.5, 0.5, 0.5, 0.5); - Core.Color result = baseColor.AddRGB(0.2, 0.3, 0.4); + Core.Color baseColor = new(0.5f, 0.5f, 0.5f, 0.5f); + Core.Color result = baseColor.AddRGB(0.2f, 0.3f, 0.4f); - Assert.AreEqual(new Core.Color(0.5, 0.7, 0.8, 0.9), result); + Assert.AreEqual(new Core.Color(0.5f, 0.7f, 0.8f, 0.9f), result); } [TestMethod] @@ -79,10 +79,10 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void AddAPercentTest() { - Core.Color baseColor = new(0.5, 0.5, 0.5, 0.5); - Core.Color result = baseColor.AddA(0.1); + Core.Color baseColor = new(0.5f, 0.5f, 0.5f, 0.5f); + Core.Color result = baseColor.AddA(0.1f); - Assert.AreEqual(new Core.Color(0.6, 0.5, 0.5, 0.5), result); + Assert.AreEqual(new Core.Color(0.6f, 0.5f, 0.5f, 0.5f), result); } [TestMethod] @@ -97,10 +97,10 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void AddRPercentTest() { - Core.Color baseColor = new(0.5, 0.5, 0.5, 0.5); - Core.Color result = baseColor.AddRGB(r: 0.1); + Core.Color baseColor = new(0.5f, 0.5f, 0.5f, 0.5f); + Core.Color result = baseColor.AddRGB(r: 0.1f); - Assert.AreEqual(new Core.Color(0.5, 0.6, 0.5, 0.5), result); + Assert.AreEqual(new Core.Color(0.5f, 0.6f, 0.5f, 0.5f), result); } [TestMethod] @@ -115,10 +115,10 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void AddGPercentTest() { - Core.Color baseColor = new(0.5, 0.5, 0.5, 0.5); - Core.Color result = baseColor.AddRGB(g: 0.1); + Core.Color baseColor = new(0.5f, 0.5f, 0.5f, 0.5f); + Core.Color result = baseColor.AddRGB(g: 0.1f); - Assert.AreEqual(new Core.Color(0.5, 0.5, 0.6, 0.5), result); + Assert.AreEqual(new Core.Color(0.5f, 0.5f, 0.6f, 0.5f), result); } [TestMethod] @@ -133,10 +133,10 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void AddBPercentTest() { - Core.Color baseColor = new(0.5, 0.5, 0.5, 0.5); - Core.Color result = baseColor.AddRGB(b: 0.1); + Core.Color baseColor = new(0.5f, 0.5f, 0.5f, 0.5f); + Core.Color result = baseColor.AddRGB(b: 0.1f); - Assert.AreEqual(new Core.Color(0.5, 0.5, 0.5, 0.6), result); + Assert.AreEqual(new Core.Color(0.5f, 0.5f, 0.5f, 0.6f), result); } #endregion @@ -155,10 +155,10 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void SubtractRGBPercentTest() { - Core.Color baseColor = new(0.5, 0.5, 0.5, 0.5); - Core.Color result = baseColor.SubtractRGB(0.2, 0.3, 0.4); + Core.Color baseColor = new(0.5f, 0.5f, 0.5f, 0.5f); + Core.Color result = baseColor.SubtractRGB(0.2f, 0.3f, 0.4f); - Assert.AreEqual(new Core.Color(0.5, 0.3, 0.2, 0.1), result); + Assert.AreEqual(new Core.Color(0.5f, 0.3f, 0.2f, 0.1f), result); } [TestMethod] @@ -173,10 +173,10 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void SubtractAPercentTest() { - Core.Color baseColor = new(0.5, 0.5, 0.5, 0.5); - Core.Color result = baseColor.SubtractA(0.1); + Core.Color baseColor = new(0.5f, 0.5f, 0.5f, 0.5f); + Core.Color result = baseColor.SubtractA(0.1f); - Assert.AreEqual(new Core.Color(0.4, 0.5, 0.5, 0.5), result); + Assert.AreEqual(new Core.Color(0.4f, 0.5f, 0.5f, 0.5f), result); } [TestMethod] @@ -191,10 +191,10 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void SubtractRPercentTest() { - Core.Color baseColor = new(0.5, 0.5, 0.5, 0.5); - Core.Color result = baseColor.SubtractRGB(r: 0.1); + Core.Color baseColor = new(0.5f, 0.5f, 0.5f, 0.5f); + Core.Color result = baseColor.SubtractRGB(r: 0.1f); - Assert.AreEqual(new Core.Color(0.5, 0.4, 0.5, 0.5), result); + Assert.AreEqual(new Core.Color(0.5f, 0.4f, 0.5f, 0.5f), result); } [TestMethod] @@ -209,10 +209,10 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void SubtractGPercentTest() { - Core.Color baseColor = new(0.5, 0.5, 0.5, 0.5); - Core.Color result = baseColor.SubtractRGB(g: 0.1); + Core.Color baseColor = new(0.5f, 0.5f, 0.5f, 0.5f); + Core.Color result = baseColor.SubtractRGB(g: 0.1f); - Assert.AreEqual(new Core.Color(0.5, 0.5, 0.4, 0.5), result); + Assert.AreEqual(new Core.Color(0.5f, 0.5f, 0.4f, 0.5f), result); } [TestMethod] @@ -227,10 +227,10 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void SubtractBPercentTest() { - Core.Color baseColor = new(0.5, 0.5, 0.5, 0.5); - Core.Color result = baseColor.SubtractRGB(b: 0.1); + Core.Color baseColor = new(0.5f, 0.5f, 0.5f, 0.5f); + Core.Color result = baseColor.SubtractRGB(b: 0.1f); - Assert.AreEqual(new Core.Color(0.5, 0.5, 0.5, 0.4), result); + Assert.AreEqual(new Core.Color(0.5f, 0.5f, 0.5f, 0.4f), result); } #endregion @@ -240,46 +240,46 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void MultiplyRGBPercentTest() { - Core.Color baseColor = new(0.2, 0.2, 0.2, 0.2); + Core.Color baseColor = new(0.2f, 0.2f, 0.2f, 0.2f); Core.Color result = baseColor.MultiplyRGB(3, 4, 5); - Assert.AreEqual(new Core.Color(0.2, 0.6, 0.8, 1.0), result); + Assert.AreEqual(new Core.Color(0.2f, 0.6f, 0.8f, 1.0f), result); } [TestMethod] public void MultiplyAPercentTest() { - Core.Color baseColor = new(0.2, 0.2, 0.2, 0.2); + Core.Color baseColor = new(0.2f, 0.2f, 0.2f, 0.2f); Core.Color result = baseColor.MultiplyA(3); - Assert.AreEqual(new Core.Color(0.6, 0.2, 0.2, 0.2), result); + Assert.AreEqual(new Core.Color(0.6f, 0.2f, 0.2f, 0.2f), result); } [TestMethod] public void MultiplyRPercentTest() { - Core.Color baseColor = new(0.2, 0.2, 0.2, 0.2); + Core.Color baseColor = new(0.2f, 0.2f, 0.2f, 0.2f); Core.Color result = baseColor.MultiplyRGB(r: 3); - Assert.AreEqual(new Core.Color(0.2, 0.6, 0.2, 0.2), result); + Assert.AreEqual(new Core.Color(0.2f, 0.6f, 0.2f, 0.2f), result); } [TestMethod] public void MultiplyGPercentTest() { - Core.Color baseColor = new(0.2, 0.2, 0.2, 0.2); + Core.Color baseColor = new(0.2f, 0.2f, 0.2f, 0.2f); Core.Color result = baseColor.MultiplyRGB(g: 3); - Assert.AreEqual(new Core.Color(0.2, 0.2, 0.6, 0.2), result); + Assert.AreEqual(new Core.Color(0.2f, 0.2f, 0.6f, 0.2f), result); } [TestMethod] public void MultiplyBPercentTest() { - Core.Color baseColor = new(0.2, 0.2, 0.2, 0.2); + Core.Color baseColor = new(0.2f, 0.2f, 0.2f, 0.2f); Core.Color result = baseColor.MultiplyRGB(b: 3); - Assert.AreEqual(new Core.Color(0.2, 0.2, 0.2, 0.6), result); + Assert.AreEqual(new Core.Color(0.2f, 0.2f, 0.2f, 0.6f), result); } #endregion @@ -289,46 +289,46 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void DivideRGBPercentTest() { - Core.Color baseColor = new(0.2, 0.6, 0.8, 1.0); + Core.Color baseColor = new(0.2f, 0.6f, 0.8f, 1.0f); Core.Color result = baseColor.DivideRGB(3, 4, 5); - Assert.AreEqual(new Core.Color(0.2, 0.2, 0.2, 0.2), result); + Assert.AreEqual(new Core.Color(0.2f, 0.2f, 0.2f, 0.2f), result); } [TestMethod] public void DivideAPercentTest() { - Core.Color baseColor = new(0.6, 0.2, 0.2, 0.2); + Core.Color baseColor = new(0.6f, 0.2f, 0.2f, 0.2f); Core.Color result = baseColor.DivideA(3); - Assert.AreEqual(new Core.Color(0.2, 0.2, 0.2, 0.2), result); + Assert.AreEqual(new Core.Color(0.2f, 0.2f, 0.2f, 0.2f), result); } [TestMethod] public void DivideRPercentTest() { - Core.Color baseColor = new(0.2, 0.6, 0.2, 0.2); + Core.Color baseColor = new(0.2f, 0.6f, 0.2f, 0.2f); Core.Color result = baseColor.DivideRGB(r: 3); - Assert.AreEqual(new Core.Color(0.2, 0.2, 0.2, 0.2), result); + Assert.AreEqual(new Core.Color(0.2f, 0.2f, 0.2f, 0.2f), result); } [TestMethod] public void DivideGPercentTest() { - Core.Color baseColor = new(0.2, 0.2, 0.6, 0.2); + Core.Color baseColor = new(0.2f, 0.2f, 0.6f, 0.2f); Core.Color result = baseColor.DivideRGB(g: 3); - Assert.AreEqual(new Core.Color(0.2, 0.2, 0.2, 0.2), result); + Assert.AreEqual(new Core.Color(0.2f, 0.2f, 0.2f, 0.2f), result); } [TestMethod] public void DivideBPercentTest() { - Core.Color baseColor = new(0.2, 0.2, 0.2, 0.6); + Core.Color baseColor = new(0.2f, 0.2f, 0.2f, 0.6f); Core.Color result = baseColor.DivideRGB(b: 3); - Assert.AreEqual(new Core.Color(0.2, 0.2, 0.2, 0.2), result); + Assert.AreEqual(new Core.Color(0.2f, 0.2f, 0.2f, 0.2f), result); } #endregion @@ -347,10 +347,10 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void SetRGBPercentTest() { - Core.Color baseColor = new(0.5, 0.5, 0.5, 0.5); - Core.Color result = baseColor.SetRGB(0.2, 0.3, 0.4); + Core.Color baseColor = new(0.5f, 0.5f, 0.5f, 0.5f); + Core.Color result = baseColor.SetRGB(0.2f, 0.3f, 0.4f); - Assert.AreEqual(new Core.Color(0.5, 0.2, 0.3, 0.4), result); + Assert.AreEqual(new Core.Color(0.5f, 0.2f, 0.3f, 0.4f), result); } [TestMethod] @@ -365,10 +365,10 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void SetAPercentTest() { - Core.Color baseColor = new(0.5, 0.5, 0.5, 0.5); - Core.Color result = baseColor.SetA(0.1); + Core.Color baseColor = new(0.5f, 0.5f, 0.5f, 0.5f); + Core.Color result = baseColor.SetA(0.1f); - Assert.AreEqual(new Core.Color(0.1, 0.5, 0.5, 0.5), result); + Assert.AreEqual(new Core.Color(0.1f, 0.5f, 0.5f, 0.5f), result); } [TestMethod] @@ -383,10 +383,10 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void SetRPercentTest() { - Core.Color baseColor = new(0.5, 0.5, 0.5, 0.5); - Core.Color result = baseColor.SetRGB(r: 0.1); + Core.Color baseColor = new(0.5f, 0.5f, 0.5f, 0.5f); + Core.Color result = baseColor.SetRGB(r: 0.1f); - Assert.AreEqual(new Core.Color(0.5, 0.1, 0.5, 0.5), result); + Assert.AreEqual(new Core.Color(0.5f, 0.1f, 0.5f, 0.5f), result); } [TestMethod] @@ -401,10 +401,10 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void SetGPercentTest() { - Core.Color baseColor = new(0.5, 0.5, 0.5, 0.5); - Core.Color result = baseColor.SetRGB(g: 0.1); + Core.Color baseColor = new(0.5f, 0.5f, 0.5f, 0.5f); + Core.Color result = baseColor.SetRGB(g: 0.1f); - Assert.AreEqual(new Core.Color(0.5, 0.5, 0.1, 0.5), result); + Assert.AreEqual(new Core.Color(0.5f, 0.5f, 0.1f, 0.5f), result); } [TestMethod] @@ -419,10 +419,10 @@ namespace RGB.NET.Core.Tests.Color [TestMethod] public void SetBPercentTest() { - Core.Color baseColor = new(0.5, 0.5, 0.5, 0.5); - Core.Color result = baseColor.SetRGB(b: 0.1); + Core.Color baseColor = new(0.5f, 0.5f, 0.5f, 0.5f); + Core.Color result = baseColor.SetRGB(b: 0.1f); - Assert.AreEqual(new Core.Color(0.5, 0.5, 0.5, 0.1), result); + Assert.AreEqual(new Core.Color(0.5f, 0.5f, 0.5f, 0.1f), result); } #endregion From 520fb386026f1742bec07558870cacb58d6648e0 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Mon, 22 Feb 2021 00:46:48 +0100 Subject: [PATCH 03/22] Added generic base-class for PixelTexture --- .../Rendering/Textures/PixelTexture.cs | 70 +++++++++++++------ 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/RGB.NET.Core/Rendering/Textures/PixelTexture.cs b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs index 1f4afb6..d5b6bab 100644 --- a/RGB.NET.Core/Rendering/Textures/PixelTexture.cs +++ b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs @@ -1,15 +1,14 @@ using System; +using System.Runtime.CompilerServices; namespace RGB.NET.Core { - public sealed class PixelTexture : ITexture + public abstract class PixelTexture : ITexture { #region Properties & Fields - private readonly int _dataWidth; - private readonly int _dataHeight; - private readonly ReadOnlyMemory _data; - private readonly ISampler _sampler; + protected ISampler Sampler { get; set; } + protected T[] Data { get; set; } public Size Size { get; } @@ -17,12 +16,11 @@ namespace RGB.NET.Core { get { - if (_data.IsEmpty) return Color.Transparent; + if (Data.Length == 0) return Color.Transparent; int x = (int)Math.Round(Size.Width * point.X.Clamp(0, 1)); int y = (int)Math.Round(Size.Height * point.Y.Clamp(0, 1)); - - return _data.Span[(y * _dataWidth) + x]; + return GetColor(x, y); } } @@ -30,14 +28,14 @@ namespace RGB.NET.Core { get { - if (_data.IsEmpty) return Color.Transparent; + if (Data.Length == 0) return Color.Transparent; int x = (int)Math.Round(Size.Width * rectangle.Location.X.Clamp(0, 1)); int y = (int)Math.Round(Size.Height * rectangle.Location.Y.Clamp(0, 1)); int width = (int)Math.Round(Size.Width * rectangle.Size.Width.Clamp(0, 1)); int height = (int)Math.Round(Size.Height * rectangle.Size.Height.Clamp(0, 1)); - return _sampler.SampleColor(in _data, x, y, width, height); + return Sampler.SampleColor(x, y, width, height, GetColor); } } @@ -45,22 +43,52 @@ namespace RGB.NET.Core #region Constructors - public PixelTexture(int with, int height, ReadOnlyMemory data) - : this(with, height, data, new AverageSampler()) - { } - - public PixelTexture(int with, int height, ReadOnlyMemory data, ISampler sampler) + public PixelTexture(int with, int height, T[] data, ISampler sampler) { - this._data = data; - this._dataWidth = with; - this._dataHeight = height; - this._sampler = sampler; - - if (_data.Length != (with * height)) throw new ArgumentException($"Data-Length {_data.Length} differs from the given size {with}x{height} ({with * height})."); + this.Data = data; + this.Sampler = sampler; Size = new Size(with, height); } #endregion + + #region Methods + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected abstract Color GetColor(int x, int y); + + #endregion + } + + public sealed class PixelTexture : PixelTexture + { + #region Properties & Fields + + private readonly int _stride; + + #endregion + + #region Constructors + + public PixelTexture(int with, int height, Color[] data) + : this(with, height, data, new AverageSampler()) + { } + + public PixelTexture(int with, int height, Color[] data, ISampler sampler) + : base(with, height, data, sampler) + { + this._stride = with; + + if (Data.Length != (with * height)) throw new ArgumentException($"Data-Length {Data.Length} differs from the given size {with}x{height} ({with * height})."); + } + + #endregion + + #region Methods + + protected override Color GetColor(int x, int y) => Data[(y * _stride) + x]; + + #endregion } } From dade203c943b65f68ae61957341c3f6e0bf7502c Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Mon, 22 Feb 2021 21:09:51 +0100 Subject: [PATCH 04/22] Changed Brush Render-Method to be virtual; Added list not empty check to Decorator application --- RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs b/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs index 77a39e6..782c496 100644 --- a/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs +++ b/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs @@ -47,7 +47,7 @@ namespace RGB.NET.Core #region Methods - public IEnumerable<(RenderTarget renderTarget, Color color)> Render(Rectangle rectangle, IEnumerable renderTargets) + public virtual IEnumerable<(RenderTarget renderTarget, Color color)> Render(Rectangle rectangle, IEnumerable renderTargets) { foreach (RenderTarget renderTarget in renderTargets) { @@ -66,6 +66,8 @@ namespace RGB.NET.Core /// The to be modified. protected virtual void ApplyDecorators(in Rectangle rectangle, in RenderTarget renderTarget, ref Color color) { + if (Decorators.Count == 0) return; + lock (Decorators) foreach (IBrushDecorator decorator in Decorators) if (decorator.IsEnabled) From 34a2acc6c4b65e606281547a1332cb4c556060db Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Mon, 22 Feb 2021 21:53:48 +0100 Subject: [PATCH 05/22] Added missing in-parameters --- .../Color/Behaviors/DefaultColorBehavior.cs | 12 ++--- .../Color/Behaviors/IColorBehavior.cs | 8 +-- RGB.NET.Core/Color/Color.cs | 13 ++--- RGB.NET.Core/Color/HSVColor.cs | 18 +++---- RGB.NET.Core/Color/RGBColor.cs | 50 +++++++++---------- RGB.NET.Core/Devices/AbstractRGBDevice.cs | 2 +- RGB.NET.Core/Devices/IRGBDevice.cs | 2 +- RGB.NET.Core/Extensions/ColorExtensions.cs | 2 +- RGB.NET.Core/Extensions/MathExtensions.cs | 2 +- RGB.NET.Core/Extensions/PointExtensions.cs | 14 ++++-- .../Extensions/RectangleExtensions.cs | 28 +++++------ RGB.NET.Core/Positioning/Point.cs | 19 +++---- RGB.NET.Core/Positioning/Rectangle.cs | 8 +-- RGB.NET.Core/Positioning/Rotation.cs | 14 +++--- RGB.NET.Core/Positioning/Size.cs | 23 +++++---- Tests/RGB.NET.Core.Tests/Color/ColorTest.cs | 24 ++++----- 16 files changed, 123 insertions(+), 116 deletions(-) diff --git a/RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs b/RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs index 53289c6..48ef24f 100644 --- a/RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs +++ b/RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs @@ -8,18 +8,18 @@ /// Converts the individual byte values of this to a human-readable string. ///
/// A string that contains the individual byte values of this . For example "[A: 255, R: 255, G: 0, B: 0]". - public virtual string ToString(Color color) => $"[A: {color.GetA()}, R: {color.GetR()}, G: {color.GetG()}, B: {color.GetB()}]"; + public virtual string ToString(in Color color) => $"[A: {color.GetA()}, R: {color.GetR()}, G: {color.GetG()}, B: {color.GetB()}]"; /// /// Tests whether the specified object is a and is equivalent to this . /// /// The object to test. /// true if is a equivalent to this ; otherwise, false. - public virtual bool Equals(Color color, object? obj) + public virtual bool Equals(in Color color, object? obj) { - if (!(obj is Color)) return false; + if (!(obj is Color color2)) return false; - (float a, float r, float g, float b) = ((Color)obj).GetRGB(); + (float a, float r, float g, float b) = color2.GetRGB(); return color.A.EqualsInTolerance(a) && color.R.EqualsInTolerance(r) && color.G.EqualsInTolerance(g) && color.B.EqualsInTolerance(b); } @@ -27,7 +27,7 @@ /// Returns a hash code for this . ///
/// An integer value that specifies the hash code for this . - public virtual int GetHashCode(Color color) + public virtual int GetHashCode(in Color color) { unchecked { @@ -43,7 +43,7 @@ /// Blends a over this color. ///
/// The to blend. - public virtual Color Blend(Color baseColor, Color blendColor) + public virtual Color Blend(in Color baseColor, in Color blendColor) { if (blendColor.A.EqualsInTolerance(0)) return baseColor; diff --git a/RGB.NET.Core/Color/Behaviors/IColorBehavior.cs b/RGB.NET.Core/Color/Behaviors/IColorBehavior.cs index 3ee7b78..0e4a23f 100644 --- a/RGB.NET.Core/Color/Behaviors/IColorBehavior.cs +++ b/RGB.NET.Core/Color/Behaviors/IColorBehavior.cs @@ -2,12 +2,12 @@ { public interface IColorBehavior { - string ToString(Color color); + string ToString(in Color color); - bool Equals(Color color, object? obj); + bool Equals(in Color color, object? obj); - int GetHashCode(Color color); + int GetHashCode(in Color color); - Color Blend(Color baseColor, Color blendColor); + Color Blend(in Color baseColor, in Color blendColor); } } diff --git a/RGB.NET.Core/Color/Color.cs b/RGB.NET.Core/Color/Color.cs index 0948c47..9e8f83e 100644 --- a/RGB.NET.Core/Color/Color.cs +++ b/RGB.NET.Core/Color/Color.cs @@ -15,10 +15,11 @@ namespace RGB.NET.Core { #region Constants + private static readonly Color TRANSPARENT = new(0, 0, 0, 0); /// /// Gets an transparent color [A: 0, R: 0, G: 0, B: 0] /// - public static Color Transparent => new(0, 0, 0, 0); + public static ref readonly Color Transparent => ref TRANSPARENT; #endregion @@ -174,7 +175,7 @@ namespace RGB.NET.Core /// Initializes a new instance of the struct by cloning a existing . ///
/// The the values are copied from. - public Color(Color color) + public Color(in Color color) : this(color.A, color.R, color.G, color.B) { } @@ -206,7 +207,7 @@ namespace RGB.NET.Core /// Blends a over this color, as defined by the current . ///
/// The to blend. - public Color Blend(Color color) => Behavior.Blend(this, color); + public Color Blend(in Color color) => Behavior.Blend(this, color); #endregion @@ -218,7 +219,7 @@ namespace RGB.NET.Core /// The base color. /// The color to blend. /// The blended color. - public static Color operator +(Color color1, Color color2) => color1.Blend(color2); + public static Color operator +(in Color color1, in Color color2) => color1.Blend(color2); /// /// Returns a value that indicates whether two specified are equal. @@ -226,7 +227,7 @@ namespace RGB.NET.Core /// The first to compare. /// The second to compare. /// true if and are equal; otherwise, false. - public static bool operator ==(Color color1, Color color2) => color1.Equals(color2); + public static bool operator ==(in Color color1, in Color color2) => color1.Equals(color2); /// /// Returns a value that indicates whether two specified are equal. @@ -234,7 +235,7 @@ namespace RGB.NET.Core /// The first to compare. /// The second to compare. /// true if and are not equal; otherwise, false. - public static bool operator !=(Color color1, Color color2) => !(color1 == color2); + public static bool operator !=(in Color color1, in Color color2) => !(color1 == color2); /// /// Converts a of ARGB-components to a . diff --git a/RGB.NET.Core/Color/HSVColor.cs b/RGB.NET.Core/Color/HSVColor.cs index 40c89c8..492742f 100644 --- a/RGB.NET.Core/Color/HSVColor.cs +++ b/RGB.NET.Core/Color/HSVColor.cs @@ -13,21 +13,21 @@ namespace RGB.NET.Core /// /// /// - public static float GetHue(this Color color) => color.GetHSV().hue; + public static float GetHue(this in Color color) => color.GetHSV().hue; /// /// Gets the saturation component value (HSV-color space) of this in the range [0..1]. /// /// /// - public static float GetSaturation(this Color color) => color.GetHSV().saturation; + public static float GetSaturation(this in Color color) => color.GetHSV().saturation; /// /// Gets the value component value (HSV-color space) of this in the range [0..1]. /// /// /// - public static float GetValue(this Color color) => color.GetHSV().value; + public static float GetValue(this in Color color) => color.GetHSV().value; /// /// Gets the hue, saturation and value component values (HSV-color space) of this . @@ -37,7 +37,7 @@ namespace RGB.NET.Core /// /// /// - public static (float hue, float saturation, float value) GetHSV(this Color color) + public static (float hue, float saturation, float value) GetHSV(this in Color color) => CaclulateHSVFromRGB(color.R, color.G, color.B); #endregion @@ -51,7 +51,7 @@ namespace RGB.NET.Core /// The saturation value to add. /// The value value to add. /// The new color after the modification. - public static Color AddHSV(this Color color, float hue = 0, float saturation = 0, float value = 0) + public static Color AddHSV(this in Color color, float hue = 0, float saturation = 0, float value = 0) { (float cHue, float cSaturation, float cValue) = color.GetHSV(); return Create(color.A, cHue + hue, cSaturation + saturation, cValue + value); @@ -64,7 +64,7 @@ namespace RGB.NET.Core /// The saturation value to subtract. /// The value value to subtract. /// The new color after the modification. - public static Color SubtractHSV(this Color color, float hue = 0, float saturation = 0, float value = 0) + public static Color SubtractHSV(this in Color color, float hue = 0, float saturation = 0, float value = 0) { (float cHue, float cSaturation, float cValue) = color.GetHSV(); return Create(color.A, cHue - hue, cSaturation - saturation, cValue - value); @@ -77,7 +77,7 @@ namespace RGB.NET.Core /// The saturation value to multiply. /// The value value to multiply. /// The new color after the modification. - public static Color MultiplyHSV(this Color color, float hue = 1, float saturation = 1, float value = 1) + public static Color MultiplyHSV(this in Color color, float hue = 1, float saturation = 1, float value = 1) { (float cHue, float cSaturation, float cValue) = color.GetHSV(); return Create(color.A, cHue * hue, cSaturation * saturation, cValue * value); @@ -90,7 +90,7 @@ namespace RGB.NET.Core /// The saturation value to divide. /// The value value to divide. /// The new color after the modification. - public static Color DivideHSV(this Color color, float hue = 1, float saturation = 1, float value = 1) + public static Color DivideHSV(this in Color color, float hue = 1, float saturation = 1, float value = 1) { (float cHue, float cSaturation, float cValue) = color.GetHSV(); return Create(color.A, cHue / hue, cSaturation / saturation, cValue / value); @@ -103,7 +103,7 @@ namespace RGB.NET.Core /// The saturation value to set. /// The value value to set. /// The new color after the modification. - public static Color SetHSV(this Color color, float? hue = null, float? saturation = null, float? value = null) + public static Color SetHSV(this in Color color, float? hue = null, float? saturation = null, float? value = null) { (float cHue, float cSaturation, float cValue) = color.GetHSV(); return Create(color.A, hue ?? cHue, saturation ?? cSaturation, value ?? cValue); diff --git a/RGB.NET.Core/Color/RGBColor.cs b/RGB.NET.Core/Color/RGBColor.cs index 17919ec..9f4c2cb 100644 --- a/RGB.NET.Core/Color/RGBColor.cs +++ b/RGB.NET.Core/Color/RGBColor.cs @@ -13,35 +13,35 @@ namespace RGB.NET.Core /// /// /// - public static byte GetA(this Color color) => color.A.GetByteValueFromPercentage(); + public static byte GetA(this in Color color) => color.A.GetByteValueFromPercentage(); /// /// Gets the R component value of this as byte in the range [0..255]. /// /// /// - public static byte GetR(this Color color) => color.R.GetByteValueFromPercentage(); + public static byte GetR(this in Color color) => color.R.GetByteValueFromPercentage(); /// /// Gets the G component value of this as byte in the range [0..255]. /// /// /// - public static byte GetG(this Color color) => color.G.GetByteValueFromPercentage(); + public static byte GetG(this in Color color) => color.G.GetByteValueFromPercentage(); /// /// Gets the B component value of this as byte in the range [0..255]. /// /// /// - public static byte GetB(this Color color) => color.B.GetByteValueFromPercentage(); + public static byte GetB(this in Color color) => color.B.GetByteValueFromPercentage(); /// /// Gets the A, R, G and B component value of this as byte in the range [0..255]. /// /// /// - public static (byte a, byte r, byte g, byte b) GetRGBBytes(this Color color) + public static (byte a, byte r, byte g, byte b) GetRGBBytes(this in Color color) => (color.GetA(), color.GetR(), color.GetG(), color.GetB()); /// @@ -49,7 +49,7 @@ namespace RGB.NET.Core /// /// /// - public static (float a, float r, float g, float b) GetRGB(this Color color) + public static (float a, float r, float g, float b) GetRGB(this in Color color) => (color.A, color.R, color.G, color.B); #endregion @@ -65,7 +65,7 @@ namespace RGB.NET.Core /// The green value to add. /// The blue value to add. /// The new color after the modification. - public static Color AddRGB(this Color color, int r = 0, int g = 0, int b = 0) + public static Color AddRGB(this in Color color, int r = 0, int g = 0, int b = 0) => new(color.A, color.GetR() + r, color.GetG() + g, color.GetB() + b); /// @@ -75,7 +75,7 @@ namespace RGB.NET.Core /// The green value to add. /// The blue value to add. /// The new color after the modification. - public static Color AddRGB(this Color color, float r = 0, float g = 0, float b = 0) + public static Color AddRGB(this in Color color, float r = 0, float g = 0, float b = 0) => new(color.A, color.R + r, color.G + g, color.B + b); /// @@ -83,7 +83,7 @@ namespace RGB.NET.Core /// /// The alpha value to add. /// The new color after the modification. - public static Color AddA(this Color color, int a) + public static Color AddA(this in Color color, int a) => new(color.GetA() + a, color.R, color.G, color.B); /// @@ -91,7 +91,7 @@ namespace RGB.NET.Core /// /// The alpha value to add. /// The new color after the modification. - public static Color AddA(this Color color, float a) + public static Color AddA(this in Color color, float a) => new(color.A + a, color.R, color.G, color.B); #endregion @@ -105,7 +105,7 @@ namespace RGB.NET.Core /// The green value to subtract. /// The blue value to subtract. /// The new color after the modification. - public static Color SubtractRGB(this Color color, int r = 0, int g = 0, int b = 0) + public static Color SubtractRGB(this in Color color, int r = 0, int g = 0, int b = 0) => new(color.A, color.GetR() - r, color.GetG() - g, color.GetB() - b); /// @@ -115,7 +115,7 @@ namespace RGB.NET.Core /// The green value to subtract. /// The blue value to subtract. /// The new color after the modification. - public static Color SubtractRGB(this Color color, float r = 0, float g = 0, float b = 0) + public static Color SubtractRGB(this in Color color, float r = 0, float g = 0, float b = 0) => new(color.A, color.R - r, color.G - g, color.B - b); /// @@ -123,7 +123,7 @@ namespace RGB.NET.Core /// /// The alpha value to subtract. /// The new color after the modification. - public static Color SubtractA(this Color color, int a) + public static Color SubtractA(this in Color color, int a) => new(color.GetA() - a, color.R, color.G, color.B); /// @@ -131,7 +131,7 @@ namespace RGB.NET.Core /// /// The alpha value to subtract. /// The new color after the modification. - public static Color SubtractA(this Color color, float aPercent) + public static Color SubtractA(this in Color color, float aPercent) => new(color.A - aPercent, color.R, color.G, color.B); #endregion @@ -145,7 +145,7 @@ namespace RGB.NET.Core /// The green value to multiply. /// The blue value to multiply. /// The new color after the modification. - public static Color MultiplyRGB(this Color color, float r = 1, float g = 1, float b = 1) + public static Color MultiplyRGB(this in Color color, float r = 1, float g = 1, float b = 1) => new(color.A, color.R * r, color.G * g, color.B * b); /// @@ -153,7 +153,7 @@ namespace RGB.NET.Core /// /// The alpha value to multiply. /// The new color after the modification. - public static Color MultiplyA(this Color color, float a) + public static Color MultiplyA(this in Color color, float a) => new(color.A * a, color.R, color.G, color.B); #endregion @@ -167,7 +167,7 @@ namespace RGB.NET.Core /// The green value to divide. /// The blue value to divide. /// The new color after the modification. - public static Color DivideRGB(this Color color, float r = 1, float g = 1, float b = 1) + public static Color DivideRGB(this in Color color, float r = 1, float g = 1, float b = 1) => new(color.A, color.R / r, color.G / g, color.B / b); /// @@ -175,7 +175,7 @@ namespace RGB.NET.Core /// /// The alpha value to divide. /// The new color after the modification. - public static Color DivideA(this Color color, float a) + public static Color DivideA(this in Color color, float a) => new(color.A / a, color.R, color.G, color.B); #endregion @@ -189,7 +189,7 @@ namespace RGB.NET.Core /// The green value to set. /// The blue value to set. /// The new color after the modification. - public static Color SetRGB(this Color color, byte? r = null, byte? g = null, byte? b = null) + public static Color SetRGB(this in Color color, byte? r = null, byte? g = null, byte? b = null) => new(color.A, r ?? color.GetR(), g ?? color.GetG(), b ?? color.GetB()); /// @@ -199,7 +199,7 @@ namespace RGB.NET.Core /// The green value to set. /// The blue value to set. /// The new color after the modification. - public static Color SetRGB(this Color color, int? r = null, int? g = null, int? b = null) + public static Color SetRGB(this in Color color, int? r = null, int? g = null, int? b = null) => new(color.A, r ?? color.GetR(), g ?? color.GetG(), b ?? color.GetB()); /// @@ -209,7 +209,7 @@ namespace RGB.NET.Core /// The green value to set. /// The blue value to set. /// The new color after the modification. - public static Color SetRGB(this Color color, float? r = null, float? g = null, float? b = null) + public static Color SetRGB(this in Color color, float? r = null, float? g = null, float? b = null) => new(color.A, r ?? color.R, g ?? color.G, b ?? color.B); /// @@ -217,14 +217,14 @@ namespace RGB.NET.Core /// /// The alpha value to set. /// The new color after the modification. - public static Color SetA(this Color color, int a) => new(a, color.R, color.G, color.B); + public static Color SetA(this in Color color, int a) => new(a, color.R, color.G, color.B); /// /// Sets the given alpha value of this color. /// /// The alpha value to set. /// The new color after the modification. - public static Color SetA(this Color color, float a) => new(a, color.R, color.G, color.B); + public static Color SetA(this in Color color, float a) => new(a, color.R, color.G, color.B); #endregion @@ -236,13 +236,13 @@ namespace RGB.NET.Core /// Gets the current color as a RGB-HEX-string. /// /// The RGB-HEX-string. - public static string AsRGBHexString(this Color color, bool leadingHash = true) => (leadingHash ? "#" : "") + ConversionHelper.ToHex(color.GetR(), color.GetG(), color.GetB()); + public static string AsRGBHexString(this in Color color, bool leadingHash = true) => (leadingHash ? "#" : "") + ConversionHelper.ToHex(color.GetR(), color.GetG(), color.GetB()); /// /// Gets the current color as a ARGB-HEX-string. /// /// The ARGB-HEX-string. - public static string AsARGBHexString(this Color color, bool leadingHash = true) => (leadingHash ? "#" : "") + ConversionHelper.ToHex(color.GetA(), color.GetR(), color.GetG(), color.GetB()); + public static string AsARGBHexString(this in Color color, bool leadingHash = true) => (leadingHash ? "#" : "") + ConversionHelper.ToHex(color.GetA(), color.GetR(), color.GetG(), color.GetB()); #endregion diff --git a/RGB.NET.Core/Devices/AbstractRGBDevice.cs b/RGB.NET.Core/Devices/AbstractRGBDevice.cs index f0083c8..0b6fe09 100644 --- a/RGB.NET.Core/Devices/AbstractRGBDevice.cs +++ b/RGB.NET.Core/Devices/AbstractRGBDevice.cs @@ -114,7 +114,7 @@ namespace RGB.NET.Core /// The location of the to initialize. /// The size of the to initialize. /// The initialized led. - public virtual Led? AddLed(LedId ledId, Point location, Size size, object? customData = null) + public virtual Led? AddLed(LedId ledId, in Point location, in Size size, object? customData = null) { if ((ledId == LedId.Invalid) || LedMapping.ContainsKey(ledId)) return null; diff --git a/RGB.NET.Core/Devices/IRGBDevice.cs b/RGB.NET.Core/Devices/IRGBDevice.cs index 6a83e50..0ad1dc7 100644 --- a/RGB.NET.Core/Devices/IRGBDevice.cs +++ b/RGB.NET.Core/Devices/IRGBDevice.cs @@ -58,7 +58,7 @@ namespace RGB.NET.Core /// Specifies whether all (including clean ones) should be updated. void Update(bool flushLeds = false); - Led? AddLed(LedId ledId, Point location, Size size, object? customData = null); + Led? AddLed(LedId ledId, in Point location, in Size size, object? customData = null); Led? RemoveLed(LedId ledId); diff --git a/RGB.NET.Core/Extensions/ColorExtensions.cs b/RGB.NET.Core/Extensions/ColorExtensions.cs index 15d0c80..b905baf 100644 --- a/RGB.NET.Core/Extensions/ColorExtensions.cs +++ b/RGB.NET.Core/Extensions/ColorExtensions.cs @@ -13,7 +13,7 @@ namespace RGB.NET.Core /// The start color of the distance calculation. /// The end color fot the distance calculation. /// - public static double DistanceTo(this Color color1, Color color2) + public static double DistanceTo(this in Color color1, in Color color2) { (_, byte r1, byte g1, byte b1) = color1.GetRGBBytes(); (_, byte r2, byte g2, byte b2) = color2.GetRGBBytes(); diff --git a/RGB.NET.Core/Extensions/MathExtensions.cs b/RGB.NET.Core/Extensions/MathExtensions.cs index d47db3f..ad098bf 100644 --- a/RGB.NET.Core/Extensions/MathExtensions.cs +++ b/RGB.NET.Core/Extensions/MathExtensions.cs @@ -13,7 +13,7 @@ namespace RGB.NET.Core /// /// Defines the precision RGB.NET processes floating point comparisons in. /// - public const float TOLERANCE = 1E-10f; + public const float TOLERANCE = 1E-7f; #endregion diff --git a/RGB.NET.Core/Extensions/PointExtensions.cs b/RGB.NET.Core/Extensions/PointExtensions.cs index 00436c1..cdc04f7 100644 --- a/RGB.NET.Core/Extensions/PointExtensions.cs +++ b/RGB.NET.Core/Extensions/PointExtensions.cs @@ -13,7 +13,7 @@ namespace RGB.NET.Core /// The x-ammount to move. /// The y-ammount to move. /// The new location of the point. - public static Point Translate(this Point point, float x = 0, float y = 0) => new(point.X + x, point.Y + y); + public static Point Translate(this in Point point, float x = 0, float y = 0) => new(point.X + x, point.Y + y); /// /// Rotates the specified by the given amuont around the given origin. @@ -22,14 +22,18 @@ namespace RGB.NET.Core /// The rotation. /// The origin to rotate around. [0,0] if not set. /// The new location of the point. - public static Point Rotate(this Point point, Rotation rotation, Point origin = new()) + public static Point Rotate(this in Point point, in Rotation rotation, in Point origin = new()) { float sin = MathF.Sin(rotation.Radians); float cos = MathF.Cos(rotation.Radians); - point = new Point(point.X - origin.X, point.Y - origin.Y); - point = new Point((point.X * cos) - (point.Y * sin), (point.X * sin) + (point.Y * cos)); - return new Point(point.X + origin.X, point.Y + origin.Y); ; + float x = point.X - origin.X; + float y = point.Y - origin.Y; + + x = (x * cos) - (y * sin); + y = (x * sin) + (y * cos); + + return new Point(x + origin.X, y + origin.Y); ; } #endregion diff --git a/RGB.NET.Core/Extensions/RectangleExtensions.cs b/RGB.NET.Core/Extensions/RectangleExtensions.cs index 634c3f6..ce5745e 100644 --- a/RGB.NET.Core/Extensions/RectangleExtensions.cs +++ b/RGB.NET.Core/Extensions/RectangleExtensions.cs @@ -12,7 +12,7 @@ namespace RGB.NET.Core /// The rectangle to modify. /// The new location of the rectangle. /// The modified . - public static Rectangle SetLocation(this Rectangle rect, Point location) => new(location, rect.Size); + public static Rectangle SetLocation(this in Rectangle rect, in Point location) => new(location, rect.Size); /// /// Sets the of the of the given rectangle. @@ -20,7 +20,7 @@ namespace RGB.NET.Core /// The rectangle to modify. /// The new x-location of the rectangle. /// The modified . - public static Rectangle SetX(this Rectangle rect, float x) => new(new Point(x, rect.Location.Y), rect.Size); + public static Rectangle SetX(this in Rectangle rect, float x) => new(new Point(x, rect.Location.Y), rect.Size); /// /// Sets the of the of the given rectangle. @@ -28,7 +28,7 @@ namespace RGB.NET.Core /// The rectangle to modify. /// The new y-location of the rectangle. /// The modified . - public static Rectangle SetY(this Rectangle rect, float y) => new(new Point(rect.Location.X, y), rect.Size); + public static Rectangle SetY(this in Rectangle rect, float y) => new(new Point(rect.Location.X, y), rect.Size); /// /// Sets the of the given rectangle. @@ -36,7 +36,7 @@ namespace RGB.NET.Core /// The rectangle to modify. /// The new size of the rectangle. /// The modified . - public static Rectangle SetSize(this Rectangle rect, Size size) => new(rect.Location, size); + public static Rectangle SetSize(this in Rectangle rect, in Size size) => new(rect.Location, size); /// /// Sets the of the of the given rectangle. @@ -44,7 +44,7 @@ namespace RGB.NET.Core /// The rectangle to modify. /// The new width of the rectangle. /// The modified . - public static Rectangle SetWidth(this Rectangle rect, float width) => new(rect.Location, new Size(width, rect.Size.Height)); + public static Rectangle SetWidth(this in Rectangle rect, float width) => new(rect.Location, new Size(width, rect.Size.Height)); /// /// Sets the of the of the given rectangle. @@ -52,14 +52,14 @@ namespace RGB.NET.Core /// The rectangle to modify. /// The new height of the rectangle. /// The modified . - public static Rectangle SetHeight(this Rectangle rect, float height) => new(rect.Location, new Size(rect.Size.Width, height)); + public static Rectangle SetHeight(this in Rectangle rect, float height) => new(rect.Location, new Size(rect.Size.Width, height)); /// /// Calculates the percentage of intersection of a rectangle. /// /// The intersecting rectangle. /// The percentage of intersection. - public static float CalculateIntersectPercentage(this Rectangle rect, in Rectangle intersectingRect) + public static float CalculateIntersectPercentage(this in Rectangle rect, in Rectangle intersectingRect) { if (rect.IsEmpty || intersectingRect.IsEmpty) return 0; @@ -72,7 +72,7 @@ namespace RGB.NET.Core /// /// The intersecting /// A new representing the intersection this and the one provided as parameter. - public static Rectangle CalculateIntersection(this Rectangle rect, in Rectangle intersectingRectangle) + public static Rectangle CalculateIntersection(this in Rectangle rect, in Rectangle intersectingRectangle) { float x1 = Math.Max(rect.Location.X, intersectingRectangle.Location.X); float x2 = Math.Min(rect.Location.X + rect.Size.Width, intersectingRectangle.Location.X + intersectingRectangle.Size.Width); @@ -91,7 +91,7 @@ namespace RGB.NET.Core /// /// The to test. /// true if the rectangle contains the given point; otherwise false. - public static bool Contains(this Rectangle rect, in Point point) => rect.Contains(point.X, point.Y); + public static bool Contains(this in Rectangle rect, in Point point) => rect.Contains(point.X, point.Y); /// /// Determines if the specified location is contained within this . @@ -99,7 +99,7 @@ namespace RGB.NET.Core /// The X-location to test. /// The Y-location to test. /// true if the rectangle contains the given coordinates; otherwise false. - public static bool Contains(this Rectangle rect, float x, float y) => (rect.Location.X <= x) && (x < (rect.Location.X + rect.Size.Width)) + public static bool Contains(this in Rectangle rect, float x, float y) => (rect.Location.X <= x) && (x < (rect.Location.X + rect.Size.Width)) && (rect.Location.Y <= y) && (y < (rect.Location.Y + rect.Size.Height)); /// @@ -107,7 +107,7 @@ namespace RGB.NET.Core /// /// The to test. /// true if the rectangle contains the given rect; otherwise false. - public static bool Contains(this Rectangle rect, in Rectangle rect2) => (rect.Location.X <= rect2.Location.X) && ((rect2.Location.X + rect2.Size.Width) <= (rect.Location.X + rect.Size.Width)) + public static bool Contains(this in Rectangle rect, in Rectangle rect2) => (rect.Location.X <= rect2.Location.X) && ((rect2.Location.X + rect2.Size.Width) <= (rect.Location.X + rect.Size.Width)) && (rect.Location.Y <= rect2.Location.Y) && ((rect2.Location.Y + rect2.Size.Height) <= (rect.Location.Y + rect.Size.Height)); /// @@ -116,7 +116,7 @@ namespace RGB.NET.Core /// The to move. /// The amount to move. /// The moved rectangle. - public static Rectangle Translate(this Rectangle rect, in Point point) => rect.Translate(point.X, point.Y); + public static Rectangle Translate(this in Rectangle rect, in Point point) => rect.Translate(point.X, point.Y); /// /// Moves the specified by the given amount. @@ -125,7 +125,7 @@ namespace RGB.NET.Core /// The x-ammount to move. /// The y-ammount to move. /// The moved rectangle. - public static Rectangle Translate(this Rectangle rect, float x = 0, float y = 0) => new(rect.Location.Translate(x, y), rect.Size); + public static Rectangle Translate(this in Rectangle rect, float x = 0, float y = 0) => new(rect.Location.Translate(x, y), rect.Size); /// /// Rotates the specified by the given amuont around the given origin. @@ -141,7 +141,7 @@ namespace RGB.NET.Core /// The rotation. /// The origin to rotate around. [0,0] if not set. /// A array of containing the new locations of the corners of the original rectangle. - public static Point[] Rotate(this Rectangle rect, in Rotation rotation, in Point origin = new()) + public static Point[] Rotate(this in Rectangle rect, in Rotation rotation, in Point origin = new()) { Point[] points = { rect.Location, // top left diff --git a/RGB.NET.Core/Positioning/Point.cs b/RGB.NET.Core/Positioning/Point.cs index aa533f4..5f04a76 100644 --- a/RGB.NET.Core/Positioning/Point.cs +++ b/RGB.NET.Core/Positioning/Point.cs @@ -13,10 +13,11 @@ namespace RGB.NET.Core { #region Constants + private static readonly Point INVALID = new(float.NaN, float.NaN); /// /// Gets a [NaN,NaN]-Point. /// - public static Point Invalid => new(float.NaN, float.NaN); + public static ref readonly Point Invalid => ref INVALID; #endregion @@ -95,7 +96,7 @@ namespace RGB.NET.Core /// The first to compare. /// The second to compare. /// true if and are equal; otherwise, false. - public static bool operator ==(Point point1, Point point2) => point1.Equals(point2); + public static bool operator ==(in Point point1, in Point point2) => point1.Equals(point2); /// /// Returns a value that indicates whether two specified are equal. @@ -103,7 +104,7 @@ namespace RGB.NET.Core /// The first to compare. /// The second to compare. /// true if and are not equal; otherwise, false. - public static bool operator !=(Point point1, Point point2) => !(point1 == point2); + public static bool operator !=(in Point point1, in Point point2) => !(point1 == point2); /// /// Returns a new representing the addition of the two provided . @@ -111,7 +112,7 @@ namespace RGB.NET.Core /// The first . /// The second . /// A new representing the addition of the two provided . - public static Point operator +(Point point1, Point point2) => new(point1.X + point2.X, point1.Y + point2.Y); + public static Point operator +(in Point point1, in Point point2) => new(point1.X + point2.X, point1.Y + point2.Y); /// /// Returns a new created from the provided and . @@ -119,7 +120,7 @@ namespace RGB.NET.Core /// The of the rectangle. /// The of the rectangle. /// The rectangle created from the provided and . - public static Rectangle operator +(Point point, Size size) => new(point, size); + public static Rectangle operator +(in Point point, in Size size) => new(point, size); /// /// Returns a new representing the subtraction of the two provided . @@ -127,7 +128,7 @@ namespace RGB.NET.Core /// The first . /// The second . /// A new representing the subtraction of the two provided . - public static Point operator -(Point point1, Point point2) => new(point1.X - point2.X, point1.Y - point2.Y); + public static Point operator -(in Point point1, in Point point2) => new(point1.X - point2.X, point1.Y - point2.Y); /// /// Returns a new representing the multiplication of the two provided . @@ -135,7 +136,7 @@ namespace RGB.NET.Core /// The first . /// The second . /// A new representing the multiplication of the two provided . - public static Point operator *(Point point1, Point point2) => new(point1.X * point2.X, point1.Y * point2.Y); + public static Point operator *(in Point point1, in Point point2) => new(point1.X * point2.X, point1.Y * point2.Y); /// /// Returns a new representing the division of the two provided . @@ -143,7 +144,7 @@ namespace RGB.NET.Core /// The first . /// The second . /// A new representing the division of the two provided . - public static Point operator /(Point point1, Point point2) + public static Point operator /(in Point point1, in Point point2) { if (point2.X.EqualsInTolerance(0) || point2.Y.EqualsInTolerance(0)) return Invalid; return new Point(point1.X / point2.X, point1.Y / point2.Y); @@ -155,7 +156,7 @@ namespace RGB.NET.Core /// The . /// The . /// A new representing the multiplication of the and the provided . - public static Point operator *(Point point, Scale scale) => new(point.X * scale.Horizontal, point.Y * scale.Vertical); + public static Point operator *(in Point point, in Scale scale) => new(point.X * scale.Horizontal, point.Y * scale.Vertical); #endregion } diff --git a/RGB.NET.Core/Positioning/Rectangle.cs b/RGB.NET.Core/Positioning/Rectangle.cs index eddffb5..3c545e6 100644 --- a/RGB.NET.Core/Positioning/Rectangle.cs +++ b/RGB.NET.Core/Positioning/Rectangle.cs @@ -156,7 +156,7 @@ namespace RGB.NET.Core #region Methods - private static (Point location, Size size) InitializeFromPoints(Point point1, Point point2) + private static (Point location, Size size) InitializeFromPoints(in Point point1, in Point point2) { float posX = Math.Min(point1.X, point2.X); float posY = Math.Min(point1.Y, point2.Y); @@ -212,7 +212,7 @@ namespace RGB.NET.Core /// The first to compare. /// The second to compare. /// true if and are equal; otherwise, false. - public static bool operator ==(Rectangle rectangle1, Rectangle rectangle2) => rectangle1.Equals(rectangle2); + public static bool operator ==(in Rectangle rectangle1, in Rectangle rectangle2) => rectangle1.Equals(rectangle2); /// /// Returns a value that indicates whether two specified are equal. @@ -220,10 +220,10 @@ namespace RGB.NET.Core /// The first to compare. /// The second to compare. /// true if and are not equal; otherwise, false. - public static bool operator !=(Rectangle rectangle1, Rectangle rectangle2) => !(rectangle1 == rectangle2); + public static bool operator !=(in Rectangle rectangle1, in Rectangle rectangle2) => !(rectangle1 == rectangle2); // DarthAffe 20.02.2021: Used for normalization - public static Rectangle operator /(Rectangle rectangle1, Rectangle rectangle2) + public static Rectangle operator /(in Rectangle rectangle1, in Rectangle rectangle2) { float x = rectangle1.Location.X / (rectangle2.Size.Width - rectangle2.Location.X); float y = rectangle1.Location.Y / (rectangle2.Size.Height - rectangle2.Location.Y); diff --git a/RGB.NET.Core/Positioning/Rotation.cs b/RGB.NET.Core/Positioning/Rotation.cs index d0de9d2..39a5315 100644 --- a/RGB.NET.Core/Positioning/Rotation.cs +++ b/RGB.NET.Core/Positioning/Rotation.cs @@ -103,7 +103,7 @@ namespace RGB.NET.Core /// The first to compare. /// The second to compare. /// true if and are equal; otherwise, false. - public static bool operator ==(Rotation rotation1, Rotation rotation2) => rotation1.Equals(rotation2); + public static bool operator ==(in Rotation rotation1, in Rotation rotation2) => rotation1.Equals(rotation2); /// /// Returns a value that indicates whether two specified are equal. @@ -111,7 +111,7 @@ namespace RGB.NET.Core /// The first to compare. /// The second to compare. /// true if and are not equal; otherwise, false. - public static bool operator !=(Rotation rotation1, Rotation rotation2) => !(rotation1 == rotation2); + public static bool operator !=(in Rotation rotation1, in Rotation rotation2) => !(rotation1 == rotation2); /// /// Returns a new representing the addition of the and the provided value. @@ -119,7 +119,7 @@ namespace RGB.NET.Core /// The . /// The value to add. /// A new representing the addition of the and the provided value. - public static Rotation operator +(Rotation rotation, float value) => new(rotation.Degrees + value); + public static Rotation operator +(in Rotation rotation, float value) => new(rotation.Degrees + value); /// /// Returns a new representing the subtraction of the and the provided value. @@ -127,7 +127,7 @@ namespace RGB.NET.Core /// The . /// The value to substract. /// A new representing the subtraction of the and the provided value. - public static Rotation operator -(Rotation rotation, float value) => new(rotation.Degrees - value); + public static Rotation operator -(in Rotation rotation, float value) => new(rotation.Degrees - value); /// /// Returns a new representing the multiplication of the and the provided value. @@ -135,7 +135,7 @@ namespace RGB.NET.Core /// The . /// The value to multiply with. /// A new representing the multiplication of the and the provided value. - public static Rotation operator *(Rotation rotation, float value) => new(rotation.Degrees * value); + public static Rotation operator *(in Rotation rotation, float value) => new(rotation.Degrees * value); /// /// Returns a new representing the division of the and the provided value. @@ -143,7 +143,7 @@ namespace RGB.NET.Core /// The . /// The value to device with. /// A new representing the division of the and the provided value. - public static Rotation operator /(Rotation rotation, float value) => value.EqualsInTolerance(0) ? new Rotation(0) : new Rotation(rotation.Degrees / value); + public static Rotation operator /(in Rotation rotation, float value) => value.EqualsInTolerance(0) ? new Rotation(0) : new Rotation(rotation.Degrees / value); /// /// Converts a float to a . @@ -155,7 +155,7 @@ namespace RGB.NET.Core /// Converts to a float representing the rotation in degrees. /// /// The rotatio to convert. - public static implicit operator float(Rotation rotation) => rotation.Degrees; + public static implicit operator float(in Rotation rotation) => rotation.Degrees; #endregion } diff --git a/RGB.NET.Core/Positioning/Size.cs b/RGB.NET.Core/Positioning/Size.cs index 690dc6b..3a8c279 100644 --- a/RGB.NET.Core/Positioning/Size.cs +++ b/RGB.NET.Core/Positioning/Size.cs @@ -13,10 +13,11 @@ namespace RGB.NET.Core { #region Constants + private static readonly Size INVALID = new(float.NaN, float.NaN); /// /// Gets a [NaN,NaN]-Size. /// - public static Size Invalid => new(float.NaN, float.NaN); + public static ref readonly Size Invalid => ref INVALID; #endregion @@ -115,7 +116,7 @@ namespace RGB.NET.Core /// The first to compare. /// The second to compare. /// true if and are equal; otherwise, false. - public static bool operator ==(Size size1, Size size2) => size1.Equals(size2); + public static bool operator ==(in Size size1, in Size size2) => size1.Equals(size2); /// /// Returns a value that indicates whether two specified are equal. @@ -123,7 +124,7 @@ namespace RGB.NET.Core /// The first to compare. /// The second to compare. /// true if and are not equal; otherwise, false. - public static bool operator !=(Size size1, Size size2) => !(size1 == size2); + public static bool operator !=(in Size size1, in Size size2) => !(size1 == size2); /// /// Returns a new representing the addition of the two provided . @@ -131,7 +132,7 @@ namespace RGB.NET.Core /// The first . /// The second . /// A new representing the addition of the two provided . - public static Size operator +(Size size1, Size size2) => new(size1.Width + size2.Width, size1.Height + size2.Height); + public static Size operator +(in Size size1, in Size size2) => new(size1.Width + size2.Width, size1.Height + size2.Height); /// /// Returns a new created from the provided and . @@ -139,7 +140,7 @@ namespace RGB.NET.Core /// The of the rectangle. /// The of the rectangle. /// The rectangle created from the provided and . - public static Rectangle operator +(Size size, Point point) => new(point, size); + public static Rectangle operator +(in Size size, in Point point) => new(point, size); /// /// Returns a new representing the subtraction of the two provided . @@ -147,7 +148,7 @@ namespace RGB.NET.Core /// The first . /// The second . /// A new representing the subtraction of the two provided . - public static Size operator -(Size size1, Size size2) => new(size1.Width - size2.Width, size1.Height - size2.Height); + public static Size operator -(in Size size1, in Size size2) => new(size1.Width - size2.Width, size1.Height - size2.Height); /// /// Returns a new representing the multiplication of the two provided . @@ -155,7 +156,7 @@ namespace RGB.NET.Core /// The first . /// The second . /// A new representing the multiplication of the two provided . - public static Size operator *(Size size1, Size size2) => new(size1.Width * size2.Width, size1.Height * size2.Height); + public static Size operator *(in Size size1, in Size size2) => new(size1.Width * size2.Width, size1.Height * size2.Height); /// /// Returns a new representing the multiplication of the and the provided factor. @@ -163,7 +164,7 @@ namespace RGB.NET.Core /// The . /// The factor by which the should be multiplied. /// A new representing the multiplication of the and the provided factor. - public static Size operator *(Size size, float factor) => new(size.Width * factor, size.Height * factor); + public static Size operator *(in Size size, float factor) => new(size.Width * factor, size.Height * factor); /// /// Returns a new representing the division of the two provided . @@ -171,7 +172,7 @@ namespace RGB.NET.Core /// The first . /// The second . /// A new representing the division of the two provided . - public static Size operator /(Size size1, Size size2) + public static Size operator /(in Size size1, in Size size2) => size2.Width.EqualsInTolerance(0) || size2.Height.EqualsInTolerance(0) ? Invalid : new Size(size1.Width / size2.Width, size1.Height / size2.Height); @@ -181,7 +182,7 @@ namespace RGB.NET.Core /// The . /// The factor by which the should be divided. /// A new representing the division of the and the provided factor. - public static Size operator /(Size size, float factor) => factor.EqualsInTolerance(0) ? Invalid : new Size(size.Width / factor, size.Height / factor); + public static Size operator /(in Size size, float factor) => factor.EqualsInTolerance(0) ? Invalid : new Size(size.Width / factor, size.Height / factor); /// /// Returns a new representing the multiplication of the and the given . @@ -189,7 +190,7 @@ namespace RGB.NET.Core /// The to scale. /// The scaling factor. /// A new representing the multiplication of the and the given . - public static Size operator *(Size size, Scale scale) => new(size.Width * scale.Horizontal, size.Height * scale.Vertical); + public static Size operator *(in Size size, in Scale scale) => new(size.Width * scale.Horizontal, size.Height * scale.Vertical); #endregion } diff --git a/Tests/RGB.NET.Core.Tests/Color/ColorTest.cs b/Tests/RGB.NET.Core.Tests/Color/ColorTest.cs index 67b5b77..4b22146 100644 --- a/Tests/RGB.NET.Core.Tests/Color/ColorTest.cs +++ b/Tests/RGB.NET.Core.Tests/Color/ColorTest.cs @@ -324,13 +324,13 @@ namespace RGB.NET.Core.Tests.Color Assert.AreEqual(1, color2.A); Core.Color color3 = new(128, 0, 0, 0); - Assert.AreEqual(128 / 255.0, color3.A); + Assert.AreEqual(128 / 255.0f, color3.A); Core.Color color4 = new(30, 0, 0, 0); - Assert.AreEqual(30 / 255.0, color4.A); + Assert.AreEqual(30 / 255.0f, color4.A); Core.Color color5 = new(201, 0, 0, 0); - Assert.AreEqual(201 / 255.0, color5.A); + Assert.AreEqual(201 / 255.0f, color5.A); } [TestMethod] @@ -343,13 +343,13 @@ namespace RGB.NET.Core.Tests.Color Assert.AreEqual(1, color2.R); Core.Color color3 = new(0, 128, 0, 0); - Assert.AreEqual(128 / 255.0, color3.R); + Assert.AreEqual(128 / 255.0f, color3.R); Core.Color color4 = new(0, 30, 0, 0); - Assert.AreEqual(30 / 255.0, color4.R); + Assert.AreEqual(30 / 255.0f, color4.R); Core.Color color5 = new(0, 201, 0, 0); - Assert.AreEqual(201 / 255.0, color5.R); + Assert.AreEqual(201 / 255.0f, color5.R); } [TestMethod] @@ -362,13 +362,13 @@ namespace RGB.NET.Core.Tests.Color Assert.AreEqual(1, color2.G); Core.Color color3 = new(0, 0, 128, 0); - Assert.AreEqual(128 / 255.0, color3.G); + Assert.AreEqual(128 / 255.0f, color3.G); Core.Color color4 = new(0, 0, 30, 0); - Assert.AreEqual(30 / 255.0, color4.G); + Assert.AreEqual(30 / 255.0f, color4.G); Core.Color color5 = new(0, 0, 201, 0); - Assert.AreEqual(201 / 255.0, color5.G); + Assert.AreEqual(201 / 255.0f, color5.G); } [TestMethod] @@ -381,13 +381,13 @@ namespace RGB.NET.Core.Tests.Color Assert.AreEqual(1, color2.B); Core.Color color3 = new(0, 0, 0, 128); - Assert.AreEqual(128 / 255.0, color3.B); + Assert.AreEqual(128 / 255.0f, color3.B); Core.Color color4 = new(0, 0, 0, 30); - Assert.AreEqual(30 / 255.0, color4.B); + Assert.AreEqual(30 / 255.0f, color4.B); Core.Color color5 = new(0, 0, 0, 201); - Assert.AreEqual(201 / 255.0, color5.B); + Assert.AreEqual(201 / 255.0f, color5.B); } #endregion From c9634f39133849fc2e2d9ef764c1da00a7841c83 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Tue, 23 Feb 2021 01:38:53 +0100 Subject: [PATCH 06/22] Optimized Textures and Sampler --- .../Rendering/Textures/PixelTexture.cs | 57 ++++++++++++--- .../Textures/Sampler/AverageColorSampler.cs | 34 +++++++++ .../Textures/Sampler/AverageSampler.cs | 38 ---------- .../Rendering/Textures/Sampler/ISampler.cs | 6 +- .../Rendering/Textures/Sampler/SamplerInfo.cs | 26 +++++++ .../RGB.NET.Presets.csproj.DotSettings | 3 +- RGB.NET.Presets/Textures/BytePixelTexture.cs | 72 +++++++++++++++++++ RGB.NET.Presets/Textures/Enums/ColorFormat.cs | 8 +++ RGB.NET.Presets/Textures/FloatPixelTexture.cs | 72 +++++++++++++++++++ .../Textures/Sampler/AverageByteSampler.cs | 31 ++++++++ .../Textures/Sampler/AverageFloatSampler.cs | 30 ++++++++ 11 files changed, 325 insertions(+), 52 deletions(-) create mode 100644 RGB.NET.Core/Rendering/Textures/Sampler/AverageColorSampler.cs delete mode 100644 RGB.NET.Core/Rendering/Textures/Sampler/AverageSampler.cs create mode 100644 RGB.NET.Core/Rendering/Textures/Sampler/SamplerInfo.cs create mode 100644 RGB.NET.Presets/Textures/BytePixelTexture.cs create mode 100644 RGB.NET.Presets/Textures/Enums/ColorFormat.cs create mode 100644 RGB.NET.Presets/Textures/FloatPixelTexture.cs create mode 100644 RGB.NET.Presets/Textures/Sampler/AverageByteSampler.cs create mode 100644 RGB.NET.Presets/Textures/Sampler/AverageFloatSampler.cs diff --git a/RGB.NET.Core/Rendering/Textures/PixelTexture.cs b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs index d5b6bab..7193e52 100644 --- a/RGB.NET.Core/Rendering/Textures/PixelTexture.cs +++ b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs @@ -1,18 +1,28 @@ using System; +using System.Buffers; using System.Runtime.CompilerServices; namespace RGB.NET.Core { public abstract class PixelTexture : ITexture + where T : unmanaged { + #region Constants + + private const int STACK_ALLOC_LIMIT = 1024; + + #endregion + #region Properties & Fields - protected ISampler Sampler { get; set; } + private readonly int _dataPerColor; + + protected ISampler Sampler { get; set; } protected T[] Data { get; set; } public Size Size { get; } - public Color this[in Point point] + public virtual Color this[in Point point] { get { @@ -24,7 +34,7 @@ namespace RGB.NET.Core } } - public Color this[in Rectangle rectangle] + public virtual Color this[in Rectangle rectangle] { get { @@ -35,7 +45,23 @@ namespace RGB.NET.Core int width = (int)Math.Round(Size.Width * rectangle.Size.Width.Clamp(0, 1)); int height = (int)Math.Round(Size.Height * rectangle.Size.Height.Clamp(0, 1)); - return Sampler.SampleColor(x, y, width, height, GetColor); + int bufferSize = width * height * _dataPerColor; + if (bufferSize <= STACK_ALLOC_LIMIT) + { + Span buffer = stackalloc T[bufferSize]; + GetRegionData(x, y, width, height, buffer); + return Sampler.SampleColor(new SamplerInfo(width, height, buffer)); + } + else + { + T[] rent = ArrayPool.Shared.Rent(bufferSize); + Span buffer = new Span(rent).Slice(0, bufferSize); + GetRegionData(x, y, width, height, buffer); + Color color = Sampler.SampleColor(new SamplerInfo(width, height, buffer)); + ArrayPool.Shared.Return(rent); + + return color; + } } } @@ -43,9 +69,10 @@ namespace RGB.NET.Core #region Constructors - public PixelTexture(int with, int height, T[] data, ISampler sampler) + public PixelTexture(int with, int height, T[] data, int dataPerColor, ISampler sampler) { this.Data = data; + this._dataPerColor = dataPerColor; this.Sampler = sampler; Size = new Size(with, height); @@ -55,8 +82,8 @@ namespace RGB.NET.Core #region Methods - [MethodImpl(MethodImplOptions.AggressiveInlining)] protected abstract Color GetColor(int x, int y); + protected abstract void GetRegionData(int x, int y, int width, int height, in Span buffer); #endregion } @@ -72,11 +99,11 @@ namespace RGB.NET.Core #region Constructors public PixelTexture(int with, int height, Color[] data) - : this(with, height, data, new AverageSampler()) + : this(with, height, data, new AverageColorSampler()) { } - public PixelTexture(int with, int height, Color[] data, ISampler sampler) - : base(with, height, data, sampler) + public PixelTexture(int with, int height, Color[] data, ISampler sampler) + : base(with, height, data, 1, sampler) { this._stride = with; @@ -87,8 +114,20 @@ namespace RGB.NET.Core #region Methods + [MethodImpl(MethodImplOptions.AggressiveInlining)] protected override Color GetColor(int x, int y) => Data[(y * _stride) + x]; + protected override void GetRegionData(int x, int y, int width, int height, in Span buffer) + { + Span data = Data.AsSpan(); + for (int i = 0; i < height; i++) + { + Span dataSlice = data.Slice(((y + i) * _stride) + x, width); + Span destination = buffer.Slice(i * width, width); + dataSlice.CopyTo(destination); + } + } + #endregion } } diff --git a/RGB.NET.Core/Rendering/Textures/Sampler/AverageColorSampler.cs b/RGB.NET.Core/Rendering/Textures/Sampler/AverageColorSampler.cs new file mode 100644 index 0000000..5492f90 --- /dev/null +++ b/RGB.NET.Core/Rendering/Textures/Sampler/AverageColorSampler.cs @@ -0,0 +1,34 @@ +namespace RGB.NET.Core +{ + public class AverageColorSampler : ISampler + { + #region Properties & Fields + + public bool SampleAlpha { get; set; } + + #endregion + + #region Methods + + public Color SampleColor(SamplerInfo info) + { + int count = info.Width * info.Height; + if (count == 0) return Color.Transparent; + + float a = 0, r = 0, g = 0, b = 0; + foreach (Color color in info.Data) + { + a += color.A; + r += color.R; + g += color.G; + b += color.B; + } + + return SampleAlpha + ? new Color(a / count, r / count, g / count, b / count) + : new Color(r / count, g / count, b / count); + } + + #endregion + } +} diff --git a/RGB.NET.Core/Rendering/Textures/Sampler/AverageSampler.cs b/RGB.NET.Core/Rendering/Textures/Sampler/AverageSampler.cs deleted file mode 100644 index c9e95ce..0000000 --- a/RGB.NET.Core/Rendering/Textures/Sampler/AverageSampler.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace RGB.NET.Core -{ - public class AverageSampler : ISampler - { - #region Properties & Fields - - public bool SampleAlpha { get; set; } - - #endregion - - #region Methods - - public Color SampleColor(int x, int y, int width, int height, GetColor getColor) - { - int maxX = x + width; - int maxY = y + height; - int count = width * height; - if (count == 0) return Color.Transparent; - - float a = 0, r = 0, g = 0, b = 0; - for (int yPos = y; yPos < maxY; yPos++) - for (int xPos = x; xPos < maxX; xPos++) - { - Color color = getColor(x, y); - a += color.A; - r += color.R; - g += color.G; - b += color.B; - } - - return SampleAlpha - ? new Color(a / count, r / count, g / count, b / count) - : new Color(r / count, g / count, b / count); - } - - #endregion - } -} diff --git a/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs b/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs index 2d9fced..9bfd812 100644 --- a/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs +++ b/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs @@ -1,9 +1,7 @@ namespace RGB.NET.Core { - public delegate Color GetColor(int x, int y); - - public interface ISampler + public interface ISampler { - Color SampleColor(int x, int y, int width, int height, GetColor getColorFunc); + Color SampleColor(SamplerInfo info); } } diff --git a/RGB.NET.Core/Rendering/Textures/Sampler/SamplerInfo.cs b/RGB.NET.Core/Rendering/Textures/Sampler/SamplerInfo.cs new file mode 100644 index 0000000..a544381 --- /dev/null +++ b/RGB.NET.Core/Rendering/Textures/Sampler/SamplerInfo.cs @@ -0,0 +1,26 @@ +using System; + +namespace RGB.NET.Core +{ + public readonly ref struct SamplerInfo + { + #region Properties & Fields + + public int Width { get; } + public int Height { get; } + public ReadOnlySpan Data { get; } + + #endregion + + #region Constructors + + public SamplerInfo(int width, int height, ReadOnlySpan data) + { + this.Width = width; + this.Height = height; + this.Data = data; + } + + #endregion + } +} diff --git a/RGB.NET.Presets/RGB.NET.Presets.csproj.DotSettings b/RGB.NET.Presets/RGB.NET.Presets.csproj.DotSettings index 5cecdd9..3af07cd 100644 --- a/RGB.NET.Presets/RGB.NET.Presets.csproj.DotSettings +++ b/RGB.NET.Presets/RGB.NET.Presets.csproj.DotSettings @@ -1,4 +1,5 @@  False False - True \ No newline at end of file + True + True \ No newline at end of file diff --git a/RGB.NET.Presets/Textures/BytePixelTexture.cs b/RGB.NET.Presets/Textures/BytePixelTexture.cs new file mode 100644 index 0000000..d83398a --- /dev/null +++ b/RGB.NET.Presets/Textures/BytePixelTexture.cs @@ -0,0 +1,72 @@ +using System; +using RGB.NET.Core; +using RGB.NET.Presets.Textures.Sampler; + +namespace RGB.NET.Presets.Textures +{ + public sealed class BytePixelTexture : PixelTexture + { + #region Properties & Fields + + private readonly int _stride; + + public ColorFormat ColorFormat { get; } + + public override Color this[in Rectangle rectangle] + { + get + { + Color color = base[rectangle]; + if (ColorFormat == ColorFormat.BGR) + return new Color(color.A, color.B, color.G, color.R); + + return color; + } + } + + #endregion + + #region Constructors + + public BytePixelTexture(int with, int height, byte[] data, ColorFormat colorFormat = ColorFormat.RGB) + : this(with, height, data, new AverageByteSampler(), colorFormat) + { } + + public BytePixelTexture(int with, int height, byte[] data, ISampler sampler, ColorFormat colorFormat = ColorFormat.RGB) + : base(with, height, data, 3, sampler) + { + this._stride = with; + this.ColorFormat = colorFormat; + + if (Data.Length != ((with * height) * 3)) throw new ArgumentException($"Data-Length {Data.Length} differs from the given size {with}x{height} * 3 bytes ({with * height * 3})."); + } + + #endregion + + #region Methods + + protected override Color GetColor(int x, int y) + { + int offset = ((y * _stride) + x) * 3; + + if (ColorFormat == ColorFormat.BGR) + return new Color(Data[offset + 2], Data[offset + 1], Data[offset + 1]); + + return new Color(Data[offset], Data[offset + 1], Data[offset + 2]); + } + + protected override void GetRegionData(int x, int y, int width, int height, in Span buffer) + { + int width3 = width * 3; + Span data = Data.AsSpan(); + for (int i = 0; i < height; i++) + { + Span dataSlice = data.Slice((((y + i) * _stride) + x) * 3, width3); + Span destination = buffer.Slice(i * width3, width3); + dataSlice.CopyTo(destination); + } + } + + #endregion + } +} diff --git a/RGB.NET.Presets/Textures/Enums/ColorFormat.cs b/RGB.NET.Presets/Textures/Enums/ColorFormat.cs new file mode 100644 index 0000000..a098ff5 --- /dev/null +++ b/RGB.NET.Presets/Textures/Enums/ColorFormat.cs @@ -0,0 +1,8 @@ +namespace RGB.NET.Presets.Textures +{ + public enum ColorFormat + { + RGB, + BGR + } +} diff --git a/RGB.NET.Presets/Textures/FloatPixelTexture.cs b/RGB.NET.Presets/Textures/FloatPixelTexture.cs new file mode 100644 index 0000000..410f9c9 --- /dev/null +++ b/RGB.NET.Presets/Textures/FloatPixelTexture.cs @@ -0,0 +1,72 @@ +using System; +using RGB.NET.Core; +using RGB.NET.Presets.Textures.Sampler; + +namespace RGB.NET.Presets.Textures +{ + public sealed class FloatPixelTexture : PixelTexture + { + #region Properties & Fields + + private readonly int _stride; + + public ColorFormat ColorFormat { get; } + + public override Color this[in Rectangle rectangle] + { + get + { + Color color = base[rectangle]; + if (ColorFormat == ColorFormat.BGR) + return new Color(color.A, color.B, color.G, color.R); + + return color; + } + } + + #endregion + + #region Constructors + + public FloatPixelTexture(int with, int height, float[] data, ColorFormat colorFormat = ColorFormat.RGB) + : this(with, height, data, new AverageFloatSampler(), colorFormat) + { } + + public FloatPixelTexture(int with, int height, float[] data, ISampler sampler, ColorFormat colorFormat = ColorFormat.RGB) + : base(with, height, data, 3, sampler) + { + this._stride = with; + this.ColorFormat = colorFormat; + + if (Data.Length != ((with * height) * 3)) throw new ArgumentException($"Data-Length {Data.Length} differs from the given size {with}x{height} * 3 bytes ({with * height * 3})."); + } + + #endregion + + #region Methods + + protected override Color GetColor(int x, int y) + { + int offset = ((y * _stride) + x) * 3; + + if (ColorFormat == ColorFormat.BGR) + return new Color(Data[offset + 2], Data[offset + 1], Data[offset + 1]); + + return new Color(Data[offset], Data[offset + 1], Data[offset + 2]); + } + + protected override void GetRegionData(int x, int y, int width, int height, in Span buffer) + { + int width3 = width * 3; + Span data = Data.AsSpan(); + for (int i = 0; i < height; i++) + { + Span dataSlice = data.Slice((((y + i) * _stride) + x) * 3, width3); + Span destination = buffer.Slice(i * width3, width3); + dataSlice.CopyTo(destination); + } + } + + #endregion + } +} diff --git a/RGB.NET.Presets/Textures/Sampler/AverageByteSampler.cs b/RGB.NET.Presets/Textures/Sampler/AverageByteSampler.cs new file mode 100644 index 0000000..694dbe6 --- /dev/null +++ b/RGB.NET.Presets/Textures/Sampler/AverageByteSampler.cs @@ -0,0 +1,31 @@ +using System; +using RGB.NET.Core; + +namespace RGB.NET.Presets.Textures.Sampler +{ + public class AverageByteSampler : ISampler + { + #region Methods + + public Color SampleColor(SamplerInfo info) + { + int count = info.Width * info.Height; + if (count == 0) return Color.Transparent; + + ReadOnlySpan data = info.Data; + + uint r = 0, g = 0, b = 0; + for (int i = 0; i < data.Length; i += 3) + { + r += data[i]; + g += data[i + 1]; + b += data[i + 2]; + } + + float divisor = count * byte.MaxValue; + return new Color(r / divisor, g / divisor, b / divisor); + } + + #endregion + } +} diff --git a/RGB.NET.Presets/Textures/Sampler/AverageFloatSampler.cs b/RGB.NET.Presets/Textures/Sampler/AverageFloatSampler.cs new file mode 100644 index 0000000..59e1987 --- /dev/null +++ b/RGB.NET.Presets/Textures/Sampler/AverageFloatSampler.cs @@ -0,0 +1,30 @@ +using System; +using RGB.NET.Core; + +namespace RGB.NET.Presets.Textures.Sampler +{ + public class AverageFloatSampler : ISampler + { + #region Methods + + public Color SampleColor(SamplerInfo info) + { + int count = info.Width * info.Height; + if (count == 0) return Color.Transparent; + + ReadOnlySpan data = info.Data; + + float r = 0, g = 0, b = 0; + for (int i = 0; i < data.Length; i += 3) + { + r += data[i]; + g += data[i + 1]; + b += data[i + 2]; + } + + return new Color(r / count, g / count, b / count); + } + + #endregion + } +} From b857fb2c81c6784835b331cb5cafea4fe74cba6c Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Tue, 23 Feb 2021 23:01:04 +0100 Subject: [PATCH 07/22] Changed Data-Spans in texture to be readonly --- RGB.NET.Core/Rendering/Textures/PixelTexture.cs | 4 ++-- RGB.NET.Presets/Textures/BytePixelTexture.cs | 4 ++-- RGB.NET.Presets/Textures/FloatPixelTexture.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/RGB.NET.Core/Rendering/Textures/PixelTexture.cs b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs index 7193e52..f6525cf 100644 --- a/RGB.NET.Core/Rendering/Textures/PixelTexture.cs +++ b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs @@ -119,10 +119,10 @@ namespace RGB.NET.Core protected override void GetRegionData(int x, int y, int width, int height, in Span buffer) { - Span data = Data.AsSpan(); + ReadOnlySpan data = Data.AsSpan(); for (int i = 0; i < height; i++) { - Span dataSlice = data.Slice(((y + i) * _stride) + x, width); + ReadOnlySpan dataSlice = data.Slice(((y + i) * _stride) + x, width); Span destination = buffer.Slice(i * width, width); dataSlice.CopyTo(destination); } diff --git a/RGB.NET.Presets/Textures/BytePixelTexture.cs b/RGB.NET.Presets/Textures/BytePixelTexture.cs index d83398a..c1ed31c 100644 --- a/RGB.NET.Presets/Textures/BytePixelTexture.cs +++ b/RGB.NET.Presets/Textures/BytePixelTexture.cs @@ -58,10 +58,10 @@ namespace RGB.NET.Presets.Textures protected override void GetRegionData(int x, int y, int width, int height, in Span buffer) { int width3 = width * 3; - Span data = Data.AsSpan(); + ReadOnlySpan data = Data.AsSpan(); for (int i = 0; i < height; i++) { - Span dataSlice = data.Slice((((y + i) * _stride) + x) * 3, width3); + ReadOnlySpan dataSlice = data.Slice((((y + i) * _stride) + x) * 3, width3); Span destination = buffer.Slice(i * width3, width3); dataSlice.CopyTo(destination); } diff --git a/RGB.NET.Presets/Textures/FloatPixelTexture.cs b/RGB.NET.Presets/Textures/FloatPixelTexture.cs index 410f9c9..aa8bd77 100644 --- a/RGB.NET.Presets/Textures/FloatPixelTexture.cs +++ b/RGB.NET.Presets/Textures/FloatPixelTexture.cs @@ -58,10 +58,10 @@ namespace RGB.NET.Presets.Textures protected override void GetRegionData(int x, int y, int width, int height, in Span buffer) { int width3 = width * 3; - Span data = Data.AsSpan(); + ReadOnlySpan data = Data.AsSpan(); for (int i = 0; i < height; i++) { - Span dataSlice = data.Slice((((y + i) * _stride) + x) * 3, width3); + ReadOnlySpan dataSlice = data.Slice((((y + i) * _stride) + x) * 3, width3); Span destination = buffer.Slice(i * width3, width3); dataSlice.CopyTo(destination); } From 8ddf0bc734b71e1211f4343e56da6b0bec6af017 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Wed, 24 Feb 2021 13:05:06 +0100 Subject: [PATCH 08/22] Moved LedGroupExtension to Core --- .../Extensions => RGB.NET.Core/Groups}/LedGroupExtension.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) rename {RGB.NET.Presets/Groups/Extensions => RGB.NET.Core/Groups}/LedGroupExtension.cs (98%) diff --git a/RGB.NET.Presets/Groups/Extensions/LedGroupExtension.cs b/RGB.NET.Core/Groups/LedGroupExtension.cs similarity index 98% rename from RGB.NET.Presets/Groups/Extensions/LedGroupExtension.cs rename to RGB.NET.Core/Groups/LedGroupExtension.cs index c9f2677..3a8c9f7 100644 --- a/RGB.NET.Presets/Groups/Extensions/LedGroupExtension.cs +++ b/RGB.NET.Core/Groups/LedGroupExtension.cs @@ -1,9 +1,7 @@ // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedMember.Global -using RGB.NET.Core; - -namespace RGB.NET.Presets.Groups +namespace RGB.NET.Core { /// /// Offers some extensions and helper-methods for related things. From cc7abb63f0455bcba5d72b51e1208b60ab33398e Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Wed, 24 Feb 2021 13:05:15 +0100 Subject: [PATCH 09/22] Simplified textures --- .../Rendering/Textures/PixelTexture.cs | 73 +++++++++++-------- .../Textures/Sampler/AverageColorSampler.cs | 18 ++--- .../Rendering/Textures/Sampler/ISampler.cs | 6 +- RGB.NET.Presets/Textures/BytePixelTexture.cs | 39 ++-------- RGB.NET.Presets/Textures/FloatPixelTexture.cs | 39 ++-------- .../Textures/Sampler/AverageByteSampler.cs | 20 +++-- .../Textures/Sampler/AverageFloatSampler.cs | 19 +++-- 7 files changed, 85 insertions(+), 129 deletions(-) diff --git a/RGB.NET.Core/Rendering/Textures/PixelTexture.cs b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs index f6525cf..f193ec2 100644 --- a/RGB.NET.Core/Rendering/Textures/PixelTexture.cs +++ b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs @@ -15,13 +15,14 @@ namespace RGB.NET.Core #region Properties & Fields - private readonly int _dataPerColor; - - protected ISampler Sampler { get; set; } - protected T[] Data { get; set; } + private readonly int _dataPerPixel; + private readonly int _stride; + public ISampler Sampler { get; set; } public Size Size { get; } + protected abstract ReadOnlySpan Data { get; } + public virtual Color this[in Point point] { get @@ -30,7 +31,7 @@ namespace RGB.NET.Core int x = (int)Math.Round(Size.Width * point.X.Clamp(0, 1)); int y = (int)Math.Round(Size.Height * point.Y.Clamp(0, 1)); - return GetColor(x, y); + return GetColor(GetPixelData(x, y)); } } @@ -45,22 +46,30 @@ namespace RGB.NET.Core int width = (int)Math.Round(Size.Width * rectangle.Size.Width.Clamp(0, 1)); int height = (int)Math.Round(Size.Height * rectangle.Size.Height.Clamp(0, 1)); - int bufferSize = width * height * _dataPerColor; + int bufferSize = width * height * _dataPerPixel; if (bufferSize <= STACK_ALLOC_LIMIT) { Span buffer = stackalloc T[bufferSize]; GetRegionData(x, y, width, height, buffer); - return Sampler.SampleColor(new SamplerInfo(width, height, buffer)); + + Span pixelData = stackalloc T[_dataPerPixel]; + Sampler.SampleColor(new SamplerInfo(width, height, buffer), pixelData); + + return GetColor(pixelData); } else { T[] rent = ArrayPool.Shared.Rent(bufferSize); + Span buffer = new Span(rent).Slice(0, bufferSize); GetRegionData(x, y, width, height, buffer); - Color color = Sampler.SampleColor(new SamplerInfo(width, height, buffer)); + + Span pixelData = stackalloc T[_dataPerPixel]; + Sampler.SampleColor(new SamplerInfo(width, height, buffer), pixelData); + ArrayPool.Shared.Return(rent); - return color; + return GetColor(pixelData); } } } @@ -69,10 +78,10 @@ namespace RGB.NET.Core #region Constructors - public PixelTexture(int with, int height, T[] data, int dataPerColor, ISampler sampler) + public PixelTexture(int with, int height, int dataPerPixel, ISampler sampler) { - this.Data = data; - this._dataPerColor = dataPerColor; + this._stride = with; + this._dataPerPixel = dataPerPixel; this.Sampler = sampler; Size = new Size(with, height); @@ -82,8 +91,22 @@ namespace RGB.NET.Core #region Methods - protected abstract Color GetColor(int x, int y); - protected abstract void GetRegionData(int x, int y, int width, int height, in Span buffer); + protected abstract Color GetColor(ReadOnlySpan pixel); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected virtual ReadOnlySpan GetPixelData(int x, int y) => Data.Slice((y * _stride) + x, _dataPerPixel); + + protected virtual void GetRegionData(int x, int y, int width, int height, Span buffer) + { + int dataWidth = width * _dataPerPixel; + ReadOnlySpan data = Data; + for (int i = 0; i < height; i++) + { + ReadOnlySpan dataSlice = data.Slice((((y + i) * _stride) + x) * _dataPerPixel, dataWidth); + Span destination = buffer.Slice(i * dataWidth, dataWidth); + dataSlice.CopyTo(destination); + } + } #endregion } @@ -92,7 +115,9 @@ namespace RGB.NET.Core { #region Properties & Fields - private readonly int _stride; + private readonly Color[] _data; + + protected override ReadOnlySpan Data => _data; #endregion @@ -103,9 +128,9 @@ namespace RGB.NET.Core { } public PixelTexture(int with, int height, Color[] data, ISampler sampler) - : base(with, height, data, 1, sampler) + : base(with, height, 1, sampler) { - this._stride = with; + this._data = data; if (Data.Length != (with * height)) throw new ArgumentException($"Data-Length {Data.Length} differs from the given size {with}x{height} ({with * height})."); } @@ -114,19 +139,7 @@ namespace RGB.NET.Core #region Methods - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override Color GetColor(int x, int y) => Data[(y * _stride) + x]; - - protected override void GetRegionData(int x, int y, int width, int height, in Span buffer) - { - ReadOnlySpan data = Data.AsSpan(); - for (int i = 0; i < height; i++) - { - ReadOnlySpan dataSlice = data.Slice(((y + i) * _stride) + x, width); - Span destination = buffer.Slice(i * width, width); - dataSlice.CopyTo(destination); - } - } + protected override Color GetColor(ReadOnlySpan pixel) => pixel[0]; #endregion } diff --git a/RGB.NET.Core/Rendering/Textures/Sampler/AverageColorSampler.cs b/RGB.NET.Core/Rendering/Textures/Sampler/AverageColorSampler.cs index 5492f90..11c3dd2 100644 --- a/RGB.NET.Core/Rendering/Textures/Sampler/AverageColorSampler.cs +++ b/RGB.NET.Core/Rendering/Textures/Sampler/AverageColorSampler.cs @@ -1,19 +1,15 @@ -namespace RGB.NET.Core +using System; + +namespace RGB.NET.Core { public class AverageColorSampler : ISampler { - #region Properties & Fields - - public bool SampleAlpha { get; set; } - - #endregion - #region Methods - public Color SampleColor(SamplerInfo info) + public void SampleColor(in SamplerInfo info, Span pixelData) { int count = info.Width * info.Height; - if (count == 0) return Color.Transparent; + if (count == 0) return; float a = 0, r = 0, g = 0, b = 0; foreach (Color color in info.Data) @@ -24,9 +20,7 @@ b += color.B; } - return SampleAlpha - ? new Color(a / count, r / count, g / count, b / count) - : new Color(r / count, g / count, b / count); + pixelData[0] = new Color(a / count, r / count, g / count, b / count); } #endregion diff --git a/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs b/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs index 9bfd812..2b76c5f 100644 --- a/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs +++ b/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs @@ -1,7 +1,9 @@ -namespace RGB.NET.Core +using System; + +namespace RGB.NET.Core { public interface ISampler { - Color SampleColor(SamplerInfo info); + void SampleColor(in SamplerInfo info, Span pixelData); } } diff --git a/RGB.NET.Presets/Textures/BytePixelTexture.cs b/RGB.NET.Presets/Textures/BytePixelTexture.cs index c1ed31c..1e993b6 100644 --- a/RGB.NET.Presets/Textures/BytePixelTexture.cs +++ b/RGB.NET.Presets/Textures/BytePixelTexture.cs @@ -8,22 +8,11 @@ namespace RGB.NET.Presets.Textures { #region Properties & Fields - private readonly int _stride; + private readonly byte[] _data; + protected override ReadOnlySpan Data => _data; public ColorFormat ColorFormat { get; } - public override Color this[in Rectangle rectangle] - { - get - { - Color color = base[rectangle]; - if (ColorFormat == ColorFormat.BGR) - return new Color(color.A, color.B, color.G, color.R); - - return color; - } - } - #endregion #region Constructors @@ -33,9 +22,9 @@ namespace RGB.NET.Presets.Textures { } public BytePixelTexture(int with, int height, byte[] data, ISampler sampler, ColorFormat colorFormat = ColorFormat.RGB) - : base(with, height, data, 3, sampler) + : base(with, height, 3, sampler) { - this._stride = with; + this._data = data; this.ColorFormat = colorFormat; if (Data.Length != ((with * height) * 3)) throw new ArgumentException($"Data-Length {Data.Length} differs from the given size {with}x{height} * 3 bytes ({with * height * 3})."); @@ -45,26 +34,12 @@ namespace RGB.NET.Presets.Textures #region Methods - protected override Color GetColor(int x, int y) + protected override Color GetColor(ReadOnlySpan pixel) { - int offset = ((y * _stride) + x) * 3; - if (ColorFormat == ColorFormat.BGR) - return new Color(Data[offset + 2], Data[offset + 1], Data[offset + 1]); + return new Color(pixel[2], pixel[1], pixel[0]); - return new Color(Data[offset], Data[offset + 1], Data[offset + 2]); - } - - protected override void GetRegionData(int x, int y, int width, int height, in Span buffer) - { - int width3 = width * 3; - ReadOnlySpan data = Data.AsSpan(); - for (int i = 0; i < height; i++) - { - ReadOnlySpan dataSlice = data.Slice((((y + i) * _stride) + x) * 3, width3); - Span destination = buffer.Slice(i * width3, width3); - dataSlice.CopyTo(destination); - } + return new Color(pixel[0], pixel[1], pixel[2]); } #endregion diff --git a/RGB.NET.Presets/Textures/FloatPixelTexture.cs b/RGB.NET.Presets/Textures/FloatPixelTexture.cs index aa8bd77..936cdd9 100644 --- a/RGB.NET.Presets/Textures/FloatPixelTexture.cs +++ b/RGB.NET.Presets/Textures/FloatPixelTexture.cs @@ -8,22 +8,11 @@ namespace RGB.NET.Presets.Textures { #region Properties & Fields - private readonly int _stride; + private readonly float[] _data; + protected override ReadOnlySpan Data => _data; public ColorFormat ColorFormat { get; } - public override Color this[in Rectangle rectangle] - { - get - { - Color color = base[rectangle]; - if (ColorFormat == ColorFormat.BGR) - return new Color(color.A, color.B, color.G, color.R); - - return color; - } - } - #endregion #region Constructors @@ -33,9 +22,9 @@ namespace RGB.NET.Presets.Textures { } public FloatPixelTexture(int with, int height, float[] data, ISampler sampler, ColorFormat colorFormat = ColorFormat.RGB) - : base(with, height, data, 3, sampler) + : base(with, height, 3, sampler) { - this._stride = with; + this._data = data; this.ColorFormat = colorFormat; if (Data.Length != ((with * height) * 3)) throw new ArgumentException($"Data-Length {Data.Length} differs from the given size {with}x{height} * 3 bytes ({with * height * 3})."); @@ -45,26 +34,12 @@ namespace RGB.NET.Presets.Textures #region Methods - protected override Color GetColor(int x, int y) + protected override Color GetColor(ReadOnlySpan pixel) { - int offset = ((y * _stride) + x) * 3; - if (ColorFormat == ColorFormat.BGR) - return new Color(Data[offset + 2], Data[offset + 1], Data[offset + 1]); + return new Color(pixel[2], pixel[1], pixel[0]); - return new Color(Data[offset], Data[offset + 1], Data[offset + 2]); - } - - protected override void GetRegionData(int x, int y, int width, int height, in Span buffer) - { - int width3 = width * 3; - ReadOnlySpan data = Data.AsSpan(); - for (int i = 0; i < height; i++) - { - ReadOnlySpan dataSlice = data.Slice((((y + i) * _stride) + x) * 3, width3); - Span destination = buffer.Slice(i * width3, width3); - dataSlice.CopyTo(destination); - } + return new Color(pixel[0], pixel[1], pixel[2]); } #endregion diff --git a/RGB.NET.Presets/Textures/Sampler/AverageByteSampler.cs b/RGB.NET.Presets/Textures/Sampler/AverageByteSampler.cs index 694dbe6..8c91242 100644 --- a/RGB.NET.Presets/Textures/Sampler/AverageByteSampler.cs +++ b/RGB.NET.Presets/Textures/Sampler/AverageByteSampler.cs @@ -7,23 +7,21 @@ namespace RGB.NET.Presets.Textures.Sampler { #region Methods - public Color SampleColor(SamplerInfo info) + public void SampleColor(in SamplerInfo info, Span pixelData) { int count = info.Width * info.Height; - if (count == 0) return Color.Transparent; + if (count == 0) return; ReadOnlySpan data = info.Data; - uint r = 0, g = 0, b = 0; - for (int i = 0; i < data.Length; i += 3) - { - r += data[i]; - g += data[i + 1]; - b += data[i + 2]; - } + int dataLength = pixelData.Length; + Span sums = stackalloc uint[dataLength]; + for (int i = 0; i < data.Length; i += dataLength) + for (int j = 0; j < sums.Length; j++) + sums[j] += data[i + j]; - float divisor = count * byte.MaxValue; - return new Color(r / divisor, g / divisor, b / divisor); + for (int i = 0; i < pixelData.Length; i++) + pixelData[i] = (byte)MathF.Round(sums[i] / (float)count); } #endregion diff --git a/RGB.NET.Presets/Textures/Sampler/AverageFloatSampler.cs b/RGB.NET.Presets/Textures/Sampler/AverageFloatSampler.cs index 59e1987..a9584a3 100644 --- a/RGB.NET.Presets/Textures/Sampler/AverageFloatSampler.cs +++ b/RGB.NET.Presets/Textures/Sampler/AverageFloatSampler.cs @@ -7,22 +7,21 @@ namespace RGB.NET.Presets.Textures.Sampler { #region Methods - public Color SampleColor(SamplerInfo info) + public void SampleColor(in SamplerInfo info, Span pixelData) { int count = info.Width * info.Height; - if (count == 0) return Color.Transparent; + if (count == 0) return; ReadOnlySpan data = info.Data; - float r = 0, g = 0, b = 0; - for (int i = 0; i < data.Length; i += 3) - { - r += data[i]; - g += data[i + 1]; - b += data[i + 2]; - } + int dataLength = pixelData.Length; + Span sums = stackalloc float[dataLength]; + for (int i = 0; i < data.Length; i += dataLength) + for (int j = 0; j < sums.Length; j++) + sums[j] += data[i + j]; - return new Color(r / count, g / count, b / count); + for (int i = 0; i < pixelData.Length; i++) + pixelData[i] = sums[i] / count; } #endregion From 105fdea2d799151a524fc217fda3f1d4e5b27c1c Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Thu, 25 Feb 2021 00:30:09 +0100 Subject: [PATCH 10/22] Small optimizations --- RGB.NET.Core/RGBSurface.cs | 4 ++-- RGB.NET.Core/Rendering/Textures/PixelTexture.cs | 6 +++--- .../Rendering/Textures/Sampler/AverageColorSampler.cs | 2 +- RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs | 2 +- RGB.NET.Presets/Textures/BytePixelTexture.cs | 2 +- RGB.NET.Presets/Textures/FloatPixelTexture.cs | 2 +- RGB.NET.Presets/Textures/Sampler/AverageByteSampler.cs | 5 +++-- RGB.NET.Presets/Textures/Sampler/AverageFloatSampler.cs | 2 +- 8 files changed, 13 insertions(+), 12 deletions(-) diff --git a/RGB.NET.Core/RGBSurface.cs b/RGB.NET.Core/RGBSurface.cs index 58208a3..a6c346f 100644 --- a/RGB.NET.Core/RGBSurface.cs +++ b/RGB.NET.Core/RGBSurface.cs @@ -228,8 +228,8 @@ namespace RGB.NET.Core foreach ((RenderTarget renderTarget, Color c) in render) { Color color = c; - foreach (IColorCorrection colorCorrection in renderTarget.Led.Device.ColorCorrections) - colorCorrection.ApplyTo(ref color); + for (int i = 0; i < renderTarget.Led.Device.ColorCorrections.Count; i++) + renderTarget.Led.Device.ColorCorrections[i].ApplyTo(ref color); renderTarget.Led.Color = color; } diff --git a/RGB.NET.Core/Rendering/Textures/PixelTexture.cs b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs index f193ec2..43a7828 100644 --- a/RGB.NET.Core/Rendering/Textures/PixelTexture.cs +++ b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs @@ -91,12 +91,12 @@ namespace RGB.NET.Core #region Methods - protected abstract Color GetColor(ReadOnlySpan pixel); + protected abstract Color GetColor(in ReadOnlySpan pixel); [MethodImpl(MethodImplOptions.AggressiveInlining)] protected virtual ReadOnlySpan GetPixelData(int x, int y) => Data.Slice((y * _stride) + x, _dataPerPixel); - protected virtual void GetRegionData(int x, int y, int width, int height, Span buffer) + protected virtual void GetRegionData(int x, int y, int width, int height, in Span buffer) { int dataWidth = width * _dataPerPixel; ReadOnlySpan data = Data; @@ -139,7 +139,7 @@ namespace RGB.NET.Core #region Methods - protected override Color GetColor(ReadOnlySpan pixel) => pixel[0]; + protected override Color GetColor(in ReadOnlySpan pixel) => pixel[0]; #endregion } diff --git a/RGB.NET.Core/Rendering/Textures/Sampler/AverageColorSampler.cs b/RGB.NET.Core/Rendering/Textures/Sampler/AverageColorSampler.cs index 11c3dd2..4910dbc 100644 --- a/RGB.NET.Core/Rendering/Textures/Sampler/AverageColorSampler.cs +++ b/RGB.NET.Core/Rendering/Textures/Sampler/AverageColorSampler.cs @@ -6,7 +6,7 @@ namespace RGB.NET.Core { #region Methods - public void SampleColor(in SamplerInfo info, Span pixelData) + public void SampleColor(in SamplerInfo info, in Span pixelData) { int count = info.Width * info.Height; if (count == 0) return; diff --git a/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs b/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs index 2b76c5f..ce507bd 100644 --- a/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs +++ b/RGB.NET.Core/Rendering/Textures/Sampler/ISampler.cs @@ -4,6 +4,6 @@ namespace RGB.NET.Core { public interface ISampler { - void SampleColor(in SamplerInfo info, Span pixelData); + void SampleColor(in SamplerInfo info, in Span pixelData); } } diff --git a/RGB.NET.Presets/Textures/BytePixelTexture.cs b/RGB.NET.Presets/Textures/BytePixelTexture.cs index 1e993b6..ab008b7 100644 --- a/RGB.NET.Presets/Textures/BytePixelTexture.cs +++ b/RGB.NET.Presets/Textures/BytePixelTexture.cs @@ -34,7 +34,7 @@ namespace RGB.NET.Presets.Textures #region Methods - protected override Color GetColor(ReadOnlySpan pixel) + protected override Color GetColor(in ReadOnlySpan pixel) { if (ColorFormat == ColorFormat.BGR) return new Color(pixel[2], pixel[1], pixel[0]); diff --git a/RGB.NET.Presets/Textures/FloatPixelTexture.cs b/RGB.NET.Presets/Textures/FloatPixelTexture.cs index 936cdd9..686f05c 100644 --- a/RGB.NET.Presets/Textures/FloatPixelTexture.cs +++ b/RGB.NET.Presets/Textures/FloatPixelTexture.cs @@ -34,7 +34,7 @@ namespace RGB.NET.Presets.Textures #region Methods - protected override Color GetColor(ReadOnlySpan pixel) + protected override Color GetColor(in ReadOnlySpan pixel) { if (ColorFormat == ColorFormat.BGR) return new Color(pixel[2], pixel[1], pixel[0]); diff --git a/RGB.NET.Presets/Textures/Sampler/AverageByteSampler.cs b/RGB.NET.Presets/Textures/Sampler/AverageByteSampler.cs index 8c91242..b2f3770 100644 --- a/RGB.NET.Presets/Textures/Sampler/AverageByteSampler.cs +++ b/RGB.NET.Presets/Textures/Sampler/AverageByteSampler.cs @@ -7,7 +7,7 @@ namespace RGB.NET.Presets.Textures.Sampler { #region Methods - public void SampleColor(in SamplerInfo info, Span pixelData) + public void SampleColor(in SamplerInfo info, in Span pixelData) { int count = info.Width * info.Height; if (count == 0) return; @@ -20,8 +20,9 @@ namespace RGB.NET.Presets.Textures.Sampler for (int j = 0; j < sums.Length; j++) sums[j] += data[i + j]; + float divisor = count * byte.MaxValue; for (int i = 0; i < pixelData.Length; i++) - pixelData[i] = (byte)MathF.Round(sums[i] / (float)count); + pixelData[i] = (sums[i] / divisor).GetByteValueFromPercentage(); } #endregion diff --git a/RGB.NET.Presets/Textures/Sampler/AverageFloatSampler.cs b/RGB.NET.Presets/Textures/Sampler/AverageFloatSampler.cs index a9584a3..12b0368 100644 --- a/RGB.NET.Presets/Textures/Sampler/AverageFloatSampler.cs +++ b/RGB.NET.Presets/Textures/Sampler/AverageFloatSampler.cs @@ -7,7 +7,7 @@ namespace RGB.NET.Presets.Textures.Sampler { #region Methods - public void SampleColor(in SamplerInfo info, Span pixelData) + public void SampleColor(in SamplerInfo info, in Span pixelData) { int count = info.Width * info.Height; if (count == 0) return; From 1975b9bf486c5eabf0490e29543f2513ed021937 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Fri, 26 Feb 2021 00:31:16 +0100 Subject: [PATCH 11/22] Added XYZ, Lab and LCh color-methods --- RGB.NET.Core/Color/HclColor.cs | 203 +++++++++++++++++++++++++++++ RGB.NET.Core/Color/LabColor.cs | 228 +++++++++++++++++++++++++++++++++ RGB.NET.Core/Color/XYZColor.cs | 200 +++++++++++++++++++++++++++++ 3 files changed, 631 insertions(+) create mode 100644 RGB.NET.Core/Color/HclColor.cs create mode 100644 RGB.NET.Core/Color/LabColor.cs create mode 100644 RGB.NET.Core/Color/XYZColor.cs diff --git a/RGB.NET.Core/Color/HclColor.cs b/RGB.NET.Core/Color/HclColor.cs new file mode 100644 index 0000000..ee05be7 --- /dev/null +++ b/RGB.NET.Core/Color/HclColor.cs @@ -0,0 +1,203 @@ +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedMember.Global +using System; + +namespace RGB.NET.Core +{ + public static class HclColor + { + #region Getter + + /// + /// Gets the H component value (Hcl-color space) of this in the range [0..360]. + /// + /// + /// + public static float GetHclH(this in Color color) => color.GetHcl().l; + + /// + /// Gets the c component value (Hcl-color space) of this in the range [0..1]. + /// + /// + /// + public static float GetHclC(this in Color color) => color.GetHcl().c; + + /// + /// Gets the l component value (Hcl-color space) of this in the range [0..1]. + /// + /// + /// + public static float GetHclL(this in Color color) => color.GetHcl().h; + + /// + /// Gets the H, c and l component values (Hcl-color space) of this . + /// H in the range [0..360]. + /// c in the range [0..1]. + /// l in the range [0..1]. + /// + /// + /// + public static (float h, float c, float l) GetHcl(this in Color color) + => CalculateHclFromRGB(color.R, color.G, color.B); + + #endregion + + #region Manipulation + + /// + /// Adds the given Hcl values to this color. + /// + /// The H value to add. + /// The c value to add. + /// The l value to add. + /// The new color after the modification. + public static Color AddHcl(this in Color color, float h = 0, float c = 0, float l = 0) + { + (float cH, float cC, float cL) = color.GetHcl(); + return Create(color.A, cH + h, cC + c, cL + l); + } + + /// + /// Subtracts the given Hcl values to this color. + /// + /// The H value to subtract. + /// The c value to subtract. + /// The l value to subtract. + /// The new color after the modification. + public static Color SubtractHcl(this in Color color, float h = 0, float c = 0, float l = 0) + { + (float cH, float cC, float cL) = color.GetHcl(); + return Create(color.A, cH - h, cC - c, cL - l); + } + + /// + /// Multiplies the given Hcl values to this color. + /// + /// The H value to multiply. + /// The c value to multiply. + /// The l value to multiply. + /// The new color after the modification. + public static Color MultiplyHcl(this in Color color, float h = 1, float c = 1, float l = 1) + { + (float cH, float cC, float cL) = color.GetHcl(); + return Create(color.A, cH * h, cC * c, cL * l); + } + + /// + /// Divides the given Hcl values to this color. + /// + /// The H value to divide. + /// The c value to divide. + /// The l value to divide. + /// The new color after the modification. + public static Color DivideHcl(this in Color color, float h = 1, float c = 1, float l = 1) + { + (float cH, float cC, float cL) = color.GetHcl(); + return Create(color.A, cH / h, cC / c, cL / l); + } + + /// + /// Sets the given X value of this color. + /// + /// The H value to set. + /// The c value to set. + /// The l value to set. + /// The new color after the modification. + public static Color SetHcl(this in Color color, float? h = null, float? c = null, float? l = null) + { + (float cH, float cC, float cL) = color.GetHcl(); + return Create(color.A, h ?? cH, c ?? cC, l ?? cL); + } + + #endregion + + #region Factory + + /// + /// Creates a new instance of the struct using Hcl-Values. + /// + /// The H component value of this . + /// The c component value of this . + /// The l component value of this . + /// The color created from the values. + public static Color Create(float h, float c, float l) + => Create(1.0f, h, c, l); + + /// + /// Creates a new instance of the struct using alpha and Hcl-Values. + /// + /// The alphc component value of this . + /// The H component value of this . + /// The c component value of this . + /// The l component value of this . + /// The color created from the values. + public static Color Create(byte alpha, float h, float c, float l) + => Create((float)alpha / byte.MaxValue, h, c, l); + + /// + /// Creates a new instance of the struct using alpha and Hcl-Values. + /// + /// The alphc component value of this . + /// The H component value of this . + /// The c component value of this . + /// The l component value of this . + /// The color created from the values. + public static Color Create(int alpha, float h, float c, float l) + => Create((float)alpha / byte.MaxValue, h, c, l); + + /// + /// Creates a new instance of the struct using alpha and Hcl-Values. + /// + /// The alphc component value of this . + /// The H component value of this . + /// The c component value of this . + /// The l component value of this . + /// The color created from the values. + public static Color Create(float alpha, float h, float c, float l) + { + (float r, float g, float _b) = CalculateRGBFromHcl(h, c, l); + return new Color(alpha, r, g, _b); + } + + #endregion + + #region Helper + + private static (float h, float c, float l) CalculateHclFromRGB(float r, float g, float b) + { + const float RADIANS_DEGREES_CONVERSION = 180.0f / MathF.PI; + + (float l, float a, float _b) = LabColor.CalculateLabFromRGB(r, g, b); + + float h, c; + if (r.EqualsInTolerance(g) && r.EqualsInTolerance(b)) //DarthAffe 26.02.2021: The cumulated rounding errors are big enough to cause problems in that case + { + h = 0; + c = 0; + } + else + { + h = MathF.Atan2(_b, a); + if (h >= 0) h *= RADIANS_DEGREES_CONVERSION; + else h = 360 - (-h * RADIANS_DEGREES_CONVERSION); + + c = MathF.Sqrt((a * a) + (_b * _b)); + } + + return (h, c, l); + } + + private static (float r, float g, float b) CalculateRGBFromHcl(float h, float c, float l) + { + const float DEGREES_RADIANS_CONVERSION = MathF.PI / 180.0f; + + h *= DEGREES_RADIANS_CONVERSION; + float a = c * MathF.Cos(h); + float b = c * MathF.Sign(h); + + return LabColor.CalculateRGBFromLab(l, a, b); + } + + #endregion + } +} diff --git a/RGB.NET.Core/Color/LabColor.cs b/RGB.NET.Core/Color/LabColor.cs new file mode 100644 index 0000000..6b2b17b --- /dev/null +++ b/RGB.NET.Core/Color/LabColor.cs @@ -0,0 +1,228 @@ +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedMember.Global +using System; + +namespace RGB.NET.Core +{ + public static class LabColor + { + #region Getter + + /// + /// Gets the L component value (Lab-color space) of this in the range [0..100]. + /// + /// + /// + public static float GetLabL(this in Color color) => color.GetLab().l; + + /// + /// Gets the a component value (Lab-color space) of this in the range [0..1]. + /// + /// + /// + public static float GetLabA(this in Color color) => color.GetLab().a; + + /// + /// Gets the b component value (Lab-color space) of this in the range [0..1]. + /// + /// + /// + public static float GetLabB(this in Color color) => color.GetLab().b; + + /// + /// Gets the L, a and b component values (Lab-color space) of this . + /// L in the range [0..100]. + /// a in the range [0..1]. + /// b in the range [0..1]. + /// + /// + /// + public static (float l, float a, float b) GetLab(this in Color color) + => CalculateLabFromRGB(color.R, color.G, color.B); + + #endregion + + #region Manipulation + + /// + /// Adds the given Lab values to this color. + /// + /// The L value to add. + /// The a value to add. + /// The b value to add. + /// The new color after the modification. + public static Color AddLab(this in Color color, float l = 0, float a = 0, float b = 0) + { + (float cL, float cA, float cB) = color.GetLab(); + return Create(color.A, cL + l, cA + a, cB + b); + } + + /// + /// Subtracts the given Lab values to this color. + /// + /// The L value to subtract. + /// The a value to subtract. + /// The b value to subtract. + /// The new color after the modification. + public static Color SubtractLab(this in Color color, float l = 0, float a = 0, float b = 0) + { + (float cL, float cA, float cB) = color.GetLab(); + return Create(color.A, cL - l, cA - a, cB - b); + } + + /// + /// Multiplies the given Lab values to this color. + /// + /// The L value to multiply. + /// The a value to multiply. + /// The b value to multiply. + /// The new color after the modification. + public static Color MultiplyLab(this in Color color, float l = 1, float a = 1, float b = 1) + { + (float cL, float cA, float cB) = color.GetLab(); + return Create(color.A, cL * l, cA * a, cB * b); + } + + /// + /// Divides the given Lab values to this color. + /// + /// The L value to divide. + /// The a value to divide. + /// The b value to divide. + /// The new color after the modification. + public static Color DivideLab(this in Color color, float l = 1, float a = 1, float b = 1) + { + (float cL, float cA, float cB) = color.GetLab(); + return Create(color.A, cL / l, cA / a, cB / b); + } + + /// + /// Sets the given X valueof this color. + /// + /// The L value to set. + /// The a value to set. + /// The b value to set. + /// The new color after the modification. + public static Color SetLab(this in Color color, float? l = null, float? a = null, float? b = null) + { + (float cL, float cA, float cB) = color.GetLab(); + return Create(color.A, l ?? cL, a ?? cA, b ?? cB); + } + + #endregion + + #region Factory + + /// + /// Creates a new instance of the struct using Lab-Values. + /// + /// The L component value of this . + /// The a component value of this . + /// The b component value of this . + /// The color created from the values. + public static Color Create(float l, float a, float b) + => Create(1.0f, l, a, b); + + /// + /// Creates a new instance of the struct using alpha and Lab-Values. + /// + /// The alpha component value of this . + /// The L component value of this . + /// The a component value of this . + /// The b component value of this . + /// The color created from the values. + public static Color Create(byte alpha, float l, float a, float b) + => Create((float)alpha / byte.MaxValue, l, a, b); + + /// + /// Creates a new instance of the struct using alpha and Lab-Values. + /// + /// The alpha component value of this . + /// The L component value of this . + /// The a component value of this . + /// The b component value of this . + /// The color created from the values. + public static Color Create(int alpha, float l, float a, float b) + => Create((float)alpha / byte.MaxValue, l, a, b); + + /// + /// Creates a new instance of the struct using alpha and Lab-Values. + /// + /// The alpha component value of this . + /// The L component value of this . + /// The a component value of this . + /// The b component value of this . + /// The color created from the values. + public static Color Create(float alpha, float l, float a, float b) + { + (float r, float g, float _b) = CalculateRGBFromLab(l, a, b); + return new Color(alpha, r, g, _b); + } + + #endregion + + #region Helper + + internal static (float l, float a, float b) CalculateLabFromRGB(float r, float g, float b) + { + (float x, float y, float z) = XYZColor.CaclulateXYZFromRGB(r, g, b); + return CaclulateLabFromXYZ(x, y, z); + + //const float LAB_MULTIPLIER = (1f / 127f) * 0.5f; + + //(float x, float y, float z) = XYZColor.CaclulateXYZFromRGB(r, g, b); + //(float l, float a, float _b) = CaclulateLabFromXYZ(x, y, z); + //return (l / 100.0f, 0.5f + (a * LAB_MULTIPLIER), 0.5f + (_b * LAB_MULTIPLIER)); + } + + internal static (float r, float g, float b) CalculateRGBFromLab(float l, float a, float b) + { + (float x, float y, float z) = CalculateXYZFromLab(l, a, b); + return XYZColor.CalculateRGBFromXYZ(x, y, z); + + //(float x, float y, float z) = CalculateXYZFromLab(100.0f * l, 254.0f * (a - 0.5f), 2.0f * 254.0f * (b - 0.5f)); + //return XYZColor.CalculateRGBFromXYZ(x, y, z); + } + + private static (float l, float a, float b) CaclulateLabFromXYZ(float x, float y, float z) + { + const float ONETHRID = 1.0f / 3.0f; + const float FACTOR2 = 16.0f / 116.0f; + + x /= 95.047f; + y /= 100.0f; + z /= 108.883f; + + x = ((x > 0.008856f) ? (MathF.Pow(x, ONETHRID)) : ((7.787f * x) + FACTOR2)); + y = ((y > 0.008856f) ? (MathF.Pow(y, ONETHRID)) : ((7.787f * y) + FACTOR2)); + z = ((z > 0.008856f) ? (MathF.Pow(z, ONETHRID)) : ((7.787f * z) + FACTOR2)); + + float l = (116.0f * y) - 16.0f; + float a = 500.0f * (x - y); + float b = 200.0f * (y - z); + + return (l, a, b); + } + + private static (float x, float y, float z) CalculateXYZFromLab(float l, float a, float b) + { + const float FACTOR2 = 16.0f / 116.0f; + + float y = (l + 16.0f) / 116.0f; + float x = (a / 500.0f) + y; + float z = y - (b / 200.0f); + + float powX = MathF.Pow(y, 3.0f); + float powY = MathF.Pow(y, 3.0f); + float powZ = MathF.Pow(y, 3.0f); + + y = ((powY > 0.008856f) ? (powY) : ((y - FACTOR2) / 7.787f)); + x = ((powX > 0.008856f) ? (powX) : ((x - FACTOR2) / 7.787f)); + z = ((powZ > 0.008856f) ? (powZ) : ((z - FACTOR2) / 7.787f)); + + return (95.047f * x, 100.0f * y, 108.883f * z); + } + + #endregion + } +} diff --git a/RGB.NET.Core/Color/XYZColor.cs b/RGB.NET.Core/Color/XYZColor.cs new file mode 100644 index 0000000..d02329e --- /dev/null +++ b/RGB.NET.Core/Color/XYZColor.cs @@ -0,0 +1,200 @@ +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedMember.Global +using System; + +namespace RGB.NET.Core +{ + public static class XYZColor + { + #region Getter + + /// + /// Gets the X component value (XYZ-color space) of this in the range [0..95.047]. + /// + /// + /// + public static float GetX(this in Color color) => color.GetXYZ().x; + + /// + /// Gets the Y component value (XYZ-color space) of this in the range [0..100]. + /// + /// + /// + public static float GetY(this in Color color) => color.GetXYZ().y; + + /// + /// Gets the Z component value (XYZ-color space) of this in the range [0..108.883]. + /// + /// + /// + public static float GetZ(this in Color color) => color.GetXYZ().z; + + /// + /// Gets the X, Y and Z component values (XYZ-color space) of this . + /// X in the range [0..95.047]. + /// Y in the range [0..100]. + /// Z in the range [0..108.883]. + /// + /// + /// + public static (float x, float y, float z) GetXYZ(this in Color color) + => CaclulateXYZFromRGB(color.R, color.G, color.B); + + #endregion + + #region Manipulation + + /// + /// Adds the given XYZ values to this color. + /// + /// The X value to add. + /// The Y value to add. + /// The Z value to add. + /// The new color after the modification. + public static Color AddXYZ(this in Color color, float x = 0, float y = 0, float z = 0) + { + (float cX, float cY, float cZ) = color.GetXYZ(); + return Create(color.A, cX + x, cY + y, cZ + z); + } + + /// + /// Subtracts the given XYZ values to this color. + /// + /// The X value to subtract. + /// The Y value to subtract. + /// The Z value to subtract. + /// The new color after the modification. + public static Color SubtractXYZ(this in Color color, float x = 0, float y = 0, float z = 0) + { + (float cX, float cY, float cZ) = color.GetXYZ(); + return Create(color.A, cX - x, cY - y, cZ - z); + } + + /// + /// Multiplies the given XYZ values to this color. + /// + /// The X value to multiply. + /// The Y value to multiply. + /// The Z value to multiply. + /// The new color after the modification. + public static Color MultiplyXYZ(this in Color color, float x = 1, float y = 1, float z = 1) + { + (float cX, float cY, float cZ) = color.GetXYZ(); + return Create(color.A, cX * x, cY * y, cZ * z); + } + + /// + /// Divides the given XYZ values to this color. + /// + /// The X value to divide. + /// The Y value to divide. + /// The Z value to divide. + /// The new color after the modification. + public static Color DivideXYZ(this in Color color, float x = 1, float y = 1, float z = 1) + { + (float cX, float cY, float cZ) = color.GetXYZ(); + return Create(color.A, cX / x, cY / y, cZ / z); + } + + /// + /// Sets the given X valueof this color. + /// + /// The X value to set. + /// The Y value to set. + /// The Z value to set. + /// The new color after the modification. + public static Color SetXYZ(this in Color color, float? x = null, float? y = null, float? value = null) + { + (float cX, float cY, float cZ) = color.GetXYZ(); + return Create(color.A, x ?? cX, y ?? cY, value ?? cZ); + } + + #endregion + + #region Factory + + /// + /// Creates a new instance of the struct using XYZ-Values. + /// + /// The X component value of this . + /// The Y component value of this . + /// The Z component value of this . + /// The color created from the values. + public static Color Create(float x, float y, float z) + => Create(1.0f, x, y, z); + + /// + /// Creates a new instance of the struct using alpha and XYZ-Values. + /// + /// The alpha component value of this . + /// The X component value of this . + /// The Y component value of this . + /// The Z component value of this . + /// The color created from the values. + public static Color Create(byte a, float x, float y, float z) + => Create((float)a / byte.MaxValue, x, y, z); + + /// + /// Creates a new instance of the struct using alpha and XYZ-Values. + /// + /// The alpha component value of this . + /// The X component value of this . + /// The Y component value of this . + /// The Z component value of this . + /// The color created from the values. + public static Color Create(int a, float x, float y, float z) + => Create((float)a / byte.MaxValue, x, y, z); + + /// + /// Creates a new instance of the struct using alpha and XYZ-Values. + /// + /// The alpha component value of this . + /// The X component value of this . + /// The Y component value of this . + /// The Z component value of this . + /// The color created from the values. + public static Color Create(float a, float x, float y, float z) + { + (float r, float g, float b) = CalculateRGBFromXYZ(x, y, z); + return new Color(a, r, g, b); + } + + #endregion + + #region Helper + + internal static (float x, float y, float z) CaclulateXYZFromRGB(float r, float g, float b) + { + r = ((r > 0.04045f) ? MathF.Pow(((r + 0.055f) / 1.055f), 2.4f) : (r / 12.92f)) * 100.0f; + g = ((g > 0.04045f) ? MathF.Pow(((g + 0.055f) / 1.055f), 2.4f) : (g / 12.92f)) * 100.0f; + b = ((b > 0.04045f) ? MathF.Pow(((b + 0.055f) / 1.055f), 2.4f) : (b / 12.92f)) * 100.0f; + + float x = (r * 0.4124f) + (g * 0.3576f) + (b * 0.1805f); + float y = (r * 0.2126f) + (g * 0.7152f) + (b * 0.0722f); + float z = (r * 0.0193f) + (g * 0.1192f) + (b * 0.9505f); + + return (x, y, z); + } + + internal static (float r, float g, float b) CalculateRGBFromXYZ(float x, float y, float z) + { + const float INVERSE_EXPONENT = 1.0f / 2.4f; + + x /= 100.0f; + y /= 100.0f; + z /= 100.0f; + + float r = (x * 3.2406f) + (y * -1.5372f) + (z * -0.4986f); + float g = (x * -0.9689f) + (y * 1.8758f) + (z * 0.0415f); + float b = (x * 0.0557f) + (y * -0.2040f) + (z * 1.0570f); + + r = ((r > 0.0031308f) ? ((1.055f * (MathF.Pow(r, INVERSE_EXPONENT))) - 0.055f) : (12.92f * r)); + g = ((g > 0.0031308f) ? ((1.055f * (MathF.Pow(g, INVERSE_EXPONENT))) - 0.055f) : (12.92f * g)); + b = ((b > 0.0031308f) ? ((1.055f * (MathF.Pow(b, INVERSE_EXPONENT))) - 0.055f) : (12.92f * b)); + + return (r, g, b); + } + + #endregion + } +} From fe2f6e00f1be8aed10d76f841ac56dd681035347 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Fri, 26 Feb 2021 01:03:54 +0100 Subject: [PATCH 12/22] Fixed some erorrs in color calculations --- RGB.NET.Core/Color/HclColor.cs | 2 +- RGB.NET.Core/Color/LabColor.cs | 17 ++++------------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/RGB.NET.Core/Color/HclColor.cs b/RGB.NET.Core/Color/HclColor.cs index ee05be7..368ae8d 100644 --- a/RGB.NET.Core/Color/HclColor.cs +++ b/RGB.NET.Core/Color/HclColor.cs @@ -193,7 +193,7 @@ namespace RGB.NET.Core h *= DEGREES_RADIANS_CONVERSION; float a = c * MathF.Cos(h); - float b = c * MathF.Sign(h); + float b = c * MathF.Sin(h); return LabColor.CalculateRGBFromLab(l, a, b); } diff --git a/RGB.NET.Core/Color/LabColor.cs b/RGB.NET.Core/Color/LabColor.cs index 6b2b17b..5583a79 100644 --- a/RGB.NET.Core/Color/LabColor.cs +++ b/RGB.NET.Core/Color/LabColor.cs @@ -167,21 +167,12 @@ namespace RGB.NET.Core { (float x, float y, float z) = XYZColor.CaclulateXYZFromRGB(r, g, b); return CaclulateLabFromXYZ(x, y, z); - - //const float LAB_MULTIPLIER = (1f / 127f) * 0.5f; - - //(float x, float y, float z) = XYZColor.CaclulateXYZFromRGB(r, g, b); - //(float l, float a, float _b) = CaclulateLabFromXYZ(x, y, z); - //return (l / 100.0f, 0.5f + (a * LAB_MULTIPLIER), 0.5f + (_b * LAB_MULTIPLIER)); } internal static (float r, float g, float b) CalculateRGBFromLab(float l, float a, float b) { (float x, float y, float z) = CalculateXYZFromLab(l, a, b); return XYZColor.CalculateRGBFromXYZ(x, y, z); - - //(float x, float y, float z) = CalculateXYZFromLab(100.0f * l, 254.0f * (a - 0.5f), 2.0f * 254.0f * (b - 0.5f)); - //return XYZColor.CalculateRGBFromXYZ(x, y, z); } private static (float l, float a, float b) CaclulateLabFromXYZ(float x, float y, float z) @@ -212,15 +203,15 @@ namespace RGB.NET.Core float x = (a / 500.0f) + y; float z = y - (b / 200.0f); - float powX = MathF.Pow(y, 3.0f); + float powX = MathF.Pow(x, 3.0f); float powY = MathF.Pow(y, 3.0f); - float powZ = MathF.Pow(y, 3.0f); + float powZ = MathF.Pow(z, 3.0f); - y = ((powY > 0.008856f) ? (powY) : ((y - FACTOR2) / 7.787f)); x = ((powX > 0.008856f) ? (powX) : ((x - FACTOR2) / 7.787f)); + y = ((powY > 0.008856f) ? (powY) : ((y - FACTOR2) / 7.787f)); z = ((powZ > 0.008856f) ? (powZ) : ((z - FACTOR2) / 7.787f)); - return (95.047f * x, 100.0f * y, 108.883f * z); + return (x * 95.047f, y * 100.0f, z * 108.883f); } #endregion From 0780f37852eb6b47c7570d65b36740e330f82cd6 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Sat, 27 Feb 2021 00:26:20 +0100 Subject: [PATCH 13/22] Added check for empty or one pixel requrests in Texture --- RGB.NET.Core/Rendering/Textures/PixelTexture.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/RGB.NET.Core/Rendering/Textures/PixelTexture.cs b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs index 43a7828..0820319 100644 --- a/RGB.NET.Core/Rendering/Textures/PixelTexture.cs +++ b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs @@ -29,8 +29,8 @@ namespace RGB.NET.Core { if (Data.Length == 0) return Color.Transparent; - int x = (int)Math.Round(Size.Width * point.X.Clamp(0, 1)); - int y = (int)Math.Round(Size.Height * point.Y.Clamp(0, 1)); + int x = (int)MathF.Round(Size.Width * point.X.Clamp(0, 1)); + int y = (int)MathF.Round(Size.Height * point.Y.Clamp(0, 1)); return GetColor(GetPixelData(x, y)); } } @@ -41,10 +41,13 @@ namespace RGB.NET.Core { if (Data.Length == 0) return Color.Transparent; - int x = (int)Math.Round(Size.Width * rectangle.Location.X.Clamp(0, 1)); - int y = (int)Math.Round(Size.Height * rectangle.Location.Y.Clamp(0, 1)); - int width = (int)Math.Round(Size.Width * rectangle.Size.Width.Clamp(0, 1)); - int height = (int)Math.Round(Size.Height * rectangle.Size.Height.Clamp(0, 1)); + int x = (int)MathF.Round(Size.Width * rectangle.Location.X.Clamp(0, 1)); + int y = (int)MathF.Round(Size.Height * rectangle.Location.Y.Clamp(0, 1)); + int width = (int)MathF.Round(Size.Width * rectangle.Size.Width.Clamp(0, 1)); + int height = (int)MathF.Round(Size.Height * rectangle.Size.Height.Clamp(0, 1)); + + if ((width == 0) || (height == 0)) return Color.Transparent; + if ((width == 1) && (height == 1)) return GetColor(GetPixelData(x, y)); int bufferSize = width * height * _dataPerPixel; if (bufferSize <= STACK_ALLOC_LIMIT) From 9c8d67740d26850f5a6a1497747ec451302840eb Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Mon, 1 Mar 2021 22:49:31 +0100 Subject: [PATCH 14/22] Added custom stride parameter to PixelTexture --- RGB.NET.Core/Rendering/Textures/PixelTexture.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RGB.NET.Core/Rendering/Textures/PixelTexture.cs b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs index 0820319..9b14405 100644 --- a/RGB.NET.Core/Rendering/Textures/PixelTexture.cs +++ b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs @@ -81,9 +81,9 @@ namespace RGB.NET.Core #region Constructors - public PixelTexture(int with, int height, int dataPerPixel, ISampler sampler) + public PixelTexture(int with, int height, int dataPerPixel, ISampler sampler, int stride = -1) { - this._stride = with; + this._stride = stride == -1 ? with : stride; this._dataPerPixel = dataPerPixel; this.Sampler = sampler; From 2222808c23c6323eb8164f6cdff9f5400cea0b7e Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Wed, 3 Mar 2021 23:06:22 +0100 Subject: [PATCH 15/22] Changed update-Pprameter away from dictionary --- .../Events/SurfaceLayoutChangedEventArgs.cs | 1 - .../Rendering/Brushes/AbstractBrush.cs | 1 - RGB.NET.Core/Update/Devices/UpdateQueue.cs | 41 +++++++++++-------- .../Generic/AsusUpdateQueue.cs | 4 +- .../Generic/CoolerMasterUpdateQueue.cs | 12 +++--- .../Generic/CorsairDeviceUpdateQueue.cs | 23 +++++------ RGB.NET.Devices.DMX/E131/E131UpdateQueue.cs | 9 ++-- .../PerDevice/LogitechPerDeviceUpdateQueue.cs | 6 +-- .../PerKey/LogitechPerKeyUpdateQueue.cs | 15 ++++--- .../Zone/LogitechZoneUpdateQueue.cs | 24 +++++------ .../Generic/MsiDeviceUpdateQueue.cs | 8 ++-- .../Generic/LimitedColorUpdateQueue.cs | 11 +++-- .../Generic/MidiUpdateQueue.cs | 9 ++-- .../Generic/RGBColorUpdateQueue.cs | 9 ++-- .../ChromaLink/RazerChromaLinkUpdateQueue.cs | 9 ++-- .../Generic/RazerUpdateQueue.cs | 5 +-- .../Headset/RazerHeadsetUpdateQueue.cs | 11 +++-- .../Keyboard/RazerKeyboardUpdateQueue.cs | 10 ++--- .../Keypad/RazerKeypadUpdateQueue.cs | 10 ++--- .../Mouse/RazerMouseUpdateQueue.cs | 10 ++--- .../Mousepad/RazerMousepadUpdateQueue.cs | 10 ++--- .../Generic/SteelSeriesDeviceUpdateQueue.cs | 6 +-- .../Arduino/ArduinoWS2812USBUpdateQueue.cs | 4 +- .../BitwizardWS2812USBUpdateQueue.cs | 2 +- .../Generic/SerialPortUpdateQueue.cs | 9 ++-- .../NodeMCU/NodeMCUWS2812USBUpdateQueue.cs | 11 +++-- .../Generic/WootingUpdateQueue.cs | 12 +++--- 27 files changed, 133 insertions(+), 149 deletions(-) diff --git a/RGB.NET.Core/Events/SurfaceLayoutChangedEventArgs.cs b/RGB.NET.Core/Events/SurfaceLayoutChangedEventArgs.cs index 64a91df..e591385 100644 --- a/RGB.NET.Core/Events/SurfaceLayoutChangedEventArgs.cs +++ b/RGB.NET.Core/Events/SurfaceLayoutChangedEventArgs.cs @@ -2,7 +2,6 @@ // ReSharper disable UnusedAutoPropertyAccessor.Global using System; -using System.Collections.Generic; namespace RGB.NET.Core { diff --git a/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs b/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs index 782c496..e4d7274 100644 --- a/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs +++ b/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs @@ -3,7 +3,6 @@ // ReSharper disable VirtualMemberNeverOverridden.Global using System.Collections.Generic; -using System.Linq; namespace RGB.NET.Core { diff --git a/RGB.NET.Core/Update/Devices/UpdateQueue.cs b/RGB.NET.Core/Update/Devices/UpdateQueue.cs index d64584e..76e6180 100644 --- a/RGB.NET.Core/Update/Devices/UpdateQueue.cs +++ b/RGB.NET.Core/Update/Devices/UpdateQueue.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers; using System.Collections.Generic; using System.Linq; @@ -16,7 +17,7 @@ namespace RGB.NET.Core private readonly object _dataLock = new(); private readonly IDeviceUpdateTrigger _updateTrigger; - private Dictionary? _currentDataSet; + private readonly Dictionary _currentDataSet = new(); #endregion @@ -45,17 +46,25 @@ namespace RGB.NET.Core /// provided by the trigger. protected virtual void OnUpdate(object? sender, CustomUpdateData customData) { - Dictionary dataSet; + (TIdentifier, TData)[] dataSet; lock (_dataLock) { - if (_currentDataSet == null) return; + if (_currentDataSet.Count == 0) return; - dataSet = _currentDataSet; - _currentDataSet = null; + dataSet = ArrayPool<(TIdentifier, TData)>.Shared.Rent(_currentDataSet.Count); + Span<(TIdentifier, TData)> data = new Span<(TIdentifier, TData)>(dataSet).Slice(0, _currentDataSet.Count); + + int i = 0; + foreach ((TIdentifier key, TData value) in _currentDataSet) + data[i++] = (key, value); + + _currentDataSet.Clear(); } - if (dataSet.Count != 0) + if (dataSet.Length != 0) Update(dataSet); + + ArrayPool<(TIdentifier, TData)>.Shared.Return(dataSet); } /// @@ -69,26 +78,22 @@ namespace RGB.NET.Core /// Performs the update this queue is responsible for. /// /// The set of data that needs to be updated. - protected abstract void Update(Dictionary dataSet); + protected abstract void Update(in ReadOnlySpan<(TIdentifier key, TData color)> dataSet); /// /// Sets or merges the provided data set in the current dataset and notifies the trigger that there is new data available. /// /// The set of data. // ReSharper disable once MemberCanBeProtected.Global - public virtual void SetData(Dictionary dataSet) + public virtual void SetData(IEnumerable<(TIdentifier, TData)> dataSet) { - if (dataSet.Count == 0) return; + IList<(TIdentifier, TData)> data = dataSet.ToList(); + if (data.Count == 0) return; lock (_dataLock) { - if (_currentDataSet == null) - _currentDataSet = dataSet; - else - { - foreach ((TIdentifier key, TData value) in dataSet) - _currentDataSet[key] = value; - } + foreach ((TIdentifier key, TData value) in data) + _currentDataSet[key] = value; } _updateTrigger.TriggerHasData(); @@ -100,7 +105,7 @@ namespace RGB.NET.Core public virtual void Reset() { lock (_dataLock) - _currentDataSet = null; + _currentDataSet.Clear(); } /// @@ -135,7 +140,7 @@ namespace RGB.NET.Core /// Calls for a data set created out of the provided list of . /// /// - public void SetData(IEnumerable leds) => SetData(leds.ToDictionary(x => x.CustomData ?? x.Id, x => x.Color)); + public void SetData(IEnumerable leds) => SetData(leds.Select(x => (x.CustomData ?? x.Id, x.Color))); #endregion } diff --git a/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs b/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs index 1623fa7..73cbc31 100644 --- a/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs +++ b/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System; using AuraServiceLib; using RGB.NET.Core; @@ -43,7 +43,7 @@ namespace RGB.NET.Devices.Asus } /// - protected override void Update(Dictionary dataSet) + protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { if (Device == null) return; diff --git a/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterUpdateQueue.cs b/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterUpdateQueue.cs index 21b26ce..42c96fe 100644 --- a/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterUpdateQueue.cs +++ b/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterUpdateQueue.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System; using RGB.NET.Core; using RGB.NET.Devices.CoolerMaster.Native; @@ -28,7 +28,7 @@ namespace RGB.NET.Devices.CoolerMaster : base(updateTrigger) { this._deviceIndex = deviceIndex; - + _deviceMatrix = new _CoolerMasterColorMatrix(); _deviceMatrix.KeyColor = new _CoolerMasterKeyColor[_CoolerMasterColorMatrix.ROWS, _CoolerMasterColorMatrix.COLUMNS]; } @@ -38,12 +38,12 @@ namespace RGB.NET.Devices.CoolerMaster #region Methods /// - protected override void Update(Dictionary dataSet) + protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - foreach (KeyValuePair data in dataSet) + foreach ((object key, Color color) in dataSet) { - (int row, int column) = ((int, int))data.Key; - _deviceMatrix.KeyColor[row, column] = new _CoolerMasterKeyColor(data.Value.GetR(), data.Value.GetG(), data.Value.GetB()); + (int row, int column) = ((int, int))key; + _deviceMatrix.KeyColor[row, column] = new _CoolerMasterKeyColor(color.GetR(), color.GetG(), color.GetB()); } _CoolerMasterSDK.SetAllLedColor(_deviceMatrix, _deviceIndex); diff --git a/RGB.NET.Devices.Corsair/Generic/CorsairDeviceUpdateQueue.cs b/RGB.NET.Devices.Corsair/Generic/CorsairDeviceUpdateQueue.cs index ae1859a..340fdee 100644 --- a/RGB.NET.Devices.Corsair/Generic/CorsairDeviceUpdateQueue.cs +++ b/RGB.NET.Devices.Corsair/Generic/CorsairDeviceUpdateQueue.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Runtime.InteropServices; using RGB.NET.Core; using RGB.NET.Devices.Corsair.Native; @@ -36,26 +35,26 @@ namespace RGB.NET.Devices.Corsair #region Methods /// - protected override void Update(Dictionary dataSet) + protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { int structSize = Marshal.SizeOf(typeof(_CorsairLedColor)); - IntPtr ptr = Marshal.AllocHGlobal(structSize * dataSet.Count); + IntPtr ptr = Marshal.AllocHGlobal(structSize * dataSet.Length); IntPtr addPtr = new(ptr.ToInt64()); - foreach (KeyValuePair data in dataSet) + foreach ((object key, Color color) in dataSet) { - _CorsairLedColor color = new() - { - ledId = (int)data.Key, - r = data.Value.GetR(), - g = data.Value.GetG(), - b = data.Value.GetB() + _CorsairLedColor corsairColor = new() + { + ledId = (int)key, + r = color.GetR(), + g = color.GetG(), + b = color.GetB() }; - Marshal.StructureToPtr(color, addPtr, false); + Marshal.StructureToPtr(corsairColor, addPtr, false); addPtr = new IntPtr(addPtr.ToInt64() + structSize); } - _CUESDK.CorsairSetLedsColorsBufferByDeviceIndex(_deviceIndex, dataSet.Count, ptr); + _CUESDK.CorsairSetLedsColorsBufferByDeviceIndex(_deviceIndex, dataSet.Length, ptr); _CUESDK.CorsairSetLedsColorsFlushBuffer(); Marshal.FreeHGlobal(ptr); } diff --git a/RGB.NET.Devices.DMX/E131/E131UpdateQueue.cs b/RGB.NET.Devices.DMX/E131/E131UpdateQueue.cs index dcf301e..e7a3f96 100644 --- a/RGB.NET.Devices.DMX/E131/E131UpdateQueue.cs +++ b/RGB.NET.Devices.DMX/E131/E131UpdateQueue.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Net.Sockets; using RGB.NET.Core; @@ -52,15 +51,15 @@ namespace RGB.NET.Devices.DMX.E131 #region Methods /// - protected override void Update(Dictionary dataSet) + protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { DataPacket.SetSequenceNumber(GetNextSequenceNumber()); - foreach (KeyValuePair data in dataSet) + foreach ((object key, Color color) in dataSet) { - LedChannelMapping mapping = (LedChannelMapping)data.Key; + LedChannelMapping mapping = (LedChannelMapping)key; foreach ((int channel, Func getValue) in mapping) - DataPacket.SetChannel(channel, getValue(data.Value)); + DataPacket.SetChannel(channel, getValue(color)); } _socket.Send(DataPacket, DataPacket.Length); diff --git a/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceUpdateQueue.cs b/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceUpdateQueue.cs index 8ea4c6a..a1ef25e 100644 --- a/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceUpdateQueue.cs +++ b/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceUpdateQueue.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; using RGB.NET.Core; using RGB.NET.Devices.Logitech.Native; @@ -27,9 +25,9 @@ namespace RGB.NET.Devices.Logitech #region Methods /// - protected override void Update(Dictionary dataSet) + protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - Color color = dataSet.Values.First(); + Color color = dataSet[0].color; _LogitechGSDK.LogiLedSetTargetDevice(LogitechDeviceCaps.DeviceRGB); _LogitechGSDK.LogiLedSetLighting((int)Math.Round(color.R * 100), diff --git a/RGB.NET.Devices.Logitech/PerKey/LogitechPerKeyUpdateQueue.cs b/RGB.NET.Devices.Logitech/PerKey/LogitechPerKeyUpdateQueue.cs index a166a3a..6077ed6 100644 --- a/RGB.NET.Devices.Logitech/PerKey/LogitechPerKeyUpdateQueue.cs +++ b/RGB.NET.Devices.Logitech/PerKey/LogitechPerKeyUpdateQueue.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using RGB.NET.Core; using RGB.NET.Devices.Logitech.Native; @@ -33,27 +32,27 @@ namespace RGB.NET.Devices.Logitech #region Methods /// - protected override void Update(Dictionary dataSet) + protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { _LogitechGSDK.LogiLedSetTargetDevice(LogitechDeviceCaps.PerKeyRGB); Array.Clear(_bitmap, 0, _bitmap.Length); bool usesBitmap = false; - foreach (KeyValuePair data in dataSet) + foreach ((object key, Color color) in dataSet) { - (LedId id, LogitechLedId customData) = ((LedId, LogitechLedId))data.Key; + (LedId id, LogitechLedId customData) = ((LedId, LogitechLedId))key; // DarthAffe 26.03.2017: This is only needed since update by name doesn't work as expected for all keys ... if (BitmapMapping.BitmapOffset.TryGetValue(id, out int bitmapOffset)) { - BitmapMapping.SetColor(_bitmap, bitmapOffset, data.Value); + BitmapMapping.SetColor(_bitmap, bitmapOffset, color); usesBitmap = true; } else _LogitechGSDK.LogiLedSetLightingForKeyWithKeyName((int)customData, - (int)Math.Round(data.Value.R * 100), - (int)Math.Round(data.Value.G * 100), - (int)Math.Round(data.Value.B * 100)); + (int)MathF.Round(color.R * 100), + (int)MathF.Round(color.G * 100), + (int)MathF.Round(color.B * 100)); } if (usesBitmap) diff --git a/RGB.NET.Devices.Logitech/Zone/LogitechZoneUpdateQueue.cs b/RGB.NET.Devices.Logitech/Zone/LogitechZoneUpdateQueue.cs index c3fb9ef..7c34363 100644 --- a/RGB.NET.Devices.Logitech/Zone/LogitechZoneUpdateQueue.cs +++ b/RGB.NET.Devices.Logitech/Zone/LogitechZoneUpdateQueue.cs @@ -13,12 +13,12 @@ namespace RGB.NET.Devices.Logitech #region Constants private static readonly Dictionary DEVICE_TYPE_MAPPING = new() - { - {RGBDeviceType.Keyboard, LogitechDeviceType.Keyboard}, - {RGBDeviceType.Mouse, LogitechDeviceType.Mouse}, - {RGBDeviceType.Headset, LogitechDeviceType.Headset}, - {RGBDeviceType.Mousepad, LogitechDeviceType.Mousemat}, - {RGBDeviceType.Speaker, LogitechDeviceType.Speaker} + { + { RGBDeviceType.Keyboard, LogitechDeviceType.Keyboard }, + { RGBDeviceType.Mouse, LogitechDeviceType.Mouse }, + { RGBDeviceType.Headset, LogitechDeviceType.Headset }, + { RGBDeviceType.Mousepad, LogitechDeviceType.Mousemat }, + { RGBDeviceType.Speaker, LogitechDeviceType.Speaker } }; #endregion @@ -48,17 +48,17 @@ namespace RGB.NET.Devices.Logitech #region Methods /// - protected override void Update(Dictionary dataSet) + protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { _LogitechGSDK.LogiLedSetTargetDevice(LogitechDeviceCaps.All); - foreach (KeyValuePair data in dataSet) + foreach ((object key, Color color) in dataSet) { - int zone = (int)data.Key; + int zone = (int)key; _LogitechGSDK.LogiLedSetLightingForTargetZone(_deviceType, zone, - (int)Math.Round(data.Value.R * 100), - (int)Math.Round(data.Value.G * 100), - (int)Math.Round(data.Value.B * 100)); + (int)MathF.Round(color.R * 100), + (int)MathF.Round(color.G * 100), + (int)MathF.Round(color.B * 100)); } } diff --git a/RGB.NET.Devices.Msi/Generic/MsiDeviceUpdateQueue.cs b/RGB.NET.Devices.Msi/Generic/MsiDeviceUpdateQueue.cs index b2dffc0..6f6bf73 100644 --- a/RGB.NET.Devices.Msi/Generic/MsiDeviceUpdateQueue.cs +++ b/RGB.NET.Devices.Msi/Generic/MsiDeviceUpdateQueue.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System; using RGB.NET.Core; using RGB.NET.Devices.Msi.Native; @@ -34,10 +34,10 @@ namespace RGB.NET.Devices.Msi #region Methods /// - protected override void Update(Dictionary dataSet) + protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - foreach (KeyValuePair data in dataSet) - _MsiSDK.SetLedColor(_deviceType, (int)data.Key, data.Value.GetR(), data.Value.GetG(), data.Value.GetB()); + foreach ((object key, Color color) in dataSet) + _MsiSDK.SetLedColor(_deviceType, (int)key, color.GetR(), color.GetG(), color.GetB()); } #endregion diff --git a/RGB.NET.Devices.Novation/Generic/LimitedColorUpdateQueue.cs b/RGB.NET.Devices.Novation/Generic/LimitedColorUpdateQueue.cs index 588e359..959e360 100644 --- a/RGB.NET.Devices.Novation/Generic/LimitedColorUpdateQueue.cs +++ b/RGB.NET.Devices.Novation/Generic/LimitedColorUpdateQueue.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using RGB.NET.Core; using Sanford.Multimedia.Midi; @@ -26,10 +25,10 @@ namespace RGB.NET.Devices.Novation #region Methods /// - protected override ShortMessage CreateMessage(KeyValuePair data) + protected override ShortMessage CreateMessage(object key, in Color color) { - (byte mode, byte id) = ((byte, byte))data.Key; - return new ShortMessage(mode, id, Convert.ToByte(ConvertColor(data.Value))); + (byte mode, byte id) = ((byte, byte))key; + return new ShortMessage(mode, id, Convert.ToByte(ConvertColor(color))); } /// @@ -38,9 +37,9 @@ namespace RGB.NET.Devices.Novation /// /// The to convert. /// The novation-representation of the . - protected virtual int ConvertColor(Color color) + protected virtual int ConvertColor(in Color color) { - (double hue, double saturation, double value) = color.GetHSV(); + (double hue, double _, double value) = color.GetHSV(); if ((hue >= 330) || (hue < 30)) return (int)Math.Ceiling(value * 3); // red with brightness 1, 2 or 3 diff --git a/RGB.NET.Devices.Novation/Generic/MidiUpdateQueue.cs b/RGB.NET.Devices.Novation/Generic/MidiUpdateQueue.cs index 5ce5547..f29241b 100644 --- a/RGB.NET.Devices.Novation/Generic/MidiUpdateQueue.cs +++ b/RGB.NET.Devices.Novation/Generic/MidiUpdateQueue.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using RGB.NET.Core; using Sanford.Multimedia.Midi; @@ -37,10 +36,10 @@ namespace RGB.NET.Devices.Novation #region Methods /// - protected override void Update(Dictionary dataSet) + protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - foreach (KeyValuePair data in dataSet) - SendMessage(CreateMessage(data)); + foreach ((object key, Color color) in dataSet) + SendMessage(CreateMessage(key, color)); } /// @@ -59,7 +58,7 @@ namespace RGB.NET.Devices.Novation /// /// The data set to create the message from. /// The message created out of the data set. - protected abstract ShortMessage? CreateMessage(KeyValuePair data); + protected abstract ShortMessage? CreateMessage(object key, in Color color); /// public override void Dispose() diff --git a/RGB.NET.Devices.Novation/Generic/RGBColorUpdateQueue.cs b/RGB.NET.Devices.Novation/Generic/RGBColorUpdateQueue.cs index 2998059..024fe58 100644 --- a/RGB.NET.Devices.Novation/Generic/RGBColorUpdateQueue.cs +++ b/RGB.NET.Devices.Novation/Generic/RGBColorUpdateQueue.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using RGB.NET.Core; using Sanford.Multimedia.Midi; @@ -152,12 +151,12 @@ namespace RGB.NET.Devices.Novation #region Methods /// - protected override ShortMessage? CreateMessage(KeyValuePair data) + protected override ShortMessage? CreateMessage(object key, in Color color) { - (byte mode, byte id) = ((byte, byte))data.Key; + (byte mode, byte id) = ((byte, byte))key; if (mode == 0x00) return null; - return new ShortMessage(mode, id, Convert.ToByte(ConvertColor(data.Value))); + return new ShortMessage(mode, id, Convert.ToByte(ConvertColor(color))); } /// @@ -166,7 +165,7 @@ namespace RGB.NET.Devices.Novation /// /// The to convert. /// The novation-representation of the . - protected virtual int ConvertColor(Color color) + protected virtual int ConvertColor(in Color color) { int bestVelocity = 0; double bestMatchDistance = double.MaxValue; diff --git a/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkUpdateQueue.cs b/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkUpdateQueue.cs index 7455aa4..94a3823 100644 --- a/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkUpdateQueue.cs +++ b/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkUpdateQueue.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Runtime.InteropServices; using RGB.NET.Core; using RGB.NET.Devices.Razer.Native; @@ -27,15 +26,15 @@ namespace RGB.NET.Devices.Razer #region Methods /// - protected override IntPtr CreateEffectParams(Dictionary dataSet) + protected override IntPtr CreateEffectParams(in ReadOnlySpan<(object key, Color color)> dataSet) { _Color[] colors = new _Color[_Defines.CHROMALINK_MAX_LEDS]; - foreach (KeyValuePair data in dataSet) - colors[(int)data.Key] = new _Color(data.Value); + foreach ((object key, Color color) in dataSet) + colors[(int)key] = new _Color(color); _ChromaLinkCustomEffect effectParams = new() - { Color = colors }; + { Color = colors }; IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(effectParams)); Marshal.StructureToPtr(effectParams, ptr, false); diff --git a/RGB.NET.Devices.Razer/Generic/RazerUpdateQueue.cs b/RGB.NET.Devices.Razer/Generic/RazerUpdateQueue.cs index de99795..32a4287 100644 --- a/RGB.NET.Devices.Razer/Generic/RazerUpdateQueue.cs +++ b/RGB.NET.Devices.Razer/Generic/RazerUpdateQueue.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using RGB.NET.Core; using RGB.NET.Devices.Razer.Native; @@ -35,7 +34,7 @@ namespace RGB.NET.Devices.Razer #region Methods /// - protected override void Update(Dictionary dataSet) + protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { IntPtr effectParams = CreateEffectParams(dataSet); Guid effectId = Guid.NewGuid(); @@ -71,7 +70,7 @@ namespace RGB.NET.Devices.Razer /// /// The data to be updated. /// An pointing to the effect parameter struct. - protected abstract IntPtr CreateEffectParams(Dictionary dataSet); + protected abstract IntPtr CreateEffectParams(in ReadOnlySpan<(object key, Color color)> dataSet); #endregion } diff --git a/RGB.NET.Devices.Razer/Headset/RazerHeadsetUpdateQueue.cs b/RGB.NET.Devices.Razer/Headset/RazerHeadsetUpdateQueue.cs index 7e5d9b7..2442490 100644 --- a/RGB.NET.Devices.Razer/Headset/RazerHeadsetUpdateQueue.cs +++ b/RGB.NET.Devices.Razer/Headset/RazerHeadsetUpdateQueue.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Runtime.InteropServices; using RGB.NET.Core; using RGB.NET.Devices.Razer.Native; @@ -27,16 +26,16 @@ namespace RGB.NET.Devices.Razer #region Methods /// - protected override IntPtr CreateEffectParams(Dictionary dataSet) + protected override IntPtr CreateEffectParams(in ReadOnlySpan<(object key, Color color)> dataSet) { _Color[] colors = new _Color[_Defines.HEADSET_MAX_LEDS]; - foreach (KeyValuePair data in dataSet) - colors[(int)data.Key] = new _Color(data.Value); + foreach ((object key, Color color) in dataSet) + colors[(int)key] = new _Color(color); _HeadsetCustomEffect effectParams = new() - { Color = colors }; - + { Color = colors }; + IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(effectParams)); Marshal.StructureToPtr(effectParams, ptr, false); diff --git a/RGB.NET.Devices.Razer/Keyboard/RazerKeyboardUpdateQueue.cs b/RGB.NET.Devices.Razer/Keyboard/RazerKeyboardUpdateQueue.cs index e87a987..bc08035 100644 --- a/RGB.NET.Devices.Razer/Keyboard/RazerKeyboardUpdateQueue.cs +++ b/RGB.NET.Devices.Razer/Keyboard/RazerKeyboardUpdateQueue.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Runtime.InteropServices; using RGB.NET.Core; using RGB.NET.Devices.Razer.Native; @@ -27,15 +26,14 @@ namespace RGB.NET.Devices.Razer #region Methods /// - protected override IntPtr CreateEffectParams(Dictionary dataSet) + protected override IntPtr CreateEffectParams(in ReadOnlySpan<(object key, Color color)> dataSet) { _Color[] colors = new _Color[_Defines.KEYBOARD_MAX_LEDS]; - foreach (KeyValuePair data in dataSet) - colors[(int)data.Key] = new _Color(data.Value); + foreach ((object key, Color color) in dataSet) + colors[(int)key] = new _Color(color); - _KeyboardCustomEffect effectParams = new() - { Color = colors }; + _KeyboardCustomEffect effectParams = new() { Color = colors }; IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(effectParams)); Marshal.StructureToPtr(effectParams, ptr, false); diff --git a/RGB.NET.Devices.Razer/Keypad/RazerKeypadUpdateQueue.cs b/RGB.NET.Devices.Razer/Keypad/RazerKeypadUpdateQueue.cs index f0e884d..74edb8e 100644 --- a/RGB.NET.Devices.Razer/Keypad/RazerKeypadUpdateQueue.cs +++ b/RGB.NET.Devices.Razer/Keypad/RazerKeypadUpdateQueue.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Runtime.InteropServices; using RGB.NET.Core; using RGB.NET.Devices.Razer.Native; @@ -27,15 +26,14 @@ namespace RGB.NET.Devices.Razer #region Methods /// - protected override IntPtr CreateEffectParams(Dictionary dataSet) + protected override IntPtr CreateEffectParams(in ReadOnlySpan<(object key, Color color)> dataSet) { _Color[] colors = new _Color[_Defines.KEYPAD_MAX_LEDS]; - foreach (KeyValuePair data in dataSet) - colors[(int)data.Key] = new _Color(data.Value); + foreach ((object key, Color color) in dataSet) + colors[(int)key] = new _Color(color); - _KeypadCustomEffect effectParams = new() - { Color = colors }; + _KeypadCustomEffect effectParams = new() { Color = colors }; IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(effectParams)); Marshal.StructureToPtr(effectParams, ptr, false); diff --git a/RGB.NET.Devices.Razer/Mouse/RazerMouseUpdateQueue.cs b/RGB.NET.Devices.Razer/Mouse/RazerMouseUpdateQueue.cs index 95547d8..6e10732 100644 --- a/RGB.NET.Devices.Razer/Mouse/RazerMouseUpdateQueue.cs +++ b/RGB.NET.Devices.Razer/Mouse/RazerMouseUpdateQueue.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Runtime.InteropServices; using RGB.NET.Core; using RGB.NET.Devices.Razer.Native; @@ -27,15 +26,14 @@ namespace RGB.NET.Devices.Razer #region Methods /// - protected override IntPtr CreateEffectParams(Dictionary dataSet) + protected override IntPtr CreateEffectParams(in ReadOnlySpan<(object key, Color color)> dataSet) { _Color[] colors = new _Color[_Defines.MOUSE_MAX_LEDS]; - foreach (KeyValuePair data in dataSet) - colors[(int)data.Key] = new _Color(data.Value); + foreach ((object key, Color color) in dataSet) + colors[(int)key] = new _Color(color); - _MouseCustomEffect effectParams = new() - { Color = colors }; + _MouseCustomEffect effectParams = new() { Color = colors }; IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(effectParams)); Marshal.StructureToPtr(effectParams, ptr, false); diff --git a/RGB.NET.Devices.Razer/Mousepad/RazerMousepadUpdateQueue.cs b/RGB.NET.Devices.Razer/Mousepad/RazerMousepadUpdateQueue.cs index 419099b..d9388f7 100644 --- a/RGB.NET.Devices.Razer/Mousepad/RazerMousepadUpdateQueue.cs +++ b/RGB.NET.Devices.Razer/Mousepad/RazerMousepadUpdateQueue.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Runtime.InteropServices; using RGB.NET.Core; using RGB.NET.Devices.Razer.Native; @@ -27,15 +26,14 @@ namespace RGB.NET.Devices.Razer #region Methods /// - protected override IntPtr CreateEffectParams(Dictionary dataSet) + protected override IntPtr CreateEffectParams(in ReadOnlySpan<(object key, Color color)> dataSet) { _Color[] colors = new _Color[_Defines.MOUSEPAD_MAX_LEDS]; - foreach (KeyValuePair data in dataSet) - colors[(int)data.Key] = new _Color(data.Value); + foreach ((object key, Color color) in dataSet) + colors[(int)key] = new _Color(color); - _MousepadCustomEffect effectParams = new() - { Color = colors }; + _MousepadCustomEffect effectParams = new() { Color = colors }; IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(effectParams)); Marshal.StructureToPtr(effectParams, ptr, false); diff --git a/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateQueue.cs b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateQueue.cs index 25de272..b3b966d 100644 --- a/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateQueue.cs +++ b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateQueue.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System; using System.Linq; using RGB.NET.Core; using RGB.NET.Devices.SteelSeries.API; @@ -44,8 +44,8 @@ namespace RGB.NET.Devices.SteelSeries } /// - protected override void Update(Dictionary dataSet) - => SteelSeriesSDK.UpdateLeds(_deviceType, dataSet.Select(x => (((SteelSeriesLedId)x.Key).GetAPIName(), x.Value.ToIntArray())).Where(x => x.Item1 != null).ToList()!); + protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) + => SteelSeriesSDK.UpdateLeds(_deviceType, dataSet.ToArray().Select(x => (((SteelSeriesLedId)x.key).GetAPIName(), x.color.ToIntArray())).Where(x => x.Item1 != null).ToList()!); #endregion } diff --git a/RGB.NET.Devices.WS281X/Arduino/ArduinoWS2812USBUpdateQueue.cs b/RGB.NET.Devices.WS281X/Arduino/ArduinoWS2812USBUpdateQueue.cs index ebe5a76..9263e64 100644 --- a/RGB.NET.Devices.WS281X/Arduino/ArduinoWS2812USBUpdateQueue.cs +++ b/RGB.NET.Devices.WS281X/Arduino/ArduinoWS2812USBUpdateQueue.cs @@ -50,9 +50,9 @@ namespace RGB.NET.Devices.WS281X.Arduino } /// - protected override IEnumerable GetCommands(Dictionary dataSet) + protected override IEnumerable GetCommands(IList<(object key, Color color)> dataSet) { - foreach (IGrouping channelData in dataSet.Select(x => (((int channel, int key))x.Key, x.Value)) + foreach (IGrouping channelData in dataSet.Select(x => (((int channel, int key))x.key, x.color)) .GroupBy(x => x.Item1.channel)) { int channel = channelData.Key; diff --git a/RGB.NET.Devices.WS281X/Bitwizard/BitwizardWS2812USBUpdateQueue.cs b/RGB.NET.Devices.WS281X/Bitwizard/BitwizardWS2812USBUpdateQueue.cs index 242b6d1..623f0fe 100644 --- a/RGB.NET.Devices.WS281X/Bitwizard/BitwizardWS2812USBUpdateQueue.cs +++ b/RGB.NET.Devices.WS281X/Bitwizard/BitwizardWS2812USBUpdateQueue.cs @@ -36,7 +36,7 @@ namespace RGB.NET.Devices.WS281X.Bitwizard } /// - protected override IEnumerable GetCommands(Dictionary dataSet) + protected override IEnumerable GetCommands(IList<(object key, Color color)> dataSet) { foreach ((object key, Color value) in dataSet) yield return $"pix {(int)key} {value.AsRGBHexString(false)}"; diff --git a/RGB.NET.Devices.WS281X/Generic/SerialPortUpdateQueue.cs b/RGB.NET.Devices.WS281X/Generic/SerialPortUpdateQueue.cs index b3f2b4e..7bee162 100644 --- a/RGB.NET.Devices.WS281X/Generic/SerialPortUpdateQueue.cs +++ b/RGB.NET.Devices.WS281X/Generic/SerialPortUpdateQueue.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using RGB.NET.Core; namespace RGB.NET.Devices.WS281X @@ -56,9 +57,9 @@ namespace RGB.NET.Devices.WS281X } /// - protected override void Update(Dictionary dataSet) + protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - foreach (TData command in GetCommands(dataSet)) + foreach (TData command in GetCommands(dataSet.ToArray())) { SerialConnection.ReadTo(Prompt); SendCommand(command); @@ -70,7 +71,7 @@ namespace RGB.NET.Devices.WS281X /// /// The set of data that needs to be updated. /// The commands to be sent. - protected abstract IEnumerable GetCommands(Dictionary dataSet); + protected abstract IEnumerable GetCommands(IList<(object key, Color color)> dataSet); /// /// Sends a command as a string followed by a line-break to the device. diff --git a/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBUpdateQueue.cs b/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBUpdateQueue.cs index 2c020c4..ef25700 100644 --- a/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBUpdateQueue.cs +++ b/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBUpdateQueue.cs @@ -77,10 +77,9 @@ namespace RGB.NET.Devices.WS281X.NodeMCU } /// - protected override void Update(Dictionary dataSet) + protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - foreach (IGrouping channelData in dataSet.Select(x => (((int channel, int key))x.Key, x.Value)) - .GroupBy(x => x.Item1.channel)) + foreach (IGrouping channelData in dataSet.ToArray().Select(x => (((int channel, int key))x.key, x.color)).GroupBy(x => x.Item1.channel)) { byte[] buffer = GetBuffer(channelData); _sendDataAction(buffer); @@ -98,7 +97,7 @@ namespace RGB.NET.Devices.WS281X.NodeMCU _udpClient?.Send(buffer, buffer.Length); } - private byte[] GetBuffer(IGrouping data) + private byte[] GetBuffer(IGrouping data) { int channel = data.Key; byte[] buffer = _dataBuffer[channel]; @@ -106,8 +105,8 @@ namespace RGB.NET.Devices.WS281X.NodeMCU buffer[0] = GetSequenceNumber(channel); buffer[1] = (byte)channel; int i = 2; - foreach ((byte _, byte r, byte g, byte b) in data.OrderBy(x => x.Item1.key) - .Select(x => x.Value.GetRGBBytes())) + foreach ((byte _, byte r, byte g, byte b) in data.OrderBy(x => x.identifier.key) + .Select(x => x.color.GetRGBBytes())) { buffer[i++] = r; buffer[i++] = g; diff --git a/RGB.NET.Devices.Wooting/Generic/WootingUpdateQueue.cs b/RGB.NET.Devices.Wooting/Generic/WootingUpdateQueue.cs index 8f89610..da4b3bf 100644 --- a/RGB.NET.Devices.Wooting/Generic/WootingUpdateQueue.cs +++ b/RGB.NET.Devices.Wooting/Generic/WootingUpdateQueue.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System; using RGB.NET.Core; using RGB.NET.Devices.Wooting.Native; @@ -26,17 +26,17 @@ namespace RGB.NET.Devices.Wooting.Generic #region Methods /// - protected override void Update(Dictionary dataSet) + protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - foreach (KeyValuePair data in dataSet) + foreach ((object key, Color color) in dataSet) { - (int row, int column) = ((int, int))data.Key; - _WootingSDK.ArraySetSingle((byte)row, (byte)column, data.Value.GetR(), data.Value.GetG(), data.Value.GetB()); + (int row, int column) = ((int, int))key; + _WootingSDK.ArraySetSingle((byte)row, (byte)column, color.GetR(), color.GetG(), color.GetB()); } _WootingSDK.ArrayUpdateKeyboard(); } - + #endregion } } From f6f3e9185c760fdd461585251b47e641a3cc51eb Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Wed, 3 Mar 2021 23:29:31 +0100 Subject: [PATCH 16/22] Moved color-correction logic deeper down to the device --- RGB.NET.Core/Devices/AbstractRGBDevice.cs | 28 ++++++++++++++++++- RGB.NET.Core/RGBSurface.cs | 8 +----- RGB.NET.Core/Update/Devices/UpdateQueue.cs | 10 ------- RGB.NET.Devices.Asus/Generic/AsusRGBDevice.cs | 4 +-- .../Generic/CoolerMasterRGBDevice.cs | 2 +- .../Generic/CorsairRGBDevice.cs | 2 +- RGB.NET.Devices.DMX/E131/E131Device.cs | 2 +- .../PerDevice/LogitechPerDeviceRGBDevice.cs | 2 +- .../PerKey/LogitechPerKeyRGBDevice.cs | 2 +- .../Zone/LogitechZoneRGBDevice.cs | 2 +- RGB.NET.Devices.Msi/Generic/MsiRGBDevice.cs | 2 +- .../Generic/NovationRGBDevice.cs | 2 +- .../Generic/RazerRGBDevice.cs | 2 +- .../Generic/SteelSeriesRGBDevice.cs | 2 +- .../Arduino/ArduinoWS2812USBDevice.cs | 2 +- .../Bitwizard/BitwizardWS2812USBDevice.cs | 2 +- .../NodeMCU/NodeMCUWS2812USBDevice.cs | 2 +- .../Keyboard/WootingKeyboardRGBDevice.cs | 2 +- 18 files changed, 44 insertions(+), 34 deletions(-) diff --git a/RGB.NET.Core/Devices/AbstractRGBDevice.cs b/RGB.NET.Core/Devices/AbstractRGBDevice.cs index 0b6fe09..7046139 100644 --- a/RGB.NET.Core/Devices/AbstractRGBDevice.cs +++ b/RGB.NET.Core/Devices/AbstractRGBDevice.cs @@ -84,7 +84,33 @@ namespace RGB.NET.Core UpdateLeds(ledsToUpdate); } - protected virtual IEnumerable GetLedsToUpdate(bool flushLeds) => ((RequiresFlush || flushLeds) ? LedMapping.Values : LedMapping.Values.Where(x => x.IsDirty)); + protected virtual IEnumerable GetLedsToUpdate(bool flushLeds) => ((RequiresFlush || flushLeds) ? LedMapping.Values : LedMapping.Values.Where(x => x.IsDirty)).Where(led => led.Color.A > 0); + protected virtual IEnumerable<(object key, Color color)> GetUpdateData(IEnumerable leds) + { + if (ColorCorrections.Count > 0) + { + foreach (Led led in leds) + { + Color color = led.Color; + object key = led.CustomData ?? led.Id; + + foreach (IColorCorrection colorCorrection in ColorCorrections) + colorCorrection.ApplyTo(ref color); + + yield return (key, color); + } + } + else + { + foreach (Led led in leds) + { + Color color = led.Color; + object key = led.CustomData ?? led.Id; + + yield return (key, color); + } + } + } /// public virtual void Dispose() diff --git a/RGB.NET.Core/RGBSurface.cs b/RGB.NET.Core/RGBSurface.cs index a6c346f..94169b5 100644 --- a/RGB.NET.Core/RGBSurface.cs +++ b/RGB.NET.Core/RGBSurface.cs @@ -226,13 +226,7 @@ namespace RGB.NET.Core } foreach ((RenderTarget renderTarget, Color c) in render) - { - Color color = c; - for (int i = 0; i < renderTarget.Led.Device.ColorCorrections.Count; i++) - renderTarget.Led.Device.ColorCorrections[i].ApplyTo(ref color); - - renderTarget.Led.Color = color; - } + renderTarget.Led.Color = c; } /// diff --git a/RGB.NET.Core/Update/Devices/UpdateQueue.cs b/RGB.NET.Core/Update/Devices/UpdateQueue.cs index 76e6180..4b48593 100644 --- a/RGB.NET.Core/Update/Devices/UpdateQueue.cs +++ b/RGB.NET.Core/Update/Devices/UpdateQueue.cs @@ -133,15 +133,5 @@ namespace RGB.NET.Core { } #endregion - - #region Methods - - /// - /// Calls for a data set created out of the provided list of . - /// - /// - public void SetData(IEnumerable leds) => SetData(leds.Select(x => (x.CustomData ?? x.Id, x.Color))); - - #endregion } } diff --git a/RGB.NET.Devices.Asus/Generic/AsusRGBDevice.cs b/RGB.NET.Devices.Asus/Generic/AsusRGBDevice.cs index f0fc1bc..3973048 100644 --- a/RGB.NET.Devices.Asus/Generic/AsusRGBDevice.cs +++ b/RGB.NET.Devices.Asus/Generic/AsusRGBDevice.cs @@ -49,7 +49,7 @@ namespace RGB.NET.Devices.Asus public void Initialize(IDeviceUpdateTrigger updateTrigger) { InitializeLayout(); - + UpdateQueue = new AsusUpdateQueue(updateTrigger); UpdateQueue.Initialize(DeviceInfo.Device); } @@ -60,7 +60,7 @@ namespace RGB.NET.Devices.Asus protected abstract void InitializeLayout(); /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(ledsToUpdate.Where(x => x.Color.A > 0)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); /// public override void Dispose() diff --git a/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterRGBDevice.cs b/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterRGBDevice.cs index b176bc7..ac17daa 100644 --- a/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterRGBDevice.cs +++ b/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterRGBDevice.cs @@ -62,7 +62,7 @@ namespace RGB.NET.Devices.CoolerMaster protected abstract void InitializeLayout(); /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(ledsToUpdate.Where(x => x.Color.A > 0)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); /// /// diff --git a/RGB.NET.Devices.Corsair/Generic/CorsairRGBDevice.cs b/RGB.NET.Devices.Corsair/Generic/CorsairRGBDevice.cs index d573ba2..ef2a854 100644 --- a/RGB.NET.Devices.Corsair/Generic/CorsairRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/Generic/CorsairRGBDevice.cs @@ -84,7 +84,7 @@ namespace RGB.NET.Devices.Corsair /// protected override void UpdateLeds(IEnumerable ledsToUpdate) - => DeviceUpdateQueue?.SetData(ledsToUpdate.Where(x => (x.Color.A > 0) && (x.CustomData is CorsairLedId ledId && (ledId != CorsairLedId.Invalid)))); + => DeviceUpdateQueue?.SetData(GetUpdateData(ledsToUpdate.Where(x => (x.Color.A > 0) && (x.CustomData is CorsairLedId ledId && (ledId != CorsairLedId.Invalid))))); /// public override void Dispose() diff --git a/RGB.NET.Devices.DMX/E131/E131Device.cs b/RGB.NET.Devices.DMX/E131/E131Device.cs index 3a8c4fe..9b18d01 100644 --- a/RGB.NET.Devices.DMX/E131/E131Device.cs +++ b/RGB.NET.Devices.DMX/E131/E131Device.cs @@ -50,7 +50,7 @@ namespace RGB.NET.Devices.DMX.E131 /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => _updateQueue?.SetData(ledsToUpdate.Where(x => x.Color.A > 0)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => _updateQueue?.SetData(GetUpdateData(ledsToUpdate)); /// public override void Dispose() diff --git a/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceRGBDevice.cs b/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceRGBDevice.cs index 416e18e..8855e6b 100644 --- a/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceRGBDevice.cs +++ b/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceRGBDevice.cs @@ -36,7 +36,7 @@ namespace RGB.NET.Devices.Logitech protected override object GetLedCustomData(LedId ledId) => (ledId, LogitechLedId.DEVICE); /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(ledsToUpdate.Where(x => x.Color.A > 0).Take(1)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate.Take(1))); #endregion } diff --git a/RGB.NET.Devices.Logitech/PerKey/LogitechPerKeyRGBDevice.cs b/RGB.NET.Devices.Logitech/PerKey/LogitechPerKeyRGBDevice.cs index 2b5a85d..1fbec2d 100644 --- a/RGB.NET.Devices.Logitech/PerKey/LogitechPerKeyRGBDevice.cs +++ b/RGB.NET.Devices.Logitech/PerKey/LogitechPerKeyRGBDevice.cs @@ -29,7 +29,7 @@ namespace RGB.NET.Devices.Logitech protected override object GetLedCustomData(LedId ledId) => (ledId, PerKeyIdMapping.DEFAULT.TryGetValue(ledId, out LogitechLedId logitechLedId) ? logitechLedId : LogitechLedId.Invalid); /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(ledsToUpdate.Where(x => x.Color.A > 0)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); #endregion } diff --git a/RGB.NET.Devices.Logitech/Zone/LogitechZoneRGBDevice.cs b/RGB.NET.Devices.Logitech/Zone/LogitechZoneRGBDevice.cs index 4b0da4f..5e7b8c9 100644 --- a/RGB.NET.Devices.Logitech/Zone/LogitechZoneRGBDevice.cs +++ b/RGB.NET.Devices.Logitech/Zone/LogitechZoneRGBDevice.cs @@ -59,7 +59,7 @@ namespace RGB.NET.Devices.Logitech protected override object? GetLedCustomData(LedId ledId) => (int)(ledId - _baseLedId); /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(ledsToUpdate.Where(x => x.Color.A > 0)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); #endregion } diff --git a/RGB.NET.Devices.Msi/Generic/MsiRGBDevice.cs b/RGB.NET.Devices.Msi/Generic/MsiRGBDevice.cs index 3da1d27..44b52eb 100644 --- a/RGB.NET.Devices.Msi/Generic/MsiRGBDevice.cs +++ b/RGB.NET.Devices.Msi/Generic/MsiRGBDevice.cs @@ -60,7 +60,7 @@ namespace RGB.NET.Devices.Msi /// protected override void UpdateLeds(IEnumerable ledsToUpdate) - => DeviceUpdateQueue?.SetData(ledsToUpdate.Where(x => (x.Color.A > 0) && (x.CustomData is int))); + => DeviceUpdateQueue?.SetData(GetUpdateData(ledsToUpdate.Where(x => (x.Color.A > 0) && (x.CustomData is int)))); /// public override void Dispose() diff --git a/RGB.NET.Devices.Novation/Generic/NovationRGBDevice.cs b/RGB.NET.Devices.Novation/Generic/NovationRGBDevice.cs index 2976355..d6669ce 100644 --- a/RGB.NET.Devices.Novation/Generic/NovationRGBDevice.cs +++ b/RGB.NET.Devices.Novation/Generic/NovationRGBDevice.cs @@ -65,7 +65,7 @@ namespace RGB.NET.Devices.Novation protected abstract void InitializeLayout(); /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(ledsToUpdate.Where(x => x.Color.A > 0)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); /// /// Resets the back to default. diff --git a/RGB.NET.Devices.Razer/Generic/RazerRGBDevice.cs b/RGB.NET.Devices.Razer/Generic/RazerRGBDevice.cs index afab079..6e7c61a 100644 --- a/RGB.NET.Devices.Razer/Generic/RazerRGBDevice.cs +++ b/RGB.NET.Devices.Razer/Generic/RazerRGBDevice.cs @@ -68,7 +68,7 @@ namespace RGB.NET.Devices.Razer protected abstract void InitializeLayout(); /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(ledsToUpdate.Where(x => x.Color.A > 0)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); /// /// Resets the device. diff --git a/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesRGBDevice.cs b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesRGBDevice.cs index 1f31857..9cc5f39 100644 --- a/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesRGBDevice.cs +++ b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesRGBDevice.cs @@ -62,7 +62,7 @@ namespace RGB.NET.Devices.SteelSeries protected override object GetLedCustomData(LedId ledId) => _ledMapping[ledId]; /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(ledsToUpdate.Where(x => x.Color.A > 0)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); /// public override void Dispose() diff --git a/RGB.NET.Devices.WS281X/Arduino/ArduinoWS2812USBDevice.cs b/RGB.NET.Devices.WS281X/Arduino/ArduinoWS2812USBDevice.cs index 1a9f186..ab658e5 100644 --- a/RGB.NET.Devices.WS281X/Arduino/ArduinoWS2812USBDevice.cs +++ b/RGB.NET.Devices.WS281X/Arduino/ArduinoWS2812USBDevice.cs @@ -63,7 +63,7 @@ namespace RGB.NET.Devices.WS281X.Arduino protected override IEnumerable GetLedsToUpdate(bool flushLeds) => (flushLeds || LedMapping.Values.Any(x => x.IsDirty)) ? LedMapping.Values : Enumerable.Empty(); /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(ledsToUpdate.Where(x => x.Color.A > 0)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate)); /// public override void Dispose() diff --git a/RGB.NET.Devices.WS281X/Bitwizard/BitwizardWS2812USBDevice.cs b/RGB.NET.Devices.WS281X/Bitwizard/BitwizardWS2812USBDevice.cs index 6e2d813..5bb6bcc 100644 --- a/RGB.NET.Devices.WS281X/Bitwizard/BitwizardWS2812USBDevice.cs +++ b/RGB.NET.Devices.WS281X/Bitwizard/BitwizardWS2812USBDevice.cs @@ -57,7 +57,7 @@ namespace RGB.NET.Devices.WS281X.Bitwizard protected override object GetLedCustomData(LedId ledId) => _ledOffset + ((int)ledId - (int)LedId.LedStripe1); /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(ledsToUpdate.Where(x => x.Color.A > 0)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate)); /// public override void Dispose() diff --git a/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBDevice.cs b/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBDevice.cs index b471e17..635d61b 100644 --- a/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBDevice.cs +++ b/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBDevice.cs @@ -63,7 +63,7 @@ namespace RGB.NET.Devices.WS281X.NodeMCU protected override IEnumerable GetLedsToUpdate(bool flushLeds) => (flushLeds || LedMapping.Values.Any(x => x.IsDirty)) ? LedMapping.Values : Enumerable.Empty(); /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(ledsToUpdate.Where(x => x.Color.A > 0)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate)); /// public override void Dispose() diff --git a/RGB.NET.Devices.Wooting/Keyboard/WootingKeyboardRGBDevice.cs b/RGB.NET.Devices.Wooting/Keyboard/WootingKeyboardRGBDevice.cs index 7994145..bd8edea 100644 --- a/RGB.NET.Devices.Wooting/Keyboard/WootingKeyboardRGBDevice.cs +++ b/RGB.NET.Devices.Wooting/Keyboard/WootingKeyboardRGBDevice.cs @@ -47,7 +47,7 @@ namespace RGB.NET.Devices.Wooting.Keyboard protected override object GetLedCustomData(LedId ledId) => WootingKeyboardLedMappings.Mapping[DeviceInfo.DeviceIndex][WootingPhysicalKeyboardLayout.US][ledId]; /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(ledsToUpdate.Where(x => x.Color.A > 0)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); #endregion } From 2a9a43683c23daeb9ffd05abe8ecbd056719b74a Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Thu, 4 Mar 2021 23:33:00 +0100 Subject: [PATCH 17/22] Streamlined device loading/handling in device providers --- RGB.NET.Core/Devices/AbstractRGBDevice.cs | 31 ++- .../Devices/AbstractRGBDeviceProvider.cs | 119 ++++++++++ RGB.NET.Core/Devices/IRGBDevice.cs | 2 +- RGB.NET.Core/Devices/IRGBDeviceProvider.cs | 9 + RGB.NET.Core/Update/AbstractUpdateTrigger.cs | 3 + .../Update/Devices/DeviceUpdateTrigger.cs | 2 +- RGB.NET.Core/Update/Devices/IUpdateQueue.cs | 24 ++ RGB.NET.Core/Update/Devices/UpdateQueue.cs | 4 +- RGB.NET.Core/Update/IUpdateTrigger.cs | 2 + RGB.NET.Core/Update/ManualUpdateTrigger.cs | 2 +- RGB.NET.Core/Update/TimerUpdateTrigger.cs | 2 +- RGB.NET.Devices.Asus/AsusDeviceProvider.cs | 129 ++-------- .../Dram/AsusDramRGBDevice.cs | 11 +- RGB.NET.Devices.Asus/Generic/AsusRGBDevice.cs | 60 +---- .../Generic/AsusUnspecifiedRGBDevice.cs | 10 +- .../Generic/AsusUpdateQueue.cs | 19 +- .../Generic/IAsusRGBDevice.cs | 6 +- .../GraphicsCard/AsusGraphicsCardRGBDevice.cs | 11 +- .../Headset/AsusHeadsetRGBDevice.cs | 11 +- .../Keyboard/AsusKeyboardRGBDevice.cs | 11 +- .../Mainboard/AsusMainboardRGBDevice.cs | 13 +- .../Mouse/AsusMouseRGBDevice.cs | 11 +- .../CoolerMasterDeviceProvider.cs | 127 +++------- .../Generic/CoolerMasterRGBDevice.cs | 48 +--- .../Generic/ICoolerMasterRGBDevice.cs | 6 +- .../Keyboard/CoolerMasterKeyboardRGBDevice.cs | 13 +- .../Mouse/CoolerMasterMouseRGBDevice.cs | 9 +- .../CorsairDeviceProvider.cs | 224 ++++++------------ .../Custom/CorsairCustomRGBDevice.cs | 13 +- .../Generic/CorsairRGBDevice.cs | 84 +------ .../Generic/ICorsairRGBDevice.cs | 6 +- .../Headset/CorsairHeadsetRGBDevice.cs | 11 +- .../CorsairHeadsetStandRGBDevice.cs | 11 +- .../Keyboard/CorsairKeyboardRGBDevice.cs | 11 +- .../Memory/CorsairMemoryRGBDevice.cs | 11 +- .../Mouse/CorsairMouseRGBDevice.cs | 11 +- .../Mousepad/CorsairMousepadRGBDevice.cs | 11 +- RGB.NET.Devices.DMX/DMXDeviceProvider.cs | 78 ++---- RGB.NET.Devices.DMX/E131/E131Device.cs | 35 +-- RGB.NET.Devices.Debug/DebugDeviceProvider.cs | 52 +--- .../DebugDeviceUpdateQueue.cs | 22 ++ RGB.NET.Devices.Debug/DebugRGBDevice.cs | 6 +- .../Generic/ILogitechRGBDevice.cs | 6 +- .../Generic/LogitechRGBDevice.cs | 45 +--- .../LogitechDeviceProvider.cs | 151 +++--------- .../PerDevice/LogitechPerDeviceRGBDevice.cs | 15 +- .../PerKey/LogitechPerKeyRGBDevice.cs | 7 +- .../Zone/LogitechZoneRGBDevice.cs | 14 +- RGB.NET.Devices.Msi/Generic/IMsiRGBDevice.cs | 6 +- RGB.NET.Devices.Msi/Generic/MsiRGBDevice.cs | 60 +---- .../GraphicsCard/MsiGraphicsCardRGBDevice.cs | 11 +- .../Mainboard/MsiMainboardRGBDevice.cs | 11 +- .../Mouse/MsiMouseRGBDevice.cs | 11 +- RGB.NET.Devices.Msi/MsiDeviceProvider.cs | 140 ++++------- .../Generic/INovationRGBDevice.cs | 6 +- .../Generic/NovationRGBDevice.cs | 52 +--- .../Launchpad/NovationLaunchpadRGBDevice.cs | 11 +- .../NovationDeviceProvider.cs | 84 ++----- .../ChromaLink/RazerChromaLinkRGBDevice.cs | 14 +- .../Generic/IRazerRGBDevice.cs | 7 +- .../Generic/RazerRGBDevice.cs | 51 +--- .../Headset/RazerHeadsetRGBDevice.cs | 14 +- .../Keyboard/RazerKeyboardRGBDevice.cs | 14 +- .../Keypad/RazerKeypadRGBDevice.cs | 14 +- .../Mouse/RazerMouseRGBDevice.cs | 14 +- .../Mousepad/RazerMousepadRGBDevice.cs | 15 +- RGB.NET.Devices.Razer/RazerDeviceProvider.cs | 196 +++++---------- .../Generic/ISteelSeriesRGBDevice.cs | 7 +- .../Generic/SteelSeriesRGBDevice.cs | 35 +-- .../SteelSeriesDeviceProvider.cs | 96 +++----- .../Arduino/ArduinoWS2812USBDevice.cs | 28 +-- .../Arduino/ArduinoWS281XDeviceDefinition.cs | 5 +- .../Bitwizard/BitwizardWS2812USBDevice.cs | 29 +-- .../BitwizardWS281XDeviceDefinition.cs | 31 ++- .../NodeMCU/NodeMCUWS2812USBDevice.cs | 26 +- .../NodeMCU/NodeMCUWS281XDeviceDefinition.cs | 4 +- .../WS281XDeviceProvider.cs | 67 +----- .../Generic/IWootingRGBDevice.cs | 6 +- .../Generic/WootingRGBDevice.cs | 51 +--- .../Keyboard/WootingKeyboardRGBDevice.cs | 14 +- .../WootingDeviceProvider.cs | 82 ++----- 81 files changed, 867 insertions(+), 1864 deletions(-) create mode 100644 RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs create mode 100644 RGB.NET.Core/Update/Devices/IUpdateQueue.cs create mode 100644 RGB.NET.Devices.Debug/DebugDeviceUpdateQueue.cs diff --git a/RGB.NET.Core/Devices/AbstractRGBDevice.cs b/RGB.NET.Core/Devices/AbstractRGBDevice.cs index 7046139..cf47142 100644 --- a/RGB.NET.Core/Devices/AbstractRGBDevice.cs +++ b/RGB.NET.Core/Devices/AbstractRGBDevice.cs @@ -34,7 +34,7 @@ namespace RGB.NET.Core } /// - public abstract TDeviceInfo DeviceInfo { get; } + public TDeviceInfo DeviceInfo { get; } /// IRGBDeviceInfo IRGBDevice.DeviceInfo => DeviceInfo; @@ -52,6 +52,8 @@ namespace RGB.NET.Core /// protected Dictionary LedMapping { get; } = new(); + protected IUpdateQueue UpdateQueue { get; } + #region Indexer /// @@ -68,6 +70,16 @@ namespace RGB.NET.Core #endregion + #region Constructors + + protected AbstractRGBDevice(TDeviceInfo deviceOnfo, IUpdateQueue updateQueue) + { + this.DeviceInfo = deviceOnfo; + this.UpdateQueue = updateQueue; + } + + #endregion + #region Methods /// @@ -112,14 +124,16 @@ namespace RGB.NET.Core } } + /// + /// Sends all the updated to the device. + /// + protected virtual void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate)); + /// public virtual void Dispose() { - try - { - LedMapping.Clear(); - } - catch { /* this really shouldn't happen */ } + try { UpdateQueue.Dispose(); } catch { /* :( */ } + try { LedMapping.Clear(); } catch { /* this really shouldn't happen */ } } /// @@ -128,11 +142,6 @@ namespace RGB.NET.Core protected virtual void DeviceUpdate() { } - /// - /// Sends all the updated to the device. - /// - protected abstract void UpdateLeds(IEnumerable ledsToUpdate); - /// /// Initializes the with the specified id. /// diff --git a/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs b/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs new file mode 100644 index 0000000..7f0c4ef --- /dev/null +++ b/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +namespace RGB.NET.Core +{ + public abstract class AbstractRGBDeviceProvider : IRGBDeviceProvider + { + #region Properties & Fields + + private readonly double _defaultUpdateRateHardLimit; + + public bool IsInitialized { get; protected set; } + public bool ThrowsExceptions { get; protected set; } + + public virtual IEnumerable Devices { get; protected set; } = Enumerable.Empty(); + + protected Dictionary UpdateTriggers { get; } = new(); + + #endregion + + #region Events + + public event EventHandler? Exception; + + #endregion + + #region Constructors + + protected AbstractRGBDeviceProvider(double defaultUpdateRateHardLimit = 0) + { + this._defaultUpdateRateHardLimit = defaultUpdateRateHardLimit; + } + + #endregion + + #region Methods + + public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false) + { + ThrowsExceptions = throwExceptions; + + try + { + Reset(); + + InitializeSDK(); + + Devices = new ReadOnlyCollection(GetLoadedDevices(loadFilter).ToList()); + + foreach (IDeviceUpdateTrigger updateTrigger in UpdateTriggers.Values) + updateTrigger.Start(); + + IsInitialized = true; + } + catch (Exception ex) + { + Reset(); + Throw(ex); + return false; + } + + return true; + } + + protected virtual IEnumerable GetLoadedDevices(RGBDeviceType loadFilter) + { + foreach (IRGBDevice device in LoadDevices()) + { + if (loadFilter.HasFlag(device.DeviceInfo.DeviceType)) + yield return device; + else + device.Dispose(); + } + } + + protected abstract void InitializeSDK(); + + protected abstract IEnumerable LoadDevices(); + + protected virtual IDeviceUpdateTrigger GetUpdateTrigger(int id = -1, double? updateRateHardLimit = null) + { + if (!UpdateTriggers.TryGetValue(id, out IDeviceUpdateTrigger? updaeTrigger)) + UpdateTriggers[id] = (updaeTrigger = new DeviceUpdateTrigger(updateRateHardLimit ?? _defaultUpdateRateHardLimit)); + + return updaeTrigger; + } + + protected virtual void Reset() + { + foreach (IDeviceUpdateTrigger updateTrigger in UpdateTriggers.Values) + updateTrigger.Dispose(); + + Devices = Enumerable.Empty(); + IsInitialized = false; + } + + protected virtual void Throw(Exception ex) + { + try { OnException(ex); } catch { /* we don't want to throw due to bad event handlers */ } + + if (ThrowsExceptions) + throw ex; + } + + protected virtual void OnException(Exception ex) => Exception?.Invoke(this, ex); + + public virtual void Dispose() + { + IEnumerable devices = Devices; + Reset(); + foreach (IRGBDevice device in devices) + device.Dispose(); + } + + #endregion + } +} diff --git a/RGB.NET.Core/Devices/IRGBDevice.cs b/RGB.NET.Core/Devices/IRGBDevice.cs index 0ad1dc7..983d54d 100644 --- a/RGB.NET.Core/Devices/IRGBDevice.cs +++ b/RGB.NET.Core/Devices/IRGBDevice.cs @@ -19,7 +19,7 @@ namespace RGB.NET.Core /// Gets generic information about the . /// IRGBDeviceInfo DeviceInfo { get; } - + IList ColorCorrections { get; } #endregion diff --git a/RGB.NET.Core/Devices/IRGBDeviceProvider.cs b/RGB.NET.Core/Devices/IRGBDeviceProvider.cs index 6060feb..afa4ab0 100644 --- a/RGB.NET.Core/Devices/IRGBDeviceProvider.cs +++ b/RGB.NET.Core/Devices/IRGBDeviceProvider.cs @@ -22,6 +22,15 @@ namespace RGB.NET.Core #endregion + #region Events + + /// + /// Occurs when an exception is thrown in the device provider + /// + event EventHandler? Exception; + + #endregion + #region Methods bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false); diff --git a/RGB.NET.Core/Update/AbstractUpdateTrigger.cs b/RGB.NET.Core/Update/AbstractUpdateTrigger.cs index 722c30e..3d754fd 100644 --- a/RGB.NET.Core/Update/AbstractUpdateTrigger.cs +++ b/RGB.NET.Core/Update/AbstractUpdateTrigger.cs @@ -30,6 +30,9 @@ namespace RGB.NET.Core /// Optional custom-data passed to the subscribers of the .event. protected virtual void OnUpdate(CustomUpdateData? updateData = null) => Update?.Invoke(this, updateData ?? new CustomUpdateData()); + /// + public abstract void Start(); + /// public abstract void Dispose(); diff --git a/RGB.NET.Core/Update/Devices/DeviceUpdateTrigger.cs b/RGB.NET.Core/Update/Devices/DeviceUpdateTrigger.cs index 43caf4c..61e85a3 100644 --- a/RGB.NET.Core/Update/Devices/DeviceUpdateTrigger.cs +++ b/RGB.NET.Core/Update/Devices/DeviceUpdateTrigger.cs @@ -86,7 +86,7 @@ namespace RGB.NET.Core /// /// Starts the trigger. /// - public void Start() + public override void Start() { if (IsRunning) return; diff --git a/RGB.NET.Core/Update/Devices/IUpdateQueue.cs b/RGB.NET.Core/Update/Devices/IUpdateQueue.cs new file mode 100644 index 0000000..0fbcd7a --- /dev/null +++ b/RGB.NET.Core/Update/Devices/IUpdateQueue.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; + +namespace RGB.NET.Core +{ + public interface IUpdateQueue : IDisposable + where TIdentifier : notnull + { + /// + /// Sets or merges the provided data set in the current dataset and notifies the trigger that there is new data available. + /// + /// The set of data. + // ReSharper disable once MemberCanBeProtected.Global + void SetData(IEnumerable<(TIdentifier, TData)> dataSet); + + /// + /// Resets the current data set. + /// + void Reset(); + } + + public interface IUpdateQueue : IUpdateQueue + { } +} diff --git a/RGB.NET.Core/Update/Devices/UpdateQueue.cs b/RGB.NET.Core/Update/Devices/UpdateQueue.cs index 4b48593..364ac6b 100644 --- a/RGB.NET.Core/Update/Devices/UpdateQueue.cs +++ b/RGB.NET.Core/Update/Devices/UpdateQueue.cs @@ -10,7 +10,7 @@ namespace RGB.NET.Core /// /// The type of the key used to identify some data. /// The type of the data. - public abstract class UpdateQueue : IDisposable + public abstract class UpdateQueue : IUpdateQueue where TIdentifier : notnull { #region Properties & Fields @@ -123,7 +123,7 @@ namespace RGB.NET.Core /// /// Represents a generic using an object as the key and a color as the value. /// - public abstract class UpdateQueue : UpdateQueue + public abstract class UpdateQueue : UpdateQueue, IUpdateQueue { #region Constructors diff --git a/RGB.NET.Core/Update/IUpdateTrigger.cs b/RGB.NET.Core/Update/IUpdateTrigger.cs index e80c3c0..4d75cae 100644 --- a/RGB.NET.Core/Update/IUpdateTrigger.cs +++ b/RGB.NET.Core/Update/IUpdateTrigger.cs @@ -16,5 +16,7 @@ namespace RGB.NET.Core /// Occurs when the trigger wants to cause an update. /// event EventHandler? Update; + + void Start(); } } diff --git a/RGB.NET.Core/Update/ManualUpdateTrigger.cs b/RGB.NET.Core/Update/ManualUpdateTrigger.cs index 27d18da..728f43e 100644 --- a/RGB.NET.Core/Update/ManualUpdateTrigger.cs +++ b/RGB.NET.Core/Update/ManualUpdateTrigger.cs @@ -44,7 +44,7 @@ namespace RGB.NET.Core /// /// Starts the trigger if needed, causing it to performing updates. /// - private void Start() + public override void Start() { if (UpdateTask == null) { diff --git a/RGB.NET.Core/Update/TimerUpdateTrigger.cs b/RGB.NET.Core/Update/TimerUpdateTrigger.cs index 24321be..a63c29b 100644 --- a/RGB.NET.Core/Update/TimerUpdateTrigger.cs +++ b/RGB.NET.Core/Update/TimerUpdateTrigger.cs @@ -56,7 +56,7 @@ namespace RGB.NET.Core /// /// Starts the trigger if needed, causing it to performing updates. /// - public void Start() + public override void Start() { lock (_lock) { diff --git a/RGB.NET.Devices.Asus/AsusDeviceProvider.cs b/RGB.NET.Devices.Asus/AsusDeviceProvider.cs index 00f22f4..59a1351 100644 --- a/RGB.NET.Devices.Asus/AsusDeviceProvider.cs +++ b/RGB.NET.Devices.Asus/AsusDeviceProvider.cs @@ -3,8 +3,6 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; using AuraServiceLib; using RGB.NET.Core; @@ -14,7 +12,7 @@ namespace RGB.NET.Devices.Asus /// /// Represents a device provider responsible for Cooler Master devices. /// - public class AsusDeviceProvider : IRGBDeviceProvider + public class AsusDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields @@ -24,20 +22,6 @@ namespace RGB.NET.Devices.Asus /// public static AsusDeviceProvider Instance => _instance ?? new AsusDeviceProvider(); - /// - /// - /// Indicates if the SDK is initialized and ready to use. - /// - public bool IsInitialized { get; private set; } - - /// - public IEnumerable Devices { get; private set; } = Enumerable.Empty(); - - /// - /// The used to trigger the updates for asus devices. - /// - public DeviceUpdateTrigger UpdateTrigger { get; } - private IAuraSdk2? _sdk; #endregion @@ -52,107 +36,44 @@ namespace RGB.NET.Devices.Asus { if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(AsusDeviceProvider)}"); _instance = this; - - UpdateTrigger = new DeviceUpdateTrigger(); } #endregion - + #region Methods - /// - public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false) + protected override void InitializeSDK() { - IsInitialized = false; + _sdk = (IAuraSdk2)new AuraSdk(); + _sdk.SwitchMode(); + } - try + protected override IEnumerable LoadDevices() + { + if (_sdk == null) yield break; + + foreach (IAuraSyncDevice device in _sdk.Enumerate(0)) { - UpdateTrigger.Stop(); - - // ReSharper disable once SuspiciousTypeConversion.Global - _sdk = (IAuraSdk2)new AuraSdk(); - _sdk.SwitchMode(); - - IList devices = new List(); - foreach (IAuraSyncDevice device in _sdk.Enumerate(0)) + yield return (AsusDeviceType)device.Type switch { - try - { - IAsusRGBDevice rgbDevice; - switch ((AsusDeviceType)device.Type) - { - case AsusDeviceType.MB_RGB: - rgbDevice = new AsusMainboardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mainboard, device, WMIHelper.GetMainboardInfo()?.model ?? device.Name)); - break; - - case AsusDeviceType.MB_ADDRESABLE: - rgbDevice = new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.LedStripe, device), LedId.LedStripe1); - break; - - case AsusDeviceType.VGA_RGB: - rgbDevice = new AsusGraphicsCardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.GraphicsCard, device)); - break; - - case AsusDeviceType.HEADSET_RGB: - rgbDevice = new AsusHeadsetRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Headset, device)); - break; - - case AsusDeviceType.DRAM_RGB: - rgbDevice = new AsusDramRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.DRAM, device)); - break; - - case AsusDeviceType.KEYBOARD_RGB: - case AsusDeviceType.NB_KB_RGB: - case AsusDeviceType.NB_KB_4ZONE_RGB: - rgbDevice = new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device)); - break; - - case AsusDeviceType.MOUSE_RGB: - rgbDevice = new AsusMouseRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mouse, device)); - break; - - default: - rgbDevice = new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Unknown, device), LedId.Custom1); - break; - } - - if (loadFilter.HasFlag(rgbDevice.DeviceInfo.DeviceType)) - { - rgbDevice.Initialize(UpdateTrigger); - devices.Add(rgbDevice); - } - } - catch - { - if (throwExceptions) - throw; - } - } - - UpdateTrigger.Start(); - - Devices = new ReadOnlyCollection(devices); - IsInitialized = true; + AsusDeviceType.MB_RGB => new AsusMainboardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mainboard, device, WMIHelper.GetMainboardInfo()?.model ?? device.Name), GetUpdateTrigger()), + AsusDeviceType.MB_ADDRESABLE => new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.LedStripe, device), LedId.LedStripe1, GetUpdateTrigger()), + AsusDeviceType.VGA_RGB => new AsusGraphicsCardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.GraphicsCard, device), GetUpdateTrigger()), + AsusDeviceType.HEADSET_RGB => new AsusHeadsetRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Headset, device), GetUpdateTrigger()), + AsusDeviceType.DRAM_RGB => new AsusDramRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.DRAM, device), GetUpdateTrigger()), + AsusDeviceType.KEYBOARD_RGB => new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device), GetUpdateTrigger()), + AsusDeviceType.NB_KB_RGB => new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device), GetUpdateTrigger()), + AsusDeviceType.NB_KB_4ZONE_RGB => new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device), GetUpdateTrigger()), + AsusDeviceType.MOUSE_RGB => new AsusMouseRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mouse, device), GetUpdateTrigger()), + _ => new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Unknown, device), LedId.Custom1, GetUpdateTrigger()) + }; } - catch - { - if (throwExceptions) - throw; - return false; - } - return true; } /// - public void Dispose() + public override void Dispose() { - try { UpdateTrigger.Dispose(); } - catch { /* at least we tried */ } - - foreach (IRGBDevice device in Devices) - try { device.Dispose(); } - catch { /* at least we tried */ } - Devices = Enumerable.Empty(); + base.Dispose(); try { _sdk?.ReleaseControl(0); } catch { /* at least we tried */ } diff --git a/RGB.NET.Devices.Asus/Dram/AsusDramRGBDevice.cs b/RGB.NET.Devices.Asus/Dram/AsusDramRGBDevice.cs index 6920a01..ef1b046 100644 --- a/RGB.NET.Devices.Asus/Dram/AsusDramRGBDevice.cs +++ b/RGB.NET.Devices.Asus/Dram/AsusDramRGBDevice.cs @@ -15,16 +15,17 @@ namespace RGB.NET.Devices.Asus /// Initializes a new instance of the class. /// /// The specific information provided by Asus for the DRAM. - internal AsusDramRGBDevice(AsusRGBDeviceInfo info) - : base(info) - { } + internal AsusDramRGBDevice(AsusRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, updateTrigger) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { int ledCount = DeviceInfo.Device.Lights.Count; for (int i = 0; i < ledCount; i++) diff --git a/RGB.NET.Devices.Asus/Generic/AsusRGBDevice.cs b/RGB.NET.Devices.Asus/Generic/AsusRGBDevice.cs index 3973048..f80056a 100644 --- a/RGB.NET.Devices.Asus/Generic/AsusRGBDevice.cs +++ b/RGB.NET.Devices.Asus/Generic/AsusRGBDevice.cs @@ -1,75 +1,23 @@ -using System.Collections.Generic; -using System.Linq; -using RGB.NET.Core; +using RGB.NET.Core; namespace RGB.NET.Devices.Asus { /// - /// /// /// Represents a generic Asus-device. (keyboard, mouse, headset, mousepad). /// public abstract class AsusRGBDevice : AbstractRGBDevice, IAsusRGBDevice where TDeviceInfo : AsusRGBDeviceInfo { - #region Properties & Fields - - /// - /// - /// Gets information about the . - /// - public override TDeviceInfo DeviceInfo { get; } - - /// - /// Gets or sets the update queue performing updates for this device. - /// - // ReSharper disable once MemberCanBePrivate.Global - protected AsusUpdateQueue? UpdateQueue { get; set; } - - #endregion - #region Constructors /// /// Initializes a new instance of the class. /// /// The generic information provided by Asus for the device. - protected AsusRGBDevice(TDeviceInfo info) - { - this.DeviceInfo = info; - } - - #endregion - - #region Methods - - /// - /// Initializes the device. - /// - public void Initialize(IDeviceUpdateTrigger updateTrigger) - { - InitializeLayout(); - - UpdateQueue = new AsusUpdateQueue(updateTrigger); - UpdateQueue.Initialize(DeviceInfo.Device); - } - - /// - /// Initializes the and of the device. - /// - protected abstract void InitializeLayout(); - - /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); - - /// - public override void Dispose() - { - try { UpdateQueue?.Dispose(); } - catch { /* at least we tried */ } - - base.Dispose(); - } + protected AsusRGBDevice(TDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, new AsusUpdateQueue(updateTrigger, info.Device)) + { } #endregion } diff --git a/RGB.NET.Devices.Asus/Generic/AsusUnspecifiedRGBDevice.cs b/RGB.NET.Devices.Asus/Generic/AsusUnspecifiedRGBDevice.cs index c114b52..e0abfa5 100644 --- a/RGB.NET.Devices.Asus/Generic/AsusUnspecifiedRGBDevice.cs +++ b/RGB.NET.Devices.Asus/Generic/AsusUnspecifiedRGBDevice.cs @@ -21,18 +21,19 @@ namespace RGB.NET.Devices.Asus /// Initializes a new instance of the class. /// /// The specific information provided by Asus for the headset. - internal AsusUnspecifiedRGBDevice(AsusRGBDeviceInfo info, LedId baseLedId) - : base(info) + internal AsusUnspecifiedRGBDevice(AsusRGBDeviceInfo info, LedId baseLedId, IDeviceUpdateTrigger updateTrigger) + : base(info, updateTrigger) { this._baseLedId = baseLedId; + + InitializeLayout(); } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { int ledCount = DeviceInfo.Device.Lights.Count; for (int i = 0; i < ledCount; i++) @@ -41,6 +42,7 @@ namespace RGB.NET.Devices.Asus /// protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)_baseLedId; + #endregion } } diff --git a/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs b/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs index 73cbc31..70b1a38 100644 --- a/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs +++ b/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs @@ -15,7 +15,7 @@ namespace RGB.NET.Devices.Asus /// /// The device to be updated. /// - protected IAuraSyncDevice? Device { get; private set; } + protected IAuraSyncDevice Device { get; } #endregion @@ -25,28 +25,19 @@ namespace RGB.NET.Devices.Asus /// Initializes a new instance of the class. /// /// The update trigger used by this queue. - public AsusUpdateQueue(IDeviceUpdateTrigger updateTrigger) + public AsusUpdateQueue(IDeviceUpdateTrigger updateTrigger, IAuraSyncDevice device) : base(updateTrigger) - { } + { + this.Device = device; + } #endregion #region Methods - /// - /// Initializes the queue. - /// - /// The device to be updated. - public void Initialize(IAuraSyncDevice device) - { - Device = device; - } - /// protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - if (Device == null) return; - try { if ((Device.Type == (uint)AsusDeviceType.KEYBOARD_RGB) || (Device.Type == (uint)AsusDeviceType.NB_KB_RGB)) diff --git a/RGB.NET.Devices.Asus/Generic/IAsusRGBDevice.cs b/RGB.NET.Devices.Asus/Generic/IAsusRGBDevice.cs index 720fd3c..74b0d08 100644 --- a/RGB.NET.Devices.Asus/Generic/IAsusRGBDevice.cs +++ b/RGB.NET.Devices.Asus/Generic/IAsusRGBDevice.cs @@ -5,8 +5,6 @@ namespace RGB.NET.Devices.Asus /// /// Represents a asus RGB-device. /// - internal interface IAsusRGBDevice : IRGBDevice - { - void Initialize(IDeviceUpdateTrigger updateTrigger); - } + public interface IAsusRGBDevice : IRGBDevice + { } } diff --git a/RGB.NET.Devices.Asus/GraphicsCard/AsusGraphicsCardRGBDevice.cs b/RGB.NET.Devices.Asus/GraphicsCard/AsusGraphicsCardRGBDevice.cs index 8c0f98a..698b2c3 100644 --- a/RGB.NET.Devices.Asus/GraphicsCard/AsusGraphicsCardRGBDevice.cs +++ b/RGB.NET.Devices.Asus/GraphicsCard/AsusGraphicsCardRGBDevice.cs @@ -15,16 +15,17 @@ namespace RGB.NET.Devices.Asus /// Initializes a new instance of the class. /// /// The specific information provided by Asus for the graphics card. - internal AsusGraphicsCardRGBDevice(AsusRGBDeviceInfo info) - : base(info) - { } + internal AsusGraphicsCardRGBDevice(AsusRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, updateTrigger) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { int ledCount = DeviceInfo.Device.Lights.Count; for (int i = 0; i < ledCount; i++) diff --git a/RGB.NET.Devices.Asus/Headset/AsusHeadsetRGBDevice.cs b/RGB.NET.Devices.Asus/Headset/AsusHeadsetRGBDevice.cs index 96c4c87..22d14d9 100644 --- a/RGB.NET.Devices.Asus/Headset/AsusHeadsetRGBDevice.cs +++ b/RGB.NET.Devices.Asus/Headset/AsusHeadsetRGBDevice.cs @@ -15,16 +15,17 @@ namespace RGB.NET.Devices.Asus /// Initializes a new instance of the class. /// /// The specific information provided by Asus for the headset. - internal AsusHeadsetRGBDevice(AsusRGBDeviceInfo info) - : base(info) - { } + internal AsusHeadsetRGBDevice(AsusRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, updateTrigger) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { int ledCount = DeviceInfo.Device.Lights.Count; for (int i = 0; i < ledCount; i++) diff --git a/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardRGBDevice.cs b/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardRGBDevice.cs index b10eb60..28cfbec 100644 --- a/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardRGBDevice.cs +++ b/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardRGBDevice.cs @@ -24,16 +24,17 @@ namespace RGB.NET.Devices.Asus /// Initializes a new instance of the class. /// /// The specific information provided by Asus for the keyboard. - internal AsusKeyboardRGBDevice(AsusKeyboardRGBDeviceInfo info) - : base(info) - { } + internal AsusKeyboardRGBDevice(AsusKeyboardRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, updateTrigger) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { Dictionary reversedMapping = AsusKeyboardLedMapping.MAPPING.ToDictionary(x => x.Value, x => x.Key); diff --git a/RGB.NET.Devices.Asus/Mainboard/AsusMainboardRGBDevice.cs b/RGB.NET.Devices.Asus/Mainboard/AsusMainboardRGBDevice.cs index e4b25a5..bde9f1b 100644 --- a/RGB.NET.Devices.Asus/Mainboard/AsusMainboardRGBDevice.cs +++ b/RGB.NET.Devices.Asus/Mainboard/AsusMainboardRGBDevice.cs @@ -15,16 +15,17 @@ namespace RGB.NET.Devices.Asus /// Initializes a new instance of the class. /// /// The specific information provided by Asus for the mainboard. - internal AsusMainboardRGBDevice(AsusRGBDeviceInfo info) - : base(info) - { } + internal AsusMainboardRGBDevice(AsusRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, updateTrigger) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { int ledCount = DeviceInfo.Device.Lights.Count; for (int i = 0; i < ledCount; i++) @@ -33,7 +34,7 @@ namespace RGB.NET.Devices.Asus /// protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Mainboard1; - + #endregion } } diff --git a/RGB.NET.Devices.Asus/Mouse/AsusMouseRGBDevice.cs b/RGB.NET.Devices.Asus/Mouse/AsusMouseRGBDevice.cs index cd97e88..fdbd204 100644 --- a/RGB.NET.Devices.Asus/Mouse/AsusMouseRGBDevice.cs +++ b/RGB.NET.Devices.Asus/Mouse/AsusMouseRGBDevice.cs @@ -15,16 +15,17 @@ namespace RGB.NET.Devices.Asus /// Initializes a new instance of the class. /// /// The specific information provided by Asus for the mouse. - internal AsusMouseRGBDevice(AsusRGBDeviceInfo info) - : base(info) - { } + internal AsusMouseRGBDevice(AsusRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, updateTrigger) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { int ledCount = DeviceInfo.Device.Lights.Count; for (int i = 0; i < ledCount; i++) diff --git a/RGB.NET.Devices.CoolerMaster/CoolerMasterDeviceProvider.cs b/RGB.NET.Devices.CoolerMaster/CoolerMasterDeviceProvider.cs index f7e57dc..eb96ce0 100644 --- a/RGB.NET.Devices.CoolerMaster/CoolerMasterDeviceProvider.cs +++ b/RGB.NET.Devices.CoolerMaster/CoolerMasterDeviceProvider.cs @@ -3,8 +3,6 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; using RGB.NET.Core; using RGB.NET.Devices.CoolerMaster.Helper; using RGB.NET.Devices.CoolerMaster.Native; @@ -15,7 +13,7 @@ namespace RGB.NET.Devices.CoolerMaster /// /// Represents a device provider responsible for Cooler Master devices. /// - public class CoolerMasterDeviceProvider : IRGBDeviceProvider + public class CoolerMasterDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields @@ -37,20 +35,6 @@ namespace RGB.NET.Devices.CoolerMaster /// public static List PossibleX64NativePaths { get; } = new() { "x64/CMSDK.dll" }; - /// - /// - /// Indicates if the SDK is initialized and ready to use. - /// - public bool IsInitialized { get; private set; } - - /// - public IEnumerable Devices { get; private set; } = Enumerable.Empty(); - - /// - /// The used to trigger the updates for cooler master devices. - /// - public DeviceUpdateTrigger UpdateTrigger { get; } - #endregion #region Constructors @@ -63,97 +47,48 @@ namespace RGB.NET.Devices.CoolerMaster { if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(CoolerMasterDeviceProvider)}"); _instance = this; - - UpdateTrigger = new DeviceUpdateTrigger(); } #endregion #region Methods - /// - public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false) + protected override void InitializeSDK() { - IsInitialized = false; - - try - { - UpdateTrigger.Stop(); - - _CoolerMasterSDK.Reload(); - if (_CoolerMasterSDK.GetSDKVersion() <= 0) return false; - - IList devices = new List(); - - foreach (CoolerMasterDevicesIndexes index in Enum.GetValues(typeof(CoolerMasterDevicesIndexes))) - { - try - { - RGBDeviceType deviceType = index.GetDeviceType(); - if (deviceType == RGBDeviceType.None) continue; - - if (_CoolerMasterSDK.IsDevicePlugged(index)) - { - if (!loadFilter.HasFlag(deviceType)) continue; - - ICoolerMasterRGBDevice device; - switch (deviceType) - { - case RGBDeviceType.Keyboard: - CoolerMasterPhysicalKeyboardLayout physicalLayout = _CoolerMasterSDK.GetDeviceLayout(index); - device = new CoolerMasterKeyboardRGBDevice(new CoolerMasterKeyboardRGBDeviceInfo(index, physicalLayout)); - break; - - case RGBDeviceType.Mouse: - device = new CoolerMasterMouseRGBDevice(new CoolerMasterMouseRGBDeviceInfo(index)); - break; - - default: - if (throwExceptions) - throw new RGBDeviceException("Unknown Device-Type"); - else - continue; - } - - if (!_CoolerMasterSDK.EnableLedControl(true, index)) - throw new RGBDeviceException("Failed to enable LED control for device " + index); - - device.Initialize(UpdateTrigger); - devices.Add(device); - } - } - catch { if (throwExceptions) throw; } - } - - UpdateTrigger.Start(); - - Devices = new ReadOnlyCollection(devices); - IsInitialized = true; - } - catch - { - if (throwExceptions) - throw; - return false; - } - - return true; + _CoolerMasterSDK.Reload(); + if (_CoolerMasterSDK.GetSDKVersion() <= 0) Throw(new RGBDeviceException("Failed to initialize CoolerMaster-SDK")); } - /// - public void Dispose() + protected override IEnumerable LoadDevices() { - try { UpdateTrigger.Dispose(); } - catch { /* at least we tried */ } + foreach (CoolerMasterDevicesIndexes index in Enum.GetValues(typeof(CoolerMasterDevicesIndexes))) + { + RGBDeviceType deviceType = index.GetDeviceType(); + if (deviceType == RGBDeviceType.None) continue; - foreach (IRGBDevice device in Devices) - try { device.Dispose(); } - catch { /* at least we tried */ } - Devices = Enumerable.Empty(); + if (_CoolerMasterSDK.IsDevicePlugged(index)) + { + if (!_CoolerMasterSDK.EnableLedControl(true, index)) + Throw(new RGBDeviceException("Failed to enable LED control for device " + index)); + else + { + switch (deviceType) + { + case RGBDeviceType.Keyboard: + yield return new CoolerMasterKeyboardRGBDevice(new CoolerMasterKeyboardRGBDeviceInfo(index, _CoolerMasterSDK.GetDeviceLayout(index)), GetUpdateTrigger()); + break; - // DarthAffe 03.03.2020: Should be done but isn't possible due to an weird winodws-hook inside the sdk which corrupts the stack when unloading the dll - //try { _CoolerMasterSDK.UnloadCMSDK(); } - //catch { /* at least we tried */ } + case RGBDeviceType.Mouse: + yield return new CoolerMasterMouseRGBDevice(new CoolerMasterMouseRGBDeviceInfo(index), GetUpdateTrigger()); + break; + + default: + Throw(new RGBDeviceException("Unknown Device-Type")); + break; + } + } + } + } } #endregion diff --git a/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterRGBDevice.cs b/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterRGBDevice.cs index ac17daa..fdeaf39 100644 --- a/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterRGBDevice.cs +++ b/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterRGBDevice.cs @@ -1,76 +1,34 @@ using System; -using System.Collections.Generic; -using System.Linq; using RGB.NET.Core; using RGB.NET.Devices.CoolerMaster.Native; namespace RGB.NET.Devices.CoolerMaster { /// - /// /// /// Represents a generic CoolerMaster-device. (keyboard, mouse, headset, mousepad). /// public abstract class CoolerMasterRGBDevice : AbstractRGBDevice, ICoolerMasterRGBDevice where TDeviceInfo : CoolerMasterRGBDeviceInfo { - #region Properties & Fields - - /// - /// - /// Gets information about the . - /// - public override TDeviceInfo DeviceInfo { get; } - - /// - /// Gets or sets the update queue performing updates for this device. - /// - // ReSharper disable once MemberCanBePrivate.Global - protected CoolerMasterUpdateQueue? UpdateQueue { get; set; } - - #endregion - #region Constructors /// /// Initializes a new instance of the class. /// /// The generic information provided by CoolerMaster for the device. - protected CoolerMasterRGBDevice(TDeviceInfo info) - { - this.DeviceInfo = info; - } + protected CoolerMasterRGBDevice(TDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, new CoolerMasterUpdateQueue(updateTrigger, info.DeviceIndex)) + { } #endregion #region Methods - - /// - /// Initializes the device. - /// - public void Initialize(IDeviceUpdateTrigger updateTrigger) - { - InitializeLayout(); - - UpdateQueue = new CoolerMasterUpdateQueue(updateTrigger, DeviceInfo.DeviceIndex); - } - - /// - /// Initializes the and of the device. - /// - protected abstract void InitializeLayout(); - - /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); - /// /// public override void Dispose() { - try { UpdateQueue?.Dispose(); } - catch { /* at least we tried */ } - _CoolerMasterSDK.EnableLedControl(false, DeviceInfo.DeviceIndex); base.Dispose(); diff --git a/RGB.NET.Devices.CoolerMaster/Generic/ICoolerMasterRGBDevice.cs b/RGB.NET.Devices.CoolerMaster/Generic/ICoolerMasterRGBDevice.cs index 8483843..4edd1e9 100644 --- a/RGB.NET.Devices.CoolerMaster/Generic/ICoolerMasterRGBDevice.cs +++ b/RGB.NET.Devices.CoolerMaster/Generic/ICoolerMasterRGBDevice.cs @@ -5,8 +5,6 @@ namespace RGB.NET.Devices.CoolerMaster /// /// Represents a CoolerMaster RGB-device. /// - internal interface ICoolerMasterRGBDevice : IRGBDevice - { - void Initialize(IDeviceUpdateTrigger updateTrigger); - } + public interface ICoolerMasterRGBDevice : IRGBDevice + { } } diff --git a/RGB.NET.Devices.CoolerMaster/Keyboard/CoolerMasterKeyboardRGBDevice.cs b/RGB.NET.Devices.CoolerMaster/Keyboard/CoolerMasterKeyboardRGBDevice.cs index 29df3be..9007148 100644 --- a/RGB.NET.Devices.CoolerMaster/Keyboard/CoolerMasterKeyboardRGBDevice.cs +++ b/RGB.NET.Devices.CoolerMaster/Keyboard/CoolerMasterKeyboardRGBDevice.cs @@ -22,16 +22,17 @@ namespace RGB.NET.Devices.CoolerMaster /// Initializes a new instance of the class. /// /// The specific information provided by CoolerMaster for the keyboard - internal CoolerMasterKeyboardRGBDevice(CoolerMasterKeyboardRGBDeviceInfo info) - : base(info) - { } + internal CoolerMasterKeyboardRGBDevice(CoolerMasterKeyboardRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, updateTrigger) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { if (!CoolerMasterKeyboardLedMappings.Mapping.TryGetValue(DeviceInfo.DeviceIndex, out Dictionary>? deviceMappings)) throw new RGBDeviceException($"Failed to find a CoolerMasterKeyboardLedMapping for device index {DeviceInfo.DeviceIndex}"); @@ -44,7 +45,7 @@ namespace RGB.NET.Devices.CoolerMaster /// protected override object GetLedCustomData(LedId ledId) => CoolerMasterKeyboardLedMappings.Mapping[DeviceInfo.DeviceIndex][DeviceInfo.PhysicalLayout][ledId]; - + #endregion } } diff --git a/RGB.NET.Devices.CoolerMaster/Mouse/CoolerMasterMouseRGBDevice.cs b/RGB.NET.Devices.CoolerMaster/Mouse/CoolerMasterMouseRGBDevice.cs index e1efb77..aa4c3aa 100644 --- a/RGB.NET.Devices.CoolerMaster/Mouse/CoolerMasterMouseRGBDevice.cs +++ b/RGB.NET.Devices.CoolerMaster/Mouse/CoolerMasterMouseRGBDevice.cs @@ -16,16 +16,15 @@ namespace RGB.NET.Devices.CoolerMaster /// Initializes a new instance of the class. /// /// The specific information provided by CoolerMaster for the mouse - internal CoolerMasterMouseRGBDevice(CoolerMasterMouseRGBDeviceInfo info) - : base(info) + internal CoolerMasterMouseRGBDevice(CoolerMasterMouseRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, updateTrigger) { } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { Dictionary mapping = CoolerMasterMouseLedMappings.Mapping[DeviceInfo.DeviceIndex]; @@ -35,7 +34,7 @@ namespace RGB.NET.Devices.CoolerMaster /// protected override object GetLedCustomData(LedId ledId) => CoolerMasterMouseLedMappings.Mapping[DeviceInfo.DeviceIndex][ledId]; - + #endregion } } diff --git a/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs b/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs index 4f7a57a..3e05167 100644 --- a/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs +++ b/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs @@ -15,7 +15,7 @@ namespace RGB.NET.Devices.Corsair /// /// Represents a device provider responsible for corsair (CUE) devices. /// - public class CorsairDeviceProvider : IRGBDeviceProvider + public class CorsairDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields @@ -37,12 +37,6 @@ namespace RGB.NET.Devices.Corsair /// public static List PossibleX64NativePaths { get; } = new() { "x64/CUESDK.dll", "x64/CUESDK_2015.dll", "x64/CUESDK_2013.dll" }; - /// - /// - /// Indicates if the SDK is initialized and ready to use. - /// - public bool IsInitialized { get; private set; } - /// /// Gets the protocol details for the current SDK-connection. /// @@ -53,14 +47,6 @@ namespace RGB.NET.Devices.Corsair /// public CorsairError LastError => _CUESDK.CorsairGetLastError(); - /// - public IEnumerable Devices { get; private set; } = Enumerable.Empty(); - - /// - /// The used to trigger the updates for corsair devices. - /// - public DeviceUpdateTrigger UpdateTrigger { get; } - #endregion #region Constructors @@ -73,156 +59,108 @@ namespace RGB.NET.Devices.Corsair { if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(CorsairDeviceProvider)}"); _instance = this; - - UpdateTrigger = new DeviceUpdateTrigger(); } #endregion #region Methods - /// - /// Thrown if the SDK is already initialized or if the SDK is not compatible to CUE. - /// Thrown if the CUE-SDK provides an error. - public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false) + protected override void InitializeSDK() { - IsInitialized = false; + _CUESDK.Reload(); - try - { - UpdateTrigger.Stop(); + ProtocolDetails = new CorsairProtocolDetails(_CUESDK.CorsairPerformProtocolHandshake()); - _CUESDK.Reload(); + CorsairError error = LastError; + if (error != CorsairError.Success) + Throw(new CUEException(error)); - ProtocolDetails = new CorsairProtocolDetails(_CUESDK.CorsairPerformProtocolHandshake()); + if (ProtocolDetails.BreakingChanges) + Throw(new RGBDeviceException("The SDK currently used isn't compatible with the installed version of CUE.\r\n" + + $"CUE-Version: {ProtocolDetails.ServerVersion} (Protocol {ProtocolDetails.ServerProtocolVersion})\r\n" + + $"SDK-Version: {ProtocolDetails.SdkVersion} (Protocol {ProtocolDetails.SdkProtocolVersion})")); - CorsairError error = LastError; - if (error != CorsairError.Success) - throw new CUEException(error); - - if (ProtocolDetails.BreakingChanges) - throw new RGBDeviceException("The SDK currently used isn't compatible with the installed version of CUE.\r\n" - + $"CUE-Version: {ProtocolDetails.ServerVersion} (Protocol {ProtocolDetails.ServerProtocolVersion})\r\n" - + $"SDK-Version: {ProtocolDetails.SdkVersion} (Protocol {ProtocolDetails.SdkProtocolVersion})"); - - // DarthAffe 02.02.2021: 127 is iCUE - if (!_CUESDK.CorsairSetLayerPriority(128)) - throw new CUEException(LastError); - - Dictionary modelCounter = new(); - IList devices = new List(); - int deviceCount = _CUESDK.CorsairGetDeviceCount(); - for (int i = 0; i < deviceCount; i++) - { - try - { - _CorsairDeviceInfo nativeDeviceInfo = (_CorsairDeviceInfo)Marshal.PtrToStructure(_CUESDK.CorsairGetDeviceInfo(i), typeof(_CorsairDeviceInfo))!; - CorsairRGBDeviceInfo info = new(i, RGBDeviceType.Unknown, nativeDeviceInfo, modelCounter); - if (!info.CapsMask.HasFlag(CorsairDeviceCaps.Lighting)) - continue; // Everything that doesn't support lighting control is useless - - CorsairDeviceUpdateQueue? deviceUpdateQueue = null; - foreach (ICorsairRGBDevice device in GetRGBDevice(info, i, nativeDeviceInfo, modelCounter)) - { - if ((device == null) || !loadFilter.HasFlag(device.DeviceInfo.DeviceType)) continue; - - deviceUpdateQueue ??= new CorsairDeviceUpdateQueue(UpdateTrigger, info.CorsairDeviceIndex); - - device.Initialize(deviceUpdateQueue); - - error = LastError; - if (error != CorsairError.Success) - throw new CUEException(error); - - devices.Add(device); - } - } - catch { if (throwExceptions) throw; } - } - - UpdateTrigger.Start(); - - Devices = new ReadOnlyCollection(devices); - IsInitialized = true; - } - catch - { - Reset(); - if (throwExceptions) throw; - return false; - } - - return true; + // DarthAffe 02.02.2021: 127 is iCUE + if (!_CUESDK.CorsairSetLayerPriority(128)) + Throw(new CUEException(LastError)); } - private static IEnumerable GetRGBDevice(CorsairRGBDeviceInfo info, int i, _CorsairDeviceInfo nativeDeviceInfo, Dictionary modelCounter) + protected override IEnumerable LoadDevices() { - switch (info.CorsairDeviceType) + Dictionary modelCounter = new(); + int deviceCount = _CUESDK.CorsairGetDeviceCount(); + for (int i = 0; i < deviceCount; i++) { - case CorsairDeviceType.Keyboard: - yield return new CorsairKeyboardRGBDevice(new CorsairKeyboardRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); - break; + _CorsairDeviceInfo nativeDeviceInfo = (_CorsairDeviceInfo)Marshal.PtrToStructure(_CUESDK.CorsairGetDeviceInfo(i), typeof(_CorsairDeviceInfo))!; + CorsairRGBDeviceInfo info = new(i, RGBDeviceType.Unknown, nativeDeviceInfo, modelCounter); + if (!info.CapsMask.HasFlag(CorsairDeviceCaps.Lighting)) + continue; // Everything that doesn't support lighting control is useless - case CorsairDeviceType.Mouse: - yield return new CorsairMouseRGBDevice(new CorsairMouseRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); - break; + CorsairDeviceUpdateQueue updateQueue = new(GetUpdateTrigger(), info.CorsairDeviceIndex); + switch (info.CorsairDeviceType) + { + case CorsairDeviceType.Keyboard: + yield return new CorsairKeyboardRGBDevice(new CorsairKeyboardRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue); + break; - case CorsairDeviceType.Headset: - yield return new CorsairHeadsetRGBDevice(new CorsairHeadsetRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); - break; + case CorsairDeviceType.Mouse: + yield return new CorsairMouseRGBDevice(new CorsairMouseRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue); + break; - case CorsairDeviceType.Mousepad: - yield return new CorsairMousepadRGBDevice(new CorsairMousepadRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); - break; + case CorsairDeviceType.Headset: + yield return new CorsairHeadsetRGBDevice(new CorsairHeadsetRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue); + break; - case CorsairDeviceType.HeadsetStand: - yield return new CorsairHeadsetStandRGBDevice(new CorsairHeadsetStandRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); - break; + case CorsairDeviceType.Mousepad: + yield return new CorsairMousepadRGBDevice(new CorsairMousepadRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue); + break; - case CorsairDeviceType.MemoryModule: - yield return new CorsairMemoryRGBDevice(new CorsairMemoryRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); - break; + case CorsairDeviceType.HeadsetStand: + yield return new CorsairHeadsetStandRGBDevice(new CorsairHeadsetStandRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue); + break; - case CorsairDeviceType.Cooler: - case CorsairDeviceType.CommanderPro: - case CorsairDeviceType.LightningNodePro: - _CorsairChannelsInfo? channelsInfo = nativeDeviceInfo.channels; - if (channelsInfo != null) - { - IntPtr channelInfoPtr = channelsInfo.channels; + case CorsairDeviceType.MemoryModule: + yield return new CorsairMemoryRGBDevice(new CorsairMemoryRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue); + break; - for (int channel = 0; channel < channelsInfo.channelsCount; channel++) + case CorsairDeviceType.Cooler: + case CorsairDeviceType.CommanderPro: + case CorsairDeviceType.LightningNodePro: + _CorsairChannelsInfo? channelsInfo = nativeDeviceInfo.channels; + if (channelsInfo != null) { - CorsairLedId referenceLed = GetChannelReferenceId(info.CorsairDeviceType, channel); - if (referenceLed == CorsairLedId.Invalid) continue; + IntPtr channelInfoPtr = channelsInfo.channels; - _CorsairChannelInfo channelInfo = (_CorsairChannelInfo)Marshal.PtrToStructure(channelInfoPtr, typeof(_CorsairChannelInfo))!; - - int channelDeviceInfoStructSize = Marshal.SizeOf(typeof(_CorsairChannelDeviceInfo)); - IntPtr channelDeviceInfoPtr = channelInfo.devices; - - for (int device = 0; device < channelInfo.devicesCount; device++) + for (int channel = 0; channel < channelsInfo.channelsCount; channel++) { - _CorsairChannelDeviceInfo channelDeviceInfo = (_CorsairChannelDeviceInfo)Marshal.PtrToStructure(channelDeviceInfoPtr, typeof(_CorsairChannelDeviceInfo))!; + CorsairLedId referenceLed = GetChannelReferenceId(info.CorsairDeviceType, channel); + if (referenceLed == CorsairLedId.Invalid) continue; - yield return new CorsairCustomRGBDevice(new CorsairCustomRGBDeviceInfo(info, nativeDeviceInfo, channelDeviceInfo, referenceLed, modelCounter)); - referenceLed += channelDeviceInfo.deviceLedCount; + _CorsairChannelInfo channelInfo = (_CorsairChannelInfo)Marshal.PtrToStructure(channelInfoPtr, typeof(_CorsairChannelInfo))!; - channelDeviceInfoPtr = new IntPtr(channelDeviceInfoPtr.ToInt64() + channelDeviceInfoStructSize); + int channelDeviceInfoStructSize = Marshal.SizeOf(typeof(_CorsairChannelDeviceInfo)); + IntPtr channelDeviceInfoPtr = channelInfo.devices; + + for (int device = 0; device < channelInfo.devicesCount; device++) + { + _CorsairChannelDeviceInfo channelDeviceInfo = (_CorsairChannelDeviceInfo)Marshal.PtrToStructure(channelDeviceInfoPtr, typeof(_CorsairChannelDeviceInfo))!; + + yield return new CorsairCustomRGBDevice(new CorsairCustomRGBDeviceInfo(info, nativeDeviceInfo, channelDeviceInfo, referenceLed, modelCounter), updateQueue); + referenceLed += channelDeviceInfo.deviceLedCount; + + channelDeviceInfoPtr = new IntPtr(channelDeviceInfoPtr.ToInt64() + channelDeviceInfoStructSize); + } + + int channelInfoStructSize = Marshal.SizeOf(typeof(_CorsairChannelInfo)); + channelInfoPtr = new IntPtr(channelInfoPtr.ToInt64() + channelInfoStructSize); } - - int channelInfoStructSize = Marshal.SizeOf(typeof(_CorsairChannelInfo)); - channelInfoPtr = new IntPtr(channelInfoPtr.ToInt64() + channelInfoStructSize); } - } + break; - break; - - - // ReSharper disable once RedundantCaseLabel - case CorsairDeviceType.Unknown: - default: - throw new RGBDeviceException("Unknown Device-Type"); + default: + Throw(new RGBDeviceException("Unknown Device-Type")); + break; + } } } @@ -240,23 +178,17 @@ namespace RGB.NET.Devices.Corsair }; } - private void Reset() + protected override void Reset() { ProtocolDetails = null; - Devices = Enumerable.Empty(); - IsInitialized = false; + + base.Reset(); } /// - public void Dispose() + public override void Dispose() { - try { UpdateTrigger.Dispose(); } - catch { /* at least we tried */ } - - foreach (IRGBDevice device in Devices) - try { device.Dispose(); } - catch { /* at least we tried */ } - Devices = Enumerable.Empty(); + base.Dispose(); try { _CUESDK.UnloadCUESDK(); } catch { /* at least we tried */ } diff --git a/RGB.NET.Devices.Corsair/Custom/CorsairCustomRGBDevice.cs b/RGB.NET.Devices.Corsair/Custom/CorsairCustomRGBDevice.cs index 0ea52b4..fc67e5a 100644 --- a/RGB.NET.Devices.Corsair/Custom/CorsairCustomRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/Custom/CorsairCustomRGBDevice.cs @@ -25,16 +25,17 @@ namespace RGB.NET.Devices.Corsair /// Initializes a new instance of the class. /// /// The specific information provided by CUE for the custom-device. - internal CorsairCustomRGBDevice(CorsairCustomRGBDeviceInfo info) - : base(info) - { } + internal CorsairCustomRGBDevice(CorsairCustomRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue) + : base(info, updateQueue) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { LedId referenceId = GetReferenceLed(DeviceInfo.DeviceType); @@ -45,7 +46,7 @@ namespace RGB.NET.Devices.Corsair AddLed(ledId, new Point(i * 10, 0), new Size(10, 10)); } } - + protected override object GetLedCustomData(LedId ledId) => _idMapping.TryGetValue(ledId, out CorsairLedId id) ? id : CorsairLedId.Invalid; protected virtual LedId GetReferenceLed(RGBDeviceType deviceType) diff --git a/RGB.NET.Devices.Corsair/Generic/CorsairRGBDevice.cs b/RGB.NET.Devices.Corsair/Generic/CorsairRGBDevice.cs index ef2a854..c7e1864 100644 --- a/RGB.NET.Devices.Corsair/Generic/CorsairRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/Generic/CorsairRGBDevice.cs @@ -1,99 +1,23 @@ -using System.Collections.Generic; -using System.Linq; -using RGB.NET.Core; +using RGB.NET.Core; namespace RGB.NET.Devices.Corsair { /// - /// /// /// Represents a generic CUE-device. (keyboard, mouse, headset, mousepad). /// public abstract class CorsairRGBDevice : AbstractRGBDevice, ICorsairRGBDevice where TDeviceInfo : CorsairRGBDeviceInfo { - #region Properties & Fields - - /// - /// - /// Gets information about the . - /// - public override TDeviceInfo DeviceInfo { get; } - - /// - /// Gets a dictionary containing all of the . - /// - // ReSharper disable once MemberCanBePrivate.Global - protected Dictionary InternalLedMapping { get; } = new(); - - /// - /// Gets or sets the update queue performing updates for this device. - /// - // ReSharper disable once MemberCanBePrivate.Global - protected CorsairDeviceUpdateQueue? DeviceUpdateQueue { get; set; } - - #endregion - - #region Indexer - - /// - /// Gets the with the specified . - /// - /// The of the to get. - /// The with the specified or null if no is found. - // ReSharper disable once MemberCanBePrivate.Global - public Led? this[CorsairLedId ledId] => InternalLedMapping.TryGetValue(ledId, out Led? led) ? led : null; - - #endregion - #region Constructors /// /// Initializes a new instance of the class. /// /// The generic information provided by CUE for the device. - protected CorsairRGBDevice(TDeviceInfo info) - { - this.DeviceInfo = info; - } - - #endregion - - #region Methods - - /// - /// Initializes the device. - /// - public void Initialize(CorsairDeviceUpdateQueue deviceUpdateQueue) - { - DeviceUpdateQueue = deviceUpdateQueue; - - InitializeLayout(); - - foreach (Led led in LedMapping.Values) - { - if (led.CustomData is CorsairLedId ledId && (ledId != CorsairLedId.Invalid)) - InternalLedMapping.Add(ledId, led); - } - } - - /// - /// Initializes the and of the device. - /// - protected abstract void InitializeLayout(); - - /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) - => DeviceUpdateQueue?.SetData(GetUpdateData(ledsToUpdate.Where(x => (x.Color.A > 0) && (x.CustomData is CorsairLedId ledId && (ledId != CorsairLedId.Invalid))))); - - /// - public override void Dispose() - { - try { DeviceUpdateQueue?.Dispose(); } - catch { /* at least we tried */ } - - base.Dispose(); - } + protected CorsairRGBDevice(TDeviceInfo info, CorsairDeviceUpdateQueue updateQueue) + : base(info, updateQueue) + { } #endregion } diff --git a/RGB.NET.Devices.Corsair/Generic/ICorsairRGBDevice.cs b/RGB.NET.Devices.Corsair/Generic/ICorsairRGBDevice.cs index 325c46c..9caca09 100644 --- a/RGB.NET.Devices.Corsair/Generic/ICorsairRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/Generic/ICorsairRGBDevice.cs @@ -5,8 +5,6 @@ namespace RGB.NET.Devices.Corsair /// /// Represents a corsair RGB-device. /// - internal interface ICorsairRGBDevice : IRGBDevice - { - void Initialize(CorsairDeviceUpdateQueue deviceUpdateQueue); - } + public interface ICorsairRGBDevice : IRGBDevice + { } } diff --git a/RGB.NET.Devices.Corsair/Headset/CorsairHeadsetRGBDevice.cs b/RGB.NET.Devices.Corsair/Headset/CorsairHeadsetRGBDevice.cs index 7a39b28..92455d9 100644 --- a/RGB.NET.Devices.Corsair/Headset/CorsairHeadsetRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/Headset/CorsairHeadsetRGBDevice.cs @@ -18,16 +18,17 @@ namespace RGB.NET.Devices.Corsair /// Initializes a new instance of the class. /// /// The specific information provided by CUE for the headset - internal CorsairHeadsetRGBDevice(CorsairHeadsetRGBDeviceInfo info) - : base(info) - { } + internal CorsairHeadsetRGBDevice(CorsairHeadsetRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue) + : base(info, updateQueue) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { AddLed(LedId.Headset1, new Point(0, 0), new Size(10, 10)); AddLed(LedId.Headset2, new Point(10, 0), new Size(10, 10)); diff --git a/RGB.NET.Devices.Corsair/HeadsetStand/CorsairHeadsetStandRGBDevice.cs b/RGB.NET.Devices.Corsair/HeadsetStand/CorsairHeadsetStandRGBDevice.cs index 966fc77..ca17c0e 100644 --- a/RGB.NET.Devices.Corsair/HeadsetStand/CorsairHeadsetStandRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/HeadsetStand/CorsairHeadsetStandRGBDevice.cs @@ -23,16 +23,17 @@ namespace RGB.NET.Devices.Corsair /// Initializes a new instance of the class. /// /// The specific information provided by CUE for the headset stand - internal CorsairHeadsetStandRGBDevice(CorsairHeadsetStandRGBDeviceInfo info) - : base(info) - { } + internal CorsairHeadsetStandRGBDevice(CorsairHeadsetStandRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue) + : base(info, updateQueue) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { _CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions)); if (nativeLedPositions == null) return; diff --git a/RGB.NET.Devices.Corsair/Keyboard/CorsairKeyboardRGBDevice.cs b/RGB.NET.Devices.Corsair/Keyboard/CorsairKeyboardRGBDevice.cs index 1d950dd..268cd75 100644 --- a/RGB.NET.Devices.Corsair/Keyboard/CorsairKeyboardRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/Keyboard/CorsairKeyboardRGBDevice.cs @@ -28,16 +28,17 @@ namespace RGB.NET.Devices.Corsair /// Initializes a new instance of the class. /// /// The specific information provided by CUE for the keyboard - internal CorsairKeyboardRGBDevice(CorsairKeyboardRGBDeviceInfo info) - : base(info) - { } + internal CorsairKeyboardRGBDevice(CorsairKeyboardRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue) + : base(info, updateQueue) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { _CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions)); if (nativeLedPositions == null) return; diff --git a/RGB.NET.Devices.Corsair/Memory/CorsairMemoryRGBDevice.cs b/RGB.NET.Devices.Corsair/Memory/CorsairMemoryRGBDevice.cs index f174b8c..cdc42e7 100644 --- a/RGB.NET.Devices.Corsair/Memory/CorsairMemoryRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/Memory/CorsairMemoryRGBDevice.cs @@ -22,16 +22,17 @@ namespace RGB.NET.Devices.Corsair /// Initializes a new instance of the class. /// /// The specific information provided by CUE for the memory. - internal CorsairMemoryRGBDevice(CorsairMemoryRGBDeviceInfo info) - : base(info) - { } + internal CorsairMemoryRGBDevice(CorsairMemoryRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue) + : base(info, updateQueue) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { _CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions)); if (nativeLedPositions == null) return; diff --git a/RGB.NET.Devices.Corsair/Mouse/CorsairMouseRGBDevice.cs b/RGB.NET.Devices.Corsair/Mouse/CorsairMouseRGBDevice.cs index f9bfa42..a3d015f 100644 --- a/RGB.NET.Devices.Corsair/Mouse/CorsairMouseRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/Mouse/CorsairMouseRGBDevice.cs @@ -19,16 +19,17 @@ namespace RGB.NET.Devices.Corsair /// Initializes a new instance of the class. /// /// The specific information provided by CUE for the mouse - internal CorsairMouseRGBDevice(CorsairMouseRGBDeviceInfo info) - : base(info) - { } + internal CorsairMouseRGBDevice(CorsairMouseRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue) + : base(info, updateQueue) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { switch (DeviceInfo.PhysicalLayout) { diff --git a/RGB.NET.Devices.Corsair/Mousepad/CorsairMousepadRGBDevice.cs b/RGB.NET.Devices.Corsair/Mousepad/CorsairMousepadRGBDevice.cs index 00b526d..1f74aee 100644 --- a/RGB.NET.Devices.Corsair/Mousepad/CorsairMousepadRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/Mousepad/CorsairMousepadRGBDevice.cs @@ -23,16 +23,17 @@ namespace RGB.NET.Devices.Corsair /// Initializes a new instance of the class. /// /// The specific information provided by CUE for the mousepad - internal CorsairMousepadRGBDevice(CorsairMousepadRGBDeviceInfo info) - : base(info) - { } + internal CorsairMousepadRGBDevice(CorsairMousepadRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue) + : base(info, updateQueue) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { _CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions)); if (nativeLedPositions == null) return; diff --git a/RGB.NET.Devices.DMX/DMXDeviceProvider.cs b/RGB.NET.Devices.DMX/DMXDeviceProvider.cs index 4720e1e..0d23fd5 100644 --- a/RGB.NET.Devices.DMX/DMXDeviceProvider.cs +++ b/RGB.NET.Devices.DMX/DMXDeviceProvider.cs @@ -3,8 +3,6 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; using RGB.NET.Core; using RGB.NET.Devices.DMX.E131; @@ -14,7 +12,7 @@ namespace RGB.NET.Devices.DMX /// /// Represents a device provider responsible for DMX devices. /// - public class DMXDeviceProvider : IRGBDeviceProvider + public class DMXDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields @@ -24,22 +22,11 @@ namespace RGB.NET.Devices.DMX /// public static DMXDeviceProvider Instance => _instance ?? new DMXDeviceProvider(); - /// - public bool IsInitialized { get; private set; } - - /// - public IEnumerable Devices { get; private set; } = Enumerable.Empty(); - /// /// Gets a list of all defined device-definitions. /// public List DeviceDefinitions { get; } = new(); - /// - /// The used to trigger the updates for dmx devices. - /// - public DeviceUpdateTrigger UpdateTrigger { get; } - #endregion #region Constructors @@ -52,8 +39,6 @@ namespace RGB.NET.Devices.DMX { if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(DMXDeviceProvider)}"); _instance = this; - - UpdateTrigger = new DeviceUpdateTrigger(); } #endregion @@ -66,58 +51,27 @@ namespace RGB.NET.Devices.DMX /// The to add. public void AddDeviceDefinition(IDMXDeviceDefinition deviceDefinition) => DeviceDefinitions.Add(deviceDefinition); - /// - public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false) + protected override void InitializeSDK() { } + + protected override IEnumerable LoadDevices() { - IsInitialized = false; - - try + foreach (IDMXDeviceDefinition dmxDeviceDefinition in DeviceDefinitions) { - UpdateTrigger.Stop(); - - IList devices = new List(); - - foreach (IDMXDeviceDefinition dmxDeviceDefinition in DeviceDefinitions) + IRGBDevice? device = null; + try { - try - { - if (dmxDeviceDefinition is E131DMXDeviceDefinition e131DMXDeviceDefinition) - { - if (e131DMXDeviceDefinition.Leds.Count > 0) - { - E131Device device = new(new E131DeviceInfo(e131DMXDeviceDefinition), e131DMXDeviceDefinition.Leds); - device.Initialize(UpdateTrigger); - devices.Add(device); - } - } - } - catch { if (throwExceptions) throw; } + if (dmxDeviceDefinition is E131DMXDeviceDefinition e131DMXDeviceDefinition) + if (e131DMXDeviceDefinition.Leds.Count > 0) + device = new E131Device(new E131DeviceInfo(e131DMXDeviceDefinition), e131DMXDeviceDefinition.Leds, GetUpdateTrigger(0)); + } + catch (Exception ex) + { + Throw(ex); } - UpdateTrigger.Start(); - - Devices = new ReadOnlyCollection(devices); - IsInitialized = true; + if (device != null) + yield return device; } - catch - { - if (throwExceptions) throw; - return false; - } - - return true; - } - - /// - public void Dispose() - { - try { UpdateTrigger.Dispose(); } - catch { /* at least we tried */ } - - foreach (IRGBDevice device in Devices) - try { device.Dispose(); } - catch { /* at least we tried */ } - Devices = Enumerable.Empty(); } #endregion diff --git a/RGB.NET.Devices.DMX/E131/E131Device.cs b/RGB.NET.Devices.DMX/E131/E131Device.cs index 9b18d01..0c170c6 100644 --- a/RGB.NET.Devices.DMX/E131/E131Device.cs +++ b/RGB.NET.Devices.DMX/E131/E131Device.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using RGB.NET.Core; namespace RGB.NET.Devices.DMX.E131 @@ -12,55 +11,39 @@ namespace RGB.NET.Devices.DMX.E131 { #region Properties & Fields - /// - public override E131DeviceInfo DeviceInfo { get; } - private readonly Dictionary getValueFunc)>> _ledMappings; - private E131UpdateQueue? _updateQueue; - #endregion #region Constructors /// - internal E131Device(E131DeviceInfo deviceInfo, Dictionary getValueFunc)>> ledMappings) + internal E131Device(E131DeviceInfo deviceInfo, Dictionary getValueFunc)>> ledMappings, IDeviceUpdateTrigger updateTrigger) + : base(deviceInfo, new E131UpdateQueue(updateTrigger, deviceInfo.Hostname, deviceInfo.Port)) { - this.DeviceInfo = deviceInfo; this._ledMappings = ledMappings; + + InitializeLayout(); + + E131UpdateQueue updateQueue = (E131UpdateQueue)UpdateQueue; + updateQueue.DataPacket.SetCID(DeviceInfo.CID); + updateQueue.DataPacket.SetUniverse(DeviceInfo.Universe); } #endregion #region Methods - internal void Initialize(IDeviceUpdateTrigger updateTrigger) + private void InitializeLayout() { int count = 0; foreach (LedId id in _ledMappings.Keys) AddLed(id, new Point((count++) * 10, 0), new Size(10, 10)); - - _updateQueue = new E131UpdateQueue(updateTrigger, DeviceInfo.Hostname, DeviceInfo.Port); - _updateQueue.DataPacket.SetCID(DeviceInfo.CID); - _updateQueue.DataPacket.SetUniverse(DeviceInfo.Universe); } /// protected override object GetLedCustomData(LedId ledId) => new LedChannelMapping(_ledMappings[ledId]); - - /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => _updateQueue?.SetData(GetUpdateData(ledsToUpdate)); - - /// - public override void Dispose() - { - try { _updateQueue?.Dispose(); } - catch { /* at least we tried */ } - - base.Dispose(); - } - #endregion } } diff --git a/RGB.NET.Devices.Debug/DebugDeviceProvider.cs b/RGB.NET.Devices.Debug/DebugDeviceProvider.cs index 66ec439..5e9ab8b 100644 --- a/RGB.NET.Devices.Debug/DebugDeviceProvider.cs +++ b/RGB.NET.Devices.Debug/DebugDeviceProvider.cs @@ -3,8 +3,6 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; using RGB.NET.Core; using RGB.NET.Layout; @@ -14,7 +12,7 @@ namespace RGB.NET.Devices.Debug /// /// Represents a device provider responsible for debug devices. /// - public class DebugDeviceProvider : IRGBDeviceProvider + public class DebugDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields @@ -24,13 +22,7 @@ namespace RGB.NET.Devices.Debug /// public static DebugDeviceProvider Instance => _instance ?? new DebugDeviceProvider(); - /// - public bool IsInitialized { get; private set; } - - /// - public IEnumerable Devices { get; private set; } = Enumerable.Empty(); - - private List<(IDeviceLayout layout, string imageLayout, Action>? updateLedsAction)> _fakeDeviceDefinitions = new(); + private List<(IDeviceLayout layout, Action>? updateLedsAction)> _fakeDeviceDefinitions = new(); #endregion @@ -54,48 +46,28 @@ namespace RGB.NET.Devices.Debug /// Adds a new fake device definition. /// /// The path of the layout file to be used. - /// The image-layout to load. /// A action emulating led-updates. - public void AddFakeDeviceDefinition(IDeviceLayout layout, string imageLayout, Action>? updateLedsAction = null) - => _fakeDeviceDefinitions.Add((layout, imageLayout, updateLedsAction)); + public void AddFakeDeviceDefinition(IDeviceLayout layout, Action>? updateLedsAction = null) + => _fakeDeviceDefinitions.Add((layout, updateLedsAction)); /// /// Removes all previously added fake device definitions. /// public void ClearFakeDeviceDefinitions() => _fakeDeviceDefinitions.Clear(); - /// - public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.Unknown, bool throwExceptions = false) + protected override void InitializeSDK() { } + + protected override IEnumerable LoadDevices() { - IsInitialized = false; - try - { - List devices = new(); - foreach ((IDeviceLayout layout, string imageLayout, Action>? updateLedsAction) in _fakeDeviceDefinitions) - { - DebugRGBDevice device = new(layout, updateLedsAction); - devices.Add(device); - } - - Devices = new ReadOnlyCollection(devices); - IsInitialized = true; - - return true; - } - catch - { - if (throwExceptions) throw; - return false; - } + foreach ((IDeviceLayout layout, Action>? updateLedsAction) in _fakeDeviceDefinitions) + yield return new DebugRGBDevice(layout, updateLedsAction); } /// - public void ResetDevices() - { } - - /// - public void Dispose() + public override void Dispose() { + base.Dispose(); + _fakeDeviceDefinitions.Clear(); } diff --git a/RGB.NET.Devices.Debug/DebugDeviceUpdateQueue.cs b/RGB.NET.Devices.Debug/DebugDeviceUpdateQueue.cs new file mode 100644 index 0000000..7fe823d --- /dev/null +++ b/RGB.NET.Devices.Debug/DebugDeviceUpdateQueue.cs @@ -0,0 +1,22 @@ +using System; +using RGB.NET.Core; + +namespace RGB.NET.Devices.Debug +{ + internal class DebugDeviceUpdateQueue : UpdateQueue + { + #region Constructors + + public DebugDeviceUpdateQueue() + : base(new DeviceUpdateTrigger()) + { } + + #endregion + + #region Methods + + protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { } + + #endregion + } +} diff --git a/RGB.NET.Devices.Debug/DebugRGBDevice.cs b/RGB.NET.Devices.Debug/DebugRGBDevice.cs index 052e870..fa11042 100644 --- a/RGB.NET.Devices.Debug/DebugRGBDevice.cs +++ b/RGB.NET.Devices.Debug/DebugRGBDevice.cs @@ -13,9 +13,6 @@ namespace RGB.NET.Devices.Debug { #region Properties & Fields - /// - public override DebugRGBDeviceInfo DeviceInfo { get; } - public IDeviceLayout Layout { get; } private Action>? _updateLedsAction; @@ -27,12 +24,11 @@ namespace RGB.NET.Devices.Debug /// Internal constructor of . /// internal DebugRGBDevice(IDeviceLayout layout, Action>? updateLedsAction = null) + : base(new DebugRGBDeviceInfo(layout.Type, layout.Vendor ?? "RGB.NET", layout.Model ?? "Debug", layout.CustomData), new DebugDeviceUpdateQueue()) { this.Layout = layout; this._updateLedsAction = updateLedsAction; - DeviceInfo = new DebugRGBDeviceInfo(layout.Type, layout.Vendor ?? "RGB.NET", layout.Model ?? "Debug", layout.CustomData); - Layout.ApplyTo(this, true); } diff --git a/RGB.NET.Devices.Logitech/Generic/ILogitechRGBDevice.cs b/RGB.NET.Devices.Logitech/Generic/ILogitechRGBDevice.cs index 4c8e260..7c3b2be 100644 --- a/RGB.NET.Devices.Logitech/Generic/ILogitechRGBDevice.cs +++ b/RGB.NET.Devices.Logitech/Generic/ILogitechRGBDevice.cs @@ -5,8 +5,6 @@ namespace RGB.NET.Devices.Logitech /// /// Represents a logitech RGB-device. /// - internal interface ILogitechRGBDevice : IRGBDevice - { - void Initialize(UpdateQueue updateQueue); - } + public interface ILogitechRGBDevice : IRGBDevice + { } } diff --git a/RGB.NET.Devices.Logitech/Generic/LogitechRGBDevice.cs b/RGB.NET.Devices.Logitech/Generic/LogitechRGBDevice.cs index eacb6b6..f217795 100644 --- a/RGB.NET.Devices.Logitech/Generic/LogitechRGBDevice.cs +++ b/RGB.NET.Devices.Logitech/Generic/LogitechRGBDevice.cs @@ -3,60 +3,21 @@ namespace RGB.NET.Devices.Logitech { /// - /// /// /// Represents a generic Logitech-device. (keyboard, mouse, headset, mousepad). /// public abstract class LogitechRGBDevice : AbstractRGBDevice, ILogitechRGBDevice where TDeviceInfo : LogitechRGBDeviceInfo { - #region Properties & Fields - - /// - /// - /// Gets information about the . - /// - public override TDeviceInfo DeviceInfo { get; } - - /// - /// Gets or sets the update queue performing updates for this device. - /// - // ReSharper disable once MemberCanBePrivate.Global - protected UpdateQueue? UpdateQueue { get; set; } - - #endregion - #region Constructors /// /// Initializes a new instance of the class. /// /// The generic information provided by Logitech for the device. - protected LogitechRGBDevice(TDeviceInfo info) - { - this.DeviceInfo = info; - } - - #endregion - - #region Methods - - /// - /// Initializes the device. - /// - public virtual void Initialize(UpdateQueue updateQueue) - { - UpdateQueue = updateQueue; - } - - /// - public override void Dispose() - { - try { UpdateQueue?.Dispose(); } - catch { /* at least we tried */ } - - base.Dispose(); - } + protected LogitechRGBDevice(TDeviceInfo info, IUpdateQueue updateQueue) + : base(info, updateQueue) + { } #endregion } diff --git a/RGB.NET.Devices.Logitech/LogitechDeviceProvider.cs b/RGB.NET.Devices.Logitech/LogitechDeviceProvider.cs index 8e57da6..aa75343 100644 --- a/RGB.NET.Devices.Logitech/LogitechDeviceProvider.cs +++ b/RGB.NET.Devices.Logitech/LogitechDeviceProvider.cs @@ -3,8 +3,6 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; using RGB.NET.Core; using RGB.NET.Devices.Logitech.HID; using RGB.NET.Devices.Logitech.Native; @@ -15,7 +13,7 @@ namespace RGB.NET.Devices.Logitech /// /// Represents a device provider responsible for logitech devices. /// - public class LogitechDeviceProvider : IRGBDeviceProvider + public class LogitechDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields @@ -37,21 +35,8 @@ namespace RGB.NET.Devices.Logitech /// public static List PossibleX64NativePaths { get; } = new() { "x64/LogitechLedEnginesWrapper.dll" }; - /// - public bool IsInitialized { get; private set; } - - /// - public IEnumerable Devices { get; private set; } = Enumerable.Empty(); - - /// - /// The used to trigger the updates for logitech devices. - /// - public DeviceUpdateTrigger UpdateTrigger { get; } - - // ReSharper disable once CollectionNeverQueried.Local - for now this is just to make sure they're never collected - private readonly Dictionary _zoneUpdateQueues = new(); - private LogitechPerDeviceUpdateQueue _perDeviceUpdateQueue; - private LogitechPerKeyUpdateQueue _perKeyUpdateQueue; + private LogitechPerDeviceUpdateQueue? _perDeviceUpdateQueue; + private LogitechPerKeyUpdateQueue? _perKeyUpdateQueue; #endregion @@ -65,116 +50,54 @@ namespace RGB.NET.Devices.Logitech { if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(LogitechDeviceProvider)}"); _instance = this; - - UpdateTrigger = new DeviceUpdateTrigger(); - _perDeviceUpdateQueue = new LogitechPerDeviceUpdateQueue(UpdateTrigger); - _perKeyUpdateQueue = new LogitechPerKeyUpdateQueue(UpdateTrigger); } #endregion #region Methods - /// - public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false) + protected override void InitializeSDK() { - try + _perDeviceUpdateQueue = new LogitechPerDeviceUpdateQueue(GetUpdateTrigger()); + _perKeyUpdateQueue = new LogitechPerKeyUpdateQueue(GetUpdateTrigger()); + + _LogitechGSDK.Reload(); + if (!_LogitechGSDK.LogiLedInit()) Throw(new RGBDeviceException("Failed to initialize Logitech-SDK.")); + + _LogitechGSDK.LogiLedSaveCurrentLighting(); + } + + //TODO DarthAffe 04.03.2021: Rework device selection and configuration for HID-based providers + protected override IEnumerable LoadDevices() + { + DeviceChecker.LoadDeviceList(); + + if (DeviceChecker.IsPerKeyDeviceConnected && (_perKeyUpdateQueue != null)) { - if (IsInitialized) - _LogitechGSDK.LogiLedRestoreLighting(); - } - catch { /* At least we tried ... */ } - - IsInitialized = false; - - try - { - UpdateTrigger.Stop(); - - _LogitechGSDK.Reload(); - if (!_LogitechGSDK.LogiLedInit()) return false; - - _LogitechGSDK.LogiLedSaveCurrentLighting(); - - IList devices = new List(); - DeviceChecker.LoadDeviceList(); - - try - { - if (DeviceChecker.IsPerKeyDeviceConnected) - { - (string model, RGBDeviceType deviceType, int _, int _) = DeviceChecker.PerKeyDeviceData; - if (loadFilter.HasFlag(deviceType)) //TODO DarthAffe 07.12.2017: Check if it's worth to try another device if the one returned doesn't match the filter - { - ILogitechRGBDevice device = new LogitechPerKeyRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.PerKeyRGB, 0)); - device.Initialize(_perKeyUpdateQueue); - devices.Add(device); - } - } - } - catch { if (throwExceptions) throw; } - - try - { - if (DeviceChecker.IsPerDeviceDeviceConnected) - { - (string model, RGBDeviceType deviceType, int _, int _) = DeviceChecker.PerDeviceDeviceData; - if (loadFilter.HasFlag(deviceType)) //TODO DarthAffe 07.12.2017: Check if it's worth to try another device if the one returned doesn't match the filter - { - ILogitechRGBDevice device = new LogitechPerDeviceRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.DeviceRGB, 0)); - device.Initialize(_perDeviceUpdateQueue); - devices.Add(device); - } - } - } - catch { if (throwExceptions) throw; } - - try - { - if (DeviceChecker.IsZoneDeviceConnected) - { - foreach ((string model, RGBDeviceType deviceType, int _, int zones) in DeviceChecker.ZoneDeviceData) - try - { - if (loadFilter.HasFlag(deviceType)) - { - LogitechZoneUpdateQueue updateQueue = new(UpdateTrigger, deviceType); - ILogitechRGBDevice device = new LogitechZoneRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.DeviceRGB, zones)); - device.Initialize(updateQueue); - devices.Add(device); - _zoneUpdateQueues.Add(deviceType, updateQueue); - } - } - catch { if (throwExceptions) throw; } - } - } - catch { if (throwExceptions) throw; } - - UpdateTrigger.Start(); - - Devices = new ReadOnlyCollection(devices); - IsInitialized = true; - } - catch - { - if (throwExceptions) - throw; - return false; + (string model, RGBDeviceType deviceType, int _, int _) = DeviceChecker.PerKeyDeviceData; + yield return new LogitechPerKeyRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.PerKeyRGB, 0), _perKeyUpdateQueue); } - return true; + if (DeviceChecker.IsPerDeviceDeviceConnected && (_perDeviceUpdateQueue != null)) + { + (string model, RGBDeviceType deviceType, int _, int _) = DeviceChecker.PerDeviceDeviceData; + yield return new LogitechPerDeviceRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.DeviceRGB, 0), _perDeviceUpdateQueue); + } + + if (DeviceChecker.IsZoneDeviceConnected) + { + foreach ((string model, RGBDeviceType deviceType, int _, int zones) in DeviceChecker.ZoneDeviceData) + { + LogitechZoneUpdateQueue updateQueue = new(GetUpdateTrigger(), deviceType); + yield return new LogitechZoneRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.DeviceRGB, zones), updateQueue); + } + } } /// - public void Dispose() + public override void Dispose() { - try { UpdateTrigger.Dispose(); } - catch { /* at least we tried */ } - - foreach (IRGBDevice device in Devices) - try { device.Dispose(); } - catch { /* at least we tried */ } - Devices = Enumerable.Empty(); + base.Dispose(); try { _LogitechGSDK.LogiLedRestoreLighting(); } catch { /* at least we tried */ } diff --git a/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceRGBDevice.cs b/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceRGBDevice.cs index 8855e6b..b65ba13 100644 --- a/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceRGBDevice.cs +++ b/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceRGBDevice.cs @@ -17,26 +17,25 @@ namespace RGB.NET.Devices.Logitech /// Initializes a new instance of the class. /// /// The specific information provided by logitech for the per-device-lightable device - internal LogitechPerDeviceRGBDevice(LogitechRGBDeviceInfo info) - : base(info) - { } + internal LogitechPerDeviceRGBDevice(LogitechRGBDeviceInfo info, IUpdateQueue updateQueue) + : base(info, updateQueue) + { + InitializeLayout(); + } #endregion #region Methods - /// - public override void Initialize(UpdateQueue updateQueue) + private void InitializeLayout() { - base.Initialize(updateQueue); - AddLed(LedId.Custom1, new Point(0, 0), new Size(10, 10)); } /// protected override object GetLedCustomData(LedId ledId) => (ledId, LogitechLedId.DEVICE); /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate.Take(1))); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate.Take(1))); #endregion } diff --git a/RGB.NET.Devices.Logitech/PerKey/LogitechPerKeyRGBDevice.cs b/RGB.NET.Devices.Logitech/PerKey/LogitechPerKeyRGBDevice.cs index 1fbec2d..29660c3 100644 --- a/RGB.NET.Devices.Logitech/PerKey/LogitechPerKeyRGBDevice.cs +++ b/RGB.NET.Devices.Logitech/PerKey/LogitechPerKeyRGBDevice.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using RGB.NET.Core; namespace RGB.NET.Devices.Logitech @@ -17,8 +16,8 @@ namespace RGB.NET.Devices.Logitech /// Initializes a new instance of the class. /// /// The specific information provided by logitech for the per-key-lightable device - internal LogitechPerKeyRGBDevice(LogitechRGBDeviceInfo info) - : base(info) + internal LogitechPerKeyRGBDevice(LogitechRGBDeviceInfo info, IUpdateQueue updateQueue) + : base(info, updateQueue) { } #endregion @@ -29,7 +28,7 @@ namespace RGB.NET.Devices.Logitech protected override object GetLedCustomData(LedId ledId) => (ledId, PerKeyIdMapping.DEFAULT.TryGetValue(ledId, out LogitechLedId logitechLedId) ? logitechLedId : LogitechLedId.Invalid); /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate)); #endregion } diff --git a/RGB.NET.Devices.Logitech/Zone/LogitechZoneRGBDevice.cs b/RGB.NET.Devices.Logitech/Zone/LogitechZoneRGBDevice.cs index 5e7b8c9..120dbf1 100644 --- a/RGB.NET.Devices.Logitech/Zone/LogitechZoneRGBDevice.cs +++ b/RGB.NET.Devices.Logitech/Zone/LogitechZoneRGBDevice.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using RGB.NET.Core; namespace RGB.NET.Devices.Logitech @@ -36,21 +35,20 @@ namespace RGB.NET.Devices.Logitech /// Initializes a new instance of the class. /// /// The specific information provided by logitech for the zone-lightable device - internal LogitechZoneRGBDevice(LogitechRGBDeviceInfo info) - : base(info) + internal LogitechZoneRGBDevice(LogitechRGBDeviceInfo info, IUpdateQueue updateQueue) + : base(info, updateQueue) { _baseLedId = BASE_LED_MAPPING.TryGetValue(info.DeviceType, out LedId id) ? id : LedId.Custom1; + + InitializeLayout(); } #endregion #region Methods - /// - public override void Initialize(UpdateQueue updateQueue) + private void InitializeLayout() { - base.Initialize(updateQueue); - for (int i = 0; i < DeviceInfo.Zones; i++) AddLed(_baseLedId + i, new Point(i * 10, 0), new Size(10, 10)); } @@ -59,7 +57,7 @@ namespace RGB.NET.Devices.Logitech protected override object? GetLedCustomData(LedId ledId) => (int)(ledId - _baseLedId); /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate)); #endregion } diff --git a/RGB.NET.Devices.Msi/Generic/IMsiRGBDevice.cs b/RGB.NET.Devices.Msi/Generic/IMsiRGBDevice.cs index cd09af0..c30d4a2 100644 --- a/RGB.NET.Devices.Msi/Generic/IMsiRGBDevice.cs +++ b/RGB.NET.Devices.Msi/Generic/IMsiRGBDevice.cs @@ -5,8 +5,6 @@ namespace RGB.NET.Devices.Msi /// /// Represents a MSI RGB-device. /// - internal interface IMsiRGBDevice : IRGBDevice - { - void Initialize(MsiDeviceUpdateQueue updateQueue, int ledCount); - } + public interface IMsiRGBDevice : IRGBDevice + { } } diff --git a/RGB.NET.Devices.Msi/Generic/MsiRGBDevice.cs b/RGB.NET.Devices.Msi/Generic/MsiRGBDevice.cs index 44b52eb..888155b 100644 --- a/RGB.NET.Devices.Msi/Generic/MsiRGBDevice.cs +++ b/RGB.NET.Devices.Msi/Generic/MsiRGBDevice.cs @@ -1,75 +1,23 @@ -using System.Collections.Generic; -using System.Linq; -using RGB.NET.Core; +using RGB.NET.Core; namespace RGB.NET.Devices.Msi { /// - /// /// /// Represents a generic MSI-device. (keyboard, mouse, headset, mousepad). /// public abstract class MsiRGBDevice : AbstractRGBDevice, IMsiRGBDevice where TDeviceInfo : MsiRGBDeviceInfo { - #region Properties & Fields - - /// - /// - /// Gets information about the . - /// - public override TDeviceInfo DeviceInfo { get; } - - /// - /// Gets or sets the update queue performing updates for this device. - /// - // ReSharper disable once MemberCanBePrivate.Global - protected MsiDeviceUpdateQueue? DeviceUpdateQueue { get; set; } - - #endregion - #region Constructors /// /// Initializes a new instance of the class. /// /// The generic information provided by MSI for the device. - protected MsiRGBDevice(TDeviceInfo info) - { - this.DeviceInfo = info; - } - - #endregion - - #region Methods - - /// - /// Initializes the device. - /// - public void Initialize(MsiDeviceUpdateQueue updateQueue, int ledCount) - { - DeviceUpdateQueue = updateQueue; - - InitializeLayout(ledCount); - } - - /// - /// Initializes the and of the device. - /// - protected abstract void InitializeLayout(int ledCount); - - /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) - => DeviceUpdateQueue?.SetData(GetUpdateData(ledsToUpdate.Where(x => (x.Color.A > 0) && (x.CustomData is int)))); - - /// - public override void Dispose() - { - try { DeviceUpdateQueue?.Dispose(); } - catch { /* at least we tried */ } - - base.Dispose(); - } + protected MsiRGBDevice(TDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, new MsiDeviceUpdateQueue(updateTrigger, info.MsiDeviceType)) + { } #endregion } diff --git a/RGB.NET.Devices.Msi/GraphicsCard/MsiGraphicsCardRGBDevice.cs b/RGB.NET.Devices.Msi/GraphicsCard/MsiGraphicsCardRGBDevice.cs index 8a41f90..629212c 100644 --- a/RGB.NET.Devices.Msi/GraphicsCard/MsiGraphicsCardRGBDevice.cs +++ b/RGB.NET.Devices.Msi/GraphicsCard/MsiGraphicsCardRGBDevice.cs @@ -16,16 +16,17 @@ namespace RGB.NET.Devices.Msi /// Initializes a new instance of the class. /// /// The specific information provided by MSI for graphics cards. - internal MsiGraphicsCardRGBDevice(MsiRGBDeviceInfo info) - : base(info) - { } + internal MsiGraphicsCardRGBDevice(MsiRGBDeviceInfo info, int ledCount, IDeviceUpdateTrigger updateTrigger) + : base(info, updateTrigger) + { + InitializeLayout(ledCount); + } #endregion #region Methods - /// - protected override void InitializeLayout(int ledCount) + private void InitializeLayout(int ledCount) { for (int i = 0; i < ledCount; i++) { diff --git a/RGB.NET.Devices.Msi/Mainboard/MsiMainboardRGBDevice.cs b/RGB.NET.Devices.Msi/Mainboard/MsiMainboardRGBDevice.cs index 5cf8b00..01f25ad 100644 --- a/RGB.NET.Devices.Msi/Mainboard/MsiMainboardRGBDevice.cs +++ b/RGB.NET.Devices.Msi/Mainboard/MsiMainboardRGBDevice.cs @@ -16,16 +16,17 @@ namespace RGB.NET.Devices.Msi /// Initializes a new instance of the class. /// /// The specific information provided by MSI for the mainboard. - internal MsiMainboardRGBDevice(MsiRGBDeviceInfo info) - : base(info) - { } + internal MsiMainboardRGBDevice(MsiRGBDeviceInfo info, int ledCount, IDeviceUpdateTrigger updateTrigger) + : base(info, updateTrigger) + { + InitializeLayout(ledCount); + } #endregion #region Methods - /// - protected override void InitializeLayout(int ledCount) + private void InitializeLayout(int ledCount) { for (int i = 0; i < ledCount; i++) { diff --git a/RGB.NET.Devices.Msi/Mouse/MsiMouseRGBDevice.cs b/RGB.NET.Devices.Msi/Mouse/MsiMouseRGBDevice.cs index dd4b702..79ad777 100644 --- a/RGB.NET.Devices.Msi/Mouse/MsiMouseRGBDevice.cs +++ b/RGB.NET.Devices.Msi/Mouse/MsiMouseRGBDevice.cs @@ -16,16 +16,17 @@ namespace RGB.NET.Devices.Msi /// Initializes a new instance of the class. ///
/// The specific information provided by MSI for the mouse. - internal MsiMouseRGBDevice(MsiRGBDeviceInfo info) - : base(info) - { } + internal MsiMouseRGBDevice(MsiRGBDeviceInfo info, int ledCount, IDeviceUpdateTrigger updateTrigger) + : base(info, updateTrigger) + { + InitializeLayout(ledCount); + } #endregion #region Methods - /// - protected override void InitializeLayout(int ledCount) + private void InitializeLayout(int ledCount) { for (int i = 0; i < ledCount; i++) { diff --git a/RGB.NET.Devices.Msi/MsiDeviceProvider.cs b/RGB.NET.Devices.Msi/MsiDeviceProvider.cs index a5b718f..00abd7b 100644 --- a/RGB.NET.Devices.Msi/MsiDeviceProvider.cs +++ b/RGB.NET.Devices.Msi/MsiDeviceProvider.cs @@ -3,8 +3,6 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; using RGB.NET.Core; using RGB.NET.Devices.Msi.Exceptions; using RGB.NET.Devices.Msi.Native; @@ -15,7 +13,7 @@ namespace RGB.NET.Devices.Msi /// /// Represents a device provider responsible for MSI devices. /// - public class MsiDeviceProvider : IRGBDeviceProvider + public class MsiDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields @@ -37,20 +35,6 @@ namespace RGB.NET.Devices.Msi ///
public static List PossibleX64NativePaths { get; } = new() { "x64/MysticLight_SDK.dll" }; - /// - /// - /// Indicates if the SDK is initialized and ready to use. - /// - public bool IsInitialized { get; private set; } - - /// - public IEnumerable Devices { get; private set; } = Enumerable.Empty(); - - /// - /// The used to trigger the updates for corsair devices. - /// - public DeviceUpdateTrigger UpdateTrigger { get; } - #endregion #region Constructors @@ -63,102 +47,58 @@ namespace RGB.NET.Devices.Msi { if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(MsiDeviceProvider)}"); _instance = this; - - UpdateTrigger = new DeviceUpdateTrigger(); } #endregion #region Methods - /// - public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false) + protected override void InitializeSDK() { - IsInitialized = false; + _MsiSDK.Reload(); - try - { - UpdateTrigger.Stop(); - - _MsiSDK.Reload(); - - IList devices = new List(); - - int errorCode; - if ((errorCode = _MsiSDK.Initialize()) != 0) - ThrowMsiError(errorCode); - - if ((errorCode = _MsiSDK.GetDeviceInfo(out string[] deviceTypes, out int[] ledCounts)) != 0) - ThrowMsiError(errorCode); - - for (int i = 0; i < deviceTypes.Length; i++) - { - try - { - string deviceType = deviceTypes[i]; - int ledCount = ledCounts[i]; - - //Hex3l: MSI_MB provide access to the motherboard "leds" where a led must be intended as a led header (JRGB, JRAINBOW etc..) (Tested on MSI X570 Unify) - if (deviceType.Equals("MSI_MB")) - { - MsiDeviceUpdateQueue updateQueue = new(UpdateTrigger, deviceType); - IMsiRGBDevice motherboard = new MsiMainboardRGBDevice(new MsiRGBDeviceInfo(RGBDeviceType.Mainboard, deviceType, "MSI", "Motherboard")); - motherboard.Initialize(updateQueue, ledCount); - devices.Add(motherboard); - } - else if (deviceType.Equals("MSI_VGA")) - { - //Hex3l: Every led under MSI_VGA should be a different graphics card. Handling all the cards together seems a good way to avoid overlapping of leds - //Hex3l: The led name is the name of the card (e.g. NVIDIA GeForce RTX 2080 Ti) we could provide it in device info. - - MsiDeviceUpdateQueue updateQueue = new(UpdateTrigger, deviceType); - IMsiRGBDevice graphicscard = new MsiGraphicsCardRGBDevice(new MsiRGBDeviceInfo(RGBDeviceType.GraphicsCard, deviceType, "MSI", "GraphicsCard")); - graphicscard.Initialize(updateQueue, ledCount); - devices.Add(graphicscard); - } - else if (deviceType.Equals("MSI_MOUSE")) - { - //Hex3l: Every led under MSI_MOUSE should be a different mouse. Handling all the mouses together seems a good way to avoid overlapping of leds - //Hex3l: The led name is the name of the mouse (e.g. msi CLUTCH GM11) we could provide it in device info. - - MsiDeviceUpdateQueue updateQueue = new(UpdateTrigger, deviceType); - IMsiRGBDevice mouses = new MsiMouseRGBDevice(new MsiRGBDeviceInfo(RGBDeviceType.Mouse, deviceType, "MSI", "Mouse")); - mouses.Initialize(updateQueue, ledCount); - devices.Add(mouses); - } - - //TODO DarthAffe 22.02.2020: Add other devices - } - catch { if (throwExceptions) throw; } - } - - UpdateTrigger.Start(); - - Devices = new ReadOnlyCollection(devices); - IsInitialized = true; - } - catch - { - if (throwExceptions) - throw; - return false; - } - - return true; + int errorCode; + if ((errorCode = _MsiSDK.Initialize()) != 0) + ThrowMsiError(errorCode); } - private void ThrowMsiError(int errorCode) => throw new MysticLightException(errorCode, _MsiSDK.GetErrorMessage(errorCode)); + protected override IEnumerable LoadDevices() + { + int errorCode; + if ((errorCode = _MsiSDK.GetDeviceInfo(out string[] deviceTypes, out int[] ledCounts)) != 0) + ThrowMsiError(errorCode); + + for (int i = 0; i < deviceTypes.Length; i++) + { + string deviceType = deviceTypes[i]; + int ledCount = ledCounts[i]; + + if (deviceType.Equals("MSI_MB")) + { + //Hex3l: MSI_MB provide access to the motherboard "leds" where a led must be intended as a led header (JRGB, JRAINBOW etc..) (Tested on MSI X570 Unify) + yield return new MsiMainboardRGBDevice(new MsiRGBDeviceInfo(RGBDeviceType.Mainboard, deviceType, "MSI", "Motherboard"), ledCount, GetUpdateTrigger()); + } + else if (deviceType.Equals("MSI_VGA")) + { + //Hex3l: Every led under MSI_VGA should be a different graphics card. Handling all the cards together seems a good way to avoid overlapping of leds + //Hex3l: The led name is the name of the card (e.g. NVIDIA GeForce RTX 2080 Ti) we could provide it in device info. + yield return new MsiGraphicsCardRGBDevice(new MsiRGBDeviceInfo(RGBDeviceType.GraphicsCard, deviceType, "MSI", "GraphicsCard"), ledCount, GetUpdateTrigger()); + } + else if (deviceType.Equals("MSI_MOUSE")) + { + //Hex3l: Every led under MSI_MOUSE should be a different mouse. Handling all the mouses together seems a good way to avoid overlapping of leds + //Hex3l: The led name is the name of the mouse (e.g. msi CLUTCH GM11) we could provide it in device info. + yield return new MsiMouseRGBDevice(new MsiRGBDeviceInfo(RGBDeviceType.Mouse, deviceType, "MSI", "Mouse"), ledCount, GetUpdateTrigger()); + } + } + } + + private void ThrowMsiError(int errorCode) => Throw(new MysticLightException(errorCode, _MsiSDK.GetErrorMessage(errorCode))); /// - public void Dispose() + public override void Dispose() { - try { UpdateTrigger.Dispose(); } - catch { /* at least we tried */ } - - foreach (IRGBDevice device in Devices) - try { device.Dispose(); } - catch { /* at least we tried */ } - Devices = Enumerable.Empty(); + base.Dispose(); try { _MsiSDK.UnloadMsiSDK(); } catch { /* at least we tried */ } diff --git a/RGB.NET.Devices.Novation/Generic/INovationRGBDevice.cs b/RGB.NET.Devices.Novation/Generic/INovationRGBDevice.cs index 544df33..d717599 100644 --- a/RGB.NET.Devices.Novation/Generic/INovationRGBDevice.cs +++ b/RGB.NET.Devices.Novation/Generic/INovationRGBDevice.cs @@ -5,8 +5,6 @@ namespace RGB.NET.Devices.Novation /// /// Represents a novation RGB-device. /// - internal interface INovationRGBDevice : IRGBDevice - { - void Initialize(IDeviceUpdateTrigger updateTrigger); - } + public interface INovationRGBDevice : IRGBDevice + { } } diff --git a/RGB.NET.Devices.Novation/Generic/NovationRGBDevice.cs b/RGB.NET.Devices.Novation/Generic/NovationRGBDevice.cs index d6669ce..ffa5d9c 100644 --- a/RGB.NET.Devices.Novation/Generic/NovationRGBDevice.cs +++ b/RGB.NET.Devices.Novation/Generic/NovationRGBDevice.cs @@ -1,76 +1,45 @@ using System; using System.Collections.Generic; -using System.Linq; using RGB.NET.Core; namespace RGB.NET.Devices.Novation { /// - /// /// /// Represents a generic Novation-device. (launchpad). /// public abstract class NovationRGBDevice : AbstractRGBDevice, INovationRGBDevice where TDeviceInfo : NovationRGBDeviceInfo { - #region Properties & Fields - - /// - /// - /// Gets information about the . - /// - public override TDeviceInfo DeviceInfo { get; } - - /// - /// The used to update this . - /// - // ReSharper disable once MemberCanBePrivate.Global - protected MidiUpdateQueue? UpdateQueue { get; set; } - - #endregion - #region Constructors /// /// Initializes a new instance of the class. /// /// The generic information provided by Novation for the device. - protected NovationRGBDevice(TDeviceInfo info) - { - this.DeviceInfo = info; - } + protected NovationRGBDevice(TDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, GetUpdateQueue(updateTrigger, info)) + { } #endregion #region Methods - /// - /// Initializes the device. - /// - public void Initialize(IDeviceUpdateTrigger updateTrigger) - { - InitializeLayout(); - - UpdateQueue = DeviceInfo.ColorCapabilities switch + private static UpdateQueue GetUpdateQueue(IDeviceUpdateTrigger updateTrigger, TDeviceInfo info) => + info.ColorCapabilities switch { - NovationColorCapabilities.LimitedRG => new LimitedColorUpdateQueue(updateTrigger, DeviceInfo.DeviceId), - NovationColorCapabilities.RGB => new RGBColorUpdateQueue(updateTrigger, DeviceInfo.DeviceId), + NovationColorCapabilities.LimitedRG => new LimitedColorUpdateQueue(updateTrigger, info.DeviceId), + NovationColorCapabilities.RGB => new RGBColorUpdateQueue(updateTrigger, info.DeviceId), _ => throw new ArgumentOutOfRangeException() }; - } - - /// - /// Initializes the and of the device. - /// - protected abstract void InitializeLayout(); /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate)); /// /// Resets the back to default. /// - public virtual void Reset() => UpdateQueue?.Reset(); + public virtual void Reset() => UpdateQueue.Reset(); /// /// @@ -78,9 +47,6 @@ namespace RGB.NET.Devices.Novation { Reset(); - try { UpdateQueue?.Dispose(); } - catch { /* at least we tried */ } - base.Dispose(); } diff --git a/RGB.NET.Devices.Novation/Launchpad/NovationLaunchpadRGBDevice.cs b/RGB.NET.Devices.Novation/Launchpad/NovationLaunchpadRGBDevice.cs index 39271aa..6be8738 100644 --- a/RGB.NET.Devices.Novation/Launchpad/NovationLaunchpadRGBDevice.cs +++ b/RGB.NET.Devices.Novation/Launchpad/NovationLaunchpadRGBDevice.cs @@ -17,16 +17,17 @@ namespace RGB.NET.Devices.Novation /// Initializes a new instance of the class. ///
/// The specific information provided by Novation for the launchpad - internal NovationLaunchpadRGBDevice(NovationLaunchpadRGBDeviceInfo info) - : base(info) - { } + internal NovationLaunchpadRGBDevice(NovationLaunchpadRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, updateTrigger) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { Dictionary mapping = GetDeviceMapping(); diff --git a/RGB.NET.Devices.Novation/NovationDeviceProvider.cs b/RGB.NET.Devices.Novation/NovationDeviceProvider.cs index 89ef95d..e0af6f2 100644 --- a/RGB.NET.Devices.Novation/NovationDeviceProvider.cs +++ b/RGB.NET.Devices.Novation/NovationDeviceProvider.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Linq; using RGB.NET.Core; using Sanford.Multimedia.Midi; @@ -14,7 +13,7 @@ namespace RGB.NET.Devices.Novation /// /// Represents a device provider responsible for Novation devices. /// - public class NovationDeviceProvider : IRGBDeviceProvider + public class NovationDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields @@ -24,20 +23,6 @@ namespace RGB.NET.Devices.Novation ///
public static NovationDeviceProvider Instance => _instance ?? new NovationDeviceProvider(); - /// - /// - /// Indicates if the SDK is initialized and ready to use. - /// - public bool IsInitialized { get; private set; } - - /// - public IEnumerable Devices { get; private set; } = Enumerable.Empty(); - - /// - /// The used to trigger the updates for novation devices. - /// - public DeviceUpdateTrigger UpdateTrigger { get; } - #endregion #region Constructors @@ -50,73 +35,32 @@ namespace RGB.NET.Devices.Novation { if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(NovationDeviceProvider)}"); _instance = this; - - UpdateTrigger = new DeviceUpdateTrigger(); } #endregion #region Methods - /// - public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false) + protected override void InitializeSDK() { } + + protected override IEnumerable LoadDevices() { - IsInitialized = false; - - try + for (int index = 0; index < OutputDeviceBase.DeviceCount; index++) { - UpdateTrigger.Stop(); + MidiOutCaps outCaps = OutputDeviceBase.GetDeviceCapabilities(index); + if (outCaps.name == null) continue; - IList devices = new List(); + NovationDevices? deviceId = (NovationDevices?)Enum.GetValues(typeof(NovationDevices)) + .Cast() + .FirstOrDefault(x => x.GetDeviceId()?.ToUpperInvariant().Contains(outCaps.name.ToUpperInvariant()) ?? false); - if (loadFilter.HasFlag(RGBDeviceType.LedMatrix)) - for (int index = 0; index < OutputDeviceBase.DeviceCount; index++) - { - try - { - MidiOutCaps outCaps = OutputDeviceBase.GetDeviceCapabilities(index); - if (outCaps.name == null) continue; + if (deviceId == null) continue; - NovationDevices? deviceId = (NovationDevices?)Enum.GetValues(typeof(NovationDevices)) - .Cast() - .FirstOrDefault(x => x.GetDeviceId()?.ToUpperInvariant().Contains(outCaps.name.ToUpperInvariant()) ?? false); + NovationColorCapabilities colorCapability = deviceId.GetColorCapability(); + if (colorCapability == NovationColorCapabilities.None) continue; - if (deviceId == null) continue; - - NovationColorCapabilities colorCapability = deviceId.GetColorCapability(); - if (colorCapability == NovationColorCapabilities.None) continue; - - INovationRGBDevice device = new NovationLaunchpadRGBDevice(new NovationLaunchpadRGBDeviceInfo(outCaps.name, index, colorCapability, deviceId.GetLedIdMapping())); - device.Initialize(UpdateTrigger); - devices.Add(device); - } - catch { if (throwExceptions) throw; } - } - - UpdateTrigger.Start(); - Devices = new ReadOnlyCollection(devices); - IsInitialized = true; + yield return new NovationLaunchpadRGBDevice(new NovationLaunchpadRGBDeviceInfo(outCaps.name, index, colorCapability, deviceId.GetLedIdMapping()), GetUpdateTrigger()); } - catch - { - if (throwExceptions) - throw; - return false; - } - - return true; - } - - /// - public void Dispose() - { - try { UpdateTrigger.Dispose(); } - catch { /* at least we tried */ } - - foreach (IRGBDevice device in Devices) - try { device.Dispose(); } - catch { /* at least we tried */ } - Devices = Enumerable.Empty(); } #endregion diff --git a/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkRGBDevice.cs b/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkRGBDevice.cs index 79165d3..eca3fd1 100644 --- a/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkRGBDevice.cs +++ b/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkRGBDevice.cs @@ -19,16 +19,17 @@ namespace RGB.NET.Devices.Razer /// Initializes a new instance of the class. ///
/// The specific information provided by CUE for the chroma link. - internal RazerChromaLinkRGBDevice(RazerChromaLinkRGBDeviceInfo info) - : base(info) - { } + internal RazerChromaLinkRGBDevice(RazerChromaLinkRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, new RazerChromaLinkUpdateQueue(updateTrigger, info.DeviceId)) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { for (int i = 0; i < _Defines.CHROMALINK_MAX_LEDS; i++) AddLed(LedId.Custom1 + i, new Point(i * 11, 0), new Size(10, 10)); @@ -37,9 +38,6 @@ namespace RGB.NET.Devices.Razer /// protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Custom1; - /// - protected override RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger) => new RazerChromaLinkUpdateQueue(updateTrigger, DeviceInfo.DeviceId); - #endregion } } diff --git a/RGB.NET.Devices.Razer/Generic/IRazerRGBDevice.cs b/RGB.NET.Devices.Razer/Generic/IRazerRGBDevice.cs index 9cf89ad..e04f35a 100644 --- a/RGB.NET.Devices.Razer/Generic/IRazerRGBDevice.cs +++ b/RGB.NET.Devices.Razer/Generic/IRazerRGBDevice.cs @@ -5,9 +5,6 @@ namespace RGB.NET.Devices.Razer /// /// Represents a razer RGB-device. /// - internal interface IRazerRGBDevice : IRGBDevice - { - void Initialize(IDeviceUpdateTrigger updateTrigger); - void Reset(); - } + public interface IRazerRGBDevice : IRGBDevice + { } } diff --git a/RGB.NET.Devices.Razer/Generic/RazerRGBDevice.cs b/RGB.NET.Devices.Razer/Generic/RazerRGBDevice.cs index 6e7c61a..d9dd0ae 100644 --- a/RGB.NET.Devices.Razer/Generic/RazerRGBDevice.cs +++ b/RGB.NET.Devices.Razer/Generic/RazerRGBDevice.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using RGB.NET.Core; namespace RGB.NET.Devices.Razer @@ -12,32 +11,15 @@ namespace RGB.NET.Devices.Razer public abstract class RazerRGBDevice : AbstractRGBDevice, IRazerRGBDevice where TDeviceInfo : RazerRGBDeviceInfo { - #region Properties & Fields - - /// - /// - /// Gets information about the . - /// - public override TDeviceInfo DeviceInfo { get; } - - /// - /// Gets or sets the update queue performing updates for this device. - /// - // ReSharper disable once MemberCanBePrivate.Global - protected RazerUpdateQueue? UpdateQueue { get; set; } - - #endregion - #region Constructors /// /// Initializes a new instance of the class. /// /// The generic information provided by razer for the device. - protected RazerRGBDevice(TDeviceInfo info) + protected RazerRGBDevice(TDeviceInfo info, IUpdateQueue updateQueue) + : base(info, updateQueue) { - this.DeviceInfo = info; - RequiresFlush = true; } @@ -45,35 +27,8 @@ namespace RGB.NET.Devices.Razer #region Methods - /// - /// Initializes the device. - /// - public void Initialize(IDeviceUpdateTrigger updateTrigger) - { - InitializeLayout(); - - UpdateQueue = CreateUpdateQueue(updateTrigger); - } - - /// - /// Creates a specific for this device. - /// - /// The trigger used to update the queue. - /// The for this device. - protected abstract RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger); - - /// - /// Initializes the and of the device. - /// - protected abstract void InitializeLayout(); - /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); - - /// - /// Resets the device. - /// - public void Reset() => UpdateQueue?.Reset(); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate)); /// public override void Dispose() diff --git a/RGB.NET.Devices.Razer/Headset/RazerHeadsetRGBDevice.cs b/RGB.NET.Devices.Razer/Headset/RazerHeadsetRGBDevice.cs index 27ebbb0..e3fcf52 100644 --- a/RGB.NET.Devices.Razer/Headset/RazerHeadsetRGBDevice.cs +++ b/RGB.NET.Devices.Razer/Headset/RazerHeadsetRGBDevice.cs @@ -19,16 +19,17 @@ namespace RGB.NET.Devices.Razer /// Initializes a new instance of the class. ///
/// The specific information provided by CUE for the headset. - internal RazerHeadsetRGBDevice(RazerHeadsetRGBDeviceInfo info) - : base(info) - { } + internal RazerHeadsetRGBDevice(RazerHeadsetRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, new RazerHeadsetUpdateQueue(updateTrigger, info.DeviceId)) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { for (int i = 0; i < _Defines.HEADSET_MAX_LEDS; i++) AddLed(LedId.Headset1 + i, new Point(i * 11, 0), new Size(10, 10)); @@ -37,9 +38,6 @@ namespace RGB.NET.Devices.Razer /// protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Headset1; - /// - protected override RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger) => new RazerHeadsetUpdateQueue(updateTrigger, DeviceInfo.DeviceId); - #endregion } } diff --git a/RGB.NET.Devices.Razer/Keyboard/RazerKeyboardRGBDevice.cs b/RGB.NET.Devices.Razer/Keyboard/RazerKeyboardRGBDevice.cs index f55ea9a..9a674d9 100644 --- a/RGB.NET.Devices.Razer/Keyboard/RazerKeyboardRGBDevice.cs +++ b/RGB.NET.Devices.Razer/Keyboard/RazerKeyboardRGBDevice.cs @@ -25,16 +25,17 @@ namespace RGB.NET.Devices.Razer /// Initializes a new instance of the class. ///
/// The specific information provided by CUE for the keyboard. - internal RazerKeyboardRGBDevice(RazerKeyboardRGBDeviceInfo info) - : base(info) - { } + internal RazerKeyboardRGBDevice(RazerKeyboardRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, new RazerKeyboardUpdateQueue(updateTrigger, info.DeviceId)) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { for (int i = 0; i < _Defines.KEYBOARD_MAX_ROW; i++) for (int j = 0; j < _Defines.KEYBOARD_MAX_COLUMN; j++) @@ -44,9 +45,6 @@ namespace RGB.NET.Devices.Razer /// protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Keyboard_Escape; - /// - protected override RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger) => new RazerKeyboardUpdateQueue(updateTrigger, DeviceInfo.DeviceId); - #endregion } } diff --git a/RGB.NET.Devices.Razer/Keypad/RazerKeypadRGBDevice.cs b/RGB.NET.Devices.Razer/Keypad/RazerKeypadRGBDevice.cs index 2fac949..365ad6d 100644 --- a/RGB.NET.Devices.Razer/Keypad/RazerKeypadRGBDevice.cs +++ b/RGB.NET.Devices.Razer/Keypad/RazerKeypadRGBDevice.cs @@ -19,16 +19,17 @@ namespace RGB.NET.Devices.Razer /// Initializes a new instance of the class. ///
/// The specific information provided by CUE for the keypad. - internal RazerKeypadRGBDevice(RazerKeypadRGBDeviceInfo info) - : base(info) - { } + internal RazerKeypadRGBDevice(RazerKeypadRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, new RazerKeypadUpdateQueue(updateTrigger, info.DeviceId)) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { for (int i = 0; i < _Defines.KEYPAD_MAX_ROW; i++) for (int j = 0; j < _Defines.KEYPAD_MAX_COLUMN; j++) @@ -38,9 +39,6 @@ namespace RGB.NET.Devices.Razer /// protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Keypad1; - /// - protected override RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger) => new RazerKeypadUpdateQueue(updateTrigger, DeviceInfo.DeviceId); - #endregion } } diff --git a/RGB.NET.Devices.Razer/Mouse/RazerMouseRGBDevice.cs b/RGB.NET.Devices.Razer/Mouse/RazerMouseRGBDevice.cs index 983d90f..b3fe8f6 100644 --- a/RGB.NET.Devices.Razer/Mouse/RazerMouseRGBDevice.cs +++ b/RGB.NET.Devices.Razer/Mouse/RazerMouseRGBDevice.cs @@ -19,16 +19,17 @@ namespace RGB.NET.Devices.Razer /// Initializes a new instance of the class. ///
/// The specific information provided by CUE for the mouse. - internal RazerMouseRGBDevice(RazerMouseRGBDeviceInfo info) - : base(info) - { } + internal RazerMouseRGBDevice(RazerMouseRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, new RazerMouseUpdateQueue(updateTrigger, info.DeviceId)) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { for (int i = 0; i < _Defines.MOUSE_MAX_ROW; i++) for (int j = 0; j < _Defines.MOUSE_MAX_COLUMN; j++) @@ -38,9 +39,6 @@ namespace RGB.NET.Devices.Razer /// protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Mouse1; - /// - protected override RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger) => new RazerMouseUpdateQueue(updateTrigger, DeviceInfo.DeviceId); - #endregion } } diff --git a/RGB.NET.Devices.Razer/Mousepad/RazerMousepadRGBDevice.cs b/RGB.NET.Devices.Razer/Mousepad/RazerMousepadRGBDevice.cs index 285e211..2b5734c 100644 --- a/RGB.NET.Devices.Razer/Mousepad/RazerMousepadRGBDevice.cs +++ b/RGB.NET.Devices.Razer/Mousepad/RazerMousepadRGBDevice.cs @@ -19,16 +19,17 @@ namespace RGB.NET.Devices.Razer /// Initializes a new instance of the class. /// /// The specific information provided by CUE for the mousepad. - internal RazerMousepadRGBDevice(RazerMousepadRGBDeviceInfo info) - : base(info) - { } + internal RazerMousepadRGBDevice(RazerMousepadRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, new RazerMousepadUpdateQueue(updateTrigger, info.DeviceId)) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { for (int i = 0; i < _Defines.MOUSEPAD_MAX_LEDS; i++) AddLed(LedId.Mousepad1 + i, new Point(i * 11, 0), new Size(10, 10)); @@ -36,10 +37,6 @@ namespace RGB.NET.Devices.Razer /// protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Mousepad1; - - /// - protected override RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger) => new RazerMousepadUpdateQueue(updateTrigger, DeviceInfo.DeviceId); - #endregion } } diff --git a/RGB.NET.Devices.Razer/RazerDeviceProvider.cs b/RGB.NET.Devices.Razer/RazerDeviceProvider.cs index a44c4e2..752e224 100644 --- a/RGB.NET.Devices.Razer/RazerDeviceProvider.cs +++ b/RGB.NET.Devices.Razer/RazerDeviceProvider.cs @@ -15,7 +15,7 @@ namespace RGB.NET.Devices.Razer /// /// Represents a device provider responsible for razer devices. /// - public class RazerDeviceProvider : IRGBDeviceProvider + public class RazerDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields @@ -37,25 +37,11 @@ namespace RGB.NET.Devices.Razer /// public static List PossibleX64NativePaths { get; } = new() { @"%systemroot%\System32\RzChromaSDK.dll", @"%systemroot%\System32\RzChromaSDK64.dll" }; - /// - /// - /// Indicates if the SDK is initialized and ready to use. - /// - public bool IsInitialized { get; private set; } - - /// - public IEnumerable Devices { get; private set; } = Enumerable.Empty(); - /// /// Forces to load the devices represented by the emulator even if they aren't reported to exist. /// public bool LoadEmulatorDevices { get; set; } = false; - /// - /// The used to trigger the updates for razer devices. - /// - public DeviceUpdateTrigger UpdateTrigger { get; } - #endregion #region Constructors @@ -68,127 +54,75 @@ namespace RGB.NET.Devices.Razer { if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(RazerDeviceProvider)}"); _instance = this; - - UpdateTrigger = new DeviceUpdateTrigger(); } #endregion #region Methods - /// - public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false) + protected override void InitializeSDK() { - if (IsInitialized) - TryUnInit(); + TryUnInit(); - IsInitialized = false; + _RazerSDK.Reload(); - try - { - UpdateTrigger.Stop(); - - _RazerSDK.Reload(); - - RazerError error; - if (((error = _RazerSDK.Init()) != RazerError.Success) - && Enum.IsDefined(typeof(RazerError), error)) //HACK DarthAffe 08.02.2018: The x86-SDK seems to have a problem here ... - ThrowRazerError(error); - - IList devices = new List(); - - if (loadFilter.HasFlag(RGBDeviceType.Keyboard)) - foreach ((Guid guid, string model) in Razer.Devices.KEYBOARDS) - try - { - if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) - && (!LoadEmulatorDevices || (Razer.Devices.KEYBOARDS.FirstOrDefault().guid != guid))) continue; - - RazerKeyboardRGBDevice device = new(new RazerKeyboardRGBDeviceInfo(guid, model)); - device.Initialize(UpdateTrigger); - devices.Add(device); - } - catch { if (throwExceptions) throw; } - - if (loadFilter.HasFlag(RGBDeviceType.Mouse)) - foreach ((Guid guid, string model) in Razer.Devices.MICE) - try - { - if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) - && (!LoadEmulatorDevices || (Razer.Devices.MICE.FirstOrDefault().guid != guid))) continue; - - RazerMouseRGBDevice device = new(new RazerMouseRGBDeviceInfo(guid, model)); - device.Initialize(UpdateTrigger); - devices.Add(device); - } - catch { if (throwExceptions) throw; } - - if (loadFilter.HasFlag(RGBDeviceType.Headset)) - foreach ((Guid guid, string model) in Razer.Devices.HEADSETS) - try - { - if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) - && (!LoadEmulatorDevices || (Razer.Devices.HEADSETS.FirstOrDefault().guid != guid))) continue; - - RazerHeadsetRGBDevice device = new(new RazerHeadsetRGBDeviceInfo(guid, model)); - device.Initialize(UpdateTrigger); - devices.Add(device); - } - catch { if (throwExceptions) throw; } - - if (loadFilter.HasFlag(RGBDeviceType.Mousepad)) - foreach ((Guid guid, string model) in Razer.Devices.MOUSEMATS) - try - { - if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) - && (!LoadEmulatorDevices || (Razer.Devices.MOUSEMATS.FirstOrDefault().guid != guid))) continue; - - RazerMousepadRGBDevice device = new(new RazerMousepadRGBDeviceInfo(guid, model)); - device.Initialize(UpdateTrigger); - devices.Add(device); - } - catch { if (throwExceptions) throw; } - - if (loadFilter.HasFlag(RGBDeviceType.Keypad)) - foreach ((Guid guid, string model) in Razer.Devices.KEYPADS) - try - { - if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) - && (!LoadEmulatorDevices || (Razer.Devices.KEYPADS.FirstOrDefault().guid != guid))) continue; - - RazerKeypadRGBDevice device = new(new RazerKeypadRGBDeviceInfo(guid, model)); - device.Initialize(UpdateTrigger); - devices.Add(device); - } - catch { if (throwExceptions) throw; } - - if (loadFilter.HasFlag(RGBDeviceType.Keyboard)) - foreach ((Guid guid, string model) in Razer.Devices.CHROMALINKS) - try - { - if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) - && (!LoadEmulatorDevices || (Razer.Devices.CHROMALINKS.FirstOrDefault().guid != guid))) continue; - - RazerChromaLinkRGBDevice device = new(new RazerChromaLinkRGBDeviceInfo(guid, model)); - device.Initialize(UpdateTrigger); - devices.Add(device); - } - catch { if (throwExceptions) throw; } - - UpdateTrigger.Start(); - Devices = new ReadOnlyCollection(devices); - IsInitialized = true; - } - catch - { - TryUnInit(); - if (throwExceptions) throw; - return false; - } - - return true; + RazerError error; + if (((error = _RazerSDK.Init()) != RazerError.Success) + && Enum.IsDefined(typeof(RazerError), error)) //HACK DarthAffe 08.02.2018: The x86-SDK seems to have a problem here ... + ThrowRazerError(error); } - + + protected override IEnumerable LoadDevices() + { + foreach ((Guid guid, string model) in Razer.Devices.KEYBOARDS) + { + if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) + && (!LoadEmulatorDevices || (Razer.Devices.KEYBOARDS.FirstOrDefault().guid != guid))) continue; + + yield return new RazerKeyboardRGBDevice(new RazerKeyboardRGBDeviceInfo(guid, model), GetUpdateTrigger()); + } + + foreach ((Guid guid, string model) in Razer.Devices.MICE) + { + if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) + && (!LoadEmulatorDevices || (Razer.Devices.MICE.FirstOrDefault().guid != guid))) continue; + + yield return new RazerMouseRGBDevice(new RazerMouseRGBDeviceInfo(guid, model), GetUpdateTrigger()); + } + + foreach ((Guid guid, string model) in Razer.Devices.HEADSETS) + { + if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) + && (!LoadEmulatorDevices || (Razer.Devices.HEADSETS.FirstOrDefault().guid != guid))) continue; + + yield return new RazerHeadsetRGBDevice(new RazerHeadsetRGBDeviceInfo(guid, model), GetUpdateTrigger()); + } + + foreach ((Guid guid, string model) in Razer.Devices.MOUSEMATS) + { + if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) + && (!LoadEmulatorDevices || (Razer.Devices.MOUSEMATS.FirstOrDefault().guid != guid))) continue; + + yield return new RazerMousepadRGBDevice(new RazerMousepadRGBDeviceInfo(guid, model), GetUpdateTrigger()); + } + + foreach ((Guid guid, string model) in Razer.Devices.KEYPADS) + { + if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) + && (!LoadEmulatorDevices || (Razer.Devices.KEYPADS.FirstOrDefault().guid != guid))) continue; + + yield return new RazerKeypadRGBDevice(new RazerKeypadRGBDeviceInfo(guid, model), GetUpdateTrigger()); + } + + foreach ((Guid guid, string model) in Razer.Devices.CHROMALINKS) + { + if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) + && (!LoadEmulatorDevices || (Razer.Devices.CHROMALINKS.FirstOrDefault().guid != guid))) continue; + + yield return new RazerChromaLinkRGBDevice(new RazerChromaLinkRGBDeviceInfo(guid, model), GetUpdateTrigger()); + } + } + private void ThrowRazerError(RazerError errorCode) => throw new RazerException(errorCode); private void TryUnInit() @@ -198,15 +132,9 @@ namespace RGB.NET.Devices.Razer } /// - public void Dispose() + public override void Dispose() { - try { UpdateTrigger.Dispose(); } - catch { /* at least we tried */ } - - foreach (IRGBDevice device in Devices) - try { device.Dispose(); } - catch { /* at least we tried */ } - Devices = Enumerable.Empty(); + base.Dispose(); TryUnInit(); diff --git a/RGB.NET.Devices.SteelSeries/Generic/ISteelSeriesRGBDevice.cs b/RGB.NET.Devices.SteelSeries/Generic/ISteelSeriesRGBDevice.cs index 57364d9..0270a27 100644 --- a/RGB.NET.Devices.SteelSeries/Generic/ISteelSeriesRGBDevice.cs +++ b/RGB.NET.Devices.SteelSeries/Generic/ISteelSeriesRGBDevice.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using RGB.NET.Core; +using RGB.NET.Core; namespace RGB.NET.Devices.SteelSeries { @@ -7,7 +6,5 @@ namespace RGB.NET.Devices.SteelSeries /// Represents a steelseries RGB-device. /// internal interface ISteelSeriesRGBDevice : IRGBDevice - { - void Initialize(UpdateQueue updateQueue, Dictionary ledMapping); - } + { } } diff --git a/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesRGBDevice.cs b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesRGBDevice.cs index 9cc5f39..d97bb12 100644 --- a/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesRGBDevice.cs +++ b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesRGBDevice.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using RGB.NET.Core; namespace RGB.NET.Devices.SteelSeries @@ -13,19 +12,7 @@ namespace RGB.NET.Devices.SteelSeries { #region Properties & Fields - private Dictionary _ledMapping = new(); - - /// - /// - /// Gets information about the . - /// - public override SteelSeriesRGBDeviceInfo DeviceInfo { get; } - - /// - /// Gets or sets the update queue performing updates for this device. - /// - // ReSharper disable once MemberCanBePrivate.Global - protected UpdateQueue? UpdateQueue { get; set; } + private readonly Dictionary _ledMapping; #endregion @@ -35,34 +22,30 @@ namespace RGB.NET.Devices.SteelSeries /// Initializes a new instance of the class. /// /// The generic information provided by SteelSeries for the device. - internal SteelSeriesRGBDevice(SteelSeriesRGBDeviceInfo info) + internal SteelSeriesRGBDevice(SteelSeriesRGBDeviceInfo info, string apiName, Dictionary ledMapping, IDeviceUpdateTrigger updateTrigger) + : base(info, new SteelSeriesDeviceUpdateQueue(updateTrigger, apiName)) { - this.DeviceInfo = info; + this._ledMapping = ledMapping; + + InitializeLayout(); } #endregion #region Methods - /// - /// Initializes the device. - /// - void ISteelSeriesRGBDevice.Initialize(UpdateQueue updateQueue, Dictionary ledMapping) + private void InitializeLayout() { - _ledMapping = ledMapping; - int counter = 0; - foreach (KeyValuePair mapping in ledMapping) + foreach (KeyValuePair mapping in _ledMapping) AddLed(mapping.Key, new Point((counter++) * 10, 0), new Size(10, 10)); - - UpdateQueue = updateQueue; } /// protected override object GetLedCustomData(LedId ledId) => _ledMapping[ledId]; /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate)); /// public override void Dispose() diff --git a/RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs b/RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs index f42885f..f1793fd 100644 --- a/RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs +++ b/RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; using RGB.NET.Core; using RGB.NET.Devices.SteelSeries.API; using RGB.NET.Devices.SteelSeries.HID; @@ -12,7 +10,7 @@ namespace RGB.NET.Devices.SteelSeries /// /// Represents a device provider responsible for SteelSeries- devices. /// - public class SteelSeriesDeviceProvider : IRGBDeviceProvider + public class SteelSeriesDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields @@ -22,20 +20,6 @@ namespace RGB.NET.Devices.SteelSeries /// public static SteelSeriesDeviceProvider Instance => _instance ?? new SteelSeriesDeviceProvider(); - /// - /// - /// Indicates if the SDK is initialized and ready to use. - /// - public bool IsInitialized { get; private set; } - - /// - public IEnumerable Devices { get; private set; } = Enumerable.Empty(); - - /// - /// The used to trigger the updates for SteelSeries devices. - /// - public SteelSeriesDeviceUpdateTrigger UpdateTrigger { get; } - #endregion #region Constructors @@ -48,67 +32,41 @@ namespace RGB.NET.Devices.SteelSeries { if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(SteelSeriesDeviceProvider)}"); _instance = this; - - UpdateTrigger = new SteelSeriesDeviceUpdateTrigger(); } #endregion #region Methods - /// - public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false) + protected override void InitializeSDK() { - try - { - IsInitialized = false; - - UpdateTrigger.Stop(); - - if (!SteelSeriesSDK.IsInitialized) - SteelSeriesSDK.Initialize(); - - IList devices = new List(); - DeviceChecker.LoadDeviceList(loadFilter); - - try - { - foreach ((string model, RGBDeviceType deviceType, int _, SteelSeriesDeviceType steelSeriesDeviceType, Dictionary ledMapping) in DeviceChecker.ConnectedDevices) - { - ISteelSeriesRGBDevice device = new SteelSeriesRGBDevice(new SteelSeriesRGBDeviceInfo(deviceType, model, steelSeriesDeviceType)); - string apiName = steelSeriesDeviceType.GetAPIName() ?? throw new RGBDeviceException($"Missing API-name for device {model}"); - SteelSeriesDeviceUpdateQueue updateQueue = new(UpdateTrigger, apiName); - device.Initialize(updateQueue, ledMapping); - devices.Add(device); - } - } - catch { if (throwExceptions) throw; } - - UpdateTrigger.Start(); - - Devices = new ReadOnlyCollection(devices); - IsInitialized = true; - } - catch - { - IsInitialized = false; - if (throwExceptions) throw; - return false; - } - - return true; + if (!SteelSeriesSDK.IsInitialized) + SteelSeriesSDK.Initialize(); } - - /// - public void Dispose() - { - try { UpdateTrigger.Dispose(); } - catch { /* at least we tried */ } - foreach (IRGBDevice device in Devices) - try { device.Dispose(); } - catch { /* at least we tried */ } - Devices = Enumerable.Empty(); + protected override IEnumerable GetLoadedDevices(RGBDeviceType loadFilter) + { + DeviceChecker.LoadDeviceList(loadFilter); + + return base.GetLoadedDevices(loadFilter); + } + + protected override IEnumerable LoadDevices() + { + foreach ((string model, RGBDeviceType deviceType, int _, SteelSeriesDeviceType steelSeriesDeviceType, Dictionary ledMapping) in DeviceChecker.ConnectedDevices) + { + string? apiName = steelSeriesDeviceType.GetAPIName(); + if (apiName == null) + Throw(new RGBDeviceException($"Missing API-name for device {model}")); + else + yield return new SteelSeriesRGBDevice(new SteelSeriesRGBDeviceInfo(deviceType, model, steelSeriesDeviceType), apiName, ledMapping, GetUpdateTrigger()); + } + } + + /// + public override void Dispose() + { + base.Dispose(); try { SteelSeriesSDK.Dispose(); } catch { /* shit happens */ } diff --git a/RGB.NET.Devices.WS281X/Arduino/ArduinoWS2812USBDevice.cs b/RGB.NET.Devices.WS281X/Arduino/ArduinoWS2812USBDevice.cs index ab658e5..545dccd 100644 --- a/RGB.NET.Devices.WS281X/Arduino/ArduinoWS2812USBDevice.cs +++ b/RGB.NET.Devices.WS281X/Arduino/ArduinoWS2812USBDevice.cs @@ -8,22 +8,12 @@ using RGB.NET.Core; namespace RGB.NET.Devices.WS281X.Arduino { // ReSharper disable once InconsistentNaming - /// /// /// Represents an arduino WS2812 device. /// public class ArduinoWS2812USBDevice : AbstractRGBDevice, ILedStripe { #region Properties & Fields - - /// - /// Gets the update queue performing updates for this device. - /// - public ArduinoWS2812USBUpdateQueue UpdateQueue { get; } - - /// - public override ArduinoWS2812USBDeviceInfo DeviceInfo { get; } - /// /// Gets the channel (as defined in the arduino-sketch) this device is attached to. /// @@ -39,18 +29,19 @@ namespace RGB.NET.Devices.WS281X.Arduino /// The update trigger used by this queue. /// The update queue performing updates for this device. /// The channel (as defined in the arduino-sketch) this device is attached to. - public ArduinoWS2812USBDevice(ArduinoWS2812USBDeviceInfo deviceInfo, ArduinoWS2812USBUpdateQueue updateQueue, int channel) + public ArduinoWS2812USBDevice(ArduinoWS2812USBDeviceInfo deviceInfo, ArduinoWS2812USBUpdateQueue updateQueue, int channel, int ledCount) + : base(deviceInfo, updateQueue) { - this.DeviceInfo = deviceInfo; - this.UpdateQueue = updateQueue; this.Channel = channel; + + InitializeLayout(ledCount); } #endregion #region Methods - internal void Initialize(int ledCount) + private void InitializeLayout(int ledCount) { for (int i = 0; i < ledCount; i++) AddLed(LedId.LedStripe1 + i, new Point(i * 10, 0), new Size(10, 10)); @@ -65,15 +56,6 @@ namespace RGB.NET.Devices.WS281X.Arduino /// protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate)); - /// - public override void Dispose() - { - try { UpdateQueue.Dispose(); } - catch { /* at least we tried */ } - - base.Dispose(); - } - #endregion } } diff --git a/RGB.NET.Devices.WS281X/Arduino/ArduinoWS281XDeviceDefinition.cs b/RGB.NET.Devices.WS281X/Arduino/ArduinoWS281XDeviceDefinition.cs index c6aa63c..adbf0bf 100644 --- a/RGB.NET.Devices.WS281X/Arduino/ArduinoWS281XDeviceDefinition.cs +++ b/RGB.NET.Devices.WS281X/Arduino/ArduinoWS281XDeviceDefinition.cs @@ -67,15 +67,14 @@ namespace RGB.NET.Devices.WS281X.Arduino /// public IEnumerable CreateDevices(IDeviceUpdateTrigger updateTrigger) { + //TODO DarthAffe 04.03.2021: one queue per device ArduinoWS2812USBUpdateQueue queue = new(updateTrigger, SerialConnection); IEnumerable<(int channel, int ledCount)> channels = queue.GetChannels(); int counter = 0; foreach ((int channel, int ledCount) in channels) { string name = string.Format(Name ?? $"Arduino WS2812 USB ({Port}) [{{0}}]", ++counter); - ArduinoWS2812USBDevice device = new(new ArduinoWS2812USBDeviceInfo(name), queue, channel); - device.Initialize(ledCount); - yield return device; + yield return new ArduinoWS2812USBDevice(new ArduinoWS2812USBDeviceInfo(name), queue, channel, ledCount); } } diff --git a/RGB.NET.Devices.WS281X/Bitwizard/BitwizardWS2812USBDevice.cs b/RGB.NET.Devices.WS281X/Bitwizard/BitwizardWS2812USBDevice.cs index 5bb6bcc..9ff359d 100644 --- a/RGB.NET.Devices.WS281X/Bitwizard/BitwizardWS2812USBDevice.cs +++ b/RGB.NET.Devices.WS281X/Bitwizard/BitwizardWS2812USBDevice.cs @@ -2,13 +2,12 @@ // ReSharper disable UnusedMember.Global using System.Collections.Generic; -using System.Linq; using RGB.NET.Core; namespace RGB.NET.Devices.WS281X.Bitwizard { // ReSharper disable once InconsistentNaming - /// + /// /// /// Represents an bitwizard WS2812 USB device. /// @@ -18,14 +17,6 @@ namespace RGB.NET.Devices.WS281X.Bitwizard private readonly int _ledOffset; - /// - /// Gets the update queue performing updates for this device. - /// - public BitwizardWS2812USBUpdateQueue UpdateQueue { get; } - - /// - public override BitwizardWS2812USBDeviceInfo DeviceInfo { get; } - #endregion #region Constructors @@ -35,19 +26,18 @@ namespace RGB.NET.Devices.WS281X.Bitwizard /// /// The update trigger used by this queue. /// The update queue performing updates for this device. - public BitwizardWS2812USBDevice(BitwizardWS2812USBDeviceInfo deviceInfo, BitwizardWS2812USBUpdateQueue updateQueue, int ledOffset) + public BitwizardWS2812USBDevice(BitwizardWS2812USBDeviceInfo deviceInfo, BitwizardWS2812USBUpdateQueue updateQueue, int ledOffset, int ledCount) + : base(deviceInfo, updateQueue) { - this.DeviceInfo = deviceInfo; - this.UpdateQueue = updateQueue; - this._ledOffset = ledOffset; + InitializeLayout(ledCount); } #endregion #region Methods - internal void Initialize(int ledCount) + private void InitializeLayout(int ledCount) { for (int i = 0; i < ledCount; i++) AddLed(LedId.LedStripe1 + i, new Point(i * 10, 0), new Size(10, 10)); @@ -59,15 +49,6 @@ namespace RGB.NET.Devices.WS281X.Bitwizard /// protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate)); - /// - public override void Dispose() - { - try { UpdateQueue.Dispose(); } - catch { /* at least we tried */ } - - base.Dispose(); - } - #endregion } } diff --git a/RGB.NET.Devices.WS281X/Bitwizard/BitwizardWS281XDeviceDefinition.cs b/RGB.NET.Devices.WS281X/Bitwizard/BitwizardWS281XDeviceDefinition.cs index 3a46ac1..558548a 100644 --- a/RGB.NET.Devices.WS281X/Bitwizard/BitwizardWS281XDeviceDefinition.cs +++ b/RGB.NET.Devices.WS281X/Bitwizard/BitwizardWS281XDeviceDefinition.cs @@ -36,15 +36,7 @@ namespace RGB.NET.Devices.WS281X.Bitwizard /// public string? Name { get; set; } - /// - /// Gets or sets the pin sed to control the leds. - /// - public int Pin { get; set; } = 0; - - /// - /// Gets or sets the amount of leds of this device. - /// - public int StripLength { get; set; } = 384; + public List<(int pin, int stripLength)> Strips { get; } = new(); /// /// Gets or sets the amount of leds controlled by one pin. @@ -60,9 +52,11 @@ namespace RGB.NET.Devices.WS281X.Bitwizard /// Initializes a new instance of the class. /// /// The serial connection used for the device. - public BitwizardWS281XDeviceDefinition(ISerialConnection serialConnection) + public BitwizardWS281XDeviceDefinition(ISerialConnection serialConnection, params (int pin, int stripLength)[] strips) { this.SerialConnection = serialConnection; + + Strips.AddRange(strips); } /// @@ -70,9 +64,11 @@ namespace RGB.NET.Devices.WS281X.Bitwizard /// /// The name of the serial-port to connect to. /// The baud-rate of the serial-connection. - public BitwizardWS281XDeviceDefinition(string port, int baudRate = 115200) + public BitwizardWS281XDeviceDefinition(string port, int baudRate = 115200, params (int pin, int stripLength)[] strips) { SerialConnection = new SerialPortConnection(port, baudRate); + + Strips.AddRange(strips); } #endregion @@ -82,12 +78,13 @@ namespace RGB.NET.Devices.WS281X.Bitwizard /// public IEnumerable CreateDevices(IDeviceUpdateTrigger updateTrigger) { - BitwizardWS2812USBUpdateQueue queue = new(updateTrigger, SerialConnection); - string name = Name ?? $"Bitwizard WS2812 USB ({Port})"; - int ledOffset = Pin * MaxStripLength; - BitwizardWS2812USBDevice device = new(new BitwizardWS2812USBDeviceInfo(name), queue, ledOffset); - device.Initialize(StripLength); - yield return device; + foreach ((int pin, int stripLength) in Strips) + { + BitwizardWS2812USBUpdateQueue queue = new(updateTrigger, SerialConnection); + string name = Name ?? $"Bitwizard WS2812 USB ({Port}) Pin {pin}"; + int ledOffset = pin * MaxStripLength; + yield return new BitwizardWS2812USBDevice(new BitwizardWS2812USBDeviceInfo(name), queue, ledOffset, stripLength); + } } #endregion diff --git a/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBDevice.cs b/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBDevice.cs index 635d61b..3e59cd1 100644 --- a/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBDevice.cs +++ b/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBDevice.cs @@ -16,14 +16,6 @@ namespace RGB.NET.Devices.WS281X.NodeMCU { #region Properties & Fields - /// - /// Gets the update queue performing updates for this device. - /// - public NodeMCUWS2812USBUpdateQueue UpdateQueue { get; } - - /// - public override NodeMCUWS2812USBDeviceInfo DeviceInfo { get; } - /// /// Gets the channel (as defined in the NodeMCU-sketch) this device is attached to. /// @@ -39,18 +31,19 @@ namespace RGB.NET.Devices.WS281X.NodeMCU /// The update trigger used by this queue. /// The update queue performing updates for this device. /// The channel (as defined in the NodeMCU-sketch) this device is attached to. - public NodeMCUWS2812USBDevice(NodeMCUWS2812USBDeviceInfo deviceInfo, NodeMCUWS2812USBUpdateQueue updateQueue, int channel) + public NodeMCUWS2812USBDevice(NodeMCUWS2812USBDeviceInfo info, NodeMCUWS2812USBUpdateQueue updateQueue, int channel, int ledCount) + : base(info, updateQueue) { - this.DeviceInfo = deviceInfo; - this.UpdateQueue = updateQueue; this.Channel = channel; + + InitializeLayout(ledCount); } #endregion #region Methods - internal void Initialize(int ledCount) + private void InitializeLayout(int ledCount) { for (int i = 0; i < ledCount; i++) AddLed(LedId.LedStripe1 + i, new Point(i * 10, 0), new Size(10, 10)); @@ -65,15 +58,6 @@ namespace RGB.NET.Devices.WS281X.NodeMCU /// protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate)); - /// - public override void Dispose() - { - try { UpdateQueue.Dispose(); } - catch { /* at least we tried */ } - - base.Dispose(); - } - #endregion } } diff --git a/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS281XDeviceDefinition.cs b/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS281XDeviceDefinition.cs index b87f39e..04d34ff 100644 --- a/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS281XDeviceDefinition.cs +++ b/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS281XDeviceDefinition.cs @@ -72,9 +72,7 @@ namespace RGB.NET.Devices.WS281X.NodeMCU foreach ((int channel, int ledCount) in channels) { string name = string.Format(Name ?? $"NodeMCU WS2812 WIFI ({Hostname}) [{{0}}]", ++counter); - NodeMCUWS2812USBDevice device = new(new NodeMCUWS2812USBDeviceInfo(name), queue, channel); - device.Initialize(ledCount); - yield return device; + yield return new NodeMCUWS2812USBDevice(new NodeMCUWS2812USBDeviceInfo(name), queue, channel, ledCount); } } diff --git a/RGB.NET.Devices.WS281X/WS281XDeviceProvider.cs b/RGB.NET.Devices.WS281X/WS281XDeviceProvider.cs index aeee841..deac3ae 100644 --- a/RGB.NET.Devices.WS281X/WS281XDeviceProvider.cs +++ b/RGB.NET.Devices.WS281X/WS281XDeviceProvider.cs @@ -2,8 +2,6 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; using RGB.NET.Core; namespace RGB.NET.Devices.WS281X @@ -13,7 +11,7 @@ namespace RGB.NET.Devices.WS281X /// Represents a device provider responsible for WS2812B- and WS2811-Led-devices. /// // ReSharper disable once InconsistentNaming - public class WS281XDeviceProvider : IRGBDeviceProvider + public class WS281XDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields @@ -23,12 +21,6 @@ namespace RGB.NET.Devices.WS281X /// public static WS281XDeviceProvider Instance => _instance ?? new WS281XDeviceProvider(); - /// - public bool IsInitialized { get; private set; } - - /// - public IEnumerable Devices { get; private set; } = Enumerable.Empty(); - /// /// Gets a list of all defined device-definitions. /// @@ -36,11 +28,6 @@ namespace RGB.NET.Devices.WS281X // ReSharper disable once ReturnTypeCanBeEnumerable.Global public List DeviceDefinitions { get; } = new(); - /// - /// The used to trigger the updates for corsair devices. - /// - public DeviceUpdateTrigger UpdateTrigger { get; } - #endregion #region Constructors @@ -53,8 +40,6 @@ namespace RGB.NET.Devices.WS281X { if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(WS281XDeviceProvider)}"); _instance = this; - - UpdateTrigger = new DeviceUpdateTrigger(); } #endregion @@ -68,49 +53,23 @@ namespace RGB.NET.Devices.WS281X // ReSharper disable once UnusedMember.Global public void AddDeviceDefinition(IWS281XDeviceDefinition deviceDefinition) => DeviceDefinitions.Add(deviceDefinition); - /// - public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.Unknown, bool throwExceptions = false) + protected override void InitializeSDK() { } + + protected override IEnumerable LoadDevices() { - IsInitialized = false; - - try + int i = 0; + foreach (IWS281XDeviceDefinition deviceDefinition in DeviceDefinitions) { - UpdateTrigger.Stop(); - - List devices = new(); - foreach (IWS281XDeviceDefinition deviceDefinition in DeviceDefinitions) - { - try - { - devices.AddRange(deviceDefinition.CreateDevices(UpdateTrigger)); - } - catch { if (throwExceptions) throw; } - } - UpdateTrigger.Start(); - - Devices = new ReadOnlyCollection(devices); - IsInitialized = true; + IDeviceUpdateTrigger updateTrigger = GetUpdateTrigger(i++); + foreach (IRGBDevice device in deviceDefinition.CreateDevices(updateTrigger)) + yield return device; } - catch - { - if (throwExceptions) - throw; - return false; - } - - return true; } - - /// - public void Dispose() - { - try { UpdateTrigger.Dispose(); } - catch { /* at least we tried */} - foreach (IRGBDevice device in Devices) - try { device.Dispose(); } - catch { /* at least we tried */ } - Devices = Enumerable.Empty(); + /// + public override void Dispose() + { + base.Dispose(); DeviceDefinitions.Clear(); } diff --git a/RGB.NET.Devices.Wooting/Generic/IWootingRGBDevice.cs b/RGB.NET.Devices.Wooting/Generic/IWootingRGBDevice.cs index b7356eb..932aff9 100644 --- a/RGB.NET.Devices.Wooting/Generic/IWootingRGBDevice.cs +++ b/RGB.NET.Devices.Wooting/Generic/IWootingRGBDevice.cs @@ -5,8 +5,6 @@ namespace RGB.NET.Devices.Wooting.Generic /// /// Represents a Wooting RGB-device. /// - internal interface IWootingRGBDevice : IRGBDevice - { - void Initialize(IDeviceUpdateTrigger updateTrigger); - } + public interface IWootingRGBDevice : IRGBDevice + { } } diff --git a/RGB.NET.Devices.Wooting/Generic/WootingRGBDevice.cs b/RGB.NET.Devices.Wooting/Generic/WootingRGBDevice.cs index 4f843a8..b7a4d22 100644 --- a/RGB.NET.Devices.Wooting/Generic/WootingRGBDevice.cs +++ b/RGB.NET.Devices.Wooting/Generic/WootingRGBDevice.cs @@ -10,60 +10,15 @@ namespace RGB.NET.Devices.Wooting.Generic public abstract class WootingRGBDevice : AbstractRGBDevice, IWootingRGBDevice where TDeviceInfo : WootingRGBDeviceInfo { - #region Properties & Fields - - /// - /// - /// Gets information about the . - /// - public override TDeviceInfo DeviceInfo { get; } - - /// - /// Gets or sets the update queue performing updates for this device. - /// - // ReSharper disable once MemberCanBePrivate.Global - protected UpdateQueue? UpdateQueue { get; set; } - - #endregion - #region Constructors /// /// Initializes a new instance of the class. /// /// The generic information provided by Wooting for the device. - protected WootingRGBDevice(TDeviceInfo info) - { - this.DeviceInfo = info; - } - - #endregion - - #region Methods - - /// - /// Initializes the device. - /// - public void Initialize(IDeviceUpdateTrigger updateTrigger) - { - InitializeLayout(); - - UpdateQueue = new WootingUpdateQueue(updateTrigger); - } - - /// - /// Initializes the and of the device. - /// - protected abstract void InitializeLayout(); - - /// - public override void Dispose() - { - try { UpdateQueue?.Dispose(); } - catch { /* at least we tried */ } - - base.Dispose(); - } + protected WootingRGBDevice(TDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, new WootingUpdateQueue(updateTrigger)) + { } #endregion } diff --git a/RGB.NET.Devices.Wooting/Keyboard/WootingKeyboardRGBDevice.cs b/RGB.NET.Devices.Wooting/Keyboard/WootingKeyboardRGBDevice.cs index bd8edea..2f7ac90 100644 --- a/RGB.NET.Devices.Wooting/Keyboard/WootingKeyboardRGBDevice.cs +++ b/RGB.NET.Devices.Wooting/Keyboard/WootingKeyboardRGBDevice.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using RGB.NET.Core; using RGB.NET.Devices.Wooting.Enum; using RGB.NET.Devices.Wooting.Generic; @@ -25,16 +24,17 @@ namespace RGB.NET.Devices.Wooting.Keyboard /// Initializes a new instance of the class. /// /// The specific information provided by Wooting for the keyboard - internal WootingKeyboardRGBDevice(WootingKeyboardRGBDeviceInfo info) - : base(info) - { } + internal WootingKeyboardRGBDevice(WootingKeyboardRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger) + : base(info, updateTrigger) + { + InitializeLayout(); + } #endregion #region Methods - /// - protected override void InitializeLayout() + private void InitializeLayout() { //TODO DarthAffe 13.02.2021: Check how the mapping can work without knowing the physical layout Dictionary mapping = WootingKeyboardLedMappings.Mapping[DeviceInfo.DeviceIndex][WootingPhysicalKeyboardLayout.US]; @@ -47,7 +47,7 @@ namespace RGB.NET.Devices.Wooting.Keyboard protected override object GetLedCustomData(LedId ledId) => WootingKeyboardLedMappings.Mapping[DeviceInfo.DeviceIndex][WootingPhysicalKeyboardLayout.US][ledId]; /// - protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); + protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate)); #endregion } diff --git a/RGB.NET.Devices.Wooting/WootingDeviceProvider.cs b/RGB.NET.Devices.Wooting/WootingDeviceProvider.cs index e0dc3e5..6decd4a 100644 --- a/RGB.NET.Devices.Wooting/WootingDeviceProvider.cs +++ b/RGB.NET.Devices.Wooting/WootingDeviceProvider.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; using System.Runtime.InteropServices; using RGB.NET.Core; using RGB.NET.Devices.Wooting.Enum; @@ -15,7 +13,7 @@ namespace RGB.NET.Devices.Wooting /// /// Represents a device provider responsible for Wooting devices. /// - public class WootingDeviceProvider : IRGBDeviceProvider + public class WootingDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields @@ -37,20 +35,6 @@ namespace RGB.NET.Devices.Wooting /// public static List PossibleX64NativePaths { get; } = new() { "x64/wooting-rgb-sdk64.dll" }; - /// - /// - /// Indicates if the SDK is initialized and ready to use. - /// - public bool IsInitialized { get; private set; } - - /// - public IEnumerable Devices { get; private set; } = Enumerable.Empty(); - - /// - /// The used to trigger the updates for cooler master devices. - /// - public DeviceUpdateTrigger UpdateTrigger { get; } - #endregion #region Constructors @@ -61,68 +45,42 @@ namespace RGB.NET.Devices.Wooting /// Thrown if this constructor is called even if there is already an instance of this class. public WootingDeviceProvider() { - if (_instance != null) - throw new InvalidOperationException($"There can be only one instance of type {nameof(WootingDeviceProvider)}"); + if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(WootingDeviceProvider)}"); _instance = this; - - UpdateTrigger = new DeviceUpdateTrigger(); } #endregion #region Methods - /// - /// Thrown if the SDK failed to initialize - public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false) + protected override void InitializeSDK() { - IsInitialized = false; + _WootingSDK.Reload(); + } - try + protected override IEnumerable LoadDevices() + { + if (_WootingSDK.KeyboardConnected()) { - UpdateTrigger.Stop(); - - _WootingSDK.Reload(); - - IList devices = new List(); - if (_WootingSDK.KeyboardConnected()) + _WootingDeviceInfo nativeDeviceInfo = (_WootingDeviceInfo)Marshal.PtrToStructure(_WootingSDK.GetDeviceInfo(), typeof(_WootingDeviceInfo))!; + IWootingRGBDevice? device = nativeDeviceInfo.Model switch { - _WootingDeviceInfo nativeDeviceInfo = (_WootingDeviceInfo)Marshal.PtrToStructure(_WootingSDK.GetDeviceInfo(), typeof(_WootingDeviceInfo))!; - IWootingRGBDevice device = nativeDeviceInfo.Model switch - { - "Wooting two" => new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(WootingDevicesIndexes.WootingTwo)), - "Wooting one" => new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(WootingDevicesIndexes.WootingOne)), - _ => throw new RGBDeviceException("No supported Wooting keyboard connected") - }; + "Wooting two" => new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(WootingDevicesIndexes.WootingTwo), GetUpdateTrigger()), + "Wooting one" => new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(WootingDevicesIndexes.WootingOne), GetUpdateTrigger()), + _ => null + }; - device.Initialize(UpdateTrigger); - devices.Add(device); - } - - UpdateTrigger.Start(); - - Devices = new ReadOnlyCollection(devices); - IsInitialized = true; + if (device == null) + Throw(new RGBDeviceException("No supported Wooting keyboard connected")); + else + yield return device; } - catch - { - if (throwExceptions) throw; - return false; - } - - return true; } /// - public void Dispose() + public override void Dispose() { - try { UpdateTrigger.Dispose(); } - catch { /* at least we tried */ } - - foreach (IRGBDevice device in Devices) - try { device.Dispose(); } - catch { /* at least we tried */ } - Devices = Enumerable.Empty(); + base.Dispose(); try { _WootingSDK.Close(); } catch { /* Unlucky.. */ } From 20347cf2216b6caded735034211ac4a465e1423d Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Fri, 5 Mar 2021 10:23:17 +0100 Subject: [PATCH 18/22] Added overridable CreateUpdateTrigger to AbstractRGBDeviceProvider --- RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs b/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs index 7f0c4ef..630bf09 100644 --- a/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs +++ b/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs @@ -82,11 +82,13 @@ namespace RGB.NET.Core protected virtual IDeviceUpdateTrigger GetUpdateTrigger(int id = -1, double? updateRateHardLimit = null) { if (!UpdateTriggers.TryGetValue(id, out IDeviceUpdateTrigger? updaeTrigger)) - UpdateTriggers[id] = (updaeTrigger = new DeviceUpdateTrigger(updateRateHardLimit ?? _defaultUpdateRateHardLimit)); + UpdateTriggers[id] = (updaeTrigger = CreateUpdateTrigger(id, updateRateHardLimit ?? _defaultUpdateRateHardLimit)); return updaeTrigger; } + protected virtual IDeviceUpdateTrigger CreateUpdateTrigger(int id, double updateRateHardLimit) => new DeviceUpdateTrigger(updateRateHardLimit); + protected virtual void Reset() { foreach (IDeviceUpdateTrigger updateTrigger in UpdateTriggers.Values) From 47fd3ff203edbce5261b581640d618ba8c39f83f Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Fri, 5 Mar 2021 21:40:51 +0100 Subject: [PATCH 19/22] Fixed devices not beeing updated --- RGB.NET.Core/Update/Devices/UpdateQueue.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RGB.NET.Core/Update/Devices/UpdateQueue.cs b/RGB.NET.Core/Update/Devices/UpdateQueue.cs index 364ac6b..9330e26 100644 --- a/RGB.NET.Core/Update/Devices/UpdateQueue.cs +++ b/RGB.NET.Core/Update/Devices/UpdateQueue.cs @@ -47,12 +47,13 @@ namespace RGB.NET.Core protected virtual void OnUpdate(object? sender, CustomUpdateData customData) { (TIdentifier, TData)[] dataSet; + Span<(TIdentifier, TData)> data; lock (_dataLock) { if (_currentDataSet.Count == 0) return; dataSet = ArrayPool<(TIdentifier, TData)>.Shared.Rent(_currentDataSet.Count); - Span<(TIdentifier, TData)> data = new Span<(TIdentifier, TData)>(dataSet).Slice(0, _currentDataSet.Count); + data = new Span<(TIdentifier, TData)>(dataSet).Slice(0, _currentDataSet.Count); int i = 0; foreach ((TIdentifier key, TData value) in _currentDataSet) @@ -61,8 +62,7 @@ namespace RGB.NET.Core _currentDataSet.Clear(); } - if (dataSet.Length != 0) - Update(dataSet); + Update(data); ArrayPool<(TIdentifier, TData)>.Shared.Return(dataSet); } From f14e3c801d9c7649d0f9a5bd51792595c11a962b Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Fri, 5 Mar 2021 21:43:12 +0100 Subject: [PATCH 20/22] Moved all methods not directly tied to the surface in an extension and refactored led groups --- RGB.NET.Core/Devices/AbstractRGBDevice.cs | 3 - RGB.NET.Core/Extensions/SurfaceExtensions.cs | 64 +++++++++++++ RGB.NET.Core/Groups/AbstractLedGroup.cs | 21 +++-- RGB.NET.Core/Groups/ILedGroup.cs | 17 ++-- RGB.NET.Core/Groups/LedGroupExtension.cs | 12 +-- RGB.NET.Core/Groups/ListLedGroup.cs | 4 +- RGB.NET.Core/RGBSurface.cs | 94 ++++---------------- RGB.NET.Presets/Groups/RectangleLedGroup.cs | 17 ++-- 8 files changed, 118 insertions(+), 114 deletions(-) create mode 100644 RGB.NET.Core/Extensions/SurfaceExtensions.cs diff --git a/RGB.NET.Core/Devices/AbstractRGBDevice.cs b/RGB.NET.Core/Devices/AbstractRGBDevice.cs index cf47142..7b28a30 100644 --- a/RGB.NET.Core/Devices/AbstractRGBDevice.cs +++ b/RGB.NET.Core/Devices/AbstractRGBDevice.cs @@ -90,9 +90,6 @@ namespace RGB.NET.Core // Send LEDs to SDK List ledsToUpdate = GetLedsToUpdate(flushLeds).ToList(); - foreach (Led ledToUpdate in ledsToUpdate) - ledToUpdate.Update(); - UpdateLeds(ledsToUpdate); } diff --git a/RGB.NET.Core/Extensions/SurfaceExtensions.cs b/RGB.NET.Core/Extensions/SurfaceExtensions.cs new file mode 100644 index 0000000..0a93c69 --- /dev/null +++ b/RGB.NET.Core/Extensions/SurfaceExtensions.cs @@ -0,0 +1,64 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +namespace RGB.NET.Core +{ + public static class SurfaceExtensions + { + #region Methods + + public static void Load(this RGBSurface surface, IRGBDeviceProvider deviceProvider, RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false) + { + if (!deviceProvider.IsInitialized) + deviceProvider.Initialize(loadFilter, throwExceptions); + + surface.Attach(deviceProvider.Devices); + } + + + public static void Attach(this RGBSurface surface, IEnumerable devices) + { + foreach (IRGBDevice device in devices) + surface.Attach(device); + } + + public static void Detach(this RGBSurface surface, IEnumerable devices) + { + foreach (IRGBDevice device in devices) + surface.Detach(device); + } + + /// + /// Gets all devices of a specific type. + /// + /// The type of devices to get. + /// A collection of devices with the specified type. + public static IEnumerable GetDevices(this RGBSurface surface) + where T : class + => surface.Devices.Where(x => x is T).Cast(); + + /// + /// Gets all devices of the specified . + /// + /// The of the devices to get. + /// A collection of devices matching the specified . + public static IEnumerable GetDevices(this RGBSurface surface, RGBDeviceType deviceType) + => surface.Devices.Where(d => deviceType.HasFlag(d.DeviceInfo.DeviceType)); + + /// + /// Automatically aligns all devices to prevent overlaps. + /// + public static void AlignDevices(this RGBSurface surface) + { + float posX = 0; + foreach (IRGBDevice device in surface.Devices) + { + device.Location += new Point(posX, 0); + posX += device.ActualSize.Width + 1; + } + } + + #endregion + } +} diff --git a/RGB.NET.Core/Groups/AbstractLedGroup.cs b/RGB.NET.Core/Groups/AbstractLedGroup.cs index 3720302..c035937 100644 --- a/RGB.NET.Core/Groups/AbstractLedGroup.cs +++ b/RGB.NET.Core/Groups/AbstractLedGroup.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System.Collections; +using System.Collections.Generic; namespace RGB.NET.Core { @@ -11,7 +12,8 @@ namespace RGB.NET.Core { #region Properties & Fields - public RGBSurface? Surface { get; private set; } + RGBSurface? ILedGroup.Surface { get; set; } + public RGBSurface? Surface => ((ILedGroup)this).Surface; /// public IBrush? Brush { get; set; } @@ -28,21 +30,26 @@ namespace RGB.NET.Core /// protected AbstractLedGroup(RGBSurface? attachTo) { - attachTo?.AttachLedGroup(this); + attachTo?.Attach(this); } #endregion #region Methods - /// - public abstract IList GetLeds(); + protected abstract IEnumerable GetLeds(); /// - public virtual void OnAttach(RGBSurface surface) => Surface = surface; + public virtual void OnAttach() { } /// - public virtual void OnDetach(RGBSurface surface) => Surface = null; + public virtual void OnDetach() { } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public IEnumerator GetEnumerator() => GetLeds().GetEnumerator(); #endregion } diff --git a/RGB.NET.Core/Groups/ILedGroup.cs b/RGB.NET.Core/Groups/ILedGroup.cs index 3985f8a..adcf9b7 100644 --- a/RGB.NET.Core/Groups/ILedGroup.cs +++ b/RGB.NET.Core/Groups/ILedGroup.cs @@ -5,13 +5,14 @@ using System.Collections.Generic; namespace RGB.NET.Core { - /// /// /// Represents a generic ledgroup. /// - public interface ILedGroup : IDecoratable + public interface ILedGroup : IDecoratable, IEnumerable { - public RGBSurface? Surface { get; } + RGBSurface? Surface { get; internal set; } + + bool IsAttached => Surface != null; /// /// Gets or sets the which should be drawn over this . @@ -23,20 +24,14 @@ namespace RGB.NET.Core /// int ZIndex { get; set; } - /// - /// Gets a list containing all of this . - /// - /// The list containing all of this . - IList GetLeds(); - /// /// Called when the is attached to the . /// - void OnAttach(RGBSurface surface); + void OnAttach(); /// /// Called when the is detached from the . /// - void OnDetach(RGBSurface surface); + void OnDetach(); } } diff --git a/RGB.NET.Core/Groups/LedGroupExtension.cs b/RGB.NET.Core/Groups/LedGroupExtension.cs index 3a8c9f7..3d29d4c 100644 --- a/RGB.NET.Core/Groups/LedGroupExtension.cs +++ b/RGB.NET.Core/Groups/LedGroupExtension.cs @@ -16,11 +16,11 @@ namespace RGB.NET.Core public static ListLedGroup ToListLedGroup(this ILedGroup ledGroup) { // ReSharper disable once InvertIf - if (!(ledGroup is ListLedGroup listLedGroup)) + if (ledGroup is not ListLedGroup listLedGroup) { - if (ledGroup.Surface != null) - ledGroup.Detach(ledGroup.Surface); - listLedGroup = new ListLedGroup(ledGroup.Surface, ledGroup.GetLeds()) { Brush = ledGroup.Brush }; + if (ledGroup.IsAttached) + ledGroup.Detach(); + listLedGroup = new ListLedGroup(ledGroup.Surface, ledGroup) { Brush = ledGroup.Brush, ZIndex = ledGroup.ZIndex }; } return listLedGroup; } @@ -45,13 +45,13 @@ namespace RGB.NET.Core /// /// The to attach. /// true if the could be attached; otherwise, false. - public static bool Attach(this ILedGroup ledGroup, RGBSurface surface) => surface.AttachLedGroup(ledGroup); + public static bool Attach(this ILedGroup ledGroup, RGBSurface surface) => surface.Attach(ledGroup); /// /// Detaches the given from the . /// /// The to attach. /// true if the could be detached; otherwise, false. - public static bool Detach(this ILedGroup ledGroup, RGBSurface surface) => surface.DetachLedGroup(ledGroup); + public static bool Detach(this ILedGroup ledGroup) => ledGroup.Surface?.Detach(ledGroup) ?? false; } } diff --git a/RGB.NET.Core/Groups/ListLedGroup.cs b/RGB.NET.Core/Groups/ListLedGroup.cs index f4aa007..b6be55b 100644 --- a/RGB.NET.Core/Groups/ListLedGroup.cs +++ b/RGB.NET.Core/Groups/ListLedGroup.cs @@ -113,7 +113,7 @@ namespace RGB.NET.Core public void MergeLeds(ILedGroup groupToMerge) { lock (GroupLeds) - foreach (Led led in groupToMerge.GetLeds()) + foreach (Led led in groupToMerge) if (!GroupLeds.Contains(led)) GroupLeds.Add(led); } @@ -123,7 +123,7 @@ namespace RGB.NET.Core /// Gets a list containing the from this group. /// /// The list containing the . - public override IList GetLeds() + protected override IEnumerable GetLeds() { lock (GroupLeds) return new List(GroupLeds); diff --git a/RGB.NET.Core/RGBSurface.cs b/RGB.NET.Core/RGBSurface.cs index 94169b5..5a26b68 100644 --- a/RGB.NET.Core/RGBSurface.cs +++ b/RGB.NET.Core/RGBSurface.cs @@ -14,20 +14,15 @@ namespace RGB.NET.Core /// /// Represents a RGB-surface containing multiple devices. /// - public class RGBSurface : AbstractBindable, IDisposable + public sealed class RGBSurface : AbstractBindable, IDisposable { #region Properties & Fields private Stopwatch _deltaTimeCounter; - private IList _devices = new List(); - private IList _updateTriggers = new List(); - - // ReSharper disable InconsistentNaming - - private readonly LinkedList _ledGroups = new(); - - // ReSharper restore InconsistentNaming + private readonly IList _devices = new List(); + private readonly IList _updateTriggers = new List(); + private readonly List _ledGroups = new List(); /// /// Gets a readonly list containing all loaded . @@ -160,7 +155,7 @@ namespace RGB.NET.Core lock (_ledGroups) { // Render brushes - foreach (ILedGroup ledGroup in _ledGroups.OrderBy(x => x.ZIndex)) + foreach (ILedGroup ledGroup in _ledGroups) try { Render(ledGroup); } catch (Exception ex) { OnException(ex); } } @@ -170,6 +165,9 @@ namespace RGB.NET.Core try { device.Update(flushLeds); } catch (Exception ex) { OnException(ex); } + foreach (Led led in Leds) + led.Update(); + OnUpdated(); } } @@ -204,7 +202,7 @@ namespace RGB.NET.Core /// Thrown if the of the Brush is not valid. private void Render(ILedGroup ledGroup) { - IList leds = ledGroup.GetLeds().ToList(); + IList leds = ledGroup.ToList(); IBrush? brush = ledGroup.Brush; if ((brush == null) || !brush.IsEnabled) return; @@ -234,14 +232,16 @@ namespace RGB.NET.Core /// /// The to attach. /// true if the could be attached; otherwise, false. - public bool AttachLedGroup(ILedGroup ledGroup) + public bool Attach(ILedGroup ledGroup) { lock (_ledGroups) { - if (_ledGroups.Contains(ledGroup)) return false; + if (ledGroup.Surface != null) return false; - _ledGroups.AddLast(ledGroup); - ledGroup.OnAttach(this); + ledGroup.Surface = this; + _ledGroups.Add(ledGroup); + _ledGroups.Sort((group1, group2) => group1.ZIndex.CompareTo(group2.ZIndex)); + ledGroup.OnAttach(); return true; } @@ -252,29 +252,18 @@ namespace RGB.NET.Core /// /// The to detached. /// true if the could be detached; otherwise, false. - public bool DetachLedGroup(ILedGroup ledGroup) + public bool Detach(ILedGroup ledGroup) { lock (_ledGroups) { - LinkedListNode? node = _ledGroups.Find(ledGroup); - if (node == null) return false; - - _ledGroups.Remove(node); - node.Value.OnDetach(this); + if (!_ledGroups.Remove(ledGroup)) return false; + ledGroup.OnDetach(); + ledGroup.Surface = null; return true; } } - public void Attach(IEnumerable devices) - { - lock (_devices) - { - foreach (IRGBDevice device in devices) - Attach(device); - } - } - public void Attach(IRGBDevice device) { lock (_devices) @@ -289,15 +278,6 @@ namespace RGB.NET.Core } } - public void Detach(IEnumerable devices) - { - lock (_devices) - { - foreach (IRGBDevice device in devices) - Detach(device); - } - } - public void Detach(IRGBDevice device) { lock (_devices) @@ -313,19 +293,6 @@ namespace RGB.NET.Core } } - /// - /// Automatically aligns all devices to prevent overlaps. - /// - public void AlignDevices() - { - float posX = 0; - foreach (IRGBDevice device in Devices) - { - device.Location += new Point(posX, 0); - posX += device.ActualSize.Width + 1; - } - } - // ReSharper restore UnusedMember.Global private void DeviceOnBoundaryChanged(object? sender, EventArgs args) @@ -347,29 +314,6 @@ namespace RGB.NET.Core } } - /// - /// Gets all devices of a specific type. - /// - /// The type of devices to get. - /// A list of devices with the specified type. - public IList GetDevices() - where T : class - { - lock (_devices) - return new ReadOnlyCollection(_devices.Where(x => x is T).Cast().ToList()); - } - - /// - /// Gets all devices of the specified . - /// - /// The of the devices to get. - /// a list of devices matching the specified . - public IList GetDevices(RGBDeviceType deviceType) - { - lock (_devices) - return new ReadOnlyCollection(_devices.Where(d => deviceType.HasFlag(d.DeviceInfo.DeviceType)).ToList()); - } - /// /// Registers the provided . /// diff --git a/RGB.NET.Presets/Groups/RectangleLedGroup.cs b/RGB.NET.Presets/Groups/RectangleLedGroup.cs index b024405..a17ff98 100644 --- a/RGB.NET.Presets/Groups/RectangleLedGroup.cs +++ b/RGB.NET.Presets/Groups/RectangleLedGroup.cs @@ -93,21 +93,18 @@ namespace RGB.NET.Presets.Groups #region Methods /// - public override void OnAttach(RGBSurface surface) + public override void OnAttach() { - base.OnAttach(surface); - - if (Surface != null) - Surface.SurfaceLayoutChanged += RGBSurfaceOnSurfaceLayoutChanged; + base.OnAttach(); + Surface!.SurfaceLayoutChanged += RGBSurfaceOnSurfaceLayoutChanged; } /// - public override void OnDetach(RGBSurface surface) + public override void OnDetach() { - if (Surface != null) - Surface.SurfaceLayoutChanged -= RGBSurfaceOnSurfaceLayoutChanged; + Surface!.SurfaceLayoutChanged -= RGBSurfaceOnSurfaceLayoutChanged; - base.OnDetach(surface); + base.OnDetach(); } private void RGBSurfaceOnSurfaceLayoutChanged(SurfaceLayoutChangedEventArgs args) => InvalidateCache(); @@ -117,7 +114,7 @@ namespace RGB.NET.Presets.Groups /// Gets a list containing all of this . /// /// The list containing all of this . - public override IList GetLeds() => _ledCache ??= (Surface?.Leds.Where(led => led.AbsoluteBoundary.CalculateIntersectPercentage(Rectangle) >= MinOverlayPercentage).ToList() ?? new List()); + protected override IEnumerable GetLeds() => _ledCache ??= (Surface?.Leds.Where(led => led.AbsoluteBoundary.CalculateIntersectPercentage(Rectangle) >= MinOverlayPercentage).ToList() ?? new List()); private void InvalidateCache() => _ledCache = null; From 438e5c576a0618d0cebeb5564ab1f9123c515fee Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Fri, 5 Mar 2021 21:45:56 +0100 Subject: [PATCH 21/22] Small refactoring --- RGB.NET.Core/Extensions/SurfaceExtensions.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/RGB.NET.Core/Extensions/SurfaceExtensions.cs b/RGB.NET.Core/Extensions/SurfaceExtensions.cs index 0a93c69..fb53fc0 100644 --- a/RGB.NET.Core/Extensions/SurfaceExtensions.cs +++ b/RGB.NET.Core/Extensions/SurfaceExtensions.cs @@ -1,5 +1,6 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; +// ReSharper disable UnusedMember.Global + +using System.Collections.Generic; using System.Linq; namespace RGB.NET.Core From e6290ae48018f312269ab2d92231d7594113ba6e Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Fri, 5 Mar 2021 22:59:09 +0100 Subject: [PATCH 22/22] Fixed leds not updating --- RGB.NET.Core/Devices/AbstractRGBDevice.cs | 6 +++++- RGB.NET.Core/RGBSurface.cs | 3 --- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/RGB.NET.Core/Devices/AbstractRGBDevice.cs b/RGB.NET.Core/Devices/AbstractRGBDevice.cs index 7b28a30..db8dba1 100644 --- a/RGB.NET.Core/Devices/AbstractRGBDevice.cs +++ b/RGB.NET.Core/Devices/AbstractRGBDevice.cs @@ -90,10 +90,14 @@ namespace RGB.NET.Core // Send LEDs to SDK List ledsToUpdate = GetLedsToUpdate(flushLeds).ToList(); + + foreach (Led led in ledsToUpdate) + led.Update(); + UpdateLeds(ledsToUpdate); } - protected virtual IEnumerable GetLedsToUpdate(bool flushLeds) => ((RequiresFlush || flushLeds) ? LedMapping.Values : LedMapping.Values.Where(x => x.IsDirty)).Where(led => led.Color.A > 0); + protected virtual IEnumerable GetLedsToUpdate(bool flushLeds) => ((RequiresFlush || flushLeds) ? LedMapping.Values : LedMapping.Values.Where(x => x.IsDirty)).Where(led => led.RequestedColor?.A > 0); protected virtual IEnumerable<(object key, Color color)> GetUpdateData(IEnumerable leds) { if (ColorCorrections.Count > 0) diff --git a/RGB.NET.Core/RGBSurface.cs b/RGB.NET.Core/RGBSurface.cs index 5a26b68..692e158 100644 --- a/RGB.NET.Core/RGBSurface.cs +++ b/RGB.NET.Core/RGBSurface.cs @@ -165,9 +165,6 @@ namespace RGB.NET.Core try { device.Update(flushLeds); } catch (Exception ex) { OnException(ex); } - foreach (Led led in Leds) - led.Update(); - OnUpdated(); } }