engine/platformLinux/linuxInput.cc

538 lines
11 KiB
C++
Raw Normal View History

2024-01-07 04:36:33 +00:00
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include <SDL/SDL.h>
#include <SDL/SDL_joystick.h>
#include "sdl_utils.h"
#include "engine/platformLinux/platformLinux.h"
#include "engine/platform/platformInput.h"
#include "engine/platform/event.h"
#include "engine/console/console.h"
#include "engine/platform/gameInterface.h"
#define USE_X11_TRANSLATE
#ifdef USE_X11_TRANSLATE
static void fillAsciiTable( void );
#endif
InputManager* Input::smManager = 0;
bool Input::smActive = false;
static SDL_Joystick* joystick = 0;
static int joyNumButtons = 0;
static int joyNumAxes = 0;
static int joyNumBalls = 0;
static int joyNumHats = 0;
static U8* joyHatStates = 0;
static bool cIsJoystickDetected( SimObject* obj, S32 argc, const char** argv )
{
return ( joystick != 0 );
}
static const char* cGetJoystickAxes( SimObject* obj, S32 argc, const char** argv )
{
const char* axisNames[] = { "\tX", "\tY", "\tZ", "\tR", "\tU", "\tV" };
if( joystick == 0 ) {
return "";
}
char buffer[64];
dSprintf( buffer, sizeof( buffer ), "%d", joyNumAxes );
for( U32 i = 0; i < joyNumAxes; i++ ) {
dStrcat( buffer, axisNames[i] );
}
char* returnString = Con::getReturnBuffer( dStrlen( buffer ) + 1 );
dStrcpy( returnString, buffer );
return returnString;
}
// Small helpers.
U8 getHatState( U8 hat )
{
if( joyHatStates == 0 ) {
return 0;
}
if( hat >= joyNumHats ) {
return 0;
}
return joyHatStates[hat];
}
void setHatState( U8 hat, U8 state )
{
if( joyHatStates == 0 ) {
return;
}
if( hat >= joyNumHats ) {
return;
}
joyHatStates[hat] = state;
}
void Input::init( void )
{
Con::printf( "Input init: " );
smActive = false;
Con::addCommand( "isJoystickDetected", cIsJoystickDetected, "isJoystickDetected();", 1, 1 );
Con::addCommand( "getJoystickAxes", cGetJoystickAxes, "getJoystickAxes( device );", 2, 2 );
#ifndef DEDICATED
#ifdef USE_X11_TRANSLATE
fillAsciiTable( );
#endif
sdl_InitClipboard();
Con::printf( " Clipboard initialized" );
Con::printf( " Keyboard initialized" );
Con::printf( " Mouse initialized" );
if( SDL_Init( SDL_INIT_JOYSTICK ) < 0 ) {
Con::printf( " Joystick not initialized" );
return;
}
Con::printf( " Joystick initialized" );
int numJoysticks = SDL_NumJoysticks( );
if( numJoysticks <= 0 ) {
Con::printf( " No joysticks detected" );
return;
}
int i;
for( i = 0; i < numJoysticks; i++ ) {
SDL_Joystick* temp = SDL_JoystickOpen( i );
if( temp ) {
joystick = temp;
break;
}
}
if( !joystick ) {
Con::printf( " No openable joysticks found" );
}
joyNumButtons = SDL_JoystickNumButtons( joystick );
joyNumAxes = SDL_JoystickNumAxes( joystick );
joyNumBalls = SDL_JoystickNumBalls( joystick );
joyNumHats = SDL_JoystickNumHats( joystick );
if( joyNumHats ) {
joyHatStates = new U8[joyNumHats];
dMemset( joyHatStates, 0, joyNumHats );
}
Con::printf( " Found joystick: %s", SDL_JoystickName( i ) );
Con::printf( " Buttons: %d", joyNumButtons );
Con::printf( " Axes: %d", joyNumAxes );
Con::printf( " Balls: %d", joyNumBalls );
Con::printf( " Hats: %d", joyNumHats );
#endif
}
void Input::destroy( void )
{
Con::printf( "Input shutdown" );
smActive = false;
#ifndef DEDICATED
SDL_JoystickClose( joystick );
joystick = 0;
joyNumButtons = 0;
joyNumAxes = 0;
joyNumBalls = 0;
joyNumHats = 0;
if( joyHatStates ) {
delete[] joyHatStates;
}
#endif
}
#ifdef USE_X11_TRANSLATE
typedef struct {
U16 lower;
U16 upper;
U16 goofy;
} asciiTable_t;
#define NUM_KEYS (KEY_OEM_102+1)
#define KEY_FIRST KEY_ESCAPE
static asciiTable_t asciiTable[NUM_KEYS];
// special prototype for non-visible SDL function
extern "C" Uint16 X11_KeyToUnicode( SDLKey keysym, SDLMod modifiers );
static void fillAsciiTable( void )
{
#ifndef DEDICATED
U32 keyCode = 0;
dMemset( &asciiTable, 0, sizeof( asciiTable ) );
for( keyCode = KEY_FIRST; keyCode < NUM_KEYS; keyCode++ ) {
Uint16 key = 0;
SDLKey sym = translateKeyCodeToSDL( keyCode );
SDLMod mod = 0;
// lower case
key = X11_KeyToUnicode( sym, mod );
asciiTable[keyCode].lower = key;
// upper case
mod = KMOD_SHIFT;
key = X11_KeyToUnicode( sym, mod );
asciiTable[keyCode].upper = key;
// goofy (i18n) case
mod = KMOD_MODE;
key = X11_KeyToUnicode( sym, mod );
asciiTable[keyCode].goofy = key;
}
#endif
}
U16 Input::getKeyCode( U16 asciiCode )
{
for( S32 i = KEY_FIRST; i < NUM_KEYS; i++ ) {
if( asciiTable[i].lower == asciiCode ) {
return i;
} else if( asciiTable[i].upper == asciiCode ) {
return i;
} else if( asciiTable[i].goofy == asciiCode ) {
return i;
}
}
return 0;
}
U16 Input::getAscii( U16 keyCode, KEY_STATE keyState )
{
if( keyCode >= NUM_KEYS ) {
return 0;
}
switch( keyState ) {
case STATE_LOWER:
return asciiTable[keyCode].lower;
case STATE_UPPER:
return asciiTable[keyCode].upper;
case STATE_GOOFY:
return asciiTable[keyCode].goofy;
default:
return 0;
}
}
#else
// FIXME: 'goofy' is always '0' because we suck
typedef struct {
U16 code;
U16 lower;
U16 upper;
U16 goofy;
} asciiTable_t;
static asciiTable_t asciiTable[128] =
{
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_BACKSPACE, 8, 8, 0 },
{ KEY_TAB, 9, 9, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_RETURN, 13, 13, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_ESCAPE, 27, 27, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_SPACE, 32, 32, 0 },
{ KEY_1, 49, 33, 0 },
{ KEY_APOSTROPHE, 39, 34, 0 },
{ KEY_3, 51, 35, 0 },
{ KEY_4, 52, 36, 0 },
{ KEY_5, 53, 37, 0 },
{ KEY_7, 55, 38, 0 },
{ KEY_APOSTROPHE, 39, 34, 0 },
{ KEY_9, 58, 40, 0 },
{ KEY_0, 48, 41, 0 },
{ KEY_8, 56, 42, 0 },
{ KEY_EQUALS, 61, 43, 0 }, // 43
{ KEY_COMMA, 44, 60, 0 },
{ KEY_MINUS, 45, 95, 0 },
{ KEY_PERIOD, 46, 62, 0 },
{ KEY_BACKSLASH, 47, 63, 0 },
{ KEY_0, 48, 41, 0 }, // 48
{ KEY_1, 49, 33, 0 },
{ KEY_2, 50, 64, 0 },
{ KEY_3, 51, 35, 0 },
{ KEY_4, 52, 36, 0 },
{ KEY_5, 53, 37, 0 },
{ KEY_6, 54, 94, 0 },
{ KEY_7, 54, 38, 0 },
{ KEY_8, 56, 42, 0 },
{ KEY_9, 57, 28, 0 },
{ KEY_SEMICOLON, 59, 58, 0 }, // 58
{ KEY_SEMICOLON, 59, 58, 0 },
{ KEY_COMMA, 44, 60, 0 },
{ KEY_EQUALS, 61, 43, 0 },
{ KEY_PERIOD, 46, 62, 0 },
{ KEY_BACKSLASH, 47, 63, 0 }, // 63
{ KEY_2, 50, 64, 0 },
{ KEY_A, 97, 65, 0 }, // 65
{ KEY_B, 98, 66, 0 },
{ KEY_C, 99, 67, 0 },
{ KEY_D, 100, 68, 0 },
{ KEY_E, 101, 69, 0 },
{ KEY_F, 102, 70, 0 },
{ KEY_G, 103, 71, 0 },
{ KEY_H, 104, 72, 0 },
{ KEY_I, 105, 73, 0 },
{ KEY_J, 106, 74, 0 },
{ KEY_K, 107, 75, 0 },
{ KEY_L, 108, 76, 0 },
{ KEY_M, 109, 77, 0 },
{ KEY_N, 110, 78, 0 },
{ KEY_O, 111, 79, 0 },
{ KEY_P, 112, 80, 0 },
{ KEY_Q, 113, 81, 0 },
{ KEY_R, 114, 82, 0 },
{ KEY_S, 115, 83, 0 },
{ KEY_T, 116, 84, 0 },
{ KEY_U, 117, 85, 0 },
{ KEY_V, 118, 86, 0 },
{ KEY_W, 119, 87, 0 },
{ KEY_X, 120, 88, 0 },
{ KEY_Y, 121, 89, 0 },
{ KEY_Z, 122, 90, 0 },
{ KEY_LBRACKET, 91, 123, 0 }, // 91
{ KEY_SLASH, 92, 124, 0 },
{ KEY_RBRACKET, 93, 125, 0 },
{ KEY_6, 54, 94, 0 },
{ KEY_MINUS, 45, 95, 0 },
{ KEY_TILDE, 96, 126, 0 },
{ KEY_A, 97, 65, 0 }, // 97
{ KEY_B, 98, 66, 0 },
{ KEY_C, 99, 67, 0 },
{ KEY_D, 100, 68, 0 },
{ KEY_E, 101, 69, 0 },
{ KEY_F, 102, 70, 0 },
{ KEY_G, 103, 71, 0 },
{ KEY_H, 104, 72, 0 },
{ KEY_I, 105, 73, 0 },
{ KEY_J, 106, 74, 0 },
{ KEY_K, 107, 75, 0 },
{ KEY_L, 108, 76, 0 },
{ KEY_M, 109, 77, 0 },
{ KEY_N, 110, 78, 0 },
{ KEY_O, 111, 79, 0 },
{ KEY_P, 112, 80, 0 },
{ KEY_Q, 113, 81, 0 },
{ KEY_R, 114, 82, 0 },
{ KEY_S, 115, 83, 0 },
{ KEY_T, 116, 84, 0 },
{ KEY_U, 117, 85, 0 },
{ KEY_V, 118, 86, 0 },
{ KEY_W, 119, 87, 0 },
{ KEY_X, 120, 88, 0 },
{ KEY_Y, 121, 89, 0 },
{ KEY_Z, 122, 90, 0 },
{ KEY_LBRACKET, 91, 123, 0 }, // 123
{ KEY_SLASH, 92, 124, 0 },
{ KEY_RBRACKET, 93, 125, 0 },
{ KEY_TILDE, 94, 126, 0 },
{ KEY_DELETE, 127, 127, 0 }, // 127
};
U16 Input::getKeyCode( U16 asciiCode )
{
if( asciiCode < sizeof( asciiTable ) ) {
return asciiTable[asciiCode].code;
} else {
return 0;
}
}
U16 Input::getAscii( U16 keyCode, KEY_STATE whichOne )
{
for( S32 i = 0; i < sizeof( asciiTable ); i++ ) {
if( asciiTable[i].code == keyCode ) {
switch( whichOne ) {
case STATE_LOWER:
case STATE_GOOFY:
return asciiTable[i].lower;
case STATE_UPPER:
return asciiTable[i].upper;
}
}
}
return 0;
}
#endif
bool Input::enable( void )
{
return true;
}
void Input::disable( void )
{
}
void Input::activate( void )
{
smActive = true;
}
void Input::deactivate( void )
{
smActive = false;
}
void Input::reactivate( void )
{
// Sorry, needed this indirection for Windows...
Input::activate();
}
bool Input::isEnabled( void )
{
return true;
}
bool Input::isActive( void )
{
return smActive;
}
// bool Input::isKeyboardActive( void )
// {
// return true;
// }
//
// bool Input::isMouseActive( void )
// {
// return true;
// }
//
// bool Input::isJoystickActive( void )
// {
// return ( joystick != 0 );
// }
static JoystickCodes translateAxis( U8 axis )
{
JoystickCodes array[] = { SI_XAXIS, SI_YAXIS, SI_ZAXIS,
SI_RXAXIS, SI_RYAXIS, SI_RZAXIS };
axis = ( axis < 6 ) ? axis : 5;
return array[axis];
}
static void processAxes( void )
{
#ifndef DEDICATED
InputEvent event;
// we need continuous reporting for joystick axes
for( S32 i = 0; i < joyNumAxes; i++ ) {
S16 value = SDL_JoystickGetAxis( joystick, i );
event.deviceInst = 0;
event.deviceType = JoystickDeviceType;
event.objType = translateAxis( i );
event.objInst = 0;
event.action = SI_MOVE;
event.modifier = 0;
event.ascii = 0;
event.fValue = static_cast<float>( value ) / 32767.0f;
Game->postEvent( event );
}
#endif
}
void Input::process( void )
{
// do our immediate processing here
processAxes( );
}
//-----------------------------------------------------------------------------
// Clipboard functions
const char* Platform::getClipboard()
{
#ifdef DEDICATED
return "";
#else
return sdl_GetClipboard();
#endif
}
bool Platform::setClipboard(const char *text)
{
#ifdef DEDICATED
return false;
#else
if (!text)
return false;
sdl_PutClipboard(text);
return true;
#endif
}