mirror of
https://github.com/Relintai/rcpp_framework.git
synced 2025-02-20 15:14:26 +01:00
Added the Color class from godot. Removed the ColorUInt8 typedef.
This commit is contained in:
parent
db531000c1
commit
397459ce7b
@ -22,7 +22,7 @@ ColorUInt8::ColorUInt8() {
|
|||||||
r = 0;
|
r = 0;
|
||||||
g = 0;
|
g = 0;
|
||||||
b = 0;
|
b = 0;
|
||||||
a = 255;
|
a = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorUInt8::ColorUInt8(uint8_t p_r, uint8_t p_g, uint8_t p_b, uint8_t p_a) {
|
ColorUInt8::ColorUInt8(uint8_t p_r, uint8_t p_g, uint8_t p_b, uint8_t p_a) {
|
||||||
@ -37,4 +37,516 @@ ColorUInt8::ColorUInt8(const uint32_t key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ColorUInt8::~ColorUInt8() {
|
ColorUInt8::~ColorUInt8() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t Color::to_argb32() const {
|
||||||
|
uint32_t c = (uint8_t)Math::round(a * 255);
|
||||||
|
c <<= 8;
|
||||||
|
c |= (uint8_t)Math::round(r * 255);
|
||||||
|
c <<= 8;
|
||||||
|
c |= (uint8_t)Math::round(g * 255);
|
||||||
|
c <<= 8;
|
||||||
|
c |= (uint8_t)Math::round(b * 255);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Color::to_abgr32() const {
|
||||||
|
uint32_t c = (uint8_t)Math::round(a * 255);
|
||||||
|
c <<= 8;
|
||||||
|
c |= (uint8_t)Math::round(b * 255);
|
||||||
|
c <<= 8;
|
||||||
|
c |= (uint8_t)Math::round(g * 255);
|
||||||
|
c <<= 8;
|
||||||
|
c |= (uint8_t)Math::round(r * 255);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Color::to_rgba32() const {
|
||||||
|
uint32_t c = (uint8_t)Math::round(r * 255);
|
||||||
|
c <<= 8;
|
||||||
|
c |= (uint8_t)Math::round(g * 255);
|
||||||
|
c <<= 8;
|
||||||
|
c |= (uint8_t)Math::round(b * 255);
|
||||||
|
c <<= 8;
|
||||||
|
c |= (uint8_t)Math::round(a * 255);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t Color::to_abgr64() const {
|
||||||
|
uint64_t c = (uint16_t)Math::round(a * 65535);
|
||||||
|
c <<= 16;
|
||||||
|
c |= (uint16_t)Math::round(b * 65535);
|
||||||
|
c <<= 16;
|
||||||
|
c |= (uint16_t)Math::round(g * 65535);
|
||||||
|
c <<= 16;
|
||||||
|
c |= (uint16_t)Math::round(r * 65535);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t Color::to_argb64() const {
|
||||||
|
uint64_t c = (uint16_t)Math::round(a * 65535);
|
||||||
|
c <<= 16;
|
||||||
|
c |= (uint16_t)Math::round(r * 65535);
|
||||||
|
c <<= 16;
|
||||||
|
c |= (uint16_t)Math::round(g * 65535);
|
||||||
|
c <<= 16;
|
||||||
|
c |= (uint16_t)Math::round(b * 65535);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t Color::to_rgba64() const {
|
||||||
|
uint64_t c = (uint16_t)Math::round(r * 65535);
|
||||||
|
c <<= 16;
|
||||||
|
c |= (uint16_t)Math::round(g * 65535);
|
||||||
|
c <<= 16;
|
||||||
|
c |= (uint16_t)Math::round(b * 65535);
|
||||||
|
c <<= 16;
|
||||||
|
c |= (uint16_t)Math::round(a * 65535);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Color::get_h() const {
|
||||||
|
float min = MIN(r, g);
|
||||||
|
min = MIN(min, b);
|
||||||
|
float max = MAX(r, g);
|
||||||
|
max = MAX(max, b);
|
||||||
|
|
||||||
|
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.0;
|
||||||
|
if (h < 0) {
|
||||||
|
h += 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Color::get_s() const {
|
||||||
|
float min = MIN(r, g);
|
||||||
|
min = MIN(min, b);
|
||||||
|
float max = MAX(r, g);
|
||||||
|
max = MAX(max, b);
|
||||||
|
|
||||||
|
float delta = max - min;
|
||||||
|
|
||||||
|
return (max != 0) ? (delta / max) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Color::get_v() const {
|
||||||
|
float max = MAX(r, g);
|
||||||
|
max = MAX(max, b);
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
|
||||||
|
int i;
|
||||||
|
float f, p, q, t;
|
||||||
|
a = p_alpha;
|
||||||
|
|
||||||
|
if (p_s == 0) {
|
||||||
|
// acp_hromatic (grey)
|
||||||
|
r = g = b = p_v;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_h *= 6.0;
|
||||||
|
p_h = Math::fmod(p_h, 6);
|
||||||
|
i = Math::floor(p_h);
|
||||||
|
|
||||||
|
f = p_h - i;
|
||||||
|
p = p_v * (1 - p_s);
|
||||||
|
q = p_v * (1 - p_s * f);
|
||||||
|
t = p_v * (1 - p_s * (1 - f));
|
||||||
|
|
||||||
|
switch (i) {
|
||||||
|
case 0: // Red is the dominant color
|
||||||
|
r = p_v;
|
||||||
|
g = t;
|
||||||
|
b = p;
|
||||||
|
break;
|
||||||
|
case 1: // Green is the dominant color
|
||||||
|
r = q;
|
||||||
|
g = p_v;
|
||||||
|
b = p;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
r = p;
|
||||||
|
g = p_v;
|
||||||
|
b = t;
|
||||||
|
break;
|
||||||
|
case 3: // Blue is the dominant color
|
||||||
|
r = p;
|
||||||
|
g = q;
|
||||||
|
b = p_v;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
r = t;
|
||||||
|
g = p;
|
||||||
|
b = p_v;
|
||||||
|
break;
|
||||||
|
default: // (5) Red is the dominant color
|
||||||
|
r = p_v;
|
||||||
|
g = p;
|
||||||
|
b = q;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Color::is_equal_approx(const Color &p_color) const {
|
||||||
|
return Math::is_equal_approx(r, p_color.r) && Math::is_equal_approx(g, p_color.g) && Math::is_equal_approx(b, p_color.b) && Math::is_equal_approx(a, p_color.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Color::invert() {
|
||||||
|
r = 1.0 - r;
|
||||||
|
g = 1.0 - g;
|
||||||
|
b = 1.0 - b;
|
||||||
|
}
|
||||||
|
void Color::contrast() {
|
||||||
|
r = Math::fmod(r + 0.5, 1.0);
|
||||||
|
g = Math::fmod(g + 0.5, 1.0);
|
||||||
|
b = Math::fmod(b + 0.5, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color Color::hex(uint32_t p_hex) {
|
||||||
|
float a = (p_hex & 0xFF) / 255.0;
|
||||||
|
p_hex >>= 8;
|
||||||
|
float b = (p_hex & 0xFF) / 255.0;
|
||||||
|
p_hex >>= 8;
|
||||||
|
float g = (p_hex & 0xFF) / 255.0;
|
||||||
|
p_hex >>= 8;
|
||||||
|
float r = (p_hex & 0xFF) / 255.0;
|
||||||
|
|
||||||
|
return Color(r, g, b, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color Color::hex64(uint64_t p_hex) {
|
||||||
|
float a = (p_hex & 0xFFFF) / 65535.0;
|
||||||
|
p_hex >>= 16;
|
||||||
|
float b = (p_hex & 0xFFFF) / 65535.0;
|
||||||
|
p_hex >>= 16;
|
||||||
|
float g = (p_hex & 0xFFFF) / 65535.0;
|
||||||
|
p_hex >>= 16;
|
||||||
|
float r = (p_hex & 0xFFFF) / 65535.0;
|
||||||
|
|
||||||
|
return Color(r, g, b, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color Color::from_rgbe9995(uint32_t p_rgbe) {
|
||||||
|
float r = p_rgbe & 0x1ff;
|
||||||
|
float g = (p_rgbe >> 9) & 0x1ff;
|
||||||
|
float b = (p_rgbe >> 18) & 0x1ff;
|
||||||
|
float e = (p_rgbe >> 27);
|
||||||
|
float m = Math::pow(2, e - 15.0 - 9.0);
|
||||||
|
|
||||||
|
float rd = r * m;
|
||||||
|
float gd = g * m;
|
||||||
|
float bd = b * m;
|
||||||
|
|
||||||
|
return Color(rd, gd, bd, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float _parse_col(const String &p_str, int p_ofs) {
|
||||||
|
int ig = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
int c = p_str[i + p_ofs];
|
||||||
|
int v = 0;
|
||||||
|
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
v = c - '0';
|
||||||
|
} else if (c >= 'a' && c <= 'f') {
|
||||||
|
v = c - 'a';
|
||||||
|
v += 10;
|
||||||
|
} else if (c >= 'A' && c <= 'F') {
|
||||||
|
v = c - 'A';
|
||||||
|
v += 10;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
ig += v * 16;
|
||||||
|
} else {
|
||||||
|
ig += v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ig;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color Color::inverted() const {
|
||||||
|
Color c = *this;
|
||||||
|
c.invert();
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color Color::contrasted() const {
|
||||||
|
Color c = *this;
|
||||||
|
c.contrast();
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color Color::html(const String &p_color) {
|
||||||
|
String color = p_color;
|
||||||
|
if (color.size() == 0) {
|
||||||
|
return Color();
|
||||||
|
}
|
||||||
|
if (color[0] == '#') {
|
||||||
|
color = color.substr(1, color.size() - 1);
|
||||||
|
}
|
||||||
|
if (color.size() == 3 || color.size() == 4) {
|
||||||
|
String exp_color;
|
||||||
|
for (int i = 0; i < color.size(); i++) {
|
||||||
|
exp_color += color[i];
|
||||||
|
exp_color += color[i];
|
||||||
|
}
|
||||||
|
color = exp_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool alpha = false;
|
||||||
|
|
||||||
|
if (color.size() == 8) {
|
||||||
|
alpha = true;
|
||||||
|
} else if (color.size() == 6) {
|
||||||
|
alpha = false;
|
||||||
|
} else {
|
||||||
|
ERR_FAIL_V_MSG(Color(), "Invalid color code: " + p_color + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
int a = 255;
|
||||||
|
if (alpha) {
|
||||||
|
a = _parse_col(color, 0);
|
||||||
|
ERR_FAIL_COND_V_MSG(a < 0, Color(), "Invalid color code: " + p_color + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
int from = alpha ? 2 : 0;
|
||||||
|
|
||||||
|
int r = _parse_col(color, from + 0);
|
||||||
|
ERR_FAIL_COND_V_MSG(r < 0, Color(), "Invalid color code: " + p_color + ".");
|
||||||
|
int g = _parse_col(color, from + 2);
|
||||||
|
ERR_FAIL_COND_V_MSG(g < 0, Color(), "Invalid color code: " + p_color + ".");
|
||||||
|
int b = _parse_col(color, from + 4);
|
||||||
|
ERR_FAIL_COND_V_MSG(b < 0, Color(), "Invalid color code: " + p_color + ".");
|
||||||
|
|
||||||
|
return Color(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Color::html_is_valid(const String &p_color) {
|
||||||
|
String color = p_color;
|
||||||
|
|
||||||
|
if (color.size() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (color[0] == '#') {
|
||||||
|
color = color.substr(1, color.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool alpha = false;
|
||||||
|
|
||||||
|
if (color.size() == 8) {
|
||||||
|
alpha = true;
|
||||||
|
} else if (color.size() == 6) {
|
||||||
|
alpha = false;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alpha) {
|
||||||
|
int a = _parse_col(color, 0);
|
||||||
|
if (a < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int from = alpha ? 2 : 0;
|
||||||
|
|
||||||
|
int r = _parse_col(color, from + 0);
|
||||||
|
if (r < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int g = _parse_col(color, from + 2);
|
||||||
|
if (g < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int b = _parse_col(color, from + 4);
|
||||||
|
if (b < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String _to_hex(float p_val) {
|
||||||
|
int v = Math::round(p_val * 255);
|
||||||
|
v = CLAMP(v, 0, 255);
|
||||||
|
String ret;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
wchar_t c[2] = { 0, 0 };
|
||||||
|
int lv = v & 0xF;
|
||||||
|
if (lv < 10) {
|
||||||
|
c[0] = '0' + lv;
|
||||||
|
} else {
|
||||||
|
c[0] = 'a' + lv - 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
v >>= 4;
|
||||||
|
String cs((const wchar_t *)c);
|
||||||
|
ret = cs + ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
String Color::to_html(bool p_alpha) const {
|
||||||
|
String txt;
|
||||||
|
txt += _to_hex(r);
|
||||||
|
txt += _to_hex(g);
|
||||||
|
txt += _to_hex(b);
|
||||||
|
if (p_alpha) {
|
||||||
|
txt = _to_hex(a) + txt;
|
||||||
|
}
|
||||||
|
return txt;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const {
|
||||||
|
Color c;
|
||||||
|
c.set_hsv(p_h, p_s, p_v, p_a);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Remove once Godot 3.1 has been released
|
||||||
|
float Color::gray() const {
|
||||||
|
//WARN_DEPRECATED_MSG("'Color.gray()' is deprecated and will be removed in a future version. Use 'Color.v' for a better grayscale approximation.");
|
||||||
|
return (r + g + b) / 3.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color::operator String() const {
|
||||||
|
return String::num(r) + ", " + String::num(g) + ", " + String::num(b) + ", " + String::num(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color Color::operator+(const Color &p_color) const {
|
||||||
|
return Color(
|
||||||
|
r + p_color.r,
|
||||||
|
g + p_color.g,
|
||||||
|
b + p_color.b,
|
||||||
|
a + p_color.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Color::operator+=(const Color &p_color) {
|
||||||
|
r = r + p_color.r;
|
||||||
|
g = g + p_color.g;
|
||||||
|
b = b + p_color.b;
|
||||||
|
a = a + p_color.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color Color::operator-(const Color &p_color) const {
|
||||||
|
return Color(
|
||||||
|
r - p_color.r,
|
||||||
|
g - p_color.g,
|
||||||
|
b - p_color.b,
|
||||||
|
a - p_color.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Color::operator-=(const Color &p_color) {
|
||||||
|
r = r - p_color.r;
|
||||||
|
g = g - p_color.g;
|
||||||
|
b = b - p_color.b;
|
||||||
|
a = a - p_color.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color Color::operator*(const Color &p_color) const {
|
||||||
|
return Color(
|
||||||
|
r * p_color.r,
|
||||||
|
g * p_color.g,
|
||||||
|
b * p_color.b,
|
||||||
|
a * p_color.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color Color::operator*(const real_t &rvalue) const {
|
||||||
|
return Color(
|
||||||
|
r * rvalue,
|
||||||
|
g * rvalue,
|
||||||
|
b * rvalue,
|
||||||
|
a * rvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Color::operator*=(const Color &p_color) {
|
||||||
|
r = r * p_color.r;
|
||||||
|
g = g * p_color.g;
|
||||||
|
b = b * p_color.b;
|
||||||
|
a = a * p_color.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Color::operator*=(const real_t &rvalue) {
|
||||||
|
r = r * rvalue;
|
||||||
|
g = g * rvalue;
|
||||||
|
b = b * rvalue;
|
||||||
|
a = a * rvalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color Color::operator/(const Color &p_color) const {
|
||||||
|
return Color(
|
||||||
|
r / p_color.r,
|
||||||
|
g / p_color.g,
|
||||||
|
b / p_color.b,
|
||||||
|
a / p_color.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color Color::operator/(const real_t &rvalue) const {
|
||||||
|
return Color(
|
||||||
|
r / rvalue,
|
||||||
|
g / rvalue,
|
||||||
|
b / rvalue,
|
||||||
|
a / rvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Color::operator/=(const Color &p_color) {
|
||||||
|
r = r / p_color.r;
|
||||||
|
g = g / p_color.g;
|
||||||
|
b = b / p_color.b;
|
||||||
|
a = a / p_color.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Color::operator/=(const real_t &rvalue) {
|
||||||
|
if (rvalue == 0) {
|
||||||
|
r = 1.0;
|
||||||
|
g = 1.0;
|
||||||
|
b = 1.0;
|
||||||
|
a = 1.0;
|
||||||
|
} else {
|
||||||
|
r = r / rvalue;
|
||||||
|
g = g / rvalue;
|
||||||
|
b = b / rvalue;
|
||||||
|
a = a / rvalue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Color Color::operator-() const {
|
||||||
|
return Color(
|
||||||
|
1.0 - r,
|
||||||
|
1.0 - g,
|
||||||
|
1.0 - b,
|
||||||
|
1.0 - a);
|
||||||
|
}
|
||||||
|
@ -3,9 +3,8 @@
|
|||||||
|
|
||||||
#include "core/typedefs.h"
|
#include "core/typedefs.h"
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include "core/string.h"
|
||||||
//Todo add float version
|
#include "core/math/math.h"
|
||||||
//Not sure but probably that should be the default
|
|
||||||
|
|
||||||
class ColorUInt8 {
|
class ColorUInt8 {
|
||||||
public:
|
public:
|
||||||
@ -35,6 +34,205 @@ public:
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef ColorUInt8 Color;
|
|
||||||
|
//Taken from the Godot Engine (MIT License)
|
||||||
|
//Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.
|
||||||
|
//Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
|
||||||
|
struct Color {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
float r;
|
||||||
|
float g;
|
||||||
|
float b;
|
||||||
|
float a;
|
||||||
|
};
|
||||||
|
float components[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator==(const Color &p_color) const { return (r == p_color.r && g == p_color.g && b == p_color.b && a == p_color.a); }
|
||||||
|
bool operator!=(const Color &p_color) const { return (r != p_color.r || g != p_color.g || b != p_color.b || a != p_color.a); }
|
||||||
|
|
||||||
|
uint32_t to_rgba32() const;
|
||||||
|
uint32_t to_argb32() const;
|
||||||
|
uint32_t to_abgr32() const;
|
||||||
|
uint64_t to_rgba64() const;
|
||||||
|
uint64_t to_argb64() const;
|
||||||
|
uint64_t to_abgr64() const;
|
||||||
|
float gray() const;
|
||||||
|
float get_h() const;
|
||||||
|
float get_s() const;
|
||||||
|
float get_v() const;
|
||||||
|
void set_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0);
|
||||||
|
|
||||||
|
_FORCE_INLINE_ float &operator[](int idx) {
|
||||||
|
return components[idx];
|
||||||
|
}
|
||||||
|
_FORCE_INLINE_ const float &operator[](int idx) const {
|
||||||
|
return components[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
Color operator+(const Color &p_color) const;
|
||||||
|
void operator+=(const Color &p_color);
|
||||||
|
|
||||||
|
Color operator-() const;
|
||||||
|
Color operator-(const Color &p_color) const;
|
||||||
|
void operator-=(const Color &p_color);
|
||||||
|
|
||||||
|
Color operator*(const Color &p_color) const;
|
||||||
|
Color operator*(const float &rvalue) const;
|
||||||
|
void operator*=(const Color &p_color);
|
||||||
|
void operator*=(const float &rvalue);
|
||||||
|
|
||||||
|
Color operator/(const Color &p_color) const;
|
||||||
|
Color operator/(const float &rvalue) const;
|
||||||
|
void operator/=(const Color &p_color);
|
||||||
|
void operator/=(const float &rvalue);
|
||||||
|
|
||||||
|
bool is_equal_approx(const Color &p_color) const;
|
||||||
|
|
||||||
|
void invert();
|
||||||
|
void contrast();
|
||||||
|
Color inverted() const;
|
||||||
|
Color contrasted() const;
|
||||||
|
|
||||||
|
_FORCE_INLINE_ float get_luminance() const {
|
||||||
|
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ Color linear_interpolate(const Color &p_to, float p_weight) const {
|
||||||
|
Color res = *this;
|
||||||
|
|
||||||
|
res.r += (p_weight * (p_to.r - r));
|
||||||
|
res.g += (p_weight * (p_to.g - g));
|
||||||
|
res.b += (p_weight * (p_to.b - b));
|
||||||
|
res.a += (p_weight * (p_to.a - a));
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ Color darkened(float p_amount) const {
|
||||||
|
Color res = *this;
|
||||||
|
res.r = res.r * (1.0f - p_amount);
|
||||||
|
res.g = res.g * (1.0f - p_amount);
|
||||||
|
res.b = res.b * (1.0f - p_amount);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ Color lightened(float p_amount) const {
|
||||||
|
Color res = *this;
|
||||||
|
res.r = res.r + (1.0f - res.r) * p_amount;
|
||||||
|
res.g = res.g + (1.0f - res.g) * p_amount;
|
||||||
|
res.b = res.b + (1.0f - res.b) * p_amount;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ uint32_t to_rgbe9995() const {
|
||||||
|
const float pow2to9 = 512.0f;
|
||||||
|
const float B = 15.0f;
|
||||||
|
//const float Emax = 31.0f;
|
||||||
|
const float N = 9.0f;
|
||||||
|
|
||||||
|
float sharedexp = 65408.000f; //(( pow2to9 - 1.0f)/ pow2to9)*powf( 2.0f, 31.0f - 15.0f);
|
||||||
|
|
||||||
|
float cRed = MAX(0.0f, MIN(sharedexp, r));
|
||||||
|
float cGreen = MAX(0.0f, MIN(sharedexp, g));
|
||||||
|
float cBlue = MAX(0.0f, MIN(sharedexp, b));
|
||||||
|
|
||||||
|
float cMax = MAX(cRed, MAX(cGreen, cBlue));
|
||||||
|
|
||||||
|
// expp = MAX(-B - 1, log2(maxc)) + 1 + B
|
||||||
|
|
||||||
|
float expp = MAX(-B - 1.0f, floor(Math::log(cMax) / Math_LN2)) + 1.0f + B;
|
||||||
|
|
||||||
|
float sMax = (float)floor((cMax / Math::pow(2.0f, expp - B - N)) + 0.5f);
|
||||||
|
|
||||||
|
float exps = expp + 1.0f;
|
||||||
|
|
||||||
|
if (0.0 <= sMax && sMax < pow2to9) {
|
||||||
|
exps = expp;
|
||||||
|
}
|
||||||
|
|
||||||
|
float sRed = Math::floor((cRed / Math::pow(2.0f, exps - B - N)) + 0.5f);
|
||||||
|
float sGreen = Math::floor((cGreen / Math::pow(2.0f, exps - B - N)) + 0.5f);
|
||||||
|
float sBlue = Math::floor((cBlue / Math::pow(2.0f, exps - B - N)) + 0.5f);
|
||||||
|
|
||||||
|
return (uint32_t(Math::fast_ftoi(sRed)) & 0x1FF) | ((uint32_t(Math::fast_ftoi(sGreen)) & 0x1FF) << 9) | ((uint32_t(Math::fast_ftoi(sBlue)) & 0x1FF) << 18) | ((uint32_t(Math::fast_ftoi(exps)) & 0x1F) << 27);
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ Color blend(const Color &p_over) const {
|
||||||
|
Color res;
|
||||||
|
float sa = 1.0 - p_over.a;
|
||||||
|
res.a = a * sa + p_over.a;
|
||||||
|
if (res.a == 0) {
|
||||||
|
return Color(0, 0, 0, 0);
|
||||||
|
} else {
|
||||||
|
res.r = (r * a * sa + p_over.r * p_over.a) / res.a;
|
||||||
|
res.g = (g * a * sa + p_over.g * p_over.a) / res.a;
|
||||||
|
res.b = (b * a * sa + p_over.b * p_over.a) / res.a;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ Color to_linear() const {
|
||||||
|
return Color(
|
||||||
|
r < 0.04045 ? r * (1.0 / 12.92) : Math::pow((r + 0.055) * (1.0 / (1 + 0.055)), 2.4),
|
||||||
|
g < 0.04045 ? g * (1.0 / 12.92) : Math::pow((g + 0.055) * (1.0 / (1 + 0.055)), 2.4),
|
||||||
|
b < 0.04045 ? b * (1.0 / 12.92) : Math::pow((b + 0.055) * (1.0 / (1 + 0.055)), 2.4),
|
||||||
|
a);
|
||||||
|
}
|
||||||
|
_FORCE_INLINE_ Color to_srgb() const {
|
||||||
|
return Color(
|
||||||
|
r < 0.0031308 ? 12.92 * r : (1.0 + 0.055) * Math::pow(r, 1.0f / 2.4f) - 0.055,
|
||||||
|
g < 0.0031308 ? 12.92 * g : (1.0 + 0.055) * Math::pow(g, 1.0f / 2.4f) - 0.055,
|
||||||
|
b < 0.0031308 ? 12.92 * b : (1.0 + 0.055) * Math::pow(b, 1.0f / 2.4f) - 0.055, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Color hex(uint32_t p_hex);
|
||||||
|
static Color hex64(uint64_t p_hex);
|
||||||
|
static Color html(const String &p_color);
|
||||||
|
static bool html_is_valid(const String &p_color);
|
||||||
|
String to_html(bool p_alpha = true) const;
|
||||||
|
Color from_hsv(float p_h, float p_s, float p_v, float p_a) const;
|
||||||
|
static Color from_rgbe9995(uint32_t p_rgbe);
|
||||||
|
|
||||||
|
_FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys
|
||||||
|
operator String() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No construct parameters, r=0, g=0, b=0. a=255
|
||||||
|
*/
|
||||||
|
_FORCE_INLINE_ Color() {
|
||||||
|
r = 0;
|
||||||
|
g = 0;
|
||||||
|
b = 0;
|
||||||
|
a = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RGB / RGBA construct parameters. Alpha is optional, but defaults to 1.0
|
||||||
|
*/
|
||||||
|
_FORCE_INLINE_ Color(float p_r, float p_g, float p_b, float p_a = 1.0) {
|
||||||
|
r = p_r;
|
||||||
|
g = p_g;
|
||||||
|
b = p_b;
|
||||||
|
a = p_a;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool Color::operator<(const Color &p_color) const {
|
||||||
|
if (r == p_color.r) {
|
||||||
|
if (g == p_color.g) {
|
||||||
|
if (b == p_color.b) {
|
||||||
|
return (a < p_color.a);
|
||||||
|
} else {
|
||||||
|
return (b < p_color.b);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return g < p_color.g;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return r < p_color.r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue
Block a user