Browse Source

Merge pull request #1362 from marauder2k9-torque/ColorPicker-refactor

Color picker refactor
Brian Roberts 7 months ago
parent
commit
71d08e9e0c

+ 1 - 1
Engine/source/console/consoleFunctions.cpp

@@ -1104,7 +1104,7 @@ DefineEngineFunction(ColorRGBToHSB, const char*, (ColorI color), ,
    "@endtsexample\n"
    "@ingroup Strings")
 {
-   ColorI::Hsb hsb(color.getHSB());
+   ColorI::Hsb hsb(color.getHSB()); 
    String s(String::ToString(hsb.hue) + " " + String::ToString(hsb.sat) + " " + String::ToString(hsb.brightness));
    return Con::getReturnBuffer(s);
 }

+ 21 - 0
Engine/source/console/consoleTypes.cpp

@@ -409,6 +409,27 @@ ConsoleSetType( TypeS32Vector )
    else
       Con::printf("Vector<S32> must be set as { a, b, c, ... } or \"a b c ...\"");
 }
+//-----------------------------------------------------------------------------
+// TypeF64
+//-----------------------------------------------------------------------------
+ConsoleType(double, TypeF64, F64, "")
+ImplementConsoleTypeCasters(TypeF64, F64)
+
+ConsoleGetType(TypeF64)
+{
+   static const U32 bufSize = 256;
+   char* returnBuffer = Con::getReturnBuffer(bufSize);
+   dSprintf(returnBuffer, bufSize, "%Lg", *((F64*)dptr));
+   return returnBuffer;
+}
+ConsoleSetType(TypeF64)
+{
+   if (argc == 1)
+      *((F64*)dptr) = dAtod(argv[0]);
+   else
+      Con::printf("(TypeF64) Cannot set multiple args to a single F64.");
+}
+
 
 //-----------------------------------------------------------------------------
 // TypeF32

+ 1 - 0
Engine/source/console/consoleTypes.h

@@ -66,6 +66,7 @@ DefineConsoleType( TypeBoolVector, Vector<bool>)
 DefineConsoleType( TypeS8,  S8 )
 DefineConsoleType( TypeS32, S32 )
 DefineConsoleType( TypeS32Vector, Vector<S32> )
+DefineConsoleType( TypeF64, F64 )
 DefineConsoleType( TypeF32, F32 )
 DefineConsoleType( TypeF32Vector, Vector<F32> )
 DefineUnmappedConsoleType( TypeString, const char * ) // plain UTF-8 strings are not supported in new interop

+ 81 - 129
Engine/source/core/color.h

@@ -129,11 +129,11 @@ public:
    struct Hsb
    {
       Hsb() :hue(0), sat(0), brightness(0){};
-      Hsb(U32 h, U32 s, U32 b) :hue(h), sat(s), brightness(b){};
+      Hsb(F64 h, F64 s, F64 b) :hue(h), sat(s), brightness(b){};
 
-      U32 hue;   ///Hue
-      U32 sat;   ///Saturation
-      U32 brightness;   //Brightness/Value/Lightness
+      F64 hue;   ///Hue
+      F64 sat;   ///Saturation
+      F64 brightness;   //Brightness/Value/Lightness
    };
 
 public:
@@ -466,72 +466,48 @@ inline void ColorI::set(const ColorI& in_rCopy,
 
 inline void ColorI::set(const Hsb& color)
 {
-	U32 r = 0;
-	U32 g = 0;
-	U32 b = 0;
+   // Normalize the input HSB values
+   F64 H = (F64)color.hue / 360.0;        // Hue: [0, 360] -> [0, 1]
+   F64 S = (F64)color.sat / 100.0;        // Saturation: [0, 100] -> [0, 1]
+   F64 B = (F64)color.brightness / 100.0; // Brightness: [0, 100] -> [0, 1]
 
-	F64 L = ((F64)color.brightness) / 100.0;
-	F64 S = ((F64)color.sat) / 100.0;
-	F64 H = ((F64)color.hue) / 360.0;
+   F64 r = 0.0, g = 0.0, b = 0.0;
 
-	if (color.sat == 0)
-	{
-		r = color.brightness;
-		g = color.brightness;
-		b = color.brightness;
-	}
-	else
-	{
-		F64 temp1 = 0;
-		if (L < 0.50)
-		{
-			temp1 = L*(1 + S);
-		}
-		else
-		{
-			temp1 = L + S - (L*S);
-		}
-
-		F64 temp2 = 2.0*L - temp1;
-
-		F64 temp3 = 0;
-		for (S32 i = 0; i < 3; i++)
-		{
-			switch (i)
-			{
-			case 0: // red
-			{
-				temp3 = H + 0.33333;
-				if (temp3 > 1.0)
-					temp3 -= 1.0;
-				HSLtoRGB_Subfunction(r, temp1, temp2, temp3);
-				break;
-			}
-			case 1: // green
-			{
-				temp3 = H;
-				HSLtoRGB_Subfunction(g, temp1, temp2, temp3);
-				break;
-			}
-			case 2: // blue
-			{
-				temp3 = H - 0.33333;
-				if (temp3 < 0)
-					temp3 += 1;
-				HSLtoRGB_Subfunction(b, temp1, temp2, temp3);
-				break;
-			}
-			default:
-			{
+   if(S == 0.0)
+   {
+      // Achromatic case (grey scale)
+      r = g = b = B;
+   }
+   else
+   {
+      // Compute chroma
+      F64 C = B * S;
+
+      // Intermediate value for the hue
+      F64 X = C * (1 - mFabsD(mFmodD(H * 6.0, 2.0) - 1));
+
+      // Minimum component
+      F64 m = B - C;
+
+      // Assign r, g, b based on the hue sector
+      if (H >= 0.0 && H < 1.0 / 6.0) { r = C; g = X; b = 0.0; }
+      else if (H >= 1.0 / 6.0 && H < 2.0 / 6.0) { r = X; g = C; b = 0.0; }
+      else if (H >= 2.0 / 6.0 && H < 3.0 / 6.0) { r = 0.0; g = C; b = X; }
+      else if (H >= 3.0 / 6.0 && H < 4.0 / 6.0) { r = 0.0; g = X; b = C; }
+      else if (H >= 4.0 / 6.0 && H < 5.0 / 6.0) { r = X; g = 0.0; b = C; }
+      else if (H >= 5.0 / 6.0 && H <= 1.0) { r = C; g = 0.0; b = X; }
+
+      // Add the minimum component to normalize to the brightness
+      r += m;
+      g += m;
+      b += m;
+   }
 
-			}
-			}
-		}
-	}
-	red = (U32)((((F64)r) / 100) * 255);
-	green = (U32)((((F64)g) / 100) * 255);
-	blue = (U32)((((F64)b) / 100) * 255);
-   alpha = 255;
+   // Convert normalized [0.0, 1.0] RGB values to integer [0, 255]
+   red = static_cast<U32>(r * 255.0 + 0.5);
+   green = static_cast<U32>(g * 255.0 + 0.5);
+   blue = static_cast<U32>(b * 255.0 + 0.5);
+   alpha = 255; // Set alpha to fully opaque
 }
 
 // This is a subfunction of HSLtoRGB
@@ -744,70 +720,46 @@ inline U16 ColorI::get4444() const
 
 inline ColorI::Hsb ColorI::getHSB() const
 {
-	F64 rPercent = ((F64)red) / 255;
-	F64 gPercent = ((F64)green) / 255;
-	F64 bPercent = ((F64)blue) / 255;
-
-	F64 maxColor = 0.0;
-	if ((rPercent >= gPercent) && (rPercent >= bPercent))
-		maxColor = rPercent;
-	if ((gPercent >= rPercent) && (gPercent >= bPercent))
-		maxColor = gPercent;
-	if ((bPercent >= rPercent) && (bPercent >= gPercent))
-		maxColor = bPercent;
-
-	F64 minColor = 0.0;
-	if ((rPercent <= gPercent) && (rPercent <= bPercent))
-		minColor = rPercent;
-	if ((gPercent <= rPercent) && (gPercent <= bPercent))
-		minColor = gPercent;
-	if ((bPercent <= rPercent) && (bPercent <= gPercent))
-		minColor = bPercent;
-
-	F64 H = 0.0;
-	F64 S = 0.0;
-	F64 B = 0.0;
-
-	B = (maxColor + minColor) / 2.0;
-
-	if (maxColor == minColor)
-	{
-		H = 0.0;
-		S = 0.0;
-	}
-	else
-	{
-		if (B < 0.50)
-		{
-			S = (maxColor - minColor) / (maxColor + minColor);
-		}
-		else
-		{
-			S = (maxColor - minColor) / (2.0 - maxColor - minColor);
-		}
-		if (maxColor == rPercent)
-		{
-			H = (gPercent - bPercent) / (maxColor - minColor);
-		}
-		if (maxColor == gPercent)
-		{
-			H = 2.0 + (bPercent - rPercent) / (maxColor - minColor);
-		}
-		if (maxColor == bPercent)
-		{
-			H = 4.0 + (rPercent - gPercent) / (maxColor - minColor);
-		}
-	}
+   // Normalize RGB values to [0, 1]
+   F64 rPercent = (F64)red / 255.0;
+   F64 gPercent = (F64)green / 255.0;
+   F64 bPercent = (F64)blue / 255.0;
+
+   // Find the max and min values among the normalized RGB values
+   F64 maxColor = mMax(rPercent, mMax(gPercent, bPercent));
+   F64 minColor = mMin(rPercent, mMin(gPercent, bPercent));
+
+   // Initialize H, S, B
+   F64 H = 0.0, S = 0.0, B = maxColor;
+
+   // Compute saturation
+   F64 delta = maxColor - minColor;
+   if (delta > 0.0)
+   {
+      S = delta / maxColor; // Saturation
+
+      // Compute hue
+      if (fabs(maxColor - rPercent) < 1e-6)
+      {
+         H = 60.0 * ((gPercent - bPercent) / delta);
+      }
+      else if (fabs(maxColor - gPercent) < 1e-6)
+      {
+         H = 60.0 * (((bPercent - rPercent) / delta) + 2.0);
+      }
+      else if (fabs(maxColor - bPercent) < 1e-6)
+      {
+         H = 60.0 * (((rPercent - gPercent) / delta) + 4.0);
+      }
+   }
 
-	ColorI::Hsb val;
-	val.sat = (U32)(S * 100);
-	val.brightness = (U32)(B * 100);
-	H = H*60.0;
-	if (H < 0.0)
-		H += 360.0;
-	val.hue = (U32)H;
+   // Prepare the output HSB struct
+   ColorI::Hsb val;
+   val.hue = H;            // Round to nearest integer
+   val.sat = S * 100.0;    // Convert to percentage
+   val.brightness = B * 100.0; // Convert to percentage
 
-	return val;
+   return val;
 }
 
 inline String ColorI::getHex() const

+ 30 - 13
Engine/source/gfx/gfxDrawUtil.cpp

@@ -540,35 +540,35 @@ void GFXDrawUtil::drawRect( const Point2F &upperLeft, const Point2F &lowerRight,
 //-----------------------------------------------------------------------------
 // Draw Rectangle Fill
 //-----------------------------------------------------------------------------
-void GFXDrawUtil::drawRectFill(const RectF& rect, const ColorI& color, const F32& borderSize, const ColorI& borderColor)
+void GFXDrawUtil::drawRectFill(const RectF& rect, const ColorI& color, const F32& borderSize, const ColorI& borderColor, bool gradientFill)
 {
-   drawRoundedRect(0.0f, rect.point, Point2F(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, borderSize, borderColor);
+   drawRoundedRect(0.0f, rect.point, Point2F(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, borderSize, borderColor, gradientFill);
 }
 
-void GFXDrawUtil::drawRectFill(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize, const ColorI& borderColor)
+void GFXDrawUtil::drawRectFill(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize, const ColorI& borderColor, bool gradientFill)
 {
-   drawRoundedRect(0.0f, Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color, borderSize, borderColor);
+   drawRoundedRect(0.0f, Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color, borderSize, borderColor, gradientFill);
 }
 
-void GFXDrawUtil::drawRectFill(const RectI& rect, const ColorI& color, const F32& borderSize, const ColorI& borderColor)
+void GFXDrawUtil::drawRectFill(const RectI& rect, const ColorI& color, const F32& borderSize, const ColorI& borderColor, bool gradientFill)
 {
-   drawRoundedRect(0.0f, rect.point, Point2I(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, borderSize, borderColor);
+   drawRoundedRect(0.0f, rect.point, Point2I(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, borderSize, borderColor, gradientFill);
 }
 
-void GFXDrawUtil::drawRectFill(const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color, const F32& borderSize,const ColorI& borderColor)
+void GFXDrawUtil::drawRectFill(const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color, const F32& borderSize,const ColorI& borderColor, bool gradientFill)
 {
    // draw a rounded rect with 0 radiuse.
-   drawRoundedRect(0.0f, upperLeft, lowerRight, color, borderSize, borderColor);
+   drawRoundedRect(0.0f, upperLeft, lowerRight, color, borderSize, borderColor, gradientFill);
 }
 
-void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius, const RectI& rect, const ColorI& color, const F32& borderSize, const ColorI& borderColor)
+void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius, const RectI& rect, const ColorI& color, const F32& borderSize, const ColorI& borderColor, bool gradientFill)
 {
-   drawRoundedRect(cornerRadius, rect.point, Point2I(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, borderSize, borderColor);
+   drawRoundedRect(cornerRadius, rect.point, Point2I(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, borderSize, borderColor, gradientFill);
 }
 
-void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius, const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize, const ColorI& borderColor)
+void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius, const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize, const ColorI& borderColor, bool gradientFill)
 {
-   drawRoundedRect(cornerRadius, Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color, borderSize, borderColor);
+   drawRoundedRect(cornerRadius, Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color, borderSize, borderColor, gradientFill);
 }
 
 void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius,
@@ -576,7 +576,8 @@ void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius,
    const Point2F& lowerRight,
    const ColorI& color,
    const F32& borderSize,
-   const ColorI& borderColor)
+   const ColorI& borderColor,
+   bool gradientFill)
 {
 
    // NorthWest and NorthEast facing offset vectors
@@ -595,6 +596,14 @@ void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius,
    for (S32 i = 0; i < 4; i++)
       verts[i].color = color;
 
+   if (gradientFill)
+   {
+      verts[0].texCoord.set(0.0f, 0.0f); // top left
+      verts[1].texCoord.set(1.0f, 0.0f); // top right
+      verts[2].texCoord.set(0.0f, 1.0f); // bottom left
+      verts[3].texCoord.set(1.0f, 1.0f); // bottom right
+   }
+
    verts.unlock();
    mDevice->setVertexBuffer(verts);
 
@@ -623,6 +632,14 @@ void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius,
    mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$sizeUni"), size);
    mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$borderSize"), borderSize);
    mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$borderCol"), borderColor);
+   if (gradientFill)
+   {
+      mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$gradientFill"), 1.0f);
+   }
+   else
+   {
+      mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$gradientFill"), 0.0f);
+   }
 
    Point2F rectCenter((F32)(topLeftCorner.x + (size.x / 2.0)), (F32)(topLeftCorner.y + (size.y / 2.0)));
    mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$rectCenter"), rectCenter);

+ 7 - 7
Engine/source/gfx/gfxDrawUtil.h

@@ -57,13 +57,13 @@ public:
    // Draw Rectangles : FILL
    //-----------------------------------------------------------------------------
 
-   void drawRectFill(const Point2F& upperL, const Point2F& lowerR, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0));
-   void drawRectFill(const RectF& rect, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0));
-   void drawRectFill(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0));
-   void drawRectFill(const RectI& rect, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0));
-   void drawRoundedRect(const F32& cornerRadius, const RectI& rect, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0));
-   void drawRoundedRect(const F32& cornerRadius, const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0));
-   void drawRoundedRect(const F32& cornerRadius, const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0));
+   void drawRectFill(const Point2F& upperL, const Point2F& lowerR, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0), bool gradientFill = false);
+   void drawRectFill(const RectF& rect, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0), bool gradientFill = false);
+   void drawRectFill(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0), bool gradientFill = false);
+   void drawRectFill(const RectI& rect, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0), bool gradientFill = false);
+   void drawRoundedRect(const F32& cornerRadius, const RectI& rect, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0), bool gradientFill = false);
+   void drawRoundedRect(const F32& cornerRadius, const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0), bool gradientFill = false);
+   void drawRoundedRect(const F32& cornerRadius, const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0), bool gradientFill = false);
 
    void draw2DSquare(const Point2F& screenPoint, F32 width, F32 spinAngle = 0.0f);
 

+ 479 - 362
Engine/source/gui/controls/guiColorPicker.cpp

@@ -30,25 +30,6 @@
 #include "gfx/primBuilder.h"
 #include "gfx/gfxDrawUtil.h"
 
