mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 04:34:48 +00:00
Adds ability to control button margin of IconButtons Adds ability to define button offset of window controls Add mouse drag callback for window controls Tweaks colors of gui slider control Tweak to line split for text edit slider bitmap control Tweaks to colors for text edit slider control Tweaks to colors for Edit control Tweaks to default menubar height
617 lines
20 KiB
C++
617 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()
|
|
{
|
|
docsURL;
|
|
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.6f, 0.6f, 0.6f, 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();
|
|
}
|