mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2025-01-19 07:51:03 +00:00
commit
c6f6a17176
4 changed files with 478 additions and 42 deletions
|
@ -146,13 +146,6 @@ Set `0` by default.
|
||||||
during gameplay and released otherwise (in menu, videos, console or if
|
during gameplay and released otherwise (in menu, videos, console or if
|
||||||
game is paused).
|
game is paused).
|
||||||
|
|
||||||
* **in_sdlbackbutton**: Defines which button is used in the gamepad or
|
|
||||||
joystick as the `Esc` key, that is, to be able to access the menu
|
|
||||||
and 'cancel'/'go back' on its options. When set to `0` (the default)
|
|
||||||
the Back/Select/Minus button is used. Set this to `1` to use the
|
|
||||||
Start/Menu/Plus button, and to `2` to use the Guide/Home/PS button.
|
|
||||||
Requires a game restart when changed.
|
|
||||||
|
|
||||||
* **singleplayer**: Only available in the dedicated server. Vanilla
|
* **singleplayer**: Only available in the dedicated server. Vanilla
|
||||||
Quake II enforced that either `coop` or `deathmatch` is set to `1`
|
Quake II enforced that either `coop` or `deathmatch` is set to `1`
|
||||||
when running the dedicated server. That made it impossible to play
|
when running the dedicated server. That made it impossible to play
|
||||||
|
@ -467,6 +460,34 @@ Set `0` by default.
|
||||||
|
|
||||||
* **sw_colorlight**: enable experimental color lighting.
|
* **sw_colorlight**: enable experimental color lighting.
|
||||||
|
|
||||||
|
|
||||||
|
## Game Controller
|
||||||
|
|
||||||
|
* **in_sdlbackbutton**: Defines which button is used in the gamepad or
|
||||||
|
joystick as the `Esc` key, to access the main menu and 'cancel' /
|
||||||
|
'go back' on its options. Default is `0`, which corresponds to the
|
||||||
|
Back/Select/Minus button. Set to `1` to use Start/Menu/Plus, and to
|
||||||
|
`2` to use the Guide/Home/PS button. Requires a game restart
|
||||||
|
(or controller replug) when changed.
|
||||||
|
|
||||||
|
* **gyro_mode**: Operation mode for the gyroscope sensor of the game
|
||||||
|
controller. Options are `0` = always off, `1` = off with the
|
||||||
|
`+gyroaction` bind to enable, `2` = on with `+gyroaction` to
|
||||||
|
disable (default), `3` = always on.
|
||||||
|
|
||||||
|
* **gyro_turning_axis**: Sets which gyro axis will be used for turning.
|
||||||
|
The default `0` is "yaw" (turn), for people who prefer to hold their
|
||||||
|
controller flat, like using a pointing device. `1` is "roll" (lean),
|
||||||
|
for people who hold the controller upright, or use a device with the
|
||||||
|
controller attached to the screen, e.g. Steam Deck.
|
||||||
|
|
||||||
|
* **gyro_calibration_(x/y/z)**: Offset values on each axis of the gyro
|
||||||
|
which helps it reach true "zero movement", complete stillness. These
|
||||||
|
values are wrong if you see your in-game view "drift" when leaving
|
||||||
|
the controller alone. As these vary by device, it's better to use
|
||||||
|
'calibrate' in the 'gamepad' -> 'gyro' menu to set them.
|
||||||
|
|
||||||
|
|
||||||
## cvar operations
|
## cvar operations
|
||||||
|
|
||||||
cvar operations are special commands that allow the programmatic
|
cvar operations are special commands that allow the programmatic
|
||||||
|
|
|
@ -301,6 +301,10 @@ extern cvar_t *joy_pitchsensitivity;
|
||||||
extern cvar_t *joy_forwardsensitivity;
|
extern cvar_t *joy_forwardsensitivity;
|
||||||
extern cvar_t *joy_sidesensitivity;
|
extern cvar_t *joy_sidesensitivity;
|
||||||
extern cvar_t *joy_upsensitivity;
|
extern cvar_t *joy_upsensitivity;
|
||||||
|
extern cvar_t *gyro_mode;
|
||||||
|
extern cvar_t *gyro_turning_axis;
|
||||||
|
extern cvar_t *gyro_yawsensitivity;
|
||||||
|
extern cvar_t *gyro_pitchsensitivity;
|
||||||
extern cvar_t *m_pitch;
|
extern cvar_t *m_pitch;
|
||||||
extern cvar_t *m_yaw;
|
extern cvar_t *m_yaw;
|
||||||
extern cvar_t *m_forward;
|
extern cvar_t *m_forward;
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
|
@ -43,6 +43,15 @@
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
REASON_NONE,
|
||||||
|
REASON_CONTROLLERINIT,
|
||||||
|
REASON_GYROCALIBRATION
|
||||||
|
} updates_countdown_reasons;
|
||||||
|
|
||||||
|
// ----
|
||||||
|
|
||||||
// These are used to communicate the events collected by
|
// These are used to communicate the events collected by
|
||||||
// IN_Update() called at the beginning of a frame to the
|
// IN_Update() called at the beginning of a frame to the
|
||||||
// actual movement functions called at a later time.
|
// actual movement functions called at a later time.
|
||||||
|
@ -51,6 +60,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 +140,42 @@ static cvar_t *joy_axis_triggerright_threshold;
|
||||||
// Joystick haptic
|
// Joystick haptic
|
||||||
static cvar_t *joy_haptic_magnitude;
|
static cvar_t *joy_haptic_magnitude;
|
||||||
|
|
||||||
// Support for hot plugging of game controller
|
// Gyro mode (0=off, 3=on, 1-2=uses button to enable/disable)
|
||||||
|
cvar_t *gyro_mode;
|
||||||
|
cvar_t *gyro_turning_axis; // yaw or roll
|
||||||
|
|
||||||
|
// Gyro sensitivity
|
||||||
|
cvar_t *gyro_yawsensitivity;
|
||||||
|
cvar_t *gyro_pitchsensitivity;
|
||||||
|
|
||||||
|
// Gyro availability
|
||||||
|
qboolean gyro_hardware = false;
|
||||||
|
|
||||||
|
// Gyro is being used in this very moment
|
||||||
|
static qboolean gyro_active = false;
|
||||||
|
|
||||||
|
// Gyro calibration
|
||||||
|
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;
|
||||||
|
|
||||||
|
// To ignore SDL_JOYDEVICEADDED at game init. Allows for hot plugging of game controller afterwards.
|
||||||
static qboolean first_init = true;
|
static qboolean first_init = true;
|
||||||
static int init_delay = 30;
|
|
||||||
|
// Countdown of calls to IN_Update(), needed for controller init and gyro calibration
|
||||||
|
static unsigned int updates_countdown = 30;
|
||||||
|
|
||||||
|
// Reason for the countdown
|
||||||
|
static updates_countdown_reasons countdown_reason = REASON_CONTROLLERINIT;
|
||||||
|
|
||||||
|
// 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 / M_PI; // can change depending on hardware
|
||||||
|
|
||||||
|
extern void CalibrationFinishedCallback(void);
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
@ -187,7 +230,6 @@ IN_TranslateSDLtoQ2Key(unsigned int keysym)
|
||||||
key = K_RIGHTARROW;
|
key = K_RIGHTARROW;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case SDLK_RALT:
|
case SDLK_RALT:
|
||||||
case SDLK_LALT:
|
case SDLK_LALT:
|
||||||
key = K_ALT;
|
key = K_ALT;
|
||||||
|
@ -265,7 +307,6 @@ IN_TranslateSDLtoQ2Key(unsigned int keysym)
|
||||||
key = K_F15;
|
key = K_F15;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case SDLK_KP_7:
|
case SDLK_KP_7:
|
||||||
key = K_KP_HOME;
|
key = K_KP_HOME;
|
||||||
break;
|
break;
|
||||||
|
@ -778,6 +819,41 @@ 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 (countdown_reason == REASON_GYROCALIBRATION && updates_countdown)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
if (!gyro_turning_axis->value)
|
||||||
|
{
|
||||||
|
gyro_yaw = event.csensor.data[1] - gyro_calibration_y->value; // yaw
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gyro_yaw = -(event.csensor.data[2] - gyro_calibration_z->value); // roll
|
||||||
|
}
|
||||||
|
gyro_yaw *= gyro_yawsensitivity->value * cl_yawspeed->value;
|
||||||
|
gyro_pitch = (event.csensor.data[0] - gyro_calibration_x->value)
|
||||||
|
* gyro_pitchsensitivity->value * cl_pitchspeed->value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif // SDL_VERSION_ATLEAST(2, 0, 16)
|
||||||
|
|
||||||
case SDL_CONTROLLERDEVICEREMOVED:
|
case SDL_CONTROLLERDEVICEREMOVED:
|
||||||
if (!controller)
|
if (!controller)
|
||||||
{
|
{
|
||||||
|
@ -793,7 +869,8 @@ 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;
|
updates_countdown = 100;
|
||||||
|
countdown_reason = REASON_CONTROLLERINIT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -825,20 +902,42 @@ 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 (updates_countdown)
|
||||||
{
|
{
|
||||||
init_delay--;
|
updates_countdown--;
|
||||||
if (!init_delay)
|
if (!updates_countdown) // Countdown finished, apply needed action by reason
|
||||||
{
|
{
|
||||||
if (!first_init)
|
switch (countdown_reason)
|
||||||
{
|
{
|
||||||
IN_Controller_Shutdown(false);
|
case REASON_CONTROLLERINIT:
|
||||||
IN_Controller_Init(true);
|
if (!first_init)
|
||||||
}
|
{
|
||||||
else
|
IN_Controller_Shutdown(false);
|
||||||
{
|
IN_Controller_Init(true);
|
||||||
first_init = false;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
first_init = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REASON_GYROCALIBRATION: // finish and save calibration
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
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();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break; // avoiding compiler warning
|
||||||
}
|
}
|
||||||
|
countdown_reason = REASON_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -931,7 +1030,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 +1058,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 +1103,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 +1370,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;
|
||||||
|
updates_countdown = 300;
|
||||||
|
countdown_reason = REASON_GYROCALIBRATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean
|
||||||
|
IsCalibrationZero(void)
|
||||||
|
{
|
||||||
|
return (!gyro_calibration_x->value && !gyro_calibration_y->value && !gyro_calibration_z->value);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Game Controller
|
* Game Controller
|
||||||
*/
|
*/
|
||||||
|
@ -1373,6 +1530,35 @@ 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);
|
||||||
|
|
||||||
|
#ifndef _WIN32 // Switch controllers behave differently on Linux & Mac, so sensitivity has to be readjusted
|
||||||
|
if (gyro_data_rate <= 200.0f)
|
||||||
|
{
|
||||||
|
normalize_sdl_gyro = 1.0f / 4.5f;
|
||||||
|
}
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
|
gyro_hardware = true;
|
||||||
|
Com_Printf("Gyro sensor enabled at %.2f Hz\n", gyro_data_rate);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Com_Printf("Gyro sensor not found.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( SDL_GameControllerHasLED(controller) )
|
||||||
|
{
|
||||||
|
SDL_GameControllerSetLED(controller, 0, 80, 0); // green light
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SDL_VERSION_ATLEAST(2, 0, 16)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1388,6 +1574,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 +1611,20 @@ 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_yawsensitivity = Cvar_Get("gyro_yawsensitivity", "1.0", CVAR_ARCHIVE);
|
||||||
|
gyro_pitchsensitivity = Cvar_Get("gyro_pitchsensitivity", "1.0", CVAR_ARCHIVE);
|
||||||
|
gyro_turning_axis = Cvar_Get("gyro_turning_axis", "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 +1632,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 +1670,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 / M_PI;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1478,6 +1684,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);
|
||||||
|
|
|
@ -86,6 +86,22 @@ typedef struct
|
||||||
menulayer_t m_layers[MAX_MENU_DEPTH];
|
menulayer_t m_layers[MAX_MENU_DEPTH];
|
||||||
int m_menudepth;
|
int m_menudepth;
|
||||||
|
|
||||||
|
static float
|
||||||
|
ClampCvar(float min, float max, float value)
|
||||||
|
{
|
||||||
|
if (value < min)
|
||||||
|
{
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value > max)
|
||||||
|
{
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
static qboolean
|
static qboolean
|
||||||
M_IsGame(const char *gamename)
|
M_IsGame(const char *gamename)
|
||||||
{
|
{
|
||||||
|
@ -1294,6 +1310,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])
|
||||||
|
@ -1596,6 +1613,184 @@ 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 menulist_s s_gyro_mode_box;
|
||||||
|
static menulist_s s_turning_axis_box;
|
||||||
|
static menuslider_s s_gyro_yawsensitivity_slider;
|
||||||
|
static menuslider_s s_gyro_pitchsensitivity_slider;
|
||||||
|
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
|
||||||
|
GyroModeFunc(void *unused)
|
||||||
|
{
|
||||||
|
Cvar_SetValue("gyro_mode", (int)s_gyro_mode_box.curvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
TurningAxisFunc(void *unused)
|
||||||
|
{
|
||||||
|
Cvar_SetValue("gyro_turning_axis", (int)s_turning_axis_box.curvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
GyroYawSensitivityFunc(void *unused)
|
||||||
|
{
|
||||||
|
Cvar_SetValue("gyro_yawsensitivity", s_gyro_yawsensitivity_slider.curvalue / 10.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
GyroPitchSensitivityFunc(void *unused)
|
||||||
|
{
|
||||||
|
Cvar_SetValue("gyro_pitchsensitivity", s_gyro_pitchsensitivity_slider.curvalue / 10.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Gyro_MenuInit(void)
|
||||||
|
{
|
||||||
|
static const char *gyro_modes[] =
|
||||||
|
{
|
||||||
|
"always off",
|
||||||
|
"off, button enables",
|
||||||
|
"on, button disables",
|
||||||
|
"always on",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *axis_choices[] =
|
||||||
|
{
|
||||||
|
"yaw (turn)",
|
||||||
|
"roll (lean)",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
int y = 0;
|
||||||
|
float scale = SCR_GetMenuScale();
|
||||||
|
|
||||||
|
s_gyro_menu.x = (int)(viddef.width * 0.50f);
|
||||||
|
s_gyro_menu.nitems = 0;
|
||||||
|
|
||||||
|
s_gyro_mode_box.generic.type = MTYPE_SPINCONTROL;
|
||||||
|
s_gyro_mode_box.generic.x = 0;
|
||||||
|
s_gyro_mode_box.generic.y = y;
|
||||||
|
s_gyro_mode_box.generic.name = "gyro mode";
|
||||||
|
s_gyro_mode_box.generic.callback = GyroModeFunc;
|
||||||
|
s_gyro_mode_box.itemnames = gyro_modes;
|
||||||
|
s_gyro_mode_box.curvalue = ClampCvar(0, 3, gyro_mode->value);
|
||||||
|
|
||||||
|
s_turning_axis_box.generic.type = MTYPE_SPINCONTROL;
|
||||||
|
s_turning_axis_box.generic.x = 0;
|
||||||
|
s_turning_axis_box.generic.y = (y += 10);
|
||||||
|
s_turning_axis_box.generic.name = "turning axis";
|
||||||
|
s_turning_axis_box.generic.callback = TurningAxisFunc;
|
||||||
|
s_turning_axis_box.itemnames = axis_choices;
|
||||||
|
s_turning_axis_box.curvalue = ClampCvar(0, 1, gyro_turning_axis->value);
|
||||||
|
|
||||||
|
s_gyro_yawsensitivity_slider.generic.type = MTYPE_SLIDER;
|
||||||
|
s_gyro_yawsensitivity_slider.generic.x = 0;
|
||||||
|
s_gyro_yawsensitivity_slider.generic.y = (y += 20);
|
||||||
|
s_gyro_yawsensitivity_slider.generic.name = "yaw sensitivity";
|
||||||
|
s_gyro_yawsensitivity_slider.generic.callback = GyroYawSensitivityFunc;
|
||||||
|
s_gyro_yawsensitivity_slider.minvalue = 1;
|
||||||
|
s_gyro_yawsensitivity_slider.maxvalue = 80;
|
||||||
|
s_gyro_yawsensitivity_slider.curvalue = gyro_yawsensitivity->value * 10;
|
||||||
|
|
||||||
|
s_gyro_pitchsensitivity_slider.generic.type = MTYPE_SLIDER;
|
||||||
|
s_gyro_pitchsensitivity_slider.generic.x = 0;
|
||||||
|
s_gyro_pitchsensitivity_slider.generic.y = (y += 10);
|
||||||
|
s_gyro_pitchsensitivity_slider.generic.name = "pitch sensitivity";
|
||||||
|
s_gyro_pitchsensitivity_slider.generic.callback = GyroPitchSensitivityFunc;
|
||||||
|
s_gyro_pitchsensitivity_slider.minvalue = 1;
|
||||||
|
s_gyro_pitchsensitivity_slider.maxvalue = 80;
|
||||||
|
s_gyro_pitchsensitivity_slider.curvalue = gyro_pitchsensitivity->value * 10;
|
||||||
|
|
||||||
|
s_calibrating_text[0].generic.type = MTYPE_SEPARATOR;
|
||||||
|
s_calibrating_text[0].generic.x = 48 * scale + 30;
|
||||||
|
s_calibrating_text[0].generic.y = (y += 20);
|
||||||
|
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_gyro_mode_box);
|
||||||
|
Menu_AddItem(&s_gyro_menu, (void *)&s_turning_axis_box);
|
||||||
|
Menu_AddItem(&s_gyro_menu, (void *)&s_gyro_yawsensitivity_slider);
|
||||||
|
Menu_AddItem(&s_gyro_menu, (void *)&s_gyro_pitchsensitivity_slider);
|
||||||
|
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
|
||||||
*/
|
*/
|
||||||
|
@ -1606,6 +1801,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;
|
||||||
|
|
||||||
|
@ -1621,6 +1817,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)
|
||||||
{
|
{
|
||||||
|
@ -1759,6 +1961,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 options";
|
||||||
|
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;
|
||||||
|
@ -1857,22 +2072,6 @@ MouseSpeedFunc(void *unused)
|
||||||
Cvar_SetValue("sensitivity", s_options_sensitivity_slider.curvalue / 2.0F);
|
Cvar_SetValue("sensitivity", s_options_sensitivity_slider.curvalue / 2.0F);
|
||||||
}
|
}
|
||||||
|
|
||||||
static float
|
|
||||||
ClampCvar(float min, float max, float value)
|
|
||||||
{
|
|
||||||
if (value < min)
|
|
||||||
{
|
|
||||||
return min;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value > max)
|
|
||||||
{
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ControlsSetMenuItemValues(void)
|
ControlsSetMenuItemValues(void)
|
||||||
{
|
{
|
||||||
|
@ -5525,6 +5724,7 @@ M_Init(void)
|
||||||
Cmd_AddCommand("menu_options", M_Menu_Options_f);
|
Cmd_AddCommand("menu_options", M_Menu_Options_f);
|
||||||
Cmd_AddCommand("menu_keys", M_Menu_Keys_f);
|
Cmd_AddCommand("menu_keys", M_Menu_Keys_f);
|
||||||
Cmd_AddCommand("menu_joy", M_Menu_Joy_f);
|
Cmd_AddCommand("menu_joy", M_Menu_Joy_f);
|
||||||
|
Cmd_AddCommand("menu_gyro", M_Menu_Gyro_f);
|
||||||
Cmd_AddCommand("menu_buttons", M_Menu_ControllerButtons_f);
|
Cmd_AddCommand("menu_buttons", M_Menu_ControllerButtons_f);
|
||||||
Cmd_AddCommand("menu_altbuttons", M_Menu_ControllerAltButtons_f);
|
Cmd_AddCommand("menu_altbuttons", M_Menu_ControllerAltButtons_f);
|
||||||
Cmd_AddCommand("menu_quit", M_Menu_Quit_f);
|
Cmd_AddCommand("menu_quit", M_Menu_Quit_f);
|
||||||
|
|
Loading…
Reference in a new issue