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_gamepad_axis
,
38 k_input_type_gamepad_button
56 u32 gamepad_id
, keyboard_id
;
64 vg_named_inputs
[ 32 ];
65 VG_STATIC u32 vg_named_input_count
= 0;
67 VG_STATIC
struct input_binding
*vg_create_named_input( const char *name
,
68 enum input_type type
)
70 struct input_binding
*bind
= &vg_named_inputs
[ vg_named_input_count
++ ];
71 memset( bind
, 0, sizeof(struct input_binding
) );
80 VG_STATIC
struct input_binding
*vg_get_named_input( const char *name
)
82 for( u32 i
=0; i
<vg_named_input_count
; i
++ )
84 struct input_binding
*bind
= &vg_named_inputs
[i
];
85 if( !strcmp( bind
->name
, name
) )
99 vg_all_bindable_inputs
[] =
101 {k_input_type_keyboard_key
, "space", GLFW_KEY_SPACE
},
102 {k_input_type_keyboard_key
, ";", GLFW_KEY_SEMICOLON
},
103 {k_input_type_keyboard_key
, "-", GLFW_KEY_MINUS
},
104 {k_input_type_keyboard_key
, ".", GLFW_KEY_PERIOD
},
105 {k_input_type_keyboard_key
, ",", GLFW_KEY_COMMA
},
106 {k_input_type_keyboard_key
, "=", GLFW_KEY_EQUAL
},
107 {k_input_type_keyboard_key
, "[", GLFW_KEY_LEFT_BRACKET
},
108 {k_input_type_keyboard_key
, "]", GLFW_KEY_RIGHT_BRACKET
},
109 {k_input_type_keyboard_key
, "left", GLFW_KEY_LEFT
},
110 {k_input_type_keyboard_key
, "right", GLFW_KEY_RIGHT
},
111 {k_input_type_keyboard_key
, "up", GLFW_KEY_UP
},
112 {k_input_type_keyboard_key
, "down", GLFW_KEY_DOWN
},
113 {k_input_type_keyboard_key
, "shift", GLFW_KEY_LEFT_SHIFT
},
114 {k_input_type_keyboard_key
, "control", GLFW_KEY_LEFT_CONTROL
},
116 {k_input_type_gamepad_axis
, "gp-lt", GLFW_GAMEPAD_AXIS_LEFT_TRIGGER
},
117 {k_input_type_gamepad_axis
, "gp-rt", GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER
},
118 {k_input_type_gamepad_axis
, "gp-ls-h", GLFW_GAMEPAD_AXIS_LEFT_X
},
119 {k_input_type_gamepad_axis
, "gp-ls-v", GLFW_GAMEPAD_AXIS_LEFT_Y
},
120 {k_input_type_gamepad_axis
, "gp-rs-h", GLFW_GAMEPAD_AXIS_RIGHT_X
},
121 {k_input_type_gamepad_axis
, "gp-rs-v", GLFW_GAMEPAD_AXIS_RIGHT_Y
},
123 {k_input_type_gamepad_button
, "gp-a", GLFW_GAMEPAD_BUTTON_A
},
124 {k_input_type_gamepad_button
, "gp-b", GLFW_GAMEPAD_BUTTON_B
},
125 {k_input_type_gamepad_button
, "gp-x", GLFW_GAMEPAD_BUTTON_X
},
126 {k_input_type_gamepad_button
, "gp-y", GLFW_GAMEPAD_BUTTON_Y
},
127 {k_input_type_gamepad_button
, "gp-rb", GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER
},
128 {k_input_type_gamepad_button
, "gp-lb", GLFW_GAMEPAD_BUTTON_LEFT_BUMPER
},
129 {k_input_type_gamepad_button
, "gp-rs", GLFW_GAMEPAD_BUTTON_RIGHT_THUMB
},
130 {k_input_type_gamepad_button
, "gp-ls", GLFW_GAMEPAD_BUTTON_LEFT_THUMB
},
131 {k_input_type_gamepad_button
, "gp-dpad-down", GLFW_GAMEPAD_BUTTON_DPAD_DOWN
},
132 {k_input_type_gamepad_button
, "gp-dpad-left", GLFW_GAMEPAD_BUTTON_DPAD_LEFT
},
133 {k_input_type_gamepad_button
, "gp-dpad-right", GLFW_GAMEPAD_BUTTON_DPAD_RIGHT
},
134 {k_input_type_gamepad_button
, "gp-dpad-up", GLFW_GAMEPAD_BUTTON_DPAD_UP
}
137 VG_STATIC
const char *vg_input_to_str( u32 input
, enum input_type input_type
)
142 if( input_type
== k_input_type_keyboard_key
)
144 if( (input
>= GLFW_KEY_A
) && (input
<= GLFW_KEY_Z
) )
146 return &"a\0b\0c\0d\0e\0f\0g\0h\0i\0j\0k\0l\0m\0n\0o\0p\0"
147 "q\0r\0s\0t\0u\0v\0w\0x\0y\0z\0"[(input
-GLFW_KEY_A
)*2];
150 if( (input
>= GLFW_KEY_0
) && (input
<= GLFW_KEY_9
) )
152 return &"0\0" "1\0" "2\0" "3\0" "4\0"
153 "5\0" "6\0" "7\0" "8\0" "9\0"[(input
-GLFW_KEY_0
)*2];
157 for( int i
=0; i
<vg_list_size(vg_all_bindable_inputs
); i
++ )
159 struct input_en
*desc
= &vg_all_bindable_inputs
[i
];
161 if( (desc
->type
== input_type
) && (desc
->id
== input
) )
168 VG_STATIC
enum input_type
vg_str_to_input( const char *str
, u32
*input
)
173 return k_input_type_unknown
;
176 u32 len
= strlen(str
);
181 return k_input_type_unknown
;
188 if( (uch
>= (u8
)'a') && (uch
<= (u8
)'z') )
190 *input
= GLFW_KEY_A
+ (uch
-(u8
)'a');
191 return k_input_type_keyboard_key
;
194 if( (uch
>= (u8
)'0') && (uch
<= (u8
)'9') )
196 *input
= GLFW_KEY_0
+ (uch
-(u8
)'0');
197 return k_input_type_keyboard_key
;
201 for( int i
=0; i
<vg_list_size(vg_all_bindable_inputs
); i
++ )
203 struct input_en
*desc
= &vg_all_bindable_inputs
[i
];
205 if( !strcmp( desc
->alias
, str
) )
213 return k_input_type_unknown
;
216 VG_STATIC
void vg_print_binding_info( struct input_binding
*bind
)
218 vg_info( " name: %s\n", bind
->name
);
219 vg_info( " type: %s\n", (const char *[]){"button","axis"}[ bind
->type
] );
220 vg_info( " save this? %d\n", bind
->save_this
);
222 if( (bind
->type
== k_input_type_axis
) ||
223 (bind
->type
== k_input_type_axis_norm
) )
225 vg_info( " gamepad_axis: %s\n",
226 vg_input_to_str(bind
->axis
.gamepad_axis
, k_input_type_gamepad_axis
));
228 vg_info( " keyboard_positive: %s\n",
229 vg_input_to_str(bind
->axis
.keyboard_positive
,
230 k_input_type_keyboard_key
));
232 vg_info( " keyboard_negative: %s\n",
233 vg_input_to_str(bind
->axis
.keyboard_negative
,
234 k_input_type_keyboard_key
));
238 vg_info( " gamepad_id: %s\n",
239 vg_input_to_str(bind
->button
.gamepad_id
, k_input_type_gamepad_button
));
240 vg_info( " keyboard_id: %s\n",
241 vg_input_to_str(bind
->button
.keyboard_id
,
242 k_input_type_keyboard_key
));
252 VG_STATIC
int vg_rebind_input_cmd( int argc
, const char *argv
[] )
256 vg_info( "Usage: bind jump x\n" );
257 vg_info( " bind -steerh j\n" );
258 vg_info( " bind steerh gp-ls-h\n" );
262 if( strlen(argv
[0]) == 0 )
266 if( (argv
[0][0] == '-') || (argv
[0][0] == '+') )
269 struct input_binding
*bind
= vg_get_named_input( argv
[0]+axis_mod
);
273 vg_error( "There is no named input called %s\n", argv
[0]+axis_mod
);
279 vg_print_binding_info( bind
);
286 enum input_type type
= vg_str_to_input( argv
[1], &id
);
288 if( bind
->type
== k_input_type_button
)
292 vg_error( "Cannot use axis modifiers on button input!\n" );
296 if( type
== k_input_type_keyboard_key
)
297 bind
->button
.keyboard_id
= id
;
298 else if( type
== k_input_type_gamepad_button
)
299 bind
->button
.gamepad_id
= id
;
302 vg_error( "Unknown button or key '%s'\n", argv
[1] );
306 else if( (bind
->type
== k_input_type_axis
) ||
307 (bind
->type
== k_input_type_axis_norm
))
311 if( type
== k_input_type_keyboard_key
)
313 if( argv
[0][0] == '+' )
314 bind
->axis
.keyboard_positive
= id
;
316 bind
->axis
.keyboard_negative
= id
;
320 vg_error( "You can only bind keyboard keys to +- axises\n" );
326 if( type
== k_input_type_gamepad_axis
)
327 bind
->axis
.gamepad_axis
= id
;
330 vg_error( "You can only bind gamepad axises to this\n" );
340 VG_STATIC
void vg_input_update( u32 num
, struct input_binding
*binds
)
342 for( i32 i
=0; i
<num
; i
++ )
344 struct input_binding
*bind
= &binds
[i
];
346 if( bind
->type
== k_input_type_button
)
348 bind
->button
.prev
= bind
->button
.value
;
349 bind
->button
.value
= 0;
351 if( bind
->button
.gamepad_id
!= -1 )
352 bind
->button
.value
|= vg
.gamepad
.buttons
[ bind
->button
.gamepad_id
];
354 if( bind
->button
.keyboard_id
!= -1 )
355 bind
->button
.value
|= glfwGetKey( vg
.window
,
356 bind
->button
.keyboard_id
);
358 else if( bind
->type
== k_input_type_axis
)
360 float keyboard_value
= 0.0f
,
361 gamepad_value
= 0.0f
;
363 if( bind
->axis
.keyboard_positive
!= -1 )
364 if( glfwGetKey( vg
.window
, bind
->axis
.keyboard_positive
) )
365 keyboard_value
+= 1.0f
;
367 if( bind
->axis
.keyboard_negative
!= -1 )
368 if( glfwGetKey( vg
.window
, bind
->axis
.keyboard_negative
) )
369 keyboard_value
-= 1.0f
;
371 if( bind
->axis
.gamepad_axis
!= -1 )
372 gamepad_value
= vg
.gamepad
.axes
[ bind
->axis
.gamepad_axis
];
374 if( fabsf(gamepad_value
) <= 0.01f
)
375 gamepad_value
= 0.0f
;
377 if( fabsf(keyboard_value
) > fabsf(gamepad_value
) )
378 bind
->axis
.value
= keyboard_value
;
380 bind
->axis
.value
= gamepad_value
;
382 else if( bind
->type
== k_input_type_axis_norm
)
385 if( bind
->axis
.keyboard_positive
!= -1 )
386 if( glfwGetKey( vg
.window
, bind
->axis
.keyboard_positive
))
389 if( bind
->axis
.gamepad_axis
!= -1 )
390 value
= vg_maxf( value
, vg
.gamepad
.axes
[bind
->axis
.gamepad_axis
] );
392 bind
->axis
.value
= value
* 0.5f
+ 0.5f
;
397 VG_STATIC
int vg_input_button_down( struct input_binding
*bind
)
399 if( bind
->button
.value
&& !bind
->button
.prev
)
404 VG_STATIC
float vg_get_axis( const char *axis
)
409 VG_STATIC
int vg_console_enabled(void);
411 VG_STATIC
void vg_get_button_states( const char *name
, int *cur
, int *prev
)
415 VG_STATIC
int vg_get_button( const char *button
)
420 VG_STATIC
int vg_get_button_down( const char *button
)
425 VG_STATIC
int vg_get_button_up( const char *button
)
430 VG_STATIC
enum vg_button_state
vg_get_button_state( const char *button
)
432 if(vg_get_button_down( button
)) return k_button_state_down
;
433 if(vg_get_button_up( button
)) return k_button_state_up
;
434 if(vg_get_button( button
)) return k_button_state_pressed
;
435 return k_button_state_none
;
438 void vg_update_inputs(void)
440 if( !glfwGetGamepadState( GLFW_JOYSTICK_1
, &vg
.gamepad
) )
442 vg
.gamepad_ready
= 0;
443 vg
.gamepad
.axes
[ GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER
] = -1.0f
;
444 vg
.gamepad
.axes
[ GLFW_GAMEPAD_AXIS_LEFT_TRIGGER
] = -1.0f
;
447 /* update all inputs */
448 vg_input_update( vg_named_input_count
, vg_named_inputs
);
451 VG_STATIC
void vg_gamepad_init(void)
453 vg_acquire_thread_sync();
455 vg_function_push( (struct vg_cmd
)
458 .function
= vg_rebind_input_cmd
461 for( int id
=0; id
<=GLFW_JOYSTICK_LAST
; id
++ )
463 if( glfwJoystickPresent( id
) )
465 vg_info( "Joystick found: '%s'\n", glfwGetJoystickName(id
) );
468 if( glfwJoystickIsGamepad( id
) )
470 vg
.gamepad_name
= glfwGetGamepadName( id
);
471 vg_success( "Gamepad mapping registered: %s\n", vg
.gamepad_name
);
473 vg
.gamepad_ready
= 1;
479 vg
.gamepad
.axes
[ GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER
] = -1.0f
;
480 vg
.gamepad
.axes
[ GLFW_GAMEPAD_AXIS_LEFT_TRIGGER
] = -1.0f
;
482 vg_release_thread_sync();