Files
GTASource/game/system/keyboard.cpp
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

1091 lines
32 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// FILE : Keyboard.cpp
// PURPOSE : manages keyboard game states
// AUTHOR : Derek Payne
// STARTED : 26/05/2003
// REVISED : 10/11/2005
//
/////////////////////////////////////////////////////////////////////////////////
#include "system/keyboard.h"
// C headers
#include <stdio.h>
#include <string.h>
// Rage headers
#include "grcore/debugdraw.h"
#include "input\input.h"
#include "input/mapper.h"
#include "parsercore/streamxml.h"
#include "string/unicode.h"
#include "system/param.h"
#include "system/threadtype.h"
// framework headers
// Game headers
#include "debug/debug.h"
#include "text/messages.h"
#include "text/text.h"
#include "Text/TextConversion.h"
#include "system/control.h"
#if !__FINAL
PARAM(kblevels, "[game] Start game in Level Keyboard Mode");
PARAM(kbmodebutton, "[game] Sets the button to be used for switching keyboard modes.");
PARAM(kbDebugOnlySwitch, "[game] Toggle only between game and debug keyboard modes.");
PARAM(kbDontUseControlModeSwitch, "[game] Don't use a Control+Key press to toggle game modes.");
// used for finding what key to use for switching between keyboard modes.
#include "parser/memberenumdata.h"
extern ::rage::parEnumData parser_rage__ioMapperParameter_Data;
atString CKeyboard::ms_ThreadlStack;
sysCriticalSectionToken CKeyboard::ms_Lock;
const char* CKeyboard::ms_keyNames[KEY_MAX_CODES];
#if __WIN32PC
PARAM(kbgame, "[game] Start game in Game Keyboard Mode");
// the mouse is needed so we can indicate when to lock the mouse in dev mode.
#include "input/mouse.h"
#endif // __WIN32PC
#endif // !__FINAL
// The default key for switching between keyboard modes.
rage::ioMapperParameter CKeyboard::ms_keyboardModeButton = rage::KEY_TAB;
////////////////////////////////////////////////////////////////////////////
// name: Init
//
// purpose: initialises the keyboard and keyboard states
////////////////////////////////////////////////////////////////////////////
void CKeyboard::Init()
{
#if !__FINAL
sysCriticalSection lock(m_KeyUsageCs);
for (u32 mode=0 ; mode<KEYBOARD_MODE_OVERRIDE ; ++mode)
{
for (u32 c = 0; c < KEY_MAX_CODES; ++c)
{
for (u32 u = 0; u < KEY_MAX_USES; ++u)
{
key_usage[mode][c][u] = NULL;
key_dept[mode][c][u] = NULL;
}
}
}
m_currentKeyboardMode = KEYBOARD_MODE_DEBUG;
# if __WIN32PC
if(PARAM_kbgame.Get())
m_currentKeyboardMode = KEYBOARD_MODE_GAME;
ioMouse::SetAbsoluteOnly(m_currentKeyboardMode != KEYBOARD_MODE_GAME);
m_lastKeyboardMode = -1;
# endif // __WIN32PC
ioMapper::SetEnableKeyboard(m_currentKeyboardMode == KEYBOARD_MODE_GAME);
const char* keyName;
if(PARAM_kbmodebutton.Get(keyName))
{
bool found = false;
for(u32 i = 0; i < parser_rage__ioMapperParameter_Data.m_NumEnums && !found; ++i)
{
if(strcmp(keyName, parser_rage__ioMapperParameter_Data.m_Names[i]) == 0)
{
found = true;
// check if the parameter is actually a key.
if((parser_rage__ioMapperParameter_Data.m_Enums[i].m_Value & IOMT_KEYBOARD) == IOMT_KEYBOARD)
{
ms_keyboardModeButton = static_cast<ioMapperParameter>(parser_rage__ioMapperParameter_Data.m_Enums[i].m_Value);
}
}
}
}
// Copy the key names in the static buffer
for(s32 key=1; key<KEY_MAX_CODES; ++key)
{
const char* paramName = NULL;
for(u32 i = 0; i < parser_rage__ioMapperParameter_Data.m_NumEnums; ++i)
{
if(parser_rage__ioMapperParameter_Data.m_Enums[i].m_Value == static_cast<ioMapperParameter>(key))
paramName = parser_rage__ioMapperParameter_Data.m_Names[i];
}
if(paramName != NULL && strcmp(paramName, "") != 0)
{
if(Verifyf(strnicmp("KEY_", paramName, 4) == 0, "Invalid Key Code %d", key))
{
paramName += 4;
}
ms_keyNames[key] = paramName;
}
else
{
//Assertf(false, "Invalid Key Code %d", key);
ms_keyNames[key] = "Invalid Key";
}
}
#else
m_currentKeyboardMode = KEYBOARD_MODE_GAME;
#endif // !__FINAL
inputBufferChanged = false;
m_keyInput[0] = '\0';
}
////////////////////////////////////////////////////////////////////////////
// name: Update
//
// purpose: updates the current state of the current key pressed on the
// keyboard, so we know if it is still pressed or not.
////////////////////////////////////////////////////////////////////////////
void CKeyboard::Update()
{
#if !__FINAL
static atArray<int> m_fakeKeypressesCopy;
// clear keypresses from previous frame
while(m_fakeKeypressesCopy.GetCount())
{
int c = m_fakeKeypressesCopy.Pop();
KEYBOARD.SetKey(c, false);
}
m_fakeKeypressesCopy = m_fakeKeypresses;
// set fake keypresses
while(m_fakeKeypresses.GetCount())
{
int c = m_fakeKeypresses.Pop();
KEYBOARD.SetKey(c, true);
}
if(m_currentKeyboardMode < KEYBOARD_MODE_OVERRIDE)
{
// cycle through keyboards modes, we use KEYBOARD directly here so it
// works in game mode.
if( KEYBOARD.KeyPressed(ms_keyboardModeButton) != 0 && KEYBOARD.KeyDown(KEY_LMENU) == 0 && KEYBOARD.KeyDown(KEY_RMENU) == 0
WIN32PC_ONLY(&& (PARAM_kbDontUseControlModeSwitch.Get() || KEYBOARD.KeyDown(KEY_LCONTROL) || KEYBOARD.KeyDown(KEY_RCONTROL)) ))
{
if(PARAM_kbDebugOnlySwitch.Get())
{
if(m_currentKeyboardMode == KEYBOARD_MODE_GAME)
{
m_currentKeyboardMode = KEYBOARD_MODE_DEBUG;
}
else
{
m_currentKeyboardMode = KEYBOARD_MODE_GAME;
}
}
else
{
m_currentKeyboardMode++;
}
if(m_currentKeyboardMode == KEYBOARD_LAST_MODE+1)
m_currentKeyboardMode = KEYBOARD_FIRST_MODE;
#if __WIN32PC && !__FINAL
if(m_currentKeyboardMode == KEYBOARD_MODE_GAME)
ioMouse::SetAbsoluteOnly(false);
else if(m_lastKeyboardMode == KEYBOARD_MODE_GAME)
ioMouse::SetAbsoluteOnly(true);
m_lastKeyboardMode = m_currentKeyboardMode;
#endif // __WIN32PC && !__FINAL
WIN32PC_ONLY(if(!CSystem::IsThisThreadId(SYS_THREAD_RENDER)))
{
ioMapper::SetEnableKeyboard(m_currentKeyboardMode == KEYBOARD_MODE_GAME);
char keyboardMode[50];
CKeyboard::FillStringWithKeyboardMode(keyboardMode, 50);
CHelpMessage::SetMessageText(HELP_TEXT_SLOT_STANDARD, keyboardMode);
}
}
}
#endif
#if __WIN32PC
// get input from keyboard
KEYBOARD.GetBufferedInput(m_NewKeyInput, 16);
ConvertInputBufferIntoASCII(m_NewKeyInput, m_NewKeyInput);
if (strcmp(m_NewKeyInput, m_keyInput) == 0)
inputBufferChanged = false;
else
inputBufferChanged = true;
strcpy(m_keyInput, m_NewKeyInput);
#endif
}
////////////////////////////////////////////////////////////////////////////
// name: Shutdown
//
// purpose: Frees the usage and dept memory we previously allocated
////////////////////////////////////////////////////////////////////////////
void CKeyboard::Shutdown()
{
#if !__FINAL
for (u32 mode=0 ; mode<KEYBOARD_MODE_OVERRIDE ; ++mode)
{
for (u32 c = 0; c < KEY_MAX_CODES; ++c)
{
for (u32 u = 0; u < KEY_MAX_USES; ++u)
{
if (key_usage[mode][c][u])
{
delete key_usage[mode][c][u];
delete key_dept[mode][c][u];
}
}
}
}
#endif
}
/////////////////////////////////////////////////////////////////////////////
// name: ConvertInputBufferIntoASCII
//
// purpose: Convert the input buffer into ASCII
/////////////////////////////////////////////////////////////////////////////
void CKeyboard::ConvertInputBufferIntoASCII(char *input, char *output)
{
output = input;
while (*input != '\0')
{
switch (*(u8*)input)
{
case KEY_ESCAPE :
break;
case KEY_NUMPAD1 :
case KEY_1 :
*output = '1';
break;
case KEY_NUMPAD2 :
case KEY_2 :
*output = '2';
break;
case KEY_NUMPAD3 :
case KEY_3 :
*output = '3';
break;
case KEY_NUMPAD4 :
case KEY_4 :
*output = '4';
break;
case KEY_NUMPAD5 :
case KEY_5 :
*output = '5';
break;
case KEY_NUMPAD6 :
case KEY_6 :
*output = '6';
break;
case KEY_NUMPAD7 :
case KEY_7 :
*output = '7';
break;
case KEY_NUMPAD8 :
case KEY_8 :
*output = '8';
break;
case KEY_NUMPAD9 :
case KEY_9 :
*output = '9';
break;
case KEY_NUMPAD0 :
case KEY_0 :
*output = '0';
break;
case KEY_SUBTRACT :
case KEY_MINUS :
*output = '-';
break;
case KEY_EQUALS :
*output = '=';
break;
case KEY_TAB :
*output = 0;
break;
case KEY_Q :
*output = 'q';
break;
case KEY_W :
*output = 'w';
break;
case KEY_E :
*output = 'e';
break;
case KEY_R :
*output = 'r';
break;
case KEY_T :
*output = 't';
break;
case KEY_Y :
*output = 'y';
break;
case KEY_U :
*output = 'u';
break;
case KEY_I :
*output = 'i';
break;
case KEY_O :
*output = 'o';
break;
case KEY_P :
*output = 'p';
break;
case KEY_LBRACKET :
*output = '[';
break;
case KEY_RBRACKET :
*output = ']';
break;
case KEY_A :
*output = 'a';
break;
case KEY_S :
*output = 's';
break;
case KEY_D :
*output = 'd';
break;
case KEY_F :
*output = 'f';
break;
case KEY_G :
*output = 'g';
break;
case KEY_H :
*output = 'h';
break;
case KEY_J :
*output = 'j';
break;
case KEY_K :
*output = 'k';
break;
case KEY_L :
*output = 'l';
break;
case KEY_SEMICOLON :
*output = ';';
break;
case KEY_APOSTROPHE :
*output = '\'';
break;
case KEY_GRAVE :
*output = '#';
break;
case KEY_RSHIFT :
case KEY_LSHIFT :
*output = 0;
break;
case KEY_BACKSLASH :
*output = 92;
break;
case KEY_Z :
*output = 'z';
break;
case KEY_X :
*output = 'x';
break;
case KEY_C :
*output = 'c';
break;
case KEY_V :
*output = 'v';
break;
case KEY_B :
*output = 'b';
break;
case KEY_N :
*output = 'n';
break;
case KEY_M :
*output = 'm';
break;
case KEY_COMMA :
*output = ',';
break;
case KEY_PERIOD :
case KEY_DECIMAL :
*output = '.';
break;
case KEY_SLASH :
*output = 47;
break;
case KEY_MULTIPLY :
*output = 42;
break;
case KEY_SPACE :
*output = ' ';
break;
case KEY_ADD :
*output = '+';
break;
// case KEY_AT :
// *output = '@';
// break;
// case KEY_COLON :
// *output = ':';
// break;
// case KEY_UNDERLINE :
// *output = '_';
// break;
case KEY_DIVIDE :
*output = 47;
break;
default:
*output = *input;
break;
}
input++;
output++;
}
}
////////////////////////////////////////////////////////////////////////////
// name: GetAlteredKeyboardMode
//
// purpose: returns the current keyboard mode, taking into account ctrl, shift and alt keys
////////////////////////////////////////////////////////////////////////////
s32 CKeyboard::GetAlteredKeyboardMode(s32 NOTFINAL_ONLY(key_code))
{
#if !__FINAL
if(m_currentKeyboardMode == KEYBOARD_MODE_DEBUG)
{
const bool bControl = (KEYBOARD.KeyDown(KEY_LCONTROL) && key_code != KEY_LCONTROL) || (KEYBOARD.KeyDown(KEY_RCONTROL) && key_code != KEY_RCONTROL);
const bool bShift = (KEYBOARD.KeyDown(KEY_LSHIFT ) && key_code != KEY_LSHIFT ) || (KEYBOARD.KeyDown(KEY_RSHIFT ) && key_code != KEY_RSHIFT );
const bool bAlt = (KEYBOARD.KeyDown(KEY_LMENU ) && key_code != KEY_LMENU ) || (KEYBOARD.KeyDown(KEY_RMENU ) && key_code != KEY_RMENU );
if (bControl && bShift && bAlt) { return KEYBOARD_MODE_DEBUG_CNTRL_SHIFT_ALT; }
else if (bControl && bShift) { return KEYBOARD_MODE_DEBUG_CNTRL_SHIFT; }
else if (bControl && bAlt) { return KEYBOARD_MODE_DEBUG_CNTRL_ALT; }
else if (bShift && bAlt) { return KEYBOARD_MODE_DEBUG_SHIFT_ALT; }
else if (bControl) { return KEYBOARD_MODE_DEBUG_CTRL; }
else if (bShift) { return KEYBOARD_MODE_DEBUG_SHIFT; }
else if (bAlt) { return KEYBOARD_MODE_DEBUG_ALT; }
}
#if GTA_REPLAY
else if(m_currentKeyboardMode == KEYBOARD_MODE_REPLAY)
{
const bool bControl = (KEYBOARD.KeyDown(KEY_LCONTROL) && key_code != KEY_LCONTROL) || (KEYBOARD.KeyDown(KEY_RCONTROL) && key_code != KEY_RCONTROL);
const bool bShift = (KEYBOARD.KeyDown(KEY_LSHIFT ) && key_code != KEY_LSHIFT ) || (KEYBOARD.KeyDown(KEY_RSHIFT ) && key_code != KEY_RSHIFT );
const bool bAlt = (KEYBOARD.KeyDown(KEY_LMENU ) && key_code != KEY_LMENU ) || (KEYBOARD.KeyDown(KEY_RMENU ) && key_code != KEY_RMENU );
if (bControl && bShift && bAlt) { return KEYBOARD_MODE_REPLAY_CNTRL_SHIFT_ALT; }
else if (bControl && bShift) { return KEYBOARD_MODE_REPLAY_CNTRL_SHIFT; }
else if (bControl && bAlt) { return KEYBOARD_MODE_REPLAY_CNTRL_ALT; }
else if (bShift && bAlt) { return KEYBOARD_MODE_REPLAY_SHIFT_ALT; }
else if (bControl) { return KEYBOARD_MODE_REPLAY_CTRL; }
else if (bShift) { return KEYBOARD_MODE_REPLAY_SHIFT; }
else if (bAlt) { return KEYBOARD_MODE_REPLAY_ALT; }
}
#endif
#endif
return m_currentKeyboardMode;
}
////////////////////////////////////////////////////////////////////////////
// name: GetKeyJustDown
//
// purpose: returns the status of the passed key scan code
////////////////////////////////////////////////////////////////////////////
bool CKeyboard::GetKeyJustDown(s32 key_code, s32 use_mode, const char *BANK_ONLY(usage), const char *BANK_ONLY(dept))
{
NOTFINAL_ONLY(sysCriticalSection lock(m_KeyUsageCs));
#if __BANK
if(use_mode < KEYBOARD_MODE_OVERRIDE)
{
for (u32 u = 0; u < KEY_MAX_USES; ++u)
{
if (key_usage[use_mode][key_code][u] == NULL)
{
USE_DEBUG_MEMORY();
const char* _usage = usage ? usage : "UNDEFINED. Please change this !";
const char* _dept = dept ? dept : "UNDEFINED. Please change this !";
size_t usageLen = strlen(_usage)+1;
size_t deptLen = strlen(_dept)+1;
key_usage[use_mode][key_code][u] = rage_new char[usageLen];
key_dept[use_mode][key_code][u] = rage_new char[deptLen];
safecpy(key_usage[use_mode][key_code][u], _usage, usageLen);
safecpy(key_dept[use_mode][key_code][u], _dept, deptLen);
}
}
}
controlDebugf2("Testing CKeyboard::GetKeyJustDown() for %s.", usage);
#endif
if (!IsCorrectKeyboardMode(use_mode, key_code))
{
controlDebugf2("Test for %s failed. Use mode %d but needed %d.",
CControl::GetParameterText(static_cast<ioMapperParameter>(key_code)),
GetAlteredKeyboardMode(key_code),
use_mode);
NOTFINAL_ONLY(DebugOutputScriptCallStack());
return false;
}
bool result = (KEYBOARD.KeyPressed(key_code) != 0);
controlDebugf2("%s is %sJust Down.",
CControl::GetParameterText(static_cast<ioMapperParameter>(key_code)),
(result ? "" : "Not "));
NOTFINAL_ONLY(DebugOutputScriptCallStack());
return result;
}
////////////////////////////////////////////////////////////////////////////
// name: GetKeyJustUp
//
// purpose: returns the status of the passed key scan code
////////////////////////////////////////////////////////////////////////////
bool CKeyboard::GetKeyJustUp(s32 key_code, s32 use_mode, const char *BANK_ONLY(usage), const char *BANK_ONLY(dept))
{
NOTFINAL_ONLY(sysCriticalSection lock(m_KeyUsageCs));
#if __BANK
if(use_mode < KEYBOARD_MODE_OVERRIDE)
{
for (u32 u = 0; u < KEY_MAX_USES; ++u)
{
if (key_usage[use_mode][key_code][u] == NULL)
{
USE_DEBUG_MEMORY();
const char* _usage = usage ? usage : "UNDEFINED. Please change this !";
const char* _dept = dept ? dept : "UNDEFINED. Please change this !";
size_t usageLen = strlen(_usage)+1;
size_t deptLen = strlen(_dept)+1;
key_usage[use_mode][key_code][u] = rage_new char[usageLen];
key_dept[use_mode][key_code][u] = rage_new char[deptLen];
safecpy(key_usage[use_mode][key_code][u], _usage, usageLen);
safecpy(key_dept[use_mode][key_code][u], _dept, deptLen);
}
}
}
controlDebugf2("Testing CKeyboard::GetKeyJustUp() for %s.", usage);
#endif
if (!IsCorrectKeyboardMode(use_mode, key_code))
{
controlDebugf2("Test for %s failed. Use mode %d but needed %d.",
CControl::GetParameterText(static_cast<ioMapperParameter>(key_code)),
GetAlteredKeyboardMode(key_code),
use_mode);
NOTFINAL_ONLY(DebugOutputScriptCallStack());
return false;
}
bool result = (KEYBOARD.KeyReleased(key_code) != 0);
controlDebugf2("%s is %sJust Up.",
CControl::GetParameterText(static_cast<ioMapperParameter>(key_code)),
(result ? "" : "Not "));
NOTFINAL_ONLY(DebugOutputScriptCallStack());
return result;
}
////////////////////////////////////////////////////////////////////////////
// name: GetKeyUp
//
// purpose: returns the status of the passed key scan code
////////////////////////////////////////////////////////////////////////////
bool CKeyboard::GetKeyUp(s32 key_code, s32 use_mode, const char *BANK_ONLY(usage), const char *BANK_ONLY(dept))
{
NOTFINAL_ONLY(sysCriticalSection lock(m_KeyUsageCs));
#if __BANK
if(use_mode < KEYBOARD_MODE_OVERRIDE)
{
for (u32 u = 0; u < KEY_MAX_USES; ++u)
{
if (key_usage[use_mode][key_code][u] == NULL)
{
USE_DEBUG_MEMORY();
const char* _usage = usage ? usage : "UNDEFINED. Please change this !";
const char* _dept = dept ? dept : "UNDEFINED. Please change this !";
size_t usageLen = strlen(_usage)+1;
size_t deptLen = strlen(_dept)+1;
key_usage[use_mode][key_code][u] = rage_new char[usageLen];
key_dept[use_mode][key_code][u] = rage_new char[deptLen];
safecpy(key_usage[use_mode][key_code][u], _usage, usageLen);
safecpy(key_dept[use_mode][key_code][u], _dept, deptLen);
}
}
}
controlDebugf2("Testing CKeyboard::GetKeyUp() for %s.", usage);
#endif
if (!IsCorrectKeyboardMode(use_mode, key_code))
{
controlDebugf2("Test for %s failed. Use mode %d but needed %d.",
CControl::GetParameterText(static_cast<ioMapperParameter>(key_code)),
GetAlteredKeyboardMode(key_code),
use_mode);
NOTFINAL_ONLY(DebugOutputScriptCallStack());
return false;
}
bool result = (KEYBOARD.KeyUp(key_code) != 0);
controlDebugf2("%s is %sUp.",
CControl::GetParameterText(static_cast<ioMapperParameter>(key_code)),
(result ? "" : "Not "));
NOTFINAL_ONLY(DebugOutputScriptCallStack());
return result;
}
////////////////////////////////////////////////////////////////////////////
// name: GetKeyDown
//
// purpose: returns the status of the passed key scan code
////////////////////////////////////////////////////////////////////////////
bool CKeyboard::GetKeyDown(s32 key_code, s32 use_mode, const char *BANK_ONLY(usage), const char *BANK_ONLY(dept))
{
NOTFINAL_ONLY(sysCriticalSection lock(m_KeyUsageCs));
#if __BANK
if(use_mode < KEYBOARD_MODE_OVERRIDE)
{
for (u32 u = 0; u < KEY_MAX_USES; ++u)
{
if (key_usage[use_mode][key_code][u] == NULL)
{
USE_DEBUG_MEMORY();
const char* _usage = usage ? usage : "UNDEFINED. Please change this !";
const char* _dept = dept ? dept : "UNDEFINED. Please change this !";
size_t usageLen = strlen(_usage)+1;
size_t deptLen = strlen(_dept)+1;
key_usage[use_mode][key_code][u] = rage_new char[usageLen];
key_dept[use_mode][key_code][u] = rage_new char[deptLen];
safecpy(key_usage[use_mode][key_code][u], _usage, usageLen);
safecpy(key_dept[use_mode][key_code][u], _dept, deptLen);
}
}
}
controlDebugf2("Testing CKeyboard::GetKeyDown() for %s.", usage);
#endif
if (!IsCorrectKeyboardMode(use_mode, key_code))
{
controlDebugf2("Test for %s failed. Use mode %d but needed %d.",
CControl::GetParameterText(static_cast<ioMapperParameter>(key_code)),
GetAlteredKeyboardMode(key_code),
use_mode);
NOTFINAL_ONLY(DebugOutputScriptCallStack());
return false;
}
bool result = (KEYBOARD.KeyDown(key_code) != 0);
controlDebugf2("%s is %sDown.",
CControl::GetParameterText(static_cast<ioMapperParameter>(key_code)),
(result ? "" : "Not "));
NOTFINAL_ONLY(DebugOutputScriptCallStack());
return result;
}
////////////////////////////////////////////////////////////////////////////
// name: GetCurrentKeyPressed
//
// purpose: returns what key is currently pressed
////////////////////////////////////////////////////////////////////////////
const char* CKeyboard::GetKeyPressedBuffer(s32 use_mode)
{
if (use_mode != m_currentKeyboardMode && use_mode != KEYBOARD_MODE_OVERRIDE)
return NULL;
#if __WIN32
// standard win32 input
return m_keyInput;
#else
#if !__FINAL
// on consoles, we need to do it manually - nasty but debug only (for NODE VIEWER only at the moment)
// DP: do not put this shite in the final game, if we want to do this in the final thing, we should
// find a nicer way to do it.
for (s32 iKeyCode = KEY_ESCAPE; iKeyCode < KEY_CHATPAD_ORANGE_SHIFT; iKeyCode++)
{
if (GetKeyJustDown(iKeyCode, use_mode))
{
m_NewKeyInput[0] = iKeyCode;
m_NewKeyInput[1] = '\0';
ConvertInputBufferIntoASCII(m_NewKeyInput, m_NewKeyInput);
return m_NewKeyInput;
}
}
#endif
return NULL;
#endif
}
bool CKeyboard::IsCorrectKeyboardMode( s32 use_mode, s32 key_code )
{
return use_mode == GetAlteredKeyboardMode(key_code)
|| ( use_mode == KEYBOARD_MODE_OVERRIDE
KEYBOARD_MOUSE_ONLY(&& m_currentKeyboardMode != KEYBOARD_MODE_GAME) ); // Do not allow KEYBOARD_MODE_OVERRIDE when the keyboard could be used for playing the game.
}
#if !__FINAL
// some debug functions:
/////////////////////////////////////////////////////////////////////////////
// name: GetKeyUsage
//
// purpose: returns the string explaining the usage for this key (debug only)
/////////////////////////////////////////////////////////////////////////////
const char *CKeyboard::GetKeyUsage(s32 key_code, s32 use_mode, char* buffer, u32 maxBufferLen, u32 use)
{
NOTFINAL_ONLY(sysCriticalSection lock(m_KeyUsageCs));
Assertf(key_code > 0, "CKeyboard::GetKeyUsage - key_code 0 is not a valid key");
if (key_usage[use_mode][key_code][use])
safecpy(buffer, key_usage[use_mode][key_code][use], maxBufferLen);
else
safecpy(buffer, "Key Usage undefined", maxBufferLen);
return buffer;
}
/////////////////////////////////////////////////////////////////////////////
// name: GetKeyDept
//
// purpose: returns the department that use the key in code
/////////////////////////////////////////////////////////////////////////////
const char *CKeyboard::GetKeyDept(s32 key_code, s32 use_mode, char* buffer, u32 maxBufferLen, u32 use)
{
NOTFINAL_ONLY(sysCriticalSection lock(m_KeyUsageCs));
Assertf(key_code > 0, "CKeyboard::GetKeyDept - key_code 0 is not a valid key");
if (key_dept[use_mode][key_code][use])
safecpy(buffer, key_dept[use_mode][key_code][use], maxBufferLen);
else
safecpy(buffer, "Key Dept undefined", maxBufferLen);
return buffer;
}
/////////////////////////////////////////////////////////////////////////////
// name: GetKeyName
//
// purpose: returns a string with the actual key name (used in debug
// menus) - should be used to replace use of KeyToAscii
//
/////////////////////////////////////////////////////////////////////////////
const char* CKeyboard::GetKeyName(s32 key_code, char* pName, s32 iMaxChars)
{
Assertf(key_code > 0, "CKeyboard::GetKeyName - key_code 0 is not a valid key");
if (ms_keyNames[key_code])
safecpy(pName, ms_keyNames[key_code], iMaxChars);
else
safecpy(pName, "Key Name undefined", iMaxChars);
return pName;
}
/////////////////////////////////////////////////////////////////////////////
// name: HasUsage
//
// purpose: returns a true if the key is used, false otherwise
//
/////////////////////////////////////////////////////////////////////////////
bool CKeyboard::HasKeyUsage(s32 key_code, s32 use_mode, u32 use)
{
NOTFINAL_ONLY(sysCriticalSection lock(m_KeyUsageCs));
Assertf(key_code > 0, "CKeyboard::HasKeyUsage - key_code 0 is not a valid key");
return key_usage[use_mode][key_code][use] != NULL;
}
//
// name: PrintDebugKeys
// description: Print the debug key bindings
void CKeyboard::PrintDebugKeys()
{
NOTFINAL_ONLY(sysCriticalSection lock(m_KeyUsageCs));
#if DEBUG_DRAW
char key_name[32];
char key_usage[512];
for(s32 i=1; i<KEY_MAX_CODES; i++)
{
if(HasKeyUsage(i, KEYBOARD_MODE_DEBUG))
grcDebugDraw::AddDebugOutput("%s: %s", GetKeyName(i, key_name, 32), GetKeyUsage(i, KEYBOARD_MODE_DEBUG, key_usage, 512));
}
for(s32 i=1; i<KEY_MAX_CODES; i++)
{
if(HasKeyUsage(i, KEYBOARD_MODE_DEBUG_CTRL))
grcDebugDraw::AddDebugOutput("Ctrl+%s: %s", GetKeyName(i, key_name, 32), GetKeyUsage(i, KEYBOARD_MODE_DEBUG_CTRL, key_usage, 512));
}
for(s32 i=1; i<KEY_MAX_CODES; i++)
{
if(HasKeyUsage(i, KEYBOARD_MODE_DEBUG_SHIFT))
grcDebugDraw::AddDebugOutput("Shift+%s: %s", GetKeyName(i, key_name, 32), GetKeyUsage(i, KEYBOARD_MODE_DEBUG_SHIFT, key_usage, 512));
}
for(s32 i=1; i<KEY_MAX_CODES; i++)
{
if(HasKeyUsage(i, KEYBOARD_MODE_DEBUG_ALT))
grcDebugDraw::AddDebugOutput("Alt+%s: %s", GetKeyName(i, key_name, 32), GetKeyUsage(i, KEYBOARD_MODE_DEBUG_ALT, key_usage, 512));
}
#endif // DEBUG_DRAW
}
//
// name: PrintMarketingKeys
// description: Print the marketing debug key bindings
void CKeyboard::PrintMarketingKeys()
{
NOTFINAL_ONLY(sysCriticalSection lock(m_KeyUsageCs));
#if DEBUG_DRAW
char key_name[16];
char key_usage[512];
for(s32 i=1; i<KEY_MAX_CODES; i++)
{
if(HasKeyUsage(i, KEYBOARD_MODE_MARKETING))
{
grcDebugDraw::AddDebugOutput("%s: %s", GetKeyName(i, key_name, 16), GetKeyUsage(i, KEYBOARD_MODE_MARKETING, key_usage, 512));
}
}
#endif // DEBUG_DRAW
}
//
// name: DumpDebugKeysToXML
// description: Output the debug key to an XML stream
void CKeyboard::DumpDebugKeysToXML(fiStream* stream)
{
NOTFINAL_ONLY(sysCriticalSection lock(m_KeyUsageCs));
char key_name[32];
char key_usage[512];
char key_dept[512];
fprintf(stream, "<Mappings>\n");
// normal Keys
fprintf(stream, "<Debug>\n");
for(s32 i=1; i<KEY_MAX_CODES; i++)
{
if(HasKeyUsage(i, KEYBOARD_MODE_DEBUG))
{
fprintf(stream, "<mapping Key=\"%s\" Dept=\"%s\" Usage=\"%s\"/>\n",
GetKeyName(i, key_name, 32),
GetKeyDept(i, KEYBOARD_MODE_DEBUG, key_dept, 512),
GetKeyUsage(i, KEYBOARD_MODE_DEBUG, key_usage, 512));
}
}
fprintf(stream, "</Debug>\n");
// Ctrl Keys
fprintf(stream, "<Debug_Ctrl>\n");
for(s32 i=1; i<KEY_MAX_CODES; i++)
{
if(HasKeyUsage(i, KEYBOARD_MODE_DEBUG_CTRL))
{
fprintf(stream, "<mapping Key=\"%s\" Dept=\"%s\" Usage=\"%s\"/>\n",
GetKeyName(i, key_name, 32),
GetKeyDept(i, KEYBOARD_MODE_DEBUG_CTRL, key_dept, 512),
GetKeyUsage(i, KEYBOARD_MODE_DEBUG_CTRL, key_usage, 512));
}
}
fprintf(stream, "</Debug_Ctrl>\n");
// Shift Keys
fprintf(stream, "<Debug_Shift>\n");
for(s32 i=1; i<KEY_MAX_CODES; i++)
{
if(HasKeyUsage(i, KEYBOARD_MODE_DEBUG_SHIFT))
{
fprintf(stream, "<mapping Key=\"%s\" Dept=\"%s\" Usage=\"%s\"/>\n",
GetKeyName(i, key_name, 32),
GetKeyDept(i, KEYBOARD_MODE_DEBUG_SHIFT, key_dept, 512),
GetKeyUsage(i, KEYBOARD_MODE_DEBUG_SHIFT, key_usage, 512));
}
}
fprintf(stream, "</Debug_Shift>\n");
// Alt Keys
fprintf(stream, "<Debug_Alt>\n");
for(s32 i=1; i<KEY_MAX_CODES; i++)
{
if(HasKeyUsage(i, KEYBOARD_MODE_DEBUG_ALT))
{
fprintf(stream, "<mapping Key=\"%s\" Dept=\"%s\" Usage=\"%s\"/>\n",
GetKeyName(i, key_name, 32),
GetKeyDept(i, KEYBOARD_MODE_DEBUG_ALT, key_dept, 512),
GetKeyUsage(i, KEYBOARD_MODE_DEBUG_ALT, key_usage, 512));
}
}
fprintf(stream, "</Debug_Alt>\n");
// Ctrl + Shift Keys
fprintf(stream, "<Debug_Ctrl_Shift>\n");
for(s32 i=1; i<KEY_MAX_CODES; i++)
{
if(HasKeyUsage(i, KEYBOARD_MODE_DEBUG_CNTRL_SHIFT))
{
fprintf(stream, "<mapping Key=\"%s\" Dept=\"%s\" Usage=\"%s\"/>\n",
GetKeyName(i, key_name, 32),
GetKeyDept(i, KEYBOARD_MODE_DEBUG_CNTRL_SHIFT, key_dept, 512),
GetKeyUsage(i, KEYBOARD_MODE_DEBUG_CNTRL_SHIFT, key_usage, 512));
}
}
fprintf(stream, "</Debug_Ctrl_Shift>\n");
// Ctrl + Alt Keys
fprintf(stream, "<Debug_Ctrl_Alt>\n");
for(s32 i=1; i<KEY_MAX_CODES; i++)
{
if(HasKeyUsage(i, KEYBOARD_MODE_DEBUG_CNTRL_ALT))
{
fprintf(stream, "<mapping Key=\"%s\" Dept=\"%s\" Usage=\"%s\"/>\n",
GetKeyName(i, key_name, 32),
GetKeyDept(i, KEYBOARD_MODE_DEBUG_CNTRL_ALT, key_dept, 512),
GetKeyUsage(i, KEYBOARD_MODE_DEBUG_CNTRL_ALT, key_usage, 512));
}
}
fprintf(stream, "</Debug_Ctrl_Alt>\n");
// Shift + Alt Keys
fprintf(stream, "<Debug_Shift_Alt>\n");
for(s32 i=1; i<KEY_MAX_CODES; i++)
{
if(HasKeyUsage(i, KEYBOARD_MODE_DEBUG_SHIFT_ALT))
{
fprintf(stream, "<mapping Key=\"%s\" Dept=\"%s\" Usage=\"%s\"/>\n",
GetKeyName(i, key_name, 32),
GetKeyDept(i, KEYBOARD_MODE_DEBUG_SHIFT_ALT, key_dept, 512),
GetKeyUsage(i, KEYBOARD_MODE_DEBUG_SHIFT_ALT, key_usage, 512));
}
}
fprintf(stream, "</Debug_Shift_Alt>\n");
// Shift + Alt Keys
fprintf(stream, "<Debug_Ctrl_Shift_Alt>\n");
for(s32 i=1; i<KEY_MAX_CODES; i++)
{
if(HasKeyUsage(i, KEYBOARD_MODE_DEBUG_CNTRL_SHIFT_ALT))
{
fprintf(stream, "<mapping Key=\"%s\" Dept=\"%s\" Usage=\"%s\"/>\n",
GetKeyName(i, key_name, 32),
GetKeyDept(i, KEYBOARD_MODE_DEBUG_CNTRL_SHIFT_ALT, key_dept, 512),
GetKeyUsage(i, KEYBOARD_MODE_DEBUG_CNTRL_SHIFT_ALT, key_usage, 512));
}
}
fprintf(stream, "</Debug_Ctrl_Shift_Alt>\n");
fprintf(stream, "<Marketing>\n");
for(s32 i=1; i<KEY_MAX_CODES; i++)
{
if(HasKeyUsage(i, KEYBOARD_MODE_MARKETING))
{
fprintf(stream, "<mapping Key=\"%s\" Dept=\"%s\" Usage=\"%s\"/>\n",
GetKeyName(i, key_name, 32),
GetKeyDept(i, KEYBOARD_MODE_MARKETING, key_dept, 512),
GetKeyUsage(i, KEYBOARD_MODE_MARKETING, key_usage, 512));
}
}
fprintf(stream, "</Marketing>\n");
fprintf(stream, "</Mappings>\n");
}
char* CKeyboard::FillStringWithKeyboardMode(char* pString, s32 length)
{
switch (m_currentKeyboardMode)
{
case KEYBOARD_MODE_DEBUG :
strncpy(pString, "Keyboard : Debug", length);
break;
case KEYBOARD_MODE_DEBUG_SHIFT :
strncpy(pString, "Keyboard : Debug Shift", length);
break;
case KEYBOARD_MODE_DEBUG_CTRL :
strncpy(pString, "Keyboard : Debug Ctrl", length);
break;
case KEYBOARD_MODE_DEBUG_ALT :
strncpy(pString, "Keyboard : Debug Alt", length);
break;
case KEYBOARD_MODE_GAME :
strncpy(pString, "Keyboard : Game", length);
break;
case KEYBOARD_MODE_MARKETING :
strncpy(pString, "Keyboard : Marketing", length);
break;
case KEYBOARD_MODE_OVERRIDE :
strncpy(pString, "Keyboard : Override", length);
break;
#if GTA_REPLAY
case KEYBOARD_MODE_REPLAY:
strncpy(pString, "Keyboard : Replay", length);
break;
#endif
default :
strncpy(pString, "Keyboard : Unknown", length);
break;
}
return pString;
}
void CKeyboard::SetCurrentMode( s32 mode )
{
m_currentKeyboardMode = mode;
#if !__FINAL && __WIN32PC
ioMouse::SetAbsoluteOnly(m_currentKeyboardMode != KEYBOARD_MODE_GAME);
m_lastKeyboardMode = m_currentKeyboardMode;
#endif // !__FINAL && __WIN32PC
ioMapper::SetEnableKeyboard(m_currentKeyboardMode == KEYBOARD_MODE_GAME);
}
void CKeyboard::ChanneledOutputForStackTrace(const char* fmt, ...)
{
char buffer[256];
va_list args;
va_start(args, fmt);
vformatf(buffer, sizeof(buffer), fmt, args);
va_end(args);
ms_ThreadlStack += buffer;
ms_ThreadlStack += "\n";
}
void CKeyboard::DebugOutputScriptCallStack()
{
if(Channel_Control.MaxLevel >= DIAG_SEVERITY_DEBUG3 && sysThreadType::IsUpdateThread() && scrThread::GetActiveThread())
{
sysCriticalSection critSec(ms_Lock);
// PrintStackTrace does not exist in final.
scrThread::GetActiveThread()->PrintStackTrace(ChanneledOutputForStackTrace);
controlDebugf3("---- With stack: \n%s", ms_ThreadlStack.c_str());
ms_ThreadlStack.Clear();
}
}
#endif