-/// @name Common colors we use
-/// @{
-LinearColorF colorWhite(1.,1.,1.);
-LinearColorF colorWhiteBlend(1.,1.,1.,.75);
-LinearColorF colorBlack(.0,.0,.0);
-LinearColorF colorAlpha(0.0f, 0.0f, 0.0f, 0.0f);
-LinearColorF colorAlphaW(1.0f, 1.0f, 1.0f, 0.0f);
-
-ColorI GuiColorPickerCtrl::mColorRange[7] = {
-   ColorI(255,0,0),     // Red
-   ColorI(255,0,255),   // Pink
-   ColorI(0,0,255),     // Blue
-   ColorI(0,255,255),   // Light blue
-   ColorI(0,255,0),     // Green
-   ColorI(255,255,0),   // Yellow
-   ColorI(255,0,0),     // Red
-};
-/// @}
-
 IMPLEMENT_CONOBJECT(GuiColorPickerCtrl);
 
 ConsoleDocClass( GuiColorPickerCtrl,
@@ -60,53 +41,49 @@ ConsoleDocClass( GuiColorPickerCtrl,
 GuiColorPickerCtrl::GuiColorPickerCtrl()
 {
    setExtent(140, 30);
-   mDisplayMode = pPallet;
-   mBaseColor = LinearColorF(1.,.0,1.);
-   mPickColor = LinearColorF(.0,.0,.0);
-   mSelectorPos = Point2I(0,0);
+   mDisplayMode = pPalette;
+   mSelectorMode = sHorizontal;
    mMouseDown = mMouseOver = false;
    mActive = true;
-   mPositionChanged = false;
    mSelectorGap = 1;
    mActionOnMove = false;
    mShowReticle = true;
-   mSelectColor = false;
-   mSetColor = mSetColor.BLACK;
-   mBitmap = NULL;
+   mSelectedHue = 0;
+   mSelectedAlpha = 255;
+   mSelectedSaturation = 100;
+   mSelectedBrightness = 100;
 }
 
 GuiColorPickerCtrl::~GuiColorPickerCtrl()
 {
-   if (mBitmap)
-   {
-      delete mBitmap;
-      mBitmap = NULL;
-   }
 }
 
 ImplementEnumType( GuiColorPickMode,
    "\n\n"
    "@ingroup GuiUtil"
    "@internal" )
-   { GuiColorPickerCtrl::pPallet, "Pallete" },
-   { GuiColorPickerCtrl::pHorizColorRange, "HorizColor"},
-   { GuiColorPickerCtrl::pVertColorRange, "VertColor" },
-   { GuiColorPickerCtrl::pHorizColorBrightnessRange, "HorizBrightnessColor" },
-   { GuiColorPickerCtrl::pVertColorBrightnessRange, "VertBrightnessColor" },
-   { GuiColorPickerCtrl::pBlendColorRange, "BlendColor" },
-   { GuiColorPickerCtrl::pHorizAlphaRange, "HorizAlpha" },
-   { GuiColorPickerCtrl::pVertAlphaRange, "VertAlpha" },
+   { GuiColorPickerCtrl::pPalette,            "Pallete" },
+   { GuiColorPickerCtrl::pBlendRange,        "BlendRange" },
+   { GuiColorPickerCtrl::pHueRange,          "HueRange"},
+   { GuiColorPickerCtrl::pAlphaRange,        "AlphaRange" },
    { GuiColorPickerCtrl::pDropperBackground, "Dropper" },
 EndImplementEnumType;
 
+ImplementEnumType(GuiColorSelectorMode,
+   "\n\n"
+   "@ingroup GuiUtil"
+   "@internal")
+{ GuiColorPickerCtrl::sHorizontal,  "Horizontal" },
+{ GuiColorPickerCtrl::sVertical,    "Vertical" },
+EndImplementEnumType;
+
 void GuiColorPickerCtrl::initPersistFields()
 {
    docsURL;
    addGroup("ColorPicker");
-      addField("baseColor", TypeColorF, Offset(mBaseColor, GuiColorPickerCtrl));
-      addField("pickColor", TypeColorF, Offset(mPickColor, GuiColorPickerCtrl));
       addField("selectorGap", TypeS32,  Offset(mSelectorGap, GuiColorPickerCtrl)); 
       addField("displayMode", TYPEID< PickMode >(), Offset(mDisplayMode, GuiColorPickerCtrl) );
+      addField("selectorMode", TYPEID< SelectorMode >(), Offset(mSelectorMode, GuiColorPickerCtrl) );
       addField("actionOnMove", TypeBool,Offset(mActionOnMove, GuiColorPickerCtrl));
       addField("showReticle", TypeBool, Offset(mShowReticle, GuiColorPickerCtrl));
    endGroup("ColorPicker");
@@ -114,248 +91,227 @@ void GuiColorPickerCtrl::initPersistFields()
    Parent::initPersistFields();
 }
 
-// Function to draw a box which can have 4 different colors in each corner blended together
-void GuiColorPickerCtrl::drawBlendBox(RectI &bounds, LinearColorF &c1, LinearColorF &c2, LinearColorF &c3, LinearColorF &c4)
+void GuiColorPickerCtrl::renderBlendRange(RectI& bounds)
+{
+   ColorI currentColor;
+   currentColor.set(ColorI::Hsb(mSelectedHue, 100, 100));
+   GFX->getDrawUtil()->drawRectFill(bounds, currentColor, 0.0f, ColorI(0,0,0,0), true);
+}
+
+void GuiColorPickerCtrl::renderBlendSelector(RectI& bounds)
+{
+   // Determine the relative saturation position within the gradient
+   F32 relPosX = F32(mSelectedSaturation) / 100.0f;
+   // Determine the relative brightness position within the gradient
+   F32 relPosY = 1.0f - F32(mSelectedBrightness) / 100.0f;
+
+   // Calculate the selector position
+   Point2I selectorPos;
+   RectI selectorRect;
+
+   selectorPos.x = bounds.point.x + static_cast<S32>(relPosX * bounds.extent.x);
+   selectorPos.y = bounds.point.y + static_cast<S32>(relPosY * bounds.extent.y);
+   selectorRect.set(Point2I(selectorPos.x - mSelectorGap, selectorPos.y - mSelectorGap), Point2I(mSelectorGap * 2, mSelectorGap * 2));
+
+   ColorI currentColor;
+   currentColor.set(ColorI::Hsb(mSelectedHue, mSelectedSaturation, mSelectedBrightness));
+   GFX->getDrawUtil()->drawRectFill(selectorRect, currentColor, 2.0f, ColorI::WHITE);
+}
+
+void GuiColorPickerCtrl::renderHueGradient(RectI& bounds, U32 numColours)
 {
    GFX->setStateBlock(mStateBlock);
 
+   F32 stepSize = F32(bounds.extent.x) / F32(numColours); // For horizontal mode
+   F32 stepSizeY = F32(bounds.extent.y) / F32(numColours); // For vertical mode
    S32 l = bounds.point.x, r = bounds.point.x + bounds.extent.x;
    S32 t = bounds.point.y, b = bounds.point.y + bounds.extent.y;
 
-   LinearColorF col[4];
-   col[0] = c1;
-   col[1] = c2;
-   col[2] = c3;
-   col[3] = c4;
+   // Begin primitive building, 4 vertices per rectangle
+   PrimBuild::begin(GFXTriangleStrip, numColours * 4);
 
-   //A couple of checks to determine if color blend
-   if (c1 == colorWhite && c3 == colorAlpha && c4 == colorBlack)
+   for (U32 i = 0; i < numColours; i++)
    {
-      //Color
-      PrimBuild::begin(GFXTriangleStrip, 4);
-
-      PrimBuild::color(col[1]);
-      PrimBuild::vertex2i(l, t);
-
-      PrimBuild::color(col[1]);
-      PrimBuild::vertex2i(r, t);
+      U32 currentHue = static_cast<U32>((F32(i) / F32(numColours)) * 360.0f);
+      U32 nextHue = static_cast<U32>((F32(i + 1) / F32(numColours)) * 360.0f);
 
-      PrimBuild::color(col[1]);
-      PrimBuild::vertex2i(l, b);
+      ColorI currentColor, nextColor;
+      currentColor.set(ColorI::Hsb(currentHue, 100, 100));
+      nextColor.set(ColorI::Hsb(nextHue, 100, 100));
 
-      PrimBuild::color(col[1]);
-      PrimBuild::vertex2i(r, b);
-
-      PrimBuild::end();
-
-      //White
-      PrimBuild::begin(GFXTriangleStrip, 4);
+      switch (mSelectorMode)
+      {
+      case GuiColorPickerCtrl::sHorizontal:
+      {
+         // Draw a rectangle for the current segment
+         F32 xStart = l + i * stepSize;
+         F32 xEnd = l + (i + 1) * stepSize;
 
-      PrimBuild::color(col[0]);
-      PrimBuild::vertex2i(l, t);
+         PrimBuild::color(currentColor);
+         PrimBuild::vertex2i(xStart, t); // Top-left
 
-      PrimBuild::color(colorAlphaW);
-      PrimBuild::vertex2i(r, t);
+         PrimBuild::color(nextColor);
+         PrimBuild::vertex2i(xEnd, t); // Top-right
 
-      PrimBuild::color(col[0]);
-      PrimBuild::vertex2i(l, b);
+         PrimBuild::color(currentColor);
+         PrimBuild::vertex2i(xStart, b); // Bottom-left
 
-      PrimBuild::color(colorAlphaW);
-      PrimBuild::vertex2i(r, b);
+         PrimBuild::color(nextColor);
+         PrimBuild::vertex2i(xEnd, b); // Bottom-right
 
-      PrimBuild::end();
+         break;
+      }
+      case GuiColorPickerCtrl::sVertical:
+      {
+         // Draw a rectangle for the current segment
+         F32 yStart = t + i * stepSizeY;
+         F32 yEnd = t + (i + 1) * stepSizeY;
 
-      //Black 
-      PrimBuild::begin(GFXTriangleStrip, 4);
+         PrimBuild::color(currentColor);
+         PrimBuild::vertex2i(l, yStart); // Top-left
 
-      PrimBuild::color(col[2]);
-      PrimBuild::vertex2i(l, t);
-      PrimBuild::color(col[2]);
-      PrimBuild::vertex2i(r, t);
+         PrimBuild::color(currentColor);
+         PrimBuild::vertex2i(r, yStart); // Top-right
 
-      PrimBuild::color(col[3]);
-      PrimBuild::vertex2i(l, b);
+         PrimBuild::color(nextColor);
+         PrimBuild::vertex2i(l, yEnd); // Bottom-left
 
-      PrimBuild::color(col[3]);
-      PrimBuild::vertex2i(r, b);
+         PrimBuild::color(nextColor);
+         PrimBuild::vertex2i(r, yEnd); // Bottom-right
 
-      PrimBuild::end();
+         break;
+      }
+      default:
+         break;
+      }
    }
-   else
-   {
-      PrimBuild::begin(GFXTriangleStrip, 4);
 
-      PrimBuild::color(col[0]);
-      PrimBuild::vertex2i(l, t);
+   PrimBuild::end();
+}
 
-      PrimBuild::color(col[1]);
-      PrimBuild::vertex2i(r, t);
+void GuiColorPickerCtrl::renderHueSelector(RectI& bounds)
+{
+   // Determine the relative position within the gradient
+   F32 relPos = F32(mSelectedHue) / 360.0f;
 
-      PrimBuild::color(col[3]);
-      PrimBuild::vertex2i(l, b);
-	  
-      PrimBuild::color(col[2]);
-      PrimBuild::vertex2i(r, b);
+   // Calculate the selector position
+   Point2I selectorPos;
+   RectI selectorRect;
+   switch (mSelectorMode)
+   {
+   case GuiColorPickerCtrl::sHorizontal:
+      // X is proportional to the hue, Y is centered vertically
+      selectorPos.x = bounds.point.x + static_cast<S32>(relPos * bounds.extent.x);
+      selectorPos.y = bounds.point.y;
+      selectorRect.set(Point2I(selectorPos.x - mSelectorGap, selectorPos.y), Point2I(mSelectorGap * 2, bounds.extent.y));
+      break;
 
-      PrimBuild::end();
+   case GuiColorPickerCtrl::sVertical:
+      // Y is proportional to the hue, X is centered horizontally
+      selectorPos.x = bounds.point.x;
+      selectorPos.y = bounds.point.y + static_cast<S32>(relPos * bounds.extent.y);
+      selectorRect.set(Point2I(selectorPos.x, selectorPos.y - mSelectorGap), Point2I(bounds.extent.x, mSelectorGap * 2));
+      break;
+   default:
+      return; // Invalid mode, don't render selector
    }
+
+   ColorI currentColor;
+   currentColor.set(ColorI::Hsb(mSelectedHue, 100, 100));
+   GFX->getDrawUtil()->drawRectFill(selectorRect, currentColor, 2.0f, ColorI::WHITE);
 }
 
-//--------------------------------------------------------------------------
-/// 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::renderAlphaGradient(RectI& bounds)
 {
-
    GFX->setStateBlock(mStateBlock);
 
-   S32 l = bounds.point.x, r = bounds.point.x + bounds.extent.x + 4;
-   S32 t = bounds.point.y, b = bounds.point.y + bounds.extent.y + 4;
+   // Define the rectangle bounds
+   S32 l = bounds.point.x;
+   S32 r = bounds.point.x + bounds.extent.x;
+   S32 t = bounds.point.y;
+   S32 b = bounds.point.y + bounds.extent.y;
+
+   ColorI currentColor;
+   currentColor.set(ColorI::Hsb(mSelectedHue, 100, 100));
 
-   // Calculate increment value
-   S32 x_inc = int(mFloor((r - l) / F32(numColors - 1)));
-   S32 y_inc = int(mFloor((b - t) / F32(numColors - 1)));
+   ColorI alphaCol = ColorI::BLACK;
+   alphaCol.alpha = 0;
 
-   ColorI *col = new ColorI[numColors];
-   dMemcpy(col, colors, numColors * sizeof(ColorI));
-   for (U16 i = 0; i < numColors - 1; i++)
-         col[i] = colors[i];
+   // Begin primitive building, 4 vertices per rectangle
+   PrimBuild::begin(GFXTriangleStrip,4);
 
-   for (U16 i = 0; i < numColors - 1; i++)
+   switch (mSelectorMode)
    {
-      // This is not efficent, but then again it doesn't really need to be. -pw
-      PrimBuild::begin(GFXTriangleStrip, 4);
+   case GuiColorPickerCtrl::sHorizontal:
+   {
+      PrimBuild::color(alphaCol);
+      PrimBuild::vertex2i(l, t); // Top-left
 
-      if (!vertical)  // Horizontal (+x)
-      {
-         // First color
-         PrimBuild::color(col[i]);
-         PrimBuild::vertex2i(l, t);
-         PrimBuild::color(col[i + 1]);
-         PrimBuild::vertex2i(l + x_inc, t);
-
-         // Second color
-         PrimBuild::color(col[i]);
-         PrimBuild::vertex2i(l, b);
-         PrimBuild::color(col[i + 1]);
-         PrimBuild::vertex2i(l + x_inc, b);
-         l += x_inc;
-      }
-      else  // Vertical (+y)
-      {
-         // First color
-         PrimBuild::color(col[i]);
-         PrimBuild::vertex2i(l, t);
-         PrimBuild::color(col[i + 1]);
-         PrimBuild::vertex2i(l, t + y_inc);
-
-         // Second color
-         PrimBuild::color(col[i]);
-         PrimBuild::vertex2i(r, t);
-         PrimBuild::color(col[i + 1]);
-         PrimBuild::vertex2i(r, t + y_inc);
-         t += y_inc;
-      }
-      PrimBuild::end();
+      PrimBuild::color(currentColor);
+      PrimBuild::vertex2i(r, t); // Top-right
+
+      PrimBuild::color(alphaCol);
+      PrimBuild::vertex2i(l, b); // Bottom-left
+
+      PrimBuild::color(currentColor);
+      PrimBuild::vertex2i(r, b); // Bottom-right
+      break;
    }
+   case GuiColorPickerCtrl::sVertical:
+   {
+      PrimBuild::color(currentColor);
+      PrimBuild::vertex2i(l, t); // Top-left
 
-   SAFE_DELETE_ARRAY(col);
-}
+      PrimBuild::color(currentColor);
+      PrimBuild::vertex2i(r, t); // Top-right
 
-void GuiColorPickerCtrl::drawSelector(RectI &bounds, Point2I &selectorPos, SelectorMode mode)
-{
-   if( !mShowReticle )
-      return; 
+      PrimBuild::color(alphaCol);
+      PrimBuild::vertex2i(l, b); // Bottom-left
 
-   U16 sMax = mSelectorGap*2;
-   const ColorI color = colorWhiteBlend.toColorI();
-   switch (mode)
-   {
-      case sVertical:
-         // Now draw the vertical selector Up -> Pos
-         if (selectorPos.y > bounds.point.y)
-            GFX->getDrawUtil()->drawLine(selectorPos.x, bounds.point.y, selectorPos.x, selectorPos.y-sMax-1, color);
-         // Down -> Pos
-         if (selectorPos.y < bounds.point.y + bounds.extent.y)
-            GFX->getDrawUtil()->drawLine(selectorPos.x,	selectorPos.y + sMax, selectorPos.x, bounds.point.y + bounds.extent.y, color);
+      PrimBuild::color(alphaCol);
+      PrimBuild::vertex2i(r, b); // Bottom-right
       break;
-      case sHorizontal:
-         // Now draw the horizontal selector Left -> Pos
-         if (selectorPos.x > bounds.point.x)
-            GFX->getDrawUtil()->drawLine(bounds.point.x, selectorPos.y-1, selectorPos.x-sMax, selectorPos.y-1, color);
-         // Right -> Pos
-         if (selectorPos.x < bounds.point.x + bounds.extent.x)
-            GFX->getDrawUtil()->drawLine(bounds.point.x+mSelectorPos.x+sMax, selectorPos.y-1, bounds.point.x + bounds.extent.x, selectorPos.y-1, color);
+   }
+   default:
       break;
    }
-}
 
-//--------------------------------------------------------------------------
-/// Function to invoke calls to draw the picker box and selector
-void GuiColorPickerCtrl::renderColorBox(RectI &bounds)
-{
-   RectI pickerBounds;
-   pickerBounds.point.x = bounds.point.x+1;
-   pickerBounds.point.y = bounds.point.y+1;
-   pickerBounds.extent.x = bounds.extent.x-1;
-   pickerBounds.extent.y = bounds.extent.y-1;
+   PrimBuild::end();
 
-   if (mProfile->mBorder)
-      GFX->getDrawUtil()->drawRect(bounds, mProfile->mBorderColor);
+}
 
-   Point2I selectorPos = Point2I(bounds.point.x+mSelectorPos.x+1, bounds.point.y+mSelectorPos.y+1);
+void GuiColorPickerCtrl::renderAlphaSelector(RectI& bounds)
+{
+   // Determine the relative position within the gradient
+   F32 relPos = F32(mSelectedAlpha) / 255.0f;
 
-   // Draw color box differently depending on mode
-   RectI blendRect;
-   switch (mDisplayMode)
+   // Calculate the selector position
+   Point2I selectorPos;
+   RectI selectorRect;
+   switch (mSelectorMode)
    {
-   case pHorizColorRange:
-      drawBlendRangeBox( pickerBounds, false, 7, mColorRange);
-      drawSelector( pickerBounds, selectorPos, sVertical );
-   break;
-   case pVertColorRange:
-      drawBlendRangeBox( pickerBounds, true, 7, mColorRange);
-      drawSelector( pickerBounds, selectorPos, sHorizontal );
-   break;
-   case pHorizColorBrightnessRange:
-      blendRect = pickerBounds;
-      blendRect.point.y++;
-      blendRect.extent.y -= 2;
-      drawBlendRangeBox( pickerBounds, false, 7, mColorRange);
-      // This is being drawn slightly offset from the larger rect so as to insure 255 and 0
-      // can both be selected for every color.
-      drawBlendBox( blendRect, colorAlpha, colorAlpha, colorBlack, colorBlack );
-      blendRect.point.y += blendRect.extent.y - 1;
-      blendRect.extent.y = 2;
-      GFX->getDrawUtil()->drawRect( blendRect, colorBlack.toColorI());
-      drawSelector( pickerBounds, selectorPos, sHorizontal );
-      drawSelector( pickerBounds, selectorPos, sVertical );
-   break;
-   case pVertColorBrightnessRange:
-      drawBlendRangeBox( pickerBounds, true, 7, mColorRange);
-      drawBlendBox( pickerBounds, colorAlpha, colorBlack, colorBlack, colorAlpha );
-      drawSelector( pickerBounds, selectorPos, sHorizontal );
-      drawSelector( pickerBounds, selectorPos, sVertical );
-   break;
-   case pHorizAlphaRange:
-      drawBlendBox( pickerBounds, colorBlack, colorWhite, colorWhite, colorBlack );
-      drawSelector( pickerBounds, selectorPos, sVertical );
-   break;
-   case pVertAlphaRange:
-      drawBlendBox( pickerBounds, colorBlack, colorBlack, colorWhite, colorWhite );
-      drawSelector( pickerBounds, selectorPos, sHorizontal ); 
-   break;
-   case pBlendColorRange:
-      drawBlendBox( pickerBounds, colorWhite, mBaseColor, colorAlpha, colorBlack );
-      drawSelector( pickerBounds, selectorPos, sHorizontal );      
-      drawSelector( pickerBounds, selectorPos, sVertical );
-   break;
-   case pDropperBackground:
-   break;
-   case pPallet:
+   case GuiColorPickerCtrl::sHorizontal:
+      // X is proportional to the hue, Y is centered vertically
+      selectorPos.x = bounds.point.x + static_cast<S32>(relPos * bounds.extent.x);
+      selectorPos.y = bounds.point.y;
+      selectorRect.set(Point2I(selectorPos.x - mSelectorGap, selectorPos.y), Point2I(mSelectorGap * 2, bounds.extent.y));
+      break;
+
+   case GuiColorPickerCtrl::sVertical:
+      // Y is proportional to the hue, X is centered horizontally
+      selectorPos.x = bounds.point.x;
+      selectorPos.y = bounds.point.y + static_cast<S32>(relPos * bounds.extent.y);
+      selectorRect.set(Point2I(selectorPos.x, selectorPos.y - mSelectorGap), Point2I(bounds.extent.x, mSelectorGap * 2));
+      break;
    default:
-      GFX->getDrawUtil()->drawRectFill( pickerBounds, mBaseColor.toColorI());
-   break;
+      return; // Invalid mode, don't render selector
    }
+
+   ColorI currentColor;
+   currentColor.set(ColorI::Hsb(mSelectedHue, 100, 100));
+   currentColor.alpha = mSelectedAlpha;
+
+   GFX->getDrawUtil()->drawRectFill(selectorRect, currentColor, 2.0f, ColorI::WHITE);
 }
 
 void GuiColorPickerCtrl::onRender(Point2I offset, const RectI& updateRect)
@@ -371,87 +327,41 @@ void GuiColorPickerCtrl::onRender(Point2I offset, const RectI& updateRect)
    }
 
    RectI boundsRect(offset, getExtent());
-   renderColorBox(boundsRect);
 
-   if (mPositionChanged || mBitmap == NULL)
+   switch (mDisplayMode)
    {
-      bool nullBitmap = false;
-
-      if (mPositionChanged == false && mBitmap == NULL)
-         nullBitmap = true;
-
-      mPositionChanged = false;
-      Point2I extent = getRoot()->getExtent();
-
-      // If we are anything but a pallete, change the pick color
-      if (mDisplayMode != pPallet)
-      {
-         Point2I resolution = getRoot()->getExtent();
-
-         U32 buf_x = offset.x + mSelectorPos.x;
-         U32 buf_y = resolution.y - (extent.y - (offset.y + mSelectorPos.y));
-
-         GFXTexHandle bb(resolution.x, resolution.y, GFXFormatR8G8B8A8_SRGB, &GFXRenderTargetSRGBProfile, avar("%s() - bb (line %d)", __FUNCTION__, __LINE__));
-
-         GFXTarget *targ = GFX->getActiveRenderTarget();
-         targ->resolveTo(bb);
-
-         if (mBitmap)
-         {
-            delete mBitmap;
-            mBitmap = NULL;
-         }
-
-         mBitmap = new GBitmap(bb.getWidth(), bb.getHeight(),false,GFXFormatR8G8B8A8);
-
-         bb.copyToBmp(mBitmap);
-
-         if (!nullBitmap)
-         {
-            if (mSelectColor)
-            {
-               Point2I pos = findColor(mSetColor, offset, resolution, *mBitmap);
-               mSetColor = mSetColor.BLACK;
-               mSelectColor = false;
-               setSelectorPos(pos);
-            }
-            else
-            {
-               ColorI tmp;
-               mBitmap->getColor(buf_x, buf_y, tmp);
-
-               mPickColor = (LinearColorF)tmp;
-
-               // Now do onAction() if we are allowed
-               if (mActionOnMove)
-                  onAction();
-            }
-         }
-      }
+   case GuiColorPickerCtrl::pPalette:
+   {
+      ColorI currentColor;
+      currentColor.set(ColorI::Hsb(mSelectedHue, mSelectedSaturation, mSelectedBrightness));
+      currentColor.alpha = mSelectedAlpha;
+      GFX->getDrawUtil()->drawRectFill(boundsRect, currentColor);
+      break;
    }
-
-   //render the children
-   renderChildControls(offset, updateRect);
-}
-
-void GuiColorPickerCtrl::setSelectorPos(const LinearColorF & color)
-{
-   if (mBitmap && !mPositionChanged)
+   case GuiColorPickerCtrl::pBlendRange:
    {
-      Point2I resolution = getRoot() ? getRoot()->getExtent() : Point2I(1024, 768);
-      RectI rect(getGlobalBounds());
-      Point2I pos = findColor(color, rect.point, resolution, *mBitmap);
-      mSetColor = mSetColor.BLACK;
-      mSelectColor = false;
-
-      setSelectorPos(pos);
+      renderBlendRange(boundsRect);
+      renderBlendSelector(boundsRect);
+      break;
    }
-   else
+   case GuiColorPickerCtrl::pHueRange:
+   {
+      renderHueGradient(boundsRect, 7);
+      if(mShowReticle) renderHueSelector(boundsRect);
+      break;
+   }
+   case GuiColorPickerCtrl::pAlphaRange:
    {
-      mSetColor = color;
-      mSelectColor = true;
-      mPositionChanged = true;
+      renderAlphaGradient(boundsRect);
+      if (mShowReticle) renderAlphaSelector(boundsRect);
+      break;
+   }
+   default:
+      break;
    }
+
+   //render the children
+   renderChildControls(offset, updateRect);
 }
 
 Point2I GuiColorPickerCtrl::findColor(const LinearColorF & color, const Point2I& offset, const Point2I& resolution, GBitmap& bmp)
@@ -516,57 +426,154 @@ Point2I GuiColorPickerCtrl::findColor(const LinearColorF & color, const Point2I&
    return closestPos;
 }
 
-void GuiColorPickerCtrl::setSelectorPos(const Point2I &pos)
-{
-   Point2I ext = getExtent();
-   mSelectorPos.x = mClamp(pos.x, 1, ext.x - 1);
-   mSelectorPos.y = mClamp(pos.y, 1, ext.y - 1);
-   mPositionChanged = true;
-   setUpdate();
-}
-
 void GuiColorPickerCtrl::onMouseDown(const GuiEvent &event)
 {
    if (!mActive)
       return;
    
-   if (mDisplayMode == pDropperBackground)
-      return;
-
    mouseLock(this);
    
    if (mProfile->mCanKeyFocus)
       setFirstResponder();
 
-   if (mActive && (mDisplayMode != pDropperBackground))
-      onAction();
+   Point2I ext = getExtent();
+   Point2I mousePoint = globalToLocalCoord(event.mousePoint);
+   mMouseDown = true;
 
-   // Update the picker cross position
-   if (mDisplayMode != pPallet)
-      setSelectorPos(globalToLocalCoord(event.mousePoint));
+   switch (mDisplayMode)
+   {
+   case GuiColorPickerCtrl::pPalette:
+      return;
+   case GuiColorPickerCtrl::pBlendRange:
+   {
+      F32 relX = F32(mousePoint.x) / F32(ext.x);
+      F32 relY = 1.0f - F32(mousePoint.y) / F32(ext.y);
+      setSelectedSaturation(relX * 100.0);
+      setSelectedBrightness(relY * 100.0);
+      break;
+   }
+   case GuiColorPickerCtrl::pHueRange:
+   {
+      switch (mSelectorMode)
+      {
+      case GuiColorPickerCtrl::sHorizontal:
+      {
+         F32 relX = F32(mousePoint.x) / F32(ext.x);
+         setSelectedHue(relX * 360.0);
+         break;
+      }
+      case GuiColorPickerCtrl::sVertical:
+      {
+         F32 relY = F32(mousePoint.y) / F32(ext.y);
+         setSelectedHue(relY * 360.0);
+         break;
+      }
+      default:
+         break;
+      }
+      break;
+   }
+   case GuiColorPickerCtrl::pAlphaRange:
+   {
+      switch (mSelectorMode)
+      {
+      case GuiColorPickerCtrl::sHorizontal:
+      {
+         F32 relX = F32(mousePoint.x) / F32(ext.x);
+         setSelectedAlpha(relX * 255.0);
+         break;
+      }
+      case GuiColorPickerCtrl::sVertical:
+      {
+         F32 relY = F32(mousePoint.y) / F32(ext.y);
+         setSelectedAlpha(relY * 255.0);
+         break;
+      }
+      default:
+         break;
+      }
+      break;
+   }
+   default:
+      break;
+   }
 
-   mMouseDown = true;
+   if (mActive)
+      onAction();
 }
 
 //--------------------------------------------------------------------------
 void GuiColorPickerCtrl::onMouseDragged(const GuiEvent &event)
 {
-   if ((mActive && mMouseDown) || (mActive && (mDisplayMode == pDropperBackground)))
+   if ((mActive && mMouseDown))
    {
-      // Update the picker cross position
-      if (mDisplayMode != pPallet)
-         setSelectorPos(globalToLocalCoord(event.mousePoint));
-   }
+      Point2I ext = getExtent();
+      Point2I mousePoint = globalToLocalCoord(event.mousePoint);
+
+      switch (mDisplayMode)
+      {
+      case GuiColorPickerCtrl::pPalette:
+         return;
+      case GuiColorPickerCtrl::pBlendRange:
+      {
+         F32 relX = F32(mousePoint.x) / F32(ext.x);
+         F32 relY = 1.0f - F32(mousePoint.y) / F32(ext.y);
+         setSelectedSaturation(relX * 100.0);
+         setSelectedBrightness(relY * 100.0);
+         break;
+      }
+      case GuiColorPickerCtrl::pHueRange:
+      {
+         switch (mSelectorMode)
+         {
+         case GuiColorPickerCtrl::sHorizontal:
+         {
+            F32 relX = F32(mousePoint.x) / F32(ext.x);
+            setSelectedHue(relX * 360.0);
+            break;
+         }
+         case GuiColorPickerCtrl::sVertical:
+         {
+            F32 relY = F32(mousePoint.y) / F32(ext.y);
+            setSelectedHue(relY * 360.0);
+            break;
+         }
+         default:
+            break;
+         }
+         break;
+      }
+      case GuiColorPickerCtrl::pAlphaRange:
+      {
+         switch (mSelectorMode)
+         {
+         case GuiColorPickerCtrl::sHorizontal:
+         {
+            F32 relX = F32(mousePoint.x) / F32(ext.x);
+            setSelectedAlpha(relX * 255.0);
+            break;
+         }
+         case GuiColorPickerCtrl::sVertical:
+         {
+            F32 relY = F32(mousePoint.y) / F32(ext.y);
+            setSelectedAlpha(relY * 255.0);
+            break;
+         }
+         default:
+            break;
+         }
+         break;
+      }
+      default:
+         break;
+      }
 
-   if( !mActionOnMove )
-      execAltConsoleCallback();
+      onAction();
+   }
 }
 
 void GuiColorPickerCtrl::onMouseMove(const GuiEvent &event)
 {
-   // Only for dropper mode
-   if (mActive && (mDisplayMode == pDropperBackground))
-      setSelectorPos(globalToLocalCoord(event.mousePoint));
 }
 
 void GuiColorPickerCtrl::onMouseEnter(const GuiEvent &event)
@@ -580,54 +587,164 @@ void GuiColorPickerCtrl::onMouseLeave(const GuiEvent &)
    mMouseOver = false;
 }
 
