mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-29 23:52:22 +00:00
[input] Save/load config to/from plist configs
While the console command line is quite good for setting everything up, the devices being bound do need to be present when the commands are executed (due to needing extra data provided by the devices). Thus property lists that store the extra data (button and axis counts, device names/ids, connection names, etc) seems to be the best solution.
This commit is contained in:
parent
7c9f3a3b09
commit
fede9125e1
6 changed files with 420 additions and 26 deletions
|
@ -143,6 +143,9 @@ int IN_RegisterDriver (in_driver_t *driver, void *data);
|
||||||
void IN_DriverData (int handlle, void *data);
|
void IN_DriverData (int handlle, void *data);
|
||||||
void IN_Init (struct cbuf_s *cbuf);
|
void IN_Init (struct cbuf_s *cbuf);
|
||||||
void IN_Init_Cvars (void);
|
void IN_Init_Cvars (void);
|
||||||
|
struct plitem_s;
|
||||||
|
void IN_SaveConfig (struct plitem_s *config);
|
||||||
|
void IN_LoadConfig (struct plitem_s *config);
|
||||||
|
|
||||||
int IN_AddDevice (int driver, void *device, const char *name, const char *id);
|
int IN_AddDevice (int driver, void *device, const char *name, const char *id);
|
||||||
void IN_RemoveDevice (int devid);
|
void IN_RemoveDevice (int devid);
|
||||||
|
|
|
@ -236,6 +236,9 @@ in_axis_t *IN_FindAxis (const char *name);
|
||||||
|
|
||||||
void IN_Binding_Activate (void);
|
void IN_Binding_Activate (void);
|
||||||
void IN_Binding_Init (void);
|
void IN_Binding_Init (void);
|
||||||
|
struct plitem_s;
|
||||||
|
void IN_Binding_SaveConfig (struct plitem_s *config);
|
||||||
|
void IN_Binding_LoadConfig (struct plitem_s *config);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,12 @@ 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);
|
void IMT_Init (void);
|
||||||
|
struct plitem_s;
|
||||||
|
void IMT_SaveConfig (struct plitem_s *config);
|
||||||
|
void IMT_SaveAxisConfig (struct plitem_s *axes, int axis_ind, int dev_axis);
|
||||||
|
void IMT_SaveButtonConfig (struct plitem_s *buttons, int button_ind,
|
||||||
|
int dev_button);
|
||||||
|
void IMT_LoadConfig (struct plitem_s *config);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include "QF/plist.h"
|
#include "QF/plist.h"
|
||||||
#include "QF/progs.h" // for PR_RESMAP
|
#include "QF/progs.h" // for PR_RESMAP
|
||||||
#include "QF/sys.h"
|
#include "QF/sys.h"
|
||||||
|
#include "QF/va.h"
|
||||||
|
|
||||||
#include "QF/input/imt.h"
|
#include "QF/input/imt.h"
|
||||||
|
|
||||||
|
@ -95,23 +96,34 @@ in_binding_find_connection (const char *devname, const char *id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
alloc_input_info (in_devbindings_t *db)
|
||||||
|
{
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
in_binding_add_device (const IE_event_t *ie_event)
|
in_binding_add_device (const IE_event_t *ie_event)
|
||||||
{
|
{
|
||||||
size_t devid = ie_event->device.devid;
|
size_t devid = ie_event->device.devid;
|
||||||
|
const char *devname = IN_GetDeviceName (devid);
|
||||||
|
const char *id = IN_GetDeviceId (devid);
|
||||||
|
|
||||||
if (in_find_devid (devid)) {
|
if (!in_find_devid (devid)) {
|
||||||
// the device is already known. this is likely the result of a
|
|
||||||
// broadcast of connected devices
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DARRAY_APPEND (&known_devices, devid);
|
DARRAY_APPEND (&known_devices, devid);
|
||||||
// keep the known devices sorted by id
|
// keep the known devices sorted by id
|
||||||
heapsort (known_devices.a, known_devices.size, sizeof (int), devid_cmp);
|
heapsort (known_devices.a, known_devices.size, sizeof (int), devid_cmp);
|
||||||
|
Sys_Printf ("Added device %s %s\n", devname, id);
|
||||||
|
}
|
||||||
|
|
||||||
const char *devname = IN_GetDeviceName (devid);
|
in_devbindings_t *db = IN_GetDeviceEventData (devid);
|
||||||
const char *id = IN_GetDeviceId (devid);
|
if (db) {
|
||||||
in_devbindings_t *db = in_binding_find_connection (devname, id);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
db = in_binding_find_connection (devname, id);
|
||||||
|
|
||||||
if (db) {
|
if (db) {
|
||||||
if (db->match_id) {
|
if (db->match_id) {
|
||||||
|
@ -121,8 +133,11 @@ in_binding_add_device (const IE_event_t *ie_event)
|
||||||
}
|
}
|
||||||
db->devid = devid;
|
db->devid = devid;
|
||||||
IN_SetDeviceEventData (devid, db);
|
IN_SetDeviceEventData (devid, db);
|
||||||
} else {
|
if (!db->axis_info) {
|
||||||
Sys_Printf ("Added device %s %s\n", devname, id);
|
alloc_input_info (db);
|
||||||
|
}
|
||||||
|
IN_AxisInfo (devid, db->axis_info, &db->num_axes);
|
||||||
|
IN_ButtonInfo (devid, db->button_info, &db->num_buttons);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,6 +285,18 @@ in_binding_find_device (const char *name)
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clear_connection (in_devbindings_t *db)
|
||||||
|
{
|
||||||
|
if (db->devid >= 0) {
|
||||||
|
IN_SetDeviceEventData (db->devid, 0);
|
||||||
|
}
|
||||||
|
free (db->name);
|
||||||
|
free (db->devname);
|
||||||
|
free (db->id);
|
||||||
|
free (db->axis_info);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
in_bind_f (void)
|
in_bind_f (void)
|
||||||
{
|
{
|
||||||
|
@ -506,12 +533,10 @@ in_connect_f (void)
|
||||||
const char *device_id = Cmd_Argv (2);
|
const char *device_id = Cmd_Argv (2);
|
||||||
int devid = -1;
|
int devid = -1;
|
||||||
|
|
||||||
for (in_devbindings_t *db = devbindings_list; db; db = db->next) {
|
if (in_binding_find_device (bindname)) {
|
||||||
if (strcmp (bindname, db->name) == 0) {
|
|
||||||
Sys_Printf ("%s already exists\n", bindname);
|
Sys_Printf ("%s already exists\n", bindname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (device_id[0] == '#') {
|
if (device_id[0] == '#') {
|
||||||
char *end;
|
char *end;
|
||||||
|
@ -560,9 +585,7 @@ in_connect_f (void)
|
||||||
|
|
||||||
IN_AxisInfo (devid, 0, &db->num_axes);
|
IN_AxisInfo (devid, 0, &db->num_axes);
|
||||||
IN_ButtonInfo (devid, 0, &db->num_buttons);
|
IN_ButtonInfo (devid, 0, &db->num_buttons);
|
||||||
db->axis_info = malloc (db->num_axes * sizeof (in_axisinfo_t)
|
alloc_input_info (db);
|
||||||
+ 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_AxisInfo (devid, db->axis_info, &db->num_axes);
|
||||||
IN_ButtonInfo (devid, db->button_info, &db->num_buttons);
|
IN_ButtonInfo (devid, db->button_info, &db->num_buttons);
|
||||||
|
|
||||||
|
@ -709,3 +732,192 @@ IN_Binding_Init (void)
|
||||||
Cmd_AddCommand (cmd->name, cmd->func, cmd->desc);
|
Cmd_AddCommand (cmd->name, cmd->func, cmd->desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IN_Binding_SaveConfig (plitem_t *config)
|
||||||
|
{
|
||||||
|
plitem_t *devices = PL_NewArray ();
|
||||||
|
PL_D_AddObject (config, "devices", devices);
|
||||||
|
for (in_devbindings_t *db = devbindings_list; db; db = db->next) {
|
||||||
|
plitem_t *db_cfg = PL_NewDictionary (0); //FIXME hashlinks
|
||||||
|
PL_A_AddObject (devices, db_cfg);
|
||||||
|
PL_D_AddObject (db_cfg, "name", PL_NewString (db->name));
|
||||||
|
PL_D_AddObject (db_cfg, "devname", PL_NewString (db->devname));
|
||||||
|
if (db->match_id) {
|
||||||
|
PL_D_AddObject (db_cfg, "id", PL_NewString (db->id));
|
||||||
|
}
|
||||||
|
PL_D_AddObject (db_cfg, "num_axes",
|
||||||
|
PL_NewString (va (0, "%d", db->num_axes)));
|
||||||
|
PL_D_AddObject (db_cfg, "num_buttons",
|
||||||
|
PL_NewString (va (0, "%d", db->num_buttons)));
|
||||||
|
if (db->axis_imt_id >= 0) {
|
||||||
|
plitem_t *axes = PL_NewArray ();
|
||||||
|
PL_D_AddObject (db_cfg, "axes", axes);
|
||||||
|
for (int i = 0; i < db->num_axes; i++) {
|
||||||
|
IMT_SaveAxisConfig (axes, db->axis_imt_id + i, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (db->button_imt_id >= 0) {
|
||||||
|
plitem_t *buttons = PL_NewArray ();
|
||||||
|
PL_D_AddObject (db_cfg, "buttons", buttons);
|
||||||
|
for (int i = 0; i < db->num_buttons; i++) {
|
||||||
|
IMT_SaveButtonConfig (buttons, db->button_imt_id + i, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
parse_num (plitem_t *item)
|
||||||
|
{
|
||||||
|
char *end;
|
||||||
|
const char *str = PL_String (item);
|
||||||
|
if (!str) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int num = strtol (str, &end, 0);
|
||||||
|
if (*end || num < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
parse_int (plitem_t *item, int dflt)
|
||||||
|
{
|
||||||
|
char *end;
|
||||||
|
const char *str = PL_String (item);
|
||||||
|
if (!str) {
|
||||||
|
return dflt;
|
||||||
|
}
|
||||||
|
int num = strtol (str, &end, 0);
|
||||||
|
if (*end) {
|
||||||
|
return dflt;
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float
|
||||||
|
parse_float (plitem_t *item, float dflt)
|
||||||
|
{
|
||||||
|
char *end;
|
||||||
|
const char *str = PL_String (item);
|
||||||
|
if (!str) {
|
||||||
|
return dflt;
|
||||||
|
}
|
||||||
|
float num = strtof (str, &end);
|
||||||
|
if (*end) {
|
||||||
|
return dflt;
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IN_Binding_LoadConfig (plitem_t *config)
|
||||||
|
{
|
||||||
|
for (in_devbindings_t *db = devbindings_list; db; db = db->next) {
|
||||||
|
clear_connection (db);
|
||||||
|
}
|
||||||
|
PR_RESRESET (devbindings);
|
||||||
|
devbindings_list = 0;
|
||||||
|
|
||||||
|
plitem_t *devices = PL_ObjectForKey (config, "devices");
|
||||||
|
if (PL_Type (devices) != QFArray) {
|
||||||
|
Sys_Printf ("IN_Binding_LoadConfig: devices not an array\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0, count = PL_A_NumObjects (devices); i < count; i++) {
|
||||||
|
plitem_t *db_cfg = PL_ObjectAtIndex (devices, i);
|
||||||
|
const char *bindname = PL_String (PL_ObjectForKey (db_cfg, "name"));
|
||||||
|
const char *devname = PL_String (PL_ObjectForKey (db_cfg, "devname"));
|
||||||
|
const char *id = PL_String (PL_ObjectForKey (db_cfg, "id"));
|
||||||
|
int num_axes = parse_num (PL_ObjectForKey (db_cfg,
|
||||||
|
"num_axes"));
|
||||||
|
int num_buttons = parse_num (PL_ObjectForKey (db_cfg,
|
||||||
|
"num_buttons"));
|
||||||
|
if (in_binding_find_device (bindname)) {
|
||||||
|
Sys_Printf ("%s already exists\n", bindname);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (num_axes < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (num_buttons < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
in_devbindings_t *db = PR_RESNEW (devbindings);
|
||||||
|
db->next = devbindings_list;
|
||||||
|
devbindings_list = db;
|
||||||
|
|
||||||
|
db->name = strdup (bindname);
|
||||||
|
db->devname = strdup (devname);
|
||||||
|
if (id) {
|
||||||
|
db->id = strdup (id);
|
||||||
|
db->match_id = 1;
|
||||||
|
} else {
|
||||||
|
db->id = 0;
|
||||||
|
db->match_id = 0;
|
||||||
|
}
|
||||||
|
db->devid = -1; // not connected yet
|
||||||
|
|
||||||
|
db->num_axes = num_axes;
|
||||||
|
db->num_buttons = num_buttons;
|
||||||
|
|
||||||
|
db->axis_imt_id = -1;
|
||||||
|
db->button_imt_id = -1;
|
||||||
|
|
||||||
|
plitem_t *axes = PL_ObjectForKey (db_cfg, "axes");
|
||||||
|
if (PL_A_NumObjects (axes)) {
|
||||||
|
db->axis_imt_id = IMT_GetAxisBlock (db->num_axes);
|
||||||
|
}
|
||||||
|
for (int i = 0, count = PL_A_NumObjects (axes); i < count; i++) {
|
||||||
|
plitem_t *a = PL_ObjectAtIndex (axes, i);
|
||||||
|
const char *imt_name = PL_String (PL_ObjectForKey (a, "imt"));
|
||||||
|
int num = parse_num (PL_ObjectForKey (a, "num"));
|
||||||
|
const char *axis_name = PL_String (PL_ObjectForKey (a, "axis"));
|
||||||
|
in_recipe_t recipe = {
|
||||||
|
.min = parse_int (PL_ObjectForKey (a, "min"), 0),
|
||||||
|
.max = parse_int (PL_ObjectForKey (a, "max"), 0),
|
||||||
|
.minzone = parse_int (PL_ObjectForKey (a, "minzone"), 0),
|
||||||
|
.maxzone = parse_int (PL_ObjectForKey (a, "maxzone"), 0),
|
||||||
|
.deadzone = parse_int (PL_ObjectForKey (a, "deadzone"), 0),
|
||||||
|
.curve = parse_float (PL_ObjectForKey (a, "curve"), 1),
|
||||||
|
.scale = parse_float (PL_ObjectForKey (a, "scale"), 1),
|
||||||
|
};
|
||||||
|
if (!imt_name || num < 0 || num >= db->num_axes) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
imt_t *imt = IMT_FindIMT (imt_name);
|
||||||
|
if (!imt) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
in_axis_t *axis = IN_FindAxis (axis_name);
|
||||||
|
if (!axis) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
IMT_BindAxis (imt, db->axis_imt_id + num, axis, &recipe);
|
||||||
|
}
|
||||||
|
plitem_t *buttons = PL_ObjectForKey (db_cfg, "buttons");
|
||||||
|
if (PL_A_NumObjects (buttons)) {
|
||||||
|
db->button_imt_id = IMT_GetButtonBlock (db->num_buttons);
|
||||||
|
}
|
||||||
|
for (int i = 0, count = PL_A_NumObjects (buttons); i < count; i++) {
|
||||||
|
plitem_t *b = PL_ObjectAtIndex (buttons, i);
|
||||||
|
const char *imt_name = PL_String (PL_ObjectForKey (b, "imt"));
|
||||||
|
int num = parse_num (PL_ObjectForKey (b, "num"));
|
||||||
|
const char *binding = PL_String (PL_ObjectForKey (b, "binding"));
|
||||||
|
if (!imt_name || num < 0 || num >= db->num_buttons) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
imt_t *imt = IMT_FindIMT (imt_name);
|
||||||
|
if (!imt) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
IMT_BindButton (imt, db->button_imt_id + num, binding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// force device connection events so any connected devices get hoocked up
|
||||||
|
// with their bindings
|
||||||
|
IN_SendConnectedDevices ();
|
||||||
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
#include "QF/joystick.h"
|
#include "QF/joystick.h"
|
||||||
#include "QF/keys.h"
|
#include "QF/keys.h"
|
||||||
#include "QF/mathlib.h"
|
#include "QF/mathlib.h"
|
||||||
|
#include "QF/plist.h"
|
||||||
#include "QF/sys.h"
|
#include "QF/sys.h"
|
||||||
#include "QF/vid.h"
|
#include "QF/vid.h"
|
||||||
|
|
||||||
|
@ -321,6 +322,27 @@ IN_ProcessEvents (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IN_SaveConfig (plitem_t *config)
|
||||||
|
{
|
||||||
|
plitem_t *input_config = PL_NewDictionary (0); //FIXME hashlinks
|
||||||
|
PL_D_AddObject (config, "input", input_config);
|
||||||
|
|
||||||
|
IMT_SaveConfig (input_config);
|
||||||
|
IN_Binding_SaveConfig (input_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IN_LoadConfig (plitem_t *config)
|
||||||
|
{
|
||||||
|
plitem_t *input_config = PL_ObjectForKey (config, "input");
|
||||||
|
|
||||||
|
if (input_config) {
|
||||||
|
IMT_LoadConfig (input_config);
|
||||||
|
IN_Binding_LoadConfig (input_config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
IN_Move (void)
|
IN_Move (void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include "QF/hash.h"
|
#include "QF/hash.h"
|
||||||
#include "QF/input.h"
|
#include "QF/input.h"
|
||||||
#include "QF/mathlib.h"
|
#include "QF/mathlib.h"
|
||||||
|
#include "QF/plist.h"
|
||||||
#include "QF/sys.h"
|
#include "QF/sys.h"
|
||||||
#include "QF/va.h"
|
#include "QF/va.h"
|
||||||
|
|
||||||
|
@ -226,11 +227,13 @@ IMT_CreateContext (const char *name)
|
||||||
static in_context_t * __attribute__ ((pure))
|
static in_context_t * __attribute__ ((pure))
|
||||||
imt_find_context (const char *name)
|
imt_find_context (const char *name)
|
||||||
{
|
{
|
||||||
|
if (name) {
|
||||||
for (size_t i = 0; i < in_contexts.size; i++) {
|
for (size_t i = 0; i < in_contexts.size; i++) {
|
||||||
if (strcmp (name, in_contexts.a[i].name) == 0) {
|
if (strcmp (name, in_contexts.a[i].name) == 0) {
|
||||||
return &in_contexts.a[i];
|
return &in_contexts.a[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,6 +315,10 @@ IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
imt = malloc (sizeof (imt_t));
|
imt = malloc (sizeof (imt_t));
|
||||||
|
if (!ctx->imts) {
|
||||||
|
ctx->default_imt = imt;
|
||||||
|
ctx->active_imt = imt;
|
||||||
|
}
|
||||||
*ctx->imt_tail = imt;
|
*ctx->imt_tail = imt;
|
||||||
ctx->imt_tail = &imt->next;
|
ctx->imt_tail = &imt->next;
|
||||||
|
|
||||||
|
@ -330,7 +337,7 @@ IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name)
|
||||||
num_axes * sizeof (in_axisbinding_t *));
|
num_axes * sizeof (in_axisbinding_t *));
|
||||||
}
|
}
|
||||||
if (num_buttons) {
|
if (num_buttons) {
|
||||||
memset (imt->axis_bindings.a, 0,
|
memset (imt->button_bindings.a, 0,
|
||||||
num_buttons * sizeof (in_buttonbinding_t *));
|
num_buttons * sizeof (in_buttonbinding_t *));
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -481,7 +488,6 @@ IMT_ProcessButton (int button, int state)
|
||||||
{
|
{
|
||||||
imt_t *imt = in_contexts.a[imt_current_context].active_imt;
|
imt_t *imt = in_contexts.a[imt_current_context].active_imt;
|
||||||
|
|
||||||
Sys_Printf ("IMT_ProcessButton: %d %d\n", button, state);
|
|
||||||
while (imt) {
|
while (imt) {
|
||||||
in_buttonbinding_t *b = imt->button_bindings.a[button];
|
in_buttonbinding_t *b = imt->button_bindings.a[button];
|
||||||
if (b) {
|
if (b) {
|
||||||
|
@ -598,6 +604,8 @@ imt_drop_all_f (void)
|
||||||
free (imt);
|
free (imt);
|
||||||
}
|
}
|
||||||
ctx->active_imt = 0;
|
ctx->active_imt = 0;
|
||||||
|
ctx->default_imt = 0;
|
||||||
|
ctx->imt_tail = &ctx->imts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,3 +646,143 @@ IMT_Init (void)
|
||||||
Cmd_AddCommand (cmd->name, cmd->func, cmd->desc);
|
Cmd_AddCommand (cmd->name, cmd->func, cmd->desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMT_SaveConfig (plitem_t *config)
|
||||||
|
{
|
||||||
|
plitem_t *ctx_list = PL_NewArray ();
|
||||||
|
PL_D_AddObject (config, "contexts", ctx_list);
|
||||||
|
for (size_t i = 0; i < in_contexts.size; i++) {
|
||||||
|
in_context_t *context = &in_contexts.a[i];
|
||||||
|
plitem_t *ctx = PL_NewDictionary (0); //FIXME hashlinks
|
||||||
|
PL_A_AddObject (ctx_list, ctx);
|
||||||
|
PL_D_AddObject (ctx, "name", PL_NewString (context->name));
|
||||||
|
if (context->imts) {
|
||||||
|
plitem_t *imt_list = PL_NewArray ();
|
||||||
|
PL_D_AddObject (ctx, "imts", imt_list);
|
||||||
|
for (imt_t *imt = context->imts; imt; imt = imt->next) {
|
||||||
|
plitem_t *imt_cfg = PL_NewDictionary (0); //FIXME hashlinks
|
||||||
|
PL_D_AddObject (imt_cfg, "name", PL_NewString (imt->name));
|
||||||
|
if (imt->chain) {
|
||||||
|
PL_D_AddObject (imt_cfg, "chain",
|
||||||
|
PL_NewString (imt->chain->name));
|
||||||
|
}
|
||||||
|
PL_A_AddObject (imt_list, imt_cfg);
|
||||||
|
// the bindings are not written here because they are managed
|
||||||
|
// by IN_Binding_SaveConfig: IMT does not really know the
|
||||||
|
// device-input structure (it cound via the blocks, but it
|
||||||
|
// doesn't know the device names (by design))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (context->default_imt) {
|
||||||
|
PL_D_AddObject (ctx, "default_imt",
|
||||||
|
PL_NewString (context->default_imt->name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMT_SaveAxisConfig (plitem_t *axes, int axis_ind, int dev_axis)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < in_contexts.size; i++) {
|
||||||
|
in_context_t *context = &in_contexts.a[i];
|
||||||
|
for (imt_t *imt = context->imts; imt; imt = imt->next) {
|
||||||
|
in_axisbinding_t *a = imt->axis_bindings.a[axis_ind];
|
||||||
|
if (a) {
|
||||||
|
in_recipe_t *recipe = a->recipe;
|
||||||
|
plitem_t *axis = PL_NewDictionary (0); //FIXME hashlinks
|
||||||
|
PL_A_AddObject (axes, axis);
|
||||||
|
|
||||||
|
PL_D_AddObject (axis, "imt", PL_NewString (imt->name));
|
||||||
|
PL_D_AddObject (axis, "num",
|
||||||
|
PL_NewString (va (0, "%d", dev_axis)));
|
||||||
|
PL_D_AddObject (axis, "axis", PL_NewString (a->axis->name));
|
||||||
|
PL_D_AddObject (axis, "min",
|
||||||
|
PL_NewString (va (0, "%d", recipe->min)));
|
||||||
|
PL_D_AddObject (axis, "max",
|
||||||
|
PL_NewString (va (0, "%d", recipe->max)));
|
||||||
|
PL_D_AddObject (axis, "minzone",
|
||||||
|
PL_NewString (va (0, "%d", recipe->minzone)));
|
||||||
|
PL_D_AddObject (axis, "maxzone",
|
||||||
|
PL_NewString (va (0, "%d", recipe->maxzone)));
|
||||||
|
PL_D_AddObject (axis, "deadzone",
|
||||||
|
PL_NewString (va (0, "%d", recipe->deadzone)));
|
||||||
|
PL_D_AddObject (axis, "curve",
|
||||||
|
PL_NewString (va (0, "%.9g", recipe->curve)));
|
||||||
|
PL_D_AddObject (axis, "scale",
|
||||||
|
PL_NewString (va (0, "%.9g", recipe->scale)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMT_SaveButtonConfig (plitem_t *buttons, int button_ind, int dev_button)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < in_contexts.size; i++) {
|
||||||
|
in_context_t *context = &in_contexts.a[i];
|
||||||
|
for (imt_t *imt = context->imts; imt; imt = imt->next) {
|
||||||
|
in_buttonbinding_t *b = imt->button_bindings.a[button_ind];
|
||||||
|
if (b) {
|
||||||
|
plitem_t *button = PL_NewDictionary (0); //FIXME hashlinks
|
||||||
|
PL_A_AddObject (buttons, button);
|
||||||
|
|
||||||
|
PL_D_AddObject (button, "imt", PL_NewString (imt->name));
|
||||||
|
PL_D_AddObject (button, "num",
|
||||||
|
PL_NewString (va (0, "%d", dev_button)));
|
||||||
|
switch (b->type) {
|
||||||
|
case inb_button:
|
||||||
|
PL_D_AddObject (button, "binding",
|
||||||
|
PL_NewString (va (0, "+%s",
|
||||||
|
b->button->name)));
|
||||||
|
break;
|
||||||
|
case inb_command:
|
||||||
|
PL_D_AddObject (button, "binding",
|
||||||
|
PL_NewString (b->command));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMT_LoadConfig (plitem_t *config)
|
||||||
|
{
|
||||||
|
imt_drop_all_f ();
|
||||||
|
|
||||||
|
plitem_t *ctx_list = PL_ObjectForKey (config, "contexts");
|
||||||
|
if (PL_Type (ctx_list) != QFArray) {
|
||||||
|
Sys_Printf ("IMT_LoadConfig: contexts not an array\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0, count = PL_A_NumObjects (ctx_list); i < count; i++) {
|
||||||
|
plitem_t *ctx = PL_ObjectAtIndex (ctx_list, i);
|
||||||
|
const char *name = PL_String (PL_ObjectForKey (ctx, "name"));
|
||||||
|
in_context_t *context = imt_find_context (name);
|
||||||
|
if (!context) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
plitem_t *imts = PL_ObjectForKey (ctx, "imts");
|
||||||
|
if (!imts || PL_Type (imts) != QFArray) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (int j = 0, num_imts = PL_A_NumObjects (imts); j < num_imts; j++) {
|
||||||
|
plitem_t *imt = PL_ObjectAtIndex (imts, j);
|
||||||
|
const char *imt_name = PL_String (PL_ObjectForKey (imt, "name"));
|
||||||
|
const char *imt_chain = PL_String (PL_ObjectForKey (imt, "chain"));
|
||||||
|
if (imt_name) {
|
||||||
|
IMT_CreateIMT (context - in_contexts.a, imt_name, imt_chain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const char *default_imt = PL_String (PL_ObjectForKey (ctx,
|
||||||
|
"default_imt"));
|
||||||
|
if (default_imt) {
|
||||||
|
context->default_imt = IMT_FindIMT (default_imt);
|
||||||
|
}
|
||||||
|
if (!context->default_imt) {
|
||||||
|
context->default_imt = context->imts;
|
||||||
|
}
|
||||||
|
context->active_imt = context->default_imt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue