k_button_state_none = 0
};
-/* TODO: Fix this... */
-enum EInputMode
-{
- k_EInputMode_pc,
- k_EInputMode_gamepad
-}
-vg_input_mode;
-
-VG_STATIC struct axis_binding
+VG_STATIC struct input_binding
{
const char *name;
- union
- {
- int positive;
- int bind;
- int axis;
- };
- int negative;
-
- float value;
+
+ 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_gamepad_axis,
+ k_input_type_gamepad_button
+ }
+ type;
+
+ union
+ {
+ struct input_axis
+ {
+ u32 gamepad_axis,
+ keyboard_positive,
+ keyboard_negative;
+
+ float value;
+ }
+ axis;
+
+ struct
+ {
+ u32 gamepad_id, keyboard_id;
+ int value, prev;
+ }
+ button;
+ };
+
+ int save_this;
}
-vg_axis_binds[];
+vg_named_inputs[ 32 ];
+VG_STATIC u32 vg_named_input_count = 0;
-VG_STATIC struct button_binding
+VG_STATIC struct input_binding *vg_create_named_input( const char *name,
+ enum input_type type )
{
- const char *name;
- int bind;
-
- int value; int prev;
+ 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;
+
+ return bind;
}
-vg_button_binds[],
-vg_controller_binds[];
-#include "vg_config.h"
+VG_STATIC struct input_binding *vg_get_named_input( const char *name )
+{
+ for( u32 i=0; i<vg_named_input_count; i++ )
+ {
+ struct input_binding *bind = &vg_named_inputs[i];
+ if( !strcmp( bind->name, name ) )
+ return bind;
+ }
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wreturn-type"
+ return NULL;
+}
-VG_STATIC float vg_get_axis( const char *axis )
+struct input_en
{
- 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;
+ 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_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}
+};
-VG_STATIC struct button_binding *vg_get_button_ptr( const char *button )
+VG_STATIC const char *vg_input_to_str( u32 input, enum input_type input_type )
{
- for( int i=0; i<vg_list_size(vg_button_binds); i ++ )
- if( !strcmp(button,vg_button_binds[i].name) )
- return vg_button_binds + i;
+ 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; 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 struct button_binding *vg_get_button_ptr_c( const char *button )
+VG_STATIC enum input_type vg_str_to_input( const char *str, u32 *input )
{
- for( int i=0; i<vg_list_size(vg_controller_binds); i ++ )
- if( !strcmp(button,vg_controller_binds[i].name) )
- return vg_controller_binds + i;
- return NULL;
+ 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; 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;
}
-#pragma GCC diagnostic pop
+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"}[ 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_STATIC int vg_console_enabled(void);
+ vg_info( " keyboard_positive: %s\n",
+ vg_input_to_str(bind->axis.keyboard_positive,
+ k_input_type_keyboard_key ));
-VG_STATIC void vg_get_button_states( const char *name, int *cur, int *prev )
+ 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));
+ }
+}
+
+/*
+ * bind x jump
+ * bind a -horizontal
+ * bind d +horizontal
+ */
+
+VG_STATIC int vg_rebind_input_cmd( int argc, const char *argv[] )
{
- struct button_binding *bind = vg_get_button_ptr( name ),
- *bindc = vg_get_button_ptr_c( name );
-
- *cur = 0; *prev = 0;
+ 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;
+ }
+
+ if( strlen(argv[0]) == 0 )
+ return 0;
+
+ int axis_mod = 0;
+ if( (argv[0][0] == '-') || (argv[0][0] == '+') )
+ axis_mod = 1;
+
+ struct input_binding *bind = vg_get_named_input( argv[0]+axis_mod );
- if( bind )
+ if( !bind )
{
- *cur |= bind->value;
- *prev |= bind->prev;
+ vg_error( "There is no named input called %s\n", argv[0]+axis_mod );
+ return 0;
}
- if( bindc )
+ if( argc == 1 )
{
- *cur |= bindc->value;
- *prev |= bindc->prev;
+ vg_print_binding_info( bind );
+ return 0;
+ }
+
+ if( argc == 2 )
+ {
+ u32 id;
+ enum input_type type = vg_str_to_input( argv[1], &id );
+
+ if( bind->type == k_input_type_button )
+ {
+ if( axis_mod )
+ {
+ vg_error( "Cannot use axis modifiers on button input!\n" );
+ return 0;
+ }
+
+ 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", argv[1] );
+ return 0;
+ }
+ }
+ 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( argv[0][0] == '+' )
+ bind->axis.keyboard_positive = id;
+ else
+ bind->axis.keyboard_negative = id;
+ }
+ else
+ {
+ vg_error( "You can only bind keyboard keys to +- axises\n" );
+ return 0;
+ }
+ }
+ else
+ {
+ if( type == k_input_type_gamepad_axis )
+ bind->axis.gamepad_axis = id;
+ else
+ {
+ vg_error( "You can only bind gamepad axises to this\n" );
+ return 0;
+ }
+ }
+ }
}
+
+ return 0;
}
-VG_STATIC int vg_get_button( const char *button )
+VG_STATIC void vg_input_update( u32 num, struct input_binding *binds )
{
- int cur, prev;
- vg_get_button_states( button, &cur, &prev );
+ 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( 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( fabsf(gamepad_value) <= 0.01f )
+ gamepad_value = 0.0f;
- return cur && !vg_console_enabled();
+ 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_get_button_down( const char *button )
+VG_STATIC int vg_input_button_down( struct input_binding *bind )
{
- if( vg.engine_stage == k_engine_stage_update_fixed )
- vg_fatal_exit_loop( "Cannot use that here\n" );
+ if( bind->button.value && !bind->button.prev )
+ return 1;
+ return 0;
+}
- int cur, prev;
- vg_get_button_states( button, &cur, &prev );
+VG_STATIC float vg_get_axis( const char *axis )
+{
+ return 0.0f;
+}
+
+VG_STATIC int vg_console_enabled(void);
- return cur & (cur ^ prev) && !vg_console_enabled();
+VG_STATIC void vg_get_button_states( const char *name, int *cur, int *prev )
+{
}
-VG_STATIC int vg_get_button_up( const char *button )
+VG_STATIC int vg_get_button( const char *button )
{
- if( vg.engine_stage == k_engine_stage_update_fixed )
- vg_fatal_exit_loop( "Cannot use that here\n" );
+ return 0;
+}
- int cur, prev;
- vg_get_button_states( button, &cur, &prev );
+VG_STATIC int vg_get_button_down( const char *button )
+{
+ return 0;
+}
- return prev & (cur ^ prev) && !vg_console_enabled();
+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 )
return k_button_state_none;
}
-VG_STATIC int key_is_keyboard( int const id )
-{
- vg_static_assert( GLFW_MOUSE_BUTTON_LAST < GLFW_KEY_SPACE,
- "GLFW: Mouse has too many buttons" );
- return id > GLFW_MOUSE_BUTTON_LAST;
-}
-
-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;
-}
-
void vg_update_inputs(void)
{
if( !glfwGetGamepadState( GLFW_JOYSTICK_1, &vg.gamepad) )
vg.gamepad.axes[ GLFW_GAMEPAD_AXIS_LEFT_TRIGGER ] = -1.0f;
}
- /* 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;
- binding->value = get_button_cross_device( binding->bind );
- }
-
- for( int i=0; i<vg_list_size( vg_controller_binds ); i++ )
- {
- struct button_binding *binding = vg_controller_binds + i;
- binding->prev = binding->value;
- 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;
- binding->value = vg.gamepad.axes[ binding->bind ];
- }
+ /* update all inputs */
+ vg_input_update( vg_named_input_count, vg_named_inputs );
}
VG_STATIC void vg_gamepad_init(void)
{
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 ) )