#include "common.h"
#include "vg/vg_loader.h"
+#define VG_MAX_CONTROLLERS 4
+
VG_STATIC inline float vg_get_axis( const char *axis );
VG_STATIC inline int vg_get_button( const char *button );
struct input_binding named_inputs[ 32 ];
u32 named_input_count;
- const char *controller_name;
- SDL_GameController *controller_handle; /* null if unplugged */
- SDL_JoystickID controller_joystick_id;
- int controller_should_use_trackpad_look;
+ struct vg_controller{
+ SDL_GameController *handle; /* handle for controller. NULL if unused */
+ SDL_JoystickID instance_id; /* uid used in events */
+
+ enum evg_controller_type{
+ k_vg_controller_type_standard,
+ k_vg_controller_type_trackpads
+ }
+ type;
- float controller_axises[ SDL_CONTROLLER_AXIS_MAX ];
- int controller_buttons[ SDL_CONTROLLER_BUTTON_MAX ];
+ float axises[ SDL_CONTROLLER_AXIS_MAX ];
+ int buttons[ SDL_CONTROLLER_BUTTON_MAX ];
+ }
+ controllers[4];
+
+ int active_controller_index; /* most recent controller (by button press)
+ will be -1 if no controllers active */
+
+ /* what the user is currently using. the keyboard and controller are still
+ * active simultaneously, but this reflects what the UI should show */
+ enum userinput_method{
+ k_userinput_method_xbox,
+ k_userinput_method_playstation,
+ k_userinput_method_steamgeneric,
+ k_userinput_method_kbm
+ }
+ input_method;
}
-VG_STATIC vg_input;
+static vg_input;
VG_STATIC void vg_create_unnamed_input( struct input_binding *bind,
enum input_type type )
return;
}
+ struct vg_controller *acontroller = NULL;
+
+ if( vg_input.active_controller_index != -1 )
+ acontroller = &vg_input.controllers[vg_input.active_controller_index];
+
for( i32 i=0; i<num; i++ ){
struct input_binding *bind = &binds[i];
bind->button.prev = bind->button.value;
bind->button.value = 0;
- if( bind->button.gamepad_id != -1 )
- bind->button.value |=
- vg_input.controller_buttons[ bind->button.gamepad_id ];
+ if( acontroller && (bind->button.gamepad_id != -1) )
+ bind->button.value |= acontroller->buttons[bind->button.gamepad_id];
- if( bind->button.keyboard_id != -1 ){
+ if( bind->button.keyboard_id != -1 )
bind->button.value |= vg_getkey( bind->button.keyboard_id );
- }
if( bind->button.mouse_id != -1 ){
- if( SDL_GetMouseState(NULL, NULL) &
- SDL_BUTTON( bind->button.mouse_id ) )
+ if(SDL_GetMouseState(NULL,NULL) & SDL_BUTTON(bind->button.mouse_id))
bind->button.value |= 1;
}
}
if( vg_getkey( bind->axis.keyboard_negative ) )
keyboard_value -= 1.0f;
- if( bind->axis.gamepad_axis != -1 ){
- gamepad_value =
- vg_input.controller_axises[ bind->axis.gamepad_axis ];
+ if( acontroller && (bind->axis.gamepad_axis != -1) ){
+ gamepad_value = acontroller->axises[ bind->axis.gamepad_axis ];
if( bind->axis.gamepad_inverted )
gamepad_value *= -1.0f;
if( vg_getkey( bind->axis.keyboard_positive ))
value = 1.0f;
- if( bind->axis.gamepad_axis != -1 )
- value = vg_maxf( value,
- vg_input.controller_axises[bind->axis.gamepad_axis] );
+ if( acontroller && (bind->axis.gamepad_axis != -1) ){
+ float value1 = acontroller->axises[bind->axis.gamepad_axis];
+ value = vg_maxf( value, value1 );
+ }
bind->axis.value = value;
}
}
}
-VG_STATIC void vg_input_controller_event( SDL_Event *ev )
+/*
+ * takes SDL device index, and tries to open that on any free channel
+ */
+VG_STATIC void vg_open_gamecontroller( Sint32 index )
{
- if( ev->type == SDL_CONTROLLERAXISMOTION ){
- if( ev->caxis.which == vg_input.controller_joystick_id ){
- vg_input.controller_axises[ ev->caxis.axis ] =
- (float)ev->caxis.value / 32767.0f;
+ 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;
+ }
+
+ 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;
+ }
+ }
+ else{
+ if( !controller ){
+ controller = &vg_input.controllers[j];
+ vg_id = j;
+ }
}
}
- else if( ev->type == SDL_CONTROLLERBUTTONDOWN ){
- if( ev->cbutton.which == vg_input.controller_joystick_id )
- vg_input.controller_buttons[ ev->cbutton.button ] = 1;
+
+ 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 );
+
+ controller->axises[ SDL_CONTROLLER_AXIS_TRIGGERLEFT ] = -1.0f;
+ controller->axises[ SDL_CONTROLLER_AXIS_TRIGGERRIGHT ] = -1.0f;
+ }
+ else{
+ vg_error( ". Failed to attach game controller '%s'. Reason: %s\n",
+ name, SDL_GetError() );
+ }
}
- else if( ev->type == SDL_CONTROLLERBUTTONUP ){
- if( ev->cbutton.which == vg_input.controller_joystick_id )
- vg_input.controller_buttons[ ev->cbutton.button ] = 0;
+ else{
+ vg_error( ". Too many controllers open! ignoring '%s'\n", name );
+
}
}
-VG_STATIC void vg_try_attach_controller(void)
+VG_STATIC void vg_input_device_event( SDL_Event *ev )
{
- int joy_count = SDL_NumJoysticks();
- for( int i=0; i<joy_count; i++ ) {
- if( SDL_IsGameController(i) ) {
- vg_input.controller_handle = SDL_GameControllerOpen(i);
- vg_input.controller_joystick_id = i;
- vg_success( "Attached game controller with joystick ID %d\n", i );
- return;
+ 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_info( " . active controller is now keyboard and mouse\n" );
+ }
+ break;
+ }
+ }
}
}
}
-VG_STATIC void vg_update_inputs(void)
+VG_STATIC void vg_input_controller_event( SDL_Event *ev )
{
- vg_input.sdl_keys = SDL_GetKeyboardState(NULL);
+ 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;
+ esta->axises[ ev->caxis.axis ] = value;
+ break;
+ }
+ }
+ }
+ else if( ev->type == SDL_CONTROLLERBUTTONDOWN ){
+ struct vg_controller *active = NULL;
+
+ if( vg_input.active_controller_index != -1 )
+ 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;
+
+ 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;
+ 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( vg_input.controller_handle ){
- if( !SDL_GameControllerGetAttached( vg_input.controller_handle ) ){
- SDL_GameControllerClose( vg_input.controller_handle );
- vg_input.controller_handle = NULL;
+ if( active )
+ 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;
+ }
}
}
+}
+
+VG_STATIC void vg_process_inputs(void)
+{
+ int count;
+ vg_input.sdl_keys = SDL_GetKeyboardState( &count );
+
+ if( vg_input.input_method != k_userinput_method_kbm ){
+ /* check for giving keyboard priority */
+ for( int i=0; i<count; i++ ){
+ if( vg_input.sdl_keys[i] ){
+ vg_input.input_method = k_userinput_method_kbm;
+ break;
+ }
+ }
- if( !vg_input.controller_handle ){
- vg_input.controller_axises[ SDL_CONTROLLER_AXIS_TRIGGERLEFT ] = -1.0f;
- vg_input.controller_axises[ SDL_CONTROLLER_AXIS_TRIGGERRIGHT ] = -1.0f;
- vg_try_attach_controller();
+ /* check for giving mouse priority */
+ if( SDL_GetMouseState(NULL,NULL) &
+ (SDL_BUTTON(SDL_BUTTON_LEFT)|SDL_BUTTON(SDL_BUTTON_RIGHT)) )
+ {
+ vg_input.input_method = k_userinput_method_kbm;
+ }
}
/* update all inputs */
vg_console_reg_cmd( "bind", vg_rebind_input_cmd, vg_rebind_input_cmd_poll );
VG_VAR_F32( controller_deadzone, flags=VG_VAR_PERSISTENT );
- vg_info( "Checking for controller\n" );
+
+ vg_info( "Checking for controllers\n" );
SDL_GameControllerAddMappingsFromFile( "gamecontrollerdb.txt" );
int joy_count = SDL_NumJoysticks();
- for( int i=0; i<joy_count; i++ )
- {
- vg_info( "joystick %d: %s [gamecontroller: %d]\n",
- i, SDL_JoystickNameForIndex( i ),
- SDL_IsGameController(i) );
- }
+ for( int i=0; i<joy_count; i++ ) {
+ const char *name = SDL_JoystickNameForIndex( i );
+ int is_controller = SDL_IsGameController(i);
- vg_try_attach_controller();
+ vg_info( "%d: %s [controller: %d]\n", i, name, is_controller );
- vg_input.controller_axises[ SDL_CONTROLLER_AXIS_TRIGGERLEFT ] = -1.0f;
- vg_input.controller_axises[ SDL_CONTROLLER_AXIS_TRIGGERRIGHT ] = -1.0f;
+ if( is_controller ){
+ vg_open_gamecontroller( i );
+ }
+ }
}
VG_STATIC void vg_input_init(void)
VG_STATIC void vg_input_free(void)
{
- if( vg_input.controller_handle ){
- SDL_GameControllerClose( vg_input.controller_handle );
- vg_input.controller_handle = NULL;
+ 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;
+ }
}
}
.name = "[vg] loader",
.link = NULL,
- /* This is the old background shader */
-#if 0
- .vs =
- {
- .orig_file = NULL,
- .static_src = ""
- "layout (location=0) in vec2 a_co;"
- "out vec2 aUv;"
- "void main()"
- "{"
- "gl_Position = vec4(a_co*2.0-1.0,0.0,1.0);"
- "aUv = a_co;"
- "}"
- },
- .fs =
- {
- .orig_file = NULL,
- .static_src =
-
- "out vec4 FragColor;"
- "uniform float uTime;"
- "in vec2 aUv;"
-
- "void main()"
- "{"
- "float dither=fract(dot(vec2(171.0,231.0),gl_FragCoord.xy)/71.0)-0.5;"
- "float grad = 1.0-(aUv.y*0.5+0.5)*0.5;"
- "float fmt1 = step( 0.5, grad+dither );"
-
- "vec3 col = 0.5+0.5*sin( uTime + aUv.xyx + vec3(0.0,2.0,4.0) );"
-
- "FragColor = vec4(vec3(0.5,0.5,0.5)*grad*fmt1,1.0);"
- "}"
- }
-#else
-
/* This is the new foreground shader */
-
.vs =
{
.orig_file = NULL,
"out vec4 FragColor;"
"uniform float uTime;"
"uniform float uRatio;"
+ "uniform float uOpacity;"
"in vec2 aUv;"
"float eval_zero( vec2 uv )"
"float dither=fract(dot(vec2(171.0,231.0),gl_FragCoord.xy)/71.0)-0.5;"
"float fmt1 = step( 0.5, zero*zero + dither )*0.8+0.2;"
- "FragColor = vec4(vec3(fmt1),0.8);"
+ "FragColor = vec4(vec3(fmt1),uOpacity);"
"}"
}
-
-#endif
};
static struct vg_loader
vg_info( " -> %p\n", step->fn_free );
step->fn_free();
}
-
- vg_info( "done\n" );
}
VG_STATIC void _vg_render_log(void)
ui_draw( NULL );
}
-VG_STATIC void _vg_loader_render(void)
+VG_STATIC void _vg_loader_render_ring( float opacity )
{
- glViewport( 0,0, vg.window_x, vg.window_y );
- glBindFramebuffer( GL_FRAMEBUFFER, 0 );
- glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
- glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
-
-#if 0
- glUseProgram( _shader_loader.id );
- glUniform1f( glGetUniformLocation( _shader_loader.id, "uTime" ), vg.time );
- glBindVertexArray( vg_loader.vao );
- glDrawArrays( GL_TRIANGLES, 0, 6 );
-#endif
-
- _vg_render_log();
-
-#if 1
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_ADD);
glUniform1f( glGetUniformLocation( _shader_loader.id, "uTime" ), vg.time );
float ratio = (float)vg.window_x / (float)vg.window_y;
glUniform1f( glGetUniformLocation( _shader_loader.id, "uRatio"), ratio );
+ glUniform1f( glGetUniformLocation( _shader_loader.id, "uOpacity"), opacity );
glBindVertexArray( vg_loader.vao );
glDrawArrays( GL_TRIANGLES, 0, 6 );
-#endif
+}
+
+VG_STATIC void _vg_loader_render(void)
+{
+ glViewport( 0,0, vg.window_x, vg.window_y );
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
+ glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
+
+ _vg_render_log();
+ vg.loader_ring = 0.8f;
}