Merge pull request #1879 from Azaezel/sRGBSwatch

colorPicker/swatch srgb display.
This commit is contained in:
Areloch 2016-12-27 22:11:02 -06:00 committed by GitHub
commit b19aba2e54
7 changed files with 162 additions and 41 deletions

View file

@ -34,6 +34,9 @@
#include "console/engineAPI.h" #include "console/engineAPI.h"
#endif #endif
const F32 gGamma = 2.2f;
const F32 gOneOverGamma = 1.f / 2.2f;
class ColorI; class ColorI;
@ -104,8 +107,10 @@ class ColorF
(alpha >= 0.0f && alpha <= 1.0f); } (alpha >= 0.0f && alpha <= 1.0f); }
void clamp(); void clamp();
ColorF toLinear() const; ColorF toLinear();
ColorF toGamma() const; ColorF toGamma();
//calculate luminance, make sure color is linear first
F32 luminance();
static const ColorF ZERO; static const ColorF ZERO;
static const ColorF ONE; static const ColorF ONE;
@ -209,6 +214,9 @@ class ColorI
operator const U8*() const { return &red; } operator const U8*() const { return &red; }
ColorI toLinear();
ColorI toGamma();
static const ColorI ZERO; static const ColorI ZERO;
static const ColorI ONE; static const ColorI ONE;
static const ColorI WHITE; static const ColorI WHITE;
@ -465,14 +473,32 @@ inline void ColorF::clamp()
alpha = 0.0f; alpha = 0.0f;
} }
inline ColorF ColorF::toLinear() const inline ColorF ColorF::toGamma()
{ {
return ColorF(mPow(red, 2.2f), mPow(green, 2.2f), mPow(blue, 2.2f), alpha); ColorF color;
color.red = mPow(red,gOneOverGamma);
color.green = mPow(green, gOneOverGamma);
color.blue = mPow(blue, gOneOverGamma);
color.alpha = alpha;
return color;
} }
inline ColorF ColorF::toGamma() const inline ColorF ColorF::toLinear()
{ {
return ColorF(mPow(red, 1.0f / 2.2f), mPow(green, 1.0f / 2.2f), mPow(blue, 1.0f / 2.2f), alpha); ColorF color;
color.red = mPow(red,gGamma);
color.green = mPow(green, gGamma);
color.blue = mPow(blue, gGamma);
color.alpha = alpha;
return color;
}
inline F32 ColorF::luminance()
{
// ITU BT.709
//return red * 0.2126f + green * 0.7152f + blue * 0.0722f;
// ITU BT.601
return red * 0.3f + green * 0.59f + blue * 0.11f;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -945,6 +971,18 @@ inline String ColorI::getHex() const
return result; return result;
} }
inline ColorI ColorI::toGamma()
{
ColorF color = (ColorF)*this;
return (ColorI)color.toGamma();
}
inline ColorI ColorI::toLinear()
{
ColorF color = (ColorF)*this;
return (ColorI)color.toLinear();
}
//-------------------------------------- INLINE CONVERSION OPERATORS //-------------------------------------- INLINE CONVERSION OPERATORS
inline ColorF::operator ColorI() const inline ColorF::operator ColorI() const
{ {

View file

@ -58,7 +58,7 @@ ConsoleDocClass( GuiSwatchButtonCtrl,
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
GuiSwatchButtonCtrl::GuiSwatchButtonCtrl() GuiSwatchButtonCtrl::GuiSwatchButtonCtrl()
: mSwatchColor( 1, 1, 1, 1 ) : mSwatchColor(1, 1, 1, 1), mUseSRGB(false)
{ {
mButtonText = StringTable->insert( "" ); mButtonText = StringTable->insert( "" );
setExtent(140, 30); setExtent(140, 30);
@ -71,7 +71,8 @@ GuiSwatchButtonCtrl::GuiSwatchButtonCtrl()
void GuiSwatchButtonCtrl::initPersistFields() void GuiSwatchButtonCtrl::initPersistFields()
{ {
addField( "color", TypeColorF, Offset( mSwatchColor, GuiSwatchButtonCtrl ), "The foreground color of GuiSwatchButtonCtrl" ); addField("color", TypeColorF, Offset(mSwatchColor, GuiSwatchButtonCtrl), "The foreground color of GuiSwatchButtonCtrl");
addField( "useSRGB", TypeBool, Offset( mUseSRGB, GuiSwatchButtonCtrl ), "Render using sRGB scale" );
addField( "gridBitmap", TypeString, Offset( mGridBitmap, GuiSwatchButtonCtrl ), "The bitmap used for the transparent grid" ); addField( "gridBitmap", TypeString, Offset( mGridBitmap, GuiSwatchButtonCtrl ), "The bitmap used for the transparent grid" );
@ -107,7 +108,10 @@ void GuiSwatchButtonCtrl::onRender( Point2I offset, const RectI &updateRect )
drawer->drawBitmapStretch( mGrid, renderRect ); drawer->drawBitmapStretch( mGrid, renderRect );
// Draw swatch color as fill... // Draw swatch color as fill...
drawer->drawRectFill( renderRect, mSwatchColor ); if (!mUseSRGB)
drawer->drawRectFill( renderRect, mSwatchColor.toGamma() );
else
drawer->drawRectFill(renderRect, mSwatchColor);
// Draw any borders... // Draw any borders...
drawer->drawRect( renderRect, borderColor ); drawer->drawRect( renderRect, borderColor );

View file

@ -40,7 +40,7 @@ class GuiSwatchButtonCtrl : public GuiButtonBaseCtrl
/// The color to display on the button. /// The color to display on the button.
ColorF mSwatchColor; ColorF mSwatchColor;
bool mUseSRGB; ///< use sRGB color scale
/// Bitmap used for mGrid /// Bitmap used for mGrid
String mGridBitmap; String mGridBitmap;

View file

@ -73,6 +73,7 @@ GuiColorPickerCtrl::GuiColorPickerCtrl()
mSelectColor = false; mSelectColor = false;
mSetColor = mSetColor.BLACK; mSetColor = mSetColor.BLACK;
mBitmap = NULL; mBitmap = NULL;
mUseSRGB = false;
} }
GuiColorPickerCtrl::~GuiColorPickerCtrl() GuiColorPickerCtrl::~GuiColorPickerCtrl()
@ -104,6 +105,7 @@ void GuiColorPickerCtrl::initPersistFields()
addGroup("ColorPicker"); addGroup("ColorPicker");
addField("baseColor", TypeColorF, Offset(mBaseColor, GuiColorPickerCtrl)); addField("baseColor", TypeColorF, Offset(mBaseColor, GuiColorPickerCtrl));
addField("pickColor", TypeColorF, Offset(mPickColor, GuiColorPickerCtrl)); addField("pickColor", TypeColorF, Offset(mPickColor, GuiColorPickerCtrl));
addField("useSRGB", TypeBool, Offset(mUseSRGB, GuiColorPickerCtrl), "Render using sRGB scale");
addField("selectorGap", TypeS32, Offset(mSelectorGap, GuiColorPickerCtrl)); addField("selectorGap", TypeS32, Offset(mSelectorGap, GuiColorPickerCtrl));
addField("displayMode", TYPEID< PickMode >(), Offset(mDisplayMode, GuiColorPickerCtrl) ); addField("displayMode", TYPEID< PickMode >(), Offset(mDisplayMode, GuiColorPickerCtrl) );
addField("actionOnMove", TypeBool,Offset(mActionOnMove, GuiColorPickerCtrl)); addField("actionOnMove", TypeBool,Offset(mActionOnMove, GuiColorPickerCtrl));
@ -120,24 +122,35 @@ void GuiColorPickerCtrl::drawBlendBox(RectI &bounds, ColorF &c1, ColorF &c2, Col
S32 l = bounds.point.x, r = bounds.point.x + bounds.extent.x; S32 l = bounds.point.x, r = bounds.point.x + bounds.extent.x;
S32 t = bounds.point.y, b = bounds.point.y + bounds.extent.y; S32 t = bounds.point.y, b = bounds.point.y + bounds.extent.y;
ColorF col[4];
col[0] = c1;
col[1] = c2;
col[2] = c3;
col[3] = c4;
if (!mUseSRGB)
{
for (U32 i = 0; i < 4; i++)
col[i] = col[i].toGamma();
}
//A couple of checks to determine if color blend //A couple of checks to determine if color blend
//A couple of checks to determine if color blend //A couple of checks to determine if color blend
if(c1 == colorWhite && c3 == colorAlpha && c4 == colorBlack) if (c1 == colorWhite && c3 == colorAlpha && c4 == colorBlack)
{ {
//Color //Color
PrimBuild::begin(GFXTriangleStrip, 4); PrimBuild::begin(GFXTriangleStrip, 4);
PrimBuild::color( c2 ); PrimBuild::color(col[1]);
PrimBuild::vertex2i(l, t); PrimBuild::vertex2i(l, t);
PrimBuild::color( c2 ); PrimBuild::color(col[1]);
PrimBuild::vertex2i(r, t); PrimBuild::vertex2i(r, t);
PrimBuild::color( c2 ); PrimBuild::color(col[1]);
PrimBuild::vertex2i( l, b ); PrimBuild::vertex2i(l, b);
PrimBuild::color( c2 ); PrimBuild::color(col[1]);
PrimBuild::vertex2i(r, b); PrimBuild::vertex2i(r, b);
PrimBuild::end(); PrimBuild::end();
@ -145,14 +158,14 @@ void GuiColorPickerCtrl::drawBlendBox(RectI &bounds, ColorF &c1, ColorF &c2, Col
//White //White
PrimBuild::begin(GFXTriangleStrip, 4); PrimBuild::begin(GFXTriangleStrip, 4);
PrimBuild::color(c1); PrimBuild::color(col[0]);
PrimBuild::vertex2i(l, t); PrimBuild::vertex2i(l, t);
PrimBuild::color( colorAlphaW ); PrimBuild::color(colorAlphaW);
PrimBuild::vertex2i(r, t); PrimBuild::vertex2i(r, t);
PrimBuild::color( c1 ); PrimBuild::color(col[0]);
PrimBuild::vertex2i( l, b ); PrimBuild::vertex2i(l, b);
PrimBuild::color(colorAlphaW); PrimBuild::color(colorAlphaW);
PrimBuild::vertex2i(r, b); PrimBuild::vertex2i(r, b);
@ -162,15 +175,15 @@ void GuiColorPickerCtrl::drawBlendBox(RectI &bounds, ColorF &c1, ColorF &c2, Col
//Black //Black
PrimBuild::begin(GFXTriangleStrip, 4); PrimBuild::begin(GFXTriangleStrip, 4);
PrimBuild::color(c3); PrimBuild::color(col[2]);
PrimBuild::vertex2i(l, t); PrimBuild::vertex2i(l, t);
PrimBuild::color( c3 ); PrimBuild::color(col[2]);
PrimBuild::vertex2i( r, t ); PrimBuild::vertex2i(r, t);
PrimBuild::color( c4 ); PrimBuild::color(col[3]);
PrimBuild::vertex2i(l, b); PrimBuild::vertex2i(l, b);
PrimBuild::color( c4 ); PrimBuild::color(col[3]);
PrimBuild::vertex2i(r, b); PrimBuild::vertex2i(r, b);
PrimBuild::end(); PrimBuild::end();
@ -179,17 +192,17 @@ void GuiColorPickerCtrl::drawBlendBox(RectI &bounds, ColorF &c1, ColorF &c2, Col
{ {
PrimBuild::begin(GFXTriangleStrip, 4); PrimBuild::begin(GFXTriangleStrip, 4);
PrimBuild::color( c1 ); PrimBuild::color(col[0]);
PrimBuild::vertex2i( l, t ); PrimBuild::vertex2i(l, t);
PrimBuild::color( c2 ); PrimBuild::color(col[1]);
PrimBuild::vertex2i( r, t ); PrimBuild::vertex2i(r, t);
PrimBuild::color(c4); PrimBuild::color(col[3]);
PrimBuild::vertex2i(l, b); PrimBuild::vertex2i(l, b);
PrimBuild::color( c3 ); PrimBuild::color(col[2]);
PrimBuild::vertex2i( r, b ); PrimBuild::vertex2i(r, b);
PrimBuild::end(); PrimBuild::end();
} }
@ -199,6 +212,7 @@ void GuiColorPickerCtrl::drawBlendBox(RectI &bounds, ColorF &c1, ColorF &c2, Col
/// Function to draw a set of boxes blending throughout an array of colors /// Function to draw a set of boxes blending throughout an array of colors
void GuiColorPickerCtrl::drawBlendRangeBox(RectI &bounds, bool vertical, U8 numColors, ColorI *colors) void GuiColorPickerCtrl::drawBlendRangeBox(RectI &bounds, bool vertical, U8 numColors, ColorI *colors)
{ {
GFX->setStateBlock(mStateBlock); GFX->setStateBlock(mStateBlock);
S32 l = bounds.point.x, r = bounds.point.x + bounds.extent.x + 4; S32 l = bounds.point.x, r = bounds.point.x + bounds.extent.x + 4;
@ -208,6 +222,20 @@ void GuiColorPickerCtrl::drawBlendRangeBox(RectI &bounds, bool vertical, U8 numC
S32 x_inc = int(mFloor((r - l) / F32(numColors - 1))); S32 x_inc = int(mFloor((r - l) / F32(numColors - 1)));
S32 y_inc = int(mFloor((b - t) / F32(numColors - 1))); S32 y_inc = int(mFloor((b - t) / F32(numColors - 1)));
ColorI *col = new ColorI[numColors];
dMemcpy(col, colors, numColors * sizeof(ColorI));
if (mUseSRGB)
{
for (U16 i = 0; i < numColors - 1; i++)
col[i] = colors[i];
}
else
{
for (U16 i = 0; i < numColors - 1; i++)
col[i] = colors[i].toGamma();
}
for (U16 i = 0; i < numColors - 1; i++) for (U16 i = 0; i < numColors - 1; i++)
{ {
// This is not efficent, but then again it doesn't really need to be. -pw // This is not efficent, but then again it doesn't really need to be. -pw
@ -216,30 +244,30 @@ void GuiColorPickerCtrl::drawBlendRangeBox(RectI &bounds, bool vertical, U8 numC
if (!vertical) // Horizontal (+x) if (!vertical) // Horizontal (+x)
{ {
// First color // First color
PrimBuild::color(colors[i]); PrimBuild::color(col[i]);
PrimBuild::vertex2i(l, t); PrimBuild::vertex2i(l, t);
PrimBuild::color(colors[i + 1]); PrimBuild::color(col[i + 1]);
PrimBuild::vertex2i(l + x_inc, t); PrimBuild::vertex2i(l + x_inc, t);
// Second color // Second color
PrimBuild::color(colors[i]); PrimBuild::color(col[i]);
PrimBuild::vertex2i(l, b); PrimBuild::vertex2i(l, b);
PrimBuild::color(colors[i + 1]); PrimBuild::color(col[i + 1]);
PrimBuild::vertex2i(l + x_inc, b); PrimBuild::vertex2i(l + x_inc, b);
l += x_inc; l += x_inc;
} }
else // Vertical (+y) else // Vertical (+y)
{ {
// First color // First color
PrimBuild::color(colors[i]); PrimBuild::color(col[i]);
PrimBuild::vertex2i(l, t); PrimBuild::vertex2i(l, t);
PrimBuild::color(colors[i + 1]); PrimBuild::color(col[i + 1]);
PrimBuild::vertex2i(l, t + y_inc); PrimBuild::vertex2i(l, t + y_inc);
// Second color // Second color
PrimBuild::color(colors[i]); PrimBuild::color(col[i]);
PrimBuild::vertex2i(r, t); PrimBuild::vertex2i(r, t);
PrimBuild::color(colors[i + 1]); PrimBuild::color(col[i + 1]);
PrimBuild::vertex2i(r, t + y_inc); PrimBuild::vertex2i(r, t + y_inc);
t += y_inc; t += y_inc;
} }

View file

@ -90,6 +90,7 @@ class GuiColorPickerCtrl : public GuiControl
ColorF mPickColor; ///< Color that has been picked from control ColorF mPickColor; ///< Color that has been picked from control
ColorF mBaseColor; ///< Colour we display (in case of pallet and blend mode) ColorF mBaseColor; ///< Colour we display (in case of pallet and blend mode)
PickMode mDisplayMode; ///< Current color display mode of the selector PickMode mDisplayMode; ///< Current color display mode of the selector
bool mUseSRGB; ///< use sRGB color scale
Point2I mSelectorPos; ///< Current position of the selector Point2I mSelectorPos; ///< Current position of the selector
bool mPositionChanged; ///< Current position has changed since last render? bool mPositionChanged; ///< Current position has changed since last render?

View file

@ -718,6 +718,22 @@
canSave = "1"; canSave = "1";
canSaveDynamicFields = "0"; canSaveDynamicFields = "0";
}; };
new GuiCheckBoxCtrl() {
text = "use sRGB";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
position = "360 105";
extent = "66 16";
minExtent = "8 2";
horizSizing = "right";
vertSizing = "bottom";
profile = "GuiCheckBoxProfile";
visible = "1";
active = "1";
variable = "$displayAsSRGB";
command = "useSRGBctrl($displayAsSRGB);";
};
}; };
}; };
//--- OBJECT WRITE END --- //--- OBJECT WRITE END ---
@ -727,6 +743,15 @@ $ColorPickerCancelCallback = "";
$ColorPickerUpdateCallback = ""; $ColorPickerUpdateCallback = "";
$ColorCallbackType = 1; // ColorI $ColorCallbackType = 1; // ColorI
function useSRGBctrl(%colorScale)
{
ColorPickerDlg.useSRGB = %colorScale;
ColorRangeSelect.useSRGB = %colorScale;
ColorBlendSelect.useSRGB = %colorScale;
myColor.useSRGB = %colorScale;
oldColor.useSRGB = %colorScale;
}
// This function pushes the color picker dialog and returns to a callback the selected value // This function pushes the color picker dialog and returns to a callback the selected value
function GetColorI( %currentColor, %callback, %root, %updateCallback, %cancelCallback ) function GetColorI( %currentColor, %callback, %root, %updateCallback, %cancelCallback )
{ {

View file

@ -718,6 +718,22 @@
canSave = "1"; canSave = "1";
canSaveDynamicFields = "0"; canSaveDynamicFields = "0";
}; };
new GuiCheckBoxCtrl() {
text = "use sRGB";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
position = "360 105";
extent = "66 16";
minExtent = "8 2";
horizSizing = "right";
vertSizing = "bottom";
profile = "GuiCheckBoxProfile";
visible = "1";
active = "1";
variable = "$displayAsSRGB";
command = "useSRGBctrl($displayAsSRGB);";
};
}; };
}; };
//--- OBJECT WRITE END --- //--- OBJECT WRITE END ---
@ -727,6 +743,15 @@ $ColorPickerCancelCallback = "";
$ColorPickerUpdateCallback = ""; $ColorPickerUpdateCallback = "";
$ColorCallbackType = 1; // ColorI $ColorCallbackType = 1; // ColorI
function useSRGBctrl(%colorScale)
{
ColorPickerDlg.useSRGB = %colorScale;
ColorRangeSelect.useSRGB = %colorScale;
ColorBlendSelect.useSRGB = %colorScale;
myColor.useSRGB = %colorScale;
oldColor.useSRGB = %colorScale;
}
// This function pushes the color picker dialog and returns to a callback the selected value // This function pushes the color picker dialog and returns to a callback the selected value
function GetColorI( %currentColor, %callback, %root, %updateCallback, %cancelCallback ) function GetColorI( %currentColor, %callback, %root, %updateCallback, %cancelCallback )
{ {