mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
616 lines
20 KiB
C++
616 lines
20 KiB
C++
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "console/console.h"
|
|
#include "console/consoleTypes.h"
|
|
#include "console/engineAPI.h"
|
|
#include "gfx/gfxTextureManager.h"
|
|
#include "gui/controls/guiSliderCtrl.h"
|
|
#include "gui/core/guiDefaultControlRender.h"
|
|
#include "gfx/primBuilder.h"
|
|
#include "gfx/gfxDrawUtil.h"
|
|
#include "sfx/sfxSystem.h"
|
|
#include "sfx/sfxTrack.h"
|
|
|
|
|
|
IMPLEMENT_CONOBJECT( GuiSliderCtrl );
|
|
|
|
ConsoleDocClass( GuiSliderCtrl,
|
|
"@brief A control that displays a value between its minimal and maximal bounds using a slider placed on a vertical "
|
|
"or horizontal axis.\n\n"
|
|
|
|
"A slider displays a value and allows that value to be changed by dragging a thumb control along the axis of the "
|
|
"slider. In this way, the value is changed between its allowed minimum and maximum.\n\n"
|
|
|
|
"To hook up script code to the value changes of 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 value changes. "
|
|
"When changing the slider value from script, however, trigger of #altCommand is suppressed by default.\n\n"
|
|
|
|
"The orientation of a slider is automatically determined from the ratio of its width to its height. If a slider is "
|
|
"taller than it is wide, it will be rendered with a vertical orientation. If it is wider than it is tall, it will be "
|
|
"rendered with a horizontal orientation.\n\n"
|
|
|
|
"The rendering of a slider depends on the bitmap in the slider's profile. This bitmap must be a bitmap array comprised "
|
|
"of at least five bitmap rectangles. The rectangles are used such that:\n\n"
|
|
|
|
"- Rectangle #1: Left edge of slider\n"
|
|
"- Rectangle #2: Center piece of slider; this is stretched between the left and right edge\n"
|
|
"- Rectangle #3: Right edge of slider\n"
|
|
"- Rectangle #4: Thumb button in normal state\n"
|
|
"- Rectangle #5: Thumb button in highlighted (mouse-over) state\n\n"
|
|
|
|
"@tsexample\n"
|
|
"// Create a sound source and a slider that changes the volume of the source.\n"
|
|
"\n"
|
|
"%source = sfxPlayOnce( \"art/sound/testing\", AudioLoop2D );\n"
|
|
"\n"
|
|
"new GuiSlider()\n"
|
|
"{\n"
|
|
" // Update the sound source volume when the slider is being dragged and released.\n"
|
|
" command = %source @ \".setVolume( $ThisControl.value );\";\n"
|
|
"\n"
|
|
" // Limit the range to 0..1 since that is the allowable range for sound volumes.\n"
|
|
" range = \"0 1\";\n"
|
|
"};\n"
|
|
"@endtsexample\n\n"
|
|
|
|
"@see GuiTextEditSliderCtrl\n"
|
|
"@see GuiTextEditSliderBitmapCtrl\n\n"
|
|
|
|
"@ingroup GuiValues"
|
|
);
|
|
|
|
|
|
IMPLEMENT_CALLBACK( GuiSliderCtrl, onMouseDragged, void, (), (),
|
|
"Called when the left mouse button is dragged across the slider." );
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
GuiSliderCtrl::GuiSliderCtrl()
|
|
: mRange( 0., 1.f ),
|
|
mTicks( 10 ),
|
|
mRenderTicks(true),
|
|
mSnap( false ),
|
|
mValue( 0.5f ),
|
|
mThumbSize( 8, 20 ),
|
|
mShiftPoint( 5 ),
|
|
mShiftExtent( 10 ),
|
|
mIncAmount( 0.f ),
|
|
mDisplayValue( false ),
|
|
mMouseOver( false ),
|
|
mDepressed( false ),
|
|
mMouseDragged( false ),
|
|
mHasTexture(false),
|
|
mUseFillBar(false),
|
|
mFillBarColor(ColorI(255,255,255)),
|
|
mBitmapBounds(NULL)
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void GuiSliderCtrl::initPersistFields()
|
|
{
|
|
addGroup( "Slider" );
|
|
|
|
addField( "range", TypePoint2F, Offset( mRange, GuiSliderCtrl ),
|
|
"Min and max values corresponding to left and right slider position." );
|
|
addField( "ticks", TypeS32, Offset( mTicks, GuiSliderCtrl ),
|
|
"Spacing between tick marks in pixels. 0=off." );
|
|
addField( "snap", TypeBool, Offset( mSnap, GuiSliderCtrl ),
|
|
"Whether to snap the slider to tick marks." );
|
|
addProtectedField( "value", TypeF32, Offset( mValue, GuiSliderCtrl ),
|
|
_setValue, defaultProtectedGetFn,
|
|
"The value corresponding to the current slider position." );
|
|
addField("useFillBar", TypeBool, Offset(mUseFillBar, GuiSliderCtrl),
|
|
"Whether to render the tick marks.");
|
|
addField("fillBarColor", TypeColorI, Offset(mFillBarColor, GuiSliderCtrl),
|
|
"Whether to render the tick marks.");
|
|
addField("renderTicks", TypeBool, Offset(mRenderTicks, GuiSliderCtrl),
|
|
"Whether to render the tick marks.");
|
|
|
|
endGroup( "Slider" );
|
|
|
|
Parent::initPersistFields();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void GuiSliderCtrl::setValue(F32 val, bool doCallback)
|
|
{
|
|
_updateThumb( val, mSnap, false, doCallback );
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void GuiSliderCtrl::setActive( bool value )
|
|
{
|
|
if( !value && mDepressed )
|
|
{
|
|
// We're in the middle of a drag. Finish it here as once we've
|
|
// been deactivated, we are not going to see a mouse-up event.
|
|
|
|
mDepressed = false;
|
|
mouseUnlock();
|
|
execConsoleCallback();
|
|
}
|
|
|
|
Parent::setActive( value );
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool GuiSliderCtrl::onWake()
|
|
{
|
|
if( !Parent::onWake() )
|
|
return false;
|
|
|
|
mHasTexture = mProfile->constructBitmapArray() >= NumBitmaps;
|
|
if( mHasTexture )
|
|
{
|
|
mBitmapBounds = mProfile->mBitmapArrayRects.address();
|
|
mThumbSize = Point2I( mBitmapBounds[ SliderButtonNormal ].extent.x, mBitmapBounds[ SliderButtonNormal ].extent.y );
|
|
}
|
|
|
|
F32 value;
|
|
if( mConsoleVariable[ 0 ] )
|
|
value = getFloatVariable();
|
|
else
|
|
value = mValue;
|
|
|
|
mValue = mClampF( value, mRange.x, mRange.y );
|
|
|
|
// mouse scroll increment percentage is 5% of the range
|
|
mIncAmount = ( ( mRange.y - mRange.x ) * 0.05 );
|
|
|
|
if( ( mThumbSize.y + mProfile->mFont->getHeight() - 4 ) <= getExtent().y )
|
|
mDisplayValue = true;
|
|
else
|
|
mDisplayValue = false;
|
|
|
|
_updateThumb( mValue, mSnap, true );
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void GuiSliderCtrl::onMouseDown(const GuiEvent &event)
|
|
{
|
|
if ( !mActive || !mAwake || !mVisible )
|
|
return;
|
|
|
|
mouseLock();
|
|
setFirstResponder();
|
|
mDepressed = true;
|
|
|
|
if (mProfile->isSoundButtonDownValid())
|
|
SFX->playOnce(mProfile->getSoundButtonDownProfile());
|
|
|
|
Point2I curMousePos = globalToLocalCoord( event.mousePoint );
|
|
F32 value;
|
|
if (getWidth() >= getHeight())
|
|
value = F32(curMousePos.x-mShiftPoint) / F32(getWidth()-mShiftExtent)*(mRange.y-mRange.x) + mRange.x;
|
|
else
|
|
value = F32(curMousePos.y) / F32(getHeight())*(mRange.y-mRange.x) + mRange.x;
|
|
|
|
_updateThumb( value, mSnap || ( event.modifier & SI_SHIFT ) );
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void GuiSliderCtrl::onMouseDragged( const GuiEvent &event )
|
|
{
|
|
if ( !mActive || !mAwake || !mVisible )
|
|
return;
|
|
|
|
mMouseDragged = true;
|
|
|
|
F32 value = _getThumbValue( event );
|
|
_updateThumb( value, mSnap || ( event.modifier & SI_SHIFT ) );
|
|
|
|
onMouseDragged_callback();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void GuiSliderCtrl::onMouseUp( const GuiEvent& event )
|
|
{
|
|
if ( !mActive || !mAwake || !mVisible )
|
|
return;
|
|
|
|
mouseUnlock();
|
|
|
|
mDepressed = false;
|
|
mMouseDragged = false;
|
|
|
|
_updateThumb( _getThumbValue( event ), event.modifier & SI_SHIFT );
|
|
|
|
execConsoleCallback();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void GuiSliderCtrl::onMouseEnter(const GuiEvent &event)
|
|
{
|
|
setUpdate();
|
|
if( isMouseLocked() )
|
|
{
|
|
mDepressed = true;
|
|
mMouseOver = true;
|
|
}
|
|
else
|
|
{
|
|
if( mActive && mProfile->mSoundButtonOver )
|
|
{
|
|
//F32 pan = (F32(event.mousePoint.x)/F32(getRoot()->getWidth())*2.0f-1.0f)*0.8f;
|
|
if (mProfile->isSoundButtonOverValid())
|
|
SFX->playOnce(mProfile->getSoundButtonOverProfile());
|
|
}
|
|
|
|
mMouseOver = true;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void GuiSliderCtrl::onMouseLeave(const GuiEvent &)
|
|
{
|
|
setUpdate();
|
|
if( isMouseLocked() )
|
|
mDepressed = false;
|
|
mMouseOver = false;
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool GuiSliderCtrl::onMouseWheelUp(const GuiEvent &event)
|
|
{
|
|
if ( !mActive || !mAwake || !mVisible )
|
|
return Parent::onMouseWheelUp(event);
|
|
|
|
_updateThumb( mValue + mIncAmount, ( event.modifier & SI_SHIFT ) );
|
|
execConsoleCallback();
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool GuiSliderCtrl::onMouseWheelDown(const GuiEvent &event)
|
|
{
|
|
if ( !mActive || !mAwake || !mVisible )
|
|
return Parent::onMouseWheelUp(event);
|
|
|
|
_updateThumb( mValue - mIncAmount, ( event.modifier & SI_SHIFT ) );
|
|
execConsoleCallback();
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void GuiSliderCtrl::_updateThumb( F32 _value, bool snap, bool onWake, bool doCallback )
|
|
{
|
|
if( snap && mTicks > 0 )
|
|
{
|
|
// If the shift key is held, snap to the nearest tick, if any are being drawn
|
|
|
|
F32 tickStep = (mRange.y - mRange.x) / F32(mTicks + 1);
|
|
|
|
F32 tickSteps = (_value - mRange.x) / tickStep;
|
|
S32 actualTick = S32(tickSteps + 0.5);
|
|
|
|
_value = actualTick * tickStep + mRange.x;
|
|
}
|
|
|
|
// Clamp the thumb to legal values.
|
|
|
|
if( _value < mRange.x )
|
|
_value = mRange.x;
|
|
if( _value > mRange.y )
|
|
_value = mRange.y;
|
|
|
|
// If value hasn't changed and this isn't the initial update on
|
|
// waking, do nothing.
|
|
|
|
if( mValue == _value && !onWake )
|
|
return;
|
|
|
|
mValue = _value;
|
|
|
|
Point2I ext = getExtent();
|
|
ext.x -= ( mShiftExtent + mThumbSize.x ) / 2;
|
|
// update the bounding thumb rect
|
|
if (getWidth() >= getHeight())
|
|
{ // HORZ thumb
|
|
S32 mx = (S32)((F32(ext.x) * (mValue-mRange.x) / (mRange.y-mRange.x)));
|
|
S32 my = ext.y/2;
|
|
if(mDisplayValue)
|
|
my = mThumbSize.y/2;
|
|
|
|
mThumb.point.x = mx - (mThumbSize.x/2);
|
|
mThumb.point.y = my - (mThumbSize.y/2);
|
|
mThumb.extent = mThumbSize;
|
|
}
|
|
else
|
|
{ // VERT thumb
|
|
S32 mx = ext.x/2;
|
|
S32 my = (S32)((F32(ext.y) * (mValue-mRange.x) / (mRange.y-mRange.x)));
|
|
mThumb.point.x = mx - (mThumbSize.y/2);
|
|
mThumb.point.y = my - (mThumbSize.x/2);
|
|
mThumb.extent.x = mThumbSize.y;
|
|
mThumb.extent.y = mThumbSize.x;
|
|
}
|
|
|
|
setFloatVariable(mValue);
|
|
setUpdate();
|
|
|
|
// Use the alt console command if you want to continually update:
|
|
if ( !onWake && doCallback )
|
|
execAltConsoleCallback();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void GuiSliderCtrl::onRender(Point2I offset, const RectI &updateRect)
|
|
{
|
|
Point2I pos(offset.x+mShiftPoint, offset.y);
|
|
Point2I ext(getWidth() - mShiftExtent, getHeight());
|
|
RectI thumb = mThumb;
|
|
|
|
GFXDrawUtil* drawUtil = GFX->getDrawUtil();
|
|
|
|
if (mUseFillBar)
|
|
{
|
|
|
|
drawUtil->drawRectFill(RectI(offset.x, offset.y, getWidth() * mValue, getHeight()), mFillBarColor);
|
|
|
|
renderChildControls(offset, updateRect);
|
|
return;
|
|
}
|
|
|
|
if( mHasTexture )
|
|
{
|
|
if(mTicks > 0 && mRenderTicks)
|
|
{
|
|
// TODO: tick marks should be positioned based on the bitmap dimensions.
|
|
Point2I mid(ext.x, ext.y/2);
|
|
Point2I oldpos = pos;
|
|
pos += Point2I(1, 0);
|
|
|
|
PrimBuild::color4f( 0.f, 0.f, 0.f, 1.f );
|
|
PrimBuild::begin( GFXLineList, ( mTicks + 2 ) * 2 );
|
|
// tick marks
|
|
for (U32 t = 0; t <= (mTicks+1); t++)
|
|
{
|
|
S32 x = (S32)(F32(mid.x+1)/F32(mTicks+1)*F32(t)) + pos.x;
|
|
S32 y = pos.y + mid.y;
|
|
PrimBuild::vertex2i(x, y + mShiftPoint);
|
|
PrimBuild::vertex2i(x, y + mShiftPoint*2 + 2);
|
|
}
|
|
PrimBuild::end();
|
|
// TODO: it would be nice, if the primitive builder were a little smarter,
|
|
// so that we could change colors midstream.
|
|
PrimBuild::color4f(0.9f, 0.9f, 0.9f, 1.0f);
|
|
PrimBuild::begin( GFXLineList, ( mTicks + 2 ) * 2 );
|
|
// tick marks
|
|
for (U32 t = 0; t <= (mTicks+1); t++)
|
|
{
|
|
S32 x = (S32)(F32(mid.x+1)/F32(mTicks+1)*F32(t)) + pos.x + 1;
|
|
S32 y = pos.y + mid.y + 1;
|
|
PrimBuild::vertex2i(x, y + mShiftPoint );
|
|
PrimBuild::vertex2i(x, y + mShiftPoint * 2 + 3);
|
|
}
|
|
PrimBuild::end();
|
|
pos = oldpos;
|
|
}
|
|
|
|
S32 index = SliderButtonNormal;
|
|
if(mMouseOver)
|
|
index = SliderButtonHighlight;
|
|
drawUtil->clearBitmapModulation();
|
|
|
|
//left border
|
|
drawUtil->drawBitmapSR(mProfile->getBitmapResource(), Point2I(offset.x,offset.y), mBitmapBounds[SliderLineLeft]);
|
|
//right border
|
|
drawUtil->drawBitmapSR(mProfile->getBitmapResource(), Point2I(offset.x + getWidth() - mBitmapBounds[SliderLineRight].extent.x, offset.y), mBitmapBounds[SliderLineRight]);
|
|
|
|
|
|
//draw our center piece to our slider control's border and stretch it
|
|
RectI destRect;
|
|
destRect.point.x = offset.x + mBitmapBounds[SliderLineLeft].extent.x;
|
|
destRect.extent.x = getWidth() - mBitmapBounds[SliderLineLeft].extent.x - mBitmapBounds[SliderLineRight].extent.x;
|
|
destRect.point.y = offset.y;
|
|
destRect.extent.y = mBitmapBounds[SliderLineCenter].extent.y;
|
|
|
|
RectI stretchRect;
|
|
stretchRect = mBitmapBounds[SliderLineCenter];
|
|
stretchRect.inset(1,0);
|
|
|
|
drawUtil->drawBitmapStretchSR(mProfile->getBitmapResource(), destRect, stretchRect);
|
|
|
|
//draw our control slider button
|
|
thumb.point += pos;
|
|
drawUtil->drawBitmapSR(mProfile->getBitmapResource(),Point2I(thumb.point.x,offset.y ),mBitmapBounds[index]);
|
|
|
|
}
|
|
else if (getWidth() >= getHeight())
|
|
{
|
|
Point2I mid(ext.x, ext.y/2);
|
|
if(mDisplayValue)
|
|
mid.set(ext.x, mThumbSize.y/2);
|
|
|
|
PrimBuild::color4f( 0.f, 0.f, 0.f, 1.f );
|
|
PrimBuild::begin( GFXLineList, ( mTicks + 2 ) * 2 + 2);
|
|
// horz rule
|
|
PrimBuild::vertex2i( pos.x, pos.y + mid.y );
|
|
PrimBuild::vertex2i( pos.x + mid.x, pos.y + mid.y );
|
|
|
|
// tick marks
|
|
if (mRenderTicks)
|
|
{
|
|
for (U32 t = 0; t <= (mTicks + 1); t++)
|
|
{
|
|
S32 x = (S32)(F32(mid.x - 1) / F32(mTicks + 1) * F32(t));
|
|
PrimBuild::vertex2i(pos.x + x, pos.y + mid.y - mShiftPoint);
|
|
PrimBuild::vertex2i(pos.x + x, pos.y + mid.y + mShiftPoint);
|
|
}
|
|
}
|
|
PrimBuild::end();
|
|
}
|
|
else
|
|
{
|
|
Point2I mid(ext.x/2, ext.y);
|
|
|
|
PrimBuild::color4f( 0.f, 0.f, 0.f, 1.f );
|
|
PrimBuild::begin( GFXLineList, ( mTicks + 2 ) * 2 + 2);
|
|
// horz rule
|
|
PrimBuild::vertex2i( pos.x + mid.x, pos.y );
|
|
PrimBuild::vertex2i( pos.x + mid.x, pos.y + mid.y );
|
|
|
|
// tick marks
|
|
if (mRenderTicks)
|
|
{
|
|
for (U32 t = 0; t <= (mTicks + 1); t++)
|
|
{
|
|
S32 y = (S32)(F32(mid.y - 1) / F32(mTicks + 1) * F32(t));
|
|
PrimBuild::vertex2i(pos.x + mid.x - mShiftPoint, pos.y + y);
|
|
PrimBuild::vertex2i(pos.x + mid.x + mShiftPoint, pos.y + y);
|
|
}
|
|
}
|
|
PrimBuild::end();
|
|
mDisplayValue = false;
|
|
}
|
|
// draw the thumb
|
|
thumb.point += pos;
|
|
renderRaisedBox(thumb, mProfile);
|
|
|
|
if(mDisplayValue)
|
|
{
|
|
char buf[20];
|
|
dSprintf(buf,sizeof(buf),"%0.3f",mValue);
|
|
|
|
Point2I textStart = thumb.point;
|
|
|
|
S32 txt_w = mProfile->mFont->getStrWidth((const UTF8 *)buf);
|
|
|
|
textStart.x += (S32)((thumb.extent.x/2.0f));
|
|
textStart.y += thumb.extent.y - 2; //19
|
|
textStart.x -= (txt_w/2);
|
|
if(textStart.x < offset.x)
|
|
textStart.x = offset.x;
|
|
else if(textStart.x + txt_w > offset.x+getWidth())
|
|
textStart.x -=((textStart.x + txt_w) - (offset.x+getWidth()));
|
|
|
|
drawUtil->setBitmapModulation(mProfile->mFontColor);
|
|
drawUtil->drawText(mProfile->mFont, textStart, buf, mProfile->mFontColors);
|
|
}
|
|
renderChildControls(offset, updateRect);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool GuiSliderCtrl::resize( const Point2I& newPosition, const Point2I& newSize )
|
|
{
|
|
if( !Parent::resize( newPosition, newSize ) )
|
|
return false;
|
|
|
|
_updateThumb( mValue, false, true, false );
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void GuiSliderCtrl::parentResized( const RectI& oldParentRect, const RectI& newParentRect )
|
|
{
|
|
Parent::parentResized( oldParentRect, newParentRect );
|
|
|
|
_updateThumb( mValue, false, true, false );
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
F32 GuiSliderCtrl::_getThumbValue( const GuiEvent& event )
|
|
{
|
|
Point2I curMousePos = globalToLocalCoord( event.mousePoint );
|
|
|
|
F32 value;
|
|
if( getWidth() >= getHeight() )
|
|
value = F32( curMousePos.x - mShiftPoint ) / F32( getWidth() - mShiftExtent ) * ( mRange.y - mRange.x ) + mRange.x;
|
|
else
|
|
value = F32( curMousePos.y ) / F32( getHeight() ) * ( mRange.y - mRange.x ) + mRange.x;
|
|
|
|
if(value > mRange.y )
|
|
value = mRange.y;
|
|
else if( value < mRange.x )
|
|
value = mRange.x;
|
|
|
|
if( mSnap || ( event.modifier & SI_SHIFT && mTicks >= 1 ) )
|
|
{
|
|
// If the shift key is held, snap to the nearest tick, if any are being drawn
|
|
|
|
F32 tickStep = ( mRange.y - mRange.x ) / F32( mTicks + 1 );
|
|
|
|
F32 tickSteps = (value - mRange.x ) / tickStep;
|
|
S32 actualTick = S32( tickSteps + 0.5 );
|
|
|
|
value = actualTick * tickStep + mRange.x;
|
|
AssertFatal( value <= mRange.y && value >= mRange.x, "Error, out of bounds value generated from shift-snap of slider" );
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
//=============================================================================
|
|
// Console Methods.
|
|
//=============================================================================
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
DefineEngineMethod( GuiSliderCtrl, getValue, F32, (),,
|
|
"Get the current value of the slider based on the position of the thumb.\n"
|
|
"@return Slider position (from range.x to range.y)." )
|
|
{
|
|
return object->getValue();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
DefineEngineMethod( GuiSliderCtrl, setValue, void, ( F32 pos, bool doCallback ), ( false ),
|
|
"Set position of the thumb on the slider.\n"
|
|
"@param pos New slider position (from range.x to range.y)\n"
|
|
"@param doCallback If true, the altCommand callback will be invoked\n" )
|
|
{
|
|
object->setValue( pos, doCallback );
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
DefineEngineMethod( GuiSliderCtrl, isThumbBeingDragged, bool, (),,
|
|
"Returns true if the thumb is currently being dragged by the user. This method is mainly useful "
|
|
"for scrubbing type sliders where the slider position is sync'd to 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." )
|
|
{
|
|
return object->isThumbBeingDragged();
|
|
}
|