You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

176 lines
4.6 KiB

#include "controls/controller.h"
#include "controls/devices/kbcontroller.h"
#include "controls/devices/joystick.h"
#include "controls/devices/game_controller.h"
namespace dvl {
AxisDirection Controller::GetLeftStickOrDpadDirection(bool allow_dpad)
{
const float stickX = leftStickX;
const float stickY = leftStickY;
AxisDirection result { AxisDirectionX_NONE, AxisDirectionY_NONE };
if (stickY >= 0.5 || (allow_dpad && IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_UP))) {
result.y = AxisDirectionY_UP;
} else if (stickY <= -0.5 || (allow_dpad && IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_DOWN))) {
result.y = AxisDirectionY_DOWN;
}
if (stickX <= -0.5 || (allow_dpad && IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_LEFT))) {
result.x = AxisDirectionX_LEFT;
} else if (stickX >= 0.5 || (allow_dpad && IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_RIGHT))) {
result.x = AxisDirectionX_RIGHT;
}
return result;
}
void Controller::ScaleJoysticks()
{
const float rightDeadzone = 0.07;
const float leftDeadzone = 0.07;
if (leftStickNeedsScaling) {
leftStickX = leftStickXUnscaled;
leftStickY = leftStickYUnscaled;
ScaleJoystickAxes(&leftStickX, &leftStickY, leftDeadzone);
leftStickNeedsScaling = false;
}
if (rightStickNeedsScaling) {
rightStickX = rightStickXUnscaled;
rightStickY = rightStickYUnscaled;
ScaleJoystickAxes(&rightStickX, &rightStickY, rightDeadzone);
rightStickNeedsScaling = false;
}
}
void Controller::ScaleJoystickAxes(float *x, float *y, float deadzone)
{
//radial and scaled dead_zone
//http://www.third-helix.com/2013/04/12/doing-thumbstick-dead-zones-right.html
//input values go from -32767.0...+32767.0, output values are from -1.0 to 1.0;
if (deadzone == 0) {
return;
}
if (deadzone >= 1.0) {
*x = 0;
*y = 0;
return;
}
const float maximum = 32767.0f;
float analog_x = *x;
float analog_y = *y;
float dead_zone = deadzone * maximum;
float magnitude = std::sqrt(analog_x * analog_x + analog_y * analog_y);
if (magnitude >= dead_zone) {
// find scaled axis values with magnitudes between zero and maximum
float scalingFactor = 1.0 / magnitude * (magnitude - dead_zone) / (maximum - dead_zone);
analog_x = (analog_x * scalingFactor);
analog_y = (analog_y * scalingFactor);
// clamp to ensure results will never exceed the max_axis value
float clamping_factor = 1.0f;
float abs_analog_x = std::fabs(analog_x);
float abs_analog_y = std::fabs(analog_y);
if (abs_analog_x > 1.0 || abs_analog_y > 1.0) {
if (abs_analog_x > abs_analog_y) {
clamping_factor = 1 / abs_analog_x;
} else {
clamping_factor = 1 / abs_analog_y;
}
}
*x = (clamping_factor * analog_x);
*y = (clamping_factor * analog_y);
} else {
*x = 0;
*y = 0;
}
}
ControllerButtonEvent ToControllerButtonEvent(const SDL_Event &event)
{
ControllerButtonEvent result { ControllerButton_NONE, false };
switch (event.type) {
#ifndef USE_SDL1
case SDL_CONTROLLERBUTTONUP:
#endif
case SDL_JOYBUTTONUP:
case SDL_KEYUP:
result.up = true;
break;
default:
break;
}
#if HAS_KBCTRL == 1
KeyboardController *const keyboardController = KeyboardController::Get(event);
if (keyboardController != NULL) {
result.button = keyboardController->ToControllerButton(event);
if (result.button != ControllerButton_NONE)
return result;
}
#endif
#ifndef USE_SDL1
GameController *const controller = GameController::Get(event);
if (controller != NULL) {
result.button = controller->ToControllerButton(event);
if (result.button != ControllerButton_NONE)
return result;
}
#endif
const Joystick *const joystick = Joystick::Get(event);
if (joystick != NULL)
result.button = joystick->ToControllerButton(event);
return result;
}
bool IsControllerButtonPressed(ControllerButton button)
{
#ifndef USE_SDL1
if (GameController::IsPressedOnAnyController(button))
return true;
#endif
#if HAS_KBCTRL == 1
if (IsKbCtrlButtonPressed(button))
return true;
#endif
return Joystick::IsPressedOnAnyJoystick(button);
}
bool HandleControllerAddedOrRemovedEvent(const SDL_Event &event)
{
#ifndef USE_SDL1
switch (event.type) {
case SDL_CONTROLLERDEVICEADDED:
GameController::Add(event.cdevice.which);
break;
case SDL_CONTROLLERDEVICEREMOVED:
GameController::Remove(event.cdevice.which);
break;
case SDL_JOYDEVICEADDED:
Joystick::Add(event.jdevice.which);
break;
case SDL_JOYDEVICEREMOVED:
Joystick::Remove(event.jdevice.which);
break;
default:
return false;
}
return true;
#else
return false;
#endif
}
} // namespace dvl