Prechádzať zdrojové kódy

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

Color picker refactor rev2
Brian Roberts 7 mesiacov pred
rodič
commit
fdbac265b7
53 zmenil súbory, kde vykonal 590 pridanie a 202 odobranie
  1. 16 2
      Engine/source/console/consoleFunctions.cpp
  2. 1 1
      Engine/source/console/consoleTypes.cpp
  3. 137 30
      Engine/source/core/color.h
  4. 1 1
      Engine/source/core/util/str.h
  5. 1 1
      Engine/source/gfx/D3D11/screenshotD3D11.h
  6. 1 1
      Engine/source/gfx/gl/screenshotGL.h
  7. 3 4
      Engine/source/gfx/screenshot.h
  8. 149 95
      Engine/source/gui/controls/guiColorPicker.cpp
  9. 29 22
      Engine/source/gui/controls/guiColorPicker.h
  10. 135 45
      Templates/BaseGame/game/tools/gui/colorPicker.ed.gui
  11. 3 0
      Templates/BaseGame/game/tools/gui/images/add-simgroup-btn_ctrl_i_image.asset.taml
  12. 3 0
      Templates/BaseGame/game/tools/gui/images/add-simgroup-btn_i_image.asset.taml
  13. 3 0
      Templates/BaseGame/game/tools/gui/images/camera-btn_i_image.asset.taml
  14. 3 0
      Templates/BaseGame/game/tools/gui/images/clear-icon_i_image.asset.taml
  15. 3 0
      Templates/BaseGame/game/tools/gui/images/delete_i_image.asset.taml
  16. 3 0
      Templates/BaseGame/game/tools/gui/images/dropdown-button-arrow_d_image.asset.taml
  17. 3 0
      Templates/BaseGame/game/tools/gui/images/dropdown-button-arrow_h_image.asset.taml
  18. 3 0
      Templates/BaseGame/game/tools/gui/images/dropdown-button-arrow_i_image.asset.taml
  19. 3 0
      Templates/BaseGame/game/tools/gui/images/dropdown-button-arrow_n_image.asset.taml
  20. BIN
      Templates/BaseGame/game/tools/gui/images/eyedropper_d.png
  21. 3 0
      Templates/BaseGame/game/tools/gui/images/eyedropper_d_image.asset.taml
  22. BIN
      Templates/BaseGame/game/tools/gui/images/eyedropper_h.png
  23. 3 0
      Templates/BaseGame/game/tools/gui/images/eyedropper_h_image.asset.taml
  24. BIN
      Templates/BaseGame/game/tools/gui/images/eyedropper_i.png
  25. 3 0
      Templates/BaseGame/game/tools/gui/images/eyedropper_i_image.asset.taml
  26. BIN
      Templates/BaseGame/game/tools/gui/images/eyedropper_n.png
  27. 3 0
      Templates/BaseGame/game/tools/gui/images/eyedropper_n_image.asset.taml
  28. 3 0
      Templates/BaseGame/game/tools/gui/images/folder_d_image.asset.taml
  29. 3 0
      Templates/BaseGame/game/tools/gui/images/folder_h_image.asset.taml
  30. 3 0
      Templates/BaseGame/game/tools/gui/images/folder_i_image.asset.taml
  31. 3 0
      Templates/BaseGame/game/tools/gui/images/folder_n_image.asset.taml
  32. 3 0
      Templates/BaseGame/game/tools/gui/images/images_menuGrid_d_image.asset.taml
  33. 3 0
      Templates/BaseGame/game/tools/gui/images/images_menuGrid_h_image.asset.taml
  34. 3 0
      Templates/BaseGame/game/tools/gui/images/images_menuGrid_image.asset.taml
  35. 3 0
      Templates/BaseGame/game/tools/gui/images/images_menuGrid_n_image.asset.taml
  36. 3 0
      Templates/BaseGame/game/tools/gui/images/layers-btn_i_image.asset.taml
  37. 3 0
      Templates/BaseGame/game/tools/gui/images/lock_i_image.asset.taml
  38. 3 0
      Templates/BaseGame/game/tools/gui/images/new-folder-btn_i_image.asset.taml
  39. 3 0
      Templates/BaseGame/game/tools/gui/images/new_i_image.asset.taml
  40. 3 0
      Templates/BaseGame/game/tools/gui/images/numericslider_image.asset.taml
  41. 3 0
      Templates/BaseGame/game/tools/gui/images/open-file_i_image.asset.taml
  42. 3 0
      Templates/BaseGame/game/tools/gui/images/reset-icon_i_image.asset.taml
  43. 3 0
      Templates/BaseGame/game/tools/gui/images/selector-button_image.asset.taml
  44. 3 0
      Templates/BaseGame/game/tools/gui/images/tab-border_image.asset.taml
  45. 3 0
      Templates/BaseGame/game/tools/gui/images/textEdit_black_image.asset.taml
  46. 3 0
      Templates/BaseGame/game/tools/gui/images/textEdit_blue_image.asset.taml
  47. 3 0
      Templates/BaseGame/game/tools/gui/images/textEdit_cyan_image.asset.taml
  48. 3 0
      Templates/BaseGame/game/tools/gui/images/textEdit_green_image.asset.taml
  49. 3 0
      Templates/BaseGame/game/tools/gui/images/textEdit_magenta_image.asset.taml
  50. 3 0
      Templates/BaseGame/game/tools/gui/images/textEdit_red_image.asset.taml
  51. 3 0
      Templates/BaseGame/game/tools/gui/images/textEdit_white_image.asset.taml
  52. 3 0
      Templates/BaseGame/game/tools/gui/images/textEdit_yellow_image.asset.taml
  53. 3 0
      Templates/BaseGame/game/tools/gui/images/uv-editor-btn_i_image.asset.taml

+ 16 - 2
Engine/source/console/consoleFunctions.cpp

@@ -1104,7 +1104,21 @@ DefineEngineFunction(ColorRGBToHSB, const char*, (ColorI color), ,
    "@endtsexample\n"
    "@ingroup Strings")
 {
-   ColorI::Hsb hsb(color.getHSB()); 
+   Hsb hsb(color.getHSB()); 
+   String s(String::ToString(hsb.hue) + " " + String::ToString(hsb.sat) + " " + String::ToString(hsb.brightness));
+   return Con::getReturnBuffer(s);
+}
+
+DefineEngineFunction(ColorLinearRGBToHSB, const char*, (LinearColorF color), ,
+   "Convert from a integer RGB (red, green, blue) color to HSB (hue, saturation, brightness). HSB is also know as HSL or HSV as well, with the last letter standing for lightness or value.\n"
+   "@param color Integer color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha. It excepts an alpha, but keep in mind this will not be converted.\n"
+   "@return HSB color value, alpha isn't handled/converted so it is only the RGB value\n\n"
+   "@tsexample\n"
+   "ColorRBGToHSB( \"0 0 255 128\" ) // Returns \"240 100 100\".\n"
+   "@endtsexample\n"
+   "@ingroup Strings")
+{
+   Hsb hsb(color.getHSB());
    String s(String::ToString(hsb.hue) + " " + String::ToString(hsb.sat) + " " + String::ToString(hsb.brightness));
    return Con::getReturnBuffer(s);
 }
@@ -1133,7 +1147,7 @@ DefineEngineFunction(ColorHSBToRGB, ColorI, (Point3I hsb), ,
    "@ingroup Strings")
 {
    ColorI color;
-   color.set(ColorI::Hsb(hsb.x, hsb.y, hsb.z));
+   color.set(Hsb(hsb.x, hsb.y, hsb.z));
    return color;
 }
 

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

