blah/include/blah_color.h

250 lines
6.0 KiB
C
Raw Permalink Normal View History

2020-08-26 15:38:01 +08:00
#pragma once
#include <blah_common.h>
#include <blah_string.h>
#include <blah_spatial.h>
2021-05-11 17:27:00 +08:00
2020-08-26 15:38:01 +08:00
namespace Blah
{
struct Color
{
u8 r;
u8 g;
u8 b;
u8 a;
2020-08-26 15:38:01 +08:00
2021-05-11 17:27:00 +08:00
constexpr Color()
: r(0), g(0), b(0), a(0) {}
constexpr Color(int rgb)
: r((u8)((rgb & 0xFF0000) >> 16))
, g((u8)((rgb & 0x00FF00) >> 8))
, b((u8)(rgb & 0x0000FF))
, a(255) {}
constexpr Color(int rgb, float alpha)
: r((int)(((u8)((rgb & 0xFF0000) >> 16)) * alpha))
, g((int)(((u8)((rgb & 0x00FF00) >> 8)) * alpha))
, b((int)(((u8)(rgb & 0x0000FF)) * alpha))
, a((int)(255 * alpha)) {}
constexpr Color(u8 r, u8 g, u8 b)
: r(r)
, g(g)
, b(b)
, a(255) {}
constexpr Color(u8 r, u8 g, u8 b, u8 a)
: r(r)
, g(g)
, b(b)
, a(a) {}
constexpr Color(const Vec3f& vec3)
2021-05-11 17:27:00 +08:00
: r((int)(vec3.x * 255))
, g((int)(vec3.y * 255))
, b((int)(vec3.z * 255))
, a((int)(255)) {}
constexpr Color(const Vec3f& vec3, float alpha)
2021-05-11 17:27:00 +08:00
: r((int)(vec3.x* alpha * 255))
, g((int)(vec3.y* alpha * 255))
, b((int)(vec3.z* alpha * 255))
, a((int)(alpha * 255)) {}
constexpr Color(const Vec4f& vec4)
2021-05-11 17:27:00 +08:00
: r((int)(vec4.x * 255))
, g((int)(vec4.y * 255))
, b((int)(vec4.z * 255))
, a((int)(vec4.w * 255)) {}
2020-08-26 15:38:01 +08:00
// Parses a Hex string in the format of "#00000000" or "0x00000000" or "00000000"
2021-05-11 17:27:00 +08:00
constexpr Color(const char* hex_string)
: r(0), g(0), b(0), a(255)
{
constexpr auto to_hex = [](char n) constexpr
{
return ((n >= '0' && n <= '9') ? (n - '0') : ((n >= 'A' && n <= 'F') ? (10 + n - 'A') : ((n >= 'a' && n <= 'f') ? (10 + n - 'a') : 0)));
};
2021-05-11 17:27:00 +08:00
if (*hex_string == '#')
hex_string += 1;
else if (*hex_string == '0' && (*(hex_string + 1) == 'x' || *(hex_string + 1) == 'X'))
hex_string += 2;
int len = 0;
while (len < 8 && *(hex_string + len) != '\0')
len++;
if (len >= 6)
{
r = (to_hex(hex_string[0]) << 4) + to_hex(hex_string[1]);
g = (to_hex(hex_string[2]) << 4) + to_hex(hex_string[3]);
b = (to_hex(hex_string[4]) << 4) + to_hex(hex_string[5]);
2021-05-11 17:27:00 +08:00
}
2021-05-26 12:31:18 +08:00
if (len >= 8)
a = (to_hex(hex_string[6]) << 4) + to_hex(hex_string[7]);
2021-05-11 17:27:00 +08:00
}
2020-08-26 15:38:01 +08:00
// Premultiplies the Color
2021-05-11 17:27:00 +08:00
constexpr void premultiply()
{
r = r * a / 255;
g = g * a / 255;
b = b * a / 255;
}
2020-08-26 15:38:01 +08:00
2021-03-21 17:08:28 +08:00
// Returns an RGBA hex string of the color
String to_hex_rgba() const
{
static const char* hex = "0123456789ABCDEF";
String str = "00000000";
str[0] = hex[(r & 0xF0) >> 4];
str[1] = hex[(r & 0x0F) >> 0];
str[2] = hex[(g & 0xF0) >> 4];
str[3] = hex[(g & 0x0F) >> 0];
str[4] = hex[(b & 0xF0) >> 4];
str[5] = hex[(b & 0x0F) >> 0];
str[6] = hex[(a & 0xF0) >> 4];
str[7] = hex[(a & 0x0F) >> 0];
return str;
}
2021-03-21 17:08:28 +08:00
2021-01-31 11:48:14 +08:00
// Returns an RGB hex string of the color
String to_hex_rgb() const
{
static const char* hex = "0123456789ABCDEF";
String str = "000000";
str[0] = hex[(r & 0xF0) >> 4];
str[1] = hex[(r & 0x0F) >> 0];
str[2] = hex[(g & 0xF0) >> 4];
str[3] = hex[(g & 0x0F) >> 0];
str[4] = hex[(b & 0xF0) >> 4];
str[5] = hex[(b & 0x0F) >> 0];
return str;
}
2021-01-31 11:48:14 +08:00
2021-05-11 17:27:00 +08:00
// Converts the Color to a Vec3 (RGB)
constexpr Vec3f to_vec3() const
2021-05-26 12:31:18 +08:00
{
return Vec3f(r / 255.0f, g / 255.0f, b / 255.0f);
2021-05-26 12:31:18 +08:00
}
2020-08-26 15:38:01 +08:00
2021-05-11 17:27:00 +08:00
// Converts the Color to a Vec4 (RGBA)
constexpr Vec4f to_vec4() const
2021-05-26 12:31:18 +08:00
{
return Vec4f(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
2021-05-26 12:31:18 +08:00
}
2020-08-26 15:38:01 +08:00
2022-11-19 22:29:18 +08:00
// Converts the Color to a u32
2021-05-11 17:27:00 +08:00
constexpr u32 to_rgba() const
{
return
((u32)r << 24) |
((u32)g << 16) |
((u32)b << 8) |
(u32)a;
}
2022-11-19 22:29:18 +08:00
// Converts the Color to a u32
constexpr u32 to_rgb() const
{
return
((u32)r << 16) |
((u32)g << 8) |
(u32)b;
}
2022-11-19 22:29:18 +08:00
// Returns an RGBA Color representation of the integer value
2021-05-11 17:27:00 +08:00
static constexpr Color from_rgba(u32 value)
{
return
{
(u8)((value & 0xFF000000) >> 24),
(u8)((value & 0x00FF0000) >> 16),
(u8)((value & 0x0000FF00) >> 8),
(u8)((value & 0x000000FF))
};
}
2020-08-26 15:38:01 +08:00
2022-11-19 22:29:18 +08:00
// Returns an RGB Color representation of the integer value, with Alpha = 255
2021-05-11 17:27:00 +08:00
static constexpr Color from_rgb(u32 value)
{
return
{
(u8)((value & 0xFF0000) >> 16),
(u8)((value & 0x00FF00) >> 8),
(u8)((value & 0x0000FF))
};
}
2020-08-26 15:38:01 +08:00
2021-01-31 11:48:14 +08:00
// Lerps between two colors
2021-05-11 17:27:00 +08:00
static constexpr Color lerp(Color a, Color b, float amount)
{
if (amount < 0) amount = 0;
if (amount > 1) amount = 1;
return Color(
(u8)(a.r + (b.r - a.r) * amount),
(u8)(a.g + (b.g - a.g) * amount),
(u8)(a.b + (b.b - a.b) * amount),
(u8)(a.a + (b.a - a.a) * amount)
);
}
2020-08-26 15:38:01 +08:00
2022-11-19 22:29:18 +08:00
// Multiples the Color
2021-05-11 17:27:00 +08:00
constexpr Color operator*(float multiply) const
{
return Color(
(int)(r * multiply),
(int)(g * multiply),
(int)(b * multiply),
(int)(a * multiply));
}
2020-08-26 15:38:01 +08:00
// assignment from int
2021-05-11 17:27:00 +08:00
constexpr Color& operator= (int rgb)
{
r = (u8)((rgb & 0xFF0000) >> 16);
g = (u8)((rgb & 0x00FF00) >> 8);
b = (u8)(rgb & 0x0000FF);
a = 255;
return *this;
}
constexpr bool operator ==(const Color& rhs) const
{
return r == rhs.r && g == rhs.g && b == rhs.b && a == rhs.a;
}
constexpr bool operator !=(const Color& rhs) const
{
return r != rhs.r || g != rhs.g || b != rhs.b || a != rhs.a;
}
2021-01-31 11:48:14 +08:00
2020-08-26 15:38:01 +08:00
static const Color transparent;
static const Color white;
static const Color black;
static const Color red;
static const Color green;
static const Color blue;
static const Color yellow;
static const Color orange;
static const Color purple;
static const Color teal;
};
inline const Color Color::transparent = Color( 0, 0, 0, 0);
inline const Color Color::white = Color(255, 255, 255);
inline const Color Color::black = Color( 0, 0, 0);
inline const Color Color::red = Color(255, 0, 0);
inline const Color Color::green = Color( 0, 255, 0);
inline const Color Color::blue = Color( 0, 0, 255);
inline const Color Color::yellow = Color(255, 255, 0);
2022-07-19 01:09:54 +08:00
inline const Color Color::orange = Color(255, 165, 0);
inline const Color Color::purple = Color(255, 0, 255);
inline const Color Color::teal = Color( 0, 255, 255);
2020-08-26 15:38:01 +08:00
}