![]() |
![]() |



Author: philk
Date Submitted: 2004-07-19 14:04:26
struct Color
{
float red;
float green;
float blue;
float alpha;
Color(const float _r = 1.0f, const float _g = 1.0f, const float _b = 1.0f, const float _a = 1.0f):
red(_r),
green(_g),
blue(_b),
alpha(_a)
{
Clamp();
}
Color(const int _r, const int _g, const int _b, const int _a = 255):
red(_r / 255.f),
green(_g / 255.f),
blue(_b / 255.f),
alpha(_a / 255.f)
{
Clamp();
}
Color(const Color& _rOther):
red(_rOther.red),
green(_rOther.green),
blue(_rOther.blue),
alpha(_rOther.alpha)
{
// Not neccessary since the parent is already clamped, hopefully ;)
//Clamp();
}
const Color& operator = (const Color& _rOther)
{
red = _rOther.red;
green = _rOther.green;
blue = _rOther.blue;
alpha = _rOther.alpha;
return *this;
}
void Normalize()
{
red /= 255.f;
if (red < 0.0f)
{
red = 0.0f;
}
green /= 255.f;
if (green < 0.0f)
{
green = 0.0f;
}
blue /= 255.f;
if (blue < 0.0f)
{
blue = 0.0f;
}
alpha /= 255.f;
if (alpha < 0.0f)
{
alpha = 0.0f;
}
}
void Clamp()
{
if (red < 0.0f)
{
red = 0.0f;
}
else if (red > 1.0f)
{
red = 1.0f;
}
if (green < 0.0f)
{
green = 0.0f;
}
else if (green > 1.0f)
{
green = 1.0f;
}
if (blue < 0.0f)
{
blue = 0.0f;
}
else if (blue > 1.0f)
{
blue = 1.0f;
}
if (alpha < 0.0f)
{
alpha = 0.0f;
}
else if (alpha > 1.0f)
{
alpha = 1.0f;
}
}
void Set() const
{
cipher_r_SetColour((float*)this);
}
void Unset() const
{
cipher_r_SetColour(NULL);
}
const Color& Lerp(const Color& _rOther, float _fFactor)
{
red = red + _fFactor * (_rOther.red - red);
green = green + _fFactor * (_rOther.green - green);
blue = blue + _fFactor * (_rOther.blue - blue);
alpha = alpha + _fFactor * (_rOther.alpha - alpha);
return *this;
}
};
// A helper to set a color.
// If the class goes out of scope its destructor will reset the color value
// Since all the members are const the class does not take any memory.
// It just sits on the stack and all methods are inlined into the code.
class StackColor
{
const bool m_bSet;
Color const& m_rColor;
public:
StackColor(Color const& _rColor, const bool _bSet = true):
m_rColor(_rColor),
m_bSet(_bSet)
{
if (_bSet)
{
m_rColor.Set();
}
}
~StackColor()
{
if (m_bSet)
{
m_rColor.Unset();
}
}
};I use these classes to simplify my color management.
Especially the StackColor saved me a lot of debugging time. How often you forget to call "cipher_r_SetColour" and wonder why some shaders are drawn with the wrong colour?
StackColor ensures the colour is set back to NULL (white) when the object leaves the scope.
Example:
Color textColor(255,0,0);
{
StackColor col(textColor);
} // Here the StackColor::~StackColor is called, and resets the colour
[Recent Contributions] [Recent Source Code]
User Contributed Comments
class Color
{
unsigned int m_uiColor;
public:
Color( void ) : m_uiColor(0xFFFFFFFF) {}
Color( unsigned int uiColor ) : m_uiColor(uiColor) { };
Color( unsigned char uiRed, unsigned char uiGreen,
unsigned char uiBlue, unsigned char uiAlpha )
{
m_uiColor = ((uiRed & 0xFF) << 24) | ((uiGreen & 0xFF) << 16) |
((uiBlue & 0xFF) << 8) | (uiAlpha & 0xFF);
}
const Color& operator = ( const Color& clrSource )
{
m_uiColor = clrSource.m_uiColor;
return *this;
}
operator unsigned int ( void ) const
{
return m_uiColor;
}
// prefer indirect access with Color::Red, Color::Green, Color::Blue, and Color::Alpha
const unsigned char operator [] ( int iIndex ) const
{
unsigned char uiBytes[4] =
{
((m_uiColor & 0xff000000)>>24), ((m_uiColor & 0x00ff0000)>>16),
((m_uiColor & 0x0000ff00)>>8), ((m_uiColor & 0x000000ff))
};
return uiBytes[iIndex];
}
unsigned char getRed( void ) const
{
return this->operator[](Color::Red);
}
unsigned char getGreen( void ) const
{
return this->operator[](Color::Green);
}
unsigned char getBlue( void ) const
{
return this->operator[](Color::Blue);
}
unsigned char getAlpha( void ) const
{
return this->operator[](Color::Alpha);
}
void setRed( unsigned char uiRed )
{
m_uiColor &= ~0xFF000000;
m_uiColor |= ((uiRed & 0xFF) << 24);
}
void setGreen( unsigned char uiGreen )
{
m_uiColor &= ~0x00FF0000;
m_uiColor |= ((uiGreen & 0xFF) << 16);
}
void setBlue( unsigned char uiBlue )
{
m_uiColor &= ~0x0000FF00;
m_uiColor |= ((uiBlue & 0xFF) << 8);
}
void setAlpha( unsigned char uiAlpha )
{
m_uiColor &= ~0x000000FF;
m_uiColor |= (uiAlpha & 0xFF);
}
Color asBigEndian( void ) const // flip from ABGR to RGBA on big endian machines
{
unsigned char uiBytes[4] =
{
((m_uiColor & 0xff000000)>>24), ((m_uiColor & 0x00ff0000)>>16),
((m_uiColor & 0x0000ff00)>>8), ((m_uiColor & 0x000000ff))
};
return Color(uiBytes[Color::Alpha], uiBytes[Color::Blue],
uiBytes[Color::Green], uiBytes[Color::Red]);
}
enum indices_e { Red = 0, Green = 1, Blue = 2, Alpha = 3 };
};