@@ -419,7 +419,7 @@ ConsoleGetType(TypeF64)
 {
    static const U32 bufSize = 256;
    char* returnBuffer = Con::getReturnBuffer(bufSize);
-   dSprintf(returnBuffer, bufSize, "%Lg", *((F64*)dptr));
+   dSprintf(returnBuffer, bufSize, "%g", *((F64*)dptr));
    return returnBuffer;
 }
 ConsoleSetType(TypeF64)

+ 137 - 30
Engine/source/core/color.h

@@ -34,9 +34,24 @@
 #include "console/engineAPI.h"
 #endif
 
+#ifdef TORQUE_USE_LEGACY_GAMMA
 const F32 gGamma = 2.2f;
 const F32 gOneOverGamma = 1.f / 2.2f;
+#else
+const F32 gGamma = 2.4f;
+const F32 gOneOverGamma = 1.f / 2.4f;
 const F32 gOneOver255 = 1.f / 255.f;
+#endif
+
+struct Hsb
+{
+   Hsb() :hue(0), sat(0), brightness(0) {};
+   Hsb(U32 h, U32 s, U32 b) :hue(h), sat(s), brightness(b) {};
+
+   U32 hue;   ///Hue
+   U32 sat;   ///Saturation
+   U32 brightness;   //Brightness/Value/Lightness
+};
 
 class ColorI;
 
@@ -55,9 +70,14 @@ public:
    LinearColorF(const F32 in_r, const F32 in_g, const F32 in_b, const F32 in_a = 1.0f);
    LinearColorF(const ColorI &color);
    LinearColorF(const char* pStockColorName);
+   LinearColorF(const Hsb& color);
+
+   F32 srgbToLinearChannel(const F32 chan_col);
+   F32 linearChannelToSrgb(const F32 chan_col);
 
    void set( const F32 in_r, const F32 in_g, const F32 in_b, const F32 in_a = 1.0f );
    void set( const char* pStockColorName );
+   void set(const Hsb& color);
 
    static const LinearColorF& StockColor( const char* pStockColorName );
    StringTableEntry StockColor( void );
@@ -88,6 +108,7 @@ public:
    U32 getARGBPack() const;
    U32 getRGBAPack() const;
    U32 getABGRPack() const;
+   Hsb getHSB();
 
    void interpolate(const LinearColorF& in_rC1,
                     const LinearColorF& in_rC2,
@@ -126,16 +147,6 @@ public:
    U8 blue;
    U8 alpha;
 
-   struct Hsb
-   {
-      Hsb() :hue(0), sat(0), brightness(0){};
-      Hsb(F64 h, F64 s, F64 b) :hue(h), sat(s), brightness(b){};
-
-      F64 hue;   ///Hue
-      F64 sat;   ///Saturation
-      F64 brightness;   //Brightness/Value/Lightness
-   };
-
 public:
    ColorI() : red(0), green(0), blue(0), alpha(0) {}
    ColorI(const ColorI& in_rCopy);
@@ -247,6 +258,27 @@ public:
    static void destroy( void );
 };
 
+inline F32 LinearColorF::srgbToLinearChannel(const F32 chan_col)
+{
+   if (chan_col < 0.0405f) {
+      return chan_col / 12.92f;
+   }
+   else {
+      return mPow((chan_col + 0.055f) / 1.055f, gGamma);
+   }
+}
+
+inline F32 LinearColorF::linearChannelToSrgb(const F32 chan_col)
+{
+   if (chan_col <= 0.0031308f) {
+      return chan_col * 12.92f;
+   }
+   else {
+      return 1.055f * mPow(chan_col, gOneOverGamma) - 0.055f;
+   }
+}
+
+
 //------------------------------------------------------------------------------
 //-------------------------------------- INLINES (LinearColorF)
 //
@@ -441,6 +473,80 @@ inline F32 LinearColorF::luminance()
    return red * 0.3f + green * 0.59f + blue * 0.11f;
 }
 
+inline LinearColorF::LinearColorF(const Hsb& color)
+{
+   set(color);
+}
+
+inline void LinearColorF::set(const Hsb& color)
+{
+   F64 c = (color.brightness / 100.0) * (color.sat / 100.0);
+   F64 x = c * (1.0 - fabs(fmod(color.hue / 60.0, 2.0) - 1.0));
+   F64 m = (color.brightness / 100.0) - c;
+
+   F64 r = 0.0, g = 0.0, b = 0.0;
+   if (color.hue < 60.0) {
+      r = c; g = x; b = 0.0;
+   }
+   else if (color.hue < 120.0) {
+      r = x; g = c; b = 0.0;
+   }
+   else if (color.hue < 180.0) {
+      r = 0.0; g = c; b = x;
+   }
+   else if (color.hue < 240.0) {
+      r = 0.0; g = x; b = c;
+   }
+   else if (color.hue < 300.0) {
+      r = x; g = 0.0; b = c;
+   }
+   else {
+      r = c; g = 0.0; b = x;
+   }
+
+   r += m;
+   g += m;
+   b += m;
+
+   red = static_cast<F32>(srgbToLinearChannel(r));
+   green = static_cast<F32>(srgbToLinearChannel(g));
+   blue = static_cast<F32>(srgbToLinearChannel(b));
+   alpha = 1.0f; // Default alpha to 1.0
+}
+
+inline Hsb LinearColorF::getHSB()
+{
+   F32 r = linearChannelToSrgb(red);
+   F32 g = linearChannelToSrgb(green);
+   F32 b = linearChannelToSrgb(blue);
+
+   F32 maxVal = mMax(r, mMax(g, b));
+   F32 minVal = mMin(r, mMin(g, b));
+   F32 delta = maxVal - minVal;
+
+   Hsb hsb;
+   hsb.brightness = maxVal * 100.0; // Convert to percentage
+   hsb.sat = (maxVal > 0.0f) ? (delta / maxVal) * 100.0 : 0.0;
+
+   if (delta > 0.0f) {
+      if (r == maxVal)
+         hsb.hue = 60.0 * mFmod(((g - b) / delta), 6.0);
+      else if (g == maxVal)
+         hsb.hue = 60.0 * (((b - r) / delta) + 2.0);
+      else
+         hsb.hue = 60.0 * (((r - g) / delta) + 4.0);
+
+      if (hsb.hue < 0.0)
+         hsb.hue += 360.0;
+   }
+   else {
+      hsb.hue = 0.0;
+   }
+
+   return hsb;
+}
+
+
 //------------------------------------------------------------------------------
 //-------------------------------------- INLINES (ColorI)
 //
@@ -550,6 +656,7 @@ inline void ColorI::set(const String& hex)
 	red = (U8)(convertFromHex(redString));
 	green = (U8)(convertFromHex(greenString));
 	blue = (U8)(convertFromHex(blueString));
+   alpha = 255;
 }
 
 inline S32 ColorI::convertFromHex(const String& hex) const
@@ -718,7 +825,7 @@ inline U16 ColorI::get4444() const
               U16(U16(blue  >> 4) <<  0));
 }
 