-void GuiColorPickerCtrl::onMouseUp(const GuiEvent &)
+void GuiColorPickerCtrl::setSelectedHue(const F64& hueValue)
 {
-   //if we released the mouse within this control, perform the action
-   if (mActive && mMouseDown && (mDisplayMode != pDropperBackground))
-      mMouseDown = false;
+   if (hueValue < 0)
+   {
+      mSelectedHue = 0;
+      return;
+   }
 
-   if (mActive && (mDisplayMode == pDropperBackground))
+   if (hueValue > 360)
    {
-      // In a dropper, the alt command executes the mouse up action (to signal stopping)
-      execAltConsoleCallback();
+      mSelectedHue = 360;
+      return;
    }
 
+   mSelectedHue = hueValue;
+   
+}
+
+void GuiColorPickerCtrl::setSelectedBrightness(const F64& brightValue)
+{
+   if (brightValue < 0)
+   {
+      mSelectedBrightness = 0;
+      return;
+   }
+
+   if (brightValue > 100)
+   {
+      mSelectedBrightness = 100;
+      return;
+   }
+
+   mSelectedBrightness = brightValue;
+}
+
+void GuiColorPickerCtrl::setSelectedSaturation(const F64& satValue)
+{
+   if (satValue < 0)
+   {
+      mSelectedSaturation = 0;
+      return;
+   }
+
+   if (satValue > 100)
+   {
+      mSelectedSaturation = 100;
+      return;
+   }
+
+   mSelectedSaturation = satValue;
+}
+
+void GuiColorPickerCtrl::setSelectedAlpha(const F64& alphaValue)
+{
+   if (alphaValue < 0)
+   {
+      mSelectedAlpha = 0;
+      return;
+   }
+
+   if (alphaValue > 255)
+   {
+      mSelectedAlpha = 255;
+      return;
+   }
+
+   mSelectedAlpha = alphaValue;
+}
+
+void GuiColorPickerCtrl::onMouseUp(const GuiEvent &)
+{
+   //if we released the mouse within this control, perform the action
+   if (mActive && mMouseDown)
+      mMouseDown = false;
+
    mouseUnlock();
 }
 
