better structure
[vg.git] / src / vg / vg_input.h
diff --git a/src/vg/vg_input.h b/src/vg/vg_input.h
new file mode 100644 (file)
index 0000000..62d4690
--- /dev/null
@@ -0,0 +1,160 @@
+// Copyright (C) 2021 Harry Godden (hgn) - All Rights Reserved
+
+static inline float vg_get_axis( const char *axis ) __attribute__((unused));
+static inline int vg_get_button( const char *button ) __attribute__((unused));
+static inline int vg_get_button_down( const char *button ) __attribute__((unused));
+static inline int vg_get_button_up( const char *button ) __attribute__((unused));
+
+enum vg_button_state
+{
+       k_button_state_down = 1,
+       k_button_state_up = 3,
+       k_button_state_pressed = 2,
+       k_button_state_none = 0
+};
+
+// Input
+// ===========================================================================================================
+GLFWgamepadstate vg_gamepad;
+int                    vg_gamepad_ready = 0;
+const char *vg_gamepad_name = NULL;
+int                    vg_gamepad_id;
+
+enum EInputMode
+{
+       k_EInputMode_pc,
+       k_EInputMode_gamepad
+}
+vg_input_mode;
+
+static struct axis_binding
+{
+       const char *name;
+       union
+       {
+               int positive;
+               int bind;
+       };
+       int negative;
+       
+       float value;
+}
+vg_axis_binds[];
+
+static struct button_binding
+{
+       const char *name;
+       int bind;
+       
+       int value; int prev;
+}
+vg_button_binds[];
+
+#include "vg/config.h"
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wreturn-type"
+
+static inline float vg_get_axis( const char *axis )
+{
+       for( int i = 0; i < vg_list_size( vg_axis_binds ); i ++ )
+       {
+               if( !strcmp( axis, vg_axis_binds[i].name ) )
+               {
+                       return vg_axis_binds[i].value;
+               }
+       }
+}
+
+static inline struct button_binding *vg_get_button_ptr( const char *button )
+{
+       for( int i = 0; i < vg_list_size( vg_button_binds ); i ++ )
+       {
+               if( !strcmp( button, vg_button_binds[i].name ) )
+               {
+                       return vg_button_binds + i;
+               }
+       }
+}
+#pragma GCC diagnostic pop
+
+static int vg_console_enabled(void);
+
+static inline int vg_get_button( const char *button )
+{
+       return vg_get_button_ptr( button )->value && !vg_console_enabled();
+}
+
+static inline int vg_get_button_down( const char *button )
+{
+       struct button_binding *bind = vg_get_button_ptr( button );
+       return bind->value & (bind->value ^ bind->prev) && !vg_console_enabled();
+}
+
+static inline int vg_get_button_up( const char *button )
+{
+       struct button_binding *bind = vg_get_button_ptr( button );
+       return bind->prev & (bind->value ^ bind->prev) && !vg_console_enabled();
+}
+
+static inline enum vg_button_state vg_get_button_state( const char *button )
+{
+       if( vg_get_button_down( button ) ) return k_button_state_down;
+       if( vg_get_button_up( button ) ) return k_button_state_up;
+       if( vg_get_button( button ) ) return k_button_state_pressed;
+       return k_button_state_none;
+}
+
+static inline int key_is_keyboard( int const id )
+{
+       vg_static_assert( GLFW_MOUSE_BUTTON_LAST < GLFW_KEY_SPACE, "GLFW: Mouse has too many buttons" );
+       return id > GLFW_MOUSE_BUTTON_LAST;
+}
+
+// Mouse AND Keyboard get button press
+int get_button_cross_device( int const id )
+{
+       if( key_is_keyboard( id ) )
+       {
+               return glfwGetKey( vg_window, id );
+       }
+       else
+       {
+               return glfwGetMouseButton( vg_window, id ) == GLFW_PRESS;
+       }
+}
+
+void vg_update_inputs(void)
+{
+       // Update button inputs
+       for( int i = 0; i < vg_list_size( vg_button_binds ); i ++ )
+       {
+               struct button_binding *binding = vg_button_binds + i;
+               binding->prev = binding->value;
+       
+               if( vg_input_mode == k_EInputMode_pc )
+               {
+                       binding->value = get_button_cross_device( binding->bind );
+               }
+               else
+               {
+                       binding->value = vg_gamepad.buttons[ binding->bind ];
+               }
+       }
+       
+       // Update axis inputs
+       for( int i = 0; i < vg_list_size( vg_axis_binds ); i ++ )
+       {
+               struct axis_binding *binding = vg_axis_binds + i;
+               
+               if( vg_input_mode == k_EInputMode_pc )
+               {
+                       binding->value  = get_button_cross_device( binding->positive );
+                       binding->value -= get_button_cross_device( binding->negative );
+               }
+               else
+               {
+                       binding->value = vg_gamepad.axes[ binding->bind ];
+               }
+       }
+}