From be5517123101fe669ebfc3d3f16a0431ca2804dd Mon Sep 17 00:00:00 2001 From: Bernhard Liebl Date: Thu, 18 Jan 2018 22:03:34 +0100 Subject: [PATCH] Add Color.from_hsv() --- core/color.cpp | 49 ++++++++++++++++++++++++++++ core/color.h | 1 + core/variant_call.cpp | 2 ++ modules/gdscript/gdscript_parser.cpp | 43 ++++++++++++++++++++---- 4 files changed, 88 insertions(+), 7 deletions(-) diff --git a/core/color.cpp b/core/color.cpp index a0568d26ed44..27d8e9b891b2 100644 --- a/core/color.cpp +++ b/core/color.cpp @@ -400,6 +400,55 @@ String Color::to_html(bool p_alpha) const { return txt; } +Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) { + + const float h_ = p_h / 60.0f; + const float c = p_v * p_s; + const float x = c * (1.0f - Math::abs(Math::fmod(h_, 2.0f) - 1.0f)); + float r, g, b; + + switch ((int)h_) { + case 0: { + r = c; + g = x; + b = 0; + } break; + case 1: { + r = x; + g = c; + b = 0; + } break; + case 2: { + r = 0; + g = c; + b = x; + } break; + case 3: { + r = 0; + g = x; + b = c; + } break; + case 4: { + r = x; + g = 0; + b = c; + } break; + case 5: { + r = c; + g = 0; + b = x; + } break; + default: { + r = 0; + g = 0; + b = 0; + } break; + } + + const float m = p_v - c; + return Color(m + r, m + g, m + b, p_a); +} + float Color::gray() const { return (r + g + b) / 3.0; diff --git a/core/color.h b/core/color.h index 9af8fb0a78df..a2015a34d68d 100644 --- a/core/color.h +++ b/core/color.h @@ -190,6 +190,7 @@ struct Color { static bool html_is_valid(const String &p_color); static Color named(const String &p_name); String to_html(bool p_alpha = true) const; + Color from_hsv(float p_h, float p_s, float p_v, float p_a); _FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys operator String() const; diff --git a/core/variant_call.cpp b/core/variant_call.cpp index e9f7af3f633d..d963124717ff 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -443,6 +443,7 @@ struct _VariantCall { VCALL_LOCALMEM1R(Color, lightened); VCALL_LOCALMEM1R(Color, darkened); VCALL_LOCALMEM1R(Color, to_html); + VCALL_LOCALMEM4R(Color, from_hsv); VCALL_LOCALMEM0R(RID, get_id); @@ -1589,6 +1590,7 @@ void register_variant_methods() { ADDFUNC1R(COLOR, COLOR, Color, lightened, REAL, "amount", varray()); ADDFUNC1R(COLOR, COLOR, Color, darkened, REAL, "amount", varray()); ADDFUNC1R(COLOR, STRING, Color, to_html, BOOL, "with_alpha", varray(true)); + ADDFUNC4R(COLOR, COLOR, Color, from_hsv, REAL, "h", REAL, "s", REAL, "v", REAL, "a", varray(1.0)); ADDFUNC0R(_RID, INT, RID, get_id, varray()); diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 2a6d37812e3c..c2097a49d4d7 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -578,18 +578,47 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (identifier == StringName()) { - _set_error("Built-in type constant expected after '.'"); + _set_error("Built-in type constant or static function expected after '.'"); return NULL; } if (!Variant::has_numeric_constant(bi_type, identifier)) { - _set_error("Static constant '" + identifier.operator String() + "' not present in built-in type " + Variant::get_type_name(bi_type) + "."); - return NULL; - } + if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_OPEN && + Variant::is_method_const(bi_type, identifier) && + Variant::get_method_return_type(bi_type, identifier) == bi_type) { - ConstantNode *cn = alloc_node(); - cn->value = Variant::get_numeric_constant_value(bi_type, identifier); - expr = cn; + tokenizer->advance(); + + OperatorNode *construct = alloc_node(); + construct->op = OperatorNode::OP_CALL; + + TypeNode *tn = alloc_node(); + tn->vtype = bi_type; + construct->arguments.push_back(tn); + + OperatorNode *op = alloc_node(); + op->op = OperatorNode::OP_CALL; + op->arguments.push_back(construct); + + IdentifierNode *id = alloc_node(); + id->name = identifier; + op->arguments.push_back(id); + + if (!_parse_arguments(op, op->arguments, p_static, true)) + return NULL; + + expr = op; + } else { + + _set_error("Static constant '" + identifier.operator String() + "' not present in built-in type " + Variant::get_type_name(bi_type) + "."); + return NULL; + } + } else { + + ConstantNode *cn = alloc_node(); + cn->value = Variant::get_numeric_constant_value(bi_type, identifier); + expr = cn; + } } else if (tokenizer->get_token(1) == GDScriptTokenizer::TK_PARENTHESIS_OPEN && tokenizer->is_token_literal()) { // We check with is_token_literal, as this allows us to use match/sync/etc. as a name