mirror of
https://github.com/DarthAffe/RGB.NET.git
synced 2025-12-13 10:08:31 +00:00
Merge pull request #58 from DarthAffe/Development
Merge develop to master
This commit is contained in:
commit
74d52df866
@ -97,10 +97,10 @@ namespace RGB.NET.Brushes.Gradients
|
||||
if (!gsBefore.Offset.Equals(gsAfter.Offset))
|
||||
blendFactor = ((offset - gsBefore.Offset) / (gsAfter.Offset - gsBefore.Offset));
|
||||
|
||||
byte colA = (byte)(((gsAfter.Color.A - gsBefore.Color.A) * blendFactor) + gsBefore.Color.A);
|
||||
byte colR = (byte)(((gsAfter.Color.R - gsBefore.Color.R) * blendFactor) + gsBefore.Color.R);
|
||||
byte colG = (byte)(((gsAfter.Color.G - gsBefore.Color.G) * blendFactor) + gsBefore.Color.G);
|
||||
byte colB = (byte)(((gsAfter.Color.B - gsBefore.Color.B) * blendFactor) + gsBefore.Color.B);
|
||||
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;
|
||||
|
||||
return new Color(colA, colR, colG, colB);
|
||||
}
|
||||
|
||||
@ -73,10 +73,8 @@ namespace RGB.NET.Brushes.Gradients
|
||||
public Color GetColor(double offset)
|
||||
{
|
||||
double range = EndHue - StartHue;
|
||||
double hue = (StartHue + (range * offset)) % 360f;
|
||||
if (hue < 0)
|
||||
hue += 360;
|
||||
return Color.FromHSV(hue, 1, 1);
|
||||
double hue = StartHue + (range * offset);
|
||||
return HSVColor.Create(hue, 1, 1);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -87,7 +85,7 @@ namespace RGB.NET.Brushes.Gradients
|
||||
|
||||
StartHue += offset;
|
||||
EndHue += offset;
|
||||
|
||||
|
||||
while ((StartHue > 360) && (EndHue > 360))
|
||||
{
|
||||
StartHue -= 360;
|
||||
|
||||
@ -115,7 +115,7 @@ namespace RGB.NET.Core
|
||||
// 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!!!
|
||||
return color.MultiplyValue(Brightness.Clamp(0, 1))
|
||||
return color.MultiplyHSV(value: Brightness.Clamp(0, 1))
|
||||
.MultiplyA(Opacity.Clamp(0, 1));
|
||||
}
|
||||
|
||||
|
||||
80
RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs
Normal file
80
RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs
Normal file
@ -0,0 +1,80 @@
|
||||
namespace RGB.NET.Core
|
||||
{
|
||||
public class DefaultColorBehavior : IColorBehavior
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private static DefaultColorBehavior _instance = new DefaultColorBehavior();
|
||||
/// <summary>
|
||||
/// Gets the singleton instance of <see cref="DefaultColorBehavior"/>.
|
||||
/// </summary>
|
||||
public static DefaultColorBehavior Instance { get; } = _instance;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
private DefaultColorBehavior()
|
||||
{ }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Converts the individual byte values of this <see cref="Color"/> to a human-readable string.
|
||||
/// </summary>
|
||||
/// <returns>A string that contains the individual byte values of this <see cref="Color"/>. For example "[A: 255, R: 255, G: 0, B: 0]".</returns>
|
||||
public virtual string ToString(Color color) => $"[A: {color.GetA()}, R: {color.GetR()}, G: {color.GetG()}, B: {color.GetB()}]";
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the specified object is a <see cref="Color" /> and is equivalent to this <see cref="Color" />.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to test.</param>
|
||||
/// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Color" /> equivalent to this <see cref="Color" />; otherwise, <c>false</c>.</returns>
|
||||
public virtual bool Equals(Color color, object obj)
|
||||
{
|
||||
if (!(obj is Color)) return false;
|
||||
|
||||
(double a, double r, double g, double b) = ((Color)obj).GetRGB();
|
||||
return color.A.EqualsInTolerance(a) && color.R.EqualsInTolerance(r) && color.G.EqualsInTolerance(g) && color.B.EqualsInTolerance(b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a hash code for this <see cref="Color" />.
|
||||
/// </summary>
|
||||
/// <returns>An integer value that specifies the hash code for this <see cref="Color" />.</returns>
|
||||
public virtual int GetHashCode(Color color)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hashCode = color.A.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ color.R.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ color.G.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ color.B.GetHashCode();
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Blends a <see cref="Color"/> over this color.
|
||||
/// </summary>
|
||||
/// <param name="color">The <see cref="Color"/> to blend.</param>
|
||||
public virtual Color Blend(Color baseColor, Color blendColor)
|
||||
{
|
||||
if (blendColor.A.EqualsInTolerance(0)) return baseColor;
|
||||
|
||||
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));
|
||||
|
||||
return new Color(resultA, resultR, resultG, resultB);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
13
RGB.NET.Core/Color/Behaviors/IColorBehavior.cs
Normal file
13
RGB.NET.Core/Color/Behaviors/IColorBehavior.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace RGB.NET.Core
|
||||
{
|
||||
public interface IColorBehavior
|
||||
{
|
||||
string ToString(Color color);
|
||||
|
||||
bool Equals(Color color, object obj);
|
||||
|
||||
int GetHashCode(Color color);
|
||||
|
||||
Color Blend(Color baseColor, Color blendColor);
|
||||
}
|
||||
}
|
||||
288
RGB.NET.Core/Color/Color.cs
Normal file
288
RGB.NET.Core/Color/Color.cs
Normal file
@ -0,0 +1,288 @@
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable UnusedMember.Global
|
||||
// ReSharper disable UnusedMethodReturnValue.Global
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace RGB.NET.Core
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents an ARGB (alpha, red, green, blue) color.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("[A: {A}, R: {R}, G: {G}, B: {B}]")]
|
||||
public struct Color
|
||||
{
|
||||
#region Constants
|
||||
|
||||
/// <summary>
|
||||
/// Gets an transparent color [A: 0, R: 0, G: 0, B: 0]
|
||||
/// </summary>
|
||||
public static Color Transparent => new Color(0, 0, 0, 0);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
private static IColorBehavior _behavior = DefaultColorBehavior.Instance;
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="IColorBehavior"/> used to perform operations on colors.
|
||||
/// </summary>
|
||||
public static IColorBehavior Behavior
|
||||
{
|
||||
get => _behavior;
|
||||
set => _behavior = value ?? DefaultColorBehavior.Instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the alpha component value of this <see cref="Color"/> as percentage in the range [0..1].
|
||||
/// </summary>
|
||||
public double A { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the red component value of this <see cref="Color"/> as percentage in the range [0..1].
|
||||
/// </summary>
|
||||
public double R { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the green component value of this <see cref="Color"/> as percentage in the range [0..1].
|
||||
/// </summary>
|
||||
public double G { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the blue component value of this <see cref="Color"/> as percentage in the range [0..1].
|
||||
/// </summary>
|
||||
public double B { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using RGB-Values.
|
||||
/// Alpha defaults to 255.
|
||||
/// </summary>
|
||||
/// <param name="r">The red component value of this <see cref="T:RGB.NET.Core.Color" />.</param>
|
||||
/// <param name="g">The green component value of this <see cref="T:RGB.NET.Core.Color" />.</param>
|
||||
/// <param name="b">The blue component value of this <see cref="T:RGB.NET.Core.Color" />.</param>
|
||||
public Color(byte r, byte g, byte b)
|
||||
: this(byte.MaxValue, r, g, b)
|
||||
{ }
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using RGB-Values.
|
||||
/// Alpha defaults to 255.
|
||||
/// </summary>
|
||||
/// <param name="r">The red component value of this <see cref="T:RGB.NET.Core.Color" />.</param>
|
||||
/// <param name="g">The green component value of this <see cref="T:RGB.NET.Core.Color" />.</param>
|
||||
/// <param name="b">The blue component value of this <see cref="T:RGB.NET.Core.Color" />.</param>
|
||||
public Color(int r, int g, int b)
|
||||
: this((byte)r.Clamp(0, byte.MaxValue), (byte)g.Clamp(0, byte.MaxValue), (byte)b.Clamp(0, byte.MaxValue))
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Color"/> struct using ARGB values.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="r">The red component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="g">The green component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="b">The blue component value of this <see cref="Color"/>.</param>
|
||||
public Color(byte a, byte r, byte g, byte b)
|
||||
: this(a.GetPercentageFromByteValue(), r.GetPercentageFromByteValue(), g.GetPercentageFromByteValue(), b.GetPercentageFromByteValue())
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Color"/> struct using ARGB values.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="r">The red component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="g">The green component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="b">The blue component value of this <see cref="Color"/>.</param>
|
||||
public Color(int a, int r, int g, int b)
|
||||
: this((byte)a.Clamp(0, byte.MaxValue), (byte)r.Clamp(0, byte.MaxValue), (byte)g.Clamp(0, byte.MaxValue), (byte)b.Clamp(0, byte.MaxValue))
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Color"/> struct using RGB-percent values.
|
||||
/// Alpha defaults to 1.0.
|
||||
/// </summary>
|
||||
/// <param name="r">The red component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="g">The green component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="b">The blue component value of this <see cref="Color"/>.</param>
|
||||
public Color(double r, double g, double b)
|
||||
: this(1.0, r, g, b)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Color"/> struct using ARGB-percent values.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="r">The red component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="g">The green component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="b">The blue component value of this <see cref="Color"/>.</param>
|
||||
public Color(double a, byte r, byte g, byte b)
|
||||
: this(a, r.GetPercentageFromByteValue(), g.GetPercentageFromByteValue(), b.GetPercentageFromByteValue())
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Color"/> struct using ARGB-percent values.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="r">The red component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="g">The green component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="b">The blue component value of this <see cref="Color"/>.</param>
|
||||
public Color(double 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))
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Color"/> struct using ARGB-percent values.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="r">The red component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="g">The green component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="b">The blue component value of this <see cref="Color"/>.</param>
|
||||
public Color(int a, double r, double g, double b)
|
||||
: this((byte)a.Clamp(0, byte.MaxValue), r, g, b)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Color"/> struct using ARGB-percent values.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="r">The red component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="g">The green component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="b">The blue component value of this <see cref="Color"/>.</param>
|
||||
public Color(byte a, double r, double g, double b)
|
||||
: this(a.GetPercentageFromByteValue(), r, g, b)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Color"/> struct using ARGB-percent values.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="r">The red component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="g">The green component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="b">The blue component value of this <see cref="Color"/>.</param>
|
||||
public Color(double a, double r, double g, double b)
|
||||
{
|
||||
A = a.Clamp(0, 1);
|
||||
R = r.Clamp(0, 1);
|
||||
G = g.Clamp(0, 1);
|
||||
B = b.Clamp(0, 1);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct by cloning a existing <see cref="T:RGB.NET.Core.Color" />.
|
||||
/// </summary>
|
||||
/// <param name="color">The <see cref="T:RGB.NET.Core.Color" /> the values are copied from.</param>
|
||||
public Color(Color color)
|
||||
: this(color.A, color.R, color.G, color.B)
|
||||
{ }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Gets a human-readable string, as defined by the current <see cref="Behavior"/>.
|
||||
/// </summary>
|
||||
/// <returns>A string that contains the individual byte values of this <see cref="Color"/>. Default format: "[A: 255, R: 255, G: 0, B: 0]".</returns>
|
||||
public override string ToString() => Behavior.ToString(this);
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the specified object is a <see cref="Color" /> and is equivalent to this <see cref="Color" />, as defined by the current <see cref="Behavior"/>.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to test.</param>
|
||||
/// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Color" /> equivalent to this <see cref="Color" />; otherwise, <c>false</c>.</returns>
|
||||
public override bool Equals(object obj) => Behavior.Equals(this, obj);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a hash code for this <see cref="Color" />, as defined by the current <see cref="Behavior"/>.
|
||||
/// </summary>
|
||||
/// <returns>An integer value that specifies the hash code for this <see cref="Color" />.</returns>
|
||||
public override int GetHashCode() => Behavior.GetHashCode(this);
|
||||
|
||||
/// <summary>
|
||||
/// Blends a <see cref="Color"/> over this color, as defined by the current <see cref="Behavior"/>.
|
||||
/// </summary>
|
||||
/// <param name="color">The <see cref="Color"/> to blend.</param>
|
||||
public Color Blend(Color color) => Behavior.Blend(this, color);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
|
||||
/// <summary>
|
||||
/// Blends the provided colors as if <see cref="Blend"/> would've been called on <paramref name="color1" />.
|
||||
/// </summary>
|
||||
/// <param name="color1">The base color.</param>
|
||||
/// <param name="color2">The color to blend.</param>
|
||||
/// <returns>The blended color.</returns>
|
||||
public static Color operator +(Color color1, Color color2) => color1.Blend(color2);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value that indicates whether two specified <see cref="Color" /> are equal.
|
||||
/// </summary>
|
||||
/// <param name="color1">The first <see cref="Color" /> to compare.</param>
|
||||
/// <param name="color2">The second <see cref="Color" /> to compare.</param>
|
||||
/// <returns><c>true</c> if <paramref name="color1" /> and <paramref name="color2" /> are equal; otherwise, <c>false</c>.</returns>
|
||||
public static bool operator ==(Color color1, Color color2) => color1.Equals(color2);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value that indicates whether two specified <see cref="Color" /> are equal.
|
||||
/// </summary>
|
||||
/// <param name="color1">The first <see cref="Color" /> to compare.</param>
|
||||
/// <param name="color2">The second <see cref="Color" /> to compare.</param>
|
||||
/// <returns><c>true</c> if <paramref name="color1" /> and <paramref name="color2" /> are not equal; otherwise, <c>false</c>.</returns>
|
||||
public static bool operator !=(Color color1, Color color2) => !(color1 == color2);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="ValueTuple"/> of ARGB-components to a <see cref="Color"/>.
|
||||
/// </summary>
|
||||
/// <param name="components">The <see cref="ValueTuple"/> containing the components.</param>
|
||||
/// <returns>The color.</returns>
|
||||
public static implicit operator Color((byte r, byte g, byte b) components) => new Color(components.r, components.g, components.b);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="ValueTuple"/> of ARGB-components to a <see cref="Color"/>.
|
||||
/// </summary>
|
||||
/// <param name="components">The <see cref="ValueTuple"/> containing the components.</param>
|
||||
/// <returns>The color.</returns>
|
||||
public static implicit operator Color((byte a, byte r, byte g, byte b) components) => new Color(components.a, components.r, components.g, components.b);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="ValueTuple"/> of ARGB-components to a <see cref="Color"/>.
|
||||
/// </summary>
|
||||
/// <param name="components">The <see cref="ValueTuple"/> containing the components.</param>
|
||||
/// <returns>The color.</returns>
|
||||
public static implicit operator Color((int r, int g, int b) components) => new Color(components.r, components.g, components.b);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="ValueTuple"/> of ARGB-components to a <see cref="Color"/>.
|
||||
/// </summary>
|
||||
/// <param name="components">The <see cref="ValueTuple"/> containing the components.</param>
|
||||
/// <returns>The color.</returns>
|
||||
public static implicit operator Color((int a, int r, int g, int b) components) => new Color(components.a, components.r, components.g, components.b);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="ValueTuple"/> of ARGB-components to a <see cref="Color"/>.
|
||||
/// </summary>
|
||||
/// <param name="components">The <see cref="ValueTuple"/> containing the components.</param>
|
||||
/// <returns>The color.</returns>
|
||||
public static implicit operator Color((double r, double g, double b) components) => new Color(components.r, components.g, components.b);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="ValueTuple"/> of ARGB-components to a <see cref="Color"/>.
|
||||
/// </summary>
|
||||
/// <param name="components">The <see cref="ValueTuple"/> containing the components.</param>
|
||||
/// <returns>The color.</returns>
|
||||
public static implicit operator Color((double a, double r, double g, double b) components) => new Color(components.a, components.r, components.g, components.b);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
227
RGB.NET.Core/Color/HSVColor.cs
Normal file
227
RGB.NET.Core/Color/HSVColor.cs
Normal file
@ -0,0 +1,227 @@
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable UnusedMember.Global
|
||||
using System;
|
||||
|
||||
namespace RGB.NET.Core
|
||||
{
|
||||
public static class HSVColor
|
||||
{
|
||||
#region Getter
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hue component value (HSV-color space) of this <see cref="Color"/> as degree in the range [0..360].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static double GetHue(this Color color) => color.GetHSV().hue;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the saturation component value (HSV-color space) of this <see cref="Color"/> in the range [0..1].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static double GetSaturation(this Color color) => color.GetHSV().saturation;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value component value (HSV-color space) of this <see cref="Color"/> in the range [0..1].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static double GetValue(this Color color) => color.GetHSV().value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hue, saturation and value component values (HSV-color space) of this <see cref="Color"/>.
|
||||
/// Hue as degree in the range [0..1].
|
||||
/// Saturation in the range [0..1].
|
||||
/// Value in the range [0..1].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static (double hue, double saturation, double value) GetHSV(this Color color)
|
||||
=> CaclulateHSVFromRGB(color.R, color.G, color.B);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Manipulation
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given HSV values to this color.
|
||||
/// </summary>
|
||||
/// <param name="hue">The hue value to add.</param>
|
||||
/// <param name="saturation">The saturation value to add.</param>
|
||||
/// <param name="value">The value value to add.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color AddHSV(this Color color, double hue = 0, double saturation = 0, double value = 0)
|
||||
{
|
||||
(double cHue, double cSaturation, double cValue) = color.GetHSV();
|
||||
return Create(color.A, cHue + hue, cSaturation + saturation, cValue + value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the given HSV values to this color.
|
||||
/// </summary>
|
||||
/// <param name="hue">The hue value to subtract.</param>
|
||||
/// <param name="saturation">The saturation value to subtract.</param>
|
||||
/// <param name="value">The value value to subtract.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color SubtractHSV(this Color color, double hue = 0, double saturation = 0, double value = 0)
|
||||
{
|
||||
(double cHue, double cSaturation, double cValue) = color.GetHSV();
|
||||
return Create(color.A, cHue - hue, cSaturation - saturation, cValue - value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies the given HSV values to this color.
|
||||
/// </summary>
|
||||
/// <param name="hue">The hue value to multiply.</param>
|
||||
/// <param name="saturation">The saturation value to multiply.</param>
|
||||
/// <param name="value">The value value to multiply.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color MultiplyHSV(this Color color, double hue = 1, double saturation = 1, double value = 1)
|
||||
{
|
||||
(double cHue, double cSaturation, double cValue) = color.GetHSV();
|
||||
return Create(color.A, cHue * hue, cSaturation * saturation, cValue * value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the given HSV values to this color.
|
||||
/// </summary>
|
||||
/// <param name="hue">The hue value to divide.</param>
|
||||
/// <param name="saturation">The saturation value to divide.</param>
|
||||
/// <param name="value">The value value to divide.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color DivideHSV(this Color color, double hue = 1, double saturation = 1, double value = 1)
|
||||
{
|
||||
(double cHue, double cSaturation, double cValue) = color.GetHSV();
|
||||
return Create(color.A, cHue / hue, cSaturation / saturation, cValue / value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the given hue value of this color.
|
||||
/// </summary>
|
||||
/// <param name="hue">The hue value to set.</param>
|
||||
/// <param name="saturation">The saturation value to set.</param>
|
||||
/// <param name="value">The value value to set.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color SetHSV(this Color color, double? hue = null, double? saturation = null, double? value = null)
|
||||
{
|
||||
(double cHue, double cSaturation, double cValue) = color.GetHSV();
|
||||
return Create(color.A, hue ?? cHue, saturation ?? cSaturation, value ?? cValue);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Factory
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using HSV-Values.
|
||||
/// </summary>
|
||||
/// <param name="hue">The hue component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="saturation">The saturation component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="value">The value component value of this <see cref="Color"/>.</param>
|
||||
/// <returns>The color created from the values.</returns>
|
||||
public static Color Create(double hue, double saturation, double value)
|
||||
=> Create(1.0, hue, saturation, value);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using AHSV-Values.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="hue">The hue component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="saturation">The saturation component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="value">The value component value of this <see cref="Color"/>.</param>
|
||||
/// <returns>The color created from the values.</returns>
|
||||
public static Color Create(byte a, double hue, double saturation, double value)
|
||||
=> Create((double)a / byte.MaxValue, hue, saturation, value);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using AHSV-Values.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="hue">The hue component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="saturation">The saturation component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="value">The value component value of this <see cref="Color"/>.</param>
|
||||
/// <returns>The color created from the values.</returns>
|
||||
public static Color Create(int a, double hue, double saturation, double value)
|
||||
=> Create((double)a / byte.MaxValue, hue, saturation, value);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using AHSV-Values.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="hue">The hue component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="saturation">The saturation component value of this <see cref="Color"/>.</param>
|
||||
/// <param name="value">The value component value of this <see cref="Color"/>.</param>
|
||||
/// <returns>The color created from the values.</returns>
|
||||
public static Color Create(double a, double hue, double saturation, double value)
|
||||
{
|
||||
(double r, double g, double b) = CalculateRGBFromHSV(hue, saturation, value);
|
||||
return new Color(a, r, g, b);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper
|
||||
|
||||
private static (double h, double s, double v) CaclulateHSVFromRGB(double r, double g, double 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);
|
||||
|
||||
double 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));
|
||||
else // b is max
|
||||
hue = 4.0 + ((r - g) / (max - min));
|
||||
|
||||
hue = hue * 60.0;
|
||||
hue = hue.Wrap(0, 360);
|
||||
|
||||
double saturation = max.EqualsInTolerance(0) ? 0 : 1.0 - (min / max);
|
||||
double 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)
|
||||
{
|
||||
h = h.Wrap(0, 360);
|
||||
s = s.Clamp(0, 1);
|
||||
v = v.Clamp(0, 1);
|
||||
|
||||
if (s <= 0.0)
|
||||
return (v, v, v);
|
||||
|
||||
double hh = h / 60.0;
|
||||
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)));
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
return (v, t, p);
|
||||
case 1:
|
||||
return (q, v, p);
|
||||
case 2:
|
||||
return (p, v, t);
|
||||
case 3:
|
||||
return (p, q, v);
|
||||
case 4:
|
||||
return (t, p, v);
|
||||
default:
|
||||
return (v, p, q);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
275
RGB.NET.Core/Color/RGBColor.cs
Normal file
275
RGB.NET.Core/Color/RGBColor.cs
Normal file
@ -0,0 +1,275 @@
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable UnusedMember.Global
|
||||
using System;
|
||||
|
||||
namespace RGB.NET.Core
|
||||
{
|
||||
public static class RGBColor
|
||||
{
|
||||
#region Getter
|
||||
|
||||
/// <summary>
|
||||
/// Gets the A component value of this <see cref="Color"/> as byte in the range [0..255].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static byte GetA(this Color color) => color.A.GetByteValueFromPercentage();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the R component value of this <see cref="Color"/> as byte in the range [0..255].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static byte GetR(this Color color) => color.R.GetByteValueFromPercentage();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the G component value of this <see cref="Color"/> as byte in the range [0..255].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static byte GetG(this Color color) => color.G.GetByteValueFromPercentage();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the B component value of this <see cref="Color"/> as byte in the range [0..255].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static byte GetB(this Color color) => color.B.GetByteValueFromPercentage();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the A, R, G and B component value of this <see cref="Color"/> as byte in the range [0..255].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static (byte a, byte r, byte g, byte b) GetRGBBytes(this Color color)
|
||||
=> (color.GetA(), color.GetR(), color.GetG(), color.GetB());
|
||||
|
||||
/// <summary>
|
||||
/// Gets the A, R, G and B component value of this <see cref="Color"/> as percentage in the range [0..1].
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
public static (double a, double r, double g, double b) GetRGB(this Color color)
|
||||
=> (color.A, color.R, color.G, color.B);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Manipulation
|
||||
|
||||
#region Add
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given RGB values to this color.
|
||||
/// </summary>
|
||||
/// <param name="r">The red value to add.</param>
|
||||
/// <param name="g">The green value to add.</param>
|
||||
/// <param name="b">The blue value to add.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color AddRGB(this Color color, int r = 0, int g = 0, int b = 0)
|
||||
=> new Color(color.A, color.GetR() + r, color.GetG() + g, color.GetB() + b);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given RGB-percent values to this color.
|
||||
/// </summary>
|
||||
/// <param name="r">The red value to add.</param>
|
||||
/// <param name="g">The green value to add.</param>
|
||||
/// <param name="b">The blue value to add.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color AddRGB(this Color color, double r = 0, double g = 0, double b = 0)
|
||||
=> new Color(color.A, color.R + r, color.G + g, color.B + b);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given alpha value to this color.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha value to add.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color AddA(this Color color, int a)
|
||||
=> new Color(color.GetA() + a, color.R, color.G, color.B);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given alpha-percent value to this color.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha value to add.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color AddA(this Color color, double a)
|
||||
=> new Color(color.A + a, color.R, color.G, color.B);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Subtract
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the given RGB values to this color.
|
||||
/// </summary>
|
||||
/// <param name="r">The red value to subtract.</param>
|
||||
/// <param name="g">The green value to subtract.</param>
|
||||
/// <param name="b">The blue value to subtract.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color SubtractRGB(this Color color, int r = 0, int g = 0, int b = 0)
|
||||
=> new Color(color.A, color.GetR() - r, color.GetG() - g, color.GetB() - b);
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the given RGB values to this color.
|
||||
/// </summary>
|
||||
/// <param name="r">The red value to subtract.</param>
|
||||
/// <param name="g">The green value to subtract.</param>
|
||||
/// <param name="b">The blue value to subtract.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color SubtractRGB(this Color color, double r = 0, double g = 0, double b = 0)
|
||||
=> new Color(color.A, color.R - r, color.G - g, color.B - b);
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the given alpha value to this color.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha value to subtract.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color SubtractA(this Color color, int a)
|
||||
=> new Color(color.GetA() - a, color.R, color.G, color.B);
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the given alpha-percent value to this color.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha value to subtract.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color SubtractA(this Color color, double aPercent)
|
||||
=> new Color(color.A - aPercent, color.R, color.G, color.B);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Multiply
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies the given RGB values to this color.
|
||||
/// </summary>
|
||||
/// <param name="r">The red value to multiply.</param>
|
||||
/// <param name="g">The green value to multiply.</param>
|
||||
/// <param name="b">The blue value to multiply.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color MultiplyRGB(this Color color, double r = 1, double g = 1, double b = 1)
|
||||
=> new Color(color.A, color.R * r, color.G * g, color.B * b);
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies the given alpha value to this color.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha value to multiply.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color MultiplyA(this Color color, double a)
|
||||
=> new Color(color.A * a, color.R, color.G, color.B);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Divide
|
||||
|
||||
/// <summary>
|
||||
/// Divides the given RGB values to this color.
|
||||
/// </summary>
|
||||
/// <param name="r">The red value to divide.</param>
|
||||
/// <param name="g">The green value to divide.</param>
|
||||
/// <param name="b">The blue value to divide.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color DivideRGB(this Color color, double r = 1, double g = 1, double b = 1)
|
||||
=> new Color(color.A, color.R / r, color.G / g, color.B / b);
|
||||
|
||||
/// <summary>
|
||||
/// Divides the given alpha value to this color.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha value to divide.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color DivideA(this Color color, double a)
|
||||
=> new Color(color.A / a, color.R, color.G, color.B);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Set
|
||||
|
||||
/// <summary>
|
||||
/// Sets the given RGB value of this color.
|
||||
/// </summary>
|
||||
/// <param name="r">The red value to set.</param>
|
||||
/// <param name="g">The green value to set.</param>
|
||||
/// <param name="b">The blue value to set.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color SetRGB(this Color color, byte? r = null, byte? g = null, byte? b = null)
|
||||
=> new Color(color.A, r ?? color.GetR(), g ?? color.GetG(), b ?? color.GetB());
|
||||
|
||||
/// <summary>
|
||||
/// Sets the given RGB value of this color.
|
||||
/// </summary>
|
||||
/// <param name="r">The red value to set.</param>
|
||||
/// <param name="g">The green value to set.</param>
|
||||
/// <param name="b">The blue value to set.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color SetRGB(this Color color, int? r = null, int? g = null, int? b = null)
|
||||
=> new Color(color.A, r ?? color.GetR(), g ?? color.GetG(), b ?? color.GetB());
|
||||
|
||||
/// <summary>
|
||||
/// Sets the given RGB value of this color.
|
||||
/// </summary>
|
||||
/// <param name="r">The red value to set.</param>
|
||||
/// <param name="g">The green value to set.</param>
|
||||
/// <param name="b">The blue value to set.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color SetRGB(this Color color, double? r = null, double? g = null, double? b = null)
|
||||
=> new Color(color.A, r ?? color.R, g ?? color.G, b ?? color.B);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the given alpha value of this color.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha value to set.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color SetA(this Color color, int a) => new Color(a, color.R, color.G, color.B);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the given alpha value of this color.
|
||||
/// </summary>
|
||||
/// <param name="a">The alpha value to set.</param>
|
||||
/// <returns>The new color after the modification.</returns>
|
||||
public static Color SetA(this Color color, double a) => new Color(a, color.R, color.G, color.B);
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Conversion
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current color as a RGB-HEX-string.
|
||||
/// </summary>
|
||||
/// <returns>The RGB-HEX-string.</returns>
|
||||
public static string AsRGBHexString(this Color color, bool leadingHash = true) => (leadingHash ? "#" : "") + ConversionHelper.ToHex(color.GetR(), color.GetG(), color.GetB());
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current color as a ARGB-HEX-string.
|
||||
/// </summary>
|
||||
/// <returns>The ARGB-HEX-string.</returns>
|
||||
public static string AsARGBHexString(this Color color, bool leadingHash = true) => (leadingHash ? "#" : "") + ConversionHelper.ToHex(color.GetA(), color.GetR(), color.GetG(), color.GetB());
|
||||
|
||||
#endregion
|
||||
|
||||
#region Factory
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="T:RGB.NET.Core.Color" /> struct using a HEX-string.
|
||||
/// </summary>
|
||||
/// <param name="hexString">The HEX-representation of the color.</param>
|
||||
/// <returns>The color created from the HEX-string.</returns>
|
||||
public static Color FromHexString(string hexString)
|
||||
{
|
||||
if ((hexString == null) || (hexString.Length < 6))
|
||||
throw new ArgumentException("Invalid hex string", nameof(hexString));
|
||||
|
||||
if (hexString[0] == '#')
|
||||
hexString = hexString.Substring(1);
|
||||
|
||||
byte[] data = ConversionHelper.HexToBytes(hexString);
|
||||
if (data.Length == 3)
|
||||
return new Color(data[0], data[1], data[2]);
|
||||
if (data.Length == 4)
|
||||
return new Color(data[0], data[1], data[2], data[3]);
|
||||
|
||||
throw new ArgumentException("Invalid hex string", nameof(hexString));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -36,7 +36,14 @@ namespace RGB.NET.Core
|
||||
/// <param name="max">The higher value of the range the value is clamped to.</param>
|
||||
/// <returns>The clamped value.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static double Clamp(this double value, double min, double max) => Math.Max(min, Math.Min(max, value));
|
||||
public static double Clamp(this double value, double min, double max)
|
||||
{
|
||||
// ReSharper disable ConvertIfStatementToReturnStatement - I'm not sure why, but inlining this statement reduces performance by ~10%
|
||||
if (value < min) return min;
|
||||
if (value > max) return max;
|
||||
return value;
|
||||
// ReSharper restore ConvertIfStatementToReturnStatement
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps the provided value to be bigger or equal min and smaller or equal max.
|
||||
@ -46,7 +53,14 @@ namespace RGB.NET.Core
|
||||
/// <param name="max">The higher value of the range the value is clamped to.</param>
|
||||
/// <returns>The clamped value.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int Clamp(this int value, int min, int max) => Math.Max(min, Math.Min(max, value));
|
||||
public static int Clamp(this int value, int min, int max)
|
||||
{
|
||||
// ReSharper disable ConvertIfStatementToReturnStatement - I'm not sure why, but inlining this statement reduces performance by ~10%
|
||||
if (value < min) return min;
|
||||
if (value > max) return max;
|
||||
return value;
|
||||
// ReSharper restore ConvertIfStatementToReturnStatement
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enforces the provided value to be in the specified range by wrapping it around the edges if it exceeds them.
|
||||
@ -68,16 +82,20 @@ namespace RGB.NET.Core
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static byte GetByteValueFromPercentage(this double percentage)
|
||||
{
|
||||
if (double.IsNaN(percentage)) return 0;
|
||||
|
||||
percentage = percentage.Clamp(0, 1.0);
|
||||
return (byte)(percentage.Equals(1.0) ? 255 : percentage * 256.0);
|
||||
return (byte)(percentage >= 1.0 ? 255 : percentage * 256.0);
|
||||
}
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static double GetPercentageFromByteValue(this byte value)
|
||||
=> ((double)value) / byte.MaxValue;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,8 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=brushes/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=color/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=colorcorrection/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=color_005Cbehaviors/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=decorators/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=devices/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=devices_005Cupdate/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
@ -77,7 +77,7 @@ namespace RGB.NET.Decorators.Brush
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
public Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color) => color.SetAPercent(_currentValue);
|
||||
public Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color) => color.SetA(_currentValue);
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Update(double deltaTime)
|
||||
|
||||
@ -57,9 +57,9 @@ namespace RGB.NET.Devices.Asus
|
||||
foreach (KeyValuePair<object, Color> data in dataSet)
|
||||
{
|
||||
int index = ((int)data.Key) * 3;
|
||||
ColorData[index] = data.Value.R;
|
||||
ColorData[index + 1] = data.Value.B;
|
||||
ColorData[index + 2] = data.Value.G;
|
||||
ColorData[index] = data.Value.GetR();
|
||||
ColorData[index + 1] = data.Value.GetB();
|
||||
ColorData[index + 2] = data.Value.GetG();
|
||||
}
|
||||
|
||||
_updateAction(_handle, ColorData);
|
||||
|
||||
@ -39,7 +39,7 @@ namespace RGB.NET.Devices.CoolerMaster
|
||||
foreach (KeyValuePair<object, Color> data in dataSet)
|
||||
{
|
||||
(int row, int column) = ((int, int))data.Key;
|
||||
_CoolerMasterSDK.SetLedColor(row, column, data.Value.R, data.Value.G, data.Value.B, _deviceIndex);
|
||||
_CoolerMasterSDK.SetLedColor(row, column, data.Value.GetR(), data.Value.GetG(), data.Value.GetB(), _deviceIndex);
|
||||
}
|
||||
|
||||
_CoolerMasterSDK.RefreshLed(false, _deviceIndex);
|
||||
|
||||
@ -215,7 +215,8 @@ namespace RGB.NET.Devices.Corsair
|
||||
|
||||
for (int channel = 0; channel < channelsInfo.channelsCount; channel++)
|
||||
{
|
||||
CorsairLedId referenceLed = channel == 0 ? CorsairLedId.CustomDeviceChannel1Led1 : CorsairLedId.CustomDeviceChannel2Led1;
|
||||
CorsairLedId referenceLed = GetChannelReferenceId(info.CorsairDeviceType, channel);
|
||||
if (referenceLed == CorsairLedId.Invalid) continue;
|
||||
|
||||
_CorsairChannelInfo channelInfo = (_CorsairChannelInfo)Marshal.PtrToStructure(channelInfoPtr, typeof(_CorsairChannelInfo));
|
||||
|
||||
@ -247,6 +248,23 @@ namespace RGB.NET.Devices.Corsair
|
||||
}
|
||||
}
|
||||
|
||||
private static CorsairLedId GetChannelReferenceId(CorsairDeviceType deviceType, int channel)
|
||||
{
|
||||
if (deviceType == CorsairDeviceType.Cooler)
|
||||
return CorsairLedId.CustomLiquidCoolerChannel1Led1;
|
||||
else
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 0: return CorsairLedId.CustomDeviceChannel1Led1;
|
||||
case 1: return CorsairLedId.CustomDeviceChannel2Led1;
|
||||
case 2: return CorsairLedId.CustomDeviceChannel3Led1;
|
||||
}
|
||||
}
|
||||
|
||||
return CorsairLedId.Invalid;
|
||||
}
|
||||
|
||||
private void AddSpecialParts(ICorsairRGBDevice device)
|
||||
{
|
||||
if (device.DeviceInfo.Model.Equals("K95 RGB Platinum", StringComparison.OrdinalIgnoreCase))
|
||||
|
||||
@ -46,9 +46,9 @@ namespace RGB.NET.Devices.Corsair
|
||||
_CorsairLedColor color = new _CorsairLedColor
|
||||
{
|
||||
ledId = (int)data.Key,
|
||||
r = data.Value.R,
|
||||
g = data.Value.G,
|
||||
b = data.Value.B
|
||||
r = data.Value.GetR(),
|
||||
g = data.Value.GetG(),
|
||||
b = data.Value.GetB()
|
||||
};
|
||||
|
||||
Marshal.StructureToPtr(color, addPtr, false);
|
||||
|
||||
@ -45,6 +45,7 @@ namespace RGB.NET.Devices.Logitech.HID
|
||||
{
|
||||
("G903", RGBDeviceType.Mouse, 0xC086, 2, "default", @"Mice\G903"),
|
||||
("G900", RGBDeviceType.Mouse, 0xC539, 2, "default", @"Mice\G900"),
|
||||
("G703", RGBDeviceType.Mouse, 0xC087, 2, "default", @"Mice\G703"),
|
||||
("G403", RGBDeviceType.Mouse, 0xC083, 2, "default", @"Mice\G403"),
|
||||
("G303", RGBDeviceType.Mouse, 0xC080, 2, "default", @"Mice\G303"),
|
||||
("G Pro", RGBDeviceType.Mouse, 0xC085, 1, "default", @"Mice\GPro"),
|
||||
|
||||
@ -32,9 +32,9 @@ namespace RGB.NET.Devices.Logitech
|
||||
Color color = dataSet.Values.First();
|
||||
|
||||
_LogitechGSDK.LogiLedSetTargetDevice(LogitechDeviceCaps.DeviceRGB);
|
||||
_LogitechGSDK.LogiLedSetLighting((int)Math.Round(color.RPercent * 100),
|
||||
(int)Math.Round(color.GPercent * 100),
|
||||
(int)Math.Round(color.BPercent * 100));
|
||||
_LogitechGSDK.LogiLedSetLighting((int)Math.Round(color.R * 100),
|
||||
(int)Math.Round(color.G * 100),
|
||||
(int)Math.Round(color.B * 100));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -158,10 +158,10 @@ namespace RGB.NET.Devices.Logitech
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static void SetColor(byte[] bitmap, int offset, Color color)
|
||||
{
|
||||
bitmap[offset] = color.B;
|
||||
bitmap[offset + 1] = color.G;
|
||||
bitmap[offset + 2] = color.R;
|
||||
bitmap[offset + 3] = color.A;
|
||||
bitmap[offset] = color.GetB();
|
||||
bitmap[offset + 1] = color.GetG();
|
||||
bitmap[offset + 2] = color.GetR();
|
||||
bitmap[offset + 3] = color.GetA();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -51,9 +51,9 @@ namespace RGB.NET.Devices.Logitech
|
||||
}
|
||||
else
|
||||
_LogitechGSDK.LogiLedSetLightingForKeyWithKeyName((int)customData,
|
||||
(int)Math.Round(data.Value.RPercent * 100),
|
||||
(int)Math.Round(data.Value.GPercent * 100),
|
||||
(int)Math.Round(data.Value.BPercent * 100));
|
||||
(int)Math.Round(data.Value.R * 100),
|
||||
(int)Math.Round(data.Value.G * 100),
|
||||
(int)Math.Round(data.Value.B * 100));
|
||||
}
|
||||
|
||||
if (usesBitmap)
|
||||
|
||||
@ -56,9 +56,9 @@ namespace RGB.NET.Devices.Logitech
|
||||
{
|
||||
int zone = (int)data.Key;
|
||||
_LogitechGSDK.LogiLedSetLightingForTargetZone(_deviceType, zone,
|
||||
(int)Math.Round(data.Value.RPercent * 100),
|
||||
(int)Math.Round(data.Value.GPercent * 100),
|
||||
(int)Math.Round(data.Value.BPercent * 100));
|
||||
(int)Math.Round(data.Value.R * 100),
|
||||
(int)Math.Round(data.Value.G * 100),
|
||||
(int)Math.Round(data.Value.B * 100));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -66,7 +66,7 @@ namespace RGB.NET.Devices.Msi
|
||||
{
|
||||
string deviceType = DeviceInfo.MsiDeviceType;
|
||||
foreach (Led led in leds)
|
||||
_MsiSDK.SetLedColor(deviceType, (int)led.CustomData, led.Color.R, led.Color.G, led.Color.B);
|
||||
_MsiSDK.SetLedColor(deviceType, (int)led.CustomData, led.Color.GetR(), led.Color.GetG(), led.Color.GetB());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -40,14 +40,16 @@ namespace RGB.NET.Devices.Novation
|
||||
/// <returns>The novation-representation of the <see cref="Color"/>.</returns>
|
||||
protected virtual int ConvertColor(Color color)
|
||||
{
|
||||
if ((color.Hue >= 330) || (color.Hue < 30))
|
||||
return (int)Math.Ceiling(color.Value * 3); // red with brightness 1, 2 or 3
|
||||
(double hue, double saturation, double value) = color.GetHSV();
|
||||
|
||||
if ((color.Hue >= 30) && (color.Hue < 90)) // yellow with brightness 17, 34 or 51
|
||||
return (int)Math.Ceiling(color.Value * 3) * 17;
|
||||
if ((hue >= 330) || (hue < 30))
|
||||
return (int)Math.Ceiling(value * 3); // red with brightness 1, 2 or 3
|
||||
|
||||
if ((color.Hue >= 90) && (color.Hue < 150)) // green with brightness 16, 32 or 48
|
||||
return (int)Math.Ceiling(color.Value * 3) * 16;
|
||||
if ((hue >= 30) && (hue < 90)) // yellow with brightness 17, 34 or 51
|
||||
return (int)Math.Ceiling(value * 3) * 17;
|
||||
|
||||
if ((hue >= 90) && (hue < 150)) // green with brightness 16, 32 or 48
|
||||
return (int)Math.Ceiling(value * 3) * 16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ namespace RGB.NET.Devices.Razer.Native
|
||||
#region Constructors
|
||||
|
||||
public _Color(Color color)
|
||||
: this(color.R, color.G, color.B) { }
|
||||
: this(color.GetR(), color.GetG(), color.GetB()) { }
|
||||
|
||||
public _Color(byte red, byte green, byte blue)
|
||||
: this()
|
||||
|
||||
@ -66,7 +66,7 @@ namespace RGB.NET.Devices.SoIP.Client
|
||||
List<(LedId, Color)> leds = message.MessageString.Split(';').Select(x =>
|
||||
{
|
||||
string[] led = x.Split('|');
|
||||
return ((LedId)Enum.Parse(typeof(LedId), led[0]), Color.FromHexString(led[1]));
|
||||
return ((LedId)Enum.Parse(typeof(LedId), led[0]), RGBColor.FromHexString(led[1]));
|
||||
}).ToList();
|
||||
lock (_syncbackCache)
|
||||
foreach ((LedId ledId, Color color) in leds)
|
||||
|
||||
@ -61,7 +61,7 @@ namespace RGB.NET.Devices.SoIP.Server
|
||||
tcpClient.GetStream().WriteAsync(messageData, 0, messageData.Length);
|
||||
}
|
||||
|
||||
private string GetLedString(IEnumerable<Led> leds) => string.Join(";", leds.Select(x => x.Id.ToString() + "|" + x.Color.AsARGBHexString()));
|
||||
private string GetLedString(IEnumerable<Led> leds) => string.Join(";", leds.Select(x => x.Id.ToString() + "|" + x.Color.AsARGBHexString(false)));
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Dispose()
|
||||
|
||||
@ -46,7 +46,7 @@ namespace RGB.NET.Devices.SoIP.Server
|
||||
}
|
||||
}
|
||||
|
||||
private string GetLedString(Dictionary<object, Color> dataSet) => string.Join(";", dataSet.Select(x => x.Key.ToString() + "|" + x.Value.AsARGBHexString()));
|
||||
private string GetLedString(Dictionary<object, Color> dataSet) => string.Join(";", dataSet.Select(x => x.Key.ToString() + "|" + x.Value.AsARGBHexString(false)));
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
10
RGB.NET.Devices.SteelSeries/API/Model/CoreProps.cs
Normal file
10
RGB.NET.Devices.SteelSeries/API/Model/CoreProps.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries.API.Model
|
||||
{
|
||||
internal class CoreProps
|
||||
{
|
||||
[JsonProperty(PropertyName = "address")]
|
||||
public string Address { get; set; }
|
||||
}
|
||||
}
|
||||
34
RGB.NET.Devices.SteelSeries/API/Model/Event.cs
Normal file
34
RGB.NET.Devices.SteelSeries/API/Model/Event.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries.API.Model
|
||||
{
|
||||
internal class Event
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
[JsonProperty("game")]
|
||||
public string Game { get; set; }
|
||||
|
||||
[JsonProperty("event")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("data")]
|
||||
public Dictionary<string, object> Data { get; } = new Dictionary<string, object>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public Event()
|
||||
{ }
|
||||
|
||||
public Event(Game game, string name)
|
||||
{
|
||||
this.Name = name;
|
||||
Game = game.Name;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
30
RGB.NET.Devices.SteelSeries/API/Model/Game.cs
Normal file
30
RGB.NET.Devices.SteelSeries/API/Model/Game.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries.API.Model
|
||||
{
|
||||
internal class Game
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
[JsonProperty("game")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("game_display_name")]
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public Game()
|
||||
{ }
|
||||
|
||||
public Game(string name, string displayName)
|
||||
{
|
||||
Name = name;
|
||||
DisplayName = displayName;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
30
RGB.NET.Devices.SteelSeries/API/Model/GoLispHandler.cs
Normal file
30
RGB.NET.Devices.SteelSeries/API/Model/GoLispHandler.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries.API.Model
|
||||
{
|
||||
internal class GoLispHandler
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
[JsonProperty("game")]
|
||||
public string Game { get; set; }
|
||||
|
||||
[JsonProperty("golisp")]
|
||||
public string Handler { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public GoLispHandler()
|
||||
{ }
|
||||
|
||||
public GoLispHandler(Game game, string handler)
|
||||
{
|
||||
this.Handler = handler;
|
||||
Game = game.Name;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
120
RGB.NET.Devices.SteelSeries/API/SteelSeriesSDK.cs
Normal file
120
RGB.NET.Devices.SteelSeries/API/SteelSeriesSDK.cs
Normal file
@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using RGB.NET.Devices.SteelSeries.API.Model;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries.API
|
||||
{
|
||||
internal static class SteelSeriesSDK
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const string GAME_NAME = "RGBNET";
|
||||
private const string GAME_DISPLAYNAME = "RGB.NET";
|
||||
private const string EVENT_NAME = "UPDATELEDS";
|
||||
private const string HANDLER = @"(handler """ + EVENT_NAME + @"""
|
||||
(lambda (data)
|
||||
(let* ((device (value: data))
|
||||
(zoneData (frame: data))
|
||||
(zones (frame-keys zoneData)))
|
||||
(do ((zoneDo zones (cdr zoneDo)))
|
||||
((nil? zoneDo))
|
||||
(let* ((zone (car zoneDo))
|
||||
(color (get-slot zoneData zone)))
|
||||
(on-device device show-on-zone: color zone))))))";
|
||||
|
||||
private const string CORE_PROPS_WINDOWS = "%PROGRAMDATA%/SteelSeries/SteelSeries Engine 3/coreProps.json";
|
||||
private const string CORE_PROPS_OSX = "/Library/Application Support/SteelSeries Engine 3/coreProps.json";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
private static readonly HttpClient _client = new HttpClient();
|
||||
private static readonly Game _game = new Game(GAME_NAME, GAME_DISPLAYNAME);
|
||||
private static readonly Event _event = new Event(_game, EVENT_NAME);
|
||||
private static string _baseUrl;
|
||||
|
||||
internal static bool IsInitialized => !string.IsNullOrWhiteSpace(_baseUrl);
|
||||
|
||||
// ReSharper restore InconsistentNaming
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
internal static bool Initialize()
|
||||
{
|
||||
try
|
||||
{
|
||||
string corePropsPath = GetCorePropsPath();
|
||||
if (!string.IsNullOrWhiteSpace(corePropsPath) && File.Exists(corePropsPath))
|
||||
{
|
||||
CoreProps coreProps = JsonConvert.DeserializeObject<CoreProps>(File.ReadAllText(corePropsPath));
|
||||
_baseUrl = coreProps.Address;
|
||||
if (!_baseUrl.StartsWith("http://", StringComparison.Ordinal))
|
||||
_baseUrl = "http://" + _baseUrl;
|
||||
|
||||
RegisterGame(_game);
|
||||
RegisterGoLispHandler(new GoLispHandler(_game, HANDLER));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
_baseUrl = null;
|
||||
}
|
||||
return IsInitialized;
|
||||
}
|
||||
|
||||
internal static void UpdateLeds(string device, Dictionary<string, int[]> data)
|
||||
{
|
||||
_event.Data.Clear();
|
||||
_event.Data.Add("value", device);
|
||||
_event.Data.Add("frame", data);
|
||||
|
||||
TriggerEvent(_event);
|
||||
}
|
||||
|
||||
internal static void SendHeartbeat() => SendHeartbeat(_game);
|
||||
|
||||
internal static void ResetLeds() => StopGame(_game);
|
||||
|
||||
internal static void Dispose()
|
||||
{
|
||||
ResetLeds();
|
||||
_client.Dispose();
|
||||
}
|
||||
|
||||
private static string TriggerEvent(Event e) => PostJson("/game_event", e);
|
||||
private static string RegisterGoLispHandler(GoLispHandler handler) => PostJson("/load_golisp_handlers", handler);
|
||||
private static string RegisterEvent(Event e) => PostJson("/register_game_event", e);
|
||||
private static string UnregisterEvent(Event e) => PostJson("/remove_game_event", e);
|
||||
private static string RegisterGame(Game game) => PostJson("/game_metadata", game);
|
||||
private static string UnregisterGame(Game game) => PostJson("/remove_game", game);
|
||||
private static string StopGame(Game game) => PostJson("/stop_game", game);
|
||||
private static string SendHeartbeat(Game game) => PostJson("/game_heartbeat", game);
|
||||
|
||||
private static string PostJson(string urlSuffix, object o)
|
||||
{
|
||||
string payload = JsonConvert.SerializeObject(o);
|
||||
return _client.PostAsync(_baseUrl + urlSuffix, new StringContent(payload, Encoding.UTF8, "application/json")).Result.Content.ReadAsStringAsync().Result;
|
||||
}
|
||||
|
||||
private static string GetCorePropsPath()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return Environment.ExpandEnvironmentVariables(CORE_PROPS_WINDOWS);
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
return CORE_PROPS_OSX;
|
||||
|
||||
throw new InvalidOperationException("Unknown operating system.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
20
RGB.NET.Devices.SteelSeries/Attribute/APIName.cs
Normal file
20
RGB.NET.Devices.SteelSeries/Attribute/APIName.cs
Normal file
@ -0,0 +1,20 @@
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
internal class APIName : System.Attribute
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public APIName(string name)
|
||||
{
|
||||
this.Name = name;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
internal static class SteelSeriesEnumExtension
|
||||
{
|
||||
#region Properties & Fields
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
private static readonly Dictionary<SteelSeriesDeviceType, string> _deviceTypeNames = new Dictionary<SteelSeriesDeviceType, string>();
|
||||
private static readonly Dictionary<SteelSeriesLedId, string> _ledIdNames = new Dictionary<SteelSeriesLedId, string>();
|
||||
|
||||
// ReSharper restore InconsistentNaming
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
internal static string GetAPIName(this SteelSeriesDeviceType deviceType)
|
||||
{
|
||||
if (!_deviceTypeNames.TryGetValue(deviceType, out string apiName))
|
||||
_deviceTypeNames.Add(deviceType, apiName = GetAPIName(typeof(SteelSeriesDeviceType), deviceType));
|
||||
|
||||
return apiName;
|
||||
}
|
||||
|
||||
internal static string GetAPIName(this SteelSeriesLedId ledId)
|
||||
{
|
||||
if (!_ledIdNames.TryGetValue(ledId, out string apiName))
|
||||
_ledIdNames.Add(ledId, apiName = GetAPIName(typeof(SteelSeriesLedId), ledId));
|
||||
|
||||
return apiName;
|
||||
}
|
||||
|
||||
private static string GetAPIName(Type type, Enum value)
|
||||
{
|
||||
MemberInfo[] memInfo = type.GetMember(value.ToString());
|
||||
if (memInfo.Length == 0) return null;
|
||||
return (memInfo.FirstOrDefault()?.GetCustomAttributes(typeof(APIName), false).FirstOrDefault() as APIName)?.Name;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
23
RGB.NET.Devices.SteelSeries/Enum/SteelSeriesDeviceType.cs
Normal file
23
RGB.NET.Devices.SteelSeries/Enum/SteelSeriesDeviceType.cs
Normal file
@ -0,0 +1,23 @@
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
public enum SteelSeriesDeviceType
|
||||
{
|
||||
[APIName("rgb-per-key-zones")]
|
||||
PerKey,
|
||||
|
||||
[APIName("rgb-1-zone")]
|
||||
OneZone,
|
||||
|
||||
[APIName("rgb-2-zone")]
|
||||
TwoZone,
|
||||
|
||||
[APIName("rgb-3-zone")]
|
||||
ThreeZone,
|
||||
|
||||
[APIName("rgb-4-zone")]
|
||||
FourZone,
|
||||
|
||||
[APIName("rgb-5-zone")]
|
||||
FiveZone
|
||||
}
|
||||
}
|
||||
243
RGB.NET.Devices.SteelSeries/Enum/SteelSeriesLedId.cs
Normal file
243
RGB.NET.Devices.SteelSeries/Enum/SteelSeriesLedId.cs
Normal file
@ -0,0 +1,243 @@
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
public enum SteelSeriesLedId
|
||||
{
|
||||
[APIName("one")]
|
||||
ZoneOne,
|
||||
[APIName("two")]
|
||||
ZoneTwo,
|
||||
[APIName("three")]
|
||||
ZoneThree,
|
||||
[APIName("four")]
|
||||
ZoneFour,
|
||||
[APIName("five")]
|
||||
ZoneFive,
|
||||
|
||||
[APIName("logo")]
|
||||
Logo,
|
||||
[APIName("a")]
|
||||
A,
|
||||
[APIName("b")]
|
||||
B,
|
||||
[APIName("c")]
|
||||
C,
|
||||
[APIName("d")]
|
||||
D,
|
||||
[APIName("e")]
|
||||
E,
|
||||
[APIName("f")]
|
||||
F,
|
||||
[APIName("g")]
|
||||
G,
|
||||
[APIName("h")]
|
||||
H,
|
||||
[APIName("i")]
|
||||
I,
|
||||
[APIName("j")]
|
||||
J,
|
||||
[APIName("k")]
|
||||
K,
|
||||
[APIName("l")]
|
||||
L,
|
||||
[APIName("m")]
|
||||
M,
|
||||
[APIName("n")]
|
||||
N,
|
||||
[APIName("o")]
|
||||
O,
|
||||
[APIName("p")]
|
||||
P,
|
||||
[APIName("q")]
|
||||
Q,
|
||||
[APIName("r")]
|
||||
R,
|
||||
[APIName("s")]
|
||||
S,
|
||||
[APIName("t")]
|
||||
T,
|
||||
[APIName("u")]
|
||||
U,
|
||||
[APIName("v")]
|
||||
V,
|
||||
[APIName("w")]
|
||||
W,
|
||||
[APIName("x")]
|
||||
X,
|
||||
[APIName("y")]
|
||||
Y,
|
||||
[APIName("z")]
|
||||
Z,
|
||||
[APIName("keyboard-1")]
|
||||
Keyboard1,
|
||||
[APIName("keyboard-2")]
|
||||
Keyboard2,
|
||||
[APIName("keyboard-3")]
|
||||
Keyboard3,
|
||||
[APIName("keyboard-4")]
|
||||
Keyboard4,
|
||||
[APIName("keyboard-5")]
|
||||
Keyboard5,
|
||||
[APIName("keyboard-6")]
|
||||
Keyboard6,
|
||||
[APIName("keyboard-7")]
|
||||
Keyboard7,
|
||||
[APIName("keyboard-8")]
|
||||
Keyboard8,
|
||||
[APIName("keyboard-9")]
|
||||
Keyboard9,
|
||||
[APIName("keyboard-0")]
|
||||
Keyboard0,
|
||||
[APIName("return")]
|
||||
Return,
|
||||
[APIName("escape")]
|
||||
Escape,
|
||||
[APIName("backspace")]
|
||||
Backspace,
|
||||
[APIName("tab")]
|
||||
Tab,
|
||||
[APIName("spacebar")]
|
||||
Spacebar,
|
||||
[APIName("caps")]
|
||||
Caps,
|
||||
[APIName("dash")]
|
||||
Dash,
|
||||
[APIName("equal")]
|
||||
Equal,
|
||||
[APIName("l-bracket")]
|
||||
LBracket,
|
||||
[APIName("r-bracket")]
|
||||
RBracket,
|
||||
[APIName("backslash")]
|
||||
Backslash,
|
||||
[APIName("pound")]
|
||||
Pound,
|
||||
[APIName("semicolon")]
|
||||
Semicolon,
|
||||
[APIName("quote")]
|
||||
Quote,
|
||||
[APIName("backquote")]
|
||||
Backqoute,
|
||||
[APIName("comma")]
|
||||
Comma,
|
||||
[APIName("period")]
|
||||
Period,
|
||||
[APIName("slash")]
|
||||
Slash,
|
||||
[APIName("f1")]
|
||||
F1,
|
||||
[APIName("f2")]
|
||||
F2,
|
||||
[APIName("f3")]
|
||||
F3,
|
||||
[APIName("f4")]
|
||||
F4,
|
||||
[APIName("f5")]
|
||||
F5,
|
||||
[APIName("f6")]
|
||||
F6,
|
||||
[APIName("f7")]
|
||||
F7,
|
||||
[APIName("f8")]
|
||||
F8,
|
||||
[APIName("f9")]
|
||||
F9,
|
||||
[APIName("f10")]
|
||||
F10,
|
||||
[APIName("f11")]
|
||||
F11,
|
||||
[APIName("f12")]
|
||||
F12,
|
||||
[APIName("printscreen")]
|
||||
PrintScreen,
|
||||
[APIName("scrolllock")]
|
||||
ScrollLock,
|
||||
[APIName("pause")]
|
||||
Pause,
|
||||
[APIName("insert")]
|
||||
Insert,
|
||||
[APIName("home")]
|
||||
Home,
|
||||
[APIName("pageup")]
|
||||
PageUp,
|
||||
[APIName("delete")]
|
||||
Delete,
|
||||
[APIName("end")]
|
||||
End,
|
||||
[APIName("pagedown")]
|
||||
PageDown,
|
||||
[APIName("rightarrow")]
|
||||
RightArrow,
|
||||
[APIName("leftarrow")]
|
||||
LeftArrow,
|
||||
[APIName("downarrow")]
|
||||
DownArrow,
|
||||
[APIName("uparrow")]
|
||||
UpArrow,
|
||||
[APIName("keypad-num-lock")]
|
||||
KeypadNumLock,
|
||||
[APIName("keypad-divide")]
|
||||
KeypadDivide,
|
||||
[APIName("keypad-times")]
|
||||
KeypadTimes,
|
||||
[APIName("keypad-minus")]
|
||||
KeypadMinus,
|
||||
[APIName("keypad-plus")]
|
||||
KeypadPlus,
|
||||
[APIName("keypad-enter")]
|
||||
KeypadEnter,
|
||||
[APIName("keypad-period")]
|
||||
KeypadPeriod,
|
||||
[APIName("keypad-1")]
|
||||
Keypad1,
|
||||
[APIName("keypad-2")]
|
||||
Keypad2,
|
||||
[APIName("keypad-3")]
|
||||
Keypad3,
|
||||
[APIName("keypad-4")]
|
||||
Keypad4,
|
||||
[APIName("keypad-5")]
|
||||
Keypad5,
|
||||
[APIName("keypad-6")]
|
||||
Keypad6,
|
||||
[APIName("keypad-7")]
|
||||
Keypad7,
|
||||
[APIName("keypad-8")]
|
||||
Keypad8,
|
||||
[APIName("keypad-9")]
|
||||
Keypad9,
|
||||
[APIName("keypad-0")]
|
||||
Keypad0,
|
||||
[APIName("l-ctrl")]
|
||||
LCtrl,
|
||||
[APIName("l-shift")]
|
||||
LShift,
|
||||
[APIName("l-alt")]
|
||||
LAlt,
|
||||
[APIName("l-win")]
|
||||
LWin,
|
||||
[APIName("r-ctrl")]
|
||||
RCtrl,
|
||||
[APIName("r-shift")]
|
||||
RShift,
|
||||
[APIName("r-alt")]
|
||||
RAlt,
|
||||
[APIName("r-win")]
|
||||
RWin,
|
||||
[APIName("ss-key")]
|
||||
SSKey,
|
||||
[APIName("win-menu")]
|
||||
WinMenu,
|
||||
[APIName("m0")]
|
||||
M0,
|
||||
[APIName("m1")]
|
||||
M1,
|
||||
[APIName("m2")]
|
||||
M2,
|
||||
[APIName("m3")]
|
||||
M3,
|
||||
[APIName("m4")]
|
||||
M4,
|
||||
[APIName("m5")]
|
||||
M5,
|
||||
}
|
||||
}
|
||||
13
RGB.NET.Devices.SteelSeries/Generic/ISteelSeriesRGBDevice.cs
Normal file
13
RGB.NET.Devices.SteelSeries/Generic/ISteelSeriesRGBDevice.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a steelseries RGB-device.
|
||||
/// </summary>
|
||||
internal interface ISteelSeriesRGBDevice : IRGBDevice
|
||||
{
|
||||
void Initialize(UpdateQueue updateQueue, Dictionary<LedId, SteelSeriesLedId> ledMapping);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using RGB.NET.Core;
|
||||
using RGB.NET.Devices.SteelSeries.API;
|
||||
using RGB.NET.Devices.SteelSeries.Helper;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents the update-queue performing updates for steelseries devices.
|
||||
/// </summary>
|
||||
internal class SteelSeriesDeviceUpdateQueue : UpdateQueue
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private string _deviceType;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SteelSeriesDeviceUpdateQueue"/> class.
|
||||
/// </summary>
|
||||
/// <param name="updateTrigger">The update trigger used by this queue.</param>
|
||||
/// <param name="deviceType">The device type used to identify the device.</param>
|
||||
public SteelSeriesDeviceUpdateQueue(IDeviceUpdateTrigger updateTrigger, string deviceType)
|
||||
: base(updateTrigger)
|
||||
{
|
||||
this._deviceType = deviceType;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Update(Dictionary<object, Color> dataSet)
|
||||
{
|
||||
SteelSeriesSDK.UpdateLeds(_deviceType, dataSet.ToDictionary(x => ((SteelSeriesLedId)x.Key).GetAPIName(), x => x.Value.ToIntArray()));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
88
RGB.NET.Devices.SteelSeries/Generic/SteelSeriesRGBDevice.cs
Normal file
88
RGB.NET.Devices.SteelSeries/Generic/SteelSeriesRGBDevice.cs
Normal file
@ -0,0 +1,88 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" />
|
||||
/// <inheritdoc cref="ISteelSeriesRGBDevice" />
|
||||
/// <summary>
|
||||
/// Represents a SteelSeries-device. (keyboard, mouse, headset, mousepad).
|
||||
/// </summary>
|
||||
public class SteelSeriesRGBDevice : AbstractRGBDevice<SteelSeriesRGBDeviceInfo>, ISteelSeriesRGBDevice
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private Dictionary<LedId, SteelSeriesLedId> _ledMapping;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Gets information about the <see cref="SteelSeriesRGBDevice" />.
|
||||
/// </summary>
|
||||
public override SteelSeriesRGBDeviceInfo DeviceInfo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the update queue performing updates for this device.
|
||||
/// </summary>
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
protected UpdateQueue UpdateQueue { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SteelSeriesRGBDevice"/> class.
|
||||
/// </summary>
|
||||
/// <param name="info">The generic information provided by SteelSeries for the device.</param>
|
||||
internal SteelSeriesRGBDevice(SteelSeriesRGBDeviceInfo info)
|
||||
{
|
||||
this.DeviceInfo = info;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the device.
|
||||
/// </summary>
|
||||
void ISteelSeriesRGBDevice.Initialize(UpdateQueue updateQueue, Dictionary<LedId, SteelSeriesLedId> ledMapping)
|
||||
{
|
||||
_ledMapping = ledMapping;
|
||||
|
||||
int counter = 0;
|
||||
foreach (KeyValuePair<LedId, SteelSeriesLedId> mapping in ledMapping)
|
||||
InitializeLed(mapping.Key, new Rectangle((counter++) * 10, 0, 10, 10));
|
||||
|
||||
InitializeLayout();
|
||||
|
||||
if (Size == Size.Invalid)
|
||||
{
|
||||
Rectangle ledRectangle = new Rectangle(this.Select(x => x.LedRectangle));
|
||||
Size = ledRectangle.Size + new Size(ledRectangle.Location.X, ledRectangle.Location.Y);
|
||||
}
|
||||
|
||||
UpdateQueue = updateQueue;
|
||||
}
|
||||
|
||||
protected override object CreateLedCustomData(LedId ledId) => _ledMapping[ledId];
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(ledsToUpdate.Where(x => x.Color.A > 0));
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the <see cref="Led"/> and <see cref="Size"/> of the device.
|
||||
/// </summary>
|
||||
protected virtual void InitializeLayout()
|
||||
{
|
||||
if (!(DeviceInfo is SteelSeriesRGBDeviceInfo info)) return;
|
||||
|
||||
string layout = info.ImageLayout;
|
||||
string layoutPath = info.LayoutPath;
|
||||
ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\SteelSeries\{layoutPath}.xml"), layout, true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents a generic information for a SteelSeries-<see cref="T:RGB.NET.Core.IRGBDevice" />.
|
||||
/// </summary>
|
||||
public class SteelSeriesRGBDeviceInfo : IRGBDeviceInfo
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
/// <inheritdoc />
|
||||
public RGBDeviceType DeviceType { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string DeviceName { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Manufacturer => "SteelSeries";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Model { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public Uri Image { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public RGBDeviceLighting Lighting => RGBDeviceLighting.Key;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool SupportsSyncBack => false;
|
||||
|
||||
public SteelSeriesDeviceType SteelSeriesDeviceType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the layout used to decide which images to load.
|
||||
/// </summary>
|
||||
internal string ImageLayout { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path/name of the layout-file.
|
||||
/// </summary>
|
||||
internal string LayoutPath { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Internal constructor of managed <see cref="SteelSeriesRGBDeviceInfo"/>.
|
||||
/// </summary>
|
||||
/// <param name="deviceType">The type of the <see cref="IRGBDevice"/>.</param>
|
||||
/// <param name="model">The represented device model.</param>
|
||||
/// <param name="deviceCaps">The lighting-capabilities of the device.</param>
|
||||
/// <param name="imageLayout">The layout used to decide which images to load.</param>
|
||||
/// <param name="layoutPath">The path/name of the layout-file.</param>
|
||||
internal SteelSeriesRGBDeviceInfo(RGBDeviceType deviceType, string model, SteelSeriesDeviceType steelSeriesDeviceType, string imageLayout, string layoutPath)
|
||||
{
|
||||
this.DeviceType = deviceType;
|
||||
this.Model = model;
|
||||
this.SteelSeriesDeviceType = steelSeriesDeviceType;
|
||||
this.ImageLayout = imageLayout;
|
||||
this.LayoutPath = layoutPath;
|
||||
|
||||
DeviceName = $"{Manufacturer} {Model}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
47
RGB.NET.Devices.SteelSeries/HID/DeviceChecker.cs
Normal file
47
RGB.NET.Devices.SteelSeries/HID/DeviceChecker.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using HidSharp;
|
||||
using RGB.NET.Core;
|
||||
using DeviceDataList = System.Collections.Generic.List<(string model, RGB.NET.Core.RGBDeviceType deviceType, int id, RGB.NET.Devices.SteelSeries.SteelSeriesDeviceType steelSeriesDeviceType, string imageLayout, string layoutPath, System.Collections.Generic.Dictionary<RGB.NET.Core.LedId, RGB.NET.Devices.SteelSeries.SteelSeriesLedId> ledMapping)>;
|
||||
using LedMapping = System.Collections.Generic.Dictionary<RGB.NET.Core.LedId, RGB.NET.Devices.SteelSeries.SteelSeriesLedId>;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries.HID
|
||||
{
|
||||
internal static class DeviceChecker
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const int VENDOR_ID = 0x1038;
|
||||
|
||||
//TODO DarthAffe 16.02.2019: Add devices
|
||||
private static readonly DeviceDataList DEVICES = new DeviceDataList
|
||||
{
|
||||
("Rival 500", RGBDeviceType.Mouse, 0x170E, SteelSeriesDeviceType.TwoZone, "default", @"Mice\Rival500", new LedMapping { { LedId.Mouse1, SteelSeriesLedId.ZoneOne},
|
||||
{ LedId.Mouse2, SteelSeriesLedId.ZoneTwo} }),
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public static DeviceDataList ConnectedDevices { get; } = new DeviceDataList();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
internal static void LoadDeviceList(RGBDeviceType loadFilter)
|
||||
{
|
||||
ConnectedDevices.Clear();
|
||||
|
||||
HashSet<int> ids = new HashSet<int>(DeviceList.Local.GetHidDevices(VENDOR_ID).Select(x => x.ProductID).Distinct());
|
||||
DeviceDataList connectedDevices = DEVICES.Where(d => ids.Contains(d.id) && loadFilter.HasFlag(d.deviceType)).ToList();
|
||||
|
||||
List<SteelSeriesDeviceType> connectedDeviceTypes = connectedDevices.Select(d => d.steelSeriesDeviceType).ToList();
|
||||
foreach (SteelSeriesDeviceType deviceType in connectedDeviceTypes)
|
||||
ConnectedDevices.Add(connectedDevices.Where(d => d.steelSeriesDeviceType == deviceType).OrderByDescending(d => d.ledMapping.Count).First());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
9
RGB.NET.Devices.SteelSeries/Helper/ColorExtensions.cs
Normal file
9
RGB.NET.Devices.SteelSeries/Helper/ColorExtensions.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries.Helper
|
||||
{
|
||||
internal static class ColorExtensions
|
||||
{
|
||||
internal static int[] ToIntArray(this Color color) => new int[] { color.GetR(), color.GetB(), color.GetG() };
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win7-x86;win7-x64</RuntimeIdentifiers>
|
||||
|
||||
<Authors>Darth Affe</Authors>
|
||||
<Company>Wyrez</Company>
|
||||
<Language>en-US</Language>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<Title>RGB.NET.Devices.SteelSeries</Title>
|
||||
<AssemblyName>RGB.NET.Devices.SteelSeries</AssemblyName>
|
||||
<AssemblyTitle>RGB.NET.Devices.SteelSeries</AssemblyTitle>
|
||||
<PackageId>RGB.NET.Devices.SteelSeries</PackageId>
|
||||
<RootNamespace>RGB.NET.Devices.SteelSeries</RootNamespace>
|
||||
<Description>SteelSeries-Device-Implementations of RGB.NET</Description>
|
||||
<Summary>SteelSeries-Device-Implementations of RGB.NET, a C# (.NET) library for accessing various RGB-peripherals</Summary>
|
||||
<Copyright>Copyright © Wyrez 2017</Copyright>
|
||||
<PackageCopyright>Copyright © Wyrez 2017</PackageCopyright>
|
||||
<PackageIconUrl>http://lib.arge.be/icon.png</PackageIconUrl>
|
||||
<PackageProjectUrl>https://github.com/DarthAffe/RGB.NET</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://raw.githubusercontent.com/DarthAffe/RGB.NET/master/LICENSE</PackageLicenseUrl>
|
||||
<RepositoryType>Github</RepositoryType>
|
||||
<RepositoryUrl>https://github.com/DarthAffe/RGB.NET</RepositoryUrl>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
|
||||
<PackageReleaseNotes></PackageReleaseNotes>
|
||||
|
||||
<Version>0.0.1</Version>
|
||||
<AssemblyVersion>0.0.1</AssemblyVersion>
|
||||
<FileVersion>0.0.1</FileVersion>
|
||||
|
||||
<OutputPath>..\bin\</OutputPath>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<IncludeSource>True</IncludeSource>
|
||||
<IncludeSymbols>True</IncludeSymbols>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||
<DefineConstants>NETCORE;NETSTANDARD;NETSTANDARD2_0</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<DefineConstants>$(DefineConstants);TRACE;DEBUG</DefineConstants>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<NoWarn>$(NoWarn);CS1591;CS1572;CS1573</NoWarn>
|
||||
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\RGB.NET.Core\RGB.NET.Core.csproj" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
||||
<PackageReference Include="HidSharp" Version="2.0.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -0,0 +1,4 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=attribute/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=enum/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generic/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
129
RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs
Normal file
129
RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs
Normal file
@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using RGB.NET.Core;
|
||||
using RGB.NET.Devices.SteelSeries.API;
|
||||
using RGB.NET.Devices.SteelSeries.HID;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents a device provider responsible for SteelSeries- devices.
|
||||
/// </summary>
|
||||
public class SteelSeriesDeviceProvider : IRGBDeviceProvider
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private static SteelSeriesDeviceProvider _instance;
|
||||
/// <summary>
|
||||
/// Gets the singleton <see cref="SteelSeriesDeviceProvider"/> instance.
|
||||
/// </summary>
|
||||
public static SteelSeriesDeviceProvider Instance => _instance ?? new SteelSeriesDeviceProvider();
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Indicates if the SDK is initialized and ready to use.
|
||||
/// </summary>
|
||||
public bool IsInitialized { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Gets whether the application has exclusive access to the SDK or not.
|
||||
/// </summary>
|
||||
public bool HasExclusiveAccess => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<IRGBDevice> Devices { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="DeviceUpdateTrigger"/> used to trigger the updates for SteelSeries devices.
|
||||
/// </summary>
|
||||
public DeviceUpdateTrigger UpdateTrigger { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SteelSeriesDeviceProvider"/> class.
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException">Thrown if this constructor is called even if there is already an instance of this class.</exception>
|
||||
public SteelSeriesDeviceProvider()
|
||||
{
|
||||
if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(SteelSeriesDeviceProvider)}");
|
||||
_instance = this;
|
||||
|
||||
UpdateTrigger = new DeviceUpdateTrigger();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool exclusiveAccessIfPossible = false, bool throwExceptions = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
IsInitialized = false;
|
||||
|
||||
UpdateTrigger?.Stop();
|
||||
|
||||
if (!SteelSeriesSDK.IsInitialized)
|
||||
SteelSeriesSDK.Initialize();
|
||||
|
||||
IList<IRGBDevice> devices = new List<IRGBDevice>();
|
||||
DeviceChecker.LoadDeviceList(loadFilter);
|
||||
|
||||
try
|
||||
{
|
||||
foreach ((string model, RGBDeviceType deviceType, int _, SteelSeriesDeviceType steelSeriesDeviceType, string imageLayout, string layoutPath, Dictionary<LedId, SteelSeriesLedId> ledMapping) in DeviceChecker.ConnectedDevices)
|
||||
{
|
||||
ISteelSeriesRGBDevice device = new SteelSeriesRGBDevice(new SteelSeriesRGBDeviceInfo(deviceType, model, steelSeriesDeviceType, imageLayout, layoutPath));
|
||||
SteelSeriesDeviceUpdateQueue updateQueue = new SteelSeriesDeviceUpdateQueue(UpdateTrigger, steelSeriesDeviceType.GetAPIName());
|
||||
device.Initialize(updateQueue, ledMapping);
|
||||
devices.Add(device);
|
||||
}
|
||||
}
|
||||
catch { if (throwExceptions) throw; }
|
||||
|
||||
UpdateTrigger?.Start();
|
||||
|
||||
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
|
||||
IsInitialized = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
IsInitialized = false;
|
||||
if (throwExceptions) throw;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ResetDevices()
|
||||
{
|
||||
if (IsInitialized)
|
||||
try
|
||||
{
|
||||
SteelSeriesSDK.ResetLeds();
|
||||
}
|
||||
catch {/* shit happens */}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
SteelSeriesSDK.Dispose();
|
||||
}
|
||||
catch {/* shit happens */}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a device provider loaded used to dynamically load steelseries devices into an application.
|
||||
/// </summary>
|
||||
// ReSharper disable once UnusedMember.Global
|
||||
public class SteelSeriesDeviceProviderLoader : IRGBDeviceProviderLoader
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool RequiresInitialization => false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRGBDeviceProvider GetDeviceProvider() => SteelSeriesDeviceProvider.Instance;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -62,7 +62,7 @@ namespace RGB.NET.Devices.WS281X.Arduino
|
||||
dataBuffer[0] = (byte)((channel << 4) | UPDATE_COMMAND[0]);
|
||||
int i = 1;
|
||||
foreach ((byte _, byte r, byte g, byte b) in channelData.OrderBy(x => x.Item1.key)
|
||||
.Select(x => x.Value))
|
||||
.Select(x => x.Value.GetRGBBytes()))
|
||||
{
|
||||
dataBuffer[i++] = r;
|
||||
dataBuffer[i++] = g;
|
||||
|
||||
@ -39,7 +39,7 @@ namespace RGB.NET.Devices.WS281X.Bitwizard
|
||||
protected override IEnumerable<string> GetCommands(Dictionary<object, Color> dataSet)
|
||||
{
|
||||
foreach (KeyValuePair<object, Color> data in dataSet)
|
||||
yield return $"pix {(int)data.Key} {data.Value.AsRGBHexString()}";
|
||||
yield return $"pix {(int)data.Key} {data.Value.AsRGBHexString(false)}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
16
RGB.NET.sln
16
RGB.NET.sln
@ -39,6 +39,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Groups", "RGB.NET.G
|
||||
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
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Devices.SteelSeries", "RGB.NET.Devices.SteelSeries\RGB.NET.Devices.SteelSeries.csproj", "{FFDE4387-60F2-47B6-9704-3A57D02B8C64}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{92D7C263-D4C9-4D26-93E2-93C1F9C2CD16}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RGB.NET.Core.Tests", "Tests\RGB.NET.Core.Tests\RGB.NET.Core.Tests.csproj", "{A3FD5AD7-040A-47CA-A278-53493A25FF8A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -109,6 +115,14 @@ Global
|
||||
{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
|
||||
{0AD382DA-E999-4F74-9658-8D402EE9BF3F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FFDE4387-60F2-47B6-9704-3A57D02B8C64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FFDE4387-60F2-47B6-9704-3A57D02B8C64}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FFDE4387-60F2-47B6-9704-3A57D02B8C64}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FFDE4387-60F2-47B6-9704-3A57D02B8C64}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A3FD5AD7-040A-47CA-A278-53493A25FF8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A3FD5AD7-040A-47CA-A278-53493A25FF8A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A3FD5AD7-040A-47CA-A278-53493A25FF8A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A3FD5AD7-040A-47CA-A278-53493A25FF8A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -129,6 +143,8 @@ Global
|
||||
{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}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {7F222AD4-1F9E-4AAB-9D69-D62372D4C1BA}
|
||||
|
||||
395
Tests/RGB.NET.Core.Tests/Color/ColorTest.cs
Normal file
395
Tests/RGB.NET.Core.Tests/Color/ColorTest.cs
Normal file
@ -0,0 +1,395 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace RGB.NET.Core.Tests.Color
|
||||
{
|
||||
[TestClass]
|
||||
public class ColorTest
|
||||
{
|
||||
#region Basics
|
||||
|
||||
[TestMethod]
|
||||
public void VerifyTransparent()
|
||||
{
|
||||
Core.Color transparent = Core.Color.Transparent;
|
||||
|
||||
Assert.AreEqual(0, transparent.GetA(), "A is not 0");
|
||||
Assert.AreEqual(0, transparent.GetR(), "R is not 0");
|
||||
Assert.AreEqual(0, transparent.GetG(), "G is not 0");
|
||||
Assert.AreEqual(0, transparent.GetB(), "B is not 0");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ToStringTest()
|
||||
{
|
||||
Core.Color color = new Core.Color(255, 120, 13, 1);
|
||||
|
||||
Assert.AreEqual("[A: 255, R: 120, G: 13, B: 1]", color.ToString());
|
||||
}
|
||||
|
||||
#region HashCode
|
||||
|
||||
[TestMethod]
|
||||
public void GetHashCodeTestEqual()
|
||||
{
|
||||
Core.Color color1 = new Core.Color(100, 68, 32, 255);
|
||||
Core.Color color2 = new Core.Color(100, 68, 32, 255);
|
||||
|
||||
Assert.AreEqual(color1.GetHashCode(), color2.GetHashCode());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetHashCodeTestNotEqualA()
|
||||
{
|
||||
Core.Color color1 = new Core.Color(100, 68, 32, 255);
|
||||
Core.Color color2 = new Core.Color(99, 68, 32, 255);
|
||||
|
||||
Assert.AreNotEqual(color1.GetHashCode(), color2.GetHashCode());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetHashCodeTestNotEqualR()
|
||||
{
|
||||
Core.Color color1 = new Core.Color(100, 68, 32, 255);
|
||||
Core.Color color2 = new Core.Color(100, 69, 32, 255);
|
||||
|
||||
Assert.AreNotEqual(color1.GetHashCode(), color2.GetHashCode());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetHashCodeTestNotEqualG()
|
||||
{
|
||||
Core.Color color1 = new Core.Color(100, 68, 32, 255);
|
||||
Core.Color color2 = new Core.Color(100, 68, 200, 255);
|
||||
|
||||
Assert.AreNotEqual(color1.GetHashCode(), color2.GetHashCode());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetHashCodeTestNotEqualB()
|
||||
{
|
||||
Core.Color color1 = new Core.Color(100, 68, 32, 255);
|
||||
Core.Color color2 = new Core.Color(100, 68, 32, 0);
|
||||
|
||||
Assert.AreNotEqual(color1.GetHashCode(), color2.GetHashCode());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Equality
|
||||
|
||||
[TestMethod]
|
||||
public void EqualityTestEqual()
|
||||
{
|
||||
Core.Color color1 = new Core.Color(100, 68, 32, 255);
|
||||
Core.Color color2 = new Core.Color(100, 68, 32, 255);
|
||||
|
||||
Assert.IsTrue(color1.Equals(color2), $"Equals returns false on equal colors {color1} and {color2}");
|
||||
Assert.IsTrue(color1 == color2, $"Equal-operator returns false on equal colors {color1} and {color2}");
|
||||
Assert.IsFalse(color1 != color2, $"Not-Equal-operator returns true on equal colors {color1} and {color2}");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EqualityTestNotEqualA()
|
||||
{
|
||||
Core.Color color1 = new Core.Color(100, 68, 32, 255);
|
||||
Core.Color color2 = new Core.Color(99, 68, 32, 255);
|
||||
|
||||
Assert.IsFalse(color1.Equals(color2), $"Equals returns true on not equal colors {color1} and {color2}");
|
||||
Assert.IsFalse(color1 == color2, $"Equal-operator returns true on not equal colors {color1} and {color2}");
|
||||
Assert.IsTrue(color1 != color2, $"Not-Equal-operator returns false on not equal colors {color1} and {color2}");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EqualityTestNotEqualR()
|
||||
{
|
||||
Core.Color color1 = new Core.Color(100, 68, 32, 255);
|
||||
Core.Color color2 = new Core.Color(100, 69, 32, 255);
|
||||
|
||||
Assert.IsFalse(color1.Equals(color2), $"Equals returns true on not equal colors {color1} and {color2}");
|
||||
Assert.IsFalse(color1 == color2, $"Equal-operator returns true on not equal colors {color1} and {color2}");
|
||||
Assert.IsTrue(color1 != color2, $"Not-Equal-operator returns false on not equal colors {color1} and {color2}");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EqualityTestNotEqualG()
|
||||
{
|
||||
Core.Color color1 = new Core.Color(100, 68, 32, 255);
|
||||
Core.Color color2 = new Core.Color(100, 68, 200, 255);
|
||||
|
||||
Assert.IsFalse(color1.Equals(color2), $"Equals returns true on not equal colors {color1} and {color2}");
|
||||
Assert.IsFalse(color1 == color2, $"Equal-operator returns true on not equal colors {color1} and {color2}");
|
||||
Assert.IsTrue(color1 != color2, $"Not-Equal-operator returns false on not equal colors {color1} and {color2}");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EqualityTestNotEqualB()
|
||||
{
|
||||
Core.Color color1 = new Core.Color(100, 68, 32, 255);
|
||||
Core.Color color2 = new Core.Color(100, 68, 32, 0);
|
||||
|
||||
Assert.IsFalse(color1.Equals(color2), $"Equals returns true on not equal colors {color1} and {color2}");
|
||||
Assert.IsFalse(color1 == color2, $"Equal-operator returns true on not equal colors {color1} and {color2}");
|
||||
Assert.IsTrue(color1 != color2, $"Not-Equal-operator returns false on not equal colors {color1} and {color2}");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
[TestMethod]
|
||||
public void RGBByteConstructorTest()
|
||||
{
|
||||
Core.Color color = new Core.Color((byte)10, (byte)120, (byte)255);
|
||||
|
||||
Assert.AreEqual(255, color.GetA(), "A is not 255");
|
||||
Assert.AreEqual(10, color.GetR(), "R is not 10");
|
||||
Assert.AreEqual(120, color.GetG(), "G is not 120");
|
||||
Assert.AreEqual(255, color.GetB(), "B is not 255");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ARGBByteConstructorTest()
|
||||
{
|
||||
Core.Color color = new Core.Color((byte)200, (byte)10, (byte)120, (byte)255);
|
||||
|
||||
Assert.AreEqual(200, color.GetA(), "A is not 200");
|
||||
Assert.AreEqual(10, color.GetR(), "R is not 10");
|
||||
Assert.AreEqual(120, color.GetG(), "G is not 120");
|
||||
Assert.AreEqual(255, color.GetB(), "B is not 255");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RGBIntConstructorTest()
|
||||
{
|
||||
Core.Color color = new Core.Color(10, 120, 255);
|
||||
|
||||
Assert.AreEqual(255, color.GetA(), "A is not 255");
|
||||
Assert.AreEqual(10, color.GetR(), "R is not 10");
|
||||
Assert.AreEqual(120, color.GetG(), "G is not 120");
|
||||
Assert.AreEqual(255, color.GetB(), "B is not 255");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ARGBIntConstructorTest()
|
||||
{
|
||||
Core.Color color = new Core.Color(200, 10, 120, 255);
|
||||
|
||||
Assert.AreEqual(200, color.GetA(), "A is not 200");
|
||||
Assert.AreEqual(10, color.GetR(), "R is not 10");
|
||||
Assert.AreEqual(120, color.GetG(), "G is not 120");
|
||||
Assert.AreEqual(255, color.GetB(), "B is not 255");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RGBIntConstructorClampTest()
|
||||
{
|
||||
Core.Color color1 = new Core.Color(256, 256, 256);
|
||||
|
||||
Assert.AreEqual(255, color1.GetA(), "A is not 255");
|
||||
Assert.AreEqual(255, color1.GetR(), "R is not 255");
|
||||
Assert.AreEqual(255, color1.GetG(), "G is not 255");
|
||||
Assert.AreEqual(255, color1.GetB(), "B is not 255");
|
||||
|
||||
Core.Color color2 = new Core.Color(-1, -1, -1);
|
||||
|
||||
Assert.AreEqual(255, color2.GetA(), "A is not 255");
|
||||
Assert.AreEqual(0, color2.GetR(), "R is not 0");
|
||||
Assert.AreEqual(0, color2.GetG(), "G is not 0");
|
||||
Assert.AreEqual(0, color2.GetB(), "B is not 0");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ARGBIntConstructorClampTest()
|
||||
{
|
||||
Core.Color color = new Core.Color(256, 256, 256, 256);
|
||||
|
||||
Assert.AreEqual(255, color.GetA(), "A is not 255");
|
||||
Assert.AreEqual(255, color.GetR(), "R is not 255");
|
||||
Assert.AreEqual(255, color.GetG(), "G is not 255");
|
||||
Assert.AreEqual(255, color.GetB(), "B is not 255");
|
||||
|
||||
Core.Color color2 = new Core.Color(-1, -1, -1, -1);
|
||||
|
||||
Assert.AreEqual(0, color2.GetA(), "A is not 0");
|
||||
Assert.AreEqual(0, color2.GetR(), "R is not 0");
|
||||
Assert.AreEqual(0, color2.GetG(), "G is not 0");
|
||||
Assert.AreEqual(0, color2.GetB(), "B is not 0");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RGBPercentConstructorTest()
|
||||
{
|
||||
Core.Color color = new Core.Color(0.25341, 0.55367, 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");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ARGBPercentConstructorTest()
|
||||
{
|
||||
Core.Color color = new Core.Color(0.3315, 0.25341, 0.55367, 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");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RGBPercentConstructorClampTest()
|
||||
{
|
||||
Core.Color color1 = new Core.Color(1.1, 1.1, 1.1);
|
||||
|
||||
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 Core.Color(-1.0, -1.0, -1.0);
|
||||
|
||||
Assert.AreEqual(1, color2.A, "A is not 1");
|
||||
Assert.AreEqual(0, color2.R, "R is not 0");
|
||||
Assert.AreEqual(0, color2.G, "G is not 0");
|
||||
Assert.AreEqual(0, color2.B, "B is not 0");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ARGBPercentConstructorClampTest()
|
||||
{
|
||||
Core.Color color1 = new Core.Color(1.1, 1.1, 1.1, 1.1);
|
||||
|
||||
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 Core.Color(-1.0, -1.0, -1.0, -1.0);
|
||||
|
||||
Assert.AreEqual(0, color2.A, "A is not 0");
|
||||
Assert.AreEqual(0, color2.R, "R is not 0");
|
||||
Assert.AreEqual(0, color2.G, "G is not 0");
|
||||
Assert.AreEqual(0, color2.B, "B is not 0");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CloneConstructorTest()
|
||||
{
|
||||
Core.Color referennceColor = new Core.Color(200, 10, 120, 255);
|
||||
Core.Color color = new Core.Color(referennceColor);
|
||||
|
||||
Assert.AreEqual(200, color.GetA(), "A is not 200");
|
||||
Assert.AreEqual(10, color.GetR(), "R is not 10");
|
||||
Assert.AreEqual(120, color.GetG(), "G is not 120");
|
||||
Assert.AreEqual(255, color.GetB(), "B is not 255");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Conversion
|
||||
|
||||
[TestMethod]
|
||||
public void ColorFromComponentsTest()
|
||||
{
|
||||
Core.Color color = (255, 120, 13, 1);
|
||||
|
||||
Assert.AreEqual(255, color.GetA(), $"A doesn't equal the used component. ({color.GetA()} != 255)");
|
||||
Assert.AreEqual(120, color.GetR(), $"R doesn't equal the used component. ({color.GetR()} != 120)");
|
||||
Assert.AreEqual(13, color.GetG(), $"G doesn't equal the used component. ({color.GetG()} != 13)");
|
||||
Assert.AreEqual(1, color.GetB(), $"B doesn't equal the used component. ({color.GetB()} != 1)");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DesconstructTest()
|
||||
{
|
||||
(byte a, byte r, byte g, byte b) = new Core.Color(255, 120, 13, 1).GetRGBBytes();
|
||||
|
||||
Assert.AreEqual(255, a, $"A doesn't equal the color. ({a} != 255)");
|
||||
Assert.AreEqual(120, r, $"R doesn't equal the color. ({r} != 120)");
|
||||
Assert.AreEqual(13, g, $"G doesn't equal the color. ({g} != 13)");
|
||||
Assert.AreEqual(1, b, $"B doesn't equal the color. ({b} != 1)");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AToPercentTest()
|
||||
{
|
||||
Core.Color color1 = new Core.Color(0, 0, 0, 0);
|
||||
Assert.AreEqual(0, color1.A);
|
||||
|
||||
Core.Color color2 = new Core.Color(255, 0, 0, 0);
|
||||
Assert.AreEqual(1, color2.A);
|
||||
|
||||
Core.Color color3 = new Core.Color(128, 0, 0, 0);
|
||||
Assert.AreEqual(128 / 255.0, color3.A);
|
||||
|
||||
Core.Color color4 = new Core.Color(30, 0, 0, 0);
|
||||
Assert.AreEqual(30 / 255.0, color4.A);
|
||||
|
||||
Core.Color color5 = new Core.Color(201, 0, 0, 0);
|
||||
Assert.AreEqual(201 / 255.0, color5.A);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RToPercentTest()
|
||||
{
|
||||
Core.Color color1 = new Core.Color(0, 0, 0, 0);
|
||||
Assert.AreEqual(0, color1.R);
|
||||
|
||||
Core.Color color2 = new Core.Color(0, 255, 0, 0);
|
||||
Assert.AreEqual(1, color2.R);
|
||||
|
||||
Core.Color color3 = new Core.Color(0, 128, 0, 0);
|
||||
Assert.AreEqual(128 / 255.0, color3.R);
|
||||
|
||||
Core.Color color4 = new Core.Color(0, 30, 0, 0);
|
||||
Assert.AreEqual(30 / 255.0, color4.R);
|
||||
|
||||
Core.Color color5 = new Core.Color(0, 201, 0, 0);
|
||||
Assert.AreEqual(201 / 255.0, color5.R);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GToPercentTest()
|
||||
{
|
||||
Core.Color color1 = new Core.Color(0, 0, 0, 0);
|
||||
Assert.AreEqual(0, color1.G);
|
||||
|
||||
Core.Color color2 = new Core.Color(0, 0, 255, 0);
|
||||
Assert.AreEqual(1, color2.G);
|
||||
|
||||
Core.Color color3 = new Core.Color(0, 0, 128, 0);
|
||||
Assert.AreEqual(128 / 255.0, color3.G);
|
||||
|
||||
Core.Color color4 = new Core.Color(0, 0, 30, 0);
|
||||
Assert.AreEqual(30 / 255.0, color4.G);
|
||||
|
||||
Core.Color color5 = new Core.Color(0, 0, 201, 0);
|
||||
Assert.AreEqual(201 / 255.0, color5.G);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void BToPercentTest()
|
||||
{
|
||||
Core.Color color1 = new Core.Color(0, 0, 0, 0);
|
||||
Assert.AreEqual(0, color1.B);
|
||||
|
||||
Core.Color color2 = new Core.Color(0, 0, 0, 255);
|
||||
Assert.AreEqual(1, color2.B);
|
||||
|
||||
Core.Color color3 = new Core.Color(0, 0, 0, 128);
|
||||
Assert.AreEqual(128 / 255.0, color3.B);
|
||||
|
||||
Core.Color color4 = new Core.Color(0, 0, 0, 30);
|
||||
Assert.AreEqual(30 / 255.0, color4.B);
|
||||
|
||||
Core.Color color5 = new Core.Color(0, 0, 0, 201);
|
||||
Assert.AreEqual(201 / 255.0, color5.B);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
284
Tests/RGB.NET.Core.Tests/Color/HSVColorTest.cs
Normal file
284
Tests/RGB.NET.Core.Tests/Color/HSVColorTest.cs
Normal file
@ -0,0 +1,284 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace RGB.NET.Core.Tests.Color
|
||||
{
|
||||
[TestClass]
|
||||
public class HSVColorTest
|
||||
{
|
||||
#region Manipulation
|
||||
|
||||
#region Add
|
||||
|
||||
[TestMethod]
|
||||
public void AddHueTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.AddHSV(hue: 30);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(210, 0.5, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddHueWrapTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.AddHSV(hue: 220);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(40, 0.5, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddSaturationTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.AddHSV(saturation: 0.3);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 0.8, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddSaturationClampTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.AddHSV(saturation: 0.8);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 1.0, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddValueTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.AddHSV(value: 0.3);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 0.5, 0.8), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddValueClampTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.AddHSV(value: 0.8);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 0.5, 1.0), result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Subtract
|
||||
|
||||
[TestMethod]
|
||||
public void SubtractHueTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SubtractHSV(hue: 30);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(150, 0.5, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SubtractHueWrapTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SubtractHSV(hue: 220);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(320, 0.5, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SubtractSaturationTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SubtractHSV(saturation: 0.3);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 0.2, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SubtractSaturationClampTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SubtractHSV(saturation: 0.8);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 0, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SubtractValueTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SubtractHSV(value: 0.3);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 0.5, 0.2), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SubtractValueClampTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SubtractHSV(value: .8);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 0.5, 0), result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Multiply
|
||||
|
||||
[TestMethod]
|
||||
public void MultiplyHueTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.MultiplyHSV(hue: 1.5);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(270, 0.5, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MultiplyHueWrapTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.MultiplyHSV(hue: 3);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 0.5, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MultiplySaturationTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.2, 0.2);
|
||||
Core.Color result = baseColor.MultiplyHSV(saturation: 3);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 0.6, 0.2), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MultiplySaturationClampTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.MultiplyHSV(saturation: 3);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 1.0, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MultiplyValueTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.2, 0.2);
|
||||
Core.Color result = baseColor.MultiplyHSV(value: 3);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 0.2, 0.6), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MultiplyValueClampTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.MultiplyHSV(value: 3);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 0.5, 1.0), result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Divide
|
||||
|
||||
[TestMethod]
|
||||
public void DivideHueTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.DivideHSV(hue: 30);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(6, 0.5, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DivideSaturationTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.6, 0.6);
|
||||
Core.Color result = baseColor.DivideHSV(saturation: 2);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 0.3, 0.6), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DivideValueTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.6, 0.6);
|
||||
Core.Color result = baseColor.DivideHSV(value: 2);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 0.6, 0.3), result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Set
|
||||
|
||||
[TestMethod]
|
||||
public void SetHueTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SetHSV(hue: 30);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(30, 0.5, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SetHueWrapTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SetHSV(hue: 440);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(80, 0.5, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SetHueWrapNegativeTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SetHSV(hue: -30);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(330, 0.5, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SetSaturationTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SetHSV(saturation: 0.3);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 0.3, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SetSaturationClampTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SetHSV(saturation: 2);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 1.0, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SetValueTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SetHSV(value: 0.3);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 0.5, 0.3), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SetValueClampTest()
|
||||
{
|
||||
Core.Color baseColor = HSVColor.Create(180, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SetHSV(value: 2);
|
||||
|
||||
Assert.AreEqual(HSVColor.Create(180, 0.5, 1.0), result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
432
Tests/RGB.NET.Core.Tests/Color/RGBColorTest.cs
Normal file
432
Tests/RGB.NET.Core.Tests/Color/RGBColorTest.cs
Normal file
@ -0,0 +1,432 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace RGB.NET.Core.Tests.Color
|
||||
{
|
||||
[TestClass]
|
||||
public class RGBColorTest
|
||||
{
|
||||
#region Manipulation
|
||||
|
||||
#region Blend
|
||||
|
||||
[TestMethod]
|
||||
public void BlendOpaqueTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(255, 0, 0);
|
||||
Core.Color blendColor = new Core.Color(0, 255, 0);
|
||||
|
||||
Assert.AreEqual(blendColor, baseColor.Blend(blendColor));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void BlendTransparentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(255, 0, 0);
|
||||
Core.Color blendColor = new Core.Color(0, 0, 255, 0);
|
||||
|
||||
Assert.AreEqual(baseColor, baseColor.Blend(blendColor));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void BlendUpTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.0, 0.0, 0.0);
|
||||
Core.Color blendColor = new Core.Color(0.5, 1.0, 1.0, 1.0);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.5, 0.5, 0.5), baseColor.Blend(blendColor));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void BlendDownTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(1.0, 1.0, 1.0);
|
||||
Core.Color blendColor = new Core.Color(0.5, 0.0, 0.0, 0.0);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.5, 0.5, 0.5), baseColor.Blend(blendColor));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Add
|
||||
|
||||
[TestMethod]
|
||||
public void AddRGBTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(128, 128, 128, 128);
|
||||
Core.Color result = baseColor.AddRGB(11, 12, 13);
|
||||
|
||||
Assert.AreEqual(new Core.Color(128, 139, 140, 141), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddRGBPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.5, 0.5, 0.5, 0.5);
|
||||
Core.Color result = baseColor.AddRGB(0.2, 0.3, 0.4);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.5, 0.7, 0.8, 0.9), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddATest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(128, 128, 128, 128);
|
||||
Core.Color result = baseColor.AddA(10);
|
||||
|
||||
Assert.AreEqual(new Core.Color(138, 128, 128, 128), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddAPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.5, 0.5, 0.5, 0.5);
|
||||
Core.Color result = baseColor.AddA(0.1);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.6, 0.5, 0.5, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddRTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(128, 128, 128, 128);
|
||||
Core.Color result = baseColor.AddRGB(r: 10);
|
||||
|
||||
Assert.AreEqual(new Core.Color(128, 138, 128, 128), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddRPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.5, 0.5, 0.5, 0.5);
|
||||
Core.Color result = baseColor.AddRGB(r: 0.1);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.5, 0.6, 0.5, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddGTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(128, 128, 128, 128);
|
||||
Core.Color result = baseColor.AddRGB(g: 10);
|
||||
|
||||
Assert.AreEqual(new Core.Color(128, 128, 138, 128), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddGPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.5, 0.5, 0.5, 0.5);
|
||||
Core.Color result = baseColor.AddRGB(g: 0.1);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.5, 0.5, 0.6, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddBTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(128, 128, 128, 128);
|
||||
Core.Color result = baseColor.AddRGB(b: 10);
|
||||
|
||||
Assert.AreEqual(new Core.Color(128, 128, 128, 138), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddBPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.5, 0.5, 0.5, 0.5);
|
||||
Core.Color result = baseColor.AddRGB(b: 0.1);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.5, 0.5, 0.5, 0.6), result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Substract
|
||||
|
||||
[TestMethod]
|
||||
public void SubtractRGBTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(128, 128, 128, 128);
|
||||
Core.Color result = baseColor.SubtractRGB(11, 12, 13);
|
||||
|
||||
Assert.AreEqual(new Core.Color(128, 117, 116, 115), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SubtractRGBPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.5, 0.5, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SubtractRGB(0.2, 0.3, 0.4);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.5, 0.3, 0.2, 0.1), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SubtractATest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(128, 128, 128, 128);
|
||||
Core.Color result = baseColor.SubtractA(10);
|
||||
|
||||
Assert.AreEqual(new Core.Color(118, 128, 128, 128), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SubtractAPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.5, 0.5, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SubtractA(0.1);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.4, 0.5, 0.5, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SubtractRTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(128, 128, 128, 128);
|
||||
Core.Color result = baseColor.SubtractRGB(r: 10);
|
||||
|
||||
Assert.AreEqual(new Core.Color(128, 118, 128, 128), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SubtractRPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.5, 0.5, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SubtractRGB(r: 0.1);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.5, 0.4, 0.5, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SubtractGTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(128, 128, 128, 128);
|
||||
Core.Color result = baseColor.SubtractRGB(g: 10);
|
||||
|
||||
Assert.AreEqual(new Core.Color(128, 128, 118, 128), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SubtractGPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.5, 0.5, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SubtractRGB(g: 0.1);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.5, 0.5, 0.4, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SubtractBTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(128, 128, 128, 128);
|
||||
Core.Color result = baseColor.SubtractRGB(b: 10);
|
||||
|
||||
Assert.AreEqual(new Core.Color(128, 128, 128, 118), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SubtractBPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.5, 0.5, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SubtractRGB(b: 0.1);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.5, 0.5, 0.5, 0.4), result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Multiply
|
||||
|
||||
[TestMethod]
|
||||
public void MultiplyRGBPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.2, 0.2, 0.2, 0.2);
|
||||
Core.Color result = baseColor.MultiplyRGB(3, 4, 5);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.2, 0.6, 0.8, 1.0), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MultiplyAPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.2, 0.2, 0.2, 0.2);
|
||||
Core.Color result = baseColor.MultiplyA(3);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.6, 0.2, 0.2, 0.2), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MultiplyRPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.2, 0.2, 0.2, 0.2);
|
||||
Core.Color result = baseColor.MultiplyRGB(r: 3);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.2, 0.6, 0.2, 0.2), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MultiplyGPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.2, 0.2, 0.2, 0.2);
|
||||
Core.Color result = baseColor.MultiplyRGB(g: 3);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.2, 0.2, 0.6, 0.2), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MultiplyBPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.2, 0.2, 0.2, 0.2);
|
||||
Core.Color result = baseColor.MultiplyRGB(b: 3);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.2, 0.2, 0.2, 0.6), result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Divide
|
||||
|
||||
[TestMethod]
|
||||
public void DivideRGBPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.2, 0.6, 0.8, 1.0);
|
||||
Core.Color result = baseColor.DivideRGB(3, 4, 5);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.2, 0.2, 0.2, 0.2), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DivideAPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.6, 0.2, 0.2, 0.2);
|
||||
Core.Color result = baseColor.DivideA(3);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.2, 0.2, 0.2, 0.2), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DivideRPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.2, 0.6, 0.2, 0.2);
|
||||
Core.Color result = baseColor.DivideRGB(r: 3);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.2, 0.2, 0.2, 0.2), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DivideGPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.2, 0.2, 0.6, 0.2);
|
||||
Core.Color result = baseColor.DivideRGB(g: 3);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.2, 0.2, 0.2, 0.2), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DivideBPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.2, 0.2, 0.2, 0.6);
|
||||
Core.Color result = baseColor.DivideRGB(b: 3);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.2, 0.2, 0.2, 0.2), result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Set
|
||||
|
||||
[TestMethod]
|
||||
public void SetRGBTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(128, 128, 128, 128);
|
||||
Core.Color result = baseColor.SetRGB(11, 12, 13);
|
||||
|
||||
Assert.AreEqual(new Core.Color(128, 11, 12, 13), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SetRGBPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.5, 0.5, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SetRGB(0.2, 0.3, 0.4);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.5, 0.2, 0.3, 0.4), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SetATest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(128, 128, 128, 128);
|
||||
Core.Color result = baseColor.SetA(10);
|
||||
|
||||
Assert.AreEqual(new Core.Color(10, 128, 128, 128), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SetAPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.5, 0.5, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SetA(0.1);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.1, 0.5, 0.5, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SetRTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(128, 128, 128, 128);
|
||||
Core.Color result = baseColor.SetRGB(r: 10);
|
||||
|
||||
Assert.AreEqual(new Core.Color(128, 10, 128, 128), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SetRPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.5, 0.5, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SetRGB(r: 0.1);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.5, 0.1, 0.5, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SetGTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(128, 128, 128, 128);
|
||||
Core.Color result = baseColor.SetRGB(g: 10);
|
||||
|
||||
Assert.AreEqual(new Core.Color(128, 128, 10, 128), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SetGPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.5, 0.5, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SetRGB(g: 0.1);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.5, 0.5, 0.1, 0.5), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SetBTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(128, 128, 128, 128);
|
||||
Core.Color result = baseColor.SetRGB(b: 10);
|
||||
|
||||
Assert.AreEqual(new Core.Color(128, 128, 128, 10), result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SetBPercentTest()
|
||||
{
|
||||
Core.Color baseColor = new Core.Color(0.5, 0.5, 0.5, 0.5);
|
||||
Core.Color result = baseColor.SetRGB(b: 0.1);
|
||||
|
||||
Assert.AreEqual(new Core.Color(0.5, 0.5, 0.5, 0.1), result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
19
Tests/RGB.NET.Core.Tests/RGB.NET.Core.Tests.csproj
Normal file
19
Tests/RGB.NET.Core.Tests/RGB.NET.Core.Tests.csproj
Normal file
@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="1.3.2" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="1.3.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\RGB.NET.Core\RGB.NET.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Loading…
x
Reference in New Issue
Block a user