tge/engine/gui/controls/guiSliderCtrl.cc
2017-04-17 06:17:10 -06:00

320 lines
10 KiB
C++
Executable File

//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "console/consoleTypes.h"
#include "dgl/dgl.h"
#include "dgl/gTexManager.h"
#include "gui/controls/guiSliderCtrl.h"
#include "gui/core/guiDefaultControlRender.h"
#include "platform/event.h"
IMPLEMENT_CONOBJECT(GuiSliderCtrl);
//----------------------------------------------------------------------------
GuiSliderCtrl::GuiSliderCtrl(void)
{
mActive = true;
mRange.set( 0.0f, 1.0f );
mTicks = 10;
mValue = 0.5f;
mThumbSize.set(8,20);
mShiftPoint = 5;
mShiftExtent = 10;
mDisplayValue = false;
mMouseOver = false;
mDepressed = false;
}
//----------------------------------------------------------------------------
void GuiSliderCtrl::initPersistFields()
{
Parent::initPersistFields();
addGroup( "Slider" );
addField("range", TypePoint2F, Offset(mRange, GuiSliderCtrl));
addField("ticks", TypeS32, Offset(mTicks, GuiSliderCtrl));
addField("value", TypeF32, Offset(mValue, GuiSliderCtrl));
endGroup( "Slider" );
}
//----------------------------------------------------------------------------
ConsoleMethod( GuiSliderCtrl, getValue, F32, 2, 2, "Get the position of the slider.")
{
return object->getValue();
}
//----------------------------------------------------------------------------
void GuiSliderCtrl::setScriptValue(const char *val)
{
mValue = dAtof(val);
updateThumb(mValue);
}
//----------------------------------------------------------------------------
bool GuiSliderCtrl::onWake()
{
if (! Parent::onWake())
return false;
if(mThumbSize.y + mProfile->mFont->getHeight()-4 <= mBounds.extent.y)
mDisplayValue = true;
else
mDisplayValue = false;
updateThumb( mValue, true );
mHasTexture = mProfile->constructBitmapArray() >= NumBitmaps;
if( mHasTexture )
mBitmapBounds = mProfile->mBitmapArrayRects.address();
return true;
}
//----------------------------------------------------------------------------
void GuiSliderCtrl::onMouseDown(const GuiEvent &event)
{
if ( !mActive || !mAwake || !mVisible )
return;
mouseLock();
setFirstResponder();
mDepressed = true;
Point2I curMousePos = globalToLocalCoord(event.mousePoint);
F32 value;
if (mBounds.extent.x >= mBounds.extent.y)
value = F32(curMousePos.x-mShiftPoint) / F32(mBounds.extent.x-mShiftExtent)*(mRange.y-mRange.x) + mRange.x;
else
value = F32(curMousePos.y) / F32(mBounds.extent.y)*(mRange.y-mRange.x) + mRange.x;
updateThumb(value);
}
//----------------------------------------------------------------------------
void GuiSliderCtrl::onMouseDragged(const GuiEvent &event)
{
if ( !mActive || !mAwake || !mVisible )
return;
Point2I curMousePos = globalToLocalCoord(event.mousePoint);
F32 value;
if (mBounds.extent.x >= mBounds.extent.y)
value = F32(curMousePos.x-mShiftPoint) / F32(mBounds.extent.x-mShiftExtent)*(mRange.y-mRange.x) + mRange.x;
else
value = F32(curMousePos.y) / F32(mBounds.extent.y)*(mRange.y-mRange.x) + mRange.x;
if (value > mRange.y)
value = mRange.y;
else if (value < mRange.x)
value = mRange.x;
if ((event.modifier & SI_SHIFT) && mTicks > 2) {
// 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");
}
Con::executef(this, 1, "onMouseDragged");
updateThumb(value);
}
//----------------------------------------------------------------------------
void GuiSliderCtrl::onMouseUp(const GuiEvent &)
{
if ( !mActive || !mAwake || !mVisible )
return;
mDepressed = false;
mouseUnlock();
if (mConsoleCommand[0])
{
char buf[16];
dSprintf(buf, sizeof(buf), "%d", getId());
Con::setVariable("$ThisControl", buf);
Con::evaluate(mConsoleCommand, false);
}
}
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(Canvas->mBounds.extent.x)*2.0f-1.0f)*0.8f;
AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonOver);
alxPlay(handle);
}
mMouseOver = true;
}
}
void GuiSliderCtrl::onMouseLeave(const GuiEvent &)
{
setUpdate();
if(isMouseLocked())
mDepressed = false;
mMouseOver = false;
}
//----------------------------------------------------------------------------
void GuiSliderCtrl::updateThumb( F32 value, bool onWake )
{
mValue = value;
// clamp the thumb to legal values
if (mValue < mRange.x) mValue = mRange.x;
if (mValue > mRange.y) mValue = mRange.y;
Point2I ext = mBounds.extent;
ext.x -= ( mShiftExtent + mThumbSize.x ) / 2;
// update the bounding thumb rect
if (mBounds.extent.x >= mBounds.extent.y)
{ // 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 && mAltConsoleCommand[0] )
Con::evaluate( mAltConsoleCommand, false );
}
//----------------------------------------------------------------------------
void GuiSliderCtrl::onRender(Point2I offset, const RectI &updateRect)
{
Point2I pos(offset.x+mShiftPoint, offset.y);
Point2I ext(mBounds.extent.x - mShiftExtent, mBounds.extent.y);
RectI thumb = mThumb;
if( mHasTexture )
{
S32 index = SliderButtonNormal;
if(mMouseOver)
index = SliderButtonHighlight;
dglClearBitmapModulation();
//left border
dglDrawBitmapSR(mProfile->mTextureHandle, Point2I(offset.x,offset.y + (mBounds.extent.y / 4)), mBitmapBounds[SliderLineLeft]);
//right border
dglDrawBitmapSR(mProfile->mTextureHandle, Point2I(offset.x + mBounds.extent.x - mBitmapBounds[SliderLineRight].extent.x, offset.y + (mBounds.extent.y / 4)), 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 = mBounds.extent.x - mBitmapBounds[SliderLineLeft].extent.x - mBitmapBounds[SliderLineRight].extent.x;
destRect.point.y = offset.y + (mBounds.extent.y / 4);
destRect.extent.y = mBitmapBounds[SliderLineCenter].extent.y;
RectI stretchRect;
stretchRect = mBitmapBounds[SliderLineCenter];
stretchRect.inset(1,0);
dglDrawBitmapStretchSR(mProfile->mTextureHandle, destRect, stretchRect);
//draw our control slider button
thumb.point += pos;
dglDrawBitmapSR(mProfile->mTextureHandle,Point2I(thumb.point.x,offset.y),mBitmapBounds[index]);
}
else if (mBounds.extent.x >= mBounds.extent.y)
{
Point2I mid(ext.x, ext.y/2);
if(mDisplayValue)
mid.set(ext.x, mThumbSize.y/2);
glColor4f(mProfile->mFontColor.red, mProfile->mFontColor.green, mProfile->mFontColor.blue, 1);
glBegin(GL_LINES);
// horz rule
glVertex2i(pos.x, pos.y+mid.y);
glVertex2i(pos.x+mid.x, pos.y+mid.y);
// tick marks
for (U32 t = 0; t <= (mTicks+1); t++)
{
S32 x = (S32)(F32(mid.x-1)/F32(mTicks+1)*F32(t));
glVertex2i(pos.x+x, pos.y+mid.y-mShiftPoint);
glVertex2i(pos.x+x, pos.y+mid.y+mShiftPoint);
}
glEnd();
}
else
{
Point2I mid(ext.x/2, ext.y);
glColor4f(mProfile->mFontColor.red, mProfile->mFontColor.green, mProfile->mFontColor.blue, 1);
glBegin(GL_LINES);
// horz rule
glVertex2i(pos.x+mid.x, pos.y);
glVertex2i(pos.x+mid.x, pos.y+mid.y);
// tick marks
for (U32 t = 0; t <= (mTicks+1); t++)
{
S32 y = (S32)(F32(mid.y-1)/F32(mTicks+1)*F32(t));
glVertex2i(pos.x+mid.x-mShiftPoint, pos.y+y);
glVertex2i(pos.x+mid.x+mShiftPoint, pos.y+y);
}
glEnd();
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+mBounds.extent.x)
textStart.x -=((textStart.x + txt_w) - (offset.x+mBounds.extent.x));
dglSetBitmapModulation(mProfile->mFontColor);
dglDrawText(mProfile->mFont, textStart, buf, mProfile->mFontColors);
}
renderChildControls(offset, updateRect);
}