4d1ac0e31f68fbc1035ec26b2606df62165959d0
[fishladder.git] / 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 // Input
9 // ===========================================================================================================
10 GLFWgamepadstate vg_gamepad;
11 int vg_gamepad_ready = 0;
12 const char *vg_gamepad_name = NULL;
13 int vg_gamepad_id;
14
15 enum EInputMode
16 {
17 k_EInputMode_pc,
18 k_EInputMode_gamepad
19 }
20 vg_input_mode;
21
22 static struct axis_binding
23 {
24 const char *name;
25 union
26 {
27 int positive;
28 int bind;
29 };
30 int negative;
31
32 float value;
33 }
34 vg_axis_binds[];
35
36 static struct button_binding
37 {
38 const char *name;
39 int bind;
40
41 int value; int prev;
42 }
43 vg_button_binds[];
44
45 #include "vg/config.h"
46
47 #pragma GCC diagnostic push
48 #pragma GCC diagnostic ignored "-Wreturn-type"
49
50 static inline float vg_get_axis( const char *axis )
51 {
52 for( int i = 0; i < vg_list_size( vg_axis_binds ); i ++ )
53 {
54 if( !strcmp( axis, vg_axis_binds[i].name ) )
55 {
56 return vg_axis_binds[i].value;
57 }
58 }
59 }
60
61 static inline struct button_binding *vg_get_button_ptr( const char *button )
62 {
63 for( int i = 0; i < vg_list_size( vg_button_binds ); i ++ )
64 {
65 if( !strcmp( button, vg_button_binds[i].name ) )
66 {
67 return vg_button_binds + i;
68 }
69 }
70 }
71 #pragma GCC diagnostic pop
72
73 static inline int vg_get_button( const char *button )
74 {
75 return vg_get_button_ptr( button )->value;
76 }
77
78 static inline int vg_get_button_down( const char *button )
79 {
80 struct button_binding *bind = vg_get_button_ptr( button );
81 return bind->value & (bind->value ^ bind->prev);
82 }
83
84 static inline int vg_get_button_up( const char *button )
85 {
86 struct button_binding *bind = vg_get_button_ptr( button );
87 return bind->prev & (bind->value ^ bind->prev);
88 }
89
90 static inline int key_is_keyboard( int const id )
91 {
92 vg_static_assert( GLFW_MOUSE_BUTTON_LAST < GLFW_KEY_SPACE, "GLFW: Mouse has too many buttons" );
93 return id > GLFW_MOUSE_BUTTON_LAST;
94 }
95
96 // Mouse AND Keyboard get button press
97 int get_button_cross_device( int const id )
98 {
99 if( key_is_keyboard( id ) )
100 {
101 return glfwGetKey( vg_window, id );
102 }
103 else
104 {
105 return glfwGetMouseButton( vg_window, id ) == GLFW_PRESS;
106 }
107 }
108
109 void vg_update_inputs(void)
110 {
111 // Update button inputs
112 for( int i = 0; i < vg_list_size( vg_button_binds ); i ++ )
113 {
114 struct button_binding *binding = vg_button_binds + i;
115 binding->prev = binding->value;
116
117 if( vg_input_mode == k_EInputMode_pc )
118 {
119 binding->value = get_button_cross_device( binding->bind );
120 }
121 else
122 {
123 binding->value = vg_gamepad.buttons[ binding->bind ];
124 }
125 }
126
127 // Update axis inputs
128 for( int i = 0; i < vg_list_size( vg_axis_binds ); i ++ )
129 {
130 struct axis_binding *binding = vg_axis_binds + i;
131
132 if( vg_input_mode == k_EInputMode_pc )
133 {
134 binding->value = get_button_cross_device( binding->positive );
135 binding->value -= get_button_cross_device( binding->negative );
136 }
137 else
138 {
139 binding->value = vg_gamepad.axes[ binding->bind ];
140 }
141 }
142 }