mirror of
https://github.com/Karaka-Management/cOMS.git
synced 2026-01-11 11:18:40 +00:00
implement controller support
This commit is contained in:
parent
177affce99
commit
b031ebb25d
83
input/ControllerInput.h
Normal file
83
input/ControllerInput.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* Jingga
|
||||
*
|
||||
* @copyright Jingga
|
||||
* @license OMS License 2.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
#ifndef TOS_PLATFORM_WIN32_INPUT_CONTROLLER_CONTROLLER_INPUT_H
|
||||
#define TOS_PLATFORM_WIN32_INPUT_CONTROLLER_CONTROLLER_INPUT_H
|
||||
|
||||
#include "../stdlib/Types.h"
|
||||
|
||||
enum ControllerButton {
|
||||
CONTROLLER_BUTTON_NONE, // Needs to be skipped for input system (see -1)
|
||||
|
||||
CONTROLLER_BUTTON_STICK_LEFT_BUTTON,
|
||||
CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL,
|
||||
CONTROLLER_BUTTON_STICK_LEFT_VERTOCAL,
|
||||
|
||||
CONTROLLER_BUTTON_STICK_RIGHT_BUTTON,
|
||||
CONTROLLER_BUTTON_STICK_RIGHT_HORIZONTAL,
|
||||
CONTROLLER_BUTTON_STICK_RIGHT_VERTOCAL,
|
||||
|
||||
CONTROLLER_BUTTON_SHOULDER_LEFT_TRIGGER,
|
||||
CONTROLLER_BUTTON_SHOULDER_LEFT_BUTTON,
|
||||
|
||||
CONTROLLER_BUTTON_SHOULDER_RIGHT_TRIGGER,
|
||||
CONTROLLER_BUTTON_SHOULDER_RIGHT_BUTTON,
|
||||
|
||||
CONTROLLER_BUTTON_X,
|
||||
CONTROLLER_BUTTON_C,
|
||||
CONTROLLER_BUTTON_T,
|
||||
CONTROLLER_BUTTON_S,
|
||||
|
||||
CONTROLLER_BUTTON_DPAD_LEFT,
|
||||
CONTROLLER_BUTTON_DPAD_RIGHT,
|
||||
CONTROLLER_BUTTON_DPAD_UP,
|
||||
CONTROLLER_BUTTON_DPAD_DOWN,
|
||||
|
||||
CONTROLLER_BUTTON_OTHER_0,
|
||||
CONTROLLER_BUTTON_OTHER_1,
|
||||
CONTROLLER_BUTTON_OTHER_2,
|
||||
CONTROLLER_BUTTON_OTHER_3,
|
||||
CONTROLLER_BUTTON_OTHER_4,
|
||||
CONTROLLER_BUTTON_OTHER_5,
|
||||
CONTROLLER_BUTTON_OTHER_6,
|
||||
CONTROLLER_BUTTON_OTHER_7,
|
||||
};
|
||||
|
||||
struct ControllerInput {
|
||||
uint8 stick_left_button;
|
||||
int8 stick_left_x;
|
||||
int8 stick_left_y;
|
||||
|
||||
uint8 stick_right_button;
|
||||
int8 stick_right_x;
|
||||
int8 stick_right_y;
|
||||
|
||||
int8 shoulder_trigger_left;
|
||||
int8 shoulder_trigger_right;
|
||||
|
||||
uint8 shoulder_button_left;
|
||||
uint8 shoulder_button_right;
|
||||
|
||||
uint8 button_X;
|
||||
uint8 button_C;
|
||||
uint8 button_T;
|
||||
uint8 button_S;
|
||||
|
||||
uint8 dpad_left;
|
||||
uint8 dpad_right;
|
||||
uint8 dpad_up;
|
||||
uint8 dpad_down;
|
||||
|
||||
int16 gyro_x;
|
||||
int16 gyro_y;
|
||||
int16 gyro_z;
|
||||
|
||||
uint8 button_other[8];
|
||||
};
|
||||
|
||||
#endif
|
||||
506
input/Input.h
506
input/Input.h
|
|
@ -32,8 +32,8 @@
|
|||
// These values are used as bit flags to hint if a "key" is a keyboard/primary or mouse/secondary input
|
||||
// When adding a keybind the "key" can only be uint8 but we expand it to an int and set the first bit accordingly
|
||||
#define INPUT_MOUSE_PREFIX 0
|
||||
#define INPUT_KEYBOARD_PREFIX 16384
|
||||
#define INPUT_CONTROLLER_PREFIX 32768
|
||||
#define INPUT_KEYBOARD_PREFIX 8192
|
||||
#define INPUT_CONTROLLER_PREFIX 16384
|
||||
|
||||
#define INPUT_TYPE_MOUSE_KEYBOARD 0x01
|
||||
#define INPUT_TYPE_CONTROLLER 0x02
|
||||
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
#include "../stdlib/Types.h"
|
||||
#include "../utils/BitUtils.h"
|
||||
#include "ControllerInput.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
|
|
@ -58,7 +59,10 @@ struct InputMapping {
|
|||
|
||||
// A hotkey can be bound to a combination of up to 3 key/button presses
|
||||
uint8 hotkey_count;
|
||||
uint16* hotkeys;
|
||||
|
||||
// negative hotkeys mean any of them needs to be matched, positive hotkeys means all of them need to be matched
|
||||
// mixing positive and negative keys for one hotkey is not possible
|
||||
int16* hotkeys;
|
||||
};
|
||||
|
||||
enum KeyState {
|
||||
|
|
@ -71,7 +75,7 @@ struct InputKey {
|
|||
// Includes flag for mouse, keyboard, controller
|
||||
uint16 key_id;
|
||||
uint16 key_state;
|
||||
uint16 value; // e.g. stick/trigger keys
|
||||
int16 value; // e.g. stick/trigger keys
|
||||
uint64 time; // when was this action performed (useful to decide if key state is held vs pressed)
|
||||
};
|
||||
|
||||
|
|
@ -88,27 +92,46 @@ struct InputState {
|
|||
|
||||
uint32 x;
|
||||
uint32 y;
|
||||
|
||||
// Secondary coordinate input (usually used by controllers)
|
||||
int32 dx2;
|
||||
int32 dy2;
|
||||
|
||||
uint32 x2;
|
||||
uint32 y2;
|
||||
|
||||
// Tertiary coordinate input (usually used by controllers)
|
||||
int32 dx3;
|
||||
int32 dy3;
|
||||
|
||||
uint32 x3;
|
||||
uint32 y3;
|
||||
};
|
||||
|
||||
struct Input {
|
||||
// Device
|
||||
bool is_connected = false;
|
||||
bool is_connected;
|
||||
|
||||
#ifdef _WIN32
|
||||
// @todo maybe replace with id?!
|
||||
// -> remove _WIN32 section
|
||||
// @question maybe replace with id?!
|
||||
// -> remove _WIN32 section?
|
||||
HANDLE handle_keyboard;
|
||||
HANDLE handle_mouse;
|
||||
HANDLE handle_controller;
|
||||
#endif
|
||||
|
||||
bool state_change_button = false;
|
||||
bool state_change_mouse = false;
|
||||
bool state_change_button;
|
||||
bool state_change_mouse;
|
||||
|
||||
bool mouse_movement;
|
||||
|
||||
InputState state;
|
||||
InputMapping input_mapping;
|
||||
uint64 time_last_input_check;
|
||||
|
||||
uint32 deadzone = 10;
|
||||
|
||||
InputMapping input_mapping1;
|
||||
InputMapping input_mapping2;
|
||||
};
|
||||
|
||||
inline
|
||||
|
|
@ -122,7 +145,7 @@ void input_clean_state(InputState* state)
|
|||
}
|
||||
|
||||
inline
|
||||
bool input_action_exists(const InputState* state, uint16 key)
|
||||
bool input_action_exists(const InputState* state, int16 key)
|
||||
{
|
||||
return state->state_keys[0].key_id == key
|
||||
|| state->state_keys[1].key_id == key
|
||||
|
|
@ -138,23 +161,23 @@ bool input_action_exists(const InputState* state, uint16 key)
|
|||
}
|
||||
|
||||
inline
|
||||
bool input_is_down(const InputState* state, uint16 key)
|
||||
bool input_is_down(const InputState* state, int16 key)
|
||||
{
|
||||
return (state->state_keys[0].key_id == key && state->state_keys[0].key_state < KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[1].key_id == key && state->state_keys[1].key_state < KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[2].key_id == key && state->state_keys[2].key_state < KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[3].key_id == key && state->state_keys[3].key_state < KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[4].key_id == key && state->state_keys[4].key_state < KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[4].key_id == key && state->state_keys[4].key_state < KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[5].key_id == key && state->state_keys[5].key_state < KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[6].key_id == key && state->state_keys[6].key_state < KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[7].key_id == key && state->state_keys[7].key_state < KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[8].key_id == key && state->state_keys[8].key_state < KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[9].key_id == key && state->state_keys[9].key_state < KEY_STATE_RELEASED);
|
||||
return (state->state_keys[0].key_id == key && state->state_keys[0].key_state != KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[1].key_id == key && state->state_keys[1].key_state != KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[2].key_id == key && state->state_keys[2].key_state != KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[3].key_id == key && state->state_keys[3].key_state != KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[4].key_id == key && state->state_keys[4].key_state != KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[4].key_id == key && state->state_keys[4].key_state != KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[5].key_id == key && state->state_keys[5].key_state != KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[6].key_id == key && state->state_keys[6].key_state != KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[7].key_id == key && state->state_keys[7].key_state != KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[8].key_id == key && state->state_keys[8].key_state != KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[9].key_id == key && state->state_keys[9].key_state != KEY_STATE_RELEASED);
|
||||
}
|
||||
|
||||
inline
|
||||
bool input_is_pressed(const InputState* state, uint16 key)
|
||||
bool input_is_pressed(const InputState* state, int16 key)
|
||||
{
|
||||
return (state->state_keys[0].key_id == key && state->state_keys[0].key_state == KEY_STATE_PRESSED)
|
||||
|| (state->state_keys[1].key_id == key && state->state_keys[1].key_state == KEY_STATE_PRESSED)
|
||||
|
|
@ -170,7 +193,7 @@ bool input_is_pressed(const InputState* state, uint16 key)
|
|||
}
|
||||
|
||||
inline
|
||||
bool input_is_held(const InputState* state, uint16 key)
|
||||
bool input_is_held(const InputState* state, int16 key)
|
||||
{
|
||||
return (state->state_keys[0].key_id == key && state->state_keys[0].key_state == KEY_STATE_HELD)
|
||||
|| (state->state_keys[1].key_id == key && state->state_keys[1].key_state == KEY_STATE_HELD)
|
||||
|
|
@ -186,7 +209,7 @@ bool input_is_held(const InputState* state, uint16 key)
|
|||
}
|
||||
|
||||
inline
|
||||
bool input_is_released(const InputState* state, uint16 key)
|
||||
bool input_is_released(const InputState* state, int16 key)
|
||||
{
|
||||
return (state->state_keys[0].key_id == key && state->state_keys[0].key_state == KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[1].key_id == key && state->state_keys[1].key_state == KEY_STATE_RELEASED)
|
||||
|
|
@ -202,7 +225,7 @@ bool input_is_released(const InputState* state, uint16 key)
|
|||
}
|
||||
|
||||
inline
|
||||
bool input_was_down(const InputState* state, uint16 key)
|
||||
bool input_was_down(const InputState* state, int16 key)
|
||||
{
|
||||
return (state->state_keys[0].key_id == key && state->state_keys[0].key_state == KEY_STATE_RELEASED)
|
||||
|| (state->state_keys[1].key_id == key && state->state_keys[1].key_state == KEY_STATE_RELEASED)
|
||||
|
|
@ -220,7 +243,7 @@ bool input_was_down(const InputState* state, uint16 key)
|
|||
inline
|
||||
bool inputs_are_down(
|
||||
const InputState* state,
|
||||
uint16 key0, uint16 key1 = 0, uint16 key2 = 0, uint16 key3 = 0, uint16 key4 = 0
|
||||
int16 key0, int16 key1 = 0, int16 key2 = 0, int16 key3 = 0, int16 key4 = 0
|
||||
) {
|
||||
return (key0 != 0 && input_is_down(state, key0))
|
||||
&& (key1 == 0 || input_is_down(state, key1))
|
||||
|
|
@ -233,7 +256,7 @@ bool inputs_are_down(
|
|||
void
|
||||
input_add_hotkey(
|
||||
InputMapping* mapping, uint8 hotkey,
|
||||
uint32 key0, uint32 key1 = 0, uint32 key2 = 0
|
||||
int32 key0, int32 key1 = 0, int32 key2 = 0
|
||||
)
|
||||
{
|
||||
int count = 0;
|
||||
|
|
@ -241,19 +264,19 @@ input_add_hotkey(
|
|||
// Define required keys for hotkey
|
||||
if (key0 != 0) {
|
||||
// Note: -1 since the hotkeys MUST start at 1 (0 is a special value for empty)
|
||||
mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION] = (uint16) key0;
|
||||
mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION] = (int16) key0;
|
||||
++count;
|
||||
}
|
||||
|
||||
if (key1 != 0) {
|
||||
// Note: -1 since the hotkeys MUST start at 1 (0 is a special value for empty)
|
||||
mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION + count] = (uint16) key1;
|
||||
mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION + count] = (int16) key1;
|
||||
++count;
|
||||
}
|
||||
|
||||
if (key2 != 0) {
|
||||
// Note: -1 since the hotkeys MUST start at 1 (0 is a special value for empty)
|
||||
mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION + count] = (uint16) key2;
|
||||
mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION + count] = (int16) key2;
|
||||
}
|
||||
|
||||
int key0_offset = ((bool) (key0 & INPUT_KEYBOARD_PREFIX)) * MAX_MOUSE_KEYS
|
||||
|
|
@ -307,9 +330,9 @@ bool hotkey_is_active(const InputState* state, uint8 hotkey)
|
|||
inline
|
||||
bool hotkey_keys_are_active(const InputState* __restrict state, const InputMapping* __restrict mapping, uint8 hotkey)
|
||||
{
|
||||
uint16 key0 = mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION];
|
||||
uint16 key1 = mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION + 1];
|
||||
uint16 key2 = mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION + 2];
|
||||
int16 key0 = mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION];
|
||||
int16 key1 = mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION + 1];
|
||||
int16 key2 = mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION + 2];
|
||||
|
||||
// This may seem a little bit confusing but we don't care if a input key is down or up
|
||||
// Any state means it was used recently BUT NOT YET HANDLED
|
||||
|
|
@ -317,19 +340,19 @@ bool hotkey_keys_are_active(const InputState* __restrict state, const InputMappi
|
|||
// Therefore, if a key has a state -> treat it as if active
|
||||
bool is_active = input_action_exists(state, key0);
|
||||
if (!is_active || key1 == 0) {
|
||||
return is_active;
|
||||
return is_active || input_action_exists(state, -key0);
|
||||
}
|
||||
|
||||
is_active &= input_action_exists(state, key1);
|
||||
if (!is_active || key2 == 0) {
|
||||
return is_active;
|
||||
return is_active || input_action_exists(state, -key1);
|
||||
}
|
||||
|
||||
return (is_active &= input_action_exists(state, key2));
|
||||
return (is_active &= input_action_exists(state, key2)) || input_action_exists(state, -key2);
|
||||
}
|
||||
|
||||
inline
|
||||
void input_set_state(InputState* state, uint16 key_id, uint16 new_state)
|
||||
void input_set_state(InputState* state, InputKey* __restrict new_key)
|
||||
{
|
||||
InputKey* free_state = NULL;
|
||||
bool action_required = true;
|
||||
|
|
@ -337,8 +360,10 @@ void input_set_state(InputState* state, uint16 key_id, uint16 new_state)
|
|||
for (int j = 0; j < MAX_KEY_STATES; ++j) {
|
||||
if (!free_state && state->state_keys[j].key_id == 0) {
|
||||
free_state = &state->state_keys[j];
|
||||
} else if (state->state_keys[j].key_id == key_id) {
|
||||
state->state_keys[j].key_state = new_state;
|
||||
} else if (state->state_keys[j].key_id == new_key->key_id) {
|
||||
state->state_keys[j].key_state = new_key->key_state;
|
||||
state->state_keys[j].value = new_key->value;
|
||||
state->state_keys[j].time = new_key->time;
|
||||
action_required = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -347,23 +372,347 @@ void input_set_state(InputState* state, uint16 key_id, uint16 new_state)
|
|||
return;
|
||||
}
|
||||
|
||||
free_state->key_id = key_id;
|
||||
free_state->key_state = new_state;
|
||||
// @todo implement
|
||||
// free_state->time = 0;
|
||||
free_state->key_id = new_key->key_id;
|
||||
free_state->key_state = new_key->key_state;
|
||||
free_state->value = new_key->value;
|
||||
free_state->time = new_key->time;
|
||||
}
|
||||
|
||||
// Controllers are a little bit special
|
||||
// We need to manually check the specific buttons and set their key
|
||||
// Since some controllers are constantly sending data like mad it's not possible to handle them event based
|
||||
// We need to poll them and then check the old state against this new state (annoying but necessary)
|
||||
// Mice are fully supported by RawInput and are fairly generalized in terms of their buttons -> no special function needed
|
||||
inline
|
||||
void input_set_controller_state(Input* input, ControllerInput* controller, uint64 time)
|
||||
{
|
||||
// Check active keys that might need to be set to inactive
|
||||
for (int i = 0; i < MAX_KEY_PRESSES; ++i) {
|
||||
if ((input->state.state_keys[i].key_id & INPUT_CONTROLLER_PREFIX)
|
||||
&& input->state.state_keys[i].key_state != KEY_STATE_RELEASED
|
||||
) {
|
||||
uint32 key_id = input->state.state_keys[i].key_id & ~INPUT_CONTROLLER_PREFIX;
|
||||
|
||||
if ((key_id == CONTROLLER_BUTTON_STICK_LEFT_BUTTON && controller->stick_left_button == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL && OMS_ABS(controller->stick_left_x) < input->deadzone)
|
||||
|| (key_id == CONTROLLER_BUTTON_STICK_LEFT_VERTOCAL && OMS_ABS(controller->stick_left_y) < input->deadzone)
|
||||
|| (key_id == CONTROLLER_BUTTON_STICK_RIGHT_BUTTON && controller->stick_right_button == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_STICK_RIGHT_HORIZONTAL && OMS_ABS(controller->stick_right_x) < input->deadzone)
|
||||
|| (key_id == CONTROLLER_BUTTON_STICK_RIGHT_VERTOCAL && OMS_ABS(controller->stick_right_y) < input->deadzone)
|
||||
|| (key_id == CONTROLLER_BUTTON_SHOULDER_LEFT_TRIGGER && OMS_ABS(controller->shoulder_trigger_left) < input->deadzone)
|
||||
|| (key_id == CONTROLLER_BUTTON_SHOULDER_LEFT_BUTTON && controller->shoulder_button_left == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_SHOULDER_RIGHT_TRIGGER && OMS_ABS(controller->shoulder_trigger_right) < input->deadzone)
|
||||
|| (key_id == CONTROLLER_BUTTON_SHOULDER_RIGHT_BUTTON && controller->shoulder_button_right == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_X && controller->button_X == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_C && controller->button_C == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_T && controller->button_T == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_S && controller->button_S == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_DPAD_LEFT && controller->dpad_left == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_DPAD_RIGHT && controller->dpad_right == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_DPAD_UP && controller->dpad_up == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_DPAD_DOWN && controller->dpad_down == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_OTHER_0 && controller->button_other[0] == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_OTHER_1 && controller->button_other[1] == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_OTHER_2 && controller->button_other[2] == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_OTHER_3 && controller->button_other[3] == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_OTHER_4 && controller->button_other[4] == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_OTHER_5 && controller->button_other[5] == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_OTHER_6 && controller->button_other[6] == 0)
|
||||
|| (key_id == CONTROLLER_BUTTON_OTHER_7 && controller->button_other[7] == 0)
|
||||
) {
|
||||
input->state.state_keys[i].key_state = KEY_STATE_RELEASED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Special keys
|
||||
// @todo this code means we cannot change this behavior (e.g. swap mouse view to dpad, swap sticks, ...)
|
||||
if (OMS_ABS(controller->stick_right_x) > input->deadzone) {
|
||||
input->state.dx += controller->stick_right_x / 8;
|
||||
input->state_change_mouse = true;
|
||||
} else {
|
||||
input->state.dx = 0;
|
||||
}
|
||||
|
||||
if (OMS_ABS(controller->stick_right_y) > input->deadzone) {
|
||||
input->state.dy += controller->stick_right_y / 8;
|
||||
input->state_change_mouse = true;
|
||||
} else {
|
||||
input->state.dy = 0;
|
||||
}
|
||||
|
||||
if (OMS_ABS(controller->stick_left_x) > input->deadzone) {
|
||||
input->state.dx2 += controller->stick_left_x / 8;
|
||||
// @todo needs state change flag like mouse?!
|
||||
} else {
|
||||
input->state.dx2 = 0;
|
||||
}
|
||||
|
||||
if (OMS_ABS(controller->stick_left_y) > input->deadzone) {
|
||||
input->state.dy2 += controller->stick_left_y / 8;
|
||||
input->state.y2 += controller->stick_left_y / 8;
|
||||
// @todo needs state change flag like mouse?!
|
||||
} else {
|
||||
input->state.dy2 = 0;
|
||||
}
|
||||
|
||||
// General Keys
|
||||
int count = 0;
|
||||
InputKey keys[5];
|
||||
|
||||
// @todo this logic below is painful, fix
|
||||
if (count < 5 && controller->stick_left_button != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_STICK_LEFT_BUTTON | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->stick_left_button;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && OMS_ABS(controller->stick_left_x) > input->deadzone) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->stick_left_x;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && OMS_ABS(controller->stick_left_y) > input->deadzone) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_STICK_LEFT_VERTOCAL | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->stick_left_y;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->stick_right_button != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_STICK_RIGHT_BUTTON | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->stick_right_button;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && OMS_ABS(controller->stick_right_x) > input->deadzone) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_STICK_RIGHT_HORIZONTAL | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->stick_right_x;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && OMS_ABS(controller->stick_right_y) > input->deadzone) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_STICK_RIGHT_VERTOCAL | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->stick_right_y;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && OMS_ABS(controller->shoulder_trigger_left) > input->deadzone) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_SHOULDER_LEFT_TRIGGER | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->shoulder_trigger_left;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->shoulder_button_left != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_SHOULDER_LEFT_BUTTON | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->shoulder_button_left;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && OMS_ABS(controller->shoulder_trigger_right) > input->deadzone) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_SHOULDER_RIGHT_TRIGGER | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->shoulder_trigger_right;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->shoulder_button_right != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_SHOULDER_RIGHT_BUTTON | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->shoulder_button_right;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->button_X != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_X | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->button_X;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->button_C != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_C | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->button_C;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->button_T != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_T | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->button_T;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->button_S != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_S | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->button_S;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->dpad_left != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_DPAD_LEFT | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->dpad_left;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->dpad_right != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_DPAD_RIGHT | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->dpad_right;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->dpad_up != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_DPAD_UP | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->dpad_up;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->dpad_down != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_DPAD_DOWN | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->dpad_down;
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->button_other[0] != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_OTHER_0 | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->button_other[0];
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->button_other[1] != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_OTHER_1 | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->button_other[1];
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->button_other[2] != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_OTHER_2 | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->button_other[2];
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->button_other[3] != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_OTHER_3 | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->button_other[3];
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->button_other[4] != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_OTHER_4 | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->button_other[4];
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->button_other[5] != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_OTHER_5 | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->button_other[5];
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->button_other[6] != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_OTHER_6 | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->button_other[6];
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count < 5 && controller->button_other[7] != 0) {
|
||||
keys[count].key_id = CONTROLLER_BUTTON_OTHER_7 | INPUT_CONTROLLER_PREFIX;
|
||||
keys[count].key_state = KEY_STATE_PRESSED;
|
||||
keys[count].value = controller->button_other[7];
|
||||
keys[count].time = time;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
input_set_state(&input->state, &keys[i]);
|
||||
}
|
||||
|
||||
input->state_change_button = true;
|
||||
}
|
||||
|
||||
void
|
||||
input_hotkey_state(InputState* __restrict state, const InputMapping* mapping)
|
||||
input_hotkey_state(Input* input)
|
||||
{
|
||||
memset(state->state_hotkeys, 0, sizeof(uint8) * MAX_KEY_PRESSES);
|
||||
memset(input->state.state_hotkeys, 0, sizeof(uint8) * MAX_KEY_PRESSES);
|
||||
|
||||
int i = 0;
|
||||
int active_hotkeys = 0;
|
||||
|
||||
// Check every key down state
|
||||
for (int key_state = 0; key_state < MAX_KEY_STATES; ++key_state) {
|
||||
if (state->state_keys[key_state].key_id == 0
|
||||
|| state->state_keys[key_state].key_state == KEY_STATE_RELEASED
|
||||
if (input->state.state_keys[key_state].key_id == 0
|
||||
|| input->state.state_keys[key_state].key_state == KEY_STATE_RELEASED
|
||||
) {
|
||||
// no key defined for this down state
|
||||
continue;
|
||||
|
|
@ -372,31 +721,46 @@ input_hotkey_state(InputState* __restrict state, const InputMapping* mapping)
|
|||
// Is a key defined for this state AND is at least one hotkey defined for this key
|
||||
// If no hotkey is defined we don't care
|
||||
// Careful, remember MAX_MOUSE_KEYS offset
|
||||
InputKey* input = &state->state_keys[key_state];
|
||||
int32 internal_key_id = (input->key_id & ~(INPUT_KEYBOARD_PREFIX | INPUT_CONTROLLER_PREFIX))
|
||||
+ ((bool) (input->key_id & INPUT_KEYBOARD_PREFIX)) * MAX_MOUSE_KEYS
|
||||
+ ((bool) (input->key_id & INPUT_CONTROLLER_PREFIX)) * (MAX_MOUSE_KEYS + MAX_KEYBOARD_KEYS);
|
||||
InputKey* key = &input->state.state_keys[key_state];
|
||||
int32 internal_key_id = (key->key_id & ~(INPUT_KEYBOARD_PREFIX | INPUT_CONTROLLER_PREFIX))
|
||||
+ ((bool) (key->key_id & INPUT_KEYBOARD_PREFIX)) * MAX_MOUSE_KEYS
|
||||
+ ((bool) (key->key_id & INPUT_CONTROLLER_PREFIX)) * (MAX_MOUSE_KEYS + MAX_KEYBOARD_KEYS);
|
||||
|
||||
const uint8* hotkeys_for_key = mapping->keys[internal_key_id - 1];
|
||||
if (hotkeys_for_key[0] == 0) {
|
||||
// no possible hotkey associated with this key
|
||||
continue;
|
||||
}
|
||||
// Handle 2 input devices (1 = keyboard + mouse, 2 = controller)
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
InputMapping* mapping;
|
||||
if (i == 0) {
|
||||
mapping = &input->input_mapping1;
|
||||
} else {
|
||||
// @todo Maybe we want to ignore < INPUT_CONTROLLER_PREFIX since we could use this to handle alt keybinds
|
||||
if (!input->handle_controller || key->key_id < INPUT_CONTROLLER_PREFIX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check every possible hotkey
|
||||
// Since multiple input devices have their own button/key indices whe have to do this weird range handling
|
||||
for (int possible_hotkey_idx = 0; possible_hotkey_idx < MAX_KEY_TO_HOTKEY; ++possible_hotkey_idx) {
|
||||
// We only support a slimited amount of active hotkeys
|
||||
if (i >= MAX_KEY_PRESSES) {
|
||||
return;
|
||||
mapping = &input->input_mapping2;
|
||||
}
|
||||
|
||||
bool is_pressed = hotkey_keys_are_active(state, mapping, hotkeys_for_key[possible_hotkey_idx]);
|
||||
const uint8* hotkeys_for_key = mapping->keys[internal_key_id - 1];
|
||||
if (hotkeys_for_key[0] == 0) {
|
||||
// no possible hotkey associated with this key
|
||||
continue;
|
||||
}
|
||||
|
||||
// store active hotkey, if it is not already active
|
||||
if (is_pressed && !hotkey_is_active(state, hotkeys_for_key[possible_hotkey_idx])) {
|
||||
state->state_hotkeys[i] = hotkeys_for_key[possible_hotkey_idx];
|
||||
++i;
|
||||
// Check every possible hotkey
|
||||
// Since multiple input devices have their own button/key indices whe have to do this weird range handling
|
||||
for (int possible_hotkey_idx = 0; possible_hotkey_idx < MAX_KEY_TO_HOTKEY; ++possible_hotkey_idx) {
|
||||
// We only support a slimited amount of active hotkeys
|
||||
if (active_hotkeys >= MAX_KEY_PRESSES) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_pressed = hotkey_keys_are_active(&input->state, mapping, hotkeys_for_key[possible_hotkey_idx]);
|
||||
|
||||
// store active hotkey, if it is not already active
|
||||
if (is_pressed && !hotkey_is_active(&input->state, hotkeys_for_key[possible_hotkey_idx])) {
|
||||
input->state.state_hotkeys[active_hotkeys] = hotkeys_for_key[possible_hotkey_idx];
|
||||
++active_hotkeys;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -405,6 +769,8 @@ input_hotkey_state(InputState* __restrict state, const InputMapping* mapping)
|
|||
// @bug how to handle priority? e.g. there might be a hotkey for 1 and one for alt+1
|
||||
// in this case only the hotkey for alt+1 should be triggered
|
||||
// @bug how to handle other conditions besides buttons pressed together? some hotkeys are only available in certain situations
|
||||
// @bug how to handle alternative hotkeys (e.g. keyboard and controller at the same time)
|
||||
// @bug how to handle values (e.g. stick may or may not set the x/y or dx/dy in some situations)
|
||||
}
|
||||
|
||||
#endif
|
||||
0
platform/win32/input/DirectInput.h
Normal file
0
platform/win32/input/DirectInput.h
Normal file
|
|
@ -6,13 +6,15 @@
|
|||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
#ifndef TOS_INPUT_RAW_H
|
||||
#define TOS_INPUT_RAW_H
|
||||
#ifndef TOS_PLATFORM_WIN32_INPUT_RAW_H
|
||||
#define TOS_PLATFORM_WIN32_INPUT_RAW_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "../../../stdlib/Types.h"
|
||||
#include "../../../input/Input.h"
|
||||
#include "../../../input/ControllerInput.h"
|
||||
#include "controller/DualShock4.h"
|
||||
#include "../../../utils/TestUtils.h"
|
||||
#include "../../../utils/MathUtils.h"
|
||||
#include "../../../memory/RingMemory.h"
|
||||
|
|
@ -169,39 +171,38 @@ void input_raw_handle(RAWINPUT* __restrict raw, Input* states, int state_count,
|
|||
}
|
||||
|
||||
if (raw->data.mouse.usButtonFlags) {
|
||||
uint16 new_state;
|
||||
uint16 button;
|
||||
InputKey key;
|
||||
|
||||
if (raw->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) {
|
||||
new_state = KEY_STATE_PRESSED;
|
||||
button = 1;
|
||||
key.key_state = KEY_STATE_PRESSED;
|
||||
key.key_id = 1;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP) {
|
||||
new_state = KEY_STATE_RELEASED;
|
||||
button = 1;
|
||||
key.key_state = KEY_STATE_RELEASED;
|
||||
key.key_id = 1;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) {
|
||||
new_state = KEY_STATE_PRESSED;
|
||||
button = 2;
|
||||
key.key_state = KEY_STATE_PRESSED;
|
||||
key.key_id = 2;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) {
|
||||
new_state = KEY_STATE_RELEASED;
|
||||
button = 2;
|
||||
key.key_state = KEY_STATE_RELEASED;
|
||||
key.key_id = 2;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) {
|
||||
new_state = KEY_STATE_PRESSED;
|
||||
button = 3;
|
||||
key.key_state = KEY_STATE_PRESSED;
|
||||
key.key_id = 3;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) {
|
||||
new_state = KEY_STATE_RELEASED;
|
||||
button = 3;
|
||||
key.key_state = KEY_STATE_RELEASED;
|
||||
key.key_id = 3;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) {
|
||||
new_state = KEY_STATE_PRESSED;
|
||||
button = 4;
|
||||
key.key_state = KEY_STATE_PRESSED;
|
||||
key.key_id = 4;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_UP) {
|
||||
new_state = KEY_STATE_RELEASED;
|
||||
button = 4;
|
||||
key.key_state = KEY_STATE_RELEASED;
|
||||
key.key_id = 4;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) {
|
||||
new_state = KEY_STATE_PRESSED;
|
||||
button = 5;
|
||||
key.key_state = KEY_STATE_PRESSED;
|
||||
key.key_id = 5;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP) {
|
||||
new_state = KEY_STATE_RELEASED;
|
||||
button = 5;
|
||||
key.key_state = KEY_STATE_RELEASED;
|
||||
key.key_id = 5;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
|
@ -218,9 +219,11 @@ void input_raw_handle(RAWINPUT* __restrict raw, Input* states, int state_count,
|
|||
|
||||
// @question is mouse wheel really considered a button change?
|
||||
|
||||
button |= INPUT_MOUSE_PREFIX;
|
||||
key.key_id |= INPUT_MOUSE_PREFIX;
|
||||
key.value = 0;
|
||||
key.time = time;
|
||||
|
||||
input_set_state(&states[i].state, button, new_state);
|
||||
input_set_state(&states[i].state, &key);
|
||||
states[i].state_change_button = true;
|
||||
} else if (states[i].mouse_movement) {
|
||||
// do we want to handle mouse movement for every individual movement, or do we want to pull it
|
||||
|
|
@ -270,66 +273,45 @@ void input_raw_handle(RAWINPUT* __restrict raw, Input* states, int state_count,
|
|||
return;
|
||||
}
|
||||
|
||||
int16 new_state = -1;
|
||||
uint16 new_state;
|
||||
if (raw->data.keyboard.Flags == RI_KEY_BREAK) {
|
||||
new_state = KEY_STATE_RELEASED;
|
||||
} else if (raw->data.keyboard.Flags == RI_KEY_MAKE) {
|
||||
new_state = KEY_STATE_PRESSED;
|
||||
}
|
||||
|
||||
if (new_state < 0) {
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
// @todo change to MakeCode instead of VKey
|
||||
uint16 key = raw->data.keyboard.VKey | INPUT_KEYBOARD_PREFIX;
|
||||
|
||||
input_set_state(&states[i].state, key, new_state);
|
||||
InputKey key = {(uint16) (raw->data.keyboard.VKey | INPUT_KEYBOARD_PREFIX), new_state, 0, time};
|
||||
input_set_state(&states[i].state, &key);
|
||||
states[i].state_change_button = true;
|
||||
} else if (raw->header.dwType == RIM_TYPEHID) {
|
||||
if (raw->header.dwSize > sizeof(RAWINPUT)) {
|
||||
// @todo Find a way to handle most common controllers
|
||||
// DualShock 3
|
||||
// Dualshock 4
|
||||
// DualSense
|
||||
// Xbox
|
||||
return;
|
||||
|
||||
/*
|
||||
// @performance This shouldn't be done every time, it should be polling based
|
||||
// Controllers often CONSTANTLY send data -> really bad
|
||||
// Maybe we can add timer usage
|
||||
while (i < state_count
|
||||
&& states[i].handle_controller != raw->header.hDevice
|
||||
) {
|
||||
++i;
|
||||
}
|
||||
|
||||
if (i >= state_count || !states[i].is_connected) {
|
||||
if (i >= state_count || !states[i].is_connected
|
||||
|| time - states[i].time_last_input_check < 5
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// @performance The code below is horrible, we need to probably make it controller dependant
|
||||
// Sometimes a controller may have a time component or a gyro which results in the controller
|
||||
// constantly sending input data
|
||||
ControllerInput controller = {};
|
||||
input_map_dualshock4(&controller, raw->data.hid.bRawData);
|
||||
input_set_controller_state(&states[i], &controller, time);
|
||||
|
||||
// @todo implement actual step usage
|
||||
bool is_same = simd_compare(
|
||||
raw->data.hid.bRawData,
|
||||
states[i].state.controller_state,
|
||||
raw->header.dwSize - sizeof(RAWINPUT),
|
||||
8
|
||||
);
|
||||
|
||||
if (!is_same) {
|
||||
memcpy(states[i].state.controller_state, raw->data.hid.bRawData, raw->header.dwSize - sizeof(RAWINPUT));
|
||||
|
||||
char buffer[100];
|
||||
int j = 0;
|
||||
for (j = 0; j < raw->header.dwSize - sizeof(RAWINPUT); ++j) {
|
||||
buffer[j] = raw->data.hid.bRawData[j];
|
||||
}
|
||||
|
||||
DEBUG_OUTPUT(buffer);
|
||||
}
|
||||
*/
|
||||
states[i].time_last_input_check = time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -351,7 +333,6 @@ void input_handle(LPARAM lParam, Input* __restrict states, int state_count, Ring
|
|||
input_raw_handle((RAWINPUT *) lpb, states, state_count, time);
|
||||
}
|
||||
|
||||
// @bug Somehow this function skips some inputs (input_handle works)!!!!!
|
||||
void input_handle_buffered(int buffer_size, Input* __restrict states, int state_count, RingMemory* ring, uint64 time)
|
||||
{
|
||||
uint32 cb_size;
|
||||
|
|
|
|||
|
|
@ -6,13 +6,14 @@
|
|||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
#ifndef TOS_INPUT_XINPUT_H
|
||||
#define TOS_INPUT_XINPUT_H
|
||||
#ifndef TOS_PLATFORM_WIN32_INPUT_XINPUT_H
|
||||
#define TOS_PLATFORM_WIN32_INPUT_XINPUT_H
|
||||
|
||||
#include <XInput.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "../../../input/Input.h"
|
||||
#include "../../../input/ControllerInput.h"
|
||||
#include "../../../stdlib/Types.h"
|
||||
#include "../../../utils/MathUtils.h"
|
||||
|
||||
|
|
@ -33,35 +34,6 @@ DWORD WINAPI XInputSetStateStub(DWORD, XINPUT_VIBRATION*) {
|
|||
global_persist x_input_set_state* XInputSetState_ = XInputSetStateStub;
|
||||
#define XInputSetState XInputSetState_
|
||||
|
||||
struct ControllerInput {
|
||||
uint32 id = 0;
|
||||
bool is_connected = false;
|
||||
|
||||
// After handling the state change the game loop should set this to false
|
||||
bool state_change = false;
|
||||
|
||||
// @question maybe make part of button
|
||||
bool up = false;
|
||||
bool down = false;
|
||||
bool left = false;
|
||||
bool right = false;
|
||||
|
||||
byte trigger_old[4];
|
||||
byte trigger[4];
|
||||
|
||||
// these are bitfields
|
||||
uint16 button_old;
|
||||
uint16 button;
|
||||
|
||||
int16 stickl_x = 0;
|
||||
int16 stickl_y = 0;
|
||||
bool stickl_press = false;
|
||||
|
||||
int16 stickr_x = 0;
|
||||
int16 stickr_y = 0;
|
||||
bool stickr_press = false;
|
||||
};
|
||||
|
||||
void xinput_load() {
|
||||
HMODULE lib = LoadLibraryExA((LPCSTR) "xinput1_4.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
if(!lib) {
|
||||
|
|
@ -107,9 +79,6 @@ ControllerInput* init_controllers()
|
|||
XINPUT_STATE controller_state;
|
||||
if (XInputGetState(controller_index, &controller_state) == ERROR_SUCCESS) {
|
||||
++c;
|
||||
|
||||
controllers[c].id = controller_index;
|
||||
controllers[c].is_connected = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -118,6 +87,7 @@ ControllerInput* init_controllers()
|
|||
|
||||
void handle_controller_input(ControllerInput* states)
|
||||
{
|
||||
/*
|
||||
uint32 controller_index = 0;
|
||||
while(states[controller_index].is_connected) {
|
||||
XINPUT_STATE controller_state;
|
||||
|
|
@ -127,7 +97,7 @@ void handle_controller_input(ControllerInput* states)
|
|||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
states[controller_index].up = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP;
|
||||
states[controller_index].down = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN;
|
||||
states[controller_index].left = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT;
|
||||
|
|
@ -153,10 +123,11 @@ void handle_controller_input(ControllerInput* states)
|
|||
states[controller_index].stickr_x = controller_state.Gamepad.sThumbRX;
|
||||
states[controller_index].stickr_y = controller_state.Gamepad.sThumbRY;
|
||||
states[controller_index].stickr_press = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB;
|
||||
*/
|
||||
|
||||
|
||||
++controller_index;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
#endif
|
||||
0
platform/win32/input/controller/DualSense.h
Normal file
0
platform/win32/input/controller/DualSense.h
Normal file
113
platform/win32/input/controller/DualShock4.h
Normal file
113
platform/win32/input/controller/DualShock4.h
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* Jingga
|
||||
*
|
||||
* @copyright Jingga
|
||||
* @license OMS License 2.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
#ifndef TOS_PLATFORM_WIN32_INPUT_CONTROLLER_DUALSHOCK4_H
|
||||
#define TOS_PLATFORM_WIN32_INPUT_CONTROLLER_DUALSHOCK4_H
|
||||
|
||||
#include "../../../../stdlib/Types.h"
|
||||
#include "../../../../input/ControllerInput.h"
|
||||
#include "../../../../utils/BitUtils.h"
|
||||
|
||||
inline
|
||||
void input_map_dualshock4(ControllerInput* controller, byte* data)
|
||||
{
|
||||
++data;
|
||||
|
||||
// 0 is not the origin -> need to shift
|
||||
controller->stick_left_x = *data++;
|
||||
controller->stick_left_x = OMS_MIN(controller->stick_left_x - 128, 127);
|
||||
controller->stick_left_y = *data++;
|
||||
controller->stick_left_y = OMS_MIN(controller->stick_left_y - 128, 127);
|
||||
|
||||
controller->stick_right_x = *data++;
|
||||
controller->stick_right_x = OMS_MIN(controller->stick_right_x - 128, 127);
|
||||
controller->stick_right_y = *data++;
|
||||
controller->stick_right_y = OMS_MIN(controller->stick_right_y - 128, 127);
|
||||
|
||||
controller->button_T = BITS_GET_8_L2R(*data, 0, 1);
|
||||
controller->button_C = BITS_GET_8_L2R(*data, 1, 1);
|
||||
controller->button_X = BITS_GET_8_L2R(*data, 2, 1);
|
||||
controller->button_S = BITS_GET_8_L2R(*data, 3, 1);
|
||||
|
||||
uint32 d_pad_state = BITS_GET_8_L2R(*data, 4, 4);
|
||||
if (d_pad_state == 8) {
|
||||
controller->dpad_left = 0;
|
||||
controller->dpad_right = 0;
|
||||
controller->dpad_up = 0;
|
||||
controller->dpad_down = 0;
|
||||
} else if (d_pad_state == 0) {
|
||||
controller->dpad_left = 0;
|
||||
controller->dpad_right = 0;
|
||||
controller->dpad_up = 127;
|
||||
controller->dpad_down = 0;
|
||||
} else if (d_pad_state == 1) {
|
||||
controller->dpad_left = 0;
|
||||
controller->dpad_right = 127;
|
||||
controller->dpad_up = 127;
|
||||
controller->dpad_down = 0;
|
||||
} else if (d_pad_state == 2) {
|
||||
controller->dpad_left = 0;
|
||||
controller->dpad_right = 127;
|
||||
controller->dpad_up = 0;
|
||||
controller->dpad_down = 0;
|
||||
} else if (d_pad_state == 3) {
|
||||
controller->dpad_left = 0;
|
||||
controller->dpad_right = 127;
|
||||
controller->dpad_up = 0;
|
||||
controller->dpad_down = 127;
|
||||
} else if (d_pad_state == 4) {
|
||||
controller->dpad_left = 0;
|
||||
controller->dpad_right = 0;
|
||||
controller->dpad_up = 0;
|
||||
controller->dpad_down = 127;
|
||||
} else if (d_pad_state == 5) {
|
||||
controller->dpad_left = 127;
|
||||
controller->dpad_right = 0;
|
||||
controller->dpad_up = 0;
|
||||
controller->dpad_down = 127;
|
||||
} else if (d_pad_state == 6) {
|
||||
controller->dpad_left = 127;
|
||||
controller->dpad_right = 0;
|
||||
controller->dpad_up = 0;
|
||||
controller->dpad_down = 0;
|
||||
} else if (d_pad_state == 7) {
|
||||
controller->dpad_left = 127;
|
||||
controller->dpad_right = 0;
|
||||
controller->dpad_up = 127;
|
||||
controller->dpad_down = 0;
|
||||
}
|
||||
|
||||
++data;
|
||||
|
||||
controller->stick_right_button = BITS_GET_8_L2R(*data, 0, 1);
|
||||
controller->stick_left_button = BITS_GET_8_L2R(*data, 1, 1);
|
||||
|
||||
controller->button_other[0] = BITS_GET_8_L2R(*data, 2, 1); // option
|
||||
controller->button_other[1] = BITS_GET_8_L2R(*data, 3, 1); // share
|
||||
|
||||
controller->shoulder_button_right = BITS_GET_8_L2R(*data, 6, 1); // tpad
|
||||
controller->shoulder_button_left = BITS_GET_8_L2R(*data, 7, 1); // ps
|
||||
|
||||
++data;
|
||||
|
||||
controller->button_other[2] = BITS_GET_8_L2R(*data, 6, 1);
|
||||
controller->button_other[3] = BITS_GET_8_L2R(*data, 7, 1);
|
||||
|
||||
++data;
|
||||
|
||||
controller->shoulder_trigger_right = *data++;
|
||||
controller->shoulder_trigger_left = *data++;
|
||||
|
||||
data += 3;
|
||||
|
||||
controller->gyro_x = *data++;
|
||||
controller->gyro_y = *data++;
|
||||
controller->gyro_z = *data++;
|
||||
}
|
||||
|
||||
#endif
|
||||
1
platform/win32/input/controller/XBoxS.h
Normal file
1
platform/win32/input/controller/XBoxS.h
Normal file
|
|
@ -0,0 +1 @@
|
|||
// Maybe: https://xboxdevwiki.net/Xbox_Input_Devices
|
||||
Loading…
Reference in New Issue
Block a user