mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-23 04:52:07 +00:00
Gyro aiming implementation
SDL 2.0.16 and a controller with a gyroscope required to make it work. Manual calibration of the gyro sensor is needed to avoid "drifting"; a menu option to do it is included. New cvar 'gyro_mode' for mode of operation, and to assign action to the new "+gyroaction" button: disable or enable the gyro.
This commit is contained in:
parent
a80f5b6cd7
commit
d3da95cfc8
2 changed files with 283 additions and 10 deletions
|
@ -30,8 +30,8 @@
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
#include "header/input.h"
|
#include "header/input.h"
|
||||||
#include "../../client/header/keyboard.h"
|
#include "../header/keyboard.h"
|
||||||
#include "../../client/header/client.h"
|
#include "../header/client.h"
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ static int sdl_back_button = SDL_CONTROLLER_BUTTON_BACK;
|
||||||
static float joystick_yaw, joystick_pitch;
|
static float joystick_yaw, joystick_pitch;
|
||||||
static float joystick_forwardmove, joystick_sidemove;
|
static float joystick_forwardmove, joystick_sidemove;
|
||||||
static float joystick_up;
|
static float joystick_up;
|
||||||
|
static float gyro_yaw, gyro_pitch;
|
||||||
static qboolean mlooking;
|
static qboolean mlooking;
|
||||||
|
|
||||||
// The last time input events were processed.
|
// The last time input events were processed.
|
||||||
|
@ -130,9 +131,33 @@ static cvar_t *joy_axis_triggerright_threshold;
|
||||||
// Joystick haptic
|
// Joystick haptic
|
||||||
static cvar_t *joy_haptic_magnitude;
|
static cvar_t *joy_haptic_magnitude;
|
||||||
|
|
||||||
|
// Gyro mode (0=off, 3=on, 1-2=uses button to enable/disable)
|
||||||
|
cvar_t *gyro_mode;
|
||||||
|
|
||||||
|
// Gyro availability
|
||||||
|
qboolean gyro_hardware = false;
|
||||||
|
|
||||||
|
// Gyro is being used in this very moment
|
||||||
|
static qboolean gyro_active = false;
|
||||||
|
|
||||||
|
// Gyro calibration
|
||||||
|
static qboolean calibrating_gyro = false;
|
||||||
|
static float gyro_accum[3];
|
||||||
|
static unsigned int num_samples;
|
||||||
|
|
||||||
|
static cvar_t *gyro_calibration_x;
|
||||||
|
static cvar_t *gyro_calibration_y;
|
||||||
|
static cvar_t *gyro_calibration_z;
|
||||||
|
|
||||||
// Support for hot plugging of game controller
|
// Support for hot plugging of game controller
|
||||||
static qboolean first_init = true;
|
static qboolean first_init = true;
|
||||||
static int init_delay = 30;
|
static int in_delay = 30;
|
||||||
|
|
||||||
|
// Factors used to transform from SDL input to Q2 "view angle" change
|
||||||
|
#define NORMALIZE_SDL_AXIS (1.0f/32768.0f)
|
||||||
|
static float normalize_sdl_gyro = 1.0f/3.1f; // can change depending on hardware
|
||||||
|
|
||||||
|
extern void CalibrationFinishedCallback(void);
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
@ -778,6 +803,32 @@ IN_Update(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 16) // support for controller sensors (gyro, accelerometer)
|
||||||
|
case SDL_CONTROLLERSENSORUPDATE:
|
||||||
|
if (event.csensor.sensor != SDL_SENSOR_GYRO)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (calibrating_gyro)
|
||||||
|
{
|
||||||
|
gyro_accum[0] += event.csensor.data[0];
|
||||||
|
gyro_accum[1] += event.csensor.data[1];
|
||||||
|
gyro_accum[2] += event.csensor.data[2];
|
||||||
|
num_samples++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!gyro_active || !gyro_mode->value)
|
||||||
|
{
|
||||||
|
gyro_yaw = gyro_pitch = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gyro_yaw = (event.csensor.data[1] - gyro_calibration_y->value) * cl_yawspeed->value;
|
||||||
|
gyro_pitch = (event.csensor.data[0] - gyro_calibration_x->value) * cl_pitchspeed->value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif // SDL_VERSION_ATLEAST(2, 0, 16)
|
||||||
|
|
||||||
case SDL_CONTROLLERDEVICEREMOVED:
|
case SDL_CONTROLLERDEVICEREMOVED:
|
||||||
if (!controller)
|
if (!controller)
|
||||||
{
|
{
|
||||||
|
@ -793,7 +844,7 @@ IN_Update(void)
|
||||||
if (!controller)
|
if (!controller)
|
||||||
{
|
{
|
||||||
// This should be lower, but some controllers just don't want to get detected by the OS
|
// This should be lower, but some controllers just don't want to get detected by the OS
|
||||||
init_delay = 100;
|
in_delay = 100;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -825,12 +876,23 @@ IN_Update(void)
|
||||||
// Hot plugging delay handling, to not be "overwhelmed" because some controllers
|
// Hot plugging delay handling, to not be "overwhelmed" because some controllers
|
||||||
// present themselves as two different devices, triggering SDL_JOYDEVICEADDED
|
// present themselves as two different devices, triggering SDL_JOYDEVICEADDED
|
||||||
// too many times. They could trigger it even at game initialization.
|
// too many times. They could trigger it even at game initialization.
|
||||||
if (init_delay)
|
// Also used to keep time of the 'controller gyro calibration' pause.
|
||||||
|
if (in_delay)
|
||||||
{
|
{
|
||||||
init_delay--;
|
in_delay--;
|
||||||
if (!init_delay)
|
if (!in_delay)
|
||||||
{
|
{
|
||||||
if (!first_init)
|
if (calibrating_gyro)
|
||||||
|
{
|
||||||
|
const float inverseSamples = 1.f / num_samples;
|
||||||
|
Cvar_SetValue("gyro_calibration_x", gyro_accum[0] * inverseSamples);
|
||||||
|
Cvar_SetValue("gyro_calibration_y", gyro_accum[1] * inverseSamples);
|
||||||
|
Cvar_SetValue("gyro_calibration_z", gyro_accum[2] * inverseSamples);
|
||||||
|
calibrating_gyro = false;
|
||||||
|
Com_Printf("Calibration results:\n X=%f Y=%f Z=%f\n", gyro_calibration_x->value, gyro_calibration_y->value, gyro_calibration_z->value);
|
||||||
|
CalibrationFinishedCallback();
|
||||||
|
}
|
||||||
|
else if (!first_init)
|
||||||
{
|
{
|
||||||
IN_Controller_Shutdown(false);
|
IN_Controller_Shutdown(false);
|
||||||
IN_Controller_Init(true);
|
IN_Controller_Init(true);
|
||||||
|
@ -841,6 +903,7 @@ IN_Update(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -931,7 +994,9 @@ IN_Move(usercmd_t *cmd)
|
||||||
// 1/32768 is to normalize the input values from SDL (they're between -32768 and
|
// 1/32768 is to normalize the input values from SDL (they're between -32768 and
|
||||||
// 32768 and we want -1 to 1) for movement this is not needed, as those are
|
// 32768 and we want -1 to 1) for movement this is not needed, as those are
|
||||||
// absolute values independent of framerate
|
// absolute values independent of framerate
|
||||||
float joyViewFactor = (1.0f/32768.0f) * (cls.rframetime/0.01666f);
|
float frametime_ratio = cls.rframetime/0.01666f;
|
||||||
|
float joyViewFactor = NORMALIZE_SDL_AXIS * frametime_ratio;
|
||||||
|
float gyroViewFactor = normalize_sdl_gyro * frametime_ratio;
|
||||||
|
|
||||||
if (joystick_yaw)
|
if (joystick_yaw)
|
||||||
{
|
{
|
||||||
|
@ -957,6 +1022,16 @@ IN_Move(usercmd_t *cmd)
|
||||||
{
|
{
|
||||||
cmd->upmove -= (m_up->value * joystick_up) / 32768;
|
cmd->upmove -= (m_up->value * joystick_up) / 32768;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gyro_yaw)
|
||||||
|
{
|
||||||
|
cl.viewangles[YAW] += (m_yaw->value * gyro_yaw) * gyroViewFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gyro_pitch)
|
||||||
|
{
|
||||||
|
cl.viewangles[PITCH] -= (m_pitch->value * gyro_pitch) * gyroViewFactor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
@ -992,6 +1067,32 @@ IN_JoyAltSelectorUp(void)
|
||||||
joy_altselector_pressed = false;
|
joy_altselector_pressed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
IN_GyroActionDown(void)
|
||||||
|
{
|
||||||
|
switch ((int)gyro_mode->value)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
gyro_active = true;
|
||||||
|
return;
|
||||||
|
case 2:
|
||||||
|
gyro_active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
IN_GyroActionUp(void)
|
||||||
|
{
|
||||||
|
switch ((int)gyro_mode->value)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
gyro_active = false;
|
||||||
|
return;
|
||||||
|
case 2:
|
||||||
|
gyro_active = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Removes all pending events from SDLs queue.
|
* Removes all pending events from SDLs queue.
|
||||||
*/
|
*/
|
||||||
|
@ -1233,6 +1334,26 @@ Haptic_Feedback(char *name, int effect_volume, int effect_duration,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gyro calibration functions, called from menu
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
StartCalibration(void)
|
||||||
|
{
|
||||||
|
gyro_accum[0] = 0.0;
|
||||||
|
gyro_accum[1] = 0.0;
|
||||||
|
gyro_accum[2] = 0.0;
|
||||||
|
num_samples = 0;
|
||||||
|
calibrating_gyro = true;
|
||||||
|
in_delay = 290;
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean
|
||||||
|
IsCalibrationZero(void)
|
||||||
|
{
|
||||||
|
return (!gyro_calibration_x->value && !gyro_calibration_y->value && !gyro_calibration_z->value);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Game Controller
|
* Game Controller
|
||||||
*/
|
*/
|
||||||
|
@ -1373,6 +1494,20 @@ IN_Controller_Init(qboolean notify_user)
|
||||||
IN_Haptic_Effects_Info();
|
IN_Haptic_Effects_Info();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 16) // support for controller sensors
|
||||||
|
if ( SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO)
|
||||||
|
&& !SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE) )
|
||||||
|
{
|
||||||
|
float gyro_data_rate = SDL_GameControllerGetSensorDataRate(controller, SDL_SENSOR_GYRO);
|
||||||
|
if (gyro_data_rate <= 200.0f)
|
||||||
|
{
|
||||||
|
normalize_sdl_gyro = 1.0f/4.5f;
|
||||||
|
}
|
||||||
|
gyro_hardware = true;
|
||||||
|
Com_Printf("Gyro sensor enabled at %.2f Hz\n", gyro_data_rate);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1388,6 +1523,7 @@ IN_Init(void)
|
||||||
|
|
||||||
mouse_x = mouse_y = 0;
|
mouse_x = mouse_y = 0;
|
||||||
joystick_yaw = joystick_pitch = joystick_forwardmove = joystick_sidemove = 0;
|
joystick_yaw = joystick_pitch = joystick_forwardmove = joystick_sidemove = 0;
|
||||||
|
gyro_yaw = gyro_pitch = 0;
|
||||||
|
|
||||||
exponential_speedup = Cvar_Get("exponential_speedup", "0", CVAR_ARCHIVE);
|
exponential_speedup = Cvar_Get("exponential_speedup", "0", CVAR_ARCHIVE);
|
||||||
freelook = Cvar_Get("freelook", "1", CVAR_ARCHIVE);
|
freelook = Cvar_Get("freelook", "1", CVAR_ARCHIVE);
|
||||||
|
@ -1424,6 +1560,16 @@ IN_Init(void)
|
||||||
joy_axis_triggerleft_threshold = Cvar_Get("joy_axis_triggerleft_threshold", "0.15", CVAR_ARCHIVE);
|
joy_axis_triggerleft_threshold = Cvar_Get("joy_axis_triggerleft_threshold", "0.15", CVAR_ARCHIVE);
|
||||||
joy_axis_triggerright_threshold = Cvar_Get("joy_axis_triggerright_threshold", "0.15", CVAR_ARCHIVE);
|
joy_axis_triggerright_threshold = Cvar_Get("joy_axis_triggerright_threshold", "0.15", CVAR_ARCHIVE);
|
||||||
|
|
||||||
|
gyro_calibration_x = Cvar_Get("gyro_calibration_x", "0.0", CVAR_ARCHIVE);
|
||||||
|
gyro_calibration_y = Cvar_Get("gyro_calibration_y", "0.0", CVAR_ARCHIVE);
|
||||||
|
gyro_calibration_z = Cvar_Get("gyro_calibration_z", "0.0", CVAR_ARCHIVE);
|
||||||
|
|
||||||
|
gyro_mode = Cvar_Get("gyro_mode", "2", CVAR_ARCHIVE);
|
||||||
|
if ((int)gyro_mode->value == 2)
|
||||||
|
{
|
||||||
|
gyro_active = true;
|
||||||
|
}
|
||||||
|
|
||||||
windowed_mouse = Cvar_Get("windowed_mouse", "1", CVAR_USERINFO | CVAR_ARCHIVE);
|
windowed_mouse = Cvar_Get("windowed_mouse", "1", CVAR_USERINFO | CVAR_ARCHIVE);
|
||||||
|
|
||||||
Cmd_AddCommand("+mlook", IN_MLookDown);
|
Cmd_AddCommand("+mlook", IN_MLookDown);
|
||||||
|
@ -1431,6 +1577,8 @@ IN_Init(void)
|
||||||
|
|
||||||
Cmd_AddCommand("+joyaltselector", IN_JoyAltSelectorDown);
|
Cmd_AddCommand("+joyaltselector", IN_JoyAltSelectorDown);
|
||||||
Cmd_AddCommand("-joyaltselector", IN_JoyAltSelectorUp);
|
Cmd_AddCommand("-joyaltselector", IN_JoyAltSelectorUp);
|
||||||
|
Cmd_AddCommand("+gyroaction", IN_GyroActionDown);
|
||||||
|
Cmd_AddCommand("-gyroaction", IN_GyroActionUp);
|
||||||
|
|
||||||
SDL_StartTextInput();
|
SDL_StartTextInput();
|
||||||
|
|
||||||
|
@ -1467,7 +1615,10 @@ IN_Controller_Shutdown(qboolean notify_user)
|
||||||
if (controller)
|
if (controller)
|
||||||
{
|
{
|
||||||
SDL_GameControllerClose(controller);
|
SDL_GameControllerClose(controller);
|
||||||
controller = NULL;
|
controller = NULL;
|
||||||
|
gyro_hardware = false;
|
||||||
|
gyro_yaw = gyro_pitch = 0;
|
||||||
|
normalize_sdl_gyro = 1.0f/3.1f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1478,6 +1629,11 @@ IN_Shutdown(void)
|
||||||
Cmd_RemoveCommand("+mlook");
|
Cmd_RemoveCommand("+mlook");
|
||||||
Cmd_RemoveCommand("-mlook");
|
Cmd_RemoveCommand("-mlook");
|
||||||
|
|
||||||
|
Cmd_RemoveCommand("+joyaltselector");
|
||||||
|
Cmd_RemoveCommand("-joyaltselector");
|
||||||
|
Cmd_RemoveCommand("+gyroaction");
|
||||||
|
Cmd_RemoveCommand("-gyroaction");
|
||||||
|
|
||||||
Com_Printf("Shutting down input.\n");
|
Com_Printf("Shutting down input.\n");
|
||||||
|
|
||||||
IN_Controller_Shutdown(false);
|
IN_Controller_Shutdown(false);
|
||||||
|
|
|
@ -1293,6 +1293,7 @@ char *controller_bindnames[][2] =
|
||||||
{"invprev", "prev item"},
|
{"invprev", "prev item"},
|
||||||
{"invnext", "next item"},
|
{"invnext", "next item"},
|
||||||
{"cmd help", "help computer"},
|
{"cmd help", "help computer"},
|
||||||
|
{"+gyroaction", "gyro off / on"},
|
||||||
{"+joyaltselector", "alt buttons modifier"}
|
{"+joyaltselector", "alt buttons modifier"}
|
||||||
};
|
};
|
||||||
#define NUM_CONTROLLER_BINDNAMES (sizeof controller_bindnames / sizeof controller_bindnames[0])
|
#define NUM_CONTROLLER_BINDNAMES (sizeof controller_bindnames / sizeof controller_bindnames[0])
|
||||||
|
@ -1595,6 +1596,102 @@ M_Menu_ControllerAltButtons_f(void)
|
||||||
M_PushMenu(ControllerAltButtons_MenuDraw, ControllerAltButtons_MenuKey);
|
M_PushMenu(ControllerAltButtons_MenuDraw, ControllerAltButtons_MenuKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GYRO OPTIONS MENU
|
||||||
|
*/
|
||||||
|
|
||||||
|
static menuframework_s s_gyro_menu;
|
||||||
|
|
||||||
|
static menuseparator_s s_calibrating_text[2];
|
||||||
|
static menuaction_s s_calibrate_gyro;
|
||||||
|
|
||||||
|
extern qboolean gyro_hardware;
|
||||||
|
extern void StartCalibration(void);
|
||||||
|
extern qboolean IsCalibrationZero(void);
|
||||||
|
|
||||||
|
static void
|
||||||
|
CalibrateGyroFunc(void *unused)
|
||||||
|
{
|
||||||
|
if (!gyro_hardware)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_popup_string = "Calibrating, please wait...";
|
||||||
|
m_popup_endtime = cls.realtime + 4650;
|
||||||
|
M_Popup();
|
||||||
|
R_EndFrame();
|
||||||
|
StartCalibration();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CalibrationFinishedCallback(void)
|
||||||
|
{
|
||||||
|
Menu_SetStatusBar(&s_gyro_menu, NULL);
|
||||||
|
m_popup_string = "Calibration complete!";
|
||||||
|
m_popup_endtime = cls.realtime + 1900;
|
||||||
|
M_Popup();
|
||||||
|
R_EndFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Gyro_MenuInit(void)
|
||||||
|
{
|
||||||
|
int y = 0;
|
||||||
|
float scale = SCR_GetMenuScale();
|
||||||
|
|
||||||
|
s_gyro_menu.x = (int)(viddef.width * 0.50f);
|
||||||
|
s_gyro_menu.nitems = 0;
|
||||||
|
|
||||||
|
s_calibrating_text[0].generic.type = MTYPE_SEPARATOR;
|
||||||
|
s_calibrating_text[0].generic.x = 48 * scale + 30;
|
||||||
|
s_calibrating_text[0].generic.y = y;
|
||||||
|
s_calibrating_text[0].generic.name = "place the controller on a flat,";
|
||||||
|
|
||||||
|
s_calibrating_text[1].generic.type = MTYPE_SEPARATOR;
|
||||||
|
s_calibrating_text[1].generic.x = 48 * scale + 30;
|
||||||
|
s_calibrating_text[1].generic.y = (y += 10);
|
||||||
|
s_calibrating_text[1].generic.name = "stable surface to...";
|
||||||
|
|
||||||
|
s_calibrate_gyro.generic.type = MTYPE_ACTION;
|
||||||
|
s_calibrate_gyro.generic.x = 0;
|
||||||
|
s_calibrate_gyro.generic.y = (y += 15);
|
||||||
|
s_calibrate_gyro.generic.name = "calibrate";
|
||||||
|
s_calibrate_gyro.generic.callback = CalibrateGyroFunc;
|
||||||
|
|
||||||
|
Menu_AddItem(&s_gyro_menu, (void *)&s_calibrating_text[0]);
|
||||||
|
Menu_AddItem(&s_gyro_menu, (void *)&s_calibrating_text[1]);
|
||||||
|
Menu_AddItem(&s_gyro_menu, (void *)&s_calibrate_gyro);
|
||||||
|
|
||||||
|
if (IsCalibrationZero())
|
||||||
|
{
|
||||||
|
Menu_SetStatusBar(&s_gyro_menu, "Calibration required");
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu_Center(&s_gyro_menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Gyro_MenuDraw(void)
|
||||||
|
{
|
||||||
|
Menu_AdjustCursor(&s_gyro_menu, 1);
|
||||||
|
Menu_Draw(&s_gyro_menu);
|
||||||
|
M_Popup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
Gyro_MenuKey(int key)
|
||||||
|
{
|
||||||
|
return Default_MenuKey(&s_gyro_menu, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
M_Menu_Gyro_f(void)
|
||||||
|
{
|
||||||
|
Gyro_MenuInit();
|
||||||
|
M_PushMenu(Gyro_MenuDraw, Gyro_MenuKey);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JOY MENU
|
* JOY MENU
|
||||||
*/
|
*/
|
||||||
|
@ -1605,6 +1702,7 @@ static menuslider_s s_joy_forwardsensitivity_slider;
|
||||||
static menuslider_s s_joy_sidesensitivity_slider;
|
static menuslider_s s_joy_sidesensitivity_slider;
|
||||||
static menuslider_s s_joy_upsensitivity_slider;
|
static menuslider_s s_joy_upsensitivity_slider;
|
||||||
static menuslider_s s_joy_haptic_slider;
|
static menuslider_s s_joy_haptic_slider;
|
||||||
|
static menuaction_s s_joy_gyro_action;
|
||||||
static menuaction_s s_joy_customize_buttons_action;
|
static menuaction_s s_joy_customize_buttons_action;
|
||||||
static menuaction_s s_joy_customize_alt_buttons_action;
|
static menuaction_s s_joy_customize_alt_buttons_action;
|
||||||
|
|
||||||
|
@ -1620,6 +1718,12 @@ CustomizeControllerAltButtonsFunc(void *unused)
|
||||||
M_Menu_ControllerAltButtons_f();
|
M_Menu_ControllerAltButtons_f();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ConfigGyroFunc(void *unused)
|
||||||
|
{
|
||||||
|
M_Menu_Gyro_f();
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
HapticMagnitudeFunc(void *unused)
|
HapticMagnitudeFunc(void *unused)
|
||||||
{
|
{
|
||||||
|
@ -1758,6 +1862,19 @@ Joy_MenuInit(void)
|
||||||
Menu_AddItem(&s_joy_menu, (void *)&s_joy_haptic_slider);
|
Menu_AddItem(&s_joy_menu, (void *)&s_joy_haptic_slider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gyro_hardware)
|
||||||
|
{
|
||||||
|
y += 10;
|
||||||
|
|
||||||
|
s_joy_gyro_action.generic.type = MTYPE_ACTION;
|
||||||
|
s_joy_gyro_action.generic.x = 0;
|
||||||
|
s_joy_gyro_action.generic.y = y;
|
||||||
|
y += 10;
|
||||||
|
s_joy_gyro_action.generic.name = "gyro calibration";
|
||||||
|
s_joy_gyro_action.generic.callback = ConfigGyroFunc;
|
||||||
|
Menu_AddItem(&s_joy_menu, (void *)&s_joy_gyro_action);
|
||||||
|
}
|
||||||
|
|
||||||
y += 10;
|
y += 10;
|
||||||
|
|
||||||
s_joy_customize_buttons_action.generic.type = MTYPE_ACTION;
|
s_joy_customize_buttons_action.generic.type = MTYPE_ACTION;
|
||||||
|
|
Loading…
Reference in a new issue