//----------------------------------------------------------------------------- // 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); }