- Joystick axes can be configured in the menu again. TODO: Config saving

and loading, XInput, allow axes to be used as buttons (for the Xbox
  controller's trigger buttons), allow the joystick to move through the
  menus, and my PS2 adapter which has no Vista x64 drivers.
  * I'm sure SDL is broken again. Don't bother reporting it, because I already know.

SVN r1680 (trunk)
This commit is contained in:
Randy Heit 2009-06-26 02:45:05 +00:00
parent 6d1cee3398
commit 590eb5cb76
8 changed files with 549 additions and 166 deletions

View file

@ -1,4 +1,10 @@
June 22, 2009 June 25, 2009
- Joystick axes can be configured in the menu again. TODO: Config saving
and loading, XInput, allow axes to be used as buttons (for the Xbox
controller's trigger buttons), allow the joystick to move through the
menus, and my PS2 adapter which has no Vista x64 drivers.
June 22, 2009
- Changed the definition of SBarInfoCoordinate to use bitfields to pack its - Changed the definition of SBarInfoCoordinate to use bitfields to pack its
members into 32 bits so that it can be stored in a plain old int without members into 32 bits so that it can be stored in a plain old int without
any transformations. The transformation coord -> int -> coord was any transformations. The transformation coord -> int -> coord was

View file

@ -584,7 +584,7 @@ void G_BuildTiccmd (ticcmd_t *cmd)
// Remap some axes depending on button state. // Remap some axes depending on button state.
if (Button_Strafe.bDown || (Button_Mlook.bDown && lookstrafe)) if (Button_Strafe.bDown || (Button_Mlook.bDown && lookstrafe))
{ {
joyaxes[JOYAXIS_Side] = -joyaxes[JOYAXIS_Yaw]; joyaxes[JOYAXIS_Side] = joyaxes[JOYAXIS_Yaw];
joyaxes[JOYAXIS_Yaw] = 0; joyaxes[JOYAXIS_Yaw] = 0;
} }
if (Button_Mlook.bDown) if (Button_Mlook.bDown)
@ -604,7 +604,7 @@ void G_BuildTiccmd (ticcmd_t *cmd)
LocalKeyboardTurner = true; LocalKeyboardTurner = true;
} }
side += int(MAXPLMOVE * joyaxes[JOYAXIS_Side]); side -= int(MAXPLMOVE * joyaxes[JOYAXIS_Side]);
forward += int(joyaxes[JOYAXIS_Forward] * MAXPLMOVE); forward += int(joyaxes[JOYAXIS_Forward] * MAXPLMOVE);
fly += int(joyaxes[JOYAXIS_Up] * 2048); fly += int(joyaxes[JOYAXIS_Up] * 2048);

View file

@ -92,7 +92,7 @@ enum
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
SBarInfoCoordinate::SBarInfoCoordinate(int coord, bool relCenter) : SBarInfoCoordinate::SBarInfoCoordinate(int coord, bool relCenter) :
value(coord), relCenter(relCenter) relCenter(relCenter), value(coord)
{ {
} }

View file

@ -101,7 +101,7 @@ typedef enum {
discretes, discretes,
cdiscrete, cdiscrete,
ediscrete, ediscrete,
discrete_guid, discrete_joy,
control, control,
screenres, screenres,
bitflag, bitflag,
@ -112,9 +112,13 @@ typedef enum {
colorpicker, colorpicker,
intslider, intslider,
palettegrid, palettegrid,
joy_sens,
joy_slider,
joy_map,
joy_inverter,
} itemtype; } itemtype;
struct GUIDName; struct IJoystickConfig;
struct menuitem_t struct menuitem_t
{ {
@ -127,6 +131,7 @@ struct menuitem_t
FColorCVar *colorcvar; FColorCVar *colorcvar;
int selmode; int selmode;
float fval; float fval;
int joyselection;
} a; } a;
union { union {
float min; /* aka numvalues aka invflag */ float min; /* aka numvalues aka invflag */
@ -152,13 +157,14 @@ struct menuitem_t
struct value_t *values; struct value_t *values;
struct valuestring_t *valuestrings; struct valuestring_t *valuestrings;
struct valueenum_t *enumvalues; struct valueenum_t *enumvalues;
GUIDName *guidvalues; TArray<IJoystickConfig *> *joyvalues;
char *command; char *command;
void (*cfunc)(FBaseCVar *cvar, float newval); void (*cfunc)(FBaseCVar *cvar, float newval);
void (*mfunc)(void); void (*mfunc)(void);
void (*lfunc)(int); void (*lfunc)(int);
int highlight; int highlight;
int flagmask; int flagmask;
int joyslidernum;
} e; } e;
}; };

View file

@ -3,7 +3,7 @@
** New options menu code ** New options menu code
** **
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** Copyright 1998-2006 Randy Heit ** Copyright 1998-2009 Randy Heit
** All rights reserved. ** All rights reserved.
** **
** Redistribution and use in source and binary forms, with or without ** Redistribution and use in source and binary forms, with or without
@ -289,7 +289,10 @@ menu_t MouseMenu =
* *
*=======================================*/ *=======================================*/
#define SELECTED_JOYSTICK (Joysticks[JoystickItems[1].a.joyselection])
EXTERN_CVAR (Bool, use_joystick) EXTERN_CVAR (Bool, use_joystick)
void UpdateJoystickMenu();
#if 0 #if 0
EXTERN_CVAR (Float, joy_speedmultiplier) EXTERN_CVAR (Float, joy_speedmultiplier)
EXTERN_CVAR (Int, joy_xaxis) EXTERN_CVAR (Int, joy_xaxis)
@ -318,12 +321,12 @@ EXTERN_CVAR (GUID, joy_guid)
static value_t JoyAxisMapNames[6] = static value_t JoyAxisMapNames[6] =
{ {
{ 0.0, "None" }, { (float)JOYAXIS_None, "None" },
{ 1.0, "Turning" }, { (float)JOYAXIS_Yaw, "Turning" },
{ 2.0, "Looking Up/Down" }, { (float)JOYAXIS_Pitch, "Looking Up/Down" },
{ 3.0, "Moving Forward" }, { (float)JOYAXIS_Forward, "Moving Forward" },
{ 4.0, "Strafing" }, { (float)JOYAXIS_Side, "Strafing" },
{ 5.0, "Moving Up/Down" } { (float)JOYAXIS_Up, "Moving Up/Down" }
}; };
static value_t Inversion[2] = static value_t Inversion[2] =
@ -332,55 +335,13 @@ static value_t Inversion[2] =
{ 1.0, "Inverted" } { 1.0, "Inverted" }
}; };
static menuitem_t JoystickItems[] = static TArray<IJoystickConfig *> Joysticks;
{
#if 0
{ discrete, "Enable joystick", {&use_joystick}, {2.0}, {0.0}, {0.0}, {YesNo} },
{ discrete_guid,"Active joystick", {&joy_guid}, {0.0}, {0.0}, {0.0}, {NULL} },
{ slider, "Overall sensitivity", {&joy_speedmultiplier}, {0.9f}, {2.0}, {0.2f}, {NULL} },
#endif
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ whitetext,"Axis Assignments", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} }, static TArray<menuitem_t> JoystickItems;
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
};
menu_t JoystickMenu = menu_t JoystickMenu =
{ {
"JOYSTICK OPTIONS", "JOYSTICK OPTIONS",
0,
countof(JoystickItems),
0,
JoystickItems,
}; };
@ -1633,19 +1594,6 @@ int M_FindCurVal (float cur, valuestring_t *values, int numvals)
return v; return v;
} }
#if 0
int M_FindCurGUID (const GUID &guid, GUIDName *values, int numvals)
{
int v;
for (v = 0; v < numvals; v++)
if (memcmp (&values[v].ID, &guid, sizeof(GUID)) == 0)
break;
return v;
}
#endif
const char *M_FindCurVal(const char *cur, valueenum_t *values, int numvals) const char *M_FindCurVal(const char *cur, valueenum_t *values, int numvals)
{ {
for (int v = 0; v < numvals; ++v) for (int v = 0; v < numvals; ++v)
@ -1753,7 +1701,23 @@ void M_OptDrawer ()
if (item->type != screenres) if (item->type != screenres)
{ {
width = SmallFont->StringWidth (item->label); const char *label;
if (item->type != discrete_joy)
{
label = item->label;
}
else
{
if (item->e.joyvalues->Size() == 0)
{
label = "No devices connected";
}
else
{
label = (*item->e.joyvalues)[item->a.joyselection]->GetName();
}
}
width = SmallFont->StringWidth(label);
switch (item->type) switch (item->type)
{ {
case more: case more:
@ -1769,6 +1733,13 @@ void M_OptDrawer ()
color = item->type != rightmore ? CR_GREEN : MoreColor; color = item->type != rightmore ? CR_GREEN : MoreColor;
break; break;
case discrete_joy:
x = 160 - width / 2;
// Move cursor to the left of this item.
indent = x - 14;
color = ValueColor;
break;
case redtext: case redtext:
x = 160 - width / 2; x = 160 - width / 2;
color = LabelColor; color = LabelColor;
@ -1802,7 +1773,7 @@ void M_OptDrawer ()
? CR_YELLOW : LabelColor; ? CR_YELLOW : LabelColor;
break; break;
} }
screen->DrawText (SmallFont, color, x, y, item->label, DTA_Clean, true, DTA_ColorOverlay, overlay, TAG_DONE); screen->DrawText (SmallFont, color, x, y, label, DTA_Clean, true, DTA_ColorOverlay, overlay, TAG_DONE);
switch (item->type) switch (item->type)
{ {
@ -1846,11 +1817,19 @@ void M_OptDrawer ()
case discrete: case discrete:
case cdiscrete: case cdiscrete:
case inverter: case inverter:
case joy_map:
{ {
int v, vals; int v, vals;
overlay = 0; overlay = 0;
value = item->a.cvar->GetGenericRep (CVAR_Float); if (item->type == joy_map)
{
value.Float = (float)SELECTED_JOYSTICK->GetAxisMap(item->a.joyselection);
}
else
{
value = item->a.cvar->GetGenericRep (CVAR_Float);
}
if (item->type == inverter) if (item->type == inverter)
{ {
value.Float = (value.Float < 0.f); value.Float = (value.Float < 0.f);
@ -1902,34 +1881,37 @@ void M_OptDrawer ()
} }
break; break;
#if 0
case discrete_guid:
{
int v, vals;
vals = (int)item->b.numvalues;
v = M_FindCurGUID (*(item->a.guidcvar), item->e.guidvalues, vals);
if (v == vals)
{
UCVarValue val = item->a.guidcvar->GetGenericRep (CVAR_String);
screen->DrawText (SmallFont, ValueColor, indent + 14, y, val.String, DTA_Clean, true, TAG_DONE);
}
else
{
screen->DrawText (SmallFont, ValueColor, indent + 14, y, item->e.guidvalues[v].Name,
DTA_Clean, true, TAG_DONE);
}
}
break;
#endif
case nochoice: case nochoice:
screen->DrawText (SmallFont, CR_GOLD, indent + 14, y, screen->DrawText (SmallFont, CR_GOLD, indent + 14, y,
(item->e.values[(int)item->b.min]).name, DTA_Clean, true, TAG_DONE); (item->e.values[(int)item->b.min]).name, DTA_Clean, true, TAG_DONE);
break; break;
case joy_sens:
value.Float = SELECTED_JOYSTICK->GetSensitivity();
M_DrawSlider (indent + 14, y + labelofs, item->b.min, item->c.max, value.Float);
break;
case joy_slider:
if (item->e.joyslidernum == 0)
{
value.Float = SELECTED_JOYSTICK->GetAxisScale(item->a.joyselection);
}
else
{
assert(item->e.joyslidernum == 1);
value.Float = SELECTED_JOYSTICK->GetAxisDeadZone(item->a.joyselection);
}
M_DrawSlider (indent + 14, y + labelofs, item->b.min, item->c.max, fabs(value.Float));
break;
case joy_inverter:
assert(item->e.joyslidernum == 0);
value.Float = SELECTED_JOYSTICK->GetAxisScale(item->a.joyselection);
screen->DrawText(SmallFont, ValueColor, indent + 14, y,
(value.Float < 0) ? "Yes" : "No",
DTA_Clean, true, TAG_DONE);
break;
case slider: case slider:
value = item->a.cvar->GetGenericRep (CVAR_Float); value = item->a.cvar->GetGenericRep (CVAR_Float);
M_DrawSlider (indent + 14, y + labelofs, item->b.min, item->c.max, value.Float); M_DrawSlider (indent + 14, y + labelofs, item->b.min, item->c.max, value.Float);
@ -2356,6 +2338,47 @@ void M_OptResponder (event_t *ev)
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE); S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
break; break;
case joy_sens:
value.Float = SELECTED_JOYSTICK->GetSensitivity() - item->d.step;
if (value.Float < item->b.min)
value.Float = item->b.min;
SELECTED_JOYSTICK->SetSensitivity(value.Float);
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
break;
case joy_slider:
if (item->e.joyslidernum == 0)
{
value.Float = SELECTED_JOYSTICK->GetAxisScale(item->a.joyselection);
}
else
{
assert(item->e.joyslidernum == 1);
value.Float = SELECTED_JOYSTICK->GetAxisDeadZone(item->a.joyselection);
}
if (value.Float >= 0)
{
value.Float -= item->d.step;
if (value.Float < item->b.min)
value.Float = item->b.min;
}
else
{
value.Float += item->d.step;
if (value.Float < -item->c.max)
value.Float = -item->c.max;
}
if (item->e.joyslidernum == 0)
{
SELECTED_JOYSTICK->SetAxisScale(item->a.joyselection, value.Float);
}
else
{
SELECTED_JOYSTICK->SetAxisDeadZone(item->a.joyselection, value.Float);
}
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
break;
case palettegrid: case palettegrid:
SelColorIndex = (SelColorIndex - 1) & 15; SelColorIndex = (SelColorIndex - 1) & 15;
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", 1, ATTN_NONE); S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", 1, ATTN_NONE);
@ -2364,12 +2387,20 @@ void M_OptResponder (event_t *ev)
case discretes: case discretes:
case discrete: case discrete:
case cdiscrete: case cdiscrete:
case joy_map:
{ {
int cur; int cur;
int numvals; int numvals;
numvals = (int)item->b.min; numvals = (int)item->b.min;
value = item->a.cvar->GetGenericRep (CVAR_Float); if (item->type == joy_map)
{
value.Float = (float)SELECTED_JOYSTICK->GetAxisMap(item->a.joyselection);
}
else
{
value = item->a.cvar->GetGenericRep (CVAR_Float);
}
if (item->type != discretes) if (item->type != discretes)
{ {
cur = M_FindCurVal (value.Float, item->e.values, numvals); cur = M_FindCurVal (value.Float, item->e.values, numvals);
@ -2382,7 +2413,14 @@ void M_OptResponder (event_t *ev)
cur = numvals - 1; cur = numvals - 1;
value.Float = item->type != discretes ? item->e.values[cur].value : item->e.valuestrings[cur].value; value.Float = item->type != discretes ? item->e.values[cur].value : item->e.valuestrings[cur].value;
item->a.cvar->SetGenericRep (value, CVAR_Float); if (item->type == joy_map)
{
SELECTED_JOYSTICK->SetAxisMap(item->a.joyselection, (EJoyAxis)(int)value.Float);
}
else
{
item->a.cvar->SetGenericRep (value, CVAR_Float);
}
// Hack hack. Rebuild list of resolutions // Hack hack. Rebuild list of resolutions
if (item->e.values == Depths) if (item->e.values == Depths)
@ -2417,22 +2455,14 @@ void M_OptResponder (event_t *ev)
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE); S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
break; break;
#if 0 case discrete_joy:
case discrete_guid: if (--item->a.joyselection < 0)
{ {
int cur; item->a.joyselection = item->e.joyvalues->Size() - 1;
int numvals;
numvals = (int)item->b.numvalues;
cur = M_FindCurGUID (*(item->a.guidcvar), item->e.guidvalues, numvals);
if (--cur < 0)
cur = numvals - 1;
*(item->a.guidcvar) = item->e.guidvalues[cur].ID;
} }
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE); UpdateJoystickMenu();
S_Sound(CHAN_VOICE|CHAN_UI, "menu/change", 1, ATTN_NONE);
break; break;
#endif
case inverter: case inverter:
value = item->a.cvar->GetGenericRep (CVAR_Float); value = item->a.cvar->GetGenericRep (CVAR_Float);
@ -2441,6 +2471,13 @@ void M_OptResponder (event_t *ev)
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE); S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
break; break;
case joy_inverter:
assert(item->e.joyslidernum == 0);
value.Float = SELECTED_JOYSTICK->GetAxisScale(item->a.joyselection);
SELECTED_JOYSTICK->SetAxisScale(item->a.joyselection, -value.Float);
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
break;
case screenres: case screenres:
{ {
int col; int col;
@ -2507,6 +2544,47 @@ void M_OptResponder (event_t *ev)
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE); S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
break; break;
case joy_sens:
value.Float = SELECTED_JOYSTICK->GetSensitivity() + item->d.step;
if (value.Float > item->c.max)
value.Float = item->c.max;
SELECTED_JOYSTICK->SetSensitivity(value.Float);
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
break;
case joy_slider:
if (item->e.joyslidernum == 0)
{
value.Float = SELECTED_JOYSTICK->GetAxisScale(item->a.joyselection);
}
else
{
assert(item->e.joyslidernum == 1);
value.Float = SELECTED_JOYSTICK->GetAxisDeadZone(item->a.joyselection);
}
if (value.Float >= 0)
{
value.Float += item->d.step;
if (value.Float > item->c.max)
value.Float = item->c.max;
}
else
{
value.Float -= item->d.step;
if (value.Float > item->b.min)
value.Float = -item->b.min;
}
if (item->e.joyslidernum == 0)
{
SELECTED_JOYSTICK->SetAxisScale(item->a.joyselection, value.Float);
}
else
{
SELECTED_JOYSTICK->SetAxisDeadZone(item->a.joyselection, value.Float);
}
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
break;
case palettegrid: case palettegrid:
SelColorIndex = (SelColorIndex + 1) & 15; SelColorIndex = (SelColorIndex + 1) & 15;
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", 1, ATTN_NONE); S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", 1, ATTN_NONE);
@ -2515,12 +2593,20 @@ void M_OptResponder (event_t *ev)
case discretes: case discretes:
case discrete: case discrete:
case cdiscrete: case cdiscrete:
case joy_map:
{ {
int cur; int cur;
int numvals; int numvals;
numvals = (int)item->b.min; numvals = (int)item->b.min;
value = item->a.cvar->GetGenericRep (CVAR_Float); if (item->type == joy_map)
{
value.Float = (float)SELECTED_JOYSTICK->GetAxisMap(item->a.joyselection);
}
else
{
value = item->a.cvar->GetGenericRep (CVAR_Float);
}
if (item->type != discretes) if (item->type != discretes)
{ {
cur = M_FindCurVal (value.Float, item->e.values, numvals); cur = M_FindCurVal (value.Float, item->e.values, numvals);
@ -2533,7 +2619,14 @@ void M_OptResponder (event_t *ev)
cur = 0; cur = 0;
value.Float = item->type != discretes ? item->e.values[cur].value : item->e.valuestrings[cur].value; value.Float = item->type != discretes ? item->e.values[cur].value : item->e.valuestrings[cur].value;
item->a.cvar->SetGenericRep (value, CVAR_Float); if (item->type == joy_map)
{
SELECTED_JOYSTICK->SetAxisMap(item->a.joyselection, (EJoyAxis)(int)value.Float);
}
else
{
item->a.cvar->SetGenericRep (value, CVAR_Float);
}
// Hack hack. Rebuild list of resolutions // Hack hack. Rebuild list of resolutions
if (item->e.values == Depths) if (item->e.values == Depths)
@ -2568,22 +2661,14 @@ void M_OptResponder (event_t *ev)
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE); S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
break; break;
#if 0 case discrete_joy:
case discrete_guid: if ((unsigned)++item->a.joyselection >= item->e.joyvalues->Size())
{ {
int cur; item->a.joyselection = 0;
int numvals;
numvals = (int)item->b.numvalues;
cur = M_FindCurGUID (*(item->a.guidcvar), item->e.guidvalues, numvals);
if (++cur >= numvals)
cur = 0;
*(item->a.guidcvar) = item->e.guidvalues[cur].ID;
} }
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE); UpdateJoystickMenu();
S_Sound(CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
break; break;
#endif
case inverter: case inverter:
value = item->a.cvar->GetGenericRep (CVAR_Float); value = item->a.cvar->GetGenericRep (CVAR_Float);
@ -2592,6 +2677,13 @@ void M_OptResponder (event_t *ev)
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE); S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
break; break;
case joy_inverter:
assert(item->e.joyslidernum == 0);
value.Float = SELECTED_JOYSTICK->GetAxisScale(item->a.joyselection);
SELECTED_JOYSTICK->SetAxisScale(item->a.joyselection, -value.Float);
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
break;
case screenres: case screenres:
{ {
int col; int col;
@ -2743,6 +2835,13 @@ void M_OptResponder (event_t *ev)
item->a.cvar->SetGenericRep (value, CVAR_Float); item->a.cvar->SetGenericRep (value, CVAR_Float);
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE); S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
} }
else if (item->type == joy_inverter)
{
assert(item->e.joyslidernum == 0);
value.Float = SELECTED_JOYSTICK->GetAxisScale(item->a.joyselection);
SELECTED_JOYSTICK->SetAxisScale(item->a.joyselection, -value.Float);
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
}
else if (item->type == screenres) else if (item->type == screenres)
{ {
} }
@ -2995,34 +3094,96 @@ CCMD (menu_mouse)
void UpdateJoystickMenu () void UpdateJoystickMenu ()
{ {
#if 0 int i;
static FIntCVar * const cvars[8] = menuitem_t item = { whitetext };
{ int itemnum;
&joy_xaxis, &joy_yaxis, &joy_zaxis, IJoystickConfig *joy;
&joy_xrot, &joy_yrot, &joy_zrot,
&joy_slider, &joy_dial
};
static FFloatCVar * const cvars2[5] =
{
&joy_yawspeed, &joy_pitchspeed, &joy_forwardspeed,
&joy_sidespeed, &joy_upspeed
};
static FFloatCVar * const cvars3[8] =
{
&joy_xthreshold, &joy_ythreshold, &joy_zthreshold,
&joy_xrotthreshold, &joy_yrotthreshold, &joy_zrotthreshold,
&joy_sliderthreshold, &joy_dialthreshold
};
int i, line; if (JoystickItems.Size() > 1)
if (JoystickNames.Size() == 0)
{ {
JoystickItems[0].type = redtext; itemnum = JoystickItems[1].a.joyselection;
JoystickItems[0].label = "No joysticks connected";
line = 1;
} }
else else
{
itemnum = 0;
}
JoystickItems.Clear();
I_GetJoysticks(Joysticks);
if (Joysticks.Size() == 0)
{
item.type = redtext;
item.label = "No joysticks connected";
JoystickItems.Push(item);
}
else
{
item.type = discrete;
item.label = "Enable joystick";
item.a.cvar = &use_joystick;
item.b.numvalues = 2;
item.e.values = YesNo;
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 = whitetext;
item.label = "Axis Configuration";
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].type = discrete;
JoystickItems[0].label = "Enable joystick"; JoystickItems[0].label = "Enable joystick";
@ -3093,17 +3254,17 @@ void UpdateJoystickMenu ()
} }
} }
} }
#endif
JoystickMenu.numitems = line; JoystickMenu.items = &JoystickItems[0];
if (JoystickMenu.lastOn >= line) JoystickMenu.numitems = JoystickItems.Size();
if (JoystickMenu.lastOn >= JoystickMenu.numitems)
{ {
JoystickMenu.lastOn = line - 1; JoystickMenu.lastOn = JoystickMenu.numitems - 1;
} }
if (screen != NULL) if (screen != NULL)
{ {
CalcIndent (&JoystickMenu); CalcIndent(&JoystickMenu);
} }
#endif
} }
static void JoystickOptions () static void JoystickOptions ()

View file

@ -120,7 +120,7 @@ public:
// TYPES ------------------------------------------------------------------- // TYPES -------------------------------------------------------------------
class FDInputJoystick : public FInputDevice class FDInputJoystick : public FInputDevice, IJoystickConfig
{ {
public: public:
FDInputJoystick(const GUID *instance, FString &name); FDInputJoystick(const GUID *instance, FString &name);
@ -134,6 +134,21 @@ public:
FString GetIdentifier(); FString GetIdentifier();
void SetDefaultConfig(); void SetDefaultConfig();
// IJoystick interface
FString GetName();
float GetSensitivity();
virtual void SetSensitivity(float scale);
int GetNumAxes();
float GetAxisDeadZone(int axis);
EJoyAxis GetAxisMap(int axis);
const char *GetAxisName(int axis);
float GetAxisScale(int axis);
void SetAxisDeadZone(int axis, float deadzone);
void SetAxisMap(int axis, EJoyAxis gameaxis);
void SetAxisScale(int axis, float scale);
protected: protected:
struct AxisInfo struct AxisInfo
{ {
@ -188,6 +203,7 @@ public:
void ProcessInput(); void ProcessInput();
bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result); bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result);
void AddAxes(float axes[NUM_JOYAXIS]); void AddAxes(float axes[NUM_JOYAXIS]);
void GetDevices(TArray<IJoystickConfig *> &sticks);
protected: protected:
struct Enumerator struct Enumerator
@ -447,7 +463,7 @@ void FDInputJoystick::AddAxes(float axes[NUM_JOYAXIS])
axisval = (axisval - deadzone) / (1.0 - deadzone); axisval = (axisval - deadzone) / (1.0 - deadzone);
} }
// Add to the game axis. // Add to the game axis.
axes[Axes[i].GameAxis] += float(axisval * mul * Axes[i].Multiplier); axes[Axes[i].GameAxis] -= float(axisval * mul * Axes[i].Multiplier);
} }
} }
@ -803,23 +819,23 @@ void FDInputJoystick::SetDefaultConfig()
// Two axes? Horizontal is yaw and vertical is forward. // Two axes? Horizontal is yaw and vertical is forward.
if (Axes.Size() == 2) if (Axes.Size() == 2)
{ {
Axes[0].GameAxis = JOYAXIS_Yaw; Axes[0].Multiplier = -1; Axes[0].GameAxis = JOYAXIS_Yaw;
Axes[1].GameAxis = JOYAXIS_Forward; Axes[1].GameAxis = JOYAXIS_Forward;
} }
// Three axes? First two are movement, third is yaw. // Three axes? First two are movement, third is yaw.
else if (Axes.Size() >= 3) else if (Axes.Size() >= 3)
{ {
Axes[0].GameAxis = JOYAXIS_Side; Axes[0].GameAxis = JOYAXIS_Side;
Axes[1].GameAxis = JOYAXIS_Forward; Axes[1].Multiplier = -1; Axes[1].GameAxis = JOYAXIS_Forward;
Axes[2].GameAxis = JOYAXIS_Yaw; Axes[2].Multiplier = -1; Axes[2].GameAxis = JOYAXIS_Yaw;
// Four axes? First two are movement, last two are looking around. // Four axes? First two are movement, last two are looking around.
if (Axes.Size() >= 4) if (Axes.Size() >= 4)
{ {
Axes[3].GameAxis = JOYAXIS_Pitch; Axes[3].Multiplier = -0.75f; Axes[3].GameAxis = JOYAXIS_Pitch; Axes[3].Multiplier = 0.75f;
// Five axes? Use the fifth one for moving up and down. // Five axes? Use the fifth one for moving up and down.
if (Axes.Size() >= 5) if (Axes.Size() >= 5)
{ {
Axes[4].GameAxis = JOYAXIS_Up; Axes[4].Multiplier = -1; Axes[4].GameAxis = JOYAXIS_Up;
} }
} }
} }
@ -827,6 +843,152 @@ void FDInputJoystick::SetDefaultConfig()
// the user might want to use it. // the user might want to use it.
} }
//===========================================================================
//
// FDInputJoystick :: GetName
//
//===========================================================================
FString FDInputJoystick::GetName()
{
return Name;
}
//===========================================================================
//
// FDInputJoystick :: GetSensitivity
//
//===========================================================================
float FDInputJoystick::GetSensitivity()
{
return Multiplier;
}
//===========================================================================
//
// FDInputJoystick :: SetSensitivity
//
//===========================================================================
void FDInputJoystick::SetSensitivity(float scale)
{
Multiplier = scale;
}
//===========================================================================
//
// FDInputJoystick :: GetNumAxes
//
//===========================================================================
int FDInputJoystick::GetNumAxes()
{
return (int)Axes.Size();
}
//===========================================================================
//
// FDInputJoystick :: GetAxisDeadZone
//
//===========================================================================
float FDInputJoystick::GetAxisDeadZone(int axis)
{
if (unsigned(axis) >= Axes.Size())
{
return 0;
}
return Axes[axis].DeadZone;
}
//===========================================================================
//
// FDInputJoystick :: GetAxisMap
//
//===========================================================================
EJoyAxis FDInputJoystick::GetAxisMap(int axis)
{
if (unsigned(axis) >= Axes.Size())
{
return JOYAXIS_None;
}
return Axes[axis].GameAxis;
}
//===========================================================================
//
// FDInputJoystick :: GetAxisName
//
//===========================================================================
const char *FDInputJoystick::GetAxisName(int axis)
{
if (unsigned(axis) < Axes.Size())
{
return Axes[axis].Name;
}
return "Invalid";
}
//===========================================================================
//
// FDInputJoystick :: GetAxisScale
//
//===========================================================================
float FDInputJoystick::GetAxisScale(int axis)
{
if (unsigned(axis) >= Axes.Size())
{
return 0;
}
return Axes[axis].Multiplier;
}
//===========================================================================
//
// FDInputJoystick :: SetAxisDeadZone
//
//===========================================================================
void FDInputJoystick::SetAxisDeadZone(int axis, float deadzone)
{
if (unsigned(axis) < Axes.Size())
{
Axes[axis].DeadZone = clamp(deadzone, 0.f, 1.f);
}
}
//===========================================================================
//
// FDInputJoystick :: SetAxisMap
//
//===========================================================================
void FDInputJoystick::SetAxisMap(int axis, EJoyAxis gameaxis)
{
if (unsigned(axis) < Axes.Size())
{
Axes[axis].GameAxis = (unsigned(gameaxis) < NUM_JOYAXIS) ? gameaxis : JOYAXIS_None;
}
}
//===========================================================================
//
// FDInputJoystick :: SetAxisScale
//
//===========================================================================
void FDInputJoystick::SetAxisScale(int axis, float scale)
{
if (unsigned(axis) < Axes.Size())
{
Axes[axis].Multiplier = scale;
}
}
//=========================================================================== //===========================================================================
// //
// FDInputJoystickManager - Constructor // FDInputJoystickManager - Constructor
@ -902,6 +1064,23 @@ void FDInputJoystickManager :: AddAxes(float axes[NUM_JOYAXIS])
} }
} }
//===========================================================================
//
// FDInputJoystickManager :: GetJoysticks
//
// Adds the IJoystick interfaces for each device we created to the sticks
// array.
//
//===========================================================================
void FDInputJoystickManager::GetDevices(TArray<IJoystickConfig *> &sticks)
{
for (unsigned i = 0; i < Devices.Size(); ++i)
{
sticks.Push(Devices[i]);
}
}
//=========================================================================== //===========================================================================
// //
// FDInputJoystickManager :: WndProcHook // FDInputJoystickManager :: WndProcHook
@ -1161,7 +1340,7 @@ void FDInputJoystickManager::EnumDevices()
// Append numbers. // Append numbers.
for (k = i - 1; k < j; ++k) for (k = i - 1; k < j; ++k)
{ {
controllers[k].Name.AppendFormat(" %d", k - i - 2); controllers[k].Name.AppendFormat(" #%d", k - i + 2);
} }
} }
} }

