/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Additional permissions under GNU GPL version 3 section 7 If you modify this Program, or any covered work, by linking or combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK (or a modified version of those libraries), containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the licensors of this Program grant you additional permission to convey the resulting work. Corresponding Source for a non-source form of such a combination shall include the source code for the parts of OpenSSL and IJG JPEG Library used as well as that of the covered work. You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ // plInputDevice.cpp #include "STRING" #include "plInputMap.h" #include "plKeyMap.h" #include "hsUtils.h" #include "../plResMgr/plLocalization.h" ControlEventCode plInputMap::ConvertCharToControlCode(const char* c) { for (int i = 0; fCmdConvert[i].fCode != END_CONTROLS; i++) { if (stricmp(fCmdConvert[i].fDesc, c) == 0) return (fCmdConvert[i].fCode); } return (END_CONTROLS); } const char *plInputMap::ConvertControlCodeToString( ControlEventCode code ) { for( int i = 0; fCmdConvert[ i ].fCode != END_CONTROLS; i++ ) { if( fCmdConvert[ i ].fCode == code ) return fCmdConvert[ i ].fDesc; } return nil; } // // plMouseMap // plMouseMap::~plMouseMap() { for (int i = 0; i < fMap.Count(); i++) delete(fMap[i]); fMap.SetCountAndZero(0); } int plMouseMap::AddMapping(plMouseInfo* pNfo) { for (int i = 0; i < fMap.Count(); i++) { if (fMap[i] == pNfo) return -1; } fMap.Append(pNfo); return (fMap.Count() - 1); } //// plKeyBinding and Smaller Classes //////////////////////////////////////// plKeyCombo::plKeyCombo() { fKey = KEY_UNMAPPED; fFlags = 0; } hsBool plKeyCombo::IsSatisfiedBy(const plKeyCombo &combo) const { if (fKey != combo.fKey) return false; if ((fFlags & kShift) && !(combo.fFlags & kShift)) return false; if ((fFlags & kCtrl) && !(combo.fFlags & kCtrl)) return false; return true; } // Handy konstant for plKeyCombos plKeyCombo plKeyCombo::kUnmapped = plKeyCombo( KEY_UNMAPPED, 0 ); plKeyBinding::plKeyBinding() { fCode = END_CONTROLS; fCodeFlags = 0; fKey1 = plKeyCombo::kUnmapped; fKey2 = plKeyCombo::kUnmapped; fString = nil; } plKeyBinding::plKeyBinding( ControlEventCode code, UInt32 codeFlags, const plKeyCombo &key1, const plKeyCombo &key2, const char *string /*= nil*/ ) { fCode = code; fCodeFlags = codeFlags; fKey1 = key1; fKey2 = key2; fString = ( string == nil ) ? nil : hsStrcpy( string ); } plKeyBinding::~plKeyBinding() { delete [] fString; } const plKeyCombo &plKeyBinding::GetMatchingKey( plKeyDef keyDef ) const { if (fKey1.fKey == keyDef) return fKey1; if (fKey2.fKey == keyDef) return fKey2; return plKeyCombo::kUnmapped; } void plKeyBinding::SetKey1( const plKeyCombo &newCombo ) { fKey1 = newCombo; } void plKeyBinding::SetKey2( const plKeyCombo &newCombo ) { fKey2 = newCombo; } void plKeyBinding::ClearKeys( void ) { fKey1 = fKey2 = plKeyCombo::kUnmapped; } hsBool plKeyBinding::HasUnmappedKey() const { return fKey1.fKey == KEY_UNMAPPED || fKey2.fKey == KEY_UNMAPPED; } ////////////////////////////////////////////////////////////////////////////// //// plKeyMap Implementation ///////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// plKeyMap::plKeyMap() { } plKeyMap::~plKeyMap() { ClearAll(); } void plKeyMap::ClearAll( void ) { UInt32 i; for( i = 0; i < fBindings.GetCount(); i++ ) delete fBindings[ i ]; fBindings.Reset(); } //// AddCode ////////////////////////////////////////////////////////////////////////// // Adds a given control code to the map. Once you add it, you can't change its flags. // Returns false if the code is already present hsBool plKeyMap::AddCode( ControlEventCode code, UInt32 codeFlags ) { if( IFindBinding( code ) != nil ) return false; fBindings.Append( TRACKED_NEW plKeyBinding( code, codeFlags, plKeyCombo::kUnmapped, plKeyCombo::kUnmapped ) ); return true; } //// AddConsoleCommand /////////////////////////////////////////////////////// // Same but for console commands. No flags b/c console commands always use // the same flags. hsBool plKeyMap::AddConsoleCommand( const char *command ) { if( IFindConsoleBinding( command ) != nil ) return false; fBindings.Append( TRACKED_NEW plKeyBinding( B_CONTROL_CONSOLE_COMMAND, kControlFlagDownEvent | kControlFlagNoRepeat | kControlFlagNoDeactivate, plKeyCombo::kUnmapped, plKeyCombo::kUnmapped, command ) ); return true; } //// IFindBinding //////////////////////////////////////////////////////////// // Find the binding for a given code. plKeyBinding *plKeyMap::IFindBinding( ControlEventCode code ) const { UInt32 i; for( i = 0; i < fBindings.GetCount(); i++ ) { if( fBindings[ i ]->GetCode() == code ) return fBindings[ i ]; } return nil; } //// IFindBindingByKey /////////////////////////////////////////////////////// // Find the binding for a given key. plKeyBinding *plKeyMap::IFindBindingByKey( const plKeyCombo &combo ) const { UInt32 i; for( i = 0; i < fBindings.GetCount(); i++ ) { if( fBindings[ i ]->GetKey1() == combo || fBindings[ i ]->GetKey2() == combo ) return fBindings[ i ]; } return nil; } // Find ALL bindings that could be triggered by this combo. Meaning that if we have multiple // bindings for a key with different shift/ctrl combinations, we want any that are satisfied with // the given combo. // We guarantee that the first binding in the result array is that one with priority. void plKeyMap::IFindAllBindingsByKey(const plKeyCombo &combo, hsTArray &result) const { UInt32 i; UInt8 bestScore = 0; for (i = 0; i < fBindings.GetCount(); i++) { hsBool s1, s2; s1 = fBindings[i]->GetKey1().IsSatisfiedBy(combo); s2 = fBindings[i]->GetKey2().IsSatisfiedBy(combo); if (s1 || s2) { UInt8 myScore = 0; if (s1) myScore = fBindings[i]->GetKey1().fFlags; if (s2 && (fBindings[i]->GetKey2().fFlags > myScore)) myScore = fBindings[i]->GetKey2().fFlags; if (myScore >= bestScore) result.Insert(0, fBindings[i]); else result.Append(fBindings[i]); } } } //// IFindConsoleBinding ///////////////////////////////////////////////////// // You should be able to figure this out by now. plKeyBinding *plKeyMap::IFindConsoleBinding( const char *command ) const { UInt32 i; for( i = 0; i < fBindings.GetCount(); i++ ) { if( fBindings[ i ]->GetCode() == B_CONTROL_CONSOLE_COMMAND ) { if( stricmp( fBindings[ i ]->GetExtendedString(), command ) == 0 ) return fBindings[ i ]; } } return nil; } //// IActuallyBind /////////////////////////////////////////////////////////// // Does the nitty gritty of binding by pref void plKeyMap::IActuallyBind( plKeyBinding *binding, const plKeyCombo &combo, BindPref pref ) { // Bind according to preference switch( pref ) { case kNoPreference: // Pick a free slot, or 1st one if none if( binding->GetKey1() == plKeyCombo::kUnmapped ) binding->SetKey1( combo ); else if( binding->GetKey2() == plKeyCombo::kUnmapped ) binding->SetKey2( combo ); else binding->SetKey1( combo ); break; case kNoPreference2nd: // Pick a free slot, or 2nd one if none if( binding->GetKey1() == plKeyCombo::kUnmapped ) binding->SetKey1( combo ); else if( binding->GetKey2() == plKeyCombo::kUnmapped ) binding->SetKey2( combo ); else binding->SetKey2( combo ); break; case kFirstAlways: // Always bind to the first key binding->SetKey1( combo ); break; case kSecondAlways: // You get the idea binding->SetKey2( combo ); break; default: hsAssert( false, "Invalid bind preference in IActuallyBind()" ); } } //// BindKey ///////////////////////////////////////////////////////////////// // Adds a key binding to a given code. Returns false if the code isn't in // this map or if key is already mapped. hsBool plKeyMap::BindKey( const plKeyCombo &combo, ControlEventCode code, BindPref pref /*= kNoPreference*/ ) { plKeyBinding* binding = nil; // Control combos are ok. Binding directly to control is not. if ( combo.fKey == KEY_CTRL ) return false; // unless we are bindind to unmappped... if ( combo.fKey != KEY_UNMAPPED) { // Make sure key isn't already used binding = IFindBindingByKey( combo ); if( binding != nil ) return false; } // Get binding for this code binding = IFindBinding( code ); if( binding == nil ) return false; IActuallyBind( binding, combo, pref ); return true; } //// BindKeyToConsoleCmd ///////////////////////////////////////////////////// // Console command version hsBool plKeyMap::BindKeyToConsoleCmd( const plKeyCombo &combo, const char *command, BindPref pref /*= kNoPreference*/ ) { plKeyBinding* binding = nil; // Control combos are ok. Binding directly to control is not. if ( combo.fKey == KEY_CTRL ) return false; // unless we are bindind to unmappped... if ( combo.fKey != KEY_UNMAPPED) { // Make sure key isn't already used binding = IFindBindingByKey( combo ); if( binding != nil ) return false; } // Get binding for this code binding = IFindConsoleBinding( command ); if( binding == nil ) return false; IActuallyBind( binding, combo, pref ); return true; } //// FindBinding ///////////////////////////////////////////////////////////// // Searches for the binding for a given code. Returns nil if not found const plKeyBinding *plKeyMap::FindBinding( ControlEventCode code ) const { return IFindBinding( code ); } //// FindBindingByKey //////////////////////////////////////////////////////// // Same thing but by key const plKeyBinding *plKeyMap::FindBindingByKey( const plKeyCombo &combo ) const { return IFindBindingByKey( combo ); } // Same thing, but returns multiple matches (see IFindAllBindingsByKey) void plKeyMap::FindAllBindingsByKey( const plKeyCombo &combo, hsTArray &result ) const { hsTArray bindings; IFindAllBindingsByKey( combo, bindings ); int i; for (i = 0; i < bindings.GetCount(); i++) result.Append(bindings[i]); } const plKeyBinding* plKeyMap::FindConsoleBinding( const char *command ) const { return IFindConsoleBinding(command); } //// EnsureKeysClear ///////////////////////////////////////////////////////// // Basically UnmapKey(), but for two keys at once and won't assert if you // give it unmapped keys void plKeyMap::EnsureKeysClear( const plKeyCombo &key1, const plKeyCombo &key2 ) { if( key1 != plKeyCombo::kUnmapped ) UnmapKey( key1 ); if( key2 != plKeyCombo::kUnmapped ) UnmapKey( key2 ); } //// UnmapKey //////////////////////////////////////////////////////////////// // Unmaps the given key, no matter what binding it is in void plKeyMap::UnmapKey( const plKeyCombo &combo ) { if( combo == plKeyCombo::kUnmapped ) { hsAssert( false, "Trying to unbind invalid key" ); return; } plKeyBinding *binding; // Just in case we're in multiple bindings, even tho we are guarding against // that while( ( binding = IFindBindingByKey( combo ) ) != nil ) { if( binding->GetKey1() == combo ) binding->SetKey1( plKeyCombo::kUnmapped ); if( binding->GetKey2() == combo ) binding->SetKey2( plKeyCombo::kUnmapped ); } } //// UnmapBinding //////////////////////////////////////////////////////////// // Unmaps the keys for a single binding void plKeyMap::UnmapBinding( ControlEventCode code ) { plKeyBinding *binding = IFindBinding( code ); if( binding != nil ) binding->ClearKeys(); } //// UnmapAllBindings //////////////////////////////////////////////////////// // Unmaps all the bindings, but leaves the code records themselves void plKeyMap::UnmapAllBindings( void ) { UInt32 i; for( i = 0; i < fBindings.GetCount(); i++ ) fBindings[ i ]->ClearKeys(); } //// EraseBinding //////////////////////////////////////////////////////////// // Erases the given code binding. Note: should never really be used, but // provided here for completeness void plKeyMap::EraseBinding( ControlEventCode code ) { UInt32 i; for( i = 0; i < fBindings.GetCount(); i++ ) { if( fBindings[ i ]->GetCode() == code ) { delete fBindings[ i ]; fBindings.Remove( i ); return; } } } char* plKeyMap::ConvertVKeyToChar( UInt32 vk ) { Win32keyConvert* keyConvert = &fKeyConversionEnglish[0]; switch (plLocalization::GetLanguage()) { case plLocalization::kFrench: keyConvert = &fKeyConversionFrench[0]; break; case plLocalization::kGerman: keyConvert = &fKeyConversionGerman[0]; break; // case plLocalization::kSpanish: // keyConvert = &fKeyConversionSpanish[0]; // break; // case plLocalization::kItalian: // keyConvert = &fKeyConversionItalian[0]; // break; // default is English } for (int i = 0; keyConvert[i].fVKey != 0xffffffff; i++) { if (keyConvert[i].fVKey == vk) return (keyConvert[i].fKeyName); } return nil; } plKeyDef plKeyMap::ConvertCharToVKey( const char *c ) { Win32keyConvert* keyConvert = &fKeyConversionEnglish[0]; switch (plLocalization::GetLanguage()) { case plLocalization::kFrench: keyConvert = &fKeyConversionFrench[0]; break; case plLocalization::kGerman: keyConvert = &fKeyConversionGerman[0]; break; // case plLocalization::kSpanish: // keyConvert = &fKeyConversionSpanish[0]; // break; // case plLocalization::kItalian: // keyConvert = &fKeyConversionItalian[0]; // break; // default is English } for (int i = 0; keyConvert[i].fVKey != 0xffffffff; i++) { if (stricmp(keyConvert[i].fKeyName, c) == 0) return (plKeyDef)(keyConvert[i].fVKey); } // Is it just a single character? if( isalnum( *c ) && strlen( c ) == 1 ) return (plKeyDef)toupper( *c ); // if we didn't find anything yet... // ...then look thru all the other language mappings that we know about, // ...just in case they keep switching languages on us if ( plLocalization::GetLanguage() != plLocalization::kEnglish) { for (int i = 0; fKeyConversionEnglish[i].fVKey != 0xffffffff; i++) { if (stricmp(fKeyConversionEnglish[i].fKeyName, c) == 0) return (plKeyDef)(fKeyConversionEnglish[i].fVKey); } } if ( plLocalization::GetLanguage() != plLocalization::kFrench) { for (int i = 0; fKeyConversionFrench[i].fVKey != 0xffffffff; i++) { if (stricmp(fKeyConversionFrench[i].fKeyName, c) == 0) return (plKeyDef)(fKeyConversionFrench[i].fVKey); } } if ( plLocalization::GetLanguage() != plLocalization::kGerman) { for (int i = 0; fKeyConversionGerman[i].fVKey != 0xffffffff; i++) { if (stricmp(fKeyConversionGerman[i].fKeyName, c) == 0) return (plKeyDef)(fKeyConversionGerman[i].fVKey); } } /* if ( plLocalization::GetLanguage() != plLocalization::kSpanish) { for (int i = 0; fKeyConversionSpanish[i].fVKey != 0xffffffff; i++) { if (stricmp(fKeyConversionSpanish[i].fKeyName, c) == 0) return (plKeyDef)(fKeyConversionSpanish[i].fVKey); } } if ( plLocalization::GetLanguage() != plLocalization::kItalian) { for (int i = 0; fKeyConversionItalian[i].fVKey != 0xffffffff; i++) { if (stricmp(fKeyConversionItalian[i].fKeyName, c) == 0) return (plKeyDef)(fKeyConversionItalian[i].fVKey); } } */ // finally, just give up... unmapped! return KEY_UNMAPPED; } const char* plKeyMap::GetStringCtrl() { switch (plLocalization::GetLanguage()) { case plLocalization::kFrench: return "Ctrl+"; break; case plLocalization::kGerman: return "Strg+"; break; /* case plLocalization::kSpanish: return "Ctrl+"; break; case plLocalization::kItalian: return "Ctrl+"; break; */ // default is English } return "Ctrl+"; } const char* plKeyMap::GetStringShift() { switch (plLocalization::GetLanguage()) { case plLocalization::kFrench: return "Maj+"; break; case plLocalization::kGerman: return "Umschalt+"; break; /* case plLocalization::kSpanish: return "Mayúsculas+"; break; case plLocalization::kItalian: return "Shift+"; break; */ // default is English } return "Shift+"; } const char* plKeyMap::GetStringUnmapped() { switch (plLocalization::GetLanguage()) { case plLocalization::kFrench: return "(NonDéfini)"; break; case plLocalization::kGerman: return "(NichtZugewiesen)"; break; /* case plLocalization::kSpanish: return "(SinMapear)"; break; case plLocalization::kItalian: return "(NonAssegnato)"; break; */ // default is English } return "(unmapped)"; } // If the binding has one of these keys, but not the other, go and bind the other // (if there's an unmapped space for it). void plKeyMap::HandleAutoDualBinding(plKeyDef key1, plKeyDef key2) { ICheckAndBindDupe(key1, key2); ICheckAndBindDupe(key2, key1); } void plKeyMap::ICheckAndBindDupe(plKeyDef origKey, plKeyDef dupeKey) { hsTArray bindings; plKeyCombo combo; combo.fKey = origKey; IFindAllBindingsByKey(combo, bindings); int i; for (i = 0; i < bindings.GetCount(); i++) { plKeyBinding *binding = bindings[i]; if (binding->HasUnmappedKey()) { combo = binding->GetMatchingKey(origKey); combo.fKey = dupeKey; if (IFindBindingByKey(combo) == nil) IActuallyBind(binding, combo, kNoPreference); } } } Win32keyConvert plKeyMap::fKeyConversionEnglish[] = { { VK_F1, "F1"}, { VK_F2, "F2"}, { VK_F3, "F3"}, { VK_F4, "F4"}, { VK_F5, "F5"}, { VK_F6, "F6"}, { VK_F7, "F7"}, { VK_F8, "F8"}, { VK_F9, "F9"}, { VK_F10, "F10"}, { VK_F11, "F11"}, { VK_F12, "F12"}, { VK_ESCAPE, "Esc"}, { VK_TAB, "Tab"}, { VK_UP, "UpArrow"}, { VK_DOWN, "DownArrow"}, { VK_LEFT, "LeftArrow"}, { VK_RIGHT, "RightArrow"}, { VK_BACK, "Backspace"}, { VK_RETURN, "Enter"}, { VK_PAUSE, "Pause"}, { VK_CAPITAL, "CapsLock"}, { VK_PRIOR, "PageUp"}, { VK_NEXT, "PageDn"}, { VK_END, "End"}, { VK_HOME, "Home"}, { VK_SNAPSHOT, "PrintScrn"}, { VK_INSERT, "Insert"}, { VK_DELETE, "Delete"}, { VK_NUMPAD0, "NumPad0"}, { VK_NUMPAD1, "NumPad1"}, { VK_NUMPAD2, "NumPad2"}, { VK_NUMPAD3, "NumPad3"}, { VK_NUMPAD4, "NumPad4"}, { VK_NUMPAD5, "NumPad5"}, { VK_NUMPAD6, "NumPad6"}, { VK_NUMPAD7, "NumPad7"}, { VK_NUMPAD8, "NumPad8"}, { VK_NUMPAD9, "NumPad9"}, { VK_MULTIPLY, "NumPad*"}, { VK_ADD, "NumPad+"}, { VK_SUBTRACT, "NumPad-"}, { VK_DECIMAL, "NumPad."}, { VK_DIVIDE, "NumPad/"}, { VK_SPACE, "SpaceBar"}, { VK_OEM_COMMA, "Comma"}, { VK_OEM_PERIOD,"Period"}, { VK_OEM_MINUS, "Minus"}, { VK_OEM_PLUS, "Plus"}, { VK_SHIFT, "Shift" }, // not valid outside USA { VK_OEM_1, "Semicolon"}, { VK_OEM_2, "ForewardSlash"}, { VK_OEM_3, "Tilde"}, { VK_OEM_4, "LeftBracket"}, { VK_OEM_5, "Backslash"}, { VK_OEM_6, "RightBracket"}, { VK_OEM_7, "Quote"}, { 0xffffffff, "Unused"}, }; Win32keyConvert plKeyMap::fKeyConversionFrench[] = { { VK_F1, "F1"}, { VK_F2, "F2"}, { VK_F3, "F3"}, { VK_F4, "F4"}, { VK_F5, "F5"}, { VK_F6, "F6"}, { VK_F7, "F7"}, { VK_F8, "F8"}, { VK_F9, "F9"}, { VK_F10, "F10"}, { VK_F11, "F11"}, { VK_F12, "F12"}, { VK_ESCAPE, "Échap"}, { VK_TAB, "Tab"}, { VK_UP, "FlècheHaut"}, { VK_DOWN, "FlècheBas"}, { VK_LEFT, "FlècheGauche"}, { VK_RIGHT, "FlècheDroite"}, { VK_BACK, "Retour"}, { VK_RETURN, "Entrée"}, { VK_PAUSE, "Pause"}, { VK_CAPITAL, "CapsLock"}, { VK_PRIOR, "PagePréc"}, { VK_NEXT, "PageSuiv"}, { VK_END, "Fin"}, { VK_HOME, "Origine"}, { VK_SNAPSHOT, "ImprÉcran"}, { VK_INSERT, "Inser"}, { VK_DELETE, "Suppr"}, { VK_NUMPAD0, "PavNum0"}, { VK_NUMPAD1, "PavNum1"}, { VK_NUMPAD2, "PavNum2"}, { VK_NUMPAD3, "PavNum3"}, { VK_NUMPAD4, "PavNum4"}, { VK_NUMPAD5, "PavNum5"}, { VK_NUMPAD6, "PavNum6"}, { VK_NUMPAD7, "PavNum7"}, { VK_NUMPAD8, "PavNum8"}, { VK_NUMPAD9, "PavNum9"}, { VK_MULTIPLY, "PavNum*"}, { VK_ADD, "PavNum+"}, { VK_SUBTRACT, "PavNum-"}, { VK_DECIMAL, "PavNum."}, { VK_DIVIDE, "PavNum/"}, { VK_SPACE, "Espace"}, { VK_OEM_COMMA, "Virgule"}, { VK_OEM_PERIOD,"Point"}, { VK_OEM_MINUS, "Moins"}, { VK_OEM_PLUS, "Plus"}, { VK_SHIFT, "Maj" }, // not valid outside USA { VK_OEM_1, "Point-virgule"}, { VK_OEM_2, "BarreOblique"}, { VK_OEM_3, "Tilde"}, { VK_OEM_4, "ParenthèseG"}, { VK_OEM_5, "BarreInverse"}, { VK_OEM_6, "ParenthèseD"}, { VK_OEM_7, "Guillemet"}, { 0xffffffff, "Unused"}, }; Win32keyConvert plKeyMap::fKeyConversionGerman[] = { { VK_F1, "F1"}, { VK_F2, "F2"}, { VK_F3, "F3"}, { VK_F4, "F4"}, { VK_F5, "F5"}, { VK_F6, "F6"}, { VK_F7, "F7"}, { VK_F8, "F8"}, { VK_F9, "F9"}, { VK_F10, "F10"}, { VK_F11, "F11"}, { VK_F12, "F12"}, { VK_ESCAPE, "Esc"}, { VK_TAB, "Tab"}, { VK_UP, "PfeilHoch"}, { VK_DOWN, "PfeilRunter"}, { VK_LEFT, "PfeilLinks"}, { VK_RIGHT, "PfeilRechts"}, { VK_BACK, "Backspace"}, { VK_RETURN, "Enter"}, { VK_PAUSE, "Pause"}, { VK_CAPITAL, "Feststelltaste"}, { VK_PRIOR, "BildHoch"}, { VK_NEXT, "BildRunter"}, { VK_END, "Ende"}, { VK_HOME, "Pos1"}, { VK_SNAPSHOT, "Druck"}, { VK_INSERT, "Einf"}, { VK_DELETE, "Entf"}, { VK_NUMPAD0, "ZB0"}, { VK_NUMPAD1, "ZB1"}, { VK_NUMPAD2, "ZB2"}, { VK_NUMPAD3, "ZB3"}, { VK_NUMPAD4, "ZB4"}, { VK_NUMPAD5, "ZB5"}, { VK_NUMPAD6, "ZB6"}, { VK_NUMPAD7, "ZB7"}, { VK_NUMPAD8, "ZB8"}, { VK_NUMPAD9, "ZB9"}, { VK_MULTIPLY, "ZB*"}, { VK_ADD, "ZB+"}, { VK_SUBTRACT, "ZB-"}, { VK_DECIMAL, "ZB."}, { VK_DIVIDE, "ZB/"}, { VK_SPACE, "Leertaste"}, { VK_OEM_COMMA, "Komma"}, { VK_OEM_PERIOD,"Punkt"}, { VK_OEM_MINUS, "Minus"}, { VK_OEM_PLUS, "Plus"}, { VK_SHIFT, "Umschalt" }, // not valid outside USA { VK_OEM_1, "Ü"}, { VK_OEM_2, "#"}, { VK_OEM_3, "Ö"}, { VK_OEM_4, "ß"}, { VK_OEM_5, "Backslash"}, { VK_OEM_6, "Akzent"}, { VK_OEM_7, "Ä"}, { 0xffffffff, "Unused"}, }; /* Win32keyConvert plKeyMap::fKeyConversionSpanish[] = { { VK_F1, "F1"}, { VK_F2, "F2"}, { VK_F3, "F3"}, { VK_F4, "F4"}, { VK_F5, "F5"}, { VK_F6, "F6"}, { VK_F7, "F7"}, { VK_F8, "F8"}, { VK_F9, "F9"}, { VK_F10, "F10"}, { VK_F11, "F11"}, { VK_F12, "F12"}, { VK_ESCAPE, "Esc"}, { VK_TAB, "Tabulador"}, { VK_UP, "CursorArriba"}, { VK_DOWN, "CursorAbajo"}, { VK_LEFT, "CursorIzquierdo"}, { VK_RIGHT, "CursorDerecho"}, { VK_BACK, "Retroceso"}, { VK_RETURN, "Intro"}, { VK_PAUSE, "Pausa"}, { VK_CAPITAL, "BloqMayús"}, { VK_PRIOR, "RePág"}, { VK_NEXT, "AVPág"}, { VK_END, "Fin"}, { VK_HOME, "Inicio"}, { VK_SNAPSHOT, "ImprPetSis"}, { VK_INSERT, "Insert"}, { VK_DELETE, "Supr"}, { VK_NUMPAD0, "TecNum0"}, { VK_NUMPAD1, "TecNum1"}, { VK_NUMPAD2, "TecNum2"}, { VK_NUMPAD3, "TecNum3"}, { VK_NUMPAD4, "TecNum4"}, { VK_NUMPAD5, "TecNum5"}, { VK_NUMPAD6, "TecNum6"}, { VK_NUMPAD7, "TecNum7"}, { VK_NUMPAD8, "TecNum8"}, { VK_NUMPAD9, "TecNum9"}, { VK_MULTIPLY, "TecNum*"}, { VK_ADD, "TecNum+"}, { VK_SUBTRACT, "TecNum-"}, { VK_DECIMAL, "TecNum."}, { VK_DIVIDE, "TecNum/"}, { VK_SPACE, "BarraEspacio"}, { VK_OEM_COMMA, "Coma"}, { VK_OEM_PERIOD,"Punto"}, { VK_OEM_MINUS, "Menos"}, { VK_OEM_PLUS, "Más"}, { VK_SHIFT, "Mayúsculas" }, // not valid outside USA { VK_OEM_1, "PuntoYComa"}, { VK_OEM_2, "Barra"}, { VK_OEM_3, "Tilde"}, { VK_OEM_4, "AbrirParéntesis"}, { VK_OEM_5, "BarraInvertida"}, { VK_OEM_6, "CerrarParéntesis"}, { VK_OEM_7, "Comillas"}, { 0xffffffff, "Unused"}, }; Win32keyConvert plKeyMap::fKeyConversionItalian[] = { { VK_F1, "F1"}, { VK_F2, "F2"}, { VK_F3, "F3"}, { VK_F4, "F4"}, { VK_F5, "F5"}, { VK_F6, "F6"}, { VK_F7, "F7"}, { VK_F8, "F8"}, { VK_F9, "F9"}, { VK_F10, "F10"}, { VK_F11, "F11"}, { VK_F12, "F12"}, { VK_ESCAPE, "Esc"}, { VK_TAB, "Tab"}, { VK_UP, "FrecciaSu"}, { VK_DOWN, "FrecciaGiù"}, { VK_LEFT, "FrecciaSx"}, { VK_RIGHT, "FrecciaDx"}, { VK_BACK, "Backspace"}, { VK_RETURN, "Invio"}, { VK_PAUSE, "Pausa"}, { VK_CAPITAL, "BlocMaiusc"}, { VK_PRIOR, "PagSu"}, { VK_NEXT, "PagGiù"}, { VK_END, "Fine"}, { VK_HOME, "Home"}, { VK_SNAPSHOT, "Stamp"}, { VK_INSERT, "Ins"}, { VK_DELETE, "Canc"}, { VK_NUMPAD0, "TastNum0"}, { VK_NUMPAD1, "TastNum1"}, { VK_NUMPAD2, "TastNum2"}, { VK_NUMPAD3, "TastNum3"}, { VK_NUMPAD4, "TastNum4"}, { VK_NUMPAD5, "TastNum5"}, { VK_NUMPAD6, "TastNum6"}, { VK_NUMPAD7, "TastNum7"}, { VK_NUMPAD8, "TastNum8"}, { VK_NUMPAD9, "TastNum9"}, { VK_MULTIPLY, "TastNum*"}, { VK_ADD, "TastNum+"}, { VK_SUBTRACT, "TastNum-"}, { VK_DECIMAL, "TastNum."}, { VK_DIVIDE, "TastNum/"}, { VK_SPACE, "Spazio"}, { VK_OEM_COMMA, "Virgola"}, { VK_OEM_PERIOD,"Punto"}, { VK_OEM_MINUS, "Meno"}, { VK_OEM_PLUS, "QuadraDx"}, { VK_SHIFT, "Shift" }, // not valid outside USA { VK_OEM_1, "QuadraSx"}, { VK_OEM_2, "ù"}, { VK_OEM_3, "ò"}, { VK_OEM_4, "Apostrofo"}, { VK_OEM_5, "\\"}, { VK_OEM_6, "ì"}, { VK_OEM_7, "à"}, { 0xffffffff, "Unused"}, }; */ CommandConvert plInputMap::fCmdConvert[] = { { B_CONTROL_ACTION, "Use Key" }, { B_CONTROL_JUMP, "Jump Key" }, { B_CONTROL_DIVE, "Dive Key" }, { B_CONTROL_MOVE_FORWARD, "Walk Forward" }, { B_CONTROL_MOVE_BACKWARD, "Walk Backward" }, { B_CONTROL_STRAFE_LEFT, "Strafe Left" }, { B_CONTROL_STRAFE_RIGHT, "Strafe Right" }, { B_CONTROL_MOVE_UP, "Move Up" }, { B_CONTROL_MOVE_DOWN, "Move Down" }, { B_CONTROL_ROTATE_LEFT, "Turn Left" }, { B_CONTROL_ROTATE_RIGHT, "Turn Right" }, { B_CONTROL_ROTATE_UP, "Turn Up" }, { B_CONTROL_ROTATE_DOWN, "Turn Down" }, { B_CONTROL_MODIFIER_FAST, "Fast Modifier" }, { B_CONTROL_EQUIP, "PickUp Item" }, { B_CONTROL_DROP, "Drop Item" }, { B_TOGGLE_DRIVE_MODE, "Drive" }, { B_CONTROL_ALWAYS_RUN, "Always Run" }, { B_CAMERA_MOVE_FORWARD, "Camera Forward"}, { B_CAMERA_MOVE_BACKWARD, "Camera Backward"}, { B_CAMERA_MOVE_UP, "Camera Up"}, { B_CAMERA_MOVE_DOWN, "Camera Down"}, { B_CAMERA_MOVE_LEFT, "Camera Left"}, { B_CAMERA_MOVE_RIGHT, "Camera Right"}, { B_CAMERA_MOVE_FAST, "Camera Fast"}, { B_CAMERA_ROTATE_RIGHT, "Camera Yaw Right"}, { B_CAMERA_ROTATE_LEFT, "Camera Yaw Left"}, { B_CAMERA_ROTATE_UP, "Camera Pitch Up"}, { B_CAMERA_ROTATE_DOWN, "Camera Pitch Down"}, { B_CAMERA_PAN_UP, "Camera Pan Up"}, { B_CAMERA_PAN_DOWN, "Camera Pan Down"}, { B_CAMERA_PAN_LEFT, "Camera Pan Left"}, { B_CAMERA_PAN_RIGHT, "Camera Pan Right"}, { B_CAMERA_PAN_TO_CURSOR, "Camera Pan To Cursor"}, { B_CAMERA_RECENTER, "Camera Recenter"}, { B_SET_CONSOLE_MODE, "Console"}, { B_CAMERA_DRIVE_SPEED_UP, "Decrease Camera Drive Speed" }, { B_CAMERA_DRIVE_SPEED_DOWN, "Increase Camera Drive Speed" }, { S_INCREASE_MIC_VOL, "Increase Microphone Sensitivity" }, { S_DECREASE_MIC_VOL, "Decrease Microphone Sensitivity" }, { S_PUSH_TO_TALK, "Push to talk" }, { S_SET_WALK_MODE, "Set Walk Mode" }, { B_CONTROL_TURN_TO, "Turn To Click" }, { B_CONTROL_TOGGLE_PHYSICAL, "Toggle Physical" }, { S_SET_FIRST_PERSON_MODE, "Toggle First Person" }, { B_CAMERA_ZOOM_IN, "Camera Zoom In" }, { B_CAMERA_ZOOM_OUT, "Camera Zoom Out" }, { B_CONTROL_EXIT_MODE, "Exit Mode" }, { B_CONTROL_OPEN_KI, "Open KI" }, { B_CONTROL_OPEN_BOOK, "Open Player Book" }, { B_CONTROL_EXIT_GUI_MODE, "Exit GUI Mode" }, { B_CONTROL_MODIFIER_STRAFE, "Strafe Modifier" }, { END_CONTROLS, ""}, };