📄 actionmap.cc
字号:
pRetNode->deadZoneEnd = 0.0;
pRetNode->scaleFactor = 1.0;
pRetNode->consoleFunction = NULL;
pRetNode->makeConsoleCommand = NULL;
pRetNode->breakConsoleCommand = NULL;
return pRetNode;
}
//------------------------------------------------------------------------------
void ActionMap::removeNode(const U32 inDeviceType, const U32 inDeviceInst, const U32 inModifiers, const U32 inAction)
{
// DMMTODO - Slow INITIAL implementation. Replace with a faster version...
//
DeviceMap* pDeviceMap = NULL;
U32 i;
for (i = 0; i < mDeviceMaps.size(); i++) {
if (mDeviceMaps[i]->deviceType == inDeviceType &&
mDeviceMaps[i]->deviceInst == inDeviceInst) {
pDeviceMap = mDeviceMaps[i];
break;
}
}
if (pDeviceMap == NULL)
return;
U32 realMods = inModifiers;
if (realMods & SI_SHIFT)
realMods |= SI_SHIFT;
if (realMods & SI_CTRL)
realMods |= SI_CTRL;
if (realMods & SI_ALT)
realMods |= SI_ALT;
if (realMods & SI_MAC_OPT)
realMods |= SI_MAC_OPT;
for (i = 0; i < pDeviceMap->nodeMap.size(); i++) {
if (pDeviceMap->nodeMap[i].modifiers == realMods &&
pDeviceMap->nodeMap[i].action == inAction) {
dFree(pDeviceMap->nodeMap[i].makeConsoleCommand);
dFree(pDeviceMap->nodeMap[i].breakConsoleCommand);
pDeviceMap->nodeMap.erase(i);
}
}
}
//------------------------------------------------------------------------------
const ActionMap::Node* ActionMap::findNode(const U32 inDeviceType, const U32 inDeviceInst,
const U32 inModifiers, const U32 inAction)
{
// DMMTODO - Slow INITIAL implementation. Replace with a faster version...
//
DeviceMap* pDeviceMap = NULL;
U32 i;
for (i = 0; i < mDeviceMaps.size(); i++)
{
if (mDeviceMaps[i]->deviceType == inDeviceType && mDeviceMaps[i]->deviceInst == inDeviceInst)
{
pDeviceMap = mDeviceMaps[i];
break;
}
}
if (pDeviceMap == NULL)
return NULL;
U32 realMods = inModifiers;
if (realMods & SI_SHIFT)
realMods |= SI_SHIFT;
if (realMods & SI_CTRL)
realMods |= SI_CTRL;
if (realMods & SI_ALT)
realMods |= SI_ALT;
if (realMods & SI_MAC_OPT)
realMods |= SI_MAC_OPT;
for (i = 0; i < pDeviceMap->nodeMap.size(); i++)
{
if (pDeviceMap->nodeMap[i].action == KEY_ANYKEY && pDeviceMap->nodeMap[i].modifiers == realMods && dIsDecentChar(inAction))
return &pDeviceMap->nodeMap[i];
else if (pDeviceMap->nodeMap[i].modifiers == realMods && pDeviceMap->nodeMap[i].action == inAction)
return &pDeviceMap->nodeMap[i];
}
return NULL;
}
//------------------------------------------------------------------------------
bool ActionMap::findBoundNode( const char* function, U32 &devMapIndex, U32 &nodeIndex )
{
// Loop through all of the existing nodes to find the one mapped to the
// given function:
for ( U32 i = 0; i < mDeviceMaps.size(); i++ )
{
const DeviceMap* dvcMap = mDeviceMaps[i];
for ( U32 j = 0; j < dvcMap->nodeMap.size(); j++ )
{
const Node* node = &dvcMap->nodeMap[j];
if ( !( node->flags & Node::BindCmd ) && ( dStricmp( function, node->consoleFunction ) == 0 ) )
{
devMapIndex = i;
nodeIndex = j;
return( true );
}
}
}
return( false );
}
//------------------------------------------------------------------------------
bool ActionMap::processUnbind(const char *device, const char *action)
{
U32 deviceType;
U32 deviceInst;
if(!getDeviceTypeAndInstance(device, deviceType, deviceInst))
return false;
EventDescriptor eventDescriptor;
if (!createEventDescriptor(action, &eventDescriptor))
return false;
removeNode(deviceType, deviceInst, eventDescriptor.flags,eventDescriptor.eventCode);
return true;
}
//------------------------------------------------------------------------------
// This function is for the use of the control remapper.
// It will only check against the console function (since all remappable commands are
// bound using bind and not bindCmd).
//
const char* ActionMap::getBinding( const char* command )
{
U32 devMapIndex, nodeIndex;
if ( findBoundNode( command, devMapIndex, nodeIndex ) )
{
char buffer[256];
const DeviceMap* deviceMap = mDeviceMaps[devMapIndex];
char deviceBuffer[32];
if ( !getDeviceName( deviceMap->deviceType, deviceMap->deviceInst, deviceBuffer ) )
return( "" );
const Node* node = &deviceMap->nodeMap[nodeIndex];
const char* modifierString = getModifierString( node->modifiers );
char keyBuffer[64];
if ( !getKeyString( node->action, keyBuffer ) )
return( "" );
dSprintf( buffer, sizeof( buffer ), "%s\t%s%s", deviceBuffer, modifierString, keyBuffer );
// Copy the buffer and return it:
char* returnString = Con::getReturnBuffer( dStrlen( buffer ) + 1 );
dStrcpy( returnString, buffer );
return( returnString );
}
return( "" );
}
//------------------------------------------------------------------------------
// This function is for the use of the control remapper.
// The intent of this function is to determine if the given event descriptor is already
// bound in this action map. If so, this function returns the command it is bound to.
// If not, it returns NULL.
//
const char* ActionMap::getCommand( const char* device, const char* action )
{
U32 deviceType;
U32 deviceInst;
if ( getDeviceTypeAndInstance( device, deviceType, deviceInst ) )
{
EventDescriptor eventDescriptor;
if ( createEventDescriptor( action, &eventDescriptor ) )
{
const ActionMap::Node* mapNode = findNode( deviceType, deviceInst, eventDescriptor.flags, eventDescriptor.eventCode );
if ( mapNode )
{
if ( mapNode->flags & Node::BindCmd )
{
S32 bufferLen = dStrlen( mapNode->makeConsoleCommand ) + dStrlen( mapNode->breakConsoleCommand ) + 2;
char* returnString = Con::getReturnBuffer( bufferLen );
dSprintf( returnString, bufferLen, "%s\t%s",
( mapNode->makeConsoleCommand ? mapNode->makeConsoleCommand : "" ),
( mapNode->breakConsoleCommand ? mapNode->breakConsoleCommand : "" ) );
return( returnString );
}
else
return( mapNode->consoleFunction );
}
}
}
return( "" );
}
//------------------------------------------------------------------------------
// This function returns whether or not the mapping specified is inverted.
// Obviously, this should only be used for axes.
bool ActionMap::isInverted( const char* device, const char* action )
{
U32 deviceType;
U32 deviceInst;
if ( getDeviceTypeAndInstance( device, deviceType, deviceInst ) )
{
EventDescriptor eventDescriptor;
if ( createEventDescriptor( action, &eventDescriptor ) )
{
const ActionMap::Node* mapNode = findNode( deviceType, deviceInst, eventDescriptor.flags, eventDescriptor.eventCode );
if ( mapNode )
return( mapNode->flags & Node::Inverted );
}
}
Con::errorf( "The input event specified by %s %s is not in this action map!", device, action );
return( false );
}
//------------------------------------------------------------------------------
F32 ActionMap::getScale( const char* device, const char* action )
{
U32 deviceType;
U32 deviceInst;
if ( getDeviceTypeAndInstance( device, deviceType, deviceInst ) )
{
EventDescriptor eventDescriptor;
if ( createEventDescriptor( action, &eventDescriptor ) )
{
const ActionMap::Node* mapNode = findNode( deviceType, deviceInst, eventDescriptor.flags, eventDescriptor.eventCode );
if ( mapNode )
{
if ( mapNode->flags & Node::HasScale )
return( mapNode->scaleFactor );
else
return( 1.0f );
}
}
}
Con::errorf( "The input event specified by %s %s is not in this action map!", device, action );
return( 1.0f );
}
//------------------------------------------------------------------------------
const char* ActionMap::getDeadZone( const char* device, const char* action )
{
U32 deviceType;
U32 deviceInst;
if ( getDeviceTypeAndInstance( device, deviceType, deviceInst ) )
{
EventDescriptor eventDescriptor;
if ( createEventDescriptor( action, &eventDescriptor ) )
{
const ActionMap::Node* mapNode = findNode( deviceType, deviceInst, eventDescriptor.flags, eventDescriptor.eventCode );
if ( mapNode )
{
if ( mapNode->flags & Node::HasDeadZone )
{
char buf[64];
dSprintf( buf, sizeof( buf ), "%g %g", mapNode->deadZoneBegin, mapNode->deadZoneEnd );
char* returnString = Con::getReturnBuffer( dStrlen( buf ) + 1 );
dStrcpy( returnString, buf );
return( returnString );
}
else
return( "0 0" );
}
}
}
Con::errorf( "The input event specified by %s %s is not in this action map!", device, action );
return( "" );
}
//------------------------------------------------------------------------------
const char* ActionMap::buildActionString( const InputEvent* event )
{
const char* modifierString = getModifierString( event->modifier );
char objectBuffer[64];
if ( !getKeyString( event->objInst, objectBuffer ) )
return( "" );
U32 returnLen = dStrlen( modifierString ) + dStrlen( objectBuffer ) + 2;
char* returnString = Con::getReturnBuffer( returnLen );
dSprintf( returnString, returnLen - 1, "%s%s", modifierString, objectBuffer );
return( returnString );
}
//------------------------------------------------------------------------------
bool ActionMap::getDeviceTypeAndInstance(const char *pDeviceName, U32 &deviceType, U32 &deviceInstance)
{
U32 offset = 0;
if (dStrnicmp(pDeviceName, "keyboard", dStrlen("keyboard")) == 0) {
deviceType = KeyboardDeviceType;
offset = dStrlen("keyboard");
} else if (dStrnicmp(pDeviceName, "mouse", dStrlen("mouse")) == 0) {
deviceType = MouseDeviceType;
offset = dStrlen("mouse");
} else if (dStrnicmp(pDeviceName, "joystick", dStrlen("joystick")) == 0) {
deviceType = JoystickDeviceType;
offset = dStrlen("joystick");
} else {
return false;
}
if (dStrlen(pDeviceName) > offset) {
const char* pInst = pDeviceName + offset;
S32 instNum = dAtoi(pInst);
if (instNum < 0)
deviceInstance = 0;
else
deviceInstance = instNum;
} else {
deviceInstance = 0;
}
return true;
}
//------------------------------------------------------------------------------
bool ActionMap::getDeviceName(const U32 deviceType, const U32 deviceInstance, char* buffer)
{
switch (deviceType) {
case KeyboardDeviceType:
dStrcpy(buffer, "keyboard");
break;
case MouseDeviceType:
dSprintf(buffer, 16, "mouse%d", deviceInstance);
break;
case JoystickDeviceType:
dSprintf(buffer, 16, "joystick%d", deviceInstance);
break;
default:
Con::errorf( "ActionMap::getDeviceName: unknown device type specified, %d (inst: %d)", deviceType, deviceInstance);
return false;
}
return true;
}
//------------------------------------------------------------------------------
const char* ActionMap::getModifierString(const U32 modifiers)
{
U32 realModifiers = modifiers;
if ( modifiers & SI_LSHIFT || modifiers & SI_RSHIFT )
realModifiers |= SI_SHIFT;
if ( modifiers & SI_LCTRL || modifiers & SI_RCTRL )
realModifiers |= SI_CTRL;
if ( modifiers & SI_LALT || modifiers & SI_RALT )
realModifiers |= SI_ALT;
if ( modifiers & SI_MAC_LOPT || modifiers & SI_MAC_ROPT )
realModifiers |= SI_MAC_OPT;
switch (realModifiers & (SI_SHIFT|SI_CTRL|SI_ALT|SI_MAC_OPT)) {
#if defined(TORQUE_OS_MAC)
// optional code, to output alt as cmd on mac.
// interpreter sees them as the same...
case (SI_SHIFT|SI_CTRL|SI_ALT):
return "shift-ctrl-cmd ";
case (SI_SHIFT|SI_ALT):
return "shift-cmd ";
case (SI_CTRL|SI_ALT):
return "ctrl-cmd ";
case (SI_ALT):
return "cmd ";
#else
case (SI_SHIFT|SI_CTRL|SI_ALT):
return "shift-ctrl-alt ";
case (SI_SHIFT|SI_ALT):
return "shift-alt ";
case (SI_CTRL|SI_ALT):
return "ctrl-alt ";
case (SI_ALT):
return "alt ";
#endif
case (SI_SHIFT|SI_CTRL):
return "shift-ctrl ";
case (SI_SHIFT):
return "shift ";
case (SI_CTRL):
return "ctrl ";
// plus new mac cases:
case (SI_SHIFT|SI_CTRL|SI_MAC_OPT):
return "shift-ctrl-opt ";
case (SI_SHIFT|SI_MAC_OPT):
return "shift-opt ";
case (SI_CTRL|SI_MAC_OPT):
return "ctrl-opt ";
case (SI_MAC_OPT):
return "opt ";
case 0:
return "";
default:
AssertFatal(false, "Error, should never reach the default case in getModifierString");
return "";
}
}
//------------------------------------------------------------------------------
bool ActionMap::getKeyString(const U32 action, char* buffer)
{
U16 asciiCode = Input::getAscii(action, STATE_LOWER);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -