Game Development Community

capturing mouse and keyboard events

by Ron Yacketta · in Torque Game Engine · 06/29/2002 (6:10 pm) · 44 replies

Folks,

I have been searching for a way to capture both a keyboard and mouse event at the same time
IE: LEFT_CTL + button1

I would like to be able to capture them at the same time to use in an inventory system I have been cooking up. The basic idea would be to have a player LCTR+button1 (or dbl click) on an object to drop it.

I would like to attempt to keep it all within scripts, but if engine modifications are needed so be it.

any ideas folks?

Regards,

Ron
Page «Previous 1 2 3 Last »
#1
06/29/2002 (7:09 pm)
The platform code already passes the current modifier key state (ctrl, ...) with all input events. Is this enough?
#2
06/29/2002 (7:59 pm)
Quig,

I have been looking within the scripts to track down keypresses and mouse button usage. Maybe I am not looking in the right place or for the right information, would you be able to provide a bit more information to get me rolling down the right path?

Regards,
Ron
#3
06/29/2002 (9:38 pm)
Well, it seems like torque already supports this.

You could do something like:

moveMap.bind(mouse0, "ctrl button0", mouseFire);

The gory details of event flow are as follows, starting from winDInputDevice.cc:

in DInputDevice::buildEvent, new InputEvent structures are created for each Input event. Each of these structures has a modifier field that contains the current state of the modifier keys.

The event is posted using postEvent in gameInterface.cc, which calls processEvent, which calls DemoGame::processInputEvent in main.cc

processInputEvent looks like it passes the event to the global action map, followed by the Canvas, followed by the current Action map. The ActionMap::processAction function looks for a binding for the event and executes it if found.

bindings are established using the ActionMap::processBind() function. This is called by the console function bind(). A lot of the work for processBind() is done in the ActionMap::createEventDescriptor() function, including parsing out the modifier strings.

This is all based on my reading of the code, no guarantees on accuracy :)
#4
06/29/2002 (11:36 pm)
// Create some flags
$FLAG_ONE = false;
$FLAG_TWO = false;

function someFunction()
{
   // Pop off all othere existing action maps
   if( isObject(moveMap) )
      moveMap.pop();
   if( isObject(InventoryMap) )
      InventoryMap.delete();
   // others ... ?

   // Declare new action map for our gui control
   new ActionMap(InventoryMap);

   // Setup the keys
   InventoryMap.bind(keyboard, "lcontrol", flagOne);
   InventoryMap.bind(mouse0, "button0", flagTwo);

   // Push the action map
   InventoryMap.push();
}

function flagOne(%val)
{
   if(%val)
      $FLAG_ONE = true;
   else
      $FLAG_ONE = false;

   checkBinding();
}

function flagTwo(%val)
{
   if(%val)
      $FLAG_TWO = true;
   else
      $FLAG_TWO = false;

   checkBinding();
}

function checkBinding()
{
   if($FLAG_ONE && $FLAG_TWO)
   {
      // do something ...
   }
}
#5
06/30/2002 (6:23 am)
Quig,

I to read the code, but was under the impression that one could not mix bindings.

That is (mouse, "ctrl button0", blah, blah); type of deal.

From what I gathered (could be totaly off the cuff here), the code takes the "mouse" parameter and finds an associated device then looks for the "ctrl button0" attribute of that device. Seeing that a mouse does not have a ctrl, it would fail on that associaton correct?

Regards,
Ron
#6
06/30/2002 (10:08 am)
ActionMap::createEventDescriptor() looks for the modifiers in all cases, so I think this will work (at least it worked for me).
#7
06/30/2002 (11:42 am)
Quig,

Thanxs I will give it a whirl, I was hesitent to try it at first. Seeing that you have tried and was sucussful, I will to give it a shot ;)

-Ron
#8
06/30/2002 (5:50 pm)
Quig,

What I thought was right, doing a "moveMap.bindCmd(mouse, "lcontrol button0", "DropInvItem();","" );" is not possible. it ONLY captures the mouse button0. I added the following to defaul.bind.cs

function DropInvItem()
{
    echo("Caught LCRTL + BUTTON0 comnination\n");
//    commandToServer( 'DropObject', %obj );
}
moveMap.bindCmd(mouse, "lcontrol button0", "DropInvItem();","" );

The function was fired regardless of what keyboard key was pressed.

Looks like I will need to either modify the platform code (not a good idea at all) or do a two stage event process within the script as mentioned in a previous post

-Ron
#9
06/30/2002 (6:09 pm)
O.K

I think I have totaly confused the crud out of myself *sigh*
I am following the use of "onMouseDown", but do not see any thing to differentiate between the different mouse buttons.

I keep bumping into the general use of "onMouseDown", can someone kindly give me a swift kick in the keister and lead me down the path of good ;)

Maybe its due to having one to many LBL's (Labatt's blue Lite) today *shrug*

