Game Development Community

SetCursorPos Behavior Bug?

by William Lee Sims · in Torque Game Engine Advanced · 01/27/2009 (1:58 pm) · 6 replies

I've ported my TGE 1.5.2 game (in-progress) to TGEA 1.8. In 1.5, I used to be able to call setCursorPos on the canvas from an ::onRightMouseDragged event and the mouse would move there and all would be fine.

In TGEA, I call setCursorPos from any mouse event and I get another mouse event. Specifically, I move the mouse to the center of the screen after each call so that I can get a delta in <x/y> for camera rotation. If my delta after moving the mouse is <2,0>, then I'll get another event where the delta is <-2,0>.

I noticed a resource for WOW-like camera movement and saw that they put in an "ignore next mouse event" in TGEA 1.7.1 (IIRC). The code for mouse events isn't the same anymore with 1.8, but I don't like the idea of ignoring the next mouse event anyway. Here's why...

If I move diagonally, I'll get 2 events, 1 right after the other, that have deltas from the center of something like <2,0> and <0,3>. Right after I'll get two more events from my setCursorPos calls: <-2,0> and <0,-3>. If I use the "ignore next mouse event", I lose the <0,3> and the <0,-3>.

So my question is, should setCursorPos cause a mouse event and should I find a way around this, or is this an unintended bug?

Thanks!

#1
01/27/2009 (4:39 pm)
Does the second mouse event happen inside the first mouse event? If so, then adding some sort of recursion protection would work, and would still allow you to recieve multiple mouse events

(eg: if ($inMouseEvent = 1) return; $inMouseEvent = 1; SetCursorPos(); $inMouseEvent=0;)

#2
01/27/2009 (11:08 pm)
As soon as I saw your post, I knew that this would fix the problem.

Alas, the setCursorPos call queues up the event with a Windows call (also called SetCursorPos), essentially waiting until my function is done before calling me again. UGH!

I'm going to dread if I have to keep a list of all the deltas I get and then remove them as I find their opposites. There must be something more elegant.

Somebody out there must be using right-mouse-button orbit camera logic out there? Anybody?
#3
01/27/2009 (11:19 pm)
Just lock the mouse. Torque will automatically recenter it without causing any ugliness with OS events.
#4
01/28/2009 (12:52 am)
Here is my (current) code:
void GameTSCtrl::onRightMouseDown(const GuiEvent &evt)
{ 
  GuiCanvas *canvas;
  Sim::findObject( "Canvas", canvas );
  canvas->mouseLock( this );
  canvas->showCursor( false );
}
void GameTSCtrl::onRightMouseUp(const GuiEvent &evt)
{ 
  GuiCanvas *canvas;
  Sim::findObject( "Canvas", canvas );
  canvas->mouseUnlock( this );
  canvas->showCursor( true );
}
void GameTSCtrl::onRightMouseDragged(const GuiEvent &evt)
{
  int diffX = evt.mousePoint.x - getExtent().x / 2;
  int diffY = evt.mousePoint.y - getExtent().y / 2;
  Con::printf( "MouseEventPos <%d,%d>, delta <%d,%d>.", 
    evt.mousePoint.x, evt.mousePoint.y,
    diffX, diffY );
  
  if( diffX != 0 )
    Con::executef( "yaw", Con::getIntArg(diffX) );
  if( diffY != 0 )
    Con::executef( "pitch", Con::getIntArg(diffY) );
}

If I right click and drag in the upper-left hand corner, I get these messages:
MouseEventPos <7,5>, delta <-505,-379>.
MouseEventPos <8,5>, delta <-504,-379>.
MouseEventPos <9,5>, delta <-503,-379>.
MouseEventPos <10,5>, delta <-502,-379>.
MouseEventPos <11,5>, delta <-501,-379>.

First, the mouse never hides. Second, the events are shown where the mouse currently is. Clearly, the deltas are just way off due to the lack of centering. Am I maybe overlooking some other function call I need to make?
#5
01/28/2009 (12:59 am)
I would recommend looking at editTSCtrl.cpp. It contains code to hide the mouse onRightMouseDown, get deltas in onRightMouseDragged, and show the mouse again in onRightMouseUp.
#6
02/05/2009 (9:05 am)
I thought I'd follow up and say that taking code from editTSCtrl worked.

The hidden mouse still hits an imaginary wall about the same time that the visible mouse would, but the overall feel is about right.