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}