1 /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
6 #include "vg/vg_loader.h"
8 static inline float vg_get_axis( const char *axis
);
9 static inline int vg_get_button( const char *button
);
12 * Cannot be used in fixed update
14 static inline int vg_get_button_down( const char *button
);
15 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 /* TODO: Fix this... */
33 static struct axis_binding
48 static struct button_binding
56 vg_controller_binds
[];
58 #include "vg_config.h"
60 #pragma GCC diagnostic push
61 #pragma GCC diagnostic ignored "-Wreturn-type"
63 static inline float vg_get_axis( const char *axis
)
65 for( int i
= 0; i
< vg_list_size( vg_axis_binds
); i
++ )
66 if( !strcmp( axis
, vg_axis_binds
[i
].name
) )
67 return vg_axis_binds
[i
].value
;
70 static inline struct button_binding
*vg_get_button_ptr( const char *button
)
72 for( int i
=0; i
<vg_list_size(vg_button_binds
); i
++ )
73 if( !strcmp(button
,vg_button_binds
[i
].name
) )
74 return vg_button_binds
+ i
;
78 static inline struct button_binding
*vg_get_button_ptr_c( const char *button
)
80 for( int i
=0; i
<vg_list_size(vg_controller_binds
); i
++ )
81 if( !strcmp(button
,vg_controller_binds
[i
].name
) )
82 return vg_controller_binds
+ i
;
86 #pragma GCC diagnostic pop
88 static int vg_console_enabled(void);
90 static inline void vg_get_button_states( const char *name
, int *cur
, int *prev
)
92 struct button_binding
*bind
= vg_get_button_ptr( name
),
93 *bindc
= vg_get_button_ptr_c( name
);
105 *cur
|= bindc
->value
;
106 *prev
|= bindc
->prev
;
110 static inline int vg_get_button( const char *button
)
113 vg_get_button_states( button
, &cur
, &prev
);
115 return cur
&& !vg_console_enabled();
118 static inline int vg_get_button_down( const char *button
)
120 if( vg
.engine_stage
== k_engine_stage_update_fixed
)
121 vg_fatal_exit_loop( "Cannot use that here\n" );
124 vg_get_button_states( button
, &cur
, &prev
);
126 return cur
& (cur
^ prev
) && !vg_console_enabled();
129 static inline int vg_get_button_up( const char *button
)
131 if( vg
.engine_stage
== k_engine_stage_update_fixed
)
132 vg_fatal_exit_loop( "Cannot use that here\n" );
135 vg_get_button_states( button
, &cur
, &prev
);
137 return prev
& (cur
^ prev
) && !vg_console_enabled();
140 static inline enum vg_button_state
vg_get_button_state( const char *button
)
142 if(vg_get_button_down( button
)) return k_button_state_down
;
143 if(vg_get_button_up( button
)) return k_button_state_up
;
144 if(vg_get_button( button
)) return k_button_state_pressed
;
145 return k_button_state_none
;
148 static inline int key_is_keyboard( int const id
)
150 vg_static_assert( GLFW_MOUSE_BUTTON_LAST
< GLFW_KEY_SPACE
,
151 "GLFW: Mouse has too many buttons" );
152 return id
> GLFW_MOUSE_BUTTON_LAST
;
155 int get_button_cross_device( int const id
)
157 if( key_is_keyboard( id
) )
158 return glfwGetKey( vg
.window
, id
);
160 return glfwGetMouseButton( vg
.window
, id
) == GLFW_PRESS
;
163 void vg_update_inputs(void)
165 if( !glfwGetGamepadState( GLFW_JOYSTICK_1
, &vg
.gamepad
) )
166 vg
.gamepad_ready
= 0;
168 /* Update button inputs */
169 for( int i
= 0; i
< vg_list_size( vg_button_binds
); i
++ )
171 struct button_binding
*binding
= vg_button_binds
+ i
;
172 binding
->prev
= binding
->value
;
173 binding
->value
= get_button_cross_device( binding
->bind
);
176 for( int i
=0; i
<vg_list_size( vg_controller_binds
); i
++ )
178 struct button_binding
*binding
= vg_controller_binds
+ i
;
179 binding
->prev
= binding
->value
;
180 binding
->value
= vg
.gamepad
.buttons
[ binding
->bind
];
183 /* Update axis inputs */
184 for( int i
= 0; i
< vg_list_size( vg_axis_binds
); i
++ )
186 struct axis_binding
*binding
= vg_axis_binds
+ i
;
187 binding
->value
= vg
.gamepad
.axes
[ binding
->bind
];
191 static void vg_gamepad_init(void)
193 vg_acquire_thread_sync();
195 for( int id
=0; id
<=GLFW_JOYSTICK_LAST
; id
++ )
197 if( glfwJoystickPresent( id
) )
199 vg_info( "Joystick found: '%s'\n", glfwGetJoystickName(id
) );
202 if( glfwJoystickIsGamepad( id
) )
204 vg
.gamepad_name
= glfwGetGamepadName( id
);
205 vg_success( "Gamepad mapping registered: %s\n", vg
.gamepad_name
);
207 vg
.gamepad_ready
= 1;
213 vg_release_thread_sync();