#include "client.h"
#include <GLFW/glfw3.h>
extern unsigned sys_msg_time;
extern GLFWwindow *glfw_window;
#define JOY_ABSOLUTE_AXIS 0x00000000
#define JOY_RELATIVE_AXIS 0x00000010
#define JOY_MAX_AXES 6
#define JOY_AXIS_X 0
#define JOY_AXIS_Y 1
#define JOY_AXIS_Z 2
#define JOY_AXIS_R 3
#define JOY_AXIS_U 4
#define JOY_AXIS_V 5
enum _ControlList { AxisNada = 0, AxisForward, AxisLook, AxisSide, AxisTurn, AxisUp };
int dwAxisFlags[JOY_MAX_AXES];
int dwAxisMap[JOY_MAX_AXES];
int dwControlMap[JOY_MAX_AXES];
int pdwRawValue[JOY_MAX_AXES];
cvar_t *in_mouse;
cvar_t *in_joystick;
cvar_t *joy_name;
cvar_t *joy_advanced;
cvar_t *joy_advaxisx;
cvar_t *joy_advaxisy;
cvar_t *joy_advaxisz;
cvar_t *joy_advaxisr;
cvar_t *joy_advaxisu;
cvar_t *joy_advaxisv;
cvar_t *joy_forwardthreshold;
cvar_t *joy_sidethreshold;
cvar_t *joy_pitchthreshold;
cvar_t *joy_yawthreshold;
cvar_t *joy_forwardsensitivity;
cvar_t *joy_sidesensitivity;
cvar_t *joy_pitchsensitivity;
cvar_t *joy_yawsensitivity;
cvar_t *joy_upthreshold;
cvar_t *joy_upsensitivity;
bool joy_avail, joy_advancedinit, joy_haspov;
unsigned int joy_oldbuttonstate, joy_oldpovstate;
int joy_id;
unsigned int joy_flags;
int joy_numbuttons;
bool in_appactive;
extern bool ActiveApp;
void IN_StartupJoystick(void);
void IN_JoyMove(usercmd_t *cmd);
cvar_t *m_filter;
bool mlooking;
void IN_MLookDown(void) { mlooking = true; }
void IN_MLookUp(void) {
mlooking = false;
if(!freelook->value && lookspring->value)
IN_CenterView();
}
int mouse_buttons;
int mouse_oldbuttonstate;
int mouse_x, mouse_y, old_mouse_x, old_mouse_y, mx_accum, my_accum;
bool mouseactive;
bool restore_spi;
bool mouseinitialized;
void IN_ActivateMouse(void) {
if(!mouseinitialized)
return;
if(!in_mouse->value) {
mouseactive = false;
return;
}
if(mouseactive)
return;
mouseactive = true;
if(glfwRawMouseMotionSupported())
glfwSetInputMode(glfw_window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
glfwSetInputMode(glfw_window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
}
void IN_DeactivateMouse(void) {
if(!mouseinitialized)
return;
if(!mouseactive)
return;
mouseactive = false;
glfwSetInputMode(glfw_window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
void IN_StartupMouse(void) {
cvar_t *cv;
cv = Cvar_Get("in_initmouse", "1", CVAR_NOSET);
if(!cv->value)
return;
mouseinitialized = true;
mouse_buttons = 3;
}
void IN_MouseMove(usercmd_t *cmd) {
static double omx, omy;
double mx, my, temp;
if(!mouseactive)
return;
glfwGetCursorPos(glfw_window, &mx, &my);
temp = mx - omx;
omx = mx;
mx = temp;
temp = my - omy;
omy = my;
my = temp;
if(m_filter->value) {
mouse_x = (mx + old_mouse_x) * 0.5;
mouse_y = (my + old_mouse_y) * 0.5;
} else {
mouse_x = mx;
mouse_y = my;
}
old_mouse_x = mx;
old_mouse_y = my;
mouse_x *= sensitivity->value;
mouse_y *= sensitivity->value;
if((in_strafe.state & 1) || (lookstrafe->value && mlooking))
cmd->sidemove += m_side->value * mouse_x;
else
cl.viewangles[YAW] -= m_yaw->value * mouse_x;
if((mlooking || freelook->value) && !(in_strafe.state & 1)) {
cl.viewangles[PITCH] += m_pitch->value * mouse_y;
} else {
cmd->forwardmove -= m_forward->value * mouse_y;
}
}
cvar_t *v_centermove;
cvar_t *v_centerspeed;
void IN_Init(void) {
m_filter = Cvar_Get("m_filter", "0", 0);
in_mouse = Cvar_Get("in_mouse", "1", CVAR_ARCHIVE);
in_joystick = Cvar_Get("in_joystick", "0", CVAR_ARCHIVE);
joy_name = Cvar_Get("joy_name", "joystick", 0);
joy_advanced = Cvar_Get("joy_advanced", "0", 0);
joy_advaxisx = Cvar_Get("joy_advaxisx", "0", 0);
joy_advaxisy = Cvar_Get("joy_advaxisy", "0", 0);
joy_advaxisz = Cvar_Get("joy_advaxisz", "0", 0);
joy_advaxisr = Cvar_Get("joy_advaxisr", "0", 0);
joy_advaxisu = Cvar_Get("joy_advaxisu", "0", 0);
joy_advaxisv = Cvar_Get("joy_advaxisv", "0", 0);
joy_forwardthreshold = Cvar_Get("joy_forwardthreshold", "0.15", 0);
joy_sidethreshold = Cvar_Get("joy_sidethreshold", "0.15", 0);
joy_upthreshold = Cvar_Get("joy_upthreshold", "0.15", 0);
joy_pitchthreshold = Cvar_Get("joy_pitchthreshold", "0.15", 0);
joy_yawthreshold = Cvar_Get("joy_yawthreshold", "0.15", 0);
joy_forwardsensitivity = Cvar_Get("joy_forwardsensitivity", "-1", 0);
joy_sidesensitivity = Cvar_Get("joy_sidesensitivity", "-1", 0);
joy_upsensitivity = Cvar_Get("joy_upsensitivity", "-1", 0);
joy_pitchsensitivity = Cvar_Get("joy_pitchsensitivity", "1", 0);
joy_yawsensitivity = Cvar_Get("joy_yawsensitivity", "-1", 0);
v_centermove = Cvar_Get("v_centermove", "0.15", 0);
v_centerspeed = Cvar_Get("v_centerspeed", "500", 0);
Cmd_AddCommand("+mlook", IN_MLookDown);
Cmd_AddCommand("-mlook", IN_MLookUp);
IN_StartupMouse();
IN_StartupJoystick();
}
void IN_Shutdown(void) { IN_DeactivateMouse(); }
void IN_Activate(bool active) {
in_appactive = active;
mouseactive = !active; }
void IN_Frame(void) {
if(!mouseinitialized)
return;
if(!in_mouse || !in_appactive) {
IN_DeactivateMouse();
return;
}
if(!cl.refresh_prepped || cls.key_dest == key_console || cls.key_dest == key_menu) {
if(Cvar_VariableValue("vid_fullscreen") == 0) {
IN_DeactivateMouse();
return;
}
}
IN_ActivateMouse();
}
void IN_Move(usercmd_t *cmd) {
IN_MouseMove(cmd);
if(ActiveApp)
IN_JoyMove(cmd);
}
void IN_ClearStates(void) {
mx_accum = 0;
my_accum = 0;
mouse_oldbuttonstate = 0;
}
void IN_StartupJoystick(void) {
cvar_t *cv;
joy_avail = false;
cv = Cvar_Get("in_initjoy", "1", CVAR_NOSET);
if(!cv->value)
return;
for(joy_id = 0; joy_id < GLFW_JOYSTICK_LAST; joy_id++) {
if(glfwJoystickPresent(GLFW_JOYSTICK_1 + joy_id))
break;
}
if(joy_id >= GLFW_JOYSTICK_LAST) {
Com_Printf("\njoystick not found -- no valid joysticks\n\n");
return;
}
glfwGetJoystickButtons(joy_id, &joy_numbuttons);
int hats;
glfwGetJoystickHats(joy_id, &hats);
joy_haspov = hats > 0;
joy_oldbuttonstate = joy_oldpovstate = 0;
joy_avail = true;
Com_Printf("\njoystick detected\n\n");
}
void IN_Commands(void) {
int i, key_index;
int buttonstate, povstate;
if(!joy_avail) {
return;
}
int num_buttons;
const unsigned char *buttons = glfwGetJoystickButtons(joy_id, &num_buttons);
buttonstate = 0;
for(i = 0; i < joy_numbuttons; i++) {
if(buttons[i] == GLFW_PRESS)
buttonstate |= (1 << i);
if((buttonstate & (1 << i)) && !(joy_oldbuttonstate & (1 << i))) {
key_index = (i < 4) ? K_JOY1 : K_AUX1;
Key_Event(key_index + i, true, 0);
}
if(!(buttonstate & (1 << i)) && (joy_oldbuttonstate & (1 << i))) {
key_index = (i < 4) ? K_JOY1 : K_AUX1;
Key_Event(key_index + i, false, 0);
}
}
joy_oldbuttonstate = buttonstate;
if(joy_haspov) {
int num_hats;
const unsigned char *hats = glfwGetJoystickHats(joy_id, &num_hats);
povstate = 0;
if(hats[0] != 0) {
if(hats[0] & GLFW_HAT_UP)
povstate |= 0x01;
if(hats[0] & GLFW_HAT_RIGHT)
povstate |= 0x02;
if(hats[0] & GLFW_HAT_DOWN)
povstate |= 0x04;
if(hats[0] & GLFW_HAT_LEFT)
povstate |= 0x08;
}
for(i = 0; i < 4; i++) {
if((povstate & (1 << i)) && !(joy_oldpovstate & (1 << i))) {
Key_Event(K_AUX29 + i, true, 0);
}
if(!(povstate & (1 << i)) && (joy_oldpovstate & (1 << i))) {
Key_Event(K_AUX29 + i, false, 0);
}
}
joy_oldpovstate = povstate;
}
}
void IN_JoyMove(usercmd_t *cmd) {
float speed, aspeed;
float fAxisValue;
int i;
if(!joy_avail || !in_joystick->value) {
return;
}
int num_axis;
const float *axes = glfwGetJoystickAxes(joy_id, &num_axis);
if((in_speed.state & 1) ^ (int)cl_run->value)
speed = 2;
else
speed = 1;
aspeed = speed * cls.frametime;
for(i = 0; i < num_axis; i++) {
fAxisValue = axes[i];
switch(dwAxisMap[i]) {
case AxisForward:
if((joy_advanced->value == 0.0) && mlooking) {
if(fabs(fAxisValue) > joy_pitchthreshold->value) {
if(m_pitch->value < 0.0) {
cl.viewangles[PITCH] -= (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value;
} else {
cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value;
}
}
} else {
if(fabs(fAxisValue) > joy_forwardthreshold->value) {
cmd->forwardmove += (fAxisValue * joy_forwardsensitivity->value) * speed * cl_forwardspeed->value;
}
}
break;
case AxisSide:
if(fabs(fAxisValue) > joy_sidethreshold->value) {
cmd->sidemove += (fAxisValue * joy_sidesensitivity->value) * speed * cl_sidespeed->value;
}
break;
case AxisUp:
if(fabs(fAxisValue) > joy_upthreshold->value) {
cmd->upmove += (fAxisValue * joy_upsensitivity->value) * speed * cl_upspeed->value;
}
break;
case AxisTurn:
if((in_strafe.state & 1) || (lookstrafe->value && mlooking)) {
if(fabs(fAxisValue) > joy_sidethreshold->value) {
cmd->sidemove -= (fAxisValue * joy_sidesensitivity->value) * speed * cl_sidespeed->value;
}
} else {
if(fabs(fAxisValue) > joy_yawthreshold->value) {
if(dwControlMap[i] == JOY_ABSOLUTE_AXIS) {
cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity->value) * aspeed * cl_yawspeed->value;
} else {
cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity->value) * speed * 180.0;
}
}
}
break;
case AxisLook:
if(mlooking) {
if(fabs(fAxisValue) > joy_pitchthreshold->value) {
if(dwControlMap[i] == JOY_ABSOLUTE_AXIS) {
cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value;
} else {
cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * speed * 180.0;
}
}
}
break;
default:
break;
}
}
}