[input] Add logical axes

Like logical buttons, logical axes are engine-defined destinations to
which input ("physical") axes can be bound.
This commit is contained in:
Bill Currie 2021-10-01 15:38:48 +09:00
parent a4f71cb4d5
commit 36f6dcc65e
3 changed files with 131 additions and 1 deletions

View file

@ -80,7 +80,41 @@ typedef struct in_device_s {
const char *id;
} in_device_t;
/*** Current state of the button.
/*** Recipe for converting an axis to a floating point value.
Recipes apply only to absolute axes.
\a deadzone applies only to balanced axes, thus it doubles as a flag
for balanced (>= 0) or unbalanced (< 0).
\a curve is applied after the input has been converted
*/
typedef struct in_recipe_s {
int minzone; ///< Size of deadzone near axis minimum
int maxzone; ///< Size of deadzone near axis maximum
int deadzone; ///< Size of deadzone near axis center (balanced)
float curve; ///< Power factor for absolute axes
} in_recipe_t;
typedef enum {
ina_set, ///< write the axis value to the destination
ina_accumulate, ///< add the axis value to the destination
} in_axis_mode;
/*** Logical axis.
Logical axes are the inputs defined by the game on which axis inputs
(usually "physical" axes) can act. Depending on the mode, the physical
axis value is either written as-is, or added to the existing value. It is
the responsibility of the code using the axis to clear the value for
accumulated inputs.
*/
typedef struct in_axis_s {
float value; ///< converted value of the axis
in_axis_mode mode; ///< method used for updating the destination
} in_axis_t;
/*** Current state of the logical 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
@ -94,6 +128,14 @@ typedef enum {
inb_edge_up = 1<<2, ///< button released this frame
} in_button_state;
/*** Logical button.
Logical buttons are the inputs defined by the game on which button inputs
(usually "physical" buttons) can act. Up to two button inputs can be
bound to a logical button. The logical button acts as an or gate where
either input will put the logical button in the pressed state, and both
inputs must be inactive for the logical button to be released.
*/
typedef struct in_button_s {
int down[2]; ///< button ids holding this button down
int state; ///< in_button_state
@ -222,6 +264,8 @@ void IN_ClearStates (void);
int IN_RegisterButton (in_button_t *button, const char *name,
const char *description);
int IN_RegisterAxis (in_axis_t *axis, const char *name,
const char *description);
void IN_Move (void); // FIXME: was cmduser_t?
// add additional movement on top of the keyboard move cmd

View file

@ -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_axis.c \
libs/input/in_button.c \
libs/input/in_common.c \
libs/input/in_event.c

85
libs/input/in_axis.c Normal file
View file

@ -0,0 +1,85 @@
/*
in_axis.c
Logical axis support
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2021/10/1
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 <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "QF/cmd.h"
#include "QF/hash.h"
#include "QF/input.h"
#include "QF/sys.h"
typedef struct regaxis_s {
const char *name;
const char *description;
in_axis_t *axis;
} regaxis_t;
static hashtab_t *axis_tab;
static const char *
axis_get_key (const void *b, void *data)
{
__auto_type regaxis = (const regaxis_t *) b;
return regaxis->name;
}
static void
axis_free (void *b, void *data)
{
free (b);
}
VISIBLE int
IN_RegisterAxis (in_axis_t *axis, const char *name, const char *description)
{
if (Hash_Find (axis_tab, name)) {
return 0;
}
regaxis_t *regaxis = malloc (sizeof (regaxis_t));
regaxis->name = name;
regaxis->description = description;
regaxis->axis = axis;
return 1;
}
static void __attribute__((constructor))
in_axis_init (void)
{
axis_tab = Hash_NewTable (127, axis_get_key, axis_free, 0, 0);
}