-inline ColorI::Hsb ColorI::getHSB() const
+inline Hsb ColorI::getHSB() const
 {
    // Normalize RGB values to [0, 1]
    F64 rPercent = (F64)red / 255.0;
@@ -739,22 +846,22 @@ inline ColorI::Hsb ColorI::getHSB() const
       S = delta / maxColor; // Saturation
 
       // Compute hue
-      if (fabs(maxColor - rPercent) < 1e-6)
+      if (mFabsD(maxColor - rPercent) < 1e-6)
       {
          H = 60.0 * ((gPercent - bPercent) / delta);
       }
-      else if (fabs(maxColor - gPercent) < 1e-6)
+      else if (mFabsD(maxColor - gPercent) < 1e-6)
       {
          H = 60.0 * (((bPercent - rPercent) / delta) + 2.0);
       }
-      else if (fabs(maxColor - bPercent) < 1e-6)
+      else if (mFabsD(maxColor - bPercent) < 1e-6)
       {
          H = 60.0 * (((rPercent - gPercent) / delta) + 4.0);
       }
    }
 
    // Prepare the output HSB struct
-   ColorI::Hsb val;
+   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
@@ -781,9 +888,9 @@ inline String ColorI::getHex() const
 
 inline LinearColorF::LinearColorF( const ColorI &color)
 {
-   red = sSrgbToLinear[color.red],
-   green = sSrgbToLinear[color.green],
-   blue = sSrgbToLinear[color.blue],
+   red =    srgbToLinearChannel(color.red * gOneOver255),
+   green =  srgbToLinearChannel(color.green * gOneOver255),
+   blue =   srgbToLinearChannel(color.blue * gOneOver255),
    alpha = F32(color.alpha * gOneOver255);
 }
 
@@ -798,14 +905,14 @@ inline ColorI LinearColorF::toColorI(const bool keepAsLinear)
       else
       {
    #ifdef TORQUE_USE_LEGACY_GAMMA
-         float r = mPow(red, gOneOverGamma);
-         float g = mPow(green, gOneOverGamma);
-         float b = mPow(blue, gOneOverGamma);
+         F32 r = mPow(red, gOneOverGamma);
+         F32 g = mPow(green, gOneOverGamma);
+         F32 b = mPow(blue, gOneOverGamma);
          return ColorI(U8(r * 255.0f + 0.5), U8(g * 255.0f + 0.5), U8(b * 255.0f + 0.5), U8(alpha * 255.0f + 0.5));
    #else
-         float r = red < 0.0031308f ? 12.92f * red : 1.055f * mPow(red, 1.0f / 2.4f) - 0.055f;
-         float g = green < 0.0031308f ? 12.92f * green : 1.055f * mPow(green, 1.0f / 2.4f) - 0.055f;
-         float b = blue < 0.0031308f ? 12.92f * blue : 1.055f * mPow(blue, 1.0f / 2.4f) - 0.055f;
+         F32 r = linearChannelToSrgb(red);
+         F32 g = linearChannelToSrgb(green);
+         F32 b = linearChannelToSrgb(blue);
          return ColorI(U8(r * 255.0f + 0.5), U8(g * 255.0f + 0.5), U8(b * 255.0f + 0.5), U8(alpha * 255.0f + 0.5f));
    #endif
       }
@@ -822,14 +929,14 @@ inline ColorI LinearColorF::toColorI(const bool keepAsLinear)
       else
       {
    #ifdef TORQUE_USE_LEGACY_GAMMA
-         float r = mPow(red, gOneOverGamma);
-         float g = mPow(green, gOneOverGamma);
-         float b = mPow(blue, gOneOverGamma);
+         F32 r = mPow(red, gOneOverGamma);
+         F32 g = mPow(green, gOneOverGamma);
+         F32 b = mPow(blue, gOneOverGamma);
          return ColorI(U8(r * 255.0f + 0.5), U8(g * 255.0f + 0.5), U8(b * 255.0f + 0.5), U8(alpha * 255.0f + 0.5));
    #else
-         float r = red < 0.0031308f ? 12.92f * red : 1.055f * mPow(red, 1.0f / 2.4f) - 0.055f;
-         float g = green < 0.0031308f ? 12.92f * green : 1.055f * mPow(green, 1.0f / 2.4f) - 0.055f;
-         float b = blue < 0.0031308f ? 12.92f * blue : 1.055f * mPow(blue, 1.0f / 2.4f) - 0.055f;
+         F32 r = linearChannelToSrgb(red);
+         F32 g = linearChannelToSrgb(green);
+         F32 b = linearChannelToSrgb(blue);
          return ColorI(U8(r * 255.0f + 0.5f), U8(g * 255.0f + 0.5f), U8(b * 255.0f + 0.5f), U8(alpha * 255.0f + 0.5f));
    #endif
       }

+ 1 - 1
Engine/source/core/util/str.h

@@ -186,7 +186,7 @@ public:
    static inline String ToString( U32 v ) { return ToString( "%u", v ); }
    static inline String ToString( S32 v ) { return ToString( "%d", v ); }
    static inline String ToString( F32 v ) { return ToString( "%g", v ); }
-   static inline String ToString( F64 v ) { return ToString( "%Lg", v ); }
+   static inline String ToString( F64 v ) { return ToString( "%g", v ); }
    inline operator const char* () { return c_str(); }
    static String SpanToString(const char* start, const char* end);
 

+ 1 - 1
Engine/source/gfx/D3D11/screenshotD3D11.h

@@ -29,7 +29,7 @@
 //**************************************************************************
 class ScreenShotD3D11 : public ScreenShot
 {
-protected:
+public:
 
    GBitmap* _captureBackBuffer() override;
 

+ 1 - 1
Engine/source/gfx/gl/screenshotGL.h

@@ -29,7 +29,7 @@
 //**************************************************************************
 class ScreenShotGL : public ScreenShot
 {
-protected:
+public:
 
    GBitmap* _captureBackBuffer() override;
 

+ 3 - 4
Engine/source/gfx/screenshot.h

@@ -40,10 +40,6 @@ class Frustum;
 
 class ScreenShot
 {
-   /// This is overloaded to copy the current GFX 
-   /// backbuffer to a new bitmap.
-	virtual GBitmap* _captureBackBuffer() { return NULL; }
-
    /// This is set to toggle the capture.
    bool mPending;
 
@@ -76,6 +72,9 @@ public:
    ScreenShot();
    virtual ~ScreenShot() { }
 
+   /// This is overloaded to copy the current GFX 
+   /// backbuffer to a new bitmap.
+   virtual GBitmap* _captureBackBuffer() { return NULL; }
    /// Used to start the screenshot capture.
    void setPending( const char *filename, bool writeJPG, S32 tiles, F32 overlap );
 

+ 149 - 95
Engine/source/gui/controls/guiColorPicker.cpp

@@ -29,6 +29,8 @@
 #include "gui/controls/guiColorPicker.h"
 #include "gfx/primBuilder.h"
 #include "gfx/gfxDrawUtil.h"
+#include "postFx/postEffectManager.h"
+#include "gfx/screenshot.h"
 
 IMPLEMENT_CONOBJECT(GuiColorPickerCtrl);
 
@@ -47,15 +49,23 @@ GuiColorPickerCtrl::GuiColorPickerCtrl()
    mActive = true;
    mSelectorGap = 1;
    mActionOnMove = false;
+   mDropperActive = false;
    mShowReticle = true;
    mSelectedHue = 0;
    mSelectedAlpha = 255;
    mSelectedSaturation = 100;
    mSelectedBrightness = 100;
+   eyeDropperPos = Point2I::Zero;
+   eyeDropperCap = NULL;
 }
 
 GuiColorPickerCtrl::~GuiColorPickerCtrl()
 {
+   if (eyeDropperCap != NULL)
+   {
+      delete eyeDropperCap;
+      eyeDropperCap = NULL;
+   }
 }
 
 ImplementEnumType( GuiColorPickMode,
@@ -94,7 +104,7 @@ void GuiColorPickerCtrl::initPersistFields()
 void GuiColorPickerCtrl::renderBlendRange(RectI& bounds)
 {
    ColorI currentColor;
-   currentColor.set(ColorI::Hsb(mSelectedHue, 100, 100));
+   currentColor.set(Hsb(mSelectedHue, 100, 100));
    GFX->getDrawUtil()->drawRectFill(bounds, currentColor, 0.0f, ColorI(0,0,0,0), true);
 }
 
@@ -114,7 +124,7 @@ void GuiColorPickerCtrl::renderBlendSelector(RectI& bounds)
    selectorRect.set(Point2I(selectorPos.x - mSelectorGap, selectorPos.y - mSelectorGap), Point2I(mSelectorGap * 2, mSelectorGap * 2));
 
    ColorI currentColor;
-   currentColor.set(ColorI::Hsb(mSelectedHue, mSelectedSaturation, mSelectedBrightness));
+   currentColor.set(Hsb(mSelectedHue, mSelectedSaturation, mSelectedBrightness));
    GFX->getDrawUtil()->drawRectFill(selectorRect, currentColor, 2.0f, ColorI::WHITE);
 }
 
@@ -136,8 +146,8 @@ void GuiColorPickerCtrl::renderHueGradient(RectI& bounds, U32 numColours)
       U32 nextHue = static_cast<U32>((F32(i + 1) / F32(numColours)) * 360.0f);
 
       ColorI currentColor, nextColor;
-      currentColor.set(ColorI::Hsb(currentHue, 100, 100));
-      nextColor.set(ColorI::Hsb(nextHue, 100, 100));
+      currentColor.set(Hsb(currentHue, 100, 100));
+      nextColor.set(Hsb(nextHue, 100, 100));
 
       switch (mSelectorMode)
       {
@@ -217,7 +227,7 @@ void GuiColorPickerCtrl::renderHueSelector(RectI& bounds)
    }
 
    ColorI currentColor;
-   currentColor.set(ColorI::Hsb(mSelectedHue, 100, 100));
+   currentColor.set(Hsb(mSelectedHue, 100, 100));
    GFX->getDrawUtil()->drawRectFill(selectorRect, currentColor, 2.0f, ColorI::WHITE);
 }
 
@@ -232,7 +242,7 @@ void GuiColorPickerCtrl::renderAlphaGradient(RectI& bounds)
    S32 b = bounds.point.y + bounds.extent.y;
 
    ColorI currentColor;
-   currentColor.set(ColorI::Hsb(mSelectedHue, 100, 100));
+   currentColor.set(Hsb(mSelectedHue, 100, 100));
 
    ColorI alphaCol = ColorI::BLACK;
    alphaCol.alpha = 0;
@@ -308,12 +318,38 @@ void GuiColorPickerCtrl::renderAlphaSelector(RectI& bounds)
    }
 
    ColorI currentColor;
-   currentColor.set(ColorI::Hsb(mSelectedHue, 100, 100));
+   currentColor.set(Hsb(mSelectedHue, 100, 100));
    currentColor.alpha = mSelectedAlpha;
 
    GFX->getDrawUtil()->drawRectFill(selectorRect, currentColor, 2.0f, ColorI::WHITE);
 }
 
+void GuiColorPickerCtrl::renderEyeDropper()
+{
+   if (eyeDropperCap != NULL)
+   {
+      GFX->getDrawUtil()->drawBitmap(eyeHandle, getRoot()->getPosition());
+
+      Point2I resolution = getRoot()->getExtent();
+      Point2I magnifierSize(100, 100);
+      Point2I magnifierPosition = eyeDropperPos + Point2I(20, 20);
+
+      // Adjust position to ensure magnifier stays on screen
+      if (magnifierPosition.x + magnifierSize.x > resolution.x)
+         magnifierPosition.x = eyeDropperPos.x - magnifierSize.x - 20;
+      if (magnifierPosition.y + magnifierSize.y > resolution.y)
+         magnifierPosition.y = eyeDropperPos.y - magnifierSize.y - 20;
+
+      RectI magnifierBounds(magnifierPosition, magnifierSize);
+
+      ColorI currentColor;
+      currentColor.set(Hsb(mSelectedHue, mSelectedSaturation, mSelectedBrightness));
+      currentColor.alpha = mSelectedAlpha;
+
+      GFX->getDrawUtil()->drawRectFill(magnifierBounds, currentColor, 2.0f, ColorI::BLACK);
+   }
+}
+
 void GuiColorPickerCtrl::onRender(Point2I offset, const RectI& updateRect)
 {
    if (mStateBlock.isNull())
@@ -333,7 +369,7 @@ void GuiColorPickerCtrl::onRender(Point2I offset, const RectI& updateRect)
    case GuiColorPickerCtrl::pPalette:
    {
       ColorI currentColor;
-      currentColor.set(ColorI::Hsb(mSelectedHue, mSelectedSaturation, mSelectedBrightness));
+      currentColor.set(Hsb(mSelectedHue, mSelectedSaturation, mSelectedBrightness));
       currentColor.alpha = mSelectedAlpha;
       GFX->getDrawUtil()->drawRectFill(boundsRect, currentColor);
       break;
@@ -356,6 +392,15 @@ void GuiColorPickerCtrl::onRender(Point2I offset, const RectI& updateRect)
       if (mShowReticle) renderAlphaSelector(boundsRect);
       break;
    }
+   case GuiColorPickerCtrl::pDropperBackground:
+   {
+      if (mDropperActive)
+      {
+         // Render the magnified view of our currently selected color.
+         renderEyeDropper();
+      }
+      break;
+   }
    default:
       break;
    }
@@ -364,72 +409,31 @@ void GuiColorPickerCtrl::onRender(Point2I offset, const RectI& updateRect)
    renderChildControls(offset, updateRect);
 }
 
