-/* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
-#ifndef VG_INPUT_H
-#define VG_INPUT_H
-
-#include "common.h"
-#include "vg/vg_loader.h"
+#pragma once
+/* Copyright (C) 2021-2024 Harry Godden (hgn) - All Rights Reserved */
#define VG_MAX_CONTROLLERS 4
-static float controller_deadzone = 0.05f;
+#include "vg_platform.h"
+
+extern f32 controller_deadzone;
+
+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
+};
-struct{
+enum vg_input_op
+{
+ /* data source */
+ vg_keyboard,
+ vg_mouse,
+ vg_joy_button,
+ vg_joy_axis,
+ vg_joy_ls,
+ vg_joy_rs,
+
+ /* modes */
+ vg_mode_mul,
+ vg_mode_sub,
+ vg_mode_add,
+ vg_mode_absmax,
+ vg_mode_max,
+
+ /* control */
+ vg_index,
+ vg_end,
+ vg_gui_visible,
+
+ /* math */
+ vg_normalize
+};
+
+struct vg_input
+{
const u8 *sdl_keys;
+ u32 sdl_mouse;
struct vg_controller{
SDL_GameController *handle; /* handle for controller. NULL if unused */
display_input_method;
SDL_GameControllerType display_input_type;
}
-static vg_input = { .active_controller_index = -2 };
-
-static u8 vg_getkey( SDL_Keycode kc )
-{
- SDL_Scancode sc = SDL_GetScancodeFromKey( kc );
- return vg_input.sdl_keys[sc];
-}
-
-/*
- * takes SDL device index, and tries to open that on any free channel
- */
-static int vg_open_gamecontroller( Sint32 index )
-{
- struct vg_controller *controller = NULL;
- int vg_id = 0;
- const char *name = SDL_GameControllerNameForIndex( index );
- SDL_JoystickID instance_id = SDL_JoystickGetDeviceInstanceID( index );
-
- if( instance_id == -1 ){
- vg_error( ". Invalid device index (vg_open_gamecontroller)\n" );
- return -1;
- }
-
- for( int j=0; j<VG_MAX_CONTROLLERS; j++ ){
- struct vg_controller *esta = &vg_input.controllers[j];
-
- if( esta->handle ){
- if( esta->instance_id == instance_id ){
- vg_warn( " . SDL_JoystickID[%d] is already in open at index #%d\n",
- esta->instance_id, j );
- return -1;
- }
- }
- else{
- if( !controller ){
- controller = &vg_input.controllers[j];
- vg_id = j;
- }
- }
- }
-
- if( controller ){
- controller->handle = SDL_GameControllerOpen( index );
- controller->instance_id = instance_id;
-
- if( controller->handle ){
- vg_success(
- " . opened SDL_JoystickID[%d] as controller '%s' at index #%d\n",
- instance_id, name, vg_id );
-
- for( u32 i=0; i< SDL_CONTROLLER_BUTTON_MAX; i++ )
- controller->buttons[i] = 0;
-
- 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;
- vg_input.display_input_type =
- SDL_GameControllerGetType( controller->handle );
- }
-
- return vg_id;
- }
- else{
- vg_error( ". Failed to attach game controller '%s'. Reason: %s\n",
- name, SDL_GetError() );
- return -1;
- }
- }
- else{
- vg_error( ". Too many controllers open! ignoring '%s'\n", name );
- return -1;
- }
-}
-
-static void vg_input_device_event( SDL_Event *ev )
-{
- if( ev->type == SDL_CONTROLLERDEVICEADDED ){
- int is_controller = SDL_IsGameController( ev->cdevice.which );
- const char *name = SDL_JoystickNameForIndex( ev->cdevice.which );
-
- Sint32 index = ev->cdevice.which;
- SDL_JoystickID instance_id = SDL_JoystickGetDeviceInstanceID( index );
- vg_info( "SDL_CONTROLLERDEVICEADDED | device index: %d, name: '%s'\n",
- index, name );
-
- if( is_controller ){
- vg_open_gamecontroller( index );
- }
- }
- else if( ev->type == SDL_CONTROLLERDEVICEREMOVED ){
- vg_info( "SDL_CONTROLLERDEVICEREMOVED | instance_id: %d\n",
- ev->cdevice.which );
-
- for( int i=0; i<VG_MAX_CONTROLLERS; i++ ){
- struct vg_controller *controller = &vg_input.controllers[i];
-
- if( controller->handle ){
- if( controller->instance_id == ev->cdevice.which ){
- vg_info( " . closing controller at index #%d\n", i );
- SDL_GameControllerClose( controller->handle );
- controller->handle = NULL;
- controller->instance_id = -1;
-
- if( vg_input.active_controller_index == i ){
- vg_input.active_controller_index = -1;
- vg_input.display_input_method = k_input_method_kbm;
- vg_info( "display_input: k_input_method_kbm\n" );
- }
- break;
- }
- }
- }
- }
-}
-
-static void vg_input_controller_event( SDL_Event *ev )
-{
- if( ev->type == SDL_CONTROLLERAXISMOTION ){
- for( int i=0; i<VG_MAX_CONTROLLERS; i++ ){
- struct vg_controller *esta = &vg_input.controllers[i];
-
- if( ev->caxis.which == esta->instance_id ){
- float value = (float)ev->caxis.value / 32767.0f;
-
- if( ev->caxis.axis == SDL_CONTROLLER_AXIS_LEFTX ||
- ev->caxis.axis == SDL_CONTROLLER_AXIS_LEFTY ||
- ev->caxis.axis == SDL_CONTROLLER_AXIS_RIGHTX ||
- ev->caxis.axis == SDL_CONTROLLER_AXIS_RIGHTY )
- {
- float deadz = vg_clampf( controller_deadzone, 0.0f, 0.999f ),
- high = vg_maxf( 0.0f, fabsf(value) - deadz );
-
- value = vg_signf(value) * (high / (1.0f-deadz));
- }
-
- esta->axises[ ev->caxis.axis ] = value;
- break;
- }
- }
- }
- else if( ev->type == SDL_CONTROLLERBUTTONDOWN ){
- struct vg_controller *active = NULL;
-
- if( vg_input.active_controller_index >= 0 )
- active = &vg_input.controllers[vg_input.active_controller_index];
-
- if( !active || (ev->cbutton.which != active->instance_id) ){
- active = NULL;
- vg_input.active_controller_index = -1;
- vg_input.display_input_method = k_input_method_kbm;
-
- for( int i=0; i<VG_MAX_CONTROLLERS; i++ ){
- if( vg_input.controllers[i].instance_id == ev->cbutton.which ){
- active = &vg_input.controllers[i];
- vg_input.active_controller_index = i;
- vg_input.display_input_type =
- SDL_GameControllerGetType(active->handle);
- break;
- }
- }
-
- if( active ){
- vg_info( "Switching active controller index to #%d\n",
- vg_input.active_controller_index );
- }
- else{
- vg_error( "Input out of range (SDL_JoystickID#%d)\n",
- ev->cbutton.which );
- }
- }
-
- if( active ){
- if( vg_input.display_input_method != k_input_method_controller ){
- vg_input.display_input_method = k_input_method_controller;
- vg_info( "display_input: k_input_method_controller\n" );
- }
- active->buttons[ ev->cbutton.button ] = 1;
- }
- }
- else if( ev->type == SDL_CONTROLLERBUTTONUP ){
- for( int i=0; i<VG_MAX_CONTROLLERS; i++ ){
- struct vg_controller *esta = &vg_input.controllers[i];
-
- if( ev->cbutton.which == esta->instance_id ){
- esta->buttons[ ev->cbutton.button ] = 0;
- break;
- }
- }
- }
-}
-
-static void vg_process_inputs(void)
-{
- int count;
- vg_input.sdl_keys = SDL_GetKeyboardState( &count );
-
- if( vg_input.display_input_method != k_input_method_kbm ){
- /* check for giving keyboard priority */
- for( int i=0; i<count; i++ ){
- if( vg_input.sdl_keys[i] ){
- vg_input.display_input_method = k_input_method_kbm;
- vg_info( "display_input: k_input_method_kbm (keyboard %d)\n", i );
- break;
- }
- }
-
- /* check for giving mouse priority */
- if( SDL_GetMouseState(NULL,NULL) &
- (SDL_BUTTON(SDL_BUTTON_LEFT)|SDL_BUTTON(SDL_BUTTON_RIGHT)|
- SDL_BUTTON(SDL_BUTTON_MIDDLE)) )
- {
- vg_input.display_input_method = k_input_method_kbm;
- vg_info( "display_input: k_input_method_kbm (mouse)\n" );
- }
- }
-}
-
-static void async_vg_input_init( void *payload, u32 size )
-{
- VG_VAR_F32( controller_deadzone, flags=VG_VAR_PERSISTENT );
-
- vg_info( "Checking for controllers\n" );
- SDL_GameControllerAddMappingsFromFile( "gamecontrollerdb.txt" );
-
- int joy_count = SDL_NumJoysticks();
- for( int i=0; i<joy_count; i++ ) {
- const char *name = SDL_JoystickNameForIndex( i );
- int is_controller = SDL_IsGameController(i);
-
- vg_info( "%d: %s [controller: %d]\n", i, name, is_controller );
-
- if( is_controller ){
- vg_open_gamecontroller( i );
- }
- }
-}
-
-static void vg_input_init(void)
-{
- vg_async_call( async_vg_input_init, NULL, 0 );
-}
-
-static void vg_input_free(void)
-{
- for( int i=0; i<VG_MAX_CONTROLLERS; i++ ){
- struct vg_controller *controller = &vg_input.controllers[i];
-
- if( controller->handle ){
- SDL_GameControllerClose( controller->handle );
- controller->handle = NULL;
- }
- }
-}
-
-#endif
+extern vg_input;
+
+u8 vg_getkey( SDL_Keycode kc );
+void vg_process_inputs(void);
+void async_vg_input_init( void *payload, u32 size );
+void vg_input_init(void);
+void vg_input_free(void);
+struct vg_controller *vg_active_controller(void);
+u8 vg_controller_button( SDL_GameControllerButton button );
+f32 vg_controller_axis( SDL_GameControllerAxis axis );
+void vg_exec_input_program( enum vg_input_type type, vg_input_op *ops,
+ void *out_result );
+const char *controller_button_str( SDL_GameControllerButton button );
+void vg_keyboard_key_string( vg_str *str, u32 key, int special_glyphs );
+void vg_mouse_button_string( vg_str *str, u32 button, int special_glyphs );
+void vg_joy_axis_string( vg_str *str, SDL_GameControllerAxis axis,
+ int special_glyphs );
+void vg_joy_string( vg_str *str, vg_input_op op, int special_glyphs );
+void vg_input_string( vg_str *str, vg_input_op *ops, int glyphs );
+void vg_input_device_event( SDL_Event *ev );
+void vg_input_controller_event( SDL_Event *ev );