//----------------------------------------------------------------------------- // 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; } //---------------------------------------------------------------------------- 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 ); return true; } //---------------------------------------------------------------------------- void GuiSliderCtrl::onMouseDown(const GuiEvent &event) { if ( !mActive || !mAwake || !mVisible ) return; mouseLock(); setFirstResponder(); 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"); } updateThumb(value); } //---------------------------------------------------------------------------- void GuiSliderCtrl::onMouseUp(const GuiEvent &) { if ( !mActive || !mAwake || !mVisible ) return; mouseUnlock(); if (mConsoleCommand[0]) { char buf[16]; dSprintf(buf, sizeof(buf), "%d", getId()); Con::setVariable("$ThisControl", buf); Con::evaluate(mConsoleCommand, 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); if (mBounds.extent.x >= mBounds.extent.y) { Point2I mid(ext.x, ext.y/2); if(mDisplayValue) mid.set(ext.x, mThumbSize.y/2); glColor4f(0, 0, 0, 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(0, 0, 0, 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 RectI thumb = mThumb; 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); }