diff --git a/include/QF/in_event.h b/include/QF/in_event.h index 31ec88f46..1f960bda8 100644 --- a/include/QF/in_event.h +++ b/include/QF/in_event.h @@ -32,16 +32,15 @@ #define __QF_in_event_h #include "QF/qtypes.h" -#include "QF/joystick.h" // needed for JOY_MAX_AXES typedef struct { - int x, y; - unsigned int buttons; + int x, y; + unsigned buttons; } IE_mouse_event_t; typedef struct { - int key_code; - qboolean pressed; + int key_code; + qboolean pressed; } IE_key_event_t; typedef struct { diff --git a/include/QF/input.h b/include/QF/input.h index 5f3d3e424..c46819981 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -80,6 +80,120 @@ typedef struct in_device_s { const char *id; } in_device_t; +/*** Current state of the button. + + Captures the current state and any transitions during the last frame. + Not all combinations are valid (inb_edge_up|inb_down and inb_edge_down + (no inb_down) are not valid states), but inb_edge_up|inb_edge_down )with + or without inb_down) is valid as it represents a double transition during + the frame. +*/ +typedef enum { + inb_down = 1<<0, ///< button is held + inb_edge_down = 1<<1, ///< button pressed this frame + inb_edge_up = 1<<2, ///< button released this frame +} in_button_state; + +typedef struct in_button_s { + int down[2]; ///< button ids holding this button down + int state; ///< in_button_state +} in_button_t; + +/*** Represent the button's activity in the last frame as a float. + + The detected activity is: + steady off (up) + steady on (down) + off to on (up to down) transition + on to off )down to up) transition + pulse on (off-on-off or up-down-up) + pulse off (on-off-on or down-up-down) + Any additional transitions are treated as a pulse appropriate for the + final state of the button. + + \param button Pointer to the button being tested. + \return Float value between 0 (off/up) and 1 (on/down) + \note The edge transitions are cleared, so for each frame, this + is a one-shot function (ie, it is NOT idempotent). +*/ +GNU89INLINE inline float IN_ButtonState (in_button_t *button); + +/*** Test whether a button has been pressed in the last frame. + + Both steady-state on, and brief clicks are detected. + + \return True if the button is currently held or was pulsed on + in the last frame. + \note The edge transitions are cleared, so for each frame, this + is a one-shot function (ie, it is NOT idempotent). +*/ +GNU89INLINE inline int IN_ButtonPressed (in_button_t *button); + +/*** Test whether a button was released in the last frame. + + Valid only if the button is still released. A pulsed off does not + count as being released as the button is still held. + + \return True if the button is currently released and the release + was in the last frame. + \note The edge transitions are cleared, so for each frame, this + is a one-shot function (ie, it is NOT idempotent). +*/ +GNU89INLINE inline int IN_ButtonReleased (in_button_t *button); + +#ifndef IMPLEMENT_INPUT_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +float +IN_ButtonState (in_button_t *button) +{ + static const float state_values[8] = { + // held down for the entire frame + [inb_down] = 1, + // released this frame + [inb_edge_up] = 0, // instant falloff + // pressed this frame + [inb_edge_down|inb_down] = 0.5, + // pressed and released this frame + [inb_edge_down|inb_edge_up] = 0.25, + // released and pressed this frame + [inb_edge_down|inb_edge_up|inb_down] = 0.75, + }; + int state = button->state; + button->state &= inb_down; // clear edges, preserve pressed + return state_values[state & (inb_down|inb_edge_down|inb_edge_up)]; +} + +#ifndef IMPLEMENT_INPUT_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +IN_ButtonPressed (in_button_t *button) +{ + int state = button->state; + button->state &= inb_down; // clear edges, preserve pressed + // catch even press and release that occurs between frames + return (state & (inb_down | inb_edge_down)) != 0; +} + +#ifndef IMPLEMENT_INPUT_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +IN_ButtonReleased (in_button_t *button) +{ + int state = button->state; + button->state &= inb_down; // clear edges, preserve pressed + // catch only full release (a pulsed on does count as a release) + return (state & (inb_down | inb_edge_up)) == inb_edge_up; +} + extern viewdelta_t viewdelta; #define freelook (in_mlook.state & 1 || in_freelook->int_val) @@ -106,6 +220,9 @@ void IN_UpdateGrab (struct cvar_s *); void IN_ClearStates (void); +int IN_RegisterButton (in_button_t *button, const char *name, + const char *description); + void IN_Move (void); // FIXME: was cmduser_t? // add additional movement on top of the keyboard move cmd @@ -121,7 +238,7 @@ extern qboolean in_mouse_avail; extern float in_mouse_x, in_mouse_y; -extern kbutton_t in_strafe, in_klook, in_speed, in_mlook; +extern in_button_t in_strafe, in_klook, in_speed, in_mlook; #endif #endif//__QF_input_h diff --git a/include/QF/keys.h b/include/QF/keys.h index 0159d80bc..3919eebc3 100644 --- a/include/QF/keys.h +++ b/include/QF/keys.h @@ -532,11 +532,6 @@ typedef enum { } keydest_t; #ifndef __QFCC__ -typedef struct { - int down[2]; // key nums holding it down - int state; // low bit is down state -} kbutton_t; - extern knum_t key_toggleconsole; typedef struct keybind_s { diff --git a/libs/input/Makemodule.am b/libs/input/Makemodule.am index c74f6c998..e160f456f 100644 --- a/libs/input/Makemodule.am +++ b/libs/input/Makemodule.am @@ -20,6 +20,7 @@ libs_input_libQFinput_la_DEPENDENCIES= $(input_deps) libs_input_libQFinput_la_SOURCES= \ libs/input/keys.c \ libs/input/old_keys.c \ + libs/input/in_button.c \ libs/input/in_common.c \ libs/input/in_event.c diff --git a/libs/input/in_button.c b/libs/input/in_button.c new file mode 100644 index 000000000..027f868ba --- /dev/null +++ b/libs/input/in_button.c @@ -0,0 +1,185 @@ +/* + in_button.c + + Logical button support + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/09/29 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cmd.h" +#include "QF/hash.h" +#include "QF/input.h" +#include "QF/sys.h" + +typedef struct regbutton_s { + const char *name; + const char *description; + in_button_t *button; + char *press_cmd; + char *release_cmd; +} regbutton_t; + +static hashtab_t *button_tab; + +static const char * +button_get_key (const void *b, void *data) +{ + __auto_type regbutton = (const regbutton_t *) b; + return regbutton->name; +} + +static void +button_free (void *b, void *data) +{ + free (b); +} + +static void +button_press (in_button_t *button, int id) +{ + if (id == button->down[0] || id == button->down[1]) { + // repeating key + return; + } + + if (!button->down[0]) { + button->down[0] = id; + } else if (!button->down[1]) { + button->down[1] = id; + } else { + Sys_Printf ("Three keys down for a button!\n"); + return; + } + + if (button->state & inb_down) { + // still down + return; + } + button->state |= inb_down | inb_edge_down; +} + +static void +button_release (in_button_t *button, int id) +{ + if (id == -1) { + // typed manually at the console, assume for unsticking, so clear all + button->down[0] = button->down[1] = 0; + button->state = inb_edge_up; + return; + } + + if (button->down[0] == id) { + button->down[0] = 0; + } else if (button->down[1] == id) { + button->down[1] = 0; + } else { + // key up without coresponding down (menu pass through) + return; + } + if (button->down[0] || button->down[1]) { + // some other key is still holding it down + return; + } + + if (!(button->state & inb_down)) { + // still up (this should not happen) + return; + } + button->state &= ~inb_down; // now up + button->state |= inb_edge_up; +} + +static void +button_press_cmd (void *_b) +{ + in_button_t *button = _b; + const char *idstr = Cmd_Argv (1); + // assume typed manually at the console for continuous down + int id = -1; + + if (idstr[0]) { + id = atoi (idstr); + } + button_press (button, id); +} + +static void +button_release_cmd (void *_b) +{ + in_button_t *button = _b; + const char *idstr = Cmd_Argv (1); + // assume typed manually at the console, probably for unsticking + int id = -1; + + if (idstr[0]) { + id = atoi (idstr); + } + button_release (button, id); +} + +VISIBLE int +IN_RegisterButton (in_button_t *button, const char *name, + const char *description) +{ + if (Hash_Find (button_tab, name)) { + return 0; + } + size_t size = strlen (name) + 2; + regbutton_t *regbutton = malloc (sizeof (regbutton_t) + 2 * size); + regbutton->name = name; + regbutton->description = description; + regbutton->button = button; + + regbutton->press_cmd = (char *) (regbutton + 1); + regbutton->release_cmd = regbutton->press_cmd + size; + *regbutton->press_cmd = '+'; + *regbutton->release_cmd = '-'; + strcpy (regbutton->press_cmd + 1, name); + strcpy (regbutton->release_cmd + 1, name); + + Cmd_AddDataCommand (regbutton->press_cmd, button_press_cmd, button, + "Set the button's state to on/pressed."); + Cmd_AddDataCommand (regbutton->release_cmd, button_release_cmd, button, + "Set the button's state to on/pressed."); + + return 1; +} + +static void __attribute__((constructor)) +in_evdev_register_driver (void) +{ + button_tab = Hash_NewTable (127, button_get_key, button_free, 0, 0); +} diff --git a/libs/input/in_common.c b/libs/input/in_common.c index c31f117d0..07dcf2d66 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -51,6 +51,7 @@ #include "QF/cvar.h" #include "QF/darray.h" #include "QF/in_event.h" +#define IMPLEMENT_INPUT_Funcs #include "QF/input.h" #include "QF/joystick.h" #include "QF/keys.h" @@ -80,9 +81,6 @@ cvar_t *in_mouse_pre_amp; cvar_t *lookstrafe; int64_t in_timeout = 10000;//10ms default timeout -kbutton_t in_mlook, in_klook; -kbutton_t in_strafe; -kbutton_t in_speed; qboolean in_mouse_avail; float in_mouse_x, in_mouse_y; @@ -315,7 +313,7 @@ IN_Move (void) in_mouse_x *= in_mouse_amp->value * in_amp->value; in_mouse_y *= in_mouse_amp->value * in_amp->value; - +#if 0 if ((in_strafe.state & 1) || (lookstrafe->int_val && freelook)) viewdelta.position[0] += in_mouse_x; else @@ -326,6 +324,7 @@ IN_Move (void) } else { viewdelta.position[2] -= in_mouse_y; } +#endif in_mouse_x = in_mouse_y = 0.0; } diff --git a/nq/include/client.h b/nq/include/client.h index a00b94890..5f58349e3 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -307,8 +307,6 @@ int CL_ReadFromServer (void); void CL_WriteToServer (usercmd_t *cmd); void CL_BaseMove (usercmd_t *cmd); -float CL_KeyState (kbutton_t *key); - // cl_demo.c void CL_StopPlayback (void); void CL_StopRecording (void); @@ -341,10 +339,10 @@ void CL_SignonReply (void); void CL_RelinkEntities (void); void CL_ClearEnts (void); -extern kbutton_t in_left, in_right, in_forward, in_back; -extern kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright; -extern kbutton_t in_use, in_jump, in_attack; -extern kbutton_t in_up, in_down; +extern in_button_t in_left, in_right, in_forward, in_back; +extern in_button_t in_lookup, in_lookdown, in_moveleft, in_moveright; +extern in_button_t in_use, in_jump, in_attack; +extern in_button_t in_up, in_down; extern double realtime; diff --git a/nq/source/cl_chase.c b/nq/source/cl_chase.c index 6f0c430c6..151a1d739 100644 --- a/nq/source/cl_chase.c +++ b/nq/source/cl_chase.c @@ -192,16 +192,16 @@ Chase_Update (void) // VectorCopy (cl.viewstate.angles, cmd.angles); if (in_strafe.state & 1) { - cmd.sidemove += cl_sidespeed->value * CL_KeyState (&in_right); - cmd.sidemove -= cl_sidespeed->value * CL_KeyState (&in_left); + cmd.sidemove += cl_sidespeed->value * IN_ButtonState (&in_right); + cmd.sidemove -= cl_sidespeed->value * IN_ButtonState (&in_left); } - cmd.sidemove += cl_sidespeed->value * CL_KeyState (&in_moveright); - cmd.sidemove -= cl_sidespeed->value * CL_KeyState (&in_moveleft); + cmd.sidemove += cl_sidespeed->value * IN_ButtonState (&in_moveright); + cmd.sidemove -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); if (!(in_klook.state & 1)) { cmd.forwardmove += cl_forwardspeed->value - * CL_KeyState (&in_forward); - cmd.forwardmove -= cl_backspeed->value * CL_KeyState (&in_back); + * IN_ButtonState (&in_forward); + cmd.forwardmove -= cl_backspeed->value * IN_ButtonState (&in_back); } if (in_speed.state & 1) { cmd.forwardmove *= cl_movespeedkey->value; diff --git a/nq/source/cl_input.c b/nq/source/cl_input.c index 58787e7e7..c480700e1 100644 --- a/nq/source/cl_input.c +++ b/nq/source/cl_input.c @@ -67,144 +67,83 @@ state bit 2 is edge triggered on the down to up transition */ -kbutton_t in_left, in_right, in_forward, in_back; -kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright; -kbutton_t in_use, in_jump, in_attack; -kbutton_t in_up, in_down; +in_button_t in_left, in_right, in_forward, in_back; +in_button_t in_lookup, in_lookdown, in_moveleft, in_moveright; +in_button_t in_use, in_jump, in_attack; +in_button_t in_up, in_down; +in_button_t in_strafe, in_klook, in_speed, in_mlook; + +static struct { + const char *name; + in_button_t *button; + const char *description; +} cl_in_buttons[] = { + { "left", &in_left, + "When active the player is turning left" + }, + { "right", &in_right, + "When active the player is turning right" + }, + { "forward", &in_forward, + "When active the player is moving forward" + }, + { "back", &in_back, + "When active the player is moving backwards" + }, + { "lookup", &in_lookup, + "When active the player's view is looking up" + }, + { "lookdown", &in_lookdown, + "When active the player's view is looking down" + }, + { "moveleft", &in_moveleft, + "When active the player is strafing left" + }, + { "moveright", &in_moveright, + "When active the player is strafing right" + }, + { "use", &in_use, + "Left over command for opening doors and triggering switches" + }, + { "jump", &in_jump, + "When active the player is jumping" + }, + { "attack", &in_attack, + "When active player is firing/using current weapon" + }, + { "moveup", &in_up, + "When active the player is swimming up in a liquid" + }, + { "movedown", &in_down, + "When active the player is swimming down in a liquid" + }, + { "strafe", &in_strafe, + "When active, +left and +right function like +moveleft and +moveright" + }, + { "speed", &in_speed, + "When active the player is running" + }, + { "klook", &in_klook, + "When active, +forward and +back perform +lookup and +lookdown" + }, + { "mlook", &in_mlook, + "When active moving the mouse or joystick forwards " + "and backwards performs +lookup and " + "+lookdown" + }, + { } +}; int in_impulse; void (*write_angles) (sizebuf_t *sb, const vec3_t angles); -static void -KeyPress (void *_b) -{ - kbutton_t *b = _b; - const char *c; - int k; - - c = Cmd_Argv (1); - if (c[0]) - k = atoi (c); - else - k = -1; // typed manually at the console for - // continuous down - - if (k == b->down[0] || k == b->down[1]) - return; // repeating key - - if (!b->down[0]) - b->down[0] = k; - else if (!b->down[1]) - b->down[1] = k; - else { - Sys_Printf ("Three keys down for a button!\n"); - return; - } - - if (b->state & 1) - return; // still down - b->state |= 1 + 2; // down + impulse down -} - -static void -KeyRelease (void *_b) -{ - kbutton_t *b = _b; - const char *c; - int k; - - c = Cmd_Argv (1); - if (c[0]) - k = atoi (c); - else { // typed manually at the console, - // assume for unsticking, so clear - // all - b->down[0] = b->down[1] = 0; - b->state = 4; // impulse up - return; - } - - if (b->down[0] == k) - b->down[0] = 0; - else if (b->down[1] == k) - b->down[1] = 0; - else - return; // key up without coresponding down - // (menu pass through) - if (b->down[0] || b->down[1]) - return; // some other key is still holding it - // down - - if (!(b->state & 1)) - return; // still up (this should not happen) - b->state &= ~1; // now up - b->state |= 4; // impulse up -} - -static void -IN_MLookRelease (void *data) -{ - KeyRelease (&in_mlook); - if (!freelook && lookspring->int_val) - V_StartPitchDrift (); -} - static void IN_Impulse (void *data) { in_impulse = atoi (Cmd_Argv (1)); } -/* - CL_KeyState - - Returns 0.25 if a key was pressed and released during the frame, - 0.5 if it was pressed and held - 0 if held then released, and - 1.0 if held for the entire time -*/ -float -CL_KeyState (kbutton_t *key) -{ - float val; - qboolean impulsedown, impulseup, down; - - impulsedown = key->state & 2; - impulseup = key->state & 4; - down = key->state & 1; - val = 0; - - if (impulsedown && !impulseup) { - if (down) - val = 0.5; // pressed and held this frame - else - val = 0; // I_Error (); - } - if (impulseup && !impulsedown) { - if (down) - val = 0; // I_Error (); - else - val = 0; // released this frame - } - if (!impulsedown && !impulseup) { - if (down) - val = 1.0; // held the entire frame - else - val = 0; // up the entire frame - } - if (impulsedown && impulseup) { - if (down) - val = 0.75; // released and re-pressed this frame - else - val = 0.25; // pressed and released this frame - } - - key->state &= 1; // clear impulses - - return val; -} - cvar_t *cl_anglespeedkey; cvar_t *cl_backspeed; cvar_t *cl_forwardspeed; @@ -228,7 +167,7 @@ CL_AdjustAngles (void) pitchspeed = cl_pitchspeed->value; yawspeed = cl_yawspeed->value; - if (in_speed.state & 1) { + if (in_speed.state & inb_down) { pitchspeed *= cl_anglespeedkey->value; yawspeed *= cl_anglespeedkey->value; } @@ -241,19 +180,19 @@ CL_AdjustAngles (void) pitchspeed *= host_frametime; yawspeed *= host_frametime; - if (!(in_strafe.state & 1)) { - cl.viewstate.angles[YAW] -= yawspeed * CL_KeyState (&in_right); - cl.viewstate.angles[YAW] += yawspeed * CL_KeyState (&in_left); + if (!(in_strafe.state & inb_down)) { + cl.viewstate.angles[YAW] -= yawspeed * IN_ButtonState (&in_right); + cl.viewstate.angles[YAW] += yawspeed * IN_ButtonState (&in_left); cl.viewstate.angles[YAW] = anglemod (cl.viewstate.angles[YAW]); } - if (in_klook.state & 1) { + if (in_klook.state & inb_down) { V_StopPitchDrift (); - cl.viewstate.angles[PITCH] -= pitchspeed * CL_KeyState (&in_forward); - cl.viewstate.angles[PITCH] += pitchspeed * CL_KeyState (&in_back); + cl.viewstate.angles[PITCH] -= pitchspeed * IN_ButtonState (&in_forward); + cl.viewstate.angles[PITCH] += pitchspeed * IN_ButtonState (&in_back); } - up = CL_KeyState (&in_lookup); - down = CL_KeyState (&in_lookdown); + up = IN_ButtonState (&in_lookup); + down = IN_ButtonState (&in_lookdown); cl.viewstate.angles[PITCH] -= pitchspeed * up; cl.viewstate.angles[PITCH] += pitchspeed * down; @@ -281,6 +220,10 @@ CL_AdjustAngles (void) void CL_BaseMove (usercmd_t *cmd) { + if (IN_ButtonReleased (&in_mlook) && !freelook && lookspring->int_val) { + V_StartPitchDrift (); + } + if (cls.state != ca_active) { return; } @@ -289,24 +232,24 @@ CL_BaseMove (usercmd_t *cmd) memset (cmd, 0, sizeof (*cmd)); - if (in_strafe.state & 1) { - cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_right); - cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_left); + if (in_strafe.state & inb_down) { + cmd->sidemove += cl_sidespeed->value * IN_ButtonState (&in_right); + cmd->sidemove -= cl_sidespeed->value * IN_ButtonState (&in_left); } - cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_moveright); - cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_moveleft); + cmd->sidemove += cl_sidespeed->value * IN_ButtonState (&in_moveright); + cmd->sidemove -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); - cmd->upmove += cl_upspeed->value * CL_KeyState (&in_up); - cmd->upmove -= cl_upspeed->value * CL_KeyState (&in_down); + cmd->upmove += cl_upspeed->value * IN_ButtonState (&in_up); + cmd->upmove -= cl_upspeed->value * IN_ButtonState (&in_down); - if (!(in_klook.state & 1)) { - cmd->forwardmove += cl_forwardspeed->value * CL_KeyState (&in_forward); - cmd->forwardmove -= cl_backspeed->value * CL_KeyState (&in_back); + if (!(in_klook.state & inb_down)) { + cmd->forwardmove += cl_forwardspeed->value * IN_ButtonState (&in_forward); + cmd->forwardmove -= cl_backspeed->value * IN_ButtonState (&in_back); } // adjust for speed key - if (in_speed.state & 1) { + if (in_speed.state & inb_down) { cmd->forwardmove *= cl_movespeedkey->value; cmd->sidemove *= cl_movespeedkey->value; cmd->upmove *= cl_movespeedkey->value; @@ -347,7 +290,7 @@ CL_BaseMove (usercmd_t *cmd) cl.viewstate.angles[YAW] += viewdelta.angles[YAW] * m_yaw->value; cl.viewstate.angles[ROLL] += viewdelta.angles[ROLL]; - if (freelook && !(in_strafe.state & 1)) { + if (freelook && !(in_strafe.state & inb_down)) { cl.viewstate.angles[PITCH] = bound (-70, cl.viewstate.angles[PITCH], 80); } @@ -381,13 +324,9 @@ CL_SendMove (usercmd_t *cmd) // send button bits bits = 0; - if (in_attack.state & 3) - bits |= 1; - in_attack.state &= ~2; - - if (in_jump.state & 3) - bits |= 2; - in_jump.state &= ~2; + bits |= IN_ButtonPressed (&in_attack) << 0; + bits |= IN_ButtonPressed (&in_jump) << 1; + bits |= IN_ButtonPressed (&in_use) << 2; MSG_WriteByte (&buf, bits); @@ -412,86 +351,10 @@ CL_SendMove (usercmd_t *cmd) void CL_Input_Init (void) { - Cmd_AddDataCommand ("+moveup", KeyPress, &in_up, - "When active the player is swimming up in a liquid"); - Cmd_AddDataCommand ("-moveup", KeyRelease, &in_up, - "When active the player is not swimming up in a " - "liquid"); - Cmd_AddDataCommand ("+movedown", KeyPress, &in_down, - "When active the player is swimming down in a liquid"); - Cmd_AddDataCommand ("-movedown", KeyRelease, &in_down, - "When active the player is not swimming down in a " - "liquid"); - Cmd_AddDataCommand ("+left", KeyPress, &in_left, - "When active the player is turning left"); - Cmd_AddDataCommand ("-left", KeyRelease, &in_left, - "When active the player is not turning left"); - Cmd_AddDataCommand ("+right", KeyPress, &in_right, - "When active the player is turning right"); - Cmd_AddDataCommand ("-right", KeyRelease, &in_right, - "When active the player is not turning right"); - Cmd_AddDataCommand ("+forward", KeyPress, &in_forward, - "When active the player is moving forward"); - Cmd_AddDataCommand ("-forward", KeyRelease, &in_forward, - "When active the player is not moving forward"); - Cmd_AddDataCommand ("+back", KeyPress, &in_back, - "When active the player is moving backwards"); - Cmd_AddDataCommand ("-back", KeyRelease, &in_back, - "When active the player is not moving backwards"); - Cmd_AddDataCommand ("+lookup", KeyPress, &in_lookup, - "When active the player's view is looking up"); - Cmd_AddDataCommand ("-lookup", KeyRelease, &in_lookup, - "When active the player's view is not looking up"); - Cmd_AddDataCommand ("+lookdown", KeyPress, &in_lookdown, - "When active the player's view is looking down"); - Cmd_AddDataCommand ("-lookdown", KeyRelease, &in_lookdown, - "When active the player's view is not looking up"); - Cmd_AddDataCommand ("+strafe", KeyPress, &in_strafe, - "When active, +left and +right function like " - "+moveleft and +moveright"); - Cmd_AddDataCommand ("-strafe", KeyRelease, &in_strafe, - "When active, +left and +right stop functioning like " - "+moveleft and +moveright"); - Cmd_AddDataCommand ("+moveleft", KeyPress, &in_moveleft, - "When active the player is strafing left"); - Cmd_AddDataCommand ("-moveleft", KeyRelease, &in_moveleft, - "When active the player is not strafing left"); - Cmd_AddDataCommand ("+moveright", KeyPress, &in_moveright, - "When active the player is strafing right"); - Cmd_AddDataCommand ("-moveright", KeyRelease, &in_moveright, - "When active the player is not strafing right"); - Cmd_AddDataCommand ("+speed", KeyPress, &in_speed, - "When active the player is running"); - Cmd_AddDataCommand ("-speed", KeyRelease, &in_speed, - "When active the player is not running"); - Cmd_AddDataCommand ("+attack", KeyPress, &in_attack, - "When active player is firing/using current weapon"); - Cmd_AddDataCommand ("-attack", KeyRelease, &in_attack, - "When active player is not firing/using current " - "weapon"); - Cmd_AddDataCommand ("+use", KeyPress, &in_use, - "Non-functional. Left over command for opening doors " - "and triggering switches"); - Cmd_AddDataCommand ("-use", KeyRelease, &in_use, - "Non-functional. Left over command for opening doors " - "and triggering switches"); - Cmd_AddDataCommand ("+jump", KeyPress, &in_jump, - "When active the player is jumping"); - Cmd_AddDataCommand ("-jump", KeyRelease, &in_jump, - "When active the player is not jumping"); + for (int i = 0; cl_in_buttons[i].name; i++) { + IN_RegisterButton (cl_in_buttons[i].button, cl_in_buttons[i].name, + cl_in_buttons[i].description); + } Cmd_AddDataCommand ("impulse", IN_Impulse, 0, "Call a game function or QuakeC function."); - Cmd_AddDataCommand ("+klook", KeyPress, &in_klook, - "When active, +forward and +back perform +lookup and " - "+lookdown"); - Cmd_AddDataCommand ("-klook", KeyRelease, &in_klook, - "When active, +forward and +back don't perform " - "+lookup and +lookdown"); - Cmd_AddDataCommand ("+mlook", KeyPress, &in_mlook, - "When active moving the mouse or joystick forwards " - "and backwards performs +lookup and " - "+lookdown"); - Cmd_AddDataCommand ("-mlook", IN_MLookRelease, &in_mlook, - "When active moving the mouse or joystick forwards " - "and backwards doesn't perform +lookup and +lookdown"); } diff --git a/qw/include/cl_input.h b/qw/include/cl_input.h index a722967d6..0413e6ffa 100644 --- a/qw/include/cl_input.h +++ b/qw/include/cl_input.h @@ -46,12 +46,10 @@ int CL_ReadFromServer (void); void CL_WriteToServer (usercmd_t *cmd); void CL_BaseMove (usercmd_t *cmd); -float CL_KeyState (kbutton_t *key); - -extern kbutton_t in_left, in_right, in_forward, in_back; -extern kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright; -extern kbutton_t in_use, in_jump, in_attack; -extern kbutton_t in_up, in_down; +extern in_button_t in_left, in_right, in_forward, in_back; +extern in_button_t in_lookup, in_lookdown, in_moveleft, in_moveright; +extern in_button_t in_use, in_jump, in_attack; +extern in_button_t in_up, in_down; extern int in_impulse; #endif diff --git a/qw/source/cl_chase.c b/qw/source/cl_chase.c index 68c9e207a..481002354 100644 --- a/qw/source/cl_chase.c +++ b/qw/source/cl_chase.c @@ -192,16 +192,16 @@ Chase_Update (void) // VectorCopy (cl.viewstate.angles, cmd.angles); if (in_strafe.state & 1) { - cmd.sidemove += cl_sidespeed->value * CL_KeyState (&in_right); - cmd.sidemove -= cl_sidespeed->value * CL_KeyState (&in_left); + cmd.sidemove += cl_sidespeed->value * IN_ButtonState (&in_right); + cmd.sidemove -= cl_sidespeed->value * IN_ButtonState (&in_left); } - cmd.sidemove += cl_sidespeed->value * CL_KeyState (&in_moveright); - cmd.sidemove -= cl_sidespeed->value * CL_KeyState (&in_moveleft); + cmd.sidemove += cl_sidespeed->value * IN_ButtonState (&in_moveright); + cmd.sidemove -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); if (!(in_klook.state & 1)) { cmd.forwardmove += cl_forwardspeed->value - * CL_KeyState (&in_forward); - cmd.forwardmove -= cl_backspeed->value * CL_KeyState (&in_back); + * IN_ButtonState (&in_forward); + cmd.forwardmove -= cl_backspeed->value * IN_ButtonState (&in_back); } if (in_speed.state & 1) { cmd.forwardmove *= cl_movespeedkey->value; diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index 770e16358..9bbc86e6a 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -80,88 +80,75 @@ cvar_t *cl_spamimpulse; state bit 2 is edge triggered on the down to up transition */ -kbutton_t in_left, in_right, in_forward, in_back; -kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright; -kbutton_t in_use, in_jump, in_attack; -kbutton_t in_up, in_down; +in_button_t in_left, in_right, in_forward, in_back; +in_button_t in_lookup, in_lookdown, in_moveleft, in_moveright; +in_button_t in_use, in_jump, in_attack; +in_button_t in_up, in_down; +in_button_t in_strafe, in_klook, in_speed, in_mlook; + +static struct { + const char *name; + in_button_t *button; + const char *description; +} cl_in_buttons[] = { + { "left", &in_left, + "When active the player is turning left" + }, + { "right", &in_right, + "When active the player is turning right" + }, + { "forward", &in_forward, + "When active the player is moving forward" + }, + { "back", &in_back, + "When active the player is moving backwards" + }, + { "lookup", &in_lookup, + "When active the player's view is looking up" + }, + { "lookdown", &in_lookdown, + "When active the player's view is looking down" + }, + { "moveleft", &in_moveleft, + "When active the player is strafing left" + }, + { "moveright", &in_moveright, + "When active the player is strafing right" + }, + { "use", &in_use, + "Left over command for opening doors and triggering switches" + }, + { "jump", &in_jump, + "When active the player is jumping" + }, + { "attack", &in_attack, + "When active player is firing/using current weapon" + }, + { "moveup", &in_up, + "When active the player is swimming up in a liquid" + }, + { "movedown", &in_down, + "When active the player is swimming down in a liquid" + }, + { "strafe", &in_strafe, + "When active, +left and +right function like +moveleft and +moveright" + }, + { "speed", &in_speed, + "When active the player is running" + }, + { "klook", &in_klook, + "When active, +forward and +back perform +lookup and +lookdown" + }, + { "mlook", &in_mlook, + "When active moving the mouse or joystick forwards " + "and backwards performs +lookup and " + "+lookdown" + }, + { } +}; int in_impulse; - -static void -KeyPress (void *_b) -{ - kbutton_t *b = _b; - const char *c; - int k; - - c = Cmd_Argv (1); - if (c[0]) - k = atoi (c); - else - k = -1; // typed manually at the console for - // continuous down - - if (k == b->down[0] || k == b->down[1]) - return; // repeating key - - if (!b->down[0]) - b->down[0] = k; - else if (!b->down[1]) - b->down[1] = k; - else { - Sys_Printf ("Three keys down for a button!\n"); - return; - } - - if (b->state & 1) - return; // still down - b->state |= 1 + 2; // down + impulse down -} - -static void -KeyRelease (void *_b) -{ - kbutton_t *b = _b; - const char *c; - int k; - - c = Cmd_Argv (1); - if (c[0]) - k = atoi (c); - else { // typed manually at the console, - // assume for unsticking, so clear - // all - b->down[0] = b->down[1] = 0; - b->state = 4; // impulse up - return; - } - - if (b->down[0] == k) - b->down[0] = 0; - else if (b->down[1] == k) - b->down[1] = 0; - else - return; // key up without coresponding down - // (menu pass through) - if (b->down[0] || b->down[1]) - return; // some other key is still holding it - // down - - if (!(b->state & 1)) - return; // still up (this should not happen) - b->state &= ~1; // now up - b->state |= 4; // impulse up -} - -static void -IN_MLookRelease (void *data) -{ - KeyRelease (&in_mlook); - if (!freelook && lookspring->int_val) - V_StartPitchDrift (); -} - static void IN_Impulse (void *data) { @@ -172,55 +159,6 @@ IN_Impulse (void *data) Team_BestWeaponImpulse (); // HACK HACK HACK } -/* - CL_KeyState - - Returns 0.25 if a key was pressed and released during the frame, - 0.5 if it was pressed and held - 0 if held then released, and - 1.0 if held for the entire time -*/ -float -CL_KeyState (kbutton_t *key) -{ - float val; - qboolean impulsedown, impulseup, down; - - impulsedown = key->state & 2; - impulseup = key->state & 4; - down = key->state & 1; - val = 0; - - if (impulsedown && !impulseup) { - if (down) - val = 0.5; // pressed and held this frame - else - val = 0; // I_Error (); - } - if (impulseup && !impulsedown) { - if (down) - val = 0; // I_Error (); - else - val = 0; // released this frame - } - if (!impulsedown && !impulseup) { - if (down) - val = 1.0; // held the entire frame - else - val = 0; // up the entire frame - } - if (impulsedown && impulseup) { - if (down) - val = 0.75; // released and re-pressed this frame - else - val = 0.25; // pressed and released this frame - } - - key->state &= 1; // clear impulses - - return val; -} - cvar_t *cl_anglespeedkey; cvar_t *cl_backspeed; cvar_t *cl_forwardspeed; @@ -244,7 +182,7 @@ CL_AdjustAngles (void) pitchspeed = cl_pitchspeed->value; yawspeed = cl_yawspeed->value; - if (in_speed.state & 1) { + if (in_speed.state & inb_down) { pitchspeed *= cl_anglespeedkey->value; yawspeed *= cl_anglespeedkey->value; } @@ -257,19 +195,19 @@ CL_AdjustAngles (void) pitchspeed *= host_frametime; yawspeed *= host_frametime; - if (!(in_strafe.state & 1)) { - cl.viewstate.angles[YAW] -= yawspeed * CL_KeyState (&in_right); - cl.viewstate.angles[YAW] += yawspeed * CL_KeyState (&in_left); + if (!(in_strafe.state & inb_down)) { + cl.viewstate.angles[YAW] -= yawspeed * IN_ButtonState (&in_right); + cl.viewstate.angles[YAW] += yawspeed * IN_ButtonState (&in_left); cl.viewstate.angles[YAW] = anglemod (cl.viewstate.angles[YAW]); } - if (in_klook.state & 1) { + if (in_klook.state & inb_down) { V_StopPitchDrift (); - cl.viewstate.angles[PITCH] -= pitchspeed * CL_KeyState (&in_forward); - cl.viewstate.angles[PITCH] += pitchspeed * CL_KeyState (&in_back); + cl.viewstate.angles[PITCH] -= pitchspeed * IN_ButtonState (&in_forward); + cl.viewstate.angles[PITCH] += pitchspeed * IN_ButtonState (&in_back); } - up = CL_KeyState (&in_lookup); - down = CL_KeyState (&in_lookdown); + up = IN_ButtonState (&in_lookup); + down = IN_ButtonState (&in_lookdown); cl.viewstate.angles[PITCH] -= pitchspeed * up; cl.viewstate.angles[PITCH] += pitchspeed * down; @@ -297,6 +235,10 @@ CL_AdjustAngles (void) void CL_BaseMove (usercmd_t *cmd) { + if (IN_ButtonReleased (&in_mlook) && !freelook && lookspring->int_val) { + V_StartPitchDrift (); + } + if (cls.state != ca_active) { return; } @@ -306,24 +248,24 @@ CL_BaseMove (usercmd_t *cmd) memset (cmd, 0, sizeof (*cmd)); VectorCopy (cl.viewstate.angles, cmd->angles); - if (in_strafe.state & 1) { - cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_right); - cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_left); + if (in_strafe.state & inb_down) { + cmd->sidemove += cl_sidespeed->value * IN_ButtonState (&in_right); + cmd->sidemove -= cl_sidespeed->value * IN_ButtonState (&in_left); } - cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_moveright); - cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_moveleft); + cmd->sidemove += cl_sidespeed->value * IN_ButtonState (&in_moveright); + cmd->sidemove -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); - cmd->upmove += cl_upspeed->value * CL_KeyState (&in_up); - cmd->upmove -= cl_upspeed->value * CL_KeyState (&in_down); + cmd->upmove += cl_upspeed->value * IN_ButtonState (&in_up); + cmd->upmove -= cl_upspeed->value * IN_ButtonState (&in_down); - if (!(in_klook.state & 1)) { - cmd->forwardmove += cl_forwardspeed->value * CL_KeyState (&in_forward); - cmd->forwardmove -= cl_backspeed->value * CL_KeyState (&in_back); + if (!(in_klook.state & inb_down)) { + cmd->forwardmove += cl_forwardspeed->value * IN_ButtonState (&in_forward); + cmd->forwardmove -= cl_backspeed->value * IN_ButtonState (&in_back); } // adjust for speed key - if (in_speed.state & 1) { + if (in_speed.state & inb_down) { cmd->forwardmove *= cl_movespeedkey->value; cmd->sidemove *= cl_movespeedkey->value; cmd->upmove *= cl_movespeedkey->value; @@ -364,7 +306,7 @@ CL_BaseMove (usercmd_t *cmd) cl.viewstate.angles[YAW] += viewdelta.angles[YAW] * m_yaw->value; cl.viewstate.angles[ROLL] += viewdelta.angles[ROLL]; - if (freelook && !(in_strafe.state & 1)) { + if (freelook && !(in_strafe.state & inb_down)) { cl.viewstate.angles[PITCH] = bound (-70, cl.viewstate.angles[PITCH], 80); } @@ -393,19 +335,9 @@ CL_FinishMove (usercmd_t *cmd) return; // figure button bits - if (in_attack.state & 3) - cmd->buttons |= 1; - in_attack.state &= ~2; - - if (in_jump.state & 3) - cmd->buttons |= 2; - in_jump.state &= ~2; - -// 1999-10-29 +USE fix by Maddes start - if (in_use.state & 3) - cmd->buttons |= 4; - in_use.state &= ~2; -// 1999-10-29 +USE fix by Maddes end + cmd->buttons |= IN_ButtonPressed (&in_attack) << 0; + cmd->buttons |= IN_ButtonPressed (&in_jump) << 1; + cmd->buttons |= IN_ButtonPressed (&in_use) << 2; // send milliseconds of time to apply the move accum += (host_frametime * 1000.0); @@ -576,88 +508,12 @@ CL_SendCmd (void) void CL_Input_Init (void) { - Cmd_AddDataCommand ("+moveup", KeyPress, &in_up, - "When active the player is swimming up in a liquid"); - Cmd_AddDataCommand ("-moveup", KeyRelease, &in_up, - "When active the player is not swimming up in a " - "liquid"); - Cmd_AddDataCommand ("+movedown", KeyPress, &in_down, - "When active the player is swimming down in a liquid"); - Cmd_AddDataCommand ("-movedown", KeyRelease, &in_down, - "When active the player is not swimming down in a " - "liquid"); - Cmd_AddDataCommand ("+left", KeyPress, &in_left, - "When active the player is turning left"); - Cmd_AddDataCommand ("-left", KeyRelease, &in_left, - "When active the player is not turning left"); - Cmd_AddDataCommand ("+right", KeyPress, &in_right, - "When active the player is turning right"); - Cmd_AddDataCommand ("-right", KeyRelease, &in_right, - "When active the player is not turning right"); - Cmd_AddDataCommand ("+forward", KeyPress, &in_forward, - "When active the player is moving forward"); - Cmd_AddDataCommand ("-forward", KeyRelease, &in_forward, - "When active the player is not moving forward"); - Cmd_AddDataCommand ("+back", KeyPress, &in_back, - "When active the player is moving backwards"); - Cmd_AddDataCommand ("-back", KeyRelease, &in_back, - "When active the player is not moving backwards"); - Cmd_AddDataCommand ("+lookup", KeyPress, &in_lookup, - "When active the player's view is looking up"); - Cmd_AddDataCommand ("-lookup", KeyRelease, &in_lookup, - "When active the player's view is not looking up"); - Cmd_AddDataCommand ("+lookdown", KeyPress, &in_lookdown, - "When active the player's view is looking down"); - Cmd_AddDataCommand ("-lookdown", KeyRelease, &in_lookdown, - "When active the player's view is not looking up"); - Cmd_AddDataCommand ("+strafe", KeyPress, &in_strafe, - "When active, +left and +right function like " - "+moveleft and +moveright"); - Cmd_AddDataCommand ("-strafe", KeyRelease, &in_strafe, - "When active, +left and +right stop functioning like " - "+moveleft and +moveright"); - Cmd_AddDataCommand ("+moveleft", KeyPress, &in_moveleft, - "When active the player is strafing left"); - Cmd_AddDataCommand ("-moveleft", KeyRelease, &in_moveleft, - "When active the player is not strafing left"); - Cmd_AddDataCommand ("+moveright", KeyPress, &in_moveright, - "When active the player is strafing right"); - Cmd_AddDataCommand ("-moveright", KeyRelease, &in_moveright, - "When active the player is not strafing right"); - Cmd_AddDataCommand ("+speed", KeyPress, &in_speed, - "When active the player is running"); - Cmd_AddDataCommand ("-speed", KeyRelease, &in_speed, - "When active the player is not running"); - Cmd_AddDataCommand ("+attack", KeyPress, &in_attack, - "When active player is firing/using current weapon"); - Cmd_AddDataCommand ("-attack", KeyRelease, &in_attack, - "When active player is not firing/using current " - "weapon"); - Cmd_AddDataCommand ("+use", KeyPress, &in_use, - "Non-functional. Left over command for opening doors " - "and triggering switches"); - Cmd_AddDataCommand ("-use", KeyRelease, &in_use, - "Non-functional. Left over command for opening doors " - "and triggering switches"); - Cmd_AddDataCommand ("+jump", KeyPress, &in_jump, - "When active the player is jumping"); - Cmd_AddDataCommand ("-jump", KeyRelease, &in_jump, - "When active the player is not jumping"); + for (int i = 0; cl_in_buttons[i].name; i++) { + IN_RegisterButton (cl_in_buttons[i].button, cl_in_buttons[i].name, + cl_in_buttons[i].description); + } Cmd_AddDataCommand ("impulse", IN_Impulse, 0, "Call a game function or QuakeC function."); - Cmd_AddDataCommand ("+klook", KeyPress, &in_klook, - "When active, +forward and +back perform +lookup and " - "+lookdown"); - Cmd_AddDataCommand ("-klook", KeyRelease, &in_klook, - "When active, +forward and +back don't perform " - "+lookup and +lookdown"); - Cmd_AddDataCommand ("+mlook", KeyPress, &in_mlook, - "When active moving the mouse or joystick forwards " - "and backwards performs +lookup and " - "+lookdown"); - Cmd_AddDataCommand ("-mlook", IN_MLookRelease, &in_mlook, - "When active moving the mouse or joystick forwards " - "and backwards doesn't perform +lookup and +lookdown"); } void