Game Development Community

Plan for justin`dujardin

by Justin DuJardin · 05/11/2005 (2:56 pm) · 4 comments

Ahhhh finals are just about enough to make me pull my hair out, and have brought with them the unfortunate side effect of leaving me little to no time to care for my love that is Torque(2D/GE/SE). However, I did manage to get a small amount of time to go ahead and update something that has bothered me for some time in TGE-GuiScrollControls not scrolling while your mouse is depressed.

It's really quite a simple fix, and perhaps not the best fix available but it suits my needs just fine, so I figured I could spare ten minutes to share it with the rest of the community!

For this update, we'll only be working in two files
GuiScrollCtrl.cc
GuiScrollCtrl.h

First off we need a way to update our scroll according to if the cursor is depressed, so we'll need to add a onPreRender function to our ScrollControl, mine is shown below, which can be pasted into GuiScrollCtrl.cc with no problems.

guiScrollCtrl.cc
void GuiScrollCtrl::onPreRender()
{
   Parent::onPreRender();

   // Short circuit if not depressed to save cycles
   if( stateDepressed != true )
      return;

   //default to one second, though it shouldn't be necessary
   U32 timeThreshold = 1000; 

   // We don't want to scroll by pages at an interval the same as when we're scrolling
   // using the arrow buttons, so adjust accordingly.
   switch( curHitRegion )
   {
   case UpPage:
   case DownPage:
   case LeftPage:
   case RightPage:
      timeThreshold = 200;
      break;
   case UpArrow:
   case DownArrow:
   case LeftArrow:
   case RightArrow:
      timeThreshold = 20;
      break;
   default:
      // Neither a button or a page, don't scroll (shouldn't get here)
      return;
      break;
   };

   S32 timeElapsed = Platform::getVirtualMilliseconds() - mLastUpdated;

   if ( ( timeElapsed > 0 ) && ( timeElapsed > timeThreshold ) )
   {

      mLastUpdated = Platform::getVirtualMilliseconds();   
      scrollByRegion(curHitRegion);
   }

}

You'll also want to add a declaration of this function in GuiScrollCtrl.h which I opted to place directly above the onRender declaraction, mine is shown below.

guiScrollCtrl.h
[b]void onPreRender();[/b]
   void onRender(Point2I offset, const RectI &updateRect);

Note : For those of you that are unfamiliar with onPreRender, it is invoked each time the GuiCanvas renders a frame, so you may want to be careful about doing heavy processing in the onPreRender function of your controls. It is however, rather useful when writing controls that need to act on their own at given intervals.

Next you'll want to note that the above function makes use of a class member that is not defined in GuiScrollCtrl, mLastUpdated. mLastUpdated is simply a S32 that I've defined in GuiScrollCtrl.h that holds the virtualMilliseconds of the last time we performed an action, in this case, scrolled continuously while the mouse was depressed over either our scroll controls arrow buttons or on the scroll control to scroll by page. So you'll need to add the member mLastUpdated to your GuiScrollCtrl.h in the protected section, I placed mine directly below mThumbMouseDelta's declaration as shown below

guiScrollCtrl.h
S32 mThumbMouseDelta;

   [b]S32 mLastUpdated;[/b]

Now that we have our mLastUpdated readily accessible we want to go ahead and do one more thing, which is we need to initialize it when we mouse down on the scroll control. We could opt not to do so for the sake of having not to modify our onMouseDown, but that would (and does) result in some erratic behavior when scrolling (our preRender starts scrolling immediately after we mouse down). So what we're going to do is give it a delay before it starts scrolling itself, so we click and 0.5 seconds later if we're still mouse down'd then it will start scrolling. So we'll add this line of code to our onMouseDown procedure, I added it immediately after the assignment of stateDepressed = true as shown below.

guiScrollCtrl.cc - onMouseDown
void GuiScrollCtrl::onMouseDown(const GuiEvent &event)
{
   mouseLock();
   setFirstResponder();

   setUpdate();

   Point2I curMousePos = globalToLocalCoord(event.mousePoint);
   curHitRegion = findHitRegion(curMousePos);
   stateDepressed = true;
[b]
   // Set a 0.5 second delay before we start scrolling
   mLastUpdated = Platform::getVirtualMilliseconds() + 500; 
[/b]
   scrollByRegion(curHitRegion);

   if (curHitRegion == VertThumb)
   {
      mChildRelPosAnchor = mChildRelPos;
      mThumbMouseDelta = curMousePos.y - mVThumbPos;
   }
   else if (curHitRegion == HorizThumb)
   {
      mChildRelPosAnchor = mChildRelPos;
      mThumbMouseDelta = curMousePos.x - mHThumbPos;
   }
}

That should be all we need to do, our scroll control should now continue to scroll when we click and hold our mouse button down on it!

This was a bit rushed putting together (the .plan) so if I've missed anything I apologize, let me know and I'll update it as soon as possible.

I hope a few of you find this as useful as I do... and with that, it's back to studying for my last final tommorow!

-justin'

edit : quick update, onPreRender now invokes parent, and short circuits a bit better.

#1
05/11/2005 (4:49 pm)
gui snob!
#2
05/11/2005 (11:15 pm)
Good work Justin, glad to see you are enjoying working on gui work ;)
#3
05/12/2005 (6:46 am)
@Adept : You sir are mean... But oh so right ;)

@Zach : Hah thanks man, perhaps we'll get to conspire on some GUI stuff while I'm up there this summer, buahahaha!
#4
05/20/2005 (7:05 pm)
Perfect - thank You!