📄 actionmap.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "sim/actionMap.h"
#include "platform/event.h"
#include "console/console.h"
#include "platform/platform.h"
#include "platform/platformInput.h"
#include "platform/platformAssert.h"
#include "core/fileStream.h"
#include "core/resManager.h"
IMPLEMENT_CONOBJECT(ActionMap);
// This is used for determing keys that have ascii codes for the foreign keyboards. IsAlpha doesn't work on foreign keys.
#define dIsDecentChar(c) (((char(0xa0) <= (c)) && ((c) <= char(0xff))) || (( char(0x21) <= (c)) && ((c) <= char(0x7e))) || (( char(0x91) <= (c)) && ((c) <= char(0x92))))
struct CodeMapping
{
const char* pDescription;
U8 type;
U32 code;
};
struct AsciiMapping
{
const char* pDescription;
U16 asciiCode;
};
extern CodeMapping gVirtualMap[];
extern AsciiMapping gAsciiMap[];
//------------------------------------------------------------------------------
//-------------------------------------- Action maps
//
Vector<ActionMap::BreakEntry> ActionMap::smBreakTable(__FILE__, __LINE__);
//------------------------------------------------------------------------------
ActionMap::ActionMap()
{
VECTOR_SET_ASSOCIATION(mDeviceMaps);
}
//------------------------------------------------------------------------------
ActionMap::~ActionMap()
{
for (U32 i = 0; i < mDeviceMaps.size(); i++)
delete mDeviceMaps[i];
mDeviceMaps.clear();
}
//------------------------------------------------------------------------------
ActionMap::DeviceMap::~DeviceMap()
{
for(U32 i = 0; i < nodeMap.size(); i++)
{
dFree(nodeMap[i].makeConsoleCommand);
dFree(nodeMap[i].breakConsoleCommand);
}
}
//------------------------------------------------------------------------------
bool ActionMap::onAdd()
{
if (Parent::onAdd() == false)
return false;
Sim::getActionMapGroup()->addObject(this);
return true;
}
//--------------------------------------------------------------------------
void ActionMap::dumpActionMap(const char* fileName, const bool append) const
{
if (fileName != NULL) {
// Dump the deletion, and creation script commands, followed by all the binds
// to a script.
FileStream iostrm;
if ( !ResourceManager->openFileForWrite( iostrm, fileName, append ? FileStream::WriteAppend : FileStream::Write ) )
{
Con::errorf( "Unable to open file '%s' for writing.", fileName );
return;
}
char lineBuffer[1024];
if ( append )
iostrm.setPosition( iostrm.getStreamSize() );
else
{
// IMPORTANT -- do NOT change the following line, it identifies the file as an input map file
dStrcpy( lineBuffer, "// Torque Input Map File\n" );
iostrm.write( dStrlen( lineBuffer ), lineBuffer );
}
dSprintf(lineBuffer, 1023, "%s.delete();\n"
"new ActionMap(%s);\n", getName(), getName());
iostrm.write(dStrlen(lineBuffer), lineBuffer);
// Dump all the binds to the console...
for (S32 i = 0; i < mDeviceMaps.size(); i++) {
const DeviceMap* pDevMap = mDeviceMaps[i];
char devbuffer[32];
getDeviceName(pDevMap->deviceType, pDevMap->deviceInst, devbuffer);
for (S32 j = 0; j < pDevMap->nodeMap.size(); j++) {
const Node& rNode = pDevMap->nodeMap[j];
const char* pModifierString = getModifierString(rNode.modifiers);
char objectbuffer[64];
if (getKeyString(rNode.action, objectbuffer) == false)
continue;
const char* command = (rNode.flags & Node::BindCmd) ? "bindCmd" : "bind";
dSprintf(lineBuffer, 1023, "%s.%s(%s, \"%s%s\"",
getName(),
command,
devbuffer,
pModifierString, objectbuffer);
if (rNode.flags & (Node::HasScale|Node::HasDeadZone|Node::Ranged|Node::Inverted)) {
char buff[10];
U32 curr = 0;
buff[curr++] = ',';
buff[curr++] = ' ';
if (rNode.flags & Node::HasScale)
buff[curr++] = 'S';
if (rNode.flags & Node::Ranged)
buff[curr++] = 'R';
if (rNode.flags & Node::HasDeadZone)
buff[curr++] = 'D';
if (rNode.flags & Node::Inverted)
buff[curr++] = 'I';
buff[curr] = '\0';
dStrcat(lineBuffer, buff);
}
if (rNode.flags & Node::HasDeadZone) {
char buff[64];
dSprintf(buff, 63, ", \"%g %g\"", rNode.deadZoneBegin, rNode.deadZoneEnd);
dStrcat(lineBuffer, buff);
}
if (rNode.flags & Node::HasScale) {
char buff[64];
dSprintf(buff, 63, ", %g", rNode.scaleFactor);
dStrcat(lineBuffer, buff);
}
if (rNode.flags & Node::BindCmd) {
if (rNode.makeConsoleCommand) {
dStrcat(lineBuffer, ", \"");
U32 pos = dStrlen(lineBuffer);
expandEscape(lineBuffer + pos, rNode.makeConsoleCommand);
dStrcat(lineBuffer, "\"");
} else {
dStrcat(lineBuffer, ", \"\"");
}
if (rNode.breakConsoleCommand) {
dStrcat(lineBuffer, ", \"");
U32 pos = dStrlen(lineBuffer);
expandEscape(lineBuffer + pos, rNode.breakConsoleCommand);
dStrcat(lineBuffer, "\"");
}
else
dStrcat(lineBuffer, ", \"\"");
} else {
dStrcat(lineBuffer, ", ");
dStrcat(lineBuffer, rNode.consoleFunction);
}
dStrcat(lineBuffer, ");\n");
iostrm.write(dStrlen(lineBuffer), lineBuffer);
}
}
iostrm.close();
}
else {
// Dump all the binds to the console...
for (S32 i = 0; i < mDeviceMaps.size(); i++) {
const DeviceMap* pDevMap = mDeviceMaps[i];
char devbuffer[32];
getDeviceName(pDevMap->deviceType, pDevMap->deviceInst, devbuffer);
for (S32 j = 0; j < pDevMap->nodeMap.size(); j++) {
const Node& rNode = pDevMap->nodeMap[j];
const char* pModifierString = getModifierString(rNode.modifiers);
char keybuffer[64];
if (getKeyString(rNode.action, keybuffer) == false)
continue;
const char* command = (rNode.flags & Node::BindCmd) ? "bindCmd" : "bind";
char finalBuffer[1024];
dSprintf(finalBuffer, 1023, "%s.%s(%s, \"%s%s\"",
getName(),
command,
devbuffer,
pModifierString, keybuffer);
if (rNode.flags & (Node::HasScale|Node::HasDeadZone|Node::Ranged|Node::Inverted)) {
char buff[10];
U32 curr = 0;
buff[curr++] = ',';
buff[curr++] = ' ';
if (rNode.flags & Node::HasScale)
buff[curr++] = 'S';
if (rNode.flags & Node::Ranged)
buff[curr++] = 'R';
if (rNode.flags & Node::HasDeadZone)
buff[curr++] = 'D';
if (rNode.flags & Node::Inverted)
buff[curr++] = 'I';
buff[curr] = '\0';
dStrcat(finalBuffer, buff);
}
if (rNode.flags & Node::HasDeadZone) {
char buff[64];
dSprintf(buff, 63, ", \"%g %g\"", rNode.deadZoneBegin, rNode.deadZoneEnd);
dStrcat(finalBuffer, buff);
}
if (rNode.flags & Node::HasScale) {
char buff[64];
dSprintf(buff, 63, ", %g", rNode.scaleFactor);
dStrcat(finalBuffer, buff);
}
if (rNode.flags & Node::BindCmd) {
if (rNode.makeConsoleCommand) {
dStrcat(finalBuffer, ", \"");
dStrcat(finalBuffer, rNode.makeConsoleCommand);
dStrcat(finalBuffer, "\"");
} else {
dStrcat(finalBuffer, ", \"\"");
}
if (rNode.breakConsoleCommand) {
dStrcat(finalBuffer, ", \"");
dStrcat(finalBuffer, rNode.breakConsoleCommand);
dStrcat(finalBuffer, "\"");
}
else
dStrcat(finalBuffer, ", \"\"");
} else {
dStrcat(finalBuffer, ", ");
dStrcat(finalBuffer, rNode.consoleFunction);
}
dStrcat(finalBuffer, ");");
Con::printf(finalBuffer);
}
}
}
}
//--------------------------------------------------------------------------
bool ActionMap::createEventDescriptor(const char* pEventString, EventDescriptor* pDescriptor)
{
#ifdef TGE_RPG
if(!pEventString || !pEventString[0])
return false;
#endif
char copyBuffer[256];
dStrcpy(copyBuffer, pEventString);
// Do we have modifiers?
char* pSpace = dStrchr(copyBuffer, ' ');
char* pObjectString;
if (pSpace != NULL) {
// Yes. Parse them out...
//
pDescriptor->flags = 0;
pObjectString = pSpace + 1;
pSpace[0] = '\0';
char* pModifier = dStrtok(copyBuffer, "-");
while (pModifier != NULL) {
if (dStricmp(pModifier, "shift") == 0) {
pDescriptor->flags |= SI_SHIFT;
} else if (dStricmp(pModifier, "ctrl") == 0) {
pDescriptor->flags |= SI_CTRL;
} else if (dStricmp(pModifier, "alt") == 0) {
pDescriptor->flags |= SI_ALT;
} else if (dStricmp(pModifier, "cmd") == 0) {
pDescriptor->flags |= SI_ALT;
} else if (dStricmp(pModifier, "opt") == 0) {
pDescriptor->flags |= SI_MAC_OPT;
}
pModifier = dStrtok(NULL, "-");
}
} else {
// No.
pDescriptor->flags = 0;
pObjectString = copyBuffer;
}
// Now we need to map the key string to the proper KEY code from event.h
//
AssertFatal(dStrlen(pObjectString) != 0, "Error, no key was specified!");
if (dStrlen(pObjectString) == 1)
{
if (dIsDecentChar(*pObjectString)) // includes foreign chars
{
U16 asciiCode = (*pObjectString);
// clear out the FF in upper 8bits for foreign keys??
asciiCode &= 0xFF;
U16 keyCode = Input::getKeyCode(asciiCode);
if ( keyCode >= KEY_0 )
{
pDescriptor->eventType = SI_KEY;
pDescriptor->eventCode = keyCode;
return true;
}
else if (dIsalpha(*pObjectString) == true)
{
pDescriptor->eventType = SI_KEY;
pDescriptor->eventCode = KEY_A+dTolower(*pObjectString)-'a';
return true;
}
else if (dIsdigit(*pObjectString) == true)
{
pDescriptor->eventType = SI_KEY;
pDescriptor->eventCode = KEY_0+(*pObjectString)-'0';
return true;
}
}
return false;
}
else
{
pDescriptor->eventCode = 0;
// Gotta search through the Ascii table...
for (U16 i = 0; gAsciiMap[i].asciiCode != 0xFFFF; i++)
{
if (dStricmp(pObjectString, gAsciiMap[i].pDescription) == 0)
{
U16 asciiCode = gAsciiMap[i].asciiCode;
U16 keyCode = Input::getKeyCode(asciiCode);
if ( keyCode >= KEY_0 )
{
pDescriptor->eventType = SI_KEY;
pDescriptor->eventCode = keyCode;
return(true);
}
else
{
break;
}
}
}
// Didn't find an ascii match. Check the virtual map table
for (U32 j = 0; gVirtualMap[j].code != 0xFFFFFFFF; j++)
{
if (dStricmp(pObjectString, gVirtualMap[j].pDescription) == 0)
{
pDescriptor->eventType = gVirtualMap[j].type;
pDescriptor->eventCode = gVirtualMap[j].code;
return true;
}
}
}
return false;
}
//------------------------------------------------------------------------------
ActionMap::Node* ActionMap::getNode(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) {
mDeviceMaps.increment();
mDeviceMaps.last() = new DeviceMap;
pDeviceMap = mDeviceMaps.last();
pDeviceMap->deviceInst = inDeviceInst;
pDeviceMap->deviceType = inDeviceType;
}
for (i = 0; i < pDeviceMap->nodeMap.size(); i++) {
if (pDeviceMap->nodeMap[i].modifiers == inModifiers &&
pDeviceMap->nodeMap[i].action == inAction) {
return &pDeviceMap->nodeMap[i];
}
}
// If we're here, the node doesn't exist. create it.
pDeviceMap->nodeMap.increment();
Node* pRetNode = &pDeviceMap->nodeMap.last();
pRetNode->modifiers = inModifiers;
pRetNode->action = inAction;
pRetNode->flags = 0;
pRetNode->deadZoneBegin = 0.0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -