1 /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
6 #include "vg/vg_loader.h"
8 VG_STATIC
inline float vg_get_axis( const char *axis
);
9 VG_STATIC
inline int vg_get_button( const char *button
);
12 * Cannot be used in fixed update
14 VG_STATIC
inline int vg_get_button_down( const char *button
);
15 VG_STATIC
inline int vg_get_button_up( const char *button
);
19 k_button_state_down
= 1,
20 k_button_state_up
= 3,
21 k_button_state_pressed
= 2,
22 k_button_state_none
= 0
25 VG_STATIC
struct input_binding
33 k_input_type_axis_norm
,
36 k_input_type_keyboard_key
,
37 k_input_type_mouse_button
, /* ? TODO */
38 k_input_type_gamepad_axis
,
39 k_input_type_gamepad_button
58 u32 gamepad_id
, keyboard_id
;
66 vg_named_inputs
[ 32 ];
67 VG_STATIC u32 vg_named_input_count
= 0;
69 VG_STATIC
void vg_create_unnamed_input( struct input_binding
*bind
,
70 enum input_type type
)
72 memset( bind
, 0, sizeof(struct input_binding
) );
74 bind
->name
= "API DEFINED";
78 bind
->axis
.gamepad_axis
= -1;
79 bind
->axis
.keyboard_positive
= -1;
80 bind
->axis
.keyboard_negative
= -1;
81 bind
->button
.gamepad_id
= -1;
82 bind
->button
.keyboard_id
= -1;
85 VG_STATIC
struct input_binding
*vg_create_named_input( const char *name
,
86 enum input_type type
)
88 struct input_binding
*bind
= &vg_named_inputs
[ vg_named_input_count
++ ];
89 memset( bind
, 0, sizeof(struct input_binding
) );
95 bind
->axis
.gamepad_axis
= -1;
96 bind
->axis
.keyboard_positive
= -1;
97 bind
->axis
.keyboard_negative
= -1;
98 bind
->button
.gamepad_id
= -1;
99 bind
->button
.keyboard_id
= -1;
104 VG_STATIC
struct input_binding
*vg_get_named_input( const char *name
)
106 if( name
[0] == '+' || name
[0] == '-' )
109 for( u32 i
=0; i
<vg_named_input_count
; i
++ )
111 struct input_binding
*bind
= &vg_named_inputs
[i
];
112 if( !strcmp( bind
->name
, name
) )
121 enum input_type type
;
126 vg_all_bindable_inputs
[] =
128 {k_input_type_keyboard_key
, "space", GLFW_KEY_SPACE
},
129 {k_input_type_keyboard_key
, ";", GLFW_KEY_SEMICOLON
},
130 {k_input_type_keyboard_key
, "-", GLFW_KEY_MINUS
},
131 {k_input_type_keyboard_key
, ".", GLFW_KEY_PERIOD
},
132 {k_input_type_keyboard_key
, ",", GLFW_KEY_COMMA
},
133 {k_input_type_keyboard_key
, "=", GLFW_KEY_EQUAL
},
134 {k_input_type_keyboard_key
, "[", GLFW_KEY_LEFT_BRACKET
},
135 {k_input_type_keyboard_key
, "]", GLFW_KEY_RIGHT_BRACKET
},
136 {k_input_type_keyboard_key
, "left", GLFW_KEY_LEFT
},
137 {k_input_type_keyboard_key
, "right", GLFW_KEY_RIGHT
},
138 {k_input_type_keyboard_key
, "up", GLFW_KEY_UP
},
139 {k_input_type_keyboard_key
, "down", GLFW_KEY_DOWN
},
140 {k_input_type_keyboard_key
, "shift", GLFW_KEY_LEFT_SHIFT
},
141 {k_input_type_keyboard_key
, "control", GLFW_KEY_LEFT_CONTROL
},
142 {k_input_type_keyboard_key
, "\2enter", GLFW_KEY_ENTER
},
143 {k_input_type_keyboard_key
, "\2escape", GLFW_KEY_ESCAPE
},
145 {k_input_type_gamepad_axis
, "gp-lt", GLFW_GAMEPAD_AXIS_LEFT_TRIGGER
},
146 {k_input_type_gamepad_axis
, "gp-rt", GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER
},
147 {k_input_type_gamepad_axis
, "gp-ls-h", GLFW_GAMEPAD_AXIS_LEFT_X
},
148 {k_input_type_gamepad_axis
, "gp-ls-v", GLFW_GAMEPAD_AXIS_LEFT_Y
},
149 {k_input_type_gamepad_axis
, "gp-rs-h", GLFW_GAMEPAD_AXIS_RIGHT_X
},
150 {k_input_type_gamepad_axis
, "gp-rs-v", GLFW_GAMEPAD_AXIS_RIGHT_Y
},
152 {k_input_type_gamepad_button
, "gp-a", GLFW_GAMEPAD_BUTTON_A
},
153 {k_input_type_gamepad_button
, "gp-b", GLFW_GAMEPAD_BUTTON_B
},
154 {k_input_type_gamepad_button
, "gp-x", GLFW_GAMEPAD_BUTTON_X
},
155 {k_input_type_gamepad_button
, "gp-y", GLFW_GAMEPAD_BUTTON_Y
},
156 {k_input_type_gamepad_button
, "gp-rb", GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER
},
157 {k_input_type_gamepad_button
, "gp-lb", GLFW_GAMEPAD_BUTTON_LEFT_BUMPER
},
158 {k_input_type_gamepad_button
, "gp-rs", GLFW_GAMEPAD_BUTTON_RIGHT_THUMB
},
159 {k_input_type_gamepad_button
, "gp-ls", GLFW_GAMEPAD_BUTTON_LEFT_THUMB
},
160 {k_input_type_gamepad_button
, "gp-dpad-down", GLFW_GAMEPAD_BUTTON_DPAD_DOWN
},
161 {k_input_type_gamepad_button
, "gp-dpad-left", GLFW_GAMEPAD_BUTTON_DPAD_LEFT
},
162 {k_input_type_gamepad_button
, "gp-dpad-right", GLFW_GAMEPAD_BUTTON_DPAD_RIGHT
},
163 {k_input_type_gamepad_button
, "gp-dpad-up", GLFW_GAMEPAD_BUTTON_DPAD_UP
},
164 {k_input_type_gamepad_button
, "\2gp-menu", GLFW_GAMEPAD_BUTTON_BACK
}
167 VG_STATIC
const char *vg_input_to_str( u32 input
, enum input_type input_type
)
172 if( input_type
== k_input_type_keyboard_key
)
174 if( (input
>= GLFW_KEY_A
) && (input
<= GLFW_KEY_Z
) )
176 return &"a\0b\0c\0d\0e\0f\0g\0h\0i\0j\0k\0l\0m\0n\0o\0p\0"
177 "q\0r\0s\0t\0u\0v\0w\0x\0y\0z\0"[(input
-GLFW_KEY_A
)*2];
180 if( (input
>= GLFW_KEY_0
) && (input
<= GLFW_KEY_9
) )
182 return &"0\0" "1\0" "2\0" "3\0" "4\0"
183 "5\0" "6\0" "7\0" "8\0" "9\0"[(input
-GLFW_KEY_0
)*2];
187 for( int i
=0; i
<vg_list_size(vg_all_bindable_inputs
); i
++ )
189 struct input_en
*desc
= &vg_all_bindable_inputs
[i
];
191 if( (desc
->type
== input_type
) && (desc
->id
== input
) )
198 VG_STATIC
enum input_type
vg_str_to_input( const char *str
, u32
*input
)
203 return k_input_type_unknown
;
206 u32 len
= strlen(str
);
211 return k_input_type_unknown
;
218 if( (uch
>= (u8
)'a') && (uch
<= (u8
)'z') )
220 *input
= GLFW_KEY_A
+ (uch
-(u8
)'a');
221 return k_input_type_keyboard_key
;
224 if( (uch
>= (u8
)'0') && (uch
<= (u8
)'9') )
226 *input
= GLFW_KEY_0
+ (uch
-(u8
)'0');
227 return k_input_type_keyboard_key
;
231 for( int i
=0; i
<vg_list_size(vg_all_bindable_inputs
); i
++ )
233 struct input_en
*desc
= &vg_all_bindable_inputs
[i
];
235 if( !strcmp( desc
->alias
, str
) )
243 return k_input_type_unknown
;
246 VG_STATIC
void vg_print_binding_info( struct input_binding
*bind
)
248 vg_info( " name: %s\n", bind
->name
);
249 vg_info( " type: %s\n", (const char *[]){"button","axis","axis[0-1]"}
251 vg_info( " save this? %d\n", bind
->save_this
);
253 if( (bind
->type
== k_input_type_axis
) ||
254 (bind
->type
== k_input_type_axis_norm
) )
256 vg_info( " gamepad_axis: %s\n",
257 vg_input_to_str(bind
->axis
.gamepad_axis
, k_input_type_gamepad_axis
));
259 vg_info( " keyboard_positive: %s\n",
260 vg_input_to_str(bind
->axis
.keyboard_positive
,
261 k_input_type_keyboard_key
));
263 vg_info( " keyboard_negative: %s\n",
264 vg_input_to_str(bind
->axis
.keyboard_negative
,
265 k_input_type_keyboard_key
));
269 vg_info( " gamepad_id: %s\n",
270 vg_input_to_str(bind
->button
.gamepad_id
, k_input_type_gamepad_button
));
271 vg_info( " keyboard_id: %s\n",
272 vg_input_to_str(bind
->button
.keyboard_id
,
273 k_input_type_keyboard_key
));
277 VG_STATIC
void vg_apply_bind_str( struct input_binding
*bind
,
283 if( (mod
[0] == '-') || (mod
[0] == '+') )
291 if( (str
[0] == '-' ) )
298 enum input_type type
= vg_str_to_input( str
, &id
);
300 if( bind
->type
== k_input_type_button
)
304 vg_error( "Cannot use axis modifiers on button input!\n" );
310 vg_error( "Cannot invert button input!\n" );
314 if( type
== k_input_type_keyboard_key
)
315 bind
->button
.keyboard_id
= id
;
316 else if( type
== k_input_type_gamepad_button
)
317 bind
->button
.gamepad_id
= id
;
320 vg_error( "Unknown button or key '%s'\n", str
);
324 else if( (bind
->type
== k_input_type_axis
) ||
325 (bind
->type
== k_input_type_axis_norm
))
329 if( type
== k_input_type_keyboard_key
)
333 vg_error( "Cannot invert a keyboard key!\n" );
338 bind
->axis
.keyboard_positive
= id
;
340 bind
->axis
.keyboard_negative
= id
;
344 vg_error( "You can only bind keyboard keys to +- axises\n" );
350 if( type
== k_input_type_gamepad_axis
)
352 bind
->axis
.gamepad_inverted
= invert
;
353 bind
->axis
.gamepad_axis
= id
;
357 vg_error( "You can only bind gamepad axises to this\n" );
368 * bind -gp-ls-h horizontal
371 VG_STATIC
int vg_rebind_input_cmd( int argc
, const char *argv
[] )
375 vg_info( "Usage: bind jump x\n" );
376 vg_info( " bind -steerh j\n" );
377 vg_info( " bind steerh gp-ls-h\n" );
381 const char *str_bind_name
= argv
[0];
382 struct input_binding
*bind
= vg_get_named_input( str_bind_name
);
386 vg_error( "There is no bind with that name '%s'\n", str_bind_name
);
392 vg_print_binding_info( bind
);
398 const char *str_input_id
= argv
[1];
400 vg_apply_bind_str( bind
, str_bind_name
, str_input_id
);
407 VG_STATIC
void vg_input_update( u32 num
, struct input_binding
*binds
)
409 if( vg_console
.enabled
)
411 for( i32 i
=0; i
<num
; i
++ )
413 struct input_binding
*bind
= &binds
[i
];
415 if( bind
->type
== k_input_type_button
)
417 bind
->button
.prev
= bind
->button
.value
;
418 bind
->button
.value
= 0;
425 for( i32 i
=0; i
<num
; i
++ )
427 struct input_binding
*bind
= &binds
[i
];
429 if( bind
->type
== k_input_type_button
)
431 bind
->button
.prev
= bind
->button
.value
;
432 bind
->button
.value
= 0;
434 if( bind
->button
.gamepad_id
!= -1 )
435 bind
->button
.value
|= vg
.gamepad
.buttons
[ bind
->button
.gamepad_id
];
437 if( bind
->button
.keyboard_id
!= -1 )
438 bind
->button
.value
|= glfwGetKey( vg
.window
,
439 bind
->button
.keyboard_id
);
441 else if( bind
->type
== k_input_type_axis
)
443 float keyboard_value
= 0.0f
,
444 gamepad_value
= 0.0f
;
446 if( bind
->axis
.keyboard_positive
!= -1 )
447 if( glfwGetKey( vg
.window
, bind
->axis
.keyboard_positive
) )
448 keyboard_value
+= 1.0f
;
450 if( bind
->axis
.keyboard_negative
!= -1 )
451 if( glfwGetKey( vg
.window
, bind
->axis
.keyboard_negative
) )
452 keyboard_value
-= 1.0f
;
454 if( bind
->axis
.gamepad_axis
!= -1 )
456 gamepad_value
= vg
.gamepad
.axes
[ bind
->axis
.gamepad_axis
];
457 if( bind
->axis
.gamepad_inverted
)
458 gamepad_value
*= -1.0f
;
461 if( fabsf(gamepad_value
) <= 0.01f
)
462 gamepad_value
= 0.0f
;
464 if( fabsf(keyboard_value
) > fabsf(gamepad_value
) )
465 bind
->axis
.value
= keyboard_value
;
467 bind
->axis
.value
= gamepad_value
;
469 else if( bind
->type
== k_input_type_axis_norm
)
472 if( bind
->axis
.keyboard_positive
!= -1 )
473 if( glfwGetKey( vg
.window
, bind
->axis
.keyboard_positive
))
476 if( bind
->axis
.gamepad_axis
!= -1 )
477 value
= vg_maxf( value
, vg
.gamepad
.axes
[bind
->axis
.gamepad_axis
] );
479 bind
->axis
.value
= value
* 0.5f
+ 0.5f
;
484 VG_STATIC
int vg_console_enabled(void);
485 VG_STATIC
int vg_input_button_down( struct input_binding
*bind
)
487 if( bind
->button
.value
&& !bind
->button
.prev
)
493 VG_STATIC
float vg_get_axis( const char *axis
)
499 VG_STATIC
void vg_get_button_states( const char *name
, int *cur
, int *prev
)
503 VG_STATIC
int vg_get_button( const char *button
)
508 VG_STATIC
int vg_get_button_down( const char *button
)
513 VG_STATIC
int vg_get_button_up( const char *button
)
518 VG_STATIC
enum vg_button_state
vg_get_button_state( const char *button
)
520 if(vg_get_button_down( button
)) return k_button_state_down
;
521 if(vg_get_button_up( button
)) return k_button_state_up
;
522 if(vg_get_button( button
)) return k_button_state_pressed
;
523 return k_button_state_none
;
527 void vg_update_inputs(void)
529 if( !glfwGetGamepadState( GLFW_JOYSTICK_1
, &vg
.gamepad
) )
531 vg
.gamepad_ready
= 0;
532 vg
.gamepad
.axes
[ GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER
] = -1.0f
;
533 vg
.gamepad
.axes
[ GLFW_GAMEPAD_AXIS_LEFT_TRIGGER
] = -1.0f
;
536 /* update all inputs */
537 vg_input_update( vg_named_input_count
, vg_named_inputs
);
540 VG_STATIC
void vg_gamepad_init(void)
542 vg_acquire_thread_sync();
544 vg_function_push( (struct vg_cmd
)
547 .function
= vg_rebind_input_cmd
550 for( int id
=0; id
<=GLFW_JOYSTICK_LAST
; id
++ )
552 if( glfwJoystickPresent( id
) )
554 vg_info( "Joystick found: '%s'\n", glfwGetJoystickName(id
) );
557 if( glfwJoystickIsGamepad( id
) )
559 vg
.gamepad_name
= glfwGetGamepadName( id
);
560 vg_success( "Gamepad mapping registered: %s\n", vg
.gamepad_name
);
562 /* This path usually only gets chosen when starting outside of steam */
563 if( !strcmp(vg
.gamepad_name
, "Steam Controller") )
564 vg
.gamepad_use_trackpad_look
= 1;
566 vg
.gamepad_ready
= 1;
572 vg
.gamepad
.axes
[ GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER
] = -1.0f
;
573 vg
.gamepad
.axes
[ GLFW_GAMEPAD_AXIS_LEFT_TRIGGER
] = -1.0f
;
575 vg_release_thread_sync();