X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=src%2Fvg%2Fvg_input.h;h=5b16287fbce20ca63238037d95a1b5712dad067b;hb=3dd767bb10e6fee9cbffeb185d1a9685810c17b5;hp=4818d52ab099c3aa10813e93104522cdc00f7eb9;hpb=95c9a820474d4974ee394f2fcfae82fbfa367dbd;p=vg.git diff --git a/src/vg/vg_input.h b/src/vg/vg_input.h index 4818d52..5b16287 100644 --- a/src/vg/vg_input.h +++ b/src/vg/vg_input.h @@ -1,9 +1,18 @@ /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */ +#ifndef VG_INPUT_H +#define VG_INPUT_H -static inline float vg_get_axis( const char *axis ); -static inline int vg_get_button( const char *button ); -static inline int vg_get_button_down( const char *button ); -static inline int vg_get_button_up( const char *button ); +#include "common.h" +#include "vg/vg_loader.h" + +VG_STATIC inline float vg_get_axis( const char *axis ); +VG_STATIC inline int vg_get_button( const char *button ); + +/* + * Cannot be used in fixed update + */ +VG_STATIC inline int vg_get_button_down( const char *button ); +VG_STATIC inline int vg_get_button_up( const char *button ); enum vg_button_state { @@ -13,144 +22,557 @@ enum vg_button_state k_button_state_none = 0 }; -GLFWgamepadstate vg_gamepad; -int vg_gamepad_ready = 0; -const char *vg_gamepad_name = NULL; -int vg_gamepad_id; +VG_STATIC struct input_binding +{ + const char *name; + + enum input_type + { + k_input_type_button, + k_input_type_axis, + k_input_type_axis_norm, + + k_input_type_unknown, + k_input_type_keyboard_key, + k_input_type_mouse_button, /* ? TODO */ + k_input_type_gamepad_axis, + k_input_type_gamepad_button + } + type; + + union + { + struct input_axis + { + u32 gamepad_axis, + keyboard_positive, + keyboard_negative; + + int gamepad_inverted; + float value; + } + axis; + + struct + { + u32 gamepad_id, keyboard_id; + int value, prev; + } + button; + }; + + int save_this; +} +vg_named_inputs[ 32 ]; +VG_STATIC u32 vg_named_input_count = 0; + +VG_STATIC void vg_create_unnamed_input( struct input_binding *bind, + enum input_type type ) +{ + memset( bind, 0, sizeof(struct input_binding) ); + + bind->name = "API DEFINED"; + bind->save_this = 0; + bind->type = type; + + bind->axis.gamepad_axis = -1; + bind->axis.keyboard_positive = -1; + bind->axis.keyboard_negative = -1; + bind->button.gamepad_id = -1; + bind->button.keyboard_id = -1; +} -/* TODO: Fix this... */ -enum EInputMode +VG_STATIC struct input_binding *vg_create_named_input( const char *name, + enum input_type type ) { - k_EInputMode_pc, - k_EInputMode_gamepad + struct input_binding *bind = &vg_named_inputs[ vg_named_input_count ++ ]; + memset( bind, 0, sizeof(struct input_binding) ); + + bind->name = name; + bind->save_this = 0; + bind->type = type; + + bind->axis.gamepad_axis = -1; + bind->axis.keyboard_positive = -1; + bind->axis.keyboard_negative = -1; + bind->button.gamepad_id = -1; + bind->button.keyboard_id = -1; + + return bind; } -vg_input_mode; -static struct axis_binding +VG_STATIC struct input_binding *vg_get_named_input( const char *name ) { - const char *name; - union - { - int positive; - int bind; - int axis; - }; - int negative; - - float value; + if( name[0] == '+' || name[0] == '-' ) + name ++; + + for( u32 i=0; iname, name ) ) + return bind; + } + + return NULL; } -vg_axis_binds[]; -static struct button_binding +struct input_en { - const char *name; - int bind; - - int value; int prev; + enum input_type type; + + const char *alias; + int id; +} +vg_all_bindable_inputs[] = +{ + {k_input_type_keyboard_key, "space", GLFW_KEY_SPACE}, + {k_input_type_keyboard_key, ";", GLFW_KEY_SEMICOLON}, + {k_input_type_keyboard_key, "-", GLFW_KEY_MINUS}, + {k_input_type_keyboard_key, ".", GLFW_KEY_PERIOD}, + {k_input_type_keyboard_key, ",", GLFW_KEY_COMMA}, + {k_input_type_keyboard_key, "=", GLFW_KEY_EQUAL}, + {k_input_type_keyboard_key, "[", GLFW_KEY_LEFT_BRACKET}, + {k_input_type_keyboard_key, "]", GLFW_KEY_RIGHT_BRACKET}, + {k_input_type_keyboard_key, "left", GLFW_KEY_LEFT}, + {k_input_type_keyboard_key, "right", GLFW_KEY_RIGHT}, + {k_input_type_keyboard_key, "up", GLFW_KEY_UP}, + {k_input_type_keyboard_key, "down", GLFW_KEY_DOWN}, + {k_input_type_keyboard_key, "shift", GLFW_KEY_LEFT_SHIFT}, + {k_input_type_keyboard_key, "control", GLFW_KEY_LEFT_CONTROL}, + {k_input_type_keyboard_key, "\2enter", GLFW_KEY_ENTER}, + {k_input_type_keyboard_key, "\2escape", GLFW_KEY_ESCAPE }, + + {k_input_type_gamepad_axis, "gp-lt", GLFW_GAMEPAD_AXIS_LEFT_TRIGGER}, + {k_input_type_gamepad_axis, "gp-rt", GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER}, + {k_input_type_gamepad_axis, "gp-ls-h", GLFW_GAMEPAD_AXIS_LEFT_X}, + {k_input_type_gamepad_axis, "gp-ls-v", GLFW_GAMEPAD_AXIS_LEFT_Y}, + {k_input_type_gamepad_axis, "gp-rs-h", GLFW_GAMEPAD_AXIS_RIGHT_X}, + {k_input_type_gamepad_axis, "gp-rs-v", GLFW_GAMEPAD_AXIS_RIGHT_Y}, + + {k_input_type_gamepad_button, "gp-a", GLFW_GAMEPAD_BUTTON_A}, + {k_input_type_gamepad_button, "gp-b", GLFW_GAMEPAD_BUTTON_B}, + {k_input_type_gamepad_button, "gp-x", GLFW_GAMEPAD_BUTTON_X}, + {k_input_type_gamepad_button, "gp-y", GLFW_GAMEPAD_BUTTON_Y}, + {k_input_type_gamepad_button, "gp-rb", GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER}, + {k_input_type_gamepad_button, "gp-lb", GLFW_GAMEPAD_BUTTON_LEFT_BUMPER}, + {k_input_type_gamepad_button, "gp-rs", GLFW_GAMEPAD_BUTTON_RIGHT_THUMB}, + {k_input_type_gamepad_button, "gp-ls", GLFW_GAMEPAD_BUTTON_LEFT_THUMB}, + {k_input_type_gamepad_button, "gp-dpad-down", GLFW_GAMEPAD_BUTTON_DPAD_DOWN}, + {k_input_type_gamepad_button, "gp-dpad-left", GLFW_GAMEPAD_BUTTON_DPAD_LEFT}, + {k_input_type_gamepad_button, "gp-dpad-right", GLFW_GAMEPAD_BUTTON_DPAD_RIGHT}, + {k_input_type_gamepad_button, "gp-dpad-up", GLFW_GAMEPAD_BUTTON_DPAD_UP}, + {k_input_type_gamepad_button, "\2gp-menu", GLFW_GAMEPAD_BUTTON_BACK} +}; + +VG_STATIC const char *vg_input_to_str( u32 input, enum input_type input_type ) +{ + if( input == -1 ) + return NULL; + + if( input_type == k_input_type_keyboard_key ) + { + if( (input >= GLFW_KEY_A) && (input <= GLFW_KEY_Z) ) + { + return &"a\0b\0c\0d\0e\0f\0g\0h\0i\0j\0k\0l\0m\0n\0o\0p\0" + "q\0r\0s\0t\0u\0v\0w\0x\0y\0z\0"[(input-GLFW_KEY_A)*2]; + } + + if( (input >= GLFW_KEY_0) && (input <= GLFW_KEY_9) ) + { + return &"0\0" "1\0" "2\0" "3\0" "4\0" + "5\0" "6\0" "7\0" "8\0" "9\0"[(input-GLFW_KEY_0)*2]; + } + } + + for( int i=0; itype == input_type) && (desc->id == input) ) + return desc->alias; + } + + return NULL; +} + +VG_STATIC enum input_type vg_str_to_input( const char *str, u32 *input ) +{ + if( !str ) + { + *input = -1; + return k_input_type_unknown; + } + + u32 len = strlen(str); + + if( len == 0 ) + { + *input = -1; + return k_input_type_unknown; + } + + if( len == 1 ) + { + u8 uch = str[0]; + + if( (uch >= (u8)'a') && (uch <= (u8)'z') ) + { + *input = GLFW_KEY_A + (uch-(u8)'a'); + return k_input_type_keyboard_key; + } + + if( (uch >= (u8)'0') && (uch <= (u8)'9') ) + { + *input = GLFW_KEY_0 + (uch-(u8)'0'); + return k_input_type_keyboard_key; + } + } + + for( int i=0; ialias, str ) ) + { + *input = desc->id; + return desc->type; + } + } + + *input = -1; + return k_input_type_unknown; +} + +VG_STATIC void vg_print_binding_info( struct input_binding *bind ) +{ + vg_info( " name: %s\n", bind->name ); + vg_info( " type: %s\n", (const char *[]){"button","axis","axis[0-1]"} + [ bind->type ] ); + vg_info( " save this? %d\n", bind->save_this ); + + if( (bind->type == k_input_type_axis) || + (bind->type == k_input_type_axis_norm) ) + { + vg_info( " gamepad_axis: %s\n", + vg_input_to_str(bind->axis.gamepad_axis, k_input_type_gamepad_axis)); + + vg_info( " keyboard_positive: %s\n", + vg_input_to_str(bind->axis.keyboard_positive, + k_input_type_keyboard_key )); + + vg_info( " keyboard_negative: %s\n", + vg_input_to_str(bind->axis.keyboard_negative, + k_input_type_keyboard_key )); + } + else + { + vg_info( " gamepad_id: %s\n", + vg_input_to_str(bind->button.gamepad_id, k_input_type_gamepad_button)); + vg_info( " keyboard_id: %s\n", + vg_input_to_str(bind->button.keyboard_id, + k_input_type_keyboard_key)); + } } -vg_button_binds[]; -#include "vg_config.h" +VG_STATIC void vg_apply_bind_str( struct input_binding *bind, + const char *mod, + const char *str ) +{ + int axis_mod = 0; + char modch = ' '; + if( (mod[0] == '-') || (mod[0] == '+') ) + { + axis_mod = 1; + modch = mod[0]; + mod ++; + } + + int invert = 0; + if( (str[0] == '-' ) ) + { + invert = 1; + str ++; + } + + u32 id; + enum input_type type = vg_str_to_input( str, &id ); + + if( bind->type == k_input_type_button ) + { + if( axis_mod ) + { + vg_error( "Cannot use axis modifiers on button input!\n" ); + return; + } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wreturn-type" + if( invert ) + { + vg_error( "Cannot invert button input!\n" ); + return; + } -static inline float vg_get_axis( const char *axis ) + if( type == k_input_type_keyboard_key ) + bind->button.keyboard_id = id; + else if( type == k_input_type_gamepad_button ) + bind->button.gamepad_id = id; + else + { + vg_error( "Unknown button or key '%s'\n", str ); + return; + } + } + else if( (bind->type == k_input_type_axis ) || + (bind->type == k_input_type_axis_norm)) + { + if( axis_mod ) + { + if( type == k_input_type_keyboard_key ) + { + if( invert ) + { + vg_error( "Cannot invert a keyboard key!\n" ); + return; + } + + if( modch == '+' ) + bind->axis.keyboard_positive = id; + else + bind->axis.keyboard_negative = id; + } + else + { + vg_error( "You can only bind keyboard keys to +- axises\n" ); + return; + } + } + else + { + if( type == k_input_type_gamepad_axis ) + { + bind->axis.gamepad_inverted = invert; + bind->axis.gamepad_axis = id; + } + else + { + vg_error( "You can only bind gamepad axises to this\n" ); + return; + } + } + } +} + +/* + * bind x jump + * bind a -horizontal + * bind d +horizontal + * bind -gp-ls-h horizontal + */ + +VG_STATIC int vg_rebind_input_cmd( int argc, const char *argv[] ) { - for( int i = 0; i < vg_list_size( vg_axis_binds ); i ++ ) - { - if( !strcmp( axis, vg_axis_binds[i].name ) ) - { - return vg_axis_binds[i].value; - } - } + if( argc == 0 ) + { + vg_info( "Usage: bind jump x\n" ); + vg_info( " bind -steerh j\n" ); + vg_info( " bind steerh gp-ls-h\n" ); + return 0; + } + + const char *str_bind_name = argv[0]; + struct input_binding *bind = vg_get_named_input( str_bind_name ); + + if( !bind ) + { + vg_error( "There is no bind with that name '%s'\n", str_bind_name ); + return 0; + } + + if( argc == 1 ) + { + vg_print_binding_info( bind ); + return 0; + } + + if( argc == 2 ) + { + const char *str_input_id = argv[1]; + + vg_apply_bind_str( bind, str_bind_name, str_input_id ); + return 0; + } + + return 0; } -static inline struct button_binding *vg_get_button_ptr( const char *button ) +VG_STATIC void vg_input_update( u32 num, struct input_binding *binds ) { - for( int i=0; itype == k_input_type_button ) + { + bind->button.prev = bind->button.value; + bind->button.value = 0; + } + } + + return; + } + + for( i32 i=0; itype == k_input_type_button ) + { + bind->button.prev = bind->button.value; + bind->button.value = 0; + + if( bind->button.gamepad_id != -1 ) + bind->button.value |= vg.gamepad.buttons[ bind->button.gamepad_id ]; + + if( bind->button.keyboard_id != -1 ) + bind->button.value |= glfwGetKey( vg.window, + bind->button.keyboard_id ); + } + else if( bind->type == k_input_type_axis ) + { + float keyboard_value = 0.0f, + gamepad_value = 0.0f; + + if( bind->axis.keyboard_positive != -1 ) + if( glfwGetKey( vg.window, bind->axis.keyboard_positive ) ) + keyboard_value += 1.0f; + + if( bind->axis.keyboard_negative != -1 ) + if( glfwGetKey( vg.window, bind->axis.keyboard_negative ) ) + keyboard_value -= 1.0f; + + if( bind->axis.gamepad_axis != -1 ) + { + gamepad_value = vg.gamepad.axes[ bind->axis.gamepad_axis ]; + if( bind->axis.gamepad_inverted ) + gamepad_value *= -1.0f; + } + + if( fabsf(gamepad_value) <= 0.01f ) + gamepad_value = 0.0f; + + if( fabsf(keyboard_value) > fabsf(gamepad_value) ) + bind->axis.value = keyboard_value; + else + bind->axis.value = gamepad_value; + } + else if( bind->type == k_input_type_axis_norm ) + { + float value = -1.0f; + if( bind->axis.keyboard_positive != -1 ) + if( glfwGetKey( vg.window, bind->axis.keyboard_positive )) + value = 1.0f; + + if( bind->axis.gamepad_axis != -1 ) + value = vg_maxf( value, vg.gamepad.axes[bind->axis.gamepad_axis] ); + + bind->axis.value = value * 0.5f + 0.5f; + } + } +} + +VG_STATIC int vg_console_enabled(void); +VG_STATIC int vg_input_button_down( struct input_binding *bind ) +{ + if( bind->button.value && !bind->button.prev ) + return 1; + return 0; +} +#if 0 + +VG_STATIC float vg_get_axis( const char *axis ) +{ + return 0.0f; } -#pragma GCC diagnostic pop -static int vg_console_enabled(void); -static inline int vg_get_button( const char *button ) +VG_STATIC void vg_get_button_states( const char *name, int *cur, int *prev ) { - return vg_get_button_ptr( button )->value && !vg_console_enabled(); } -static inline int vg_get_button_down( const char *button ) +VG_STATIC int vg_get_button( const char *button ) { - struct button_binding *bind = vg_get_button_ptr( button ); - return bind->value & (bind->value ^ bind->prev) && !vg_console_enabled(); + return 0; } -static inline int vg_get_button_up( const char *button ) +VG_STATIC int vg_get_button_down( const char *button ) { - struct button_binding *bind = vg_get_button_ptr( button ); - return bind->prev & (bind->value ^ bind->prev) && !vg_console_enabled(); + return 0; } -static inline enum vg_button_state vg_get_button_state( const char *button ) +VG_STATIC int vg_get_button_up( const char *button ) +{ + return 0; +} + +VG_STATIC enum vg_button_state vg_get_button_state( const char *button ) { if(vg_get_button_down( button )) return k_button_state_down; if(vg_get_button_up( button )) return k_button_state_up; if(vg_get_button( button )) return k_button_state_pressed; return k_button_state_none; } +#endif -static inline int key_is_keyboard( int const id ) +void vg_update_inputs(void) { - vg_static_assert( GLFW_MOUSE_BUTTON_LAST < GLFW_KEY_SPACE, - "GLFW: Mouse has too many buttons" ); - return id > GLFW_MOUSE_BUTTON_LAST; -} + if( !glfwGetGamepadState( GLFW_JOYSTICK_1, &vg.gamepad) ) + { + vg.gamepad_ready = 0; + vg.gamepad.axes[ GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER ] = -1.0f; + vg.gamepad.axes[ GLFW_GAMEPAD_AXIS_LEFT_TRIGGER ] = -1.0f; + } -int get_button_cross_device( int const id ) -{ - if( key_is_keyboard( id ) ) - return glfwGetKey( vg_window, id ); - else - return glfwGetMouseButton( vg_window, id ) == GLFW_PRESS; + /* update all inputs */ + vg_input_update( vg_named_input_count, vg_named_inputs ); } -void vg_update_inputs(void) +VG_STATIC void vg_gamepad_init(void) { - /* Update button inputs */ - for( int i = 0; i < vg_list_size( vg_button_binds ); i ++ ) - { - struct button_binding *binding = vg_button_binds + i; - binding->prev = binding->value; - - if( vg_input_mode == k_EInputMode_pc ) - { - binding->value = get_button_cross_device( binding->bind ); - } - else - { - binding->value = vg_gamepad.buttons[ binding->bind ]; - } - } - - /* Update axis inputs */ - for( int i = 0; i < vg_list_size( vg_axis_binds ); i ++ ) - { - struct axis_binding *binding = vg_axis_binds + i; - - if( vg_input_mode == k_EInputMode_pc ) - { - binding->value = get_button_cross_device( binding->positive ); - binding->value -= get_button_cross_device( binding->negative ); - } - else - { - binding->value = vg_gamepad.axes[ binding->bind ]; - } - } + vg_acquire_thread_sync(); + + vg_function_push( (struct vg_cmd) + { + .name = "bind", + .function = vg_rebind_input_cmd + }); + + for( int id=0; id<=GLFW_JOYSTICK_LAST; id ++ ) + { + if( glfwJoystickPresent( id ) ) + { + vg_info( "Joystick found: '%s'\n", glfwGetJoystickName(id) ); + } + + if( glfwJoystickIsGamepad( id ) ) + { + vg.gamepad_name = glfwGetGamepadName( id ); + vg_success( "Gamepad mapping registered: %s\n", vg.gamepad_name ); + + /* This path usually only gets chosen when starting outside of steam */ + if( !strcmp(vg.gamepad_name, "Steam Controller") ) + vg.gamepad_use_trackpad_look = 1; + + vg.gamepad_ready = 1; + vg.gamepad_id = id; + break; + } + } + + vg.gamepad.axes[ GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER ] = -1.0f; + vg.gamepad.axes[ GLFW_GAMEPAD_AXIS_LEFT_TRIGGER ] = -1.0f; + + vg_release_thread_sync(); } + +#endif