Submitting an engine modification?
by Vern Jensen · in Torque Game Builder · 12/03/2007 (11:49 pm) · 9 replies
I've just fixed the Mac version of the engine to accept modifier keys (bindKey, etc.) by themselves. Just curious what I should do to share these changes to make them most useful. Should I submit them to GarageGames? If so, where is the appropriate place to do that? (I get the impression that I use the web support email thing, it'll get lost.)
Should I post the code here? It's a simple function modification, plus a function addition, to one .cpp file.
Should I post the code here? It's a simple function modification, plus a function addition, to one .cpp file.
#2
12/04/2007 (3:42 pm)
I like to see Blogs and Resources instead of forum posts. They're easier to find. Maybe even a page on TDN.
#3
I'm scanning the forums all the time. If you post it here, it will get to the engine dev's (as Stephen noted).
You could also submit a resource or a blog (under your account settings). I'm trying to get better about scanning through them as well. The forums and blogs alone are a lot to scan.
Regardless, if you submit a resource or a blog, post it here so that Stephen or I can point people in the right direction.
12/05/2007 (7:11 am)
@VernI'm scanning the forums all the time. If you post it here, it will get to the engine dev's (as Stephen noted).
You could also submit a resource or a blog (under your account settings). I'm trying to get better about scanning through them as well. The forums and blogs alone are a lot to scan.
Regardless, if you submit a resource or a blog, post it here so that Stephen or I can point people in the right direction.
#4
12/05/2007 (11:21 am)
Alright. I've been doing some testing and fine-tuning, and will post here once I'm content that I've done what I can with it.
#5
There are some problems with it though, where it does not behave as the Windows version does:
1) The Mac version detects Control/Alt/Shift/etc. on BOTH SIDES of the keyboard, even if you specify only one side. For instance, in script:
moveMap.bindCmd(keyboard, "lcontrol", "echo(\"left ctrl key pushed\");", "echo(\"left ctrl key released\");");
This will echo to the console even if the *right* control key is pushed. Same for shift and the other modifiers. I'm not sure why this is.
2) The TorqueScript keywords "shift" "ctrl" "alt" and "opt" all fail to get events when used with bindCmd. What DO work are: lShift, lcontrol, lalt, win_lwindow, lopt. But these in reality return events for ALL MODIFIER keys, not just the left side, as mentioned previously.
3) rShift, rcontrol, ralt, win_rwindow, ropt fail to work.
Despite these things, I'm still glad to be able to listen for modifier keypresses, alone. It was simply impossible on the Mac before, because Torque had basically a placeholder function that *did nothing* when a modifier key was pushed. So in my opinion, even somewhat broken code is better than no code. But maybe whoever is on the Torque team can figure out how to get these remaining problems resolved, or simply document them, so they're known. (The fact that modifiers were unsupported on Macs was, and still is, *undocumented*.)
12/05/2007 (12:14 pm)
Okay, first, the code, which goes into macCarbEvents.cc, replacing the existing _OnRawModifiers() function:static void PostModifierEvent(U8 theKey, U8 action); // NEW CODE
//-----------------------------------------------------------------------------
static OSStatus _OnRawModifiers(EventRef theEvent)
{
static U32 oldModState = 0L;
U32 keyMods;
GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &keyMods);
// -------------------------------------- BEGIN NEW CODE --------------------------------------
U8 objInst = 0;
U8 action;
// Figure out which modifier keys have been pushed since last pass
if ( (keyMods & shiftKey) && !(oldModState & shiftKey)) PostModifierEvent(KEY_LSHIFT, SI_MAKE);
if ( (keyMods & rightShiftKey) && !(oldModState & rightShiftKey)) PostModifierEvent(KEY_RSHIFT, SI_MAKE);
if ( (keyMods & cmdKey) && !(oldModState & cmdKey)) PostModifierEvent(KEY_WIN_LWINDOW, SI_MAKE); // Using KEY_WIN_LWINDOW for Command
if ( (keyMods & optionKey) && !(oldModState & optionKey)) PostModifierEvent(KEY_LALT, SI_MAKE); // // NOTE: I'm using "Alt" for "Option"
if ( (keyMods & rightOptionKey) && !(oldModState & rightOptionKey)) PostModifierEvent(KEY_RALT, SI_MAKE); // NOTE: I'm using "Alt" for "Option"
if ( (keyMods & controlKey) && !(oldModState & controlKey)) PostModifierEvent(KEY_LCONTROL, SI_MAKE);
if ( (keyMods & rightControlKey) && !(oldModState & rightControlKey)) PostModifierEvent(KEY_RCONTROL, SI_MAKE);
// Find out which modifier keys have been released since last pass
if ( !(keyMods & shiftKey) && (oldModState & shiftKey)) PostModifierEvent(KEY_LSHIFT, SI_BREAK);
if ( !(keyMods & rightShiftKey) && (oldModState & rightShiftKey)) PostModifierEvent(KEY_RSHIFT, SI_BREAK);
if ( !(keyMods & cmdKey) && (oldModState & cmdKey)) PostModifierEvent(KEY_WIN_LWINDOW, SI_BREAK); // Using KEY_WIN_LWINDOW for Command
if ( !(keyMods & optionKey) && (oldModState & optionKey)) PostModifierEvent(KEY_LALT, SI_BREAK); // NOTE: I'm using "Alt" for "Option"
if ( !(keyMods & rightOptionKey) && (oldModState & rightOptionKey)) PostModifierEvent(KEY_RALT, SI_BREAK); // NOTE: I'm using "Alt" for "Option"
if ( !(keyMods & controlKey) && (oldModState & controlKey)) PostModifierEvent(KEY_LCONTROL, SI_BREAK);
if ( !(keyMods & rightControlKey) && (oldModState & rightControlKey)) PostModifierEvent(KEY_RCONTROL, SI_BREAK);
// -------------------------------------- END NEW CODE --------------------------------------
oldModState = keyMods;
return noErr;
}
// -------------------------------------- BEGIN NEW CODE --------------------------------------
static void PostModifierEvent(U8 theKey, U8 action)
{
InputEvent torqueEvent;
float fvalue;
if (action == SI_BREAK)
fvalue = 0.0f;
else
fvalue = 1.0f;
//---- fill the event ----
torqueEvent.deviceType = KeyboardDeviceType;
torqueEvent.deviceInst = 0;
torqueEvent.objType = SI_KEY;
torqueEvent.objInst = theKey;
torqueEvent.modifier = 0; // keyUp events not sent to script unless this is 0!
torqueEvent.ascii = 0;
torqueEvent.action = action;
torqueEvent.fValue = fvalue;
Game->postEvent(torqueEvent);
}
// -------------------------------------- END NEW CODE --------------------------------------There are some problems with it though, where it does not behave as the Windows version does:
1) The Mac version detects Control/Alt/Shift/etc. on BOTH SIDES of the keyboard, even if you specify only one side. For instance, in script:
moveMap.bindCmd(keyboard, "lcontrol", "echo(\"left ctrl key pushed\");", "echo(\"left ctrl key released\");");
This will echo to the console even if the *right* control key is pushed. Same for shift and the other modifiers. I'm not sure why this is.
2) The TorqueScript keywords "shift" "ctrl" "alt" and "opt" all fail to get events when used with bindCmd. What DO work are: lShift, lcontrol, lalt, win_lwindow, lopt. But these in reality return events for ALL MODIFIER keys, not just the left side, as mentioned previously.
3) rShift, rcontrol, ralt, win_rwindow, ropt fail to work.
Despite these things, I'm still glad to be able to listen for modifier keypresses, alone. It was simply impossible on the Mac before, because Torque had basically a placeholder function that *did nothing* when a modifier key was pushed. So in my opinion, even somewhat broken code is better than no code. But maybe whoever is on the Torque team can figure out how to get these remaining problems resolved, or simply document them, so they're known. (The fact that modifiers were unsupported on Macs was, and still is, *undocumented*.)
#6
right arrow key down
shift down
right arrow key up
the TorqueScript's method to handle key releases will not be called for the right arrow key being released, due to the shift key being down. In other words, the Torque engine is interpreting this as a "shift + right arrow key" and therefore won't sent you a keyUp event unless you *also* bind "shift right" in bindCmd. This results in it being necessary to do something like this:
I figured this was a bug in my Mac version of the code, until I tried the Windows version (which I havent' modified), and found it behaves the same way!!!
That's unfortunate, because the "Mac" version of the engine can be fixed pretty easily, so that the above TorqueScript craziness is not necessary:
Note that the way Torque currrently handles this should indeed be considered to be a bug, because it happens even if you do this:
shift key down
right arrow key down
right arrow key up
[You receive no TorqueScript notification of the right arrow key being released, unless you use my modification above.]
This is clearly incorrect, because the first event -- when the right arrow key was pushed down, *should* have been interpreted as "shift right" down, if indeed the engine wants to also interpret the right arrow key beign released as "shift right" released. But it doesn't. It sends an event for the right arrow key being pressed, but none for it being released, due to the shift key being down. And again, this is how the Windows version behaves, which is unaffected by my modifications.
-Vern
12/05/2007 (12:22 pm)
Oh, one other thing: I've noticed that, after adding this code, it changes how other things respond. I use the arrow keys to control my player's ship, and *now*, if you push keys in this order:right arrow key down
shift down
right arrow key up
the TorqueScript's method to handle key releases will not be called for the right arrow key being released, due to the shift key being down. In other words, the Torque engine is interpreting this as a "shift + right arrow key" and therefore won't sent you a keyUp event unless you *also* bind "shift right" in bindCmd. This results in it being necessary to do something like this:
moveMap.bindCmd(keyboard, "left", "updateLeftKey(true);", "updateLeftKey(false);"); moveMap.bindCmd(keyboard, "right", "updateRightKey(true);", "updateRightKey(false);"); // NOTE: We must ALSO bind all possible combinations of shift, command, control, etc. with // the left/right keys, otherwise, if you push left/right while holding one of these keys, // and then release it, it won't generate a keyUp event for us, since a modifier is down at the same time. moveMap.bindCmd(keyboard, "shift left", "updateLeftKey(true);", "updateLeftKey(false);"); moveMap.bindCmd(keyboard, "shift right", "updateRightKey(true);", "updateRightKey(false);"); moveMap.bindCmd(keyboard, "ctrl left", "updateLeftKey(true);", "updateLeftKey(false);"); moveMap.bindCmd(keyboard, "ctrl right", "updateRightKey(true);", "updateRightKey(false);"); moveMap.bindCmd(keyboard, "opt left", "updateLeftKey(true);", "updateLeftKey(false);"); moveMap.bindCmd(keyboard, "opt right", "updateRightKey(true);", "updateRightKey(false);"); moveMap.bindCmd(keyboard, "cmd left", "updateLeftKey(true);", "updateLeftKey(false);"); moveMap.bindCmd(keyboard, "cmd right", "updateRightKey(true);", "updateRightKey(false);");
I figured this was a bug in my Mac version of the code, until I tried the Windows version (which I havent' modified), and found it behaves the same way!!!
That's unfortunate, because the "Mac" version of the engine can be fixed pretty easily, so that the above TorqueScript craziness is not necessary:
//-----------------------------------------------------------------------------
static void _OnRawKey(EventRef theEvent, InputEvent &torqueEvent)
{
// --------- modifiers ---------
UInt32 keyMods = 0;
GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32,
NULL, sizeof(UInt32), NULL, &keyMods);
U8 modifierKeys = 0;
if (keyMods & shiftKey) modifierKeys |= SI_LSHIFT;
if (keyMods & rightShiftKey) modifierKeys |= SI_RSHIFT;
if (keyMods & cmdKey) modifierKeys |= SI_LALT;
if (keyMods & optionKey) modifierKeys |= SI_MAC_LOPT;
if (keyMods & rightOptionKey) modifierKeys |= SI_MAC_ROPT;
if (keyMods & controlKey) modifierKeys |= SI_LCTRL;
if (keyMods & rightControlKey) modifierKeys |= SI_RCTRL;
// --
// ------- keycode & keychar -----
UInt32 keyCode = 0;
char keyChar = 0;
GetEventParameter(theEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
GetEventParameter(theEvent, kEventParamKeyMacCharCodes, typeChar,NULL, sizeof(char), NULL, &keyChar);
// --
// ------- action & value ( make, break, repeat ) -----
U8 action;
float fvalue;
U32 eventKind = GetEventKind(theEvent);
switch(eventKind)
{
case kEventRawKeyDown:
action = SI_MAKE;
fvalue = 1.0f;
break;
case kEventRawKeyUp:
action = SI_BREAK;
fvalue = 0.0f;
break;
case kEventRawKeyRepeat:
action = SI_REPEAT;
fvalue = 1.0f;
break;
default:
AssertISV(false, "Unhandled keyboard event kind!");
}
// --
//---- fill the event ----
torqueEvent.deviceType = KeyboardDeviceType;
torqueEvent.deviceInst = 0;
torqueEvent.objType = SI_KEY;
torqueEvent.objInst = TranslateOSKeyCode(keyCode);
torqueEvent.modifier = 0; //modifierKeys;
torqueEvent.ascii = 0;
torqueEvent.action = action;
torqueEvent.fValue = fvalue;
// -------------------------------------- BEGIN NEW CODE --------------------------------------
// Make it so modifiers have no effect on most keys. You must detect modifiers separately in script.
// (This is so that, for example, you still get keyUp/down events for the arrow keys, regardless of whether
// a modifier key is held down.)
if (keyCode >= 0x30 || keyCode == 0x24)
torqueEvent.modifier = 0;
// -------------------------------------- END NEW CODE --------------------------------------
}Note that the way Torque currrently handles this should indeed be considered to be a bug, because it happens even if you do this:
shift key down
right arrow key down
right arrow key up
[You receive no TorqueScript notification of the right arrow key being released, unless you use my modification above.]
This is clearly incorrect, because the first event -- when the right arrow key was pushed down, *should* have been interpreted as "shift right" down, if indeed the engine wants to also interpret the right arrow key beign released as "shift right" released. But it doesn't. It sends an event for the right arrow key being pressed, but none for it being released, due to the shift key being down. And again, this is how the Windows version behaves, which is unaffected by my modifications.
-Vern
#7
12/05/2007 (12:50 pm)
Very good. I added this to my report. Either Stephen or I will get this to the right people. Thank you again!
#8
12/05/2007 (1:29 pm)
Cool, good to hear.
#9
10/30/2013 (10:02 am)
For some reason, six years later, whenever I have a problem Vern has the answer. I couldn't understand why I wasn't getting key up events when the shift key was down - and here's the answer.
Torque 3D Owner Stephen Zepp