Replace ColorN and from HTML with a string constructor

This commit is contained in:
Aaron Franke 2020-12-06 17:37:34 -05:00
parent b24c24f64b
commit f55445079a
No known key found for this signature in database
GPG key ID: 40A1750B977E56BF
9 changed files with 110 additions and 70 deletions

View file

@ -408,6 +408,8 @@ Color Color::get_named_color(int p_idx) {
return named_colors[p_idx].color; return named_colors[p_idx].color;
} }
// For a version that errors on invalid values instead of returning
// a default color, use the Color(String) constructor instead.
Color Color::from_string(const String &p_string, const Color &p_default) { Color Color::from_string(const String &p_string, const Color &p_default) {
if (html_is_valid(p_string)) { if (html_is_valid(p_string)) {
return html(p_string); return html(p_string);

View file

@ -241,6 +241,19 @@ struct Color {
b = p_c.b; b = p_c.b;
a = p_a; a = p_a;
} }
Color(const String &p_code) {
if (html_is_valid(p_code)) {
*this = html(p_code);
} else {
*this = named(p_code);
}
}
Color(const String &p_code, float p_a) {
*this = Color(p_code);
a = p_a;
}
}; };
bool Color::operator<(const Color &p_color) const { bool Color::operator<(const Color &p_color) const {

View file

@ -2023,7 +2023,7 @@ Variant::operator Color() const {
if (type == COLOR) { if (type == COLOR) {
return *reinterpret_cast<const Color *>(_data._mem); return *reinterpret_cast<const Color *>(_data._mem);
} else if (type == STRING) { } else if (type == STRING) {
return Color::html(operator String()); return Color(operator String());
} else if (type == INT) { } else if (type == INT) {
return Color::hex(operator int()); return Color::hex(operator int());
} else { } else {

View file

@ -688,6 +688,8 @@ void Variant::_register_variant_constructors() {
add_constructor<VariantConstructor<Color, Color, double>>(sarray("from", "alpha")); add_constructor<VariantConstructor<Color, Color, double>>(sarray("from", "alpha"));
add_constructor<VariantConstructor<Color, double, double, double>>(sarray("r", "g", "b")); add_constructor<VariantConstructor<Color, double, double, double>>(sarray("r", "g", "b"));
add_constructor<VariantConstructor<Color, double, double, double, double>>(sarray("r", "g", "b", "a")); add_constructor<VariantConstructor<Color, double, double, double, double>>(sarray("r", "g", "b", "a"));
add_constructor<VariantConstructor<Color, String>>(sarray("code"));
add_constructor<VariantConstructor<Color, String, double>>(sarray("code", "alpha"));
add_constructor<VariantConstructNoArgs<StringName>>(sarray()); add_constructor<VariantConstructNoArgs<StringName>>(sarray());
add_constructor<VariantConstructor<StringName, StringName>>(sarray("from")); add_constructor<VariantConstructor<StringName, StringName>>(sarray("from"));

View file

@ -5,7 +5,7 @@
</brief_description> </brief_description>
<description> <description>
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). 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).
You can also create a color from standardized color names by using [code]ColorN[/code] ([b]FIXME:[/b] No longer true, a Color(String) constructor should be re-implemented for that) or directly using the color constants defined here. The standardized color set is based on the [url=https://en.wikipedia.org/wiki/X11_color_names]X11 color names[/url]. You can also create a color from standardized color names by using the string constructor or directly using the color constants defined here. The standardized color set is based on the [url=https://en.wikipedia.org/wiki/X11_color_names]X11 color names[/url].
If you want to supply values in a range of 0 to 255, you should use [method @GDScript.Color8]. If you want to supply values in a range of 0 to 255, you should use [method @GDScript.Color8].
[b]Note:[/b] In a boolean context, a Color will evaluate to [code]false[/code] if it's equal to [code]Color(0, 0, 0, 1)[/code] (opaque black). Otherwise, a Color will always evaluate to [code]true[/code]. [b]Note:[/b] In a boolean context, a Color will evaluate to [code]false[/code] if it's equal to [code]Color(0, 0, 0, 1)[/code] (opaque black). Otherwise, a Color will always evaluate to [code]true[/code].
[url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/color_constants.png]Color constants cheatsheet[/url] [url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/color_constants.png]Color constants cheatsheet[/url]
@ -51,6 +51,26 @@
[/codeblocks] [/codeblocks]
</description> </description>
</method> </method>
<method name="Color" qualifiers="constructor">
<return type="Color">
</return>
<argument index="0" name="code" type="String">
</argument>
<argument index="1" name="alpha" type="float">
</argument>
<description>
Constructs a [Color] either from an HTML color code or from a standardized color name, with [code]alpha[/code] on the range of 0 to 1. Supported color names are the same as the constants.
</description>
</method>
<method name="Color" qualifiers="constructor">
<return type="Color">
</return>
<argument index="0" name="code" type="String">
</argument>
<description>
Constructs a [Color] either from an HTML color code or from a standardized color name. Supported color names are the same as the constants.
</description>
</method>
<method name="Color" qualifiers="constructor"> <method name="Color" qualifiers="constructor">
<return type="Color"> <return type="Color">
</return> </return>

View file

@ -104,7 +104,7 @@ namespace Godot
/// <summary> /// <summary>
/// The HSV hue of this color, on the range 0 to 1. /// The HSV hue of this color, on the range 0 to 1.
/// </summary> /// </summary>
/// <value>Getting is a long process, refer to the source code for details. Setting uses <see cref="FromHsv"/>.</value> /// <value>Getting is a long process, refer to the source code for details. Setting uses <see cref="FromHSV"/>.</value>
public float h public float h
{ {
get get
@ -145,14 +145,14 @@ namespace Godot
} }
set set
{ {
this = FromHsv(value, s, v, a); this = FromHSV(value, s, v, a);
} }
} }
/// <summary> /// <summary>
/// The HSV saturation of this color, on the range 0 to 1. /// The HSV saturation of this color, on the range 0 to 1.
/// </summary> /// </summary>
/// <value>Getting is equivalent to the ratio between the min and max RGB value. Setting uses <see cref="FromHsv"/>.</value> /// <value>Getting is equivalent to the ratio between the min and max RGB value. Setting uses <see cref="FromHSV"/>.</value>
public float s public float s
{ {
get get
@ -166,14 +166,14 @@ namespace Godot
} }
set set
{ {
this = FromHsv(h, value, v, a); this = FromHSV(h, value, v, a);
} }
} }
/// <summary> /// <summary>
/// The HSV value (brightness) of this color, on the range 0 to 1. /// The HSV value (brightness) of this color, on the range 0 to 1.
/// </summary> /// </summary>
/// <value>Getting is equivalent to using `Max()` on the RGB components. Setting uses <see cref="FromHsv"/>.</value> /// <value>Getting is equivalent to using `Max()` on the RGB components. Setting uses <see cref="FromHSV"/>.</value>
public float v public float v
{ {
get get
@ -182,7 +182,7 @@ namespace Godot
} }
set set
{ {
this = FromHsv(h, s, value, a); this = FromHSV(h, s, value, a);
} }
} }
@ -455,7 +455,7 @@ namespace Godot
/// </summary> /// </summary>
/// <param name="includeAlpha">Whether or not to include alpha. If false, the color is RGB instead of RGBA.</param> /// <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> /// <returns>A string for the HTML hexadecimal representation of this color.</returns>
public string ToHtml(bool includeAlpha = true) public string ToHTML(bool includeAlpha = true)
{ {
var txt = string.Empty; var txt = string.Empty;
@ -531,19 +531,51 @@ namespace Godot
r = (rgba & 0xFFFF) / 65535.0f; r = (rgba & 0xFFFF) / 65535.0f;
} }
/// <summary>
/// Constructs a color either from an HTML color code or from a
/// standardized color name. Supported
/// color names are the same as the <see cref="Colors"/> constants.
/// </summary>
/// <param name="code">The HTML color code or color name to construct from.</param>
public Color(string code)
{
if (HtmlIsValid(code))
{
this = FromHTML(code);
}
else
{
this = Named(code);
}
}
/// <summary>
/// Constructs a color either from an HTML color code or from a
/// standardized color name, with `alpha` on the range of 0 to 1. Supported
/// color names are the same as the <see cref="Colors"/> constants.
/// </summary>
/// <param name="code">The HTML color code or color name to construct from.</param>
/// <param name="alpha">The alpha (transparency) value, typically on the range of 0 to 1.</param>
public Color(string code, float alpha)
{
this = new Color(code);
a = alpha;
}
/// <summary> /// <summary>
/// Constructs a color from the HTML hexadecimal color string in RGBA format. /// Constructs a color from the HTML hexadecimal color string in RGBA format.
/// </summary> /// </summary>
/// <param name="rgba">A string for the HTML hexadecimal representation of this color.</param> /// <param name="rgba">A string for the HTML hexadecimal representation of this color.</param>
public Color(string rgba) private static Color FromHTML(string rgba)
{ {
Color c;
if (rgba.Length == 0) if (rgba.Length == 0)
{ {
r = 0f; c.r = 0f;
g = 0f; c.g = 0f;
b = 0f; c.b = 0f;
a = 1.0f; c.a = 1.0f;
return; return c;
} }
if (rgba[0] == '#') if (rgba[0] == '#')
@ -577,47 +609,48 @@ namespace Godot
throw new ArgumentOutOfRangeException("Invalid color code. Length is " + rgba.Length + " but a length of 6 or 8 is expected: " + rgba); throw new ArgumentOutOfRangeException("Invalid color code. Length is " + rgba.Length + " but a length of 6 or 8 is expected: " + rgba);
} }
a = 1.0f; c.a = 1.0f;
if (isShorthand) if (isShorthand)
{ {
r = ParseCol4(rgba, 0) / 15f; c.r = ParseCol4(rgba, 0) / 15f;
g = ParseCol4(rgba, 1) / 15f; c.g = ParseCol4(rgba, 1) / 15f;
b = ParseCol4(rgba, 2) / 15f; c.b = ParseCol4(rgba, 2) / 15f;
if (alpha) if (alpha)
{ {
a = ParseCol4(rgba, 3) / 15f; c.a = ParseCol4(rgba, 3) / 15f;
} }
} }
else else
{ {
r = ParseCol8(rgba, 0) / 255f; c.r = ParseCol8(rgba, 0) / 255f;
g = ParseCol8(rgba, 2) / 255f; c.g = ParseCol8(rgba, 2) / 255f;
b = ParseCol8(rgba, 4) / 255f; c.b = ParseCol8(rgba, 4) / 255f;
if (alpha) if (alpha)
{ {
a = ParseCol8(rgba, 6) / 255f; c.a = ParseCol8(rgba, 6) / 255f;
} }
} }
if (r < 0) if (c.r < 0)
{ {
throw new ArgumentOutOfRangeException("Invalid color code. Red part is not valid hexadecimal: " + rgba); throw new ArgumentOutOfRangeException("Invalid color code. Red part is not valid hexadecimal: " + rgba);
} }
if (g < 0) if (c.g < 0)
{ {
throw new ArgumentOutOfRangeException("Invalid color code. Green part is not valid hexadecimal: " + rgba); throw new ArgumentOutOfRangeException("Invalid color code. Green part is not valid hexadecimal: " + rgba);
} }
if (b < 0) if (c.b < 0)
{ {
throw new ArgumentOutOfRangeException("Invalid color code. Blue part is not valid hexadecimal: " + rgba); throw new ArgumentOutOfRangeException("Invalid color code. Blue part is not valid hexadecimal: " + rgba);
} }
if (a < 0) if (c.a < 0)
{ {
throw new ArgumentOutOfRangeException("Invalid color code. Alpha part is not valid hexadecimal: " + rgba); throw new ArgumentOutOfRangeException("Invalid color code. Alpha part is not valid hexadecimal: " + rgba);
} }
return c;
} }
/// <summary> /// <summary>
@ -640,9 +673,8 @@ namespace Godot
/// the constants defined in <see cref="Colors"/>. /// the constants defined in <see cref="Colors"/>.
/// </summary> /// </summary>
/// <param name="name">The name of the color.</param> /// <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> /// <returns>The constructed color.</returns>
public static Color ColorN(string name, float alpha = 1f) private static Color Named(string name)
{ {
name = name.Replace(" ", String.Empty); name = name.Replace(" ", String.Empty);
name = name.Replace("-", String.Empty); name = name.Replace("-", String.Empty);
@ -656,9 +688,7 @@ namespace Godot
throw new ArgumentOutOfRangeException($"Invalid Color Name: {name}"); throw new ArgumentOutOfRangeException($"Invalid Color Name: {name}");
} }
Color color = Colors.namedColors[name]; return Colors.namedColors[name];
color.a = alpha;
return color;
} }
/// <summary> /// <summary>
@ -671,11 +701,11 @@ namespace Godot
/// <param name="value">The HSV value (brightness), 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> /// <param name="alpha">The alpha (transparency) value, typically on the range of 0 to 1.</param>
/// <returns>The constructed color.</returns> /// <returns>The constructed color.</returns>
public static Color FromHsv(float hue, float saturation, float value, float alpha = 1.0f) public static Color FromHSV(float hue, float saturation, float value, float alpha = 1.0f)
{ {
if (saturation == 0) if (saturation == 0)
{ {
// acp_hromatic (grey) // Achromatic (grey)
return new Color(value, value, value, alpha); return new Color(value, value, value, alpha);
} }
@ -715,7 +745,7 @@ namespace Godot
/// <param name="hue">Output parameter for the HSV hue.</param> /// <param name="hue">Output parameter for the HSV hue.</param>
/// <param name="saturation">Output parameter for the HSV saturation.</param> /// <param name="saturation">Output parameter for the HSV saturation.</param>
/// <param name="value">Output parameter for the HSV value.</param> /// <param name="value">Output parameter for the HSV value.</param>
public void ToHsv(out float hue, out float saturation, out float value) public void ToHSV(out float hue, out float saturation, out float value)
{ {
float max = (float)Mathf.Max(r, Mathf.Max(g, b)); float max = (float)Mathf.Max(r, Mathf.Max(g, b));
float min = (float)Mathf.Min(r, Mathf.Min(g, b)); float min = (float)Mathf.Min(r, Mathf.Min(g, b));
@ -803,7 +833,8 @@ namespace Godot
} }
// Check if each hex digit is valid. // Check if each hex digit is valid.
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++)
{
if (ParseCol4(color, i) == -1) if (ParseCol4(color, i) == -1)
{ {
return false; return false;

View file

@ -202,24 +202,20 @@
<constant name="BYTES_TO_VAR" value="62" enum="BuiltinFunc"> <constant name="BYTES_TO_VAR" value="62" enum="BuiltinFunc">
Deserialize a [Variant] from a [PackedByteArray] serialized using [constant VAR_TO_BYTES]. Deserialize a [Variant] from a [PackedByteArray] serialized using [constant VAR_TO_BYTES].
</constant> </constant>
<constant name="COLORN" value="63" enum="BuiltinFunc"> <constant name="MATH_SMOOTHSTEP" value="63" enum="BuiltinFunc">
Return the [Color] with the given name and alpha ranging from 0 to 1.
[b]Note:[/b] Names are defined in [code]color_names.inc[/code].
</constant>
<constant name="MATH_SMOOTHSTEP" value="64" enum="BuiltinFunc">
Return a number smoothly interpolated between the first two inputs, based on the third input. Similar to [constant MATH_LERP], but interpolates faster at the beginning and slower at the end. Using Hermite interpolation formula: Return a number smoothly interpolated between the first two inputs, based on the third input. Similar to [constant MATH_LERP], but interpolates faster at the beginning and slower at the end. Using Hermite interpolation formula:
[codeblock] [codeblock]
var t = clamp((weight - from) / (to - from), 0.0, 1.0) var t = clamp((weight - from) / (to - from), 0.0, 1.0)
return t * t * (3.0 - 2.0 * t) return t * t * (3.0 - 2.0 * t)
[/codeblock] [/codeblock]
</constant> </constant>
<constant name="MATH_POSMOD" value="65" enum="BuiltinFunc"> <constant name="MATH_POSMOD" value="64" enum="BuiltinFunc">
</constant> </constant>
<constant name="MATH_LERP_ANGLE" value="66" enum="BuiltinFunc"> <constant name="MATH_LERP_ANGLE" value="65" enum="BuiltinFunc">
</constant> </constant>
<constant name="TEXT_ORD" value="67" enum="BuiltinFunc"> <constant name="TEXT_ORD" value="66" enum="BuiltinFunc">
</constant> </constant>
<constant name="FUNC_MAX" value="68" enum="BuiltinFunc"> <constant name="FUNC_MAX" value="67" enum="BuiltinFunc">
Represents the size of the [enum BuiltinFunc] enum. Represents the size of the [enum BuiltinFunc] enum.
</constant> </constant>
</constants> </constants>

View file

@ -101,7 +101,6 @@ const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX
"str2var", "str2var",
"var2bytes", "var2bytes",
"bytes2var", "bytes2var",
"color_named",
"smoothstep", "smoothstep",
"posmod", "posmod",
"lerp_angle", "lerp_angle",
@ -200,7 +199,6 @@ int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) {
case LOGIC_MAX: case LOGIC_MAX:
case LOGIC_MIN: case LOGIC_MIN:
case TYPE_CONVERT: case TYPE_CONVERT:
case COLORN:
return 2; return 2;
case MATH_LERP: case MATH_LERP:
case MATH_LERP_ANGLE: case MATH_LERP_ANGLE:
@ -476,13 +474,6 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const
return PropertyInfo(Variant::BOOL, "allow_objects"); return PropertyInfo(Variant::BOOL, "allow_objects");
} }
} break; } break;
case COLORN: {
if (p_idx == 0) {
return PropertyInfo(Variant::STRING, "name");
} else {
return PropertyInfo(Variant::FLOAT, "alpha");
}
} break;
case FUNC_MAX: { case FUNC_MAX: {
} }
} }
@ -635,9 +626,6 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons
t = Variant::BOOL; t = Variant::BOOL;
} }
} break; } break;
case COLORN: {
t = Variant::COLOR;
} break;
case FUNC_MAX: { case FUNC_MAX: {
} }
} }
@ -1175,15 +1163,6 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
*r_return = ret; *r_return = ret;
} break;
case VisualScriptBuiltinFunc::COLORN: {
VALIDATE_ARG_NUM(1);
Color color = Color::named(*p_inputs[0]);
color.a = *p_inputs[1];
*r_return = String(color);
} break; } break;
default: { default: {
} }
@ -1292,7 +1271,6 @@ void VisualScriptBuiltinFunc::_bind_methods() {
BIND_ENUM_CONSTANT(STR_TO_VAR); BIND_ENUM_CONSTANT(STR_TO_VAR);
BIND_ENUM_CONSTANT(VAR_TO_BYTES); BIND_ENUM_CONSTANT(VAR_TO_BYTES);
BIND_ENUM_CONSTANT(BYTES_TO_VAR); BIND_ENUM_CONSTANT(BYTES_TO_VAR);
BIND_ENUM_CONSTANT(COLORN);
BIND_ENUM_CONSTANT(MATH_SMOOTHSTEP); BIND_ENUM_CONSTANT(MATH_SMOOTHSTEP);
BIND_ENUM_CONSTANT(MATH_POSMOD); BIND_ENUM_CONSTANT(MATH_POSMOD);
BIND_ENUM_CONSTANT(MATH_LERP_ANGLE); BIND_ENUM_CONSTANT(MATH_LERP_ANGLE);
@ -1388,5 +1366,4 @@ void register_visual_script_builtin_func_node() {
VisualScriptLanguage::singleton->add_register_func("functions/built_in/str2var", create_builtin_func_node<VisualScriptBuiltinFunc::STR_TO_VAR>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/str2var", create_builtin_func_node<VisualScriptBuiltinFunc::STR_TO_VAR>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/var2bytes", create_builtin_func_node<VisualScriptBuiltinFunc::VAR_TO_BYTES>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/var2bytes", create_builtin_func_node<VisualScriptBuiltinFunc::VAR_TO_BYTES>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/bytes2var", create_builtin_func_node<VisualScriptBuiltinFunc::BYTES_TO_VAR>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/bytes2var", create_builtin_func_node<VisualScriptBuiltinFunc::BYTES_TO_VAR>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/color_named", create_builtin_func_node<VisualScriptBuiltinFunc::COLORN>);
} }

View file

@ -101,7 +101,6 @@ public:
STR_TO_VAR, STR_TO_VAR,
VAR_TO_BYTES, VAR_TO_BYTES,
BYTES_TO_VAR, BYTES_TO_VAR,
COLORN,
MATH_SMOOTHSTEP, MATH_SMOOTHSTEP,
MATH_POSMOD, MATH_POSMOD,
MATH_LERP_ANGLE, MATH_LERP_ANGLE,