-const char *GuiColorPickerCtrl::getScriptValue()
+/// <summary>
+/// This command is to be used by Palette only as it updates everything else across the colour picker gui.
+/// </summary>
+DefineEngineMethod(GuiColorPickerCtrl, executeUpdate, void, (), , "Execute the onAction command.")
+{
+   object->onAction();
+}
+
+DefineEngineMethod(GuiColorPickerCtrl, setSelectedHue, void, (F64 hueValue), , "Sets the selected hue value should be 0-360.")
+{
+   object->setSelectedHue(hueValue);
+}
+
+DefineEngineMethod(GuiColorPickerCtrl, getSelectedHue, F64, (), , "Gets the current selected hue value.")
+{
+   return object->getSelectedHue();
+}
+
+DefineEngineMethod(GuiColorPickerCtrl, setSelectedBrightness, void, (F64 brightness), , "Sets the selected brightness value should be 0-100.")
+{
+   object->setSelectedBrightness(brightness);
+}
+
+DefineEngineMethod(GuiColorPickerCtrl, getSelectedBrightness, F64, (), , "Gets the current selected brightness.")
+{
+   return object->getSelectedBrightness();
+}
+
+DefineEngineMethod(GuiColorPickerCtrl, setSelectedSaturation, void, (F64 saturation), , "Sets the selected saturation value should be 0-100.")
 {
-   static char temp[256];
-   LinearColorF color = getValue();
-   dSprintf( temp, 256, "%f %f %f %f", color.red, color.green, color.blue, color.alpha );
-   return temp;
+   object->setSelectedSaturation(saturation);
 }
 
