8c43550e0e074ec908ca6a99d594cf4392dc9f47
[vg.git] / src / vg / vg_input.h
1 // Copyright (C) 2021 Harry Godden (hgn) - All Rights Reserved
2
3 static inline float vg_get_axis( const char *axis ) __attribute__((unused));
4 static inline int vg_get_button( const char *button ) __attribute__((unused));
5 static inline int vg_get_button_down( const char *button ) __attribute__((unused));
6 static inline int vg_get_button_up( const char *button ) __attribute__((unused));
7
8 enum vg_button_state
9 {
10 k_button_state_down = 1,
11 k_button_state_up = 3,
12 k_button_state_pressed = 2,
13 k_button_state_none = 0
14 };
15
16 // Input
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 enum EInputMode
24 {
25 k_EInputMode_pc,
26 k_EInputMode_gamepad
27 }
28 vg_input_mode;
29
30 static struct axis_binding
31 {
32 const char *name;
33 union
34 {
35 int positive;
36 int bind;
37 };
38 int negative;
39
40 float value;
41 }
42 vg_axis_binds[];
43
44 static struct button_binding
45 {
46 const char *name;
47 int bind;
48
49 int value; int prev;
50 }
51 vg_button_binds[];
52
53 #include "vg_config.h"
54
55 #pragma GCC diagnostic push
56 #pragma GCC diagnostic ignored "-Wreturn-type"
57
58 static inline float vg_get_axis( const char *axis )
59 {
60 for( int i = 0; i < vg_list_size( vg_axis_binds ); i ++ )
61 {
62 if( !strcmp( axis, vg_axis_binds[i].name ) )
63 {
64 return vg_axis_binds[i].value;
65 }
66 }
67 }
68
69 static inline struct button_binding *vg_get_button_ptr( const char *button )
70 {
71 for( int i = 0; i < vg_list_size( vg_button_binds ); i ++ )
72 {
73 if( !strcmp( button, vg_button_binds[i].name ) )
74 {
75 return vg_button_binds + i;
76 }
77 }
78 }
79 #pragma GCC diagnostic pop
80
81 static int vg_console_enabled(void);
82
83 static inline int vg_get_button( const char *button )
84 {
85 return vg_get_button_ptr( button )->value && !vg_console_enabled();
86 }
87
88 static inline int vg_get_button_down( const char *button )
89 {
90 struct button_binding *bind = vg_get_button_ptr( button );
91 return bind->value & (bind->value ^ bind->prev) && !vg_console_enabled();
92 }
93
94 static inline int vg_get_button_up( const char *button )
95 {
96 struct button_binding *bind = vg_get_button_ptr( button );
97 return bind->prev & (bind->value ^ bind->prev) && !vg_console_enabled();
98 }
99
100 static inline enum vg_button_state vg_get_button_state( const char *button )
101 {
102 if( vg_get_button_down( button ) ) return k_button_state_down;
103 if( vg_get_button_up( button ) ) return k_button_state_up;
104 if( vg_get_button( button ) ) return k_button_state_pressed;
105 return k_button_state_none;
106 }
107
108 static inline int key_is_keyboard( int const id )
109 {
110 vg_static_assert( GLFW_MOUSE_BUTTON_LAST < GLFW_KEY_SPACE, "GLFW: Mouse has too many buttons" );
111 return id > GLFW_MOUSE_BUTTON_LAST;
112 }
113
114 // Mouse AND Keyboard get button press
115 int get_button_cross_device( int const id )
116 {
117 if( key_is_keyboard( id ) )
118 {
119 return glfwGetKey( vg_window, id );
120 }
121 else
122 {
123 return glfwGetMouseButton( vg_window, id ) == GLFW_PRESS;
124 }
125 }
126
127 void vg_update_inputs(void)
128 {
129 // Update button inputs
130 for( int i = 0; i < vg_list_size( vg_button_binds ); i ++ )
131 {
132 struct button_binding *binding = vg_button_binds + i;
133 binding->prev = binding->value;
134
135 if( vg_input_mode == k_EInputMode_pc )
136 {
137 binding->value = get_button_cross_device( binding->bind );
138 }
139 else
140 {
141 binding->value = vg_gamepad.buttons[ binding->bind ];
142 }
143 }
144
145 // Update axis inputs
146 for( int i = 0; i < vg_list_size( vg_axis_binds ); i ++ )
147 {
148 struct axis_binding *binding = vg_axis_binds + i;
149
150 if( vg_input_mode == k_EInputMode_pc )
151 {
152 binding->value = get_button_cross_device( binding->positive );
153 binding->value -= get_button_cross_device( binding->negative );
154 }
155 else
156 {
157 binding->value = vg_gamepad.axes[ binding->bind ];
158 }
159 }
160 }