Mouse Input over GUI and 3D scene
by Chris Groot · in Torque 3D Professional · 03/14/2011 (8:06 am) · 2 replies
I'm working on creating a GUI for a project and I'm having an issue with getting mouse input over 2D GUI components as well as the 3D scene. I would like to be able to click on 2D GUI buttons as well as click or drag in the 3D scene and have it effect the 3D camera. I have tried various combinations of setting the canvas content, changing the modal flag, and pushing dialogs and to no avail have I been able to get mouse input for both the 3D scene and the 2D buttons. The two end results I get are complete 2D GUI mouse input or 3D scene mouse input. I have been able to get mouse input over multiple GUI files by manipulation of the pushDialog function as well as the modal flag, the current 2D GUI I have consists of 3 different .gui files and I am able to get input over all 3 guis with no issues, so I know its not a matter of not getting input over multiple gui files.
What seems to be the issue is that when I push the GUI dialogs on top of the 3D scene they are taking priority over the 3D scene despite the fact that I am setting their modal flag to true. Each of my 2D GUIs' content control is just a generic GUIControl and my 3D scene GUI is a GameTSCtrl. Even adding a 2D GUI button to the PlayGui.gui file results in no input to that button but still input to the 3D scene.
I am wondering if anyone might be able to help me in figuring out how to get mouse input for both the 2D buttons as well as the 3D scene? If this question has been answered on another thread and I missed it in my forum searches, wondering if someone could link me to that thread? Thanks
What seems to be the issue is that when I push the GUI dialogs on top of the 3D scene they are taking priority over the 3D scene despite the fact that I am setting their modal flag to true. Each of my 2D GUIs' content control is just a generic GUIControl and my 3D scene GUI is a GameTSCtrl. Even adding a 2D GUI button to the PlayGui.gui file results in no input to that button but still input to the 3D scene.
I am wondering if anyone might be able to help me in figuring out how to get mouse input for both the 2D buttons as well as the 3D scene? If this question has been answered on another thread and I missed it in my forum searches, wondering if someone could link me to that thread? Thanks
#2
What makes this so confusing is that the engine handles mouse events in different ways depending on if the cursor is on (displayed) or off (the normal situation while in-game). When the cursor is off mouse movements, clicks, etc. are sent to the movemap. If it is on then it is sent to the event handlers in gameTSCtrl.cpp. You don't need to change this behavior, just redefine these event handlers to do what you want.
On the script side there isn't much you can do to accomplish this. You need to make a few minor changes but it's limited to turning on the cursor using noCursor="0" in playGui.gui, removing the movemap.bind commands for mouse pitch and yaw, and in ~/core/scripts/client/cursor.cs making sure that the argument in lockMouse function call in showCursor() and hideCursor() are what you want. If it is "true" then the cursor is controlled by T3D and you can turn it on and off or change it through the source code. I used "true" because I wanted to turn off the cursor when the right mouse button is clicked. If this is "false" then the windows system cursor is used. In this case the cursor can roam the entire display. You can make it work with either setting, it seems to depend only on if you want to change the cursor.
On the engine side you will need to rewrite gameTSCtrl.cpp and gameTSCtrl.h. I used James Spellman's WoW Player Control Emulation resource located at: www.garagegames.com/community/resources/view/11152. This appears to have been written for TGE but the later posts discussing its application to TSE/TGEA are pretty close to what you need for T3D. You will find that some of the code referenced in the resource doesn't seem to exist in T3D any longer but you can ignore it, unless you want the object highlighting and selection to work. You will also find that the getCursorPos() and setCursorPos() do not work correctly. They both get or set a position based on the display upper left corner instead of the upper left corner of the T3D canvas. I think this is a bug (who cares what is happening outside of the canvas?) and have posted a fix to the setCursorPos here: www.garagegames.com/community/forums/viewthread/125099. You really don't need the getCursorPos function because the cursor position is provided by the GuiEvent &evt provided in the mouse event handler in gameTSCtrl.cpp.
There is also a newer thread referenced toward the last page of comments that does the same thing but with more features. Didn't see it until I was almost done and this gave me what I was looking for.
Hope that this helps.
03/29/2011 (4:36 pm)
It sounds like you've found a workable solution for your question. As it happens I'm working on pretty much the same thing so here is the rundown on what I've discovered. What I want to do is similar to what you mention in your post - use the right mouse key to select, left mouse key to move (pitch and yaw) but also be able to act on dialogs. And the movemap must still work too for everything but the mouse.What makes this so confusing is that the engine handles mouse events in different ways depending on if the cursor is on (displayed) or off (the normal situation while in-game). When the cursor is off mouse movements, clicks, etc. are sent to the movemap. If it is on then it is sent to the event handlers in gameTSCtrl.cpp. You don't need to change this behavior, just redefine these event handlers to do what you want.
On the script side there isn't much you can do to accomplish this. You need to make a few minor changes but it's limited to turning on the cursor using noCursor="0" in playGui.gui, removing the movemap.bind commands for mouse pitch and yaw, and in ~/core/scripts/client/cursor.cs making sure that the argument in lockMouse function call in showCursor() and hideCursor() are what you want. If it is "true" then the cursor is controlled by T3D and you can turn it on and off or change it through the source code. I used "true" because I wanted to turn off the cursor when the right mouse button is clicked. If this is "false" then the windows system cursor is used. In this case the cursor can roam the entire display. You can make it work with either setting, it seems to depend only on if you want to change the cursor.
On the engine side you will need to rewrite gameTSCtrl.cpp and gameTSCtrl.h. I used James Spellman's WoW Player Control Emulation resource located at: www.garagegames.com/community/resources/view/11152. This appears to have been written for TGE but the later posts discussing its application to TSE/TGEA are pretty close to what you need for T3D. You will find that some of the code referenced in the resource doesn't seem to exist in T3D any longer but you can ignore it, unless you want the object highlighting and selection to work. You will also find that the getCursorPos() and setCursorPos() do not work correctly. They both get or set a position based on the display upper left corner instead of the upper left corner of the T3D canvas. I think this is a bug (who cares what is happening outside of the canvas?) and have posted a fix to the setCursorPos here: www.garagegames.com/community/forums/viewthread/125099. You really don't need the getCursorPos function because the cursor position is provided by the GuiEvent &evt provided in the mouse event handler in gameTSCtrl.cpp.
There is also a newer thread referenced toward the last page of comments that does the same thing but with more features. Didn't see it until I was almost done and this gave me what I was looking for.
Hope that this helps.
Torque 3D Owner Chris Groot
VRSim
For anyone struggling with the above mentioned issue, some engine functions to look at to better understand mouse input are: GuiCanvas.cpp processInputEvent, processMouseEvent, and rootMouseDown, GuiControl.cpp findHitControl , and in script: default.bind.cs and core/client/cursor.cs