mirror of
https://github.com/Relintai/rcpp_framework.git
synced 2024-11-14 04:57:21 +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;
|
||||
g = 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) {
|
||||
@ -38,3 +38,515 @@ ColorUInt8::ColorUInt8(const uint32_t key) {
|
||||
|
||||
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 <inttypes.h>
|
||||
|
||||
//Todo add float version
|
||||
//Not sure but probably that should be the default
|
||||
#include "core/string.h"
|
||||
#include "core/math/math.h"
|
||||
|
||||
class ColorUInt8 {
|
||||
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
|
Loading…
Reference in New Issue
Block a user