Explorar o código

display correct values

Few fixes to display float values if the inspector field asks for floats
Split Hsb out from colorI now linearColorF can return HSB from its own color without having to go through the colorI conversion, hopefully gets rid of rounding errors etc since we are only doing the calc once.
marauder2k7 hai 7 meses
pai
achega
704e304eef

+ 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;
 }
 

+ 128 - 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(F64 h, F64 s, F64 b) :hue(h), sat(s), brightness(b) {};
+
+   F64 hue;   ///Hue
+   F64 sat;   ///Saturation
+   F64 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() const;
 
    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,72 @@ 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;
+   }
+
+   red = static_cast<F32>(r + m);
+   green = static_cast<F32>(g + m);
+   blue = static_cast<F32>(b + m);
+   alpha = 1.0f; // Default alpha to 1.0
+}
+
+inline Hsb LinearColorF::getHSB() const
+{
+   F32 maxVal = mMax( red, mMax(green, blue));
+   F32 minVal = mMin(red, mMin(green, blue));
+   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 (red == maxVal)
+         hsb.hue = 60.0 * mFmod(((green - blue) / delta), 6.0);
+      else if (green == maxVal)
+         hsb.hue = 60.0 * (((blue - red) / delta) + 2.0);
+      else
+         hsb.hue = 60.0 * (((red - green) / delta) + 4.0);
+
+      if (hsb.hue < 0.0)
+         hsb.hue += 360.0;
+   }
+   else {
+      hsb.hue = 0.0;
+   }
+
+   return hsb;
+}
+
+
 //------------------------------------------------------------------------------
 //-------------------------------------- INLINES (ColorI)
 //
@@ -719,7 +817,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;
@@ -740,22 +838,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
@@ -782,9 +880,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);
 }
 
@@ -799,14 +897,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
       }
@@ -823,14 +921,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
       }

+ 18 - 19
Engine/source/gui/controls/guiColorPicker.cpp

@@ -103,7 +103,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);
 }
 
@@ -123,7 +123,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);
 }
 
@@ -145,8 +145,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)
       {
@@ -226,7 +226,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);
 }
 
@@ -241,7 +241,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;
@@ -317,7 +317,7 @@ 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);
@@ -342,7 +342,7 @@ void GuiColorPickerCtrl::renderEyeDropper()
       RectI magnifierBounds(magnifierPosition, magnifierSize);
 
       ColorI currentColor;
-      currentColor.set(ColorI::Hsb(mSelectedHue, mSelectedSaturation, mSelectedBrightness));
+      currentColor.set(Hsb(mSelectedHue, mSelectedSaturation, mSelectedBrightness));
       currentColor.alpha = mSelectedAlpha;
 
       GFX->getDrawUtil()->drawRectFill(magnifierBounds, currentColor, 2.0f, ColorI::BLACK);
@@ -368,7 +368,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;
@@ -593,7 +593,7 @@ void GuiColorPickerCtrl::onMouseMove(const GuiEvent &event)
       eyeDropperCap->getColor(eyeDropperPos.x, eyeDropperPos.y, sampledColor);
 
       // Convert the sampled color to HSB
-      ColorI::Hsb hsb = sampledColor.getHSB();
+      Hsb hsb = sampledColor.getHSB();
       mSelectedHue = hsb.hue;
       mSelectedSaturation = hsb.sat;
       mSelectedBrightness = hsb.brightness;
@@ -779,7 +779,7 @@ DefineEngineMethod(GuiColorPickerCtrl, getSelectedAlpha, F64, (), , "Gets the cu
 
 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);
@@ -789,26 +789,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;
 }

+ 8 - 4
Templates/BaseGame/game/tools/gui/colorPicker.ed.gui

@@ -109,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) {
@@ -437,8 +437,12 @@ 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);
+   }
    // these automatically update our ColorNewSelected which
    // updates all text fields including these.
    ColorHueRange.setSelectedHue(getWord(%hsb, 0));
@@ -448,7 +452,7 @@ function ColorPickerRGBClass::onValidate(%this)
    ColorBlendRange.setSelectedBrightness(getWord(%hsb, 2));
    ColorBlendRange.executeUpdate();
 
-   ColorAlphaRange.setSelectedAlpha(%alpha);
+   ColorAlphaRange.setSelectedAlpha(%alpha * 255.0);
    ColorAlphaRange.executeUpdate();
 }