View file

@ -744,6 +744,18 @@ void I_GetAxes(float axes[NUM_JOYAXIS])
} }
} }
void I_GetJoysticks(TArray<IJoystickConfig *> &sticks)
{
sticks.Clear();
for (int i = 0; i < NUM_JOYDEVICES; ++i)
{
if (JoyDevices[i] != NULL)
{
JoyDevices[i]->GetDevices(sticks);
}
}
}
void I_PutInClipboard (const char *str) void I_PutInClipboard (const char *str)
{ {
if (str == NULL || !OpenClipboard (Window)) if (str == NULL || !OpenClipboard (Window))

View file

@ -43,7 +43,25 @@ void I_PutInClipboard (const char *str);
FString I_GetFromClipboard (bool windows_has_no_selection_clipboard); FString I_GetFromClipboard (bool windows_has_no_selection_clipboard);
void I_GetEvent(); void I_GetEvent();
struct NOVTABLE IJoystickConfig
{
virtual FString GetName() = 0;
virtual float GetSensitivity() = 0;
virtual void SetSensitivity(float scale) = 0;
virtual int GetNumAxes() = 0;
virtual float GetAxisDeadZone(int axis) = 0;
virtual EJoyAxis GetAxisMap(int axis) = 0;
virtual const char *GetAxisName(int axis) = 0;
virtual float GetAxisScale(int axis) = 0;
virtual void SetAxisDeadZone(int axis, float zone) = 0;
virtual void SetAxisMap(int axis, EJoyAxis gameaxis) = 0;
virtual void SetAxisScale(int axis, float scale) = 0;
};
void I_GetAxes(float axes[NUM_JOYAXIS]); void I_GetAxes(float axes[NUM_JOYAXIS]);
void I_GetJoysticks(TArray<IJoystickConfig *> &sticks);
#ifdef USE_WINDOWS_DWORD #ifdef USE_WINDOWS_DWORD
// Don't make these definitions available to the main body of the source code. // Don't make these definitions available to the main body of the source code.
@ -109,10 +127,11 @@ protected:
void PostKeyEvent(int keynum, INTBOOL down, bool foreground); void PostKeyEvent(int keynum, INTBOOL down, bool foreground);
}; };
class FJoystickCollection : public FInputDevice class NOVTABLE FJoystickCollection : public FInputDevice
{ {
public: public:
virtual void AddAxes(float axes[NUM_JOYAXIS]) = 0; virtual void AddAxes(float axes[NUM_JOYAXIS]) = 0;
virtual void GetDevices(TArray<IJoystickConfig *> &sticks) = 0;
}; };
enum enum