Files
coven/input/input.jai

397 lines
8.1 KiB
Plaintext

#load "sdl_input.jai";
LEFT_STICK_DEADZONE :: 0.239;
RIGHT_STICK_DEADZONE :: 0.265;
Key_Flags :: enum_flags u8 {
NONE :: 0;
DOWN :: 1;
START :: 2;
END :: 4;
EATEN :: 8;
}
Key_Code :: enum {
INVALID :: 0;
A;
B;
C;
D;
E;
F;
G;
H;
I;
J;
K;
L;
M;
N;
O;
P;
Q;
R;
S;
T;
U;
V;
W;
X;
Y;
Z;
ZERO;
ONE;
TWO;
THREE;
FOUR;
FIVE;
SIX;
SEVEN;
EIGHT;
NINE;
F1;
F2;
F3;
F4;
F5;
F6;
F7;
F8;
F9;
F10;
F11;
F12;
SPACE;
BACKSPACE;
RETURN;
TAB;
SHIFT;
CTRL;
ALT;
DELETE;
TILDE;
ESCAPE;
LEFT;
RIGHT;
UP;
DOWN;
MOUSE_LEFT;
MOUSE_RIGHT;
KEYS_MAX;
}
Gamepad_Button :: enum {
SPECIAL_BOTTOM;
SPECIAL_TOP;
SPECIAL_LEFT;
SPECIAL_RIGHT;
LEFT_STICK_LEFT;
LEFT_STICK_RIGHT;
LEFT_STICK_UP;
LEFT_STICK_DOWN;
LEFT_STICK_BUTTON;
RIGHT_STICK_BUTTON;
DPAD_LEFT;
DPAD_RIGHT;
DPAD_UP;
DPAD_DOWN;
LEFT_BUMPER;
RIGHT_BUMPER;
LEFT_TRIGGER;
RIGHT_TRIGGER;
GAMEPAD_MAX;
}
Gamepad :: struct {
id : s32;
left_stick_x : float;
left_stick_y : float;
right_stick_x : float;
right_stick_y : float;
buttons : [Gamepad_Button.GAMEPAD_MAX] Key_Flags;
}
MAX_GAMEPADS :: 4;
MAX_MAPPINGS :: 4;
Action :: enum {}
Action_Mapping :: struct {
gamepad_buttons: [MAX_MAPPINGS] Gamepad_Button;
keys: [MAX_MAPPINGS] Key_Code;
gamepad_mapping_count: s32;
key_mapping_count: s32;
}
Last_Touched_State :: enum {
KEYBOARD_AND_MOUSE;
GAMEPAD;
}
Input_State :: struct {
exit : bool;
action_mappings: [..] Action_Mapping;
keys: [Key_Code.KEYS_MAX] Key_Flags;
mouse : struct {
x : float;
y : float;
delta_x : float;
delta_y : float;
first: bool = true;
wheel: float;
}
normalized_viewport_mouse_position: Vector2;
viewport_mouse_position: Vector2;
gamepads: [MAX_GAMEPADS] Gamepad;
num_gamepads: s32;
has_char : bool;
current_char: s8;
last_touched: Last_Touched_State;
}
init_input :: () {
engine.input = .{};
engine.input.has_char = false;
init_sdl_input();
}
update_key_state :: (key: Key_Code, down: bool) {
using engine.input;
flags := keys[key];
if down {
if !(flags & Key_Flags.DOWN) {
flags = Key_Flags.DOWN | Key_Flags.START;
}
} else {
flags = Key_Flags.END;
}
keys[key] = flags;
engine.input.last_touched = .KEYBOARD_AND_MOUSE;
}
update_gamepad_state :: (gamepad: *Gamepad, button: Gamepad_Button, down: bool) {
flags := gamepad.buttons[button];
if down {
if !(flags & Key_Flags.DOWN) {
flags = Key_Flags.DOWN | Key_Flags.START;
engine.input.last_touched = .GAMEPAD;
}
} else if flags & Key_Flags.DOWN {
flags = Key_Flags.END;
}
gamepad.buttons[button] = flags;
}
update_input :: () {
engine.input.mouse.delta_x = 0.0;
engine.input.mouse.delta_y = 0.0;
engine.input.mouse.wheel = 0.0;
engine.input.has_char = false;
remove_all_temp_key_flags(*engine.input);
update_sdl_input();
update_gamepad_input();
#if !EDITOR {
engine.input.viewport_mouse_position.x = engine.input.mouse.x;
engine.input.viewport_mouse_position.y = engine.input.mouse.y;
engine.input.normalized_viewport_mouse_position = engine.input.viewport_mouse_position / Vector2.{xx engine.renderer.render_target_width, xx engine.renderer.render_target_height};
}
}
remove_all_temp_key_flags :: (using input_state: *Input_State) {
for 0..Key_Code.KEYS_MAX - 1 {
keys[it] &= ~Key_Flags.START;
keys[it] &= ~Key_Flags.END;
keys[it] &= ~Key_Flags.EATEN;
}
for g: 0..num_gamepads-1 {
for 0..Gamepad_Button.GAMEPAD_MAX-1 {
gamepads[g].buttons[it] &= ~Key_Flags.START;
gamepads[g].buttons[it] &= ~Key_Flags.END;
}
}
}
eat_all_input :: (using input_state: *Input_State) {
for 0..Key_Code.KEYS_MAX - 1 {
eat_key(cast(Key_Code)it);
}
}
eat_mouse_input :: (using input_state: *Input_State) {
eat_key(.MOUSE_LEFT);
eat_key(.MOUSE_RIGHT);
}
eat_key :: (key: Key_Code) {
engine.input.keys[key] |= Key_Flags.EATEN;
}
action_down :: (action: Action) -> bool {
mapping := engine.input.action_mappings[action];
for 0..mapping.key_mapping_count-1 {
if key_down(mapping.keys[it]) {
return true;
}
}
for 0..mapping.gamepad_mapping_count-1 {
if gamepad_down(0, mapping.gamepad_buttons[it]) {
return true;
}
}
return false;
}
action_pressed :: (action: Action) -> bool {
mapping := engine.input.action_mappings[action];
for 0..mapping.key_mapping_count-1 {
if key_pressed(mapping.keys[it]) {
return true;
}
}
for 0..mapping.gamepad_mapping_count-1 {
if gamepad_pressed(0, mapping.gamepad_buttons[it]) {
return true;
}
}
return false;
}
action_up :: (action: Action) -> bool {
mapping := engine.input.action_mappings[action];
for 0..mapping.key_mapping_count-1 {
if key_up(mapping.keys[it]) {
return true;
}
}
for 0..mapping.gamepad_mapping_count-1 {
if gamepad_up(0, mapping.gamepad_buttons[it]) {
return true;
}
}
return false;
}
get_mouse_delta_x :: inline () -> float {
return engine.input.mouse.delta_x;
}
get_mouse_delta_y :: inline () -> float {
return engine.input.mouse.delta_y;
}
get_mouse_delta :: () -> float, float {
return get_mouse_delta_x(), get_mouse_delta_y();
}
get_mouse_wheel_input :: () -> float {
return engine.input.mouse.wheel;
}
get_horizontal_axis :: () -> float {
if #complete engine.input.last_touched == {
case .KEYBOARD_AND_MOUSE;
if key_pressed(.A) || key_pressed(.LEFT) return -1.0;
else if key_pressed(.D) || key_pressed(.RIGHT) return 1.0;
else return 0.0;
case .GAMEPAD;
if gamepad_pressed(0, .DPAD_LEFT) return -1.0;
else if gamepad_pressed(0, .DPAD_RIGHT) return 1.0;
return engine.input.gamepads[0].left_stick_x;
}
}
get_vertical_axis :: () -> float {
if #complete engine.input.last_touched == {
case .KEYBOARD_AND_MOUSE;
if key_pressed(.S) || key_pressed(.DOWN) return -1.0;
else if key_pressed(.W) || key_pressed(.UP) return 1.0;
else return 0.0;
case .GAMEPAD;
if gamepad_pressed(0, .DPAD_DOWN) return -1.0;
else if gamepad_pressed(0, .DPAD_UP) return 1.0;
return -engine.input.gamepads[0].left_stick_y;
}
}
get_right_horizontal_axis :: () -> float {
if #complete engine.input.last_touched == {
case .KEYBOARD_AND_MOUSE;
return engine.input.mouse.delta_x;
case .GAMEPAD;
return engine.input.gamepads[0].right_stick_x;
}
}
get_right_vertical_axis :: () -> float {
if #complete engine.input.last_touched == {
case .KEYBOARD_AND_MOUSE;
return engine.input.mouse.delta_y;
case .GAMEPAD;
return -engine.input.gamepads[0].right_stick_y;
}
}
key_down :: (key: Key_Code) -> bool {
flags := engine.input.keys[key];
return flags & .START && !(flags & .EATEN);
}
key_pressed :: (key: Key_Code) -> bool {
flags := engine.input.keys[key];
return flags & .DOWN && !(flags & .EATEN);
}
key_up :: (key: Key_Code) -> bool {
flags := engine.input.keys[key];
return flags & .END && !(flags & .EATEN);
}
gamepad_down :: (index: s32, button: Gamepad_Button) -> bool {
return cast(bool)(engine.input.gamepads[index].buttons[button] & .START);
}
gamepad_pressed :: (index: s32, button: Gamepad_Button) -> bool {
return cast(bool)(engine.input.gamepads[index].buttons[button] & .DOWN);
}
gamepad_up :: (index: s32, button: Gamepad_Button) -> bool {
return cast(bool)(engine.input.gamepads[index].buttons[button] & .END);
}