f7df7511b860b16c4c21ccea526ea2d94eacc0e9
[vg.git] / src / vg / vg_input.h
1 /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
2 #ifndef VG_INPUT_H
3 #define VG_INPUT_H
4
5 #include "common.h"
6 #include "vg/vg_loader.h"
7
8 VG_STATIC inline float vg_get_axis( const char *axis );
9 VG_STATIC inline int vg_get_button( const char *button );
10
11 /*
12 * Cannot be used in fixed update
13 */
14 VG_STATIC inline int vg_get_button_down( const char *button );
15 VG_STATIC inline int vg_get_button_up( const char *button );
16
17 enum vg_button_state
18 {
19 k_button_state_down = 1,
20 k_button_state_up = 3,
21 k_button_state_pressed = 2,
22 k_button_state_none = 0
23 };
24
25 /* TODO: Fix this... */
26 enum EInputMode
27 {
28 k_EInputMode_pc,
29 k_EInputMode_gamepad
30 }
31 vg_input_mode;
32
33 VG_STATIC struct axis_binding
34 {
35 const char *name;
36 union
37 {
38 int positive;
39 int bind;
40 int axis;
41 };
42 int negative;
43
44 float value;
45 }
46 vg_axis_binds[];
47
48 VG_STATIC struct button_binding
49 {
50 const char *name;
51 int bind;
52
53 int value; int prev;
54 }
55 vg_button_binds[],
56 vg_controller_binds[];
57
58 #include "vg_config.h"
59
60 #pragma GCC diagnostic push
61 #pragma GCC diagnostic ignored "-Wreturn-type"
62
63 VG_STATIC float vg_get_axis( const char *axis )
64 {
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;
68 }
69
70 VG_STATIC struct button_binding *vg_get_button_ptr( const char *button )
71 {
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;
75 return NULL;
76 }
77
78 VG_STATIC struct button_binding *vg_get_button_ptr_c( const char *button )
79 {
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;
83 return NULL;
84 }
85
86 #pragma GCC diagnostic pop
87
88 VG_STATIC int vg_console_enabled(void);
89
90 VG_STATIC void vg_get_button_states( const char *name, int *cur, int *prev )
91 {
92 struct button_binding *bind = vg_get_button_ptr( name ),
93 *bindc = vg_get_button_ptr_c( name );
94
95 *cur = 0; *prev = 0;
96
97 if( bind )
98 {
99 *cur |= bind->value;
100 *prev |= bind->prev;
101 }
102
103 if( bindc )
104 {
105 *cur |= bindc->value;
106 *prev |= bindc->prev;
107 }
108 }
109
110 VG_STATIC int vg_get_button( const char *button )
111 {
112 int cur, prev;
113 vg_get_button_states( button, &cur, &prev );
114
115 return cur && !vg_console_enabled();
116 }
117
118 VG_STATIC int vg_get_button_down( const char *button )
119 {
120 if( vg.engine_stage == k_engine_stage_update_fixed )
121 vg_fatal_exit_loop( "Cannot use that here\n" );
122
123 int cur, prev;
124 vg_get_button_states( button, &cur, &prev );
125
126 return cur & (cur ^ prev) && !vg_console_enabled();
127 }
128
129 VG_STATIC int vg_get_button_up( const char *button )
130 {
131 if( vg.engine_stage == k_engine_stage_update_fixed )
132 vg_fatal_exit_loop( "Cannot use that here\n" );
133
134 int cur, prev;
135 vg_get_button_states( button, &cur, &prev );
136
137 return prev & (cur ^ prev) && !vg_console_enabled();
138 }
139
140 VG_STATIC enum vg_button_state vg_get_button_state( const char *button )
141 {
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;
146 }
147
148 VG_STATIC int key_is_keyboard( int const id )
149 {
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;
153 }
154
155 int get_button_cross_device( int const id )
156 {
157 if( key_is_keyboard( id ) )
158 return glfwGetKey( vg.window, id );
159 else
160 return glfwGetMouseButton( vg.window, id ) == GLFW_PRESS;
161 }
162
163 void vg_update_inputs(void)
164 {
165 if( !glfwGetGamepadState( GLFW_JOYSTICK_1, &vg.gamepad) )
166 {
167 vg.gamepad_ready = 0;
168 vg.gamepad.axes[ GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER ] = -1.0f;
169 vg.gamepad.axes[ GLFW_GAMEPAD_AXIS_LEFT_TRIGGER ] = -1.0f;
170 }
171
172 /* Update button inputs */
173 for( int i = 0; i < vg_list_size( vg_button_binds ); i ++ )
174 {
175 struct button_binding *binding = vg_button_binds + i;
176 binding->prev = binding->value;
177 binding->value = get_button_cross_device( binding->bind );
178 }
179
180 for( int i=0; i<vg_list_size( vg_controller_binds ); i++ )
181 {
182 struct button_binding *binding = vg_controller_binds + i;
183 binding->prev = binding->value;
184 binding->value = vg.gamepad.buttons[ binding->bind ];
185 }
186
187 /* Update axis inputs */
188 for( int i = 0; i < vg_list_size( vg_axis_binds ); i ++ )
189 {
190 struct axis_binding *binding = vg_axis_binds + i;
191 binding->value = vg.gamepad.axes[ binding->bind ];
192 }
193 }
194
195 VG_STATIC void vg_gamepad_init(void)
196 {
197 vg_acquire_thread_sync();
198
199 for( int id=0; id<=GLFW_JOYSTICK_LAST; id ++ )
200 {
201 if( glfwJoystickPresent( id ) )
202 {
203 vg_info( "Joystick found: '%s'\n", glfwGetJoystickName(id) );
204 }
205
206 if( glfwJoystickIsGamepad( id ) )
207 {
208 vg.gamepad_name = glfwGetGamepadName( id );
209 vg_success( "Gamepad mapping registered: %s\n", vg.gamepad_name );
210
211 vg.gamepad_ready = 1;
212 vg.gamepad_id = id;
213 break;
214 }
215 }
216
217 vg.gamepad.axes[ GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER ] = -1.0f;
218 vg.gamepad.axes[ GLFW_GAMEPAD_AXIS_LEFT_TRIGGER ] = -1.0f;
219
220 vg_release_thread_sync();
221 }
222
223 #endif