Catching mouse events on the scene window?
by Spencer Grey · in Torque Game Engine · 07/05/2006 (1:27 pm) · 12 replies
Hey,
Is it possible to catch mouse events in the scene window itself, as opposed to the gui controls? Something like sceneWindow2D::onCollision() from tgb.
Thanks.
Is it possible to catch mouse events in the scene window itself, as opposed to the gui controls? Something like sceneWindow2D::onCollision() from tgb.
Thanks.
#2
07/05/2006 (2:38 pm)
Here is a good article on how to implement left clicking to select objects in the window. I believe that right click to move is not something you would want to implement as an event off your screen, but rather just off of your basic action mapping. I could be wrong on this part, I've been too lazy to re-implement it on my prototype now that I got left click picking working.
#3
As far as the basic action mapping for right clicking ... I just spent half a day trying to get that to work. Apparently, when I set the cursor to on for playGui, it no longer grabs my mouse events (through action map binding). It calls my functions when I right/left click and the cursor is off, but as soon as I turn it on, it stops calling the bound functions.
I think (wild guess) that it has something to do with the the auto mouse look when the cursor is off. The cursor.cs script has a function that locks the mouse, and the x/y axis is bound to move the camera (default fps view). I have a feeling that somewhere, something is making the playGui ignore the mouse when you set the cursor to true so the camera doesnt follow your cursor around.
Thats the theory I've come up with after poking around for a little while atleast. Now, I'm going home and getting some sleep. Maybe tomorrow when I'm not half-dead I'll be able to figure this thing out.
07/05/2006 (3:00 pm)
Thanks for the link. So I'm going to assume that I'll need to change the source code and recompile for the object selection. Not a problem, thanks for pointing me in the right direction.As far as the basic action mapping for right clicking ... I just spent half a day trying to get that to work. Apparently, when I set the cursor to on for playGui, it no longer grabs my mouse events (through action map binding). It calls my functions when I right/left click and the cursor is off, but as soon as I turn it on, it stops calling the bound functions.
I think (wild guess) that it has something to do with the the auto mouse look when the cursor is off. The cursor.cs script has a function that locks the mouse, and the x/y axis is bound to move the camera (default fps view). I have a feeling that somewhere, something is making the playGui ignore the mouse when you set the cursor to true so the camera doesnt follow your cursor around.
Thats the theory I've come up with after poking around for a little while atleast. Now, I'm going home and getting some sleep. Maybe tomorrow when I'm not half-dead I'll be able to figure this thing out.
#4
If anyone has any idea how to get this going in the real game, that would be great. I'm trying to figure out what exactly theyre doing, but no luck yet.
07/06/2006 (7:58 am)
It just occured to me that the editor has the exact movement scheme that I want. You can run back/foward and strafe with the arrow keys, and you control the direction your facing with the right mouse button. If anyone has any idea how to get this going in the real game, that would be great. I'm trying to figure out what exactly theyre doing, but no luck yet.
#5
I notice there's a GuiMouseEventCtrl, and I tried dropping that into place, but it also wasn't firing right click events for some reason. Needless to say, the GuiMouseEventCtrl also stole the left click selecting that I'd implemented as posted above, so I'd need to pass that event up if that were to work.
I'm at a bit of a loss right now, but I'm sure it's something wrong with what I'm doing. Sorry, Spencer, hopefully someone else will chime in with a more authoritative answer... 'cause I need to know this too.
07/06/2006 (8:37 am)
Hrm... yeah, not real sure on that myself. I've just been fiddling with this a bit, and it looks like the events to use are onRightMouseDown and onRightMouseUp, but for some reason when I attach these events to playGui, they don't seem to fire.I notice there's a GuiMouseEventCtrl, and I tried dropping that into place, but it also wasn't firing right click events for some reason. Needless to say, the GuiMouseEventCtrl also stole the left click selecting that I'd implemented as posted above, so I'd need to pass that event up if that were to work.
I'm at a bit of a loss right now, but I'm sure it's something wrong with what I'm doing. Sorry, Spencer, hopefully someone else will chime in with a more authoritative answer... 'cause I need to know this too.
#6
I have a feeling that its actually simpler than I thought. I unbound the yaw and pitch functions from the moveMap actionMap, and replaced them with (placeholder) mlYaw and mlPitch functions. The difference is simple: if !$mouselook, then return. I bound a function mouseLook to the right mouse button, which simply sets $mouselook = %val.
So now the camera stays still when I move my mouse around unless I'm holding down the right mouse button.
The next hurdle is figuring out why I cant see a cursor. I tried using canvas.setCursor() but that (a)doesn't make a cursor visible for playGui, and (b)when I re-toggle the console the cursor resets.
This goes back to my original theory that theres a function somewhere that turns off/hides/sets the cursor to empy and locks the mouse.
Must find it ... >.< (if it really exists that is)
Edit --
Okay, so as I said earlier, when I set playGui.noCursor to 0 (turning the cursor on), then tge stops calling my bound mouse functions. I've traced it down to the cursor.cs in the common/client folder. Eventually, noCursor = 0 trickles down and becomes:
If I comment all three of those things out, then its like playGui.noCursor is still set to 1 -- I can detect clicks, but no mouse cursor.
If I have even a single one of those, then I'm not detecting mouse clicks. If I leave lockMouse(false) uncommented, for example, then I can bring my mouse outside of the game, but I can no longer get clicks. Everything else remains the same.
Kinda confused right now. Not sure where to look.
07/06/2006 (8:57 am)
I'm not sure if your trying to do the same thing as I am, but I figured I'd post my progress incase it helps at all.I have a feeling that its actually simpler than I thought. I unbound the yaw and pitch functions from the moveMap actionMap, and replaced them with (placeholder) mlYaw and mlPitch functions. The difference is simple: if !$mouselook, then return. I bound a function mouseLook to the right mouse button, which simply sets $mouselook = %val.
So now the camera stays still when I move my mouse around unless I'm holding down the right mouse button.
The next hurdle is figuring out why I cant see a cursor. I tried using canvas.setCursor() but that (a)doesn't make a cursor visible for playGui, and (b)when I re-toggle the console the cursor resets.
This goes back to my original theory that theres a function somewhere that turns off/hides/sets the cursor to empy and locks the mouse.
Must find it ... >.< (if it really exists that is)
Edit --
Okay, so as I said earlier, when I set playGui.noCursor to 0 (turning the cursor on), then tge stops calling my bound mouse functions. I've traced it down to the cursor.cs in the common/client folder. Eventually, noCursor = 0 trickles down and becomes:
function cursorOn()
{
if ( $cursorControlled )
lockMouse(false);
Canvas.cursorOn();
Canvas.setCursor(DefaultCursor);
}If I comment all three of those things out, then its like playGui.noCursor is still set to 1 -- I can detect clicks, but no mouse cursor.
If I have even a single one of those, then I'm not detecting mouse clicks. If I leave lockMouse(false) uncommented, for example, then I can bring my mouse outside of the game, but I can no longer get clicks. Everything else remains the same.
Kinda confused right now. Not sure where to look.
#7
Or is it just that I don't really understand what's on there, and it calls the bind twice, once for click and once for unclick? That's what your $mouselook = %val looks like it's doing to me.
Still, that's a big problem with it ignoring that if noCursor is 0.
I'm thinking perhaps the better bet would be to figure out how to get the onRightMouseDown event to fire on PlayGui and then use it to set noCursor to 1, and onRightMouseUp event setting noCursor to 0.
I'm thinking if you can suss that out, that might help, but I'm at the DayJob(tm) now, so can't hack on it. I'll try to take a look at it tonight if you haven't sussed it before then and let you know what I find, 'cause I definitely gotta have this.
07/06/2006 (10:14 am)
When you say you bound it to the right mouse button, did you use the moveMap.bind method, or some other method? I wasn't really sure how to bind the mouseup for that.Or is it just that I don't really understand what's on there, and it calls the bind twice, once for click and once for unclick? That's what your $mouselook = %val looks like it's doing to me.
Still, that's a big problem with it ignoring that if noCursor is 0.
I'm thinking perhaps the better bet would be to figure out how to get the onRightMouseDown event to fire on PlayGui and then use it to set noCursor to 1, and onRightMouseUp event setting noCursor to 0.
I'm thinking if you can suss that out, that might help, but I'm at the DayJob(tm) now, so can't hack on it. I'll try to take a look at it tonight if you haven't sussed it before then and let you know what I find, 'cause I definitely gotta have this.
#8
I think your right, in that ideally it would use a guiMouseEventCtrl, or something like it. Otherwise the right click movement would go through no matter where you click, when you most likely just want it to go through on the screen, not the gui.
I'll keep looking, but my progress has pretty much halted.
07/06/2006 (11:01 am)
I used the moveMap.bind method. The %val arg that's automatically passed in is how I got the click/unclicks.I think your right, in that ideally it would use a guiMouseEventCtrl, or something like it. Otherwise the right click movement would go through no matter where you click, when you most likely just want it to go through on the screen, not the gui.
I'll keep looking, but my progress has pretty much halted.
#9
I couldn't find anyway to do this that didn't mod the source code (something were looking to stay away from here, since we're just seeing what can be done as is for now), but I finally came up with a hack that works. It's simple enough too, along the lines of what you were saying.
You can't grab mouse events off of the game window, so I created a new gui file and placed a mouseEventCtrl in it. I sized it to be as big as my game window is. Just use the canvas.pushDialog to get it to appear. I placed mine in the client/serverconnection.cs file.
Now, to get the camera to move when you hold the right button down and move the mouse...
I'm in the middle of working out how to get the cursor to dissapear when you click then reappear in the same spot when you let go. The stored position seems to be getting reset when I let go for some reason, but thats not a big deal. Figured you don't need my exact finished code anyway.
Alright, take what you need, leave what you don't. Hope this helped a bit. Thanks for the insight, it set me on the right path!
07/06/2006 (12:50 pm)
Alright, I found a solution (to what I want atleast). The functionality I wanted was to click the right mouse, and while it was down have the camera move left/right up/down depending on where you move the mouse, much like the fps view does automatically. I couldn't find anyway to do this that didn't mod the source code (something were looking to stay away from here, since we're just seeing what can be done as is for now), but I finally came up with a hack that works. It's simple enough too, along the lines of what you were saying.
You can't grab mouse events off of the game window, so I created a new gui file and placed a mouseEventCtrl in it. I sized it to be as big as my game window is. Just use the canvas.pushDialog to get it to appear. I placed mine in the client/serverconnection.cs file.
function GameConnection::initialControlSet(%this)
{
echo ("*** Initial Control Object");
// The first control object has been set by the server
// and we are now ready to go.
// first check if the editor is active
if (!Editor::checkActiveLoadDone())
{
if (Canvas.getContent() != PlayGui.getId()){
Canvas.setContent(PlayGui); //was here already
Canvas.pushDialog(playMouseGui); //added the pushDialog
}
}
}Now, to get the camera to move when you hold the right button down and move the mouse...
function playMouseGui::onRightMouseDown(%this) {
//store the position of the cursor when you press down
%this.cursorPos = canvas.getCursorPos();
}
function playMouseGui::onRightMouseDragged(%this) {
//get the difference between the current mouse position and the stored, then add that
//difference to the mvYaw/Pitch
%cursorPos = canvas.getCursorPos();
%x = getWord(%cursorPos, 0);
%y = getWord(%cursorPos, 1);
%lastX = getWord(%this.cursorPos, 0);
%lastY = getWord(%this.cursorPos, 1);
//bigger number for faster movement
%xDiff = (%x - %lastX) / 1.5;
%yDiff = (%y - %lastY) / 1.5;
//same code as in the moveMap.bind, just replaced %val with the diff
$mvYaw += getMouseAdjustAmount(%xDiff);
$mvPitch += getMouseAdjustAmount(%yDiff);
//ideally will set the cursor back to the stored position, bugged now
//canvas.setCursorPos(%this.cursorPos);
//using this until I fix the bugs
%this.cursorPos = %cursorPos;
}I'm in the middle of working out how to get the cursor to dissapear when you click then reappear in the same spot when you let go. The stored position seems to be getting reset when I let go for some reason, but thats not a big deal. Figured you don't need my exact finished code anyway.
Alright, take what you need, leave what you don't. Hope this helped a bit. Thanks for the insight, it set me on the right path!
#10
07/06/2006 (1:11 pm)
Cool, yeah, looks like good stuff. I'll see how well it integrates with the changes I've already got in place for mouse events tonight. Thanks to you too!
#11
Make sure you use that if you try it =p
-- Edit
Discovered that using lockMouse will snap the mouse back to the middle automatically on release. So I'm just locking it on press, releasing on up. So I dont need either of those lines at the bottom.
07/06/2006 (1:17 pm)
I just made a 1 line change to the very bottom of that code, since my canvas.setCursorPos() was bugging the whole thing out more than I realized when I posted it. I pasted the original line of code in there which works fine.Make sure you use that if you try it =p
-- Edit
Discovered that using lockMouse will snap the mouse back to the middle automatically on release. So I'm just locking it on press, releasing on up. So I dont need either of those lines at the bottom.
#12
In ./engine/game/gameTSCtrl.h, I added this code to the public declaration block:
In ./engine/game/gameTSCtrl.cc, I added these methods (just before the onMouseMove event, but you can stick 'em where you like):
Finally, since guiShapeNameHud tends to take up the entire screen, I also added in a pass through there, by modifying ./engine/game/fps/guiShapeNameHud.cc in two places, this in the public block declaration of the class definition:
... and then just above the onRender method, I added this block:
From there, I just changed the scripted methods you supplied to use PlayGui instead of PlayMouseGui, so this way we don't have to create a dummy control.
Your mileage may vary, but since I had already modified these files for my picking algorithms, I figured it would work for me.
I'd just like to add that this is my first modification to the engine itself that didn't involve step-by-step instructions, though the modification I made is similar to the object picking modification, though simpler.
Still, I'm feelin' pretty comfortable with the code-base.
07/06/2006 (8:27 pm)
Since I had already modified gameTSCtrl to support left click targeting, I went ahead and modified the control so it would support the onRightMouseDown and onRightMouseDragged events. I had to modify three of the files in the C++ portion of the engine, here's what I changed:In ./engine/game/gameTSCtrl.h, I added this code to the public declaration block:
// right click event additions void onRightMouseDown(const GuiEvent &evt); void onRightMouseDragged(const GuiEvent &evt);
In ./engine/game/gameTSCtrl.cc, I added these methods (just before the onMouseMove event, but you can stick 'em where you like):
//---------------------------------------------------------------------------
// right click event additions
//---------------------------------------------------------------------------
void GameTSCtrl::onRightMouseDown(const GuiEvent &evt) {
Con::executef(this, 1, "onRightMouseDown");
}
//---------------------------------------------------------------------------
// right click event additions
//---------------------------------------------------------------------------
void GameTSCtrl::onRightMouseDragged(const GuiEvent &evt) {
Con::executef(this, 1, "onRightMouseDragged");
}Finally, since guiShapeNameHud tends to take up the entire screen, I also added in a pass through there, by modifying ./engine/game/fps/guiShapeNameHud.cc in two places, this in the public block declaration of the class definition:
// right click event additions virtual void onRightMouseDown(const GuiEvent &evt); virtual void onRightMouseDragged(const GuiEvent &evt);
... and then just above the onRender method, I added this block:
//--------------------------------------------------------------------------
// right click event additions
//--------------------------------------------------------------------------
void GuiShapeNameHud::onRightMouseDown(const GuiEvent &evt)
{
// Let's let the parent execute its event handling (if any)
GuiTSCtrl *parent = dynamic_cast<GuiTSCtrl*>(getParent());
if (parent)
parent->onRightMouseDown(evt);
}
//--------------------------------------------------------------------------
// right click event additions
//--------------------------------------------------------------------------
void GuiShapeNameHud::onRightMouseDragged(const GuiEvent &evt)
{
// Let's let the parent execute its event handling (if any)
GuiTSCtrl *parent = dynamic_cast<GuiTSCtrl*>(getParent());
if (parent)
parent->onRightMouseDragged(evt);
}From there, I just changed the scripted methods you supplied to use PlayGui instead of PlayMouseGui, so this way we don't have to create a dummy control.
Your mileage may vary, but since I had already modified these files for my picking algorithms, I figured it would work for me.
I'd just like to add that this is my first modification to the engine itself that didn't involve step-by-step instructions, though the modification I made is similar to the object picking modification, though simpler.
Still, I'm feelin' pretty comfortable with the code-base.
Torque Owner Spencer Grey
I'm just exploring tge right now, and was trying to set up a right click to mouse look type of thing. Ideally, the left click would eventually select objects.
Is there a way to do this without modding the source code? Right now I'm just seeing what this thing can do as is.
Hope this makes sense, as I'm on 2 hours sleep. Thanks in advance.