-void GuiColorPickerCtrl::setScriptValue(const char *value)
+DefineEngineMethod(GuiColorPickerCtrl, getSelectedSaturation, F64, (), , "Gets the current selected saturation value.")
 {
-   LinearColorF newValue;
-   dSscanf(value, "%f %f %f %f", &newValue.red, &newValue.green, &newValue.blue, &newValue.alpha);
-   setValue(newValue);
+   return object->getSelectedSaturation();
 }
 
-DefineEngineMethod(GuiColorPickerCtrl, getSelectorPos, Point2I, (), , "Gets the current position of the selector")
+DefineEngineMethod(GuiColorPickerCtrl, setSelectedAlpha, void, (F64 alpha), , "Sets the selected alpha value should be 0-255.")
 {
-   return object->getSelectorPos();
+   object->setSelectedAlpha(alpha);
 }
 
-DefineEngineMethod(GuiColorPickerCtrl, setSelectorPos, void, (Point2I newPos), , "Sets the current position of the selector")
+DefineEngineMethod(GuiColorPickerCtrl, getSelectedAlpha, F64, (), , "Gets the current selected alpha value.")
 {
-   object->setSelectorPos(newPos);
+   return object->getSelectedAlpha();
 }
 
-DefineEngineMethod(GuiColorPickerCtrl, updateColor, void, (), , "Forces update of pick color")
+DefineEngineMethod(GuiColorPickerCtrl, setSelectedColorI, void, (ColorI col), , "Sets the current selected hsb from a colorI value.")
 {
-   object->updateColor();
+   ColorI::Hsb hsb(col.getHSB());
+   object->setSelectedHue(hsb.hue);
+   object->setSelectedSaturation(hsb.sat);
+   object->setSelectedBrightness(hsb.brightness);
+   object->setSelectedAlpha(col.alpha);
 }
 
