|
@@ -3,15 +3,44 @@ using System.Runtime.InteropServices;
|
|
|
|
|
|
namespace Godot
|
|
|
{
|
|
|
+ /// <summary>
|
|
|
+ /// A color represented by red, green, blue, and alpha (RGBA) components.
|
|
|
+ /// The alpha component is often used for transparency.
|
|
|
+ /// Values are in floating-point and usually range from 0 to 1.
|
|
|
+ /// Some properties (such as CanvasItem.modulate) may accept values
|
|
|
+ /// greater than 1 (overbright or HDR colors).
|
|
|
+ ///
|
|
|
+ /// If you want to supply values in a range of 0 to 255, you should use
|
|
|
+ /// <see cref="Color8"/> and the `r8`/`g8`/`b8`/`a8` properties.
|
|
|
+ /// </summary>
|
|
|
[Serializable]
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
public struct Color : IEquatable<Color>
|
|
|
{
|
|
|
+ /// <summary>
|
|
|
+ /// The color's red component, typically on the range of 0 to 1.
|
|
|
+ /// </summary>
|
|
|
public float r;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// The color's green component, typically on the range of 0 to 1.
|
|
|
+ /// </summary>
|
|
|
public float g;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// The color's blue component, typically on the range of 0 to 1.
|
|
|
+ /// </summary>
|
|
|
public float b;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// The color's alpha (transparency) component, typically on the range of 0 to 1.
|
|
|
+ /// </summary>
|
|
|
public float a;
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Wrapper for <see cref="r"/> that uses the range 0 to 255 instead of 0 to 1.
|
|
|
+ /// </summary>
|
|
|
+ /// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
|
|
|
public int r8
|
|
|
{
|
|
|
get
|
|
@@ -24,6 +53,10 @@ namespace Godot
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Wrapper for <see cref="g"/> that uses the range 0 to 255 instead of 0 to 1.
|
|
|
+ /// </summary>
|
|
|
+ /// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
|
|
|
public int g8
|
|
|
{
|
|
|
get
|
|
@@ -36,6 +69,10 @@ namespace Godot
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Wrapper for <see cref="b"/> that uses the range 0 to 255 instead of 0 to 1.
|
|
|
+ /// </summary>
|
|
|
+ /// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
|
|
|
public int b8
|
|
|
{
|
|
|
get
|
|
@@ -48,6 +85,10 @@ namespace Godot
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Wrapper for <see cref="a"/> that uses the range 0 to 255 instead of 0 to 1.
|
|
|
+ /// </summary>
|
|
|
+ /// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
|
|
|
public int a8
|
|
|
{
|
|
|
get
|
|
@@ -60,6 +101,10 @@ namespace Godot
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// The HSV hue of this color, on the range 0 to 1.
|
|
|
+ /// </summary>
|
|
|
+ /// <value>Getting is a long process, refer to the source code for details. Setting uses <see cref="FromHsv"/>.</value>
|
|
|
public float h
|
|
|
{
|
|
|
get
|
|
@@ -70,21 +115,31 @@ namespace Godot
|
|
|
float delta = max - min;
|
|
|
|
|
|
if (delta == 0)
|
|
|
+ {
|
|
|
return 0;
|
|
|
+ }
|
|
|
|
|
|
float h;
|
|
|
|
|
|
if (r == max)
|
|
|
+ {
|
|
|
h = (g - b) / delta; // Between yellow & magenta
|
|
|
+ }
|
|
|
else if (g == max)
|
|
|
+ {
|
|
|
h = 2 + (b - r) / delta; // Between cyan & yellow
|
|
|
+ }
|
|
|
else
|
|
|
+ {
|
|
|
h = 4 + (r - g) / delta; // Between magenta & cyan
|
|
|
+ }
|
|
|
|
|
|
h /= 6.0f;
|
|
|
|
|
|
if (h < 0)
|
|
|
+ {
|
|
|
h += 1.0f;
|
|
|
+ }
|
|
|
|
|
|
return h;
|
|
|
}
|
|
@@ -94,6 +149,10 @@ namespace Godot
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// The HSV saturation of this color, on the range 0 to 1.
|
|
|
+ /// </summary>
|
|
|
+ /// <value>Getting is equivalent to the ratio between the min and max RGB value. Setting uses <see cref="FromHsv"/>.</value>
|
|
|
public float s
|
|
|
{
|
|
|
get
|
|
@@ -103,7 +162,7 @@ namespace Godot
|
|
|
|
|
|
float delta = max - min;
|
|
|
|
|
|
- return max != 0 ? delta / max : 0;
|
|
|
+ return max == 0 ? 0 : delta / max;
|
|
|
}
|
|
|
set
|
|
|
{
|
|
@@ -111,6 +170,10 @@ namespace Godot
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// The HSV value (brightness) of this color, on the range 0 to 1.
|
|
|
+ /// </summary>
|
|
|
+ /// <value>Getting is equivalent to using `Max()` on the RGB components. Setting uses <see cref="FromHsv"/>.</value>
|
|
|
public float v
|
|
|
{
|
|
|
get
|
|
@@ -123,25 +186,10 @@ namespace Godot
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public static Color ColorN(string name, float alpha = 1f)
|
|
|
- {
|
|
|
- name = name.Replace(" ", String.Empty);
|
|
|
- name = name.Replace("-", String.Empty);
|
|
|
- name = name.Replace("_", String.Empty);
|
|
|
- name = name.Replace("'", String.Empty);
|
|
|
- name = name.Replace(".", String.Empty);
|
|
|
- name = name.ToLower();
|
|
|
-
|
|
|
- if (!Colors.namedColors.ContainsKey(name))
|
|
|
- {
|
|
|
- throw new ArgumentOutOfRangeException($"Invalid Color Name: {name}");
|
|
|
- }
|
|
|
-
|
|
|
- Color color = Colors.namedColors[name];
|
|
|
- color.a = alpha;
|
|
|
- return color;
|
|
|
- }
|
|
|
-
|
|
|
+ /// <summary>
|
|
|
+ /// Access color components using their index.
|
|
|
+ /// </summary>
|
|
|
+ /// <value>`[0]` is equivalent to `.r`, `[1]` is equivalent to `.g`, `[2]` is equivalent to `.b`, `[3]` is equivalent to `.a`.</value>
|
|
|
public float this[int index]
|
|
|
{
|
|
|
get
|
|
@@ -182,73 +230,13 @@ namespace Godot
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void ToHsv(out float hue, out float saturation, out float value)
|
|
|
- {
|
|
|
- float max = (float)Mathf.Max(r, Mathf.Max(g, b));
|
|
|
- float min = (float)Mathf.Min(r, Mathf.Min(g, b));
|
|
|
-
|
|
|
- float delta = max - min;
|
|
|
-
|
|
|
- if (delta == 0)
|
|
|
- {
|
|
|
- hue = 0;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- if (r == max)
|
|
|
- hue = (g - b) / delta; // Between yellow & magenta
|
|
|
- else if (g == max)
|
|
|
- hue = 2 + (b - r) / delta; // Between cyan & yellow
|
|
|
- else
|
|
|
- hue = 4 + (r - g) / delta; // Between magenta & cyan
|
|
|
-
|
|
|
- hue /= 6.0f;
|
|
|
-
|
|
|
- if (hue < 0)
|
|
|
- hue += 1.0f;
|
|
|
- }
|
|
|
-
|
|
|
- saturation = max == 0 ? 0 : 1f - 1f * min / max;
|
|
|
- value = max;
|
|
|
- }
|
|
|
-
|
|
|
- public static Color FromHsv(float hue, float saturation, float value, float alpha = 1.0f)
|
|
|
- {
|
|
|
- if (saturation == 0)
|
|
|
- {
|
|
|
- // acp_hromatic (grey)
|
|
|
- return new Color(value, value, value, alpha);
|
|
|
- }
|
|
|
-
|
|
|
- int i;
|
|
|
- float f, p, q, t;
|
|
|
-
|
|
|
- hue *= 6.0f;
|
|
|
- hue %= 6f;
|
|
|
- i = (int)hue;
|
|
|
-
|
|
|
- f = hue - i;
|
|
|
- p = value * (1 - saturation);
|
|
|
- q = value * (1 - saturation * f);
|
|
|
- t = value * (1 - saturation * (1 - f));
|
|
|
-
|
|
|
- switch (i)
|
|
|
- {
|
|
|
- case 0: // Red is the dominant color
|
|
|
- return new Color(value, t, p, alpha);
|
|
|
- case 1: // Green is the dominant color
|
|
|
- return new Color(q, value, p, alpha);
|
|
|
- case 2:
|
|
|
- return new Color(p, value, t, alpha);
|
|
|
- case 3: // Blue is the dominant color
|
|
|
- return new Color(p, q, value, alpha);
|
|
|
- case 4:
|
|
|
- return new Color(t, p, value, alpha);
|
|
|
- default: // (5) Red is the dominant color
|
|
|
- return new Color(value, p, q, alpha);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
+ /// <summary>
|
|
|
+ /// Returns a new color resulting from blending this color over another.
|
|
|
+ /// If the color is opaque, the result is also opaque.
|
|
|
+ /// The second color may have a range of alpha values.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="over">The color to blend over.</param>
|
|
|
+ /// <returns>This color blended over `over`.</returns>
|
|
|
public Color Blend(Color over)
|
|
|
{
|
|
|
Color res;
|
|
@@ -268,6 +256,10 @@ namespace Godot
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Returns the most contrasting color.
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>The most contrasting color</returns>
|
|
|
public Color Contrasted()
|
|
|
{
|
|
|
return new Color(
|
|
@@ -278,6 +270,12 @@ namespace Godot
|
|
|
);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Returns a new color resulting from making this color darker
|
|
|
+ /// by the specified ratio (on the range of 0 to 1).
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="amount">The ratio to darken by.</param>
|
|
|
+ /// <returns>The darkened color.</returns>
|
|
|
public Color Darkened(float amount)
|
|
|
{
|
|
|
Color res = this;
|
|
@@ -287,6 +285,10 @@ namespace Godot
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Returns the inverted color: `(1 - r, 1 - g, 1 - b, a)`.
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>The inverted color.</returns>
|
|
|
public Color Inverted()
|
|
|
{
|
|
|
return new Color(
|
|
@@ -297,6 +299,12 @@ namespace Godot
|
|
|
);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Returns a new color resulting from making this color lighter
|
|
|
+ /// by the specified ratio (on the range of 0 to 1).
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="amount">The ratio to lighten by.</param>
|
|
|
+ /// <returns>The darkened color.</returns>
|
|
|
public Color Lightened(float amount)
|
|
|
{
|
|
|
Color res = this;
|
|
@@ -306,6 +314,13 @@ namespace Godot
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Returns the result of the linear interpolation between
|
|
|
+ /// this color and `to` by amount `weight`.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="to">The destination color for interpolation.</param>
|
|
|
+ /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
|
|
+ /// <returns>The resulting color of the interpolation.</returns>
|
|
|
public Color Lerp(Color to, float weight)
|
|
|
{
|
|
|
return new Color
|
|
@@ -317,6 +332,13 @@ namespace Godot
|
|
|
);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Returns the result of the linear interpolation between
|
|
|
+ /// this color and `to` by color amount `weight`.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="to">The destination color for interpolation.</param>
|
|
|
+ /// <param name="weight">A color with components on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
|
|
+ /// <returns>The resulting color of the interpolation.</returns>
|
|
|
public Color Lerp(Color to, Color weight)
|
|
|
{
|
|
|
return new Color
|
|
@@ -328,6 +350,12 @@ namespace Godot
|
|
|
);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Returns the color's 32-bit integer in ABGR format
|
|
|
+ /// (each byte represents a component of the ABGR profile).
|
|
|
+ /// ABGR is the reversed version of the default format.
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>A uint representing this color in ABGR32 format.</returns>
|
|
|
public uint ToAbgr32()
|
|
|
{
|
|
|
uint c = (byte)Math.Round(a * 255);
|
|
@@ -341,6 +369,12 @@ namespace Godot
|
|
|
return c;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Returns the color's 64-bit integer in ABGR format
|
|
|
+ /// (each word represents a component of the ABGR profile).
|
|
|
+ /// ABGR is the reversed version of the default format.
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>A ulong representing this color in ABGR64 format.</returns>
|
|
|
public ulong ToAbgr64()
|
|
|
{
|
|
|
ulong c = (ushort)Math.Round(a * 65535);
|
|
@@ -354,6 +388,12 @@ namespace Godot
|
|
|
return c;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Returns the color's 32-bit integer in ARGB format
|
|
|
+ /// (each byte represents a component of the ARGB profile).
|
|
|
+ /// ARGB is more compatible with DirectX, but not used much in Godot.
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>A uint representing this color in ARGB32 format.</returns>
|
|
|
public uint ToArgb32()
|
|
|
{
|
|
|
uint c = (byte)Math.Round(a * 255);
|
|
@@ -367,6 +407,12 @@ namespace Godot
|
|
|
return c;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Returns the color's 64-bit integer in ARGB format
|
|
|
+ /// (each word represents a component of the ARGB profile).
|
|
|
+ /// ARGB is more compatible with DirectX, but not used much in Godot.
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>A ulong representing this color in ARGB64 format.</returns>
|
|
|
public ulong ToArgb64()
|
|
|
{
|
|
|
ulong c = (ushort)Math.Round(a * 65535);
|
|
@@ -380,6 +426,12 @@ namespace Godot
|
|
|
return c;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Returns the color's 32-bit integer in RGBA format
|
|
|
+ /// (each byte represents a component of the RGBA profile).
|
|
|
+ /// RGBA is Godot's default and recommended format.
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>A uint representing this color in RGBA32 format.</returns>
|
|
|
public uint ToRgba32()
|
|
|
{
|
|
|
uint c = (byte)Math.Round(r * 255);
|
|
@@ -393,6 +445,12 @@ namespace Godot
|
|
|
return c;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Returns the color's 64-bit integer in RGBA format
|
|
|
+ /// (each word represents a component of the RGBA profile).
|
|
|
+ /// RGBA is Godot's default and recommended format.
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>A ulong representing this color in RGBA64 format.</returns>
|
|
|
public ulong ToRgba64()
|
|
|
{
|
|
|
ulong c = (ushort)Math.Round(r * 65535);
|
|
@@ -406,6 +464,11 @@ namespace Godot
|
|
|
return c;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Returns the color's HTML hexadecimal color string in RGBA format.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="includeAlpha">Whether or not to include alpha. If false, the color is RGB instead of RGBA.</param>
|
|
|
+ /// <returns>A string for the HTML hexadecimal representation of this color.</returns>
|
|
|
public string ToHtml(bool includeAlpha = true)
|
|
|
{
|
|
|
var txt = string.Empty;
|
|
@@ -415,12 +478,20 @@ namespace Godot
|
|
|
txt += ToHex32(b);
|
|
|
|
|
|
if (includeAlpha)
|
|
|
- txt = ToHex32(a) + txt;
|
|
|
+ {
|
|
|
+ txt += ToHex32(a);
|
|
|
+ }
|
|
|
|
|
|
return txt;
|
|
|
}
|
|
|
|
|
|
- // Constructors
|
|
|
+ /// <summary>
|
|
|
+ /// Constructs a color from RGB values on the range of 0 to 1.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="r">The color's red component, typically on the range of 0 to 1.</param>
|
|
|
+ /// <param name="g">The color's green component, typically on the range of 0 to 1.</param>
|
|
|
+ /// <param name="b">The color's blue component, typically on the range of 0 to 1.</param>
|
|
|
+ /// <param name="a">The color's alpha (transparency) value, typically on the range of 0 to 1. Default: 1.</param>
|
|
|
public Color(float r, float g, float b, float a = 1.0f)
|
|
|
{
|
|
|
this.r = r;
|
|
@@ -429,6 +500,11 @@ namespace Godot
|
|
|
this.a = a;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Constructs a color from an existing color and an alpha value.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="c">The color to construct from. Only its RGB values are used.</param>
|
|
|
+ /// <param name="a">The color's alpha (transparency) value, typically on the range of 0 to 1. Default: 1.</param>
|
|
|
public Color(Color c, float a = 1.0f)
|
|
|
{
|
|
|
r = c.r;
|
|
@@ -437,6 +513,11 @@ namespace Godot
|
|
|
this.a = a;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Constructs a color from a 32-bit integer
|
|
|
+ /// (each byte represents a component of the RGBA profile).
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="rgba">The uint representing the color.</param>
|
|
|
public Color(uint rgba)
|
|
|
{
|
|
|
a = (rgba & 0xFF) / 255.0f;
|
|
@@ -448,6 +529,11 @@ namespace Godot
|
|
|
r = (rgba & 0xFF) / 255.0f;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Constructs a color from a 64-bit integer
|
|
|
+ /// (each word represents a component of the RGBA profile).
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="rgba">The ulong representing the color.</param>
|
|
|
public Color(ulong rgba)
|
|
|
{
|
|
|
a = (rgba & 0xFFFF) / 65535.0f;
|
|
@@ -459,6 +545,212 @@ namespace Godot
|
|
|
r = (rgba & 0xFFFF) / 65535.0f;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Constructs a color from the HTML hexadecimal color string in RGBA format.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="rgba">A string for the HTML hexadecimal representation of this color.</param>
|
|
|
+ public Color(string rgba)
|
|
|
+ {
|
|
|
+ if (rgba.Length == 0)
|
|
|
+ {
|
|
|
+ r = 0f;
|
|
|
+ g = 0f;
|
|
|
+ b = 0f;
|
|
|
+ a = 1.0f;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (rgba[0] == '#')
|
|
|
+ {
|
|
|
+ rgba = rgba.Substring(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ bool alpha;
|
|
|
+
|
|
|
+ if (rgba.Length == 8)
|
|
|
+ {
|
|
|
+ alpha = true;
|
|
|
+ }
|
|
|
+ else if (rgba.Length == 6)
|
|
|
+ {
|
|
|
+ alpha = false;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ throw new ArgumentOutOfRangeException("Invalid color code. Length is " + rgba.Length + " but a length of 6 or 8 is expected: " + rgba);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (alpha)
|
|
|
+ {
|
|
|
+ a = ParseCol8(rgba, 6) / 255f;
|
|
|
+
|
|
|
+ if (a < 0)
|
|
|
+ {
|
|
|
+ throw new ArgumentOutOfRangeException("Invalid color code. Alpha part is not valid hexadecimal: " + rgba);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ a = 1.0f;
|
|
|
+ }
|
|
|
+
|
|
|
+ int from = alpha ? 2 : 0;
|
|
|
+
|
|
|
+ r = ParseCol8(rgba, 0) / 255f;
|
|
|
+
|
|
|
+ if (r < 0)
|
|
|
+ {
|
|
|
+ throw new ArgumentOutOfRangeException("Invalid color code. Red part is not valid hexadecimal: " + rgba);
|
|
|
+ }
|
|
|
+
|
|
|
+ g = ParseCol8(rgba, 2) / 255f;
|
|
|
+
|
|
|
+ if (g < 0)
|
|
|
+ {
|
|
|
+ throw new ArgumentOutOfRangeException("Invalid color code. Green part is not valid hexadecimal: " + rgba);
|
|
|
+ }
|
|
|
+
|
|
|
+ b = ParseCol8(rgba, 4) / 255f;
|
|
|
+
|
|
|
+ if (b < 0)
|
|
|
+ {
|
|
|
+ throw new ArgumentOutOfRangeException("Invalid color code. Blue part is not valid hexadecimal: " + rgba);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Returns a color constructed from integer red, green, blue, and alpha channels.
|
|
|
+ /// Each channel should have 8 bits of information ranging from 0 to 255.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="r8">The red component represented on the range of 0 to 255.</param>
|
|
|
+ /// <param name="g8">The green component represented on the range of 0 to 255.</param>
|
|
|
+ /// <param name="b8">The blue component represented on the range of 0 to 255.</param>
|
|
|
+ /// <param name="a8">The alpha (transparency) component represented on the range of 0 to 255.</param>
|
|
|
+ /// <returns>The constructed color.</returns>
|
|
|
+ public static Color Color8(byte r8, byte g8, byte b8, byte a8 = 255)
|
|
|
+ {
|
|
|
+ return new Color(r8 / 255f, g8 / 255f, b8 / 255f, a8 / 255f);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Returns a color according to the standardized name, with the
|
|
|
+ /// specified alpha value. Supported color names are the same as
|
|
|
+ /// the constants defined in <see cref="Colors"/>.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="name">The name of the color.</param>
|
|
|
+ /// <param name="alpha">The alpha (transparency) component represented on the range of 0 to 1. Default: 1.</param>
|
|
|
+ /// <returns>The constructed color.</returns>
|
|
|
+ public static Color ColorN(string name, float alpha = 1f)
|
|
|
+ {
|
|
|
+ name = name.Replace(" ", String.Empty);
|
|
|
+ name = name.Replace("-", String.Empty);
|
|
|
+ name = name.Replace("_", String.Empty);
|
|
|
+ name = name.Replace("'", String.Empty);
|
|
|
+ name = name.Replace(".", String.Empty);
|
|
|
+ name = name.ToLower();
|
|
|
+
|
|
|
+ if (!Colors.namedColors.ContainsKey(name))
|
|
|
+ {
|
|
|
+ throw new ArgumentOutOfRangeException($"Invalid Color Name: {name}");
|
|
|
+ }
|
|
|
+
|
|
|
+ Color color = Colors.namedColors[name];
|
|
|
+ color.a = alpha;
|
|
|
+ return color;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Constructs a color from an HSV profile, with values on the
|
|
|
+ /// range of 0 to 1. This is equivalent to using each of
|
|
|
+ /// the `h`/`s`/`v` properties, but much more efficient.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="hue">The HSV hue, typically on the range of 0 to 1.</param>
|
|
|
+ /// <param name="saturation">The HSV saturation, typically on the range of 0 to 1.</param>
|
|
|
+ /// <param name="value">The HSV value (brightness), typically on the range of 0 to 1.</param>
|
|
|
+ /// <param name="alpha">The alpha (transparency) value, typically on the range of 0 to 1.</param>
|
|
|
+ /// <returns>The constructed color.</returns>
|
|
|
+ public static Color FromHsv(float hue, float saturation, float value, float alpha = 1.0f)
|
|
|
+ {
|
|
|
+ if (saturation == 0)
|
|
|
+ {
|
|
|
+ // acp_hromatic (grey)
|
|
|
+ return new Color(value, value, value, alpha);
|
|
|
+ }
|
|
|
+
|
|
|
+ int i;
|
|
|
+ float f, p, q, t;
|
|
|
+
|
|
|
+ hue *= 6.0f;
|
|
|
+ hue %= 6f;
|
|
|
+ i = (int)hue;
|
|
|
+
|
|
|
+ f = hue - i;
|
|
|
+ p = value * (1 - saturation);
|
|
|
+ q = value * (1 - saturation * f);
|
|
|
+ t = value * (1 - saturation * (1 - f));
|
|
|
+
|
|
|
+ switch (i)
|
|
|
+ {
|
|
|
+ case 0: // Red is the dominant color
|
|
|
+ return new Color(value, t, p, alpha);
|
|
|
+ case 1: // Green is the dominant color
|
|
|
+ return new Color(q, value, p, alpha);
|
|
|
+ case 2:
|
|
|
+ return new Color(p, value, t, alpha);
|
|
|
+ case 3: // Blue is the dominant color
|
|
|
+ return new Color(p, q, value, alpha);
|
|
|
+ case 4:
|
|
|
+ return new Color(t, p, value, alpha);
|
|
|
+ default: // (5) Red is the dominant color
|
|
|
+ return new Color(value, p, q, alpha);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Converts a color to HSV values. This is equivalent to using each of
|
|
|
+ /// the `h`/`s`/`v` properties, but much more efficient.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="hue">Output parameter for the HSV hue.</param>
|
|
|
+ /// <param name="saturation">Output parameter for the HSV saturation.</param>
|
|
|
+ /// <param name="value">Output parameter for the HSV value.</param>
|
|
|
+ public void ToHsv(out float hue, out float saturation, out float value)
|
|
|
+ {
|
|
|
+ float max = (float)Mathf.Max(r, Mathf.Max(g, b));
|
|
|
+ float min = (float)Mathf.Min(r, Mathf.Min(g, b));
|
|
|
+
|
|
|
+ float delta = max - min;
|
|
|
+
|
|
|
+ if (delta == 0)
|
|
|
+ {
|
|
|
+ hue = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (r == max)
|
|
|
+ {
|
|
|
+ hue = (g - b) / delta; // Between yellow & magenta
|
|
|
+ }
|
|
|
+ else if (g == max)
|
|
|
+ {
|
|
|
+ hue = 2 + (b - r) / delta; // Between cyan & yellow
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ hue = 4 + (r - g) / delta; // Between magenta & cyan
|
|
|
+ }
|
|
|
+
|
|
|
+ hue /= 6.0f;
|
|
|
+
|
|
|
+ if (hue < 0)
|
|
|
+ {
|
|
|
+ hue += 1.0f;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ saturation = max == 0 ? 0 : 1f - 1f * min / max;
|
|
|
+ value = max;
|
|
|
+ }
|
|
|
+
|
|
|
private static int ParseCol8(string str, int ofs)
|
|
|
{
|
|
|
int ig = 0;
|
|
@@ -488,9 +780,13 @@ namespace Godot
|
|
|
}
|
|
|
|
|
|
if (i == 0)
|
|
|
+ {
|
|
|
ig += v * 16;
|
|
|
+ }
|
|
|
else
|
|
|
+ {
|
|
|
ig += v;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return ig;
|
|
@@ -508,9 +804,13 @@ namespace Godot
|
|
|
int lv = v & 0xF;
|
|
|
|
|
|
if (lv < 10)
|
|
|
+ {
|
|
|
c = (char)('0' + lv);
|
|
|
+ }
|
|
|
else
|
|
|
+ {
|
|
|
c = (char)('a' + lv - 10);
|
|
|
+ }
|
|
|
|
|
|
v >>= 4;
|
|
|
ret = c + ret;
|
|
@@ -522,10 +822,14 @@ namespace Godot
|
|
|
internal static bool HtmlIsValid(string color)
|
|
|
{
|
|
|
if (color.Length == 0)
|
|
|
+ {
|
|
|
return false;
|
|
|
+ }
|
|
|
|
|
|
if (color[0] == '#')
|
|
|
+ {
|
|
|
color = color.Substring(1, color.Length - 1);
|
|
|
+ }
|
|
|
|
|
|
bool alpha;
|
|
|
|
|
@@ -544,83 +848,27 @@ namespace Godot
|
|
|
if (alpha)
|
|
|
{
|
|
|
if (ParseCol8(color, 0) < 0)
|
|
|
+ {
|
|
|
return false;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
int from = alpha ? 2 : 0;
|
|
|
|
|
|
if (ParseCol8(color, from + 0) < 0)
|
|
|
- return false;
|
|
|
- if (ParseCol8(color, from + 2) < 0)
|
|
|
- return false;
|
|
|
- if (ParseCol8(color, from + 4) < 0)
|
|
|
- return false;
|
|
|
-
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- public static Color Color8(byte r8, byte g8, byte b8, byte a8 = 255)
|
|
|
- {
|
|
|
- return new Color(r8 / 255f, g8 / 255f, b8 / 255f, a8 / 255f);
|
|
|
- }
|
|
|
-
|
|
|
- public Color(string rgba)
|
|
|
- {
|
|
|
- if (rgba.Length == 0)
|
|
|
{
|
|
|
- r = 0f;
|
|
|
- g = 0f;
|
|
|
- b = 0f;
|
|
|
- a = 1.0f;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (rgba[0] == '#')
|
|
|
- rgba = rgba.Substring(1);
|
|
|
-
|
|
|
- bool alpha;
|
|
|
-
|
|
|
- if (rgba.Length == 8)
|
|
|
- {
|
|
|
- alpha = true;
|
|
|
- }
|
|
|
- else if (rgba.Length == 6)
|
|
|
- {
|
|
|
- alpha = false;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- throw new ArgumentOutOfRangeException("Invalid color code. Length is " + rgba.Length + " but a length of 6 or 8 is expected: " + rgba);
|
|
|
+ return false;
|
|
|
}
|
|
|
-
|
|
|
- if (alpha)
|
|
|
+ if (ParseCol8(color, from + 2) < 0)
|
|
|
{
|
|
|
- a = ParseCol8(rgba, 0) / 255f;
|
|
|
-
|
|
|
- if (a < 0)
|
|
|
- throw new ArgumentOutOfRangeException("Invalid color code. Alpha part is not valid hexadecimal: " + rgba);
|
|
|
+ return false;
|
|
|
}
|
|
|
- else
|
|
|
+ if (ParseCol8(color, from + 4) < 0)
|
|
|
{
|
|
|
- a = 1.0f;
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
- int from = alpha ? 2 : 0;
|
|
|
-
|
|
|
- r = ParseCol8(rgba, from + 0) / 255f;
|
|
|
-
|
|
|
- if (r < 0)
|
|
|
- throw new ArgumentOutOfRangeException("Invalid color code. Red part is not valid hexadecimal: " + rgba);
|
|
|
-
|
|
|
- g = ParseCol8(rgba, from + 2) / 255f;
|
|
|
-
|
|
|
- if (g < 0)
|
|
|
- throw new ArgumentOutOfRangeException("Invalid color code. Green part is not valid hexadecimal: " + rgba);
|
|
|
-
|
|
|
- b = ParseCol8(rgba, from + 4) / 255f;
|
|
|
-
|
|
|
- if (b < 0)
|
|
|
- throw new ArgumentOutOfRangeException("Invalid color code. Blue part is not valid hexadecimal: " + rgba);
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
public static Color operator +(Color left, Color right)
|
|
@@ -708,13 +956,13 @@ namespace Godot
|
|
|
if (Mathf.IsEqualApprox(left.g, right.g))
|
|
|
{
|
|
|
if (Mathf.IsEqualApprox(left.b, right.b))
|
|
|
+ {
|
|
|
return left.a < right.a;
|
|
|
+ }
|
|
|
return left.b < right.b;
|
|
|
}
|
|
|
-
|
|
|
return left.g < right.g;
|
|
|
}
|
|
|
-
|
|
|
return left.r < right.r;
|
|
|
}
|
|
|
|
|
@@ -725,13 +973,13 @@ namespace Godot
|
|
|
if (Mathf.IsEqualApprox(left.g, right.g))
|
|
|
{
|
|
|
if (Mathf.IsEqualApprox(left.b, right.b))
|
|
|
+ {
|
|
|
return left.a > right.a;
|
|
|
+ }
|
|
|
return left.b > right.b;
|
|
|
}
|
|
|
-
|
|
|
return left.g > right.g;
|
|
|
}
|
|
|
-
|
|
|
return left.r > right.r;
|
|
|
}
|
|
|
|
|
@@ -750,6 +998,12 @@ namespace Godot
|
|
|
return r == other.r && g == other.g && b == other.b && a == other.a;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Returns true if this color and `other` are approximately equal, by running
|
|
|
+ /// <see cref="Godot.Mathf.IsEqualApprox(float, float)"/> on each component.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="other">The other color to compare.</param>
|
|
|
+ /// <returns>Whether or not the colors are approximately equal.</returns>
|
|
|
public bool IsEqualApprox(Color other)
|
|
|
{
|
|
|
return Mathf.IsEqualApprox(r, other.r) && Mathf.IsEqualApprox(g, other.g) && Mathf.IsEqualApprox(b, other.b) && Mathf.IsEqualApprox(a, other.a);
|