/*==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, ""},
};