-DefineEngineMethod(GuiColorPickerCtrl, setSelectorColor, void, (LinearColorF color), ,
-   "Sets the current position of the selector based on a color.n"
-   "@param color Color to look for.n")
+DefineEngineMethod(GuiColorPickerCtrl, getSelectedColorI, ColorI, (), , "Gets the current selected hsb as a colorI value.")
+{
+   ColorI col;
+   col.set(ColorI::Hsb(object->getSelectedHue(), object->getSelectedSaturation(), object->getSelectedBrightness()));
+   col.alpha = object->getSelectedAlpha();
+   return col;
+}
+
+DefineEngineMethod(GuiColorPickerCtrl, setSelectedLinearColor, void, (LinearColorF colF), , "Sets the current selected hsb froma a LinearColorF value.")
+{
+   ColorI col = colF.toColorI();
+   ColorI::Hsb hsb(col.getHSB());
+   object->setSelectedHue(hsb.hue);
+   object->setSelectedSaturation(hsb.sat);
+   object->setSelectedBrightness(hsb.brightness);
+   object->setSelectedAlpha(col.alpha);
+}
+
+
+DefineEngineMethod(GuiColorPickerCtrl, getSelectedLinearColor, LinearColorF, (), , "Gets the current selected hsb as a LinearColorF value.")
 {
-   object->setSelectorPos(color);
+   ColorI col;
+   col.set(ColorI::Hsb(object->getSelectedHue(), object->getSelectedSaturation(), object->getSelectedBrightness()));
+   col.alpha = object->getSelectedAlpha();
+   return LinearColorF(col);
 }

+ 88 - 54
Engine/source/gui/controls/guiColorPicker.h

@@ -32,25 +32,22 @@
 /// This control draws a box containing a color specified by mPickColor, 
 /// in a way according to one of the PickMode enum's, stored as mDisplayMode.
 /// 
-/// The color the box represents is stored as mBaseColour (for pPallete, pBlendColorRange), 
+/// The color the box represents is stored as mBaseColour (for pPalette, pBlendColorRange), 
 /// whilst the color chosen by the box is stored as mPickColor.
 ///
 /// Whenever the control is clicked, it will do one of many things :
 ///
-/// -# If its in pPallete mode, execute the regular "command"
-/// -# If its in pBlendColorRange mode, update the selector position. The position will be re-read upon the next render. In addition, a cross will be drawn where the color has been selected from. As with 1, "command" will be executed.
-/// -# If its in pHorizColorRange or pVertColorRange mode, it will function in a similar manner to 2, but the selector will resemble a horizontal or vertical bar.
-/// -# If its in pHorizAlphaRange or pVertAlphaRange mode, it will also function the same way as 3
+/// -# If its in pPalette mode, execute the regular "command"
+/// -# If its in pBlendRange mode, update the selector position. The position will be re-read upon the next render. In addition, a cross will be drawn where the color has been selected from. As with 1, "command" will be executed.
+/// -# If its in pHueRange or pAlphaRange mode, it will function in a similar manner to 2, but the selector will resemble a horizontal or vertical bar.
+/// -# If its in pAlphaRange mode, it will also function the same way as 3
 /// -# If its in pDropperBackground mode, nothing will happen
 ///
 /// Colours are drawn in different ways according to mDisplayMode:
 ///
-/// -# With pPallete, a box with a blank color, mBaseColor is drawn.
-/// -# With pHorizColorRange, a horizontal box with colors blending in the range, mColorRange.
-/// -# With pVertColorRange, a vertical box with colors blending in the range, mColorRange.
-/// -# With pBlendColorRange, a box, the bottom colors being black, but the top left being white, and the top right being mBaseColor.
-/// -# With pHorizAlphaRange, a horizontal box with black blending with an alpha from 0 to 255
-/// -# With pVertAlphaRange, a vertical box with black blending with an apha from 0 to 255
+/// -# With pPalette, a box with a blank color, mBaseColor is drawn.
+/// -# With pHueRange, a box containing the hue range 0-360.
+/// -# With pAlphaRange, a box containing the alpha range 0-255.
 /// -# With pDropperBackground, nothing is drawn
 class GuiColorPickerCtrl : public GuiControl
 {
@@ -59,14 +56,10 @@ class GuiColorPickerCtrl : public GuiControl
   public:
    enum PickMode
    {
-     pPallet = 0,                ///< We just have a solid color; We just act like a pallet 
-     pHorizColorRange,           ///< We have a range of base colors going horizontally
-     pVertColorRange,            ///< We have a range of base colors going vertically
-     pHorizColorBrightnessRange, ///< HorizColorRange with brightness
-     pVertColorBrightnessRange,  ///< VertColorRange with brightness
-     pBlendColorRange,           ///< We have a box which shows a range in brightness of the color
-     pHorizAlphaRange,           ///< We have a box which shows a range in alpha going horizontally
-     pVertAlphaRange,            ///< We have a box which shows a range in alpha going vertically
+     pPalette = 0,                ///< We just have a solid color; We just act like a pallet
+     pBlendRange,                ///< The full range of brightness and saturation.
+     pHueRange,                  ///< The full hue range 0-360.
+     pAlphaRange,                ///< The full alpha range 0-255.
      pDropperBackground          ///< The control does not draw anything; Only does something when you click, or move the mouse (when active)
    };
    
@@ -77,37 +70,63 @@ class GuiColorPickerCtrl : public GuiControl
    };
 
   protected:
-   /// @name Core Rendering functions
-   /// @{
-   void renderColorBox(RectI &bounds); ///< Function that draws the actual color box
-   void drawSelector(RectI &bounds, Point2I &selectorPos, SelectorMode mode); /// < Function that draws the selection indicator
-   void drawBlendBox(RectI &bounds, LinearColorF &c1, LinearColorF &c2, LinearColorF &c3, LinearColorF &c4);
-   void drawBlendRangeBox(RectI &bounds, bool vertical, U8 numColors, ColorI *colors);
-   /// @}
+
+   /// <summary>
+   /// Render the hue gradient for pBlendRange mode.
+   /// </summary>
+   /// <param name="bounds">The bounds of the ctrl.</param>
+   void renderBlendRange(RectI& bounds);
+
+   /// <summary>
+   /// Render the selector for pBlendRange mode.
+   /// </summary>
+   /// <param name="bounds">The bounds of the ctrl.</param>
+   void renderBlendSelector(RectI& bounds);
+
+   /// <summary>
+   /// Render the hue gradient for pHueRange mode.
+   /// </summary>
+   /// <param name="bounds">The bounds of the ctrl.</param>
+   /// <param name="numColours">The number of splits in the gradient. 7 as default.</param>
+   void renderHueGradient(RectI& bounds, U32 numColours);
+
+   /// <summary>
+   /// Render the selector for pHueRange mode.
+   /// </summary>
+   /// <param name="bounds">The bounds of the ctrl.</param>
+   void renderHueSelector(RectI& bounds);
+
+   /// <summary>
+   /// Render the alpha gradient for pAlphaRange mode.
+   /// </summary>
+   /// <param name="bounds">The bounds of the ctrl.</param>
+   void renderAlphaGradient(RectI& bounds);
+
+   /// <summary>
+   /// Render the selector for pAlphaRange mode.
+   /// </summary>
+   /// <param name="bounds">The bounds of the ctrl.</param>
+   void renderAlphaSelector(RectI& bounds);
 
    /// @name Core Variables
    /// @{
-   LinearColorF mPickColor;		///< Color that has been picked from control
-   LinearColorF mBaseColor;		///< Colour we display (in case of pallet and blend mode)
    PickMode mDisplayMode;	///< Current color display mode of the selector
-   
-   Point2I mSelectorPos;	///< Current position of the selector
-   bool mPositionChanged;	///< Current position has changed since last render?
+   SelectorMode mSelectorMode;	///< Current color display mode of the selector
+   F64 mSelectedHue;
+   F64 mSelectedSaturation;
+   F64 mSelectedBrightness;
+   F64 mSelectedAlpha;
+
    bool mMouseOver;		///< Mouse is over?
    bool mMouseDown;		///< Mouse button down?
    bool mActionOnMove;		///< Perform onAction() when position has changed?
-
-   bool mSelectColor;
-   LinearColorF mSetColor;
-   GBitmap* mBitmap;
+   bool mShowReticle;       ///< Show reticle on render
 
    Point2I findColor(const LinearColorF & color, const Point2I& offset, const Point2I& resolution, GBitmap& bmp);
    
    S32   mSelectorGap;		///< The half-way "gap" between the selector pos and where the selector is allowed to draw. 
 
    GFXStateBlockRef mStateBlock;
-
-   static ColorI mColorRange[7]; ///< Color range for pHorizColorRange and pVertColorRange
    /// @}
 
   public:
@@ -120,23 +139,7 @@ class GuiColorPickerCtrl : public GuiControl
 
    static void initPersistFields();
    void onRender(Point2I offset, const RectI &updateRect) override;
-   bool mShowReticle;       ///< Show reticle on render
-   /// @name Color Value Functions
-   /// @{
-   /// NOTE: setValue only sets baseColor, since setting pickColor wouldn't be useful
-   void setValue(LinearColorF &value) {mBaseColor = value;}
-   /// NOTE: getValue() returns baseColor if pallet (since pallet controls can't "pick" colours themselves)
-   LinearColorF getValue() { return mDisplayMode == pPallet ? mBaseColor : mPickColor; }
-   const char *getScriptValue() override;
-   void setScriptValue(const char *value) override;
-   void updateColor() {mPositionChanged = true;}
-   /// @}
-
-   /// @name Selector Functions
-   /// @{
-   void setSelectorPos(const Point2I &pos); ///< Set new pos (in local coords)
-   void setSelectorPos(const LinearColorF & color);
-   Point2I getSelectorPos() {return mSelectorPos;}
+   
    /// @}
 
    /// @name Input Events
@@ -149,9 +152,40 @@ class GuiColorPickerCtrl : public GuiControl
    void onMouseEnter(const GuiEvent &) override;
    void onMouseLeave(const GuiEvent &) override;
    /// @}
+
+   // script getters and setters
+   /// <summary>
+   /// Set the selected hue.
+   /// </summary>
+   /// <param name="hueValue">Hue value, 0 - 360.</param>
+   void setSelectedHue(const F64& hueValue);
+   F64 getSelectedHue() { return mSelectedHue; }
+
+   /// <summary>
+   /// Set the selected brightness.
+   /// </summary>
+   /// <param name="brightValue">Brightness value, 0 - 100.</param>
+   void setSelectedBrightness(const F64& brightValue);
+   F64 getSelectedBrightness() { return mSelectedBrightness; }
+
+   /// <summary>
+   /// Set the selected saturation.
+   /// </summary>
+   /// <param name="satValue">Saturation value, 0 - 100.</param>
+   void setSelectedSaturation(const F64& satValue);
+   F64 getSelectedSaturation() { return mSelectedSaturation; }
+
+   /// <summary>
+   /// Set the selected alpha.
+   /// </summary>
+   /// <param name="alphaValue">Alpha value, 0 - 255.</param>
+   void setSelectedAlpha(const F64& alphaValue);
+   F64 getSelectedAlpha() { return mSelectedAlpha; }
 };
 
 typedef GuiColorPickerCtrl::PickMode GuiColorPickMode;
+typedef GuiColorPickerCtrl::SelectorMode GuiColorSelectorMode;
 DefineEnumType( GuiColorPickMode );
+DefineEnumType(GuiColorSelectorMode);
 
 #endif

+ 2 - 2
Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.tscript

@@ -156,10 +156,10 @@ singleton ShaderData( CubemapSaveShader )
 //-----------------------------------------------------------------------------
 singleton ShaderData( RoundedRectangleGUI )
 {
-   DXVertexShaderFile   = $Core::CommonShaderPath @ "/fixedFunction/colorV.hlsl";
+   DXVertexShaderFile   = $Core::CommonShaderPath @ "/fixedFunction/addColorTextureV.hlsl";
    DXPixelShaderFile    = $Core::CommonShaderPath @ "/fixedFunction/roundedRectangleP.hlsl";
 
-   OGLVertexShaderFile  = $Core::CommonShaderPath @ "/fixedFunction/gl/colorV.glsl";
+   OGLVertexShaderFile  = $Core::CommonShaderPath @ "/fixedFunction/gl/addColorTextureV.glsl";
    OGLPixelShaderFile   = $Core::CommonShaderPath @ "/fixedFunction/gl/roundedRectangleP.glsl";
       
    pixVersion = 3.0;   

+ 20 - 18
Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/roundedRectangleP.glsl

@@ -20,6 +20,7 @@
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 in vec4 color;
+in vec2 texCoord;
 
 out vec4 OUT_col;
 
@@ -29,6 +30,7 @@ uniform vec2 oneOverViewport;
 uniform float radius;
 uniform float borderSize;
 uniform vec4 borderCol;
+uniform float gradientFill;
 
 float RoundedRectSDF(vec2 p, vec2 size, float radius)
 {
@@ -57,13 +59,19 @@ void main()
 
     float cornerRadius = radius;
 
-    // if ((p.y < 0.0 && p.x < 0.0) || // top left corner
-    //     (p.y < 0.0 && p.x > 0.0) || // top right corner
-    //     (p.y > 0.0 && p.x > 0.0) || // bottom right corner.  
-    //     (p.y > 0.0 && p.x < 0.0))  // bottom left corner
-    // {
-    //     cornerRadius = radius;   
-    // } 
+    vec4 baseColor = color;
+
+    if(gradientFill > 0.5f)
+    {
+        float blendX = (1.0 - texCoord.x);
+        float blendY = texCoord.y;
+        float gamma = 2.4;
+        blendX = pow(abs(blendX), gamma);
+        blendY = pow(abs(blendY), 1/gamma);
+        
+        vec4 interpolatedColor = mix(mix(baseColor,vec4(1.0f, 1.0f, 1.0f, 1.0f), blendX),vec4(0.0f, 0.0f, 0.0f, 1.0f), blendY);
+        baseColor = interpolatedColor; 
+    }
 
     if(cornerRadius > 0.0 || halfBorder > 0.0)
     {
@@ -73,26 +81,20 @@ void main()
         {
             if(sdf < 0.0)
             {
-                // if ((p.y >= -halfSize.y - radius + halfBorder && p.y <= -halfSize.y + radius - halfBorder)  ||  // top border
-                //     (p.y >= halfSize.y - radius + halfBorder && p.y <= halfSize.y + radius - halfBorder)    ||  // bottom border
-                //     (p.x >= -halfSize.x - radius + halfBorder && p.x <= -halfSize.x + radius - halfBorder)  ||  // left border
-                //     (p.x >= halfSize.x - radius + halfBorder && p.x <= halfSize.x + radius - halfBorder) ) {    // right border
-                    
-                // }
-                toColor = color;
-                sdf = abs(sdf) / borderSize;
+                toColor = baseColor;
+                sdf = abs(sdf) - borderSize;
             } 
             
         } 
         else{
-            fromColor = color; 
+            fromColor = baseColor; 
         }  
 
         float alpha = smoothstep(-1.0, 1.0, sdf); 
-        OUT_col = mix(fromColor, toColor, alpha);
+        OUT_col = mix(fromColor, baseColor, alpha);
     }
     else
     {
-        OUT_col = color;
+        OUT_col = baseColor; 
     }
 }

+ 20 - 17
Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl

@@ -26,14 +26,17 @@ struct Conn
 {
    float4 HPOS             : TORQUE_POSITION;
    float4 color            : COLOR;
+   float2 texCoord         : TEXCOORD0;
 };
 
+
 uniform float2 sizeUni;
 uniform float2 rectCenter;
 uniform float2 oneOverViewport;
 uniform float radius;
 uniform float borderSize;
 uniform float4 borderCol;
+uniform float gradientFill;
 
 float RoundedRectSDF(float2 p, float2 size, float radius)
 {
@@ -62,13 +65,19 @@ float4 main(Conn IN) : TORQUE_TARGET0
 
     float cornerRadius = radius;
 
-    // if ((p.y < 0.0 && p.x < 0.0) || // top left corner
-    //     (p.y < 0.0 && p.x > 0.0) || // top right corner
-    //     (p.y > 0.0 && p.x > 0.0) || // bottom right corner.  
-    //     (p.y > 0.0 && p.x < 0.0))  // bottom left corner
-    // {
-    //     cornerRadius = radius;   
-    // } 
+    float4 baseColor = IN.color;
+
+    if(gradientFill > 0.5f)
+    {
+        float blendX = 1.0 - IN.texCoord.x;
+        float blendY = IN.texCoord.y;
+        float gamma = 2.4;
+        blendX = pow(abs(blendX), gamma);
+        blendY = pow(abs(blendY), 1/gamma);
+
+        float4 interpolatedColor = lerp(lerp(baseColor,float4(1.0f, 1.0f, 1.0f, 1.0f), blendX),float4(0.0f, 0.0f, 0.0f, 1.0f), blendY);
+        baseColor = interpolatedColor;
+    }
 
     if(cornerRadius > 0.0 || halfBorder > 0.0)
     {
@@ -78,19 +87,13 @@ float4 main(Conn IN) : TORQUE_TARGET0
         {
             if(sdf < 0.0)
             {
-                // if ((p.y >= -halfSize.y - radius + halfBorder && p.y <= -halfSize.y + radius - halfBorder)  ||  // top border
-                //     (p.y >= halfSize.y - radius + halfBorder && p.y <= halfSize.y + radius - halfBorder)    ||  // bottom border
-                //     (p.x >= -halfSize.x - radius + halfBorder && p.x <= -halfSize.x + radius - halfBorder)  ||  // left border
-                //     (p.x >= halfSize.x - radius + halfBorder && p.x <= halfSize.x + radius - halfBorder) ) {    // right border
-                    
-                // }
-                toColor = IN.color;
-                sdf = abs(sdf) / borderSize;
+                toColor = baseColor;
+                sdf = abs(sdf) - borderSize;
             } 
             
         } 
         else{
-            fromColor = IN.color; 
+            fromColor = baseColor; 
         }  
 
         float alpha = smoothstep(-1.0, 1.0, sdf); 
@@ -98,6 +101,6 @@ float4 main(Conn IN) : TORQUE_TARGET0
     }
     else
     {
-        return IN.color;
+        return baseColor;
     }
 }

File diff suppressed because it is too large
+ 267 - 708
Templates/BaseGame/game/tools/gui/colorPicker.ed.gui


Some files were not shown because too many files changed in this diff