spacebox/src/Color.hpp

116 lines
3.3 KiB
C++

/* +-------------------------------------------------------+
____/ \____ /| Open source game framework licensed to freely use, |
\ / / | copy, and modify, created for dank.game |
+--\ ^__^ /--+ | |
| ~/ \~ | | Download at https://open.shampoo.ooo/shampoo/spacebox |
| ~~~~~~~~~~~~ | +-------------------------------------------------------+
| SPACE ~~~~~ | /
| ~~~~~~~ BOX |/
+-------------*/
#pragma once
#include <cstdint>
#include <cstdlib>
#include <cmath>
#include <ostream>
#include <type_traits>
#include "SDL_pixels.h"
#include "glm/glm.hpp"
struct Color : SDL_Color
{
public:
Color();
Color(const SDL_Color&);
template<glm::length_t dimensions, typename Type, glm::qualifier qualifier>
Color(glm::vec<dimensions, Type, qualifier> vector)
{
if constexpr (dimensions == 2)
{
*this = Color(vector.x, vector.y, 0.0f);
}
else if constexpr (dimensions == 3)
{
*this = Color(vector.x, vector.y, vector.z);
}
else if constexpr (dimensions == 4)
{
*this = Color(vector.x, vector.y, vector.z, vector.w);
}
}
void percent(float, float, float);
void percent(float, float, float, float);
void hsv(float, float = 1.0f, float = 1.0f);
float hue() const;
void shift_hue(float);
operator std::uint32_t() const;
operator std::uint16_t() const;
operator std::uint8_t() const;
bool operator==(const Color&) const;
bool operator!=(const Color&) const;
bool operator<(const Color&) const;
/*!
* Get the color's RGBA value represented as a 4D vector of values between 0.0 and 1.0.
*/
glm::vec4 normal() const;
template <typename Type>
Color(Type red, Type green, Type blue, Type alpha = 255)
{
if (std::is_floating_point<Type>())
{
red = std::round(red);
green = std::round(green);
blue = std::round(blue);
alpha = std::round(alpha);
}
r = static_cast<int>(red) & 255;
g = static_cast<int>(green) & 255;
b = static_cast<int>(blue) & 255;
a = static_cast<int>(alpha) & 255;
}
/*!
* Convert sb::Color to glm::vec of 3 or 4 dimensions. If vector is 3-dimensional, return only the RGB portion
* of the color.
*/
template<glm::length_t dimensions, typename Type, glm::qualifier qualifier>
operator glm::vec<dimensions, Type, qualifier>() const
{
if constexpr (dimensions == 3)
{
return glm::vec3 {r, g, b};
}
else if constexpr (dimensions == 4)
{
return glm::vec4 {r, g, b, a};
}
else
{
throw std::runtime_error("Cannot convert color the glm::vec of dimensions other than 3 or 4");
}
}
};
void RGBtoHSV(const float&, const float&, const float&, float&, float&, float&);
void HSVtoRGB(float&, float&, float&, const float&, const float&, const float&);
namespace std
{
std::ostream& operator<<(std::ostream&, const Color&);
}
/* Add Color class to the sb namespace. This should be the default location, but Color is left in the global namespace
* for backward compatibility.
*/
namespace sb
{
using ::Color;
}