mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
Merge branch 'joystick'
This give much better control over individual joystick axes. They now have per-axis pre and post amplification, the linear controller mappings are more intuitive, and axes can now bet setup as buttons using thresholds. Many thanks to Johnny on Flame for his work on the "user interface".
This commit is contained in:
commit
8314edce4d
7 changed files with 510 additions and 86 deletions
|
@ -146,4 +146,9 @@ int Menu_KeyEvent (knum_t key, short unicode, qboolean down);
|
|||
void Menu_Enter (void);
|
||||
void Menu_Leave (void);
|
||||
|
||||
void Menu_Enter_f (void);
|
||||
void Menu_Leave_f (void);
|
||||
void Menu_Prev_f (void);
|
||||
void Menu_Next_f (void);
|
||||
|
||||
#endif // __console_h
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#define __QF_joystick_h_
|
||||
|
||||
#include <QF/qtypes.h>
|
||||
#include "QF/quakeio.h"
|
||||
|
||||
#define JOY_MAX_AXES 8
|
||||
#define JOY_MAX_BUTTONS 18
|
||||
|
@ -36,17 +37,47 @@
|
|||
extern struct cvar_s *joy_device; // Joystick device name
|
||||
extern struct cvar_s *joy_enable; // Joystick enabling flag
|
||||
|
||||
extern qboolean joy_found; // Joystick present?
|
||||
extern qboolean joy_active; // Joystick in use?
|
||||
|
||||
struct joy_axis {
|
||||
struct cvar_s *axis;
|
||||
int current;
|
||||
struct joy_axis_button {
|
||||
float threshold;
|
||||
int key;
|
||||
int state;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
js_none, // ignore axis
|
||||
js_position, // linear delta
|
||||
js_angles, // linear delta
|
||||
js_button, // axis button
|
||||
} js_dest_t;
|
||||
|
||||
typedef enum {
|
||||
js_clear,
|
||||
js_amp,
|
||||
js_pre_amp,
|
||||
js_deadzone,
|
||||
js_offset,
|
||||
js_type,
|
||||
js_axis_button,
|
||||
} js_opt_t;
|
||||
|
||||
struct joy_axis {
|
||||
int current;
|
||||
float amp;
|
||||
float pre_amp;
|
||||
int deadzone;
|
||||
float offset;
|
||||
js_dest_t dest;
|
||||
int axis; // if linear delta
|
||||
int num_buttons; // if axis button
|
||||
struct joy_axis_button *axis_buttons; // if axis button
|
||||
};
|
||||
|
||||
extern qboolean joy_found; // Joystick present?
|
||||
extern qboolean joy_active; // Joystick in use?
|
||||
|
||||
struct joy_button {
|
||||
int old;
|
||||
int current;
|
||||
int old;
|
||||
int current;
|
||||
};
|
||||
|
||||
extern struct joy_axis joy_axes[JOY_MAX_AXES];
|
||||
|
@ -64,6 +95,7 @@ extern struct joy_button joy_buttons[JOY_MAX_BUTTONS];
|
|||
joy_enable->int_val are zero.
|
||||
*/
|
||||
void JOY_Command (void);
|
||||
void joy_clear_axis (int i);
|
||||
|
||||
/*
|
||||
JOY_Move (usercmd_t *) // FIXME: Not anymore!
|
||||
|
@ -111,4 +143,14 @@ void JOY_Close (void);
|
|||
*/
|
||||
void JOY_Read (void);
|
||||
|
||||
|
||||
const char *JOY_GetOption_c (int i);
|
||||
int JOY_GetOption_i (const char *c);
|
||||
|
||||
const char *JOY_GetDest_c (int i);
|
||||
int JOY_GetDest_i (const char *c);
|
||||
|
||||
|
||||
void Joy_WriteBindings (QFile *f);
|
||||
|
||||
#endif // __QF_joystick_h_
|
||||
|
|
|
@ -410,6 +410,42 @@ typedef enum {
|
|||
QFJ_BUTTON31,
|
||||
QFJ_BUTTON32,
|
||||
|
||||
//
|
||||
// joystick axes (for button emulation without consuming buttons)
|
||||
//
|
||||
QFJ_AXIS1,
|
||||
QFJ_AXIS2,
|
||||
QFJ_AXIS3,
|
||||
QFJ_AXIS4,
|
||||
QFJ_AXIS5,
|
||||
QFJ_AXIS6,
|
||||
QFJ_AXIS7,
|
||||
QFJ_AXIS8,
|
||||
QFJ_AXIS9,
|
||||
QFJ_AXIS10,
|
||||
QFJ_AXIS11,
|
||||
QFJ_AXIS12,
|
||||
QFJ_AXIS13,
|
||||
QFJ_AXIS14,
|
||||
QFJ_AXIS15,
|
||||
QFJ_AXIS16,
|
||||
QFJ_AXIS17,
|
||||
QFJ_AXIS18,
|
||||
QFJ_AXIS19,
|
||||
QFJ_AXIS20,
|
||||
QFJ_AXIS21,
|
||||
QFJ_AXIS22,
|
||||
QFJ_AXIS23,
|
||||
QFJ_AXIS24,
|
||||
QFJ_AXIS25,
|
||||
QFJ_AXIS26,
|
||||
QFJ_AXIS27,
|
||||
QFJ_AXIS28,
|
||||
QFJ_AXIS29,
|
||||
QFJ_AXIS30,
|
||||
QFJ_AXIS31,
|
||||
QFJ_AXIS32,
|
||||
|
||||
QFK_LAST
|
||||
} knum_t;
|
||||
|
||||
|
@ -473,6 +509,7 @@ void Key_KeydestCallback (keydest_callback_t *callback);
|
|||
|
||||
|
||||
const char *Key_KeynumToString (knum_t keynum);
|
||||
int Key_StringToKeynum (const char *str);
|
||||
struct progs_s;
|
||||
void Key_Progs_Init (struct progs_s *pr);
|
||||
#endif
|
||||
|
|
|
@ -452,6 +452,26 @@ bi_Menu_Enter (progs_t *pr)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Menu_Leave (progs_t *pr)
|
||||
{
|
||||
if (menu) {
|
||||
if (menu->leave_hook) {
|
||||
run_menu_pre ();
|
||||
PR_ExecuteProgram (&menu_pr_state, menu->leave_hook);
|
||||
run_menu_post ();
|
||||
}
|
||||
menu = menu->parent;
|
||||
if (!menu) {
|
||||
if (con_data.force_commandline) {
|
||||
Key_SetKeyDest (key_console);
|
||||
} else {
|
||||
Key_SetKeyDest (key_game);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
togglemenu_f (void)
|
||||
{
|
||||
|
@ -517,9 +537,38 @@ static builtin_t builtins[] = {
|
|||
{"Menu_Next", bi_Menu_Next, -1},
|
||||
{"Menu_Prev", bi_Menu_Prev, -1},
|
||||
{"Menu_Enter", bi_Menu_Enter, -1},
|
||||
{"Menu_Leave", bi_Menu_Leave, -1},
|
||||
{0},
|
||||
};
|
||||
|
||||
|
||||
|
||||
void
|
||||
Menu_Enter_f (void)
|
||||
{
|
||||
if (!Menu_KeyEvent(QFK_RETURN, '\0', true))
|
||||
Menu_KeyEvent('y', 'y', true);
|
||||
}
|
||||
|
||||
void
|
||||
Menu_Leave_f (void)
|
||||
{
|
||||
Menu_Leave ();
|
||||
}
|
||||
|
||||
void
|
||||
Menu_Prev_f (void)
|
||||
{
|
||||
Menu_KeyEvent (QFK_UP, '\0', true);
|
||||
}
|
||||
|
||||
void
|
||||
Menu_Next_f (void)
|
||||
{
|
||||
Menu_KeyEvent (QFK_DOWN, '\0', true);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Menu_Init (void)
|
||||
{
|
||||
|
@ -549,6 +598,10 @@ Menu_Init (void)
|
|||
"Toggle the display of the menu");
|
||||
Cmd_RemoveCommand ("quit");
|
||||
Cmd_AddCommand ("quit", quit_f, "Exit the program");
|
||||
Cmd_AddCommand ("Menu_Enter", Menu_Enter_f, "Do menu action/move up in the menu tree.");
|
||||
Cmd_AddCommand ("Menu_Leave", Menu_Leave_f, "Move down in the menu tree.");
|
||||
Cmd_AddCommand ("Menu_Prev", Menu_Prev_f, "Move cursor up.");
|
||||
Cmd_AddCommand ("Menu_Next", Menu_Next_f, "Move cursor up.");
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -37,8 +37,10 @@
|
|||
#include "QF/mathlib.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/va.h"
|
||||
#include "QF/cmd.h"
|
||||
|
||||
#include "compat.h"
|
||||
#include <string.h>
|
||||
|
||||
cvar_t *joy_device; // Joystick device name
|
||||
cvar_t *joy_enable; // Joystick enabling flag
|
||||
|
@ -48,25 +50,59 @@ cvar_t *joy_pre_amp; // Joystick pre-amplification
|
|||
qboolean joy_found = false;
|
||||
qboolean joy_active = false;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const char *string;
|
||||
} ocvar_t;
|
||||
|
||||
ocvar_t joy_axes_cvar_init[JOY_MAX_AXES] = {
|
||||
{"joyaxis1", "1"},
|
||||
{"joyaxis2", "2"},
|
||||
{"joyaxis3", "3"},
|
||||
{"joyaxis4", "0"},
|
||||
{"joyaxis5", "0"},
|
||||
{"joyaxis6", "0"},
|
||||
{"joyaxis7", "0"},
|
||||
{"joyaxis8", "0"}
|
||||
};
|
||||
|
||||
struct joy_axis joy_axes[JOY_MAX_AXES];
|
||||
struct joy_button joy_buttons[JOY_MAX_BUTTONS];
|
||||
|
||||
void
|
||||
joy_clear_axis (int i)
|
||||
{
|
||||
joy_axes[i].dest = js_none;
|
||||
joy_axes[i].amp = 1;
|
||||
joy_axes[i].pre_amp = 1;
|
||||
joy_axes[i].deadzone = 12500;
|
||||
|
||||
joy_axes[i].num_buttons = 0;
|
||||
if (joy_axes[i].axis_buttons) {
|
||||
free (joy_axes[i].axis_buttons);
|
||||
joy_axes[i].axis_buttons = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
joy_check_axis_buttons (struct joy_axis *ja, float value)
|
||||
{
|
||||
struct joy_axis_button *ab;
|
||||
int pressed = -1;
|
||||
int i;
|
||||
|
||||
// the axis button list is sorted in decending order of absolute threshold
|
||||
for (i = 0; i < ja->num_buttons; i++) {
|
||||
ab = &ja->axis_buttons[i];
|
||||
if ((value < 0) == (ab->threshold < 0)
|
||||
&& fabsf (value) >= fabsf (ab->threshold)) {
|
||||
pressed = i;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
// make sure any buttons that are no longer active are "released"
|
||||
for (i = 0; i < ja->num_buttons; i++) {
|
||||
if (i == pressed)
|
||||
continue;
|
||||
ab = &ja->axis_buttons[i];
|
||||
if (ab->state) {
|
||||
Key_Event (ab->key, 0, 0);
|
||||
ab->state = 0;
|
||||
}
|
||||
}
|
||||
// press the active button if there is one
|
||||
if (pressed >= 0) {
|
||||
// FIXME support repeat?
|
||||
if (!ab->state)
|
||||
Key_Event (ab->key, 0, 1);
|
||||
ab->state = 1;
|
||||
}
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
JOY_Command (void)
|
||||
|
@ -77,70 +113,36 @@ JOY_Command (void)
|
|||
VISIBLE void
|
||||
JOY_Move (void)
|
||||
{
|
||||
float mult_joy;
|
||||
struct joy_axis *ja;
|
||||
float value;
|
||||
float amp = joy_amp->value * in_amp->value;
|
||||
float pre = joy_pre_amp->value * in_pre_amp->value;
|
||||
int i;
|
||||
|
||||
if (!joy_active || !joy_enable->int_val)
|
||||
return;
|
||||
|
||||
mult_joy = (joy_amp->value * joy_pre_amp->value *
|
||||
in_amp->value * in_pre_amp->value) / 200.0;
|
||||
// Yes, mult_joy looks like a mess, but use of pre_amp values is useful in
|
||||
// scripts, and *_pre_amp will matter once joystick filtering/acceleration
|
||||
// is implemented
|
||||
|
||||
for (i = 0; i < JOY_MAX_AXES; i++) {
|
||||
switch (joy_axes[i].axis->int_val) {
|
||||
case 1:
|
||||
if (joy_axes[i].current)
|
||||
viewdelta.angles[YAW] -= joy_axes[i].current * mult_joy;
|
||||
ja = &joy_axes[i];
|
||||
value = ja->current * pre * ja->pre_amp;
|
||||
if (fabs (value) < ja->deadzone)
|
||||
value = -ja->offset;
|
||||
value += ja->offset;
|
||||
value *= amp * ja->amp / 100.0f;
|
||||
switch (ja->dest) {
|
||||
case js_none:
|
||||
// ignore axis
|
||||
break;
|
||||
case -1:
|
||||
if (joy_axes[i].current)
|
||||
viewdelta.angles[YAW] += joy_axes[i].current * mult_joy;
|
||||
case js_position:
|
||||
if (ja->current)
|
||||
viewdelta.position[(ja->axis) ? 2 : 0] += value;
|
||||
break;
|
||||
case 2:
|
||||
if (joy_axes[i].current)
|
||||
viewdelta.position[2] -= joy_axes[i].current * mult_joy;
|
||||
case js_angles:
|
||||
if (ja->current)
|
||||
viewdelta.angles[(ja->axis) ? 1 : 0] -= value;
|
||||
break;
|
||||
case -2:
|
||||
if (joy_axes[i].current)
|
||||
viewdelta.position[2] += joy_axes[i].current * mult_joy;
|
||||
break;
|
||||
case 3:
|
||||
if (joy_axes[i].current)
|
||||
viewdelta.position[0] += joy_axes[i].current * mult_joy;
|
||||
break;
|
||||
case -3:
|
||||
if (joy_axes[i].current)
|
||||
viewdelta.position[0] -= joy_axes[i].current * mult_joy;
|
||||
break;
|
||||
case 4:
|
||||
if (joy_axes[i].current)
|
||||
viewdelta.angles[PITCH] -= joy_axes[i].current * mult_joy;
|
||||
break;
|
||||
case -4:
|
||||
if (joy_axes[i].current)
|
||||
viewdelta.angles[PITCH] += joy_axes[i].current * mult_joy;
|
||||
break;
|
||||
case 5:
|
||||
if (joy_axes[i].current)
|
||||
viewdelta.position[1] -= joy_axes[i].current * mult_joy;
|
||||
break;
|
||||
case -5:
|
||||
if (joy_axes[i].current)
|
||||
viewdelta.position[1] += joy_axes[i].current * mult_joy;
|
||||
break;
|
||||
// Futureproofing
|
||||
case 6:
|
||||
if (joy_axes[i].current)
|
||||
viewdelta.angles[ROLL] += joy_axes[i].current * mult_joy;
|
||||
break;
|
||||
case -6:
|
||||
if (joy_axes[i].current)
|
||||
viewdelta.angles[ROLL] -= joy_axes[i].current * mult_joy;
|
||||
break;
|
||||
default:
|
||||
case js_button:
|
||||
joy_check_axis_buttons (ja, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -149,7 +151,7 @@ JOY_Move (void)
|
|||
VISIBLE void
|
||||
JOY_Init (void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if (JOY_Open () == -1) {
|
||||
Sys_MaskPrintf (SYS_VID, "JOY: Joystick not found.\n");
|
||||
|
@ -182,13 +184,235 @@ joyamp_f (cvar_t *var)
|
|||
Cvar_Set (var, va ("%g", max (0.0001, var->value)));
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
js_dest_t destnum;
|
||||
} js_dests_t;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
js_dest_t optnum;
|
||||
} js_opts_t;
|
||||
|
||||
js_dests_t js_dests[] = {
|
||||
{"none", js_none}, // ignore axis
|
||||
{"movement", js_position}, // linear delta
|
||||
{"aim", js_angles}, // linear delta
|
||||
{"button", js_button}, // axis button
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
|
||||
js_opts_t js_opts[] = {
|
||||
{"clear", js_clear},
|
||||
{"amp", js_amp},
|
||||
{"pre_amp", js_pre_amp},
|
||||
{"deadzone", js_deadzone},
|
||||
{"offset", js_offset},
|
||||
{"type", js_type},
|
||||
{"button", js_axis_button},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
const char *
|
||||
JOY_GetOption_c (int i)
|
||||
{
|
||||
js_opts_t *opt;
|
||||
|
||||
for (opt = &js_opts[0]; opt->name; opt++) {
|
||||
if ((int) opt->optnum == i)
|
||||
return opt->name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
JOY_GetOption_i (const char *c)
|
||||
{
|
||||
js_opts_t *opt;
|
||||
|
||||
for (opt = &js_opts[0]; opt->name; opt++) {
|
||||
if (!strcmp (opt->name, c))
|
||||
return opt->optnum;
|
||||
}
|
||||
|
||||
return -1; // Failure code;
|
||||
}
|
||||
|
||||
const char *
|
||||
JOY_GetDest_c (int i)
|
||||
{
|
||||
js_dests_t *dest;
|
||||
|
||||
for (dest = &js_dests[0]; dest->name; dest++) {
|
||||
if ((int) dest->destnum == i)
|
||||
return dest->name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
JOY_GetDest_i (const char *c)
|
||||
{
|
||||
js_dests_t *dest;
|
||||
|
||||
for (dest = &js_dests[0]; dest->name; dest++) {
|
||||
if (!strcmp (dest->name, c))
|
||||
return dest->destnum;
|
||||
}
|
||||
|
||||
return -1; // Failure code;
|
||||
}
|
||||
|
||||
static void
|
||||
in_joy_button_add_f (int ax, int index)
|
||||
{
|
||||
int n;
|
||||
size_t size;
|
||||
const char *key = Cmd_Argv (index);
|
||||
int keynum;
|
||||
const char *thrsh = Cmd_Argv (index + 1);
|
||||
float threshold;
|
||||
char *end = 0;
|
||||
|
||||
keynum = strtol (key, &end, 10) + QFJ_AXIS1;
|
||||
if (*end || keynum < QFJ_AXIS1 || keynum > QFJ_AXIS32) {
|
||||
// if the key is not valid, try a key name
|
||||
keynum = Key_StringToKeynum (key);
|
||||
}
|
||||
if (keynum == -1) {
|
||||
Sys_Printf ("\"%s\" isn't a valid key\n", key);
|
||||
}
|
||||
threshold = strtof (thrsh, &end);
|
||||
if (*end) {
|
||||
Sys_Printf ("invalid threshold: %s\n", thrsh);
|
||||
keynum = -1;
|
||||
}
|
||||
if (keynum == -1)
|
||||
return;
|
||||
|
||||
n = joy_axes[ax].num_buttons++;
|
||||
size = n * sizeof (joy_axes[ax].axis_buttons);
|
||||
joy_axes[ax].axis_buttons = realloc (joy_axes[ax].axis_buttons, size);
|
||||
joy_axes[ax].axis_buttons[n].key = keynum;
|
||||
joy_axes[ax].axis_buttons[n].threshold = threshold;
|
||||
}
|
||||
|
||||
static void
|
||||
in_joy_f (void)
|
||||
{
|
||||
const char *arg;
|
||||
int i, ax, c = Cmd_Argc ();
|
||||
|
||||
if (c == 2) {
|
||||
ax = JOY_GetOption_i (Cmd_Argv (1));
|
||||
switch (ax) {
|
||||
case js_clear:
|
||||
Sys_Printf ("Clearing all joystick settings...\n");
|
||||
for (i = 0; i < JOY_MAX_AXES; i++) {
|
||||
joy_clear_axis (i);
|
||||
}
|
||||
break;
|
||||
case js_amp:
|
||||
Sys_Printf ("[...]<amp> [<#amp>]: Axis sensitivity\n");
|
||||
break;
|
||||
case js_pre_amp:
|
||||
Sys_Printf ("[...]<pre_amp> [<#pre_amp>]: Axis sensitivity.\n");
|
||||
break;
|
||||
case js_deadzone:
|
||||
Sys_Printf ("[...]<deadzone> [<#dz>]: Axis deadzone.\n");
|
||||
break;
|
||||
case js_offset:
|
||||
Sys_Printf ("[...]<offset> [<#off>]: Axis initial position.\n");
|
||||
break;
|
||||
case js_type:
|
||||
Sys_Printf ("[...]<type> [<act> <#act>].\n");
|
||||
Sys_Printf ("Values for <act>:\n");
|
||||
Sys_Printf ("none: #0\n");
|
||||
Sys_Printf ("aim: #1..0\n");
|
||||
Sys_Printf ("movement: #1..0\n");
|
||||
|
||||
break;
|
||||
case js_axis_button:
|
||||
/* TODO */
|
||||
break;
|
||||
default:
|
||||
ax = strtol (Cmd_Argv (1), NULL, 0);
|
||||
|
||||
Sys_Printf ("<=====> AXIS %i <=====>\n", ax);
|
||||
Sys_Printf ("amp: %.9g\n", joy_axes[ax].amp);
|
||||
Sys_Printf ("pre_amp: %.9g\n", joy_axes[ax].pre_amp);
|
||||
Sys_Printf ("deadzone: %i\n", joy_axes[ax].deadzone);
|
||||
Sys_Printf ("offset: %.9g\n", joy_axes[ax].offset);
|
||||
Sys_Printf ("type: %s\n",
|
||||
JOY_GetDest_c (joy_axes[ax].dest));
|
||||
Sys_Printf ("<====================>\n");
|
||||
break;
|
||||
}
|
||||
return;
|
||||
} else if (c < 4) {
|
||||
if (JOY_GetOption_i (Cmd_Argv (2)) == js_clear) {
|
||||
ax = strtol (Cmd_Argv (1), NULL, 0);
|
||||
|
||||
joy_clear_axis (ax);
|
||||
return;
|
||||
} else {
|
||||
Sys_Printf ("in_joy <axis#> [<var> <value>]*\n"
|
||||
" Configures the joystick behaviour\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ax = strtol (Cmd_Argv (1), NULL, 0);
|
||||
|
||||
i = 2;
|
||||
while (i < c) {
|
||||
int var = JOY_GetOption_i (Cmd_Argv (i++));
|
||||
|
||||
switch (var) {
|
||||
case js_amp:
|
||||
joy_axes[ax].amp = strtof (Cmd_Argv (i++), NULL);
|
||||
break;
|
||||
case js_pre_amp:
|
||||
joy_axes[ax].pre_amp = strtof (Cmd_Argv (i++), NULL);
|
||||
break;
|
||||
case js_deadzone:
|
||||
joy_axes[ax].deadzone = strtol (Cmd_Argv (i++), NULL, 10);
|
||||
break;
|
||||
case js_offset:
|
||||
joy_axes[ax].offset = strtol (Cmd_Argv (i++), NULL, 10);
|
||||
break;
|
||||
case js_type:
|
||||
joy_axes[ax].dest = JOY_GetDest_i (Cmd_Argv (i++));
|
||||
joy_axes[ax].axis = strtol (Cmd_Argv (i++), NULL, 10);
|
||||
if (joy_axes[ax].axis > 1 || joy_axes[ax].axis < 0) {
|
||||
joy_axes[ax].axis = 0;
|
||||
Sys_Printf ("Invalid axis value.");
|
||||
}
|
||||
break;
|
||||
case js_axis_button:
|
||||
arg = Cmd_Argv (i++);
|
||||
if (!strcmp ("add", arg)) {
|
||||
in_joy_button_add_f (ax, i);
|
||||
i += 2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Sys_Printf ("Unknown option %s.\n", Cmd_Argv (i - 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
JOY_Init_Cvars (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
joy_device = Cvar_Get ("joy_device", "/dev/input/js0", CVAR_NONE | CVAR_ROM, 0,
|
||||
"Joystick device");
|
||||
joy_device = Cvar_Get ("joy_device", "/dev/input/js0",
|
||||
CVAR_NONE | CVAR_ROM, 0, "Joystick device");
|
||||
joy_enable = Cvar_Get ("joy_enable", "1", CVAR_NONE | CVAR_ARCHIVE, 0,
|
||||
"Joystick enable flag");
|
||||
joy_amp = Cvar_Get ("joy_amp", "1", CVAR_NONE | CVAR_ARCHIVE, joyamp_f,
|
||||
|
@ -196,10 +420,38 @@ JOY_Init_Cvars (void)
|
|||
joy_pre_amp = Cvar_Get ("joy_pre_amp", "1", CVAR_NONE | CVAR_ARCHIVE,
|
||||
joyamp_f, "Joystick pre-amplification");
|
||||
|
||||
Cmd_AddCommand ("in_joy", in_joy_f, "Configures the joystick behaviour");
|
||||
|
||||
for (i = 0; i < JOY_MAX_AXES; i++) {
|
||||
joy_axes[i].axis = Cvar_Get (joy_axes_cvar_init[i].name,
|
||||
joy_axes_cvar_init[i].string,
|
||||
CVAR_ARCHIVE, 0, "Set joystick axes");
|
||||
joy_axes[i].dest = js_none;
|
||||
joy_axes[i].amp = 1;
|
||||
joy_axes[i].pre_amp = 1;
|
||||
joy_axes[i].deadzone = 500;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Joy_WriteBindings (QFile * f)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < JOY_MAX_AXES; i++) {
|
||||
Qprintf (f, "in_joy %i amp %.9g pre_amp %.9g deadzone %i "
|
||||
"offset %.9g type %s %i\n",
|
||||
i, joy_axes[i].amp, joy_axes[i].pre_amp, joy_axes[i].deadzone,
|
||||
joy_axes[i].offset, JOY_GetDest_c (joy_axes[i].dest),
|
||||
joy_axes[i].axis);
|
||||
|
||||
if (joy_axes[i].num_buttons > 0) {
|
||||
int n;
|
||||
|
||||
for (n = 0; n < joy_axes[i].num_buttons; n++) {
|
||||
Qprintf (f, "in_joy %i button add %s %.9g\n", i,
|
||||
Key_KeynumToString (joy_axes[i].axis_buttons[n].key),
|
||||
joy_axes[i].axis_buttons[n].threshold);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -443,6 +443,39 @@ keyname_t keynames[] = {
|
|||
{ "J_BUTTON31", QFJ_BUTTON31 },
|
||||
{ "J_BUTTON32", QFJ_BUTTON32 },
|
||||
|
||||
{ "J_AXIS1", QFJ_AXIS1 },
|
||||
{ "J_AXIS2", QFJ_AXIS2 },
|
||||
{ "J_AXIS3", QFJ_AXIS3 },
|
||||
{ "J_AXIS4", QFJ_AXIS4 },
|
||||
{ "J_AXIS5", QFJ_AXIS5 },
|
||||
{ "J_AXIS6", QFJ_AXIS6 },
|
||||
{ "J_AXIS7", QFJ_AXIS7 },
|
||||
{ "J_AXIS8", QFJ_AXIS8 },
|
||||
{ "J_AXIS9", QFJ_AXIS9 },
|
||||
{ "J_AXIS10", QFJ_AXIS10 },
|
||||
{ "J_AXIS11", QFJ_AXIS11 },
|
||||
{ "J_AXIS12", QFJ_AXIS12 },
|
||||
{ "J_AXIS13", QFJ_AXIS13 },
|
||||
{ "J_AXIS14", QFJ_AXIS14 },
|
||||
{ "J_AXIS15", QFJ_AXIS15 },
|
||||
{ "J_AXIS16", QFJ_AXIS16 },
|
||||
{ "J_AXIS17", QFJ_AXIS17 },
|
||||
{ "J_AXIS18", QFJ_AXIS18 },
|
||||
{ "J_AXIS19", QFJ_AXIS19 },
|
||||
{ "J_AXIS20", QFJ_AXIS20 },
|
||||
{ "J_AXIS21", QFJ_AXIS21 },
|
||||
{ "J_AXIS22", QFJ_AXIS22 },
|
||||
{ "J_AXIS23", QFJ_AXIS23 },
|
||||
{ "J_AXIS24", QFJ_AXIS24 },
|
||||
{ "J_AXIS25", QFJ_AXIS25 },
|
||||
{ "J_AXIS26", QFJ_AXIS26 },
|
||||
{ "J_AXIS27", QFJ_AXIS27 },
|
||||
{ "J_AXIS28", QFJ_AXIS28 },
|
||||
{ "J_AXIS29", QFJ_AXIS29 },
|
||||
{ "J_AXIS30", QFJ_AXIS30 },
|
||||
{ "J_AXIS31", QFJ_AXIS31 },
|
||||
{ "J_AXIS32", QFJ_AXIS32 },
|
||||
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
|
@ -599,7 +632,7 @@ Key_Console (knum_t key, short unicode)
|
|||
the given string. Single ascii characters return themselves, while
|
||||
the QFK_* names are matched up.
|
||||
*/
|
||||
static int
|
||||
VISIBLE int
|
||||
Key_StringToKeynum (const char *str)
|
||||
{
|
||||
keyname_t *kn;
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "QF/cvar.h"
|
||||
#include "QF/draw.h"
|
||||
#include "QF/input.h"
|
||||
#include "QF/joystick.h"
|
||||
#include "QF/keys.h"
|
||||
#include "QF/msg.h"
|
||||
#include "QF/qfplist.h"
|
||||
|
@ -113,6 +114,7 @@ CL_WriteConfiguration (void)
|
|||
|
||||
Key_WriteBindings (f);
|
||||
Cvar_WriteVariables (f);
|
||||
Joy_WriteBindings (f);
|
||||
|
||||
Qclose (f);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue