📄 wininput.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "platformWin32/platformWin32.h"
#include "platform/platformInput.h"
#include "platform/platformVideo.h"
#include "platformWin32/winDirectInput.h"
#include "platform/event.h"
#include "console/console.h"
#ifdef TGE_RPG
#include "console/consoleTypes.h"
#endif
#ifdef LOG_INPUT
#include <time.h>
#include <stdarg.h>
#endif
// Static class variables:
InputManager* Input::smManager;
bool Input::smActive;
bool Input::smLastKeyboardActivated;
bool Input::smLastMouseActivated;
bool Input::smLastJoystickActivated;
#ifdef TGE_RPG
bool Input::smEnableDirectInput;
#endif
#ifdef LOG_INPUT
static HANDLE gInputLog;
#endif
static void fillAsciiTable();
//------------------------------------------------------------------------------
//
// This function gets the standard ASCII code corresponding to our key code
// and the existing modifier key state.
//
//------------------------------------------------------------------------------
struct AsciiData
{
struct KeyData
{
U16 ascii;
bool isDeadChar;
};
KeyData upper;
KeyData lower;
KeyData goofy;
};
#define NUM_KEYS ( KEY_OEM_102 + 1 )
#define KEY_FIRST KEY_ESCAPE
static AsciiData AsciiTable[NUM_KEYS];
//------------------------------------------------------------------------------
void Input::init()
{
Con::printf( "Input Init:" );
destroy();
#ifdef LOG_INPUT
struct tm* newTime;
time_t aclock;
time( &aclock );
newTime = localtime( &aclock );
asctime( newTime );
gInputLog = CreateFile( "input.log", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
log( "Input log opened at %s\n", asctime( newTime ) );
#endif
smActive = false;
smLastKeyboardActivated = true;
smLastMouseActivated = true;
smLastJoystickActivated = true;
#ifdef TGE_RPG
smEnableDirectInput = false;
Con::addVariable("$enableDirectInput",TypeBool, &smEnableDirectInput);
#endif
OSVERSIONINFO OSVersionInfo;
dMemset( &OSVersionInfo, 0, sizeof( OSVERSIONINFO ) );
OSVersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
if ( GetVersionEx( &OSVersionInfo ) )
{
#ifdef LOG_INPUT
log( "Operating System:\n" );
switch ( OSVersionInfo.dwPlatformId )
{
case VER_PLATFORM_WIN32s:
log( " Win32s on Windows 3.1 version %d.%d\n", OSVersionInfo.dwMajorVersion, OSVersionInfo.dwMinorVersion );
break;
case VER_PLATFORM_WIN32_WINDOWS:
log( " Windows 95 version %d.%d\n", OSVersionInfo.dwMajorVersion, OSVersionInfo.dwMinorVersion );
log( " Build number %d\n", LOWORD( OSVersionInfo.dwBuildNumber ) );
break;
case VER_PLATFORM_WIN32_NT:
log( " WinNT version %d.%d\n", OSVersionInfo.dwMajorVersion, OSVersionInfo.dwMinorVersion );
log( " Build number %d\n", OSVersionInfo.dwBuildNumber );
break;
}
if ( OSVersionInfo.szCSDVersion != NULL )
log( " %s\n", OSVersionInfo.szCSDVersion );
log( "\n" );
#endif
if ( !( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && OSVersionInfo.dwMajorVersion < 5 ) )
{
smManager = new DInputManager;
if ( !smManager->enable() )
{
Con::printf( " DirectInput not enabled." );
delete smManager;
smManager = NULL;
}
else
{
DInputManager::init();
Con::printf( " DirectInput enabled." );
}
}
else
Con::printf( " WinNT detected -- DirectInput not enabled." );
}
fillAsciiTable();
Con::printf( "" );
}
//------------------------------------------------------------------------------
ConsoleFunction( isJoystickDetected, bool, 1, 1, "isJoystickDetected()" )
{
argc; argv;
return( DInputDevice::joystickDetected() );
}
//------------------------------------------------------------------------------
ConsoleFunction( getJoystickAxes, const char*, 2, 2, "getJoystickAxes( instance )" )
{
argc;
DInputManager* mgr = dynamic_cast<DInputManager*>( Input::getManager() );
if ( mgr )
return( mgr->getJoystickAxesString( dAtoi( argv[1] ) ) );
return( "" );
}
//------------------------------------------------------------------------------
static void fillAsciiTable()
{
#ifdef LOG_INPUT
char buf[256];
Input::log( "--- Filling the ASCII table! ---\n" );
#endif
//HKL layout = GetKeyboardLayout( 0 );
U8 state[256];
U16 ascii[2];
U32 dikCode, vKeyCode, keyCode;
S32 result;
dMemset( &AsciiTable, 0, sizeof( AsciiTable ) );
dMemset( &state, 0, sizeof( state ) );
for ( keyCode = KEY_FIRST; keyCode < NUM_KEYS; keyCode++ )
{
ascii[0] = ascii[1] = 0;
dikCode = Key_to_DIK( keyCode );
if ( dikCode )
{
//vKeyCode = MapVirtualKeyEx( dikCode, 1, layout );
vKeyCode = MapVirtualKey( dikCode, 1 );
#ifdef LOG_INPUT
dSprintf( buf, sizeof( buf ), "KC: %#04X DK: %#04X VK: %#04X\n",
keyCode, dikCode, vKeyCode );
Input::log( buf );
#endif
// Lower case:
ascii[0] = ascii[1] = 0;
//result = ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout );
result = ToAscii( vKeyCode, dikCode, state, ascii, 0 );
#ifdef LOG_INPUT
dSprintf( buf, sizeof( buf ), " LOWER- R: %d A[0]: %#06X A[1]: %#06X\n",
result, ascii[0], ascii[1] );
Input::log( buf );
#endif
if ( result == 2 )
AsciiTable[keyCode].lower.ascii = ascii[1] ? ascii[1] : ( ascii[0] >> 8 );
else if ( result == 1 )
AsciiTable[keyCode].lower.ascii = ascii[0];
else if ( result < 0 )
{
AsciiTable[keyCode].lower.ascii = ascii[0];
AsciiTable[keyCode].lower.isDeadChar = true;
// Need to clear the dead character from the keyboard layout:
//ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout );
ToAscii( vKeyCode, dikCode, state, ascii, 0 );
}
// Upper case:
ascii[0] = ascii[1] = 0;
state[VK_SHIFT] = 0x80;
//result = ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout );
result = ToAscii( vKeyCode, dikCode, state, ascii, 0 );
#ifdef LOG_INPUT
dSprintf( buf, sizeof( buf ), " UPPER- R: %d A[0]: %#06X A[1]: %#06X\n",
result, ascii[0], ascii[1] );
Input::log( buf );
#endif
if ( result == 2 )
AsciiTable[keyCode].upper.ascii = ascii[1] ? ascii[1] : ( ascii[0] >> 8 );
else if ( result == 1 )
AsciiTable[keyCode].upper.ascii = ascii[0];
else if ( result < 0 )
{
AsciiTable[keyCode].upper.ascii = ascii[0];
AsciiTable[keyCode].upper.isDeadChar = true;
// Need to clear the dead character from the keyboard layout:
//ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout );
ToAscii( vKeyCode, dikCode, state, ascii, 0 );
}
state[VK_SHIFT] = 0;
// Foreign mod case:
ascii[0] = ascii[1] = 0;
state[VK_CONTROL] = 0x80;
state[VK_MENU] = 0x80;
//result = ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout );
result = ToAscii( vKeyCode, dikCode, state, ascii, 0 );
#ifdef LOG_INPUT
dSprintf( buf, sizeof( buf ), " GOOFY- R: %d A[0]: %#06X A[1]: %#06X\n",
result, ascii[0], ascii[1] );
Input::log( buf );
#endif
if ( result == 2 )
AsciiTable[keyCode].goofy.ascii = ascii[1] ? ascii[1] : ( ascii[0] >> 8 );
else if ( result == 1 )
AsciiTable[keyCode].goofy.ascii = ascii[0];
else if ( result < 0 )
{
AsciiTable[keyCode].goofy.ascii = ascii[0];
AsciiTable[keyCode].goofy.isDeadChar = true;
// Need to clear the dead character from the keyboard layout:
//ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout );
ToAscii( vKeyCode, dikCode, state, ascii, 0 );
}
state[VK_CONTROL] = 0;
state[VK_MENU] = 0;
}
}
#ifdef LOG_INPUT
Input::log( "--- Finished filling the ASCII table! ---\n\n" );
#endif
}
//------------------------------------------------------------------------------
U16 Input::getKeyCode( U16 asciiCode )
{
U16 keyCode = 0;
U16 i;
// This is done three times so the lowerkey will always
// be found first. Some foreign keyboards have duplicate
// chars on some keys.
for ( i = KEY_FIRST; i < NUM_KEYS && !keyCode; i++ )
{
if ( AsciiTable[i].lower.ascii == asciiCode )
{
keyCode = i;
break;
};
}
for ( i = KEY_FIRST; i < NUM_KEYS && !keyCode; i++ )
{
if ( AsciiTable[i].upper.ascii == asciiCode )
{
keyCode = i;
break;
};
}
for ( i = KEY_FIRST; i < NUM_KEYS && !keyCode; i++ )
{
if ( AsciiTable[i].goofy.ascii == asciiCode )
{
keyCode = i;
break;
};
}
return( keyCode );
}
//------------------------------------------------------------------------------
U16 Input::getAscii( U16 keyCode, KEY_STATE keyState )
{
if ( keyCode >= NUM_KEYS )
return 0;
switch ( keyState )
{
case STATE_LOWER:
return AsciiTable[keyCode].lower.ascii;
case STATE_UPPER:
return AsciiTable[keyCode].upper.ascii;
case STATE_GOOFY:
return AsciiTable[keyCode].goofy.ascii;
default:
return(0);
}
}
//------------------------------------------------------------------------------
void Input::destroy()
{
#ifdef LOG_INPUT
if ( gInputLog )
{
log( "*** CLOSING LOG ***\n" );
CloseHandle( gInputLog );
gInputLog = NULL;
}
#endif
if ( smManager && smManager->isEnabled() )
{
smManager->disable();
delete smManager;
smManager = NULL;
}
}
//------------------------------------------------------------------------------
bool Input::enable()
{
if ( smManager && !smManager->isEnabled() )
return( smManager->enable() );
return( false );
}
//------------------------------------------------------------------------------
void Input::disable()
{
if ( smManager && smManager->isEnabled() )
smManager->disable();
}
//------------------------------------------------------------------------------
void Input::activate()
{
//#ifdef UNICODE
#if defined(TGE_RPG) || defined(UNICODE)
winState.imeHandle = ImmGetContext( winState.appWindow );
ImmReleaseContext( winState.appWindow, winState.imeHandle );
#endif
DInputDevice::resetModifierKeys();
#ifdef TGE_RPG
if ( !smEnableDirectInput )
return;
#else
if ( !Con::getBoolVariable( "$enableDirectInput" ) )
return;
#endif
if ( smManager && smManager->isEnabled() && !smActive )
{
Con::printf( "Activating DirectInput..." );
#ifdef LOG_INPUT
Input::log( "Activating DirectInput...\n" );
#endif
smActive = true;
DInputManager* dInputManager = dynamic_cast<DInputManager*>( smManager );
if ( dInputManager )
{
if ( dInputManager->isKeyboardEnabled() && smLastKeyboardActivated )
dInputManager->activateKeyboard();
if ( Video::isFullScreen() )
{
// DirectInput Mouse Hook-Up:
if ( dInputManager->isMouseEnabled() && smLastMouseActivated )
dInputManager->activateMouse();
}
else
dInputManager->deactivateMouse();
if ( dInputManager->isJoystickEnabled() && smLastJoystickActivated )
dInputManager->activateJoystick();
}
}
}
//------------------------------------------------------------------------------
void Input::deactivate()
{
if ( smManager && smManager->isEnabled() && smActive )
{
#ifdef LOG_INPUT
Input::log( "Deactivating DirectInput...\n" );
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -