X-Git-Url: https://harrygodden.com/git/?p=vg.git;a=blobdiff_plain;f=vg_input.h;h=d8e398cf8d9edd9e8c995445913307ea1b811a59;hp=cd7130d745f0aae33d608de4efed992790aa85d2;hb=HEAD;hpb=3f8eb36bc705028519cd9e047b24f9b0e97f368e diff --git a/vg_input.h b/vg_input.h index cd7130d..1636e07 100644 --- a/vg_input.h +++ b/vg_input.h @@ -1,23 +1,24 @@ -/* 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 { +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 { +enum vg_input_op +{ /* data source */ vg_keyboard, vg_mouse, @@ -42,9 +43,11 @@ enum vg_input_op { vg_normalize }; -struct{ +struct vg_input +{ const u8 *sdl_keys; u32 sdl_mouse; + f32 hidden_mouse_travel; struct vg_controller{ SDL_GameController *handle; /* handle for controller. NULL if unused */ @@ -67,570 +70,24 @@ struct{ 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; jhandle ){ - 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; - - 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; ihandle ){ - 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; icaxis.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; icbutton.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; icbutton.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 ); - vg_input.sdl_mouse = SDL_GetMouseState(NULL,NULL); - - if( vg_input.display_input_method != k_input_method_kbm ){ - /* check for giving keyboard priority */ - for( int i=0; ihandle ){ - SDL_GameControllerClose( controller->handle ); - controller->handle = NULL; - } - } -} - -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 ); -} - -/* - * Run an input program. out_result must point to memory with sufficient - * storage respective to the size set by type. - */ -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_joy_ls) || (op == vg_joy_rs) ){ - if( type == k_vg_input_type_joy_v2f ){ - vg_input_apply_to_f32( mode, - vg_controller_axis( op==vg_joy_ls? SDL_CONTROLLER_AXIS_LEFTX: - SDL_CONTROLLER_AXIS_RIGHTX), - &out_joy[0] ); - vg_input_apply_to_f32( mode, - vg_controller_axis( op==vg_joy_ls? SDL_CONTROLLER_AXIS_LEFTY: - SDL_CONTROLLER_AXIS_RIGHTY), - &out_joy[1] ); - } - } - else if( op == vg_index ) - index = ops[pc ++]; - else if( op == vg_end ) - return; - else if( op == vg_normalize ) - v2_normalize( out_joy ); - else if( op == vg_gui_visible ) - pc ++; - else - vg_fatal_error( "unknown op\n" ); - - goto next_code; -} - -/* - * Get vendor specific button glyphs based on SDL button ID - */ -static const char *controller_button_str( SDL_GameControllerButton button ){ - static const char *controller_glyphs[ SDL_CONTROLLER_BUTTON_MAX ][2] = { - /* xbox/generic playstation */ - [ SDL_CONTROLLER_BUTTON_A ] = { "\x1e\x85","\x1e\x82" }, - [ SDL_CONTROLLER_BUTTON_B ] = { "\x1e\x86","\x1e\x81" }, - [ SDL_CONTROLLER_BUTTON_X ] = { "\x1e\x83","\x1e\x7f" }, - [ SDL_CONTROLLER_BUTTON_Y ] = { "\x1e\x84","\x1e\x80" }, - [ SDL_CONTROLLER_BUTTON_LEFTSTICK ] = { "\x87", "\x87" }, - [ SDL_CONTROLLER_BUTTON_RIGHTSTICK ] = { "\x8b", "\x8b" }, - [ SDL_CONTROLLER_BUTTON_LEFTSHOULDER ] = { "\x91", "\x91" }, - [ SDL_CONTROLLER_BUTTON_RIGHTSHOULDER ]= { "\x92", "\x92" }, - [ SDL_CONTROLLER_BUTTON_DPAD_LEFT ] = { "\x1e\x93","\x1e\x93" }, - [ SDL_CONTROLLER_BUTTON_DPAD_UP ] = { "\x1e\x94","\x1e\x94" }, - [ SDL_CONTROLLER_BUTTON_DPAD_RIGHT ] = { "\x1e\x95","\x1e\x95" }, - [ SDL_CONTROLLER_BUTTON_DPAD_DOWN ] = { "\x1e\x96","\x1e\x96" }, - [ SDL_CONTROLLER_BUTTON_GUIDE ] = { "\x91", "\x91" }, - }; - - if( vg_input.display_input_type == SDL_CONTROLLER_TYPE_PS3 || - vg_input.display_input_type == SDL_CONTROLLER_TYPE_PS4 || - vg_input.display_input_type == SDL_CONTROLLER_TYPE_PS5 ) - { - return controller_glyphs[ button ][ 1 ]; - } - else if( vg_input.display_input_type == - SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO || - vg_input.display_input_type == - SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT || - vg_input.display_input_type == - SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR || - vg_input.display_input_type == - SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT ) - { - return NULL; - } - else - return controller_glyphs[ button ][ 0 ]; -} - -/* - * Cat keyboard key string. special_glyphs include SR glyphs - */ -static void vg_keyboard_key_string( vg_str *str, u32 key, int special_glyphs ){ - if( (key >= SDLK_a) && (key <= SDLK_z) ){ - key = (key-SDLK_a)+(u32)'A'; - - if( special_glyphs ){ - vg_strcatch( str, '\x1f' ); - vg_strcatch( str, key ); - vg_strcatch( str, ' ' ); - } - else - vg_strcatch( str, key ); - } - else if( (key == SDLK_LSHIFT) || (key == SDLK_RSHIFT) ) - vg_strcat( str, special_glyphs? "\x9e": "shift" ); - else if( (key == SDLK_LCTRL) || (key == SDLK_RCTRL) ) - vg_strcat( str, special_glyphs? "\x9f": "ctrl" ); - else if( (key == SDLK_LALT) || (key == SDLK_RALT) ) - vg_strcat( str, special_glyphs? "\xa0": "alt" ); - else if( key == SDLK_SPACE ) - vg_strcat( str, special_glyphs? "\xa1": "space" ); - else if( (key == SDLK_RETURN) || (key == SDLK_RETURN2) ) - vg_strcat( str, special_glyphs? "\xa2": "return" ); - else if( key == SDLK_ESCAPE ) - vg_strcat( str, special_glyphs? "\xa3": "escape" ); - else if( key == SDLK_RIGHT ) - vg_strcat( str, special_glyphs? "\x1f\x95 ": "right" ); - else if( key == SDLK_LEFT ) - vg_strcat( str, special_glyphs? "\x1f\x93 ": "left" ); - else if( key == SDLK_UP ) - vg_strcat( str, special_glyphs? "\x1f\x94 ": "up" ); - else if( key == SDLK_DOWN ) - vg_strcat( str, special_glyphs? "\x1f\x96 ": "down" ); - else { - vg_strcat( str, "keyboard key #" ); - vg_strcati32( str, key ); - } -} - -/* - * Cat mouse button string. special_glyphs include SR glyphs - */ -static void vg_mouse_button_string( vg_str *str, u32 button, - int special_glyphs ){ - if ( button == SDL_BUTTON_LEFT ) - vg_strcat( str, special_glyphs? "\x99": "left mouse" ); - else if( button == SDL_BUTTON_RIGHT ) - vg_strcat( str, special_glyphs? "\x9a": "right mouse" ); - else if( button == SDL_BUTTON_MIDDLE ) - vg_strcat( str, special_glyphs? "\x9c": "middle mouse" ); - else{ - vg_strcat( str, "mouse button #" ); - vg_strcati32( str, button ); - } -} - -/* - * Cat string represeinting single axis - */ -static void vg_joy_axis_string( vg_str *str, - SDL_GameControllerAxis axis, int special_glyphs ){ - if( axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT ) - vg_strcat( str, special_glyphs?"\x8f":"left trigger" ); - else if( axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT ) - vg_strcat( str, special_glyphs?"\x90":"right trigger" ); - else if( axis == SDL_CONTROLLER_AXIS_LEFTX ) - vg_strcat( str, special_glyphs?"\x88":"left stick horizontal" ); - else if( axis == SDL_CONTROLLER_AXIS_LEFTY ) - vg_strcat( str, special_glyphs?"\x89":"left stick vertical" ); - else if( axis == SDL_CONTROLLER_AXIS_RIGHTX ) - vg_strcat( str, special_glyphs?"\x8c":"right stick horizontal" ); - else if( axis == SDL_CONTROLLER_AXIS_RIGHTY ) - vg_strcat( str, special_glyphs?"\x8d":"right stick vertical" ); - else{ - vg_strcat( str, "axis " ); - vg_strcati32( str, axis ); - } -} - -/* - * Cat string represeinting whole joystick - */ -static void vg_joy_string( vg_str *str, vg_input_op op, int special_glyphs ){ - if( op == vg_joy_ls ) - vg_strcat( str, special_glyphs? "\x87": "left stick" ); - else - vg_strcat( str, special_glyphs? "\x8b": "right stick" ); -} - -/* - * Convert an input program into a readable string - */ -static void vg_input_string( vg_str *str, vg_input_op *ops, int glyphs ){ - u32 pc = 0; - int applicable = 0, visible = 1; - -next_code:; - vg_input_op op = ops[ pc ++ ]; - - if( (op == vg_keyboard) || (op == vg_mouse) ){ - if( (vg_input.display_input_method == k_input_method_kbm) && visible ){ - applicable = 1; - - if( op == vg_keyboard ) - vg_keyboard_key_string( str, ops[pc], glyphs ); - else - vg_mouse_button_string( str, ops[pc], glyphs ); - } - else applicable = 0; - pc ++; - } - else if( (op == vg_joy_button) || (op == vg_joy_axis) ){ - if( (vg_input.display_input_method == k_input_method_controller) - && visible ){ - applicable = 1; - - if( op == vg_joy_button ) - vg_strcat( str, controller_button_str(ops[pc]) ); - else - vg_joy_axis_string( str, ops[pc], glyphs ); - } - else applicable = 0; - pc ++; - } - else if( (op == vg_joy_ls) || (op == vg_joy_rs) ){ - if( (vg_input.display_input_method == k_input_method_controller) - && visible ){ - applicable = 1; - vg_joy_string( str, op, glyphs ); - } - else applicable = 0; - } - else if( op == vg_mode_mul ){ - if( applicable && visible ) - vg_strcat( str, " + " ); - } - else if( op == vg_index ) - pc ++; - else if( op == vg_gui_visible ) - visible = ops[pc++]; - else if( op == vg_end ) - return; - - goto next_code; -} - -#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 );