Core: Extend Color API

* Fix issues with alpha value <> transparency
* Use type traits to convert between different color classes (fixes #14515)
This commit is contained in:
wmayer
2024-08-21 22:26:46 +02:00
committed by Chris Hennes
parent 224c25b770
commit ffa3fa5b5a
12 changed files with 494 additions and 50 deletions

View File

@@ -67,6 +67,16 @@ void Color::set(float red, float green, float blue, float alpha)
a = alpha;
}
float Color::transparency() const
{
return 1.0F - a;
}
void Color::setTransparency(float value)
{
a = 1.0F - value;
}
// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
Color& Color::setPackedValue(uint32_t rgba)
{

View File

@@ -25,7 +25,7 @@
#define APP_COLOR_H
#ifdef __GNUC__
# include <cstdint>
#include <cstdint>
#endif
#include <cmath>
#include <string>
@@ -35,6 +35,50 @@
namespace App
{
template<class color_type>
struct color_traits
{
color_traits() = default;
explicit color_traits(const color_type& ct)
: ct(ct)
{}
float redF() const
{
return static_cast<float>(ct.redF());
}
float greenF() const
{
return static_cast<float>(ct.greenF());
}
float blueF() const
{
return static_cast<float>(ct.blueF());
}
int red() const
{
return ct.red();
}
int green() const
{
return ct.green();
}
int blue() const
{
return ct.blue();
}
int alpha() const
{
return ct.alpha();
}
static color_type makeColor(int red, int green, int blue, int alpha = 255)
{
return color_type{red, green, blue, alpha};
}
private:
color_type ct;
};
/** Color class
*/
class AppExport Color
@@ -42,9 +86,9 @@ class AppExport Color
public:
/**
* Defines the color as (R,G,B,A) whereas all values are in the range [0,1].
* \a A defines the transparency.
* \a A defines the alpha value.
*/
explicit Color(float R=0.0,float G=0.0, float B=0.0, float A=0.0);
explicit Color(float R = 0.0, float G = 0.0, float B = 0.0, float A = 1.0);
/**
* Does basically the same as the constructor above unless that (R,G,B,A) is
@@ -61,9 +105,11 @@ public:
bool operator!=(const Color& c) const;
/**
* Defines the color as (R,G,B,A) whereas all values are in the range [0,1].
* \a A defines the transparency, 0 means complete opaque and 1 invisible.
* \a A defines the alpha value, 1 means fully opaque and 0 transparent.
*/
void set(float R,float G, float B, float A=0.0);
void set(float R, float G, float B, float A = 1.0);
float transparency() const;
void setTransparency(float value);
Color& operator=(const Color& c) = default;
Color& operator=(Color&& c) = default;
/**
@@ -97,43 +143,56 @@ public:
*/
void setPackedARGB(uint32_t);
template <typename T>
static uint32_t asPackedRGBA(const T& color) {
return (color.red() << 24) | (color.green() << 16) | (color.blue() << 8) | color.alpha();
template<typename T>
static uint32_t asPackedRGBA(const T& color)
{
color_traits<T> ct{color};
return (ct.red() << 24) | (ct.green() << 16) | (ct.blue() << 8) | ct.alpha();
}
template <typename T>
static T fromPackedRGBA(uint32_t color) {
return T((color >> 24) & 0xff, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
template<typename T>
static T fromPackedRGBA(uint32_t color)
{
return color_traits<T>::makeColor((color >> 24) & 0xff,
(color >> 16) & 0xff,
(color >> 8) & 0xff,
(color & 0xff));
}
template <typename T>
static uint32_t asPackedRGB(const T& color) {
return (color.red() << 24) | (color.green() << 16) | (color.blue() << 8);
template<typename T>
static uint32_t asPackedRGB(const T& color)
{
color_traits<T> ct{color};
return (ct.red() << 24) | (ct.green() << 16) | (ct.blue() << 8);
}
template <typename T>
static T fromPackedRGB(uint32_t color) {
return T((color >> 24) & 0xff, (color >> 16) & 0xff, (color >> 8) & 0xff);
template<typename T>
static T fromPackedRGB(uint32_t color)
{
return color_traits<T>::makeColor((color >> 24) & 0xff,
(color >> 16) & 0xff,
(color >> 8) & 0xff);
}
/**
* creates FC Color from template type, e.g. Qt QColor
*/
template <typename T>
void setValue(const T& q) {
set(q.redF(),q.greenF(),q.blueF());
template<typename T>
void setValue(const T& q)
{
color_traits<T> ct{q};
set(ct.redF(), ct.greenF(), ct.blueF());
}
/**
* returns a template type e.g. Qt color equivalent to FC color
*
*/
template <typename T>
template<typename T>
inline T asValue() const
{
// clang-format off
return(T(int(std::lround(r * 255.0F)),
int(std::lround(g * 255.0F)),
int(std::lround(b * 255.0F))));
return color_traits<T>::makeColor(int(std::lround(r * 255.0F)),
int(std::lround(g * 255.0F)),
int(std::lround(b * 255.0F)));
// clang-format on
}
/**
@@ -149,9 +208,9 @@ public:
bool fromHexString(const std::string& hex);
/// color values, public accessible
float r,g,b,a;
float r {}, g {}, b {}, a {};
};
} //namespace App
} // namespace App
#endif // APP_COLOR_H
#endif // APP_COLOR_H

View File

@@ -540,8 +540,9 @@ inline Color ColorGradient::getColor (float fVal) const
{
Color color = _getColor(fVal);
if (isOutsideInvisible()) {
if (isOutOfRange(fVal))
color.a = 0.8f;
if (isOutOfRange(fVal)) {
color.a = 0.2F;
}
}
return color;

View File

@@ -55,7 +55,7 @@ Part::Part()
ADD_PROPERTY_TYPE(License, (""), 0, App::Prop_None, "License string of the Item");
ADD_PROPERTY_TYPE(LicenseURL, (""), 0, App::Prop_None, "URL to the license text/contract");
// color and appearance
ADD_PROPERTY(Color, (1.0, 1.0, 1.0, 1.0)); // set transparent -> not used
ADD_PROPERTY(Color, (1.0, 1.0, 1.0, 0.0)); // set transparent -> not used
GroupExtension::initExtension(this);
}

View File

@@ -1038,19 +1038,19 @@ public:
*/
void setValue(const Material& mat);
void setValue(const Color& col);
void setValue(float r, float g, float b, float a = 0.0F);
void setValue(float r, float g, float b, float a = 1.0F);
void setValue(uint32_t rgba);
void setAmbientColor(const Color& col);
void setAmbientColor(float r, float g, float b, float a = 0.0F);
void setAmbientColor(float r, float g, float b, float a = 1.0F);
void setAmbientColor(uint32_t rgba);
void setDiffuseColor(const Color& col);
void setDiffuseColor(float r, float g, float b, float a = 0.0F);
void setDiffuseColor(float r, float g, float b, float a = 1.0F);
void setDiffuseColor(uint32_t rgba);
void setSpecularColor(const Color& col);
void setSpecularColor(float r, float g, float b, float a = 0.0F);
void setSpecularColor(float r, float g, float b, float a = 1.0F);
void setSpecularColor(uint32_t rgba);
void setEmissiveColor(const Color& col);
void setEmissiveColor(float r, float g, float b, float a = 0.0F);
void setEmissiveColor(float r, float g, float b, float a = 1.0F);
void setEmissiveColor(uint32_t rgba);
void setShininess(float);
void setTransparency(float);
@@ -1123,32 +1123,32 @@ public:
void setValue(int index, const Material& mat);
void setAmbientColor(const Color& col);
void setAmbientColor(float r, float g, float b, float a = 0.0F);
void setAmbientColor(float r, float g, float b, float a = 1.0F);
void setAmbientColor(uint32_t rgba);
void setAmbientColor(int index, const Color& col);
void setAmbientColor(int index, float r, float g, float b, float a = 0.0F);
void setAmbientColor(int index, float r, float g, float b, float a = 1.0F);
void setAmbientColor(int index, uint32_t rgba);
void setDiffuseColor(const Color& col);
void setDiffuseColor(float r, float g, float b, float a = 0.0F);
void setDiffuseColor(float r, float g, float b, float a = 1.0F);
void setDiffuseColor(uint32_t rgba);
void setDiffuseColor(int index, const Color& col);
void setDiffuseColor(int index, float r, float g, float b, float a = 0.0F);
void setDiffuseColor(int index, float r, float g, float b, float a = 1.0F);
void setDiffuseColor(int index, uint32_t rgba);
void setDiffuseColors(const std::vector<App::Color>& colors);
void setSpecularColor(const Color& col);
void setSpecularColor(float r, float g, float b, float a = 0.0F);
void setSpecularColor(float r, float g, float b, float a = 1.0F);
void setSpecularColor(uint32_t rgba);
void setSpecularColor(int index, const Color& col);
void setSpecularColor(int index, float r, float g, float b, float a = 0.0F);
void setSpecularColor(int index, float r, float g, float b, float a = 1.0F);
void setSpecularColor(int index, uint32_t rgba);
void setEmissiveColor(const Color& col);
void setEmissiveColor(float r, float g, float b, float a = 0.0F);
void setEmissiveColor(float r, float g, float b, float a = 1.0F);
void setEmissiveColor(uint32_t rgba);
void setEmissiveColor(int index, const Color& col);
void setEmissiveColor(int index, float r, float g, float b, float a = 0.0F);
void setEmissiveColor(int index, float r, float g, float b, float a = 1.0F);
void setEmissiveColor(int index, uint32_t rgba);
void setShininess(float);