-
Notifications
You must be signed in to change notification settings - Fork 77
Description
Approved from Discussion
https://discord.com/channels/372137812037730304/1430217634204356608
Problem Statement
The current ColorHelper API is unintuitive for an object-oriented environment and poorly utilizes the HsvColor and HslColor.
Overview
Proposed ColorHelper API
public static class ColorHelper
{
public static bool TryParseColor(string colorString, out Color color);
public static bool TryParseHexColor(string hexString, out Color color);
public static bool TryParseHslColor(string hslColor, out Color color);
public static bool TryParseHsvColor(string hsvColor, out Color color);
public static bool TryParseScreenColor(string screenColor, out Color color);
public static bool TryParseColorName(string colorName, out Color color);
public static Color ParseColor(string colorString);
public static Color ParseHexColor(string hexString);
public static Color ParseHslColor(string hslColor);
public static Color ParseHsvColor(string hsvColor);
public static Color ParseScreenColor(string screenColor);
public static Color ParseColorName(string colorName);
}
public static class ColorExtensions
{
public static int ToInt(this Color color);
public static HslColor ToHsl(this Color color);
public static HsvColor ToHsv(this Color color);
}
public struct HslColor
{
// The properties will apply clamps on set to restrict the values to a valid range
public double H { readonly get; set;}
public double S { readonly get; set;}
public double L { readonly get; set;}
public double A { readonly get; set;}
public static HslColor Create(double hue, double saturation, double lightness, double alpha = 1);
public Color ToColor();
public string ToString(); // hsv(hue, sat, lightness)
// Cast operators
public static implicit operator Color(HslColor color);
public static explicit operator HslColor(Color color);
public static explicit operator HslColor(HsvColor color);
}
public struct HsvColor
{
// The properties will apply clamps on set to restrict the values to a valid range
public double H { readonly get; set;}
public double S { readonly get; set;}
public double V { readonly get; set;}
public double A { readonly get; set;}
public static HsvColor Create(double hue, double saturation, double value, double alpha = 1);
public Color ToColor();
public string ToString(); // hsv(hue, sat, value)
// Cast operators
public static implicit operator Color(HsvColor color);
public static explicit operator HsvColor(Color color);
public static explicit operator HsvColor(HslColor color);
}
Breaking Changes
Due to its nature as an API change, this proposal would introduce breaking changes. However, each of these changes can be easily remedied by a simple change in function call or by utilizing a casting operation.
Method changes
(These will be marked obsolete, but will still be available until the next major version)
ToHex(this Color color)
- Redundant withToString()
ToColor(this string colorString)
- Replaced withColorHelper.ParseColor(string colorString)
ColorHelper.FromHsl(double hue, ...)
- Replaced with(Color)HslColor.Create(double hue, ...)
(NOTE: The cast could be done implicitly)ColorHelper.FromHsv(double hue, ...)
- Replaced with(Color)HsvColor.Create(double hue, ...)
(NOTE: The cast could be done implicitly)
Also, the ToColor
function only supported hex, screen color, and color name parsing. In the current version I have drafted, ParseColor
also only supports these and does not support hsl or hsv, even though in my opinion it probably should... This would result in a changed behavior, and therefore I have not yet added it.
Struct changes
All members of the HslColor
and HsvColor
structs were public fields with no constraints in value.
These have been replaced with properties that have been restricted to valid ranges for the property. If a developer had been relying on invalid ranges or behavior related to the members being fields, this will no longer work.
In the following example, hsl.H
would previously be 500
but will now be clamped to 360
.
HslColor hsl = default;
hsl.H = 500;
These changes also mean that the struct must be given a value before being used.
For example, the following code would be valid before but would now say that hsl
is not defined on the second line.
HslColor hsl;
hsl.H = 240;