Event handling of modifier keys
From TDN
(This code discussion is based on TGE1.5.2 source.)
One of the handy things you can do in Torquescript is bind the modifier keys (shift, control, alt) to the moveMap. For example in my client/scripts/default.bind.cs I toggle the display of certain hud elements when the shift key is pressed;
$is_left_shift_down = 0;
function toggleLeftShift(%val)
{
echo ("toggleLeftShift(" @ %val @ ")");
$is_left_shift_down = %val;
updateSymbolEntryDisplay();
}
moveMap.bind(keyboard, "lshift", toggleLeftShift );
Which works fine in a Windows build. It didn't work for my Mac build however until I made the following substitution in platformMacCarb/macCarbEvents.cc replacing the existing _OnRawModifiers() function with this;
//-----------------------------------------------------------------------------
static OSStatus _OnRawModifiers(EventRef theEvent)
{
static U32 oldModState = 0L;
U32 mods;
GetEventParameter(theEvent, kEventParamKeyModifiers,
typeUInt32, NULL, sizeof(UInt32), NULL, &mods);
// slesh ---
// want to notify app of modifier press alone, not just in conjunction with other keys
// what changed in modifier keys since last modifier notification...
U32 makeMods = ~oldModState & mods;
U32 breakMods = oldModState & ~mods;
UInt32 keyCode = 0;
U32 action = 0;
if (makeMods & shiftKey) {
keyCode = KEY_LSHIFT;
action = SI_MAKE;
} else if (breakMods & shiftKey) {
keyCode = KEY_LSHIFT;
action = SI_BREAK;
}
/*if (makeMods & rightShiftKey) {
keyCode = KEY_RSHIFT;
if (mods & rightShiftKey)
action = SI_MAKE;
else
action = SI_BREAK;
}*/
if (makeMods & cmdKey) {
keyCode = KEY_LALT;
action = SI_MAKE;
} else if (breakMods & cmdKey) {
keyCode = KEY_LALT;
action = SI_BREAK;
}
if (makeMods & optionKey) {
keyCode = KEY_LALT; //KEY_MAC_OPT;
action = SI_MAKE;
} else if (breakMods & optionKey) {
keyCode = KEY_LALT; //KEY_MAC_OPT;
action = SI_BREAK;
}
//if (changedMods & rightOptionKey) keyCode = SI_MAC_ROPT;
if (makeMods & controlKey) {
keyCode = KEY_LCONTROL; //SI_LCTRL;
action = SI_MAKE;
} else if (breakMods & controlKey) {
keyCode = KEY_LCONTROL; //SI_LCTRL;
action = SI_BREAK;
}
//if (changedMods & rightControlKey) keyCode = SI_RCTRL;
InputEvent torqueEvent;
torqueEvent.deviceType = KeyboardDeviceType;
torqueEvent.deviceInst = 0;
torqueEvent.objType = SI_KEY;
torqueEvent.objInst = keyCode;
torqueEvent.modifier = 0;
torqueEvent.ascii = 0;
torqueEvent.action = action;
torqueEvent.fValue = (action == SI_BREAK) ? 0.0f : 1.0f;
Game->postEvent(torqueEvent);
// --- end slesh
oldModState = mods;
return noErr;
}
Or something to that effect.
Here is a modified version by Alex Stone which accomodates multiple key-state changes per event.
static OSStatus _OnRawModifiers(EventRef theEvent)
{
static U32 oldModState = 0L;
U32 mods;
GetEventParameter(theEvent, kEventParamKeyModifiers,
typeUInt32, NULL, sizeof(UInt32), NULL, &mods);
InputEvent evt;
U32 makeMods = ~oldModState & mods;
U32 breakMods = oldModState & ~mods;
evt.deviceType = KeyboardDeviceType;
evt.deviceInst = 0;
evt.objType = SI_KEY;
evt.modifier = 0;
evt.ascii = 0;
//evt.action = action;
//evt.fValue = fvalue;
//Figure out which keys are now up (Break), which ones are now down (Make)
if(breakMods & shiftKey)
{
evt.objInst = KEY_LSHIFT;
evt.action = SI_BREAK;
evt.fValue = 0.0f;
Game->postEvent(evt);
}
else if(makeMods & shiftKey)
{
evt.objInst = KEY_LSHIFT;
evt.action = SI_MAKE;
evt.fValue = 1.0f;
Game->postEvent(evt);
}
if(breakMods & rightShiftKey)
{
evt.objInst = KEY_RSHIFT;
evt.action = SI_BREAK;
evt.fValue = 0.0f;
Game->postEvent(evt);
}
else if(makeMods & rightShiftKey)
{
evt.objInst = KEY_RSHIFT;
evt.action = SI_MAKE;
evt.fValue = 1.0f;
Game->postEvent(evt);
}
if(breakMods & controlKey)
{
evt.objInst = KEY_LCONTROL;
evt.action = SI_BREAK;
evt.fValue = 0.0f;
Game->postEvent(evt);
}
else if(makeMods & controlKey)
{
evt.objInst = KEY_LCONTROL;
evt.action = SI_MAKE;
evt.fValue = 1.0f;
Game->postEvent(evt);
}
if(breakMods & rightControlKey)
{
evt.objInst = KEY_RCONTROL;
evt.action = SI_BREAK;
evt.fValue = 0.0f;
Game->postEvent(evt);
}
else if(makeMods & rightControlKey)
{
evt.objInst = KEY_RCONTROL;
evt.action = SI_MAKE;
evt.fValue = 1.0f;
Game->postEvent(evt);
}
if(breakMods & (optionKey | cmdKey))
{
evt.objInst = KEY_LALT;
evt.action = SI_BREAK;
evt.fValue = 0.0f;
Game->postEvent(evt);
}
else if(makeMods & (optionKey | cmdKey))
{
evt.objInst = KEY_LALT;
evt.action = SI_MAKE;
evt.fValue = 1.0f;
Game->postEvent(evt);
}
if(breakMods & rightOptionKey)
{
evt.objInst = KEY_RALT;
evt.action = SI_BREAK;
evt.fValue = 0.0f;
Game->postEvent(evt);
}
else if(makeMods & rightOptionKey)
{
evt.objInst = KEY_RALT;
evt.action = SI_MAKE;
evt.fValue = 1.0f;
Game->postEvent(evt);
}
oldModState = mods;
return noErr;
}



