|
@@ -1,2294 +1,2294 @@
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
-// Copyright (c) 2013 GarageGames, LLC
|
|
|
|
-//
|
|
|
|
-// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
-// of this software and associated documentation files (the "Software"), to
|
|
|
|
-// deal in the Software without restriction, including without limitation the
|
|
|
|
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
|
-// sell copies of the Software, and to permit persons to whom the Software is
|
|
|
|
-// furnished to do so, subject to the following conditions:
|
|
|
|
-//
|
|
|
|
-// The above copyright notice and this permission notice shall be included in
|
|
|
|
-// all copies or substantial portions of the Software.
|
|
|
|
-//
|
|
|
|
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
-// IN THE SOFTWARE.
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
-
|
|
|
|
-#include "input/actionMap.h"
|
|
|
|
-#include "platform/event.h"
|
|
|
|
-#include "console/console.h"
|
|
|
|
-#include "platform/platform.h"
|
|
|
|
-#include "platform/platformInput.h"
|
|
|
|
-#include "platform/platformAssert.h"
|
|
|
|
-#include "io/fileStream.h"
|
|
|
|
-#include "io/resource/resourceManager.h"
|
|
|
|
-
|
|
|
|
-// Script bindings.
|
|
|
|
-#include "actionMap_ScriptBinding.h"
|
|
|
|
-
|
|
|
|
-#define CONST_E 2.7182818284590452353602874f
|
|
|
|
-
|
|
|
|
-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 < (U32)mDeviceMaps.size(); i++)
|
|
|
|
- delete mDeviceMaps[i];
|
|
|
|
- mDeviceMaps.clear();
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-ActionMap::DeviceMap::~DeviceMap()
|
|
|
|
-{
|
|
|
|
- for(U32 i = 0; i < (U32)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, "if (isObject(%s)) %s.delete();\n"
|
|
|
|
- "new ActionMap(%s);\n", getName(), 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)
|
|
|
|
-{
|
|
|
|
- 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,SimObject* object /*= NULL*/)
|
|
|
|
-{
|
|
|
|
- // DMMTODO - Slow INITIAL implementation. Replace with a faster version...
|
|
|
|
- //
|
|
|
|
- DeviceMap* pDeviceMap = NULL;
|
|
|
|
- U32 i;
|
|
|
|
- for (i = 0; i < (U32)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 < (U32)pDeviceMap->nodeMap.size(); i++)
|
|
|
|
- {
|
|
|
|
- if (pDeviceMap->nodeMap[i].modifiers == inModifiers &&
|
|
|
|
- pDeviceMap->nodeMap[i].action == inAction &&
|
|
|
|
- ( (object != NULL) ? object == pDeviceMap->nodeMap[i].object : true )) // Check for an object match if the object exists
|
|
|
|
- {
|
|
|
|
- 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;
|
|
|
|
- pRetNode->deadZoneEnd = 0.0;
|
|
|
|
- pRetNode->scaleFactor = 1.0;
|
|
|
|
-
|
|
|
|
- pRetNode->consoleFunction = NULL;
|
|
|
|
- pRetNode->makeConsoleCommand = NULL;
|
|
|
|
- pRetNode->breakConsoleCommand = NULL;
|
|
|
|
-
|
|
|
|
- //[neob, 5/7/2007 - #2975]
|
|
|
|
- pRetNode->object = 0;
|
|
|
|
-
|
|
|
|
- return pRetNode;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-void ActionMap::removeNode(const U32 inDeviceType, const U32 inDeviceInst, const U32 inModifiers, const U32 inAction, SimObject* object /*= NULL*/)
|
|
|
|
-{
|
|
|
|
- // DMMTODO - Slow INITIAL implementation. Replace with a faster version...
|
|
|
|
- //
|
|
|
|
- DeviceMap* pDeviceMap = NULL;
|
|
|
|
- U32 i;
|
|
|
|
- for (i = 0; i < (U32)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 < (U32)pDeviceMap->nodeMap.size(); i++) {
|
|
|
|
- if (pDeviceMap->nodeMap[i].modifiers == realMods &&
|
|
|
|
- pDeviceMap->nodeMap[i].action == inAction &&
|
|
|
|
- ( (object != NULL) ? object == pDeviceMap->nodeMap[i].object : true ))
|
|
|
|
- {
|
|
|
|
- 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 < (U32)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 < (U32)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 )
|
|
|
|
-{
|
|
|
|
- devMapIndex = 0;
|
|
|
|
- nodeIndex = 0;
|
|
|
|
- return nextBoundNode( function, devMapIndex, nodeIndex );
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-bool ActionMap::nextBoundNode( 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 = devMapIndex; i < (U32)mDeviceMaps.size(); i++ )
|
|
|
|
- {
|
|
|
|
- const DeviceMap* dvcMap = mDeviceMaps[i];
|
|
|
|
-
|
|
|
|
- for ( U32 j = nodeIndex; j < (U32)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 );
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- nodeIndex = 0;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return( false );
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-bool ActionMap::processUnbind(const char *device, const char *action, SimObject* object /*= NULL*/)
|
|
|
|
-{
|
|
|
|
- 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, object);
|
|
|
|
- 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 )
|
|
|
|
-{
|
|
|
|
- char* returnString = Con::getReturnBuffer( 1024 );
|
|
|
|
- returnString[0] = 0;
|
|
|
|
-
|
|
|
|
- char buffer[256];
|
|
|
|
- char deviceBuffer[32];
|
|
|
|
- char keyBuffer[64];
|
|
|
|
-
|
|
|
|
- U32 devMapIndex = 0, nodeIndex = 0;
|
|
|
|
- while ( nextBoundNode( command, devMapIndex, nodeIndex ) )
|
|
|
|
- {
|
|
|
|
- const DeviceMap* deviceMap = mDeviceMaps[devMapIndex];
|
|
|
|
-
|
|
|
|
- if ( getDeviceName( deviceMap->deviceType, deviceMap->deviceInst, deviceBuffer ) )
|
|
|
|
- {
|
|
|
|
- const Node* node = &deviceMap->nodeMap[nodeIndex];
|
|
|
|
- const char* modifierString = getModifierString( node->modifiers );
|
|
|
|
-
|
|
|
|
- if ( getKeyString( node->action, keyBuffer ) )
|
|
|
|
- {
|
|
|
|
- dSprintf( buffer, sizeof( buffer ), "%s\t%s%s", deviceBuffer, modifierString, keyBuffer );
|
|
|
|
- if ( returnString[0] )
|
|
|
|
- dStrcat( returnString, "\t" );
|
|
|
|
- dStrcat( returnString, buffer );
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- ++nodeIndex;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return returnString;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-// 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 if (dStrnicmp(pDeviceName, "accelerometer", dStrlen("accelerometer")) == 0)
|
|
|
|
- {
|
|
|
|
- deviceType = AccelerometerDeviceType;
|
|
|
|
- offset = dStrlen("accelerometer");
|
|
|
|
- }
|
|
|
|
- else if (dStrnicmp(pDeviceName, "gyroscope", dStrlen("gyroscope")) == 0)
|
|
|
|
- {
|
|
|
|
- deviceType = GyroscopeDeviceType;
|
|
|
|
- offset = dStrlen("gyroscope");
|
|
|
|
- }
|
|
|
|
- else if (dStrnicmp(pDeviceName, "touchdevice", dStrlen("touchdevice")) == 0)
|
|
|
|
- {
|
|
|
|
- deviceType = ScreenTouchDeviceType;
|
|
|
|
- offset = dStrlen("touchdevice");
|
|
|
|
- }
|
|
|
|
- else if (dStrnicmp(pDeviceName, "gamepad", dStrlen("gamepad")) == 0)
|
|
|
|
- {
|
|
|
|
- deviceType = GamepadDeviceType;
|
|
|
|
- offset = dStrlen("gamepad");
|
|
|
|
- }
|
|
|
|
- else if (dStrnicmp(pDeviceName, "leapdevice", dStrlen("leapdevice")) == 0)
|
|
|
|
- {
|
|
|
|
- deviceType = LeapMotionDeviceType;
|
|
|
|
- offset = dStrlen("leapdevice");
|
|
|
|
- }
|
|
|
|
- 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;
|
|
|
|
-
|
|
|
|
- case AccelerometerDeviceType:
|
|
|
|
- dStrcpy(buffer, "accelerometer");
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case GyroscopeDeviceType:
|
|
|
|
- dStrcpy(buffer, "gyroscope");
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case ScreenTouchDeviceType:
|
|
|
|
- dStrcpy(buffer, "touchdevice");
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case GamepadDeviceType:
|
|
|
|
- dSprintf(buffer, 16, "gamepad%d", deviceInstance);
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case LeapMotionDeviceType:
|
|
|
|
- dStrcpy(buffer, "leapdevice");
|
|
|
|
- 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_OSX)
|
|
|
|
- // optional code, to output alt as cmd on mac.
|
|
|
|
- // interpreter sees them as the same...
|
|
|
|
- case (SI_SHIFT|SI_CTRL|SI_ALT):
|
|
|
|
- return "cmd-shift-ctrl ";
|
|
|
|
-
|
|
|
|
- case (SI_SHIFT|SI_ALT):
|
|
|
|
- return "cmd-shift ";
|
|
|
|
-
|
|
|
|
- case (SI_CTRL|SI_ALT):
|
|
|
|
- return "cmd-ctrl ";
|
|
|
|
-
|
|
|
|
- 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_ALT|SI_SHIFT|SI_CTRL|SI_MAC_OPT):
|
|
|
|
- return "cmd-shift-ctrl-opt ";
|
|
|
|
-
|
|
|
|
- case (SI_ALT|SI_SHIFT|SI_MAC_OPT):
|
|
|
|
- return "cmd-shift-opt ";
|
|
|
|
-
|
|
|
|
- case (SI_ALT|SI_CTRL|SI_MAC_OPT):
|
|
|
|
- return "cmd-ctrl-opt ";
|
|
|
|
-
|
|
|
|
- case (SI_ALT|SI_MAC_OPT):
|
|
|
|
- return "cmd-opt ";
|
|
|
|
-
|
|
|
|
- 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);
|
|
|
|
-
|
|
|
|
-// if (action >= KEY_A && action <= KEY_Z) {
|
|
|
|
-// buffer[0] = char(action - KEY_A + 'a');
|
|
|
|
-// buffer[1] = '\0';
|
|
|
|
-// return true;
|
|
|
|
-// } else if (action >= KEY_0 && action <= KEY_9) {
|
|
|
|
-// buffer[0] = char(action - KEY_0 + '0');
|
|
|
|
-// buffer[1] = '\0';
|
|
|
|
- if ( (asciiCode != 0) && dIsDecentChar((char)asciiCode))
|
|
|
|
- {
|
|
|
|
- for (U32 i = 0; gAsciiMap[i].asciiCode != 0xFFFF; i++) {
|
|
|
|
- if (gAsciiMap[i].asciiCode == asciiCode)
|
|
|
|
- {
|
|
|
|
- dStrcpy(buffer, gAsciiMap[i].pDescription);
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- // Must not have found a string for that ascii code just record the char
|
|
|
|
- buffer[0] = char(asciiCode);
|
|
|
|
- buffer[1] = '\0';
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- if (action >= KEY_A && action <= KEY_Z)
|
|
|
|
- {
|
|
|
|
- buffer[0] = char(action - KEY_A + 'a');
|
|
|
|
- buffer[1] = '\0';
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- else if (action >= KEY_0 && action <= KEY_9) {
|
|
|
|
- buffer[0] = char(action - KEY_0 + '0');
|
|
|
|
- buffer[1] = '\0';
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- for (U32 i = 0; gVirtualMap[i].code != 0xFFFFFFFF; i++) {
|
|
|
|
- if (gVirtualMap[i].code == action) {
|
|
|
|
- dStrcpy(buffer, gVirtualMap[i].pDescription);
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- Con::errorf( "ActionMap::getKeyString: no string for action %d", action );
|
|
|
|
- return false;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//--------------------------------------------------------------------------
|
|
|
|
-bool ActionMap::processBindCmd(const char *device, const char *action, const char *makeCmd, const char *breakCmd)
|
|
|
|
-{
|
|
|
|
- U32 deviceType;
|
|
|
|
- U32 deviceInst;
|
|
|
|
-
|
|
|
|
- if(!getDeviceTypeAndInstance(device, deviceType, deviceInst))
|
|
|
|
- {
|
|
|
|
- Con::printf("processBindCmd: unknown device: %s", device);
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Ok, we now have the deviceType and instance. Create an event descriptor
|
|
|
|
- // for the bind...
|
|
|
|
- //
|
|
|
|
- EventDescriptor eventDescriptor;
|
|
|
|
- if (createEventDescriptor(action, &eventDescriptor) == false) {
|
|
|
|
- Con::printf("Could not create a description for binding: %s", action);
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // SI_POV == SI_MOVE, and the POV works fine with bindCmd, so we have to add these manually.
|
|
|
|
- if( ( eventDescriptor.eventCode == SI_XAXIS ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_YAXIS ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_ZAXIS ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_RXAXIS ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_RYAXIS ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_RZAXIS ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_SLIDER ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_XPOV ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_YPOV ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_XPOV2 ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_YPOV2 ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_ACCELX ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_ACCELY ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_ACCELZ ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_GRAVX ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_GRAVY ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_GRAVZ ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_GYROX ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_GYROY ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_GYROZ ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_YAW ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_PITCH ) ||
|
|
|
|
- ( eventDescriptor.eventCode == SI_ROLL ) )
|
|
|
|
- {
|
|
|
|
- Con::warnf( "ActionMap::processBindCmd - Cannot use 'bindCmd' with a move event type. Use 'bind' instead." );
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Create the full bind entry, and place it in the map
|
|
|
|
- //
|
|
|
|
- // DMMTODO
|
|
|
|
- Node* pBindNode = getNode(deviceType, deviceInst,
|
|
|
|
- eventDescriptor.flags,
|
|
|
|
- eventDescriptor.eventCode);
|
|
|
|
-
|
|
|
|
- pBindNode->flags = Node::BindCmd;
|
|
|
|
- pBindNode->deadZoneBegin = 0;
|
|
|
|
- pBindNode->deadZoneEnd = 0;
|
|
|
|
- pBindNode->scaleFactor = 1;
|
|
|
|
- if(makeCmd[0])
|
|
|
|
- pBindNode->makeConsoleCommand = dStrdup(makeCmd);
|
|
|
|
- else
|
|
|
|
- pBindNode->makeConsoleCommand = dStrdup("");
|
|
|
|
-
|
|
|
|
- if(breakCmd[0])
|
|
|
|
- pBindNode->breakConsoleCommand = dStrdup(breakCmd);
|
|
|
|
- else
|
|
|
|
- pBindNode->breakConsoleCommand = dStrdup("");
|
|
|
|
- return true;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-bool ActionMap::processBind(const U32 argc, const char** argv, SimObject* object)
|
|
|
|
-{
|
|
|
|
- // Ok, the bind will come in the following format:
|
|
|
|
- // [device] [key or button] <[param spec] [param] ...> [fnName]
|
|
|
|
- //
|
|
|
|
- const char* pDeviceName = argv[0];
|
|
|
|
- const char* pEvent = argv[1];
|
|
|
|
- const char* pFnName = argv[argc - 1];
|
|
|
|
-
|
|
|
|
- // Determine the device
|
|
|
|
- U32 deviceType;
|
|
|
|
- U32 deviceInst;
|
|
|
|
-
|
|
|
|
- if(!getDeviceTypeAndInstance(argv[0], deviceType, deviceInst))
|
|
|
|
- {
|
|
|
|
- Con::printf("processBind: unknown device: %s", pDeviceName);
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Ok, we now have the deviceType and instance. Create an event descriptor
|
|
|
|
- // for the bind...
|
|
|
|
- //
|
|
|
|
- EventDescriptor eventDescriptor;
|
|
|
|
- if (createEventDescriptor(pEvent, &eventDescriptor) == false) {
|
|
|
|
- Con::printf("Could not create a description for binding: %s", pEvent);
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Event has now been described, and device determined. we need now to extract
|
|
|
|
- // any modifiers that the action map will apply to incoming events before
|
|
|
|
- // calling the bound function...
|
|
|
|
- //
|
|
|
|
- // DMMTODO
|
|
|
|
- U32 assignedFlags = 0;
|
|
|
|
- F32 deadZoneBegin = 0.0f;
|
|
|
|
- F32 deadZoneEnd = 0.0f;
|
|
|
|
- F32 scaleFactor = 1.0f;
|
|
|
|
-
|
|
|
|
- if (argc != 3) {
|
|
|
|
- // We have the following: "[DSIR]" [deadZone] [scale]
|
|
|
|
- //
|
|
|
|
- const char* pSpec = argv[2];
|
|
|
|
-
|
|
|
|
- for (U32 i = 0; pSpec[i] != '\0'; i++) {
|
|
|
|
- switch (pSpec[i]) {
|
|
|
|
- case 'r': case 'R':
|
|
|
|
- assignedFlags |= Node::HasScale;
|
|
|
|
- break;
|
|
|
|
- case 's': case 'S':
|
|
|
|
- assignedFlags |= Node::HasScale;
|
|
|
|
- break;
|
|
|
|
- case 'd': case 'D':
|
|
|
|
- assignedFlags |= Node::HasDeadZone;
|
|
|
|
- break;
|
|
|
|
- case 'i': case 'I':
|
|
|
|
- assignedFlags |= Node::Inverted;
|
|
|
|
- break;
|
|
|
|
- case 'n': case 'N':
|
|
|
|
- assignedFlags |= Node::NonLinear;
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- default:
|
|
|
|
- AssertFatal(false, avar("Misunderstood specifier in bind (spec string: %s)",
|
|
|
|
- pSpec));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Ok, we have the flags. Scan the dead zone and scale, if any.
|
|
|
|
- //
|
|
|
|
- U32 curArg = 3;
|
|
|
|
- if (assignedFlags & Node::HasDeadZone) {
|
|
|
|
- dSscanf(argv[curArg], "%g %g", &deadZoneBegin, &deadZoneEnd);
|
|
|
|
- curArg++;
|
|
|
|
- }
|
|
|
|
- if (assignedFlags & Node::HasScale) {
|
|
|
|
- scaleFactor = dAtof(argv[curArg]);
|
|
|
|
- curArg++;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (curArg != (argc - 1)) {
|
|
|
|
- AssertFatal(curArg == (argc - 1), "error in bind spec somewhere...");
|
|
|
|
- Con::printf("Improperly specified bind for key: %s", argv[2]);
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Ensure that the console function is properly specified?
|
|
|
|
- //
|
|
|
|
- // DMMTODO
|
|
|
|
-
|
|
|
|
- // Create the full bind entry, and place it in the map
|
|
|
|
- //
|
|
|
|
- // DMMTODO
|
|
|
|
- Node* pBindNode = getNode(deviceType, deviceInst,
|
|
|
|
- eventDescriptor.flags,
|
|
|
|
- eventDescriptor.eventCode, object);
|
|
|
|
-
|
|
|
|
- pBindNode->flags = assignedFlags;
|
|
|
|
- pBindNode->deadZoneBegin = deadZoneBegin;
|
|
|
|
- pBindNode->deadZoneEnd = deadZoneEnd;
|
|
|
|
- pBindNode->scaleFactor = scaleFactor;
|
|
|
|
- pBindNode->object = object;
|
|
|
|
- pBindNode->consoleFunction = StringTable->insert(pFnName);
|
|
|
|
-
|
|
|
|
- return true;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-
|
|
|
|
-bool ActionMap::processLeap(const InputEvent* pEvent)
|
|
|
|
-{
|
|
|
|
- static const char *argv[5];
|
|
|
|
- char buffer[64];
|
|
|
|
-
|
|
|
|
- const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType );
|
|
|
|
-
|
|
|
|
- if (pNode == NULL)
|
|
|
|
- {
|
|
|
|
- // Check to see if we clear the modifiers, do we find an action?
|
|
|
|
- if (pEvent->modifier != 0)
|
|
|
|
- pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
|
|
|
|
-
|
|
|
|
- if (pNode == NULL)
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // "Do nothing" bind:
|
|
|
|
- if ( !pNode->consoleFunction[0] )
|
|
|
|
- return( true );
|
|
|
|
-
|
|
|
|
- argv[0] = pNode->consoleFunction;
|
|
|
|
-
|
|
|
|
- float values[3];
|
|
|
|
- values[0] = pEvent->fValues[0];
|
|
|
|
- values[1] = pEvent->fValues[1];
|
|
|
|
- values[2] = pEvent->fValues[2];
|
|
|
|
-
|
|
|
|
- if ( pNode->flags & Node::HasDeadZone )
|
|
|
|
- {
|
|
|
|
- if ( pEvent->fValues[0] >= pNode->deadZoneBegin && pEvent->fValues[0] <= pNode->deadZoneEnd )
|
|
|
|
- values[0] = 0.0f;
|
|
|
|
- if ( pEvent->fValues[1] >= pNode->deadZoneBegin && pEvent->fValues[1] <= pNode->deadZoneEnd )
|
|
|
|
- values[1] = 0.0f;
|
|
|
|
- if ( pEvent->fValues[2] >= pNode->deadZoneBegin && pEvent->fValues[2] <= pNode->deadZoneEnd )
|
|
|
|
- values[2] = 0.0f;
|
|
|
|
-
|
|
|
|
- // All values are all null, so don't bother executing the function
|
|
|
|
- if (!values[0] && !values[1] && !values[2])
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- switch(pEvent->objType)
|
|
|
|
- {
|
|
|
|
- case LM_HANDPOS:
|
|
|
|
-
|
|
|
|
- // ID
|
|
|
|
- argv[1] = Con::getIntArg(pEvent->iValue);
|
|
|
|
-
|
|
|
|
- // Position
|
|
|
|
- dSprintf(buffer, sizeof(buffer), "%f %f %f", values[0], values[1], values[2]);
|
|
|
|
-
|
|
|
|
- argv[2] = buffer;
|
|
|
|
-
|
|
|
|
- if (pNode->object)
|
|
|
|
- Con::executef(pNode->object, 3, argv[0], argv[1], argv[2]);
|
|
|
|
- else
|
|
|
|
- Con::execute(3, argv);
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case LM_HANDROT:
|
|
|
|
-
|
|
|
|
- // ID
|
|
|
|
- argv[1] = Con::getIntArg(pEvent->iValue);
|
|
|
|
-
|
|
|
|
- // Rotation
|
|
|
|
- dSprintf(buffer, sizeof(buffer), "%f %f %f", values[0], values[1], values[2]);
|
|
|
|
-
|
|
|
|
- argv[2] = buffer;
|
|
|
|
-
|
|
|
|
- if (pNode->object)
|
|
|
|
- Con::executef(pNode->object, 3, argv[0], argv[1], argv[2]);
|
|
|
|
- else
|
|
|
|
- Con::execute(3, argv);
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case LM_FINGERPOS:
|
|
|
|
-
|
|
|
|
- // IDs
|
|
|
|
- argv[1] = pEvent->fingerIDs;
|
|
|
|
-
|
|
|
|
- // X-coordinates
|
|
|
|
- argv[2] = pEvent->fingersX;
|
|
|
|
-
|
|
|
|
- // Y-coordinates
|
|
|
|
- argv[3] = pEvent->fingersY;
|
|
|
|
-
|
|
|
|
- // Z-coordinates
|
|
|
|
- argv[4] = pEvent->fingersZ;
|
|
|
|
-
|
|
|
|
- if (pNode->object)
|
|
|
|
- Con::executef(pNode->object, 5, argv[0], argv[1], argv[2], argv[3], argv[4]);
|
|
|
|
- else
|
|
|
|
- Con::execute(5, argv);
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case LM_HANDAXIS:
|
|
|
|
- default:
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return true;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-
|
|
|
|
-bool ActionMap::processGesture(const InputEvent* pEvent)
|
|
|
|
-{
|
|
|
|
- static const char *argv[6];
|
|
|
|
- char buffer[64];
|
|
|
|
-
|
|
|
|
- const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType );
|
|
|
|
-
|
|
|
|
- if (pNode == NULL)
|
|
|
|
- {
|
|
|
|
- // Check to see if we clear the modifiers, do we find an action?
|
|
|
|
- if (pEvent->modifier != 0)
|
|
|
|
- pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
|
|
|
|
-
|
|
|
|
- if (pNode == NULL)
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // "Do nothing" bind:
|
|
|
|
- if ( !pNode->consoleFunction[0] )
|
|
|
|
- return( true );
|
|
|
|
-
|
|
|
|
- // Function
|
|
|
|
- argv[0] = pNode->consoleFunction;
|
|
|
|
-
|
|
|
|
- switch(pEvent->objType)
|
|
|
|
- {
|
|
|
|
- case SI_CIRCLE_GESTURE:
|
|
|
|
-
|
|
|
|
- // ID
|
|
|
|
- argv[1] = Con::getIntArg(pEvent->iValue);
|
|
|
|
-
|
|
|
|
- // Progress
|
|
|
|
- argv[2] = Con::getFloatArg(pEvent->fValues[0]);
|
|
|
|
-
|
|
|
|
- // Radius
|
|
|
|
- argv[3] = Con::getFloatArg(pEvent->fValues[1]);
|
|
|
|
-
|
|
|
|
- // Direction (1 clockwise, 0 counter-clockwise)
|
|
|
|
- argv[4] = Con::getFloatArg(pEvent->fValues[2]);
|
|
|
|
-
|
|
|
|
- // State
|
|
|
|
- argv[5] = Con::getFloatArg(pEvent->fValues[3]);
|
|
|
|
-
|
|
|
|
- if (pNode->object)
|
|
|
|
- Con::executef(pNode->object, 6, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
|
|
|
|
- else
|
|
|
|
- Con::execute(6, argv);
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case SI_SWIPE_GESTURE:
|
|
|
|
-
|
|
|
|
- // ID
|
|
|
|
- argv[1] = Con::getIntArg(pEvent->iValue);
|
|
|
|
-
|
|
|
|
- // State
|
|
|
|
- argv[2] = Con::getFloatArg(pEvent->fValues[0]);
|
|
|
|
-
|
|
|
|
- // Direction
|
|
|
|
- dSprintf(buffer, sizeof(buffer), "%f %f %f", pEvent->fValues[1], pEvent->fValues[2], pEvent->fValues[3]);
|
|
|
|
-
|
|
|
|
- argv[3] = buffer;
|
|
|
|
- // Speed
|
|
|
|
- argv[4] = Con::getFloatArg(pEvent->fValues[4]);
|
|
|
|
-
|
|
|
|
- if (pNode->object)
|
|
|
|
- Con::executef(pNode->object, 5, argv[0], argv[1], argv[2], argv[3], argv[4]);
|
|
|
|
- else
|
|
|
|
- Con::execute(5, argv);
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case SI_KEYTAP_GESTURE:
|
|
|
|
- case SI_SCREENTAP_GESTURE:
|
|
|
|
-
|
|
|
|
- // ID
|
|
|
|
- argv[1] = Con::getIntArg(pEvent->iValue);
|
|
|
|
-
|
|
|
|
- // Position
|
|
|
|
- dSprintf(buffer, sizeof(buffer), "%f %f %f", pEvent->fValues[0], pEvent->fValues[1], pEvent->fValues[2]);
|
|
|
|
-
|
|
|
|
- argv[2] = buffer;
|
|
|
|
-
|
|
|
|
- // Direction
|
|
|
|
- dSprintf(buffer, sizeof(buffer), "%f %f %f", pEvent->fValues[3], pEvent->fValues[4], pEvent->fValues[5]);
|
|
|
|
-
|
|
|
|
- argv[3] = buffer;
|
|
|
|
-
|
|
|
|
- if (pNode->object)
|
|
|
|
- Con::executef(pNode->object, 4, argv[0], argv[1], argv[2], argv[3]);
|
|
|
|
- else
|
|
|
|
- Con::execute(5, argv);
|
|
|
|
-
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case SI_PINCH_GESTURE:
|
|
|
|
- case SI_SCALE_GESTURE:
|
|
|
|
- default:
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return true;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-
|
|
|
|
-bool ActionMap::processTouch(const InputEvent* pEvent)
|
|
|
|
-{
|
|
|
|
- static const char *argv[4];
|
|
|
|
- const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst);
|
|
|
|
-
|
|
|
|
- if (pNode == NULL)
|
|
|
|
- {
|
|
|
|
- // Check to see if we clear the modifiers, do we find an action?
|
|
|
|
- if (pEvent->modifier != 0)
|
|
|
|
- pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
|
|
|
|
-
|
|
|
|
- if (pNode == NULL)
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // "Do nothing" bind:
|
|
|
|
- if ( !pNode->consoleFunction[0] )
|
|
|
|
- return( true );
|
|
|
|
-
|
|
|
|
- // Ok, we're all set up, call the function.
|
|
|
|
- argv[0] = pNode->consoleFunction;
|
|
|
|
- argv[1] = pEvent->fingerIDs;
|
|
|
|
- argv[2] = pEvent->fingersX;
|
|
|
|
- argv[3] = pEvent->fingersY;
|
|
|
|
-
|
|
|
|
- if (pNode->object)
|
|
|
|
- Con::executef(pNode->object, 4, argv[0], argv[1], argv[2], argv[3]);
|
|
|
|
- else
|
|
|
|
- Con::execute(4, argv);
|
|
|
|
-
|
|
|
|
- return true;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-
|
|
|
|
-bool ActionMap::processButton(const InputEvent* pEvent)
|
|
|
|
-{
|
|
|
|
- static const char *argv[2];
|
|
|
|
- const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst);
|
|
|
|
-
|
|
|
|
- if (pNode == NULL)
|
|
|
|
- {
|
|
|
|
- // Check to see if we clear the modifiers, do we find an action?
|
|
|
|
- if (pEvent->modifier != 0)
|
|
|
|
- pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
|
|
|
|
-
|
|
|
|
- if (pNode == NULL)
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Whadda ya know, we have this bound. Set up, and call the console
|
|
|
|
- // function associated with it...
|
|
|
|
- //
|
|
|
|
- F32 value = pEvent->fValues[0];
|
|
|
|
-
|
|
|
|
- if (pNode->flags & Node::Ranged)
|
|
|
|
- {
|
|
|
|
- value = (value * 2.0f) - 1.0f;
|
|
|
|
-
|
|
|
|
- if (pNode->flags & Node::Inverted)
|
|
|
|
- value *= -1.0f;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- if (pNode->flags & Node::Inverted)
|
|
|
|
- value = 1.0f - value;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (pNode->flags & Node::HasScale)
|
|
|
|
- value *= pNode->scaleFactor;
|
|
|
|
-
|
|
|
|
- if (pNode->flags & Node::HasDeadZone)
|
|
|
|
- {
|
|
|
|
- if (value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd)
|
|
|
|
- value = 0.0f;
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- if( value > 0 )
|
|
|
|
- value = ( value - pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
|
|
|
|
- else
|
|
|
|
- value = ( value + pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if( pNode->flags & Node::NonLinear )
|
|
|
|
- value = ( value < 0.f ? -1.f : 1.f ) * mPow( mFabs( value ), CONST_E );
|
|
|
|
-
|
|
|
|
- // Ok, we're all set up, call the function.
|
|
|
|
- if(pNode->flags & Node::BindCmd)
|
|
|
|
- {
|
|
|
|
- // it's a bind command
|
|
|
|
- if(pNode->makeConsoleCommand)
|
|
|
|
- Con::evaluate(pNode->makeConsoleCommand);
|
|
|
|
- }
|
|
|
|
- else if ( pNode->consoleFunction[0] )
|
|
|
|
- {
|
|
|
|
- argv[0] = pNode->consoleFunction;
|
|
|
|
- argv[1] = Con::getFloatArg(value);
|
|
|
|
-
|
|
|
|
- if (pNode->object)
|
|
|
|
- Con::executef(pNode->object, 2, argv[0], argv[1]);
|
|
|
|
- else
|
|
|
|
- Con::execute(2, argv);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // [neo, 5/13/2007 - #3109]
|
|
|
|
- // The execs/evaluate above could have called reentrant script code which made calls to
|
|
|
|
- // bindCmd() etc, channging the node map underneath us. If enough nodes were added then
|
|
|
|
- // the node map vector would realloc, with the result that pNode would then be pointing
|
|
|
|
- // at garbage and cause a crash when passed to enterBreakEvent() below. So we just look
|
|
|
|
- // it up again to be safe. This is not needed in the other cases below as we return right
|
|
|
|
- // after the execs and don't use pNode again.
|
|
|
|
- pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst );
|
|
|
|
-
|
|
|
|
- if( pNode == NULL )
|
|
|
|
- return true; // We already called any bound methods/functions so our job is done
|
|
|
|
-
|
|
|
|
- //
|
|
|
|
- // And enter the break into the table if this is a make event...
|
|
|
|
- enterBreakEvent(pEvent, pNode);
|
|
|
|
-
|
|
|
|
- return true;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-
|
|
|
|
-bool ActionMap::processMove(const InputEvent* pEvent)
|
|
|
|
-{
|
|
|
|
- static const char *argv[2];
|
|
|
|
-
|
|
|
|
- if (pEvent->deviceType == MouseDeviceType)
|
|
|
|
- {
|
|
|
|
- const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType);
|
|
|
|
-
|
|
|
|
- if (pNode == NULL)
|
|
|
|
- {
|
|
|
|
- // Check to see if we clear the modifiers, do we find an action?
|
|
|
|
- if (pEvent->modifier != 0)
|
|
|
|
- pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objType);
|
|
|
|
-
|
|
|
|
- if (pNode == NULL)
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // "Do nothing" bind:
|
|
|
|
- if ( !pNode->consoleFunction[0] )
|
|
|
|
- return( true );
|
|
|
|
-
|
|
|
|
- // Whadda ya know, we have this bound. Set up, and call the console
|
|
|
|
- // function associated with it. Mouse events ignore range and dead
|
|
|
|
- // zone params.
|
|
|
|
- //
|
|
|
|
- F32 value = pEvent->fValues[0];
|
|
|
|
-
|
|
|
|
- if (pNode->flags & Node::Inverted)
|
|
|
|
- value *= -1.0f;
|
|
|
|
- if (pNode->flags & Node::HasScale)
|
|
|
|
- value *= pNode->scaleFactor;
|
|
|
|
-
|
|
|
|
- // Ok, we're all set up, call the function.
|
|
|
|
- argv[0] = pNode->consoleFunction;
|
|
|
|
- argv[1] = Con::getFloatArg(value);
|
|
|
|
-
|
|
|
|
- if (pNode->object)
|
|
|
|
- Con::executef(pNode->object, 2, argv[0], argv[1]);
|
|
|
|
- else
|
|
|
|
- Con::execute(2, argv);
|
|
|
|
-
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- else if ( (pEvent->objType == XI_POS || pEvent->objType == XI_FLOAT || pEvent->objType == XI_ROT || pEvent->objType == XI_INT) )
|
|
|
|
- {
|
|
|
|
- const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst);
|
|
|
|
-
|
|
|
|
- if( pNode == NULL )
|
|
|
|
- return false;
|
|
|
|
-
|
|
|
|
- // Ok, we're all set up, call the function.
|
|
|
|
- argv[0] = pNode->consoleFunction;
|
|
|
|
- S32 argc = 1;
|
|
|
|
-
|
|
|
|
- if (pEvent->objType == XI_INT)
|
|
|
|
- {
|
|
|
|
- // Handle the integer as some sort of motion such as a
|
|
|
|
- // single component to an absolute position
|
|
|
|
- argv[1] = Con::getIntArg( pEvent->iValue );
|
|
|
|
- argc += 1;
|
|
|
|
- }
|
|
|
|
- else if (pEvent->objType == XI_FLOAT)
|
|
|
|
- {
|
|
|
|
- // Handle float as some sort of motion such as a
|
|
|
|
- // single component to an absolute position
|
|
|
|
- argv[1] = Con::getFloatArg( pEvent->fValues[0] );
|
|
|
|
- argc += 1;
|
|
|
|
- }
|
|
|
|
- else if (pEvent->objType == XI_POS)
|
|
|
|
- {
|
|
|
|
- // Handle Point3F type position
|
|
|
|
- argv[1] = Con::getFloatArg( pEvent->fValues[0] );
|
|
|
|
- argv[2] = Con::getFloatArg( pEvent->fValues[1] );
|
|
|
|
- argv[3] = Con::getFloatArg( pEvent->fValues[2] );
|
|
|
|
-
|
|
|
|
- argc += 3;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (pNode->object)
|
|
|
|
- {
|
|
|
|
- Con::execute(pNode->object, argc, argv);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- Con::execute(argc, argv);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- else if ( pEvent->deviceType == JoystickDeviceType || pEvent->deviceType == GamepadDeviceType )
|
|
|
|
- {
|
|
|
|
- // Joystick events...
|
|
|
|
- const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst );
|
|
|
|
-
|
|
|
|
- if( pNode == NULL )
|
|
|
|
- return false;
|
|
|
|
-
|
|
|
|
- // "Do nothing" bind:
|
|
|
|
- if ( !pNode->consoleFunction[0] )
|
|
|
|
- return( true );
|
|
|
|
-
|
|
|
|
- // Whadda ya know, we have this bound. Set up, and call the console
|
|
|
|
- // function associated with it. Joystick move events are the same as mouse
|
|
|
|
- // move events except that they don't ignore dead zone.
|
|
|
|
- //
|
|
|
|
- F32 value = pEvent->fValues[0];
|
|
|
|
- if ( pNode->flags & Node::Inverted )
|
|
|
|
- value *= -1.0f;
|
|
|
|
-
|
|
|
|
- if ( pNode->flags & Node::HasScale )
|
|
|
|
- value *= pNode->scaleFactor;
|
|
|
|
-
|
|
|
|
- if ( pNode->flags & Node::HasDeadZone )
|
|
|
|
- {
|
|
|
|
- if ( value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd )
|
|
|
|
- {
|
|
|
|
- value = 0.0f;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- if( value > 0 )
|
|
|
|
- value = ( value - pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
|
|
|
|
- else
|
|
|
|
- value = ( value + pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if( pNode->flags & Node::NonLinear )
|
|
|
|
- value = ( value < 0.f ? -1.f : 1.f ) * mPow( mFabs( value ), CONST_E );
|
|
|
|
-
|
|
|
|
- // Ok, we're all set up, call the function.
|
|
|
|
- argv[0] = pNode->consoleFunction;
|
|
|
|
- argv[1] = Con::getFloatArg( value );
|
|
|
|
-
|
|
|
|
- if (pNode->object)
|
|
|
|
- Con::executef(pNode->object, S32(argv[0]), argv[1]);
|
|
|
|
- else
|
|
|
|
- Con::execute(2, argv);
|
|
|
|
-
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return false;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-
|
|
|
|
-bool ActionMap::processMotion(const InputEvent* pEvent)
|
|
|
|
-{
|
|
|
|
- static const char *argv[2];
|
|
|
|
-
|
|
|
|
- // iOS Accelerometer, Gyroscope and DeviceMotion processing
|
|
|
|
- // Currently, this is identical to the joystick handling.
|
|
|
|
-
|
|
|
|
- // This was copied over into its own section because this will
|
|
|
|
- // give us a dedicated section to tweak processing based on iOS specific
|
|
|
|
- // devices. No point in trying to mangle joystick code any further
|
|
|
|
- const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType );
|
|
|
|
-
|
|
|
|
- if ( pNode == NULL )
|
|
|
|
- {
|
|
|
|
- // Check to see if we clear the modifiers, do we find an action?
|
|
|
|
- if (pEvent->modifier != 0)
|
|
|
|
- pNode = findNode( pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objType );
|
|
|
|
-
|
|
|
|
- if ( pNode == NULL )
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // "Do nothing" bind:
|
|
|
|
- if ( !pNode->consoleFunction[0] )
|
|
|
|
- return( true );
|
|
|
|
-
|
|
|
|
- F32 value = pEvent->fValues[0];
|
|
|
|
-
|
|
|
|
- if ( pNode->flags & Node::Inverted )
|
|
|
|
- value *= -1.0f;
|
|
|
|
-
|
|
|
|
- if ( pNode->flags & Node::HasScale )
|
|
|
|
- value *= pNode->scaleFactor;
|
|
|
|
-
|
|
|
|
- if ( pNode->flags & Node::HasDeadZone )
|
|
|
|
- {
|
|
|
|
- if ( value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd )
|
|
|
|
- value = 0.0f;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Ok, we're all set up, call the function.
|
|
|
|
- argv[0] = pNode->consoleFunction;
|
|
|
|
- argv[1] = Con::getFloatArg( value );
|
|
|
|
-
|
|
|
|
- if (pNode->object)
|
|
|
|
- Con::executef(pNode->object, 2, argv[0], argv[1]);
|
|
|
|
- else
|
|
|
|
- Con::execute(2, argv);
|
|
|
|
-
|
|
|
|
- return true;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-
|
|
|
|
-bool ActionMap::processXInput(const InputEvent* pEvent)
|
|
|
|
-{
|
|
|
|
- static const char *argv[2];
|
|
|
|
-
|
|
|
|
- if ((pEvent->objType == XI_FLOAT || pEvent->objType == XI_INT))
|
|
|
|
- {
|
|
|
|
- const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType );
|
|
|
|
-
|
|
|
|
- if (pNode == NULL )
|
|
|
|
- return false;
|
|
|
|
-
|
|
|
|
- // Ok, we're all set up, call the function.
|
|
|
|
- argv[0] = pNode->consoleFunction;
|
|
|
|
- S32 argc = 1;
|
|
|
|
-
|
|
|
|
- if (pEvent->objType == XI_INT)
|
|
|
|
- {
|
|
|
|
- // Handle the integer as some sort of motion such as a
|
|
|
|
- // single component to an absolute position
|
|
|
|
- argv[1] = Con::getIntArg( pEvent->iValue );
|
|
|
|
- argc += 1;
|
|
|
|
- }
|
|
|
|
- else if (pEvent->objType == XI_FLOAT)
|
|
|
|
- {
|
|
|
|
- // Handle float as some sort of motion such as a
|
|
|
|
- // single component to an absolute position
|
|
|
|
- argv[1] = Con::getFloatArg( pEvent->fValues[0] );
|
|
|
|
- argc += 1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (pNode->object)
|
|
|
|
- {
|
|
|
|
- Con::execute(pNode->object, argc, argv);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- Con::execute(argc, argv);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return true;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-
|
|
|
|
-bool ActionMap::processAction(const InputEvent* pEvent)
|
|
|
|
-{
|
|
|
|
- switch(pEvent->action)
|
|
|
|
- {
|
|
|
|
- case SI_LEAP:
|
|
|
|
- return processLeap(pEvent);
|
|
|
|
- break;
|
|
|
|
- case SI_GESTURE:
|
|
|
|
- return processGesture(pEvent);
|
|
|
|
- break;
|
|
|
|
- case SI_TOUCH:
|
|
|
|
- return processTouch(pEvent);
|
|
|
|
- break;
|
|
|
|
- case SI_MAKE:
|
|
|
|
- return processButton(pEvent);
|
|
|
|
- break;
|
|
|
|
- case SI_MOVE:
|
|
|
|
- return processMove(pEvent);
|
|
|
|
- break;
|
|
|
|
- case SI_MOTION:
|
|
|
|
- return processMotion(pEvent);
|
|
|
|
- break;
|
|
|
|
- case SI_BREAK:
|
|
|
|
- return checkBreakTable(pEvent);
|
|
|
|
- break;
|
|
|
|
- case SI_VALUE:
|
|
|
|
- return processXInput(pEvent);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return false;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-void ActionMap::enterBreakEvent(const InputEvent* pEvent, const Node* pNode)
|
|
|
|
-{
|
|
|
|
- // There aren't likely to be many breaks outstanding at any one given time,
|
|
|
|
- // so a simple linear search is probably sufficient. Note that the break table
|
|
|
|
- // is static to the class, all breaks are directed to the action map that received
|
|
|
|
- // the make.
|
|
|
|
- //
|
|
|
|
- S32 entry = -1;
|
|
|
|
- for (U32 i = 0; i < (U32)smBreakTable.size(); i++) {
|
|
|
|
- if (smBreakTable[i].deviceType == U32(pEvent->deviceType) &&
|
|
|
|
- smBreakTable[i].deviceInst == U32(pEvent->deviceInst) &&
|
|
|
|
- smBreakTable[i].objInst == U32(pEvent->objInst)) {
|
|
|
|
- // Match.
|
|
|
|
- entry = i;
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (entry == -1) {
|
|
|
|
- smBreakTable.increment();
|
|
|
|
- entry = smBreakTable.size() - 1;
|
|
|
|
-
|
|
|
|
- smBreakTable[entry].deviceType = pEvent->deviceType;
|
|
|
|
- smBreakTable[entry].deviceInst = pEvent->deviceInst;
|
|
|
|
- smBreakTable[entry].objInst = pEvent->objInst;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Ok, we now have the entry, and know that the device desc. and the objInst match.
|
|
|
|
- // Copy out the node information...
|
|
|
|
- //
|
|
|
|
- smBreakTable[entry].object = pNode->object;
|
|
|
|
- // [neo, 5/7/2007 - #2975]
|
|
|
|
- // object above can be deleted in between a make/break and so object will point
|
|
|
|
- // to turfed memory and crash. To keep things simple we just store id as well so
|
|
|
|
- // we can look it up to validate object ref.
|
|
|
|
- smBreakTable[entry].objectId = pNode->object ? pNode->object->getId() : 0;
|
|
|
|
-
|
|
|
|
- smBreakTable[entry].consoleFunction = pNode->consoleFunction;
|
|
|
|
-
|
|
|
|
- if(pNode->breakConsoleCommand)
|
|
|
|
- smBreakTable[entry].breakConsoleCommand = dStrdup(pNode->breakConsoleCommand);
|
|
|
|
- else
|
|
|
|
- smBreakTable[entry].breakConsoleCommand = NULL;
|
|
|
|
-
|
|
|
|
- smBreakTable[entry].flags = pNode->flags;
|
|
|
|
- smBreakTable[entry].deadZoneBegin = pNode->deadZoneBegin;
|
|
|
|
- smBreakTable[entry].deadZoneEnd = pNode->deadZoneEnd;
|
|
|
|
- smBreakTable[entry].scaleFactor = pNode->scaleFactor;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-bool ActionMap::checkBreakTable(const InputEvent* pEvent)
|
|
|
|
-{
|
|
|
|
- for (U32 i = 0; i < (U32)smBreakTable.size(); i++) {
|
|
|
|
- if (smBreakTable[i].deviceType == U32(pEvent->deviceType) &&
|
|
|
|
- smBreakTable[i].deviceInst == U32(pEvent->deviceInst) &&
|
|
|
|
- smBreakTable[i].objInst == U32(pEvent->objInst)) {
|
|
|
|
- // Match. Issue the break event...
|
|
|
|
- //
|
|
|
|
- F32 value = pEvent->fValues[0];
|
|
|
|
- if (smBreakTable[i].flags & Node::Ranged) {
|
|
|
|
- value = (value * 2.0f) - 1.0f;
|
|
|
|
- if (smBreakTable[i].flags & Node::Inverted)
|
|
|
|
- value *= -1.0f;
|
|
|
|
- } else {
|
|
|
|
- if (smBreakTable[i].flags & Node::Inverted)
|
|
|
|
- value = 1.0f - value;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (smBreakTable[i].flags & Node::HasScale)
|
|
|
|
- value *= smBreakTable[i].scaleFactor;
|
|
|
|
-
|
|
|
|
- if (smBreakTable[i].flags & Node::HasDeadZone)
|
|
|
|
- if (value >= smBreakTable[i].deadZoneBegin &&
|
|
|
|
- value <= smBreakTable[i].deadZoneEnd)
|
|
|
|
- value = 0.0f;
|
|
|
|
-
|
|
|
|
- // Ok, we're all set up, call the function.
|
|
|
|
- if(smBreakTable[i].consoleFunction)
|
|
|
|
- {
|
|
|
|
- if ( smBreakTable[i].consoleFunction[0] )
|
|
|
|
- {
|
|
|
|
- static const char *argv[2];
|
|
|
|
- argv[0] = smBreakTable[i].consoleFunction;
|
|
|
|
- argv[1] = Con::getFloatArg(value);
|
|
|
|
-
|
|
|
|
- if( smBreakTable[i].object )
|
|
|
|
- {
|
|
|
|
- // [neo, 5/7/2007 - #2975]
|
|
|
|
- // object above can be deleted in between a make/break and so object will point
|
|
|
|
- // to turfed memory and crash. To keep things simple we just store id as well so
|
|
|
|
- // we can look it up to validate object ref.
|
|
|
|
- if( smBreakTable[i].objectId > 0 && Sim::findObject( smBreakTable[i].objectId ) )
|
|
|
|
- Con::executef(smBreakTable[i].object, 2, argv[0], argv[1]);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- Con::execute(2, argv);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else if(smBreakTable[i].breakConsoleCommand)
|
|
|
|
- {
|
|
|
|
- Con::evaluate(smBreakTable[i].breakConsoleCommand);
|
|
|
|
- dFree(smBreakTable[i].breakConsoleCommand);
|
|
|
|
- }
|
|
|
|
- smBreakTable.erase(i);
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return false;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-bool ActionMap::handleEvent(const InputEvent* pEvent)
|
|
|
|
-{
|
|
|
|
- // Interate through the ActionMapSet until we get a map that
|
|
|
|
- // handles the event or we run out of maps...
|
|
|
|
- //
|
|
|
|
- SimSet* pActionMapSet = Sim::getActiveActionMapSet();
|
|
|
|
- AssertFatal(pActionMapSet && pActionMapSet->size() != 0,
|
|
|
|
- "error, no ActiveMapSet or no global action map...");
|
|
|
|
-
|
|
|
|
- for (SimSet::iterator itr = pActionMapSet->end() - 1;
|
|
|
|
- itr > pActionMapSet->begin(); itr--) {
|
|
|
|
- ActionMap* pMap = static_cast<ActionMap*>(*itr);
|
|
|
|
- if (pMap->processAction(pEvent) == true)
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return false;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-bool ActionMap::handleEventGlobal(const InputEvent* pEvent)
|
|
|
|
-{
|
|
|
|
- // Interate through the ActionMapSet until we get a map that
|
|
|
|
- // handles the event or we run out of maps...
|
|
|
|
- //
|
|
|
|
- SimSet* pActionMapSet = Sim::getActiveActionMapSet();
|
|
|
|
- AssertFatal(pActionMapSet && pActionMapSet->size() != 0,
|
|
|
|
- "error, no ActiveMapSet or no global action map...");
|
|
|
|
-
|
|
|
|
- return ((ActionMap*)pActionMapSet->first())->processAction(pEvent);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//------------------------------------------------------------------------------
|
|
|
|
-//-------------------------------------- Key code to string mapping
|
|
|
|
-// TODO: Add most obvious aliases...
|
|
|
|
-//
|
|
|
|
-CodeMapping gVirtualMap[] =
|
|
|
|
-{
|
|
|
|
- //-------------------------------------- KEYBOARD EVENTS
|
|
|
|
- //
|
|
|
|
- { "backspace", SI_KEY, KEY_BACKSPACE },
|
|
|
|
- { "tab", SI_KEY, KEY_TAB },
|
|
|
|
-
|
|
|
|
- { "return", SI_KEY, KEY_RETURN },
|
|
|
|
- { "enter", SI_KEY, KEY_RETURN },
|
|
|
|
-
|
|
|
|
- { "shift", SI_KEY, KEY_SHIFT },
|
|
|
|
- { "ctrl", SI_KEY, KEY_CONTROL },
|
|
|
|
- { "alt", SI_KEY, KEY_ALT },
|
|
|
|
- { "pause", SI_KEY, KEY_PAUSE },
|
|
|
|
- { "capslock", SI_KEY, KEY_CAPSLOCK },
|
|
|
|
-
|
|
|
|
- { "escape", SI_KEY, KEY_ESCAPE },
|
|
|
|
-
|
|
|
|
- { "space", SI_KEY, KEY_SPACE },
|
|
|
|
- { "pagedown", SI_KEY, KEY_PAGE_DOWN },
|
|
|
|
- { "pageup", SI_KEY, KEY_PAGE_UP },
|
|
|
|
- { "end", SI_KEY, KEY_END },
|
|
|
|
- { "home", SI_KEY, KEY_HOME },
|
|
|
|
- { "left", SI_KEY, KEY_LEFT },
|
|
|
|
- { "up", SI_KEY, KEY_UP },
|
|
|
|
- { "right", SI_KEY, KEY_RIGHT },
|
|
|
|
- { "down", SI_KEY, KEY_DOWN },
|
|
|
|
- { "print", SI_KEY, KEY_PRINT },
|
|
|
|
- { "insert", SI_KEY, KEY_INSERT },
|
|
|
|
- { "delete", SI_KEY, KEY_DELETE },
|
|
|
|
- { "help", SI_KEY, KEY_HELP },
|
|
|
|
-
|
|
|
|
- { "win_lwindow", SI_KEY, KEY_WIN_LWINDOW },
|
|
|
|
- { "win_rwindow", SI_KEY, KEY_WIN_RWINDOW },
|
|
|
|
- { "win_apps", SI_KEY, KEY_WIN_APPS },
|
|
|
|
-
|
|
|
|
- { "cmd", SI_KEY, KEY_ALT },
|
|
|
|
- { "opt", SI_KEY, KEY_MAC_OPT },
|
|
|
|
- { "lopt", SI_KEY, KEY_MAC_LOPT },
|
|
|
|
- { "ropt", SI_KEY, KEY_MAC_ROPT },
|
|
|
|
-
|
|
|
|
- { "numpad0", SI_KEY, KEY_NUMPAD0 },
|
|
|
|
- { "numpad1", SI_KEY, KEY_NUMPAD1 },
|
|
|
|
- { "numpad2", SI_KEY, KEY_NUMPAD2 },
|
|
|
|
- { "numpad3", SI_KEY, KEY_NUMPAD3 },
|
|
|
|
- { "numpad4", SI_KEY, KEY_NUMPAD4 },
|
|
|
|
- { "numpad5", SI_KEY, KEY_NUMPAD5 },
|
|
|
|
- { "numpad6", SI_KEY, KEY_NUMPAD6 },
|
|
|
|
- { "numpad7", SI_KEY, KEY_NUMPAD7 },
|
|
|
|
- { "numpad8", SI_KEY, KEY_NUMPAD8 },
|
|
|
|
- { "numpad9", SI_KEY, KEY_NUMPAD9 },
|
|
|
|
- { "numpadmult", SI_KEY, KEY_MULTIPLY },
|
|
|
|
- { "numpadadd", SI_KEY, KEY_ADD },
|
|
|
|
- { "numpadsep", SI_KEY, KEY_SEPARATOR },
|
|
|
|
- { "numpadminus", SI_KEY, KEY_SUBTRACT },
|
|
|
|
- { "numpaddecimal", SI_KEY, KEY_DECIMAL },
|
|
|
|
- { "numpaddivide", SI_KEY, KEY_DIVIDE },
|
|
|
|
- { "numpadenter", SI_KEY, KEY_NUMPADENTER },
|
|
|
|
-
|
|
|
|
- { "f1", SI_KEY, KEY_F1 },
|
|
|
|
- { "f2", SI_KEY, KEY_F2 },
|
|
|
|
- { "f3", SI_KEY, KEY_F3 },
|
|
|
|
- { "f4", SI_KEY, KEY_F4 },
|
|
|
|
- { "f5", SI_KEY, KEY_F5 },
|
|
|
|
- { "f6", SI_KEY, KEY_F6 },
|
|
|
|
- { "f7", SI_KEY, KEY_F7 },
|
|
|
|
- { "f8", SI_KEY, KEY_F8 },
|
|
|
|
- { "f9", SI_KEY, KEY_F9 },
|
|
|
|
- { "f10", SI_KEY, KEY_F10 },
|
|
|
|
- { "f11", SI_KEY, KEY_F11 },
|
|
|
|
- { "f12", SI_KEY, KEY_F12 },
|
|
|
|
- { "f13", SI_KEY, KEY_F13 },
|
|
|
|
- { "f14", SI_KEY, KEY_F14 },
|
|
|
|
- { "f15", SI_KEY, KEY_F15 },
|
|
|
|
- { "f16", SI_KEY, KEY_F16 },
|
|
|
|
- { "f17", SI_KEY, KEY_F17 },
|
|
|
|
- { "f18", SI_KEY, KEY_F18 },
|
|
|
|
- { "f19", SI_KEY, KEY_F19 },
|
|
|
|
- { "f20", SI_KEY, KEY_F20 },
|
|
|
|
- { "f21", SI_KEY, KEY_F21 },
|
|
|
|
- { "f22", SI_KEY, KEY_F22 },
|
|
|
|
- { "f23", SI_KEY, KEY_F23 },
|
|
|
|
- { "f24", SI_KEY, KEY_F24 },
|
|
|
|
-
|
|
|
|
- { "numlock", SI_KEY, KEY_NUMLOCK },
|
|
|
|
- { "scrolllock", SI_KEY, KEY_SCROLLLOCK },
|
|
|
|
-
|
|
|
|
- { "lshift", SI_KEY, KEY_LSHIFT },
|
|
|
|
- { "rshift", SI_KEY, KEY_RSHIFT },
|
|
|
|
- { "lcontrol", SI_KEY, KEY_LCONTROL },
|
|
|
|
- { "rcontrol", SI_KEY, KEY_RCONTROL },
|
|
|
|
- { "lalt", SI_KEY, KEY_LALT },
|
|
|
|
- { "ralt", SI_KEY, KEY_RALT },
|
|
|
|
- { "tilde", SI_KEY, KEY_TILDE },
|
|
|
|
-
|
|
|
|
- { "minus", SI_KEY, KEY_MINUS },
|
|
|
|
- { "equals", SI_KEY, KEY_EQUALS },
|
|
|
|
- { "lbracket", SI_KEY, KEY_LBRACKET },
|
|
|
|
- { "rbracket", SI_KEY, KEY_RBRACKET },
|
|
|
|
- { "backslash", SI_KEY, KEY_BACKSLASH },
|
|
|
|
- { "semicolon", SI_KEY, KEY_SEMICOLON },
|
|
|
|
- { "apostrophe", SI_KEY, KEY_APOSTROPHE },
|
|
|
|
- { "comma", SI_KEY, KEY_COMMA },
|
|
|
|
- { "period", SI_KEY, KEY_PERIOD },
|
|
|
|
- { "slash", SI_KEY, KEY_SLASH },
|
|
|
|
- { "lessthan", SI_KEY, KEY_OEM_102 },
|
|
|
|
-
|
|
|
|
- //-------------------------------------- BUTTON EVENTS
|
|
|
|
- // Joystick/Mouse buttons
|
|
|
|
- { "button0", SI_BUTTON, KEY_BUTTON0 },
|
|
|
|
- { "button1", SI_BUTTON, KEY_BUTTON1 },
|
|
|
|
- { "button2", SI_BUTTON, KEY_BUTTON2 },
|
|
|
|
- { "button3", SI_BUTTON, KEY_BUTTON3 },
|
|
|
|
- { "button4", SI_BUTTON, KEY_BUTTON4 },
|
|
|
|
- { "button5", SI_BUTTON, KEY_BUTTON5 },
|
|
|
|
- { "button6", SI_BUTTON, KEY_BUTTON6 },
|
|
|
|
- { "button7", SI_BUTTON, KEY_BUTTON7 },
|
|
|
|
- { "button8", SI_BUTTON, KEY_BUTTON8 },
|
|
|
|
- { "button9", SI_BUTTON, KEY_BUTTON9 },
|
|
|
|
- { "button10", SI_BUTTON, KEY_BUTTON10 },
|
|
|
|
- { "button11", SI_BUTTON, KEY_BUTTON11 },
|
|
|
|
- { "button12", SI_BUTTON, KEY_BUTTON12 },
|
|
|
|
- { "button13", SI_BUTTON, KEY_BUTTON13 },
|
|
|
|
- { "button14", SI_BUTTON, KEY_BUTTON14 },
|
|
|
|
- { "button15", SI_BUTTON, KEY_BUTTON15 },
|
|
|
|
- { "button16", SI_BUTTON, KEY_BUTTON16 },
|
|
|
|
- { "button17", SI_BUTTON, KEY_BUTTON17 },
|
|
|
|
- { "button18", SI_BUTTON, KEY_BUTTON18 },
|
|
|
|
- { "button19", SI_BUTTON, KEY_BUTTON19 },
|
|
|
|
- { "button20", SI_BUTTON, KEY_BUTTON20 },
|
|
|
|
- { "button21", SI_BUTTON, KEY_BUTTON21 },
|
|
|
|
- { "button22", SI_BUTTON, KEY_BUTTON22 },
|
|
|
|
- { "button23", SI_BUTTON, KEY_BUTTON23 },
|
|
|
|
- { "button24", SI_BUTTON, KEY_BUTTON24 },
|
|
|
|
- { "button25", SI_BUTTON, KEY_BUTTON25 },
|
|
|
|
- { "button26", SI_BUTTON, KEY_BUTTON26 },
|
|
|
|
- { "button27", SI_BUTTON, KEY_BUTTON27 },
|
|
|
|
- { "button28", SI_BUTTON, KEY_BUTTON28 },
|
|
|
|
- { "button29", SI_BUTTON, KEY_BUTTON29 },
|
|
|
|
- { "button30", SI_BUTTON, KEY_BUTTON30 },
|
|
|
|
- { "button31", SI_BUTTON, KEY_BUTTON31 },
|
|
|
|
-
|
|
|
|
- //-------------------------------------- MOVE EVENTS
|
|
|
|
- // Mouse/Joystick axes:
|
|
|
|
- { "xaxis", SI_MOVE, SI_XAXIS },
|
|
|
|
- { "yaxis", SI_MOVE, SI_YAXIS },
|
|
|
|
- { "zaxis", SI_MOVE, SI_ZAXIS },
|
|
|
|
- { "rxaxis", SI_MOVE, SI_RXAXIS },
|
|
|
|
- { "ryaxis", SI_MOVE, SI_RYAXIS },
|
|
|
|
- { "rzaxis", SI_MOVE, SI_RZAXIS },
|
|
|
|
- { "slider", SI_MOVE, SI_SLIDER },
|
|
|
|
-
|
|
|
|
- //-------------------------------------- POV EVENTS
|
|
|
|
- // Joystick POV:
|
|
|
|
- { "xpov", SI_POV, SI_XPOV },
|
|
|
|
- { "ypov", SI_POV, SI_YPOV },
|
|
|
|
- { "upov", SI_POV, SI_UPOV },
|
|
|
|
- { "dpov", SI_POV, SI_DPOV },
|
|
|
|
- { "lpov", SI_POV, SI_LPOV },
|
|
|
|
- { "rpov", SI_POV, SI_RPOV },
|
|
|
|
- { "xpov2", SI_POV, SI_XPOV2 },
|
|
|
|
- { "ypov2", SI_POV, SI_YPOV2 },
|
|
|
|
- { "upov2", SI_POV, SI_UPOV2 },
|
|
|
|
- { "dpov2", SI_POV, SI_DPOV2 },
|
|
|
|
- { "lpov2", SI_POV, SI_LPOV2 },
|
|
|
|
- { "rpov2", SI_POV, SI_RPOV2 },
|
|
|
|
-
|
|
|
|
- #if defined( TORQUE_OS_WIN32 ) || defined( TORQUE_OS_XENON )
|
|
|
|
- //-------------------------------------- XINPUT EVENTS
|
|
|
|
- // Controller connect / disconnect:
|
|
|
|
- { "connect", XI_BUTTON, XI_CONNECT },
|
|
|
|
-
|
|
|
|
- // L & R Thumbsticks:
|
|
|
|
- { "thumblx", XI_AXIS, XI_THUMBLX },
|
|
|
|
- { "thumbly", XI_AXIS, XI_THUMBLY },
|
|
|
|
- { "thumbrx", XI_AXIS, XI_THUMBRX },
|
|
|
|
- { "thumbry", XI_AXIS, XI_THUMBRY },
|
|
|
|
-
|
|
|
|
- // L & R Triggers:
|
|
|
|
- { "triggerl", XI_AXIS, XI_LEFT_TRIGGER },
|
|
|
|
- { "triggerr", XI_AXIS, XI_RIGHT_TRIGGER },
|
|
|
|
-
|
|
|
|
- // DPAD Buttons:
|
|
|
|
- { "dpadu", XI_BUTTON, SI_UPOV },
|
|
|
|
- { "dpadd", XI_BUTTON, SI_DPOV },
|
|
|
|
- { "dpadl", XI_BUTTON, SI_LPOV },
|
|
|
|
- { "dpadr", XI_BUTTON, SI_RPOV },
|
|
|
|
-
|
|
|
|
- // START & BACK Buttons:
|
|
|
|
- { "btn_start", XI_BUTTON, XI_START },
|
|
|
|
- { "btn_back", XI_BUTTON, XI_BACK },
|
|
|
|
-
|
|
|
|
- // L & R Thumbstick Buttons:
|
|
|
|
- { "btn_lt", XI_BUTTON, XI_LEFT_THUMB },
|
|
|
|
- { "btn_rt", XI_BUTTON, XI_RIGHT_THUMB },
|
|
|
|
-
|
|
|
|
- // L & R Shoulder Buttons:
|
|
|
|
- { "btn_l", XI_BUTTON, XI_LEFT_SHOULDER },
|
|
|
|
- { "btn_r", XI_BUTTON, XI_RIGHT_SHOULDER },
|
|
|
|
-
|
|
|
|
- // Primary buttons:
|
|
|
|
- { "btn_a", XI_BUTTON, XI_A },
|
|
|
|
- { "btn_b", XI_BUTTON, XI_B },
|
|
|
|
- { "btn_x", XI_BUTTON, XI_X },
|
|
|
|
- { "btn_y", XI_BUTTON, XI_Y },
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- //-------------------------------------- MOTION EVENTS
|
|
|
|
- // Accelerometer/Gyroscope axes:
|
|
|
|
- { "accelx", SI_MOTION, SI_ACCELX },
|
|
|
|
- { "accely", SI_MOTION, SI_ACCELY },
|
|
|
|
- { "accelz", SI_MOTION, SI_ACCELZ },
|
|
|
|
- { "gravityx", SI_MOTION, SI_GRAVX },
|
|
|
|
- { "gravityy", SI_MOTION, SI_GRAVY },
|
|
|
|
- { "gravityz", SI_MOTION, SI_GRAVZ },
|
|
|
|
- { "gyrox", SI_MOTION, SI_GYROX },
|
|
|
|
- { "gyroy", SI_MOTION, SI_GYROY },
|
|
|
|
- { "gyroz", SI_MOTION, SI_GYROZ },
|
|
|
|
- { "yaw", SI_MOTION, SI_YAW },
|
|
|
|
- { "pitch", SI_MOTION, SI_PITCH },
|
|
|
|
- { "roll", SI_MOTION, SI_ROLL },
|
|
|
|
-
|
|
|
|
- //-------------------------------------- TOUCH EVENTS
|
|
|
|
- // Touch events:
|
|
|
|
- { "touchdown", SI_TOUCH, SI_TOUCHDOWN },
|
|
|
|
- { "touchup", SI_TOUCH, SI_TOUCHUP },
|
|
|
|
- { "touchmove", SI_TOUCH, SI_TOUCHMOVE },
|
|
|
|
-
|
|
|
|
- //-------------------------------------- GESTURE EVENTS
|
|
|
|
- // Preset gesture events:
|
|
|
|
- { "circleGesture", SI_GESTURE, SI_CIRCLE_GESTURE },
|
|
|
|
- { "swipeGesture", SI_GESTURE, SI_SWIPE_GESTURE },
|
|
|
|
- { "screenTapGesture", SI_GESTURE, SI_SCREENTAP_GESTURE },
|
|
|
|
- { "keyTapGesture", SI_GESTURE, SI_KEYTAP_GESTURE },
|
|
|
|
- { "pinchGesture", SI_GESTURE, SI_PINCH_GESTURE },
|
|
|
|
- { "scaleGesture", SI_GESTURE, SI_SCALE_GESTURE },
|
|
|
|
-
|
|
|
|
- //-------------------------------------- GESTURE EVENTS
|
|
|
|
- // Preset gesture events:
|
|
|
|
- { "leapHandAxis", SI_LEAP, LM_HANDAXIS },
|
|
|
|
- { "leapHandPos", SI_LEAP, LM_HANDPOS },
|
|
|
|
- { "leapHandRot", SI_LEAP, LM_HANDROT },
|
|
|
|
- { "leapFingerPos", SI_LEAP, LM_FINGERPOS },
|
|
|
|
-
|
|
|
|
- //-------------------------------------- MISCELLANEOUS EVENTS
|
|
|
|
- //
|
|
|
|
- { "anykey", SI_KEY, KEY_ANYKEY },
|
|
|
|
- { "nomatch", SI_UNKNOWN, 0xFFFFFFFF }
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-AsciiMapping gAsciiMap[] =
|
|
|
|
-{
|
|
|
|
- //--- KEYBOARD EVENTS
|
|
|
|
- //
|
|
|
|
- { "space", 0x0020 },
|
|
|
|
- //{ "exclamation", 0x0021 },
|
|
|
|
- { "doublequote", 0x0022 },
|
|
|
|
- //{ "pound", 0x0023 },
|
|
|
|
- //{ "ampersand", 0x0026 },
|
|
|
|
- { "apostrophe", 0x0027 },
|
|
|
|
- //{ "lparen", 0x0028 },
|
|
|
|
- //{ "rparen", 0x0029 },
|
|
|
|
- { "comma", 0x002c },
|
|
|
|
- { "minus", 0x002d },
|
|
|
|
- { "period", 0x002e },
|
|
|
|
- //{ "slash", 0x002f },
|
|
|
|
- //{ "colon", 0x003a },
|
|
|
|
- //{ "semicolon", 0x003b },
|
|
|
|
- //{ "lessthan", 0x003c },
|
|
|
|
- //{ "equals", 0x003d },
|
|
|
|
- //{ "morethan", 0x003e },
|
|
|
|
- //{ "lbracket", 0x005b },
|
|
|
|
- { "backslash", 0x005c },
|
|
|
|
- //{ "rbracket", 0x005d },
|
|
|
|
- //{ "circumflex", 0x005e },
|
|
|
|
- //{ "underscore", 0x005f },
|
|
|
|
- { "grave", 0x0060 },
|
|
|
|
- //{ "tilde", 0x007e },
|
|
|
|
- //{ "vertbar", 0x007c },
|
|
|
|
- //{ "exclamdown", 0x00a1 },
|
|
|
|
- //{ "cent", 0x00a2 },
|
|
|
|
- //{ "sterling", 0x00a3 },
|
|
|
|
- //{ "currency", 0x00a4 },
|
|
|
|
- //{ "brokenbar", 0x00a6 },
|
|
|
|
- //{ "ring", 0x00b0 },
|
|
|
|
- //{ "plusminus", 0x00b1 },
|
|
|
|
- { "super2", 0x00b2 },
|
|
|
|
- { "super3", 0x00b3 },
|
|
|
|
- { "acute", 0x00b4 },
|
|
|
|
- //{ "mu", 0x00b5 },
|
|
|
|
- //{ "ordmasculine", 0x00ba },
|
|
|
|
- //{ "questiondown", 0x00bf },
|
|
|
|
- //{ "gemandbls", 0x00df },
|
|
|
|
- //{ "agrave", 0x00e0 },
|
|
|
|
- //{ "aacute", 0x00e1 },
|
|
|
|
- //{ "acircumflex", 0x00e2 },
|
|
|
|
- //{ "atilde", 0x00e3 },
|
|
|
|
- //{ "adieresis", 0x00e4 },
|
|
|
|
- //{ "aring", 0x00e5 },
|
|
|
|
- //{ "ae", 0x00e6 },
|
|
|
|
- //{ "ccedille", 0x00e7 },
|
|
|
|
- //{ "egrave", 0x00e8 },
|
|
|
|
- //{ "eacute", 0x00e9 },
|
|
|
|
- //{ "ecircumflex", 0x00ea },
|
|
|
|
- //{ "edieresis", 0x00eb },
|
|
|
|
- //{ "igrave", 0x00ec },
|
|
|
|
- //{ "iacute", 0x00ed },
|
|
|
|
- //{ "icircumflex", 0x00ee },
|
|
|
|
- //{ "idieresis", 0x00ef },
|
|
|
|
- //{ "ntilde", 0x00f1 },
|
|
|
|
- //{ "ograve", 0x00f2 },
|
|
|
|
- //{ "oacute", 0x00f3 },
|
|
|
|
- //{ "ocircumflex", 0x00f4 },
|
|
|
|
- //{ "otilde", 0x00f5 },
|
|
|
|
- //{ "odieresis", 0x00f6 },
|
|
|
|
- //{ "divide", 0x00f7 },
|
|
|
|
- //{ "oslash", 0x00f8 },
|
|
|
|
- //{ "ugrave", 0x00f9 },
|
|
|
|
- //{ "uacute", 0x00fa },
|
|
|
|
- //{ "ucircumflex", 0x00fb },
|
|
|
|
- //{ "udieresis", 0x00fc },
|
|
|
|
- //{ "ygrave", 0x00fd },
|
|
|
|
- //{ "thorn", 0x00fe },
|
|
|
|
- //{ "ydieresis", 0x00ff },
|
|
|
|
- { "nomatch", 0xFFFF }
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-////Device Event Types
|
|
|
|
-//#define SI_UNKNOWN 0x01
|
|
|
|
-//#define SI_BUTTON 0x02
|
|
|
|
-//#define SI_POV 0x03
|
|
|
|
-//#define SI_XPOV 0x04
|
|
|
|
-//#define SI_YPOV 0x05
|
|
|
|
-//#define SI_UPOV 0x06
|
|
|
|
-//#define SI_DPOV 0x07
|
|
|
|
-//#define SI_LPOV 0x08
|
|
|
|
-//#define SI_RPOV 0x09
|
|
|
|
-//#define SI_KEY 0x0A
|
|
|
|
-//#define SI_XAXIS 0x0B
|
|
|
|
-//#define SI_YAXIS 0x0C
|
|
|
|
-//#define SI_ZAXIS 0x0D
|
|
|
|
-//#define SI_RXAXIS 0x0E
|
|
|
|
-//#define SI_RYAXIS 0x0F
|
|
|
|
-//#define SI_RZAXIS 0x10
|
|
|
|
-//#define SI_SLIDER 0x11
|
|
|
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
|
+// Copyright (c) 2013 GarageGames, LLC
|
|
|
|
+//
|
|
|
|
+// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
+// of this software and associated documentation files (the "Software"), to
|
|
|
|
+// deal in the Software without restriction, including without limitation the
|
|
|
|
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
|
+// sell copies of the Software, and to permit persons to whom the Software is
|
|
|
|
+// furnished to do so, subject to the following conditions:
|
|
|
|
+//
|
|
|
|
+// The above copyright notice and this permission notice shall be included in
|
|
|
|
+// all copies or substantial portions of the Software.
|
|
|
|
+//
|
|
|
|
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
+// IN THE SOFTWARE.
|
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+#include "input/actionMap.h"
|
|
|
|
+#include "platform/event.h"
|
|
|
|
+#include "console/console.h"
|
|
|
|
+#include "platform/platform.h"
|
|
|
|
+#include "platform/platformInput.h"
|
|
|
|
+#include "platform/platformAssert.h"
|
|
|
|
+#include "io/fileStream.h"
|
|
|
|
+#include "io/resource/resourceManager.h"
|
|
|
|
+
|
|
|
|
+// Script bindings.
|
|
|
|
+#include "actionMap_ScriptBinding.h"
|
|
|
|
+
|
|
|
|
+#define CONST_E 2.7182818284590452353602874f
|
|
|
|
+
|
|
|
|
+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 < (U32)mDeviceMaps.size(); i++)
|
|
|
|
+ delete mDeviceMaps[i];
|
|
|
|
+ mDeviceMaps.clear();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+ActionMap::DeviceMap::~DeviceMap()
|
|
|
|
+{
|
|
|
|
+ for(U32 i = 0; i < (U32)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, "if (isObject(%s)) %s.delete();\n"
|
|
|
|
+ "new ActionMap(%s);\n", getName(), 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)
|
|
|
|
+{
|
|
|
|
+ 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,SimObject* object /*= NULL*/)
|
|
|
|
+{
|
|
|
|
+ // DMMTODO - Slow INITIAL implementation. Replace with a faster version...
|
|
|
|
+ //
|
|
|
|
+ DeviceMap* pDeviceMap = NULL;
|
|
|
|
+ U32 i;
|
|
|
|
+ for (i = 0; i < (U32)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 < (U32)pDeviceMap->nodeMap.size(); i++)
|
|
|
|
+ {
|
|
|
|
+ if (pDeviceMap->nodeMap[i].modifiers == inModifiers &&
|
|
|
|
+ pDeviceMap->nodeMap[i].action == inAction &&
|
|
|
|
+ ( (object != NULL) ? object == pDeviceMap->nodeMap[i].object : true )) // Check for an object match if the object exists
|
|
|
|
+ {
|
|
|
|
+ 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;
|
|
|
|
+ pRetNode->deadZoneEnd = 0.0;
|
|
|
|
+ pRetNode->scaleFactor = 1.0;
|
|
|
|
+
|
|
|
|
+ pRetNode->consoleFunction = NULL;
|
|
|
|
+ pRetNode->makeConsoleCommand = NULL;
|
|
|
|
+ pRetNode->breakConsoleCommand = NULL;
|
|
|
|
+
|
|
|
|
+ //[neob, 5/7/2007 - #2975]
|
|
|
|
+ pRetNode->object = 0;
|
|
|
|
+
|
|
|
|
+ return pRetNode;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+void ActionMap::removeNode(const U32 inDeviceType, const U32 inDeviceInst, const U32 inModifiers, const U32 inAction, SimObject* object /*= NULL*/)
|
|
|
|
+{
|
|
|
|
+ // DMMTODO - Slow INITIAL implementation. Replace with a faster version...
|
|
|
|
+ //
|
|
|
|
+ DeviceMap* pDeviceMap = NULL;
|
|
|
|
+ U32 i;
|
|
|
|
+ for (i = 0; i < (U32)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 < (U32)pDeviceMap->nodeMap.size(); i++) {
|
|
|
|
+ if (pDeviceMap->nodeMap[i].modifiers == realMods &&
|
|
|
|
+ pDeviceMap->nodeMap[i].action == inAction &&
|
|
|
|
+ ( (object != NULL) ? object == pDeviceMap->nodeMap[i].object : true ))
|
|
|
|
+ {
|
|
|
|
+ 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 < (U32)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 < (U32)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 )
|
|
|
|
+{
|
|
|
|
+ devMapIndex = 0;
|
|
|
|
+ nodeIndex = 0;
|
|
|
|
+ return nextBoundNode( function, devMapIndex, nodeIndex );
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+bool ActionMap::nextBoundNode( 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 = devMapIndex; i < (U32)mDeviceMaps.size(); i++ )
|
|
|
|
+ {
|
|
|
|
+ const DeviceMap* dvcMap = mDeviceMaps[i];
|
|
|
|
+
|
|
|
|
+ for ( U32 j = nodeIndex; j < (U32)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 );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ nodeIndex = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return( false );
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+bool ActionMap::processUnbind(const char *device, const char *action, SimObject* object /*= NULL*/)
|
|
|
|
+{
|
|
|
|
+ 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, object);
|
|
|
|
+ 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 )
|
|
|
|
+{
|
|
|
|
+ char* returnString = Con::getReturnBuffer( 1024 );
|
|
|
|
+ returnString[0] = 0;
|
|
|
|
+
|
|
|
|
+ char buffer[256];
|
|
|
|
+ char deviceBuffer[32];
|
|
|
|
+ char keyBuffer[64];
|
|
|
|
+
|
|
|
|
+ U32 devMapIndex = 0, nodeIndex = 0;
|
|
|
|
+ while ( nextBoundNode( command, devMapIndex, nodeIndex ) )
|
|
|
|
+ {
|
|
|
|
+ const DeviceMap* deviceMap = mDeviceMaps[devMapIndex];
|
|
|
|
+
|
|
|
|
+ if ( getDeviceName( deviceMap->deviceType, deviceMap->deviceInst, deviceBuffer ) )
|
|
|
|
+ {
|
|
|
|
+ const Node* node = &deviceMap->nodeMap[nodeIndex];
|
|
|
|
+ const char* modifierString = getModifierString( node->modifiers );
|
|
|
|
+
|
|
|
|
+ if ( getKeyString( node->action, keyBuffer ) )
|
|
|
|
+ {
|
|
|
|
+ dSprintf( buffer, sizeof( buffer ), "%s\t%s%s", deviceBuffer, modifierString, keyBuffer );
|
|
|
|
+ if ( returnString[0] )
|
|
|
|
+ dStrcat( returnString, "\t" );
|
|
|
|
+ dStrcat( returnString, buffer );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ++nodeIndex;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return returnString;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+// 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 if (dStrnicmp(pDeviceName, "accelerometer", dStrlen("accelerometer")) == 0)
|
|
|
|
+ {
|
|
|
|
+ deviceType = AccelerometerDeviceType;
|
|
|
|
+ offset = dStrlen("accelerometer");
|
|
|
|
+ }
|
|
|
|
+ else if (dStrnicmp(pDeviceName, "gyroscope", dStrlen("gyroscope")) == 0)
|
|
|
|
+ {
|
|
|
|
+ deviceType = GyroscopeDeviceType;
|
|
|
|
+ offset = dStrlen("gyroscope");
|
|
|
|
+ }
|
|
|
|
+ else if (dStrnicmp(pDeviceName, "touchdevice", dStrlen("touchdevice")) == 0)
|
|
|
|
+ {
|
|
|
|
+ deviceType = ScreenTouchDeviceType;
|
|
|
|
+ offset = dStrlen("touchdevice");
|
|
|
|
+ }
|
|
|
|
+ else if (dStrnicmp(pDeviceName, "gamepad", dStrlen("gamepad")) == 0)
|
|
|
|
+ {
|
|
|
|
+ deviceType = GamepadDeviceType;
|
|
|
|
+ offset = dStrlen("gamepad");
|
|
|
|
+ }
|
|
|
|
+ else if (dStrnicmp(pDeviceName, "leapdevice", dStrlen("leapdevice")) == 0)
|
|
|
|
+ {
|
|
|
|
+ deviceType = LeapMotionDeviceType;
|
|
|
|
+ offset = dStrlen("leapdevice");
|
|
|
|
+ }
|
|
|
|
+ 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;
|
|
|
|
+
|
|
|
|
+ case AccelerometerDeviceType:
|
|
|
|
+ dStrcpy(buffer, "accelerometer");
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case GyroscopeDeviceType:
|
|
|
|
+ dStrcpy(buffer, "gyroscope");
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case ScreenTouchDeviceType:
|
|
|
|
+ dStrcpy(buffer, "touchdevice");
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case GamepadDeviceType:
|
|
|
|
+ dSprintf(buffer, 16, "gamepad%d", deviceInstance);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case LeapMotionDeviceType:
|
|
|
|
+ dStrcpy(buffer, "leapdevice");
|
|
|
|
+ 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_OSX)
|
|
|
|
+ // optional code, to output alt as cmd on mac.
|
|
|
|
+ // interpreter sees them as the same...
|
|
|
|
+ case (SI_SHIFT|SI_CTRL|SI_ALT):
|
|
|
|
+ return "cmd-shift-ctrl ";
|
|
|
|
+
|
|
|
|
+ case (SI_SHIFT|SI_ALT):
|
|
|
|
+ return "cmd-shift ";
|
|
|
|
+
|
|
|
|
+ case (SI_CTRL|SI_ALT):
|
|
|
|
+ return "cmd-ctrl ";
|
|
|
|
+
|
|
|
|
+ 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_ALT|SI_SHIFT|SI_CTRL|SI_MAC_OPT):
|
|
|
|
+ return "cmd-shift-ctrl-opt ";
|
|
|
|
+
|
|
|
|
+ case (SI_ALT|SI_SHIFT|SI_MAC_OPT):
|
|
|
|
+ return "cmd-shift-opt ";
|
|
|
|
+
|
|
|
|
+ case (SI_ALT|SI_CTRL|SI_MAC_OPT):
|
|
|
|
+ return "cmd-ctrl-opt ";
|
|
|
|
+
|
|
|
|
+ case (SI_ALT|SI_MAC_OPT):
|
|
|
|
+ return "cmd-opt ";
|
|
|
|
+
|
|
|
|
+ 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);
|
|
|
|
+
|
|
|
|
+// if (action >= KEY_A && action <= KEY_Z) {
|
|
|
|
+// buffer[0] = char(action - KEY_A + 'a');
|
|
|
|
+// buffer[1] = '\0';
|
|
|
|
+// return true;
|
|
|
|
+// } else if (action >= KEY_0 && action <= KEY_9) {
|
|
|
|
+// buffer[0] = char(action - KEY_0 + '0');
|
|
|
|
+// buffer[1] = '\0';
|
|
|
|
+ if ( (asciiCode != 0) && dIsDecentChar((char)asciiCode))
|
|
|
|
+ {
|
|
|
|
+ for (U32 i = 0; gAsciiMap[i].asciiCode != 0xFFFF; i++) {
|
|
|
|
+ if (gAsciiMap[i].asciiCode == asciiCode)
|
|
|
|
+ {
|
|
|
|
+ dStrcpy(buffer, gAsciiMap[i].pDescription);
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // Must not have found a string for that ascii code just record the char
|
|
|
|
+ buffer[0] = char(asciiCode);
|
|
|
|
+ buffer[1] = '\0';
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ if (action >= KEY_A && action <= KEY_Z)
|
|
|
|
+ {
|
|
|
|
+ buffer[0] = char(action - KEY_A + 'a');
|
|
|
|
+ buffer[1] = '\0';
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ else if (action >= KEY_0 && action <= KEY_9) {
|
|
|
|
+ buffer[0] = char(action - KEY_0 + '0');
|
|
|
|
+ buffer[1] = '\0';
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ for (U32 i = 0; gVirtualMap[i].code != 0xFFFFFFFF; i++) {
|
|
|
|
+ if (gVirtualMap[i].code == action) {
|
|
|
|
+ dStrcpy(buffer, gVirtualMap[i].pDescription);
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Con::errorf( "ActionMap::getKeyString: no string for action %d", action );
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//--------------------------------------------------------------------------
|
|
|
|
+bool ActionMap::processBindCmd(const char *device, const char *action, const char *makeCmd, const char *breakCmd)
|
|
|
|
+{
|
|
|
|
+ U32 deviceType;
|
|
|
|
+ U32 deviceInst;
|
|
|
|
+
|
|
|
|
+ if(!getDeviceTypeAndInstance(device, deviceType, deviceInst))
|
|
|
|
+ {
|
|
|
|
+ Con::printf("processBindCmd: unknown device: %s", device);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Ok, we now have the deviceType and instance. Create an event descriptor
|
|
|
|
+ // for the bind...
|
|
|
|
+ //
|
|
|
|
+ EventDescriptor eventDescriptor;
|
|
|
|
+ if (createEventDescriptor(action, &eventDescriptor) == false) {
|
|
|
|
+ Con::printf("Could not create a description for binding: %s", action);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // SI_POV == SI_MOVE, and the POV works fine with bindCmd, so we have to add these manually.
|
|
|
|
+ if( ( eventDescriptor.eventCode == SI_XAXIS ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_YAXIS ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_ZAXIS ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_RXAXIS ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_RYAXIS ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_RZAXIS ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_SLIDER ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_XPOV ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_YPOV ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_XPOV2 ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_YPOV2 ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_ACCELX ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_ACCELY ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_ACCELZ ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_GRAVX ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_GRAVY ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_GRAVZ ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_GYROX ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_GYROY ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_GYROZ ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_YAW ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_PITCH ) ||
|
|
|
|
+ ( eventDescriptor.eventCode == SI_ROLL ) )
|
|
|
|
+ {
|
|
|
|
+ Con::warnf( "ActionMap::processBindCmd - Cannot use 'bindCmd' with a move event type. Use 'bind' instead." );
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Create the full bind entry, and place it in the map
|
|
|
|
+ //
|
|
|
|
+ // DMMTODO
|
|
|
|
+ Node* pBindNode = getNode(deviceType, deviceInst,
|
|
|
|
+ eventDescriptor.flags,
|
|
|
|
+ eventDescriptor.eventCode);
|
|
|
|
+
|
|
|
|
+ pBindNode->flags = Node::BindCmd;
|
|
|
|
+ pBindNode->deadZoneBegin = 0;
|
|
|
|
+ pBindNode->deadZoneEnd = 0;
|
|
|
|
+ pBindNode->scaleFactor = 1;
|
|
|
|
+ if(makeCmd[0])
|
|
|
|
+ pBindNode->makeConsoleCommand = dStrdup(makeCmd);
|
|
|
|
+ else
|
|
|
|
+ pBindNode->makeConsoleCommand = dStrdup("");
|
|
|
|
+
|
|
|
|
+ if(breakCmd[0])
|
|
|
|
+ pBindNode->breakConsoleCommand = dStrdup(breakCmd);
|
|
|
|
+ else
|
|
|
|
+ pBindNode->breakConsoleCommand = dStrdup("");
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+bool ActionMap::processBind(const U32 argc, const char** argv, SimObject* object)
|
|
|
|
+{
|
|
|
|
+ // Ok, the bind will come in the following format:
|
|
|
|
+ // [device] [key or button] <[param spec] [param] ...> [fnName]
|
|
|
|
+ //
|
|
|
|
+ const char* pDeviceName = argv[0];
|
|
|
|
+ const char* pEvent = argv[1];
|
|
|
|
+ const char* pFnName = argv[argc - 1];
|
|
|
|
+
|
|
|
|
+ // Determine the device
|
|
|
|
+ U32 deviceType;
|
|
|
|
+ U32 deviceInst;
|
|
|
|
+
|
|
|
|
+ if(!getDeviceTypeAndInstance(argv[0], deviceType, deviceInst))
|
|
|
|
+ {
|
|
|
|
+ Con::printf("processBind: unknown device: %s", pDeviceName);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Ok, we now have the deviceType and instance. Create an event descriptor
|
|
|
|
+ // for the bind...
|
|
|
|
+ //
|
|
|
|
+ EventDescriptor eventDescriptor;
|
|
|
|
+ if (createEventDescriptor(pEvent, &eventDescriptor) == false) {
|
|
|
|
+ Con::printf("Could not create a description for binding: %s", pEvent);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Event has now been described, and device determined. we need now to extract
|
|
|
|
+ // any modifiers that the action map will apply to incoming events before
|
|
|
|
+ // calling the bound function...
|
|
|
|
+ //
|
|
|
|
+ // DMMTODO
|
|
|
|
+ U32 assignedFlags = 0;
|
|
|
|
+ F32 deadZoneBegin = 0.0f;
|
|
|
|
+ F32 deadZoneEnd = 0.0f;
|
|
|
|
+ F32 scaleFactor = 1.0f;
|
|
|
|
+
|
|
|
|
+ if (argc != 3) {
|
|
|
|
+ // We have the following: "[DSIR]" [deadZone] [scale]
|
|
|
|
+ //
|
|
|
|
+ const char* pSpec = argv[2];
|
|
|
|
+
|
|
|
|
+ for (U32 i = 0; pSpec[i] != '\0'; i++) {
|
|
|
|
+ switch (pSpec[i]) {
|
|
|
|
+ case 'r': case 'R':
|
|
|
|
+ assignedFlags |= Node::HasScale;
|
|
|
|
+ break;
|
|
|
|
+ case 's': case 'S':
|
|
|
|
+ assignedFlags |= Node::HasScale;
|
|
|
|
+ break;
|
|
|
|
+ case 'd': case 'D':
|
|
|
|
+ assignedFlags |= Node::HasDeadZone;
|
|
|
|
+ break;
|
|
|
|
+ case 'i': case 'I':
|
|
|
|
+ assignedFlags |= Node::Inverted;
|
|
|
|
+ break;
|
|
|
|
+ case 'n': case 'N':
|
|
|
|
+ assignedFlags |= Node::NonLinear;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ AssertFatal(false, avar("Misunderstood specifier in bind (spec string: %s)",
|
|
|
|
+ pSpec));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Ok, we have the flags. Scan the dead zone and scale, if any.
|
|
|
|
+ //
|
|
|
|
+ U32 curArg = 3;
|
|
|
|
+ if (assignedFlags & Node::HasDeadZone) {
|
|
|
|
+ dSscanf(argv[curArg], "%g %g", &deadZoneBegin, &deadZoneEnd);
|
|
|
|
+ curArg++;
|
|
|
|
+ }
|
|
|
|
+ if (assignedFlags & Node::HasScale) {
|
|
|
|
+ scaleFactor = dAtof(argv[curArg]);
|
|
|
|
+ curArg++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (curArg != (argc - 1)) {
|
|
|
|
+ AssertFatal(curArg == (argc - 1), "error in bind spec somewhere...");
|
|
|
|
+ Con::printf("Improperly specified bind for key: %s", argv[2]);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Ensure that the console function is properly specified?
|
|
|
|
+ //
|
|
|
|
+ // DMMTODO
|
|
|
|
+
|
|
|
|
+ // Create the full bind entry, and place it in the map
|
|
|
|
+ //
|
|
|
|
+ // DMMTODO
|
|
|
|
+ Node* pBindNode = getNode(deviceType, deviceInst,
|
|
|
|
+ eventDescriptor.flags,
|
|
|
|
+ eventDescriptor.eventCode, object);
|
|
|
|
+
|
|
|
|
+ pBindNode->flags = assignedFlags;
|
|
|
|
+ pBindNode->deadZoneBegin = deadZoneBegin;
|
|
|
|
+ pBindNode->deadZoneEnd = deadZoneEnd;
|
|
|
|
+ pBindNode->scaleFactor = scaleFactor;
|
|
|
|
+ pBindNode->object = object;
|
|
|
|
+ pBindNode->consoleFunction = StringTable->insert(pFnName);
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+bool ActionMap::processLeap(const InputEvent* pEvent)
|
|
|
|
+{
|
|
|
|
+ static const char *argv[5];
|
|
|
|
+ char buffer[64];
|
|
|
|
+
|
|
|
|
+ const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType );
|
|
|
|
+
|
|
|
|
+ if (pNode == NULL)
|
|
|
|
+ {
|
|
|
|
+ // Check to see if we clear the modifiers, do we find an action?
|
|
|
|
+ if (pEvent->modifier != 0)
|
|
|
|
+ pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
|
|
|
|
+
|
|
|
|
+ if (pNode == NULL)
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // "Do nothing" bind:
|
|
|
|
+ if ( !pNode->consoleFunction[0] )
|
|
|
|
+ return( true );
|
|
|
|
+
|
|
|
|
+ argv[0] = pNode->consoleFunction;
|
|
|
|
+
|
|
|
|
+ float values[3];
|
|
|
|
+ values[0] = pEvent->fValues[0];
|
|
|
|
+ values[1] = pEvent->fValues[1];
|
|
|
|
+ values[2] = pEvent->fValues[2];
|
|
|
|
+
|
|
|
|
+ if ( pNode->flags & Node::HasDeadZone )
|
|
|
|
+ {
|
|
|
|
+ if ( pEvent->fValues[0] >= pNode->deadZoneBegin && pEvent->fValues[0] <= pNode->deadZoneEnd )
|
|
|
|
+ values[0] = 0.0f;
|
|
|
|
+ if ( pEvent->fValues[1] >= pNode->deadZoneBegin && pEvent->fValues[1] <= pNode->deadZoneEnd )
|
|
|
|
+ values[1] = 0.0f;
|
|
|
|
+ if ( pEvent->fValues[2] >= pNode->deadZoneBegin && pEvent->fValues[2] <= pNode->deadZoneEnd )
|
|
|
|
+ values[2] = 0.0f;
|
|
|
|
+
|
|
|
|
+ // All values are all null, so don't bother executing the function
|
|
|
|
+ if (!values[0] && !values[1] && !values[2])
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ switch(pEvent->objType)
|
|
|
|
+ {
|
|
|
|
+ case LM_HANDPOS:
|
|
|
|
+
|
|
|
|
+ // ID
|
|
|
|
+ argv[1] = Con::getIntArg(pEvent->iValue);
|
|
|
|
+
|
|
|
|
+ // Position
|
|
|
|
+ dSprintf(buffer, sizeof(buffer), "%f %f %f", values[0], values[1], values[2]);
|
|
|
|
+
|
|
|
|
+ argv[2] = buffer;
|
|
|
|
+
|
|
|
|
+ if (pNode->object)
|
|
|
|
+ Con::executef(pNode->object, 3, argv[0], argv[1], argv[2]);
|
|
|
|
+ else
|
|
|
|
+ Con::execute(3, argv);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case LM_HANDROT:
|
|
|
|
+
|
|
|
|
+ // ID
|
|
|
|
+ argv[1] = Con::getIntArg(pEvent->iValue);
|
|
|
|
+
|
|
|
|
+ // Rotation
|
|
|
|
+ dSprintf(buffer, sizeof(buffer), "%f %f %f", values[0], values[1], values[2]);
|
|
|
|
+
|
|
|
|
+ argv[2] = buffer;
|
|
|
|
+
|
|
|
|
+ if (pNode->object)
|
|
|
|
+ Con::executef(pNode->object, 3, argv[0], argv[1], argv[2]);
|
|
|
|
+ else
|
|
|
|
+ Con::execute(3, argv);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case LM_FINGERPOS:
|
|
|
|
+
|
|
|
|
+ // IDs
|
|
|
|
+ argv[1] = pEvent->fingerIDs;
|
|
|
|
+
|
|
|
|
+ // X-coordinates
|
|
|
|
+ argv[2] = pEvent->fingersX;
|
|
|
|
+
|
|
|
|
+ // Y-coordinates
|
|
|
|
+ argv[3] = pEvent->fingersY;
|
|
|
|
+
|
|
|
|
+ // Z-coordinates
|
|
|
|
+ argv[4] = pEvent->fingersZ;
|
|
|
|
+
|
|
|
|
+ if (pNode->object)
|
|
|
|
+ Con::executef(pNode->object, 5, argv[0], argv[1], argv[2], argv[3], argv[4]);
|
|
|
|
+ else
|
|
|
|
+ Con::execute(5, argv);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case LM_HANDAXIS:
|
|
|
|
+ default:
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+bool ActionMap::processGesture(const InputEvent* pEvent)
|
|
|
|
+{
|
|
|
|
+ static const char *argv[6];
|
|
|
|
+ char buffer[64];
|
|
|
|
+
|
|
|
|
+ const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType );
|
|
|
|
+
|
|
|
|
+ if (pNode == NULL)
|
|
|
|
+ {
|
|
|
|
+ // Check to see if we clear the modifiers, do we find an action?
|
|
|
|
+ if (pEvent->modifier != 0)
|
|
|
|
+ pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
|
|
|
|
+
|
|
|
|
+ if (pNode == NULL)
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // "Do nothing" bind:
|
|
|
|
+ if ( !pNode->consoleFunction[0] )
|
|
|
|
+ return( true );
|
|
|
|
+
|
|
|
|
+ // Function
|
|
|
|
+ argv[0] = pNode->consoleFunction;
|
|
|
|
+
|
|
|
|
+ switch(pEvent->objType)
|
|
|
|
+ {
|
|
|
|
+ case SI_CIRCLE_GESTURE:
|
|
|
|
+
|
|
|
|
+ // ID
|
|
|
|
+ argv[1] = Con::getIntArg(pEvent->iValue);
|
|
|
|
+
|
|
|
|
+ // Progress
|
|
|
|
+ argv[2] = Con::getFloatArg(pEvent->fValues[0]);
|
|
|
|
+
|
|
|
|
+ // Radius
|
|
|
|
+ argv[3] = Con::getFloatArg(pEvent->fValues[1]);
|
|
|
|
+
|
|
|
|
+ // Direction (1 clockwise, 0 counter-clockwise)
|
|
|
|
+ argv[4] = Con::getFloatArg(pEvent->fValues[2]);
|
|
|
|
+
|
|
|
|
+ // State
|
|
|
|
+ argv[5] = Con::getFloatArg(pEvent->fValues[3]);
|
|
|
|
+
|
|
|
|
+ if (pNode->object)
|
|
|
|
+ Con::executef(pNode->object, 6, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
|
|
|
|
+ else
|
|
|
|
+ Con::execute(6, argv);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SI_SWIPE_GESTURE:
|
|
|
|
+
|
|
|
|
+ // ID
|
|
|
|
+ argv[1] = Con::getIntArg(pEvent->iValue);
|
|
|
|
+
|
|
|
|
+ // State
|
|
|
|
+ argv[2] = Con::getFloatArg(pEvent->fValues[0]);
|
|
|
|
+
|
|
|
|
+ // Direction
|
|
|
|
+ dSprintf(buffer, sizeof(buffer), "%f %f %f", pEvent->fValues[1], pEvent->fValues[2], pEvent->fValues[3]);
|
|
|
|
+
|
|
|
|
+ argv[3] = buffer;
|
|
|
|
+ // Speed
|
|
|
|
+ argv[4] = Con::getFloatArg(pEvent->fValues[4]);
|
|
|
|
+
|
|
|
|
+ if (pNode->object)
|
|
|
|
+ Con::executef(pNode->object, 5, argv[0], argv[1], argv[2], argv[3], argv[4]);
|
|
|
|
+ else
|
|
|
|
+ Con::execute(5, argv);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SI_KEYTAP_GESTURE:
|
|
|
|
+ case SI_SCREENTAP_GESTURE:
|
|
|
|
+
|
|
|
|
+ // ID
|
|
|
|
+ argv[1] = Con::getIntArg(pEvent->iValue);
|
|
|
|
+
|
|
|
|
+ // Position
|
|
|
|
+ dSprintf(buffer, sizeof(buffer), "%f %f %f", pEvent->fValues[0], pEvent->fValues[1], pEvent->fValues[2]);
|
|
|
|
+
|
|
|
|
+ argv[2] = buffer;
|
|
|
|
+
|
|
|
|
+ // Direction
|
|
|
|
+ dSprintf(buffer, sizeof(buffer), "%f %f %f", pEvent->fValues[3], pEvent->fValues[4], pEvent->fValues[5]);
|
|
|
|
+
|
|
|
|
+ argv[3] = buffer;
|
|
|
|
+
|
|
|
|
+ if (pNode->object)
|
|
|
|
+ Con::executef(pNode->object, 4, argv[0], argv[1], argv[2], argv[3]);
|
|
|
|
+ else
|
|
|
|
+ Con::execute(5, argv);
|
|
|
|
+
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SI_PINCH_GESTURE:
|
|
|
|
+ case SI_SCALE_GESTURE:
|
|
|
|
+ default:
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+bool ActionMap::processTouch(const InputEvent* pEvent)
|
|
|
|
+{
|
|
|
|
+ static const char *argv[4];
|
|
|
|
+ const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst);
|
|
|
|
+
|
|
|
|
+ if (pNode == NULL)
|
|
|
|
+ {
|
|
|
|
+ // Check to see if we clear the modifiers, do we find an action?
|
|
|
|
+ if (pEvent->modifier != 0)
|
|
|
|
+ pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
|
|
|
|
+
|
|
|
|
+ if (pNode == NULL)
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // "Do nothing" bind:
|
|
|
|
+ if ( !pNode->consoleFunction[0] )
|
|
|
|
+ return( true );
|
|
|
|
+
|
|
|
|
+ // Ok, we're all set up, call the function.
|
|
|
|
+ argv[0] = pNode->consoleFunction;
|
|
|
|
+ argv[1] = pEvent->fingerIDs;
|
|
|
|
+ argv[2] = pEvent->fingersX;
|
|
|
|
+ argv[3] = pEvent->fingersY;
|
|
|
|
+
|
|
|
|
+ if (pNode->object)
|
|
|
|
+ Con::executef(pNode->object, 4, argv[0], argv[1], argv[2], argv[3]);
|
|
|
|
+ else
|
|
|
|
+ Con::execute(4, argv);
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+bool ActionMap::processButton(const InputEvent* pEvent)
|
|
|
|
+{
|
|
|
|
+ static const char *argv[2];
|
|
|
|
+ const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst);
|
|
|
|
+
|
|
|
|
+ if (pNode == NULL)
|
|
|
|
+ {
|
|
|
|
+ // Check to see if we clear the modifiers, do we find an action?
|
|
|
|
+ if (pEvent->modifier != 0)
|
|
|
|
+ pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
|
|
|
|
+
|
|
|
|
+ if (pNode == NULL)
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Whadda ya know, we have this bound. Set up, and call the console
|
|
|
|
+ // function associated with it...
|
|
|
|
+ //
|
|
|
|
+ F32 value = pEvent->fValues[0];
|
|
|
|
+
|
|
|
|
+ if (pNode->flags & Node::Ranged)
|
|
|
|
+ {
|
|
|
|
+ value = (value * 2.0f) - 1.0f;
|
|
|
|
+
|
|
|
|
+ if (pNode->flags & Node::Inverted)
|
|
|
|
+ value *= -1.0f;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ if (pNode->flags & Node::Inverted)
|
|
|
|
+ value = 1.0f - value;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (pNode->flags & Node::HasScale)
|
|
|
|
+ value *= pNode->scaleFactor;
|
|
|
|
+
|
|
|
|
+ if (pNode->flags & Node::HasDeadZone)
|
|
|
|
+ {
|
|
|
|
+ if (value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd)
|
|
|
|
+ value = 0.0f;
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ if( value > 0 )
|
|
|
|
+ value = ( value - pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
|
|
|
|
+ else
|
|
|
|
+ value = ( value + pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if( pNode->flags & Node::NonLinear )
|
|
|
|
+ value = ( value < 0.f ? -1.f : 1.f ) * mPow( mFabs( value ), CONST_E );
|
|
|
|
+
|
|
|
|
+ // Ok, we're all set up, call the function.
|
|
|
|
+ if(pNode->flags & Node::BindCmd)
|
|
|
|
+ {
|
|
|
|
+ // it's a bind command
|
|
|
|
+ if(pNode->makeConsoleCommand)
|
|
|
|
+ Con::evaluate(pNode->makeConsoleCommand);
|
|
|
|
+ }
|
|
|
|
+ else if ( pNode->consoleFunction[0] )
|
|
|
|
+ {
|
|
|
|
+ argv[0] = pNode->consoleFunction;
|
|
|
|
+ argv[1] = Con::getFloatArg(value);
|
|
|
|
+
|
|
|
|
+ if (pNode->object)
|
|
|
|
+ Con::executef(pNode->object, 2, argv[0], argv[1]);
|
|
|
|
+ else
|
|
|
|
+ Con::execute(2, argv);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // [neo, 5/13/2007 - #3109]
|
|
|
|
+ // The execs/evaluate above could have called reentrant script code which made calls to
|
|
|
|
+ // bindCmd() etc, channging the node map underneath us. If enough nodes were added then
|
|
|
|
+ // the node map vector would realloc, with the result that pNode would then be pointing
|
|
|
|
+ // at garbage and cause a crash when passed to enterBreakEvent() below. So we just look
|
|
|
|
+ // it up again to be safe. This is not needed in the other cases below as we return right
|
|
|
|
+ // after the execs and don't use pNode again.
|
|
|
|
+ pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst );
|
|
|
|
+
|
|
|
|
+ if( pNode == NULL )
|
|
|
|
+ return true; // We already called any bound methods/functions so our job is done
|
|
|
|
+
|
|
|
|
+ //
|
|
|
|
+ // And enter the break into the table if this is a make event...
|
|
|
|
+ enterBreakEvent(pEvent, pNode);
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+bool ActionMap::processMove(const InputEvent* pEvent)
|
|
|
|
+{
|
|
|
|
+ static const char *argv[4];
|
|
|
|
+
|
|
|
|
+ if (pEvent->deviceType == MouseDeviceType)
|
|
|
|
+ {
|
|
|
|
+ const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType);
|
|
|
|
+
|
|
|
|
+ if (pNode == NULL)
|
|
|
|
+ {
|
|
|
|
+ // Check to see if we clear the modifiers, do we find an action?
|
|
|
|
+ if (pEvent->modifier != 0)
|
|
|
|
+ pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objType);
|
|
|
|
+
|
|
|
|
+ if (pNode == NULL)
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // "Do nothing" bind:
|
|
|
|
+ if ( !pNode->consoleFunction[0] )
|
|
|
|
+ return( true );
|
|
|
|
+
|
|
|
|
+ // Whadda ya know, we have this bound. Set up, and call the console
|
|
|
|
+ // function associated with it. Mouse events ignore range and dead
|
|
|
|
+ // zone params.
|
|
|
|
+ //
|
|
|
|
+ F32 value = pEvent->fValues[0];
|
|
|
|
+
|
|
|
|
+ if (pNode->flags & Node::Inverted)
|
|
|
|
+ value *= -1.0f;
|
|
|
|
+ if (pNode->flags & Node::HasScale)
|
|
|
|
+ value *= pNode->scaleFactor;
|
|
|
|
+
|
|
|
|
+ // Ok, we're all set up, call the function.
|
|
|
|
+ argv[0] = pNode->consoleFunction;
|
|
|
|
+ argv[1] = Con::getFloatArg(value);
|
|
|
|
+
|
|
|
|
+ if (pNode->object)
|
|
|
|
+ Con::executef(pNode->object, 2, argv[0], argv[1]);
|
|
|
|
+ else
|
|
|
|
+ Con::execute(2, argv);
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ else if ( (pEvent->objType == XI_POS || pEvent->objType == XI_FLOAT || pEvent->objType == XI_ROT || pEvent->objType == XI_INT) )
|
|
|
|
+ {
|
|
|
|
+ const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst);
|
|
|
|
+
|
|
|
|
+ if( pNode == NULL )
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ // Ok, we're all set up, call the function.
|
|
|
|
+ argv[0] = pNode->consoleFunction;
|
|
|
|
+ S32 argc = 1;
|
|
|
|
+
|
|
|
|
+ if (pEvent->objType == XI_INT)
|
|
|
|
+ {
|
|
|
|
+ // Handle the integer as some sort of motion such as a
|
|
|
|
+ // single component to an absolute position
|
|
|
|
+ argv[1] = Con::getIntArg( pEvent->iValue );
|
|
|
|
+ argc += 1;
|
|
|
|
+ }
|
|
|
|
+ else if (pEvent->objType == XI_FLOAT)
|
|
|
|
+ {
|
|
|
|
+ // Handle float as some sort of motion such as a
|
|
|
|
+ // single component to an absolute position
|
|
|
|
+ argv[1] = Con::getFloatArg( pEvent->fValues[0] );
|
|
|
|
+ argc += 1;
|
|
|
|
+ }
|
|
|
|
+ else if (pEvent->objType == XI_POS)
|
|
|
|
+ {
|
|
|
|
+ // Handle Point3F type position
|
|
|
|
+ argv[1] = Con::getFloatArg( pEvent->fValues[0] );
|
|
|
|
+ argv[2] = Con::getFloatArg( pEvent->fValues[1] );
|
|
|
|
+ argv[3] = Con::getFloatArg( pEvent->fValues[2] );
|
|
|
|
+
|
|
|
|
+ argc += 3;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (pNode->object)
|
|
|
|
+ {
|
|
|
|
+ Con::execute(pNode->object, argc, argv);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ Con::execute(argc, argv);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ else if ( pEvent->deviceType == JoystickDeviceType || pEvent->deviceType == GamepadDeviceType )
|
|
|
|
+ {
|
|
|
|
+ // Joystick events...
|
|
|
|
+ const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst );
|
|
|
|
+
|
|
|
|
+ if( pNode == NULL )
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ // "Do nothing" bind:
|
|
|
|
+ if ( !pNode->consoleFunction[0] )
|
|
|
|
+ return( true );
|
|
|
|
+
|
|
|
|
+ // Whadda ya know, we have this bound. Set up, and call the console
|
|
|
|
+ // function associated with it. Joystick move events are the same as mouse
|
|
|
|
+ // move events except that they don't ignore dead zone.
|
|
|
|
+ //
|
|
|
|
+ F32 value = pEvent->fValues[0];
|
|
|
|
+ if ( pNode->flags & Node::Inverted )
|
|
|
|
+ value *= -1.0f;
|
|
|
|
+
|
|
|
|
+ if ( pNode->flags & Node::HasScale )
|
|
|
|
+ value *= pNode->scaleFactor;
|
|
|
|
+
|
|
|
|
+ if ( pNode->flags & Node::HasDeadZone )
|
|
|
|
+ {
|
|
|
|
+ if ( value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd )
|
|
|
|
+ {
|
|
|
|
+ value = 0.0f;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ if( value > 0 )
|
|
|
|
+ value = ( value - pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
|
|
|
|
+ else
|
|
|
|
+ value = ( value + pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if( pNode->flags & Node::NonLinear )
|
|
|
|
+ value = ( value < 0.f ? -1.f : 1.f ) * mPow( mFabs( value ), CONST_E );
|
|
|
|
+
|
|
|
|
+ // Ok, we're all set up, call the function.
|
|
|
|
+ argv[0] = pNode->consoleFunction;
|
|
|
|
+ argv[1] = Con::getFloatArg( value );
|
|
|
|
+
|
|
|
|
+ if (pNode->object)
|
|
|
|
+ Con::executef(pNode->object, S32(argv[0]), argv[1]);
|
|
|
|
+ else
|
|
|
|
+ Con::execute(2, argv);
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+bool ActionMap::processMotion(const InputEvent* pEvent)
|
|
|
|
+{
|
|
|
|
+ static const char *argv[2];
|
|
|
|
+
|
|
|
|
+ // iOS Accelerometer, Gyroscope and DeviceMotion processing
|
|
|
|
+ // Currently, this is identical to the joystick handling.
|
|
|
|
+
|
|
|
|
+ // This was copied over into its own section because this will
|
|
|
|
+ // give us a dedicated section to tweak processing based on iOS specific
|
|
|
|
+ // devices. No point in trying to mangle joystick code any further
|
|
|
|
+ const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType );
|
|
|
|
+
|
|
|
|
+ if ( pNode == NULL )
|
|
|
|
+ {
|
|
|
|
+ // Check to see if we clear the modifiers, do we find an action?
|
|
|
|
+ if (pEvent->modifier != 0)
|
|
|
|
+ pNode = findNode( pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objType );
|
|
|
|
+
|
|
|
|
+ if ( pNode == NULL )
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // "Do nothing" bind:
|
|
|
|
+ if ( !pNode->consoleFunction[0] )
|
|
|
|
+ return( true );
|
|
|
|
+
|
|
|
|
+ F32 value = pEvent->fValues[0];
|
|
|
|
+
|
|
|
|
+ if ( pNode->flags & Node::Inverted )
|
|
|
|
+ value *= -1.0f;
|
|
|
|
+
|
|
|
|
+ if ( pNode->flags & Node::HasScale )
|
|
|
|
+ value *= pNode->scaleFactor;
|
|
|
|
+
|
|
|
|
+ if ( pNode->flags & Node::HasDeadZone )
|
|
|
|
+ {
|
|
|
|
+ if ( value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd )
|
|
|
|
+ value = 0.0f;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Ok, we're all set up, call the function.
|
|
|
|
+ argv[0] = pNode->consoleFunction;
|
|
|
|
+ argv[1] = Con::getFloatArg( value );
|
|
|
|
+
|
|
|
|
+ if (pNode->object)
|
|
|
|
+ Con::executef(pNode->object, 2, argv[0], argv[1]);
|
|
|
|
+ else
|
|
|
|
+ Con::execute(2, argv);
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+bool ActionMap::processXInput(const InputEvent* pEvent)
|
|
|
|
+{
|
|
|
|
+ static const char *argv[2];
|
|
|
|
+
|
|
|
|
+ if ((pEvent->objType == XI_FLOAT || pEvent->objType == XI_INT))
|
|
|
|
+ {
|
|
|
|
+ const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType );
|
|
|
|
+
|
|
|
|
+ if (pNode == NULL )
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ // Ok, we're all set up, call the function.
|
|
|
|
+ argv[0] = pNode->consoleFunction;
|
|
|
|
+ S32 argc = 1;
|
|
|
|
+
|
|
|
|
+ if (pEvent->objType == XI_INT)
|
|
|
|
+ {
|
|
|
|
+ // Handle the integer as some sort of motion such as a
|
|
|
|
+ // single component to an absolute position
|
|
|
|
+ argv[1] = Con::getIntArg( pEvent->iValue );
|
|
|
|
+ argc += 1;
|
|
|
|
+ }
|
|
|
|
+ else if (pEvent->objType == XI_FLOAT)
|
|
|
|
+ {
|
|
|
|
+ // Handle float as some sort of motion such as a
|
|
|
|
+ // single component to an absolute position
|
|
|
|
+ argv[1] = Con::getFloatArg( pEvent->fValues[0] );
|
|
|
|
+ argc += 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (pNode->object)
|
|
|
|
+ {
|
|
|
|
+ Con::execute(pNode->object, argc, argv);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ Con::execute(argc, argv);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+bool ActionMap::processAction(const InputEvent* pEvent)
|
|
|
|
+{
|
|
|
|
+ switch(pEvent->action)
|
|
|
|
+ {
|
|
|
|
+ case SI_LEAP:
|
|
|
|
+ return processLeap(pEvent);
|
|
|
|
+ break;
|
|
|
|
+ case SI_GESTURE:
|
|
|
|
+ return processGesture(pEvent);
|
|
|
|
+ break;
|
|
|
|
+ case SI_TOUCH:
|
|
|
|
+ return processTouch(pEvent);
|
|
|
|
+ break;
|
|
|
|
+ case SI_MAKE:
|
|
|
|
+ return processButton(pEvent);
|
|
|
|
+ break;
|
|
|
|
+ case SI_MOVE:
|
|
|
|
+ return processMove(pEvent);
|
|
|
|
+ break;
|
|
|
|
+ case SI_MOTION:
|
|
|
|
+ return processMotion(pEvent);
|
|
|
|
+ break;
|
|
|
|
+ case SI_BREAK:
|
|
|
|
+ return checkBreakTable(pEvent);
|
|
|
|
+ break;
|
|
|
|
+ case SI_VALUE:
|
|
|
|
+ return processXInput(pEvent);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+void ActionMap::enterBreakEvent(const InputEvent* pEvent, const Node* pNode)
|
|
|
|
+{
|
|
|
|
+ // There aren't likely to be many breaks outstanding at any one given time,
|
|
|
|
+ // so a simple linear search is probably sufficient. Note that the break table
|
|
|
|
+ // is static to the class, all breaks are directed to the action map that received
|
|
|
|
+ // the make.
|
|
|
|
+ //
|
|
|
|
+ S32 entry = -1;
|
|
|
|
+ for (U32 i = 0; i < (U32)smBreakTable.size(); i++) {
|
|
|
|
+ if (smBreakTable[i].deviceType == U32(pEvent->deviceType) &&
|
|
|
|
+ smBreakTable[i].deviceInst == U32(pEvent->deviceInst) &&
|
|
|
|
+ smBreakTable[i].objInst == U32(pEvent->objInst)) {
|
|
|
|
+ // Match.
|
|
|
|
+ entry = i;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (entry == -1) {
|
|
|
|
+ smBreakTable.increment();
|
|
|
|
+ entry = smBreakTable.size() - 1;
|
|
|
|
+
|
|
|
|
+ smBreakTable[entry].deviceType = pEvent->deviceType;
|
|
|
|
+ smBreakTable[entry].deviceInst = pEvent->deviceInst;
|
|
|
|
+ smBreakTable[entry].objInst = pEvent->objInst;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Ok, we now have the entry, and know that the device desc. and the objInst match.
|
|
|
|
+ // Copy out the node information...
|
|
|
|
+ //
|
|
|
|
+ smBreakTable[entry].object = pNode->object;
|
|
|
|
+ // [neo, 5/7/2007 - #2975]
|
|
|
|
+ // object above can be deleted in between a make/break and so object will point
|
|
|
|
+ // to turfed memory and crash. To keep things simple we just store id as well so
|
|
|
|
+ // we can look it up to validate object ref.
|
|
|
|
+ smBreakTable[entry].objectId = pNode->object ? pNode->object->getId() : 0;
|
|
|
|
+
|
|
|
|
+ smBreakTable[entry].consoleFunction = pNode->consoleFunction;
|
|
|
|
+
|
|
|
|
+ if(pNode->breakConsoleCommand)
|
|
|
|
+ smBreakTable[entry].breakConsoleCommand = dStrdup(pNode->breakConsoleCommand);
|
|
|
|
+ else
|
|
|
|
+ smBreakTable[entry].breakConsoleCommand = NULL;
|
|
|
|
+
|
|
|
|
+ smBreakTable[entry].flags = pNode->flags;
|
|
|
|
+ smBreakTable[entry].deadZoneBegin = pNode->deadZoneBegin;
|
|
|
|
+ smBreakTable[entry].deadZoneEnd = pNode->deadZoneEnd;
|
|
|
|
+ smBreakTable[entry].scaleFactor = pNode->scaleFactor;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+bool ActionMap::checkBreakTable(const InputEvent* pEvent)
|
|
|
|
+{
|
|
|
|
+ for (U32 i = 0; i < (U32)smBreakTable.size(); i++) {
|
|
|
|
+ if (smBreakTable[i].deviceType == U32(pEvent->deviceType) &&
|
|
|
|
+ smBreakTable[i].deviceInst == U32(pEvent->deviceInst) &&
|
|
|
|
+ smBreakTable[i].objInst == U32(pEvent->objInst)) {
|
|
|
|
+ // Match. Issue the break event...
|
|
|
|
+ //
|
|
|
|
+ F32 value = pEvent->fValues[0];
|
|
|
|
+ if (smBreakTable[i].flags & Node::Ranged) {
|
|
|
|
+ value = (value * 2.0f) - 1.0f;
|
|
|
|
+ if (smBreakTable[i].flags & Node::Inverted)
|
|
|
|
+ value *= -1.0f;
|
|
|
|
+ } else {
|
|
|
|
+ if (smBreakTable[i].flags & Node::Inverted)
|
|
|
|
+ value = 1.0f - value;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (smBreakTable[i].flags & Node::HasScale)
|
|
|
|
+ value *= smBreakTable[i].scaleFactor;
|
|
|
|
+
|
|
|
|
+ if (smBreakTable[i].flags & Node::HasDeadZone)
|
|
|
|
+ if (value >= smBreakTable[i].deadZoneBegin &&
|
|
|
|
+ value <= smBreakTable[i].deadZoneEnd)
|
|
|
|
+ value = 0.0f;
|
|
|
|
+
|
|
|
|
+ // Ok, we're all set up, call the function.
|
|
|
|
+ if(smBreakTable[i].consoleFunction)
|
|
|
|
+ {
|
|
|
|
+ if ( smBreakTable[i].consoleFunction[0] )
|
|
|
|
+ {
|
|
|
|
+ static const char *argv[2];
|
|
|
|
+ argv[0] = smBreakTable[i].consoleFunction;
|
|
|
|
+ argv[1] = Con::getFloatArg(value);
|
|
|
|
+
|
|
|
|
+ if( smBreakTable[i].object )
|
|
|
|
+ {
|
|
|
|
+ // [neo, 5/7/2007 - #2975]
|
|
|
|
+ // object above can be deleted in between a make/break and so object will point
|
|
|
|
+ // to turfed memory and crash. To keep things simple we just store id as well so
|
|
|
|
+ // we can look it up to validate object ref.
|
|
|
|
+ if( smBreakTable[i].objectId > 0 && Sim::findObject( smBreakTable[i].objectId ) )
|
|
|
|
+ Con::executef(smBreakTable[i].object, 2, argv[0], argv[1]);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ Con::execute(2, argv);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else if(smBreakTable[i].breakConsoleCommand)
|
|
|
|
+ {
|
|
|
|
+ Con::evaluate(smBreakTable[i].breakConsoleCommand);
|
|
|
|
+ dFree(smBreakTable[i].breakConsoleCommand);
|
|
|
|
+ }
|
|
|
|
+ smBreakTable.erase(i);
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+bool ActionMap::handleEvent(const InputEvent* pEvent)
|
|
|
|
+{
|
|
|
|
+ // Interate through the ActionMapSet until we get a map that
|
|
|
|
+ // handles the event or we run out of maps...
|
|
|
|
+ //
|
|
|
|
+ SimSet* pActionMapSet = Sim::getActiveActionMapSet();
|
|
|
|
+ AssertFatal(pActionMapSet && pActionMapSet->size() != 0,
|
|
|
|
+ "error, no ActiveMapSet or no global action map...");
|
|
|
|
+
|
|
|
|
+ for (SimSet::iterator itr = pActionMapSet->end() - 1;
|
|
|
|
+ itr > pActionMapSet->begin(); itr--) {
|
|
|
|
+ ActionMap* pMap = static_cast<ActionMap*>(*itr);
|
|
|
|
+ if (pMap->processAction(pEvent) == true)
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+bool ActionMap::handleEventGlobal(const InputEvent* pEvent)
|
|
|
|
+{
|
|
|
|
+ // Interate through the ActionMapSet until we get a map that
|
|
|
|
+ // handles the event or we run out of maps...
|
|
|
|
+ //
|
|
|
|
+ SimSet* pActionMapSet = Sim::getActiveActionMapSet();
|
|
|
|
+ AssertFatal(pActionMapSet && pActionMapSet->size() != 0,
|
|
|
|
+ "error, no ActiveMapSet or no global action map...");
|
|
|
|
+
|
|
|
|
+ return ((ActionMap*)pActionMapSet->first())->processAction(pEvent);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+//-------------------------------------- Key code to string mapping
|
|
|
|
+// TODO: Add most obvious aliases...
|
|
|
|
+//
|
|
|
|
+CodeMapping gVirtualMap[] =
|
|
|
|
+{
|
|
|
|
+ //-------------------------------------- KEYBOARD EVENTS
|
|
|
|
+ //
|
|
|
|
+ { "backspace", SI_KEY, KEY_BACKSPACE },
|
|
|
|
+ { "tab", SI_KEY, KEY_TAB },
|
|
|
|
+
|
|
|
|
+ { "return", SI_KEY, KEY_RETURN },
|
|
|
|
+ { "enter", SI_KEY, KEY_RETURN },
|
|
|
|
+
|
|
|
|
+ { "shift", SI_KEY, KEY_SHIFT },
|
|
|
|
+ { "ctrl", SI_KEY, KEY_CONTROL },
|
|
|
|
+ { "alt", SI_KEY, KEY_ALT },
|
|
|
|
+ { "pause", SI_KEY, KEY_PAUSE },
|
|
|
|
+ { "capslock", SI_KEY, KEY_CAPSLOCK },
|
|
|
|
+
|
|
|
|
+ { "escape", SI_KEY, KEY_ESCAPE },
|
|
|
|
+
|
|
|
|
+ { "space", SI_KEY, KEY_SPACE },
|
|
|
|
+ { "pagedown", SI_KEY, KEY_PAGE_DOWN },
|
|
|
|
+ { "pageup", SI_KEY, KEY_PAGE_UP },
|
|
|
|
+ { "end", SI_KEY, KEY_END },
|
|
|
|
+ { "home", SI_KEY, KEY_HOME },
|
|
|
|
+ { "left", SI_KEY, KEY_LEFT },
|
|
|
|
+ { "up", SI_KEY, KEY_UP },
|
|
|
|
+ { "right", SI_KEY, KEY_RIGHT },
|
|
|
|
+ { "down", SI_KEY, KEY_DOWN },
|
|
|
|
+ { "print", SI_KEY, KEY_PRINT },
|
|
|
|
+ { "insert", SI_KEY, KEY_INSERT },
|
|
|
|
+ { "delete", SI_KEY, KEY_DELETE },
|
|
|
|
+ { "help", SI_KEY, KEY_HELP },
|
|
|
|
+
|
|
|
|
+ { "win_lwindow", SI_KEY, KEY_WIN_LWINDOW },
|
|
|
|
+ { "win_rwindow", SI_KEY, KEY_WIN_RWINDOW },
|
|
|
|
+ { "win_apps", SI_KEY, KEY_WIN_APPS },
|
|
|
|
+
|
|
|
|
+ { "cmd", SI_KEY, KEY_ALT },
|
|
|
|
+ { "opt", SI_KEY, KEY_MAC_OPT },
|
|
|
|
+ { "lopt", SI_KEY, KEY_MAC_LOPT },
|
|
|
|
+ { "ropt", SI_KEY, KEY_MAC_ROPT },
|
|
|
|
+
|
|
|
|
+ { "numpad0", SI_KEY, KEY_NUMPAD0 },
|
|
|
|
+ { "numpad1", SI_KEY, KEY_NUMPAD1 },
|
|
|
|
+ { "numpad2", SI_KEY, KEY_NUMPAD2 },
|
|
|
|
+ { "numpad3", SI_KEY, KEY_NUMPAD3 },
|
|
|
|
+ { "numpad4", SI_KEY, KEY_NUMPAD4 },
|
|
|
|
+ { "numpad5", SI_KEY, KEY_NUMPAD5 },
|
|
|
|
+ { "numpad6", SI_KEY, KEY_NUMPAD6 },
|
|
|
|
+ { "numpad7", SI_KEY, KEY_NUMPAD7 },
|
|
|
|
+ { "numpad8", SI_KEY, KEY_NUMPAD8 },
|
|
|
|
+ { "numpad9", SI_KEY, KEY_NUMPAD9 },
|
|
|
|
+ { "numpadmult", SI_KEY, KEY_MULTIPLY },
|
|
|
|
+ { "numpadadd", SI_KEY, KEY_ADD },
|
|
|
|
+ { "numpadsep", SI_KEY, KEY_SEPARATOR },
|
|
|
|
+ { "numpadminus", SI_KEY, KEY_SUBTRACT },
|
|
|
|
+ { "numpaddecimal", SI_KEY, KEY_DECIMAL },
|
|
|
|
+ { "numpaddivide", SI_KEY, KEY_DIVIDE },
|
|
|
|
+ { "numpadenter", SI_KEY, KEY_NUMPADENTER },
|
|
|
|
+
|
|
|
|
+ { "f1", SI_KEY, KEY_F1 },
|
|
|
|
+ { "f2", SI_KEY, KEY_F2 },
|
|
|
|
+ { "f3", SI_KEY, KEY_F3 },
|
|
|
|
+ { "f4", SI_KEY, KEY_F4 },
|
|
|
|
+ { "f5", SI_KEY, KEY_F5 },
|
|
|
|
+ { "f6", SI_KEY, KEY_F6 },
|
|
|
|
+ { "f7", SI_KEY, KEY_F7 },
|
|
|
|
+ { "f8", SI_KEY, KEY_F8 },
|
|
|
|
+ { "f9", SI_KEY, KEY_F9 },
|
|
|
|
+ { "f10", SI_KEY, KEY_F10 },
|
|
|
|
+ { "f11", SI_KEY, KEY_F11 },
|
|
|
|
+ { "f12", SI_KEY, KEY_F12 },
|
|
|
|
+ { "f13", SI_KEY, KEY_F13 },
|
|
|
|
+ { "f14", SI_KEY, KEY_F14 },
|
|
|
|
+ { "f15", SI_KEY, KEY_F15 },
|
|
|
|
+ { "f16", SI_KEY, KEY_F16 },
|
|
|
|
+ { "f17", SI_KEY, KEY_F17 },
|
|
|
|
+ { "f18", SI_KEY, KEY_F18 },
|
|
|
|
+ { "f19", SI_KEY, KEY_F19 },
|
|
|
|
+ { "f20", SI_KEY, KEY_F20 },
|
|
|
|
+ { "f21", SI_KEY, KEY_F21 },
|
|
|
|
+ { "f22", SI_KEY, KEY_F22 },
|
|
|
|
+ { "f23", SI_KEY, KEY_F23 },
|
|
|
|
+ { "f24", SI_KEY, KEY_F24 },
|
|
|
|
+
|
|
|
|
+ { "numlock", SI_KEY, KEY_NUMLOCK },
|
|
|
|
+ { "scrolllock", SI_KEY, KEY_SCROLLLOCK },
|
|
|
|
+
|
|
|
|
+ { "lshift", SI_KEY, KEY_LSHIFT },
|
|
|
|
+ { "rshift", SI_KEY, KEY_RSHIFT },
|
|
|
|
+ { "lcontrol", SI_KEY, KEY_LCONTROL },
|
|
|
|
+ { "rcontrol", SI_KEY, KEY_RCONTROL },
|
|
|
|
+ { "lalt", SI_KEY, KEY_LALT },
|
|
|
|
+ { "ralt", SI_KEY, KEY_RALT },
|
|
|
|
+ { "tilde", SI_KEY, KEY_TILDE },
|
|
|
|
+
|
|
|
|
+ { "minus", SI_KEY, KEY_MINUS },
|
|
|
|
+ { "equals", SI_KEY, KEY_EQUALS },
|
|
|
|
+ { "lbracket", SI_KEY, KEY_LBRACKET },
|
|
|
|
+ { "rbracket", SI_KEY, KEY_RBRACKET },
|
|
|
|
+ { "backslash", SI_KEY, KEY_BACKSLASH },
|
|
|
|
+ { "semicolon", SI_KEY, KEY_SEMICOLON },
|
|
|
|
+ { "apostrophe", SI_KEY, KEY_APOSTROPHE },
|
|
|
|
+ { "comma", SI_KEY, KEY_COMMA },
|
|
|
|
+ { "period", SI_KEY, KEY_PERIOD },
|
|
|
|
+ { "slash", SI_KEY, KEY_SLASH },
|
|
|
|
+ { "lessthan", SI_KEY, KEY_OEM_102 },
|
|
|
|
+
|
|
|
|
+ //-------------------------------------- BUTTON EVENTS
|
|
|
|
+ // Joystick/Mouse buttons
|
|
|
|
+ { "button0", SI_BUTTON, KEY_BUTTON0 },
|
|
|
|
+ { "button1", SI_BUTTON, KEY_BUTTON1 },
|
|
|
|
+ { "button2", SI_BUTTON, KEY_BUTTON2 },
|
|
|
|
+ { "button3", SI_BUTTON, KEY_BUTTON3 },
|
|
|
|
+ { "button4", SI_BUTTON, KEY_BUTTON4 },
|
|
|
|
+ { "button5", SI_BUTTON, KEY_BUTTON5 },
|
|
|
|
+ { "button6", SI_BUTTON, KEY_BUTTON6 },
|
|
|
|
+ { "button7", SI_BUTTON, KEY_BUTTON7 },
|
|
|
|
+ { "button8", SI_BUTTON, KEY_BUTTON8 },
|
|
|
|
+ { "button9", SI_BUTTON, KEY_BUTTON9 },
|
|
|
|
+ { "button10", SI_BUTTON, KEY_BUTTON10 },
|
|
|
|
+ { "button11", SI_BUTTON, KEY_BUTTON11 },
|
|
|
|
+ { "button12", SI_BUTTON, KEY_BUTTON12 },
|
|
|
|
+ { "button13", SI_BUTTON, KEY_BUTTON13 },
|
|
|
|
+ { "button14", SI_BUTTON, KEY_BUTTON14 },
|
|
|
|
+ { "button15", SI_BUTTON, KEY_BUTTON15 },
|
|
|
|
+ { "button16", SI_BUTTON, KEY_BUTTON16 },
|
|
|
|
+ { "button17", SI_BUTTON, KEY_BUTTON17 },
|
|
|
|
+ { "button18", SI_BUTTON, KEY_BUTTON18 },
|
|
|
|
+ { "button19", SI_BUTTON, KEY_BUTTON19 },
|
|
|
|
+ { "button20", SI_BUTTON, KEY_BUTTON20 },
|
|
|
|
+ { "button21", SI_BUTTON, KEY_BUTTON21 },
|
|
|
|
+ { "button22", SI_BUTTON, KEY_BUTTON22 },
|
|
|
|
+ { "button23", SI_BUTTON, KEY_BUTTON23 },
|
|
|
|
+ { "button24", SI_BUTTON, KEY_BUTTON24 },
|
|
|
|
+ { "button25", SI_BUTTON, KEY_BUTTON25 },
|
|
|
|
+ { "button26", SI_BUTTON, KEY_BUTTON26 },
|
|
|
|
+ { "button27", SI_BUTTON, KEY_BUTTON27 },
|
|
|
|
+ { "button28", SI_BUTTON, KEY_BUTTON28 },
|
|
|
|
+ { "button29", SI_BUTTON, KEY_BUTTON29 },
|
|
|
|
+ { "button30", SI_BUTTON, KEY_BUTTON30 },
|
|
|
|
+ { "button31", SI_BUTTON, KEY_BUTTON31 },
|
|
|
|
+
|
|
|
|
+ //-------------------------------------- MOVE EVENTS
|
|
|
|
+ // Mouse/Joystick axes:
|
|
|
|
+ { "xaxis", SI_MOVE, SI_XAXIS },
|
|
|
|
+ { "yaxis", SI_MOVE, SI_YAXIS },
|
|
|
|
+ { "zaxis", SI_MOVE, SI_ZAXIS },
|
|
|
|
+ { "rxaxis", SI_MOVE, SI_RXAXIS },
|
|
|
|
+ { "ryaxis", SI_MOVE, SI_RYAXIS },
|
|
|
|
+ { "rzaxis", SI_MOVE, SI_RZAXIS },
|
|
|
|
+ { "slider", SI_MOVE, SI_SLIDER },
|
|
|
|
+
|
|
|
|
+ //-------------------------------------- POV EVENTS
|
|
|
|
+ // Joystick POV:
|
|
|
|
+ { "xpov", SI_POV, SI_XPOV },
|
|
|
|
+ { "ypov", SI_POV, SI_YPOV },
|
|
|
|
+ { "upov", SI_POV, SI_UPOV },
|
|
|
|
+ { "dpov", SI_POV, SI_DPOV },
|
|
|
|
+ { "lpov", SI_POV, SI_LPOV },
|
|
|
|
+ { "rpov", SI_POV, SI_RPOV },
|
|
|
|
+ { "xpov2", SI_POV, SI_XPOV2 },
|
|
|
|
+ { "ypov2", SI_POV, SI_YPOV2 },
|
|
|
|
+ { "upov2", SI_POV, SI_UPOV2 },
|
|
|
|
+ { "dpov2", SI_POV, SI_DPOV2 },
|
|
|
|
+ { "lpov2", SI_POV, SI_LPOV2 },
|
|
|
|
+ { "rpov2", SI_POV, SI_RPOV2 },
|
|
|
|
+
|
|
|
|
+ #if defined( TORQUE_OS_WIN32 ) || defined( TORQUE_OS_XENON )
|
|
|
|
+ //-------------------------------------- XINPUT EVENTS
|
|
|
|
+ // Controller connect / disconnect:
|
|
|
|
+ { "connect", XI_BUTTON, XI_CONNECT },
|
|
|
|
+
|
|
|
|
+ // L & R Thumbsticks:
|
|
|
|
+ { "thumblx", XI_AXIS, XI_THUMBLX },
|
|
|
|
+ { "thumbly", XI_AXIS, XI_THUMBLY },
|
|
|
|
+ { "thumbrx", XI_AXIS, XI_THUMBRX },
|
|
|
|
+ { "thumbry", XI_AXIS, XI_THUMBRY },
|
|
|
|
+
|
|
|
|
+ // L & R Triggers:
|
|
|
|
+ { "triggerl", XI_AXIS, XI_LEFT_TRIGGER },
|
|
|
|
+ { "triggerr", XI_AXIS, XI_RIGHT_TRIGGER },
|
|
|
|
+
|
|
|
|
+ // DPAD Buttons:
|
|
|
|
+ { "dpadu", XI_BUTTON, SI_UPOV },
|
|
|
|
+ { "dpadd", XI_BUTTON, SI_DPOV },
|
|
|
|
+ { "dpadl", XI_BUTTON, SI_LPOV },
|
|
|
|
+ { "dpadr", XI_BUTTON, SI_RPOV },
|
|
|
|
+
|
|
|
|
+ // START & BACK Buttons:
|
|
|
|
+ { "btn_start", XI_BUTTON, XI_START },
|
|
|
|
+ { "btn_back", XI_BUTTON, XI_BACK },
|
|
|
|
+
|
|
|
|
+ // L & R Thumbstick Buttons:
|
|
|
|
+ { "btn_lt", XI_BUTTON, XI_LEFT_THUMB },
|
|
|
|
+ { "btn_rt", XI_BUTTON, XI_RIGHT_THUMB },
|
|
|
|
+
|
|
|
|
+ // L & R Shoulder Buttons:
|
|
|
|
+ { "btn_l", XI_BUTTON, XI_LEFT_SHOULDER },
|
|
|
|
+ { "btn_r", XI_BUTTON, XI_RIGHT_SHOULDER },
|
|
|
|
+
|
|
|
|
+ // Primary buttons:
|
|
|
|
+ { "btn_a", XI_BUTTON, XI_A },
|
|
|
|
+ { "btn_b", XI_BUTTON, XI_B },
|
|
|
|
+ { "btn_x", XI_BUTTON, XI_X },
|
|
|
|
+ { "btn_y", XI_BUTTON, XI_Y },
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ //-------------------------------------- MOTION EVENTS
|
|
|
|
+ // Accelerometer/Gyroscope axes:
|
|
|
|
+ { "accelx", SI_MOTION, SI_ACCELX },
|
|
|
|
+ { "accely", SI_MOTION, SI_ACCELY },
|
|
|
|
+ { "accelz", SI_MOTION, SI_ACCELZ },
|
|
|
|
+ { "gravityx", SI_MOTION, SI_GRAVX },
|
|
|
|
+ { "gravityy", SI_MOTION, SI_GRAVY },
|
|
|
|
+ { "gravityz", SI_MOTION, SI_GRAVZ },
|
|
|
|
+ { "gyrox", SI_MOTION, SI_GYROX },
|
|
|
|
+ { "gyroy", SI_MOTION, SI_GYROY },
|
|
|
|
+ { "gyroz", SI_MOTION, SI_GYROZ },
|
|
|
|
+ { "yaw", SI_MOTION, SI_YAW },
|
|
|
|
+ { "pitch", SI_MOTION, SI_PITCH },
|
|
|
|
+ { "roll", SI_MOTION, SI_ROLL },
|
|
|
|
+
|
|
|
|
+ //-------------------------------------- TOUCH EVENTS
|
|
|
|
+ // Touch events:
|
|
|
|
+ { "touchdown", SI_TOUCH, SI_TOUCHDOWN },
|
|
|
|
+ { "touchup", SI_TOUCH, SI_TOUCHUP },
|
|
|
|
+ { "touchmove", SI_TOUCH, SI_TOUCHMOVE },
|
|
|
|
+
|
|
|
|
+ //-------------------------------------- GESTURE EVENTS
|
|
|
|
+ // Preset gesture events:
|
|
|
|
+ { "circleGesture", SI_GESTURE, SI_CIRCLE_GESTURE },
|
|
|
|
+ { "swipeGesture", SI_GESTURE, SI_SWIPE_GESTURE },
|
|
|
|
+ { "screenTapGesture", SI_GESTURE, SI_SCREENTAP_GESTURE },
|
|
|
|
+ { "keyTapGesture", SI_GESTURE, SI_KEYTAP_GESTURE },
|
|
|
|
+ { "pinchGesture", SI_GESTURE, SI_PINCH_GESTURE },
|
|
|
|
+ { "scaleGesture", SI_GESTURE, SI_SCALE_GESTURE },
|
|
|
|
+
|
|
|
|
+ //-------------------------------------- GESTURE EVENTS
|
|
|
|
+ // Preset gesture events:
|
|
|
|
+ { "leapHandAxis", SI_LEAP, LM_HANDAXIS },
|
|
|
|
+ { "leapHandPos", SI_LEAP, LM_HANDPOS },
|
|
|
|
+ { "leapHandRot", SI_LEAP, LM_HANDROT },
|
|
|
|
+ { "leapFingerPos", SI_LEAP, LM_FINGERPOS },
|
|
|
|
+
|
|
|
|
+ //-------------------------------------- MISCELLANEOUS EVENTS
|
|
|
|
+ //
|
|
|
|
+ { "anykey", SI_KEY, KEY_ANYKEY },
|
|
|
|
+ { "nomatch", SI_UNKNOWN, 0xFFFFFFFF }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+AsciiMapping gAsciiMap[] =
|
|
|
|
+{
|
|
|
|
+ //--- KEYBOARD EVENTS
|
|
|
|
+ //
|
|
|
|
+ { "space", 0x0020 },
|
|
|
|
+ //{ "exclamation", 0x0021 },
|
|
|
|
+ { "doublequote", 0x0022 },
|
|
|
|
+ //{ "pound", 0x0023 },
|
|
|
|
+ //{ "ampersand", 0x0026 },
|
|
|
|
+ { "apostrophe", 0x0027 },
|
|
|
|
+ //{ "lparen", 0x0028 },
|
|
|
|
+ //{ "rparen", 0x0029 },
|
|
|
|
+ { "comma", 0x002c },
|
|
|
|
+ { "minus", 0x002d },
|
|
|
|
+ { "period", 0x002e },
|
|
|
|
+ //{ "slash", 0x002f },
|
|
|
|
+ //{ "colon", 0x003a },
|
|
|
|
+ //{ "semicolon", 0x003b },
|
|
|
|
+ //{ "lessthan", 0x003c },
|
|
|
|
+ //{ "equals", 0x003d },
|
|
|
|
+ //{ "morethan", 0x003e },
|
|
|
|
+ //{ "lbracket", 0x005b },
|
|
|
|
+ { "backslash", 0x005c },
|
|
|
|
+ //{ "rbracket", 0x005d },
|
|
|
|
+ //{ "circumflex", 0x005e },
|
|
|
|
+ //{ "underscore", 0x005f },
|
|
|
|
+ { "grave", 0x0060 },
|
|
|
|
+ //{ "tilde", 0x007e },
|
|
|
|
+ //{ "vertbar", 0x007c },
|
|
|
|
+ //{ "exclamdown", 0x00a1 },
|
|
|
|
+ //{ "cent", 0x00a2 },
|
|
|
|
+ //{ "sterling", 0x00a3 },
|
|
|
|
+ //{ "currency", 0x00a4 },
|
|
|
|
+ //{ "brokenbar", 0x00a6 },
|
|
|
|
+ //{ "ring", 0x00b0 },
|
|
|
|
+ //{ "plusminus", 0x00b1 },
|
|
|
|
+ { "super2", 0x00b2 },
|
|
|
|
+ { "super3", 0x00b3 },
|
|
|
|
+ { "acute", 0x00b4 },
|
|
|
|
+ //{ "mu", 0x00b5 },
|
|
|
|
+ //{ "ordmasculine", 0x00ba },
|
|
|
|
+ //{ "questiondown", 0x00bf },
|
|
|
|
+ //{ "gemandbls", 0x00df },
|
|
|
|
+ //{ "agrave", 0x00e0 },
|
|
|
|
+ //{ "aacute", 0x00e1 },
|
|
|
|
+ //{ "acircumflex", 0x00e2 },
|
|
|
|
+ //{ "atilde", 0x00e3 },
|
|
|
|
+ //{ "adieresis", 0x00e4 },
|
|
|
|
+ //{ "aring", 0x00e5 },
|
|
|
|
+ //{ "ae", 0x00e6 },
|
|
|
|
+ //{ "ccedille", 0x00e7 },
|
|
|
|
+ //{ "egrave", 0x00e8 },
|
|
|
|
+ //{ "eacute", 0x00e9 },
|
|
|
|
+ //{ "ecircumflex", 0x00ea },
|
|
|
|
+ //{ "edieresis", 0x00eb },
|
|
|
|
+ //{ "igrave", 0x00ec },
|
|
|
|
+ //{ "iacute", 0x00ed },
|
|
|
|
+ //{ "icircumflex", 0x00ee },
|
|
|
|
+ //{ "idieresis", 0x00ef },
|
|
|
|
+ //{ "ntilde", 0x00f1 },
|
|
|
|
+ //{ "ograve", 0x00f2 },
|
|
|
|
+ //{ "oacute", 0x00f3 },
|
|
|
|
+ //{ "ocircumflex", 0x00f4 },
|
|
|
|
+ //{ "otilde", 0x00f5 },
|
|
|
|
+ //{ "odieresis", 0x00f6 },
|
|
|
|
+ //{ "divide", 0x00f7 },
|
|
|
|
+ //{ "oslash", 0x00f8 },
|
|
|
|
+ //{ "ugrave", 0x00f9 },
|
|
|
|
+ //{ "uacute", 0x00fa },
|
|
|
|
+ //{ "ucircumflex", 0x00fb },
|
|
|
|
+ //{ "udieresis", 0x00fc },
|
|
|
|
+ //{ "ygrave", 0x00fd },
|
|
|
|
+ //{ "thorn", 0x00fe },
|
|
|
|
+ //{ "ydieresis", 0x00ff },
|
|
|
|
+ { "nomatch", 0xFFFF }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+////Device Event Types
|
|
|
|
+//#define SI_UNKNOWN 0x01
|
|
|
|
+//#define SI_BUTTON 0x02
|
|
|
|
+//#define SI_POV 0x03
|
|
|
|
+//#define SI_XPOV 0x04
|
|
|
|
+//#define SI_YPOV 0x05
|
|
|
|
+//#define SI_UPOV 0x06
|
|
|
|
+//#define SI_DPOV 0x07
|
|
|
|
+//#define SI_LPOV 0x08
|
|
|
|
+//#define SI_RPOV 0x09
|
|
|
|
+//#define SI_KEY 0x0A
|
|
|
|
+//#define SI_XAXIS 0x0B
|
|
|
|
+//#define SI_YAXIS 0x0C
|
|
|
|
+//#define SI_ZAXIS 0x0D
|
|
|
|
+//#define SI_RXAXIS 0x0E
|
|
|
|
+//#define SI_RYAXIS 0x0F
|
|
|
|
+//#define SI_RZAXIS 0x10
|
|
|
|
+//#define SI_SLIDER 0x11
|