input programs? experimental..
[vg.git] / vg_input.h
index 6b8cd79ee04513aa7ba9e7146edd9ee779b4afae..9c5be8447ecc242f4baff8171601fbfc18f39a18 100644 (file)
@@ -7,11 +7,47 @@
 
 #define VG_MAX_CONTROLLERS 4
 
-VG_STATIC float controller_deadzone = 0.05f;
-
-struct
-{
+static float controller_deadzone = 0.05f;
+typedef u32 vg_input_op;
+typedef vg_input_op *vg_input_program;
+
+enum vg_input_type {
+   k_vg_input_type_button_u8,
+   k_vg_input_type_axis_f32,
+   k_vg_input_type_joy_v2f
+};
+
+enum vg_input_op {
+   /* data source */
+   vg_keyboard,
+   vg_mouse,
+   vg_joy_button,
+   vg_joy_axis,
+
+   /* hacky constants */
+   vg_0_0f,
+   vg_0_5f,
+   vg_1_0f,
+   vg_2_0f,
+
+   /* modes */
+   vg_mode_mul,
+   vg_mode_sub,
+   vg_mode_add,
+   vg_mode_absmax,
+   vg_mode_max,
+
+   /* control */
+   vg_index,
+   vg_end,
+
+   /* math */
+   vg_normalize
+};
+
+struct{
    const u8 *sdl_keys;
+   u32 sdl_mouse;
 
    struct vg_controller{
       SDL_GameController *handle; /* handle for controller. NULL if unused */
@@ -36,7 +72,7 @@ struct
 }
 static vg_input = { .active_controller_index = -2 };
 
-VG_STATIC u8 vg_getkey( SDL_Keycode kc )
+static u8 vg_getkey( SDL_Keycode kc )
 {
    SDL_Scancode sc = SDL_GetScancodeFromKey( kc );
    return vg_input.sdl_keys[sc];
@@ -45,7 +81,7 @@ VG_STATIC u8 vg_getkey( SDL_Keycode kc )
 /*
  * takes SDL device index, and tries to open that on any free channel
  */
-VG_STATIC int vg_open_gamecontroller( Sint32 index )
+static int vg_open_gamecontroller( Sint32 index )
 {
    struct vg_controller *controller = NULL;
    int vg_id = 0;
@@ -90,9 +126,6 @@ VG_STATIC int vg_open_gamecontroller( Sint32 index )
          for( u32 i=0; i< SDL_CONTROLLER_AXIS_MAX; i++ )
             controller->axises[i] = 0.0f;
 
-         controller->axises[ SDL_CONTROLLER_AXIS_TRIGGERLEFT ] = -1.0f;
-         controller->axises[ SDL_CONTROLLER_AXIS_TRIGGERRIGHT ] = -1.0f;
-
          if( vg_input.active_controller_index == -2 ){
             vg_input.active_controller_index = vg_id;
             vg_input.display_input_method = k_input_method_controller;
@@ -114,7 +147,7 @@ VG_STATIC int vg_open_gamecontroller( Sint32 index )
    }
 }
 
-VG_STATIC void vg_input_device_event( SDL_Event *ev )
+static void vg_input_device_event( SDL_Event *ev )
 {
    if( ev->type == SDL_CONTROLLERDEVICEADDED ){
       int is_controller = SDL_IsGameController( ev->cdevice.which );
@@ -155,7 +188,7 @@ VG_STATIC void vg_input_device_event( SDL_Event *ev )
    }
 }
 
-VG_STATIC void vg_input_controller_event( SDL_Event *ev )
+static void vg_input_controller_event( SDL_Event *ev )
 {
    if( ev->type == SDL_CONTROLLERAXISMOTION ){
       for( int i=0; i<VG_MAX_CONTROLLERS; i++ ){
@@ -174,6 +207,10 @@ VG_STATIC void vg_input_controller_event( SDL_Event *ev )
                
                value = vg_signf(value) * (high / (1.0f-deadz));
             }
+            else if( ev->caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT ||
+                     ev->caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT ){
+               value = 0.5f + value*0.5f;
+            }
 
             esta->axises[ ev->caxis.axis ] = value;
             break;
@@ -231,10 +268,11 @@ VG_STATIC void vg_input_controller_event( SDL_Event *ev )
    }
 }
 
-VG_STATIC void vg_process_inputs(void)
+static void vg_process_inputs(void)
 {
    int count;
    vg_input.sdl_keys = SDL_GetKeyboardState( &count );
+   vg_input.sdl_mouse = SDL_GetMouseState(NULL,NULL);
 
    if( vg_input.display_input_method != k_input_method_kbm ){
       /* check for giving keyboard priority */
@@ -247,7 +285,7 @@ VG_STATIC void vg_process_inputs(void)
       }
 
       /* check for giving mouse priority */
-      if( SDL_GetMouseState(NULL,NULL) & 
+      if( vg_input.sdl_mouse & 
             (SDL_BUTTON(SDL_BUTTON_LEFT)|SDL_BUTTON(SDL_BUTTON_RIGHT)|
              SDL_BUTTON(SDL_BUTTON_MIDDLE)) )
       {
@@ -257,7 +295,7 @@ VG_STATIC void vg_process_inputs(void)
    }
 }
 
-VG_STATIC void async_vg_input_init( void *payload, u32 size )
+static void async_vg_input_init( void *payload, u32 size )
 {
    VG_VAR_F32( controller_deadzone, flags=VG_VAR_PERSISTENT );
 
@@ -277,12 +315,12 @@ VG_STATIC void async_vg_input_init( void *payload, u32 size )
    }
 }
 
-VG_STATIC void vg_input_init(void)
+static void vg_input_init(void)
 {
    vg_async_call( async_vg_input_init, NULL, 0 );
 }
 
-VG_STATIC void vg_input_free(void)
+static void vg_input_free(void)
 {
    for( int i=0; i<VG_MAX_CONTROLLERS; i++ ){
       struct vg_controller *controller = &vg_input.controllers[i];
@@ -294,4 +332,113 @@ VG_STATIC void vg_input_free(void)
    }
 }
 
+struct vg_controller *vg_active_controller(void){
+   if( vg_input.active_controller_index >= 0 )
+      return &vg_input.controllers[vg_input.active_controller_index];
+   else
+      return NULL;
+}
+
+static u8 vg_controller_button( SDL_GameControllerButton button ){
+   struct vg_controller *c = vg_active_controller();
+   if( c ) return c->buttons[ button ];
+   else return 0;
+}
+
+static f32 vg_controller_axis( SDL_GameControllerAxis axis ){
+   struct vg_controller *c = vg_active_controller();
+   if( c ) return c->axises[ axis ];
+   else return 0;
+}
+
+static void vg_input_apply_to_u8( vg_input_op mode, u8 data, u8 *inout_result ){
+   if     ( mode == vg_mode_absmax )  *inout_result |= data;
+   else if( mode == vg_mode_mul )     *inout_result &= data;
+   else vg_fatal_error( "mode not supported for destination type (%d)", mode );
+}
+
+static void vg_input_apply_to_f32( vg_input_op mode, f32 data, 
+                                   f32 *inout_result ){
+   if     ( mode == vg_mode_absmax ){
+      if( fabsf(data) > fabsf(*inout_result) )
+         *inout_result = data;
+   }
+   else if( mode == vg_mode_max ) *inout_result = vg_maxf(*inout_result,data);
+   else if( mode == vg_mode_mul ) *inout_result *= (f32)data;
+   else if( mode == vg_mode_sub ) *inout_result -= (f32)data;
+   else if( mode == vg_mode_add ) *inout_result += (f32)data;
+   else vg_fatal_error( "mode not supported for destination type (%d)", mode );
+}
+
+static void vg_exec_input_program( enum vg_input_type type, vg_input_op *ops, 
+                                   void *out_result ){
+   u8 *out_button = NULL;
+   f32 *out_joy = NULL;
+
+   if( type == k_vg_input_type_button_u8 ){
+      out_button = out_result;
+      *out_button = 0;
+   }
+   else if( type == k_vg_input_type_axis_f32 ){
+      out_joy = out_result;
+      out_joy[0] = 0.0f;
+   }
+   else if( type == k_vg_input_type_joy_v2f ){
+      out_joy = out_result;
+      out_joy[0] = 0.0f;
+      out_joy[1] = 0.0f;
+   }
+
+   /* computer state */
+   vg_input_op mode = vg_mode_absmax;
+   u32 pc = 0, index = 0;
+
+next_code:;
+   vg_input_op op = ops[ pc ++ ];
+
+   if( (op >= vg_mode_mul) && (op <= vg_mode_max) ){
+      mode = op;
+   }
+   else if( (op == vg_keyboard) || (op == vg_mouse) || (op == vg_joy_button) ){
+      u8 state = 0;
+
+      if( op == vg_keyboard )
+         state = vg_getkey(ops[pc ++]);
+      else if( op == vg_mouse )
+         state = (vg_input.sdl_mouse & SDL_BUTTON(ops[pc ++]))?1:0;
+      else
+         state = vg_controller_button(ops[pc ++]);
+
+      if( type == k_vg_input_type_button_u8 )
+         vg_input_apply_to_u8( mode, state, out_button );
+      else
+         vg_input_apply_to_f32( mode, (f32)state, &out_joy[index] );
+   }
+   else if( op == vg_joy_axis ){
+      f32 state = vg_controller_axis( ops[pc ++] );
+      if( type == k_vg_input_type_button_u8 )
+         vg_input_apply_to_u8( mode, state>0.5f?1:0, out_button );
+      else 
+         vg_input_apply_to_f32( mode, state, &out_joy[index] );
+   }
+   else if( (op >= vg_0_0f) && (op <= vg_2_0f) ){
+      f32 value = (f32)(op - vg_0_5f) * 0.5f;
+      vg_input_apply_to_f32( mode, value, &out_joy[index] );
+   }
+   else if( op == vg_index ){
+      index = ops[pc ++];
+   }
+   else if( op == vg_end ){
+      return;
+   }
+   else if( op == vg_normalize ){
+      v2_normalize( out_joy );
+   }
+   else {
+      vg_fatal_error( "unknown op\n" );
+   }
+
+   goto next_code;
+}
+
 #endif