mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 12:31:10 +00:00
[input] Make a start on the new binding system
Input Mapping Tables are still at the core as they are a good concept, however they include both axis and button mappings, and the size is not hard-coded, but dependent on the known devices. Not much actually works yet (nq segfaults when a key is pressed).
This commit is contained in:
parent
14a5ec7b41
commit
825d8b7a49
14 changed files with 629 additions and 81 deletions
|
@ -114,6 +114,8 @@ include_qf_glsl = \
|
|||
include_qf_input = \
|
||||
include/QF/binding.h \
|
||||
include/QF/event.h
|
||||
include/QF/imt.h
|
||||
|
||||
include_qf_math = \
|
||||
include/QF/math/dual.h \
|
||||
include/QF/math/half.h \
|
||||
|
|
|
@ -45,6 +45,7 @@ typedef struct in_buttoninfo_s {
|
|||
} in_buttoninfo_t;
|
||||
|
||||
#include "QF/input/binding.h"
|
||||
#include "QF/input/imt.h"
|
||||
|
||||
#ifndef __QFCC__
|
||||
|
||||
|
@ -104,15 +105,17 @@ typedef struct in_device_s {
|
|||
\a button_info holds the current raw state of the button
|
||||
|
||||
\a axis_imt_id is 0 if the device has no axis bindings, otherwise it is
|
||||
the based index into the imt array for the imt group.
|
||||
the index into the imt array for the imt group.
|
||||
|
||||
\a button_imt_i is 0 if the device has no button bindings, otherwise it
|
||||
\a button_imt_id is 0 if the device has no button bindings, otherwise it
|
||||
is the index into the imt array for the imt group.
|
||||
*/
|
||||
typedef struct in_devbindings_s {
|
||||
const char *name; ///< name used when binding inputs
|
||||
const char *id; ///< physical device name or id (preferred)
|
||||
in_device_t *device; ///< device associated with these bindings
|
||||
int devid; ///< id of device associated with these bindings
|
||||
int num_axes;
|
||||
int num_buttons;
|
||||
in_axisinfo_t *axis_info; ///< axis range info and raw state
|
||||
in_buttoninfo_t *button_info; ///< button raw state
|
||||
int axis_imt_id; ///< index into array of imt axis bindings
|
||||
|
|
|
@ -217,6 +217,8 @@ int IN_RegisterAxis (in_axis_t *axis, const char *name,
|
|||
const char *description);
|
||||
in_button_t *IN_FindButton (const char *name);
|
||||
|
||||
void IN_Binding_Init (void);
|
||||
|
||||
#endif
|
||||
|
||||
#endif//__QF_input_binding_h
|
||||
|
|
87
include/QF/input/imt.h
Normal file
87
include/QF/input/imt.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
imt.h
|
||||
|
||||
Input Mapping Table management
|
||||
|
||||
Copyright (C) 2001 Zephaniah E. Hull <warp@babylon.d2dc.net>
|
||||
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
|
||||
|
||||
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
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __QF_input_imt_h
|
||||
#define __QF_input_imt_h
|
||||
|
||||
#ifndef __QFCC__
|
||||
|
||||
#include "QF/darray.h"
|
||||
|
||||
#include "QF/input/binding.h"
|
||||
|
||||
typedef enum {
|
||||
imt_button,
|
||||
imt_axis,
|
||||
} imt_type;
|
||||
|
||||
/** Describe a region of imt bindings (axis or button)
|
||||
|
||||
Each device may have a block of axis bindings and a block of button
|
||||
bindings (some devices will have only the one block). The device name is
|
||||
used instead of a pointer to the device descriptor so configs can be
|
||||
preserved even if the device is not present.
|
||||
|
||||
Bindings are allocated to a device in contiguous blocks.
|
||||
*/
|
||||
typedef struct imt_block_s {
|
||||
const char *device; ///< name of the owning device
|
||||
int base; ///< index of first binding
|
||||
int count; ///< number of bindings
|
||||
} imt_block_t;
|
||||
|
||||
/** Input Mapping Table
|
||||
*/
|
||||
typedef struct imt_s {
|
||||
struct imt_s *next; ///< list of tables attached to key_dest
|
||||
struct imt_s *chain; ///< fallback table if input not bound
|
||||
const char *name; ///< for user interaction
|
||||
int written;
|
||||
struct DARRAY_TYPE (in_axisbinding_t *) axis_bindings;
|
||||
struct DARRAY_TYPE (in_buttonbinding_t *) button_bindings;
|
||||
} imt_t;
|
||||
|
||||
typedef struct in_context_s {
|
||||
imt_t *imts;
|
||||
imt_t **imt_tail;
|
||||
imt_t *active_imt;
|
||||
imt_t *default_imt;
|
||||
} in_context_t;
|
||||
|
||||
int IMT_GetAxisBlock (const char *device, int num_axes);
|
||||
int IMT_GetButtonBlock (const char *device, int num_buttons);
|
||||
int IMT_CreateContext (void);
|
||||
imt_t *IMT_FindIMT (const char *name);
|
||||
int IMT_CreateIMT (int context, const char *imt_name,
|
||||
const char *chain_imt_name);
|
||||
void IMT_ProcessAxis (int axis, int value);
|
||||
void IMT_ProcessButton (int button, int state);
|
||||
|
||||
#endif
|
||||
|
||||
#endif//__QF_input_imt_h
|
|
@ -534,26 +534,12 @@ typedef enum {
|
|||
#ifndef __QFCC__
|
||||
extern knum_t key_toggleconsole;
|
||||
|
||||
typedef struct keybind_s {
|
||||
char *str;
|
||||
} keybind_t;
|
||||
|
||||
/** Input Mapping Table
|
||||
*/
|
||||
typedef struct imt_s {
|
||||
struct imt_s *next; ///< list of tables attached to key_dest
|
||||
struct imt_s *chain; ///< fallback table if key not bound
|
||||
const char *name; ///< for user interaction
|
||||
keybind_t bindings[QFK_LAST];
|
||||
int written; ///< avoid duplicate config file writes
|
||||
} imt_t;
|
||||
|
||||
/** Chain of input mapping tables ascociated with a keydest sub-system (game,
|
||||
menu, etc).
|
||||
*/
|
||||
typedef struct keytarget_s {
|
||||
imt_t *imts; ///< list of tables attached to this target
|
||||
imt_t *active; ///< currently active table in this target
|
||||
struct imt_s *imts; ///< list of tables attached to this target
|
||||
struct imt_s *active; ///< currently active table in this target
|
||||
} keytarget_t;
|
||||
|
||||
extern int keydown[QFK_LAST];
|
||||
|
@ -612,7 +598,7 @@ void Key_Init_Cvars (void);
|
|||
\param imt_name The name of the imt to find. Case insensitive.
|
||||
\return The named imt, or null if not found.
|
||||
*/
|
||||
imt_t *Key_FindIMT (const char *imt_name) __attribute__((pure));
|
||||
struct imt_s *Key_FindIMT (const char *imt_name) __attribute__((pure));
|
||||
|
||||
/** Create a new imt and attach it to the specified keydest target.
|
||||
|
||||
|
@ -667,7 +653,7 @@ void Key_ClearStates (void);
|
|||
\param key The key for which to get the binding.
|
||||
\return The command string bound to the key, or null if unbound.
|
||||
*/
|
||||
const char *Key_GetBinding (imt_t *imt, knum_t key) __attribute__((pure));
|
||||
const char *Key_GetBinding (struct imt_s *imt, knum_t key) __attribute__((pure));
|
||||
|
||||
/** Bind a command string to a key in the specified input mapping table.
|
||||
|
||||
|
@ -678,7 +664,7 @@ const char *Key_GetBinding (imt_t *imt, knum_t key) __attribute__((pure));
|
|||
\param keynum The key to which the command string will be bound.
|
||||
\param binding The command string that will be bound.
|
||||
*/
|
||||
void Key_SetBinding (imt_t *imt, knum_t keynum, const char *binding);
|
||||
void Key_SetBinding (struct imt_s *imt, knum_t keynum, const char *binding);
|
||||
|
||||
/** Set the current keydest target.
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
#include "QF/cbuf.h"
|
||||
#include "QF/cmd.h"
|
||||
#include "QF/keys.h"
|
||||
#include "QF/input.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/gib.h"
|
||||
|
||||
|
|
|
@ -21,9 +21,11 @@ libs_input_libQFinput_la_SOURCES= \
|
|||
libs/input/keys.c \
|
||||
libs/input/old_keys.c \
|
||||
libs/input/in_axis.c \
|
||||
libs/input/in_binding.c \
|
||||
libs/input/in_button.c \
|
||||
libs/input/in_common.c \
|
||||
libs/input/in_event.c
|
||||
libs/input/in_event.c \
|
||||
libs/input/in_imt.c
|
||||
|
||||
EXTRA_LTLIBRARIES += \
|
||||
libs/input/libinput_evdev.la
|
||||
|
|
154
libs/input/in_binding.c
Normal file
154
libs/input/in_binding.c
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
in_binding.c
|
||||
|
||||
Input binding management
|
||||
|
||||
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2021/11/2
|
||||
|
||||
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"
|
||||
|
||||
#include "QF/input/imt.h"
|
||||
|
||||
#include "QF/input/binding.h"
|
||||
#include "QF/input/event.h"
|
||||
#include "QF/input/imt.h"
|
||||
|
||||
typedef struct DARRAY_TYPE (in_devbindings_t) in_devbindingset_t;
|
||||
|
||||
static in_devbindingset_t devbindings = DARRAY_STATIC_INIT (8);
|
||||
|
||||
static void
|
||||
in_binding_add_device (const IE_event_t *ie_event)
|
||||
{
|
||||
size_t devid = ie_event->device.devid;
|
||||
if (devid >= devbindings.size) {
|
||||
DARRAY_RESIZE (&devbindings, devid + 1);
|
||||
memset (&devbindings.a[devid], 0, sizeof (in_devbindings_t));
|
||||
}
|
||||
in_devbindings_t *db = &devbindings.a[devid];
|
||||
if (db->id) {
|
||||
if (db->id != IN_GetDeviceId (devid)) {
|
||||
Sys_Error ("in_binding_add_device: devid conflict: %zd", devid);
|
||||
}
|
||||
Sys_Printf ("in_binding_add_device: readd %s\n", db->id);
|
||||
return;
|
||||
}
|
||||
db->id = IN_GetDeviceId (devid);
|
||||
db->devid = devid;
|
||||
IN_AxisInfo (devid, 0, &db->num_axes);
|
||||
IN_ButtonInfo (devid, 0, &db->num_buttons);
|
||||
db->axis_info = malloc (db->num_axes * sizeof (in_axisinfo_t)
|
||||
+ db->num_buttons * sizeof (in_buttoninfo_t));
|
||||
db->button_info = (in_buttoninfo_t *) &db->axis_info[db->num_axes];
|
||||
IN_AxisInfo (devid, db->axis_info, &db->num_axes);
|
||||
IN_ButtonInfo (devid, db->button_info, &db->num_buttons);
|
||||
Sys_Printf ("in_binding_add_device: %s %d %d\n", db->id, db->num_axes,
|
||||
db->num_buttons);
|
||||
}
|
||||
|
||||
static void
|
||||
in_binding_remove_device (const IE_event_t *ie_event)
|
||||
{
|
||||
size_t devid = ie_event->device.devid;
|
||||
in_devbindings_t *db = &devbindings.a[devid];
|
||||
|
||||
if (devid >= devbindings.size) {
|
||||
Sys_Error ("in_binding_remove_device: invalid devid: %zd", devid);
|
||||
}
|
||||
if (!db->id) {
|
||||
return;
|
||||
}
|
||||
free (db->axis_info); // axis and button info in same block
|
||||
memset (db, 0, sizeof (*db));
|
||||
}
|
||||
|
||||
static void
|
||||
in_binding_axis (const IE_event_t *ie_event)
|
||||
{
|
||||
size_t devid = ie_event->axis.devid;
|
||||
int axis = ie_event->axis.axis;
|
||||
int value = ie_event->axis.value;
|
||||
in_devbindings_t *db = &devbindings.a[devid];
|
||||
|
||||
if (devid < devbindings.size && axis < db->num_axes) {
|
||||
db->axis_info[axis].value = value;
|
||||
if (db->axis_imt_id) {
|
||||
IMT_ProcessAxis (db->axis_imt_id + axis, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
in_binding_button (const IE_event_t *ie_event)
|
||||
{
|
||||
size_t devid = ie_event->button.devid;
|
||||
int button = ie_event->button.button;
|
||||
int state = ie_event->button.state;
|
||||
in_devbindings_t *db = &devbindings.a[devid];
|
||||
|
||||
if (devid < devbindings.size && button < db->num_buttons) {
|
||||
db->button_info[button].state = state;
|
||||
if (db->button_imt_id) {
|
||||
IMT_ProcessButton (db->button_imt_id + button, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
in_binding_event_handler (const IE_event_t *ie_event, void *unused)
|
||||
{
|
||||
static void (*handlers[]) (const IE_event_t *ie_event) = {
|
||||
[ie_add_device] = in_binding_add_device,
|
||||
[ie_remove_device] = in_binding_remove_device,
|
||||
[ie_axis] = in_binding_axis,
|
||||
[ie_button] = in_binding_button,
|
||||
};
|
||||
if (ie_event->type < 0 || ie_event->type > ie_button
|
||||
|| !handlers[ie_event->type]) {
|
||||
return 0;
|
||||
}
|
||||
handlers[ie_event->type] (ie_event);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
IN_Binding_Init (void)
|
||||
{
|
||||
IE_Add_Handler (in_binding_event_handler, 0);
|
||||
}
|
|
@ -102,7 +102,7 @@ IN_DriverData (int handle, void *data)
|
|||
}
|
||||
|
||||
static int
|
||||
in_add_device (int driver, in_device_t *device, const char *name,
|
||||
in_add_device (int driver, void *device, const char *name,
|
||||
const char *id)
|
||||
{
|
||||
size_t devid;
|
||||
|
@ -353,7 +353,8 @@ IN_Init (cbuf_t *cbuf)
|
|||
in_regdriver_t *rd = &in_drivers.a[i];
|
||||
rd->driver.init (rd->data);
|
||||
}
|
||||
Key_Init (cbuf);
|
||||
IN_Binding_Init ();
|
||||
//Key_Init (cbuf);
|
||||
//JOY_Init ();
|
||||
|
||||
in_mouse_x = in_mouse_y = 0.0;
|
||||
|
@ -362,7 +363,7 @@ IN_Init (cbuf_t *cbuf)
|
|||
void
|
||||
IN_Init_Cvars (void)
|
||||
{
|
||||
Key_Init_Cvars ();
|
||||
//Key_Init_Cvars ();
|
||||
//JOY_Init_Cvars ();
|
||||
in_grab = Cvar_Get ("in_grab", "0", CVAR_ARCHIVE, IN_UpdateGrab,
|
||||
"With this set to 1, quake will grab the mouse, "
|
||||
|
@ -392,7 +393,7 @@ IN_ClearStates (void)
|
|||
rd->driver.clear_states (rd->data);
|
||||
}
|
||||
}
|
||||
Key_ClearStates ();
|
||||
//Key_ClearStates ();
|
||||
}
|
||||
|
||||
#ifdef HAVE_EVDEV
|
||||
|
|
|
@ -58,11 +58,6 @@ static int evdev_driver_handle = -1;
|
|||
static PR_RESMAP (devmap_t) devmap;
|
||||
static devmap_t *devmap_list;
|
||||
|
||||
static void
|
||||
in_evdev_keydest_callback (keydest_t key_dest, void *data)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
in_evdev_add_select (qf_fd_set *fdset, int *maxfd, void *data)
|
||||
{
|
||||
|
@ -179,8 +174,6 @@ device_remove (device_t *dev)
|
|||
static void
|
||||
in_evdev_init (void *data)
|
||||
{
|
||||
Key_KeydestCallback (in_evdev_keydest_callback, 0);
|
||||
|
||||
inputlib_init (device_add, device_remove);
|
||||
}
|
||||
|
||||
|
|
238
libs/input/in_imt.c
Normal file
238
libs/input/in_imt.c
Normal file
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
in_imt.c
|
||||
|
||||
Input Mapping Table management
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2021/10/30
|
||||
|
||||
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/sys.h"
|
||||
|
||||
#include "QF/input/imt.h"
|
||||
|
||||
#include "QF/input/binding.h"
|
||||
#include "QF/input/imt.h"
|
||||
|
||||
typedef struct DARRAY_TYPE (in_context_t) in_contextset_t;
|
||||
typedef struct DARRAY_TYPE (imt_block_t) imt_blockset_t;
|
||||
/** Binding blocks are allocated across all imts
|
||||
*/
|
||||
static imt_blockset_t axis_blocks = DARRAY_STATIC_INIT (8);
|
||||
static imt_blockset_t button_blocks = DARRAY_STATIC_INIT (8);
|
||||
|
||||
static in_contextset_t in_contexts = DARRAY_STATIC_INIT (8);
|
||||
|
||||
static imt_block_t * __attribute__((pure))
|
||||
imt_find_block (imt_blockset_t *blockset, const char *device)
|
||||
{
|
||||
for (size_t i = 0; i < blockset->size; i++) {
|
||||
if (strcmp (blockset->a[i].device, device) == 0) {
|
||||
return &blockset->a[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static imt_block_t *
|
||||
imt_get_block (imt_blockset_t *blockset)
|
||||
{
|
||||
return DARRAY_OPEN_AT (blockset, blockset->size, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
imt_get_next_base (imt_blockset_t *blockset)
|
||||
{
|
||||
if (!blockset->size) {
|
||||
return 0;
|
||||
}
|
||||
imt_block_t *b = &blockset->a[blockset->size - 1];
|
||||
return b->base + b->count;
|
||||
}
|
||||
|
||||
static int
|
||||
imt_get_axis_block (int count)
|
||||
{
|
||||
int base = imt_get_next_base (&axis_blocks);
|
||||
|
||||
for (size_t i = 0; i < in_contexts.size; i++) {
|
||||
for (imt_t *imt = in_contexts.a[i].imts; imt; imt = imt->next) {
|
||||
in_axisbinding_t **binding;
|
||||
binding = DARRAY_OPEN_AT (&imt->axis_bindings, base, count);
|
||||
memset (binding, 0, count * sizeof (binding));
|
||||
}
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
static int
|
||||
imt_get_button_block (int count)
|
||||
{
|
||||
int base = imt_get_next_base (&button_blocks);
|
||||
|
||||
for (size_t i = 0; i < in_contexts.size; i++) {
|
||||
for (imt_t *imt = in_contexts.a[i].imts; imt; imt = imt->next) {
|
||||
in_buttonbinding_t **binding;
|
||||
binding = DARRAY_OPEN_AT (&imt->button_bindings, base, count);
|
||||
memset (binding, 0, count * sizeof (binding));
|
||||
}
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
int
|
||||
IMT_GetAxisBlock (const char *device, int num_axes)
|
||||
{
|
||||
imt_block_t *block;
|
||||
if (!(block = imt_find_block (&axis_blocks, device))) {
|
||||
block = imt_get_block (&axis_blocks);
|
||||
block->device = device;
|
||||
block->base = imt_get_axis_block (num_axes);
|
||||
block->count = num_axes;
|
||||
}
|
||||
return block - axis_blocks.a;
|
||||
}
|
||||
|
||||
int
|
||||
IMT_GetButtonBlock (const char *device, int num_buttons)
|
||||
{
|
||||
imt_block_t *block;
|
||||
if (!(block = imt_find_block (&button_blocks, device))) {
|
||||
block = imt_get_block (&button_blocks);
|
||||
block->device = device;
|
||||
block->base = imt_get_button_block (num_buttons);
|
||||
block->count = num_buttons;
|
||||
}
|
||||
return block - button_blocks.a;
|
||||
}
|
||||
|
||||
int
|
||||
IMT_CreateContext (void)
|
||||
{
|
||||
in_context_t *ctx = DARRAY_OPEN_AT (&in_contexts, in_contexts.size, 1);
|
||||
memset (ctx, 0, sizeof (*ctx));
|
||||
ctx->imt_tail = &ctx->imts;
|
||||
return ctx - in_contexts.a;
|
||||
}
|
||||
|
||||
static imt_t * __attribute__ ((pure))
|
||||
imt_find_imt (in_context_t *ctx, const char *name)
|
||||
{
|
||||
for (imt_t *imt = ctx->imts; imt; imt = imt->next) {
|
||||
if (strcasecmp (imt->name, name) == 0) {
|
||||
return imt;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
imt_t * __attribute__ ((pure))
|
||||
IMT_FindIMT (const char *name)
|
||||
{
|
||||
for (size_t i = 0; i < in_contexts.size; i++) {
|
||||
in_context_t *ctx = &in_contexts.a[i];
|
||||
imt_t *imt = imt_find_imt (ctx, name);
|
||||
if (imt) {
|
||||
return imt;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name)
|
||||
{
|
||||
in_context_t *ctx = &in_contexts.a[context];
|
||||
imt_t *imt;
|
||||
imt_t *chain_imt = 0;
|
||||
|
||||
if ((size_t) context >= in_contexts.size) {
|
||||
Sys_Printf ("invalid imt context %d\n", context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (IMT_FindIMT (imt_name)) {
|
||||
Sys_Printf ("imt %s already exists\n", imt_name);
|
||||
return 0;
|
||||
}
|
||||
if (chain_imt_name) {
|
||||
chain_imt = IMT_FindIMT (chain_imt_name);
|
||||
if (!chain_imt) {
|
||||
Sys_Printf ("chain imt %s does not exist\n", chain_imt_name);
|
||||
return 0;
|
||||
}
|
||||
chain_imt = imt_find_imt (ctx, chain_imt_name);
|
||||
if (!chain_imt) {
|
||||
Sys_Printf ("chain imt %s not in target context\n",
|
||||
chain_imt_name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
imt = malloc (sizeof (imt_t));
|
||||
*ctx->imt_tail = imt;
|
||||
ctx->imt_tail = &imt->next;
|
||||
|
||||
imt->next = 0;
|
||||
imt->chain = chain_imt;
|
||||
imt->name = strdup (imt_name);
|
||||
imt->written = 0;
|
||||
DARRAY_INIT (&imt->axis_bindings, 8);
|
||||
DARRAY_INIT (&imt->button_bindings, 8);
|
||||
int num_axes = imt_get_next_base (&axis_blocks);
|
||||
int num_buttons = imt_get_next_base (&button_blocks);
|
||||
DARRAY_RESIZE (&imt->axis_bindings, num_axes);
|
||||
DARRAY_RESIZE (&imt->button_bindings, num_buttons);
|
||||
if (num_axes) {
|
||||
memset (imt->axis_bindings.a, 0,
|
||||
num_axes * sizeof (in_axisbinding_t *));
|
||||
}
|
||||
if (num_buttons) {
|
||||
memset (imt->axis_bindings.a, 0,
|
||||
num_buttons * sizeof (in_buttonbinding_t *));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
IMT_ProcessAxis (int axis, int value)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
IMT_ProcessButton (int button, int state)
|
||||
{
|
||||
}
|
|
@ -41,15 +41,44 @@
|
|||
|
||||
#include "QF/cbuf.h"
|
||||
#include "QF/cmd.h"
|
||||
#include "QF/cmem.h"
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/darray.h"
|
||||
#include "QF/dstring.h"
|
||||
#include "QF/keys.h"
|
||||
#include "QF/input.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
#include "compat.h"
|
||||
#include "old_keys.h"
|
||||
|
||||
static memsuper_t *binding_mem;
|
||||
/*
|
||||
static in_axisbinding_t *
|
||||
alloc_axis_binding (void)
|
||||
{
|
||||
return cmemalloc (binding_mem, sizeof (in_axisbinding_t));
|
||||
}
|
||||
*/
|
||||
static void
|
||||
free_axis_binding (in_axisbinding_t *binding)
|
||||
{
|
||||
cmemfree (binding_mem, binding);
|
||||
}
|
||||
|
||||
static in_buttonbinding_t *
|
||||
alloc_button_binding (void)
|
||||
{
|
||||
return cmemalloc (binding_mem, sizeof (in_buttonbinding_t));
|
||||
}
|
||||
|
||||
static void
|
||||
free_button_binding (in_buttonbinding_t *binding)
|
||||
{
|
||||
cmemfree (binding_mem, binding);
|
||||
}
|
||||
|
||||
/* key up events are sent even if in console mode */
|
||||
|
||||
static keydest_t key_dest = key_console;
|
||||
|
@ -90,12 +119,6 @@ static const char *keydest_names[] = {
|
|||
"key_last"
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
imt_t imtnum;
|
||||
} imtname_t;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
knum_t keynum;
|
||||
|
@ -615,12 +638,25 @@ Key_SetBinding (imt_t *imt, knum_t keynum, const char *binding)
|
|||
if (keynum == (knum_t) -1)
|
||||
return;
|
||||
|
||||
if (imt->bindings[keynum].str) {
|
||||
free (imt->bindings[keynum].str);
|
||||
imt->bindings[keynum].str = NULL;
|
||||
if (imt->button_bindings.a[keynum]) {
|
||||
if (imt->button_bindings.a[keynum]->type == inb_command) {
|
||||
free (imt->button_bindings.a[keynum]->command);
|
||||
}
|
||||
free_button_binding (imt->button_bindings.a[keynum]);
|
||||
imt->button_bindings.a[keynum] = 0;
|
||||
}
|
||||
if (binding) {
|
||||
imt->bindings[keynum].str = strdup(binding);
|
||||
in_buttonbinding_t *b = alloc_button_binding ();
|
||||
imt->button_bindings.a[keynum] = b;
|
||||
in_button_t *button;
|
||||
if (binding[0] == '+' && (button = IN_FindButton (binding + 1))) {
|
||||
b->type = inb_button;
|
||||
b->bind_id = keynum; //FIXME alloc?
|
||||
b->button = button;
|
||||
} else {
|
||||
b->type = inb_command;
|
||||
b->command = strdup(binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -659,14 +695,23 @@ process_binding (knum_t key, const char *kb)
|
|||
static qboolean
|
||||
Key_Game (knum_t key, short unicode)
|
||||
{
|
||||
const char *kb;
|
||||
imt_t *imt = key_targets[key_dest].active;
|
||||
|
||||
while (imt) {
|
||||
kb = imt->bindings[key].str;
|
||||
if (kb) {
|
||||
if (keydown[key] <= 1)
|
||||
process_binding (key, kb);
|
||||
in_buttonbinding_t *b = imt->button_bindings.a[key];
|
||||
if (b) {
|
||||
switch (b->type) {
|
||||
case inb_button:
|
||||
if (keydown[key] <= 1) {
|
||||
IN_ButtonAction (b->button, key, keydown[key]);
|
||||
}
|
||||
break;
|
||||
case inb_command:
|
||||
if (keydown[key] <= 1) {
|
||||
process_binding (key, b->command);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
imt = imt->chain;
|
||||
|
@ -830,9 +875,20 @@ Key_IMT_Drop_All_f (void)
|
|||
while (key_targets[kd].imts) {
|
||||
imt = key_targets[kd].imts;
|
||||
key_targets[kd].imts = imt->next;
|
||||
for (int i = 0; i < QFK_LAST; i++) {
|
||||
if (imt->bindings[i].str) {
|
||||
free (imt->bindings[i].str);
|
||||
for (size_t i = 0; i < imt->axis_bindings.size; i++) {
|
||||
free_axis_binding (imt->axis_bindings.a[i]);
|
||||
}
|
||||
for (size_t i = 0; i < imt->button_bindings.size; i++) {
|
||||
in_buttonbinding_t *b = imt->button_bindings.a[i];
|
||||
if (b) {
|
||||
switch (b->type) {
|
||||
case inb_button:
|
||||
break;
|
||||
case inb_command:
|
||||
free (b->command);
|
||||
break;
|
||||
}
|
||||
free_button_binding (b);
|
||||
}
|
||||
}
|
||||
free ((char *) imt->name);
|
||||
|
@ -843,7 +899,7 @@ Key_IMT_Drop_All_f (void)
|
|||
}
|
||||
|
||||
static void
|
||||
Key_In_Bind (const char *imt_name, const char *key_name, const char *cmd)
|
||||
Key_In_BindButton (const char *imt_name, const char *key_name, const char *cmd)
|
||||
{
|
||||
imt_t *imt;
|
||||
int key;
|
||||
|
@ -861,11 +917,21 @@ Key_In_Bind (const char *imt_name, const char *key_name, const char *cmd)
|
|||
}
|
||||
|
||||
if (!cmd) {
|
||||
if (imt->bindings[key].str)
|
||||
Sys_Printf ("%s %s \"%s\"\n", imt_name, key_name,
|
||||
imt->bindings[key].str);
|
||||
else
|
||||
in_buttonbinding_t *b = imt->button_bindings.a[key];
|
||||
if (b) {
|
||||
switch (b->type) {
|
||||
case inb_button:
|
||||
Sys_Printf ("%s %s \"+%s\"\n", imt_name, key_name,
|
||||
b->button->name);
|
||||
break;
|
||||
case inb_command:
|
||||
Sys_Printf ("%s %s \"%s\"\n", imt_name, key_name,
|
||||
b->command);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
Sys_Printf ("%s %s is not bound\n", imt_name, key_name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Key_SetBinding (imt, key, cmd);
|
||||
|
@ -880,25 +946,25 @@ Key_In_Bind_f (void)
|
|||
|
||||
c = Cmd_Argc ();
|
||||
|
||||
if (c < 3) {
|
||||
Sys_Printf ("in_bind <imt> <key> [command] : attach a command to a "
|
||||
"key\n");
|
||||
if (c < 4 || strcmp (Cmd_Argv (2), "button") != 0) {
|
||||
Sys_Printf ("in_bind <imt> button <key> [command]\n"
|
||||
" attach a command to a key\n");
|
||||
return;
|
||||
}
|
||||
|
||||
imt = Cmd_Argv (1);
|
||||
|
||||
key = Cmd_Argv (2);
|
||||
key = Cmd_Argv (3);
|
||||
|
||||
if (c >= 4) {
|
||||
if (c >= 5) {
|
||||
cmd_buf = dstring_newstr ();
|
||||
for (i = 3; i < c; i++) {
|
||||
for (i = 4; i < c; i++) {
|
||||
dasprintf (cmd_buf, "%s%s", i > 3 ? " " : "", Cmd_Argv (i));
|
||||
}
|
||||
cmd = cmd_buf->str;
|
||||
}
|
||||
|
||||
Key_In_Bind (imt, key, cmd);
|
||||
Key_In_BindButton (imt, key, cmd);
|
||||
if (cmd_buf) {
|
||||
dstring_delete (cmd_buf);
|
||||
}
|
||||
|
@ -941,7 +1007,7 @@ Key_Bind_f (void)
|
|||
cmd = cmd_buf->str;
|
||||
}
|
||||
|
||||
Key_In_Bind ("imt_mod", key, cmd);
|
||||
Key_In_BindButton ("imt_mod", key, cmd);
|
||||
if (cmd_buf) {
|
||||
dstring_delete (cmd_buf);
|
||||
}
|
||||
|
@ -1054,9 +1120,6 @@ key_printf (QFile *f, const char *fmt, ...)
|
|||
static void
|
||||
key_write_imt (QFile *f, keydest_t kd, imt_t *imt)
|
||||
{
|
||||
int i;
|
||||
const char *bind;
|
||||
|
||||
if (!imt || imt->written) {
|
||||
return;
|
||||
}
|
||||
|
@ -1068,11 +1131,19 @@ key_write_imt (QFile *f, keydest_t kd, imt_t *imt)
|
|||
} else {
|
||||
key_printf (f, "imt_create %s %s\n", keydest_names[kd], imt->name);
|
||||
}
|
||||
for (i = 0; i < QFK_LAST; i++) {
|
||||
bind = imt->bindings[i].str;
|
||||
if (bind) {
|
||||
key_printf (f, "in_bind %s %s \"%s\"\n", imt->name,
|
||||
Key_KeynumToString (i), bind);
|
||||
for (size_t i = 0; i < imt->button_bindings.size; i++) {
|
||||
in_buttonbinding_t *b = imt->button_bindings.a[i];
|
||||
if (b) {
|
||||
switch (b->type) {
|
||||
case inb_button:
|
||||
key_printf (f, "in_bind %s button %s \"+%s\"\n", imt->name,
|
||||
Key_KeynumToString (i), b->button->name);
|
||||
break;
|
||||
case inb_command:
|
||||
key_printf (f, "in_bind %s button %s \"%s\"\n", imt->name,
|
||||
Key_KeynumToString (i), b->command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1161,7 +1232,7 @@ Key_Event (knum_t key, short unicode, qboolean down)
|
|||
//FIXME maybe still a tad over-coupled. Use callbacks for menu and console
|
||||
//toggles? Should keys know anything about menu and console?
|
||||
if (key_dest != key_console && key == key_toggleconsole
|
||||
&& keydown[key] == 1) {
|
||||
&& keydown[key] == 1) {
|
||||
Cbuf_AddText (cbuf, "toggleconsole");
|
||||
return;
|
||||
}
|
||||
|
@ -1258,8 +1329,8 @@ Key_CreateDefaultIMTs (void)
|
|||
default_imts[i].chain_imt_name);
|
||||
}
|
||||
for (i = 0; default_bindings[i].imt; i++) {
|
||||
Key_In_Bind (default_bindings[i].imt, default_bindings[i].key,
|
||||
default_bindings[i].command);
|
||||
Key_In_BindButton (default_bindings[i].imt, default_bindings[i].key,
|
||||
default_bindings[i].command);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1320,7 +1391,15 @@ const char *
|
|||
Key_GetBinding (imt_t *imt, knum_t key)
|
||||
{
|
||||
if (imt) {
|
||||
return imt->bindings[key].str;
|
||||
in_buttonbinding_t *b = imt->button_bindings.a[key];
|
||||
if (b) {
|
||||
switch (b->type) {
|
||||
case inb_button:
|
||||
return va (0, "+%s", b->button->name);
|
||||
case inb_command:
|
||||
return b->command;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#endif
|
||||
|
||||
#include "QF/csqc.h"
|
||||
#include "QF/keys.h"
|
||||
#include "QF/input.h"
|
||||
#include "QF/progs.h"
|
||||
#include "QF/zone.h"
|
||||
|
||||
|
@ -89,7 +89,7 @@ bi_Key_LookupBinding (progs_t *pr)
|
|||
imt = Key_FindIMT (imt_name);
|
||||
if (imt) {
|
||||
for (i = 0; i < QFK_LAST; i++) {
|
||||
keybind = imt->bindings[i].str;
|
||||
//XXX keybind = imt->button_bindings.a[i].str;
|
||||
if (keybind == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ bi_Key_CountBinding (progs_t *pr)
|
|||
imt = Key_FindIMT (imt_name);
|
||||
if (imt) {
|
||||
for (i = 0; i < QFK_LAST; i++) {
|
||||
keybind = imt->bindings[i].str;
|
||||
//XXX keybind = imt->button_bindings.a[i].str;
|
||||
if (keybind == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -563,6 +563,7 @@ static void
|
|||
qwaq_input_init (qwaq_input_resources_t *res)
|
||||
{
|
||||
res->input_event_handler = IE_Add_Handler (qwaq_input_event_handler, res);
|
||||
IE_Set_Focus (res->input_event_handler);
|
||||
IN_DriverData (term_driver_handle, res);
|
||||
|
||||
if (res->key_sequences) {
|
||||
|
|
Loading…
Reference in a new issue