-Ron
#10
06/30/2002 (7:06 pm)
Did you check out my code snipit above? :/
#11
07/01/2002 (5:06 am)
Yes,

But what i was looking for was "onRightMouseDown", now that I had time to sleep off all the LBL and take a second look I found that function. It seems to not work right thought (at all even) *shrug*, not time to muckw ith it now heading off to work

-Ron
#12
07/01/2002 (7:54 am)
O.K

At work looking at the TGE (shame on me, using the man's (boss) time to code games ;) ) and wondering why this does not work ;)

1) changed guiBitMapCtrl's parent (and class decleration) from GuiControl to GuiMouseEventCtrl
2) added a virtual member to guiBitMapCtrl for onRightMouseDown (which should call its parent right?)
3) added a new .gui and .cs to the example base for testing
4) fired up the game and never once get a onRightMouseDown event, but I can get a onMouseDown event.

according to GuiMouseEventCtrl

void GuiMouseEventCtrl::onRightMouseDown(const GuiEvent & event)
{
   if(mLockMouse)
      mouseLock();
   sendMouseEvent("onRightMouseDown", event);
}

the "onRightMouseDown" should be exec'ed on the client correct?

am I loosing it or what?

Regards,
Ron
#13
07/01/2002 (8:29 am)
It's getting exec'd, trust me.

The question is, where are you trying to catch if it's getting exec'd, in scripts?

If you are then you'll need to manual code that in with a Con::executef call, or make a call to Parent::
#14
07/01/2002 (8:37 am)
in the .cs I have

function TestGuiBitMapCtrl::onRightMouseDown()
{
  echo("Right mouse button pressed\n"):
}

function TestGuiBitMapCtrl::onMouseDown()
{
  echo("Left (default) button pressed\n");
}

the onMouseDown works without a hitch, but onRightMouseDown does not.

I know it is something simple and silly I am overlooking.
Maybe another cup of joe or two will get me head on right *shrug*

-Ron
#15
07/01/2002 (8:38 am)
BTW- You are going to have to do one of two things that I can tell.

1. I know that keyboard + mouse events can be captured together and call a function. This was scripted in Tribes 1 by MrPoop(You probably woulnd't know him) if I remember correctly. Since I cant seem to find that script anymore and since the Tribes 1 scripting language is quite a bit different then the Tribes 2 language you are out of luck with that. But the point is, it can be scripted. Now, I offered one method of scripting it, with a left ctrl + left mouse down 'flag' type system which will work. There are probably other methods of doing this as well.

2. Or you can code it in by extending the input system with a new function or something of that sort. You're most likely bet would be to look into where the bind() console function is defined and make a new one, change that one, or what have you.
#16
07/01/2002 (8:44 am)
To make the code change would require one to be able to-do so under all platforms. I currently only have access to Winblows and linux, which would rule out MacOS.

If I keep it within the scripting, it is cross platform from the start.

Also, anotherthing that bothers me. The onMouseDown is being called from GuiMouseEventCtrl without a virtual member function in GuiBitmapCtrl. Which means, I do not need to have the virtual member I created for onRightMouseDown in GuiBitmapCtrl. For some reason (unknown yet), the onMouseDown for GuiMouseEventCtrl works like a champ every time, but onRightMouseDown is a flop.
#17
07/01/2002 (10:27 am)
[EDIT]
Quig, you were right!!
I heard you speaking, but nothing was registering yesterday. I think it was the beer, had way to many to comprehend simple english.
[/EDIT]

O.K

Here is the (my) final verdict (findings) on capturing keyboard events at the same times as mouse events.

After drinking a couple more cups of joe (4 to be exact ;) ) and several echo statements within scripts and numerous other log calls in the code I finally tracked it down.

Man I feel real stupid now ;)

in GuiMouseEventCtrl you will notice the following two functions:

//------------------------------------------------------------------------------
void GuiMouseEventCtrl::sendMouseEvent(const char * name, const GuiEvent & event)
{
   char buf[3][32];
   dSprintf(buf[0], 32, "%d", event.modifier);
   dSprintf(buf[1], 32, "%d %d", event.mousePoint.x, event.mousePoint.y);
   dSprintf(buf[2], 32, "%d", event.mouseClickCount);
   Con::executef(this, 4, name, buf[0], buf[1], buf[2]);
}

//------------------------------------------------------------------------------
void GuiMouseEventCtrl::consoleInit()
{
   Con::setIntVariable("$EventModifier::LSHIFT",      SI_LSHIFT);
   Con::setIntVariable("$EventModifier::RSHIFT",      SI_RSHIFT);
   Con::setIntVariable("$EventModifier::SHIFT",       SI_SHIFT);
   Con::setIntVariable("$EventModifier::LCTRL",       SI_LCTRL);
   Con::setIntVariable("$EventModifier::RCTRL",       SI_RCTRL);
   Con::setIntVariable("$EventModifier::CTRL",        SI_CTRL);
   Con::setIntVariable("$EventModifier::LALT",        SI_LALT);
   Con::setIntVariable("$EventModifier::RALT",        SI_RALT);
   Con::setIntVariable("$EventModifier::ALT",         SI_ALT);
}

