📄 win_input.c
字号:
if (!g_wv.hWnd)
{
Com_Printf ("No window for DirectInput mouse init, delaying\n");
s_wmv.mouseStartupDelayed = qtrue;
return;
}
if ( IN_InitDIMouse() ) {
s_wmv.mouseInitialized = qtrue;
return;
}
Com_Printf ("Falling back to Win32 mouse support...\n");
}
s_wmv.mouseInitialized = qtrue;
IN_InitWin32Mouse();
}
/*
===========
IN_MouseEvent
===========
*/
void IN_MouseEvent (int mstate)
{
int i;
if ( !s_wmv.mouseInitialized )
return;
// perform button actions
for (i = 0 ; i < 3 ; i++ )
{
if ( (mstate & (1<<i)) &&
!(s_wmv.oldButtonState & (1<<i)) )
{
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MOUSE1 + i, qtrue, 0, NULL );
}
if ( !(mstate & (1<<i)) &&
(s_wmv.oldButtonState & (1<<i)) )
{
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MOUSE1 + i, qfalse, 0, NULL );
}
}
s_wmv.oldButtonState = mstate;
}
/*
===========
IN_MouseMove
===========
*/
void IN_MouseMove ( void ) {
int mx, my;
if ( g_pMouse ) {
IN_DIMouse( &mx, &my );
} else {
IN_Win32Mouse( &mx, &my );
}
if ( !mx && !my ) {
return;
}
Sys_QueEvent( 0, SE_MOUSE, mx, my, 0, NULL );
}
/*
=========================================================================
=========================================================================
*/
/*
===========
IN_Startup
===========
*/
void IN_Startup( void ) {
Com_Printf ("\n------- Input Initialization -------\n");
IN_StartupMouse ();
IN_StartupJoystick ();
IN_StartupMIDI();
Com_Printf ("------------------------------------\n");
in_mouse->modified = qfalse;
in_joystick->modified = qfalse;
}
/*
===========
IN_Shutdown
===========
*/
void IN_Shutdown( void ) {
IN_DeactivateMouse();
IN_ShutdownDIMouse();
IN_ShutdownMIDI();
Cmd_RemoveCommand("midiinfo" );
}
/*
===========
IN_Init
===========
*/
void IN_Init( void ) {
// MIDI input controler variables
in_midi = Cvar_Get ("in_midi", "0", CVAR_ARCHIVE);
in_midiport = Cvar_Get ("in_midiport", "1", CVAR_ARCHIVE);
in_midichannel = Cvar_Get ("in_midichannel", "1", CVAR_ARCHIVE);
in_mididevice = Cvar_Get ("in_mididevice", "0", CVAR_ARCHIVE);
Cmd_AddCommand( "midiinfo", MidiInfo_f );
// mouse variables
in_mouse = Cvar_Get ("in_mouse", "1", CVAR_ARCHIVE|CVAR_LATCH);
in_logitechbug = Cvar_Get ("in_logitechbug", "0", CVAR_ARCHIVE);
// joystick variables
in_joystick = Cvar_Get ("in_joystick", "0", CVAR_ARCHIVE|CVAR_LATCH);
in_joyBallScale = Cvar_Get ("in_joyBallScale", "0.02", CVAR_ARCHIVE);
in_debugJoystick = Cvar_Get ("in_debugjoystick", "0", CVAR_TEMP);
joy_threshold = Cvar_Get ("joy_threshold", "0.15", CVAR_ARCHIVE);
IN_Startup();
}
/*
===========
IN_Activate
Called when the main window gains or loses focus.
The window may have been destroyed and recreated
between a deactivate and an activate.
===========
*/
void IN_Activate (qboolean active) {
in_appactive = active;
if ( !active )
{
IN_DeactivateMouse();
}
}
/*
==================
IN_Frame
Called every frame, even if not generating commands
==================
*/
void IN_Frame (void) {
// post joystick events
IN_JoyMove();
if ( !s_wmv.mouseInitialized ) {
if (s_wmv.mouseStartupDelayed && g_wv.hWnd)
{
Com_Printf("Proceeding with delayed mouse init\n");
IN_StartupMouse();
s_wmv.mouseStartupDelayed = qfalse;
}
return;
}
if ( cls.keyCatchers & KEYCATCH_CONSOLE ) {
// temporarily deactivate if not in the game and
// running on the desktop
// voodoo always counts as full screen
if (Cvar_VariableValue ("r_fullscreen") == 0
&& strcmp( Cvar_VariableString("r_glDriver"), _3DFX_DRIVER_NAME) ) {
IN_DeactivateMouse ();
return;
}
}
if ( !in_appactive ) {
IN_DeactivateMouse ();
return;
}
IN_ActivateMouse();
// post events to the system que
IN_MouseMove();
}
/*
===================
IN_ClearStates
===================
*/
void IN_ClearStates (void)
{
s_wmv.oldButtonState = 0;
}
/*
=========================================================================
JOYSTICK
=========================================================================
*/
/*
===============
IN_StartupJoystick
===============
*/
void IN_StartupJoystick (void) {
int numdevs;
MMRESULT mmr;
// assume no joystick
joy.avail = qfalse;
if (! in_joystick->integer ) {
Com_Printf ("Joystick is not active.\n");
return;
}
// verify joystick driver is present
if ((numdevs = joyGetNumDevs ()) == 0)
{
Com_Printf ("joystick not found -- driver not present\n");
return;
}
// cycle through the joystick ids for the first valid one
mmr = 0;
for (joy.id=0 ; joy.id<numdevs ; joy.id++)
{
Com_Memset (&joy.ji, 0, sizeof(joy.ji));
joy.ji.dwSize = sizeof(joy.ji);
joy.ji.dwFlags = JOY_RETURNCENTERED;
if ((mmr = joyGetPosEx (joy.id, &joy.ji)) == JOYERR_NOERROR)
break;
}
// abort startup if we didn't find a valid joystick
if (mmr != JOYERR_NOERROR)
{
Com_Printf ("joystick not found -- no valid joysticks (%x)\n", mmr);
return;
}
// get the capabilities of the selected joystick
// abort startup if command fails
Com_Memset (&joy.jc, 0, sizeof(joy.jc));
if ((mmr = joyGetDevCaps (joy.id, &joy.jc, sizeof(joy.jc))) != JOYERR_NOERROR)
{
Com_Printf ("joystick not found -- invalid joystick capabilities (%x)\n", mmr);
return;
}
Com_Printf( "Joystick found.\n" );
Com_Printf( "Pname: %s\n", joy.jc.szPname );
Com_Printf( "OemVxD: %s\n", joy.jc.szOEMVxD );
Com_Printf( "RegKey: %s\n", joy.jc.szRegKey );
Com_Printf( "Numbuttons: %i / %i\n", joy.jc.wNumButtons, joy.jc.wMaxButtons );
Com_Printf( "Axis: %i / %i\n", joy.jc.wNumAxes, joy.jc.wMaxAxes );
Com_Printf( "Caps: 0x%x\n", joy.jc.wCaps );
if ( joy.jc.wCaps & JOYCAPS_HASPOV ) {
Com_Printf( "HASPOV\n" );
} else {
Com_Printf( "no POV\n" );
}
// old button and POV states default to no buttons pressed
joy.oldbuttonstate = 0;
joy.oldpovstate = 0;
// mark the joystick as available
joy.avail = qtrue;
}
/*
===========
JoyToF
===========
*/
float JoyToF( int value ) {
float fValue;
// move centerpoint to zero
value -= 32768;
// convert range from -32768..32767 to -1..1
fValue = (float)value / 32768.0;
if ( fValue < -1 ) {
fValue = -1;
}
if ( fValue > 1 ) {
fValue = 1;
}
return fValue;
}
int JoyToI( int value ) {
// move centerpoint to zero
value -= 32768;
return value;
}
int joyDirectionKeys[16] = {
K_LEFTARROW, K_RIGHTARROW,
K_UPARROW, K_DOWNARROW,
K_JOY16, K_JOY17,
K_JOY18, K_JOY19,
K_JOY20, K_JOY21,
K_JOY22, K_JOY23,
K_JOY24, K_JOY25,
K_JOY26, K_JOY27
};
/*
===========
IN_JoyMove
===========
*/
void IN_JoyMove( void ) {
float fAxisValue;
int i;
DWORD buttonstate, povstate;
int x, y;
// verify joystick is available and that the user wants to use it
if ( !joy.avail ) {
return;
}
// collect the joystick data, if possible
Com_Memset (&joy.ji, 0, sizeof(joy.ji));
joy.ji.dwSize = sizeof(joy.ji);
joy.ji.dwFlags = JOY_RETURNALL;
if ( joyGetPosEx (joy.id, &joy.ji) != JOYERR_NOERROR ) {
// read error occurred
// turning off the joystick seems too harsh for 1 read error,\
// but what should be done?
// Com_Printf ("IN_ReadJoystick: no response\n");
// joy.avail = false;
return;
}
if ( in_debugJoystick->integer ) {
Com_Printf( "%8x %5i %5.2f %5.2f %5.2f %5.2f %6i %6i\n",
joy.ji.dwButtons,
joy.ji.dwPOV,
JoyToF( joy.ji.dwXpos ), JoyToF( joy.ji.dwYpos ),
JoyToF( joy.ji.dwZpos ), JoyToF( joy.ji.dwRpos ),
JoyToI( joy.ji.dwUpos ), JoyToI( joy.ji.dwVpos ) );
}
// loop through the joystick buttons
// key a joystick event or auxillary event for higher number buttons for each state change
buttonstate = joy.ji.dwButtons;
for ( i=0 ; i < joy.jc.wNumButtons ; i++ ) {
if ( (buttonstate & (1<<i)) && !(joy.oldbuttonstate & (1<<i)) ) {
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_JOY1 + i, qtrue, 0, NULL );
}
if ( !(buttonstate & (1<<i)) && (joy.oldbuttonstate & (1<<i)) ) {
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_JOY1 + i, qfalse, 0, NULL );
}
}
joy.oldbuttonstate = buttonstate;
povstate = 0;
// convert main joystick motion into 6 direction button bits
for (i = 0; i < joy.jc.wNumAxes && i < 4 ; i++) {
// get the floating point zero-centered, potentially-inverted data for the current axis
fAxisValue = JoyToF( (&joy.ji.dwXpos)[i] );
if ( fAxisValue < -joy_threshold->value ) {
povstate |= (1<<(i*2));
} else if ( fAxisValue > joy_threshold->value ) {
povstate |= (1<<(i*2+1));
}
}
// convert POV information from a direction into 4 button bits
if ( joy.jc.wCaps & JOYCAPS_HASPOV ) {
if ( joy.ji.dwPOV != JOY_POVCENTERED ) {
if (joy.ji.dwPOV == JOY_POVFORWARD)
povstate |= 1<<12;
if (joy.ji.dwPOV == JOY_POVBACKWARD)
povstate |= 1<<13;
if (joy.ji.dwPOV == JOY_POVRIGHT)
povstate |= 1<<14;
if (joy.ji.dwPOV == JOY_POVLEFT)
povstate |= 1<<15;
}
}
// determine which bits have changed and key an auxillary event for each change
for (i=0 ; i < 16 ; i++) {
if ( (povstate & (1<<i)) && !(joy.oldpovstate & (1<<i)) ) {
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, joyDirectionKeys[i], qtrue, 0, NULL );
}
if ( !(povstate & (1<<i)) && (joy.oldpovstate & (1<<i)) ) {
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, joyDirectionKeys[i], qfalse, 0, NULL );
}
}
joy.oldpovstate = povstate;
// if there is a trackball like interface, simulate mouse moves
if ( joy.jc.wNumAxes >= 6 ) {
x = JoyToI( joy.ji.dwUpos ) * in_joyBallScale->value;
y = JoyToI( joy.ji.dwVpos ) * in_joyBallScale->value;
if ( x || y ) {
Sys_QueEvent( g_wv.sysMsgTime, SE_MOUSE, x, y, 0, NULL );
}
}
}
/*
=========================================================================
MIDI
=========================================================================
*/
static void MIDI_NoteOff( int note )
{
int qkey;
qkey = note - 60 + K_AUX1;
if ( qkey > 255 || qkey < K_AUX1 )
return;
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, qkey, qfalse, 0, NULL );
}
static void MIDI_NoteOn( int note, int velocity )
{
int qkey;
if ( velocity == 0 )
MIDI_NoteOff( note );
qkey = note - 60 + K_AUX1;
if ( qkey > 255 || qkey < K_AUX1 )
return;
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, qkey, qtrue, 0, NULL );
}
static void CALLBACK MidiInProc( HMIDIIN hMidiIn, UINT uMsg, DWORD dwInstance,
DWORD dwParam1, DWORD dwParam2 )
{
int message;
switch ( uMsg )
{
case MIM_OPEN:
break;
case MIM_CLOSE:
break;
case MIM_DATA:
message = dwParam1 & 0xff;
// note on
if ( ( message & 0xf0 ) == 0x90 )
{
if ( ( ( message & 0x0f ) + 1 ) == in_midichannel->integer )
MIDI_NoteOn( ( dwParam1 & 0xff00 ) >> 8, ( dwParam1 & 0xff0000 ) >> 16 );
}
else if ( ( message & 0xf0 ) == 0x80 )
{
if ( ( ( message & 0x0f ) + 1 ) == in_midichannel->integer )
MIDI_NoteOff( ( dwParam1 & 0xff00 ) >> 8 );
}
break;
case MIM_LONGDATA:
break;
case MIM_ERROR:
break;
case MIM_LONGERROR:
break;
}
// Sys_QueEvent( sys_msg_time, SE_KEY, wMsg, qtrue, 0, NULL );
}
static void MidiInfo_f( void )
{
int i;
const char *enableStrings[] = { "disabled", "enabled" };
Com_Printf( "\nMIDI control: %s\n", enableStrings[in_midi->integer != 0] );
Com_Printf( "port: %d\n", in_midiport->integer );
Com_Printf( "channel: %d\n", in_midichannel->integer );
Com_Printf( "current device: %d\n", in_mididevice->integer );
Com_Printf( "number of devices: %d\n", s_midiInfo.numDevices );
for ( i = 0; i < s_midiInfo.numDevices; i++ )
{
if ( i == Cvar_VariableValue( "in_mididevice" ) )
Com_Printf( "***" );
else
Com_Printf( "..." );
Com_Printf( "device %2d: %s\n", i, s_midiInfo.caps[i].szPname );
Com_Printf( "...manufacturer ID: 0x%hx\n", s_midiInfo.caps[i].wMid );
Com_Printf( "...product ID: 0x%hx\n", s_midiInfo.caps[i].wPid );
Com_Printf( "\n" );
}
}
static void IN_StartupMIDI( void )
{
int i;
if ( !Cvar_VariableValue( "in_midi" ) )
return;
//
// enumerate MIDI IN devices
//
s_midiInfo.numDevices = midiInGetNumDevs();
for ( i = 0; i < s_midiInfo.numDevices; i++ )
{
midiInGetDevCaps( i, &s_midiInfo.caps[i], sizeof( s_midiInfo.caps[i] ) );
}
//
// open the MIDI IN port
//
if ( midiInOpen( &s_midiInfo.hMidiIn,
in_mididevice->integer,
( unsigned long ) MidiInProc,
( unsigned long ) NULL,
CALLBACK_FUNCTION ) != MMSYSERR_NOERROR )
{
Com_Printf( "WARNING: could not open MIDI device %d: '%s'\n", in_mididevice->integer , s_midiInfo.caps[( int ) in_mididevice->value] );
return;
}
midiInStart( s_midiInfo.hMidiIn );
}
static void IN_ShutdownMIDI( void )
{
if ( s_midiInfo.hMidiIn )
{
midiInClose( s_midiInfo.hMidiIn );
}
Com_Memset( &s_midiInfo, 0, sizeof( s_midiInfo ) );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -