Torque3D Documentation / _generateds / guiColorPicker.cpp

guiColorPicker.cpp

Engine/source/gui/controls/guiColorPicker.cpp

More...

Common colors we use

colorAlpha (0.0f, 0.0f, 0.0f, 0.0f)
colorAlphaW (1.0f, 1.0f, 1.0f, 0.0f)
colorWhite (1., 1., 1.)
colorWhiteBlend (1., 1., 1.,.75)

Public Variables

Public Functions

ConsoleDocClass(GuiColorPickerCtrl , "@brief Editor GUI used <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> picking <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classlinearcolorf/">LinearColorF</a> from <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">palette.\n\n</a>" "@note Editor use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a>" "@internal" )
DefineEngineMethod(GuiColorPickerCtrl , getSelectorPos , Point2I , () , "Gets the current position of the selector" )
DefineEngineMethod(GuiColorPickerCtrl , setSelectorColor , void , (LinearColorF color) , "Sets the current position of the selector based on <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">color.n</a>" "@param color Color <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> look <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.n</a>" )
DefineEngineMethod(GuiColorPickerCtrl , setSelectorPos , void , (Point2I newPos) , "Sets the current position of the selector" )
DefineEngineMethod(GuiColorPickerCtrl , updateColor , void , () , "Forces update of pick color" )
ImplementEnumType(GuiColorPickMode , "\n\n" "@ingroup GuiUtil" "@internal" )

Detailed Description

Common colors we use

LinearColorF colorAlpha (0.0f, 0.0f, 0.0f, 0.0f)
LinearColorF colorAlphaW (1.0f, 1.0f, 1.0f, 0.0f)
LinearColorF colorBlack (.0,.0,.0)
LinearColorF colorWhite (1., 1., 1.)
LinearColorF colorWhiteBlend (1., 1., 1.,.75)

Public Variables

 EndImplementEnumType 

Public Functions

ConsoleDocClass(GuiColorPickerCtrl , "@brief Editor GUI used <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> picking <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classlinearcolorf/">LinearColorF</a> from <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">palette.\n\n</a>" "@note Editor use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a>" "@internal" )

DefineEngineMethod(GuiColorPickerCtrl , getSelectorPos , Point2I , () , "Gets the current position of the selector" )

DefineEngineMethod(GuiColorPickerCtrl , setSelectorColor , void , (LinearColorF color) , "Sets the current position of the selector based on <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">color.n</a>" "@param color Color <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> look <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.n</a>" )

DefineEngineMethod(GuiColorPickerCtrl , setSelectorPos , void , (Point2I newPos) , "Sets the current position of the selector" )

DefineEngineMethod(GuiColorPickerCtrl , updateColor , void , () , "Forces update of pick color" )

IMPLEMENT_CONOBJECT(GuiColorPickerCtrl )

ImplementEnumType(GuiColorPickMode , "\n\n" "@ingroup GuiUtil" "@internal" )

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23#include "console/console.h"
 24#include "gfx/gfxDevice.h"
 25#include "console/consoleTypes.h"
 26#include "console/engineAPI.h"
 27#include "gui/core/guiCanvas.h"
 28#include "gui/buttons/guiButtonCtrl.h"
 29#include "gui/core/guiDefaultControlRender.h"
 30#include "gui/controls/guiColorPicker.h"
 31#include "gfx/primBuilder.h"
 32#include "gfx/gfxDrawUtil.h"
 33
 34/// @name Common colors we use
 35/// @{
 36LinearColorF colorWhite(1.,1.,1.);
 37LinearColorF colorWhiteBlend(1.,1.,1.,.75);
 38LinearColorF colorBlack(.0,.0,.0);
 39LinearColorF colorAlpha(0.0f, 0.0f, 0.0f, 0.0f);
 40LinearColorF colorAlphaW(1.0f, 1.0f, 1.0f, 0.0f);
 41
 42ColorI GuiColorPickerCtrl::mColorRange[7] = {
 43   ColorI(255,0,0),     // Red
 44   ColorI(255,0,255),   // Pink
 45   ColorI(0,0,255),     // Blue
 46   ColorI(0,255,255),   // Light blue
 47   ColorI(0,255,0),     // Green
 48   ColorI(255,255,0),   // Yellow
 49   ColorI(255,0,0),     // Red
 50};
 51/// @}
 52
 53IMPLEMENT_CONOBJECT(GuiColorPickerCtrl);
 54
 55ConsoleDocClass( GuiColorPickerCtrl,
 56   "@brief Editor GUI used for picking a LinearColorF from a palette.\n\n"
 57   "@note Editor use only.\n\n"
 58   "@internal"
 59);
 60
 61GuiColorPickerCtrl::GuiColorPickerCtrl()
 62{
 63   setExtent(140, 30);
 64   mDisplayMode = pPallet;
 65   mBaseColor = LinearColorF(1.,.0,1.);
 66   mPickColor = LinearColorF(.0,.0,.0);
 67   mSelectorPos = Point2I(0,0);
 68   mMouseDown = mMouseOver = false;
 69   mActive = true;
 70   mPositionChanged = false;
 71   mSelectorGap = 1;
 72   mActionOnMove = false;
 73   mShowReticle = true;
 74   mSelectColor = false;
 75   mSetColor = mSetColor.BLACK;
 76   mBitmap = NULL;
 77}
 78
 79GuiColorPickerCtrl::~GuiColorPickerCtrl()
 80{
 81   if (mBitmap)
 82   {
 83      delete mBitmap;
 84      mBitmap = NULL;
 85   }
 86}
 87
 88ImplementEnumType( GuiColorPickMode,
 89   "\n\n"
 90   "@ingroup GuiUtil"
 91   "@internal" )
 92   { GuiColorPickerCtrl::pPallet, "Pallete" },
 93   { GuiColorPickerCtrl::pHorizColorRange, "HorizColor"},
 94   { GuiColorPickerCtrl::pVertColorRange, "VertColor" },
 95   { GuiColorPickerCtrl::pHorizColorBrightnessRange, "HorizBrightnessColor" },
 96   { GuiColorPickerCtrl::pVertColorBrightnessRange, "VertBrightnessColor" },
 97   { GuiColorPickerCtrl::pBlendColorRange, "BlendColor" },
 98   { GuiColorPickerCtrl::pHorizAlphaRange, "HorizAlpha" },
 99   { GuiColorPickerCtrl::pVertAlphaRange, "VertAlpha" },
100   { GuiColorPickerCtrl::pDropperBackground, "Dropper" },
101EndImplementEnumType;
102
103void GuiColorPickerCtrl::initPersistFields()
104{
105   addGroup("ColorPicker");
106      addField("baseColor", TypeColorF, Offset(mBaseColor, GuiColorPickerCtrl));
107      addField("pickColor", TypeColorF, Offset(mPickColor, GuiColorPickerCtrl));
108      addField("selectorGap", TypeS32,  Offset(mSelectorGap, GuiColorPickerCtrl)); 
109      addField("displayMode", TYPEID< PickMode >(), Offset(mDisplayMode, GuiColorPickerCtrl) );
110      addField("actionOnMove", TypeBool,Offset(mActionOnMove, GuiColorPickerCtrl));
111      addField("showReticle", TypeBool, Offset(mShowReticle, GuiColorPickerCtrl));
112   endGroup("ColorPicker");
113
114   Parent::initPersistFields();
115}
116
117// Function to draw a box which can have 4 different colors in each corner blended together
118void GuiColorPickerCtrl::drawBlendBox(RectI &bounds, LinearColorF &c1, LinearColorF &c2, LinearColorF &c3, LinearColorF &c4)
119{
120   GFX->setStateBlock(mStateBlock);
121
122   S32 l = bounds.point.x, r = bounds.point.x + bounds.extent.x;
123   S32 t = bounds.point.y, b = bounds.point.y + bounds.extent.y;
124
125   LinearColorF col[4];
126   col[0] = c1;
127   col[1] = c2;
128   col[2] = c3;
129   col[3] = c4;
130
131   //A couple of checks to determine if color blend
132   if (c1 == colorWhite && c3 == colorAlpha && c4 == colorBlack)
133   {
134      //Color
135      PrimBuild::begin(GFXTriangleStrip, 4);
136
137      PrimBuild::color(col[1]);
138      PrimBuild::vertex2i(l, t);
139
140      PrimBuild::color(col[1]);
141      PrimBuild::vertex2i(r, t);
142
143      PrimBuild::color(col[1]);
144      PrimBuild::vertex2i(l, b);
145
146      PrimBuild::color(col[1]);
147      PrimBuild::vertex2i(r, b);
148
149      PrimBuild::end();
150
151      //White
152      PrimBuild::begin(GFXTriangleStrip, 4);
153
154      PrimBuild::color(col[0]);
155      PrimBuild::vertex2i(l, t);
156
157      PrimBuild::color(colorAlphaW);
158      PrimBuild::vertex2i(r, t);
159
160      PrimBuild::color(col[0]);
161      PrimBuild::vertex2i(l, b);
162
163      PrimBuild::color(colorAlphaW);
164      PrimBuild::vertex2i(r, b);
165
166      PrimBuild::end();
167
168      //Black 
169      PrimBuild::begin(GFXTriangleStrip, 4);
170
171      PrimBuild::color(col[2]);
172      PrimBuild::vertex2i(l, t);
173      PrimBuild::color(col[2]);
174      PrimBuild::vertex2i(r, t);
175
176      PrimBuild::color(col[3]);
177      PrimBuild::vertex2i(l, b);
178
179      PrimBuild::color(col[3]);
180      PrimBuild::vertex2i(r, b);
181
182      PrimBuild::end();
183   }
184   else
185   {
186      PrimBuild::begin(GFXTriangleStrip, 4);
187
188      PrimBuild::color(col[0]);
189      PrimBuild::vertex2i(l, t);
190
191      PrimBuild::color(col[1]);
192      PrimBuild::vertex2i(r, t);
193
194      PrimBuild::color(col[3]);
195      PrimBuild::vertex2i(l, b);
196     
197      PrimBuild::color(col[2]);
198      PrimBuild::vertex2i(r, b);
199
200      PrimBuild::end();
201   }
202}
203
204//--------------------------------------------------------------------------
205/// Function to draw a set of boxes blending throughout an array of colors
206void GuiColorPickerCtrl::drawBlendRangeBox(RectI &bounds, bool vertical, U8 numColors, ColorI *colors)
207{
208
209   GFX->setStateBlock(mStateBlock);
210
211   S32 l = bounds.point.x, r = bounds.point.x + bounds.extent.x + 4;
212   S32 t = bounds.point.y, b = bounds.point.y + bounds.extent.y + 4;
213
214   // Calculate increment value
215   S32 x_inc = int(mFloor((r - l) / F32(numColors - 1)));
216   S32 y_inc = int(mFloor((b - t) / F32(numColors - 1)));
217
218   ColorI *col = new ColorI[numColors];
219   dMemcpy(col, colors, numColors * sizeof(ColorI));
220   for (U16 i = 0; i < numColors - 1; i++)
221         col[i] = colors[i];
222
223   for (U16 i = 0; i < numColors - 1; i++)
224   {
225      // This is not efficent, but then again it doesn't really need to be. -pw
226      PrimBuild::begin(GFXTriangleStrip, 4);
227
228      if (!vertical)  // Horizontal (+x)
229      {
230         // First color
231         PrimBuild::color(col[i]);
232         PrimBuild::vertex2i(l, t);
233         PrimBuild::color(col[i + 1]);
234         PrimBuild::vertex2i(l + x_inc, t);
235
236         // Second color
237         PrimBuild::color(col[i]);
238         PrimBuild::vertex2i(l, b);
239         PrimBuild::color(col[i + 1]);
240         PrimBuild::vertex2i(l + x_inc, b);
241         l += x_inc;
242      }
243      else  // Vertical (+y)
244      {
245         // First color
246         PrimBuild::color(col[i]);
247         PrimBuild::vertex2i(l, t);
248         PrimBuild::color(col[i + 1]);
249         PrimBuild::vertex2i(l, t + y_inc);
250
251         // Second color
252         PrimBuild::color(col[i]);
253         PrimBuild::vertex2i(r, t);
254         PrimBuild::color(col[i + 1]);
255         PrimBuild::vertex2i(r, t + y_inc);
256         t += y_inc;
257      }
258      PrimBuild::end();
259   }
260
261   SAFE_DELETE_ARRAY(col);
262}
263
264void GuiColorPickerCtrl::drawSelector(RectI &bounds, Point2I &selectorPos, SelectorMode mode)
265{
266   if( !mShowReticle )
267      return; 
268
269   U16 sMax = mSelectorGap*2;
270   const ColorI color = colorWhiteBlend.toColorI();
271   switch (mode)
272   {
273      case sVertical:
274         // Now draw the vertical selector Up -> Pos
275         if (selectorPos.y != bounds.point.y+1)
276            GFX->getDrawUtil()->drawLine(selectorPos.x, bounds.point.y, selectorPos.x, selectorPos.y-sMax-1, color);
277         // Down -> Pos
278         if (selectorPos.y != bounds.point.y+bounds.extent.y) 
279            GFX->getDrawUtil()->drawLine(selectorPos.x,  selectorPos.y + sMax, selectorPos.x, bounds.point.y + bounds.extent.y, color);
280      break;
281      case sHorizontal:
282         // Now draw the horizontal selector Left -> Pos
283         if (selectorPos.x != bounds.point.x) 
284            GFX->getDrawUtil()->drawLine(bounds.point.x, selectorPos.y-1, selectorPos.x-sMax, selectorPos.y-1, color);
285         // Right -> Pos
286         if (selectorPos.x != bounds.point.x) 
287            GFX->getDrawUtil()->drawLine(bounds.point.x+mSelectorPos.x+sMax, selectorPos.y-1, bounds.point.x + bounds.extent.x, selectorPos.y-1, color);
288      break;
289   }
290}
291
292//--------------------------------------------------------------------------
293/// Function to invoke calls to draw the picker box and selector
294void GuiColorPickerCtrl::renderColorBox(RectI &bounds)
295{
296   RectI pickerBounds;
297   pickerBounds.point.x = bounds.point.x+1;
298   pickerBounds.point.y = bounds.point.y+1;
299   pickerBounds.extent.x = bounds.extent.x-1;
300   pickerBounds.extent.y = bounds.extent.y-1;
301
302   if (mProfile->mBorder)
303      GFX->getDrawUtil()->drawRect(bounds, mProfile->mBorderColor);
304
305   Point2I selectorPos = Point2I(bounds.point.x+mSelectorPos.x+1, bounds.point.y+mSelectorPos.y+1);
306
307   // Draw color box differently depending on mode
308   RectI blendRect;
309   switch (mDisplayMode)
310   {
311   case pHorizColorRange:
312      drawBlendRangeBox( pickerBounds, false, 7, mColorRange);
313      drawSelector( pickerBounds, selectorPos, sVertical );
314   break;
315   case pVertColorRange:
316      drawBlendRangeBox( pickerBounds, true, 7, mColorRange);
317      drawSelector( pickerBounds, selectorPos, sHorizontal );
318   break;
319   case pHorizColorBrightnessRange:
320      blendRect = pickerBounds;
321      blendRect.point.y++;
322      blendRect.extent.y -= 2;
323      drawBlendRangeBox( pickerBounds, false, 7, mColorRange);
324      // This is being drawn slightly offset from the larger rect so as to insure 255 and 0
325      // can both be selected for every color.
326      drawBlendBox( blendRect, colorAlpha, colorAlpha, colorBlack, colorBlack );
327      blendRect.point.y += blendRect.extent.y - 1;
328      blendRect.extent.y = 2;
329      GFX->getDrawUtil()->drawRect( blendRect, colorBlack.toColorI());
330      drawSelector( pickerBounds, selectorPos, sHorizontal );
331      drawSelector( pickerBounds, selectorPos, sVertical );
332   break;
333   case pVertColorBrightnessRange:
334      drawBlendRangeBox( pickerBounds, true, 7, mColorRange);
335      drawBlendBox( pickerBounds, colorAlpha, colorBlack, colorBlack, colorAlpha );
336      drawSelector( pickerBounds, selectorPos, sHorizontal );
337      drawSelector( pickerBounds, selectorPos, sVertical );
338   break;
339   case pHorizAlphaRange:
340      drawBlendBox( pickerBounds, colorBlack, colorWhite, colorWhite, colorBlack );
341      drawSelector( pickerBounds, selectorPos, sVertical );
342   break;
343   case pVertAlphaRange:
344      drawBlendBox( pickerBounds, colorBlack, colorBlack, colorWhite, colorWhite );
345      drawSelector( pickerBounds, selectorPos, sHorizontal ); 
346   break;
347   case pBlendColorRange:
348      drawBlendBox( pickerBounds, colorWhite, mBaseColor, colorAlpha, colorBlack );
349      drawSelector( pickerBounds, selectorPos, sHorizontal );      
350      drawSelector( pickerBounds, selectorPos, sVertical );
351   break;
352   case pDropperBackground:
353   break;
354   case pPallet:
355   default:
356      GFX->getDrawUtil()->drawRectFill( pickerBounds, mBaseColor.toColorI());
357   break;
358   }
359}
360
361void GuiColorPickerCtrl::onRender(Point2I offset, const RectI& updateRect)
362{
363   if (mStateBlock.isNull())
364   {
365      GFXStateBlockDesc desc;
366      desc.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
367      desc.setZReadWrite(false);
368      desc.zWriteEnable = false;
369      desc.setCullMode(GFXCullNone);
370      mStateBlock = GFX->createStateBlock(desc);
371   }
372
373   RectI boundsRect(offset, getExtent());
374   renderColorBox(boundsRect);
375
376   if (mPositionChanged || mBitmap == NULL)
377   {
378      bool nullBitmap = false;
379
380      if (mPositionChanged == false && mBitmap == NULL)
381         nullBitmap = true;
382
383      mPositionChanged = false;
384      Point2I extent = getRoot()->getExtent();
385
386      // If we are anything but a pallete, change the pick color
387      if (mDisplayMode != pPallet)
388      {
389         Point2I resolution = getRoot()->getExtent();
390
391         U32 buf_x = offset.x + mSelectorPos.x + 1;
392         U32 buf_y = resolution.y - (extent.y - (offset.y + mSelectorPos.y + 1));
393
394         GFXTexHandle bb(resolution.x, resolution.y, GFXFormatR8G8B8A8_SRGB, &GFXRenderTargetSRGBProfile, avar("%s() - bb (line %d)", __FUNCTION__, __LINE__));
395
396         Point2I tmpPt(buf_x, buf_y);
397
398         GFXTarget *targ = GFX->getActiveRenderTarget();
399         targ->resolveTo(bb);
400
401         if (mBitmap)
402         {
403            delete mBitmap;
404            mBitmap = NULL;
405         }
406
407         mBitmap = new GBitmap(bb.getWidth(), bb.getHeight(),false,GFXFormatR8G8B8A8);
408
409         bb.copyToBmp(mBitmap);
410
411         if (!nullBitmap)
412         {
413            if (mSelectColor)
414            {
415               Point2I pos = findColor(mSetColor, offset, resolution, *mBitmap);
416               mSetColor = mSetColor.BLACK;
417               mSelectColor = false;
418               setSelectorPos(pos);
419            }
420            else
421            {
422               ColorI tmp;
423               mBitmap->getColor(buf_x, buf_y, tmp);
424
425               mPickColor = (LinearColorF)tmp;
426
427               // Now do onAction() if we are allowed
428               if (mActionOnMove)
429                  onAction();
430            }
431         }
432      }
433   }
434
435   //render the children
436   renderChildControls(offset, updateRect);
437}
438
439void GuiColorPickerCtrl::setSelectorPos(const LinearColorF & color)
440{
441   if (mBitmap && !mPositionChanged)
442   {
443      Point2I resolution = getRoot() ? getRoot()->getExtent() : Point2I(1024, 768);
444      RectI rect(getGlobalBounds());
445      Point2I pos = findColor(color, rect.point, resolution, *mBitmap);
446      mSetColor = mSetColor.BLACK;
447      mSelectColor = false;
448
449      setSelectorPos(pos);
450   }
451   else
452   {
453      mSetColor = color;
454      mSelectColor = true;
455      mPositionChanged = true;
456   }
457}
458
459Point2I GuiColorPickerCtrl::findColor(const LinearColorF & color, const Point2I& offset, const Point2I& resolution, GBitmap& bmp)
460{
461   RectI rect;
462   Point2I ext = getExtent();
463   if (mDisplayMode != pDropperBackground)
464   {
465      ext.x -= 3;
466      ext.y -= 2;
467      rect = RectI(Point2I(1, 1), ext);
468   }
469   else
470   {
471      rect = RectI(Point2I(0, 0), ext);
472   }
473
474   Point2I closestPos(-1, -1);
475
476   /* Debugging
477   char filename[256];
478   dSprintf( filename, 256, "%s.%s", "colorPickerTest", "png" );
479
480   // Open up the file on disk.
481   FileStream fs;
482   if ( !fs.open( filename, Torque::FS::File::Write ) )
483   Con::errorf( "GuiObjectView::saveAsImage() - Failed to open output file '%s'!", filename );
484   else
485   {
486   // Write it and close.
487   bmp.writeBitmap( "png", fs );
488
489   fs.close();
490   }
491   */
492
493   ColorI tmp;
494   U32 buf_x;
495   U32 buf_y;
496   LinearColorF curColor;
497   F32 val(10000.0f);
498   F32 closestVal(10000.0f);
499   bool closestSet = false;
500
501   for (S32 x = rect.point.x; x <= rect.extent.x; x++)
502   {
503      for (S32 y = rect.point.y; y <= rect.extent.y; y++)
504      {
505         buf_x = offset.x + x + 1;
506         buf_y = (resolution.y - (offset.y + y + 1));
507         buf_y = resolution.y - buf_y;
508
509         //Get the color at that position
510         bmp.getColor(buf_x, buf_y, tmp);
511         curColor = (LinearColorF)tmp;
512
513         //Evaluate how close the color is to our desired color
514         val = mFabs(color.red - curColor.red) + mFabs(color.green - curColor.green) + mFabs(color.blue - curColor.blue);
515
516         if (!closestSet)
517         {
518            closestVal = val;
519            closestPos.set(x, y);
520            closestSet = true;
521         }
522         else if (val < closestVal)
523         {
524            closestVal = val;
525            closestPos.set(x, y);
526         }
527      }
528   }
529
530   return closestPos;
531}
532
533void GuiColorPickerCtrl::setSelectorPos(const Point2I &pos)
534{
535   Point2I extent = getExtent();
536   RectI rect;
537   if (mDisplayMode != pDropperBackground) 
538   {
539      extent.x -= 3;
540      extent.y -= 2;
541      rect = RectI(Point2I(1,1), extent);
542   }
543   else
544   {
545      rect = RectI(Point2I(0,0), extent);
546   }
547   
548   if (rect.pointInRect(pos)) 
549   {
550      mSelectorPos = pos;
551      mPositionChanged = true;
552      // We now need to update
553      setUpdate();
554   }
555
556   else
557   {
558      if ((pos.x > rect.point.x) && (pos.x < (rect.point.x + rect.extent.x)))
559         mSelectorPos.x = pos.x;
560      else if (pos.x <= rect.point.x)
561         mSelectorPos.x = rect.point.x;
562      else if (pos.x >= (rect.point.x + rect.extent.x))
563         mSelectorPos.x = rect.point.x + rect.extent.x - 1;
564
565      if ((pos.y > rect.point.y) && (pos.y < (rect.point.y + rect.extent.y)))
566         mSelectorPos.y = pos.y;
567      else if (pos.y <= rect.point.y)
568         mSelectorPos.y = rect.point.y;
569      else if (pos.y >= (rect.point.y + rect.extent.y))
570         mSelectorPos.y = rect.point.y + rect.extent.y - 1;
571
572      mPositionChanged = true;
573      setUpdate();
574   }
575}
576
577void GuiColorPickerCtrl::onMouseDown(const GuiEvent &event)
578{
579   if (!mActive)
580      return;
581   
582   if (mDisplayMode == pDropperBackground)
583      return;
584
585   mouseLock(this);
586   
587   if (mProfile->mCanKeyFocus)
588      setFirstResponder();
589
590   if (mActive && (mDisplayMode != pDropperBackground))
591      onAction();
592
593   // Update the picker cross position
594   if (mDisplayMode != pPallet)
595      setSelectorPos(globalToLocalCoord(event.mousePoint));
596
597   mMouseDown = true;
598}
599
600//--------------------------------------------------------------------------
601void GuiColorPickerCtrl::onMouseDragged(const GuiEvent &event)
602{
603   if ((mActive && mMouseDown) || (mActive && (mDisplayMode == pDropperBackground)))
604   {
605      // Update the picker cross position
606      if (mDisplayMode != pPallet)
607         setSelectorPos(globalToLocalCoord(event.mousePoint));
608   }
609
610   if( !mActionOnMove )
611      execAltConsoleCallback();
612}
613
614void GuiColorPickerCtrl::onMouseMove(const GuiEvent &event)
615{
616   // Only for dropper mode
617   if (mActive && (mDisplayMode == pDropperBackground))
618      setSelectorPos(globalToLocalCoord(event.mousePoint));
619}
620
621void GuiColorPickerCtrl::onMouseEnter(const GuiEvent &event)
622{
623   mMouseOver = true;
624}
625
626void GuiColorPickerCtrl::onMouseLeave(const GuiEvent &)
627{
628   // Reset state
629   mMouseOver = false;
630}
631
632void GuiColorPickerCtrl::onMouseUp(const GuiEvent &)
633{
634   //if we released the mouse within this control, perform the action
635   if (mActive && mMouseDown && (mDisplayMode != pDropperBackground))
636      mMouseDown = false;
637
638   if (mActive && (mDisplayMode == pDropperBackground))
639   {
640      // In a dropper, the alt command executes the mouse up action (to signal stopping)
641      execAltConsoleCallback();
642   }
643
644   mouseUnlock();
645}
646
647const char *GuiColorPickerCtrl::getScriptValue()
648{
649   static char temp[256];
650   LinearColorF color = getValue();
651   dSprintf( temp, 256, "%f %f %f %f", color.red, color.green, color.blue, color.alpha );
652   return temp;
653}
654
655void GuiColorPickerCtrl::setScriptValue(const char *value)
656{
657   LinearColorF newValue;
658   dSscanf(value, "%f %f %f %f", &newValue.red, &newValue.green, &newValue.blue, &newValue.alpha);
659   setValue(newValue);
660}
661
662DefineEngineMethod(GuiColorPickerCtrl, getSelectorPos, Point2I, (), , "Gets the current position of the selector")
663{
664   return object->getSelectorPos();
665}
666
667DefineEngineMethod(GuiColorPickerCtrl, setSelectorPos, void, (Point2I newPos), , "Sets the current position of the selector")
668{
669   object->setSelectorPos(newPos);
670}
671
672DefineEngineMethod(GuiColorPickerCtrl, updateColor, void, (), , "Forces update of pick color")
673{
674   object->updateColor();
675}
676
677DefineEngineMethod(GuiColorPickerCtrl, setSelectorColor, void, (LinearColorF color), ,
678   "Sets the current position of the selector based on a color.n"
679   "@param color Color to look for.n")
680{
681   object->setSelectorPos(color);
682}
683