-Point2I GuiColorPickerCtrl::findColor(const LinearColorF & color, const Point2I& offset, const Point2I& resolution, GBitmap& bmp)
+void GuiColorPickerCtrl::onMouseDown(const GuiEvent &event)
 {
-   Point2I ext = getExtent();
-   Point2I closestPos(-1, -1);
-
-   /* Debugging
-   char filename[256];
-   dSprintf( filename, 256, "%s.%s", "colorPickerTest", "png" );
-
-   // Open up the file on disk.
-   FileStream fs;
-   if ( !fs.open( filename, Torque::FS::File::Write ) )
-   Con::errorf( "GuiObjectView::saveAsImage() - Failed to open output file '%s'!", filename );
-   else
-   {
-   // Write it and close.
-   bmp.writeBitmap( "png", fs );
-
-   fs.close();
-   }
-   */
-
-   ColorI tmp;
-   U32 buf_x;
-   U32 buf_y;
-   LinearColorF curColor;
-   F32 val(10000.0f);
-   F32 closestVal(10000.0f);
-   bool closestSet = false;
+   if (!mActive)
+      return;
 
-   for (S32 x = 0; x < ext.x; x++)
-   {
-      for (S32 y = 0; y < ext.y; y++)
+   // we need to do this first.
+   if (mDisplayMode == GuiColorPickerCtrl::pDropperBackground) {
+      if (mDropperActive)
       {
-         buf_x = offset.x + x;
-         buf_y = (resolution.y - (offset.y + y));
-         buf_y = resolution.y - buf_y;
+         mDropperActive = false;
 
-         //Get the color at that position
-         bmp.getColor(buf_x, buf_y, tmp);
-         curColor = (LinearColorF)tmp;
+         //getRoot()->pushObjectToBack(this);
 
-         //Evaluate how close the color is to our desired color
-         val = mFabs(color.red - curColor.red) + mFabs(color.green - curColor.green) + mFabs(color.blue - curColor.blue);
+         onAction();
+         mouseUnlock();
 
-         if (!closestSet)
-         {
-            closestVal = val;
-            closestPos.set(x, y);
-            closestSet = true;
-         }
-         else if (val < closestVal)
+         if (eyeDropperCap != NULL)
          {
-            closestVal = val;
-            closestPos.set(x, y);
+            delete eyeDropperCap;
+            eyeDropperCap = NULL;
          }
       }
-   }
 
-   return closestPos;
-}
-
-void GuiColorPickerCtrl::onMouseDown(const GuiEvent &event)
-{
-   if (!mActive)
       return;
+   }
    
    mouseLock(this);
    
@@ -510,14 +514,15 @@ void GuiColorPickerCtrl::onMouseDragged(const GuiEvent &event)
       Point2I ext = getExtent();
       Point2I mousePoint = globalToLocalCoord(event.mousePoint);
 
+      F32 relX = mClampF(F32(mousePoint.x) / F32(ext.x), 0.0, 1.0);
+      F32 relY = mClampF(F32(mousePoint.y) / F32(ext.y), 0.0, 1.0);
       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);
+         relY = 1.0f - relY;
          setSelectedSaturation(relX * 100.0);
          setSelectedBrightness(relY * 100.0);
          break;
@@ -528,13 +533,11 @@ void GuiColorPickerCtrl::onMouseDragged(const GuiEvent &event)
          {
          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;
          }
@@ -549,13 +552,11 @@ void GuiColorPickerCtrl::onMouseDragged(const GuiEvent &event)
          {
          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;
          }
@@ -574,6 +575,29 @@ void GuiColorPickerCtrl::onMouseDragged(const GuiEvent &event)
 
 void GuiColorPickerCtrl::onMouseMove(const GuiEvent &event)
 {
+   if (mDisplayMode != pDropperBackground)
+      return;
+
+   if (!mDropperActive)
+      return;
+
+   // should not need globalToLocal as we are capturing the whole screen.
+   eyeDropperPos = globalToLocalCoord(event.mousePoint);
+
+   if (eyeDropperCap != NULL)
+   {
+      // Sample the pixel color at the mouse position. Mouse position should translate directly.
+      ColorI sampledColor;
+      eyeDropperCap->getColor(eyeDropperPos.x, eyeDropperPos.y, sampledColor);
+
+      // Convert the sampled color to HSB
+      Hsb hsb = sampledColor.getHSB();
+      mSelectedHue = hsb.hue;
+      mSelectedSaturation = hsb.sat;
+      mSelectedBrightness = hsb.brightness;
+      mSelectedAlpha = sampledColor.alpha;
+   }
+
 }
 
 void GuiColorPickerCtrl::onMouseEnter(const GuiEvent &event)
@@ -587,7 +611,16 @@ void GuiColorPickerCtrl::onMouseLeave(const GuiEvent &)
    mMouseOver = false;
 }
 
