mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 14:20:59 +00:00
[input] Implement imt creation, binding, etc
Much testing is needed, but the bulk of imt management is implemented. Axis bindings are not properly implemented yet, though.
This commit is contained in:
parent
fd5abb4c61
commit
925ca8081c
5 changed files with 235 additions and 4 deletions
|
@ -107,10 +107,7 @@ typedef enum {
|
||||||
typedef struct in_buttonbinding_s {
|
typedef struct in_buttonbinding_s {
|
||||||
in_button_type type;
|
in_button_type type;
|
||||||
union {
|
union {
|
||||||
struct {
|
|
||||||
int bind_id; ///< for button multi-press support
|
|
||||||
in_button_t *button;
|
in_button_t *button;
|
||||||
};
|
|
||||||
char *command;
|
char *command;
|
||||||
};
|
};
|
||||||
} in_buttonbinding_t;
|
} in_buttonbinding_t;
|
||||||
|
|
|
@ -85,8 +85,11 @@ void IMT_SetContextCbuf (int ctx, struct cbuf_s *cbuf);
|
||||||
imt_t *IMT_FindIMT (const char *name);
|
imt_t *IMT_FindIMT (const char *name);
|
||||||
int IMT_CreateIMT (int context, const char *imt_name,
|
int IMT_CreateIMT (int context, const char *imt_name,
|
||||||
const char *chain_imt_name);
|
const char *chain_imt_name);
|
||||||
|
void IMT_BindAxis (imt_t *imt, int axis, const char *binding);
|
||||||
|
void IMT_BindButton (imt_t *imt, int button, const char *binding);
|
||||||
qboolean IMT_ProcessAxis (int axis, int value);
|
qboolean IMT_ProcessAxis (int axis, int value);
|
||||||
qboolean IMT_ProcessButton (int button, int state);
|
qboolean IMT_ProcessButton (int button, int state);
|
||||||
|
void IMT_Init (void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -348,6 +348,7 @@ void
|
||||||
IN_Init (cbuf_t *cbuf)
|
IN_Init (cbuf_t *cbuf)
|
||||||
{
|
{
|
||||||
Sys_RegisterShutdown (IN_shutdown, 0);
|
Sys_RegisterShutdown (IN_shutdown, 0);
|
||||||
|
IMT_Init ();
|
||||||
IN_Binding_Init ();
|
IN_Binding_Init ();
|
||||||
|
|
||||||
for (size_t i = 0; i < in_drivers.size; i++) {
|
for (size_t i = 0; i < in_drivers.size; i++) {
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "QF/cmd.h"
|
#include "QF/cmd.h"
|
||||||
|
#include "QF/cmem.h"
|
||||||
#include "QF/hash.h"
|
#include "QF/hash.h"
|
||||||
#include "QF/sys.h"
|
#include "QF/sys.h"
|
||||||
#include "QF/va.h"
|
#include "QF/va.h"
|
||||||
|
@ -59,6 +60,45 @@ static imt_blockset_t button_blocks = DARRAY_STATIC_INIT (8);
|
||||||
static in_contextset_t in_contexts = DARRAY_STATIC_INIT (8);
|
static in_contextset_t in_contexts = DARRAY_STATIC_INIT (8);
|
||||||
static size_t imt_current_context;
|
static size_t imt_current_context;
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (!binding) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (!binding) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (binding->type) {
|
||||||
|
case inb_button:
|
||||||
|
break;
|
||||||
|
case inb_command:
|
||||||
|
free (binding->command);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cmemfree (binding_mem, binding);
|
||||||
|
}
|
||||||
|
|
||||||
static imt_block_t * __attribute__((pure))
|
static imt_block_t * __attribute__((pure))
|
||||||
imt_find_block (imt_blockset_t *blockset, const char *device)
|
imt_find_block (imt_blockset_t *blockset, const char *device)
|
||||||
{
|
{
|
||||||
|
@ -152,6 +192,17 @@ IMT_CreateContext (const char *name)
|
||||||
return ctx - in_contexts.a;
|
return ctx - in_contexts.a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static in_context_t *
|
||||||
|
imt_find_context (const char *name)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < in_contexts.size; i++) {
|
||||||
|
if (strcmp (name, in_contexts.a[i].name) == 0) {
|
||||||
|
return &in_contexts.a[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
IMT_GetContext (void)
|
IMT_GetContext (void)
|
||||||
{
|
{
|
||||||
|
@ -254,6 +305,45 @@ IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMT_BindAxis (imt_t *imt, int axis, const char *binding)
|
||||||
|
{
|
||||||
|
if ((size_t) axis >= imt->axis_bindings.size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
in_axisbinding_t **bind = &imt->axis_bindings.a[axis];
|
||||||
|
free_axis_binding ((*bind));
|
||||||
|
(*bind) = 0;
|
||||||
|
if (binding) {
|
||||||
|
in_axisbinding_t *a = alloc_axis_binding ();
|
||||||
|
(*bind) = a;
|
||||||
|
*a = (in_axisbinding_t) {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMT_BindButton (imt_t *imt, int button, const char *binding)
|
||||||
|
{
|
||||||
|
if ((size_t) button >= imt->button_bindings.size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
in_buttonbinding_t **bind = &imt->button_bindings.a[button];
|
||||||
|
free_button_binding ((*bind));
|
||||||
|
(*bind) = 0;
|
||||||
|
if (binding) {
|
||||||
|
in_buttonbinding_t *b = alloc_button_binding ();
|
||||||
|
(*bind) = b;
|
||||||
|
in_button_t *button;
|
||||||
|
if (binding[0] == '+' && (button = IN_FindButton (binding + 1))) {
|
||||||
|
b->type = inb_button;
|
||||||
|
b->button = button;
|
||||||
|
} else {
|
||||||
|
b->type = inb_command;
|
||||||
|
b->command = strdup(binding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
qboolean
|
qboolean
|
||||||
IMT_ProcessAxis (int axis, int value)
|
IMT_ProcessAxis (int axis, int value)
|
||||||
{
|
{
|
||||||
|
@ -315,3 +405,138 @@ IMT_ProcessButton (int button, int state)
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
imt_f (void)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
imt_t *imt;
|
||||||
|
const char *imt_name = 0;
|
||||||
|
const char *context_name;
|
||||||
|
|
||||||
|
c = Cmd_Argc ();
|
||||||
|
switch (c) {
|
||||||
|
case 3:
|
||||||
|
imt_name = Cmd_Argv (2);
|
||||||
|
case 2:
|
||||||
|
context_name = Cmd_Argv (1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
in_context_t *ctx = imt_find_context (context_name);
|
||||||
|
if (!ctx) {
|
||||||
|
Sys_Printf ("imt error: invalid context: %s\n", context_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!imt_name) {
|
||||||
|
Sys_Printf ("Current imt is %s\n", ctx->active_imt->name);
|
||||||
|
Sys_Printf ("imt <imt> : set to a specific input mapping table\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
imt = imt_find_imt (ctx, imt_name);
|
||||||
|
if (!imt) {
|
||||||
|
Sys_Printf ("\"%s\" is not an imt in %s\n", imt_name, ctx->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->active_imt = imt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
imt_list_f (void)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < in_contexts.size; i++) {
|
||||||
|
in_context_t *ctx = &in_contexts.a[i];
|
||||||
|
Sys_Printf ("context: %s\n", ctx->name);
|
||||||
|
for (imt_t *imt = ctx->imts; imt; imt = imt->next) {
|
||||||
|
if (imt->chain) {
|
||||||
|
Sys_Printf (" %s -> %s\n", imt->name, imt->chain->name);
|
||||||
|
} else {
|
||||||
|
Sys_Printf (" %s\n", imt->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
imt_create_f (void)
|
||||||
|
{
|
||||||
|
const char *context_name;
|
||||||
|
const char *imt_name;
|
||||||
|
const char *chain_imt_name = 0;
|
||||||
|
|
||||||
|
if (Cmd_Argc () < 3 || Cmd_Argc () > 4) {
|
||||||
|
Sys_Printf ("see help imt_create\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context_name = Cmd_Argv (1);
|
||||||
|
imt_name = Cmd_Argv (2);
|
||||||
|
if (Cmd_Argc () == 4) {
|
||||||
|
chain_imt_name = Cmd_Argv (3);
|
||||||
|
}
|
||||||
|
in_context_t *ctx = imt_find_context (context_name);
|
||||||
|
if (!ctx) {
|
||||||
|
Sys_Printf ("imt error: invalid context: %s\n", context_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
IMT_CreateIMT (ctx - in_contexts.a, imt_name, chain_imt_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
imt_drop_all_f (void)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < in_contexts.size; i++) {
|
||||||
|
in_context_t *ctx = &in_contexts.a[i];
|
||||||
|
while (ctx->imts) {
|
||||||
|
imt_t *imt = ctx->imts;
|
||||||
|
ctx->imts = imt->next;
|
||||||
|
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++) {
|
||||||
|
free_button_binding (imt->button_bindings.a[i]);
|
||||||
|
}
|
||||||
|
free ((char *) imt->name);
|
||||||
|
free (imt);
|
||||||
|
}
|
||||||
|
ctx->active_imt = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *name;
|
||||||
|
xcommand_t func;
|
||||||
|
const char *desc;
|
||||||
|
} imtcmd_t;
|
||||||
|
|
||||||
|
static imtcmd_t imt_commands[] = {
|
||||||
|
{ "imt", imt_f,
|
||||||
|
"Set the active imt of the specified context"
|
||||||
|
},
|
||||||
|
{ "imt_list", imt_list_f,
|
||||||
|
"List the available input mapping tables"
|
||||||
|
},
|
||||||
|
{ "imt_create", imt_create_f,
|
||||||
|
"create a new imt table:\n"
|
||||||
|
" imt_create <keydest> <imt_name> [chain_name]\n"
|
||||||
|
"\n"
|
||||||
|
"The new table will be attached to the specified keydest\n"
|
||||||
|
"imt_name must not already exist.\n"
|
||||||
|
"If given, chain_name must already exist and be on keydest.\n"
|
||||||
|
},
|
||||||
|
{ "imt_drop_all", imt_drop_all_f,
|
||||||
|
"delete all imt tables\n"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
IMT_Init (void)
|
||||||
|
{
|
||||||
|
binding_mem = new_memsuper ();
|
||||||
|
for (imtcmd_t *cmd = imt_commands; cmd->name; cmd++) {
|
||||||
|
Cmd_AddCommand (cmd->name, cmd->func, cmd->desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -59,6 +59,9 @@
|
||||||
#include "qw/include/client.h"
|
#include "qw/include/client.h"
|
||||||
#include "qw/include/host.h"
|
#include "qw/include/host.h"
|
||||||
|
|
||||||
|
int cl_game_context;
|
||||||
|
int cl_demo_context;
|
||||||
|
|
||||||
cvar_t *cl_nodelta;
|
cvar_t *cl_nodelta;
|
||||||
cvar_t *cl_maxnetfps;
|
cvar_t *cl_maxnetfps;
|
||||||
cvar_t *cl_spamimpulse;
|
cvar_t *cl_spamimpulse;
|
||||||
|
@ -522,6 +525,8 @@ CL_Input_Init (void)
|
||||||
for (int i = 0; cl_in_buttons[i]; i++) {
|
for (int i = 0; cl_in_buttons[i]; i++) {
|
||||||
IN_RegisterButton (cl_in_buttons[i]);
|
IN_RegisterButton (cl_in_buttons[i]);
|
||||||
}
|
}
|
||||||
|
cl_game_context = IMT_CreateContext ("key_game");
|
||||||
|
cl_demo_context = IMT_CreateContext ("key_demo");
|
||||||
Cmd_AddDataCommand ("impulse", IN_Impulse, 0,
|
Cmd_AddDataCommand ("impulse", IN_Impulse, 0,
|
||||||
"Call a game function or QuakeC function.");
|
"Call a game function or QuakeC function.");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue