76b3b95e7781934783363c6cb3345f0cf526661e
[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 static inline float vg_get_axis( const char *axis );
6 static inline int vg_get_button( const char *button );
7 static inline int vg_get_button_down( const char *button );
8 static inline int vg_get_button_up( const char *button );
9
10 enum vg_button_state
11 {
12 k_button_state_down = 1,
13 k_button_state_up = 3,
14 k_button_state_pressed = 2,
15 k_button_state_none = 0
16 };
17
18 GLFWgamepadstate vg_gamepad;
19 int vg_gamepad_ready = 0;
20 const char *vg_gamepad_name = NULL;
21 int vg_gamepad_id;
22
23 /* TODO: Fix this... */
24 enum EInputMode
25 {
26 k_EInputMode_pc,
27 k_EInputMode_gamepad
28 }
29 vg_input_mode;
30
31 static struct axis_binding
32 {
33 const char *name;
34 union
35 {
36 int positive;
37 int bind;
38 int axis;
39 };
40 int negative;
41
42 float value;
43 }
44 vg_axis_binds[];
45
46 static struct button_binding
47 {
48 const char *name;
49 int bind;
50
51 int value; int prev;
52 }
53 vg_button_binds[],
54 vg_controller_binds[];
55
56 #include "vg_config.h"
57
58 #pragma GCC diagnostic push
59 #pragma GCC diagnostic ignored "-Wreturn-type"
60
61 static inline float vg_get_axis( const char *axis )
62 {
63 for( int i = 0; i < vg_list_size( vg_axis_binds ); i ++ )
64 if( !strcmp( axis, vg_axis_binds[i].name ) )
65 return vg_axis_binds[i].value;
66 }
67
68 static inline struct button_binding *vg_get_button_ptr( const char *button )
69 {
70 for( int i=0; i<vg_list_size(vg_button_binds); i ++ )
71 if( !strcmp(button,vg_button_binds[i].name) )
72 return vg_button_binds + i;
73 return NULL;
74 }
75
76 static inline struct button_binding *vg_get_button_ptr_c( const char *button )
77 {
78 for( int i=0; i<vg_list_size(vg_controller_binds); i ++ )
79 if( !strcmp(button,vg_controller_binds[i].name) )
80 return vg_controller_binds + i;
81 return NULL;
82 }
83
84 #pragma GCC diagnostic pop
85
86 static int vg_console_enabled(void);
87
88 static inline void vg_get_button_states( const char *name, int *cur, int *prev )
89 {
90 struct button_binding *bind = vg_get_button_ptr( name ),
91 *bindc = vg_get_button_ptr_c( name );
92
93 *cur = 0; *prev = 0;
94
95 if( bind )
96 {
97 *cur |= bind->value;
98 *prev |= bind->prev;
99 }
100
101 if( bindc )
102 {
103 *cur |= bindc->value;
104 *prev |= bindc->prev;
105 }
106 }
107
108 static inline int vg_get_button( const char *button )
109 {
110 int cur, prev;
111 vg_get_button_states( button, &cur, &prev );
112
113 return cur && !vg_console_enabled();
114 }
115
116 static inline int vg_get_button_down( const char *button )
117 {
118 int cur, prev;
119 vg_get_button_states( button, &cur, &prev );
120
121 return cur & (cur ^ prev) && !vg_console_enabled();
122 }
123
124 static inline int vg_get_button_up( const char *button )
125 {
126 int cur, prev;
127 vg_get_button_states( button, &cur, &prev );
128
129 return prev & (cur ^ prev) && !vg_console_enabled();
130 }
131
132 static inline enum vg_button_state vg_get_button_state( const char *button )
133 {
134 if(vg_get_button_down( button )) return k_button_state_down;
135 if(vg_get_button_up( button )) return k_button_state_up;
136 if(vg_get_button( button )) return k_button_state_pressed;
137 return k_button_state_none;
138 }
139
140 static inline int key_is_keyboard( int const id )
141 {
142 vg_static_assert( GLFW_MOUSE_BUTTON_LAST < GLFW_KEY_SPACE,
143 "GLFW: Mouse has too many buttons" );
144 return id > GLFW_MOUSE_BUTTON_LAST;
145 }
146
147 int get_button_cross_device( int const id )
148 {
149 if( key_is_keyboard( id ) )
150 return glfwGetKey( vg_window, id );
151 else
152 return glfwGetMouseButton( vg_window, id ) == GLFW_PRESS;
153 }
154
155 void vg_update_inputs(void)
156 {
157 if( !glfwGetGamepadState( GLFW_JOYSTICK_1, &vg_gamepad) )
158 {
159 vg_gamepad_ready = 0;
160 }
161
162 /* Update button inputs */
163 for( int i = 0; i < vg_list_size( vg_button_binds ); i ++ )
164 {
165 struct button_binding *binding = vg_button_binds + i;
166 binding->prev = binding->value;
167 binding->value = get_button_cross_device( binding->bind );
168 }
169
170 for( int i=0; i<vg_list_size( vg_controller_binds ); i++ )
171 {
172 struct button_binding *binding = vg_controller_binds + i;
173 binding->prev = binding->value;
174 binding->value = vg_gamepad.buttons[ binding->bind ];
175 }
176
177 /* Update axis inputs */
178 for( int i = 0; i < vg_list_size( vg_axis_binds ); i ++ )
179 {
180 struct axis_binding *binding = vg_axis_binds + i;
181 binding->value = vg_gamepad.axes[ binding->bind ];
182 }
183 }
184
185 static void vg_gamepad_init(void)
186 {
187 for( int id = 0; id <= GLFW_JOYSTICK_LAST; id ++ )
188 {
189 if( glfwJoystickPresent( id ) )
190 {
191 vg_info( "Joystick found: '%s'\n", glfwGetJoystickName(id) );
192 }
193
194 if( glfwJoystickIsGamepad( id ) )
195 {
196 vg_gamepad_name = glfwGetGamepadName( id );
197 vg_success( "Gamepad with mapping registered: %s\n", vg_gamepad_name );
198
199 vg_gamepad_ready = 1;
200 vg_gamepad_id = id;
201
202 break;
203 }
204 }
205 }
206
207 #endif