-void GuiColorPickerCtrl::setSelectedHue(const F64& hueValue)
+void GuiColorPickerCtrl::onMouseUp(const GuiEvent&)
+{
+   //if we released the mouse within this control, perform the action
+   if (mActive && mMouseDown)
+      mMouseDown = false;
+
+   mouseUnlock();
+}
+
+void GuiColorPickerCtrl::setSelectedHue(const U32& hueValue)
 {
    if (hueValue < 0)
    {
@@ -605,7 +638,7 @@ void GuiColorPickerCtrl::setSelectedHue(const F64& hueValue)
    
 }
 
-void GuiColorPickerCtrl::setSelectedBrightness(const F64& brightValue)
+void GuiColorPickerCtrl::setSelectedBrightness(const U32& brightValue)
 {
    if (brightValue < 0)
    {
@@ -622,7 +655,7 @@ void GuiColorPickerCtrl::setSelectedBrightness(const F64& brightValue)
    mSelectedBrightness = brightValue;
 }
 
-void GuiColorPickerCtrl::setSelectedSaturation(const F64& satValue)
+void GuiColorPickerCtrl::setSelectedSaturation(const U32& satValue)
 {
    if (satValue < 0)
    {
@@ -639,7 +672,7 @@ void GuiColorPickerCtrl::setSelectedSaturation(const F64& satValue)
    mSelectedSaturation = satValue;
 }
 
-void GuiColorPickerCtrl::setSelectedAlpha(const F64& alphaValue)
+void GuiColorPickerCtrl::setSelectedAlpha(const U32& alphaValue)
 {
    if (alphaValue < 0)
    {
@@ -656,13 +689,27 @@ void GuiColorPickerCtrl::setSelectedAlpha(const F64& alphaValue)
    mSelectedAlpha = alphaValue;
 }
 
-void GuiColorPickerCtrl::onMouseUp(const GuiEvent &)
+void GuiColorPickerCtrl::activateEyeDropper()
 {
-   //if we released the mouse within this control, perform the action
-   if (mActive && mMouseDown)
-      mMouseDown = false;
+   // Make sure we are a pDropperBackground
+   if (mDisplayMode == GuiColorPickerCtrl::pDropperBackground)
+   {
+      mouseLock(this); // take over!
 
-   mouseUnlock();
+      setFirstResponder(); // we need this to be first responder regardless.
+
+      //getRoot()->bringObjectToFront(this);
+
+      mDropperActive = true;
+
+      // Set up our resolution.
+      Point2I resolution = getRoot()->getExtent();
+
+      eyeDropperCap = gScreenShot->_captureBackBuffer();
+
+      // Texture handle to resolve the target to.
+      eyeHandle.set(eyeDropperCap, &GFXStaticTextureSRGBProfile, false, avar("%s() - bb (line %d)", __FUNCTION__, __LINE__));
+   }
 }
 
 /// <summary>
@@ -673,49 +720,57 @@ DefineEngineMethod(GuiColorPickerCtrl, executeUpdate, void, (), , "Execute the o
    object->onAction();
 }
 
-DefineEngineMethod(GuiColorPickerCtrl, setSelectedHue, void, (F64 hueValue), , "Sets the selected hue value should be 0-360.")
+/// <summary>
+/// This command should only be used with guiColorPicker in pDropperBackground mode.
+/// </summary>
+DefineEngineMethod(GuiColorPickerCtrl, activateEyeDropper, void, (), , "Activate the dropper mode.")
+{
+   object->activateEyeDropper();
+}
+
+DefineEngineMethod(GuiColorPickerCtrl, setSelectedHue, void, (S32 hueValue), , "Sets the selected hue value should be 0-360.")
 {
    object->setSelectedHue(hueValue);
 }
 
-DefineEngineMethod(GuiColorPickerCtrl, getSelectedHue, F64, (), , "Gets the current selected hue value.")
+DefineEngineMethod(GuiColorPickerCtrl, getSelectedHue, S32, (), , "Gets the current selected hue value.")
 {
    return object->getSelectedHue();
 }
 
-DefineEngineMethod(GuiColorPickerCtrl, setSelectedBrightness, void, (F64 brightness), , "Sets the selected brightness value should be 0-100.")
+DefineEngineMethod(GuiColorPickerCtrl, setSelectedBrightness, void, (S32 brightness), , "Sets the selected brightness value should be 0-100.")
 {
    object->setSelectedBrightness(brightness);
 }
 
-DefineEngineMethod(GuiColorPickerCtrl, getSelectedBrightness, F64, (), , "Gets the current selected brightness.")
+DefineEngineMethod(GuiColorPickerCtrl, getSelectedBrightness, S32, (), , "Gets the current selected brightness.")
 {
    return object->getSelectedBrightness();
 }
 
-DefineEngineMethod(GuiColorPickerCtrl, setSelectedSaturation, void, (F64 saturation), , "Sets the selected saturation value should be 0-100.")
+DefineEngineMethod(GuiColorPickerCtrl, setSelectedSaturation, void, (S32 saturation), , "Sets the selected saturation value should be 0-100.")
 {
    object->setSelectedSaturation(saturation);
 }
 
-DefineEngineMethod(GuiColorPickerCtrl, getSelectedSaturation, F64, (), , "Gets the current selected saturation value.")
+DefineEngineMethod(GuiColorPickerCtrl, getSelectedSaturation, S32, (), , "Gets the current selected saturation value.")
 {
    return object->getSelectedSaturation();
 }
 
-DefineEngineMethod(GuiColorPickerCtrl, setSelectedAlpha, void, (F64 alpha), , "Sets the selected alpha value should be 0-255.")
+DefineEngineMethod(GuiColorPickerCtrl, setSelectedAlpha, void, (S32 alpha), , "Sets the selected alpha value should be 0-255.")
 {
    object->setSelectedAlpha(alpha);
 }
 
-DefineEngineMethod(GuiColorPickerCtrl, getSelectedAlpha, F64, (), , "Gets the current selected alpha value.")
+DefineEngineMethod(GuiColorPickerCtrl, getSelectedAlpha, S32, (), , "Gets the current selected alpha value.")
 {
    return object->getSelectedAlpha();
 }
 
 DefineEngineMethod(GuiColorPickerCtrl, setSelectedColorI, void, (ColorI col), , "Sets the current selected hsb from a colorI value.")
 {
-   ColorI::Hsb hsb(col.getHSB());
+   Hsb hsb(col.getHSB());
    object->setSelectedHue(hsb.hue);
    object->setSelectedSaturation(hsb.sat);
    object->setSelectedBrightness(hsb.brightness);
@@ -725,26 +780,25 @@ DefineEngineMethod(GuiColorPickerCtrl, setSelectedColorI, void, (ColorI col), ,
 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.set(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());
+   Hsb hsb = colF.getHSB();
    object->setSelectedHue(hsb.hue);
    object->setSelectedSaturation(hsb.sat);
    object->setSelectedBrightness(hsb.brightness);
-   object->setSelectedAlpha(col.alpha);
+   object->setSelectedAlpha(colF.alpha * 255.0);
 }
 
 
 DefineEngineMethod(GuiColorPickerCtrl, getSelectedLinearColor, LinearColorF, (), , "Gets the current selected hsb as a LinearColorF value.")
 {
-   ColorI col;
-   col.set(ColorI::Hsb(object->getSelectedHue(), object->getSelectedSaturation(), object->getSelectedBrightness()));
-   col.alpha = object->getSelectedAlpha();
-   return LinearColorF(col);
+   LinearColorF col;
+   col.set(Hsb(object->getSelectedHue(), object->getSelectedSaturation(), object->getSelectedBrightness()));
+   col.alpha = (F32)object->getSelectedAlpha() / 255.0f;
+   return col;
 }

+ 29 - 22
Engine/source/gui/controls/guiColorPicker.h

@@ -108,23 +108,27 @@ class GuiColorPickerCtrl : public GuiControl
    /// <param name="bounds">The bounds of the ctrl.</param>
    void renderAlphaSelector(RectI& bounds);
 
+   void renderEyeDropper();
+
    /// @name Core Variables
    /// @{
-   PickMode mDisplayMode;	///< Current color display mode of the selector
+   PickMode mDisplayMode;	      ///< Current color display mode of the selector
    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 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. 
+   U32 mSelectedHue;
+   U32 mSelectedSaturation;
+   U32 mSelectedBrightness;
+   U32 mSelectedAlpha;
+   Point2I eyeDropperPos;
+   GBitmap* eyeDropperCap;
+   GFXTexHandle eyeHandle;
+
+   bool mDropperActive;       ///< Is the eye dropper active?
+   bool mMouseOver;		      ///< Mouse is over?
+   bool mMouseDown;		      ///< Mouse button down?
+   bool mActionOnMove;		   ///< Perform onAction() when position has changed?
+   bool mShowReticle;         ///< Show reticle on render
+
+   S32   mSelectorGap;		   ///< The half-way "gap" between the selector pos and where the selector is allowed to draw. 
 
    GFXStateBlockRef mStateBlock;
    /// @}
@@ -158,29 +162,32 @@ class GuiColorPickerCtrl : public GuiControl
    /// Set the selected hue.
    /// </summary>
    /// <param name="hueValue">Hue value, 0 - 360.</param>
-   void setSelectedHue(const F64& hueValue);
-   F64 getSelectedHue() { return mSelectedHue; }
+   void setSelectedHue(const U32& hueValue);
+   U32 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; }
+   void setSelectedBrightness(const U32& brightValue);
+   U32 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; }
+   void setSelectedSaturation(const U32& satValue);
+   U32 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; }
+   void setSelectedAlpha(const U32& alphaValue);
+   U32 getSelectedAlpha() { return mSelectedAlpha; }
+
+   void activateEyeDropper();
+
 };
 
 typedef GuiColorPickerCtrl::PickMode GuiColorPickMode;

+ 135 - 45
Templates/BaseGame/game/tools/gui/colorPicker.ed.gui

@@ -1,43 +1,32 @@
 //--- OBJECT WRITE BEGIN ---
 $guiContent = new GuiColorPickerCtrl(ColorPickerDlg,EditorGuiGroup) {
-   displayMode = "Dropper"; // this makes the background visible
-   actionOnMove = "1";
-   position = "0 0";
-   extent = "1024 768";
-   minExtent = "8 2";
-   horizSizing = "right";
-   vertSizing = "bottom";
-   profile = "ToolsGuiDefaultProfile";
-   visible = "1";
-   active = "1";
-   Clickable = "1";
-   AffectChildren = "1";
-   tooltipProfile = "GuiToolTipProfile";
-   hovertime = "1000";
-   isContainer = "1";
-   canSave = "1";
-   canSaveDynamicFields = "0";
+      displayMode = "Dropper";
+      extent = "1024 768";
+      profile = "GuiDefaultProfile";
+      command = "%selHue = ColorPickerDlg.getSelectedHue();\n%selSat = ColorPickerDlg.getSelectedSaturation();\n%selBright = ColorPickerDlg.getSelectedBrightness();\n%selAlpha = ColorPickerDlg.getSelectedAlpha();\n\nColorHueRange.setSelectedHue(%selHue);\nColorHueRange.executeUpdate();\n\nColorBlendRange.setSelectedBrightness(%selBright);\nColorBlendRange.setSelectedSaturation(%selSat);\nColorBlendRange.executeUpdate();\n\nColorAlphaRange.setSelectedAlpha(%selAlpha);\nColorAlphaRange.executeUpdate();\n\nColorEyeDropperButton.setStateOn(false);";
+      tooltipProfile = "GuiToolTipProfile";
+      isContainer = "1";
 
    new GuiWindowCtrl() {
-         text = "  ";
-         resizeWidth = "0";
-         resizeHeight = "0";
-         canMinimize = "0";
-         canMaximize = "0";
-         closeCommand = "DoColorPickerCancelCallback(); ColorPickerDlg.getRoot().popDialog(ColorPickerDlg);";
-         position = "33 33";
-         extent = "271 574";
-         horizSizing = "windowRelative";
-         vertSizing = "windowRelative";
-         profile = "ToolsGuiWindowProfile";
-         tooltipProfile = "ToolsGuiToolTipProfile";
+      text = "  ";
+      resizeWidth = "0";
+      resizeHeight = "0";
+      canMinimize = "0";
+      canMaximize = "0";
+      closeCommand = "DoColorPickerCancelCallback(); ColorPickerDlg.getRoot().popDialog(ColorPickerDlg);";
+      position = "33 33";
+      extent = "271 574";
+      horizSizing = "windowRelative";
+      vertSizing = "windowRelative";
+      profile = "ToolsGuiWindowProfile";
+      tooltipProfile = "ToolsGuiToolTipProfile";
 
       new GuiStackControl() {
          padding = "5";
          changeChildSizeToFit = "0";
          changeChildPosition = "0";
          position = "0 24";
-         extent = "271 481";
+         extent = "271 491";
          profile = "GuiDefaultProfile";
          tooltipProfile = "GuiToolTipProfile";
 
@@ -120,7 +109,7 @@ $guiContent = new GuiColorPickerCtrl(ColorPickerDlg,EditorGuiGroup) {
                      position = "213 3";
                      extent = "50 25";
                      profile = "GuiDefaultProfile";
-                     command = "%selHue = ColorNewSelected.getSelectedHue();\n%selSat = ColorNewSelected.getSelectedSaturation();\n%selBright = ColorNewSelected.getSelectedBrightness();\n\nHueTextEditor.setText(%selHue);\nSatTextEditor.setText(%selSat);\nBrightTextEditor.setText(%selBright);\n\n%color = ColorNewSelected.getSelectedColorI();\nRedTextEdit.setText(getWord(%color, 0));\nGreenTextEdit.setText(getWord(%color, 1));\nBlueTextEdit.setText(getWord(%color, 2));\nAlphaTextEdit.setText(getWord(%color, 3));\n\n%hex = ColorRGBToHEX(%color);\nHexTextEditor.setText(%hex);";
+                     command = "%selHue = ColorNewSelected.getSelectedHue();\n%selSat = ColorNewSelected.getSelectedSaturation();\n%selBright = ColorNewSelected.getSelectedBrightness();\n\nHueTextEditor.setText(%selHue);\nSatTextEditor.setText(%selSat);\nBrightTextEditor.setText(%selBright);\n\n%color = $ColorCallbackType == 1 ? ColorNewSelected.getSelectedColorI() : ColorNewSelected.getSelectedLinearColor();\nRedTextEdit.setText(getWord(%color, 0));\nGreenTextEdit.setText(getWord(%color, 1));\nBlueTextEdit.setText(getWord(%color, 2));\nAlphaTextEdit.setText(getWord(%color, 3));\n\n%hex = ColorRGBToHEX(ColorNewSelected.getSelectedColorI());\nHexTextEditor.setText(%hex);";
                      tooltipProfile = "GuiToolTipProfile";
                   };
                   new GuiColorPickerCtrl(ColorOld) {
@@ -268,16 +257,25 @@ $guiContent = new GuiColorPickerCtrl(ColorPickerDlg,EditorGuiGroup) {
                      text = "Apply";
                      position = "211 1";
                      extent = "52 20";
-                     command = "DoColorPickerCallback();";
                      profile = "ToolsGuiButtonProfile";
+                     command = "DoColorPickerCallback();";
                      tooltipProfile = "GuiToolTipProfile";
                   };
                   new GuiButtonCtrl() {
                      text = "Cancel";
                      position = "211 24";
                      extent = "52 20";
-                     command = "DoColorPickerCancelCallback();";
                      profile = "ToolsGuiButtonProfile";
+                     command = "DoColorPickerCancelCallback();";
+                     tooltipProfile = "GuiToolTipProfile";
+                  };
+                  new GuiBitmapButtonCtrl(ColorEyeDropperButton) {
+                     BitmapAsset = "ToolsModule:eyedropper_n_image";
+                     buttonType = "ToggleButton";
+                     position = "223 56";
+                     extent = "25 25";
+                     profile = "ToolsGuiCheckBoxProfile";
+                     command = "ColorPickerDlg.activateEyeDropper();";
                      tooltipProfile = "GuiToolTipProfile";
                   };
                };
@@ -285,20 +283,26 @@ $guiContent = new GuiColorPickerCtrl(ColorPickerDlg,EditorGuiGroup) {
          };
          new GuiRolloutCtrl() {
             caption = ":: Color Palette";
+            margin = "5 5 5 5";
             position = "0 445";
-            extent = "271 36";
+            extent = "271 46";
             profile = "GuiRolloutProfile";
             tooltipProfile = "GuiToolTipProfile";
 
-            new GuiStackControl() {
-               stackingType = "Dynamic";
-               padding = "5";
-               changeChildSizeToFit = "0";
-               position = "0 17";
-               extent = "271 16";
-               profile = "GuiDefaultProfile";
-               tooltipProfile = "GuiToolTipProfile";
-            };
+            new GuiDynamicCtrlArrayControl(ColorPaletteStack) {
+                  colCount = "12";
+                  colSize = "12";
+                  rowSize = "12";
+                  rowCount = "3";
+                  rowSpacing = "1";
+                  colSpacing = "1";
+                  dynamicSize = "1";
+                  padding = "3 3 3 3";
+                  position = "0 17";
+                  extent = "271 47";
+                  profile = "GuiDefaultProfile";
+                  tooltipProfile = "GuiToolTipProfile";
+               };
          };
       };
    };
@@ -344,6 +348,87 @@ function GetColorF( %currentColor, %callback, %root, %updateCallback, %cancelCal
    %root.pushDialog(ColorPickerDlg);
 }
 
+function ColorPaletteStack::onWake(%this)
+{
+   if($Pref::ColorPicker::ColorPalette $= "")
+   {
+      $Pref::ColorPicker::ColorPalette = "#FFFFFF #FF0000 #00FF00 #0000FF";
+   }
+
+   %colorCount = getWordCount($Pref::ColorPicker::ColorPalette);
+   
+   if(%colorCount > 63)
+      %colorCount = 63;
+
+   for(%i=0; %i < %colorCount; %i++)
+   {
+      %hex = getWord($Pref::ColorPicker::ColorPalette, %i);
+      %rgb = ColorHEXToRGB(%hex);
+      %rgb = ColorIntToFloat(%rgb);
+
+      %colorBox = new GuiSwatchButtonCtrl() {
+                  extent = "16 16";
+                  color = %rgb;
+                  profile = "GuiDefaultProfile";
+                  colorHex = %hex;
+                  useMouseEvents = "1";
+                  class = "ColorPaletteSwatch";
+               };
+
+      ColorPaletteStack.Add(%colorBox);
+   }
+
+   %button = new GuiButtonCtrl() {
+               text = "+";
+               extent = "16 16";
+               profile = "ToolsGuiButtonProfile";
+               tooltipProfile = "GuiToolTipProfile";
+               command = "ColorPaletteStack.addCurrentColorToStack();";
+            };
+
+   ColorPaletteStack.Add(%button);
+}
+
+function ColorPaletteStack::addCurrentColorToStack(%this)
+{
+   %hex = HexTextEditor.getValue();
+   //Make sure we have 6 characters
+   while(strlen(%hex) < 6)
+   {
+      %hex = "0" @ %hex;
+   }
+   %hex = strupr(%hex);
+
+   $Pref::ColorPicker::ColorPalette = "#" @ %hex SPC $Pref::ColorPicker::ColorPalette;
+   ColorPaletteStack.clear();
+   ColorPaletteStack.onWake();
+}
+
+function ColorPaletteStack::onSleep(%this)
+{
+   ColorPaletteStack.clear();
+}
+
+function ColorPaletteSwatch::onMouseDown(%this)
+{
+   //Update all the other color fields
+   %rgb = ColorHEXToRGB(%this.colorHex);
+   %hsb = ColorRGBToHSB(%rgb);
+   
+   // these automatically update our ColorNewSelected which
+   // updates all text fields including these.
+   ColorHueRange.setSelectedHue(getWord(%hsb, 0));
+   ColorHueRange.executeUpdate();
+
+   ColorBlendRange.setSelectedSaturation(getWord(%hsb, 1));
+   ColorBlendRange.setSelectedBrightness(getWord(%hsb, 2));
+   ColorBlendRange.executeUpdate();
+
+   // for now just set full alpha until we save out alpha as well
+   ColorAlphaRange.setSelectedAlpha(255);
+   ColorAlphaRange.executeUpdate();
+}
+
 function ColorPickerRGBClass::onValidate(%this)
 {
    %red = RedTextEdit.getValue();
@@ -352,8 +437,13 @@ function ColorPickerRGBClass::onValidate(%this)
    %alpha = AlphaTextEdit.getValue();
 
    //Update all the other color fields
-   %hsb = ColorRGBToHSB(%red SPC %green SPC %blue);
-
+   if( $ColorCallbackType == 1)
+      %hsb = ColorRGBToHSB(%red SPC %green SPC %blue);
+   else
+   {
+      %hsb = ColorLinearRGBToHSB(%red SPC %green SPC %blue);
+      %alpha *= 255.0;
+   }
    // these automatically update our ColorNewSelected which
    // updates all text fields including these.
    ColorHueRange.setSelectedHue(getWord(%hsb, 0));

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/add-simgroup-btn_ctrl_i_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="add-simgroup-btn_ctrl_i_image"
+    imageFile="@assetFile=add-simgroup-btn_ctrl_i.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/add-simgroup-btn_i_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="add-simgroup-btn_i_image"
+    imageFile="@assetFile=add-simgroup-btn_i.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/camera-btn_i_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="camera-btn_i_image"
+    imageFile="@assetFile=camera-btn_i.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/clear-icon_i_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="clear-icon_i_image"
+    imageFile="@assetFile=clear-icon_i.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/delete_i_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="delete_i_image"
+    imageFile="@assetFile=delete_i.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/dropdown-button-arrow_d_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="dropdown-button-arrow_d_image"
+    imageFile="@assetFile=dropdown-button-arrow_d.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/dropdown-button-arrow_h_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="dropdown-button-arrow_h_image"
+    imageFile="@assetFile=dropdown-button-arrow_h.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/dropdown-button-arrow_i_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="dropdown-button-arrow_i_image"
+    imageFile="@assetFile=dropdown-button-arrow_i.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/dropdown-button-arrow_n_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="dropdown-button-arrow_n_image"
+    imageFile="@assetFile=dropdown-button-arrow_n.png"/>

BIN
Templates/BaseGame/game/tools/gui/images/eyedropper_d.png


+ 3 - 0
Templates/BaseGame/game/tools/gui/images/eyedropper_d_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="eyedropper_d_image"
+    imageFile="@assetFile=eyedropper_d.png"/>

BIN
Templates/BaseGame/game/tools/gui/images/eyedropper_h.png


+ 3 - 0
Templates/BaseGame/game/tools/gui/images/eyedropper_h_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="eyedropper_h_image"
+    imageFile="@assetFile=eyedropper_h.png"/>

BIN
Templates/BaseGame/game/tools/gui/images/eyedropper_i.png


+ 3 - 0
Templates/BaseGame/game/tools/gui/images/eyedropper_i_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="eyedropper_i_image"
+    imageFile="@assetFile=eyedropper_i.png"/>

BIN
Templates/BaseGame/game/tools/gui/images/eyedropper_n.png


+ 3 - 0
Templates/BaseGame/game/tools/gui/images/eyedropper_n_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="eyedropper_n_image"
+    imageFile="@assetFile=eyedropper_n.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/folder_d_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="folder_d_image"
+    imageFile="@assetFile=folder_d.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/folder_h_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="folder_h_image"
+    imageFile="@assetFile=folder_h.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/folder_i_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="folder_i_image"
+    imageFile="@assetFile=folder_i.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/folder_n_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="folder_n_image"
+    imageFile="@assetFile=folder_n.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/images_menuGrid_d_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="images_menuGrid_d_image"
+    imageFile="@assetFile=menuGrid_d.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/images_menuGrid_h_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="images_menuGrid_h_image"
+    imageFile="@assetFile=menuGrid_h.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/images_menuGrid_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="images_menuGrid_image"
+    imageFile="@assetFile=menuGrid.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/images_menuGrid_n_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="images_menuGrid_n_image"
+    imageFile="@assetFile=menuGrid_n.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/layers-btn_i_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="layers-btn_i_image"
+    imageFile="@assetFile=layers-btn_i.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/lock_i_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="lock_i_image"
+    imageFile="@assetFile=lock_i.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/new-folder-btn_i_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="new-folder-btn_i_image"
+    imageFile="@assetFile=new-folder-btn_i.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/new_i_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="new_i_image"
+    imageFile="@assetFile=new_i.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/numericslider_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="numericslider_image"
+    imageFile="@assetFile=numericslider.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/open-file_i_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="open-file_i_image"
+    imageFile="@assetFile=open-file_i.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/reset-icon_i_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="reset-icon_i_image"
+    imageFile="@assetFile=reset-icon_i.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/selector-button_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="selector-button_image"
+    imageFile="@assetFile=selector-button.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/tab-border_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="tab-border_image"
+    imageFile="@assetFile=tab-border.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/textEdit_black_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="textEdit_black_image"
+    imageFile="@assetFile=textEdit_black.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/textEdit_blue_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="textEdit_blue_image"
+    imageFile="@assetFile=textEdit_blue.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/textEdit_cyan_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="textEdit_cyan_image"
+    imageFile="@assetFile=textEdit_cyan.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/textEdit_green_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="textEdit_green_image"
+    imageFile="@assetFile=textEdit_green.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/textEdit_magenta_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="textEdit_magenta_image"
+    imageFile="@assetFile=textEdit_magenta.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/textEdit_red_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="textEdit_red_image"
+    imageFile="@assetFile=textEdit_red.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/textEdit_white_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="textEdit_white_image"
+    imageFile="@assetFile=textEdit_white.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/textEdit_yellow_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="textEdit_yellow_image"
+    imageFile="@assetFile=textEdit_yellow.png"/>

+ 3 - 0
Templates/BaseGame/game/tools/gui/images/uv-editor-btn_i_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="uv-editor-btn_i_image"
+    imageFile="@assetFile=uv-editor-btn_i.png"/>