diff --git a/Nuklear-XboxOG/input_manager.cpp b/Nuklear-XboxOG/input_manager.cpp index 7570340..da216e1 100644 --- a/Nuklear-XboxOG/input_manager.cpp +++ b/Nuklear-XboxOG/input_manager.cpp @@ -1,13 +1,18 @@ #include "input_manager.h" #include "graphics.h" #include "math.h" +#include "debug.h" namespace { bool mInitialized = false; + HANDLE mControllerHandles[XGetPortCount()]; + DWORD mControllerLastPacketNumber[XGetPortCount()]; + ControllerState mControllerStatesCurrent[XGetPortCount()]; + ControllerState mControllerStatesPrevious[XGetPortCount()]; + HANDLE mMouseHandles[XGetPortCount()]; - XINPUT_STATE mMouseInputStates[XGetPortCount()]; DWORD mMouseLastPacketNumber[XGetPortCount()]; MouseState mMouseStatesCurrent[XGetPortCount()]; MouseState mMouseStatesPrevious[XGetPortCount()]; @@ -20,8 +25,12 @@ void input_manager::init() { XInitDevices(0, 0); + memset(mControllerHandles, 0, sizeof(mControllerHandles)); + memset(mControllerLastPacketNumber, 0, sizeof(mControllerLastPacketNumber)); + memset(mControllerStatesCurrent, 0, sizeof(mControllerStatesCurrent)); + memset(mControllerStatesPrevious, 0, sizeof(mControllerStatesPrevious)); + memset(mMouseHandles, 0, sizeof(mMouseHandles)); - memset(mMouseInputStates, 0, sizeof(mMouseInputStates)); memset(mMouseLastPacketNumber, 0, sizeof(mMouseLastPacketNumber)); memset(mMouseStatesCurrent, 0, sizeof(mMouseStatesCurrent)); memset(mMouseStatesPrevious, 0, sizeof(mMouseStatesPrevious)); @@ -37,6 +46,100 @@ void input_manager::init() XInputDebugInitKeyboardQueue(&keyboardSettings); } +void input_manager::process_controller() +{ + DWORD insertions = 0; + DWORD removals = 0; + if (XGetDeviceChanges(XDEVICE_TYPE_GAMEPAD, &insertions, &removals) == TRUE) + { + for (int i = 0; i < XGetPortCount(); i++) + { + if ((insertions & 1) == 1) + { + mControllerHandles[i] = XInputOpen(XDEVICE_TYPE_GAMEPAD, i, XDEVICE_NO_SLOT, NULL); + } + if ((removals & 1) == 1) + { + XInputClose(mControllerHandles[i]); + mControllerHandles[i] = NULL; + } + insertions = insertions >> 1; + removals = removals >> 1; + } + } + + for (int i = 0; i < XGetPortCount(); i++) + { + XINPUT_STATE controllerInputState; + if (mControllerHandles[i] == NULL || XInputGetState(mControllerHandles[i], &controllerInputState) != 0) + { + continue; + } + + if (mControllerLastPacketNumber[i] != controllerInputState.dwPacketNumber) + { + memcpy(&mControllerStatesPrevious[i], &mControllerStatesCurrent[i], sizeof(ControllerState)); + mControllerStatesCurrent[i].buttons[CONTROLLER_A_BUTTON] = controllerInputState.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_A] > 32; + mControllerStatesCurrent[i].buttons[CONTROLLER_B_BUTTON] = controllerInputState.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_B] > 32; + mControllerStatesCurrent[i].buttons[CONTROLLER_X_BUTTON] = controllerInputState.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_X] > 32; + mControllerStatesCurrent[i].buttons[CONTROLLER_Y_BUTTON] = controllerInputState.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_Y] > 32; + mControllerStatesCurrent[i].buttons[CONTROLLER_BLACK_BUTTON] = controllerInputState.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_BLACK] > 32; + mControllerStatesCurrent[i].buttons[CONTROLLER_WHITE_BUTTON] = controllerInputState.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_WHITE] > 32; + mControllerStatesCurrent[i].buttons[CONTROLLER_LTRIGGER_BUTTON] = controllerInputState.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER] > 32; + mControllerStatesCurrent[i].buttons[CONTROLLER_RTRIGGER_BUTTON] = controllerInputState.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER] > 32; + mControllerStatesCurrent[i].buttons[CONTROLLER_DPAD_UP_BUTTON] = (controllerInputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) != 0; + mControllerStatesCurrent[i].buttons[CONTROLLER_DPAD_DOWN_BUTTON] = (controllerInputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) != 0; + mControllerStatesCurrent[i].buttons[CONTROLLER_DPAD_LEFT_BUTTON] = (controllerInputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) != 0; + mControllerStatesCurrent[i].buttons[CONTROLLER_DPAD_RIGHT_BUTTON] = (controllerInputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) != 0; + mControllerStatesCurrent[i].buttons[CONTROLLER_START_BUTTON] = (controllerInputState.Gamepad.wButtons & XINPUT_GAMEPAD_START) != 0; + mControllerStatesCurrent[i].buttons[CONTROLLER_BACK_BUTTON] = (controllerInputState.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) != 0; + mControllerStatesCurrent[i].buttons[CONTROLLER_LTHUMB_BUTTON] = (controllerInputState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) != 0; + mControllerStatesCurrent[i].buttons[CONTROLLER_RTHUMB_BUTTON] = (controllerInputState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) != 0; + + const float sensitivity = 10.0f; + const float acceleration = 1.6f; + const float friction = 0.85f; + const float maxSpeed = 15.0f; + const float deadzone = 0.25f; + + float lx = controllerInputState.Gamepad.sThumbLX / 32768.0f; + float ly = -(controllerInputState.Gamepad.sThumbLY / 32768.0f); + float rx = controllerInputState.Gamepad.sThumbRX / 32768.0f; + float ry = -(controllerInputState.Gamepad.sThumbRY / 32768.0f); + + lx = fabsf(lx) < deadzone ? 0 : (lx - math::copy_sign(deadzone, lx)) / (1.0f - deadzone); + ly = fabsf(ly) < deadzone ? 0 : (ly - math::copy_sign(deadzone, ly)) / (1.0f - deadzone); + rx = fabsf(rx) < deadzone ? 0 : (rx - math::copy_sign(deadzone, rx)) / (1.0f - deadzone); + ry = fabsf(ry) < deadzone ? 0 : (ry - math::copy_sign(deadzone, ry)) / (1.0f - deadzone); + + mControllerStatesCurrent[i].velocity_left_x = (mControllerStatesPrevious[i].velocity_left_x + lx * acceleration) * friction; + mControllerStatesCurrent[i].velocity_left_y = (mControllerStatesPrevious[i].velocity_left_y + ly * acceleration) * friction; + mControllerStatesCurrent[i].velocity_left_x = math::clamp_float(mControllerStatesCurrent[i].velocity_left_x, -maxSpeed, maxSpeed); + mControllerStatesCurrent[i].velocity_left_y = math::clamp_float(mControllerStatesCurrent[i].velocity_left_y, -maxSpeed, maxSpeed); + + mControllerStatesCurrent[i].velocity_right_x = (mControllerStatesPrevious[i].velocity_right_x + lx * acceleration) * friction; + mControllerStatesCurrent[i].velocity_right_y = (mControllerStatesPrevious[i].velocity_right_y + ly * acceleration) * friction; + mControllerStatesCurrent[i].velocity_right_x = math::clamp_float(mControllerStatesCurrent[i].velocity_right_x, -maxSpeed, maxSpeed); + mControllerStatesCurrent[i].velocity_right_y = math::clamp_float(mControllerStatesCurrent[i].velocity_right_y, -maxSpeed, maxSpeed); + + lx = lx * sensitivity; + ly = ly * sensitivity; + rx = rx * sensitivity; + ry = ry * sensitivity; + + mControllerStatesCurrent[i].thumb_left_dx = (int)lx; + mControllerStatesCurrent[i].thumb_left_dy = (int)ly; + mControllerStatesCurrent[i].thumb_right_dx = (int)rx; + mControllerStatesCurrent[i].thumb_right_dy = (int)ry; + mControllerStatesCurrent[i].thumb_left_x = math::clamp_int((int)(mControllerStatesPrevious[i].thumb_left_x + lx), 0, graphics::getWidth()); + mControllerStatesCurrent[i].thumb_left_y = math::clamp_int((int)(mControllerStatesPrevious[i].thumb_left_y + ly), 0, graphics::getHeight()); + mControllerStatesCurrent[i].thumb_right_x = math::clamp_int((int)(mControllerStatesPrevious[i].thumb_right_x + rx), 0, graphics::getWidth()); + mControllerStatesCurrent[i].thumb_right_y = math::clamp_int((int)(mControllerStatesPrevious[i].thumb_right_y + ry), 0, graphics::getHeight()); + mControllerLastPacketNumber[i] = controllerInputState.dwPacketNumber; + } + } +} + void input_manager::process_mouse() { DWORD insertions = 0; @@ -61,25 +164,26 @@ void input_manager::process_mouse() for (int i = 0; i < XGetPortCount(); i++) { - if (mMouseHandles[i] == NULL || XInputGetState(mMouseHandles[i], &mMouseInputStates[i]) != 0) + XINPUT_STATE mouseInputState; + if (mMouseHandles[i] == NULL || XInputGetState(mMouseHandles[i], &mouseInputState) != 0) { continue; } - if (mMouseLastPacketNumber[i] != mMouseInputStates[i].dwPacketNumber) + if (mMouseLastPacketNumber[i] != mouseInputState.dwPacketNumber) { - memcpy(&mMouseStatesPrevious[i], &mMouseStatesCurrent[i], sizeof(MouseState)); - mMouseStatesCurrent[i].dx = mMouseInputStates[i].DebugMouse.cMickeysX; - mMouseStatesCurrent[i].dy = mMouseInputStates[i].DebugMouse.cMickeysY; + memcpy(&mMouseStatesPrevious[i], &mouseInputState, sizeof(MouseState)); + mMouseStatesCurrent[i].dx = mouseInputState.DebugMouse.cMickeysX; + mMouseStatesCurrent[i].dy = mouseInputState.DebugMouse.cMickeysY; + mMouseStatesCurrent[i].dz = mouseInputState.DebugMouse.cWheel; mMouseStatesCurrent[i].x = math::clamp_int(mMouseStatesPrevious[i].x + mMouseStatesCurrent[i].dx, 0, graphics::getWidth()); mMouseStatesCurrent[i].y = math::clamp_int(mMouseStatesPrevious[i].y + mMouseStatesCurrent[i].dy, 0, graphics::getHeight()); - mMouseStatesCurrent[i].dz = mMouseInputStates[i].DebugMouse.cWheel; - mMouseStatesCurrent[i].button[MOUSE_LEFT_BUTTON] = (mMouseInputStates[i].DebugMouse.bButtons & XINPUT_DEBUG_MOUSE_LEFT_BUTTON) != 0; - mMouseStatesCurrent[i].button[MOUSE_RIGHT_BUTTON] = (mMouseInputStates[i].DebugMouse.bButtons & XINPUT_DEBUG_MOUSE_RIGHT_BUTTON) != 0; - mMouseStatesCurrent[i].button[MOUSE_MIDDLE_BUTTON] = (mMouseInputStates[i].DebugMouse.bButtons & XINPUT_DEBUG_MOUSE_MIDDLE_BUTTON) != 0; - mMouseStatesCurrent[i].button[MOUSE_EXTRA_BUTTON1] = (mMouseInputStates[i].DebugMouse.bButtons & XINPUT_DEBUG_MOUSE_XBUTTON1) != 0; - mMouseStatesCurrent[i].button[MOUSE_EXTRA_BUTTON2] = (mMouseInputStates[i].DebugMouse.bButtons & XINPUT_DEBUG_MOUSE_XBUTTON2) != 0; - mMouseLastPacketNumber[i] = mMouseInputStates[i].dwPacketNumber; + mMouseStatesCurrent[i].buttons[MOUSE_LEFT_BUTTON] = (mouseInputState.DebugMouse.bButtons & XINPUT_DEBUG_MOUSE_LEFT_BUTTON) != 0; + mMouseStatesCurrent[i].buttons[MOUSE_RIGHT_BUTTON] = (mouseInputState.DebugMouse.bButtons & XINPUT_DEBUG_MOUSE_RIGHT_BUTTON) != 0; + mMouseStatesCurrent[i].buttons[MOUSE_MIDDLE_BUTTON] = (mouseInputState.DebugMouse.bButtons & XINPUT_DEBUG_MOUSE_MIDDLE_BUTTON) != 0; + mMouseStatesCurrent[i].buttons[MOUSE_EXTRA_BUTTON1] = (mouseInputState.DebugMouse.bButtons & XINPUT_DEBUG_MOUSE_XBUTTON1) != 0; + mMouseStatesCurrent[i].buttons[MOUSE_EXTRA_BUTTON2] = (mouseInputState.DebugMouse.bButtons & XINPUT_DEBUG_MOUSE_XBUTTON2) != 0; + mMouseLastPacketNumber[i] = mouseInputState.dwPacketNumber; } } } @@ -136,6 +240,22 @@ void input_manager::process_keyboard() } } +bool input_manager::controller_pressed(CONTROLLER_BUTTON button, int port) +{ + for (int i = 0; i < XGetPortCount(); i++) + { + if (port >= 0 && port != i || mControllerHandles[i] == NULL) + { + continue; + } + if (mControllerStatesCurrent[i].buttons[button] == true && mControllerStatesPrevious[i].buttons[button] == false) + { + return true; + } + } + return false; +} + bool input_manager::mouse_pressed(MOUSE_BUTTON button, int port) { for (int i = 0; i < XGetPortCount(); i++) @@ -144,7 +264,7 @@ bool input_manager::mouse_pressed(MOUSE_BUTTON button, int port) { continue; } - if (mMouseStatesCurrent[i].button[button] == true && mMouseStatesPrevious[i].button[button] == false) + if (mMouseStatesCurrent[i].buttons[button] == true && mMouseStatesPrevious[i].buttons[button] == false) { return true; } @@ -152,6 +272,23 @@ bool input_manager::mouse_pressed(MOUSE_BUTTON button, int port) return false; } +bool input_manager::try_get_controller_state(int port, ControllerState* controllerState) +{ + if (controllerState != NULL) + { + for (int i = 0; i < XGetPortCount(); i++) + { + if (port >= 0 && port != i || mControllerHandles[i] == NULL) + { + continue; + } + *controllerState = mControllerStatesCurrent[i]; + return true; + } + } + return false; +} + bool input_manager::try_get_mouse_state(int port, MouseState* mouseState) { if (mouseState != NULL) @@ -201,6 +338,7 @@ bool input_manager::try_get_keyboard_state(int port, KeyboardState* keyboardStat void input_manager::pump_input(nk_context *context) { + process_controller(); process_mouse(); process_keyboard(); @@ -238,14 +376,25 @@ void input_manager::pump_input(nk_context *context) } } - MouseState mouseState; - memset(&mouseState, 0, sizeof(mouseState)); - if (try_get_mouse_state(-1, &mouseState)) + //MouseState mouseState; + //memset(&mouseState, 0, sizeof(mouseState)); + //if (try_get_mouse_state(-1, &mouseState)) + //{ + // nk_input_motion(context, mouseState.x, mouseState.y); + // nk_input_button(context, NK_BUTTON_LEFT, mouseState.x, mouseState.y, mouseState.buttons[MOUSE_LEFT_BUTTON]); + // nk_input_button(context, NK_BUTTON_MIDDLE, mouseState.x, mouseState.y, mouseState.buttons[MOUSE_MIDDLE_BUTTON]); + // nk_input_button(context, NK_BUTTON_RIGHT, mouseState.x, mouseState.y, mouseState.buttons[MOUSE_RIGHT_BUTTON]); + //} + + ControllerState controllerState; + memset(&controllerState, 0, sizeof(controllerState)); + if (try_get_controller_state(-1, &controllerState)) { - nk_input_motion(context, mouseState.x, mouseState.y); - nk_input_button(context, NK_BUTTON_LEFT, mouseState.x, mouseState.y, mouseState.button[MOUSE_LEFT_BUTTON]); - nk_input_button(context, NK_BUTTON_MIDDLE, mouseState.x, mouseState.y, mouseState.button[MOUSE_MIDDLE_BUTTON]); - nk_input_button(context, NK_BUTTON_RIGHT, mouseState.x, mouseState.y, mouseState.button[MOUSE_RIGHT_BUTTON]); + nk_input_motion(context, controllerState.thumb_left_x, controllerState.thumb_left_y); + nk_input_button(context, NK_BUTTON_LEFT, controllerState.thumb_left_x, controllerState.thumb_left_y, controllerState.buttons[CONTROLLER_A_BUTTON]); + nk_input_button(context, NK_BUTTON_MIDDLE, controllerState.thumb_left_x, controllerState.thumb_left_y, controllerState.buttons[CONTROLLER_X_BUTTON]); + nk_input_button(context, NK_BUTTON_RIGHT, controllerState.thumb_left_x, controllerState.thumb_left_y, controllerState.buttons[CONTROLLER_B_BUTTON]); } + nk_input_end(context); } diff --git a/Nuklear-XboxOG/input_manager.h b/Nuklear-XboxOG/input_manager.h index 2f61f36..3a8aad5 100644 --- a/Nuklear-XboxOG/input_manager.h +++ b/Nuklear-XboxOG/input_manager.h @@ -11,14 +11,53 @@ #define NK_INCLUDE_DEFAULT_FONT #include "nuklear.h" -typedef struct MouseState +typedef struct ControllerState +{ + int thumb_left_x; + int thumb_left_y; + int thumb_left_dx; + int thumb_left_dy; + int thumb_right_x; + int thumb_right_y; + int thumb_right_dx; + int thumb_right_dy; + + float velocity_left_x; + float velocity_left_y; + float velocity_right_x; + float velocity_right_y; + + bool buttons[16]; +} ControllerState; + +typedef enum CONTROLLER_BUTTON +{ + CONTROLLER_A_BUTTON = 0, + CONTROLLER_B_BUTTON = 1, + CONTROLLER_X_BUTTON = 2, + CONTROLLER_Y_BUTTON = 3, + CONTROLLER_BLACK_BUTTON = 4, + CONTROLLER_WHITE_BUTTON = 5, + CONTROLLER_LTRIGGER_BUTTON = 6, + CONTROLLER_RTRIGGER_BUTTON = 7, + CONTROLLER_DPAD_UP_BUTTON = 8, + CONTROLLER_DPAD_DOWN_BUTTON = 9, + CONTROLLER_DPAD_LEFT_BUTTON = 10, + CONTROLLER_DPAD_RIGHT_BUTTON = 11, + CONTROLLER_START_BUTTON = 12, + CONTROLLER_BACK_BUTTON = 13, + CONTROLLER_LTHUMB_BUTTON = 14, + CONTROLLER_RTHUMB_BUTTON = 15, +} CONTROLLER_BUTTON; + +typedef struct MouseState { int x; int y; int dx; int dy; int dz; - bool button[5]; + bool buttons[5]; } MouseState; typedef enum MOUSE_BUTTON @@ -52,9 +91,12 @@ class input_manager { public: static void init(); + static void process_controller(); static void process_mouse(); static void process_keyboard(); + static bool controller_pressed(CONTROLLER_BUTTON button, int port); static bool mouse_pressed(MOUSE_BUTTON button, int port); + static bool try_get_controller_state(int port, ControllerState* controllerState); static bool try_get_mouse_state(int port, MouseState* mouseState); static bool has_mouse(int port); static bool try_get_keyboard_state(int port, KeyboardState* keyboardState); diff --git a/Nuklear-XboxOG/math.cpp b/Nuklear-XboxOG/math.cpp index 44d790a..9148717 100644 --- a/Nuklear-XboxOG/math.cpp +++ b/Nuklear-XboxOG/math.cpp @@ -1,8 +1,22 @@ #include "math.h" +#include + int math::clamp_int(int value, int min, int max) { if (value < min) return min; if (value > max) return max; return value; +} + +float math::clamp_float(float value, float min, float max) +{ + if (value < min) return min; + if (value > max) return max; + return value; +} + +float math::copy_sign(float a, float b) +{ + return (b >= 0.0f) ? fabsf(a) : -fabsf(a); } \ No newline at end of file diff --git a/Nuklear-XboxOG/math.h b/Nuklear-XboxOG/math.h index b57c23d..d65dd97 100644 --- a/Nuklear-XboxOG/math.h +++ b/Nuklear-XboxOG/math.h @@ -4,4 +4,6 @@ class math { public: static int clamp_int(int value, int min, int max); + static float clamp_float(float value, float min, float max); + static float copy_sign(float a, float b); };