Torque3D Documentation / _generateds / guiSliderCtrl.cpp

guiSliderCtrl.cpp

Engine/source/gui/controls/guiSliderCtrl.cpp

More...

Public Functions

ConsoleDocClass(GuiSliderCtrl , "@brief A <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> that displays <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> between its minimal and maximal bounds using <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slider placed on <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> vertical " "or horizontal <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">axis.\n\n</a>" "A slider displays <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> and allows that <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be changed by dragging <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> thumb <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> along the axis of the " "slider. In this way, the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> is changed between its allowed minimum and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">maximum.\n\n</a>" "To hook up script code <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> changes of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slider, use the #command and #altCommand properties. #command is " "executed once the thumb is released by the user whereas #altCommand is called any time the slider <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> changes. " "When changing the slider <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> from script, however , trigger of #altCommand is suppressed by <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">default.\n\n</a>" "The orientation of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slider is automatically determined from the ratio of its width <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> its height. If <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slider is " "taller than it is wide, it will be rendered with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> vertical orientation. If it is wider than it is tall)
DefineEngineMethod(GuiSliderCtrl , getValue , F32 , () , "Get the current <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of the slider based on the position of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">thumb.\n</a>" "@return Slider position (from range.x <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> range.y)." )
DefineEngineMethod(GuiSliderCtrl , isThumbBeingDragged , bool , () , "Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the thumb is currently being dragged by the user. This method is mainly useful " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> scrubbing type sliders where the slider position is sync'd <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> changing value. When the " "user is dragging the thumb, however , the sync 'ing should pause and not get in the way of the user." )
DefineEngineMethod(GuiSliderCtrl , setValue , void , (F32 pos, bool doCallback) , (false) , "Set position of the thumb on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">slider.\n</a>" "@param pos New slider position (from range.x <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> range.y)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param doCallback If true, the altCommand callback will be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">invoked\n</a>" )
IMPLEMENT_CALLBACK(GuiSliderCtrl , onMouseDragged , void , () , () , "Called when the left mouse button is dragged across the slider." )

Detailed Description

Public Functions

ConsoleDocClass(GuiSliderCtrl , "@brief A <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> that displays <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> between its minimal and maximal bounds using <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slider placed on <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> vertical " "or horizontal <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">axis.\n\n</a>" "A slider displays <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> and allows that <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be changed by dragging <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> thumb <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> along the axis of the " "slider. In this way, the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> is changed between its allowed minimum and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">maximum.\n\n</a>" "To hook up script code <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> changes of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slider, use the #command and #altCommand properties. #command is " "executed once the thumb is released by the user whereas #altCommand is called any time the slider <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> changes. " "When changing the slider <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> from script, however , trigger of #altCommand is suppressed by <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">default.\n\n</a>" "The orientation of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slider is automatically determined from the ratio of its width <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> its height. If <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slider is " "taller than it is wide, it will be rendered with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> vertical orientation. If it is wider than it is tall)

DefineEngineMethod(GuiSliderCtrl , getValue , F32 , () , "Get the current <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of the slider based on the position of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">thumb.\n</a>" "@return Slider position (from range.x <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> range.y)." )

DefineEngineMethod(GuiSliderCtrl , isThumbBeingDragged , bool , () , "Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the thumb is currently being dragged by the user. This method is mainly useful " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> scrubbing type sliders where the slider position is sync'd <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> changing value. When the " "user is dragging the thumb, however , the sync 'ing should pause and not get in the way of the user." )

DefineEngineMethod(GuiSliderCtrl , setValue , void , (F32 pos, bool doCallback) , (false) , "Set position of the thumb on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">slider.\n</a>" "@param pos New slider position (from range.x <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> range.y)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param doCallback If true, the altCommand callback will be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">invoked\n</a>" )

IMPLEMENT_CALLBACK(GuiSliderCtrl , onMouseDragged , void , () , () , "Called when the left mouse button is dragged across the slider." )

IMPLEMENT_CONOBJECT(GuiSliderCtrl )

  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
 24#include "console/console.h"
 25#include "console/consoleTypes.h"
 26#include "console/engineAPI.h"
 27#include "gfx/gfxTextureManager.h"
 28#include "gui/controls/guiSliderCtrl.h"
 29#include "gui/core/guiDefaultControlRender.h"
 30#include "gfx/primBuilder.h"
 31#include "gfx/gfxDrawUtil.h"
 32#include "sfx/sfxSystem.h"
 33#include "sfx/sfxTrack.h"
 34
 35
 36IMPLEMENT_CONOBJECT( GuiSliderCtrl );
 37
 38ConsoleDocClass( GuiSliderCtrl,
 39   "@brief A control that displays a value between its minimal and maximal bounds using a slider placed on a vertical "
 40   "or horizontal axis.\n\n"
 41   
 42   "A slider displays a value and allows that value to be changed by dragging a thumb control along the axis of the "
 43   "slider.  In this way, the value is changed between its allowed minimum and maximum.\n\n"
 44   
 45   "To hook up script code to the value changes of a slider, use the #command and #altCommand properties.  #command is "
 46   "executed once the thumb is released by the user whereas #altCommand is called any time the slider value changes. "
 47   "When changing the slider value from script, however, trigger of #altCommand is suppressed by default.\n\n"
 48   
 49   "The orientation of a slider is automatically determined from the ratio of its width to its height.  If a slider is "
 50   "taller than it is wide, it will be rendered with a vertical orientation.  If it is wider than it is tall, it will be "
 51   "rendered with a horizontal orientation.\n\n"
 52   
 53   "The rendering of a slider depends on the bitmap in the slider's profile.  This bitmap must be a bitmap array comprised "
 54   "of at least five bitmap rectangles.  The rectangles are used such that:\n\n"
 55   
 56   "- Rectangle #1: Left edge of slider\n"
 57   "- Rectangle #2: Center piece of slider; this is stretched between the left and right edge\n"
 58   "- Rectangle #3: Right edge of slider\n"
 59   "- Rectangle #4: Thumb button in normal state\n"
 60   "- Rectangle #5: Thumb button in highlighted (mouse-over) state\n\n"
 61   
 62   "@tsexample\n"
 63      "// Create a sound source and a slider that changes the volume of the source.\n"
 64      "\n"
 65      "%source = sfxPlayOnce( \"art/sound/testing\", AudioLoop2D );\n"
 66      "\n"
 67      "new GuiSlider()\n"
 68      "{\n"
 69      "   // Update the sound source volume when the slider is being dragged and released.\n"
 70      "   command = %source @ \".setVolume( $ThisControl.value );\";\n"
 71      "\n"
 72      "   // Limit the range to 0..1 since that is the allowable range for sound volumes.\n"
 73      "   range = \"0 1\";\n"
 74      "};\n"
 75   "@endtsexample\n\n"
 76   
 77   "@see GuiTextEditSliderCtrl\n"
 78   "@see GuiTextEditSliderBitmapCtrl\n\n"
 79   
 80   "@ingroup GuiValues"
 81);
 82
 83
 84IMPLEMENT_CALLBACK( GuiSliderCtrl, onMouseDragged, void, (), (),
 85   "Called when the left mouse button is dragged across the slider." );
 86
 87
 88//----------------------------------------------------------------------------
 89
 90GuiSliderCtrl::GuiSliderCtrl()
 91   : mRange( 0., 1.f ),
 92     mTicks( 10 ),
 93     mRenderTicks(true),
 94     mSnap( false ),
 95     mValue( 0.5f ),
 96     mThumbSize( 8, 20 ),
 97     mShiftPoint( 5 ),
 98     mShiftExtent( 10 ),
 99     mIncAmount( 0.f ),
100     mDisplayValue( false ),
101     mMouseOver( false ),
102     mDepressed( false ),
103     mMouseDragged( false ),
104     mHasTexture(false),
105     mUseFillBar(false),
106     mFillBarColor(ColorI(255,255,255)),
107     mBitmapBounds(NULL)
108{
109}
110
111//----------------------------------------------------------------------------
112
113void GuiSliderCtrl::initPersistFields()
114{
115   addGroup( "Slider" );
116   
117      addField( "range", TypePoint2F, Offset( mRange, GuiSliderCtrl ),
118         "Min and max values corresponding to left and right slider position." );
119      addField( "ticks", TypeS32, Offset( mTicks, GuiSliderCtrl ),
120         "Spacing between tick marks in pixels. 0=off." );
121      addField( "snap",  TypeBool, Offset( mSnap,  GuiSliderCtrl ),
122         "Whether to snap the slider to tick marks." );
123      addProtectedField( "value", TypeF32, Offset( mValue, GuiSliderCtrl ),
124         _setValue, defaultProtectedGetFn,
125         "The value corresponding to the current slider position." );
126      addField("useFillBar", TypeBool, Offset(mUseFillBar, GuiSliderCtrl),
127         "Whether to render the tick marks.");
128      addField("fillBarColor", TypeColorI, Offset(mFillBarColor, GuiSliderCtrl),
129         "Whether to render the tick marks.");
130      addField("renderTicks", TypeBool, Offset(mRenderTicks, GuiSliderCtrl),
131         "Whether to render the tick marks.");
132      
133   endGroup( "Slider" );
134
135   Parent::initPersistFields();
136}
137
138//----------------------------------------------------------------------------
139
140void GuiSliderCtrl::setValue(F32 val, bool doCallback)
141{
142   _updateThumb( val, mSnap, false, doCallback );
143}
144
145//----------------------------------------------------------------------------
146
147void GuiSliderCtrl::setActive( bool value )
148{
149   if( !value && mDepressed )
150   {
151      // We're in the middle of a drag.  Finish it here as once we've
152      // been deactivated, we are not going to see a mouse-up event.
153
154      mDepressed = false;
155      mouseUnlock();
156      execConsoleCallback();
157   }
158
159   Parent::setActive( value );
160}
161
162//----------------------------------------------------------------------------
163
164bool GuiSliderCtrl::onWake()
165{
166   if( !Parent::onWake() )
167      return false;
168      
169   mHasTexture = mProfile->constructBitmapArray() >= NumBitmaps;  
170   if( mHasTexture )
171   {
172      mBitmapBounds = mProfile->mBitmapArrayRects.address();
173      mThumbSize = Point2I( mBitmapBounds[ SliderButtonNormal ].extent.x, mBitmapBounds[ SliderButtonNormal ].extent.y );
174   }
175
176   F32 value;
177   if( mConsoleVariable[ 0 ] )
178      value = getFloatVariable();
179   else
180      value = mValue;
181
182   mValue = mClampF( value, mRange.x, mRange.y );
183
184   // mouse scroll increment percentage is 5% of the range
185   mIncAmount = ( ( mRange.y - mRange.x ) * 0.05 );
186
187   if( ( mThumbSize.y + mProfile->mFont->getHeight() - 4 ) <= getExtent().y )
188      mDisplayValue = true;
189   else
190      mDisplayValue = false;
191
192   _updateThumb( mValue, mSnap, true );
193
194   return true;
195}
196
197//----------------------------------------------------------------------------
198
199void GuiSliderCtrl::onMouseDown(const GuiEvent &event)
200{
201   if ( !mActive || !mAwake || !mVisible )
202      return;
203
204   mouseLock();
205   setFirstResponder();
206   mDepressed = true;
207
208   Point2I curMousePos = globalToLocalCoord( event.mousePoint );
209   F32 value;
210   if (getWidth() >= getHeight())
211      value = F32(curMousePos.x-mShiftPoint) / F32(getWidth()-mShiftExtent)*(mRange.y-mRange.x) + mRange.x;
212   else
213      value = F32(curMousePos.y) / F32(getHeight())*(mRange.y-mRange.x) + mRange.x;
214   
215   _updateThumb( value, mSnap || ( event.modifier & SI_SHIFT ) );
216}
217
218//----------------------------------------------------------------------------
219
220void GuiSliderCtrl::onMouseDragged( const GuiEvent &event )
221{
222   if ( !mActive || !mAwake || !mVisible )
223      return;
224      
225   mMouseDragged = true;
226
227   F32 value = _getThumbValue( event );
228   _updateThumb( value, mSnap || ( event.modifier & SI_SHIFT ) );
229
230   onMouseDragged_callback();
231}
232
233//----------------------------------------------------------------------------
234
235void GuiSliderCtrl::onMouseUp( const GuiEvent& event )
236{
237   if ( !mActive || !mAwake || !mVisible )
238      return;
239
240   mouseUnlock();
241
242   mDepressed = false;
243   mMouseDragged = false;
244
245   _updateThumb( _getThumbValue( event ), event.modifier & SI_SHIFT );
246   
247   execConsoleCallback();
248}   
249
250//----------------------------------------------------------------------------
251
252void GuiSliderCtrl::onMouseEnter(const GuiEvent &event)
253{
254   setUpdate();
255   if( isMouseLocked() )
256   {
257      mDepressed = true;
258      mMouseOver = true;
259   }
260   else
261   {
262      if( mActive && mProfile->mSoundButtonOver )
263      {
264         //F32 pan = (F32(event.mousePoint.x)/F32(getRoot()->getWidth())*2.0f-1.0f)*0.8f;
265         SFX->playOnce( mProfile->mSoundButtonOver );
266      }
267      
268      mMouseOver = true;
269   }
270}
271
272//----------------------------------------------------------------------------
273
274void GuiSliderCtrl::onMouseLeave(const GuiEvent &)
275{
276   setUpdate();
277   if( isMouseLocked() )
278      mDepressed = false;
279   mMouseOver = false;
280}
281//----------------------------------------------------------------------------
282
283bool GuiSliderCtrl::onMouseWheelUp(const GuiEvent &event)
284{
285   if ( !mActive || !mAwake || !mVisible )
286      return Parent::onMouseWheelUp(event);
287
288   _updateThumb( mValue + mIncAmount, ( event.modifier & SI_SHIFT ) );
289   execConsoleCallback();
290
291   return true;
292}
293
294//----------------------------------------------------------------------------
295
296bool GuiSliderCtrl::onMouseWheelDown(const GuiEvent &event)
297{
298   if ( !mActive || !mAwake || !mVisible )
299      return Parent::onMouseWheelUp(event);
300
301   _updateThumb( mValue - mIncAmount, ( event.modifier & SI_SHIFT ) );   
302   execConsoleCallback();
303
304   return true;
305}
306
307//----------------------------------------------------------------------------
308
309void GuiSliderCtrl::_updateThumb( F32 _value, bool snap, bool onWake, bool doCallback )
310{      
311   if( snap && mTicks > 0 )
312   {
313      // If the shift key is held, snap to the nearest tick, if any are being drawn
314
315      F32 tickStep = (mRange.y - mRange.x) / F32(mTicks + 1);
316
317      F32 tickSteps = (_value - mRange.x) / tickStep;
318      S32 actualTick = S32(tickSteps + 0.5);
319
320      _value = actualTick * tickStep + mRange.x;
321   }
322   
323   // Clamp the thumb to legal values.
324
325   if( _value < mRange.x )
326      _value = mRange.x;
327   if( _value > mRange.y )
328      _value = mRange.y;
329      
330   // If value hasn't changed and this isn't the initial update on
331   // waking, do nothing.
332
333   if( mValue == _value && !onWake )
334      return;
335
336   mValue = _value;
337
338   Point2I ext = getExtent();
339   ext.x -= ( mShiftExtent + mThumbSize.x ) / 2;
340   // update the bounding thumb rect
341   if (getWidth() >= getHeight())
342   {  // HORZ thumb
343      S32 mx = (S32)((F32(ext.x) * (mValue-mRange.x) / (mRange.y-mRange.x)));
344      S32 my = ext.y/2;
345      if(mDisplayValue)
346         my = mThumbSize.y/2;
347
348      mThumb.point.x  = mx - (mThumbSize.x/2);
349      mThumb.point.y  = my - (mThumbSize.y/2);
350      mThumb.extent   = mThumbSize;
351   }
352   else
353   {  // VERT thumb
354      S32 mx = ext.x/2;
355      S32 my = (S32)((F32(ext.y) * (mValue-mRange.x) / (mRange.y-mRange.x)));
356      mThumb.point.x  = mx - (mThumbSize.y/2);
357      mThumb.point.y  = my - (mThumbSize.x/2);
358      mThumb.extent.x = mThumbSize.y;
359      mThumb.extent.y = mThumbSize.x;
360   }
361   
362   setFloatVariable(mValue);
363   setUpdate();
364
365   // Use the alt console command if you want to continually update:
366   if ( !onWake && doCallback )
367      execAltConsoleCallback();
368}
369
370//----------------------------------------------------------------------------
371
372void GuiSliderCtrl::onRender(Point2I offset, const RectI &updateRect)
373{
374   Point2I pos(offset.x+mShiftPoint, offset.y);
375   Point2I ext(getWidth() - mShiftExtent, getHeight());
376   RectI thumb = mThumb;
377
378   GFXDrawUtil* drawUtil = GFX->getDrawUtil();
379
380   if (mUseFillBar)
381   {
382
383      drawUtil->drawRectFill(RectI(offset.x, offset.y, getWidth() * mValue, getHeight()), mFillBarColor);
384
385      renderChildControls(offset, updateRect);
386      return;
387   }
388
389   if( mHasTexture )
390   {
391      if(mTicks > 0 && mRenderTicks)
392      {
393         // TODO: tick marks should be positioned based on the bitmap dimensions.
394         Point2I mid(ext.x, ext.y/2);
395         Point2I oldpos = pos;
396         pos += Point2I(1, 0);
397
398         PrimBuild::color4f( 0.f, 0.f, 0.f, 1.f );
399         PrimBuild::begin( GFXLineList, ( mTicks + 2 ) * 2 );
400         // tick marks
401         for (U32 t = 0; t <= (mTicks+1); t++)
402         {
403            S32 x = (S32)(F32(mid.x+1)/<a href="/coding/file/types_8h/#types_8h_1a841d3674577a1e86afdc2f4845f46c4b">F32</a>(mTicks+1)*F32(t)) + pos.x;
404            S32 y = pos.y + mid.y;
405            PrimBuild::vertex2i(x, y + mShiftPoint);
406            PrimBuild::vertex2i(x, y + mShiftPoint*2 + 2);
407         }
408         PrimBuild::end();
409         // TODO: it would be nice, if the primitive builder were a little smarter,
410         // so that we could change colors midstream.
411         PrimBuild::color4f(0.9f, 0.9f, 0.9f, 1.0f);
412         PrimBuild::begin( GFXLineList, ( mTicks + 2 ) * 2 );
413         // tick marks
414         for (U32 t = 0; t <= (mTicks+1); t++)
415         {
416            S32 x = (S32)(F32(mid.x+1)/<a href="/coding/file/types_8h/#types_8h_1a841d3674577a1e86afdc2f4845f46c4b">F32</a>(mTicks+1)*F32(t)) + pos.x + 1;
417            S32 y = pos.y + mid.y + 1;
418            PrimBuild::vertex2i(x, y + mShiftPoint );
419            PrimBuild::vertex2i(x, y + mShiftPoint * 2 + 3);
420         }
421         PrimBuild::end();
422         pos = oldpos;
423      }
424
425      S32 index = SliderButtonNormal;
426      if(mMouseOver)
427         index = SliderButtonHighlight;
428      drawUtil->clearBitmapModulation();
429
430      //left border
431      drawUtil->drawBitmapSR(mProfile->mTextureObject, Point2I(offset.x,offset.y), mBitmapBounds[SliderLineLeft]);
432      //right border
433      drawUtil->drawBitmapSR(mProfile->mTextureObject, Point2I(offset.x + getWidth() - mBitmapBounds[SliderLineRight].extent.x, offset.y), mBitmapBounds[SliderLineRight]);
434
435
436      //draw our center piece to our slider control's border and stretch it
437      RectI destRect;   
438      destRect.point.x = offset.x + mBitmapBounds[SliderLineLeft].extent.x;
439      destRect.extent.x = getWidth() - mBitmapBounds[SliderLineLeft].extent.x - mBitmapBounds[SliderLineRight].extent.x;
440      destRect.point.y = offset.y;
441      destRect.extent.y = mBitmapBounds[SliderLineCenter].extent.y;
442
443      RectI stretchRect;
444      stretchRect = mBitmapBounds[SliderLineCenter];
445      stretchRect.inset(1,0);
446
447      drawUtil->drawBitmapStretchSR(mProfile->mTextureObject, destRect, stretchRect);
448
449      //draw our control slider button 
450      thumb.point += pos;
451      drawUtil->drawBitmapSR(mProfile->mTextureObject,Point2I(thumb.point.x,offset.y ),mBitmapBounds[index]);
452
453   }
454   else if (getWidth() >= getHeight())
455   {
456      Point2I mid(ext.x, ext.y/2);
457      if(mDisplayValue)
458         mid.set(ext.x, mThumbSize.y/2);
459
460      PrimBuild::color4f( 0.f, 0.f, 0.f, 1.f );
461      PrimBuild::begin( GFXLineList, ( mTicks + 2 ) * 2 + 2);
462         // horz rule
463         PrimBuild::vertex2i( pos.x, pos.y + mid.y );
464         PrimBuild::vertex2i( pos.x + mid.x, pos.y + mid.y );
465
466         // tick marks
467         if (mRenderTicks)
468         {
469            for (U32 t = 0; t <= (mTicks + 1); t++)
470            {
471               S32 x = (S32)(F32(mid.x - 1) / F32(mTicks + 1) * F32(t));
472               PrimBuild::vertex2i(pos.x + x, pos.y + mid.y - mShiftPoint);
473               PrimBuild::vertex2i(pos.x + x, pos.y + mid.y + mShiftPoint);
474            }
475         }
476         PrimBuild::end();
477   }
478   else
479   {
480      Point2I mid(ext.x/2, ext.y);
481
482      PrimBuild::color4f( 0.f, 0.f, 0.f, 1.f );
483      PrimBuild::begin( GFXLineList, ( mTicks + 2 ) * 2 + 2);
484         // horz rule
485         PrimBuild::vertex2i( pos.x + mid.x, pos.y );
486         PrimBuild::vertex2i( pos.x + mid.x, pos.y + mid.y );
487
488         // tick marks
489         if (mRenderTicks)
490         {
491            for (U32 t = 0; t <= (mTicks + 1); t++)
492            {
493               S32 y = (S32)(F32(mid.y - 1) / F32(mTicks + 1) * F32(t));
494               PrimBuild::vertex2i(pos.x + mid.x - mShiftPoint, pos.y + y);
495               PrimBuild::vertex2i(pos.x + mid.x + mShiftPoint, pos.y + y);
496            }
497         }
498         PrimBuild::end();
499      mDisplayValue = false;
500   }
501   // draw the thumb
502   thumb.point += pos;
503   renderRaisedBox(thumb, mProfile);
504
505   if(mDisplayValue)
506   {
507      char buf[20];
508      dSprintf(buf,sizeof(buf),"%0.3f",mValue);
509
510      Point2I textStart = thumb.point;
511
512      S32 txt_w = mProfile->mFont->getStrWidth((const UTF8 *)buf);
513
514      textStart.x += (S32)((thumb.extent.x/2.0f));
515      textStart.y += thumb.extent.y - 2; //19
516      textStart.x -= (txt_w/2);
517      if(textStart.x < offset.x)
518         textStart.x = offset.x;
519      else if(textStart.x + txt_w > offset.x+getWidth())
520         textStart.x -=((textStart.x + txt_w) - (offset.x+getWidth()));
521
522      drawUtil->setBitmapModulation(mProfile->mFontColor);
523      drawUtil->drawText(mProfile->mFont, textStart, buf, mProfile->mFontColors);
524   }
525   renderChildControls(offset, updateRect);
526}
527
528//----------------------------------------------------------------------------
529
530bool GuiSliderCtrl::resize( const Point2I& newPosition, const Point2I& newSize )
531{
532   if( !Parent::resize( newPosition, newSize ) )
533      return false;
534   
535   _updateThumb( mValue, false, true, false );
536   return true;
537}
538
539//----------------------------------------------------------------------------
540
541void GuiSliderCtrl::parentResized( const RectI& oldParentRect, const RectI& newParentRect )
542{
543   Parent::parentResized( oldParentRect, newParentRect );
544   
545   _updateThumb( mValue, false, true, false );
546}
547
548//----------------------------------------------------------------------------
549
550F32 GuiSliderCtrl::_getThumbValue( const GuiEvent& event )
551{
552   Point2I curMousePos = globalToLocalCoord( event.mousePoint );
553
554   F32 value;
555   if( getWidth() >= getHeight() )
556      value = F32( curMousePos.x - mShiftPoint ) / F32( getWidth() - mShiftExtent ) * ( mRange.y - mRange.x ) + mRange.x;
557   else
558      value = F32( curMousePos.y ) / F32( getHeight() ) * ( mRange.y - mRange.x ) + mRange.x;
559
560   if(value > mRange.y )
561      value = mRange.y;
562   else if( value < mRange.x )
563      value = mRange.x;
564
565   if( mSnap || ( event.modifier & SI_SHIFT && mTicks >= 1 ) )
566   {
567      // If the shift key is held, snap to the nearest tick, if any are being drawn
568
569      F32 tickStep = ( mRange.y - mRange.x ) / F32( mTicks + 1 );
570
571      F32 tickSteps = (value - mRange.x ) / tickStep;
572      S32 actualTick = S32( tickSteps + 0.5 );
573
574      value = actualTick * tickStep + mRange.x;
575      AssertFatal( value <= mRange.y && value>= mRange.x, "Error, out of bounds value generated from shift-snap of slider" );
576   }
577
578   return value;
579}
580
581//=============================================================================
582//    Console Methods.
583//=============================================================================
584
585//-----------------------------------------------------------------------------
586
587DefineEngineMethod( GuiSliderCtrl, getValue, F32, (),,
588   "Get the current value of the slider based on the position of the thumb.\n"
589   "@return Slider position (from range.x to range.y)." )
590{
591   return object->getValue();
592}
593
594//----------------------------------------------------------------------------
595
596DefineEngineMethod( GuiSliderCtrl, setValue, void, ( F32 pos, bool doCallback ), ( false ),
597   "Set position of the thumb on the slider.\n"
598   "@param pos New slider position (from range.x to range.y)\n"
599   "@param doCallback If true, the altCommand callback will be invoked\n" )
600{
601   object->setValue( pos, doCallback );
602}
603
604//----------------------------------------------------------------------------
605
606DefineEngineMethod( GuiSliderCtrl, isThumbBeingDragged, bool, (),,
607   "Returns true if the thumb is currently being dragged by the user.  This method is mainly useful "
608   "for scrubbing type sliders where the slider position is sync'd to a changing value.  When the "
609   "user is dragging the thumb, however, the sync'ing should pause and not get in the way of the user." )
610{
611   return object->isThumbBeingDragged();
612}
613