mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-25 21:41:03 +00:00
- Split the joystick menu into two parts: A top level with general options
and a list of all attached controllers, and a second level for configuring an individual controller. - Fixed: Pressing Up at the top of a menu with more lines than fit on screen would find an incorrect bottom position if the menu had a custom top height. - Added the cvars joy_dinput, joy_ps2raw, and joy_xinput to enable/disable specific game controller input systems independant of each other. - Device change broadcasts are now sent to the Doom event queue, so device scanning can be handled in one common place. - Added a fast version of IsXInputDevice that uses the Raw Input device list, because querying WMI for this information is painfully slow. - Added support for compiling with FMOD Ex 4.26+ and running the game with an older DLL. This combination will now produce sound. SVN r1717 (trunk)
This commit is contained in:
parent
8e5b7373b8
commit
f74f6a1659
15 changed files with 628 additions and 374 deletions
|
@ -1,4 +1,19 @@
|
|||
July 13, 2009 (Changes by Graf Zahl)
|
||||
July 14, 2009
|
||||
- Split the joystick menu into two parts: A top level with general options
|
||||
and a list of all attached controllers, and a second level for configuring
|
||||
an individual controller.
|
||||
- Fixed: Pressing Up at the top of a menu with more lines than fit on screen
|
||||
would find an incorrect bottom position if the menu had a custom top height.
|
||||
- Added the cvars joy_dinput, joy_ps2raw, and joy_xinput to enable/disable
|
||||
specific game controller input systems independant of each other.
|
||||
- Device change broadcasts are now sent to the Doom event queue, so
|
||||
device scanning can be handled in one common place.
|
||||
- Added a fast version of IsXInputDevice that uses the Raw Input device
|
||||
list, because querying WMI for this information is painfully slow.
|
||||
- Added support for compiling with FMOD Ex 4.26+ and running the game
|
||||
with an older DLL. This combination will now produce sound.
|
||||
|
||||
July 13, 2009 (Changes by Graf Zahl)
|
||||
- added submission for raising master/children/siblings.
|
||||
- added submission for no decals on wall option.
|
||||
- removed some useless code from SpawnMissile function.
|
||||
|
|
|
@ -38,7 +38,8 @@ enum EGenericEvent
|
|||
EV_KeyDown, // data1: scan code, data2: Qwerty ASCII code
|
||||
EV_KeyUp, // same
|
||||
EV_Mouse, // x, y: mouse movement deltas
|
||||
EV_GUI_Event // subtype specifies actual event
|
||||
EV_GUI_Event, // subtype specifies actual event
|
||||
EV_DeviceChange,// a device has been connected or removed
|
||||
};
|
||||
|
||||
// Event structure.
|
||||
|
|
|
@ -101,6 +101,7 @@
|
|||
#include "v_palette.h"
|
||||
#include "m_cheat.h"
|
||||
#include "compatibility.h"
|
||||
#include "m_joy.h"
|
||||
|
||||
EXTERN_CVAR(Bool, hud_althud)
|
||||
void DrawHUD();
|
||||
|
@ -240,6 +241,8 @@ void D_ProcessEvents (void)
|
|||
for (; eventtail != eventhead ; eventtail = (eventtail+1)&(MAXEVENTS-1))
|
||||
{
|
||||
ev = &events[eventtail];
|
||||
if (ev->type == EV_DeviceChange)
|
||||
UpdateJoystickMenu(I_UpdateDeviceList());
|
||||
if (C_Responder (ev))
|
||||
continue; // console ate the event
|
||||
if (M_Responder (ev))
|
||||
|
@ -260,6 +263,11 @@ void D_ProcessEvents (void)
|
|||
|
||||
void D_PostEvent (const event_t *ev)
|
||||
{
|
||||
// Do not post duplicate consecutive EV_DeviceChange events.
|
||||
if (ev->type == EV_DeviceChange && events[eventhead].type == EV_DeviceChange)
|
||||
{
|
||||
return;
|
||||
}
|
||||
events[eventhead] = *ev;
|
||||
if (ev->type == EV_Mouse && !testpolymost && !paused && menuactive == MENU_Off &&
|
||||
ConsoleState != c_down && ConsoleState != c_falling)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "m_joy.h"
|
||||
#include "gameconfigfile.h"
|
||||
#include "d_event.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -15,6 +16,23 @@
|
|||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
EXTERN_CVAR(Bool, joy_ps2raw)
|
||||
EXTERN_CVAR(Bool, joy_dinput)
|
||||
EXTERN_CVAR(Bool, joy_xinput)
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
CUSTOM_CVAR(Bool, use_joystick, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
joy_ps2raw.Callback();
|
||||
joy_dinput.Callback();
|
||||
joy_xinput.Callback();
|
||||
#endif
|
||||
}
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
||||
//==========================================================================
|
||||
|
@ -142,3 +160,80 @@ void M_SaveJoystickConfig(IJoystickConfig *joy)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Joy_RemoveDeadZone
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
double Joy_RemoveDeadZone(double axisval, double deadzone, BYTE *buttons)
|
||||
{
|
||||
// Cancel out deadzone.
|
||||
if (fabs(axisval) < deadzone)
|
||||
{
|
||||
axisval = 0;
|
||||
*buttons = 0;
|
||||
}
|
||||
// Make the dead zone the new 0.
|
||||
else if (axisval < 0)
|
||||
{
|
||||
axisval = (axisval + deadzone) / (1.0 - deadzone);
|
||||
*buttons = 2; // button minus
|
||||
}
|
||||
else
|
||||
{
|
||||
axisval = (axisval - deadzone) / (1.0 - deadzone);
|
||||
*buttons = 1; // button plus
|
||||
}
|
||||
return axisval;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Joy_GenerateButtonEvents
|
||||
//
|
||||
// Provided two bitmasks for a set of buttons, generates events to reflect
|
||||
// any changes from the old to new set, where base is the key for bit 0,
|
||||
// base+1 is the key for bit 1, etc.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base)
|
||||
{
|
||||
int changed = oldbuttons ^ newbuttons;
|
||||
if (changed != 0)
|
||||
{
|
||||
event_t ev = { 0 };
|
||||
int mask = 1;
|
||||
for (int j = 0; j < numbuttons; mask <<= 1, ++j)
|
||||
{
|
||||
if (changed & mask)
|
||||
{
|
||||
ev.data1 = base + j;
|
||||
ev.type = (newbuttons & mask) ? EV_KeyDown : EV_KeyUp;
|
||||
D_PostEvent(&ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, const int *keys)
|
||||
{
|
||||
int changed = oldbuttons ^ newbuttons;
|
||||
if (changed != 0)
|
||||
{
|
||||
event_t ev = { 0 };
|
||||
int mask = 1;
|
||||
for (int j = 0; j < numbuttons; mask <<= 1, ++j)
|
||||
{
|
||||
if (changed & mask)
|
||||
{
|
||||
ev.data1 = keys[j];
|
||||
ev.type = (newbuttons & mask) ? EV_KeyDown : EV_KeyUp;
|
||||
D_PostEvent(&ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "doomtype.h"
|
||||
#include "tarray.h"
|
||||
#include "c_cvars.h"
|
||||
|
||||
enum EJoyAxis
|
||||
{
|
||||
|
@ -43,11 +44,18 @@ struct NOVTABLE IJoystickConfig
|
|||
virtual FString GetIdentifier() = 0;
|
||||
};
|
||||
|
||||
EXTERN_CVAR(Bool, use_joystick);
|
||||
|
||||
bool M_LoadJoystickConfig(IJoystickConfig *joy);
|
||||
void M_SaveJoystickConfig(IJoystickConfig *joy);
|
||||
|
||||
void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base);
|
||||
void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, const int *keys);
|
||||
double Joy_RemoveDeadZone(double axisval, double deadzone, BYTE *buttons);
|
||||
|
||||
// These ought to be provided by a system-specific i_input.cpp.
|
||||
void I_GetAxes(float axes[NUM_JOYAXIS]);
|
||||
void I_GetJoysticks(TArray<IJoystickConfig *> &sticks);
|
||||
IJoystickConfig *I_UpdateDeviceList();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -94,6 +94,7 @@ typedef enum {
|
|||
rightmore,
|
||||
safemore,
|
||||
rsafemore,
|
||||
joymore,
|
||||
slider,
|
||||
absslider,
|
||||
inverter,
|
||||
|
@ -101,7 +102,6 @@ typedef enum {
|
|||
discretes,
|
||||
cdiscrete,
|
||||
ediscrete,
|
||||
discrete_joy,
|
||||
control,
|
||||
screenres,
|
||||
bitflag,
|
||||
|
@ -158,7 +158,6 @@ struct menuitem_t
|
|||
struct value_t *values;
|
||||
struct valuestring_t *valuestrings;
|
||||
struct valueenum_t *enumvalues;
|
||||
TArray<IJoystickConfig *> *joyvalues;
|
||||
char *command;
|
||||
void (*cfunc)(FBaseCVar *cvar, float newval);
|
||||
void (*mfunc)(void);
|
||||
|
|
|
@ -290,34 +290,26 @@ menu_t MouseMenu =
|
|||
*
|
||||
*=======================================*/
|
||||
|
||||
#define SELECTED_JOYSTICK (Joysticks[JoystickItems[1].a.joyselection])
|
||||
EXTERN_CVAR (Bool, use_joystick)
|
||||
EXTERN_CVAR(Bool, use_joystick)
|
||||
EXTERN_CVAR(Bool, joy_ps2raw)
|
||||
EXTERN_CVAR(Bool, joy_dinput)
|
||||
EXTERN_CVAR(Bool, joy_xinput)
|
||||
|
||||
#if 0
|
||||
EXTERN_CVAR (Float, joy_speedmultiplier)
|
||||
EXTERN_CVAR (Int, joy_xaxis)
|
||||
EXTERN_CVAR (Int, joy_yaxis)
|
||||
EXTERN_CVAR (Int, joy_zaxis)
|
||||
EXTERN_CVAR (Int, joy_xrot)
|
||||
EXTERN_CVAR (Int, joy_yrot)
|
||||
EXTERN_CVAR (Int, joy_zrot)
|
||||
EXTERN_CVAR (Int, joy_slider)
|
||||
EXTERN_CVAR (Int, joy_dial)
|
||||
EXTERN_CVAR (Float, joy_xthreshold)
|
||||
EXTERN_CVAR (Float, joy_ythreshold)
|
||||
EXTERN_CVAR (Float, joy_zthreshold)
|
||||
EXTERN_CVAR (Float, joy_xrotthreshold)
|
||||
EXTERN_CVAR (Float, joy_yrotthreshold)
|
||||
EXTERN_CVAR (Float, joy_zrotthreshold)
|
||||
EXTERN_CVAR (Float, joy_sliderthreshold)
|
||||
EXTERN_CVAR (Float, joy_dialthreshold)
|
||||
EXTERN_CVAR (Float, joy_yawspeed)
|
||||
EXTERN_CVAR (Float, joy_pitchspeed)
|
||||
EXTERN_CVAR (Float, joy_forwardspeed)
|
||||
EXTERN_CVAR (Float, joy_sidespeed)
|
||||
EXTERN_CVAR (Float, joy_upspeed)
|
||||
EXTERN_CVAR (GUID, joy_guid)
|
||||
#endif
|
||||
static TArray<IJoystickConfig *> Joysticks;
|
||||
static TArray<menuitem_t> JoystickItems;
|
||||
|
||||
menu_t JoystickMenu =
|
||||
{
|
||||
"CONTROLLER OPTIONS",
|
||||
};
|
||||
|
||||
/*=======================================
|
||||
*
|
||||
* Joystick Config Menu
|
||||
*
|
||||
*=======================================*/
|
||||
|
||||
IJoystickConfig *SELECTED_JOYSTICK;
|
||||
|
||||
static value_t JoyAxisMapNames[6] =
|
||||
{
|
||||
|
@ -335,13 +327,11 @@ static value_t Inversion[2] =
|
|||
{ 1.0, "Inverted" }
|
||||
};
|
||||
|
||||
static TArray<IJoystickConfig *> Joysticks;
|
||||
static TArray<menuitem_t> JoystickConfigItems;
|
||||
|
||||
static TArray<menuitem_t> JoystickItems;
|
||||
|
||||
menu_t JoystickMenu =
|
||||
menu_t JoystickConfigMenu =
|
||||
{
|
||||
"JOYSTICK OPTIONS",
|
||||
"CONFIGURE CONTROLLER",
|
||||
};
|
||||
|
||||
|
||||
|
@ -1519,7 +1509,7 @@ static void CalcIndent (menu_t *menu)
|
|||
{
|
||||
item = menu->items + i;
|
||||
if (item->type != whitetext && item->type != redtext && item->type != screenres &&
|
||||
(item->type != discrete || !item->c.discretecenter))
|
||||
item->type != joymore && (item->type != discrete || !item->c.discretecenter))
|
||||
{
|
||||
thiswidth = SmallFont->StringWidth (item->label);
|
||||
if (thiswidth > widest)
|
||||
|
@ -1694,6 +1684,10 @@ void M_OptDrawer ()
|
|||
{
|
||||
indent = 160;
|
||||
}
|
||||
else if (item->type == joymore)
|
||||
{
|
||||
indent = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
indent = CurrentMenu->indent;
|
||||
|
@ -1703,19 +1697,19 @@ void M_OptDrawer ()
|
|||
{
|
||||
FString somestring;
|
||||
const char *label;
|
||||
if (item->type != discrete_joy)
|
||||
if (item->type != joymore)
|
||||
{
|
||||
label = item->label;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item->e.joyvalues->Size() == 0)
|
||||
if (Joysticks.Size() == 0)
|
||||
{
|
||||
label = "No devices connected";
|
||||
}
|
||||
else
|
||||
{
|
||||
somestring = (*item->e.joyvalues)[item->a.joyselection]->GetName();
|
||||
somestring = Joysticks[item->a.joyselection]->GetName();
|
||||
label = somestring;
|
||||
}
|
||||
}
|
||||
|
@ -1728,6 +1722,11 @@ void M_OptDrawer ()
|
|||
color = MoreColor;
|
||||
break;
|
||||
|
||||
case joymore:
|
||||
x = 20;
|
||||
color = MoreColor;
|
||||
break;
|
||||
|
||||
case numberedmore:
|
||||
case rsafemore:
|
||||
case rightmore:
|
||||
|
@ -1735,13 +1734,6 @@ void M_OptDrawer ()
|
|||
color = item->type != rightmore ? CR_GREEN : MoreColor;
|
||||
break;
|
||||
|
||||
case discrete_joy:
|
||||
x = 160 - width / 2;
|
||||
// Move cursor to the left of this item.
|
||||
indent = x - 14;
|
||||
color = ValueColor;
|
||||
break;
|
||||
|
||||
case redtext:
|
||||
x = 160 - width / 2;
|
||||
color = LabelColor;
|
||||
|
@ -2222,7 +2214,11 @@ void M_OptResponder (event_t *ev)
|
|||
int maxitems, rowheight;
|
||||
|
||||
// Figure out how many lines of text fit on the menu
|
||||
if (BigFont && CurrentMenu->texttitle)
|
||||
if (CurrentMenu->y != 0)
|
||||
{
|
||||
maxitems = CurrentMenu->y;
|
||||
}
|
||||
else if (BigFont && CurrentMenu->texttitle)
|
||||
{
|
||||
maxitems = 15 + BigFont->GetHeight ();
|
||||
}
|
||||
|
@ -2457,15 +2453,6 @@ void M_OptResponder (event_t *ev)
|
|||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
|
||||
break;
|
||||
|
||||
case discrete_joy:
|
||||
if (--item->a.joyselection < 0)
|
||||
{
|
||||
item->a.joyselection = item->e.joyvalues->Size() - 1;
|
||||
}
|
||||
UpdateJoystickMenu(NULL);
|
||||
S_Sound(CHAN_VOICE|CHAN_UI, "menu/change", 1, ATTN_NONE);
|
||||
break;
|
||||
|
||||
case inverter:
|
||||
value = item->a.cvar->GetGenericRep (CVAR_Float);
|
||||
value.Float = -value.Float;
|
||||
|
@ -2663,15 +2650,6 @@ void M_OptResponder (event_t *ev)
|
|||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
|
||||
break;
|
||||
|
||||
case discrete_joy:
|
||||
if ((unsigned)++item->a.joyselection >= item->e.joyvalues->Size())
|
||||
{
|
||||
item->a.joyselection = 0;
|
||||
}
|
||||
UpdateJoystickMenu(NULL);
|
||||
S_Sound(CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
|
||||
break;
|
||||
|
||||
case inverter:
|
||||
value = item->a.cvar->GetGenericRep (CVAR_Float);
|
||||
value.Float = -value.Float;
|
||||
|
@ -2775,6 +2753,7 @@ void M_OptResponder (event_t *ev)
|
|||
item->type == numberedmore ||
|
||||
item->type == rightmore ||
|
||||
item->type == rsafemore ||
|
||||
item->type == joymore ||
|
||||
item->type == safemore)
|
||||
&& item->e.mfunc)
|
||||
{
|
||||
|
@ -3094,21 +3073,114 @@ CCMD (menu_mouse)
|
|||
MouseOptions ();
|
||||
}
|
||||
|
||||
static void DrawJoystickConfigMenuHeader()
|
||||
{
|
||||
FString joyname = SELECTED_JOYSTICK->GetName();
|
||||
screen->DrawText(BigFont, gameinfo.gametype & GAME_DoomChex ? CR_RED : CR_UNTRANSLATED,
|
||||
160-BigFont->StringWidth(CurrentMenu->texttitle)/2, 5,
|
||||
CurrentMenu->texttitle, DTA_Clean, true, TAG_DONE);
|
||||
screen->DrawText(SmallFont, gameinfo.gametype & GAME_DoomChex ? CR_RED : CR_UNTRANSLATED,
|
||||
160-SmallFont->StringWidth(joyname)/2, 8 + BigFont->GetHeight(),
|
||||
joyname, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
|
||||
static void UpdateJoystickConfigMenu(IJoystickConfig *joy)
|
||||
{
|
||||
int i;
|
||||
menuitem_t item = { whitetext };
|
||||
|
||||
JoystickConfigItems.Clear();
|
||||
if (joy == NULL)
|
||||
{
|
||||
item.type = redtext;
|
||||
item.label = "Invalid controller specified for menu";
|
||||
JoystickConfigItems.Push(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
SELECTED_JOYSTICK = joy;
|
||||
|
||||
item.type = joy_sens;
|
||||
item.label = "Overall sensitivity";
|
||||
item.b.min = 0.5f;
|
||||
item.c.max = 2.f;
|
||||
item.d.step = 0.2f;
|
||||
JoystickConfigItems.Push(item);
|
||||
|
||||
item.type = redtext;
|
||||
item.label = " ";
|
||||
JoystickConfigItems.Push(item);
|
||||
|
||||
item.type = whitetext;
|
||||
if (joy->GetNumAxes() > 0)
|
||||
{
|
||||
item.label = "Axis Configuration";
|
||||
JoystickConfigItems.Push(item);
|
||||
|
||||
for (i = 0; i < joy->GetNumAxes(); ++i)
|
||||
{
|
||||
item.type = redtext;
|
||||
item.label = " ";
|
||||
JoystickConfigItems.Push(item);
|
||||
|
||||
item.type = joy_map;
|
||||
item.label = joy->GetAxisName(i);
|
||||
item.a.joyselection = i;
|
||||
item.b.numvalues = countof(JoyAxisMapNames);
|
||||
item.e.values = JoyAxisMapNames;
|
||||
JoystickConfigItems.Push(item);
|
||||
|
||||
item.type = joy_slider;
|
||||
item.label = "Sensitivity";
|
||||
item.b.min = 0;
|
||||
item.c.max = 4;
|
||||
item.d.step = 0.2f;
|
||||
item.e.joyslidernum = 0;
|
||||
JoystickConfigItems.Push(item);
|
||||
|
||||
item.type = joy_inverter;
|
||||
item.label = "Invert";
|
||||
JoystickConfigItems.Push(item);
|
||||
|
||||
item.type = joy_slider;
|
||||
item.label = "Dead Zone";
|
||||
item.b.position = 1;
|
||||
item.c.max = 0.9f;
|
||||
item.d.step = 0.05f;
|
||||
item.e.joyslidernum = 1;
|
||||
JoystickConfigItems.Push(item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item.label = "No configurable axes";
|
||||
JoystickConfigItems.Push(item);
|
||||
}
|
||||
}
|
||||
JoystickConfigMenu.items = &JoystickConfigItems[0];
|
||||
JoystickConfigMenu.numitems = JoystickConfigItems.Size();
|
||||
JoystickConfigMenu.lastOn = 0;
|
||||
JoystickConfigMenu.scrollpos = 0;
|
||||
JoystickConfigMenu.y = 25 + BigFont->GetHeight();
|
||||
JoystickConfigMenu.PreDraw = DrawJoystickConfigMenuHeader;
|
||||
if (screen != NULL)
|
||||
{
|
||||
CalcIndent(&JoystickConfigMenu);
|
||||
}
|
||||
}
|
||||
|
||||
static void StartJoystickConfigMenu()
|
||||
{
|
||||
UpdateJoystickConfigMenu(Joysticks[JoystickItems[JoystickMenu.lastOn].a.joyselection]);
|
||||
M_SwitchMenu(&JoystickConfigMenu);
|
||||
}
|
||||
|
||||
void UpdateJoystickMenu(IJoystickConfig *selected)
|
||||
{
|
||||
int i;
|
||||
menuitem_t item = { whitetext };
|
||||
int itemnum;
|
||||
IJoystickConfig *joy;
|
||||
int itemnum = -1;
|
||||
|
||||
if (JoystickItems.Size() > 1)
|
||||
{
|
||||
itemnum = JoystickItems[1].a.joyselection;
|
||||
}
|
||||
else
|
||||
{
|
||||
itemnum = 0;
|
||||
}
|
||||
JoystickItems.Clear();
|
||||
I_GetJoysticks(Joysticks);
|
||||
if ((unsigned)itemnum >= Joysticks.Size())
|
||||
|
@ -3126,162 +3198,95 @@ void UpdateJoystickMenu(IJoystickConfig *selected)
|
|||
}
|
||||
}
|
||||
}
|
||||
item.type = discrete;
|
||||
item.label = "Enable controller support";
|
||||
item.a.cvar = &use_joystick;
|
||||
item.b.numvalues = 2;
|
||||
item.e.values = YesNo;
|
||||
JoystickItems.Push(item);
|
||||
|
||||
#ifdef _WIN32
|
||||
item.label = "Enable DirectInput controllers";
|
||||
item.a.cvar = &joy_dinput;
|
||||
JoystickItems.Push(item);
|
||||
|
||||
item.label = "Enable XInput controllers";
|
||||
item.a.cvar = &joy_xinput;
|
||||
JoystickItems.Push(item);
|
||||
|
||||
item.label = "Enable raw PlayStation 2 adapters";
|
||||
item.a.cvar = &joy_ps2raw;
|
||||
JoystickItems.Push(item);
|
||||
#endif
|
||||
|
||||
item.type = redtext;
|
||||
item.label = " ";
|
||||
JoystickItems.Push(item);
|
||||
|
||||
if (Joysticks.Size() == 0)
|
||||
{
|
||||
item.type = redtext;
|
||||
item.label = "No joysticks connected";
|
||||
item.label = "No controllers detected";
|
||||
JoystickItems.Push(item);
|
||||
if (!use_joystick)
|
||||
{
|
||||
item.type = whitetext;
|
||||
item.label = "Controller support must be";
|
||||
JoystickItems.Push(item);
|
||||
|
||||
item.label = "enabled to detect any";
|
||||
JoystickItems.Push(item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item.type = discrete;
|
||||
item.label = "Enable joystick";
|
||||
item.a.cvar = &use_joystick;
|
||||
item.b.numvalues = 2;
|
||||
item.e.values = YesNo;
|
||||
item.label = "Configure controllers:";
|
||||
JoystickItems.Push(item);
|
||||
|
||||
item.type = discrete_joy;
|
||||
item.label = "Change settings for";
|
||||
item.a.joyselection = itemnum;
|
||||
item.e.joyvalues = &Joysticks;
|
||||
JoystickItems.Push(item);
|
||||
|
||||
item.type = joy_sens;
|
||||
item.label = "Overall sensitivity";
|
||||
item.b.min = 0.5f;
|
||||
item.c.max = 2.f;
|
||||
item.d.step = 0.2f;
|
||||
JoystickItems.Push(item);
|
||||
|
||||
item.type = redtext;
|
||||
item.label = " ";
|
||||
JoystickItems.Push(item);
|
||||
|
||||
joy = Joysticks[itemnum];
|
||||
if (joy->GetNumAxes() > 0)
|
||||
item.type = joymore;
|
||||
item.e.mfunc = StartJoystickConfigMenu;
|
||||
for (int i = 0; i < (int)Joysticks.Size(); ++i)
|
||||
{
|
||||
item.type = whitetext;
|
||||
item.label = "Axis Configuration";
|
||||
item.a.joyselection = i;
|
||||
if (i == itemnum)
|
||||
{
|
||||
JoystickMenu.lastOn = JoystickItems.Size();
|
||||
}
|
||||
JoystickItems.Push(item);
|
||||
|
||||
for (i = 0; i < joy->GetNumAxes(); ++i)
|
||||
{
|
||||
item.type = redtext;
|
||||
item.label = " ";
|
||||
JoystickItems.Push(item);
|
||||
|
||||
item.type = joy_map;
|
||||
item.label = joy->GetAxisName(i);
|
||||
item.a.joyselection = i;
|
||||
item.b.numvalues = countof(JoyAxisMapNames);
|
||||
item.e.values = JoyAxisMapNames;
|
||||
JoystickItems.Push(item);
|
||||
|
||||
item.type = joy_slider;
|
||||
item.label = "Sensitivity";
|
||||
item.b.min = 0;
|
||||
item.c.max = 4;
|
||||
item.d.step = 0.2f;
|
||||
item.e.joyslidernum = 0;
|
||||
JoystickItems.Push(item);
|
||||
|
||||
item.type = joy_inverter;
|
||||
item.label = "Invert";
|
||||
JoystickItems.Push(item);
|
||||
|
||||
item.type = joy_slider;
|
||||
item.label = "Dead Zone";
|
||||
item.b.position = 1;
|
||||
item.c.max = 0.9f;
|
||||
item.d.step = 0.05f;
|
||||
item.e.joyslidernum = 1;
|
||||
JoystickItems.Push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
{
|
||||
JoystickItems[0].type = discrete;
|
||||
JoystickItems[0].label = "Enable joystick";
|
||||
|
||||
JoystickItems[1].b.numvalues = float(JoystickNames.Size());
|
||||
JoystickItems[1].e.guidvalues = &JoystickNames[0];
|
||||
|
||||
line = 5;
|
||||
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
if (JoyAxisNames[i] != NULL)
|
||||
{
|
||||
JoystickItems[line].label = JoyAxisNames[i];
|
||||
JoystickItems[line].type = discrete;
|
||||
JoystickItems[line].a.intcvar = cvars[i];
|
||||
JoystickItems[line].b.numvalues = 6.f;
|
||||
JoystickItems[line].d.graycheck = NULL;
|
||||
JoystickItems[line].e.values = JoyAxisMapNames;
|
||||
line++;
|
||||
}
|
||||
}
|
||||
|
||||
JoystickItems[line].type = redtext;
|
||||
JoystickItems[line].label = " ";
|
||||
line++;
|
||||
|
||||
JoystickItems[line].type = whitetext;
|
||||
JoystickItems[line].label = "Axis Sensitivity";
|
||||
line++;
|
||||
|
||||
for (i = 0; i < 5; ++i)
|
||||
{
|
||||
JoystickItems[line].type = absslider;
|
||||
JoystickItems[line].label = JoyAxisMapNames[i+1].name;
|
||||
JoystickItems[line].a.cvar = cvars2[i];
|
||||
JoystickItems[line].b.min = 0.0;
|
||||
JoystickItems[line].c.max = 4.0;
|
||||
JoystickItems[line].d.step = 0.2f;
|
||||
line++;
|
||||
|
||||
JoystickItems[line].type = inverter;
|
||||
JoystickItems[line].label = JoyAxisMapNames[i+1].name;
|
||||
JoystickItems[line].a.cvar = cvars2[i];
|
||||
JoystickItems[line].e.values = Inversion;
|
||||
line++;
|
||||
}
|
||||
|
||||
JoystickItems[line].type = redtext;
|
||||
JoystickItems[line].label = " ";
|
||||
line++;
|
||||
|
||||
JoystickItems[line].type = whitetext;
|
||||
JoystickItems[line].label = "Axis Dead Zones";
|
||||
line++;
|
||||
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
if (JoyAxisNames[i] != NULL)
|
||||
{
|
||||
JoystickItems[line].label = JoyAxisNames[i];
|
||||
JoystickItems[line].type = slider;
|
||||
JoystickItems[line].a.cvar = cvars3[i];
|
||||
JoystickItems[line].b.min = 0.0;
|
||||
JoystickItems[line].c.max = 0.9f;
|
||||
JoystickItems[line].d.step = 0.05f;
|
||||
line++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
JoystickMenu.items = &JoystickItems[0];
|
||||
JoystickMenu.numitems = JoystickItems.Size();
|
||||
if (JoystickMenu.lastOn >= JoystickMenu.numitems)
|
||||
{
|
||||
JoystickMenu.lastOn = JoystickMenu.numitems - 1;
|
||||
}
|
||||
if (CurrentMenu == &JoystickMenu && CurrentItem >= JoystickMenu.numitems)
|
||||
{
|
||||
CurrentItem = JoystickMenu.lastOn;
|
||||
}
|
||||
if (screen != NULL)
|
||||
{
|
||||
CalcIndent(&JoystickMenu);
|
||||
}
|
||||
|
||||
// If the joystick config menu is open, close it if the device it's
|
||||
// open for is gone.
|
||||
for (i = 0; (unsigned)i < Joysticks.Size(); ++i)
|
||||
{
|
||||
if (Joysticks[i] == SELECTED_JOYSTICK)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == Joysticks.Size())
|
||||
{
|
||||
SELECTED_JOYSTICK = NULL;
|
||||
if (CurrentMenu == &JoystickConfigMenu)
|
||||
{
|
||||
M_PopMenuStack();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void JoystickOptions ()
|
||||
|
|
|
@ -474,3 +474,8 @@ void I_GetAxes(float axes[NUM_JOYAXIS])
|
|||
axes[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
IJoystickConfig *I_UpdateDeviceList()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1179,6 +1179,8 @@ void FMODSoundRenderer::PrintStatus()
|
|||
unsigned int bufferlength;
|
||||
int numbuffers;
|
||||
|
||||
Printf ("Loaded FMOD version: "TEXTCOLOR_GREEN"%x.%02x.%02x\n", ActiveFMODVersion >> 16,
|
||||
(ActiveFMODVersion >> 8) & 255, ActiveFMODVersion & 255);
|
||||
if (FMOD_OK == Sys->getOutput(&output))
|
||||
{
|
||||
Printf ("Output type: "TEXTCOLOR_GREEN"%s\n", Enum_NameForNum(OutputNames, output));
|
||||
|
@ -1361,11 +1363,12 @@ SoundStream *FMODSoundRenderer::CreateStream (SoundStreamCallback callback, int
|
|||
FMODStreamCapsule *capsule;
|
||||
FMOD::Sound *sound;
|
||||
FMOD_RESULT result;
|
||||
FMOD_CREATESOUNDEXINFO exinfo = { sizeof(exinfo), };
|
||||
FMOD_CREATESOUNDEXINFO exinfo;
|
||||
FMOD_MODE mode;
|
||||
int sample_shift;
|
||||
int channel_shift;
|
||||
|
||||
InitCreateSoundExInfo(&exinfo);
|
||||
capsule = new FMODStreamCapsule (userdata, callback, this);
|
||||
|
||||
mode = FMOD_2D | FMOD_OPENUSER | FMOD_LOOP_NORMAL | FMOD_SOFTWARE | FMOD_CREATESTREAM | FMOD_OPENONLY;
|
||||
|
@ -1434,11 +1437,12 @@ SoundStream *FMODSoundRenderer::CreateStream (SoundStreamCallback callback, int
|
|||
SoundStream *FMODSoundRenderer::OpenStream(const char *filename_or_data, int flags, int offset, int length)
|
||||
{
|
||||
FMOD_MODE mode;
|
||||
FMOD_CREATESOUNDEXINFO exinfo = { sizeof(exinfo), };
|
||||
FMOD_CREATESOUNDEXINFO exinfo;
|
||||
FMOD::Sound *stream;
|
||||
FMOD_RESULT result;
|
||||
bool url;
|
||||
|
||||
InitCreateSoundExInfo(&exinfo);
|
||||
mode = FMOD_SOFTWARE | FMOD_2D | FMOD_CREATESTREAM;
|
||||
if (flags & SoundStream::Loop)
|
||||
{
|
||||
|
@ -2129,11 +2133,12 @@ void FMODSoundRenderer::UpdateSounds()
|
|||
|
||||
SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits)
|
||||
{
|
||||
FMOD_CREATESOUNDEXINFO exinfo = { sizeof(exinfo), };
|
||||
FMOD_CREATESOUNDEXINFO exinfo;
|
||||
SoundHandle retval = { NULL };
|
||||
|
||||
if (length == 0) return retval;
|
||||
|
||||
InitCreateSoundExInfo(&exinfo);
|
||||
exinfo.length = length;
|
||||
exinfo.numchannels = channels;
|
||||
exinfo.defaultfrequency = frequency;
|
||||
|
@ -2184,11 +2189,12 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ
|
|||
|
||||
SoundHandle FMODSoundRenderer::LoadSound(BYTE *sfxdata, int length)
|
||||
{
|
||||
FMOD_CREATESOUNDEXINFO exinfo = { sizeof(exinfo), };
|
||||
FMOD_CREATESOUNDEXINFO exinfo;
|
||||
SoundHandle retval = { NULL };
|
||||
|
||||
if (length == 0) return retval;
|
||||
|
||||
InitCreateSoundExInfo(&exinfo);
|
||||
exinfo.length = length;
|
||||
|
||||
const FMOD_MODE samplemode = FMOD_3D | FMOD_OPENMEMORY | FMOD_SOFTWARE;
|
||||
|
@ -2623,7 +2629,7 @@ void FMODSoundRenderer::DrawSpectrum(float *spectrumarray, int x, int y, int wid
|
|||
|
||||
short *FMODSoundRenderer::DecodeSample(int outlen, const void *coded, int sizebytes, ECodecType type)
|
||||
{
|
||||
FMOD_CREATESOUNDEXINFO exinfo = { sizeof(exinfo), };
|
||||
FMOD_CREATESOUNDEXINFO exinfo;
|
||||
FMOD::Sound *sound;
|
||||
FMOD_SOUND_FORMAT format;
|
||||
int channels;
|
||||
|
@ -2631,6 +2637,7 @@ short *FMODSoundRenderer::DecodeSample(int outlen, const void *coded, int sizeby
|
|||
FMOD_RESULT result;
|
||||
short *outbuf;
|
||||
|
||||
InitCreateSoundExInfo(&exinfo);
|
||||
if (type == CODEC_Vorbis)
|
||||
{
|
||||
exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_OGGVORBIS;
|
||||
|
@ -2667,3 +2674,28 @@ short *FMODSoundRenderer::DecodeSample(int outlen, const void *coded, int sizeby
|
|||
}
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMODSoundRenderer :: InitCreateSoundExInfo
|
||||
//
|
||||
// Allow for compiling with 4.26 APIs while still running with older DLLs.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FMODSoundRenderer::InitCreateSoundExInfo(FMOD_CREATESOUNDEXINFO *exinfo) const
|
||||
{
|
||||
#if FMOD_VERSION >= 0x42600
|
||||
if (ActiveFMODVersion < 0x42600)
|
||||
{
|
||||
// This parameter was added for 4.26.00, and trying to pass it to older
|
||||
// DLLs will fail.
|
||||
exinfo->cbsize = myoffsetof(FMOD_CREATESOUNDEXINFO, ignoresetfilesystem);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
exinfo->cbsize = sizeof(exinfo);
|
||||
}
|
||||
memset((BYTE *)exinfo + sizeof(exinfo->cbsize), 0, exinfo->cbsize - sizeof(exinfo->cbsize));
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@ private:
|
|||
FMOD_MODE SetChanHeadSettings(SoundListener *listener, FMOD::Channel *chan, const FVector3 &pos, bool areasound, FMOD_MODE oldmode) const;
|
||||
|
||||
bool ReconnectSFXReverbUnit();
|
||||
void InitCreateSoundExInfo(FMOD_CREATESOUNDEXINFO *exinfo) const;
|
||||
|
||||
bool Init ();
|
||||
void Shutdown ();
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include <wbemidl.h>
|
||||
#endif
|
||||
#include <oleauto.h>
|
||||
#include <dbt.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#define USE_WINDOWS_DWORD
|
||||
|
@ -28,6 +27,7 @@
|
|||
#include "cmdlib.h"
|
||||
#include "v_text.h"
|
||||
#include "m_argv.h"
|
||||
#include "rawinput.h"
|
||||
|
||||
// WBEMIDL BITS -- because w32api doesn't have this, either -----------------
|
||||
|
||||
|
@ -208,9 +208,9 @@ public:
|
|||
|
||||
bool GetDevice();
|
||||
void ProcessInput();
|
||||
bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result);
|
||||
void AddAxes(float axes[NUM_JOYAXIS]);
|
||||
void GetDevices(TArray<IJoystickConfig *> &sticks);
|
||||
IJoystickConfig *Rescan();
|
||||
|
||||
protected:
|
||||
struct Enumerator
|
||||
|
@ -225,6 +225,8 @@ protected:
|
|||
static BOOL CALLBACK EnumCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef);
|
||||
static int STACK_ARGS NameSort(const void *a, const void *b);
|
||||
static bool IsXInputDevice(const GUID *guid);
|
||||
static bool IsXInputDeviceFast(const GUID *guid);
|
||||
static bool IsXInputDeviceSlow(const GUID *guid);
|
||||
};
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
@ -245,8 +247,12 @@ extern HWND Window;
|
|||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
CVAR (Bool, use_joystick, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
FJoystickCollection *JoyDevices[NUM_JOYDEVICES];
|
||||
CUSTOM_CVAR(Bool, joy_dinput, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_NOINITCALL)
|
||||
{
|
||||
I_StartupDirectInputJoystick();
|
||||
event_t ev = { EV_DeviceChange };
|
||||
D_PostEvent(&ev);
|
||||
}
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
|
@ -981,7 +987,7 @@ FDInputJoystickManager::~FDInputJoystickManager()
|
|||
|
||||
bool FDInputJoystickManager::GetDevice()
|
||||
{
|
||||
if (g_pdi == NULL || !use_joystick || Args->CheckParm("-nojoy"))
|
||||
if (g_pdi == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1041,37 +1047,6 @@ void FDInputJoystickManager::GetDevices(TArray<IJoystickConfig *> &sticks)
|
|||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FDInputJoystickManager :: WndProcHook
|
||||
//
|
||||
// Listen for device change broadcasts and rescan the attached devices
|
||||
// when they are received.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool FDInputJoystickManager::WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result)
|
||||
{
|
||||
if (message != WM_DEVICECHANGE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
char out[64];
|
||||
mysnprintf(out, countof(out), "WM_DEVICECHANGE wParam=%d\n", wParam);
|
||||
OutputDebugString(out);
|
||||
#endif
|
||||
if ((wParam != DBT_DEVNODES_CHANGED &&
|
||||
wParam != DBT_DEVICEARRIVAL &&
|
||||
wParam != DBT_CONFIGCHANGED))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
UpdateJoystickMenu(EnumDevices());
|
||||
// Return false so that other devices can handle this too if they want.
|
||||
return false;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FDInputJoystickManager :: EnumCallback STATIC
|
||||
|
@ -1101,16 +1076,46 @@ BOOL CALLBACK FDInputJoystickManager::EnumCallback(LPCDIDEVICEINSTANCE lpddi, LP
|
|||
//
|
||||
// FDInputJoystickManager :: IsXInputDevice STATIC
|
||||
//
|
||||
// Pretty much copied straight from the article "XInput and DirectInput".
|
||||
//
|
||||
// Enum each PNP device using WMI and check each device ID to see if it
|
||||
// contains "IG_" (ex. "VID_045E&PID_028E&IG_00"). If it does, then it's an
|
||||
// XInput device. Unfortunately this information can not be found by just
|
||||
// using DirectInput.
|
||||
// Does the DirectInput product GUID correspond to an XInput controller?
|
||||
|
||||
// If the product's device ID contains contains "IG_"
|
||||
// (ex. "VID_045E&PID_028E&IG_00"), then it is an XInput device.
|
||||
// Unfortunately this information can not be found by just using DirectInput.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool FDInputJoystickManager::IsXInputDevice(const GUID *guid)
|
||||
{
|
||||
if (MyGetRawInputDeviceList == NULL || MyGetRawInputDeviceInfoA == NULL)
|
||||
{
|
||||
return IsXInputDeviceSlow(guid);
|
||||
}
|
||||
else
|
||||
{
|
||||
return IsXInputDeviceFast(guid);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FDInputJoystickManager :: IsXInputDeviceSlow STATIC
|
||||
//
|
||||
// Pretty much copied straight from the article "XInput and DirectInput".
|
||||
//
|
||||
// Enum each PNP device using WMI and check each device ID. This is
|
||||
// Microsoft's reference implementation, but it is damn slow. After
|
||||
// a hardware change, connecting to the WMI server can take nearly three
|
||||
// seconds, and creating the instance enumerator consistantly takes longer
|
||||
// than 0.25 seconds.
|
||||
//
|
||||
// The XInput DLL can apparently be hacked fairly simply to work with
|
||||
// Windows 2000, and since Raw Input wasn't introduced until XP, I think
|
||||
// that's reason enough to keep this version around, despite it being
|
||||
// so horrendously slow.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool FDInputJoystickManager::IsXInputDeviceSlow(const GUID *guid)
|
||||
{
|
||||
IWbemLocator *wbemlocator = NULL;
|
||||
IEnumWbemClassObject *enumdevices = NULL;
|
||||
|
@ -1201,6 +1206,71 @@ cleanup:
|
|||
return isxinput;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FDInputJoystickManager :: IsXInputDeviceFast STATIC
|
||||
//
|
||||
// The theory of operation is the same as for IsXInputDeviceSlow, except that
|
||||
// we use the Raw Input device list to find the device ID instead of WMI.
|
||||
// This generally takes ~0.02 ms on my machine, though it occasionally spikes
|
||||
// at over 1 ms. Either way, it is a huge order of magnitude faster than WMI.
|
||||
// (around 10,000 times faster, in fact!)
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool FDInputJoystickManager::IsXInputDeviceFast(const GUID *guid)
|
||||
{
|
||||
UINT nDevices, numDevices;
|
||||
RAWINPUTDEVICELIST *devices;
|
||||
UINT i;
|
||||
bool isxinput = false;
|
||||
|
||||
if (MyGetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST)) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ((devices = (RAWINPUTDEVICELIST *)malloc(sizeof(RAWINPUTDEVICELIST) * nDevices)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ((numDevices = MyGetRawInputDeviceList(devices, &nDevices, sizeof(RAWINPUTDEVICELIST))) == (UINT)-1)
|
||||
{
|
||||
free(devices);
|
||||
return false;
|
||||
}
|
||||
for (i = 0; i < numDevices; ++i)
|
||||
{
|
||||
// I am making the assumption here that all possible XInput devices
|
||||
// will report themselves as generic HID devices and not as keyboards
|
||||
// or mice.
|
||||
if (devices[i].dwType == RIM_TYPEHID)
|
||||
{
|
||||
RID_DEVICE_INFO rdi;
|
||||
UINT cbSize;
|
||||
|
||||
cbSize = rdi.cbSize = sizeof(rdi);
|
||||
if (MyGetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICEINFO, &rdi, &cbSize) >= 0)
|
||||
{
|
||||
if(MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == guid->Data1)
|
||||
{
|
||||
char name[256];
|
||||
UINT namelen = countof(name);
|
||||
UINT reslen;
|
||||
|
||||
reslen = MyGetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICENAME, name, &namelen);
|
||||
if (reslen != (UINT)-1)
|
||||
{
|
||||
isxinput = (strstr(name, "IG_") != NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(devices);
|
||||
return isxinput;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FDInputJoystickManager :: NameSort STATIC
|
||||
|
@ -1319,6 +1389,21 @@ FDInputJoystick *FDInputJoystickManager::EnumDevices()
|
|||
return newone;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FDInputJoystickManager :: Rescan
|
||||
//
|
||||
// Used by the joy_ps2raw and joy_xinput callbacks to rescan the
|
||||
// DirectInput devices, since their presence or absence can affect the
|
||||
// results of the scan.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
IJoystickConfig *FDInputJoystickManager::Rescan()
|
||||
{
|
||||
return EnumDevices();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// I_StartupDirectInputJoystick
|
||||
|
@ -1327,84 +1412,23 @@ FDInputJoystick *FDInputJoystickManager::EnumDevices()
|
|||
|
||||
void I_StartupDirectInputJoystick()
|
||||
{
|
||||
FJoystickCollection *joys = new FDInputJoystickManager;
|
||||
if (joys->GetDevice())
|
||||
if (!joy_dinput || !use_joystick || Args->CheckParm("-nojoy"))
|
||||
{
|
||||
JoyDevices[INPUT_DIJoy] = joys;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Joy_RemoveDeadZone
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
double Joy_RemoveDeadZone(double axisval, double deadzone, BYTE *buttons)
|
||||
{
|
||||
// Cancel out deadzone.
|
||||
if (fabs(axisval) < deadzone)
|
||||
{
|
||||
axisval = 0;
|
||||
*buttons = 0;
|
||||
}
|
||||
// Make the dead zone the new 0.
|
||||
else if (axisval < 0)
|
||||
{
|
||||
axisval = (axisval + deadzone) / (1.0 - deadzone);
|
||||
*buttons = 2; // button minus
|
||||
if (JoyDevices[INPUT_DIJoy] != NULL)
|
||||
{
|
||||
delete JoyDevices[INPUT_DIJoy];
|
||||
JoyDevices[INPUT_DIJoy] = NULL;
|
||||
UpdateJoystickMenu(NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
axisval = (axisval - deadzone) / (1.0 - deadzone);
|
||||
*buttons = 1; // button plus
|
||||
}
|
||||
return axisval;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Joy_GenerateButtonEvents
|
||||
//
|
||||
// Provided two bitmasks for a set of buttons, generates events to reflect
|
||||
// any changes from the old to new set, where base is the key for bit 0,
|
||||
// base+1 is the key for bit 1, etc.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base)
|
||||
{
|
||||
int changed = oldbuttons ^ newbuttons;
|
||||
if (changed != 0)
|
||||
{
|
||||
event_t ev = { 0 };
|
||||
int mask = 1;
|
||||
for (int j = 0; j < numbuttons; mask <<= 1, ++j)
|
||||
if (JoyDevices[INPUT_DIJoy] == NULL)
|
||||
{
|
||||
if (changed & mask)
|
||||
FJoystickCollection *joys = new FDInputJoystickManager;
|
||||
if (joys->GetDevice())
|
||||
{
|
||||
ev.data1 = base + j;
|
||||
ev.type = (newbuttons & mask) ? EV_KeyDown : EV_KeyUp;
|
||||
D_PostEvent(&ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, const int *keys)
|
||||
{
|
||||
int changed = oldbuttons ^ newbuttons;
|
||||
if (changed != 0)
|
||||
{
|
||||
event_t ev = { 0 };
|
||||
int mask = 1;
|
||||
for (int j = 0; j < numbuttons; mask <<= 1, ++j)
|
||||
{
|
||||
if (changed & mask)
|
||||
{
|
||||
ev.data1 = keys[j];
|
||||
ev.type = (newbuttons & mask) ? EV_KeyDown : EV_KeyUp;
|
||||
D_PostEvent(&ev);
|
||||
JoyDevices[INPUT_DIJoy] = joys;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#endif
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#include <dbt.h>
|
||||
#include <dinput.h>
|
||||
#include <malloc.h>
|
||||
|
||||
|
@ -118,7 +119,8 @@
|
|||
#endif
|
||||
|
||||
static void FindRawInputFunctions();
|
||||
BOOL DI_InitJoy (void);
|
||||
FJoystickCollection *JoyDevices[NUM_JOYDEVICES];
|
||||
|
||||
|
||||
extern HINSTANCE g_hInst;
|
||||
extern DWORD SessionID;
|
||||
|
@ -551,6 +553,16 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
case WM_ERASEBKGND:
|
||||
return true;
|
||||
|
||||
case WM_DEVICECHANGE:
|
||||
if (wParam == DBT_DEVNODES_CHANGED ||
|
||||
wParam == DBT_DEVICEARRIVAL ||
|
||||
wParam == DBT_CONFIGCHANGED)
|
||||
{
|
||||
event_t ev = { EV_DeviceChange };
|
||||
D_PostEvent(&ev);
|
||||
}
|
||||
return DefWindowProc (hWnd, message, wParam, lParam);
|
||||
|
||||
default:
|
||||
return DefWindowProc (hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
@ -765,6 +777,24 @@ void I_GetJoysticks(TArray<IJoystickConfig *> &sticks)
|
|||
}
|
||||
}
|
||||
|
||||
// If a new controller was added, returns a pointer to it.
|
||||
IJoystickConfig *I_UpdateDeviceList()
|
||||
{
|
||||
IJoystickConfig *newone = NULL;
|
||||
for (int i = 0; i < NUM_JOYDEVICES; ++i)
|
||||
{
|
||||
if (JoyDevices[i] != NULL)
|
||||
{
|
||||
IJoystickConfig *thisnewone = JoyDevices[i]->Rescan();
|
||||
if (newone == NULL)
|
||||
{
|
||||
newone = thisnewone;
|
||||
}
|
||||
}
|
||||
}
|
||||
return newone;
|
||||
}
|
||||
|
||||
void I_PutInClipboard (const char *str)
|
||||
{
|
||||
if (str == NULL || !OpenClipboard (Window))
|
||||
|
|
|
@ -115,6 +115,7 @@ class NOVTABLE FJoystickCollection : public FInputDevice
|
|||
public:
|
||||
virtual void AddAxes(float axes[NUM_JOYAXIS]) = 0;
|
||||
virtual void GetDevices(TArray<IJoystickConfig *> &sticks) = 0;
|
||||
virtual IJoystickConfig *Rescan() = 0;
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -135,10 +136,6 @@ void I_StartupDirectInputJoystick();
|
|||
void I_StartupRawPS2();
|
||||
bool I_IsPS2Adapter(DWORD vidpid);
|
||||
|
||||
void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base);
|
||||
void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, const int *keys);
|
||||
double Joy_RemoveDeadZone(double axisval, double deadzone, BYTE *buttons);
|
||||
|
||||
// USB HID usage page numbers
|
||||
#define HID_GENERIC_DESKTOP_PAGE 0x01
|
||||
#define HID_SIMULATION_CONTROLS_PAGE 0x02
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include <windows.h>
|
||||
#include <malloc.h>
|
||||
#include <limits.h>
|
||||
#include <dbt.h>
|
||||
|
||||
#define USE_WINDOWS_DWORD
|
||||
#include "i_input.h"
|
||||
|
@ -150,12 +149,11 @@ public:
|
|||
|
||||
bool GetDevice();
|
||||
bool ProcessRawInput(RAWINPUT *raw, int code);
|
||||
bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result);
|
||||
void AddAxes(float axes[NUM_JOYAXIS]);
|
||||
void GetDevices(TArray<IJoystickConfig *> &sticks);
|
||||
IJoystickConfig *Rescan();
|
||||
|
||||
protected:
|
||||
HMODULE XInputDLL;
|
||||
TArray<FRawPS2Controller *> Devices;
|
||||
bool Registered;
|
||||
|
||||
|
@ -200,6 +198,13 @@ extern HWND Window;
|
|||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
CUSTOM_CVAR(Bool, joy_ps2raw, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_NOINITCALL)
|
||||
{
|
||||
I_StartupRawPS2();
|
||||
event_t ev = { EV_DeviceChange };
|
||||
D_PostEvent(&ev);
|
||||
}
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
static const int ButtonKeys[16] =
|
||||
|
@ -938,37 +943,6 @@ void FRawPS2Manager::GetDevices(TArray<IJoystickConfig *> &sticks)
|
|||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FRawPS2Manager :: WndProcHook
|
||||
//
|
||||
// Listen for device change broadcasts and rescan the attached devices
|
||||
// when they are received.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool FRawPS2Manager::WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result)
|
||||
{
|
||||
if (message != WM_DEVICECHANGE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
char out[64];
|
||||
mysnprintf(out, countof(out), "WM_DEVICECHANGE wParam=%d\n", wParam);
|
||||
OutputDebugString(out);
|
||||
#endif
|
||||
if ((wParam != DBT_DEVNODES_CHANGED &&
|
||||
wParam != DBT_DEVICEARRIVAL &&
|
||||
wParam != DBT_CONFIGCHANGED))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
UpdateJoystickMenu(EnumDevices());
|
||||
// Return false so that other devices can handle this too if they want.
|
||||
return false;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FRawPS2Manager :: ProcessRawInput
|
||||
|
@ -994,6 +968,17 @@ bool FRawPS2Manager::ProcessRawInput(RAWINPUT *raw, int code)
|
|||
return false;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FRawPS2Manager :: Rescan
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
IJoystickConfig *FRawPS2Manager::Rescan()
|
||||
{
|
||||
return EnumDevices();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FRawPS2Manager :: EnumDevices
|
||||
|
@ -1292,10 +1277,25 @@ void FRawPS2Manager::DoRegister()
|
|||
|
||||
void I_StartupRawPS2()
|
||||
{
|
||||
FJoystickCollection *joys = new FRawPS2Manager;
|
||||
if (joys->GetDevice())
|
||||
if (!joy_ps2raw || !use_joystick || Args->CheckParm("-nojoy"))
|
||||
{
|
||||
JoyDevices[INPUT_RawPS2] = joys;
|
||||
if (JoyDevices[INPUT_RawPS2] != NULL)
|
||||
{
|
||||
delete JoyDevices[INPUT_RawPS2];
|
||||
JoyDevices[INPUT_RawPS2] = NULL;
|
||||
UpdateJoystickMenu(NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (JoyDevices[INPUT_RawPS2] == NULL)
|
||||
{
|
||||
FJoystickCollection *joys = new FRawPS2Manager;
|
||||
if (joys->GetDevice())
|
||||
{
|
||||
JoyDevices[INPUT_RawPS2] = joys;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -120,6 +120,7 @@ public:
|
|||
bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result);
|
||||
void AddAxes(float axes[NUM_JOYAXIS]);
|
||||
void GetDevices(TArray<IJoystickConfig *> &sticks);
|
||||
IJoystickConfig *Rescan();
|
||||
|
||||
protected:
|
||||
HMODULE XInputDLL;
|
||||
|
@ -136,6 +137,13 @@ protected:
|
|||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
CUSTOM_CVAR(Bool, joy_xinput, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_NOINITCALL)
|
||||
{
|
||||
I_StartupXInput();
|
||||
event_t ev = { EV_DeviceChange };
|
||||
D_PostEvent(&ev);
|
||||
}
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
static XInputGetStateType InputGetState;
|
||||
|
@ -734,6 +742,17 @@ bool FXInputManager::WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM
|
|||
return false;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FXInputManager :: Rescan
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
IJoystickConfig *FXInputManager::Rescan()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// I_StartupXInput
|
||||
|
@ -742,10 +761,25 @@ bool FXInputManager::WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM
|
|||
|
||||
void I_StartupXInput()
|
||||
{
|
||||
FJoystickCollection *joys = new FXInputManager;
|
||||
if (joys->GetDevice())
|
||||
if (!joy_xinput || !use_joystick || Args->CheckParm("-nojoy"))
|
||||
{
|
||||
JoyDevices[INPUT_XInput] = joys;
|
||||
if (JoyDevices[INPUT_XInput] != NULL)
|
||||
{
|
||||
delete JoyDevices[INPUT_XInput];
|
||||
JoyDevices[INPUT_XInput] = NULL;
|
||||
UpdateJoystickMenu(NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (JoyDevices[INPUT_XInput] == NULL)
|
||||
{
|
||||
FJoystickCollection *joys = new FXInputManager;
|
||||
if (joys->GetDevice())
|
||||
{
|
||||
JoyDevices[INPUT_XInput] = joys;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue