{"AUX31", K_AUX31},
{"AUX32", K_AUX32},
+ {"X360_DPAD_UP", K_X360_DPAD_UP},
+ {"X360_DPAD_DOWN", K_X360_DPAD_DOWN},
+ {"X360_DPAD_LEFT", K_X360_DPAD_LEFT},
+ {"X360_DPAD_RIGHT", K_X360_DPAD_RIGHT},
+ {"X360_START", K_X360_START},
+ {"X360_BACK", K_X360_BACK},
+ {"X360_LEFT_THUMB", K_X360_LEFT_THUMB},
+ {"X360_RIGHT_THUMB", K_X360_RIGHT_THUMB},
+ {"X360_LEFT_SHOULDER", K_X360_LEFT_SHOULDER},
+ {"X360_RIGHT_SHOULDER", K_X360_RIGHT_SHOULDER},
+ {"X360_A", K_X360_A},
+ {"X360_B", K_X360_B},
+ {"X360_X", K_X360_X},
+ {"X360_Y", K_X360_Y},
+ {"X360_LEFT_TRIGGER", K_X360_LEFT_TRIGGER},
+ {"X360_RIGHT_TRIGGER", K_X360_RIGHT_TRIGGER},
+ {"X360_LEFT_THUMB_UP", K_X360_LEFT_THUMB_UP},
+ {"X360_LEFT_THUMB_DOWN", K_X360_LEFT_THUMB_DOWN},
+ {"X360_LEFT_THUMB_LEFT", K_X360_LEFT_THUMB_LEFT},
+ {"X360_LEFT_THUMB_RIGHT", K_X360_LEFT_THUMB_RIGHT},
+ {"X360_RIGHT_THUMB_UP", K_X360_RIGHT_THUMB_UP},
+ {"X360_RIGHT_THUMB_DOWN", K_X360_RIGHT_THUMB_DOWN},
+ {"X360_RIGHT_THUMB_LEFT", K_X360_RIGHT_THUMB_LEFT},
+ {"X360_RIGHT_THUMB_RIGHT", K_X360_RIGHT_THUMB_RIGHT},
+
{"SEMICOLON", ';'}, // because a raw semicolon separates commands
{"TILDE", '~'},
{"BACKQUOTE", '`'},
K_AUX31,
K_AUX32,
+ // Microsoft Xbox 360 Controller For Windows
+ K_X360_DPAD_UP,
+ K_X360_DPAD_DOWN,
+ K_X360_DPAD_LEFT,
+ K_X360_DPAD_RIGHT,
+ K_X360_START,
+ K_X360_BACK,
+ K_X360_LEFT_THUMB,
+ K_X360_RIGHT_THUMB,
+ K_X360_LEFT_SHOULDER,
+ K_X360_RIGHT_SHOULDER,
+ K_X360_A,
+ K_X360_B,
+ K_X360_X,
+ K_X360_Y,
+ K_X360_LEFT_TRIGGER,
+ K_X360_RIGHT_TRIGGER,
+ K_X360_LEFT_THUMB_UP,
+ K_X360_LEFT_THUMB_DOWN,
+ K_X360_LEFT_THUMB_LEFT,
+ K_X360_LEFT_THUMB_RIGHT,
+ K_X360_RIGHT_THUMB_UP,
+ K_X360_RIGHT_THUMB_DOWN,
+ K_X360_RIGHT_THUMB_LEFT,
+ K_X360_RIGHT_THUMB_RIGHT,
+
K_MIDINOTE0 = 896, // to this, the note number is added
K_MIDINOTE1,
K_MIDINOTE2,
extern void (*vid_menudrawfn)(void);
extern void (*vid_menukeyfn)(int key);
+#define MAXJOYAXIS 16
+// if this is changed, the corresponding code in vid_shared.c must be updated
+#define MAXJOYBUTTON 36
+typedef struct vid_joystate_s
+{
+ float axis[MAXJOYAXIS]; // -1 to +1
+ unsigned char button[MAXJOYBUTTON]; // 0 or 1
+ qboolean is360; // indicates this joystick is a Microsoft Xbox 360 Controller For Windows
+}
+vid_joystate_t;
+
+extern vid_joystate_t vid_joystate;
+
+extern cvar_t joy_index;
+extern cvar_t joy_enable;
+extern cvar_t joy_detected;
+extern cvar_t joy_active;
+
+float VID_JoyState_GetAxis(const vid_joystate_t *joystate, int axis, float sensitivity, float deadzone);
+void VID_ApplyJoyState(vid_joystate_t *joystate);
+void VID_BuildJoyState(vid_joystate_t *joystate);
+void VID_Shared_BuildJoyState_Begin(vid_joystate_t *joystate);
+void VID_Shared_BuildJoyState_Finish(vid_joystate_t *joystate);
+int VID_Shared_SetJoystick(int index);
+qboolean VID_JoyBlockEmulatedKeys(int keycode);
+void VID_EnableJoystick(qboolean enable);
+
extern qboolean vid_hidden;
extern qboolean vid_activewindow;
extern cvar_t vid_hardwaregammasupported;
if (context == NULL && window == NULL)
return;
+ VID_EnableJoystick(false);
VID_SetMouse(false, false, false);
VID_RestoreSystemGamma();
}
}
+void VID_BuildJoyState(vid_joystate_t *joystate)
+{
+ VID_Shared_BuildJoyState_Begin(joystate);
+ VID_Shared_BuildJoyState_Finish(joystate);
+}
+
+void VID_EnableJoystick(qboolean enable)
+{
+ int index = joy_enable.integer > 0 ? joy_index.integer : -1;
+ qboolean success = false;
+ int sharedcount = 0;
+ sharedcount = VID_Shared_SetJoystick(index);
+ if (index >= 0 && index < sharedcount)
+ success = true;
+
+ // update cvar containing count of XInput joysticks
+ if (joy_detected.integer != sharedcount)
+ Cvar_SetValueQuick(&joy_detected, sharedcount);
+
+ Cvar_SetValueQuick(&joy_active, success ? 1 : 0);
+}
+
void IN_Move (void)
{
+ vid_joystate_t joystate;
+ VID_EnableJoystick(true);
+ VID_BuildJoyState(&joystate);
+ VID_ApplyJoyState(&joystate);
}
static bool GetDictionaryBoolean(CFDictionaryRef d, const void *key)
if (!vidx11_display)
return;
+ VID_EnableJoystick(false);
VID_SetMouse(false, false, false);
VID_RestoreSystemGamma();
HandleEvents();
}
+void VID_BuildJoyState(vid_joystate_t *joystate)
+{
+ VID_Shared_BuildJoyState_Begin(joystate);
+ VID_Shared_BuildJoyState_Finish(joystate);
+}
+
+void VID_EnableJoystick(qboolean enable)
+{
+ int index = joy_enable.integer > 0 ? joy_index.integer : -1;
+ qboolean success = false;
+ int sharedcount = 0;
+ sharedcount = VID_Shared_SetJoystick(index);
+ if (index >= 0 && index < sharedcount)
+ success = true;
+
+ // update cvar containing count of XInput joysticks
+ if (joy_detected.integer != sharedcount)
+ Cvar_SetValueQuick(&joy_detected, sharedcount);
+
+ Cvar_SetValueQuick(&joy_active, success ? 1 : 0);
+}
+
void IN_Move (void)
{
+ vid_joystate_t joystate;
+ VID_EnableJoystick(true);
+ VID_BuildJoyState(&joystate);
+ VID_ApplyJoyState(&joystate);
}
size_t VID_ListModes(vid_mode_t *modes, size_t maxcount)
{
}
+void VID_BuildJoyState(vid_joystate_t *joystate)
+{
+}
+
void IN_Move(void)
{
}
qboolean vid_supportrefreshrate = false;
-cvar_t joy_detected = {CVAR_READONLY, "joy_detected", "0", "number of joysticks detected by engine"};
-cvar_t joy_enable = {CVAR_SAVE, "joy_enable", "0", "enables joystick support"};
-cvar_t joy_index = {0, "joy_index", "0", "selects which joystick to use if you have multiple"};
-cvar_t joy_axisforward = {0, "joy_axisforward", "1", "which joystick axis to query for forward/backward movement"};
-cvar_t joy_axisside = {0, "joy_axisside", "0", "which joystick axis to query for right/left movement"};
-cvar_t joy_axisup = {0, "joy_axisup", "-1", "which joystick axis to query for up/down movement"};
-cvar_t joy_axispitch = {0, "joy_axispitch", "3", "which joystick axis to query for looking up/down"};
-cvar_t joy_axisyaw = {0, "joy_axisyaw", "2", "which joystick axis to query for looking right/left"};
-cvar_t joy_axisroll = {0, "joy_axisroll", "-1", "which joystick axis to query for tilting head right/left"};
-cvar_t joy_deadzoneforward = {0, "joy_deadzoneforward", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
-cvar_t joy_deadzoneside = {0, "joy_deadzoneside", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
-cvar_t joy_deadzoneup = {0, "joy_deadzoneup", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
-cvar_t joy_deadzonepitch = {0, "joy_deadzonepitch", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
-cvar_t joy_deadzoneyaw = {0, "joy_deadzoneyaw", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
-cvar_t joy_deadzoneroll = {0, "joy_deadzoneroll", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
-cvar_t joy_sensitivityforward = {0, "joy_sensitivityforward", "-1", "movement multiplier"};
-cvar_t joy_sensitivityside = {0, "joy_sensitivityside", "1", "movement multiplier"};
-cvar_t joy_sensitivityup = {0, "joy_sensitivityup", "1", "movement multiplier"};
-cvar_t joy_sensitivitypitch = {0, "joy_sensitivitypitch", "1", "movement multiplier"};
-cvar_t joy_sensitivityyaw = {0, "joy_sensitivityyaw", "-1", "movement multiplier"};
-cvar_t joy_sensitivityroll = {0, "joy_sensitivityroll", "1", "movement multiplier"};
-cvar_t joy_axiskeyevents = {CVAR_SAVE, "joy_axiskeyevents", "0", "generate uparrow/leftarrow etc. keyevents for joystick axes, use if your joystick driver is not generating them"};
-cvar_t joy_axiskeyevents_deadzone = {CVAR_SAVE, "joy_axiskeyevents_deadzone", "0.5", "deadzone value for axes"};
-
#ifdef USE_GLES2
# define SETVIDEOMODE 0
#else
#else
static qboolean vid_usingvsync = false;
#endif
-static int vid_numjoysticks = 0;
-#define MAX_JOYSTICKS 8
-static SDL_Joystick *vid_joysticks[MAX_JOYSTICKS];
+static SDL_Joystick *vid_sdljoystick = NULL;
static int win_half_width = 50;
static int win_half_height = 50;
#endif
static SDL_Surface *vid_softsurface;
-// joystick axes state
-#define MAX_JOYSTICK_AXES 16
-typedef struct
-{
- float oldmove;
- float move;
- double keytime;
-}joy_axiscache_t;
-static joy_axiscache_t joy_axescache[MAX_JOYSTICK_AXES];
-
/////////////////////////
// Input handling
////
-//TODO: Add joystick support
//TODO: Add error checking
#ifndef SDLK_PERCENT
#endif
}
-static double IN_JoystickGetAxis(SDL_Joystick *joy, int axis, double sensitivity, double deadzone)
-{
- double value;
- if (axis < 0 || axis >= SDL_JoystickNumAxes(joy))
- return 0; // no such axis on this joystick
- value = SDL_JoystickGetAxis(joy, axis) * (1.0 / 32767.0);
- value = bound(-1, value, 1);
- if (fabs(value) < deadzone)
- return 0; // within deadzone around center
- return value * sensitivity;
-}
-
-/////////////////////
-// Joystick axis keyevents
-// a sort of hack emulating Arrow keys for joystick axises
-// as some drives dont send such keyevents for them
-// additionally we should block drivers that do send arrow keyevents to prevent double events
-////
-
-static void IN_JoystickKeyeventForAxis(SDL_Joystick *joy, int axis, int key_pos, int key_neg)
-{
- double joytime;
-
- if (axis < 0 || axis >= SDL_JoystickNumAxes(joy))
- return; // no such axis on this joystick
-
- joytime = Sys_DoubleTime();
- // no key event, continuous keydown event
- if (joy_axescache[axis].move == joy_axescache[axis].oldmove)
- {
- if (joy_axescache[axis].move != 0 && joytime > joy_axescache[axis].keytime)
- {
- //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].move > 0) ? key_pos : key_neg), 1, cl.time);
- Key_Event((joy_axescache[axis].move > 0) ? key_pos : key_neg, 0, 1);
- joy_axescache[axis].keytime = joytime + 0.5 / 20;
- }
- return;
- }
- // generate key up event
- if (joy_axescache[axis].oldmove)
- {
- //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].oldmove > 0) ? key_pos : key_neg), 1, cl.time);
- Key_Event((joy_axescache[axis].oldmove > 0) ? key_pos : key_neg, 0, 0);
- }
- // generate key down event
- if (joy_axescache[axis].move)
- {
- //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].move > 0) ? key_pos : key_neg), 1, cl.time);
- Key_Event((joy_axescache[axis].move > 0) ? key_pos : key_neg, 0, 1);
- joy_axescache[axis].keytime = joytime + 0.5;
- }
-}
-
-static qboolean IN_JoystickBlockDoubledKeyEvents(int keycode)
-{
- if (!joy_axiskeyevents.integer)
- return false;
-
- // block keyevent if it's going to be provided by joystick keyevent system
- if (vid_numjoysticks && joy_enable.integer && joy_index.integer >= 0 && joy_index.integer < vid_numjoysticks)
- {
- SDL_Joystick *joy = vid_joysticks[joy_index.integer];
-
- if (keycode == K_UPARROW || keycode == K_DOWNARROW)
- if (IN_JoystickGetAxis(joy, joy_axisforward.integer, 1, joy_axiskeyevents_deadzone.value) || joy_axescache[joy_axisforward.integer].move || joy_axescache[joy_axisforward.integer].oldmove)
- return true;
- if (keycode == K_RIGHTARROW || keycode == K_LEFTARROW)
- if (IN_JoystickGetAxis(joy, joy_axisside.integer, 1, joy_axiskeyevents_deadzone.value) || joy_axescache[joy_axisside.integer].move || joy_axescache[joy_axisside.integer].oldmove)
- return true;
- }
-
- return false;
-}
-
// multitouch[10][] represents the mouse pointer
// X and Y coordinates are 0-32767 as per SDL spec
#define MAXFINGERS 11
return button;
}
+void VID_BuildJoyState(vid_joystate_t *joystate)
+{
+ VID_Shared_BuildJoyState_Begin(joystate);
+
+ if (vid_sdljoystick)
+ {
+ SDL_Joystick *joy = vid_sdljoystick;
+ int j;
+ int numaxes;
+ int numbuttons;
+ numaxes = SDL_JoystickNumAxes(joy);
+ for (j = 0;j < numaxes;j++)
+ joystate->axis[j] = SDL_JoystickGetAxis(joy, j) * (1.0f / 32767.0f);
+ numbuttons = SDL_JoystickNumButtons(joy);
+ for (j = 0;j < numbuttons;j++)
+ joystate->button[j] = SDL_JoystickGetButton(joy, j);
+ }
+
+ VID_Shared_BuildJoyState_Finish(joystate);
+}
+
/////////////////////
// Movement handling
////
void IN_Move( void )
{
- int j;
static int old_x = 0, old_y = 0;
static int stuck = 0;
- int x, y, numaxes, numballs;
+ int x, y;
+ vid_joystate_t joystate;
scr_numtouchscreenareas = 0;
if (vid_touchscreen.integer)
in_windowmouse_y = y;
}
- if (vid_numjoysticks && joy_enable.integer && joy_index.integer >= 0 && joy_index.integer < vid_numjoysticks)
- {
- SDL_Joystick *joy = vid_joysticks[joy_index.integer];
-
- // balls convert to mousemove
- numballs = SDL_JoystickNumBalls(joy);
- for (j = 0;j < numballs;j++)
- {
- SDL_JoystickGetBall(joy, j, &x, &y);
- in_mouse_x += x;
- in_mouse_y += y;
- }
-
- // axes
- cl.cmd.forwardmove += IN_JoystickGetAxis(joy, joy_axisforward.integer, joy_sensitivityforward.value, joy_deadzoneforward.value) * cl_forwardspeed.value;
- cl.cmd.sidemove += IN_JoystickGetAxis(joy, joy_axisside.integer, joy_sensitivityside.value, joy_deadzoneside.value) * cl_sidespeed.value;
- cl.cmd.upmove += IN_JoystickGetAxis(joy, joy_axisup.integer, joy_sensitivityup.value, joy_deadzoneup.value) * cl_upspeed.value;
- cl.viewangles[0] += IN_JoystickGetAxis(joy, joy_axispitch.integer, joy_sensitivitypitch.value, joy_deadzonepitch.value) * cl.realframetime * cl_pitchspeed.value;
- cl.viewangles[1] += IN_JoystickGetAxis(joy, joy_axisyaw.integer, joy_sensitivityyaw.value, joy_deadzoneyaw.value) * cl.realframetime * cl_yawspeed.value;
- //cl.viewangles[2] += IN_JoystickGetAxis(joy, joy_axisroll.integer, joy_sensitivityroll.value, joy_deadzoneroll.value) * cl.realframetime * cl_rollspeed.value;
-
- // cache state of axes to emulate button events for them
- numaxes = min(MAX_JOYSTICK_AXES, SDL_JoystickNumAxes(joy));
- for (j = 0; j < numaxes; j++)
- {
- joy_axescache[j].oldmove = joy_axescache[j].move;
- joy_axescache[j].move = IN_JoystickGetAxis(joy, j, 1, joy_axiskeyevents_deadzone.value);
- }
-
- // run keyevents
- if (joy_axiskeyevents.integer)
- {
- IN_JoystickKeyeventForAxis(joy, joy_axisforward.integer, K_DOWNARROW, K_UPARROW);
- IN_JoystickKeyeventForAxis(joy, joy_axisside.integer, K_RIGHTARROW, K_LEFTARROW);
- }
- }
+ VID_BuildJoyState(&joystate);
+ VID_ApplyJoyState(&joystate);
}
/////////////////////
int keycode;
SDL_Event event;
+ VID_EnableJoystick(true);
+
while( SDL_PollEvent( &event ) )
switch( event.type ) {
case SDL_QUIT:
case SDL_KEYDOWN:
case SDL_KEYUP:
keycode = MapKey(event.key.keysym.sym);
- if (!IN_JoystickBlockDoubledKeyEvents(keycode))
+ if (!VID_JoyBlockEmulatedKeys(keycode))
Key_Event(keycode, event.key.keysym.unicode, (event.key.state == SDL_PRESSED));
break;
case SDL_ACTIVEEVENT:
Key_Event( buttonremap[event.button.button - 1], 0, event.button.state == SDL_PRESSED );
break;
case SDL_JOYBUTTONDOWN:
- if (!joy_enable.integer)
- break; // ignore down events if joystick has been disabled
case SDL_JOYBUTTONUP:
- if (event.jbutton.button < 48)
- Key_Event( event.jbutton.button + (event.jbutton.button < 16 ? K_JOY1 : K_AUX1 - 16), 0, (event.jbutton.state == SDL_PRESSED) );
- break;
case SDL_JOYAXISMOTION:
case SDL_JOYBALLMOTION:
case SDL_JOYHATMOTION:
int unicode;
SDL_Event event;
+ VID_EnableJoystick(true);
+
while( SDL_PollEvent( &event ) )
switch( event.type ) {
case SDL_QUIT:
case SDL_KEYDOWN:
case SDL_KEYUP:
keycode = MapKey(event.key.keysym.sym);
- if (!IN_JoystickBlockDoubledKeyEvents(keycode))
-#ifdef __IPHONEOS__
- // the virtual keyboard seems to produce no unicode values...
- if (missingunicodehack && keycode >= ' ' && keycode < 0x7F && event.key.keysym.unicode == 0)
- {
- Con_DPrintf("SDL hack: no unicode value reported, substituting ascii value %i\n", keycode);
- Key_Event(keycode, keycode, (event.key.state == SDL_PRESSED));
- }
- else
-#endif
+ if (!VID_JoyBlockEmulatedKeys(keycode))
Key_Event(keycode, 0, (event.key.state == SDL_PRESSED));
break;
case SDL_MOUSEBUTTONDOWN:
Key_Event( buttonremap[event.button.button - 1], 0, event.button.state == SDL_PRESSED );
break;
case SDL_JOYBUTTONDOWN:
- if (!joy_enable.integer)
- break; // ignore down events if joystick has been disabled
case SDL_JOYBUTTONUP:
- if (event.jbutton.button < 48)
- Key_Event( event.jbutton.button + (event.jbutton.button < 16 ? K_JOY1 : K_AUX1 - 16), 0, (event.jbutton.state == SDL_PRESSED) );
- break;
case SDL_JOYAXISMOTION:
case SDL_JOYBALLMOTION:
case SDL_JOYHATMOTION:
case SDL_TOUCHBUTTONUP:
// not sure what to do with this...
break;
- case SDL_JOYAXISMOTION:
- // we poll the joystick instead
- break;
- case SDL_JOYBALLMOTION:
- // we poll the joystick instead
- break;
- case SDL_JOYHATMOTION:
- // we poll the joystick instead
- break;
default:
Con_DPrintf("Received unrecognized SDL_Event type 0x%x\n", event.type);
break;
Cvar_RegisterVariable(&apple_mouse_noaccel);
#endif
#endif
- Cvar_RegisterVariable(&joy_detected);
- Cvar_RegisterVariable(&joy_enable);
- Cvar_RegisterVariable(&joy_index);
- Cvar_RegisterVariable(&joy_axisforward);
- Cvar_RegisterVariable(&joy_axisside);
- Cvar_RegisterVariable(&joy_axisup);
- Cvar_RegisterVariable(&joy_axispitch);
- Cvar_RegisterVariable(&joy_axisyaw);
- //Cvar_RegisterVariable(&joy_axisroll);
- Cvar_RegisterVariable(&joy_deadzoneforward);
- Cvar_RegisterVariable(&joy_deadzoneside);
- Cvar_RegisterVariable(&joy_deadzoneup);
- Cvar_RegisterVariable(&joy_deadzonepitch);
- Cvar_RegisterVariable(&joy_deadzoneyaw);
- //Cvar_RegisterVariable(&joy_deadzoneroll);
- Cvar_RegisterVariable(&joy_sensitivityforward);
- Cvar_RegisterVariable(&joy_sensitivityside);
- Cvar_RegisterVariable(&joy_sensitivityup);
- Cvar_RegisterVariable(&joy_sensitivitypitch);
- Cvar_RegisterVariable(&joy_sensitivityyaw);
- //Cvar_RegisterVariable(&joy_sensitivityroll);
- Cvar_RegisterVariable(&joy_axiskeyevents);
- Cvar_RegisterVariable(&joy_axiskeyevents_deadzone);
#ifdef __IPHONEOS__
Cvar_SetValueQuick(&vid_touchscreen, 1);
#endif
vid_isfullscreen = false;
}
+static int vid_sdljoystickindex = -1;
+void VID_EnableJoystick(qboolean enable)
+{
+ int index = joy_enable.integer > 0 ? joy_index.integer : -1;
+ int numsdljoysticks;
+ qboolean success = false;
+ int sharedcount = 0;
+ int sdlindex = -1;
+ sharedcount = VID_Shared_SetJoystick(index);
+ if (index >= 0 && index < sharedcount)
+ success = true;
+ sdlindex = index - sharedcount;
+
+ numsdljoysticks = SDL_NumJoysticks();
+ if (sdlindex < 0 || sdlindex >= numsdljoysticks)
+ sdlindex = -1;
+
+ // update cvar containing count of XInput joysticks + SDL joysticks
+ if (joy_detected.integer != sharedcount + numsdljoysticks)
+ Cvar_SetValueQuick(&joy_detected, sharedcount + numsdljoysticks);
+
+ if (vid_sdljoystickindex != sdlindex)
+ {
+ vid_sdljoystickindex = sdlindex;
+ // close SDL joystick if active
+ if (vid_sdljoystick)
+ SDL_JoystickClose(vid_sdljoystick);
+ vid_sdljoystick = NULL;
+ if (sdlindex >= 0)
+ {
+ vid_sdljoystick = SDL_JoystickOpen(sdlindex);
+ if (vid_sdljoystick)
+ Con_Printf("Joystick %i opened (SDL_Joystick %i is \"%s\" with %i axes, %i buttons, %i balls)\n", index, sdlindex, SDL_JoystickName(sdlindex), (int)SDL_JoystickNumAxes(vid_sdljoystick), (int)SDL_JoystickNumButtons(vid_sdljoystick), (int)SDL_JoystickNumBalls(vid_sdljoystick));
+ else
+ {
+ Con_Printf("Joystick %i failed (SDL_JoystickOpen(%i) returned: %s)\n", index, sdlindex, SDL_GetError());
+ sdlindex = -1;
+ }
+ }
+ }
+
+ if (sdlindex >= 0)
+ success = true;
+
+ Cvar_SetValueQuick(&joy_active, success ? 1 : 0);
+}
+
#if SETVIDEOMODE
// set the icon (we dont use SDL here since it would be too much a PITA)
#ifdef WIN32
GL_Init();
#endif
- vid_numjoysticks = SDL_NumJoysticks();
- vid_numjoysticks = bound(0, vid_numjoysticks, MAX_JOYSTICKS);
- Cvar_SetValueQuick(&joy_detected, vid_numjoysticks);
- Con_Printf("%d SDL joystick(s) found:\n", vid_numjoysticks);
- memset(vid_joysticks, 0, sizeof(vid_joysticks));
- for (i = 0;i < vid_numjoysticks;i++)
- {
- SDL_Joystick *joy;
- joy = vid_joysticks[i] = SDL_JoystickOpen(i);
- if (!joy)
- {
- Con_Printf("joystick #%i: open failed: %s\n", i, SDL_GetError());
- continue;
- }
- Con_Printf("joystick #%i: opened \"%s\" with %i axes, %i buttons, %i balls\n", i, SDL_JoystickName(i), (int)SDL_JoystickNumAxes(joy), (int)SDL_JoystickNumButtons(joy), (int)SDL_JoystickNumBalls(joy));
- }
-
vid_hidden = false;
vid_activewindow = false;
vid_hasfocus = true;
qboolean VID_InitModeSoft(viddef_mode_t *mode)
{
- int i;
#if SETVIDEOMODE
int flags = SDL_HWSURFACE;
if(!COM_CheckParm("-noasyncblit")) flags |= SDL_ASYNCBLIT;
VID_Soft_SharedSetup();
- vid_numjoysticks = SDL_NumJoysticks();
- vid_numjoysticks = bound(0, vid_numjoysticks, MAX_JOYSTICKS);
- Cvar_SetValueQuick(&joy_detected, vid_numjoysticks);
- Con_Printf("%d SDL joystick(s) found:\n", vid_numjoysticks);
- memset(vid_joysticks, 0, sizeof(vid_joysticks));
- for (i = 0;i < vid_numjoysticks;i++)
- {
- SDL_Joystick *joy;
- joy = vid_joysticks[i] = SDL_JoystickOpen(i);
- if (!joy)
- {
- Con_Printf("joystick #%i: open failed: %s\n", i, SDL_GetError());
- continue;
- }
- Con_Printf("joystick #%i: opened \"%s\" with %i axes, %i buttons, %i balls\n", i, SDL_JoystickName(i), (int)SDL_JoystickNumAxes(joy), (int)SDL_JoystickNumButtons(joy), (int)SDL_JoystickNumBalls(joy));
- }
-
vid_hidden = false;
vid_activewindow = false;
vid_hasfocus = true;
void VID_Shutdown (void)
{
+ VID_EnableJoystick(false);
VID_SetMouse(false, false, false);
VID_RestoreSystemGamma();
LPDIRECT3DDEVICE9 vid_d3d9dev;
#endif
+#ifdef WIN32
+//#include <XInput.h>
+#define XINPUT_GAMEPAD_DPAD_UP 0x0001
+#define XINPUT_GAMEPAD_DPAD_DOWN 0x0002
+#define XINPUT_GAMEPAD_DPAD_LEFT 0x0004
+#define XINPUT_GAMEPAD_DPAD_RIGHT 0x0008
+#define XINPUT_GAMEPAD_START 0x0010
+#define XINPUT_GAMEPAD_BACK 0x0020
+#define XINPUT_GAMEPAD_LEFT_THUMB 0x0040
+#define XINPUT_GAMEPAD_RIGHT_THUMB 0x0080
+#define XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100
+#define XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200
+#define XINPUT_GAMEPAD_A 0x1000
+#define XINPUT_GAMEPAD_B 0x2000
+#define XINPUT_GAMEPAD_X 0x4000
+#define XINPUT_GAMEPAD_Y 0x8000
+#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849
+#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
+#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
+#define XUSER_INDEX_ANY 0x000000FF
+
+typedef struct xinput_gamepad_s
+{
+ WORD wButtons;
+ BYTE bLeftTrigger;
+ BYTE bRightTrigger;
+ SHORT sThumbLX;
+ SHORT sThumbLY;
+ SHORT sThumbRX;
+ SHORT sThumbRY;
+}
+xinput_gamepad_t;
+
+typedef struct xinput_state_s
+{
+ DWORD dwPacketNumber;
+ xinput_gamepad_t Gamepad;
+}
+xinput_state_t;
+
+typedef struct xinput_keystroke_s
+{
+ WORD VirtualKey;
+ WCHAR Unicode;
+ WORD Flags;
+ BYTE UserIndex;
+ BYTE HidCode;
+}
+xinput_keystroke_t;
+
+DWORD (WINAPI *qXInputGetState)(DWORD index, xinput_state_t *state);
+DWORD (WINAPI *qXInputGetKeystroke)(DWORD index, DWORD reserved, xinput_keystroke_t *keystroke);
+
+qboolean vid_xinputinitialized = false;
+int vid_xinputindex = -1;
+#endif
+
// global video state
viddef_t vid;
// let go of the mouse, turn off sound, and restore system gamma ramps...
qboolean vid_activewindow = true;
+vid_joystate_t vid_joystate;
+
+#ifdef WIN32
+cvar_t joy_xinputavailable = {CVAR_READONLY, "joy_xinputavailable", "0", "indicates which devices are being reported by the Windows XInput API (first controller = 1, second = 2, third = 4, fourth = 8, added together)"};
+#endif
+cvar_t joy_active = {CVAR_READONLY, "joy_active", "0", "indicates that a joystick is active (detected and enabled)"};
+cvar_t joy_detected = {CVAR_READONLY, "joy_detected", "0", "number of joysticks detected by engine"};
+cvar_t joy_enable = {CVAR_SAVE, "joy_enable", "0", "enables joystick support"};
+cvar_t joy_index = {0, "joy_index", "0", "selects which joystick to use if you have multiple (0 uses the first controller, 1 uses the second, ...)"};
+cvar_t joy_axisforward = {0, "joy_axisforward", "1", "which joystick axis to query for forward/backward movement"};
+cvar_t joy_axisside = {0, "joy_axisside", "0", "which joystick axis to query for right/left movement"};
+cvar_t joy_axisup = {0, "joy_axisup", "-1", "which joystick axis to query for up/down movement"};
+cvar_t joy_axispitch = {0, "joy_axispitch", "3", "which joystick axis to query for looking up/down"};
+cvar_t joy_axisyaw = {0, "joy_axisyaw", "2", "which joystick axis to query for looking right/left"};
+cvar_t joy_axisroll = {0, "joy_axisroll", "-1", "which joystick axis to query for tilting head right/left"};
+cvar_t joy_deadzoneforward = {0, "joy_deadzoneforward", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
+cvar_t joy_deadzoneside = {0, "joy_deadzoneside", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
+cvar_t joy_deadzoneup = {0, "joy_deadzoneup", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
+cvar_t joy_deadzonepitch = {0, "joy_deadzonepitch", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
+cvar_t joy_deadzoneyaw = {0, "joy_deadzoneyaw", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
+cvar_t joy_deadzoneroll = {0, "joy_deadzoneroll", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
+cvar_t joy_sensitivityforward = {0, "joy_sensitivityforward", "-1", "movement multiplier"};
+cvar_t joy_sensitivityside = {0, "joy_sensitivityside", "1", "movement multiplier"};
+cvar_t joy_sensitivityup = {0, "joy_sensitivityup", "1", "movement multiplier"};
+cvar_t joy_sensitivitypitch = {0, "joy_sensitivitypitch", "1", "movement multiplier"};
+cvar_t joy_sensitivityyaw = {0, "joy_sensitivityyaw", "-1", "movement multiplier"};
+cvar_t joy_sensitivityroll = {0, "joy_sensitivityroll", "1", "movement multiplier"};
+cvar_t joy_axiskeyevents = {CVAR_SAVE, "joy_axiskeyevents", "0", "generate uparrow/leftarrow etc. keyevents for joystick axes, use if your joystick driver is not generating them"};
+cvar_t joy_axiskeyevents_deadzone = {CVAR_SAVE, "joy_axiskeyevents_deadzone", "0.5", "deadzone value for axes"};
+cvar_t joy_x360_axisforward = {0, "joy_x360_axisforward", "1", "which joystick axis to query for forward/backward movement"};
+cvar_t joy_x360_axisside = {0, "joy_x360_axisside", "0", "which joystick axis to query for right/left movement"};
+cvar_t joy_x360_axisup = {0, "joy_x360_axisup", "-1", "which joystick axis to query for up/down movement"};
+cvar_t joy_x360_axispitch = {0, "joy_x360_axispitch", "3", "which joystick axis to query for looking up/down"};
+cvar_t joy_x360_axisyaw = {0, "joy_x360_axisyaw", "2", "which joystick axis to query for looking right/left"};
+cvar_t joy_x360_axisroll = {0, "joy_x360_axisroll", "-1", "which joystick axis to query for tilting head right/left"};
+cvar_t joy_x360_deadzoneforward = {0, "joy_x360_deadzoneforward", "0.266", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
+cvar_t joy_x360_deadzoneside = {0, "joy_x360_deadzoneside", "0.266", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
+cvar_t joy_x360_deadzoneup = {0, "joy_x360_deadzoneup", "0.266", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
+cvar_t joy_x360_deadzonepitch = {0, "joy_x360_deadzonepitch", "0.266", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
+cvar_t joy_x360_deadzoneyaw = {0, "joy_x360_deadzoneyaw", "0.266", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
+cvar_t joy_x360_deadzoneroll = {0, "joy_x360_deadzoneroll", "0.266", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
+cvar_t joy_x360_sensitivityforward = {0, "joy_x360_sensitivityforward", "1", "movement multiplier"};
+cvar_t joy_x360_sensitivityside = {0, "joy_x360_sensitivityside", "1", "movement multiplier"};
+cvar_t joy_x360_sensitivityup = {0, "joy_x360_sensitivityup", "1", "movement multiplier"};
+cvar_t joy_x360_sensitivitypitch = {0, "joy_x360_sensitivitypitch", "-1", "movement multiplier"};
+cvar_t joy_x360_sensitivityyaw = {0, "joy_x360_sensitivityyaw", "-1", "movement multiplier"};
+cvar_t joy_x360_sensitivityroll = {0, "joy_x360_sensitivityroll", "1", "movement multiplier"};
+
// cvars for DPSOFTRAST
cvar_t vid_soft = {CVAR_SAVE, "vid_soft", "0", "enables use of the DarkPlaces Software Rasterizer rather than OpenGL or Direct3D"};
cvar_t vid_soft_threads = {CVAR_SAVE, "vid_soft_threads", "2", "the number of threads the DarkPlaces Software Rasterizer should use"};
Cvar_SetQuick(&gl_info_driver, gl_driver);
}
+float VID_JoyState_GetAxis(const vid_joystate_t *joystate, int axis, float sensitivity, float deadzone)
+{
+ float value;
+ value = (axis >= 0 && axis < MAXJOYAXIS) ? joystate->axis[axis] : 0.0f;
+ value = value > deadzone ? (value - deadzone) : (value < -deadzone ? (value + deadzone) : 0.0f);
+ value *= deadzone > 0 ? (1.0f / (1.0f - deadzone)) : 1.0f;
+ value = bound(-1, value, 1);
+ return value * sensitivity;
+}
+
+qboolean VID_JoyBlockEmulatedKeys(int keycode)
+{
+ int j;
+ vid_joystate_t joystate;
+
+ if (!joy_axiskeyevents.integer)
+ return false;
+ if (vid_joystate.is360)
+ return false;
+ if (keycode != K_UPARROW && keycode != K_DOWNARROW && keycode != K_RIGHTARROW && keycode != K_LEFTARROW)
+ return false;
+
+ // block system-generated key events for arrow keys if we're emulating the arrow keys ourselves
+ VID_BuildJoyState(&joystate);
+ for (j = 32;j < 36;j++)
+ if (vid_joystate.button[j] || joystate.button[j])
+ return true;
+
+ return false;
+}
+
+void VID_Shared_BuildJoyState_Begin(vid_joystate_t *joystate)
+{
+#ifdef WIN32
+ xinput_state_t xinputstate;
+#endif
+ memset(joystate, 0, sizeof(*joystate));
+#ifdef WIN32
+ if (vid_xinputindex >= 0 && qXInputGetState && qXInputGetState(vid_xinputindex, &xinputstate) == S_OK)
+ {
+ joystate->is360 = true;
+ joystate->button[ 0] = (xinputstate.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) != 0;
+ joystate->button[ 1] = (xinputstate.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) != 0;
+ joystate->button[ 2] = (xinputstate.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) != 0;
+ joystate->button[ 3] = (xinputstate.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) != 0;
+ joystate->button[ 4] = (xinputstate.Gamepad.wButtons & XINPUT_GAMEPAD_START) != 0;
+ joystate->button[ 5] = (xinputstate.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) != 0;
+ joystate->button[ 6] = (xinputstate.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) != 0;
+ joystate->button[ 7] = (xinputstate.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) != 0;
+ joystate->button[ 8] = (xinputstate.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) != 0;
+ joystate->button[ 9] = (xinputstate.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) != 0;
+ joystate->button[10] = (xinputstate.Gamepad.wButtons & XINPUT_GAMEPAD_A) != 0;
+ joystate->button[11] = (xinputstate.Gamepad.wButtons & XINPUT_GAMEPAD_B) != 0;
+ joystate->button[12] = (xinputstate.Gamepad.wButtons & XINPUT_GAMEPAD_X) != 0;
+ joystate->button[13] = (xinputstate.Gamepad.wButtons & XINPUT_GAMEPAD_Y) != 0;
+ joystate->button[14] = xinputstate.Gamepad.bLeftTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD;
+ joystate->button[15] = xinputstate.Gamepad.bRightTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD;
+ joystate->button[16] = xinputstate.Gamepad.sThumbLY < -16384;
+ joystate->button[17] = xinputstate.Gamepad.sThumbLY > 16384;
+ joystate->button[18] = xinputstate.Gamepad.sThumbLX < -16384;
+ joystate->button[19] = xinputstate.Gamepad.sThumbLX > 16384;
+ joystate->button[20] = xinputstate.Gamepad.sThumbRY < -16384;
+ joystate->button[21] = xinputstate.Gamepad.sThumbRY > 16384;
+ joystate->button[22] = xinputstate.Gamepad.sThumbRX < -16384;
+ joystate->button[23] = xinputstate.Gamepad.sThumbRX > 16384;
+ joystate->axis[ 4] = xinputstate.Gamepad.bLeftTrigger * (1.0f / 255.0f);
+ joystate->axis[ 5] = xinputstate.Gamepad.bRightTrigger * (1.0f / 255.0f);
+ joystate->axis[ 0] = xinputstate.Gamepad.sThumbLX * (1.0f / 32767.0f);
+ joystate->axis[ 1] = xinputstate.Gamepad.sThumbLY * (1.0f / 32767.0f);
+ joystate->axis[ 2] = xinputstate.Gamepad.sThumbRX * (1.0f / 32767.0f);
+ joystate->axis[ 3] = xinputstate.Gamepad.sThumbRY * (1.0f / 32767.0f);
+ }
+#endif
+}
+
+void VID_Shared_BuildJoyState_Finish(vid_joystate_t *joystate)
+{
+ float f, r;
+ if (!joy_axiskeyevents.integer || joystate->is360)
+ return;
+ // emulate key events for thumbstick
+ f = VID_JoyState_GetAxis(joystate, joy_axisforward.integer, 1, joy_axiskeyevents_deadzone.value) * joy_sensitivityforward.value;
+ r = VID_JoyState_GetAxis(joystate, joy_axisside.integer , 1, joy_axiskeyevents_deadzone.value) * joy_sensitivityside.value;
+#if MAXJOYBUTTON != 36
+#error this code must be updated if MAXJOYBUTTON changes!
+#endif
+ joystate->button[32] = f > 0.0f;
+ joystate->button[33] = f < 0.0f;
+ joystate->button[34] = r > 0.0f;
+ joystate->button[35] = r < 0.0f;
+
+}
+
+void VID_KeyEventForButton(qboolean oldbutton, qboolean newbutton, int key, double *timer)
+{
+ if (oldbutton)
+ {
+ if (newbutton)
+ {
+ if (realtime >= *timer)
+ {
+ Key_Event(key, 0, true);
+ *timer = realtime + 0.1;
+ }
+ }
+ else
+ {
+ Key_Event(key, 0, false);
+ *timer = 0;
+ }
+ }
+ else
+ {
+ if (newbutton)
+ {
+ Key_Event(key, 0, true);
+ *timer = realtime + 0.5;
+ }
+ }
+}
+
+#if MAXJOYBUTTON != 36
+#error this code must be updated if MAXJOYBUTTON changes!
+#endif
+static int joybuttonkey[MAXJOYBUTTON] =
+{
+ K_JOY1, K_JOY2, K_JOY3, K_JOY4, K_JOY5, K_JOY6, K_JOY7, K_JOY8, K_JOY9, K_JOY10, K_JOY11, K_JOY12, K_JOY13, K_JOY14, K_JOY15, K_JOY16,
+ K_AUX1, K_AUX2, K_AUX3, K_AUX4, K_AUX5, K_AUX6, K_AUX7, K_AUX8, K_AUX9, K_AUX10, K_AUX11, K_AUX12, K_AUX13, K_AUX14, K_AUX15, K_AUX16,
+ K_UPARROW, K_DOWNARROW, K_RIGHTARROW, K_LEFTARROW
+};
+
+static int joybuttonkey360[] =
+{
+ K_X360_DPAD_UP,
+ K_X360_DPAD_DOWN,
+ K_X360_DPAD_LEFT,
+ K_X360_DPAD_RIGHT,
+ K_X360_START,
+ K_X360_BACK,
+ K_X360_LEFT_THUMB,
+ K_X360_RIGHT_THUMB,
+ K_X360_LEFT_SHOULDER,
+ K_X360_RIGHT_SHOULDER,
+ K_X360_A,
+ K_X360_B,
+ K_X360_X,
+ K_X360_Y,
+ K_X360_LEFT_TRIGGER,
+ K_X360_RIGHT_TRIGGER,
+ K_X360_LEFT_THUMB_DOWN,
+ K_X360_LEFT_THUMB_UP,
+ K_X360_LEFT_THUMB_LEFT,
+ K_X360_LEFT_THUMB_RIGHT,
+ K_X360_RIGHT_THUMB_DOWN,
+ K_X360_RIGHT_THUMB_UP,
+ K_X360_RIGHT_THUMB_LEFT,
+ K_X360_RIGHT_THUMB_RIGHT,
+};
+
+static int joybuttonkey360menu[] =
+{
+ K_UPARROW,
+ K_DOWNARROW,
+ K_LEFTARROW,
+ K_RIGHTARROW,
+ K_PAUSE,
+ K_ESCAPE,
+ 0,
+ 0,
+ 0,
+ 0,
+ K_ENTER,
+ K_ESCAPE,
+ 0,
+ 0,
+ 0,
+ 0,
+ K_DOWNARROW,
+ K_UPARROW,
+ K_LEFTARROW,
+ K_RIGHTARROW,
+ 0,
+ 0,
+ 0,
+ 0,
+};
+
+double vid_joybuttontimer[MAXJOYBUTTON];
+void VID_ApplyJoyState(vid_joystate_t *joystate)
+{
+ int j;
+ if (joystate->is360)
+ {
+#if 0
+ // keystrokes (chatpad)
+ // DOES NOT WORK - no driver support in xinput1_3.dll :(
+ xinput_keystroke_t keystroke;
+ while (qXInputGetKeystroke && qXInputGetKeystroke(XUSER_INDEX_ANY, 0, &keystroke) == S_OK)
+ Con_Printf("XInput KeyStroke: VirtualKey %i, Unicode %i, Flags %x, UserIndex %i, HidCode %i\n", keystroke.VirtualKey, keystroke.Unicode, keystroke.Flags, keystroke.UserIndex, keystroke.HidCode);
+#endif
+
+ // emit key events for buttons
+ for (j = 0;j < (int)(sizeof(joybuttonkey360)/sizeof(joybuttonkey360[0]));j++)
+ VID_KeyEventForButton(vid_joystate.button[j] != 0, joystate->button[j] != 0, key_dest == key_menu ? joybuttonkey360menu[j] : joybuttonkey360[j], &vid_joybuttontimer[j]);
+
+ // axes
+ cl.cmd.forwardmove += VID_JoyState_GetAxis(joystate, joy_x360_axisforward.integer, joy_x360_sensitivityforward.value, joy_x360_deadzoneforward.value) * cl_forwardspeed.value;
+ cl.cmd.sidemove += VID_JoyState_GetAxis(joystate, joy_x360_axisside.integer, joy_x360_sensitivityside.value, joy_x360_deadzoneside.value) * cl_sidespeed.value;
+ cl.cmd.upmove += VID_JoyState_GetAxis(joystate, joy_x360_axisup.integer, joy_x360_sensitivityup.value, joy_x360_deadzoneup.value) * cl_upspeed.value;
+ cl.viewangles[0] += VID_JoyState_GetAxis(joystate, joy_x360_axispitch.integer, joy_x360_sensitivitypitch.value, joy_x360_deadzonepitch.value) * cl.realframetime * cl_pitchspeed.value;
+ cl.viewangles[1] += VID_JoyState_GetAxis(joystate, joy_x360_axisyaw.integer, joy_x360_sensitivityyaw.value, joy_x360_deadzoneyaw.value) * cl.realframetime * cl_yawspeed.value;
+ //cl.viewangles[2] += VID_JoyState_GetAxis(joystate, joy_x360_axisroll.integer, joy_x360_sensitivityroll.value, joy_x360_deadzoneroll.value) * cl.realframetime * cl_rollspeed.value;
+ }
+ else
+ {
+ // emit key events for buttons
+ for (j = 0;j < MAXJOYBUTTON;j++)
+ VID_KeyEventForButton(vid_joystate.button[j] != 0, joystate->button[j] != 0, joybuttonkey[j], &vid_joybuttontimer[j]);
+
+ // axes
+ cl.cmd.forwardmove += VID_JoyState_GetAxis(joystate, joy_axisforward.integer, joy_sensitivityforward.value, joy_deadzoneforward.value) * cl_forwardspeed.value;
+ cl.cmd.sidemove += VID_JoyState_GetAxis(joystate, joy_axisside.integer, joy_sensitivityside.value, joy_deadzoneside.value) * cl_sidespeed.value;
+ cl.cmd.upmove += VID_JoyState_GetAxis(joystate, joy_axisup.integer, joy_sensitivityup.value, joy_deadzoneup.value) * cl_upspeed.value;
+ cl.viewangles[0] += VID_JoyState_GetAxis(joystate, joy_axispitch.integer, joy_sensitivitypitch.value, joy_deadzonepitch.value) * cl.realframetime * cl_pitchspeed.value;
+ cl.viewangles[1] += VID_JoyState_GetAxis(joystate, joy_axisyaw.integer, joy_sensitivityyaw.value, joy_deadzoneyaw.value) * cl.realframetime * cl_yawspeed.value;
+ //cl.viewangles[2] += VID_JoyState_GetAxis(joystate, joy_axisroll.integer, joy_sensitivityroll.value, joy_deadzoneroll.value) * cl.realframetime * cl_rollspeed.value;
+ }
+
+ vid_joystate = *joystate;
+}
+
+int VID_Shared_SetJoystick(int index)
+{
+#ifdef WIN32
+ int i;
+ int xinputcount = 0;
+ int xinputindex = -1;
+ int xinputavailable = 0;
+ xinput_state_t state;
+ // detect available XInput controllers
+ for (i = 0;i < 4;i++)
+ {
+ if (qXInputGetState && qXInputGetState(i, &state) == S_OK)
+ {
+ xinputavailable |= 1<<i;
+ if (index == xinputcount)
+ xinputindex = i;
+ xinputcount++;
+ }
+ }
+ if (joy_xinputavailable.integer != xinputavailable)
+ Cvar_SetValueQuick(&joy_xinputavailable, xinputavailable);
+ if (vid_xinputindex != xinputindex)
+ {
+ vid_xinputindex = xinputindex;
+ if (xinputindex >= 0)
+ Con_Printf("Joystick %i opened (XInput Device %i)\n", index, xinputindex);
+ }
+ return xinputcount;
+#else
+ return 0;
+#endif
+}
+
+
void Force_CenterView_f (void)
{
cl.viewangles[PITCH] = 0;
}
}
+#ifdef WIN32
+static dllfunction_t xinputdllfuncs[] =
+{
+ {"XInputGetState", (void **) &qXInputGetState},
+ {"XInputGetKeystroke", (void **) &qXInputGetKeystroke},
+ {NULL, NULL}
+};
+static const char* xinputdllnames [] =
+{
+ "xinput1_3.dll",
+ "xinput1_2.dll",
+ "xinput1_1.dll",
+ NULL
+};
+static dllhandle_t xinputdll_dll = NULL;
+#endif
+
void VID_Shared_Init(void)
{
#ifdef SSE_POSSIBLE
Cvar_RegisterVariable(&vid_gl20);
Cvar_RegisterVariable(&gl_finish);
Cvar_RegisterVariable(&vid_sRGB);
+
+ Cvar_RegisterVariable(&joy_active);
+#ifdef WIN32
+ Cvar_RegisterVariable(&joy_xinputavailable);
+#endif
+ Cvar_RegisterVariable(&joy_detected);
+ Cvar_RegisterVariable(&joy_enable);
+ Cvar_RegisterVariable(&joy_index);
+ Cvar_RegisterVariable(&joy_axisforward);
+ Cvar_RegisterVariable(&joy_axisside);
+ Cvar_RegisterVariable(&joy_axisup);
+ Cvar_RegisterVariable(&joy_axispitch);
+ Cvar_RegisterVariable(&joy_axisyaw);
+ //Cvar_RegisterVariable(&joy_axisroll);
+ Cvar_RegisterVariable(&joy_deadzoneforward);
+ Cvar_RegisterVariable(&joy_deadzoneside);
+ Cvar_RegisterVariable(&joy_deadzoneup);
+ Cvar_RegisterVariable(&joy_deadzonepitch);
+ Cvar_RegisterVariable(&joy_deadzoneyaw);
+ //Cvar_RegisterVariable(&joy_deadzoneroll);
+ Cvar_RegisterVariable(&joy_sensitivityforward);
+ Cvar_RegisterVariable(&joy_sensitivityside);
+ Cvar_RegisterVariable(&joy_sensitivityup);
+ Cvar_RegisterVariable(&joy_sensitivitypitch);
+ Cvar_RegisterVariable(&joy_sensitivityyaw);
+ //Cvar_RegisterVariable(&joy_sensitivityroll);
+ Cvar_RegisterVariable(&joy_axiskeyevents);
+ Cvar_RegisterVariable(&joy_axiskeyevents_deadzone);
+ Cvar_RegisterVariable(&joy_x360_axisforward);
+ Cvar_RegisterVariable(&joy_x360_axisside);
+ Cvar_RegisterVariable(&joy_x360_axisup);
+ Cvar_RegisterVariable(&joy_x360_axispitch);
+ Cvar_RegisterVariable(&joy_x360_axisyaw);
+ //Cvar_RegisterVariable(&joy_x360_axisroll);
+ Cvar_RegisterVariable(&joy_x360_deadzoneforward);
+ Cvar_RegisterVariable(&joy_x360_deadzoneside);
+ Cvar_RegisterVariable(&joy_x360_deadzoneup);
+ Cvar_RegisterVariable(&joy_x360_deadzonepitch);
+ Cvar_RegisterVariable(&joy_x360_deadzoneyaw);
+ //Cvar_RegisterVariable(&joy_x360_deadzoneroll);
+ Cvar_RegisterVariable(&joy_x360_sensitivityforward);
+ Cvar_RegisterVariable(&joy_x360_sensitivityside);
+ Cvar_RegisterVariable(&joy_x360_sensitivityup);
+ Cvar_RegisterVariable(&joy_x360_sensitivitypitch);
+ Cvar_RegisterVariable(&joy_x360_sensitivityyaw);
+ //Cvar_RegisterVariable(&joy_x360_sensitivityroll);
+
+#ifdef WIN32
+ Sys_LoadLibrary(xinputdllnames, &xinputdll_dll, xinputdllfuncs);
+#endif
+
Cmd_AddCommand("force_centerview", Force_CenterView_f, "recenters view (stops looking up/down)");
Cmd_AddCommand("vid_restart", VID_Restart_f, "restarts video system (closes and reopens the window, restarts renderer)");
}
static unsigned int mstate_di;
#endif
-// joystick defines and variables
-// where should defines be moved?
-#define JOY_ABSOLUTE_AXIS 0x00000000 // control like a joystick
-#define JOY_RELATIVE_AXIS 0x00000010 // control like a mouse, spinner, trackball
-#define JOY_MAX_AXES 6 // X, Y, Z, R, U, V
-#define JOY_AXIS_X 0
-#define JOY_AXIS_Y 1
-#define JOY_AXIS_Z 2
-#define JOY_AXIS_R 3
-#define JOY_AXIS_U 4
-#define JOY_AXIS_V 5
-
-// joystick axes state
-typedef struct
-{
- float oldmove;
- float move;
- float mdelta;
- double keytime;
-}joy_axiscache_t;
-static joy_axiscache_t joy_axescache[JOY_MAX_AXES];
-
-enum _ControlList
-{
- AxisNada = 0, AxisForward, AxisLook, AxisSide, AxisTurn
-};
-
-static DWORD dwAxisFlags[JOY_MAX_AXES] =
-{
- JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, JOY_RETURNR, JOY_RETURNU, JOY_RETURNV
-};
-
-static DWORD dwAxisMap[JOY_MAX_AXES];
-static DWORD dwControlMap[JOY_MAX_AXES];
-static PDWORD pdwRawValue[JOY_MAX_AXES];
-
-// none of these cvars are saved over a session
-// this means that advanced controller configuration needs to be executed
-// each time. this avoids any problems with getting back to a default usage
-// or when changing from one controller to another. this way at least something
-// works.
-static cvar_t in_joystick = {CVAR_SAVE, "joystick","0", "enables joysticks"};
-static cvar_t joy_name = {0, "joyname", "joystick", "name of joystick to use (informational only, used only by joyadvanced 1 mode)"};
-static cvar_t joy_advanced = {0, "joyadvanced", "0", "use more than 2 axis joysticks (configuring this is very technical)"};
-static cvar_t joy_advaxisx = {0, "joyadvaxisx", "0", "axis mapping for joyadvanced 1 mode"};
-static cvar_t joy_advaxisy = {0, "joyadvaxisy", "0", "axis mapping for joyadvanced 1 mode"};
-static cvar_t joy_advaxisz = {0, "joyadvaxisz", "0", "axis mapping for joyadvanced 1 mode"};
-static cvar_t joy_advaxisr = {0, "joyadvaxisr", "0", "axis mapping for joyadvanced 1 mode"};
-static cvar_t joy_advaxisu = {0, "joyadvaxisu", "0", "axis mapping for joyadvanced 1 mode"};
-static cvar_t joy_advaxisv = {0, "joyadvaxisv", "0", "axis mapping for joyadvanced 1 mode"};
-static cvar_t joy_forwardthreshold = {0, "joyforwardthreshold", "0.15", "minimum joystick movement necessary to move forward"};
-static cvar_t joy_sidethreshold = {0, "joysidethreshold", "0.15", "minimum joystick movement necessary to move sideways (strafing)"};
-static cvar_t joy_pitchthreshold = {0, "joypitchthreshold", "0.15", "minimum joystick movement necessary to look up/down"};
-static cvar_t joy_yawthreshold = {0, "joyyawthreshold", "0.15", "minimum joystick movement necessary to turn left/right"};
-static cvar_t joy_forwardsensitivity = {0, "joyforwardsensitivity", "-1.0", "how fast the joystick moves forward"};
-static cvar_t joy_sidesensitivity = {0, "joysidesensitivity", "-1.0", "how fast the joystick moves sideways (strafing)"};
-static cvar_t joy_pitchsensitivity = {0, "joypitchsensitivity", "1.0", "how fast the joystick looks up/down"};
-static cvar_t joy_yawsensitivity = {0, "joyyawsensitivity", "-1.0", "how fast the joystick turns left/right"};
-static cvar_t joy_wwhack1 = {0, "joywwhack1", "0.0", "special hack for wingman warrior"};
-static cvar_t joy_wwhack2 = {0, "joywwhack2", "0.0", "special hack for wingman warrior"};
-static cvar_t joy_axiskeyevents = {CVAR_SAVE, "joy_axiskeyevents", "0", "generate uparrow/leftarrow etc. keyevents for joystick axes, use if your joystick driver is not generating them"};
-static cvar_t joy_axiskeyevents_deadzone = {CVAR_SAVE, "joy_axiskeyevents_deadzone", "0.5", "deadzone value for axes"};
-
static cvar_t vid_forcerefreshrate = {0, "vid_forcerefreshrate", "0", "try to set the given vid_refreshrate even if Windows doesn't list it as valid video mode"};
-static qboolean joy_avail, joy_advancedinit, joy_haspov;
-static DWORD joy_oldbuttonstate, joy_oldpovstate;
-
-static int joy_id;
-static DWORD joy_flags;
-static DWORD joy_numbuttons;
-
#ifdef SUPPORTDIRECTX
static LPDIRECTINPUT g_pdi;
static LPDIRECTINPUTDEVICE g_pMouse;
static HINSTANCE hInstDI;
#endif
-static JOYINFOEX ji;
-
// forward-referenced functions
-static void IN_StartupJoystick (void);
-static void Joy_AdvancedUpdate_f (void);
-static void IN_JoyMove (void);
static void IN_StartupMouse (void);
};
/* main window procedure */
-static qboolean IN_JoystickBlockDoubledKeyEvents(int keycode);
LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LONG lRet = 1;
else if( charlength == 2 ) {
asciichar[0] = asciichar[1];
}
- if (!IN_JoystickBlockDoubledKeyEvents(vkey))
+ if (!VID_JoyBlockEmulatedKeys(vkey))
Key_Event (vkey, asciichar[0], down);
break;
vid_initialized = true;
IN_StartupMouse ();
- IN_StartupJoystick ();
if (qwglSwapIntervalEXT)
{
vid_initialized = true;
IN_StartupMouse ();
- IN_StartupJoystick ();
return true;
}
vid_initialized = true;
IN_StartupMouse ();
- IN_StartupJoystick ();
return true;
}
if(vid_initialized == false)
return;
+ VID_EnableJoystick(false);
VID_SetMouse(false, false, false);
VID_RestoreSystemGamma();
}
}
+void VID_BuildJoyState(vid_joystate_t *joystate)
+{
+ VID_Shared_BuildJoyState_Begin(joystate);
+ VID_Shared_BuildJoyState_Finish(joystate);
+}
+
+void VID_EnableJoystick(qboolean enable)
+{
+ int index = joy_enable.integer > 0 ? joy_index.integer : -1;
+ qboolean success = false;
+ int sharedcount = 0;
+ sharedcount = VID_Shared_SetJoystick(index);
+ if (index >= 0 && index < sharedcount)
+ success = true;
+
+ // update cvar containing count of XInput joysticks
+ if (joy_detected.integer != sharedcount)
+ Cvar_SetValueQuick(&joy_detected, sharedcount);
+
+ Cvar_SetValueQuick(&joy_active, success ? 1 : 0);
+}
#ifdef SUPPORTDIRECTX
/*
mouseinitialized = true;
#ifdef SUPPORTDIRECTX
-// COMMANDLINEOPTION: Windows Input: -dinput enables DirectInput for mouse/joystick input
+// COMMANDLINEOPTION: Windows Input: -dinput enables DirectInput for mouse input
if (COM_CheckParm ("-dinput"))
dinput = IN_InitDInput ();
*/
void IN_Move (void)
{
+ vid_joystate_t joystate;
if (vid_activewindow && !vid_reallyhidden)
- {
IN_MouseMove ();
- IN_JoyMove ();
- }
+ VID_EnableJoystick(true);
+ VID_BuildJoyState(&joystate);
+ VID_ApplyJoyState(&joystate);
}
-/*
-===============
-IN_StartupJoystick
-===============
-*/
-static void IN_StartupJoystick (void)
-{
- int numdevs;
- JOYCAPS jc;
- MMRESULT mmr;
- mmr = 0;
-
- // assume no joystick
- joy_avail = false;
-
- // abort startup if user requests no joystick
-// COMMANDLINEOPTION: Windows Input: -nojoy disables joystick support, may be a small speed increase
- if (COM_CheckParm ("-nojoy"))
- return;
-
- // verify joystick driver is present
- if ((numdevs = joyGetNumDevs ()) == 0)
- {
- Con_Print("\njoystick not found -- driver not present\n\n");
- return;
- }
-
- // cycle through the joystick ids for the first valid one
- for (joy_id=0 ; joy_id<numdevs ; joy_id++)
- {
- memset (&ji, 0, sizeof(ji));
- ji.dwSize = sizeof(ji);
- ji.dwFlags = JOY_RETURNCENTERED;
-
- if ((mmr = joyGetPosEx (joy_id, &ji)) == JOYERR_NOERROR)
- break;
- }
-
- // abort startup if we didn't find a valid joystick
- if (mmr != JOYERR_NOERROR)
- {
- Con_Printf("\njoystick not found -- no valid joysticks (%x)\n\n", mmr);
- return;
- }
-
- // get the capabilities of the selected joystick
- // abort startup if command fails
- memset (&jc, 0, sizeof(jc));
- if ((mmr = joyGetDevCaps (joy_id, &jc, sizeof(jc))) != JOYERR_NOERROR)
- {
- Con_Printf("\njoystick not found -- invalid joystick capabilities (%x)\n\n", mmr);
- return;
- }
-
- // save the joystick's number of buttons and POV status
- joy_numbuttons = jc.wNumButtons;
- joy_haspov = (jc.wCaps & JOYCAPS_HASPOV) != 0;
-
- // old button and POV states default to no buttons pressed
- joy_oldbuttonstate = joy_oldpovstate = 0;
-
- // mark the joystick as available and advanced initialization not completed
- // this is needed as cvars are not available during initialization
-
- joy_avail = true;
- joy_advancedinit = false;
-
- Con_Print("\njoystick detected\n\n");
-}
-
-
-/*
-===========
-RawValuePointer
-===========
-*/
-static PDWORD RawValuePointer (int axis)
-{
- switch (axis)
- {
- case JOY_AXIS_X:
- return &ji.dwXpos;
- case JOY_AXIS_Y:
- return &ji.dwYpos;
- case JOY_AXIS_Z:
- return &ji.dwZpos;
- case JOY_AXIS_R:
- return &ji.dwRpos;
- case JOY_AXIS_U:
- return &ji.dwUpos;
- case JOY_AXIS_V:
- return &ji.dwVpos;
- }
- return NULL; // LordHavoc: hush compiler warning
-}
-
-
-/*
-===========
-Joy_AdvancedUpdate_f
-===========
-*/
-static void Joy_AdvancedUpdate_f (void)
-{
-
- // called once by IN_ReadJoystick and by user whenever an update is needed
- // cvars are now available
- int i;
- DWORD dwTemp;
-
- // initialize all the maps
- for (i = 0; i < JOY_MAX_AXES; i++)
- {
- dwAxisMap[i] = AxisNada;
- dwControlMap[i] = JOY_ABSOLUTE_AXIS;
- pdwRawValue[i] = RawValuePointer(i);
- }
-
- if( joy_advanced.integer == 0)
- {
- // default joystick initialization
- // 2 axes only with joystick control
- dwAxisMap[JOY_AXIS_X] = AxisTurn;
- // dwControlMap[JOY_AXIS_X] = JOY_ABSOLUTE_AXIS;
- dwAxisMap[JOY_AXIS_Y] = AxisForward;
- // dwControlMap[JOY_AXIS_Y] = JOY_ABSOLUTE_AXIS;
- }
- else
- {
- if (strcmp (joy_name.string, "joystick") != 0)
- {
- // notify user of advanced controller
- Con_Printf("\n%s configured\n\n", joy_name.string);
- }
-
- // advanced initialization here
- // data supplied by user via joy_axisn cvars
- dwTemp = (DWORD) joy_advaxisx.value;
- dwAxisMap[JOY_AXIS_X] = dwTemp & 0x0000000f;
- dwControlMap[JOY_AXIS_X] = dwTemp & JOY_RELATIVE_AXIS;
- dwTemp = (DWORD) joy_advaxisy.value;
- dwAxisMap[JOY_AXIS_Y] = dwTemp & 0x0000000f;
- dwControlMap[JOY_AXIS_Y] = dwTemp & JOY_RELATIVE_AXIS;
- dwTemp = (DWORD) joy_advaxisz.value;
- dwAxisMap[JOY_AXIS_Z] = dwTemp & 0x0000000f;
- dwControlMap[JOY_AXIS_Z] = dwTemp & JOY_RELATIVE_AXIS;
- dwTemp = (DWORD) joy_advaxisr.value;
- dwAxisMap[JOY_AXIS_R] = dwTemp & 0x0000000f;
- dwControlMap[JOY_AXIS_R] = dwTemp & JOY_RELATIVE_AXIS;
- dwTemp = (DWORD) joy_advaxisu.value;
- dwAxisMap[JOY_AXIS_U] = dwTemp & 0x0000000f;
- dwControlMap[JOY_AXIS_U] = dwTemp & JOY_RELATIVE_AXIS;
- dwTemp = (DWORD) joy_advaxisv.value;
- dwAxisMap[JOY_AXIS_V] = dwTemp & 0x0000000f;
- dwControlMap[JOY_AXIS_V] = dwTemp & JOY_RELATIVE_AXIS;
- }
-
- // compute the axes to collect from DirectInput
- joy_flags = JOY_RETURNCENTERED | JOY_RETURNBUTTONS | JOY_RETURNPOV;
- for (i = 0; i < JOY_MAX_AXES; i++)
- {
- if (dwAxisMap[i] != AxisNada)
- {
- joy_flags |= dwAxisFlags[i];
- }
- }
-}
-
-/*
-===============
-IN_ReadJoystick
-===============
-*/
-static qboolean IN_ReadJoystick (void)
-{
-
- memset (&ji, 0, sizeof(ji));
- ji.dwSize = sizeof(ji);
- ji.dwFlags = joy_flags;
-
- if (joyGetPosEx (joy_id, &ji) == JOYERR_NOERROR)
- {
- // this is a hack -- there is a bug in the Logitech WingMan Warrior DirectInput Driver
- // rather than having 32768 be the zero point, they have the zero point at 32668
- // go figure -- anyway, now we get the full resolution out of the device
- if (joy_wwhack1.integer != 0.0)
- {
- ji.dwUpos += 100;
- }
- return true;
- }
- else
- {
- // read error occurred
- // turning off the joystick seems too harsh for 1 read error,
- // but what should be done?
- return false;
- }
-}
-
-/*
-===========
- IN_JoystickGetAxisNum
-===========
-*/
-
-int IN_JoystickGetAxisNum(int ControlListType)
-{
- int i;
-
- for (i = 0; i < JOY_MAX_AXES; i++)
- if (dwAxisMap[i] == (DWORD) ControlListType)
- return i;
- return -1;
-}
-
-/*
-===========
- IN_JoystickGetAxis
-===========
-*/
-static double IN_JoystickGetAxis(int axis, double sensitivity, double deadzone)
-{
- float fAxisValue, fTemp;
-
- if (!joy_avail || axis < 0 || axis >= JOY_MAX_AXES)
- return 0; // no such axis on this joystick
-
- // get the floating point zero-centered, potentially-inverted data for the current axis
- fAxisValue = (float) *pdwRawValue[axis];
-
- // move centerpoint to zero
- fAxisValue -= 32768.0;
-
- if (joy_wwhack2.integer != 0.0)
- {
- if (dwAxisMap[axis] == AxisTurn)
- {
- // this is a special formula for the Logitech WingMan Warrior
- // y=ax^b; where a = 300 and b = 1.3
- // also x values are in increments of 800 (so this is factored out)
- // then bounds check result to level out excessively high spin rates
- fTemp = 300.0 * pow(abs(fAxisValue) / 800.0, 1.3);
- if (fTemp > 14000.0)
- fTemp = 14000.0;
- // restore direction information
- fAxisValue = (fAxisValue > 0.0) ? fTemp : -fTemp;
- }
- }
-
- // convert range from -32768..32767 to -1..1
- fAxisValue /= 32768.0;
-
- // deadzone around center
- if (fabs(fAxisValue) < deadzone)
- return 0;
-
- // apply sensitivity
- return fAxisValue * sensitivity;
-}
-
-/*
-===========
- IN_JoystickKeyeventForAxis
-===========
-*/
-
-static void IN_JoystickKeyeventForAxis(int axis, int key_pos, int key_neg)
-{
- double joytime;
-
- if (axis < 0 || axis >= JOY_MAX_AXES)
- return; // no such axis on this joystick
-
- joytime = Sys_DoubleTime();
- // no key event, continuous keydown event
- if (joy_axescache[axis].move == joy_axescache[axis].oldmove)
- {
- if (joy_axescache[axis].move != 0 && joytime > joy_axescache[axis].keytime)
- {
- //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].move > 0) ? key_pos : key_neg), 1, cl.time);
- Key_Event((joy_axescache[axis].move > 0) ? key_pos : key_neg, 0, 1);
- joy_axescache[axis].keytime = joytime + 0.5 / 20;
- }
- return;
- }
- // generate key up event
- if (joy_axescache[axis].oldmove)
- {
- //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].oldmove > 0) ? key_pos : key_neg), 1, cl.time);
- Key_Event((joy_axescache[axis].oldmove > 0) ? key_pos : key_neg, 0, 0);
- }
- // generate key down event
- if (joy_axescache[axis].move)
- {
- //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].move > 0) ? key_pos : key_neg), 1, cl.time);
- Key_Event((joy_axescache[axis].move > 0) ? key_pos : key_neg, 0, 1);
- joy_axescache[axis].keytime = joytime + 0.5;
- }
-}
-
-/*
-===========
- IN_JoystickBlockDoubledKeyEvents
-===========
-*/
-
-static qboolean IN_ReadJoystick (void);
-static qboolean IN_JoystickBlockDoubledKeyEvents(int keycode)
-{
- int axis;
-
- if (!joy_axiskeyevents.integer)
- return false;
-
- // block keyevent if it's going to be provided by joystick keyevent system
- if (joy_avail)
- {
- // collect the joystick data, if possible
- if (IN_ReadJoystick() != true)
- return false;
- axis = IN_JoystickGetAxisNum(AxisForward);
- if (keycode == K_UPARROW || keycode == K_DOWNARROW)
- if (IN_JoystickGetAxis(axis, 1, joy_axiskeyevents_deadzone.value) || joy_axescache[axis].move || joy_axescache[axis].oldmove)
- return true;
- axis = IN_JoystickGetAxisNum(AxisSide);
- if (keycode == K_RIGHTARROW || keycode == K_LEFTARROW)
- if (IN_JoystickGetAxis(axis, 1, joy_axiskeyevents_deadzone.value) || joy_axescache[axis].move || joy_axescache[axis].oldmove)
- return true;
- }
-
- return false;
-}
-
-/*
-===========
- IN_JoyMove
-===========
-*/
-static void IN_JoyMove (void)
-{
- float speed, aspeed;
- float fAxisValue;
- int i, mouselook = (in_mlook.state & 1) || freelook.integer, AxisForwardIndex = -1, AxisSideIndex = -1;
-
- // complete initialization if first time in
- // this is needed as cvars are not available at initialization time
- if( joy_advancedinit != true )
- {
- Joy_AdvancedUpdate_f();
- joy_advancedinit = true;
- }
-
- if (joy_avail)
- {
- int i, key_index;
- DWORD buttonstate, povstate;
-
- // loop through the joystick buttons
- // key a joystick event or auxillary event for higher number buttons for each state change
- buttonstate = ji.dwButtons;
- for (i=0 ; i < (int) joy_numbuttons ; i++)
- {
- if ( (buttonstate & (1<<i)) && !(joy_oldbuttonstate & (1<<i)) )
- {
- key_index = (i < 16) ? K_JOY1 : K_AUX1;
- Key_Event (key_index + i, 0, true);
- }
- if ( !(buttonstate & (1<<i)) && (joy_oldbuttonstate & (1<<i)) )
- {
- key_index = (i < 16) ? K_JOY1 : K_AUX1;
- Key_Event (key_index + i, 0, false);
- }
- }
- joy_oldbuttonstate = buttonstate;
-
- if (joy_haspov)
- {
- // convert POV information into 4 bits of state information
- // this avoids any potential problems related to moving from one
- // direction to another without going through the center position
- povstate = 0;
- if(ji.dwPOV != JOY_POVCENTERED)
- {
- if (ji.dwPOV == JOY_POVFORWARD)
- povstate |= 0x01;
- if (ji.dwPOV == JOY_POVRIGHT)
- povstate |= 0x02;
- if (ji.dwPOV == JOY_POVBACKWARD)
- povstate |= 0x04;
- if (ji.dwPOV == JOY_POVLEFT)
- povstate |= 0x08;
- }
- // determine which bits have changed and key an auxillary event for each change
- for (i=0 ; i < 4 ; i++)
- {
- if ( (povstate & (1<<i)) && !(joy_oldpovstate & (1<<i)) )
- {
- Key_Event (K_AUX29 + i, 0, true);
- }
-
- if ( !(povstate & (1<<i)) && (joy_oldpovstate & (1<<i)) )
- {
- Key_Event (K_AUX29 + i, 0, false);
- }
- }
- joy_oldpovstate = povstate;
- }
- }
-
- // verify joystick is available and that the user wants to use it
- if (!joy_avail || !in_joystick.integer)
- {
- return;
- }
-
- // collect the joystick data, if possible
- if (IN_ReadJoystick () != true)
- {
- return;
- }
-
- if (in_speed.state & 1)
- speed = cl_movespeedkey.value;
- else
- speed = 1;
- // LordHavoc: viewzoom affects sensitivity for sniping
- aspeed = speed * cl.realframetime * cl.viewzoom;
-
- // loop through the axes
- for (i = 0; i < JOY_MAX_AXES; i++)
- {
- // convert axis to real move
- switch (dwAxisMap[i])
- {
- case AxisForward:
- if (AxisForwardIndex < 0)
- AxisForwardIndex = i;
- if ((joy_advanced.integer == 0) && mouselook)
- {
- // user wants forward control to become look control
- fAxisValue = IN_JoystickGetAxis(i, joy_pitchsensitivity.value, joy_pitchthreshold.value);
- if (fAxisValue != 0)
- {
- // if mouse invert is on, invert the joystick pitch value
- // only absolute control support here (joy_advanced is false)
- if (m_pitch.value < 0.0)
- cl.viewangles[PITCH] -= fAxisValue * aspeed * cl_pitchspeed.value;
- else
- cl.viewangles[PITCH] += fAxisValue * aspeed * cl_pitchspeed.value;
- V_StopPitchDrift();
- }
- else
- {
- // no pitch movement
- // disable pitch return-to-center unless requested by user
- // *** this code can be removed when the lookspring bug is fixed
- // *** the bug always has the lookspring feature on
- if (lookspring.value == 0.0)
- V_StopPitchDrift();
- }
- }
- else
- {
- // user wants forward control to be forward control
- fAxisValue = IN_JoystickGetAxis(i, joy_forwardsensitivity.value, joy_forwardthreshold.value);
- cl.cmd.forwardmove += fAxisValue * speed * cl_forwardspeed.value;
- }
- break;
-
- case AxisSide:
- if (AxisSideIndex < 0)
- AxisSideIndex = i;
- fAxisValue = IN_JoystickGetAxis(i, joy_sidesensitivity.value, joy_sidethreshold.value);
- cl.cmd.sidemove += fAxisValue * speed * cl_sidespeed.value;
- break;
-
- case AxisTurn:
- if ((in_strafe.state & 1) || (lookstrafe.integer && mouselook))
- {
- // user wants turn control to become side control
- fAxisValue = IN_JoystickGetAxis(i, joy_sidesensitivity.value, joy_sidethreshold.value);
- cl.cmd.sidemove -= fAxisValue * speed * cl_sidespeed.value;
- }
- else
- {
- // user wants turn control to be turn control
- fAxisValue = IN_JoystickGetAxis(i, joy_yawsensitivity.value, joy_yawthreshold.value);
- if (dwControlMap[i] == JOY_ABSOLUTE_AXIS)
- cl.viewangles[YAW] += fAxisValue * aspeed * cl_yawspeed.value;
- else
- cl.viewangles[YAW] += fAxisValue * speed * 180.0;
- }
- break;
-
- case AxisLook:
- fAxisValue = IN_JoystickGetAxis(i, joy_pitchsensitivity.value, joy_pitchthreshold.value);
- if (mouselook)
- {
- if (fAxisValue != 0)
- {
- // pitch movement detected and pitch movement desired by user
- if (dwControlMap[i] == JOY_ABSOLUTE_AXIS)
- cl.viewangles[PITCH] += fAxisValue * aspeed * cl_pitchspeed.value;
- else
- cl.viewangles[PITCH] += fAxisValue * speed * 180.0;
- V_StopPitchDrift();
- }
- else
- {
- // no pitch movement
- // disable pitch return-to-center unless requested by user
- // *** this code can be removed when the lookspring bug is fixed
- // *** the bug always has the lookspring feature on
- if(lookspring.integer == 0)
- V_StopPitchDrift();
- }
- }
- break;
-
- default:
- fAxisValue = IN_JoystickGetAxis(i, 1, 0.01);
- break;
- }
-
- // cache for keyevents
- joy_axescache[i].oldmove = joy_axescache[i].move;
- joy_axescache[i].move = IN_JoystickGetAxis(i, 1, joy_axiskeyevents_deadzone.value);
- }
-
- // run keyevents
- if (joy_axiskeyevents.integer)
- {
- IN_JoystickKeyeventForAxis(AxisForwardIndex, K_DOWNARROW, K_UPARROW);
- IN_JoystickKeyeventForAxis(AxisSideIndex, K_RIGHTARROW, K_LEFTARROW);
- }
-}
-
static void IN_Init(void)
{
uiWheelMessage = RegisterWindowMessage ( "MSWHEEL_ROLLMSG" );
-
- // joystick variables
- Cvar_RegisterVariable (&in_joystick);
- Cvar_RegisterVariable (&joy_name);
- Cvar_RegisterVariable (&joy_advanced);
- Cvar_RegisterVariable (&joy_advaxisx);
- Cvar_RegisterVariable (&joy_advaxisy);
- Cvar_RegisterVariable (&joy_advaxisz);
- Cvar_RegisterVariable (&joy_advaxisr);
- Cvar_RegisterVariable (&joy_advaxisu);
- Cvar_RegisterVariable (&joy_advaxisv);
- Cvar_RegisterVariable (&joy_forwardthreshold);
- Cvar_RegisterVariable (&joy_sidethreshold);
- Cvar_RegisterVariable (&joy_pitchthreshold);
- Cvar_RegisterVariable (&joy_yawthreshold);
- Cvar_RegisterVariable (&joy_forwardsensitivity);
- Cvar_RegisterVariable (&joy_sidesensitivity);
- Cvar_RegisterVariable (&joy_pitchsensitivity);
- Cvar_RegisterVariable (&joy_yawsensitivity);
- Cvar_RegisterVariable (&joy_wwhack1);
- Cvar_RegisterVariable (&joy_wwhack2);
- Cvar_RegisterVariable (&joy_axiskeyevents);
- Cvar_RegisterVariable (&joy_axiskeyevents_deadzone);
Cvar_RegisterVariable (&vid_forcerefreshrate);
- Cmd_AddCommand ("joyadvancedupdate", Joy_AdvancedUpdate_f, "applies current joyadv* cvar settings to the joystick driver");
}
static void IN_Shutdown(void)