These two functions got me a thinking

1) why are their keyboard events in the mouse code?
2) what is being sent in the "event.modifier" variable?

so, off I went adding echo/log statements and what did I find?

well "event.modifier" sends along the keyboard event defined (captured in other platform specific code) in "GuiMouseEventCtrl::consoleInit()"

So, a echo within my script like

function TestGuiBitMapCtrl::onRightMouseDown(%this, %event, %mousexy, %click ) {
	echo("Right Mouse button pressed [" @ %this @ "," @ %event @ "," @ %mousexy @ "," @ %click @ "]\n");
}

displayed the following output when I held lctrl and pressed button1.

Right Mouse button pressed [1328,4,124 406,1]

1328 - is the script object in this case TestGuiBitMapCtrl
4 - is the event [keyboard] modified, if this case LCTRL
124 406 - are the mouse co-ords where the mouse was clicked
1 - is the number of mouse clicks


Which means their is no need to capture the keyboard and mouse events at the same time. The engine does it for us :), we just need to parse %event for the type of keyboard event we are looking for. The current keyboard events can be found in enginge\platform\event.h as follows

// Modifier Keys
// shift and ctrl are the same between platforms.
#define SI_LSHIFT    (1<<0)
#define SI_RSHIFT    (1<<1)
#define SI_SHIFT     (SI_LSHIFT|SI_RSHIFT)
#define SI_LCTRL     (1<<2)   
#define SI_RCTRL     (1<<3)
#define SI_CTRL      (SI_LCTRL|SI_RCTRL)
// win altkey, mapped to mac cmdkey.
#define SI_LALT      (1<<4)   
#define SI_RALT      (1<<5)
#define SI_ALT       (SI_LALT|SI_RALT)
// mac optionkey
#define SI_MAC_LOPT  (1<<6)   
#define SI_MAC_ROPT  (1<<7)
#define SI_MAC_OPT   (SI_MAC_LOPT|SI_MAC_ROPT)


Regards,
Ron

P.S
Playing with TGE while at work and getting paid for it is
wicked fun. As long as you don't get caught by the man (boss) ;)
#18
07/01/2002 (10:50 am)
Ron,
So does this mean we can do what you were asking about initially? Have a different function fire based on a keyboard/mouse button combo? I know I looked at this before for a little bit. but didn't get it to work correctly.

What would a default.bind example look like for your LEFT_CTRL + button1?

Yeah, I'm busy at "work" right now too :)

-Sabrecyd
#19
07/01/2002 (10:59 am)
That is the beauty of this :)
their is NO bind or bindCmd needed :)
seeing that I made GuiBitmapCtrl's parent be
GuiMouseEventCtrl all mouse events are passed back to the script engine in
GuiMouseEventCtrl::sendMouseEvent(const char * name, const GuiEvent & event)

So you just need to base a gui from GuiBitmapCtrl

IE:

new GameTSCtrl(TestGui) {
   profile = "GuiDefaultProfile";
   horizSizing = "right";
   vertSizing = "bottom";
   position = "0 0";
   extent = "640 480";
   minExtent = "8 8";
   visible = "1";
   helpTag = "0";

   new GuiBitmapCtrl(TestGuiBitMapCtrl) {
      profile = "GuiDefaultProfile";
      horizSizing = "relative";
      vertSizing = "relative";
      position = "48 116";
      extent = "520 352";
      minExtent = "8 8";
      visible = "1";
      helpTag = "0";
      lockMouse = "0";
      bitmap = "./inventory.png";
      wrap = "0";
   }
}

then in the .cs add something like
function TestGuiBitMapCtrl::onRightMouseDown(%this, %event, %mousexy, %click ) {
	echo("Right Mouse button pressed [" @ %this @ "," @ %event @ "," @ %mousexy @ "," @ %click @ "]\n");
}

That is basicly all I did :) with exception to the bind to toggle the display of TestGui.


so, to parse the LCTRL key one could do

function TestGuiBitMapCtrl::onRightMouseDown(%this, %event, %mousexy, %click ) {
if( %event == 4 ) { // event 4 is the LCTRL key
	echo("Right Mouse button pressed [" @ %this @ "," @ %event @ "," @ %mousexy @ "," @ %click @ "]\n");
}
}



-Ron
#20
07/01/2002 (11:14 am)
Ohhh...ok. Damn, that is cool.

I wonder if that would be useful for the guys that were trying to figure out an alternate way to do melee combat stuff? In any case this looks useful.

Now, if I could only sneak that beer at work I'd be all set ;)
Page «Previous 1 2 3 Last »