#define VG_MAX_CONTROLLERS 4
-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 );
VG_STATIC float controller_deadzone = 0.05f;
-enum vg_button_state{
- k_button_state_down = 1,
- k_button_state_up = 3,
- k_button_state_pressed = 2,
- k_button_state_none = 0
-};
-
-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{
- SDL_GameControllerAxis gamepad_axis;
- SDL_Keycode keyboard_positive,
- keyboard_negative;
-
- int gamepad_inverted;
- float value;
- }
- axis;
-
- struct{
- SDL_GameControllerButton gamepad_id;
- SDL_Keycode keyboard_id;
- int mouse_id;
- int value, prev;
- }
- button;
- };
-
- int save_this;
-};
-
struct
{
- const u8 *sdl_keys;
- struct input_binding named_inputs[ 32 ];
- u32 named_input_count;
+ const u8 *sdl_keys;
struct vg_controller{
SDL_GameController *handle; /* handle for controller. NULL if unused */
SDL_JoystickID instance_id; /* uid used in events */
- enum evg_controller_type{
- k_vg_controller_type_standard,
- k_vg_controller_type_trackpads
- }
- type;
-
float axises[ SDL_CONTROLLER_AXIS_MAX ];
- int buttons[ SDL_CONTROLLER_BUTTON_MAX ];
+ u32 buttons[ SDL_CONTROLLER_BUTTON_MAX ];
}
controllers[4];
/* what the user is currently using. the keyboard and controller are still
* active simultaneously, but this reflects what the UI should show */
- enum userinput_method{
- k_userinput_method_xbox,
- k_userinput_method_playstation,
- k_userinput_method_steamgeneric,
- k_userinput_method_kbm
- }
- input_method;
-}
-static vg_input;
-
-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;
- bind->button.mouse_id = -1;
-}
-
-VG_STATIC struct input_binding *vg_create_named_input( const char *name,
- enum input_type type )
-{
- struct input_binding *bind =
- &vg_input.named_inputs[ vg_input.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;
- bind->button.mouse_id = -1;
-
- return bind;
-}
-
-VG_STATIC struct input_binding *vg_get_named_input( const char *name )
-{
- if( name[0] == '+' || name[0] == '-' )
- name ++;
-
- for( u32 i=0; i<vg_input.named_input_count; i++ ){
- struct input_binding *bind = &vg_input.named_inputs[i];
- if( !strcmp( bind->name, name ) )
- return bind;
- }
-
- return NULL;
-}
-
-struct input_en
-{
- enum input_type type;
-
- const char *alias;
- int id;
-}
-vg_all_bindable_inputs[] =
-{
- {k_input_type_keyboard_key, "space", SDLK_SPACE},
- {k_input_type_keyboard_key, ";", SDLK_SEMICOLON},
- {k_input_type_keyboard_key, "-", SDLK_MINUS},
- {k_input_type_keyboard_key, ".", SDLK_PERIOD},
- {k_input_type_keyboard_key, ",", SDLK_COMMA},
- {k_input_type_keyboard_key, "=", SDLK_EQUALS},
- {k_input_type_keyboard_key, "[", SDLK_LEFTBRACKET},
- {k_input_type_keyboard_key, "]", SDLK_RIGHTBRACKET},
- {k_input_type_keyboard_key, "left", SDLK_LEFT},
- {k_input_type_keyboard_key, "right", SDLK_RIGHT},
- {k_input_type_keyboard_key, "up", SDLK_UP},
- {k_input_type_keyboard_key, "down", SDLK_DOWN},
- {k_input_type_keyboard_key, "shift", SDLK_LSHIFT},
- {k_input_type_keyboard_key, "control", SDLK_LCTRL},
- {k_input_type_keyboard_key, "\2enter", SDLK_RETURN},
- {k_input_type_keyboard_key, "\2escape", SDLK_ESCAPE },
-
- {k_input_type_gamepad_axis, "gp-lt", SDL_CONTROLLER_AXIS_TRIGGERLEFT},
- {k_input_type_gamepad_axis, "gp-rt", SDL_CONTROLLER_AXIS_TRIGGERRIGHT},
- {k_input_type_gamepad_axis, "gp-ls-h", SDL_CONTROLLER_AXIS_LEFTX},
- {k_input_type_gamepad_axis, "gp-ls-v", SDL_CONTROLLER_AXIS_LEFTY},
- {k_input_type_gamepad_axis, "gp-rs-h", SDL_CONTROLLER_AXIS_RIGHTX},
- {k_input_type_gamepad_axis, "gp-rs-v", SDL_CONTROLLER_AXIS_RIGHTY},
-
- {k_input_type_gamepad_button, "gp-a", SDL_CONTROLLER_BUTTON_A},
- {k_input_type_gamepad_button, "gp-b", SDL_CONTROLLER_BUTTON_B},
- {k_input_type_gamepad_button, "gp-x", SDL_CONTROLLER_BUTTON_X},
- {k_input_type_gamepad_button, "gp-y", SDL_CONTROLLER_BUTTON_Y},
- {k_input_type_gamepad_button, "gp-rb", SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
- {k_input_type_gamepad_button, "gp-lb", SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
- {k_input_type_gamepad_button, "gp-rs", SDL_CONTROLLER_BUTTON_RIGHTSTICK},
- {k_input_type_gamepad_button, "gp-ls", SDL_CONTROLLER_BUTTON_LEFTSTICK},
- {k_input_type_gamepad_button, "gp-dpad-down", SDL_CONTROLLER_BUTTON_DPAD_DOWN},
- {k_input_type_gamepad_button, "gp-dpad-left", SDL_CONTROLLER_BUTTON_DPAD_LEFT},
- {k_input_type_gamepad_button,"gp-dpad-right",SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
- {k_input_type_gamepad_button, "gp-dpad-up", SDL_CONTROLLER_BUTTON_DPAD_UP},
- {k_input_type_gamepad_button, "\2gp-menu", SDL_CONTROLLER_BUTTON_BACK},
-
- {k_input_type_mouse_button, "mouse1", SDL_BUTTON_LEFT },
- {k_input_type_mouse_button, "mouse2", SDL_BUTTON_RIGHT }
-};
-
-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 >= SDLK_a) && (input <= SDLK_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-SDLK_a)*2];
- }
-
- if( (input >= SDLK_0) && (input <= SDLK_9) ){
- return &"0\0" "1\0" "2\0" "3\0" "4\0"
- "5\0" "6\0" "7\0" "8\0" "9\0"[(input-SDLK_0)*2];
- }
- }
-
- for( int i=0; i<vg_list_size(vg_all_bindable_inputs); i++ ){
- struct input_en *desc = &vg_all_bindable_inputs[i];
-
- if( (desc->type == 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 = SDLK_a + (uch-(u8)'a');
- return k_input_type_keyboard_key;
- }
-
- if( (uch >= (u8)'0') && (uch <= (u8)'9') ){
- *input = SDLK_0 + (uch-(u8)'0');
- return k_input_type_keyboard_key;
- }
- }
-
- for( int i=0; i<vg_list_size(vg_all_bindable_inputs); i++ ){
- struct input_en *desc = &vg_all_bindable_inputs[i];
-
- if( !strcmp( desc->alias, 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_info( " mouse_id: %s\n",
- vg_input_to_str(bind->button.mouse_id,
- k_input_type_mouse_button));
- }
-}
-
-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;
- }
-
- if( invert ){
- vg_error( "Cannot invert button input!\n" );
- return;
- }
-
- if( type == k_input_type_keyboard_key )
- bind->button.keyboard_id = id;
- else if( type == k_input_type_mouse_button )
- bind->button.mouse_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 jump x
- * bind -horizontal a
- * bind +horizontal d
- * bind horizontal -gp-ls-h
- */
-
-VG_STATIC int vg_rebind_input_cmd( int argc, const char *argv[] )
-{
- 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;
-}
-
-VG_STATIC void vg_rebind_input_cmd_poll( int argc, const char *argv[] )
-{
- if( argc == 0 )
- return;
-
- const char *str_bind_name = argv[0];
-
- if( argc == 1 ){
- for( u32 i=0; i<vg_input.named_input_count; i++ ){
- struct input_binding *bind = &vg_input.named_inputs[i];
- console_suggest_score_text( bind->name, argv[argc-1], 0 );
- }
- }
- else if( argc == 2 ){
- for( int i=0; i<vg_list_size(vg_all_bindable_inputs); i++ ){
- struct input_en *desc = &vg_all_bindable_inputs[i];
- console_suggest_score_text( desc->alias, argv[argc-1], 0 );
- }
+ enum input_method{
+ k_input_method_kbm,
+ k_input_method_controller
}
+ display_input_method;
+ SDL_GameControllerType display_input_type;
}
+static vg_input = { .active_controller_index = -2 };
VG_STATIC u8 vg_getkey( SDL_Keycode kc )
{
return vg_input.sdl_keys[sc];
}
-VG_STATIC void vg_input_update( u32 num, struct input_binding *binds )
-{
- if( vg_console.enabled ){
- for( i32 i=0; i<num; i++ ){
- struct input_binding *bind = &binds[i];
-
- if( bind->type == k_input_type_button ){
- bind->button.prev = bind->button.value;
- bind->button.value = 0;
- }
- }
-
- return;
- }
-
- struct vg_controller *acontroller = NULL;
-
- if( vg_input.active_controller_index != -1 )
- acontroller = &vg_input.controllers[vg_input.active_controller_index];
-
- for( i32 i=0; i<num; i++ ){
- struct input_binding *bind = &binds[i];
-
- if( bind->type == k_input_type_button ){
- bind->button.prev = bind->button.value;
- bind->button.value = 0;
-
- if( acontroller && (bind->button.gamepad_id != -1) )
- bind->button.value |= acontroller->buttons[bind->button.gamepad_id];
-
- if( bind->button.keyboard_id != -1 )
- bind->button.value |= vg_getkey( bind->button.keyboard_id );
-
- if( bind->button.mouse_id != -1 ){
- if(SDL_GetMouseState(NULL,NULL) & SDL_BUTTON(bind->button.mouse_id))
- bind->button.value |= 1;
- }
- }
- else if( bind->type == k_input_type_axis ){
- float keyboard_value = 0.0f,
- gamepad_value = 0.0f;
-
- if( bind->axis.keyboard_positive != -1 )
- if( vg_getkey( bind->axis.keyboard_positive ) )
- keyboard_value += 1.0f;
-
- if( bind->axis.keyboard_negative != -1 )
- if( vg_getkey( bind->axis.keyboard_negative ) )
- keyboard_value -= 1.0f;
-
- if( acontroller && (bind->axis.gamepad_axis != -1) ){
- gamepad_value = acontroller->axises[ bind->axis.gamepad_axis ];
-
- if( bind->axis.gamepad_inverted )
- gamepad_value *= -1.0f;
- }
-
- float deadz = vg_clampf( controller_deadzone, 0.0f, 0.999f ),
- high = vg_maxf( 0.0f, fabsf(gamepad_value) - deadz ),
- norm = high / (1.0f-deadz);
-
- gamepad_value = vg_signf( gamepad_value ) * norm;
-
- 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 = 0.0f;
- if( bind->axis.keyboard_positive != -1 )
- if( vg_getkey( bind->axis.keyboard_positive ))
- value = 1.0f;
-
- if( acontroller && (bind->axis.gamepad_axis != -1) ){
- float value1 = acontroller->axises[bind->axis.gamepad_axis];
- value = vg_maxf( value, value1 );
- }
-
- bind->axis.value = value;
- }
- }
-}
-
/*
* takes SDL device index, and tries to open that on any free channel
*/
-VG_STATIC void vg_open_gamecontroller( Sint32 index )
+VG_STATIC int vg_open_gamecontroller( Sint32 index )
{
struct vg_controller *controller = NULL;
int vg_id = 0;
if( instance_id == -1 ){
vg_error( ". Invalid device index (vg_open_gamecontroller)\n" );
- return;
+ return -1;
}
for( int j=0; j<VG_MAX_CONTROLLERS; j++ ){
if( esta->instance_id == instance_id ){
vg_warn( " . SDL_JoystickID[%d] is already in open at index #%d\n",
esta->instance_id, j );
- return;
+ return -1;
}
}
else{
vg_success(
" . opened SDL_JoystickID[%d] as controller '%s' at index #%d\n",
instance_id, name, vg_id );
+
+ for( u32 i=0; i< SDL_CONTROLLER_BUTTON_MAX; i++ )
+ controller->buttons[i] = 0;
+
+ for( u32 i=0; i< SDL_CONTROLLER_AXIS_MAX; i++ )
+ controller->axises[i] = 0.0f;
controller->axises[ SDL_CONTROLLER_AXIS_TRIGGERLEFT ] = -1.0f;
controller->axises[ SDL_CONTROLLER_AXIS_TRIGGERRIGHT ] = -1.0f;
+
+ if( vg_input.active_controller_index == -2 ){
+ vg_input.active_controller_index = vg_id;
+ vg_input.display_input_method = k_input_method_controller;
+ vg_input.display_input_type =
+ SDL_GameControllerGetType( controller->handle );
+ }
+
+ return vg_id;
}
else{
vg_error( ". Failed to attach game controller '%s'. Reason: %s\n",
- name, SDL_GetError() );
+ name, SDL_GetError() );
+ return -1;
}
}
else{
vg_error( ". Too many controllers open! ignoring '%s'\n", name );
-
+ return -1;
}
}
if( vg_input.active_controller_index == i ){
vg_input.active_controller_index = -1;
- vg_info( " . active controller is now keyboard and mouse\n" );
+ vg_input.display_input_method = k_input_method_kbm;
+ vg_info( "display_input: k_input_method_kbm\n" );
}
break;
}
if( ev->caxis.which == esta->instance_id ){
float value = (float)ev->caxis.value / 32767.0f;
+
+ if( ev->caxis.axis == SDL_CONTROLLER_AXIS_LEFTX ||
+ ev->caxis.axis == SDL_CONTROLLER_AXIS_LEFTY ||
+ ev->caxis.axis == SDL_CONTROLLER_AXIS_RIGHTX ||
+ ev->caxis.axis == SDL_CONTROLLER_AXIS_RIGHTY )
+ {
+ float deadz = vg_clampf( controller_deadzone, 0.0f, 0.999f ),
+ high = vg_maxf( 0.0f, fabsf(value) - deadz );
+
+ value = vg_signf(value) * (high / (1.0f-deadz));
+ }
+
esta->axises[ ev->caxis.axis ] = value;
break;
}
else if( ev->type == SDL_CONTROLLERBUTTONDOWN ){
struct vg_controller *active = NULL;
- if( vg_input.active_controller_index != -1 )
+ if( vg_input.active_controller_index >= 0 )
active = &vg_input.controllers[vg_input.active_controller_index];
if( !active || (ev->cbutton.which != active->instance_id) ){
active = NULL;
vg_input.active_controller_index = -1;
+ vg_input.display_input_method = k_input_method_kbm;
for( int i=0; i<VG_MAX_CONTROLLERS; i++ ){
if( vg_input.controllers[i].instance_id == ev->cbutton.which ){
active = &vg_input.controllers[i];
vg_input.active_controller_index = i;
+ vg_input.display_input_type =
+ SDL_GameControllerGetType(active->handle);
break;
}
}
}
}
- if( active )
+ if( active ){
+ if( vg_input.display_input_method != k_input_method_controller ){
+ vg_input.display_input_method = k_input_method_controller;
+ vg_info( "display_input: k_input_method_controller\n" );
+ }
active->buttons[ ev->cbutton.button ] = 1;
+ }
}
else if( ev->type == SDL_CONTROLLERBUTTONUP ){
for( int i=0; i<VG_MAX_CONTROLLERS; i++ ){
int count;
vg_input.sdl_keys = SDL_GetKeyboardState( &count );
- if( vg_input.input_method != k_userinput_method_kbm ){
+ if( vg_input.display_input_method != k_input_method_kbm ){
/* check for giving keyboard priority */
for( int i=0; i<count; i++ ){
if( vg_input.sdl_keys[i] ){
- vg_input.input_method = k_userinput_method_kbm;
+ vg_input.display_input_method = k_input_method_kbm;
+ vg_info( "display_input: k_input_method_kbm (keyboard %d)\n", i );
break;
}
}
/* check for giving mouse priority */
if( SDL_GetMouseState(NULL,NULL) &
- (SDL_BUTTON(SDL_BUTTON_LEFT)|SDL_BUTTON(SDL_BUTTON_RIGHT)) )
+ (SDL_BUTTON(SDL_BUTTON_LEFT)|SDL_BUTTON(SDL_BUTTON_RIGHT)|
+ SDL_BUTTON(SDL_BUTTON_MIDDLE)) )
{
- vg_input.input_method = k_userinput_method_kbm;
+ vg_input.display_input_method = k_input_method_kbm;
+ vg_info( "display_input: k_input_method_kbm (mouse)\n" );
}
}
-
- /* update all inputs */
- vg_input_update( vg_input.named_input_count, vg_input.named_inputs );
-}
-
-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;
}
VG_STATIC void async_vg_input_init( void *payload, u32 size )
{
- vg_console_reg_cmd( "bind", vg_rebind_input_cmd, vg_rebind_input_cmd_poll );
-
VG_VAR_F32( controller_deadzone, flags=VG_VAR_PERSISTENT );
vg_info( "Checking for controllers\n" );